1.
2. RTP 协议关键参数的设置
3. H.264 基本流结构及其传输机制
3.1 H.264 基本流的结构
H.264 的基本流(elementary stream,ES)的结构分为两层,包括视频编码层(VCL)和网络适配层(NAL)。视频编码层负责高效的视频内容表示,而网络适配层负责以网络所要求的恰当的方式对数据进行打包和传送。引入NAL并使之与VCL分离带来的好处包括两方面:其一、使信号处理和网络传输分离,VCL 和NAL 可以在不同的处理平台上实现;其二、VCL 和NAL 分离设计,使得在不同的网络环境内,网关不需要因为网络环境不同而对VCL比特流进行重构和重编码。
H.264 的基本流由一系列NALU (Network Abstraction Layer Unit )组成,不同的NALU数据量各不相同。H.264 草案指出[2],当数据流是储存在介质上时,在每个NALU 前添加起始码:0x000001,用来指示一个 NALU的起始和终止位置。在这样的机制下,解码器在码流中检测起始码,作为一个NALU得起始标识,当检测到下一个起始码时,当前NALU结束。每个NALU单元由一个字节的 NALU头(NALU Header)和若干个字节的载荷数据(RBSP)组成。其中NALU 头的格式如图2 所示:
3.2 适用于 H.264 视频的传输机制
前面分别讨论了RTP 协议及H.264基本流的结构,那么如何使用RTP协议来传输H.264视频了?一个有效的办法就是从H.264视频中剥离出每个NALU,在每个NALU前添加相应的RTP包头,然后将包含RTP 包头和NALU 的数据包发送出去。下面就从RTP包头和NALU两方面分别阐述。
完整的 RTP 固定包头的格式在前面图 1 中已经指出,根据RFC3984[3],这里详细给出各个位的具体设置。
V:版本号,2 位。根据RFC3984,目前使用的RTP 版本号应设为0x10。
P:填充位,1 位。当前不使用特殊的加密算法,因此该位设为 0。
X:扩展位,1 位。当前固定头后面不跟随头扩展,因此该位也为 0。
CC:CSRC 计数,4 位。表示跟在 RTP 固定包头后面CSRC 的数目,对于本文所要实现的基本的流媒体服务器来说,没有用到混合器,该位也设为 0x0。
M:标示位,1 位。如果当前 NALU为一个接入单元最后的那个NALU,那么将M位置 1;或者当前RTP 数据包为一个NALU 的最后的那个分片时(NALU 的分片在后面讲述),M位置 1。其余情况下M 位保持为 0。
PT:载荷类型,7 位。对于H.264 视频格式,当前并没有规定一个默认的PT 值。因此选用大于 95 的值可以。此处设为0x60(十进制96)。
SQ:序号,16 位。序号的起始值为随机值,此处设为 0,每发送一个RTP 数据包,序号值加 1。
TS:时间戳,32 位。同序号一样,时间戳的起始值也为随机值,此处设为0。根据RFC3984, 与时间戳相应的时钟频率必须为90000HZ。
SSRC:同步源标示,32 位。SSRC应该被随机生成,以使在同一个RTP会话期中没有任何两个同步源具有相同的SSRC 识别符。此处仅有一个同步源,因此将其设为0x12345678。
对于每一个NALU,根据其包含的数据量的不同,其大小也有差异。在IP网络中,当要传输的IP 报文大小超过最大传输单元MTU(Maximum Transmission Unit )时就会产生IP分片情况。在以太网环境中可传输的最大 IP 报文(MTU)的大小为 1500 字节。如果发送的IP数据包大于MTU,数据包就会被拆开来传送,这样就会产生很多数据包碎片,增加丢包率,降低网络速度。对于视频传输而言,若RTP 包大于MTU 而由底层协议任意拆包,可能会导致接收端播放器的延时播放甚至无法正常播放。因此对于大于MTU 的NALU 单元,必须进行拆包处理。
RFC3984 给出了3 中不同的RTP 打包方案:
(1)Single NALU Packet:在一个RTP 包中只封装一个NALU,在本文中对于小于 1400字节的NALU 便采用这种打包方案。
(2)Aggregation Packet:在一个RTP 包中封装多个NALU,对于较小的NALU 可以采用这种打包方案,从而提高传输效率。
(3)Fragmentation Unit:一个NALU 封装在多个RTP包中,在本文中,对于大于1400字节的NALU 便采用这种方案进行拆包处理。
4. H.264 流媒体传输系统的实现
H.264RTP封包原理