H.264文件分析及编解码实现
文章目录
- 五、结果分析
H.264是国际标准化组织(ISO)和国际电信联盟(ITU)在2002年12月共同提出的继MPEG-4之后的新一代数字视频压缩格式,其具有更高的编码效率,并注重对移动和IP网络的适应,考虑信道的特点,能控制误码扩散。
一、H.264简介
1. H.264的特点
- 压缩比高:在同等图像质量的条件下,采用H.264技术压缩后的码流,数据量只有MPEG-2的1/2;
- 容错率高:H.264码流具有较强的抗误码特性,可适应丢包率高、干扰严重的信道,如IP和无线网络;
- 网络适应性强:H.264提供了网络适应层,使得H.264的文件能容易地在不同网络上传输;
- 计算复杂度高:H.264使用较高的计算复杂度,换取优越的性能,其复杂度相当于MPEG-2的2—3倍。
2. H.264编解码器
H.264编码器结构与前代MPEG-2标准差别不大,均主要采用变换编码、DPCM与运动补偿的混合结构。编解码器的结构如图所示:
3. H.264采用的技术
(1) 分层设计
H.264在视频编码层(VCL)和网络提取层(NAL)之间进行概念分割,以实现在不同的传输环境下的有效传输,便于与当前和将来的编码格式和不同类型的网络进行无缝连接。
(2) 帧内预测编码
根据邻近块的值来预测当前宏块的值,再对预测值和原始值的差值进行变换、量化和编码。对于亮度块,使用4×4与16×16编码模式,对色度块采用8×8编码模式。
以亮度块的4×4帧内预测模式为例,由周围的15个像素预测4×4的16个像素,共有9种预测模式,分别计算各自的SAE,以最小者作为该块的预测模式。
(3) 帧间预测编码——基于块的运动补偿
- 树状结构运动补偿:使用不同大小和形状的块进行运动补偿(低频区域使用大块,高频区域使用小块);
- 使用1/4像素精度运动矢量
- 在多个参考帧中进行运动搜索,选择一个与编码帧最相似的帧作为参考帧
- 引入SI帧和SP帧:适应码流带宽自适应和抗误码的要求,改善网络亲和性,支持流媒体服务
(4) 整数变换
使用整数DCT代替MPEG-2中的DCT,保证变换中无精度损失,且标准中对正反变换有详细说明,不会出现误匹配。另外,整数变换仅需要移位和加法,最大程度提高运算效率。
(5) 量化处理
H.264标准支持52个量化步长,量化参数QP每增加6,量化步长Qstep增加一倍。量化步长取值范围很广,这就为编码中兼顾比特率和编码质量提供了足够多的灵活度和准确度。
(6) 去块效应滤波
为消除块效应,H.264编码系统的预测环路中增加了自适应去块效应滤波器。
(7) 熵编码
H.264标准中给出了两种熵编码方法:CAVLC(Context-based Adaptive Variable Length Coding,基于上下文的自适应可变长编码)和CABAC(Context-based Adaptive Binary Arithmetic Coding,基于上下文的自适应二进制算术编码),其中前者为基本编码方法,后者可选编码方法,且后者的编码性能相较于前者较好,但计算复杂度更高。
二、H.264文件分析
序列参数集和图像参数集
序列参数集SPS(Sequence parameter set)
字段 | 说明 |
profile_idc | 该码流的编码规格。 |
level_idc | 标识当前码流的level。编码的Level定义了某种条件下的最大视频分辨率、最大视频帧率等参数,码流所遵从的level由level_idc指定。 |
seq_parameter_set_id | 表示当前的序列参数集的id。通过该id值,图像参数集pps可以引用其代表的sps中的参数。 |
pic_order_cnt_type | 表示解码picture order count(POC)的方法。 |
log2_max_pic_order_cnt_lsb_minus4 | 用于计算MaxPicOrderCntLsb的值,该值表示POC的上限。 计算方法为 |
num_ref_frames | 规定了可能在视频序列中任何图像帧间预测的解码过程中用到的短期参考帧和长期参考帧、互补参考场对以及不成对的参考场的最大数量。 |
pic_width_in_mbs_minus1 | 加 1 是指以宏块为单元的每个解码图像的宽度。 |
pic_height_in_map_units_minus1 | 加 1 是指以宏块为单元的每个解码图像的高度。 |
frame_mbs_only_flag | 标识位,说明宏块的编码方式。当该标识位为0时,宏块可能为帧编码或场编码;该标识位为1时,所有宏块都采用帧编码。 |
direct_8x8_inference_flag | 标识位,用于B_Skip、B_Direct模式运动矢量的推导计算。 |
gaps_in_frame_num_value_allowed_flag | 标识位,说明frame_num中是否允许不连续的值。 |
frame_cropping_flag | 标识位,说明是否需要对输出的图像帧进行裁剪。 |
vui_parameters_present_flag | 标识位,说明SPS中是否存在VUI信息。 |
图像参数集PPS(Picture parameter set)
字段 | 说明 |
pic_parameter_set_idprofile_idc | 表示当前PPS的id。某个PPS在码流中会被相应的slice引用,slice引用PPS的方式就是在Slice header中保存PPS的id值。该值的取值范围为[0,255]。该码流的编码规格。 |
seq_parameter_set_idlevel_idc | 表示当前PPS所引用的激活的SPS的id。通过这种方式,PPS中也可以取到对应SPS中的参数。该值的取值范围为[0,31]。标识当前码流的level。编码的Level定义了某种条件下的最大视频分辨率、最大视频帧率等参数,码流所遵从的level由level_idc指定。 |
entropy_coding_mode_flagseq_parameter_set_id | 熵编码模式标识,该标识位表示码流中熵编码/解码选择的算法。对于部分语法元素,在不同的编码配置下,选择的熵编码方式不同。表示当前的序列参数集的id。通过该id值,图像参数集pps可以引用其代表的sps中的参数。 |
num_slice_groups_minus1pic_order_cnt_type | 表示某一帧中slice group的个数。当该值为0时,一帧中所有的slice都属于一个slice group。slice group是一帧中宏块的组合方式,定义在协议文档的3.141部分。表示解码picture order count(POC)的方法。 |
weighted_pred_flaglog2_max_pic_order_cnt_lsb_minus4 | 标识位,表示在P/SP slice中是否开启加权预测。用于计算MaxPicOrderCntLsb的值,该值表示POC的上限。 计算方法为 |
weighted_bipred_idcnum_ref_frames | 表示在B Slice中加权预测的方法,取值范围为[0,2]。0表示默认加权预测,1表示显式加权预测,2表示隐式加权预测。规定了可能在视频序列中任何图像帧间预测的解码过程中用到的短期参考帧和长期参考帧、互补参考场对以及不成对的参考场的最大数量。 |
pic_init_qp_minus26和pic_init_qs_minus26pic_width_in_mbs_minus1 | 表示初始的量化参数。实际的量化参数由该参数、slice header中的slice_qp_delta/slice_qs_delta计算得到。加 1 是指以宏块为单元的每个解码图像的宽度。 |
chroma_qp_index_offsetpic_height_in_map_units_minus1 | 用于计算色度分量的量化参数,取值范围为[-12,12]。加 1 是指以宏块为单元的每个解码图像的高度。 |
deblocking_filter_control_present_flagframe_mbs_only_flag | 标识位,用于表示Slice header中是否存在用于去块滤波器控制的信息。当该标志位为1时,slice header中包含去块滤波相应的信息;当该标识位为0时,slice header中没有相应的信息。 |
使用码流分析仪分析.mp4文件
查看 movie.mp4 的第一帧SPS信息:
- profile_idc:100,标识high profile
- level_idc:31,对应level3.1,每秒最多处理的宏块数为108000个,每帧最多的宏块数3600
- high profile下最高比特率为17.5Mbps
- seq_parameter_set_id:0,当前序列参数集id为0.
- log2_max_pic_order_cnt_lsb_minus4:2,据此计算出POC上限为2^(2+4)=64
- pic_order_cnt_type:0
- num_ref_frames:16,参考帧最大数量为16
- pic_width_in_mbs_minus1:39,每个宏块宽度为40
- pic_height_in_map_minus1:22,一帧图像的高度为23
- gaps_in_frame_num_value_allowed_flag:0,frame_num中不允许不连续的值
- frame_mbs_only_flag:1,所有宏块采用帧编码
- frame_cropping_flag:0,输出图像帧不进行裁剪
- vui_parameters_present_flag:1,SPS中存在VUI信息
PPS信息:
- pic_parameter_set_id:0,当前PPS的id为0
- seq_parameter_set_id:0,当前PPS所引用的激活SPS的id为0,即上述SPS
- entropy_coding_mode_flag:1,熵编码模式标识为1
- num_slice_groups_minus1:0,一帧中所有的slice都属于一个slice group
- weighted_pred_flag:1,开启加权预测
- weighted_bipred_idc:2,B slice中采用隐式加权预测
- pic_init_qp_minus26:0,初始量化参数
- pic_init_qs_minus26:0,初始量化参数
- chroma_qp_index_offset:-2,用于计算色度分量
- deblocking_filter_control_present_flag:1,slice header中包含去块滤波相应的信息
- constrained_intra_pred_flag:0,I宏块可以使用来自Inter类型宏块的信息
- redundant_pic_cnt_present_flag:0,slice header中没有redundant_pic_cnt语法元素相应的信息
综上,图像宽度包含宏块数40,图像高度包含宏块数23,帧高度23x16=368,帧宽度40x16=640,分辨率640x368,帧率fps=96kbps,所有的slice都属于一个slice group
分析GOP结构
GOP(Group of Pictures,图像组)是将一个图像序列中连续的几个图像组成的一个小组,是对编码后的视频码流进行编辑、存取和压缩编码的基本单元,包含不同种类编码的帧。
增大GOP或提高GOP中P/B帧的占比,可以提高压缩比,降低码率。因此一般而言,在码率一定的条件下,GOP越大,图像质量越好(P/B帧的比重更大);在图像质量一定的条件下,GOP越大,码率越低。
三、解码
在ldecod项目中,打开decoder_test.c,可以修改输入和输出文件名,如:
即可将.264文件解码为.yuv文件:
四、编码
1. 编码参数
行 | 参数 | 含义 | 取值 |
13/56/57 | | 输入文件/ 输出文件(.264)/ 重建文件(.yuv) | |
30/31/ 33/34 | | 输入、输入视频序列的宽、高 | |
16 | | 编码帧数 | |
72 | | GOP内I帧的周期 | 0表示仅GOP的第一帧为I帧 |
73 | | IDR帧的周期,表示GOP长度 | 0表示仅GOP的第一帧为I帧 |
77 | | 是否允许IDR帧 | 0为禁用,1为允许 |
78 | | 是否允许开放GOP | 0为禁用,1为允许 |
180 | | 两个I/P帧之间B帧的数目 | |
347 | | GOP length for redundant allocation (1-16) | |
444 | | 是否允许比特率控制 | 0为禁用,1为允许 |
445 | | 比特率(单位:bps) | |
453 | | 全I帧模式适用模式1,其他情况适用模式2或3,本实验选择2 | 0:原始的JM率控制; 1:对所有帧都适用的码率控制算法; 2:在1的基础上考虑到I/P Slices的量化参数; 3: 混合二次码率控制算法,即在控制过程中考虑到实时的码率情况 |
2. 编码器调试
在下面的实验中,我们均设定IntraPeriod = 0,PrimaryGOPLength = IDRPeriod,以控制变量。
分别选择比特率为1600、1650、1700、1750、1800 kbps,再对每一比特率分别设置GOP格式为GOP15(2B)、GOP12(2B)、GOP9(2B)、GOP4(1B)、GOP12(无B)和GOP1(全I)进行编码。
运行lencode项目,对miss.yuv进行编码,运行结果如下:
以GOP12(0B)@1800 kbps的情况为例,从表格中可以看到GOP大小为12,并且可以看到帧重排。
五、结果分析
1. 码流分析
下面使用Elecard StreamEye Tools码流分析软件对编码后的内容进行分析。
以GOP15(2B)的情况为例:
图中每个矩形代表一帧(红、蓝、绿分别表示I、P、B帧),我们可以清楚地看出编码后视频的码流结构并且可以看到有帧重排(显示顺序为IBBPBBPBBPBBPBP)。下面我们以其中的4帧(I、B、B、P)进行分析。
我们在预览中打开显示宏块分界线、宏块类型和运动矢量。
画面中,红色、橙色宏块均使用帧内编码(宏块大小略有不同);黄色宏块类型为Inter(B_Skip),表示与前一帧相同,跳过不编码;绿色宏块使用前向预测编码,蓝色宏块使用双向预测编码。
在图中,我们可以看到:
- 4帧的背景部分变化均很小,因而背景部分均没有进行编码;
- B、P帧中可看到运动矢量。红色线表示前向预测,绿色线表示后向预测,因此P帧中只有红色线,I帧使用帧内编码,无运动矢量;
- 通过宏块分界线我们还可以看到H.264中不同形状、不同大小的宏块,且在低频区域的宏块更大。这也是前面提到的H.264采用的先进技术之一。
2. 视频质量客观评价
下面我们对前面编码得到的6中GOP结构的5种比特率的H.264文件进行视频质量客观评价,评价指标采用Y分量的PSNR (dB)。由于编码后H.264文件的实际比特率与目标比特率之间有一定误差,因此我们以实际比特率进行率失真曲线的绘制。
从图中可以看到,在码率相同的前提下,视频质量由好到差为:GOP12 (0B) > GOP15 (2B) > GOP12 (2B) > GOP9 (2B) > GOP4 (1B) > GOP1 (all-I)。
下表中列出了6中GOP结构各自的I、P、B帧的占比。例如我们可以比较GOP15(2B)和GOP12(2B),二者P帧占比相同,而前者的B帧占比更大,因而具有更好的图像质量。视频质量相同的前提下,可以进行类比分析,这里不再赘述。