谈谈RTP传输中的负载类型和时间戳

 最近被RTP的负载类型和时间戳搞郁闷了,一个问题调试了近一周,终于圆满解决,回头看看,发现其实主要原因还是自己没有真正地搞清楚RTP协议中负载类型和时间戳的含义。虽然做RTP传输,有着JrtplibOrtp这两个强大的库支持,一个是c++接口,一个是c语言接口,各有各的特点,各有各的应用环境,但是仅仅有库就能解决一切问题吗?可能仿照着一些例子程序,你能够完成主要的功能,但一旦问题发生了,不清楚原理你是很难定位和解决问题的,所以在此,用我的经验劝劝大家,磨刀不误砍柴工,做应用还是先把原理搞清楚再动手吧……
    看这篇文章之前,首先你应该知道什么是RTP协议,可以去看RTP协议原文(RFC3550协议),也可以看一些网友对RTP协议的讲解的文章,很多,这里我提供一篇我个人觉得写得还不错的:http://blog.csdn.net/bripengandre/archive/2008/04/01/2238818.aspx 。

   好,下面言归正传,首先谈谈RTP传输中的负载类型吧。

    首先,看RTP协议包头的格式:
          

    10~16 Bit为PT域,指的就是负载类型(PayLoad),负载类型定义了RTP负载的格式,协议原文说该域由具体应用决定其解释。
    目前,负载类型主要用来告诉接收端(或者播放器)传输的是哪种类型的媒体(例如G.729,H.264,MPEG-4等),这样接收端(或者播放器)才知道了数据流的格式,才会调用适当的编解码器去解码或者播放,这就是负载类型的主要作用。
    就ORTP库(本文用的是ortp-0.9.1)而言,负载类型定义如下:
        

    每一种负载类型都有着其独特的参数,这里基本上涵盖了当前主流的一些媒体类型,例如pcmu 、g.729、h.263(很奇怪,竟然没有定义h.264,注:新版本已经添加了对h.264的支持)、mpeg-4等等。Jrtplib库应该也有相类似的定义,你可以去找找源码,在此我就不再赘述了。

    在ORTP库和JRTplib库中,都提供了设置RTP负载类型的函数,千万要记得根据实际的应用进行设置,我就是当时没有注意,使用ORTP默认的pcmu音频的负载类型,传输H.264编码的视频数据,结果传输中一直有问题,困扰我好久好久。

    好了,再说说RTP的时间戳吧。

    首先,了解几个基本概念:

    时间戳单位:时间戳计算的单位不是秒之类的单位,而是由采样频率所代替的单位,这样做的目的就是为了是时间戳单位更为精准。比如说一个音频的采样频率为8000Hz,那么我们可以把时间戳单位设为1 / 8000。
    时间戳增量:相邻两个RTP包之间的时间差(以时间戳单位为基准)。
    采样频率:  每秒钟抽取样本的次数,例如音频的采样率一般为8000Hz
    帧率:      每秒传输或者显示帧数,例如25f/s
    
    再看看RTP时间戳课本中的定义:

    RTP包头的第2个32Bit即为RTP包的时间戳,Time Stamp ,占32位。
    时间戳反映了RTP分组中的数据的第一个字节的采样时刻。在一次会话开始时的时间戳初值也是随机选择的。即使是没有信号发送时,时间戳的数值也要随时间不断的增加。接收端使用时间戳可准确知道应当在什么时间还原哪一个数据块,从而消除传输中的抖动。时间戳还可用来使视频应用中声音和图像同步。
    在RTP协议中并没有规定时间戳的粒度,这取决于有效载荷的类型。因此RTP的时间戳又称为媒体时间戳,以强调这种时间戳的粒度取决于信号的类型。例如,对于8kHz采样的话音信号,若每隔20ms构成一个数据块,则一个数据块中包含有160个样本(0.02×8000=160)。因此每发送一个RTP分组,其时间戳的值就增加160。

    官方的解释看懂没?没看懂?没关系,我刚开始也没看懂,那就听我的解释吧。

    首先,时间戳就是一个值,用来反映某个数据块的产生(采集)时间点的,后采集的数据块的时间戳肯定是大于先采集的数据块的。有了这样一个时间戳,就可以标记数据块的先后顺序。
    第二,在实时流传输中,数据采集后立刻传递到RTP模块进行发送,那么,其实,数据块的采集时间戳就直接作为RTP包的时间戳。
    第三,如果用RTP来传输固定的文件,则这个时间戳就是读文件的时间点,依次递增。这个不再我们当前的讨论范围内,暂时不考虑。
    第四,时间戳的单位采用的是采样频率的倒数,例如采样频率为8000Hz时,时间戳的单位为1 / 8000 ,在Jrtplib库中,有设置时间戳单位的函数接口,而ORTP库中根据负载类型直接给定了时间戳的单位(音频负载1/8000,视频负载1/90000)
    第五,时间戳增量是指两个RTP包之间的时间间隔,详细点说,就是发送第二个RTP包相距发送第一个RTP包时的时间间隔(单位是时间戳单位)。
    如果采样频率为90000Hz,则由上面讨论可知,时间戳单位为1/90000,我们就假设1s钟被划分了90000个时间块,那么,如果每秒发送25帧,那么,每一个帧的发送占多少个时间块呢?当然是 90000/25 = 3600。因此,我们根据定义“时间戳增量是发送第二个RTP包相距发送第一个RTP包时的时间间隔”,故时间戳增量应该为3600。

 

      【补充】:最近思考了一下,又有了新的体会和解释,可能对大家更容易地去理解这个时间戳增量会有所帮助,补充在下面吧:

 

       其实,网络发送重点关注的是流量的平衡,即均匀地利用网络带宽,为了实现这一点,需要满足:数据采集的速率与数据网络传输的速率尽量保持一致。时间戳增量的设置影响的是RTP包的网络传输的速率,时间戳增量越小,发送速度越快。

 

      下面再进一步解释一下时间戳增量是怎么计算出来的:

 

      对于PAL制式的视频而言,每秒摄像头会采集 25 帧 数据,那么,每采集到 1帧 耗时 1/25 s ,如果我们设计为1个RTP包只包含1帧数据,并且一次发送1帧,那么,要想网络流量均匀,则时间戳增量应该设计为 1/25 s .  而在一般的RTP协议的实现中,时间戳单位不是 秒(s),而约定为采样频率的倒数,由于一般视频的采样频率是 90000,故时间戳单位为 1/90000 s,因此,实际的时间戳增量 = 时间戳增量 ( 1/25 s ) / 时间戳单位(1/90000 s) = 3600  

    在Jrtplib中好像不需要自己管理时间戳的递增,由库内部管理。但在ORTP中每次数据的发送都需要自己传入时间戳的值,即自己需要每次发完一个RTP包后,累加时间戳增量,不是很方便,这就需要自己对RTP的时间戳有比较深刻地理解,我刚开始就是因为没搞清楚,随时设置时间戳增量导致传输一直有问题,困扰我好久。

