Live555中RTP包的打包與發送過程分析
這里主要分析一下,live555中關于RTP打包發送的部分。在處理完PLAY命令之后,就開始發送RTP數據包了(其實在發送PLAY命令的response包之前,就會發送一個RTP包,這里傳輸就已經開始了)
先介紹下主要的流程:RTP包的發送是從MediaSink::startPlaying函數調用開始的,在StartPlaying函數的最后會調用函數continuePlaying。
continuePlaying函數是定義在MediaSink類中的純虛函數,需要到特定媒體的sink子類中實現,對于H264來講是在H264VideoRTPSink中實現的。H264VideoRTPSink:continuePlaying中會創建一個輔助類H264FUAFragmenter,用于H264的RTP打包。因為H264的RTP包,有些特殊需要進一步處理。接著調用其父類MultiFramedRTPSink::continuePlaying實現。
在函數MultiFramedRTPSink::continuePlaying中主要是調MultiFramedRTPSink::buildAndSendPacket函數。
看名字就知道MultiFramedRTPSink::buildAndSendPacket()函數將完成打包并發送工作。傳遞了一個True參數,表示這是第一個packet。在該函數的最后調用了MultiFramedRTPSink::packFrame() ,進一步的工作,在packFrame函數中進行,
MultiFramedRTPSink::packFrame() 將為RTP包填充數據。packFrame函數需要處理兩種情況:
1).buffer中存在未發送的數據(overflow data),這時可以將調用afterGettingFrame1函數進行后續處理工作。2).buffer不存在數據,這時需要調用source上的getNextFrame函數獲取數據。getNextFrame調用時,參數中有兩個回調用函數:afterGettingFrame函數將在獲取到數據后調用,其中只是簡單的調用了afterGettingFrame1函數而已;ourHandleClosure函數將在數據已經處理完畢時調用,如文件結束。可以看出,兩種情況下最后都是要調用afterGettingFrame1函數,
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發送功能
RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成