jrtplib的文档翻译

1 从RTPSession类开始

所有的类和函数都是jrtplib名字空间的一部分,为了简化代码,我们声明我们使用的是如下的名字空间:

using namespace jrtplib;

为了使用RTP,首先要创建一个RTPSession对象.这个构造函数接受两个参数:一个RTPRandom类的实例,一个RTPMemoryManager类的实例.现在,我们使用最简单的默认的设置,如下:

RTPSession session;

1.1 创建Session

调用带有三个参数的Create函数.

参数1

RTPSessionParams类型.指定这个session的大概的选项.这个类里面的一个参数必须要设置好,否则session就会创建失败.就是你要发送的数据的时间戳的单位,这个参数可以用一个时间段内的采样数去除以这个时间段的长度.因此,假设我们要发送一个8000Hz的语音数据,可以用如下的代码:

RTPSessionParams sessionParams;
sessionParams.SetOwnTimestampUnit(1.0/8000.0);

参数2

这个参数就真的取决于你想要一起用的RTP profile.

它是一个指向RTPTransmissionParams实例的指针,并且为传输部分描述参数.

参数3

选择要使用的传输组件,默认情况下,使用UDP通过IPV4的transmitter,并且对于这个特定的transmitter,那么参数2中的传输参数应该设为RTPUDPv4TransmissionParams类型的.因此,假设我们使用8000端口,我们可以使用如下的代码:

RTPUDPv4TransmissionParams transparams;
 
 transparams.SetPortbase(8000);

现在我们可以调用RTPSession类的Create成员函数,代码如下:

int status = session.Create(sessionparams,&transparams); if (status < 0)
 {
        std::cerr << RTPGetErrorString(status) << std::endl;
        exit(-1);
 }

如果Create函数出错,那么返回一个负值,它指出出错了.可以用RTPGetErrorString()函数来获得.

当session创建成功了,此时,要设置RTP和RTCP数据要发送的目的地.这是通过调用RTPSession的成员函数AddDestination来实现的.这个函数带一个RTPAddress类型的参数,RTPAddress是一个抽象类,对于UDP通过IPV4的transmitter,真正的子类是RTPIPv4Address.假设把数据向运行在9000端口的进程发送,那么代码如下:

 uint8_t localip[]={127,0,0,1};
 RTPIPv4Address addr(localip,9000);

 status = session.AddDestination(addr); if (status < 0)
 {
        std::cerr << RTPGetErrorString(status) << std::endl;
        exit(-1);
 }

如果这个库是用JThread支持编译的,那么收到的数据是在后台处理的.以下两种情况:

A JThread支持没有在编译时使能

B 在session参数中指定不使用poll线程

下,必须使用RTPSession的成员函数Poll来处理到达的数据并且必要时发送RTCP数据.

现在,我们先假定我们使能了poll线程.

假设在一分钟内,我们想要发送包含20ms(160个采样)的silence,并且我们想要当一个从其他地方来的包被接收的时候能够被指出来.同样假定我们有L8数据,并且要使用负荷类型为96.首先,我们将要设定一些默认值:

 session.SetDefaultPayloadType(96);
 session.SetDefaultMark(false);
 session.SetDefaultTimestampIncrement(160);

下一步,我们要创建包含160个silence采样的缓冲区,并且创建一个表示20ms的RTPTime实例.我们也保存当前时间,这样我们可以知道何时1分钟已经走完了.

uint8_t silencebuffer[160]; 
 for (int i = 0 ; i < 160 ; i++)
        silencebuffer[i] = 128;
 
 RTPTime delay(0.020);
 RTPTime starttime = RTPTime::CurrentTime();

下一步,是主循环.这个循环中,要发送一个包含160字节的负载数据.然后,数据处理开始进行,这个稍后阐述.最终,我们等待20ms并检测是否60s已经过去.

 bool done = false;
 while (!done)
 {
        status = session.SendPacket(silencebuffer,160);        
        if (status < 0)
        {
                std::cerr << RTPGetErrorString(status) << std::endl;
                exit(-1);
        }        
        //
        // Inspect incoming data here
        //
        
        RTPTime::Wait(delay);
        
        RTPTime t = RTPTime::CurrentTime();
        t -= starttime;        
        if (t > RTPTime(60.0))
                done = true;
 }

关于会话参与者的信息,以及获得包等的信息,都必须在调用成员函数BeginDataAccess和EndDataAccess之间完成.这样可以保证后台线程不会在你在访问数据的时候,同时改变你的数据.我们逐个访问会话的参与者通过GotoFirstSource和GotoNextSource成员函数.从当前选中的参与者中取得数据包,可以通过成员函数GetNextPacket,这个函数可以返回一个指向RTPPacket类的实例的指针.当你不再需要这个packet的时候,你要delete它.处理到达的数据的过程可以如下:

session.BeginDataAccess(); 
if (session.GotoFirstSource())
 {        
       do
        {
                RTPPacket *packet;                
                while ((packet = session.GetNextPacket()) != 0)
                {
                        std::cout << "Got packet with extended sequence number " 
                                  << packet->GetExtendedSequenceNumber() 
                                          << " from SSRC " << packet->GetSSRC() 
                                          << std::endl;
                        session.DeletePacket(packet);
                }
        } while (session.GotoNextSource());
 }
 session.EndDataAccess();

当前选中的源的信息可以通过GetCurrentSourceInfo成员函数RTPSession类的来获取.这个函数返回一个指针指向RTPSourceData的指针,这个对象包括了所有的关于source的信息:从那个源来的sender reports,receiver reports,SDES信息等等.

当主循环结束的时候,我们发送一个BYE包来告诉其他参与者我们的分离,并且清理RTPSession类.同样我们需要等最多10s来让BYE包被发送出去,否则,我们只是简单地离开会话,而没有发送BYE包.

 delay = RTPTime(10.0);
 session.BYEDestroy(delay,"Time's up",9);



2 错误码

除非特地指定的,否则都是0或者正返回值表示成功,负值表示出错.可以用RTPGetErrorString获取.

3 内存管理

可以通过继承RTPMemoryManager来写自己的内存管理类.下面是一个简化的实现代码:

class MyMemoryManager : public RTPMemoryManager
 { public:
        MyMemoryManager() { }
        ~MyMemoryManager() { }        
        void *AllocateBuffer(size_t numbytes, int memtype)
        {                return malloc(numbytes);
        }        void FreeBuffer(void *p)
        {
                free(p);
        }
 };

在RTPSession类的构造函数中,可以指定想要使用这个内存管理:

MyMemoryManager mgr;
 RTPSession session(0, &mgr);

此时,所有的内存分配和声明都可以通过使用mgr的AllocateBuffer和FreeBuffer来完成.

你可能感兴趣的:(jrtplib的文档翻译)