博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
谈谈RTP传输中的负载类型和时间戳
阅读量:5831 次
发布时间:2019-06-18

本文共 2636 字,大约阅读时间需要 8 分钟。

 最近被RTP的负载类型和时间戳搞郁闷了,一个问题调试了近一周,终于圆满解决,回头看看,发现其实主要原因还是自己没有真正地搞清楚RTP协议中负载类型和时间戳的含义。虽然做RTP传输,有着和这两个强大的库支持,一个是c++接口,一个是c语言接口,各有各的特点,各有各的应用环境,但是仅仅有库就能解决一切问题吗?可能仿照着一些例子程序,你能够完成主要的功能,但一旦问题发生了,不清楚原理你是很难定位和解决问题的,所以在此,用我的经验劝劝大家,磨刀不误砍柴工,做应用还是先把原理搞清楚再动手吧……

    看这篇文章之前,首先你应该知道什么是RTP协议,可以去看RTP协议原文(RFC3550协议),也可以看一些网友对RTP协议的讲解的文章,很多,这里我提供一篇我个人觉得写得还不错的: 

   好,下面言归正传,首先谈谈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的时间戳有比较深刻地理解,我刚开始就是因为没搞清楚,随时设置时间戳增量导致传输一直有问题,困扰我好久。

转载地址:http://rzgdx.baihongyu.com/

你可能感兴趣的文章
ASP.NET 2.2 Preview 1首次支持Java SignalR客户端
查看>>
深入JVM彻底剖析ygc越来越慢的原因(下)
查看>>
红帽技术开放日:参与开源社区不只有贡献代码这一种方式
查看>>
《Spark GraphX in Action》书评及作者访谈
查看>>
如何定义性能需求
查看>>
一个小米SRE的日常问题排查记录
查看>>
RPC框架的可靠性设计
查看>>
Rust编程语言的核心部件
查看>>
WiFi万能钥匙万玉权:管理应该是“自下而上”
查看>>
Visual Studio最新特性分析
查看>>
Kubernetes集群中的高性能网络策略
查看>>
Android Studio安装
查看>>
ThinkPHP实现定时任务
查看>>
xp系统安装NET4.0提示“严重故障”的解决方法
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
冒泡排序和选择排序区别
查看>>
XP SP3系统用一键还原安装的小妙招
查看>>
Linux下的JFreeChart和 汉字验证码 中文乱码问题解决方案
查看>>
Dockerfile创建Linux/CentOS6.x Nginx MySQL Tomcat PHP(LNMTP)镜像
查看>>