转载时请注明出处:http://blog.csdn.net/str999_cn/article/details/28250871原文网址:https://github.com/ebarnard/JRTPLIB/blob/master/doc/jrtplib.h/**\mainpage JRTPLIB** \author Jori Liesenborgs* \author Developed at the The Expertise Centre for Digital Media (EDM), a research* institute of the Hasselt University** \section ack 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.** \section intro 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.本文档描述JRTPLIB,一个用C++编写的面向对象的库,致力于帮助开发者使用RFC 3550中描述的实时传输协议(RTP)** 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.本库能让使用者通过RTP发送和接收数据,而不用自己去操心SSRC冲突、调度和传送RTCP数据等。使用者只需给本库提供需要发送的载荷数据,本库即能让使用者获取到传入的RTP和RTCP数据。** \subsection idea 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. This class* provides the necessary functions for sending RTP data and handles* the RTCP part internally.本库提供了好几个类,这些类在创建RTP应用程序时很有用。大多数使用者在创建一个应用程序时可能只会用到RTPSession这一个类。这个类提供了必要的函数来发送RTP数据,以及在内部处理RTCP这一部分。** \subsection changes Changes from version 2.x自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.最重要的变化之一可能就是当前版本建立在RFC 3550的基础之上,而2.x版是建立在RFC 1889基础之上的,而RFC 1889现在已经过时了。** 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.此外,2.x版是构筑在这样的理念之上的,即使用者将只需要RTPSession这一个类即可,意味着其他类自身来说是不重要的。而当前版本正好相反,致力于提供许多有用的组件,来帮助使用者构建强大的RTP应用程序。** 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.在当前版本中,和传输RTP数据包底层协议相关的代码,被打包进了一个类,该类从一个叫RTPTransmitter的类里继承了接口。这让支持不同的底层协议变得简单了。当前,支持的协议有IPv4的UDP和IPv6的UDP。** 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.对于像混音器或者译码器这样的应用程序,使用RTPSession不是一个好的选择。满足这个目的可以使用其他一些组件:一个发射组件、一个SSRC表、一个RTCP调度器等等。使用这些,构建各种应用程序都将变得简单。* \section copyright Copyright license 授权证书(略)** The library code uses the following copyright license:** \code* 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.* \endcode** 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.** \section starting Getting started with the RTPSession class开始使用RTPSession类** All classes and functions are part of the \c jrtplib namespace, so to* simplify the code a bit, we'll declare that we're using this namespace:所有类和函数都是jrtplib命名空间的一部分,所以为了简化编码,我们将申明以下命名空间:* \code* using namespace jrtplib;* \endcode* 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:* 要使用RTP,你必须要创建一个RTPSession对象。该构造函数接收2个参数,一个是RTPRandom对象的实例,一个是RTPMemoryManager对象的实例。现在,为了简便起见,我们使用默认设置,所以到目前我们的代码如下:* \code* RTPSession session;* \endcode** 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:* 要实际地创建该会话,你应该调用Create成员函数,它有3个参数:第一个是RTPSessionParams类型,它设置了本会话的通用设置。本类还有个参数必须显示地设置,否则该会话不能成功地创建。这个参数就是你要发送的数据的时间戳单位,它可以这样计算,用一段时间内的取样,除以一定的时间间隔(秒)。所以,假设你要发送的是8000赫兹的语音数据,可以使用如下代码:* \code* RTPSessionParams sessionparams;** sessionparams.SetOwnTimestampUnit(1.0/8000.0);* \endcode** The other session parameters will probably depend on the actual RTP profile* you intend to work with.会话的其他参数取决于实际的RTP的情况。** 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:Create函数的第二个参数是一个指向RTPTransmissionParams实例的指针,描述了传输模块的参数。第3个参数选择将会用到的传输部件。默认使用的是一个IPv4的UDP传输器,对这种特定类型的传输器,传输参数应该是RTPUDPv4TransmissionParams类型。假设我们的本地RTP端口要设置为8000,我们可以这样:** \code* RTPUDPv4TransmissionParams transparams;** transparams.SetPortbase(8000);* \endcode** Now, we're ready to call the Create member function of RTPSession. The return* value is stored in the integer \c 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:* 现在,我们做好了调用RTPSession的Create成员函数的准备。返回值被存储在数字变量status里,这样我们就可以检查是否出过什么错误。如果整个值是负数,那就表示有什么错误发生了。整个错误代码代表的具体错误描述,可以通过调用RTPGetErrorString来获取。* \code* int status = session.Create(sessionparams,&transparams);* if (status < 0)* {* std::cerr << RTPGetErrorString(status) << std::endl;* exit(-1);* }* \endcode** 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:* 如果会话创建成功,那么现在就应该指明RTP和RTCP数据将要发送到哪个目的地。这是通过调用RTPSession成员函数AddDestination来完成的。这个函数带有一个RTPAddress类型的参数。这是一个抽象类,对于IPv4的UDP传输器来说,实际使用的类是RTPIPv4Address。假如我们想要发送数据到运行在同一台主机的9000端口上的进程,我们可以这样:* \code* 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);* }* \endcode** 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.* 如果本库编译的时候设置了JThread支持,传入的数据时在后台线程里处理的。如果编译期没有开启JThread支持,或者你在会话参数里设置不使用轮询线程,那你必须定期地调用RTPSession成员函数Poll,以便处理传入的数据和发送必要的RTCP数据。现在,我们假定轮询线程功能是开启的。* 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:* 我们假定在1分钟持续期内,我们想发送包含20毫秒(160个样本)静默的数据包,我们还想指出来自于某人的一个数据包是否已经收到。另外,再假设我们有RFC 3551里定义的L8数据,想要使用负载类型96(注,96代表H264类型)。首先,我们要设置一些默认值:* \code* session.SetDefaultPayloadType(96);* session.SetDefaultMark(false);* session.SetDefaultTimestampIncrement(160);* \endcode** 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.* 其次,我们将创建包含160个静默样本的缓冲,和创建一个RTPTime实例,该实例表示20毫秒或者0.020秒。我们也将存储当前时间,以便我们知道1分钟已经过去。* \code* uint8_t silencebuffer[160];** for (int i = 0 ; i < 160 ; i++)* silencebuffer[i] = 128;** RTPTime delay(0.020);* RTPTime starttime = RTPTime::CurrentTime();* \endcode** 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:* 接下来,我们将显示主循环。在这个循环中,一个包含160字节数据负载的数据包会被发送。然后,数据处理会发生,但这部分会在本文稍后部分讨论。最后,我们将等待20毫秒,然后检查60分钟是否已经过去。* \code* 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;* }* \endcode** Information about participants in the session, packet retrieval* etc, has to be done between calls to the RTPSession member* functions BeginDataAccess and 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* GotoFirstSource and GotoNextSource member functions. Packets from* the currently selected participant can be retrieved using the* 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:*会话参与者的有关信息,数据包的接收等,必须要在RTPSession的成员函数BeginDataAccess和EndDataAccess的调用之间进行。这可确保后台线程不会尝试修改你正在处理的同一份数据。我们将使用GotoFirstSource和GotoNextSource成员函数来遍历所有参与者。来自当前选中的参与者的数据包能够通过GetNextPacket成员函数来获取,该函数返回一个指向RTPPacket类的实例的指针。如果你不再需要该数据包,必须将其删除。传入的数据的处理如下所示:* \code* 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();* \endcode** 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.有关当前选中的源数据的信息,可以通过使用RTPSession类的GetCurrentSourceInfo成员函数来获得。该函数返回一个指向RTPSourceData实例的指针,这包含了该源数据的所有信息:来自哪个源的发送者报告、接受者报告,SDES信息等等。** 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.当主循环结束时,我们要发送一个BYE数据包通知其他参与者我们离开了,然后清理RTPSession类。另外,我们还要等待最多10秒钟让BYE数据包发送出去,否则,我们可以直接离开该会话,不用发送BYE数据包。** \code* delay = RTPTime(10.0);* session.BYEDestroy(delay,"Time's up",9);* \endcode** The complete code of the program is given in \c example2.cpp.完整的程序代码在example2.cpp里。** \section errors Error codes** Unless specified otherwise, functions with a return type \c 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除非另有说明,返回类型是数字的函数,如果返回了一个负数值,表示有错误发生,返回0和正数表示成功。错误代码的具体描述信息可以使用RTPGetErrorString函数获取,定义在rtperror.h里。** \section memory Memory management内存管理** You can write you own memory manager by deriving a class from RTPMemoryManager.* The following example shows a very basic implementation.你可以从RTPMemoryManager类继承来写你自己的内存管理程序。以下例子显示了一个非常基础的实现。** \code* class MyMemoryManager : public RTPMemoryManager* {* public:* MyMemoryManager() { }* ~MyMemoryManager() { }** void *AllocateBuffer(size_t numbytes, int memtype)* {* return malloc(numbytes);* }** void FreeBuffer(void *p)* {* free(p);* }* };* \endcode** In the constructor of RTPSession, you can specify that you would like to use* this memory manager:* 在RTPSession的构造函数里,你可以指定你要用这个内存管理器。* \code* MyMemoryManager mgr;* RTPSession session(0, &mgr);* \endcode** Now, all memory allocation and deallocation will be done using the AllocateBuffer* and FreeBuffer implementations of \c mgr.现在所有内存的分配和回收都会由mgr实现中的AllocateBuffer和FreeBuffer来完成了。** 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.RTPmemoryManager::AllocateBuffer成员函数的第二个参数表明这个内存块的目的是什么。这能让你以不同的方式处理不同类型的数据。** 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.随着内存管理系统的引进,RTPSession类被扩展到带有以下成员函数:RTPSession::DeletePacket、RTPSession::DeleteTransmissionInfo。这些函数分别被用来清理RTPPacket实例和RTPTransmissionInfo实例。** \section contact 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* \c jori(\c dot)\c liesenborgs(\c at)\c gmail(\c dot)\c com如果你有任何有关本库的问题、评论或要求,或者如果你认为你发现了一个bug,你可以联系我的email:\c jori(\c dot)\c liesenborgs(\c at)\c gmail(\c dot)\c com** The home page of the library is* http://research.edm.uhasselt.be/jori/jrtplib/jrtplib.html本库的主页是:http://research.edm.uhasselt.be/jori/jrtplib/jrtplib.html** There is also a mailing list for the library. To subscribe to the list,* send an e-mail to \c jrtplib-subscribe(\c at)\c edm(\c dot)\c uhasselt(\c dot)\c be* and you'll receive further instructions.本库还有一个邮件列表。要订阅该列表,发送一封email到\c jrtplib-subscribe(\c at)\c edm(\c dot)\c uhasselt(\c dot)\c,然后你将会受到进一步的指示。*/
JRTPLIB 文档中文翻译
最新推荐文章于 2021-03-16 11:35:33 发布