H264 环路滤波
H.264 环路滤波是视频编码中用于减少块效应和提高视频质量的关键技术。它主要在编码侧进行,并且解码部分也必须执行,是视频编码方案不可或缺的一部分。环路滤波包括多种情况,具体如下:
-
环路滤波的四种情形:在Baseline配置下,环路滤波可能包括以下四种情况 :
- Bs = 4:宏块边界上的任一侧是帧内预测。
- Bs = 3:宏块边界上的任一侧是帧内预测,或者块边界上存在帧内预测。
- Bs = 2:两侧都是帧间预测,并且任一侧的宏块是编码的。
- Bs = 1:两侧都是帧间预测,没有宏块被编码,且使用不同的参考图片,或者任一侧的MV分量不小于4。
- Bs = 0:其他情况,不需要进行滤波。
-
滤波过程:滤波过程包括水平和垂直宏块滤波。每个宏块的四条边界都被等分为四部分,每部分对应一个最小块大小的边界,以此为单元进行滤波。每条边界的长度为16个像素 。
-
块效应的原因:块效应主要由两方面因素引起 :
- 基于块的帧内和帧间预测残差经过整数变换和量化,量化操作的离散性导致反量化恢复变换系数时产生误差,尤其在图像边界上形成视觉上的不连续。
- 运动补偿过程中,由于从不同帧的不同位置内插样点,即使最匹配的块也可能存在微小的不一致,导致复制块的边界数据不连续性。
-
环路滤波的目的:环路滤波的目的是消除由于编码过程引入的块效应,通过平滑图像边界,提高视频的平滑度和视觉质量 。
-
真假边界的区分:在进行环路滤波之前,需要区分真假边界。真边界是图像本身的特征,而假边界是由编码过程中的量化和运动补偿引起的。H.264 标准定义了两个变量 α 和 β 来判决边界是否需要进行环路滤波 。
-
滤波运算:根据边界强度 Bs 的不同,H.264 使用不同强度的滤波器。Bs = 1, 2, 3 时使用较弱的滤波器,而 Bs = 4 时可以选择强滤波器或弱滤波器,具体取决于是否存在大量细节信息 。
-
自适应滤波强度:滤波强度可以根据量化参数 QP 调整。QP 越大,α 和 β 的值也越大,意味着量化误差越大,块效应越明显,因此阈值也应该取较大值来增大滤波效果 。
-
滤波器的复杂度:在实际实现中,去块滤波器的计算复杂度非常高,可能占用解码过程中相当比例的时间 。
通过这些措施,H.264 环路滤波能够有效地减少编码后视频的块效应,改善视频质量。
x264 环路滤波
相关编码参数
- b_deblocking_filter
- i_deblocking_filter_alphac0
- i_deblocking_filter_beta
编码参数设置
- 默认:
param->b_deblocking_filter = 1;
param->i_deblocking_filter_alphac0 = 0;
param->i_deblocking_filter_beta = 0;
- 1
- 2
- 3
- preset= ultrafast
param->b_deblocking_filter = 0;
- 1
- tune= film
param->i_deblocking_filter_alphac0 = -1;
param->i_deblocking_filter_beta = -1;
- 1
- 2
- tune=animation
param->i_deblocking_filter_alphac0 = 1;
param->i_deblocking_filter_beta = 1;
- 1
- 2
- tune = grain
param->i_deblocking_filter_alphac0 = -2;
param->i_deblocking_filter_beta = -2;
- 1
- 2
- tune = stillimage
param->i_deblocking_filter_alphac0 = -3;
param->i_deblocking_filter_beta = -3;
- 1
- 2
- tune = fastdecode
param->b_deblocking_filter = 0;
- 1
- tune= touhou
param->i_deblocking_filter_alphac0 = -1;
param->i_deblocking_filter_beta = -1;
- 1
- 2
环路去块相关设置
- 在
validate_parameters
函数会将编码参数限制在合理范围内:
h->param.i_deblocking_filter_alphac0 = x264_clip3( h->param.i_deblocking_filter_alphac0, -6, 6 );
h->param.i_deblocking_filter_beta = x264_clip3( h->param.i_deblocking_filter_beta, -6, 6 );
- 1
- 2
- 在
slice_header_init
函数中会将编码参数转换到x264_slice_header_t结构体中:
int deblock_thresh = i_qp + 2 * X264_MIN(param->i_deblocking_filter_alphac0, param->i_deblocking_filter_beta);
/* If effective qp <= 15, deblocking would have no effect anyway */
if( param->b_deblocking_filter && (h->mb.b_variable_qp || 15 < deblock_thresh ) )
sh->i_disable_deblocking_filter_idc = param->b_sliced_threads ? 2 : 0;
else
sh->i_disable_deblocking_filter_idc = 1;
sh->i_alpha_c0_offset = param->i_deblocking_filter_alphac0 * 2;
sh->i_beta_offset = param->i_deblocking_filter_beta * 2;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 在
slice_header_write
函数将相关信息写入码流头中
if( sh->pps->b_deblocking_filter_control )
{
bs_write_ue( s, sh->i_disable_deblocking_filter_idc );
if( sh->i_disable_deblocking_filter_idc != 1 )
{
bs_write_se( s, sh->i_alpha_c0_offset >> 1 );
bs_write_se( s, sh->i_beta_offset >> 1 );
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 关于b_deblocking_filter_control
- 在
x264_pps_init
函数中赋值 1:pps->b_deblocking_filter_control = 1
;【这个变量直接赋值 1,中间也没有变化,意义何在?????】 - 在
x264_pps_write
函数中将其写入码流中:bs_write1( s, pps->b_deblocking_filter_control )
;
- 在
环路滤波函数关系图
环路滤波核心函数介绍
-
fdec_filter_row·
:在 x264 编码器中负责对一行宏块进行滤波处理。这个函数主要完成以下三个步骤:-
环路滤波(去块效应滤波):通过调用
x264_frame_deblock_row()
函数实现,用于平滑宏块边界,减少视觉不连续。 -
半像素内插:通过调用
x264_frame_filter()
函数实现,用于生成半像素精度的参考帧,以提高编码效率。 -
视频质量 SSIM 和 PSNR 的计算:PSNR 通过调用
x264_pixel_ssd_wxh()
函数实现,SSIM 的计算则是通过x264_pixel_ssim_wxh()
函数实现 。
-
环路滤波(去块效应滤波):通过调用
-
x264_macroblock_deblock_strength·
:该函数的作用是计算去块滤波器的强度。在 H.264/AVC 视频编码标准中,去块滤波器用于减少宏块之间的不连续性,即所谓的块效应。这种效应通常在编码过程中由于块的独立编码和量化引入。x264_macroblock_deblock_strength
函数通过分析宏块的特性来确定滤波器的强度参数,这些参数随后用于去块滤波过程。 -
x264_macroblock_deblock
函数:开启 RDO 时,会在各个宏块分析中计算 rd 代价时调用。