RTP编程

1、初始化
   在使用 JRTPLIB 进行实时流媒体数据传输之前,首先应该生成 RTPSession 类的一个实例来表示此次 RTP 会话。然后调用 Create() 方法来对其进行初始化操作
    RTPSessionParams  sessparams;

    RTPUDPv4TransmissionParams transparams;

    sessparams.SetOwnTimestampUnit(1.0/10.0);                     //设置时戳发送频率
    sessparams.SetAcceptOwnPackets(true);                     //设置参数为ture,可以接收自己发送的流媒体数据

    transparams.SetPortbase(portbase);                          //设置进行流媒体数据传输或接收的本主机端口

    sess.Create(sessparams, &transparams);                  //创建RTP任务

 

2、数据发送
   (1)、指定目标地址
   RTPIPv4Address  addr(destip, destport);          //声明RTPv4Address的对象addr,并初始化(设置目标地址)

   sess.AddDestination(addr);                                 //指定目标地址

   (2)发送流媒体数据
   SendPacket() 是 RTPSession 类提供的一个重载函数,具有多种形式:
   int SendPacket(void *data,int len);
   int SendPacket(void *data,int len,unsigned char pt,bool mark,unsigned long timestampinc);
   int SendPacket(void *data,int len,unsigned short hdrextID,void *hdrextdata,int numhdrextwords);
   int SendPacket(void *data,int len,unsigned char pt,bool mark,unsigned long timestampinc,unsigned  short hdrextID,void *hdrextdata,int numhdrextwords);


   SendPacket() 最典型的用法是类似于下面的语句,其中第一个参数是要被发送的数据,而第二个参数则指明将要发送数据的长度,再往后依次是 RTP 负载类型、标识和时戳增量。
   sess.SendPacket(buffer, 5, 0, false, 10);
 
   (3)、设置发送数据默认参数
   对于同一个 RTP 会话来讲,负载类型、标识和时戳增量通常来讲都是相同的,JRTPLIB 允许将它们设置为会话的默认参数,这是通过调用 RTPSession 类的SetDefaultPayloadType()、SetDefaultMark() 和 SetDefaultTimeStampIncrement() 方法来完成的。为 RTP 会话设置这些默认参数的好处是可以简化数据的发送,例如,如果为 RTP 会话设置了默认参数:
   sess.SetDefaultPayloadType(0);
   sess.SetDefaultMark(false);
   sess.SetDefaultTimeStampIncrement(10);
 
   之后在进行数据发送时只需指明要发送的数据及其长度就可以了:
   sess.SendPacket(buffer, 5);
 3、接收或发送延时

    RTPTime::Wait(RTPTime(1,0));       //延时10s;
4、数据接收
  (1)、接收函数
   对于流媒体数据的接收端,首先需要调用 RTPSession 类的 PollData() 方法来接收发送过来的 RTP 或者 RTCP 数据报。由于同一个 RTP 会话中允许有多个参与者(源),你既可以通过调用 RTPSession 类的 GotoFirstSource() 和 GotoNextSource() 方法来遍历数据源中的所有数据,也可以通过调用 RTPSession 类的 GotoFirstSourceWithData() 和 GotoNextSourceWithData() 方法来遍历那些携带有数据的源。在从 RTP 会话中检测出有效的数据源之后,接下去就可以调用 RTPSession 类的 GetNextPacket() 方法从中抽取 RTP 数据报,当接收到的 RTP 数据报处理完之后,一定要记得及时释放。下面的代码示范了该如何对接收到的 RTP 数据报进行处理:

   sess.BeginDataAccess();                     //上锁,开始接收RTP数据

   if (sess.GotoFirstSourceWithData()) { 
     do {   
        RTPPacket *pack;    

        while((pack = sess.GetNetPacket()) != NULL) {
              cout <<   pack->GetPayloadLength() << endl;          //打印本次所收到的数据包内容         

              // 处理接收到的数据              

        }
      } while (sess.GotoNextSourceWithData());
   }
  
   (2)、接收设置
   通过调用 RTPSession 类的 SetReceiveMode() 方法可以设置哪些到达的 RTP 数据报将会被接受或拒绝,其参数有:
   RECEIVEMODE_ALL  缺省的接收模式,所有到达的 RTP 数据报都将被接受;
   RECEIVEMODE_IGNORESOME  除了某些特定的发送者之外,所有到达的 RTP 数据报都将被接受,而被拒绝的发送者列表可以通过调用 AddToIgnoreList()、DeleteFromIgnoreList() 和 ClearIgnoreList() 方法来进行设置;
   RECEIVEMODE_ACCEPTSOME  除了某些特定的发送者之外,所有到达的 RTP 数据报都将被拒绝,而被接受的发送者列表可以通过调用 AddToAcceptList ()、DeleteFromAcceptList 和 ClearAcceptList () 方法来进行设置。

