x264 环路滤波原理系列:i_deblocking_filter_alphac0 和 i_deblocking_filter_beta 的应用

时间:2024-12-13 07:13:10

i_deblocking_filter_alphac0 和 i_deblocking_filter_beta的应用

  1. 功能:在 x264 环路滤波中,i_deblocking_filter_alphac0i_deblocking_filter_beta 是环路滤波模块中两个重要的参数,它们用于控制去块滤波器(deblocking filter)的行为条件。这些参数通常在编码器的配置中进行设置,并对最终编码视频的质量有显著影响。
  2. 应用流程:
  • 从原理流程可以看到,i_deblocking_filter_alphac0i_deblocking_filter_beta作为是否进行滤波的阈值,以及修改不同边界像素比如 p0p1p2q0q1q2的阈值条件,满足不同条件就进行相应的像素调整。
  • 第一步:默认值设置,在x264_param_default函数中完成;
  • 第二步:根据视频特点或需求调整二者的值,在param_apply_tune函数中完成;
  • 第三步:初始化 header 中去块相关变量,主要将i_deblocking_filter_alphac0i_deblocking_filter_beta转换成i_alpha_c0_offseti_beta_offset,二倍的关系,在slice_header_init函数中完成;
  • 第四步:将i_alpha_c0_offseti_beta_offset二者写入码流中,供解码识别,在slice_header_write函数中完成;
  • 第五步:将i_alpha_c0_offseti_beta_offset转换成 ab 局部变量,根据不同条件应用到具体的滤波函数中,在x264_frame_deblock_row函数中完成;rdo 模块中x264_macroblock_deblock函数有类似的操作。
  • 第六步:根据不同的分量、滤波强度、滤波方向指向具体的滤波运算函数,比如亮度分量普通滤波通过deblock_edge_luma_c函数实现,亮度分量强滤波通过deblock_edge_luma_intra_c函数实现。
  • 第七步:通过调整,修改需要滤波的重建像素值,完成滤波操作。
  • 具体如下图说明:
    在这里插入图片描述

相关函数说明

  1. x264_param_default
    • 设置 x264_param_t 结构体中的所有编码参数到默认值。这个函数非常重要,必须被调用,因为它为编码过程提供了一套合理的起点。这些参数包括但不限于分辨率、帧率、编码模式(如恒定量化参数CQP、平均比特率ABR等)、去块滤波参数、宏块树率控制(MB-tree)、量化矩阵等。
  2. param_apply_tune
    • 用于调整编码参数以适应特定的视频内容或优化视觉质量。这个函数可以根据指定的调整值(tune value)对编码参数进行优化,例如针对电影、动画、含噪点的视频、静态图片等不同类型的视频内容进行专门的参数调整。这些调整值可以是 film、animation、grain、stillimage、psnr、ssim、fastdecode、zerolatency 和 touhou 等,其中 film、animation、grain、stillimage、psnr 和 ssim 是视觉优化调整值,而 fastdecode、zerolatency 是编码速度优化调整值。param_apply_tune 函数可以同时使用多个调整值,如果它们之间不冲突的话。
    • 在实际使用中,param_apply_tune 函数通常在设置了编码器的默认参数之后被调用,以进一步细化和优化编码设置。例如,在初始化编码器参数结构体 x264_param_t 并设置了预设(preset)之后,可以通过调用 param_apply_tune 来应用特定的调整值,从而根据视频内容调整编码参数,以达到更好的编码效率和质量
  3. slice_header_init
    • 在 x264 编码器中用于初始化切片头(Slice Header)的数据结构。在 H.264/AVC 视频编码标准中,切片头是每个切片的元数据部分,它包含了解码当前切片所需的重要信息。
  4. slice_header_write
    • 将 H.264 视频编码中的切片头(Slice Header)信息写入到比特流(bitstream)中。在 H.264 视频编码标准中,每个切片的开始都有一个切片头,它携带了解码当前切片所需的必要信息。
  5. x264_frame_deblock_row
    • 用于对视频帧中的行(row)进行去块滤波处理(deblocking)。去块滤波是视频编码中常用的一种技术,用于减少宏块(macroblock)边界处的视觉不连续性,即所谓的块效应(block artifacts),这些效应通常在压缩率较高的视频编码中出现。
  6. deblock_edge
    • 用于普通滤波,也就是当边界强度(BS)为 1、2 或 3 时的滤波情况。这个函数会根据宏块的量化参数(QP)、alpha 表值和 beta 表值计算滤波的门限值,然后根据这些值和 BS 值决定是否进行滤波以及滤波的强度。
  7. deblock_edge_luma_c
    • 关于滤波强度 Bs=1、2、3 的滤波运算相关函数的具体实现,主要是亮度分量的滤波运算,色度分量相似操作。
  8. deblock_edge_intra
    • 用于强滤波,即当边界强度 Bs 为 4 时的情况。这种滤波通常用于帧内编码的宏块(Intra macroblock)或者当宏块的边界被认为是强真实边界时。与 deblock_edge 相比,deblock_edge_intra 会使用更强的滤波器参数,以减少视觉上的不连续性。
    1. deblock_edge_luma_intra_c
    • 关于滤波强度 Bs=4的滤波运算相关函数的具体实现,主要是亮度分量的滤波运算,色度分量相似操作。

