x264代码剖析(十六):核心算法之宏块编码中的量化编码

简介: <h1 style="text-align:center"><strong>x264<span style="font-family:宋体">代码剖析(十六):核心算法之宏块编码中的量化编码</span></strong></h1> <p> </p> <p>        为了进一步节省图像的传输码率,需要对图像进行压缩,通常采用变换编码及量化来消除图像中的相关性以减少图像编码的动态范

x264代码剖析(十六):核心算法之宏块编码中的量化编码

 

        为了进一步节省图像的传输码率,需要对图像进行压缩,通常采用变换编码及量化来消除图像中的相关性以减少图像编码的动态范围。本文主要介绍量化的相关内容,并给出x264中量化编码的代码分析。

 

1、量化编码

 

        量化过程就是根据图像的动态范围大小确定量化参数,既保留图像必要的细节,又可以减少码流。在图像编码中,变换编码和量化从原理上讲是两个独立的过程。但在H.264中,将两个过程中的乘法合二为一,并进一步采用整数运算,减少编解码的运算量,提高图像压缩的实时性,这些措施对峰值信噪比(PSNR)的影响很小,一般低于0.02dB,可不计。下面给出编码器中变换编码及量化过程的流程。




        下面给出毕厚杰著作的《新一代视频压缩编码标准——H.264/AVC(第二版)》中量化的相关理论知识,仅供学习参考。




2、量化源码分析

 

        量化的相关函数大都位于common/quant.c中,主要包括以下函数:

x264_quant_init():初始化量化和反量化相关的汇编函数

quant_4x4():对4x4DCT残差矩阵进行量化

QUANT_ONE():完成一个DCT系数的量化工作

quant_4x4x4():对44x4DCT残差矩阵进行量化

 

        下面对这些函数进行深入分析。


2.1x264_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;
        pf->coeff_last8 = x264_coeff_last8_mmx2;
        pf->coeff_last[  DCT_LUMA_AC] = x264_coeff_last15_mmx2;
        pf->coeff_last[ DCT_LUMA_4x4] = x264_coeff_last16_mmx2;
        pf->coeff_last[ DCT_LUMA_8x8] = x264_coeff_last64_mmx2;
        pf->coeff_level_run8 = x264_coeff_level_run8_mmx2;
        pf->coeff_level_run[  DCT_LUMA_AC] = x264_coeff_level_run15_mmx2;
        pf->coeff_level_run[ DCT_LUMA_4x4] = x264_coeff_level_run16_mmx2;
