x264中率失真优化相关函数的调用关系

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 );
}

猜你喜欢

转载自blog.csdn.net/gaussrieman123/article/details/78257078