x264代碼剖析(十六):核心算法之宏塊編碼中的量化編碼


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中量化的重點函數就分析完畢了。



注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com