时间: 2024-08-01 10:01:48

谈谈RTP传输中的负载类型和时间戳的相关文章

小技巧:IIS中的MIME类型

iis|mime|技巧 MIME(Multipurpose Internet Mail Extensions,多目的Internet邮件扩展)是创建用于电子邮件交换,网络文档,及企业网和Internet上的其他应用程序中的文件格式的规范. 每个MIME格式包含一个MIME内容类型和指示存储在这个文件中的数据的子类型.每个MIME类型由两部分组成,前面是数据的大类别,例如声音audio.图象image等,后面定义具体的种类.MIME类型和子类型一般以类型/子类型的形式列出,比如网页的类型"text

Java编码及网络传输中的编码问题

Java编码及网络传输中的编码问题 近来试着FTP搜索,遇到编码问题,研究了下. Java内部的String为Unicode编码,每个字符占两个字节. Java编解码方法如下: String str = "hi好啊me";   byte[] gbkBytes=str.getBytes("GBK");//将String的Unicode编码转为GBK编码,输出到字节中  String string=new String(gbkBytes,"GBK")

企业如何实现云计算中的负载平衡?

尽管云计算技术得到迅速采用,但在多云.多个数据中心和混合基础设施上可靠地分配工作负载的能力仍然存在着长期的缺陷.其结果是工作负载分布不均,应用程序性能下降,如果在全球范围内更好地管理工作负载,则可以避免这种情况.人们需要的是更好的全局服务器负载均衡(GSLB). 平衡云计算中的负载 由于智能地分配工作负载是至关重要的,因此负载均衡器(也称为应用交付控制器ADC)在数据输入中被广泛部署.它们的功能是将工作负载分配给后端服务器,从而确保最佳地使用总体服务器容量和更好的应用程序性能. 传统的负载平衡器

