转:JRTPLIB

JRTPLIB AuthorJoriLiesenborgsDevelopedatthethe ExpertiseCentreforDigitalMedia(EDM),aresearchinstituteofthe HasseltUniversityIntroductionThisdocumentdescribesJRTPLIB,ano…

大家好,又见面了,我是你们的朋友全栈君。

JRTPLIB

 

Author

Jori Liesenborgs

Developed at the the Expertise Centre for Digital Media (EDM), a research institute of the Hasselt University

Introduction

This document describes JRTPLIB, an object-oriented library written in C++ which aims to help developers in using the Real-time Transport Protocol (RTP) as described in RFC 3550.

The library makes it possible for the user to send and receive data using RTP, without worrying about SSRC collisions, scheduling and transmitting RTCP data etc. The user only needs to provide the library with the payload data to be sent and the library gives the user access to incoming RTP and RTCP data.

Design idea

The library provides several classes which can be helpful in creating RTP applications. Most users will probably only need the RTPSession class for building an application, or derive a class from RTPSecureSession for SRTP support. These classes provide the necessary functions for sending RTP data and handle the RTCP part internally.

Changes from version 2.x

One of the most important changes is probably the fact that this version is based on RFC 3550 and the 2.x versions were based upon RFC 1889 which is now obsolete.

Also, the 2.x series was created with the idea that the user would only need to use the RTPSession class which meant that the other classes were not very useful by themselves. This version on the other hand, aims to provide many useful components to aid the user in building RTP capable applications.

In this version, the code which is specific for the underlying protocol by which RTP packets are transported, is bundled in a class which inherits its interface from a class called RTPTransmitter. This makes it easy for different underlying protocols to be supported. Currently there is support for UDP over IPv4 and UDP over IPv6.

For applications such as a mixer or translator using the RTPSession class will not be a good solution. Other components can be used for this purpose: a transmission component, an SSRC table, an RTCP scheduler etc. Using these, it should be much easier to build all kinds of applications.

Copyright license

The library code uses the following copyright license:

Permission is hereby granted, free of charge, to any person

obtaining a copy of this software and associated documentation files

(the “Software”), to deal in the Software without restriction,

including without limitation the rights to use, copy, modify, merge,

publish, distribute, sublicense, and/or sell copies of the Software,

and to permit persons to whom the Software is furnished to do so,

subject to the following conditions:

The above copyright notice and this permission notice shall be

included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY

KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE

WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND

NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS

BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN

ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN

CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE

SOFTWARE.

There are two reasons for using this license. First, since this is the license of the 2.x series, it only seemed natural that this rewrite would contain the same license. Second, since the RTP protocol is deliberately incomplete RTP profiles can, for example, define additional header fields. The best way to deal with this is to adapt the library code itself and that’s why I like to keep the license as free as possible.

Getting started with the RTPSession class

All classes and functions are part of the jrtplib namespace, so to simplify the code a bit, we’ll declare that we’re using this namespace:

using namespace jrtplib;

To use RTP, you’ll have to create an RTPSession object. The constructor accepts two parameter, an instance of an RTPRandom object, and an instance of an RTPMemoryManager object. For now, we’ll keep it simple and use the default settings, so this is our code so far:

RTPSession session;

To actually create the session, you’ll have to call the Create member function which takes three arguments: the first one is of type RTPSessionParams and specifies the general options for the session. One parameter of this class must be set explicitly, otherwise the session will not be created successfully. This parameter is the timestamp unit of the data you intend to send and can be calculated by dividing a certain time interval (in seconds) by the number of samples in that interval. So, assuming that we’ll send 8000 Hz voice data, we can use this code:

RTPSessionParams sessionparams;

sessionparams.SetOwnTimestampUnit(1.0/8000.0);

The other session parameters will probably depend on the actual RTP profile you intend to work with.

The second argument of the Create function is a pointer to an RTPTransmissionParams instance and describes the parameters for the transmission component. The third parameter selects the type of transmission component which will be used. By default, an UDP over IPv4 transmitter is used, and for this particular transmitter, the transmission parameters should be of type RTPUDPv4TransmissionParams. Assuming that we want our RTP portbase to be 8000, we can do the following:

RTPUDPv4TransmissionParams transparams;

transparams.SetPortbase(8000);

