Press "Enter" to skip to content

H.264编码格式以及I、B、P帧判断

如果你正在了解H264,这里有你想了解的所有信息了。

在网上翻了很多资料,要准确理解H.264可以读一下这两份资料:T-REC-H.264-201610-S!!PDF-E.pdfrfc6184 RTP Payload Format for H.264 Video 。如果想读代码可以阅读ffmpeg的h264_parser.c 。其他网上的资料仅供参考。本文将根据一个实例,以及上述资料深入理解一下H264编码以及如何识别一个NULA包含的是I、B或者P Slice.

准备

示例h264文件

H264Naked (仅用于对比)

– vim或者其他可以打开H264编码源码文件的工具

感受一下

执行`vim sintel.h264`, 而后执行:`:%!xxd`,你讲看到下图:

H.264视频编解码器

编解码器规范本身在概念上区分了视频编码层(VCL)和网络抽象层(NAL)。VCL包含编解码器的信号处理功能、转换、量化和运动补偿预测等机制以及循环滤波器。NAL编码器将VCL编码器的片输出封装成网络抽象层单元(NALU),该层单元适用于通过分组网络传输或用于面向分组的多路复用环境。(翻译自:rfc6184#section-1.1)

直白的理解就是H.264这个格式就是很多NALU,在ITU-T H.264规范中规定,这些NALU是通过0x0000 0001或者 0x0000 01来分隔的。

NALU

NALU类型

所有的NAL unit都包含一个NAL unit类型八位字节。NAL单元格式八位字节格式如下:

 

请查看上一张图片,在红色方框后边的67、65等,其实对应为:

– 0x67就是二进制的0110 0111,那么F为0;NRI为11;Type为0 0111就是十进制的7;

– 0x65就是二进制的0110 0101,那么F为0;NRI为11;Type为0 0101就是十进制的5;

具体看一下每个字节是什么含义:

F: 1bit。forbidden_zero_bit。H.264规范声明如果值为1,那么为非法。会被直接丢弃。

NRI: 2bit。nal_ref_idc. 数值00表示NAL单元的内容不用于重建图像间预测的参考图像。 这样的NAL单元可以丢弃,而不会危及参考图片的完整性。大于00的值表示需要对NAL单元进行解码,以保持参考图片的完整性。

Type: 5bit。nal_unit_type. NAL unit payload类型,具体定义在ITU-T H.264规范中的Table 7-1。

– 根据含义,上述 0x67就可以理解了,F=0代表是一个正常NALU;NRI=11说明这个NULA需要解码;Type=7带表这个NALU payload为序列参数集(Sequence parameter set)。

– 上述0x65也可以理解了,Type=5是一个IDR图像中的切片(Coded slice of an IDR picture),这是一个关键帧,同时它也是一个I slice。

NALU中I、B、P帧的判断

注意:这里的I帧、B帧或者P帧,其实是把Slice翻译成了帧。

当NALU的Type为5时,帧一定为I帧。当NALU的Type为1时, 帧的类型根据slice header中的slice_type来确定,可能为I、B、P、SP等类型。如下图,截取自ITU-T H.264

首先看示例的00228130这一行,NALU类型为0x41,即0010 0001,F=0,NRI=01,Type=0 0001,所以Type=1,是一个非IDR类型的片。

接下来,我们看紧跟自0x41后边的9a88 49e1,即 1001 1010 1000 1000, 我们需要跳过first_mb_in_slice,然后取slice_type。

这里需要先理解这个ue(v), 即0阶指数哥伦布编码,解码是这样的公式

我们简写为: N = 2^m – 1 + read_bits(m)。哥伦布编码是对二进制的一个编码,比如0011 0101 , 首先看前边0的个数(m=2),然后是1作为分隔符,再之后读和前边0个数一样多位作为后缀(二进制的10,即十进制的2), 那么0011 1010 => N= 2^2 -1 + 2 = 5。

接着看例子1001 1010 1000 1000,其中按照哥伦布编码我们得到, first_mb_in_slice=1(即m=0); slice_type= 00110(m=2, N=2^2-1+2=5),再根据如下表格(截图来自ITU-T H.264),可以得到这一帧为P帧。

 

Be First to Comment

发表评论

电子邮件地址不会被公开。 必填项已用*标注