【RAC】RAC中的负载均衡和故障切换--TAF配置

[RAC]RAC中的负载均衡和故障切换--TAF配置 涉及到的内容包括:   Oracle RAC 客户端连接负载均衡(Load Balance)      实现负载均衡(Load Balance)是Oracle RAC最重要的特性之一,主要是把负载平均分配到集群中的各个节点,以提高系统的整体吞吐能力.通常情况下有两种方式来实现负载均衡,一个是基于客户端连接的负载均衡,一个是基于服务器端监听器(Listener)收集到的信息来将新的连接请求分配到连接数较少实例上的实现方式.本文主要讨论的是基于客

谈谈BLOG营销中的写作

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 开展BLOG营销其实一个核心的任务就是写作,这个也是我向咨询的企业客户经常谈到的.为什么写作的作用在BLOG营销中如此突现?因为写作的目的不仅是为了展示企业文化和增加客户信任度,另外一个就是为了配合搜索引擎营销中的搜索引擎优化工作的执行. 如果您会写作,我相信!但是,并不是每个会写作的人都会写配合BLOG营销的文章. 那么接下来,我就谈谈BL

谈谈备案过程中容易碰到的几个小问题

http://www.aliyun.com/zixun/aggregation/8456.html">网站备案是根据国家法律法规需要网站的所有者向国家有关部门申请的备案,现在主要有ICP备案和公安局备案. 公安局备案一般按照各地公安机关指定的地点和方式进行. ICP备案可以自主通过官方备案网站 http://www.miibeian.gov.cn 在线备案或者通过当地电信部门两种方式来进行备案. 网站备案的目的就是为了防止在网上从事非法的网站经营活动,打击不良互联网信息的传播,如果网站不备

怎么去掉Xcode工程中的某种类型的警告

问题描述  在我们的项目中,通常使用了大量的第三方代码,这些代码可能很复杂,我们不敢改动他们,可是作者已经停止更新了,当sdk升级或者是编译器升级后,这些遗留的代码可能会出现许许多多的警告,那么我们有没有办法去掉这些烦人的警告,不然一个工程几百个警告,你看着怎么都不爽吧.我们怎么去掉警告呢? 1. 最直接.最一劳永逸.最安全的方式,直接找到警告的那段代码,改为不警告.这个方式最安全. 可是它有一个问题,就是,当我们很多文件都有这种类型的警告的时候,我们就需要改动很多很多的源码了, 对于不是我们写

文件传输-关于C# socket传输中的连接问题

问题描述 关于C# socket传输中的连接问题 由于我初次编写网络传输这一块的代码,中间一些传输上这几道连接的地方不太明白. 现在我遇到的情景是这样的: 1.我用TCP协议传输文件至服务器, 2.客户端第一次发送文件信息等待回应, 3.服务器接收到消息后返回状态, 4.本地收到状态后开始传文件并等待传输完成回应, 5.传输完成后服务器发送完成状态回来客户端接收到整个过程就完成了. 现有服务器一台,公网IP,可以直接从任何电脑访问的那种, 我现在在服务器上写好了监听,监听收到的消息并判断,然后发

在.net中Oracle日期类型的处理

oracle 刚接触Oracle数据库,发现Oracle中的日期类型很难处理,必须为如11-11月-2004,而且必须是汉字月,不知是什么原因,从数据库里读出来再更新日期不变的情况下也不能更新了,真是麻烦,还得转换类型,在网上查了很多帖子,也没有找到好的解决办法,看msdn找到一个类CultureInfo,就写了一个方法转换日期类型. public string rqcl(string rqz) { CultureInfo ci = new CultureInfo("de-DE");