5、控制信息
      JRTPLIB 是一个高度封装后的 RTP 库,程序员在使用它时很多时候并不用关心 RTCP 数据报是如何被发送和接收的,因为这些都可以由 JRTPLIB 自己来完成。只要 PollData() 或者SendPacket() 方法被成功调用,JRTPLIB 就能够自动对到达的 RTCP 数据报进行处理,并且还会在需要的时候发送 RTCP 数据报,从而能够确保整个 RTP 会话过程的正确性。
  
      而另一方面,通过调用 RTPSession 类提供的 SetLocalName()、SetLocalEMail()、SetLocalLocation()、SetLocalPhone()、SetLocalTool() 和 SetLocalNote() 方法,JRTPLIB 又允许程序员对RTP会话的控制信息进行设置。所有这些方法在调用时都带有两个参数,其中第一个参数是一个 char 型的指针,指向将要被设置的数据;而第二个参数则是一个 int 型的数值,表明该数据中的前面多少个字符将会被使用。例如下面的语句可以被用来设置控制信息中的电子邮件地址:
   sess.SetLocalEMail("2111@qq.com",11);
  
      通过调用 RTPSession 类提供的 EnableSendName()、EnableSendEMail()、EnableSendLocation()、EnableSendPhone()、EnableSendTool() 和 EnableSendNote() 方法,可以为当前 RTP 会话选择将被发送的控制信息。

 

6、以下是我根据示例写的发送端个接收端的代码

发送端:

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

using namespace std;
#include "../include/jrtplib3/rtpsession.h"
#include "../include/jrtplib3/rtpudpv4transmitter.h"
#include "../include/jrtplib3/rtpsessionparams.h"
#include "../include/jrtplib3/rtpipv4address.h"
#include "../include/jrtplib3/rtperrors.h"
#include "../include/jrtplib3/rtppacket.h"

int checkerror(int err) {
 if (err < 0) {
  string errstr(RTPGetErrorString(err));
  cout << "Error:" << errstr <<endl;
  exit(-1);
 }
 return 0; 
}

int main(void)
{
 RTPSession sess;
 RTPUDPv4TransmissionParams transparams;
        RTPSessionParams sessparams;
 int val;
 char buffer[10] = "123456789";
 unsigned long  destip = ntohl(inet_addr("127.0.0.1"));
 int destport = 6008;
 int portbase = 6002;

 sessparams.SetOwnTimestampUnit(1.0/10.0);       
        sessparams.SetAcceptOwnPackets(true);
        transparams.SetPortbase(portbase);

 val = sess.Create(sessparams, &transparams);
 checkerror(val); 

 RTPIPv4Address addr(destip, destport);
  
 val = sess.AddDestination(addr);
 checkerror(val);
        while(1) {
  val = sess.SendPacket(buffer, sizeof(buffer), 0, false, 10);
  checkerror(val);                                                                  
  cout << "Send packet:"<< buffer << endl;
  
#ifndef RTP_SUPPORT_THREAD
                val = sess.Poll();
                checkerror(val);
#endif // RTP_SUPPORT_THREAD
  RTPTime::Wait(RTPTime(1,0));
 }
 sess.BYEDestroy(RTPTime(10,0),0,0);
 return 0;

 

接收端:

 

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

using namespace std;
#include "../include/jrtplib3/rtpsession.h"
#include "../include/jrtplib3/rtpudpv4transmitter.h"
#include "../include/jrtplib3/rtpsessionparams.h"
#include "../include/jrtplib3/rtpipv4address.h"
#include "../include/jrtplib3/rtperrors.h"
#include "../include/jrtplib3/rtppacket.h"

int checkerror(int err) {
 if (err < 0) {
  string errstr(RTPGetErrorString(err));
  cout << "Error:" << errstr <<endl;
  exit(-1);
 }
 return 0; 
}

int main(void)
{
 RTPSession sess;
 RTPUDPv4TransmissionParams transparams;
        RTPSessionParams sessparams;
 int val;
 int localport = 6008;

 sessparams.SetOwnTimestampUnit(1.0/10.0);       
        sessparams.SetAcceptOwnPackets(true);
        transparams.SetPortbase(localport);

 val = sess.Create(sessparams, &transparams);
 checkerror(val);
 
 while (1) {
         sess.BeginDataAccess();
         if (sess.GotoFirstSourceWithData()) {
                 do {
                         RTPPacket *pack;
                         while ((pack = sess.GetNextPacket()) != NULL) {
                                 cout <<"Got packet!  "
          << pack ->GetExtendedSequenceNumber()
          << "   from SSRC  "
          << pack->GetSSRC()
          << "    Length:   " 
          << pack->GetPayloadLength()
          << "   "
          << pack->GetPayloadData()
          << "  "
          << pack->GetPacketData() << endl;
                                 sess.DeletePacket(pack);
                         }
                 } while (sess.GotoNextSourceWithData());
          }
          sess.EndDataAccess();
 
#ifndef RTP_SUPPORT_THREAD
                val = sess.Poll();
                checkerror(val);
#endif // RTP_SUPPORT_THREAD
  // RTPTime::Wait(RTPTime(1,0));
 }
 sess.BYEDestroy(RTPTime(10,0),0,0);

 return 0;

 

 

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值