From: Fiona Glaser Date: Wed, 19 Aug 2009 08:49:47 +0000 (-0700) Subject: Improve QPRD X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bde792fee0ac6d32d534918db870c94fe106b6e3;p=libx264 Improve QPRD Always check the last macroblock's QP, even if the normal search doesn't reach it. Raise the failure threshold when moving towards the last macroblock's QP. 0.2-1% improved compression. --- diff --git a/encoder/analyse.c b/encoder/analyse.c index 931369cd..a566edcf 100644 --- a/encoder/analyse.c +++ b/encoder/analyse.c @@ -2203,17 +2203,30 @@ static inline void x264_mb_analyse_qp_rd( x264_t *h, x264_mb_analysis_t *a ) { int bcost, cost, direction, failures, prevcost, origcost; int orig_qp = h->mb.i_qp, bqp = h->mb.i_qp; + int last_qp_tried = 0; origcost = bcost = x264_rd_cost_mb( h, a->i_lambda2 ); /* If CBP is already zero, don't raise the quantizer any higher. */ for( direction = h->mb.cbp[h->mb.i_mb_xy] ? 1 : -1; direction >= -1; direction-=2 ) { + /* Without psy-RD, require monotonicity when moving quant away from previous + * macroblock's quant; allow 1 failure when moving quant towards previous quant. + * With psy-RD, allow 1 failure when moving quant away from previous quant, + * allow 2 failures when moving quant towards previous quant. + * Psy-RD generally seems to result in more chaotic RD score-vs-quantizer curves. */ + int threshold = (!!h->mb.i_psy_rd); + /* Raise the threshold for failures if we're moving towards the last QP. */ + if( ( h->mb.i_last_qp < orig_qp && direction == -1 ) || + ( h->mb.i_last_qp > orig_qp && direction == 1 ) ) + threshold++; h->mb.i_qp = orig_qp; failures = 0; prevcost = origcost; h->mb.i_qp += direction; while( h->mb.i_qp >= h->param.rc.i_qp_min && h->mb.i_qp <= h->param.rc.i_qp_max ) { + if( h->mb.i_last_qp == h->mb.i_qp ) + last_qp_tried = 1; h->mb.i_chroma_qp = h->chroma_qp_table[h->mb.i_qp]; cost = x264_rd_cost_mb( h, a->i_lambda2 ); COPY2_IF_LT( bcost, cost, bqp, h->mb.i_qp ); @@ -2226,13 +2239,7 @@ static inline void x264_mb_analyse_qp_rd( x264_t *h, x264_mb_analysis_t *a ) failures++; prevcost = cost; - /* Without psy-RD, require monotonicity when lowering - * quant, allow 1 failure when raising quant. - * With psy-RD, allow 1 failure when lowering quant, - * allow 2 failures when raising quant. - * Psy-RD generally seems to result in more chaotic - * RD score-vs-quantizer curves. */ - if( failures > ((direction + 1)>>1)+(!!h->mb.i_psy_rd) ) + if( failures > threshold ) break; if( direction == 1 && !h->mb.cbp[h->mb.i_mb_xy] ) break; @@ -2240,6 +2247,15 @@ static inline void x264_mb_analyse_qp_rd( x264_t *h, x264_mb_analysis_t *a ) } } + /* Always try the last block's QP. */ + if( !last_qp_tried ) + { + h->mb.i_qp = h->mb.i_last_qp; + h->mb.i_chroma_qp = h->chroma_qp_table[h->mb.i_qp]; + cost = x264_rd_cost_mb( h, a->i_lambda2 ); + COPY2_IF_LT( bcost, cost, bqp, h->mb.i_qp ); + } + h->mb.i_qp = bqp; h->mb.i_chroma_qp = h->chroma_qp_table[h->mb.i_qp];