RTP协议是real-time transport protocol的缩写,被设计来传输流媒体数据,有着广泛的应用,其它相关介绍自己去看RFC,我不打算讨论这些无聊的概念性的东西。
(1)了解RTP
可以说,RTP协议不依赖于底层协议,也就是说,它是独立的协议。而一般的,由于UDP包的快速、时实性高的特点,它通常和UDP结合在一起,作为UDP的上层载体数据的形式传播。
typedef struct {
IN OUT UINT32 timestamp;
IN OUT BOOL marker;
IN OUT BYTE payload;
OUT UINT32 sSrc;
OUT UINT16 sequenceNumber;
OUT int sByte;
OUT int len;
} rtpParam;
这是一个RTP头,很简单,并没有你想象的那么复杂,对不对?我们来看几个主要的参数,他们也是RTP的灵魂:
(1)payload。payload表示了此RTP包的数据是那种类型的数据,不同的数值表示不同的类型。如0是PCMU,8是723,24是视频263等等。
(2)SSRC,这个东西并不常用,实际上它是一个随即生成的ID,表示了一个RTP连接。在应用的时候,确保这个ID唯一就可以了。
(3)sequence number。也就是序列号,它表示了当前包是第几个包。发送方每发送一个包,就把这个数值加一。接受放可以根据这个数值来重新组合包顺序,判断包是否丢失等操作。注意:它只是表示了包的先后顺序,它不能表示时间上的任何其它信息。这个请和后面的时间戳比较。
(4)timestamp。时间戳,它的概念稍微有点复杂,我用稍微通俗点的理解去解释它,虽然这样有点不太正确。时间戳顾名思义,它表示了一个数据产生的时间,和我们邮递的邮戳一样,它是个时间标记(至于这个时间干什么用,我后面会详细的说),通常表示RTP数据包中,第一个字节数据产生的时间(至于你是不是这么用就是你写程序的问题了)。
如果你上面理解了,那么我们更进一步:实际上,时间戳增加一并不是我们通常意义上的过了一个微秒,而是增加了一个采样间隔那么长的时间。举个例子来说。不同的采集有不同的采样频率,比如一般的音频是8K的采样频率,也就是一毫秒采集8次数据,也就是每次采样间隔是1/8MS,而timestamp增加1也就意味着增加了一个采样间隔。也就是过了1/8MS。换个例子,如果令一种编码的采样频率是16K,那么timestamp增加1也就意味着系统过了1/16MS。也就是说,再同一个系统中,对不同编码,虽然使用同一个时钟,但timestamp的增长速度是不同的,在这个例子中,采样频率是16K的编码要比8K的快两倍,请记住这个区别。
(2)了解RTCP
RTCP协议是real-time transport control protocol的缩写,被设计来做RTP的控制,这个相对来说大家不怎么关心,我只介绍下它基本的东西。
RTCP实际上是RTP传输情况的反馈,通俗的说,它告诉另外一方,在一端时间内(5秒),它发送多少数据包给对方,接收到了多少对方的包。
另外,在RTCP中,还有两个比较重要的东西,一个64位的绝对时间戳和一个32位的相对时间戳。64 位时间戳也叫NTP时间戳,它的前32位是从1900 年1 月1 日0 时开始到现在的以秒为单位的整数部分,后32 位是此时间的小数部,因此,它可以肯定的表示了数据发送出去的绝对时间。32位的时间戳和RTP中的时间戳是一样的,没有任何区别。
(3)大家感兴趣的时间戳的使用和同步的一些话题。
1、SSRC的作用。
SSRC相当于一个RTP传输session的ID,就象每个人都有一个名字一样,每一个RTP传输也都有一个名字。这个数字是随机产生,并且要保证唯一。当RTP session改变(如IP等)时,这个ID也要改变。
2、序列号字段是否可以作为流内的同步标时?
我在上面已经说过,序列号只表示了包发出的先后顺序,它表示不了任何时间上的其它概念,所有严格的说,序列号并不能作为流内的同步标志。但是,由于一般来说,包的发送时间都会有严格限制,比如音频包是每秒种发送30个数据包,也就是说,每个包间隔1000/30MS,而这个时间就可以作为一个同步时间来播放。也就是说,按照序列号,每1000/30MS间隔播放一个数据包,这样也能保证同步,但是这时候请考虑丢包问题。
3、绝对时间戳和相对时间戳在进行同步处理时有什么不同
当我们取得绝对时间后,我们就可以根据这个绝对时间来播放这些数据包。这个绝对时间,加上我们需要的延时(用于数据传输,解码等等的时间)就是我们的播放时间,这样我们可以保证时间的严格同步(相当于把对方的动作延时一段时间后原原本本的再现出来)。目前,在RTP中,能得到这个绝对时间的办法只有RTCP。
对于相对时间戳,我们更关心的是两个时间戳之间的时间间隔,依靠这个时间间隔,来确定两个包的播放时间间隔。
4、单个媒体内的同步和不同媒体流之间的同步在处理方式上有什么不同
应该说,不同媒体之间同步比单媒体同步要复杂得多,除了要保证本身的播放要和时间同步外,还要保证两个或多个媒体间同步(比如音视频的同步)。这种不同更关心的两个时间戳时间的换算统一,前面我已经说过,不同编码有不同的采样频率,那么时间戳的增长速度就不同。另外,两个时间戳也需要有一个标准时间来表示时间戳的同步。最简单的方法是两个媒体的第一个时间戳相同,表示两个流的采集开始时间统一。另外还可以通过RTCP来做不同流之间的同步,这在下个问题中会提到。
5、时间戳字段如何用于作为流间同步标识
在RTP协议中, 我们取得时间戳的方法有两个:一个是RTP包中的时间戳,另外一个是RTCP包中的绝对时间戳和相对时间戳。绝对时间戳的概念上面我已经说了,它可以表示系统的绝对时间。而RTCP包中的相对时间就是RTP包中的时间。根据这两个时间,不同流都可以纠正自己播放时间和真正时间的偏差以达到和绝对时间同步的目的。反过来说,如果我们没有办法拿到这个绝对时间,只有RTP包中的相对时间,那怎我们需要确定两个流在某一时间点的时间戳的数值。通俗的说,就是在某个时间点,流A的timestamp是多少,B是多少,然后根据这个时间两个流播放的延时时间,以达到同步的目的。实现这个目的最简单的办法是在两个流开始的时候,使用相同的stamp,拿音视频来说,在某一绝对时刻,采集相应的数据,并打上相同的时间戳,以后的播放,都以这个时间做基准时间,以保证同步。