RTP Payload H264

  

一、简介

1.RTP和RTCP

        RTP全名是Real-time Transport Protocol(实时传输协议)。它是IETF提出的一个标准,对应的RFC文档为RFC3550(RFC1889为其过期版本)。RFC3550不仅定义了RTP,而且定义了配套的相关协议RTCP(Real-time Transport Control Protocol,即实时传输控制协议)。RTP被定义为在一对一或一对多的传输情况下工作,其目的是提供时间信息和实现流同步。RTP的典型应用建立在UDP(User Datagram Protocol,用户数据包协议)上,但也可以在TCP(Transfer Control Protocol,传输控制协议)或ATM(Asynchronous Transfer Mode,异步传输模式)等其他协议之上工作。应用程序通常在 UDP 上运行 RTP 以便使用其多路结点和校验服务。RTP本身只保证实时数据的传输,并不能为按顺序传送数据包提供可靠的传送机制,也不提供流量控制或拥塞控制,它依靠RTCP提供这些服务。
        RTP协议详细说明了在互联网上传递音频和视频的标准数据包格式。它一开始被设计为一个多播协议,但后来被用在很多单播应用中。RTP协议常用于流媒体系统(配合RTSP协议)、视频会议和一键通(Push to Talk)系统(配合H.323或SIP),使它成为IP电话产业的技术基础。RTP广泛应用于流媒体相关的通讯和娱乐,包括电话、视频会议、电视和基于网络的一键通业务(类似对讲机的通话)。
        RTCP全名是Realtime Transport Control Protocol(实时传输控制协议)。它负责管理传输质量,在当前应用进程之间交换控制信息。在RTP会话期间,各参与者周期性地传送RTCP包,包中含有已发送的数据包的数量、丢失的数据包的数量等统计资料,因此,服务器可以利用这些信息动态地改变传输速率,甚至改变有效载荷类型。RTP和RTCP配合使用,能以有效的反馈和最小的开销使传输效率最佳化,故特别适合传送网上的实时数据。相对于RTP来说,RTCP所占的带宽非常小,通常只有5%。

2.流媒体

       流媒体是指Internet上使用流式传输技术的连续时基媒体。当前在Internet上传输音频和视频等信息主要有两种方式:下载和流式传输两种方式。
       下载情况下,用户需要先下载整个媒体文件到本地,然后才能播放媒体文件。在视频直播等应用场合,由于生成整个媒体文件要等直播结束,也就是用户至少要在直播结束后才能看到直播节目,所以用下载方式不能实现直播。
       流式传输是实现流媒体的关键技术。使用流式传输可以边下载边观看流媒体节目。由于Internet是基于分组传输的,所以接收端收到的数据包往往有延迟和乱序(流式传输构建在UDP上)。要实现流式传输,就是要从降低延迟和恢复数据包时序入手。在发送端,为降低延迟,往往对传输数据进行预处理(降低质量和高效压缩)。在接收端为了恢复时序,采用了接收缓冲;而为了实现媒体的流畅播放,则采用了播放缓冲。
       使用接收缓冲,可以将接收到的数据包缓存起来,然后根据数据包的封装信息(如包序号和时戳等),将乱序的包重新排序,最后将重新排序了的数据包放入播放缓冲播放。
       为什么需要播放缓冲呢?容易想到,由于网络不可能很理想,并且对数据包排序需要处理时耗,我们得到排序好的数据包的时间间隔是不等的。如果不用播放缓冲,那么播放节目会很卡,这叫时延抖动。相反,使用播放缓冲,在开始播放时,花费几十秒钟先将播放缓冲填满(例如PPLIVE),可以有效地消除时延抖动,从而在不太损失实时性的前提下实现流媒体的顺畅播放。
       到目前为止,Internet 上使用较多的流式视频格式主要有以下三种:RealNetworks 公司的RealMedia,Apple 公司的QuickTime 以及Microsoft 公司的Advanced Streaming Format (ASF) 。
       上面在谈接收缓冲时,说到了流媒体数据包的封装信息(包序号和时戳等),这在后面的RTP封装中会有体现。另外,RealMedia这些流式媒体格式只是编解码有不同,但对于RTP来说,它们都是待封装传输的流媒体数据而没有什么不同。

