H.264 的功能分为两层,即视频编码层(VCL)和网络提取层(NAL,Network Abstraction Layer)。
VCL 数据即编码处理的输出,它表示被压缩编码后的视频数据序列。在 VCL 数据传输或存储之前,这些编码的 VCL 数据,先被映射或封装进 NAL 单元中。
简单的说,VCL负责数据的编码压缩,NAL负责数据的封装传输。
H.264原始码流是一个一个的NALU组成的。
每个NALU之间都使用start code(起始码)分隔。
start code为00 00 00 01 或者 00 00 01。
00 00 00 01为SPS或PPS的起始码
00 00 01是其他NALU的起始码
每个 NALU包括一个头部信息(NAL header)和一个原始字节序列负荷(RBSP)。
NAL Header
bit[7]:必须为0
bit[5-6]:标记该NALU的重要性
bit[0-4]:NALU单元的类型
下图为NAL Header的具体定义
类型为 7、8 的 NAL 单元中分别包含了序列参数集(SPS)和图像参数集(PPS),图像参数集和序列参数集在其它数据 NAL 单元的解码过程中作为参数使用,所以这两个数据对于解码图像数据非常重要。
RBSP
NAL 包将其负载数据存储在 RBSP(Raw Byte Sequence Payload) 中,RBSP 是一系列的 SODB(String Of Data Bits)。
编码后的数据精度为bit,码流是以byte为单位。
所以RBSP = SODB + RBSP trailing bits
用一幅图总结上面的内容
当我们拿到RBSP或SODB之后,就可以根据NALU Header中得到的NALU Type,去解析它们,重建图像。其中解析语法元素的框图如下:
下面来看一个H.264码流的具体结构
一张图片可以包含一个或多个分片(SLICE),而每一个分片(SLICE)又会被分为了若干宏块(Macroblock)。对于分片(SLICE)来说,有如下这些类型:
分片头(Slice Header)中包含着分片类型、分片中的宏块类型、分片帧的数量以及对应的帧的设置和参数等信息,而分片数据中则是宏块,这里就是我们要找的存储像素数据的地方。
宏块是视频信息的主要承载者,因为它包含着每一个像素的亮度和色度信息。视频解码最主要的工作则是提供高效的方式从码流中获得宏块中的像素阵列。
从上图中,可以看到,宏块中包含了宏块类型、预测类型、Coded Block Pattern、Quantization Parameter、像素的亮度和色度数据集等等信息。
参考: