diff --git a/common/common.c b/common/common.c index 4617387..d24835e 100644 --- a/common/common.c +++ b/common/common.c @@ -99,6 +99,7 @@ void x264_param_default( x264_param_t *param ) 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; @@ -569,7 +570,20 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value ) 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 ); @@ -921,6 +935,8 @@ char *x264_param2string( x264_param_t *p, int b_res ) 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.i_aq_mode == X264_AQ_AUTOVARIANCE && 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 --git a/encoder/encoder.c b/encoder/encoder.c index b797a38..541dcbb 100644 --- a/encoder/encoder.c +++ b/encoder/encoder.c @@ -595,13 +595,15 @@ static int x264_validate_parameters( x264_t *h ) 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 ); - if( h->param.rc.f_aq_strength == 0 ) + 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 ) h->param.rc.i_aq_mode = 0; /* 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 ) { 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.b_bframe_pyramid ) { diff --git a/encoder/ratecontrol.c b/encoder/ratecontrol.c index 12c6fc5..85ee705 100644 --- a/encoder/ratecontrol.c +++ b/encoder/ratecontrol.c @@ -203,8 +203,9 @@ void x264_adaptive_quant_frame( x264_t *h, x264_frame_t *frame ) int mb_x, mb_y; float strength; float avg_adj = 0.f; + float avg_offset = 0.f; /* 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,6 +229,7 @@ void x264_adaptive_quant_frame( x264_t *h, x264_frame_t *frame ) } 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; @@ -239,7 +241,7 @@ void x264_adaptive_quant_frame( x264_t *h, x264_frame_t *frame ) 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 --git a/x264.h b/x264.h index 66f4f28..aeacc09 100644 --- a/x264.h +++ b/x264.h @@ -277,6 +277,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;