live555 傳輸方式(TCP&UDP)
概述:live555底層支援TCP和UDP,通過RTSP互動時客戶端通過SETUP請求!!!
先介紹下主要的流程:RTP包的傳送是從MediaSink::startPlaying函式呼叫開始的,在StartPlaying函式的最後會呼叫函式continuePlaying。
continuePlaying函式是定義在MediaSink類中的純虛擬函式,需要到特定媒體的sink子類中實現,對於H264來講是在H264VideoRTPSink中實現的。H264VideoRTPSink:continuePlaying中會建立一個輔助類H264FUAFragmenter,用於H264的RTP打包。因為
在函式MultiFramedRTPSink::continuePlaying中主要是調MultiFramedRTPSink::buildAndSendPacket函式。
看名字就知道MultiFramedRTPSink::buildAndSendPacket()函式將完成打包併發送工作。傳遞了一個True引數,表示這是第一個packet。在該函式的最後呼叫了MultiFramedRTPSink::packFrame() ,進一步的工作,在packFrame函式中進行
MultiFramedRTPSink::packFrame()將為RTP包填充資料。packFrame函式需要處理兩種情況:
1).buffer中存在未傳送的資料(overflowdata),這時可以將呼叫afterGettingFrame1函式進行後續處理工作。2).buffer不存在資料,這時需要呼叫source上的getNextFrame函式獲取資料。getNextFrame呼叫時,引數中有兩個回撥用函式:afterGettingFrame函式將在獲取到資料後呼叫,其中只是簡單的呼叫了afterGettingFrame1函式而已;ourHandleClosure函式將在資料已經處理完畢時呼叫,如檔案結束。可以看出,兩種情況下最後都是要呼叫
afterGettingFrame1函式的複雜之處在於處理frame的分片,若一個frame大於TCP/UDP有效載荷(程式中定義為1448個位元組),就必需分片了。最簡單的情況就是一個packet(RTP包)中最多隻充許一個frame,即一個RTP包中存在一個frame或者frame的一個分片,H264就是這樣處理的:方法是將剩餘的資料記錄為buffer的溢位部分。下次呼叫packFrame函式時,直接從溢位部分複製到packet中。不過應該注意,一個frame的大小不能超過buffer的大小(預設為60000),否則會真的溢位,那就應該考慮增加buffer大小了。
處理完相關分片資訊,將會呼叫函式MultiFramedRTPSink::sendPacketIfNecessary()來發送資料包。sendPacketIfNecessary()中函式處理一些傳送的細節,如packet中含有Frame則呼叫RTPInterface::sendPacket函式傳送packet。並將下一次RTP的傳送操作加入到任務排程器中:nextTask() = envir().taskScheduler().
scheduleDelayedTask。函式引數中傳遞了sendNext函式指標。sendNext函式又呼叫了buildAndSendPacket函式,輪迴了。。。!
最後來看下RTPInterface::sendPacket函式。若是使用UDP方式傳送,將呼叫Groupsock::output函式,可以實現組播功能。groupsock只實現了UDP傳送功能,當用TCP方式傳送時呼叫sendRTPOverTcP函式,這個函式中直接呼叫socket的send函式。至此關於RTP打包傳送的主要流程分析就差不多了,具體細節實現,可參考原始碼。
TCP方式 (sendRTPOverTcP)
VLC :工具->首選項->輸入/編解碼器
VLC設定RTP over RTSP (TCP):SETUP 為RTP/AVP/TCP
- 11-30 09:55:22.878: I/RTSPServer_jni(801): [live555android.cpp:551 jint Java_com_eques_device_ui_hardware_RTSPJNI_ReadVideoData(JNIEnv*, jobject, jbyteArray, jint)]: <ycs>video ! packet->insize 1363
- 11-30 09:55:22.904: I/RTSPServer_jni(801): [RTSPServer.cpp:919 void RTSPServer::RTSPClientConnection::handleRequestBytes(int)]: RTSPClientConnection[0x5557a458]::handleRequestBytes() read 162 new bytes:SETUP rtsp://192.168.0.100:8554/1/trackID=1 RTSP/1.0
- 11-30 09:55:22.904: I/RTSPServer_jni(801): CSeq: 3
- 11-30 09:55:22.904: I/RTSPServer_jni(801): User-Agent: LIVE555 Streaming Media v2012.01.13
- 11-30 09:55:22.904: I/RTSPServer_jni(801): Transport: RTP/AVP/TCP;unicast;interleaved=0-1
- 11-30 09:55:22.904: I/RTSPServer_jni(801):
- 11-30 09:55:22.904: I/RTSPServer_jni(801): [RTSPServer.cpp:1012 void RTSPServer::RTSPClientConnection::handleRequestBytes(int)]: parseRTSPRequestString() succeeded, returning cmdName "SETUP", urlPreSuffix "1", urlSuffix "trackID=1", CSeq "3", Content-Length 0, with 0 bytes following the message.
- 11-30 09:55:22.953: I/RTSPServer_jni(801): [RTSPServer.cpp:1153 void RTSPServer::RTSPClientConnection::handleRequestBytes(int)]: sending response: RTSP/1.0 200 OK
- 11-30 09:55:22.953: I/RTSPServer_jni(801): CSeq: 3
- 11-30 09:55:22.953: I/RTSPServer_jni(801): Date: Thu, Nov 30 2017 01:55:22 GMT
- 11-30 09:55:22.953: I/RTSPServer_jni(801): Transport: RTP/AVP/TCP;unicast;destination=192.168.0.105;source=192.168.0.100;interleaved=0-1
- 11-30 09:55:22.953: I/RTSPServer_jni(801): Session: 0568BD35;timeout=65
UDP方式(Groupsock::output)
VLC :工具->首選項->輸入/編解碼器
VLC設定預設:SETUP 為RTP/AVP
- 11-30 10:12:55.662: I/RTSPServer_jni(800): [RTSPServer.cpp:919 void RTSPServer::RTSPClientConnection::handleRequestBytes(int)]: RTSPClientConnection[0x55d6e008]::handleRequestBytes() read 166 new bytes:SETUP rtsp://192.168.0.100:8554/1/trackID=1 RTSP/1.0
- 11-30 10:12:55.662: I/RTSPServer_jni(800): CSeq: 3
- 11-30 10:12:55.662: I/RTSPServer_jni(800): User-Agent: LIVE555 Streaming Media v2012.01.13
- 11-30 10:12:55.662: I/RTSPServer_jni(800): Transport: RTP/AVP;unicast;client_port=62366-62367
- 11-30 10:12:55.662: I/RTSPServer_jni(800):
- 11-30 10:12:55.662: I/RTSPServer_jni(800): [RTSPServer.cpp:1012 void RTSPServer::RTSPClientConnection::handleRequestBytes(int)]: parseRTSPRequestString() succeeded, returning cmdName "SETUP", urlPreSuffix "1", urlSuffix "trackID=1", CSeq "3", Content-Length 0, with 0 bytes following the message.
- 11-30 10:12:55.684: I/RTSPServer_jni(800): [RTSPServer.cpp:1153 void RTSPServer::RTSPClientConnection::handleRequestBytes(int)]: sending response: RTSP/1.0 200 OK
- 11-30 10:12:55.684: I/RTSPServer_jni(800): CSeq: 3
- 11-30 10:12:55.684: I/RTSPServer_jni(800): Date: Thu, Nov 30 2017 02:12:55 GMT
- 11-30 10:12:55.684: I/RTSPServer_jni(800): Transport: RTP/AVP;unicast;destination=192.168.0.105;source=192.168.0.100;client_port=62366-62367;server_port=6970-6971
- 11-30 10:12:55.684: I/RTSPServer_jni(800): Session: 77D628A6;timeout=65