jrtplib V3.11.1 收包流程

xiaoxiao2021-02-28  73

       最近在看 jrtplib的收包流程,看了这篇文章 jrtplib接收数据包流程 ,只是用的库老了点 V3.7 的,写的也太长了,不够简练,于是自己写一份

         V3.11.1的简练点的收包流程说明,捡重点,无关的流程略过。

RTP包的接收入口函数 int RTPSession::Poll() {    if ((status = rtptrans->Poll()) < 0)    // 流程一, 默认调用 RTPUDPv4Transmitter::Poll() // 处理收到的buffer,转为元数据,存入容器

    return ProcessPolledData();          // 流程二,将元数据解析为 RTP或RTCP包,分别处理之 }

     ————————————— 流程(一) 的剖析  ————————————– 说明: rtptrans是RTPSession类的成员变量,默认是Rtpudpv4transmitter类,它实现了rtp包以及rtcp包的收发工作 步骤1,分别从 rtpsock 和 rtcpsock 收数据 int RTPUDPv4Transmitter::Poll() { status = PollSocket(true); // poll RTP socket   if (rtpsock != rtcpsock) // no need to poll twice when multiplexing    {         if (status >= 0)         status = PollSocket(false); // poll RTCP socket   } } 步骤2 int RTPUDPv4Transmitter::PollSocket(bool rtp) { // 收rtp或rtcp包 recvlen = recvfrom(sock,packetbuffer,RTPUDPV4TRANS_MAXPACKSIZE,0,(struct sockaddr *)&srcaddr,&fromlen); // 收到的buffer构建元数据 pack = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTPRAWPACKET)RTPRawPacket(datacopy,recvlen,addr,curtime,rtp,GetMemoryManager()); // 将元数据存入队列 rawpacketlist.push_back(pack); }

————————————— 流程(二) 的剖析  ————————————– 步骤1 int RTPSession::ProcessPolledData() {  while ((rawpack = rtptrans->GetNextPacket()) != 0)  {     //内部遍历并解析元数据,得到RTPPacket包     if ((status = sources.ProcessRawPacket(rawpack,rtptrans,acceptownpackets)) < 0)  }          // 下面是发送rtcp相关的,没研究过    status = rtcpbuilder.BuildNextPacket(&pack)    Status=rtptrans->SendRTCPData(pack->GetCompoundPacketData(),pack->GetCompoundPacketLength()) //发送rtcp包 } 步骤2,内部解析元数据,判断是RTP还是RTCP包,然后分别处理 int RTPSources::ProcessRawPacket(RTPRawPacket *rawpack ) {      步骤2.1 解析源数据, 得到RTPPacket包,如果你测试发送的是字符串,就可以看到payload属性的值了"1234456789AB"     rtppack = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTPPACKET) RTPPacket(*rawpack,GetMemoryManager());     步骤2.2  处理RTP包     if ((status = ProcessRTPPacket(rtppack,rawpack->GetReceiveTime(),0,&stored)) < 0)     步骤2.3  处理RTCP包     status = ProcessRTCPCompoundPacket(&rtcpcomppack,rawpack->GetReceiveTime(),0);     {          在函数内部,根据遍历RTCP包,根据包类型分别处理         SR, /**< An RTCP sender report. */                 RR, /**< An RTCP receiver report. */                 SDES, /**< An RTCP source description packet. */        BYE, /**< An RTCP bye packet. */                 APP, /**< An RTCP packet containing application specific data. */                 Unknown /**< The type of RTCP packet was not recognized. */     }     // 注意把元数据解析成RTPpacket的函数如下     int RTPPacket::ParseRawPacket(RTPRawPacket &rawpack) } 步骤2.2 int RTPSources::ProcessRTPPacket( {    // 虚函数,什么都没干,可扩展    OnRTPPacket(rtppack,receivetime,senderaddress);    // 步骤2.2.1,构建 RTPInternalSourceData对象    if ((status = ObtainSourceDataInstance(ssrc,&srcdat,&created)) < 0)    // 步骤2.2.2, 内部调用 RTPInternalSourceData::ProcessRTPPacket( ) 函数来处理 .  RTP数据收包处理到此结束

   if ((status = srcdat->ProcessRTPPacket(rtppack,receivetime,stored,this)) < 0)    {         //内部按序列号用容器存储,最多存32个 packetlist.push_front(rtppack);       packetlist.insert(it,rtppack);    }    // 步骤2.2.3, 内部循环处理CSRC数组,没研究过    for (i = 0 ; i < num ; i++)    {       if ((status = ObtainSourceDataInstance(CSRCs[i],&csrcdat,&createdcsrc)) < 0)    } }  ok,到此RTPSession收RTP包后存入队列,收包流程就结束了,接下来就是处理这些收到的包了,官方示例如下:

      sess.BeginDataAccess(); //同步锁 // check incoming packets // 开始遍历参与者中第一个有RTP数据的流,如果找到了,就返回tree,否则返回false。 //在接收数据时我们常用的是这套函数,因为如果没有数据要来都没用  if (sess.GotoFirstSourceWithData())    {    //实际上是双层嵌套循环,第一层先遍历内部的RTPInternalSourceData对象,rcdat = sourcelist.GetCurrentElement();  do { RTPPacket *pack; // 再遍历该RTPInternalSourceData对象内部的 RTPpacket列表 while ((pack = sess.GetNextPacket()) != NULL) { // You can examine the data here // for test char pBuffer[100] ={0}; memcpy(pBuffer,pack->GetPayloadData(),pack->GetPayloadLength()); printf("Got packet -->%s \n",pBuffer); // 界面打印收到的字符串 // we don't longer need the packet, so // we'll delete it sess.DeletePacket(pack); } } while (sess.GotoNextSourceWithData()); } sess.EndDataAccess();  

转载请注明原文地址: https://www.6miu.com/read-54429.html

最新回复(0)