1.NAL全称Network Abstract Layer, 即网络抽象层。
在H.264/AVC视频编码标准中,无论是存储还是网络传输,H264 原始码流是由一个接一个 NALU(NAL Unit) 组成,整个系统框架被分为两个层面:视频编码层面(VCL)和网络抽象层面(NAL)。其中,前者负责有效表示视频数据的内容,而后者则负责格式化数据并提供头信息,以保证数据适合各种信道和存储介质上的传输。
VCL:负责有效表示视频数据的内容,包括核心压缩引擎和块、宏块和片的语法级别定义,设计目标是尽可能地独立于网络进行高效的编码。
NAL:负责格式化数据并提供头信息,将 VCL 产生的比特字符串适配到各种各样的网络和多元环境中,覆盖了所有片级以上的语法级别。
2.视频压缩
2.1帧内压缩
帧内压缩是生成I帧的算法 。
帧内压缩,指的是一帧图片的内部压缩。当H.264对图片进行 16 * 16 分块后,会对每个小块内的图像进行分析,如果2个小块图像比较相近,那么住需要存储一张即可,无需存储重复图块。这样可以有效压缩图片的存储大小。
帧内(Intraframe)压缩的原理是:当压缩一帧图像时,仅考虑本帧的数据而不考虑相邻帧之间的冗余信息,一般采用有损压缩算法,由于帧内压缩是编码一个完整的图像,所以可以独立的解码、显示。帧内压缩率一般不高。
2.2帧间压缩
帧间压缩是生成B帧和P帧的算法 。
帧间压缩 , 指的是图片间的图像压缩。在每帧图片划分成16 * 16 小块的图像进行分析基础上,比图片间的数据,如果两张图片比较相近,对相同的图像模块只需存储一份,对不同的部分再做存储。避免了重复数据的存储,极大改善了图片压缩空间。
帧间(Interframe)压缩的原理是:相邻几帧的数据有很大的相关性,或者说前后两帧信息变化很小的特点。连续的视频其相邻帧之间具有冗余信息,根据这一特性,压缩相邻帧之间的冗余量就可以进一步提高压缩量,减小压缩比。
帧间压缩也称为时间压缩(Temporalcompression),它通过比较时间轴上不同帧之间的数据进行压缩。帧间压缩是无损的,它通过比较本帧与相邻帧之间的差异,仅记录本帧与其相邻帧的差值,这样可以大大减少数据量。
3.NALU的类型
在H.264/AVC中,定义了多种NALU的类型,以适应不同的应用场景。下面是一些常见的类型:
帧内预测(I)
仅使用当前帧的信息进行编码。也叫帧内压缩,可以通过视频解压算法解压成一张完整的图片,它是一帧画面的完整保留,也被成为关键帧,一般在检测到丢包时,我们会立即向对方强求一个I帧。
预测(P)
使用前一帧的信息进行编码。也叫帧间压缩,前向预测编码帧,其表示的是这一帧与前一帧的差别,即预测差值与运动矢量。
双向预测(B)
使用前一帧和后一帧的信息进行编码。双向预测编码帧,记录的是本帧与前后帧的差别,其压缩率较高,但是解码对性能要求较高,一般不使用。
序列参数集(SPS)
全称Sequence Paramater Set,包含了一组连续图像的编码信息。
图像参数集(PPS)
全称Picture Paramater Set,包含了一个图像的编码信息。
4.NALU的结构
每个NALU包含了一个字节大小的NALU头信息
(NAL header),以及一个原始字节序列负荷(RBSP,Raw Byte Sequence Payload)。
4.1头部
头部是NALU的固定部分,占1字节。它包含了以下信息:
禁止位(forbidden_zero_bit)
1比特,必须为0。
NAL引用指数(nal_ref_idc)
2比特,表示该NALU的重要性。值越大,重要性越高。解码器在解码处理不过来的时候,可以丢掉重要性为0的NALU,而不影响图像的回放 。 如果当前NALU是属于参考帧的片,或是序列参数集,或是图像参数集这些重要的单位时,本句法元素必需大于0。
NAL单元类型(nal_unit_type)
5比特,表示NALU的类型。例如,类型可以是编码的视频数据、参数集等。
NALU类型的详细解析表 :
常见的NALU类型:
十六进制、二进制 类型 重要性 类型值
0x67 (0 11 00111) SPS 非常重要 type = 7
0x68 (0 11 01000) PPS 非常重要 type = 8
0x65 (0 11 00101) IDR帧 关键帧 非常重要 type = 5
0x61 (0 11 00001) I帧 非常重要 type=1非IDR的I帧不大常见
0x41 (0 10 00001) P帧 重要 type = 1
0x01 (0 00 00001) B帧 不重要 type = 1
0x06 (0 00 00110) SEI 不重要 type = 6
分析:以00 00 00 01分割之后的下一个字节就是NALU类型,将其转为二进制数据后,解读顺序为从左往右算,如下:
(1)第1位禁止位,值为1表示语法出错
(2)第2~3位为参考级别
(3)第4~8为是nal单元类型
其中0x67的二进制码为:
0110 0111
4-8为00111,转为十进制7,参考第二幅图:7对应序列参数集SPS
其中0x68的二进制码为:
0110 1000
4-8为01000,转为十进制8,参考第二幅图:8对应图像参数集PPS
其中0x65的二进制码为:
0110 0101
4-8为00101,转为十进制5,参考第二幅图:5对应IDR图像中的片(I帧)
判断是否为I帧的算法为: (NALU类型 & 0001 1111) = 5 即 NALU类型 & 31 = 5
比如0x65 & 31 = 5
4.2原始字节序列负荷(RBSP,Raw Byte Sequence Payload)
原始字节序列负荷部分是NALU的可变部分,包含了封装的数据。其内容取决于NALU的类型。