diff -NdurwBE x264-oreaqtest2/common/common.c x264-oreaqtest3/common/common.c --- x264-oreaqtest2/common/common.c 2009-08-27 11:36:14 +0300 +++ x264-oreaqtest3/common/common.c 2009-08-27 11:07:37 +0300 @@ -94,7 +94,9 @@ param->rc.f_ip_factor = 1.4; param->rc.f_pb_factor = 1.3; param->rc.i_aq_mode = X264_AQ_VARIANCE; + param->rc.i_aq_metric = 0; param->rc.f_aq_strength = 1.0; + param->rc.f_aq_sensitivity = 10; param->rc.i_lookahead = 40; param->rc.b_stat_write = 0; @@ -576,8 +578,12 @@ p->rc.f_pb_factor = atof(value); OPT("aq-mode") p->rc.i_aq_mode = atoi(value); + OPT("aq-metric") + p->rc.i_aq_metric = atoi(value); OPT("aq-strength") p->rc.f_aq_strength = atof(value); + OPT("aq-sensitivity") + p->rc.f_aq_sensitivity = atof(value); OPT("pass") { int i = x264_clip3( atoi(value), 0, 3 ); @@ -927,7 +933,7 @@ 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 ); + s += sprintf( s, ":%d:%.2f:%.2f", p->rc.i_aq_metric, p->rc.f_aq_strength, p->rc.f_aq_sensitivity ); if( p->rc.psz_zones ) s += sprintf( s, " zones=%s", p->rc.psz_zones ); else if( p->rc.i_zones ) diff -NdurwBE x264-oreaqtest2/encoder/encoder.c x264-oreaqtest3/encoder/encoder.c --- x264-oreaqtest2/encoder/encoder.c 2009-08-27 11:36:14 +0300 +++ x264-oreaqtest3/encoder/encoder.c 2009-08-27 11:12:43 +0300 @@ -634,6 +634,9 @@ h->param.rc.f_aq_strength = x264_clip3f( h->param.rc.f_aq_strength, 0, 3 ); if( h->param.rc.f_aq_strength == 0 ) h->param.rc.i_aq_mode = 0; + if( h->param.rc.f_aq_sensitivity < 0 ) + h->param.rc.f_aq_sensitivity = 0; + h->param.rc.i_aq_metric = x264_clip3( h->param.rc.i_aq_metric, 0, 1 ); /* MB-tree requires AQ to be on, even if the strength is zero. */ if( !h->param.rc.i_aq_mode && h->param.rc.b_mb_tree ) { diff -NdurwBE x264-oreaqtest2/encoder/ratecontrol.c x264-oreaqtest3/encoder/ratecontrol.c --- x264-oreaqtest2/encoder/ratecontrol.c 2009-08-27 11:36:14 +0300 +++ x264-oreaqtest3/encoder/ratecontrol.c 2009-08-27 11:28:31 +0300 @@ -61,6 +61,8 @@ double offset; } predictor_t; +typedef int (*x264_aq_metric_t)( x264_t *h, int mb_x, int mb_y, x264_frame_t *frame ); + struct x264_ratecontrol_t { /* constants */ @@ -139,6 +141,9 @@ int bframes; /* # consecutive B-frames before this P-frame */ int bframe_bits; /* total cost of those frames */ + /* AQ stuff */ + x264_aq_metric_t aq_metric_func; + int i_zones; x264_zone_t *zones; x264_zone_t *prev_zone; @@ -202,6 +207,30 @@ return var; } +static NOINLINE int aqm_4ver0c( x264_t *h, int mb_x, int mb_y, x264_frame_t *frame ) +{ + DECLARE_ALIGNED_16( static uint8_t zero[17] ) = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}; + DECLARE_ALIGNED_16( static uint8_t avg_flat[16] ); + unsigned int var=0, sad, i; + for( i=0; i<3; i++ ) + { + int w = i ? 8 : 16; + int stride = frame->i_stride[i]; + int offset = h->mb.b_interlaced + ? w * (mb_x + (mb_y&~1) * stride) + (mb_y&1) * stride + : w * (mb_x + mb_y * stride); + int pix = i ? PIXEL_8x8 : PIXEL_16x16; + stride <<= h->mb.b_interlaced; + sad = h->pixf.sad[pix]( zero, 0, frame->plane[i]+offset, stride ); + memset( avg_flat, sad >> (i?6:8), sizeof(avg_flat) ); + var += h->pixf.ssd[pix]( avg_flat, 0, frame->plane[i]+offset, stride ); + } + var = X264_MAX(var,1); + x264_emms(); + return var; +} + + void x264_adaptive_quant_frame( x264_t *h, x264_frame_t *frame ) { /* constants chosen to result in approximately the same overall bitrate as without AQ. @@ -249,8 +278,10 @@ } else { - uint32_t energy = ac_energy_mb( h, mb_x, mb_y, frame ); - qp_adj = strength * (x264_log2( X264_MAX(energy, 1) ) - 14.427f); + uint32_t energy = h->rc->aq_metric_func( h, mb_x, mb_y, frame ); + /*qp_adj = strength * (x264_log2( X264_MAX(energy, 1) ) - 14.427f);*/ + int lz = x264_clz( energy ); + qp_adj = strength * (log2_lut[(energy<>24)&0x7f] - lz + 26.573f - h->param.rc.f_aq_sensitivity); } frame->f_qp_offset[mb_x + mb_y*h->mb.i_mb_stride] = frame->f_qp_offset_aq[mb_x + mb_y*h->mb.i_mb_stride] = qp_adj; @@ -372,6 +403,11 @@ rc->last_non_b_pict_type = -1; rc->cbr_decay = 1.0; + if(h->param.rc.i_aq_metric == 1) + rc->aq_metric_func = aqm_4ver0c; + else + rc->aq_metric_func = ac_energy_mb; + if( h->param.rc.i_rc_method == X264_RC_CRF && h->param.rc.b_stat_read ) { x264_log(h, X264_LOG_ERROR, "constant rate-factor is incompatible with 2pass.\n"); diff -NdurwBE x264-oreaqtest2/x264.c x264-oreaqtest3/x264.c --- x264-oreaqtest2/x264.c 2009-08-27 11:36:14 +0300 +++ x264-oreaqtest3/x264.c 2009-08-27 11:33:34 +0300 @@ -220,10 +220,17 @@ " - 0: Disabled\n" " - 1: Variance AQ (complexity mask)\n" " - 2: Auto-variance AQ (experimental)\n", defaults->rc.i_aq_mode ); + H0( " --aq-metric The metric used for AQ [%d]\n" + " - 0: Original GIT metric (ac_energy_mb)\n" + " - 1: BM ver.0 with correction (aqm_4ver0c)\n", defaults->rc.i_aq_metric ); H0( " --aq-strength Reduces blocking and blurring in flat and\n" " textured areas. [%.1f]\n" " - 0.5: weak AQ\n" " - 1.5: strong AQ\n", defaults->rc.f_aq_strength ); + H0( " --aq-sensitivity \"Center\" of AQ curve. [%.1f]\n" + " - 5: most QPs are raised\n" + " - 10: good general-use sensitivity\n" + " - 15: most QPs are lowered\n", defaults->rc.f_aq_sensitivity ); H0( "\n" ); H0( " -p, --pass <1|2|3> Enable multipass ratecontrol\n" " - 1: First pass, creates stats file\n" @@ -447,7 +454,9 @@ { "no-fast-pskip", no_argument, NULL, 0 }, { "no-dct-decimate", no_argument, NULL, 0 }, { "aq-strength", required_argument, NULL, 0 }, + { "aq-sensitivity", required_argument, NULL, 0 }, { "aq-mode", required_argument, NULL, 0 }, + { "aq-metric", required_argument, NULL, 0 }, { "deadzone-inter", required_argument, NULL, '0' }, { "deadzone-intra", required_argument, NULL, '0' }, { "level", required_argument, NULL, 0 }, diff -NdurwBE x264-oreaqtest2/x264.h x264-oreaqtest3/x264.h --- x264-oreaqtest2/x264.h 2009-08-27 11:36:14 +0300 +++ x264-oreaqtest3/x264.h 2009-08-27 11:34:52 +0300 @@ -277,7 +277,9 @@ float f_pb_factor; int i_aq_mode; /* psy adaptive QP. (X264_AQ_*) */ + int i_aq_metric; float f_aq_strength; + float f_aq_sensitivity; int b_mb_tree; /* Macroblock-tree ratecontrol. */ int i_lookahead;