#endif
        pf->coeff_last4 = x264_coeff_last4_mmx2;
        pf->coeff_level_run4 = x264_coeff_level_run4_mmx2;
        if( cpu&X264_CPU_LZCNT )
            pf->coeff_level_run4 = x264_coeff_level_run4_mmx2_lzcnt;
    }
    if( cpu&X264_CPU_SSE2 )
    {
        pf->quant_4x4 = x264_quant_4x4_sse2;
        pf->quant_4x4x4 = x264_quant_4x4x4_sse2;
        pf->quant_8x8 = x264_quant_8x8_sse2;
        pf->quant_2x2_dc = x264_quant_2x2_dc_sse2;
        pf->quant_4x4_dc = x264_quant_4x4_dc_sse2;
        pf->dequant_4x4 = x264_dequant_4x4_sse2;
        pf->dequant_8x8 = x264_dequant_8x8_sse2;
        pf->dequant_4x4_dc = x264_dequant_4x4dc_sse2;
        pf->denoise_dct = x264_denoise_dct_sse2;
        pf->decimate_score15 = x264_decimate_score15_sse2;
        pf->decimate_score16 = x264_decimate_score16_sse2;
        pf->decimate_score64 = x264_decimate_score64_sse2;
        pf->coeff_last8 = x264_coeff_last8_sse2;
        pf->coeff_last[ DCT_LUMA_AC] = x264_coeff_last15_sse2;
        pf->coeff_last[DCT_LUMA_4x4] = x264_coeff_last16_sse2;
        pf->coeff_last[DCT_LUMA_8x8] = x264_coeff_last64_sse2;
        pf->coeff_level_run8 = x264_coeff_level_run8_sse2;
        pf->coeff_level_run[ DCT_LUMA_AC] = x264_coeff_level_run15_sse2;
        pf->coeff_level_run[DCT_LUMA_4x4] = x264_coeff_level_run16_sse2;
        if( cpu&X264_CPU_LZCNT )
        {
            pf->coeff_last4 = x264_coeff_last4_mmx2_lzcnt;
            pf->coeff_last8 = x264_coeff_last8_sse2_lzcnt;
            pf->coeff_last[ DCT_LUMA_AC] = x264_coeff_last15_sse2_lzcnt;
            pf->coeff_last[DCT_LUMA_4x4] = x264_coeff_last16_sse2_lzcnt;
            pf->coeff_last[DCT_LUMA_8x8] = x264_coeff_last64_sse2_lzcnt;
            pf->coeff_level_run8 = x264_coeff_level_run8_sse2_lzcnt;
            pf->coeff_level_run[ DCT_LUMA_AC] = x264_coeff_level_run15_sse2_lzcnt;
            pf->coeff_level_run[DCT_LUMA_4x4] = x264_coeff_level_run16_sse2_lzcnt;
        }
    }
    if( cpu&X264_CPU_SSSE3 )
    {
        pf->quant_4x4 = x264_quant_4x4_ssse3;
        pf->quant_4x4x4 = x264_quant_4x4x4_ssse3;
        pf->quant_8x8 = x264_quant_8x8_ssse3;
        pf->quant_2x2_dc = x264_quant_2x2_dc_ssse3;
        pf->quant_4x4_dc = x264_quant_4x4_dc_ssse3;
        pf->denoise_dct = x264_denoise_dct_ssse3;
        pf->decimate_score15 = x264_decimate_score15_ssse3;
        pf->decimate_score16 = x264_decimate_score16_ssse3;
        pf->decimate_score64 = x264_decimate_score64_ssse3;
        INIT_TRELLIS( ssse3 );
    }
    if( cpu&X264_CPU_SSE4 )
    {
        pf->quant_2x2_dc = x264_quant_2x2_dc_sse4;
        pf->quant_4x4_dc = x264_quant_4x4_dc_sse4;
        pf->quant_4x4 = x264_quant_4x4_sse4;
        pf->quant_4x4x4 = x264_quant_4x4x4_sse4;
        pf->quant_8x8 = x264_quant_8x8_sse4;
    }
    if( cpu&X264_CPU_AVX )
    {
        pf->denoise_dct = x264_denoise_dct_avx;
    }
    if( cpu&X264_CPU_XOP )
    {
        pf->dequant_4x4_dc = x264_dequant_4x4dc_xop;
        if( h->param.i_cqm_preset != X264_CQM_FLAT )
        {
            pf->dequant_4x4 = x264_dequant_4x4_xop;
            pf->dequant_8x8 = x264_dequant_8x8_xop;
        }
    }
    if( cpu&X264_CPU_AVX2 )
    {
        pf->quant_4x4 = x264_quant_4x4_avx2;
        pf->quant_4x4_dc = x264_quant_4x4_dc_avx2;
        pf->quant_8x8 = x264_quant_8x8_avx2;
        pf->quant_4x4x4 = x264_quant_4x4x4_avx2;
        pf->dequant_4x4 = x264_dequant_4x4_avx2;
        pf->dequant_8x8 = x264_dequant_8x8_avx2;
        pf->dequant_4x4_dc = x264_dequant_4x4dc_avx2;
        pf->denoise_dct = x264_denoise_dct_avx2;
        if( cpu&X264_CPU_LZCNT )
            pf->coeff_last[DCT_LUMA_8x8] = x264_coeff_last64_avx2_lzcnt;
    }