3.工作流程

        RTP协议从上层接收流媒体信息码流(如H.263),装配成RTP数据包发送给下层,下层协议提供RTP和RTCP的分流。如在UDP中,RTP使用一个偶数号端口,则相应的RTCP使用其后的奇数号端口。RTP数据包没有长度限制,它的最大包长只受下层协议的限制。
        RTP用于在单播或多播网络中传送实时数据。它们典型的应用场合有如下几个。
       简单的多播音频会议:语音通信通过一个多播地址和一对端口来实现。一个用于音频数据(RTP),另一个用于控制包(RTCP)。
      音频和视频会议:如果在一次会议中同时使用了音频和视频会议,这两种媒体将分别在不同的RTP会话中传送,每一个会话使用不同的传输地址(IP地址+端口)。如果一个用户同时使用了两个会话,则每个会话对应的RTCP包都使用规范化名字CNAME(Canonical Name)。与会者可以根据RTCP包中的CNAME来获取相关联的音频和视频,然后根据RTCP包中的计时信息(Network time protocol)来实现音频和视频的同步。

二、RTP协议格式

        RTP报文由报文头和报文体组成,报文头格式如下图所示。

V:RTP协议的版本号,占2位,当前协议版本号为2。
P:填充标志,占1位,如果P=1,则在该报文的尾部填充一个或多个额外的八位组,它们不是有效载荷的一部分。
X:扩展标志,占1位,如果X=1,则在RTP报头后跟有一个扩展报头。
CC:CSRC计数器,占4位,指示CSRC 标识符的个数。
M:标记,占1位,不同的有效载荷有不同的含义,对于视频,标记一帧的结束;对于音频,标记会话的开始。
PT:有效载荷类型,占7位,用于说明RTP报文中有效载荷的类型,如GSM音频、JPEM图像等,在流媒体中大部分是           用来区分音频流和视频流的,这样便于客户端进行解析。
SN:序列号,占16位,发送方在每发送完一个RTP包后就将该域的值增加1,接收方可以由该域检测包的丢失及恢             复包序列。序列号的初始值是随机的。
timestamp:时间戳,占32位,记录了该包中数据的第一个字节的采样时刻。它是去除抖动和实现同步不可缺少的。
SSRC:同步源标识符,占32位,同步源就是指RTP包流的来源。在同一个RTP会话中不能有两个相同的SSRC值。                    该标识符是随机选取的 RFC1889推荐了MD5随机算法。
CSRC:特约信源标识符,每个CSRC标识符占32位,可以有0~15个。每个CSRC标识了包含在该RTP报文有效载荷中               的所有特约信源。

三、时间戳与同步

      时间戳段是RTP报文头中说明数据包时间的同步信息,是数据能以正确的时间顺序恢复的关键。时间戳的值给出了分组中数据的第一个字节的采样时间(Sampling Instant),要求发送方时间戳的时钟是连续、单调增长的,即使在没有数据输入或发送数据时也是如此。在静默时,发送方不必发送数据,保持时间戳的增长,在接收端,由于接收到的数据分组的序号没有丢失,就知道没有发生数据丢失,而且只要比较前后分组的时间戳的差异,就可以确定输出的时间间隔。
        RTP规定一次会话的初始时间戳必须随机选择,但协议没有规定时间戳的单位,也没有规定该值的精确解释,而是由负载类型来确定时钟的颗粒,这样各种应用类型可以根据需要选择合适的输出计时精度。
        在RTP传输音频数据时,一般选定逻辑时间戳速率与采样速率相同,但是在传输视频数据时,必须使时间戳速率大于每帧的一个滴答。如果数据是在同一时刻采样的,协议标准还允许多个分组具有相同的时间戳值。
        RTCP的一个关键作用就是能让接收方同步多个RTP流,例如:当音频与视频一起传输的时候,由于编码的不同,RTP使用两个流分别进行传输,这样两个流的时间戳以不同的速率运行,接收方必须同步两个流,以保证声音与影像的一致。为能进行流同步,RTCP要求发送方给每个传送一个唯一的标识数据源的规范名(Canonical Name),尽管由一个数据源发出的不同的流具有不同的同步源标识(SSRC),但具有相同的规范名,这样接收方就知道哪些流是有关联的。

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 payload类型

PT Encoding Name Audio/Video (A/V) Clock Rate (Hz) Channels Reference 
0PCMUA80001[RFC3551]
1Reserved
2Reserved
3GSMA80001[RFC3551]
4G723A80001[Vineet_Kumar][RFC3551]
5DVI4A80001[RFC3551]
6DVI4A160001[RFC3551]
7LPCA80001[RFC3551]
8PCMAA80001[RFC3551]
9G722A80001[RFC3551]
10L16A441002[RFC3551]
11L16A441001[RFC3551]
12QCELPA80001[RFC3551]
13CNA80001[RFC3389]
14MPAA90000[RFC3551][RFC2250]
15G728A80001[RFC3551]
16DVI4A110251[Joseph_Di_Pol]
17DVI4A220501[Joseph_Di_Pol]
18G729A80001[RFC3551]
19ReservedA
20UnassignedA
21UnassignedA
22UnassignedA
23UnassignedA
24UnassignedV
25CelBV90000[RFC2029]
26JPEGV90000[RFC2435]
27UnassignedV
28nvV90000[RFC3551]
29UnassignedV
30UnassignedV
31H261V90000[RFC4587]
32MPVV90000[RFC2250]
33MP2TAV90000[RFC2250]
34H263V90000[Chunrong_Zhu]
35-71Unassigned?
72-76Reserved for RTCP conflict avoidance[RFC3551]
77-95Unassigned?
96-127dynamic?[RFC3551]

    除了上表中明确指定PT值的负载类型,还有些负载类型由于诞生的较晚,没有具体的PT值,只能使用动态(dynamic)PT值,即96到127,这就是为什么大家普遍指定H264的PT值为96。具体PT值的负载类型可以在这里查询到:
