H.264NAL单元语法

分层结构:

在H.264/AVC视频编码标准中,整个系统框架被分为了两个层面:视频编码层(VCL)和网络提取层(NAL)。前者负责有效表示视频数据的内容,而后者则负责格式化数据并提供头信息,以保证数据适合各种信道和存储介质上的传输。因此平时的每帧数据就是一个NAL单元(SPS与PPS除外)。VCL数据即被压缩编码后的视频数据序列。在VCL数据要封装到NAL单元中之后,才可以用来传输或存储。

H.264NAL单元语法

NALU (Network AbstractionLayer Unit )

●SPS:序列参数集,作用于一系列连续的编码图像;

●PSS:图像参数集,作用于编码视频序列中一个或多个独立的图像;

●I帧:帧内编码帧,是一种自带全部信息的独立帧,无需参考其它图像便可独立进行解码,视频序列中的第一个帧始终都是I帧。

●P帧:前向预测编码帧,P帧由在它前面的P帧或者I帧预测而来

●B帧:双向预测内插编码帧,B帧是以前面的I或P帧和后面的P帧为参考帧。

H.264编码器输出的码流实际上是一连串二进制比特流,这些语法是被组织成一个有层次的结构。编码视频流由一系列的图像组(GOP)顺序排列而成,一个GOP的第一帧一定是I帧,也是IDR(及时解码刷新)图像,他的编码不涉及其他帧数据。但I图像不一定是IDR图像,在GOP其他地方有可能也有I图像。

GOP中的每一帧又可以分为若干slice,再以slice为单位进行编码。每个slice是由若干宏块(Macro Block,MB)组成,其尺寸为16*16,是H.264编码的基本单位。而MB是由4个8*8亮度块和2个8*8色差块组成。

H.264的5层码流结构由上到下分别是GOP,帧,slice,MB,B。结构如下(图片源于网络)

H.264NAL单元语法

H.264NAL单元语法

H.264NAL单元语法

H.264NAL单元语法

NALU结构:

H.264单元具体结构如下:

H.264NAL单元语法

其包括原始字节序列载荷RBSP和一个字节的NAL头。

RBSP:

●SODB(String of Data Bits),数据比特串,它是最原始的编码数据。

●RBSP(Raw Byte Sequence Payload), 原始字节序列载荷,它是NAL的基本传输单元,它是在 SODB 的后面添加了结尾比特“1”和若干比特0,以便字节对齐。

NAL Header:

NALU头部占一个字节,由三部分组成forbidden_bit(禁止位,1bit),nal_reference_bit(重要性指示位 2bits)(优先级),nal_unit_type(NALU类型,5bits)。

NALU头的各个部分说明:

●F:  1  bit

forbidden_zero_bit. 在 H.264 规范中规定了这一位必须为 0.

●NRI:  2 bit

nal_ref_idc. 取 00 ~ 11, 似乎指示这个 NALU 的重要性,如 00 的 NALU 解码器可以丢弃它而不影响图像的回放. 不过一般情况下不太关心。 

●Type:  5  bit

nal_unit_type. 这个 NALU 单元的类型. 简述如下:

0     没有定义

1-23 NAL单元 单个 NAL 单元包.

24    STAP-A   单一时间的组合包

25    STAP-B   单一时间的组合包

26    MTAP16   多个时间的组合包

27    MTAP24   多个时间的组合包

28    FU-A     分片的单元

29    FU-B     分片的单元

30-31 没有定义


NALU类型:

对于一个原始的 H.264 NALU 单元常由 [Start Code] [NALU Header][NALU Payload] 三部分组成,标识NAL单元中的RBSP数据类型,NALU根据nal_unit_type的类型,可以分为:VCL的NAL单元和非VCL的NAL单元,其中,nal_unit_type为1, 2, 3, 4, 5及12的NAL单元称为VCL的NAL单元,其他类型的NAL单元为非VCL的NAL单元。详情如下:

H.264NAL单元语法

NALU起始码:

H.264在每个NALU前添加三个字节的起始码“0x 00 00 01”或四个字节起始码“0x 00 00 00 01”。

为了防止RBSP数据中出现“0x 00 00 01” 数据被误解成起始码,在编码完成一个NAL时,编码器按字节搜索NALU的RBSP数据中是否存在“00000000 00000000 000000**”,这里**表示可能的2bite数:00、01、10、11。如果存在,则在两个全0的字节后面插入一个0x03字节的添加码,即“00000000 00000000 00000011000000**”,解码时发现“0x 00 00 03 0*”字节,则扣除0x03后还原为原来的数据。

以一段实际的H.264码流为例:

H.264NAL单元语法

起始码有两种,图中红色矩形框部分,四个字节的“00 00 00 01”和三个字节的“00 00 01”都是。以起始码分割之后的下一个字节就是NALU类型,将其转为二进制数据后,解读顺序为从左往右算,如下:

(1)第1位禁止位,值为1表示语法出错

(2)第2~3位为参考级别

(3)第4~8为是nal单元类型

例如上面起始码后有67,68,06, 65,41,01,

●其中0x67的二进制码为:0110 0111

4-8为00111,转为十进制7,参考NALU类型语义表:7对应序列参数集SPS,

●其中0x68的二进制码为:0110 0100

4-8为00100,转为十进制4,参考NALU类型语义表:8对应图像参数集PPS

●同理,可得常用的NAL头对应的类型:

0x67: 序列参数集SPS

0x68: 图像参数集PPS

0x41: 不分区、非IDR图像的片

0x65: IDR  

0x61: non-IDR Slice

0x01: B Slice

0x06:补充增强信息单元SEI

0x09: 分界符AU Delimiter