#endif // HAVE_MMX
#else // !HIGH_BIT_DEPTH
#if HAVE_MMX
    INIT_TRELLIS( sse2 );
    if( cpu&X264_CPU_MMX )
    {
#if ARCH_X86
        pf->dequant_4x4 = x264_dequant_4x4_mmx;
        pf->dequant_4x4_dc = x264_dequant_4x4dc_mmx2;
        pf->dequant_8x8 = x264_dequant_8x8_mmx;
        if( h->param.i_cqm_preset == X264_CQM_FLAT )
        {
            pf->dequant_4x4 = x264_dequant_4x4_flat16_mmx;
            pf->dequant_8x8 = x264_dequant_8x8_flat16_mmx;
        }
        pf->denoise_dct = x264_denoise_dct_mmx;
#endif
    }

    if( cpu&X264_CPU_MMX2 )
    {
        pf->quant_2x2_dc = x264_quant_2x2_dc_mmx2;
#if ARCH_X86
        pf->quant_4x4 = x264_quant_4x4_mmx2;
        pf->quant_8x8 = x264_quant_8x8_mmx2;
        pf->quant_4x4_dc = x264_quant_4x4_dc_mmx2;
        pf->decimate_score15 = x264_decimate_score15_mmx2;
        pf->decimate_score16 = x264_decimate_score16_mmx2;
        pf->decimate_score64 = x264_decimate_score64_mmx2;
        pf->coeff_last[  DCT_LUMA_AC] = x264_coeff_last15_mmx2;
        pf->coeff_last[ DCT_LUMA_4x4] = x264_coeff_last16_mmx2;
        pf->coeff_last[ DCT_LUMA_8x8] = x264_coeff_last64_mmx2;
        pf->coeff_level_run[  DCT_LUMA_AC] = x264_coeff_level_run15_mmx2;
        pf->coeff_level_run[ DCT_LUMA_4x4] = x264_coeff_level_run16_mmx2;
#endif
        pf->coeff_last4 = x264_coeff_last4_mmx2;
        pf->coeff_last8 = x264_coeff_last8_mmx2;
        pf->coeff_level_run4 = x264_coeff_level_run4_mmx2;
        pf->coeff_level_run8 = x264_coeff_level_run8_mmx2;
        if( cpu&X264_CPU_LZCNT )
        {
            pf->coeff_last4 = x264_coeff_last4_mmx2_lzcnt;
            pf->coeff_last8 = x264_coeff_last8_mmx2_lzcnt;
            pf->coeff_level_run4 = x264_coeff_level_run4_mmx2_lzcnt;
            pf->coeff_level_run8 = x264_coeff_level_run8_mmx2_lzcnt;
        }
    }

    if( cpu&X264_CPU_SSE2 )
    {
        pf->quant_4x4_dc = x264_quant_4x4_dc_sse2;
        pf->quant_4x4 = x264_quant_4x4_sse2;
        pf->quant_4x4x4 = x264_quant_4x4x4_sse2;
        pf->quant_8x8 = x264_quant_8x8_sse2;
        pf->dequant_4x4 = x264_dequant_4x4_sse2;
        pf->dequant_4x4_dc = x264_dequant_4x4dc_sse2;
        pf->dequant_8x8 = x264_dequant_8x8_sse2;
        if( h->param.i_cqm_preset == X264_CQM_FLAT )
        {
            pf->dequant_4x4 = x264_dequant_4x4_flat16_sse2;
            pf->dequant_8x8 = x264_dequant_8x8_flat16_sse2;
        }
        pf->optimize_chroma_2x2_dc = x264_optimize_chroma_2x2_dc_sse2;
        pf->denoise_dct = x264_denoise_dct_sse2;
        pf->decimate_score15 = x264_decimate_score15_sse2;
        pf->decimate_score16 = x264_decimate_score16_sse2;
        pf->decimate_score64 = x264_decimate_score64_sse2;
        pf->coeff_last[ DCT_LUMA_AC] = x264_coeff_last15_sse2;
        pf->coeff_last[DCT_LUMA_4x4] = x264_coeff_last16_sse2;
        pf->coeff_last[DCT_LUMA_8x8] = x264_coeff_last64_sse2;
        pf->coeff_level_run[ DCT_LUMA_AC] = x264_coeff_level_run15_sse2;
        pf->coeff_level_run[DCT_LUMA_4x4] = x264_coeff_level_run16_sse2;
        if( cpu&X264_CPU_LZCNT )
        {
            pf->coeff_last[ DCT_LUMA_AC] = x264_coeff_last15_sse2_lzcnt;
            pf->coeff_last[DCT_LUMA_4x4] = x264_coeff_last16_sse2_lzcnt;
            pf->coeff_last[DCT_LUMA_8x8] = x264_coeff_last64_sse2_lzcnt;
            pf->coeff_level_run[ DCT_LUMA_AC] = x264_coeff_level_run15_sse2_lzcnt;
            pf->coeff_level_run[DCT_LUMA_4x4] = x264_coeff_level_run16_sse2_lzcnt;
        }
    }

    if( cpu&X264_CPU_SSSE3 )
    {
        pf->quant_2x2_dc = x264_quant_2x2_dc_ssse3;
        pf->quant_4x4_dc = x264_quant_4x4_dc_ssse3;
        pf->quant_4x4 = x264_quant_4x4_ssse3;
        pf->quant_4x4x4 = x264_quant_4x4x4_ssse3;
        pf->quant_8x8 = x264_quant_8x8_ssse3;
        pf->optimize_chroma_2x2_dc = x264_optimize_chroma_2x2_dc_ssse3;
        pf->denoise_dct = x264_denoise_dct_ssse3;
        pf->decimate_score15 = x264_decimate_score15_ssse3;
        pf->decimate_score16 = x264_decimate_score16_ssse3;
        pf->decimate_score64 = x264_decimate_score64_ssse3;
        INIT_TRELLIS( ssse3 );
        pf->coeff_level_run4 = x264_coeff_level_run4_ssse3;
        pf->coeff_level_run8 = x264_coeff_level_run8_ssse3;
        pf->coeff_level_run[ DCT_LUMA_AC] = x264_coeff_level_run15_ssse3;
        pf->coeff_level_run[DCT_LUMA_4x4] = x264_coeff_level_run16_ssse3;
        if( cpu&X264_CPU_LZCNT )
        {
            pf->coeff_level_run4 = x264_coeff_level_run4_ssse3;
            pf->coeff_level_run8 = x264_coeff_level_run8_ssse3;
            pf->coeff_level_run[ DCT_LUMA_AC] = x264_coeff_level_run15_ssse3_lzcnt;
            pf->coeff_level_run[DCT_LUMA_4x4] = x264_coeff_level_run16_ssse3_lzcnt;
        }
    }

    if( cpu&X264_CPU_SSE4 )
    {
        pf->quant_4x4_dc = x264_quant_4x4_dc_sse4;
        pf->quant_4x4 = x264_quant_4x4_sse4;
        pf->quant_8x8 = x264_quant_8x8_sse4;
        pf->optimize_chroma_2x2_dc = x264_optimize_chroma_2x2_dc_sse4;
    }

    if( cpu&X264_CPU_AVX )
    {
        pf->dequant_4x4_dc = x264_dequant_4x4dc_avx;
        if( h->param.i_cqm_preset != X264_CQM_FLAT )
        {
            pf->dequant_4x4 = x264_dequant_4x4_avx;
            pf->dequant_8x8 = x264_dequant_8x8_avx;
        }
        pf->optimize_chroma_2x2_dc = x264_optimize_chroma_2x2_dc_avx;
        pf->denoise_dct = x264_denoise_dct_avx;
    }

    if( cpu&X264_CPU_XOP )
    {
        if( h->param.i_cqm_preset != X264_CQM_FLAT )
        {
            pf->dequant_4x4 = x264_dequant_4x4_xop;
            pf->dequant_8x8 = x264_dequant_8x8_xop;
        }
    }

    if( cpu&X264_CPU_AVX2 )
    {
        pf->quant_4x4 = x264_quant_4x4_avx2;
        pf->quant_4x4_dc = x264_quant_4x4_dc_avx2;
        pf->quant_8x8 = x264_quant_8x8_avx2;
        pf->quant_4x4x4 = x264_quant_4x4x4_avx2;
        pf->dequant_4x4 = x264_dequant_4x4_avx2;
        pf->dequant_8x8 = x264_dequant_8x8_avx2;
        pf->dequant_4x4_dc = x264_dequant_4x4dc_avx2;
        if( h->param.i_cqm_preset == X264_CQM_FLAT )
        {
            pf->dequant_4x4 = x264_dequant_4x4_flat16_avx2;
            pf->dequant_8x8 = x264_dequant_8x8_flat16_avx2;
        }
        pf->decimate_score64 = x264_decimate_score64_avx2;
        pf->denoise_dct = x264_denoise_dct_avx2;
        if( cpu&X264_CPU_LZCNT )
        {
            pf->coeff_last[DCT_LUMA_8x8] = x264_coeff_last64_avx2_lzcnt;
            pf->coeff_level_run[ DCT_LUMA_AC] = x264_coeff_level_run15_avx2_lzcnt;
            pf->coeff_level_run[DCT_LUMA_4x4] = x264_coeff_level_run16_avx2_lzcnt;
        }
    }