Now, we’re ready to call the Create member function of RTPSession. The return value is stored in the integer status so we can check if something went wrong. If this value is negative, it indicates that some error occurred. A description of what this error code means can be retrieved by calling RTPGetErrorString:

int status = session.Create(sessionparams,&transparams);

if (status < 0)

{

std::cerr << RTPGetErrorString(status) << std::endl;

exit(-1);

}

If the session was created with success, this is probably a good point to specify to which destinations RTP and RTCP data should be sent. This is done by a call to the RTPSession member function AddDestination. This function takes an argument of type RTPAddress. This is an abstract class and for the UDP over IPv4 transmitter the actual class to be used is RTPIPv4Address. Suppose that we want to send our data to a process running on the same host at port 9000, we can do the following:

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);

}

If the library was compiled with JThread support, incoming data is processed in the background. If JThread support was not enabled at compile time or if you specified in the session parameters that no poll thread should be used, you’ll have to call the RTPSession member function Poll regularly to process incoming data and to send RTCP data when necessary. For now, let’s assume that we’re working with the poll thread enabled.

Lets suppose that for a duration of one minute, we want to send packets containing 20 ms (or 160 samples) of silence and we want to indicate when a packet from someone else has been received. Also suppose we have L8 data as defined in RFC 3551 and want to use payload type 96. First, we’ll set some default values:

session.SetDefaultPayloadType(96);

session.SetDefaultMark(false);

session.SetDefaultTimestampIncrement(160);

Next, we’ll create the buffer which contains 160 silence samples and create an RTPTime instance which indicates 20 ms or 0.020 seconds. We’ll also store the current time so we’ll know when one minute has passed.

uint8_t silencebuffer[160];

for (int i = 0 ; i < 160 ; i++)

silencebuffer[i] = 128;

RTPTime delay(0.020);

RTPTime starttime = RTPTime::CurrentTime();

Next, the main loop will be shown. In this loop, a packet containing 160 bytes of payload data will be sent. Then, data handling can take place but this part is described later in the text. Finally, we’ll wait 20 ms and check if sixty seconds have passed:

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;

}

Information about participants in the session, packet retrieval etc, can be done between calls to the RTPSession member functions RTPSession::BeginDataAccess and RTPSession::EndDataAccess. This ensures that the background thread doesn’t try to change the same data you’re trying to access. We’ll iterate over the participants using the RTPSession::GotoFirstSource and RTPSession::GotoNextSource member functions. Packets from the currently selected participant can be retrieved using the RTPSession::GetNextPacket member function which returns a pointer to an instance of the RTPPacket class. When you don’t need the packet anymore, it has to be deleted. The processing of incoming data will then be as follows:

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();

Information about the currently selected source can be obtained by using the GetCurrentSourceInfo member function of the RTPSession class. This function returns a pointer to an instance of RTPSourceData which contains all information about that source: sender reports from that source, receiver reports, SDES info etc.

Alternatively, packets can also be handled directly, without iterating over the sources, by overriding the RTPSession::OnValidatedRTPPacket member function. The example code in example6.cppillustrates this approach.

When the main loop is finished, we’ll send a BYE packet to inform other participants of our departure and clean up the RTPSession class. Also, we want to wait at most 10 seconds for the BYE packet to be sent, otherwise we’ll just leave the session without sending a BYE packet.

delay = RTPTime(10.0);

session.BYEDestroy(delay,”Time’s up”,9);

The complete code of the program is given in example2.cpp.

SRTP support

Support for Secure RTP (SRTP) is provided through the RTPSecureSession class, which used libsrtp for encryption/decryption of the data. This class itself is not meant to provide a complete ready-to-use solution, since there’s a wide variety of options that can be configured in libsrtp.

Instead, the class provides a means to initialize a libsrtp-context, which you can then obtain and configure further for your needs. Incoming and outgoing packets will be decrypted and encrypted respectively, using the context that was constructed and completed this way.

The example code in example7.cpp illustrates the use of this class, where a single key for sender and receiver is used, together with the default encryption algorithm.

Error codes

Unless specified otherwise, functions with a return type int will return a negative value when an error occurred and zero or a positive value upon success. A description of the error code can be obtained by using the RTPGetErrorString function, declared in rtperrors.h

Memory management

