本文共 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。
官方的解释看懂没?没看懂?没关系,我刚开始也没看懂,那就听我的解释吧。
转载地址:http://rzgdx.baihongyu.com/