#endif // HAVE_MMX

#if HAVE_ALTIVEC
    if( cpu&X264_CPU_ALTIVEC )
    {
        pf->quant_2x2_dc = x264_quant_2x2_dc_altivec;
        pf->quant_4x4_dc = x264_quant_4x4_dc_altivec;
        pf->quant_4x4 = x264_quant_4x4_altivec;
        pf->quant_8x8 = x264_quant_8x8_altivec;

        pf->dequant_4x4 = x264_dequant_4x4_altivec;
        pf->dequant_8x8 = x264_dequant_8x8_altivec;
    }
#endif

#if HAVE_ARMV6
    if( cpu&X264_CPU_ARMV6 )
    {
        pf->coeff_last4 = x264_coeff_last4_arm;
        pf->coeff_last8 = x264_coeff_last8_arm;
    }
#endif
#if HAVE_ARMV6 || ARCH_AARCH64
    if( cpu&X264_CPU_NEON )
    {
        pf->quant_2x2_dc   = x264_quant_2x2_dc_neon;
        pf->quant_4x4      = x264_quant_4x4_neon;
        pf->quant_4x4_dc   = x264_quant_4x4_dc_neon;
        pf->quant_4x4x4    = x264_quant_4x4x4_neon;
        pf->quant_8x8      = x264_quant_8x8_neon;
        pf->dequant_4x4    = x264_dequant_4x4_neon;
        pf->dequant_4x4_dc = x264_dequant_4x4_dc_neon;
        pf->dequant_8x8    = x264_dequant_8x8_neon;
        pf->coeff_last[ DCT_LUMA_AC] = x264_coeff_last15_neon;
        pf->coeff_last[DCT_LUMA_4x4] = x264_coeff_last16_neon;
        pf->coeff_last[DCT_LUMA_8x8] = x264_coeff_last64_neon;
        pf->denoise_dct = x264_denoise_dct_neon;
        pf->decimate_score15 = x264_decimate_score15_neon;
        pf->decimate_score16 = x264_decimate_score16_neon;
        pf->decimate_score64 = x264_decimate_score64_neon;
    }
