x264中率失真優化相關函式的呼叫關係
阿新 • • 發佈:2019-02-09
x264中的rdo.c函式呼叫關係
x264_rdo_init
- x264_encoder_open
cached_hadamard , cache_satd
- ssd_plane, 1
ssd_plane
- ssd_mb, 3
- x264_rd_cost_chroma, 2
- x264_rd_cost_i4x4, 3
- x264_rd_cost_i8x8, 3
- x264_rd_cost_part, 3
- x264_rd_cost_subpart, 3
x264_rd_cost_subpart:
- x264_rd_cost_part, 1
x264_rd_cost_i8x8
- x264_intra_rd_refine, 1
x264_rd_cost_i4x4:
- x264_intra_rd_refine, 1
x264_rd_cost_chroma:
- x264_intra_rd_refine, 2
上面三個函式都是在同一個函式x264_intra_rd_refine中被呼叫
ssd_mb:
- x264_macroblock_analyse, 1
- x264_rd_cost_mb, 1
在內部被x264_rd_cost_mb呼叫,在檔案外被x264_macroblock_analyse呼叫
x264_rd_cost_part:
- COST_MV_RD, 1
- x264_mb_analyse_p_rd, 1
- x264_me_refine_bidir, 1
外部三次呼叫
x264_rd_cost_mb:
- x264_intra_rd, 3
- x264_intra_rd_refine, 1
- x264_mb_analyse_b_rd, 7
- x264_mb_analyse_inter_p16x16, 1
- x264_mb_analyse_p_rd, 4
- x264_mb_analyse_qp_rd, 5
- x264_mb_analyse_transform_rd, 1
- x264_rd_cost_part, 1
被外部函式23次呼叫
提供給外部呼叫的函式為:
- x264_rdo_init
- x264_rd_cost_i8x8
- x264_rd_cost_i4x4
- x264_rd_cost_chroma
- ssd_mb
- x264_rd_cost_part
- x264_rd_cost_mb
粗體的兩個函式是主要提供給外部的介面,且外部呼叫函式中,除了x264_me_refine_bidir位於me.c,其他都是analyse.c中的函式。
x264_rd_cost_part分析
//這個函式的主要目的是計算在給定量化引數情況下,各種劃分對應的率失真代價
uint64_t x264_rd_cost_part( x264_t *h, int i_lambda2, int i4, int i_pixel )
{
// i_ssd用來記錄失真,使用的是平方誤差和,i_bits記錄位元速率
uint64_t i_ssd, i_bits;
int i8 = i4 >> 2;
//如果劃分是16*16,直接呼叫x264_rd_cost_mb
if( i_pixel == PIXEL_16x16 )
{
int i_cost = x264_rd_cost_mb( h, i_lambda2 );
return i_cost;
}
//如果劃分比8*8更小,呼叫x264_rd_cost_subpart
if( i_pixel > PIXEL_8x8 )
return x264_rd_cost_subpart( h, i_lambda2, i4, i_pixel );
h->mb.i_cbp_luma = 0;
//編碼
x264_macroblock_encode_p8x8( h, i8 );
if( i_pixel == PIXEL_16x8 )
x264_macroblock_encode_p8x8( h, i8+1 );
if( i_pixel == PIXEL_8x16 )
x264_macroblock_encode_p8x8( h, i8+2 );
//計算失真
int ssd_x = 8*(i8&1);
int ssd_y = 8*(i8>>1);
i_ssd = ssd_plane( h, i_pixel, 0, ssd_x, ssd_y );
int chromapix = h->luma2chroma_pixel[i_pixel];
int chromassd = ssd_plane( h, chromapix, 1, ssd_x>>CHROMA_H_SHIFT, ssd_y>>CHROMA_V_SHIFT )
+ ssd_plane( h, chromapix, 2, ssd_x>>CHROMA_H_SHIFT, ssd_y>>CHROMA_V_SHIFT );
i_ssd += ((uint64_t)chromassd * h->mb.i_chroma_lambda2_offset + 128) >> 8;
//計算位元速率,如果開啟cabac則用cabac,否則使用cavlc,\lamda2是率失真函式中的係數
if( h->param.b_cabac )
{
x264_cabac_t cabac_tmp;
COPY_CABAC;
x264_partition_size_cabac( h, &cabac_tmp, i8, i_pixel );
i_bits = ( (uint64_t)cabac_tmp.f8_bits_encoded * i_lambda2 + 128 ) >> 8;
}
else
i_bits = (uint64_t)x264_partition_size_cavlc( h, i8, i_pixel ) * i_lambda2;
return (i_ssd<<8) + i_bits;
}
x264_rd_cost_mb分析
static int x264_rd_cost_mb( x264_t *h, int i_lambda2 )
{
int b_transform_bak = h->mb.b_transform_8x8;
int i_ssd;
int i_bits;
int type_bak = h->mb.i_type;
//編碼
x264_macroblock_encode( h );
if( h->mb.b_deblock_rdo )
x264_macroblock_deblock( h );
//計算ssd
i_ssd = ssd_mb( h );
//計算位元速率與\lamda2相乘
if( IS_SKIP( h->mb.i_type ) )
{
i_bits = (1 * i_lambda2 + 128) >> 8;
}
else if( h->param.b_cabac )
{
x264_cabac_t cabac_tmp;
COPY_CABAC;
x264_macroblock_size_cabac( h, &cabac_tmp );
i_bits = ( (uint64_t)cabac_tmp.f8_bits_encoded * i_lambda2 + 32768 ) >> 16;
}
else
{
x264_macroblock_size_cavlc( h );
i_bits = ( (uint64_t)h->out.bs.i_bits_encoded * i_lambda2 + 128 ) >> 8;
}
h->mb.b_transform_8x8 = b_transform_bak;
h->mb.i_type = type_bak;
//返回計算得到的代價與設定的最大代價中較小的那個
return X264_MIN( i_ssd + i_bits, COST_MAX );
}