在H.264的视频编码标准中,分为两个层面:视频编码层面(VCL)和网络抽象层面(NAL)。媒体流的每帧数据就是一个NAL单元(SPS和PPS除外)。
视频编码层(VCL)
VCL()负责对视频的原始数据进行压缩和编码,VCL输出的是压缩和编码之后的纯视频流信息。
网络提取层(NAL)
NAL(Network Abstraction Layer)主要为了方便媒体流在网络中的传输,适用于各种传输网络。
NAL单元格式

F: 1位
forbidden_zero_bit。数值为 0 表示 NAL 单元类型字节和数据包不应出现位错误或其他语法违规情况。数值为 1 则表示 NAL 单元类型字节和数据包可以包含位错误或其他语法违规情况。
NRP: 2位
nal_ref_idc。值 00 以及非零值的含义与 H.264 规范中的规定保持一致。换句话说,值为 00 表示该 NAL 单元的内容不会用于重建用于帧间预测的参考图像。此类 NAL 单元可以被丢弃,而不会危及参考图像的完整性。值大于 00 则表示需要对 NAL 单元进行解码以保持参考图像的完整性。
Type: 5位
nal_unit_type表示NAL的数据类型,有以下几种,其值为1,2,3,4,5和12的NAL单元称为VCL的NAL单元,其他类型为非ACL的NAL单元。
| NAL_UNIT_TYPE | 描述 |
|---|---|
| 0 | 未使用 |
| 1 | 非IDR图像中不采用数据划分的片段【VCL】 |
| 2 | 非IDR图像中A类数据划分的片段【VCL】 |
| 3 | 非IDR图像中B类数据划分的片段【VCL】 |
| 4 | 非IDR图像中C类数据划分的片段【VCL】 |
| 5 | IDR图像中的片段【VCL】 |
| 6 | 补充增强信息片段(SEI)【NO-VCL】 |
| 7 | 序列参数集【NO-VCL】 |
| 8 | 图像参数集【NO-VCL】 |
| 9 | 分隔符(或分解符)【NO-VCL】 |
| 10 | 序列结束符【NO-VCL】 |
| 11 | 流结束符【NO-VCL】 |
| 12 | 填充数据【NO-VCL】 |
| 13~23 | 保留 |
| 24~31 | 未使用 |
NALU 载荷
SODB(String of Data Bits) 元数据比特流,即最原始的编码、压缩得到的数据。
RBSP(Raw Byte Sequence Payload),原始字节序列载荷,主要是在SODB基础上增加了补齐字节(RBSP = SODP + RBSP补齐字节)。
EBSP(Encapsulated Byte Sequence Payload)扩展字节序列载荷,主要是在RBSP基础上插入放竞争字节(0x03)。

说明:插入0x03的主要原因是,因为NALU的起始码为0x000001或0x00000001,同时H264规定,当检测到0x000000时,也可以表示NALU的结束。所以这样就会产生一个问题,就是在NALU的内部,如果出现了0x000001或0x000000时该怎么办?所以,H264有了插入0x03防止竞争的机制,在编码完成一个NAL时,如果在NALU内部出现序列(0x000000、0x000001、0x000002、0x000003)中的一个存在时,就在最后一个字节前插入一个新的字节0x03(解码时进行逆向操作)。

一帧图片和NALU之间的关联
一帧图片经过H.264编码之后,会编码(VCL层实现)为一个或者多个切片(slice)。

编码后的切片(slice)会被装在到NALU中(NAL层实现),如下图所以NALU和切片(slice)的关系。

