日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

jrtplib笔记

發布時間:2024/8/1 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 jrtplib笔记 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉自:
jrtplib 筆記(1) - CSDN博客
https://blog.csdn.net/alajl/article/details/5419489
最近要實現 non-compound rtcp(http://tools.ietf.org/html/draft-ietf-avt-rtcp-non-compound-02 )

因為我們使用的是 jrtplib 這個開源的包,這個包把 RTCP 的處理都封裝好了,所以用戶不用去過多的關心,但是我們要實現上述的功能,所以必須要修改這 個開源庫關于 RTCP 處理部分的源代碼,所以就花了一些時間,仔細的閱讀了它,但是相關的文檔不是很多,所以就只能靠自己去理解了啊。

在修改 RTCP 的實現時,我們有必要了解一下,原有 RTCP 的實現,所以我們就從下面開始了

在整個代碼 里, RTPSession 這個對象是用戶接觸到最多的,在我們的實現中,我們用到了 RtpApp 這個類(這個對象是我們自己實現的,開源庫是沒有的) , 我們用 pollData ()輪詢所有收到的數據,代碼如下

void RtpApp::pollData() // 輪詢所有數據
{
if(mSession == NULL)
return;

mSession->Poll(); mSession->BeginDataAccess();if(mSession->GotoFirstSourceWithData() == false) {// if theres no data, sleep 1msmSession->EndDataAccess();RTPTime::Wait(RTPTime(0, 1000)); } else {// process the datado{RTPPacket *pkt;while ((pkt = mSession->GetNextPacket()) != NULL){// 處理收到的數據 }} while(mSession->GotoNextSourceWithData()); // 到下一個 sourcemSession->EndDataAccess(); }

}

其中我們用到了 mSession->Poll(); 這個方法 用于輪詢所有的數據。這個方法是 RTPSession 里對數據處理的主要方法,務必要弄明白它的原理,代碼如下 :

int RTPSession::Poll() {

int status;if (!created)return ERR_RTP_SESSION_NOTCREATED;if (usingpollthread)return ERR_RTP_SESSION_USINGPOLLTHREAD;

/*

真正的對 socket 的操作,它把接受到的 RTP 和 RTCP 數據分別放到相應的隊列里( awpacketlist 隊列),并在 ProcessPolledData () 里處理了對應隊列里的數據

*/

if ((status = rtptrans->Poll()) < 0) return status;return ProcessPolledData(); // 處理收到的數據,對應于 RFC3550 的邏輯部分

}

ProcessPolledData ()這個東東,里面的邏輯是相當多的,因為它處理了所有收到的 RTP 和 RTCP 包,并且根據協議對一些回復 RTCP 包的處理也在這個方法里,所以要修改 RTCP 包,那么這個方法就是切入點了。

在方法里,我們看到了一個循環,毫無疑問,這個東東就是遍歷 rtptrans->Poll() 所收到的包,它放在了一個隊列里( RTP 和 RTCP 都在同一個隊列)

while ((rawpack = rtptrans->GetNextPacket()) != 0) {

……

}

那我們來一一分析,這個 while 循環所干的東西 :)

int RTPSession::ProcessPolledData() {

RTPRawPacket *rawpack;int status;SOURCES_LOCKwhile ((rawpack = rtptrans->GetNextPacket()) != 0) {sources.ClearOwnCollisionFlag();// 清除了 SSRC 的沖突標記,因為根據 RFC3550, 如果 SSRC 沖突的話,應該要發送 //BYE 包的,所以,先上這個標記回到初始值。 // since our sources instance also uses the scheduler (analysis of incoming packets)// we'll lock itSCHED_LOCK

// 這東東對收到的 RTP 和 RTCP 包進行處理,例如建立 SSRC , CCRC 隊列和

//SSRC 沖突標記、許多變量值的設置等等。

if ((status = sources.ProcessRawPacket(rawpack, rtptrans, acceptownpackets)) < 0) {SCHED_UNLOCKSOURCES_UNLOCKRTPDelete(rawpack, GetMemoryManager());return status;}SCHED_UNLOCK// 檢查是否 SSRC 產生了沖突,如果檢測到的沖突,那么就應當發送 BYE 包了 if (sources.DetectedOwnCollision()) // collision handling!{printf("if collision/n");bool created;// created 的值決定了我們是否需要發送 BYE 包,如果沖突列表里,有了對應

// 的地址,那么將不發送 BYE 包,否則發送

if ((status = collisionlist.UpdateAddress(rawpack->GetSenderAddress(), rawpack->GetReceiveTime(), &created)) < 0) {printf("if collisionlist updateAddress/n");SOURCES_UNLOCKRTPDelete(rawpack, GetMemoryManager());return status;}// 需要生成一個新的 BYE 包 if (created){ // change our own SSRCprintf("if created/n");PACKSENT_LOCKbool hassentpackets = sentpackets;PACKSENT_UNLOCK// 如果我們已經用沖突的 SSRC 發送了 RTP 數據,那么就生成一個新的 //BYE 包,如果沒有發送 RTP 的數據,那么這個時候發送 BYE 包是沒有 // 意義的 if (hassentpackets) {// Only send BYE packet if we've actually sent data using this// SSRCprintf("if hassentpackets/n");RTCPCompoundPacket *rtcpcomppack;BUILDER_LOCK// 生成一個新的 BYE 包 if ((status = rtcpbuilder.BuildBYEPacket(&rtcpcomppack, 0, 0, useSR_BYEifpossible)) < 0) {printf("buildbytpacket/n");BUILDER_UNLOCKSOURCES_UNLOCKRTPDelete(rawpack, GetMemoryManager());return status;}BUILDER_UNLOCK// 推入隊列 byepackets.push_back(rtcpcomppack);if (byepackets.size() == 1) // was the first packet, schedule a BYE packet (otherwise there's already one scheduled){printf("bytepacketssize==1/n");SCHED_LOCKrtcpsched.ScheduleBYEPacket(rtcpcomppack->GetCompoundPacketLength());SCHED_UNLOCK}}// bye packet is built and scheduled, now change our SSRC// and reset the packet count in the transmitterBUILDER_LOCK// 生成新的 SSRCuint32_t newssrc = packetbuilder.CreateNewSSRC(sources);BUILDER_UNLOCKPACKSENT_LOCKsentpackets = false;PACKSENT_UNLOCK// 刪除舊的 SSRCif ((status = sources.DeleteOwnSSRC()) < 0) {printf("sources.DeleteOwnSSRC/n");SOURCES_UNLOCKRTPDelete(rawpack, GetMemoryManager());return status;}// 綁定新的 SSRCif ((status = sources.CreateOwnSSRC(newssrc)) < 0) {printf("sources.CreateOwnSSRC/n");SOURCES_UNLOCKRTPDelete(rawpack, GetMemoryManager());return status;}}}RTPDelete(rawpack, GetMemoryManager());}//end whileSCHED_LOCKRTPTime d = rtcpsched.CalculateDeterministicInterval(false);SCHED_UNLOCKRTPTime t = RTPTime::CurrentTime();double Td = d.GetDouble();RTPTime sendertimeout = RTPTime(Td * sendermultiplier);RTPTime generaltimeout = RTPTime(Td * membermultiplier);RTPTime byetimeout = RTPTime(Td * byemultiplier);RTPTime colltimeout = RTPTime(Td * collisionmultiplier);RTPTime notetimeout = RTPTime(Td * notemultiplier);sources.MultipleTimeouts(t, sendertimeout, byetimeout, generaltimeout, notetimeout);collisionlist.Timeout(t, colltimeout);// We'll check if it's time for RTCP stuffSCHED_LOCKbool istime = rtcpsched.IsTime(); // 計算是否到了發送 RTCP 的時間SCHED_UNLOCKif (istime) {printf("istime/n");RTCPCompoundPacket *pack;// we'll check if there's a bye packet to send, or just a normal packetif (byepackets.empty()) { // 沒有 BYE 包發送就發送正常的 RTCP 包printf("byepacket empty and send RTCP packet/n");

// 是否支持 non-compound 的發送

if (allowNonCompoundRTCP == false) {BUILDER_LOCKprintf("rtcpbuilder.BuildNextPacket with compound/n");// 生成一個新的 RTCP 包 if ((status = rtcpbuilder.BuildNextPacket(&pack)) < 0) {BUILDER_UNLOCKSOURCES_UNLOCKreturn status;}}else if (allowNonCompoundRTCP == true) { if (firstSendRTCP) {BUILDER_LOCKprintf("rtcpbuilder.BuildNextPacket with compound/n");

// 生成一個新的 RTCP 包,根據協議,發送 non-compound 之前,必 // 須保證有一個 compound 的包已經發送

if ((status = rtcpbuilder.BuildNextPacket(&pack)) < 0) {BUILDER_UNLOCKSOURCES_UNLOCKreturn status;}}else {BUILDER_LOCKprintf("rtcpbuilder.BuildNextPacket with non-compound/n");// 生成一個新的 non compound RTCP 包if ((status = rtcpbuilder.BuildNextPacketWithNonCompound(&pack)) < 0) {BUILDER_UNLOCKSOURCES_UNLOCKreturn status;}}firstSendRTCP = false;}BUILDER_UNLOCK// 通過底層 socket ,發送出去咯 if ((status = rtptrans->SendRTCPData(pack->GetCompoundPacketData(), pack->GetCompoundPacketLength())) < 0) {printf("rtptrans->SendRTCPData error!/n");SOURCES_UNLOCKRTPDelete(pack, GetMemoryManager());return status;}PACKSENT_LOCKsentpackets = true;PACKSENT_UNLOCKOnSendRTCPCompoundPacket(pack); // we'll place this after the actual send to avoid tampering} else { // 如果 BYE 隊列不為空,優先發送 BYE 包printf("byepacket empty else/n");pack = *(byepackets.begin());byepackets.pop_front();if ((status = rtptrans->SendRTCPData(pack->GetCompoundPacketData(), pack->GetCompoundPacketLength())) < 0) {printf("rtptrans->SendRTCPData error!/n");SOURCES_UNLOCKRTPDelete(pack, GetMemoryManager());return status;}PACKSENT_LOCKsentpackets = true;PACKSENT_UNLOCKOnSendRTCPCompoundPacket(pack); // we'll place this after the actual send to avoid tamperingif (!byepackets.empty()) // more bye packets to send, schedule them{printf("byepackets.empty/n");SCHED_LOCK rtcpsched.ScheduleBYEPacket((*(byepackets.begin()))->GetCompoundPacketLength());SCHED_UNLOCK}}SCHED_LOCKrtcpsched.AnalyseOutgoing(*pack);SCHED_UNLOCKRTPDelete(pack, GetMemoryManager());}SOURCES_UNLOCKreturn 0;

}

總結

以上是生活随笔為你收集整理的jrtplib笔记的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。