jrtplib 使用

查了不少网页,自己又折腾了一段时间,终于可以实现视频的传输了。我用的是jrtplib3.7.1发送和接收rtp包

发送端:

 

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
//#include "jrtplib3/rtpsession.h"
#include "rtpsession.h"
#include "rtppacket.h"
#include "rtpudpv4transmitter.h"
#include "rtpipv4address.h"
#include "rtpsessionparams.h"
#include "rtperrors.h"
#include "qdebug.h"

#include "rtpsender.h"
RTPTime delay (0.0001);

#define PacketMaxsize 1400
//#define PacketMaxsize 64000
RtpSender::RtpSender()
{

   portbase=8000;//本地端口
    destIP="127.0.0.1";
    destip=inet_addr( destIP.toStdString().c_str() );               
   destip = ntohl(destip);
   destport=9000;


   ret =0;
   done= false;
   sendbyte=0;
   isCreat = false;
printf("send init ok/n");


}
RtpSender::~RtpSender()
{
}

// 错误处理函数
void RtpSender::checkerror(int err)
{
  if (err < 0)
  {
    std::cout << "ERROR: " << RTPGetErrorString(err) << std::endl;
    exit(-1);
  }
}


void RtpSender::initRtp()
{
  if(isCreat=true)
     sess.BYEDestroy(RTPTime(1,0),0,0);
 
  RTPSessionParams sessParams;
  sessParams.SetOwnTimestampUnit(1.0 / 90000.0); //90000 samples per second
  sessParams.SetUsePollThread(1); //background thread to call virtual callbacks - set by default, but just to be sure
  sessParams.SetMaximumPacketSize(64000);


 //setup transmission parameters
 RTPUDPv4TransmissionParams transParams;
 transParams.SetPortbase(portbase);

  // 创建RTP会话
  err_status = sess.Create(sessParams,&transParams);
  checkerror(err_status);

  // 指定RTP数据接收端

  RTPIPv4Address addr(destip,destport);
  err_status = sess.AddDestination(addr);
  checkerror(err_status);

  isCreat = true;
 /*
      qDebug() << "destIP:" << destIP;
        qDebug() << "destort: " << destport;
        qDebug() << "portbase: " << portbase;
*/
}

 

int RtpSender::m_sendPacket(unsigned char*data,int framelength)
{

  //RTPSession sess;
  // 发送流媒体数据
  sendbyte=0;
  done= false;
 do
  {
//printf("here?/n"); 
  
    if(framelength>PacketMaxsize)//需要分包
     {

         ret = sess.SendPacket(data,PacketMaxsize,96,0,1000);
     
 checkerror(ret);
         data = data + PacketMaxsize;  //update发送指针
         framelength = framelength - PacketMaxsize;
         sendbyte = sendbyte + PacketMaxsize;
//printf("divide packet/n");

     }
     else
     {
     
        ret= sess.SendPacket(data,framelength,96,1,1000);   //发送函数 第四个参数marker决定是否是该frame最后小于1400的数据
          
          checkerror(ret);
          done = true;                                                     //如果是 表示完成
          sendbyte = framelength;
//printf("send a paket/n");
     }
     RTPTime::Wait (delay);
    // RTPTime::Wait(RTPTime(1,0));
 #ifndef RTP_SUPPORT_THREAD
  status = sess.Poll();
  checkerror(status);

     #endif // RTP_SUPPORT_THREAD
  
  } while(!done);

  return sendbyte;
}

初始化rtp参考jrtplib自带的example和网页上的方法,我自己分包发送的,分包好处是接收时可以减少丢包。

接收端主要代码:

void RtpReceiver::m_receiPacket(unsigned char* recvpointer)
{
   RTPIPv4Address* addr;
   int nPort;

 

#ifndef RTP_SUPPORT_THREAD
  err_status = sess.Poll();//必要时发送rtcp
      checkerror(err_status);

#endif
      //标志位应放在循环外,保证每次都被设置
       packetflage = false;   
       DecodeEnable = false;
       recvlength =0;     //初始化接收数据 以及数据接收标示
    

      // 检索RTP数据源
   sess.BeginDataAccess();
   if (sess.GotoFirstSourceWithData() )
   {  
//printf("Begin receive/n");
    do
    {
        RTPPacket* packet;
       // RTPSourceData *srcdata;
        // 获取RTP数据报
        while ((packet = sess.GetNextPacket()) != NULL && packetflage==false) //标示为零 接收同一packet的剩余数据
        { 
            if(processpacket(recvpointer,*packet))//processpacket() 返回1 已经接受到所有的packet 可以调用解码
             {
                  packetflage =true;
                  recv_one_length=recvlength;
                  DecodeEnable =true;

             }
            else
               {
                   packetflage = false;   //返回0,packet还没接受完 继续sess.GetNextPacket()
                   DecodeEnable = false;
                }

             sess.DeletePacket(packet);// 删除RTP数据报
             
             RTPTime::Wait(RTPTime(0,1000));
          }
    /*
         //定义信号
         emit receive_done();
*/
      } while (sess.GotoNextSourceWithData());   //接收另一个packet
         
    }//end if()
   
      sess.EndDataAccess();
       // 接受RTP数据


//printf("receive end/n");
    
}

 

int RtpReceiver::processpacket(unsigned char* recvpointer,const RTPPacket &rtppack)
{
     unsigned char* payloadpointer = rtppack.GetPayloadData();    //接收该数据包数据
     bool packetmarker = rtppack.HasMarker();   //察看部否是已经传完该数据包 Returns true is the marker bit was set

    if(!packetmarker)   //未传完数据包
   {
     memcpy(recvpointer+recvoffset,payloadpointer,rtppack.GetPayloadLength());
     recvlength += rtppack.GetPayloadLength();
     recvoffset += rtppack.GetPayloadLength();  //更新接收数据保存的指针
//printf("not one packet/n");
     RecvOneflage = 0;   //标示接受位 继续执行sess.GetNextPacket()    
   }
   else
   {
     memcpy(recvpointer +recvoffset,payloadpointer,rtppack.GetPayloadLength());
     recvlength += rtppack.GetPayloadLength();
     recvoffset = 0;                     //传完,初始化
//printf("one packet received/n");    
    RecvOneflage =1;

   }
   return RecvOneflage;
}

      接收端我用一个线程不停调用m_receiPacket()函数,接收到一个完整的RTP包即一帧图像后,设置解码标志,在线程中解码,保证

接收->完整RTP->解码的顺序。一开始,我的标志位没设好,结果接到的图像花屏很严重。还以为是丢包很严重造成的。实际上没有满足上述顺序,解码了多次。

     最后的效果不错,局域网内很清楚,下一步移植到板子上试试。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值