java调用jrtplib,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 

{

std::cerr <

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 

{

std::cerr <

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 

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 

{

std::cerr <

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 <

<GetExtendedSequenceNumber()

<GetSSRC()

<

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来完成.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值