相关去块滤波数据表

/* Deblocking filter */
static const uint8_t i_alpha_table[52+12*3] =
{
     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
     0,  0,  0,  0,  0,  0,  4,  4,  5,  6,
     7,  8,  9, 10, 12, 13, 15, 17, 20, 22,
    25, 28, 32, 36, 40, 45, 50, 56, 63, 71,
    80, 90,101,113,127,144,162,182,203,226,
   255,255,
   255,255,255,255,255,255,255,255,255,255,255,255,
};
static const uint8_t i_beta_table[52+12*3] =
{
     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
     0,  0,  0,  0,  0,  0,  2,  2,  2,  3,
     3,  3,  3,  4,  4,  4,  6,  6,  7,  7,
     8,  8,  9,  9, 10, 10, 11, 11, 12, 12,
    13, 13, 14, 14, 15, 15, 16, 16, 17, 17,
    18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
};
static const int8_t i_tc0_table[52+12*3][4] =
{
    {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 },
    {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 },
    {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 },
    {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 },
    {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 },
    {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 },
    {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 1 },
    {-1, 0, 0, 1 }, {-1, 0, 0, 1 }, {-1, 0, 0, 1 }, {-1, 0, 1, 1 }, {-1, 0, 1, 1 }, {-1, 1, 1, 1 },
    {-1, 1, 1, 1 }, {-1, 1, 1, 1 }, {-1, 1, 1, 1 }, {-1, 1, 1, 2 }, {-1, 1, 1, 2 }, {-1, 1, 1, 2 },
    {-1, 1, 1, 2 }, {-1, 1, 2, 3 }, {-1, 1, 2, 3 }, {-1, 2, 2, 3 }, {-1, 2, 2, 4 }, {-1, 2, 3, 4 },
    {-1, 2, 3, 4 }, {-1, 3, 3, 5 }, {-1, 3, 4, 6 }, {-1, 3, 4, 6 }, {-1, 4, 5, 7 }, {-1, 4, 5, 8 },
    {-1, 4, 6, 9 }, {-1, 5, 7,10 }, {-1, 6, 8,11 }, {-1, 6, 8,13 }, {-1, 7,10,14 }, {-1, 8,11,16 },
    {-1, 9,12,18 }, {-1,10,13,20 }, {-1,11,15,23 }, {-1,13,17,25 },
    {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 },
    {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 },
};
#define alpha_table(x) i_alpha_table[(x)+24]
#define beta_table(x)  i_beta_table[(x)+24]
#define tc0_table(x)   i_tc0_table[(x)+24]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46