x264代码剖析(十六):核心算法之宏块编码中的量化编码
为了进一步节省图像的传输码率,需要对图像进行压缩,通常采用变换编码及量化来消除图像中的相关性以减少图像编码的动态范围。本文主要介绍量化的相关内容,并给出x264中量化编码的代码分析。
1、量化编码
量化过程就是根据图像的动态范围大小确定量化参数,既保留图像必要的细节,又可以减少码流。在图像编码中,变换编码和量化从原理上讲是两个独立的过程。但在H.264中,将两个过程中的乘法合二为一,并进一步采用整数运算,减少编解码的运算量,提高图像压缩的实时性,这些措施对峰值信噪比(PSNR)的影响很小,一般低于0.02dB,可不计。下面给出编码器中变换编码及量化过程的流程。
下面给出毕厚杰著作的《新一代视频压缩编码标准——H.264/AVC(第二版)》中量化的相关理论知识,仅供学习参考。
2、量化源码分析
量化的相关函数大都位于common/quant.c中,主要包括以下函数:
x264_quant_init():初始化量化和反量化相关的汇编函数
quant_4x4():对4x4的DCT残差矩阵进行量化
QUANT_ONE():完成一个DCT系数的量化工作
quant_4x4x4():对4个4x4的DCT残差矩阵进行量化
下面对这些函数进行深入分析。
2.1、x264_quant_init()函数
量化模块的初始化函数是x264_quant_init()。该函数对x264_quant_function_t结构体中的函数指针进行了赋值。X264运行的过程中只要调用x264_quant_function_t的函数指针就可以完成相应的功能。对应的代码分析如下:
/******************************************************************/
/******************************************************************/
/*
======Analysed by RuiDong Fang
======Csdn Blog:http://blog.csdn.net/frd2009041510
======Date:2016.03.25
*/
/******************************************************************/
/******************************************************************/
/************====== 量化 ======************/
/*
功能:量化初始化,x264_quant_init()被x264_encoder_open()函数调用
*/
void x264_quant_init( x264_t *h, int cpu, x264_quant_function_t *pf )
{
/*===== 量化=====*/
pf->quant_8x8 = quant_8x8; /针对8x8DCT的量化
pf->quant_4x4 = quant_4x4; /量化4x4=16个
pf->quant_4x4x4 = quant_4x4x4; /处理4个4x4的块
/Intra16x16中,16个DC系数Hadamard变换后对的它们量化
pf->quant_4x4_dc = quant_4x4_dc;
pf->quant_2x2_dc = quant_2x2_dc;
/*===== 反量化=====*/
pf->dequant_4x4 = dequant_4x4; /反量化4x4=16个
pf->dequant_4x4_dc = dequant_4x4_dc; /
pf->dequant_8x8 = dequant_8x8; /处理4个4x4的块针对8x8DCT的反量化
/Intra16x16中,16个DC系数Hadamard变换后对的它们反量化
pf->idct_dequant_2x4_dc = idct_dequant_2x4_dc;
pf->idct_dequant_2x4_dconly = idct_dequant_2x4_dconly;
//色度
pf->optimize_chroma_2x2_dc = optimize_chroma_2x2_dc;
pf->optimize_chroma_2x4_dc = optimize_chroma_2x4_dc;
pf->denoise_dct = x264_denoise_dct;
pf->decimate_score15 = x264_decimate_score15;
pf->decimate_score16 = x264_decimate_score16;
pf->decimate_score64 = x264_decimate_score64;
pf->coeff_last4 = x264_coeff_last4;
pf->coeff_last8 = x264_coeff_last8;
pf->coeff_last[ DCT_LUMA_AC] = x264_coeff_last15;
pf->coeff_last[ DCT_LUMA_4x4] = x264_coeff_last16;
pf->coeff_last[ DCT_LUMA_8x8] = x264_coeff_last64;
pf->coeff_level_run4 = x264_coeff_level_run4;
pf->coeff_level_run8 = x264_coeff_level_run8;
pf->coeff_level_run[ DCT_LUMA_AC] = x264_coeff_level_run15;
pf->coeff_level_run[ DCT_LUMA_4x4] = x264_coeff_level_run16;
#if HIGH_BIT_DEPTH
#if HAVE_MMX
INIT_TRELLIS( sse2 );
if( cpu&X264_CPU_MMX2 )
{
#if ARCH_X86
pf->denoise_dct = x264_denoise_dct_mmx;
pf->decimate_score15 = x264_decimate_score15_mmx2;
pf->decimate_score16 = x264_decimate_score16_mmx2;
pf->decimate_score64 = x264_decimate_score64_mmx2;