首页 > 学院 > 开发设计 > 正文

RTP封装H264

2019-11-10 18:25:25
字体:
来源:转载
供稿:网友

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码流结构解析


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表