x264 在编码完成一个宏块后,会重新根据rdo参数再次编码一次。
举个例子,如果最终得到的satd 是 20,当前的量化qp是25,计算出来的结果就全部是0,cbp 的6bits 全是0,x264 rdo 会尝试把qp值调小一点,重新编码一次,以减少细节损失。
对应看下源码:
x264_macroblock_analyse()-->x264_macroblock_encode( h );
在宏块分析里面先是做了一次编码
的最后几行
if( analysis.i_mbrd == 3 && !IS_SKIP(h->mb.i_type) )
mb_analyse_qp_rd( h, &analysis ); //如果不是skip 宏块,则做rdo
static inline void mb_analyse_qp_rd( x264_t *h, x264_mb_analysis_t *a )// RDO 选择QP
{//根据 RDO来调整 qp的值
int bcost, cost, failures, prevcost, origcost;
int orig_qp = h->mb.i_qp, bqp = h->mb.i_qp;
int last_qp_tried = 0;
origcost = bcost = rd_cost_mb( h, a->i_lambda2 );// 计算宏块的cost
int origcbp = h->mb.cbp[h->mb.i_mb_xy];
/* If CBP is already zero, don't raise the quantizer any higher. */
for( int direction = origcbp ? 1 : -1; direction >= -1; direction-=2 )
{
}
// rdo 中有个for 循环,意思是qp调整方向,是往大了调整,还是往小了调整,如果cbp全为0,表示没有残差了,就调小点,保留细节,如果cbp不为0就调大一点,尝试节省一些码率。
/* Check transform again; decision from before may no longer be optimal. */
if( h->mb.i_qp != orig_qp && h->param.analyse.b_transform_8x8 &&
x264_mb_transform_8x8_allowed( h ) )
{
h->mb.b_transform_8x8 ^= 1;
cost = rd_cost_mb( h, a->i_lambda2 );
if( cost > bcost )
h->mb.b_transform_8x8 ^= 1;
}
//调完后再做一次rd_mb_cost计算
static int 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 );
} 这里重新编码了一次。