rtp库.docx
- 文档编号:9167529
- 上传时间:2023-02-03
- 格式:DOCX
- 页数:15
- 大小:25.39KB
rtp库.docx
《rtp库.docx》由会员分享,可在线阅读,更多相关《rtp库.docx(15页珍藏版)》请在冰豆网上搜索。
rtp库
实时传输协议(Real-timeTransportProtocol,PRT)是在Internet上处理多媒体数据流的一种网络协议,利用它能够在一对一(unicast,单播)或者一对多(multicast,多播)的网络环境中实现传流媒体数据的实时传输。
RTP通常使用UDP来进行多媒体数据的传输,但如果需要的话可以使用TCP或者ATM等其它协议,整个RTP协议由两个密切相关的部分组成:
RTP数据协议和RTP控制协议。
实时流协议(RealTimeStreamingProtocol,RTSP)最早由RealNetworks和Netscape公司共同提出,它位于RTP和RTCP之上,其目的是希望通过IP网络有效地传输多媒体数据。
2.1RTP数据协议
RTP数据协议负责对流媒体数据进行封包并实现媒体流的实时传输,每一个RTP数据报都由头部(Header)和负载(Payload)两个部分组成,其中头部前12个字节的含义是固定的,而负载则可以是音频或者视频数据。
RTP数据报的头部格式如图1所示:
图1RTP头部格式
其中比较重要的几个域及其意义如下:
?
CSRC记数(CC) 表示CSRC标识的数目。
CSRC标识紧跟在RTP固定头部之后,用来表示RTP数据报的来源,RTP协议允许在同一个会话中存在多个数据源,它们可以通过RTP混合器合并为一个数据源。
例如,可以产生一个CSRC列表来表示一个电话会议,该会议通过一个RTP混合器将所有讲话者的语音数据组合为一个RTP数据源。
?
负载类型(PT) 标明RTP负载的格式,包括所采用的编码算法、采样频率、承载通道等。
例如,类型2表明该RTP数据包中承载的是用ITUG.721算法编码的语音数据,采样频率为8000Hz,并且采用单声道。
?
序列号 用来为接收方提供探测数据丢失的方法,但如何处理丢失的数据则是应用程序自己的事情,RTP协议本身并不负责数据的重传。
?
时间戳 记录了负载中第一个字节的采样时间,接收方能够时间戳能够确定数据的到达是否受到了延迟抖动的影响,但具体如何来补偿延迟抖动则是应用程序自己的事情。
开始12个八进制出现在每个rtp包中,而csrc标识列表仅出现在混合器插入时。
2.1.2复用rtp连接为使协议有效运行,复用点数目应减至最小。
rtp中,复用由定义rtp连接的目的传输地址(网络地址与端口号)提供。
例如,对音频和视频单独编码的远程会议,每个媒介被携带在单独rtp连接中,具有各自的目的传输地址。
目标不在将音频和视频放在单一rtp连接中,而根据ssrc段载荷类型进行多路分解。
使用同一ssrc,而具有不同载荷类型的交叉包将带来几个问题:
如一种载荷类型在连接期间切换,没有办法识别新值将替换那一个旧值。
ssrc定义成用于标识单个计时和系列号空间。
如媒体时钟速率不同,而要求不同系列号空间以说明那种载荷类型有丢包,交叉复用载荷类型将需要不同计时空间。
rtcp发送和接收报告可能仅描述每个ssrc的计时和系列号空间,而不携带载荷类型段。
rtp混合器不能将不兼容媒体流合并成一个流
在一个rtp连接中携带多个媒介阻止几件事:
使用不同网络路径或网络资源分配;接受媒介子集。
对每种媒介使用不同ssrc,但以相同rtp连接发送可避免前三个问题,但不能避免后两个问题。
2.1.3对rtp头特定设置的修改可以认为,现用rtp数据包头对rtp支持的所有应用类共同需要的功能集是完整的。
然而,为维持alf设计原则,头可通过改变或增加设置来裁剪,并仍允许设置无关监控和记录工具起作用。
标记位与载荷类型段携带特定设置信息,但由于很多应用需要它们,否则要容纳它们,就要增加另外32位字,故允许分配在固定头中。
包含这些段的八进制可通过设置重新定义以适应不同要求,如采用更多或更少标记位。
如有标记位,既然设置无关监控器能观察包丢失模式和标记位间关系,我们就可以定位八进制中最重要的位。
其它特殊载荷格式(视频编码)所要求的信息应该携带在包的载荷部分。
可出现在头,总是在载荷部分开始处,或在数据模式的保留值中指出。
如特殊应用类需要独立载荷格式的附加功能,应用运行的设置应该定义附加固定段跟随在现存固定头ssrc之后。
这些应用将能迅速而直接访问附加段,同时,与监控器和记录器无关设置仍能通过仅解释开始12个八进制处理rtp包。
如证实附加功能是所有设置共同需要的,新版本rtp应该对固定头作出明确改变。
Synchronizationsource(SSRC):
SSRC是一個隨機選取的識別值
,用意是使一個RTPsession中的participant都有獨一無二的識
別資訊。
但是同一個使用者在不同的RTPsession中,並不一定
要用同一個SSRC。
Contributingsource(CSRC):
之前提過mixer可以將不同來源的
RTPpacket混和放到同一個RTPpacket中。
此時,RTP也會在
RTPheader中紀錄與這個packet有關的SSRC,而這些SSRC合起
來就叫做CSRC。
从RTP数据报的格式不难看出,它包含了传输媒体的类型、格式、序列号、时间戳以及是否有附加数据等信息,这些都为实时的流媒体传输提供了相应的基础。
RTP协议的目的是提供实时数据(如交互式的音频和视频)的端到端传输服务,因此在RTP中没有连接的概念,它可以建立在底层的面向连接或面向非连接的传输协议之上;RTP也不依赖于特别的网络地址格式,而仅仅只需要底层传输协议支持组帧(Framing)和分段(Segmentation)就足够了;另外RTP本身还不提供任何可靠性机制,这些都要由传输协议或者应用程序自己来保证。
在典型的应用场合下,RTP一般是在传输协议之上作为应用程序的一部分加以实现的,如图2所示:
图2RTP与各种网络协议的关系
2.2RTCP控制协议
RTCP控制协议需要与RTP数据协议一起配合使用,当应用程序启动一个RTP会话时将同时占用两个端口,分别供RTP和RTCP使用。
RTP本身并不能为按序传输数据包提供可靠的保证,也不提供流量控制和拥塞控制,这些都由RTCP来负责完成。
通常RTCP会采用与RTP相同的分发机制,向会话中的所有成员周期性地发送控制信息,应用程序通过接收这些数据,从中获取会话参与者的相关资料,以及网络状况、分组丢失概率等反馈信息,从而能够对服务质量进行控制或者对网络状况进行诊断。
RTCP协议的功能是通过不同的RTCP数据报来实现的,主要有如下几种类型:
?
SR 发送端报告,所谓发送端是指发出RTP数据报的应用程序或者终端,发送端同时也可以是接收端。
?
RR 接收端报告,所谓接收端是指仅接收但不发送RTP数据报的应用程序或者终端。
?
SDES 源描述,主要功能是作为会话成员有关标识信息的载体,如用户名、邮件地址、电话号码等,此外还具有向会话成员传达会话控制信息的功能。
?
BYE 通知离开,主要功能是指示某一个或者几个源不再有效,即通知会话中的其他成员自己将退出会话。
?
APP 由应用程序自己定义,解决了RTCP的扩展性问题,并且为协议的实现者提供了很大的灵活性。
RTCP数据报携带有服务质量监控的必要信息,能够对服务质量进行动态的调整,并能够对网络拥塞进行有效的控制。
由于RTCP数据报采用的是多播方式,因此会话中的所有成员都可以通过RTCP数据报返回的控制信息,来了解其他参与者的当前情况。
在一个典型的应用场合下,发送媒体流的应用程序将周期性地产生发送端报告SR,该RTCP数据报含有不同媒体流间的同步信息,以及已经发送的数据报和字节的计数,接收端根据这些信息可以估计出实际的数据传输速率。
另一方面,接收端会向所有已知的发送端发送接收端报告RR,该RTCP数据报含有已接收数据报的最大序列号、丢失的数据报数目、延时抖动和时间戳等重要信息,发送端应用根据这些信息可以估计出往返时延,并且可以根据数据报丢失概率和时延抖动情况动态调整发送速率,以改善网络拥塞状况,或者根据网络状况平滑地调整应用程序的服务质量。
2.3RTSP实时流协议
作为一个应用层协议,RTSP提供了一个可供扩展的框架,它的意义在于使得实时流媒体数据的受控和点播变得可能。
总的说来,RTSP是一个流媒体表示协议,主要用来控制具有实时特性的数据发送,但它本身并不传输数据,而是必须依赖于下层传输协议所提供的某些服务。
RTSP可以对流媒体提供诸如播放、暂停、快进等操作,它负责定义具体的控制消息、操作方法、状态码等,此外还描述了与RTP间的交互操作。
RTSP在制定时较多地参考了HTTP/1.1协议,甚至许多描述与HTTP/1.1完全相同。
RTSP之所以特意使用与HTTP/1.1类似的语法和操作,在很大程度上是为了兼容现有的Web基础结构,正因如此,HTTP/1.1的扩展机制大都可以直接引入到RTSP中。
由RTSP控制的媒体流集合可以用表示描述(PresentationDescription)来定义,所谓表示是指流媒体服务器提供给客户机的一个或者多个媒体流的集合,而表示描述则包含了一个表示中各个媒体流的相关信息,如数据编码/解码算法、网络地址、媒体流的内容等。
虽然RTSP服务器同样也使用标识符来区别每一流连接会话(Session),但RTSP连接并没有被绑定到传输层连接(如TCP等),也就是说在整个RTSP连接期间,RTSP用户可打开或者关闭多个对RTSP服务器的可靠传输连接以发出RTSP请求。
此外,RTSP连接也可以基于面向无连接的传输协议(如UDP等)。
RTSP协议目前支持以下操作:
?
检索媒体 允许用户通过HTTP或者其它方法向媒体服务器提交一个表示描述。
如表示是组播的,则表示描述就包含用于该媒体流的组播地址和端口号;如果表示是单播的,为了安全在表示描述中应该只提供目的地址。
?
邀请加入 媒体服务器可以被邀请参加正在进行的会议,或者在表示中回放媒体,或者在表示中录制全部媒体或其子集,非常适合于分布式教学。
?
添加媒体 通知用户新加入的可利用媒体流,这对现场讲座来讲显得尤其有用。
与HTTP/1.1类似,RTSP请求也可以交由代理、通道或者缓存来进行处理。
三、流媒体编程
RTP是目前解决流媒体实时传输问题的最好办法,如果需要在Linux平台上进行实时流媒体编程,可以考虑使用一些开放源代码的RTP库,如LIBRTP、JRTPLIB等。
JRTPLIB是一个面向对象的RTP库,它完全遵循RFC1889设计,在很多场合下是一个非常不错的选择,下面就以JRTPLIB为例,讲述如何在Linux平台上运用RTP协议进行实时流媒体编程。
3.1环境搭建
JRTPLIB是一个用C++语言实现的RTP库,目前已经可以运行在Windows、Linux、FreeBSD、Solaris、Unix和VxWorks等多种操作系统上。
要为Linux系统安装JRTPLIB,首先从JRTPLIB的网站(http:
//lumumba.luc.ac.be/jori/jrtpl...舜κ褂玫氖?
/a>jrtplib-2.7b.tar.bz2。
假设下载后的源码包保存在/usr/local/src目录下,执行下面的命令可以对其进行解压缩:
[root@linuxgamsrc]#bzip2-dcjrtplib-2.7b.tar.bz2|tarxvf-
接下去需要对JRTPLIB进行配置和编译:
[root@linuxgamsrc]#cdjrtplib-2.7[root@linuxgamjrtplib-2.7b]#./configure[root@linuxgamjrtplib-2.7b]#make
最后再执行如下命令就可以完成JRTPLIB的安装:
[root@linuxgamjrtplib-2.7b]#makeinstall
3.2初始化
在使用JRTPLIB进行实时流媒体数据传输之前,首先应该生成RTPSession类的一个实例来表示此次RTP会话,然后调用Create()方法来对其进行初始化操作。
RTPSession类的Create()方法只有一个参数,用来指明此次RTP会话所采用的端口号。
清单1给出了一个最简单的初始化框架,它只是完成了RTP会话的初始化工作,还不具备任何实际的功能。
代码清单1:
initial.cpp
#include"rtpsession.h"intmain(void){RTPSessionsess;sess.Create(5000);return0;}
如果RTP会话创建过程失败,Create()方法将会返回一个负数,通过它虽然可以很容易地判断出函数调镁烤故浅晒Φ幕故鞘О艿模春苣衙靼壮龃淼脑虻降资裁础RTPLIB采用了统一的错误处理机制,它提供的所有函数如果返回负数就表明出现了某种形式的错误,而具体的出错信息则可以通过调用RTPGetErrorString()函数得到。
RTPGetErrorString()函数将错误代码作为参数传入,然后返回该错误代码所对应的错误信息。
清单2给出了一个更加完整的初始化框架,它可以对RTP会话初始化过程中所产生的错误进行更好的处理:
代码清单2:
framework.cpp
#include#include"rtpsession.h"intmain(void){RTPSessionsess;intstatus;char*msg;sess.Create(6000);msg=RTPGetErrorString(status);printf("ErrorString:
%s\\n",msg);return0;}
设置恰当的时戳单元,是RTP会话初始化过程所要进行的另外一项重要工作,这是通过调用RTPSession类的SetTimestampUnit()方法来实现的,该方法同样也只有一个参数,表示的是以秒为单元的时戳单元。
例如,当使用RTP会话传输8000Hz采样的音频数据时,由于时戳每秒钟将递增8000,所以时戳单元相应地应该被设置成1/8000:
sess.SetTimestampUnit(1.0/8000.0);
3.3数据发送
当RTP会话成功建立起来之后,接下去就可以开始进行流媒体数据的实时传输了。
首先需要设置好数据发送的目标地址,RTP协议允许同一会话存在多个目标地址,这可以通过调用RTPSession类的AddDestination()、DeleteDestination()和ClearDestinations()方法来完成。
例如,下面的语句表示的是让RTP会话将数据发送到本地主机的6000端口:
unsignedlongaddr=ntohl(inet_addr("127.0.0.1"));sess.AddDestination(addr,6000);
目标地址全部指定之后,接着就可以调用RTPSession类的SendPacket()方法,向所有的目标地址发送流媒体数据。
SendPacket()是RTPSession类提供的一个重载函数,它具有下列多种形式:
intSendPacket(void*data,intlen)intSendPacket(void*data,intlen,unsignedcharpt,boolmark,unsignedlongtimestampinc)intSendPacket(void*data,intlen,unsignedshorthdrextID,void*hdrextdata,intnumhdrextwords)intSendPacket(void*data,intlen,unsignedcharpt,boolmark,unsignedlongtimestampinc,unsignedshorthdrextID,void*hdrextdata,intnumhdrextwords)
SendPacket()最典型的用法是类似于下面的语句,其中第一个参数是要被发送的数据,而第二个参数则指明将要发送数据的长度,再往后依次是RTP负载类型、标识和时戳增量。
sess.SendPacket(buffer,5,0,false,10);
对于同一个RTP会话来讲,负载类型、标识和时戳增量通常来讲都是相同的,JRTPLIB允许将它们设置为会话的默认参数,这是通过调用RTPSession类的SetDefaultPayloadType()、SetDefaultMark()和SetDefaultTimeStampIncrement()方法来完成的。
为RTP会话设置这些默认参数的好处是可以简化数据的发送,例如,如果为RTP会话设置了默认参数:
sess.SetDefaultPayloadType(0);sess.SetDefaultMark(false);sess.SetDefaultTimeStampIncrement(10);
之后在进行数据发送时只需指明要发送的数据及其长度就可以了:
sess.SendPacket(buffer,5);
3.4数据接收
对于流媒体数据的接收端,首先需要调用RTPSession类的PollData()方法来接收发送过来的RTP或者RTCP数据报。
由于同一个RTP会话中允许有多个参与者(源),你既可以通过调用RTPSession类的GotoFirstSource()和GotoNextSource()方法来遍历所有的源,也可以通过调用RTPSession类的GotoFirstSourceWithData()和GotoNextSourceWithData()方法来遍历那些携带有数据的源。
在从RTP会话中检测出有效的数据源之后,接下去就可以调用RTPSession类的GetNextPacket()方法从中抽取RTP数据报,当接收到的RTP数据报处理完之后,一定要记得及时释放。
下面的代码示范了该如何对接收到的RTP数据报进行处理:
if(sess.GotoFirstSourceWithData()){do{RTPPacket*pack;pack=sess.GetNextPacket();//处理接收到的数据deletepack;}while(sess.GotoNextSourceWithData());}
JRTPLIB为RTP数据报定义了三种接收模式,其中每种接收模式都具体规定了哪些到达的RTP数据报将会被接受,而哪些到达的RTP数据报将会被拒绝。
通过调用RTPSession类的SetReceiveMode()方法可以设置下列这些接收模式:
?
RECEIVEMODE_ALL 缺省的接收模式,所有到达的RTP数据报都将被接受;
?
RECEIVEMODE_IGNORESOME 除了某些特定的发送者之外,所有到达的RTP数据报都将被接受,而被拒绝的发送者列表可以通过调用AddToIgnoreList()、DeleteFromIgnoreList()和ClearIgnoreList()方法来进行设置;
?
RECEIVEMODE_ACCEPTSOME 除了某些特定的发送者之外,所有到达的RTP数据报都将被拒绝,而被接受的发送者列表可以通过调用AddToAcceptList()、DeleteFromAcceptList和ClearAcceptList()方法来进行设置。
3.5控制信息
JRTPLIB是一个高度封装后的RTP库,程序员在使用它时很多时候并不用关心RTCP数据报是如何被发送和接收的,因为这些都可以由JRTPLIB自己来完成。
只要PollData()或者SendPacket()方法被成功调用,JRTPLIB就能够自动对到达的RTCP数据报进行处理,并且还会在需要的时候发送RTCP数据报,从而能够确保整个RTP会话过程的正确性。
而另一方面,通过调用RTPSession类提供的SetLocalName()、SetLocalEMail()、SetLocalLocation()、SetLocalPhone()、SetLocalTool()和SetLocalNote()方法,JRTPLIB又允许程序员对RTP会话的控制信息进行设置。
所有这些方法在调用时都带有两个参数,其中第一个参数是一个char型的指针,指向将要被设置的数据;而第二个参数则是一个int型的数值,表明该数据中的前面多少个字符将会被使用。
例如下面的语句可以被用来设置控制信息中的电子邮件地址:
sess.SetLocalEMail("xiaowp@",19);
在RTP会话过程中,不是所有的控制信息都需要被发送,通过调用RTPSession类提供的EnableSendName()、EnableSendEMail()、EnableSendLocation()、EnableSendPhone()、EnableSendTool()和EnableSendNote()方法,可以为当前RTP会话选择将被发送的控制信息。
3.6实际应用
最后通过一个简单的流媒体发送-接收实例,介绍如何利用JRTPLIB来进行实时流媒体的编程。
清单3给出了数据发送端的完整代码,它负责向用户指定的IP地址和端口,不断地发送RTP数据包:
代码清单3:
sender.cpp
#include#include#include"rtpsession.h"
//错误处理函数
voidcheckerror(interr)
{
if(err<0){char*errstr=RTPGetErrorString(err);printf("Error:
%s\\n",errstr);exit(-1);}
}
intmain(intargc,char**argv)
{
RTPSessionsess;
unsignedlongdestip;
intdestport;
intportbase=6000;
intstatus,index;
charbuf
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- rtp
![提示](https://static.bdocx.com/images/bang_tan.gif)