RTP Payload Type

   RTP Payload H264详细文档可以参考:

    RFC 6184 - RTP Payload Format for H.264 Video

    RFC 6184 - RTP Payload Format for H.264 Video

    RTP负载为H.264定义了三种不同的基本的负载结构,接收端可能通过RTP负载的首字节来识别它们。这一个字节类似NALU头的格式,它的类型字段则指出了代表的是哪一种结构,这个字节的结构如下:

+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|F|NRI|  Type   |
+---------------+

Type定义如下:
0     没有定义
1-23  NAL单元   单个NAL单元包.
24    STAP-A   单一时间的组合包
25    STAP-B   单一时间的组合包
26    MTAP16   多个时间的组合包
27    MTAP24   多个时间的组合包
28    FU-A     分片的单元
29    FU-B     分片的单元
30-31 没有定义

首字节的类型字段和H.264的NALU头中类型字段的区别是,当Type的值为24~31表示这是一个特别格式的NAL单元,而H.264中,只取1~23是有效的值。下面分别说明这三种负载结构。

一.Single NALU Packet(单一NAL单元模式)

    

    即一个RTP负载仅由首字节和一个NALU负载组成,对于小于1400字节的NALU便采用这种打包方案。这种情况下首字节类型字段和原始的H.264的NALU头类型字段是一样的。也就是说,在这种情况下RTP的负载是一个完整的NALU。

 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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|F|NRI|  Type   |                                               |
+-+-+-+-+-+-+-+-+                                               |
|                                                               |
|               Bytes 2..n of a single NAL unit                 |
|                                                               |
|                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                               :...OPTIONAL RTP padding        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

二. Aggregation Packet(组合封包模式)

    在一个RTP中封装多个NALU,对于较小的NALU可以采用这种打包方案,从而提高传输效率。即可能是由多个NALU组成一个RTP包。分别有4种组合方式,STAP-A、STAP-B、MTAP16和MTAP24。那么这里的RTP负载首字节类型值分别是24、25、26和27。

 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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|F|NRI|  Type   |                                               |
+-+-+-+-+-+-+-+-+                                               |
|                                                               |
|             one or more aggregation units                     |
|                                                               |
|                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                               :...OPTIONAL RTP padding        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

三.Fragmentation Units(分片封包模式FUs)

    一个NALU封装在多个RTP中,每个RTP负载由首字节(这里实际上是FU indicator,但是它和原首字节的结构一样,这里仍然称首字节)、FU header和NALU负载的一部分组成。对于大于1400字节的NALU便采用这种方案进行拆包处理。存在两种类型FU-A和FU-B,类型值分别是28和29。

FU-A类型如下图所示:

 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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| FU indicator  |   FU header   |                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |
|                                                               |
|                         FU payload                            |
|                                                               |
|                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                               :...OPTIONAL RTP padding        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

FU-B类型如下图所示

 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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| FU indicator  |   FU header   |               DON             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
|                                                               |
|                         FU payload                            |
|                                                               |
|                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                               :...OPTIONAL RTP padding        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

与FU-A相比,FU-B多了一个DON(decoding order number),DON使用的是网络字节序。FU-B只能用于隔行扫描封包模式,不能用于其他方面。

FU indicator字节结构如下所示:

+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|F|NRI|  Type   |
+---------------+

Type=28或29

FU header字节结构如下所示:

+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|S|E|R|  Type   |
+---------------+

S(Start): 1 bit,当设置成1,该位指示分片NAL单元的开始。当随后的FU负载不是分片NAL单元的开始,该位设为0。
E(End): 1 bit,当设置成1, 该位指示分片NAL单元的结束,此时荷载的最后字节也是分片NAL单元的最后一个字节。当随后的FU荷载不是分片NAL单元的结束,该位设为0。
R(Reserved): 1 bit,保留位必须设置为0,且接收者必须忽略该位。

Type:与NALU头中的Type值相同

本文由网上多篇博客整理而来。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

li_wen01

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值