您的位置:首页 > 编程语言 > PHP开发

RTP封装H264

2017-02-09 09:13 183 查看

1 H264数据结构

H264功能分为两层:视频编码层(VCL,VideoCodeing Layer)和网络提取层(NAL,Network Abstraction Layer)。VCL数据即编码处理的输出,它表示被压缩编码后的视频数据序列。在VCL数据传输或存储之前,这些编码的VCL数据,先被映射或封装在NAL单元中。每个NAL单元包括一个原始字节序列负荷(RBSP,Raw Byte Sequence Payload)、一组对应于视频编码的NAL头信息。RBSP的基本结构是:在原始编码数据的后面填充bit,1个bit“1”和若干bit“0”,以便字节对齐。NAL单元序列如图1所示。

 


图1 NAL单元序列
 
其中NAL头占用一个字节,如图2所示:包含1个bit的forbidden_zero_bit(F)、2个bit的nal_ref_idc(NRI)和5个比特的nal_unit_type(TYPE)。

  


图2 NAL头
 
F:H264规范声明设置为1指示语法为例。

NRI:00表示不是参考图像,可以丢弃;大于0的如果丢去则可能造成图像不完整。

TYPE:指示NAL类型,其取值如图3所示。

 

TYPE
NAL类型
0
未使用
1
不分区、非IDR图像的片
2
片分区A
3
片分区B
4
片分区C
5
IDR图像中的片
6
补充增强信息单元(SEI)
7
序列参数集(SPS)
8
图像参数集(PPS)
9
分界符
10
序列结束
11
码流结束
12
填充
13-23
保留
24-31
未使用
图3 NAL单元类型
 
         H264以字节流格式和RTP格式的码流结构如图4所示。

         起始码:如果NAL单元对应的片(Slice)为一帧的开始,则用4个字节的0x00000001表示,否则用3个字节表示,0x000001。

         脱壳操作:为了使NAL主体不包含起始码,在编码时没遇到连续两个字节的0x00,就插入一个字节的0x03,以和起始码相区别。解码时,则将相应0x03移除。

     


图4 H264码流结构

2 RTP封装H264

         RTP封装h264结构的数据包包括[RTP头]+[h264载荷],其中h264载荷的第一个字节(载荷头)表示了使用什么结构来对H264数据进行封装。并且载荷头的结构和NAL头是一致的,根据载荷头的后5个字节可以知道具体使用的封装结构,如图5所示。其中,可能的结构包括:

         单个NAL单元包:载荷中值包含一个NAL单元。载荷头类型域等于原始NAL单元类型,即范围在1-23之间。

         聚合包:本类型用于聚合多个NAL单元到单个RTP载荷中。分为4类:单时间聚合包类型A(STAP-A),单时间聚合包类型B(STAP-B),多时间聚合包类型16位位移(MTAP16)、多时间聚合包类型24位位移(MTAP24),其载荷头类型大小分别是:24,25,26,27。

         分片单元:用于分片单个NAL单元到多个RTP包。分为两类:FU-A、FU-B,其载荷头类型大小分别是:28,29。

 

TYPE
Packet
0
未使用
1-23
单个NAL单元包
24
STAP-A
25
STAP-B
26
MTAP16
27
MTAP24
28
FU-A
29
FU-B
30-31
未使用
图5 RTP载荷头类型

2.1 单个NAL单元包

         RTP载荷头和NAL头重合,也就是说RTP载荷仅仅包含一个NAL单元,如图6所示

举例:一个NAl单元的数据为00 0000 01 67 23 34 ……,则使用单个NAL单元包的封装结构为[RTP头] 67 23 34 ……。 

 


图6 单个NAL单元包

2.2 STAP-A

         聚合相同NAL时间的NAL单元,且不包含DON(解码顺序号)。如图7所示,RTP载荷部分包括一个字节的RTP载荷头和若干NAL单元,其中每个NAL单元前包含2个字节的NAL长度。

举例:有两个NAL单元分别为00 00 00 01 67 12 34 56,00 00 00 01 68 23 5678 9A,则使用STAP-A的封装结构为[RTP头] 78 00 04 67 12 34 56 00 05 68 23 56 78 9A

  


图7 STAP-A

2.2 STAP-B

         聚合相同NAL时间的NAL单元,且包含DON(解码顺序号)。图8所示,RTP载荷部分包括一个字节的RTP载荷头、2个字节DON和若干NAL单元,其中每个NAL单元前包含2个字节的NAL长度。

举例:有两个NAL单元分别为00 00 00 01 67 12 34 56,00 00 00 01 68 23 5678 9A,则使用STAP-B的封装结构为[RTP头] 78 [DON]00 04 67 12 34 56 00 05 68 23 56 78 9A,其中DON的获得暂不解释。



如8 STAP-B

2.3 MTAP16/24

         聚合具有差异NAL时间的NAL单元。如图9所示,MTAP16的RTP载荷包括一个字节的载荷头、2个字节的DONB(解码顺序号基址)和若干NAL单元,其中每个NAL单元前包含2字节的NAL单元长度、1个字节的DOND(解码顺序号差值)、2个字节的时间戳位移(TSoffset)。

如图10所示,MTAP24的RTP载荷包括一个字节的载荷头、2个字节的DONB(解码顺序号基址)和若干NAL单元,其中每个NAL单元前包含2字节的NAL单元长度、1个字节的DOND(解码顺序号差值)、3个字节的时间戳位移(TS offset)。

  


图9 MTAP-16
   

 
图10 MTAP-24

2.4 FU-A/B

         将一个NAL单元分片到多个RTP包中。如图11所示,FU-A的RTP载荷包括1个字节的FUindicator、一个字节的FU header和NAL单元的一部分。如图12所示,FU-B的RTP载荷包括1个字节的FU indicator、1个字节的FU header、2个字节的DON和NAL单元的一部分。

  


图11 FU-A
  


图12 FU-B
         其中FU-indicator的结构如图13所示:

         F:和NAL头的F一致。

         NRI:和NAL的NRI一致。

         TYPE:28或者29。

   


图13FU-indicator
         其中FU-header的结构如图14所示:

         S:为1表示是分片的开始,否则为0。

         E:为1表示分片的结束,否则为0。

         TYPE:和NAL头的TYPE一致。

  


图14 FU-header
         有多个FU-A/B分片获得完整的NAL单元:根据FU-header的S和E获得每一个分片,然后由FU-indicator的前3位和FU-header的后5位合成NAL头,再加上每一个分片的NAL单元的一部分就组成了完整的NAL单元。

注意:NAL头只需合成一次即可。

参考:

RTC3984

H264码流结构解析
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  rtp h264 封装