#endif
#if ARCH_AARCH64
    if( cpu&X264_CPU_ARMV8 )
    {
        pf->coeff_last4 = x264_coeff_last4_aarch64;
        pf->coeff_last8 = x264_coeff_last8_aarch64;
        pf->coeff_level_run4 = x264_coeff_level_run4_aarch64;
    }
    if( cpu&X264_CPU_NEON )
    {
        pf->coeff_level_run8 = x264_coeff_level_run8_neon;
        pf->coeff_level_run[  DCT_LUMA_AC] = x264_coeff_level_run15_neon;
        pf->coeff_level_run[ DCT_LUMA_4x4] = x264_coeff_level_run16_neon;
    }
#endif

#if HAVE_MSA
    if( cpu&X264_CPU_MSA )
    {
        pf->quant_4x4      = x264_quant_4x4_msa;
        pf->quant_4x4_dc   = x264_quant_4x4_dc_msa;
        pf->quant_4x4x4    = x264_quant_4x4x4_msa;
        pf->quant_8x8      = x264_quant_8x8_msa;
        pf->dequant_4x4    = x264_dequant_4x4_msa;
        pf->dequant_4x4_dc = x264_dequant_4x4_dc_msa;
        pf->dequant_8x8    = x264_dequant_8x8_msa;
        pf->coeff_last[DCT_LUMA_4x4] = x264_coeff_last16_msa;
        pf->coeff_last[DCT_LUMA_8x8] = x264_coeff_last64_msa;
    }
#endif
#endif // HIGH_BIT_DEPTH
    pf->coeff_last[DCT_LUMA_DC]     = pf->coeff_last[DCT_CHROMAU_DC]  = pf->coeff_last[DCT_CHROMAV_DC] =
    pf->coeff_last[DCT_CHROMAU_4x4] = pf->coeff_last[DCT_CHROMAV_4x4] = pf->coeff_last[DCT_LUMA_4x4];
    pf->coeff_last[DCT_CHROMA_AC]   = pf->coeff_last[DCT_CHROMAU_AC]  =
    pf->coeff_last[DCT_CHROMAV_AC]  = pf->coeff_last[DCT_LUMA_AC];
    pf->coeff_last[DCT_CHROMAU_8x8] = pf->coeff_last[DCT_CHROMAV_8x8] = pf->coeff_last[DCT_LUMA_8x8];

    pf->coeff_level_run[DCT_LUMA_DC]     = pf->coeff_level_run[DCT_CHROMAU_DC]  = pf->coeff_level_run[DCT_CHROMAV_DC] =
    pf->coeff_level_run[DCT_CHROMAU_4x4] = pf->coeff_level_run[DCT_CHROMAV_4x4] = pf->coeff_level_run[DCT_LUMA_4x4];
    pf->coeff_level_run[DCT_CHROMA_AC]   = pf->coeff_level_run[DCT_CHROMAU_AC]  =
    pf->coeff_level_run[DCT_CHROMAV_AC]  = pf->coeff_level_run[DCT_LUMA_AC];
}

 

       其中, x264_quant_function_t的定义如下:


typedef struct
{
    int (*quant_8x8)  ( dctcoef dct[64], udctcoef mf[64], udctcoef bias[64] );
    int (*quant_4x4)  ( dctcoef dct[16], udctcoef mf[16], udctcoef bias[16] );
    int (*quant_4x4x4)( dctcoef dct[4][16], udctcoef mf[16], udctcoef bias[16] );
    int (*quant_4x4_dc)( dctcoef dct[16], int mf, int bias );
    int (*quant_2x2_dc)( dctcoef dct[4], int mf, int bias );

    void (*dequant_8x8)( dctcoef dct[64], int dequant_mf[6][64], int i_qp );
    void (*dequant_4x4)( dctcoef dct[16], int dequant_mf[6][16], int i_qp );
    void (*dequant_4x4_dc)( dctcoef dct[16], int dequant_mf[6][16], int i_qp );

    void (*idct_dequant_2x4_dc)( dctcoef dct[8], dctcoef dct4x4[8][16], int dequant_mf[6][16], int i_qp );
    void (*idct_dequant_2x4_dconly)( dctcoef dct[8], int dequant_mf[6][16], int i_qp );

    int (*optimize_chroma_2x2_dc)( dctcoef dct[4], int dequant_mf );
    int (*optimize_chroma_2x4_dc)( dctcoef dct[8], int dequant_mf );

    void (*denoise_dct)( dctcoef *dct, uint32_t *sum, udctcoef *offset, int size );

    int (*decimate_score15)( dctcoef *dct );
    int (*decimate_score16)( dctcoef *dct );
    int (*decimate_score64)( dctcoef *dct );
    int (*coeff_last[14])( dctcoef *dct );
    int (*coeff_last4)( dctcoef *dct );
    int (*coeff_last8)( dctcoef *dct );
    int (*coeff_level_run[13])( dctcoef *dct, x264_run_level_t *runlevel );
    int (*coeff_level_run4)( dctcoef *dct, x264_run_level_t *runlevel );
    int (*coeff_level_run8)( dctcoef *dct, x264_run_level_t *runlevel );

#define TRELLIS_PARAMS const int *unquant_mf, const uint8_t *zigzag, int lambda2,\
                       int last_nnz, dctcoef *coefs, dctcoef *quant_coefs, dctcoef *dct,\
                       uint8_t *cabac_state_sig, uint8_t *cabac_state_last,\
                       uint64_t level_state0, uint16_t level_state1
    int (*trellis_cabac_4x4)( TRELLIS_PARAMS, int b_ac );
    int (*trellis_cabac_8x8)( TRELLIS_PARAMS, int b_interlaced );
    int (*trellis_cabac_4x4_psy)( TRELLIS_PARAMS, int b_ac, dctcoef *fenc_dct, int psy_trellis );
    int (*trellis_cabac_8x8_psy)( TRELLIS_PARAMS, int b_interlaced, dctcoef *fenc_dct, int psy_trellis );
    int (*trellis_cabac_dc)( TRELLIS_PARAMS, int num_coefs );
    int (*trellis_cabac_chroma_422_dc)( TRELLIS_PARAMS );
} x264_quant_function_t;


 

2.2quant_4x4()函数

 

        quant_4x4()用于对4x4DCT残差矩阵进行量化,quant_4x4()循环16次调用了QUANT_ONE()完成了量化工作。并且将DCT系数值,MF值,bias偏移值直接传递给了该宏。对应的代码分析如下:

 

