diff -uNrp a/common/common.c b/common/common.c --- a/common/common.c 2009-12-05 21:34:24 +0200 +++ b/common/common.c 2009-12-05 22:15:15 +0200 @@ -101,6 +101,7 @@ void x264_param_default( x264_param_t param->rc.f_pb_factor = 1.3; param->rc.i_aq_mode = X264_AQ_VARIANCE; param->rc.f_aq_strength = 1.0; + param->rc.f_aq_offset_strength = 0; param->rc.i_lookahead = 40; param->rc.b_stat_write = 0; @@ -577,7 +578,20 @@ int x264_param_parse( x264_param_t *p, c OPT("aq-mode") p->rc.i_aq_mode = atoi(value); OPT("aq-strength") - p->rc.f_aq_strength = atof(value); + { + if( 2 == sscanf( value, "%f:%f", &p->rc.f_aq_strength, &p->rc.f_aq_offset_strength ) || + 2 == sscanf( value, "%f,%f", &p->rc.f_aq_strength, &p->rc.f_aq_offset_strength ) ) + { } + else if( sscanf( value, "%f", &p->rc.f_aq_strength ) ) + { + p->rc.f_aq_offset_strength = 0; + } + else + { + p->rc.f_aq_strength = 0; + p->rc.f_aq_offset_strength = 0; + } + } OPT("pass") { int i = x264_clip3( atoi(value), 0, 3 ); @@ -942,7 +956,11 @@ char *x264_param2string( x264_param_t *p s += sprintf( s, " pb_ratio=%.2f", p->rc.f_pb_factor ); s += sprintf( s, " aq=%d", p->rc.i_aq_mode ); if( p->rc.i_aq_mode ) + { s += sprintf( s, ":%.2f", p->rc.f_aq_strength ); + if( p->rc.f_aq_offset_strength != 0 ) + s += sprintf( s, ":%.2f", p->rc.f_aq_offset_strength ); + } if( p->rc.psz_zones ) s += sprintf( s, " zones=%s", p->rc.psz_zones ); else if( p->rc.i_zones ) diff -uNrp a/encoder/encoder.c b/encoder/encoder.c --- a/encoder/encoder.c 2009-12-05 21:34:24 +0200 +++ b/encoder/encoder.c 2009-12-05 22:15:59 +0200 @@ -624,8 +624,9 @@ static int x264_validate_parameters( x26 else h->mb.i_psy_trellis = 0; h->param.analyse.i_chroma_qp_offset = x264_clip3(h->param.analyse.i_chroma_qp_offset, -12, 12); - h->param.rc.i_aq_mode = x264_clip3( h->param.rc.i_aq_mode, 0, 2 ); - h->param.rc.f_aq_strength = x264_clip3f( h->param.rc.f_aq_strength, 0, 3 ); + h->param.rc.i_aq_mode = x264_clip3( h->param.rc.i_aq_mode, 0, 3 ); + h->param.rc.f_aq_offset_strength = h->param.rc.i_aq_mode == X264_AQ_AUTOVARIANCE ? x264_clip3f( h->param.rc.f_aq_offset_strength, 0, 3 ) : 0; + if( h->param.rc.f_aq_strength == 0 && h->param.rc.f_aq_offset_strength == 0 ) if( h->param.rc.f_aq_strength == 0 ) h->param.rc.i_aq_mode = 0; /* MB-tree requires AQ to be on, even if the strength is zero. */ @@ -633,6 +634,7 @@ static int x264_validate_parameters( x26 { h->param.rc.i_aq_mode = 1; h->param.rc.f_aq_strength = 0; + h->param.rc.f_aq_offset_strength = 0; } if( h->param.rc.b_mb_tree && h->param.i_bframe_pyramid ) { diff -uNrp a/encoder/ratecontrol.c b/encoder/ratecontrol.c --- a/encoder/ratecontrol.c 2009-12-05 21:34:24 +0200 +++ b/encoder/ratecontrol.c 2009-12-05 22:17:36 +0200 @@ -215,9 +215,10 @@ void x264_adaptive_quant_frame( x264_t * * FIXME: while they're written in 5 significant digits, they're only tuned to 2. */ int mb_x, mb_y; float strength; - float avg_adj = 0.f; + float avg_adj = 0.0f; + float avg_offset = 0.0f; /* Need to init it anyways for MB tree. */ - if( h->param.rc.f_aq_strength == 0 ) + if( h->param.rc.f_aq_strength == 0 && h->param.rc.f_aq_offset_strength == 0 ) { int mb_xy; memset( frame->f_qp_offset, 0, h->mb.i_mb_count * sizeof(float) ); @@ -228,7 +229,9 @@ void x264_adaptive_quant_frame( x264_t * return; } - if( h->param.rc.i_aq_mode == X264_AQ_AUTOVARIANCE ) + if( h->param.rc.i_aq_mode == X264_AQ_EXPERIMENTAL ) + strength = h->param.rc.f_aq_strength * 0.5f; + else if( h->param.rc.i_aq_mode == X264_AQ_AUTOVARIANCE ) { for( mb_y = 0; mb_y < h->sps->i_mb_height; mb_y++ ) for( mb_x = 0; mb_x < h->sps->i_mb_width; mb_x++ ) @@ -241,6 +244,7 @@ void x264_adaptive_quant_frame( x264_t * } avg_adj /= h->mb.i_mb_count; strength = h->param.rc.f_aq_strength * avg_adj * (1.f / 6000.f); + avg_offset = h->param.rc.f_aq_offset_strength * (avg_adj * avg_adj - 48000.f) * (1.f / 8000.f); } else strength = h->param.rc.f_aq_strength * 1.0397f; @@ -249,10 +253,15 @@ void x264_adaptive_quant_frame( x264_t * for( mb_x = 0; mb_x < h->sps->i_mb_width; mb_x++ ) { float qp_adj; - if( h->param.rc.i_aq_mode == X264_AQ_AUTOVARIANCE ) + if( h->param.rc.i_aq_mode == X264_AQ_EXPERIMENTAL ) + { + int32_t energy = ac_energy_mb( h, mb_x, mb_y, frame ); + qp_adj = strength * (powf( energy, 0.25f ) - 14.0f); + } + else if( h->param.rc.i_aq_mode == X264_AQ_AUTOVARIANCE ) { qp_adj = frame->f_qp_offset[mb_x + mb_y*h->mb.i_mb_stride]; - qp_adj = strength * (qp_adj - avg_adj); + qp_adj = strength * (qp_adj - avg_adj) + avg_offset; } else { diff -uNrp a/x264.c b/x264.c --- a/x264.c 2009-12-05 21:34:24 +0200 +++ b/x264.c 2009-12-05 22:18:09 +0200 @@ -238,9 +238,12 @@ static void Help( x264_param_t *defaults H2( " --aq-mode AQ method [%d]\n" " - 0: Disabled\n" " - 1: Variance AQ (complexity mask)\n" - " - 2: Auto-variance AQ (experimental)\n", defaults->rc.i_aq_mode ); + " - 2: Auto-variance AQ (experimental)\n" + " - 3: New experimental AQ\n", defaults->rc.i_aq_mode ); H1( " --aq-strength Reduces blocking and blurring in flat and\n" - " textured areas. [%.1f]\n", defaults->rc.f_aq_strength ); + " textured areas. [%.1f]\n" + " (May present in #1:#2 form. Where #2 is frame QP offset.\n" + " Help with dark frames and fades. 1.0 is optimal)", defaults->rc.f_aq_strength ); H1( "\n" ); H2( " -p, --pass <1|2|3> Enable multipass ratecontrol\n" ); else H0( " -p, --pass <1|2> Enable multipass ratecontrol\n" ); diff -uNrp a/x264.h b/x264.h --- a/x264.h 2009-12-05 21:34:24 +0200 +++ b/x264.h 2009-12-05 22:18:36 +0200 @@ -92,6 +92,7 @@ typedef struct x264_t x264_t; #define X264_AQ_NONE 0 #define X264_AQ_VARIANCE 1 #define X264_AQ_AUTOVARIANCE 2 +#define X264_AQ_EXPERIMENTAL 3 #define X264_B_ADAPT_NONE 0 #define X264_B_ADAPT_FAST 1 #define X264_B_ADAPT_TRELLIS 2 @@ -286,6 +287,7 @@ typedef struct x264_param_t int i_aq_mode; /* psy adaptive QP. (X264_AQ_*) */ float f_aq_strength; + float f_aq_offset_strength; int b_mb_tree; /* Macroblock-tree ratecontrol. */ int i_lookahead;