码流格式有两种:Annex B和HVCC
Android中使用前者,Mac使用后者,本文讨论Annex B格式
一、防止竞争机制
为了防止与NALU的起始码产生混淆,引入了“防止竞争”(Emulation Prevention)机制。
具体步骤如下:
-
当编码器编码完一个NALU后,检查该NALU内部是否出现以下左侧的四个字节序列,如果存在,编码器将在最后一个字节前插入一个新的字节0x03,从而使其变成右侧的样子,这样在NALU内部就不会出现0x00 00 00或者0x00 00 01了
-
然后解码器在NALU内部检测到0x00 00 03的序列时,将0x03丢弃,恢复原始数据
下面的序列需要编码器在最后一个字节前插入一个新的字节0x03
0x00 00 00 → 0x00 00 03 00
0x00 00 01 → 0x00 00 03 01
0x00 00 02 → 0x00 00 03 02 (保留用的)
0x00 00 03 → 0x00 00 03 03
需要注意的是,这种防止竞争的处理仅在Annex B格式中使用。
另外,如果NALU对应的Slice为一帧的开始,起始码则用4字节表示,即0x00000001;否则用3字节表示,0x000001。
二、码流结构
在H.264/AVC和H.265/HEVC视频编码标准中,VCL(Video Coding Layer)和NAL(Network Abstraction Layer)是两个关键概念,它们共同构成了视频编码的框架。
VCL(Video Coding Layer):
- VCL是视频编码的核心层,负责视频数据的有效表示。
- 它包括了视频编码的所有核心技术,如帧内预测、帧间预测、变换编码、去区块效应滤波和熵编码等。
- VCL处理的是视频数据的实际编码,包括宏块(MB)和片(slice)的编码。
NAL(Network Abstraction Layer):
- NAL的主要作用是将视频编码层(VCL)输出的原始数据比特流(SODB)进行封装,以适应不同的网络和存储环境。
- NAL层将编码后的数据划分为不同的NAL单元(NAL Units),每个NAL单元包含一个原始字节序列载荷(RBSP)和相应的NAL头部信息。
- NAL层负责处理数据的传输和存储,包括添加起始码(在Annex B格式中)或其他长度前缀(在AVCC/HVCC格式中),以及处理字节对齐和防止竞争等问题。
通过NAL的介绍,我们可以理解,网络传输的码流结构是:
起始码 + NAL头 + NALU数据
Start Code + NALU Header + NALU Playload
另外,关于SODB、RBSP和EBSP的相关概念,可以参考下图:
- SODB:最原始的编码数据,是VCL(Video Coding Layer)输出的未加工的比特流。
- RBSP:原始字节序列载荷,它由SODB(String Of Data Bits)加上结尾比特(一个值为1的比特和若干个值为0的比特,用于字节对齐)构成。
- EBSP:它是扩展字节序列载荷,它是在RBSP的基础上,为了适应Annex B格式的码流,添加了起始码和可能的emulation prevention bytes后的结果
三、NALU Header
H264 NAL Header:
--------------------
|0|1|2|3|4|5|6|7|
--------------------
|F|N_R | Type |
forbidden_bit: 1 bit,
nal_reference_idc: 2bit,VCL可以表征参考帧属性,参考帧非0,非参考帧0。
Non-VCL 表征解码时的可丢弃与否,如SPS PPS不可丢弃 为1,SEI可丢弃为0
nal_unit_type: 5bit 表示当前NAL的类型
image.png
H265 NAL Header:
---------------------------------------
|0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7|
----------------------------------------
|F| Type | LayerId | Tid |
forbidden_bit: 1 bit,
nal_unit_type: 6 bit 表征当前NAL的类型,定义在标准Table 7-1。
nuhLayerId:6 bit 编码层级信息
temporalId:时间分级信息
image.png
网友评论