/************====== 4x4的DCT残差矩阵的量化 ======************/
/*
功能:quant_4x4()用于对4x4的DCT残差矩阵进行量化
*/
static int quant_4x4( dctcoef dct[16], udctcoef mf[16], udctcoef bias[16] )//输入输出都是dct[16]
{
    int nz = 0;
    for( int i = 0; i < 16; i++ )//循环16个元素
        QUANT_ONE( dct[i], mf[i], bias[i] );
    return !!nz;
}

 

        其中,QUANT_ONE()完成了一个DCT系数的量化工作,从QUANT_ONE()的定义可以看出,它实现了上文提到的H.264标准中的量化公式。它的定义如下:

 

/************====== QUANT_ONE() ======************/
/*
功能:量化1个元素
*/
#define QUANT_ONE( coef, mf, f ) \
{ \
    if( (coef) > 0 ) \
        (coef) = (f + (coef)) * (mf) >> 16; \
    else \
        (coef) = - ((f - (coef)) * (mf) >> 16); \
    nz |= (coef); \
}

 

2.3quant_4x4x4()函数

 

        quant_4x4x4()用于对44x4DCT残差矩阵进行量化。该函数的定义位于common\quant.c,从quant_4x4x4()的定义可以看出,该函数相当于调用了4quant_4x4()函数。对应的代码分析如下:


/************====== 4个4x4的DCT残差矩阵的量化 ======************/
/*
功能:quant_4x4x4()用于对4个4x4的DCT残差矩阵进行量化,从quant_4x4x4()的定义可以看出,该函数相当于调用了4次quant_4x4()函数。
*/
static int quant_4x4x4( dctcoef dct[4][16], udctcoef mf[16], udctcoef bias[16] )//输入输出都是dct[4][16] 
{
    int nza = 0;
    for( int j = 0; j < 4; j++ )//处理4个
    {
        int nz = 0;
        for( int i = 0; i < 16; i++ )
            QUANT_ONE( dct[j][i], mf[i], bias[i] );//量化
        nza |= (!!nz)<<j;
    }
    return nza;
}


大笑至此,x264中量化的重点函数就分析完毕了。


目录
相关文章
|
3天前
|
机器学习/深度学习 存储 算法
编码之舞:从算法到应用的探索之旅
在数字化时代的浪潮中,编程技术如同一种语言,连接着人类与机器。本文将带领读者踏上一场自数据结构基础至高级算法应用的探索旅程,通过实际案例分析,揭示算法在现代软件开发中的重要作用,并分享作者在编程实践中的心得体会,旨在为初学者和资深开发者提供有价值的参考与启示。
|
9天前
|
并行计算 算法 Python
Dantzig-Wolfe分解算法解释与Python代码示例
Dantzig-Wolfe分解算法解释与Python代码示例
|
11天前
|
机器学习/深度学习 算法 计算机视觉
通过MATLAB分别对比二进制编码遗传优化算法和实数编码遗传优化算法
摘要: 使用MATLAB2022a对比了二进制编码与实数编码的遗传优化算法,关注最优适应度、平均适应度及运算效率。二进制编码适用于离散问题,解表示为二进制串;实数编码适用于连续问题,直接搜索连续空间。两种编码在初始化、适应度评估、选择、交叉和变异步骤类似,但实数编码可能需更复杂策略避免局部最优。选择编码方式取决于问题特性。
|
17天前
|
存储 算法 大数据
Python算法高手的必修课:深入理解分治法、贪心算法、动态规划,让你的代码更智能!
【7月更文挑战第9天】在Python算法学习中,分治法(如归并排序)将大问题分解为小部分递归解决;贪心算法(如货币找零)在每步选择局部最优解尝试达到全局最优;动态规划(如斐波那契数列)通过存储子问题解避免重复计算,解决重叠子问题。掌握这三种方法能提升代码效率,解决复杂问题。
|
24天前
|
算法 PHP
【php经典算法】冒泡排序,冒泡排序原理,冒泡排序执行逻辑,执行过程,执行结果 代码
【php经典算法】冒泡排序,冒泡排序原理,冒泡排序执行逻辑,执行过程,执行结果 代码
14 1
|
5天前
|
缓存 算法 Java
如何使用代码实现漏桶算法
如何使用代码实现漏桶算法
|
1月前
|
人工智能 算法 Java
java中经典算法代码整理
java中经典算法代码整理
25 0
|
1月前
|
算法 IDE 开发工具
c语言的经典算法代码
c语言进阶11-经典算法代码
|
1月前
|
算法
数据结构和算法常见的问题和代码
数据结构和算法常见的问题和代码
15 0

热门文章

最新文章