[H264编解码] 第一章 NAL Unit 解析部分
包装类型:AnnexB 和 avcC
AnnexB
AnnexB 格式的原理非常简单,就是在一个 NALU 前面加上三个或者四个字节,这些字节的内容是 0 0 0 1 或者 0 0 1。当我们读取一个 H264 流的时候,一旦遇到 0 0 0 1 或者 0 0 1,我们就认为一个新的 NALU 开始了,因此,这些用来做分隔符的字节,一般也被称为 start code
AnnexB的防竞争字节
但是只在 NALU 前面加上起始码是会产生问题了,因为原始码流中,是有可能出现 0 0 0 1 或者 0 0 1 的,这样就会导致读取程序将一个 NALU 误分割成多个 NALU。为了防止这种情况发生,AnnexB 引入了防竞争字节(Emulation Prevention Bytes)的概念。
0 0 0 => 0 0 3 0
0 0 1 => 0 0 3 1
0 0 2 => 0 0 3 2
0 0 3 => 0 0 3 3
Avcc 包装类型
AnnexB 的原理是在每个 NALU 前面写上一个特殊的起始码,通过这个起始码来当做 NALU 的分隔符,从而分割每个 NALU。而 avcC 则采用了另外一种方式。那就是在 NALU 前面写上几个字节,这几个字节组成一个整数(大端字节序)这个整数表示了整个 NALU 的长度。在读取的时候,先把这个整数读出来,拿到这个 NALU 的长度,然后按照长度读取整个 NALU,我们不妨把这几个字节叫做 NALU Body Length。
EBSP RBSP SODB载荷
- EBSP 扩展字节序列载荷:去掉 0 0 0 1 的 startcode 的后的数据叫做 EBSP
- RBSP 原始字节序列载荷:NALU 去掉 startcode ,接着又去掉防竞争字节之后的数据,就叫做 RBSP
- SODB 数据比特串:去掉RBSP字节补齐部分
字节补齐的规则
rbsp_trailing_bits( ) {
rbsp_stop_one_bit /* equal to 1 比特流末尾插入1 */
while( !byte_aligned( ) )
rbsp_alignment_zero_bit /* equal to 0 */
}
nal_unit 的解析方法
将264文件进行startCode分割后,对EBSP和RBSP进行处理,然后去除字节补齐部分,于是就可开始着手处理NAL unit的解析工作。NAL unit的语法表主要描述为,
f(1)表示固定值,位宽为1位
u(2)表示unsigned int,位宽为2位
所以可以看出,头一个字节由三种句法元素组成,用于表示NAL unit type的区域为第一个字节的后五位,所以有
NAL_unit_type = nal_unit[0] & 0x1f;
nal_ref_idc
该元素表示这个 NALU 的重要性