接下来,就是主循环了。在循环中,将会发送包含160个字节的负载数据包。接着就是数据的处理,这部分将会在后面介绍,然后我们等待20ms,检查60s的时间是否过去。
bool done = false; while(!done) { status = session.SendPacket(silencebuffer, 160); if(status < 0) { std::cerr<<RTPGetErrorString(status)<<std::endl; exit(-1); } //在此检查接收的数据 RTPTime::Wait(delay); RTPTime t = RTPTime::CurrentTime(); t -= starttime; if(t > RTPTime(60.0)) done = true; } |
关于会话参与者的信息,包的取回等需要在调用RTPSession的成员函数BeginDataAccess和EndDataAccess之间完成,这样才可保证后台线程不会修改你正在获取的数据。我们使用函数GotoFirstSource和GotoNextSource来迭代遍历所有的参与者。当前选择的参与者的数据包可以使用函数GetNextPacket成员函数来获取,该成员函数返回一个指向RTPPacket类对象的指针。当不再需要数据包时,需要(手动)释放。关于接收数据的处理如下:
session.BeginDataAccess(); if(session.GotoFirstSource()) { do { RTPPacket *packet = session.GetNextPacket(); if(packet) { std::cout<<”got packet with extended sequence number ” <<packet->GetExtendedSequenceNumber(); <<” from SSRC”<<packet->GetSSRC()<<std::endl; delete packet; } } while(session.GotoNextSource()); } session.EndDataAccess(); |
关于当前选择的源的信息可以通过使用类RTPsession的成员函数GetCurrentSourceInfo来获取。该函数返回一个指向类RTPSourceData对象的指针,RTPSourceData类中包含了所有关于源的信息,如:源的发送报告,接收报告,SDES信息等。关于RTPSourceData类的详细信息参见 3.2.15节。
当主循环结束后,我们发送一个BYE包来通知会话的其他参与者,告知我们的离开,然后清理RTPSession类。并且我们想等待10s钟来保证BYE包的发送,当然也可以直接离开会话而不发送BYE包。
delay = RTPTime (10.0); session.BYEDestroy(delay, “Time’s up”, 9); |
程序的完整代码由example2.cpp给出,并且在下面给出,更多关于RTPSession的信息可以参考从 3.2.21节。
【译注:下面的例子是3.9.0版中给的example2.cpp,与英文手册中3.5.2版的例子略有不同】
#include "rtpsession.h"
#include "rtpsessionparams.h"
#include "rtpudpv4transmitter.h"
#include "rtpipv4address.h"
#include "rtptimeutilities.h"
#include "rtppacket.h"
#include <stdlib.h>
#include <iostream>
using namespace jrtplib;
int main(void)
{
#ifdef WIN32
WSADATA dat;
WSAStartup(MAKEWORD(2,2),&dat);
#endif // WIN32
RTPSession session;
RTPSessionParams sessionparams;
sessionparams.SetOwnTimestampUnit(1.0/8000.0);
RTPUDPv4TransmissionParams transparams;
transparams.SetPortbase(8000);
int status = session.Create(sessionparams,&transparams);
if (status < 0)
{
std::cerr << RTPGetErrorString(status) << std::endl;
exit(-1);
}
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);
}
session.SetDefaultPayloadType(96);
session.SetDefaultMark(false);
session.SetDefaultTimestampIncrement(160);
uint8_t silencebuffer[160];
for (int i = 0 ; i < 160 ; i++)
silencebuffer[i] = 128;
RTPTime delay(0.020);
RTPTime starttime = RTPTime::CurrentTime();
bool done = false;
while (!done)
{
status = session.SendPacket(silencebuffer,160);
if (status < 0)
{
std::cerr << RTPGetErrorString(status) << std::endl;
exit(-1);
}
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();
RTPTime::Wait(delay);
RTPTime t = RTPTime::CurrentTime();
t -= starttime;
if (t > RTPTime(60.0))
done = true;
}
delay = RTPTime(10.0);
session.BYEDestroy(delay,"Time's up",9);
#ifdef WIN32
WSACleanup();
#endif // WIN32
return 0;
}
【to be continued!】