You can write you own memory manager by deriving a class from RTPMemoryManager. The following example shows a very basic implementation.

class MyMemoryManager : public RTPMemoryManager

{

public:

MyMemoryManager() { }

~MyMemoryManager() { }

void *AllocateBuffer(size_t numbytes, int memtype)

{

return malloc(numbytes);

}

void FreeBuffer(void *p)

{

free(p);

}

};

In the constructor of RTPSession, you can specify that you would like to use this memory manager:

MyMemoryManager mgr;

RTPSession session(0, &mgr);

Now, all memory allocation and deallocation will be done using the AllocateBuffer and FreeBuffer implementations of mgr.

The second parameter of the RTPMemoryManager::AllocateBuffer member function indicates what the purpose is of this memory block. This allows you to handle different kinds of data in different ways.

With the introduction of the memory management system, the RTPSession class was extended with member function RTPSession::DeletePacket and RTPSession::DeleteTransmissionInfo. These functions should be used to deallocate RTPPacket instances and RTPTransmissionInfo instances respectively.

Acknowledgment

I would like thank the people at the Expertise Centre for Digital Media for giving me the opportunity to create this rewrite of the library. Special thanks go to Wim Lamotte for getting me started on the RTP journey many years ago.

Contact

If you have any questions, remarks or requests about the library or if you think you’ve discovered a bug, you can contact me at jori(dot)liesenborgs(at)gmail(dot)com

The home page of the library is http://research.edm.uhasselt.be/jori/jrtplib/jrtplib.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/126270.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • HelloWorld的Java代码[通俗易懂]

    HelloWorld的Java代码[通俗易懂]HelloWorld的Java代码//类名publicclassHelloWorld{//主函数,主方法,程序的入口publicstaticvoidmain(String[]args){//输出语句System.out.println(“HelloWorld!”);}}欢迎使用Markdown编辑器你好!这是你第一次使用Markdown编辑器所展示的欢迎…

    2022年5月28日
    53
  • window批处理bat命令详解_cmd批处理命令

    window批处理bat命令详解_cmd批处理命令常见问题:1.如果你自己编写的.bat文件,双击打开,出现闪退 2.批处理.bat文件中输出中文乱码 解决方法在文章末尾!前言批处理文件(batchfile)包含一系列DOS命令,通常用于自动执行重复性任务。用户只需双击批处理文件便可执行任务,而无需重复输入相同指令。编写批处理文件非常简单,但难点在于确保一切按顺序执行。编写严谨的批处理文件可以极大程度地节省时间,在应对重复性工…

    2022年8月22日
    7
  • cosx等价无穷小_第一章 函数与极限 第七节 无穷小的比较[通俗易懂]

    cosx等价无穷小_第一章 函数与极限 第七节 无穷小的比较[通俗易懂]我的公众号“每日晴天”,可关注领取我的笔记pdf版哦~——————————————————————————本文主要首先把书上的定义和知识点总结起来,方便复习要点背诵,同时在最后分割线之后补充自己当时在学习定义的过程中的理解!欢迎评论自己不懂的内容,我后续补充理解哦~谢谢支持(#^.^#)学理科其…

    2022年8月11日
    2
  • 开启新征程[通俗易懂]

    开启新征程[通俗易懂]开启新征程

    2022年4月22日
    38
  • C语言冒泡排序升序_c语言快速排序和冒泡排序

    C语言冒泡排序升序_c语言快速排序和冒泡排序任务代码:执行情况:知识总结:冒泡排序法:也叫升序排序法,但是相比起二分法查找只能应用于有序数列,二如何将一个无序数列变的有序就可以使用冒泡排序法!!!对上面的过程进行总结:该思想体现在成续上的解法是:实例:冒泡排序不仅仅可以应用于数字同样可以应用于字符字母的快速排序:心得体会:

    2025年6月15日
    0
  • java输入语句_java输入语句是什么

    java输入语句_java输入语句是什么Java的语句有很多,其中输入语句是最基本的操作之一。下面我将带大家一起了解一下要如何进行输入代码的编写。首先当你进行输入操作前要将下面两个包给加入Java程序的包行列中。先将java.io.*;以及java.util.*;导入Java代码中。importjava.util.*;importjava.io.*;charc=(char)System.in.read();是输入单个字符;int…

    2022年7月7日
    20

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号