首 先,看RTP协议包头的格式:
前12个字节在每一个RTP packet中都存在,而一系列的CSRC标记只有存在Mixer时才有。 version (V): 2 bits padding (P): 1 bit extension (X): 1 bit CSRC count (CC): 4 bits marker (M): 1 bit payload type (PT): 7 bits sequence number: 16 bits timestamp: 32 bits SSRC: 32 bits CSRC list: 0 to 15 items, 32 bits each
标识贡献的数据源。只有存在Mixer的时候才有效。如一个将多声道的语音流合并成一个单声道的语音流,在这里就列出原来每个声道的SSRC。 10~16 Bit为PT域,指的就是负载类型(PayLoad),负载类型定义了RTP负载的格式,协议原文说该域由具体应用决定其解释。 每一种 负载类型都有着其独特的参数,这里基本上涵盖了当前主流的一些媒体类型,例如pcmu 、g.729、h.263(很奇怪,竟然没有定义h.264)、mpeg-4等等。Jrtplib库应该也有相类似的定义,你可以去找找源码,在此我就不 再赘述了。 在ORTP库和JRTplib库中,都提供了设置RTP负载类型的函数,千万要记得根据实际的应用进行设置,我就是当时没有注意,使用ORTP默认的 pcmu音频的负载类型,传输H.264编码的视频数据,结果传输中一直有问题,困扰我好久好久。 好了,再说说RTP 的时间戳吧。 首先,了解几个基本概念: 时间戳单位:时间戳计算的单位不是秒之类的单位,而是由采样频率所代替的单位,这样做的目的就是 为了是时间戳单位更为精准。比如说一个音频的采样频率为8000Hz,那么我们可以把时间戳单位设为1 / 8000。 再看看RTP时间戳课本中的定义: 官方的解释看懂没?没看懂?没关系,我刚开始也没看懂,那就听我的解释吧。 首先,时间戳就是一个值,用来反映某个数据块的产生(采集)时间点的, 后采集的数据块的时间戳肯定是大于先采集的数据块的。有了这样一个时间戳,就可以标记数据块的先后顺序。
RTCP的bit图:(http://www.cnblogs.com/Jimmly/archive/2009/08/03/1537468.html)
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ //byte=0 |V=2|P| RC | PT=SR=200 | length | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // 4 | SSRC of sender | // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ // 8 | NTP timestamp, most significant word | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // 12 | NTP timestamp, least significant word | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // 16 | RTP timestamp | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // 20 | sender's packet count | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // 24 | sender's octet count | // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ // 28 |V=2|P| SC | PT=SDES=202 | length | // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ // 32 | SSRC/CSRC_1 | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // 36 | CNAME=1 | length | user and domain name ... // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
多媒体通信同步方法,主要有时间戳同步法、同步标记法、多路复用同步法三种。下面主要讨论时间戳同步法,特别是RTP时间戳同步。内容包括RTP媒 体间同步的实现,为什么需要RTCP的NTP时间来实现媒体间同步?没有RTCP,能实现RTP媒体间的同步吗?DirectShow时间戳和RTP时间 戳的区别,MPEG2-TS流的时间戳等。本文只简单讨论时间戳同步的原理,不涉及具体的实现方法,如音频帧和视频帧时间戳的计算方法,怎样根据时间戳去 做音视频的呈现等。 根据RTP规范,不同的RTP媒体流是分开传输的,且使用各自独立的时间戳进行同步。假设在一次视频点播中,传输两路RTP媒体流,一路视频,一 路音频。根据视频帧时间戳,可以实现视频流内同步,这很好理解,通过视频帧时间戳可以计算出相邻视频帧的时间间隔,也就是视频帧之间的相对时间关系很容易 通过时间戳来确定,按照这个间隔去呈现视频,就可以获得较好的效果。同理,音频流也可以实现自身的同步。 那么音频和视频这两路媒体间如何实现同步呢?我们只使用音视频的RTP时间戳,看能否实现媒体间的同步。音视频的RTP时间戳的增长速率一般是不同的,但没关系,知道了具体的单位后,两者是可以通过单位换算联系起来的。如下图:
现在来看,这种方法好像可以实现同步,因为音视频被映射到同一个时间轴上了,音频和视频帧间的相对关系很清楚。慢着,RTP规范要求时间戳的初 始值应该是一个随机值,那么假设音频帧时间戳的初始值是随机值1234,视频帧时间戳的初始值是随机值5678,看起来应该是下面这样:
这么做合适吗?我们把音频帧时间戳1234和视频帧时间戳5678对应到绝对时间轴的0上,我们这么做的理由是什么?你可能会说,因为那是第一 个音频帧和第一个视频帧,所以可以对应到同一个点上,在第一幅图中我们就是这么做的,把音频帧时间戳0和视频帧时间戳0对应到绝对时间轴的0上。但是 RTP规范并没有规定第一个视频帧的时间戳和第一个音频帧的时间戳必须或者应该对应到绝对时间轴的同一个点上,从整个RTP规范中不能直接得出这样的结 论,也推导不出这样的结论。
我们上面两幅图所做的转换是不正确的,为什么呢?因为在做转换时,隐含了一个假设,我们想当然地认为这个假设是成立的,实际上它并不总是成立。这个假设就是第一个视频帧和第一个音频帧的时间戳应该对应到同一个点上,即无论它们时间戳是多少,都应该在同一时间播放。 仅仅使用RTP时间戳是无法实现媒体间同步的,根本的原因是音频时间轴和视频时间轴是完全独立的,通过音频帧和视频帧的时间戳,无法确定一个视频帧和一个音频帧的相对时间关系,也就是无法把它们都准确定位在绝对时间轴上,只能准确定位一个。 要实现RTP媒体间同步,需要借助于RTCP,在RTCP的SR包中,包含有 上面提到,我们的那个隐含的假设并不总是成立,那就是说它有成立的时候。那是不是说当它成立时,我们就可以不用RTCP来做媒体间同步了?答案是,基本上可以这么认为。 例如,对于RTP实时流,在发送端媒体间就同步的很好,在接收端只需做少许处理,不需要RTCP,就可以实现媒体间同步。当然,这只是少数例外。因为RTP规范并不包括这个假设,所以我们还是按照RTP规范来做吧。 下面说一下DirectShow和MPEG2-TS的时间戳。DirectShow中的时间戳和RTP中的时间戳,除了单位不一样,计算方法不一样 外,本质的区别就是DirectShow中的音频帧和视频帧时间戳使用的是同一个时间轴,所以不需要借助其他的东西,仅仅使用音频帧时间戳和视频帧时间戳 就可以实现媒体间同步。MPEG2-TS流中也有时间戳,它的时间戳和RTP及DirectShow的时间戳都不同,TS流中的音频帧和视频帧时间戳使用 的也是同一个时间轴,TS流中的音频和视频是复用的,这在一定程度上就起到了同步的作用,所以它并不是在每个帧上都打时间戳,比如它的PTS时间戳就是每 隔0.1秒一个,缺失的时间戳是通过其他时间戳插值计算出来的。
本站遵循Creative Commons Attribution 3.0 License,所有文章欢迎任何形式的转载,但请注明作者及出处,尊重他人劳动成果!
文章转载自: 罗索工作室 [ http://www.rosoo.net] 本文标题:关于RTP负载类型及时间戳介绍 本文作者:poseidonqiu 本文来源:blog.chinaunix.net 本文地址: http://www.rosoo.net/a/201104/11250.html |