说明:实际实现过程中,NAL还需要对切片(slice)进行处理,然后行程NALU。
切片(slice)装载到NALU之后进行网络传输,但是NALU装载的也不一定是帧图片的切片(slice),因为NALU还可能装载用于描述视频的信息(如SPS、PPS等)。
slice Header结构
slice Header中主要保存了当前切片(slice)的一些全局信息,silice Body中的宏块(MB)在进行解码时需要依赖这些信息。以下是一些比较常见的信息:
1、first_mb_in_slice: 表示当前slice中包含的第一个宏块在整个帧中的位置。
2、slice_type: 表示当前slice类型。
| slice_type | 名称 |
|---|---|
| 0 | P(P slice) |
| 1 | B(B slice) |
| 2 | I(I slice) |
| 3 | SP(SP slice) |
| 4 | SI(SI slice) |
| 5 | P(P slice) |
| 6 | B(B slice) |
| 7 | I(I slice) |
| 8 | SP(SP slice) |
| 9 | SI(SI slice) |
3、pic_parameter_set_id: 当前slice依赖的PPS和id(指定图像参数集)。
4、colour_plane_id: 当separate_colour_plane_flag标识位的值为true时,colour_plane_id表示当前的颜色分量(0、1、2分别表示Y、U、V)。
5、frame_num: 当前帧序号的计量方式(POC)。
6、field_pic_flag: 场编码标识位,该值为1时,表示当前slice按照场进行编码;值为0时表示当前slice按照帧进行编码。
7、bottom_field_flag: 底场标识位,值为1表示当前slice是某一帧的底场;0表示当前slice为某一帧的顶场。
8、idr_pic_id: IDR帧的序号,一个IDR帧所的所有slice,其idr_pid_id应该保持一致,取值范围0~65535。
9、pic_order_cnt_lsb: 当前帧序号的另一种计量方式。
10、delta_pic_order_cnt_bottom:顶场和底场POC差值的计算方法(不存在则默认为0)。
11、slice_qp_delta: 用于计算当前slice内使用的初始qp值。
根据码流中的不同的数据类型,H.264定义了五种slice类型:
| 类型(名称) | 含义 | 描述 | Profile |
|---|---|---|---|
| I(I slice) | 帧内切片 | 仅包含 I 宏块 | ALL |
| P(P slice) | 前向预测切片 | 可包含 P 宏块和 I 宏块 | ALL |
| B(B slice) | 双向预测切片 | 可包含 B 宏块、P宏块、 I 宏块 | Extended and Main |
| SP(SP slice) | 切换前向预测切片 | 包含 P 宏块或 I 宏块 | Exteded |
| SI(SI slice) | 切换帧内切片 | 仅包含 SI 宏块 | Exteded |
1. I Slice(Intra-coded Slice,帧内切片)
-
定义:只使用帧内(本切片或本帧)信息进行预测编码,不引用其他帧的数据。
-
特点:抗误码能力强,是关键帧的基本构成单元。
-
典型应用:场景切换、编码重同步点。
-
数据类型:只包含 I 宏块。
2. P Slice(Predictive-coded Slice,前向预测切片)
-
定义:使用本帧和参考帧的数据进行前向预测压缩编码。
-
特点:编码效率高,压缩比好,但对参考帧依赖大。
-
典型应用:大部分连续画面。
-
数据类型:可包含 P 宏块和 I 宏块。
3. B Slice(Bi-predictive-coded Slice,双向预测切片)
-
定义:既能参考前面的帧,也能参考后面的帧进行双向预测编码。
-
特点:压缩率最高,依赖于多个参考帧,对解码器要求较高。
-
典型应用:高压缩场合,如蓝光或高码率视频。
-
数据类型:可包含 B、P、I 宏块。
扩展类型:SI Slice 和 SP Slice
这些类型主要在流切换、容错、码流修复等特定应用场景,实际应用较少:
4. SI Slice(Switching Intra Slice,切换帧内切片)
-
主要用于码流切换场景,便于不同码率、不同内容之间的切换。
5. SP Slice(Switching Predictive Slice,切换前向预测切片)
-
主要用于码流无损切换场景,以确保内容切换点的视频连续性。
宏块(MB)
mb_type: 确定当前宏块(MB)的编码模式(P或B),确定当前MB的分割尺寸。
mb_pred: 确定帧内预测模式(帧内宏块)。
sub_mb_pred:确定每一个子宏块的子宏块分割。
residual:预测后对饮残差图像取样的编码变换系数。
3454

被折叠的 条评论
为什么被折叠?



