1.什么是RTP
数据传输协议RTP,用于实时传输数据。RTP全名是Real-time Transport Protocol(实时传输协议)。它是IETF提出的一个标准,对应的RFC文档为RFC3550。RFC3550不仅定义了RTP,而且定义了配套的相关协议RTCP(Real-time Transport Control Protocol,即实时传输控制协议)。RTP用来为IP网上的语音、图像、传真等多种需要实时传输的多媒体数据提供端到端的实时传输服务。RTP为Internet上端到端的实时传输提供时间信息和流同步,但并不保证服务质量,服务质量由RTCP来提供。
2.RTP包格式
RTP报文由两部分组成:报头和有效载荷。RTP报头格式如下图所示,其中:
·V:RTP协议的版本号,占2位,当前协议版本号为2。
·P:填充标志,占1位,如果P=1,则在该报文的尾部将填充一个或多个额外的八位组,它们不是有效载荷的一部分。
·X:扩展标志,占1位,如果X=1,则在RTP报头后跟有一个扩展报头。
·CC:CSRC计数器,占 4位,指示CSRC 标识符的个数。主要用于多流组合传播,比如说5个人发送rtp到网关边缘,边缘把5个rtp转发给另外一个边缘,然后解出原始流。
·M: 标记,占1位,不同的有效载荷有不同的含义,对于视频,标记一帧的结束;对于音频,标记会话的开始。
·PT: 有效载荷类型,占7位,用于说明RTP报文中有效载荷的类型,如GSM音频、JPEM图像等。
·序列号:占16位,用于标识发送者所发送的RTP报文的序列号,每发送一个报文,序列号增1。接收者通过序列号来检测报文丢失情况,重新排序报文,恢复数据。
·时戳 (Timestamp):占32位,时戳反映了该RTP报文的第一个八位组的采样时刻。接收者使用时戳来计算延迟和延迟抖动,并进行同步控制。
·同步信源(SSRC)标识符:占32位,用于标识同步信源。该标识符是随机选择的,参加同一视频会议的两个同步信源不能有相同的SSRC。
·特约信源(CSRC)标识符:每个CSRC标识符占32位,可以有0~15个。每个CSRC标识了包含在该RTP报文有效载荷中的所有特约信源。
这里的同步信源是指产生媒体流的信源,它通过RTP报头中的一个32位数字SSRC标识符来标识,而不依赖于网络地址,接收者将根据SSRC标识符来区分不同的信源,进行RTP报文的分组。特约信源是指当混合器接收到一个或多个同步信源的RTP报文后,经过混合处理产生一个新的组合RTP报文,并把混合器作为组合RTP报文的 SSRC,而将原来所有的SSRC都作为CSRC传送给接收者,使接收者知道组成组合报文的各个SSRC。
在发送端,上层应用程序以分组形式将编码后的媒体数据传给RTP通信模块,作为RTP报文的有效载荷,RTP通信模块将根据上层应用提供的参数在有效载荷前添加RTP报头,形成 RTP报文,通过Socket接口选择UDP协议发送出去。
在接收端,RTP通信模块通过Socket接口接收到RTP报文后,将RTP报头分离出来作相应处理,再将RTP报文的有效载荷作为数据分组传递给上层应用。
考虑到在Internet这种复杂的环境中举行视频会议,RTP定义了两种中间系统:混合器(Mixer)和转换器(Translator)。
在Internet上举行视频会议时,可能有少数参加者通过低速链路与使用高速网络的多数参加者相连接。为了不强制所有会议参加者都使用低带宽和低质量的数据编码,RTP允许在低带宽区域附近使用混合器作为RTP级中继器。混合器从一个或多个信源接收RTP 报文,对到达的数据报文进行重新同步和重新组合,这些重组的数据流被混合成一个数据流,将数据编码转化为在低带宽上可用的类型,并通过低速链路向低带宽区域转发。为了对多个输入信源进行统一的同步,混合器在多个媒体流之间进行定时调整,产生它自己的定时同步,因此所有从混合器输出的报文都把混合器作为同步信源。为了保证接收者能够正确识别混合器处理前的原始报文发送者,混合器在RTP报头中设置了CSRC标识符队列,以标识那些产生混和报文的原始同步信源。
在Internet环境中,一些会议的参加者可能被隔离在应用级防火墙的外面,这些参加者被禁止直接使用 IP组播地址进行访问,虽然他们可能是通过高速链路连接的。在这些情况下,RTP允许使用转换器作为RTP级中继器。在防火墙两端分别安装一个转换器,防火墙之外的转换器过滤所有接收到的组播报文,并通过一条安全的连接传送给防火墙之内的转换器,内部转换器将这些组播报文再转发送给内部网络中的组播组成员。
3.rtp会话过程
当应用程序建立一个RTP会话时,应用程序将确定一对目的传输地址。目的传输地址由一个网络地址和一对端口组成,有两个端口:一个给RTP包,一个给RTCP包,使得RTP/RTCP数据能够正确发送。RTP数据发向偶数的UDP端口,而对应的控制信号RTCP数据发向相邻的奇数UDP端口(偶数的UDP端口+1),这样就构成一个UDP端口对。 RTP的发送过程如下,接收过程则相反。
1)RTP协议从上层接收流媒体信息码流(如H.263),封装成RTP数据包;
2)RTCP从上层接收控制信息,封装成RTCP控制包。
2)RTP将RTP 数据包发往UDP端口对中偶数端口;RTCP将RTCP控制包发往UDP端口对中的接收端口。
四、RTP载荷H264码流:
红色RTP协议头,黄色H264码流RTP头后是RTP载荷,RTP载荷第一个字节格式跟NALU头一样:
F: forbidden_zero_bit, 占1位,在 H.264 规范中规定了这一位必须为 0
NRI: nal_ref_idc, 占2位,取值从0到3,指示这个 NALU 的重要性,取值越大约重要。
Type:nalu是指包含在 NAL 单元中的 RBSP 数据结构的类型,其中0未指,1-19在264协议中有定义,20-23为264协议指定的保留位。24-29在RFC3984中进行了指定。其中STAP-A为24,FU-A为28。可以参见下面两个图:
常用 types:
Payload Type | Codec |
0 | PCM μ -Law |
8 | PCM-A Law |
9 | G..722 audio codec |
4 | G..723 audio codec |
15 | G..728 audio codec |
18 | G..729 audio codec |
34 | G..763 audio codec |
31 | G..761 audio codec |
1) 单个NAL单元包:荷载中只包含一个NAL单元。NAL头类型域等于原始 NAL单元(NALU)类型,即Type在范围1到23之间。
2)组合包:本类型用于聚合多个NAL单元到单个RTP荷载中。本包有四种版本,单时间聚合包类型A(STAP-A)单时间聚合包类型B(STAP-B),多时间聚合包类型(MTAP)16位位移(MTAP16),多时间聚合包类型(MTAP)24位位移(MTAP24)。赋予STAP-A,STAP-B,MTAP16,MTAP24的NAL单元类型号(Type)分别是24 25 26 27
3)分片包:用于分片单个NAL单元到多个RTP包。现存两个版本FU-A,FU-B,用NAL单元类型(Type)28 29标识
常用的打包时的分包规则:如果小于MTU采用单个NAL单元包,如果大于MTU就采用FUs分片方式
五、单个NAL单元包格式
对于NALU(NAL单元)的长度小于MTU大小的包,一般采用单一NAL单元模式
定义在此的NAL单元包必须只包含一个。RTP序号必须符合NAL单元的解码顺序。这种情况下,NAL单元的第一字节和RTP荷载头第一个字节重合。如上图所示。
对于一个原始H264的NALU单元常由[start code] [NALU Header] [NALU Payload]三部分组成,其中start code用于标识这是一个NALU单元的开始,必须是“00 00 00 01”或“00 00 01”,NALU头仅一个字节,其后都是NALU单元载荷。
打包时去除“00 00 01”或“00 00 00 01”的开始码,把其他数据封装成RTP包即可。
如有一个 H.264 的 NALU 是这样的:
[00 00 00 01 67 42 A0 1E 23 56 0E 2F ... ]
这是一个序列参数集 NAL 单元。 [00 00 00 01] 是四个字节的开始码, 67 是 NALU 头, 42 开始的数据是 NALU 载荷.
封装成 RTP 包将如下:
[ RTP Header ] [ 67 42 A0 1E 23 56 0E 2F ... ]
即只要去掉 4 个字节的开始码就可以了.
六、组合封包格式
当NALU的长度特别小时,可以把几个NALU单元封在一个RTP包中
七、分片单元(FU-A)
当NALU的长度超过MTU时,就必须对NALU单元进行分片封包,也称为Fragmentation Units (FUs)NAL单元的一个分片由整数个连续NAL单元字节组成。每个NAL单元字节必须正好是该NAL单元一个分片的一部分。
STAP-A 是什么?
STAP-A的作用是可以把连个nalu单元封装在一个RTP包里面进行传输,注意的是-A的格式都是不允许跨帧的,也就是两个nalu单元的时间戳必须是相同的。常见的场景是sps和pps两个小包被合并封装。
STAP-A格式
见上图,RTP头后面仅跟着STAP-A的头,这个格式F,NRI和Type组合而成,占一个字节,字段定义见前面Single NAL Unit的介绍,这里的Type为24。后面两个字节为第一个nalu单元的长度,后面跟个第一个nalu数据同Single NAL Unit的封装一致,第一个数据结束后,跟着第二个nalu的长度,占2个字节,依次类推。
FU-A是什么?
FU-A的作用是把一个原始的大的nalu切成多个数据包进行传输,主要场景在一个slice比较大的情况。FU-A会比较特殊,有FU-A起始包,FU-A包(如果只切两个包可能没有)和FU-A结束包组成。
FU-A格式
3.1 FU indicator
FU indicator
这个头已经很熟悉了,前面出现过多次,对于FU-A,type查前面的表可以知道是对应28.
3.2 FU header
FU header
这个头占一个字节,其中
S: 占1位如果是1表示当前这个包是FU-A的起始包
E: 占1位如果是1表示当前这个包是FU-A的结束包
R: 占1位,保留位,为0
Type: 实际包含的nalu的类型,见前面的表格
总结一下:
以上就是出现在sdp协商中的mode 1方式所支持的RFC3984包,这种方式在3984协议叫做叫做non-Interleaved,非交错模式,简单理解就是在一次封装的单元中必须是同一帧的数据。在协议中还支持Interleaved模式,交错模式,这种模式允许不同的帧做打包,考虑到传输的实时性,出现的比较少,需要协商出mode 2的能力,这种情况打包和解包需要支持STAP-B,MTAP16,MTAP24以及FU-B格式,实际应用很少见,有需要可以参考协议文档。