diff --git a/common/common.c b/common/common.c index 1f01030..7237885 100644 --- a/common/common.c +++ b/common/common.c @@ -93,8 +93,18 @@ void x264_param_default( x264_param_t *param ) param->rc.i_qp_step = 4; 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_mode = X264_AQ_MIX; + param->rc.i_aq_metric = 0; param->rc.f_aq_strength = 1.0; + param->rc.f_aq_sensitivity = 10; + param->rc.f_aq_ifactor = 1.0; + param->rc.f_aq_pfactor = 1.0; + param->rc.f_aq_bfactor = 1.0; + param->rc.b_aq2 = 0; + param->rc.f_aq2_strength = 0.0; + param->rc.f_aq2_sensitivity = 15.0; + param->rc.b_aq_debug = 0; + param->rc.psz_aq_debug_name = "x264_aq_debug.aq"; param->rc.i_lookahead = 40; param->rc.b_stat_write = 0; @@ -551,8 +561,30 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value ) 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("aq-ifactor") + p->rc.f_aq_ifactor = atof(value); + OPT("aq-pfactor") + p->rc.f_aq_pfactor = atof(value); + OPT("aq-bfactor") + p->rc.f_aq_bfactor = atof(value); + OPT("aq2-strength") + { + p->rc.f_aq2_strength = atof(value); + p->rc.b_aq2 = 1; + } + OPT("aq2-sensitivity") + p->rc.f_aq2_sensitivity = atof(value); + OPT("aq-debug") + { + p->rc.b_aq_debug = 1; + p->rc.psz_aq_debug_name = strdup(value); + } OPT("pass") { int i = x264_clip3( atoi(value), 0, 3 ); @@ -897,7 +929,20 @@ char *x264_param2string( x264_param_t *p, int b_res ) 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, " aq-metric=%d", p->rc.i_aq_metric ); + s += sprintf( s, " aq-strength=%.2f", p->rc.f_aq_strength ); + s += sprintf( s, " aq-sensitivity=%.2f", p->rc.f_aq_sensitivity ); + s += sprintf( s, " aq-ifactor=%.2f", p->rc.f_aq_ifactor ); + s += sprintf( s, " aq-pfactor=%.2f", p->rc.f_aq_pfactor ); + s += sprintf( s, " aq-bfactor=%.2f", p->rc.f_aq_bfactor ); + } + s += sprintf( s, " aq2=%d", p->rc.b_aq2 ); + if( p->rc.b_aq2 ) + { + s += sprintf( s, " aq2-strength=%.2f", p->rc.f_aq2_strength ); + s += sprintf( s, " aq2-sensitivity=%.2f", p->rc.f_aq2_sensitivity ); + } if( p->rc.psz_zones ) s += sprintf( s, " zones=%s", p->rc.psz_zones ); else if( p->rc.i_zones ) diff --git a/common/frame.c b/common/frame.c index 2e5ba44..b11c362 100644 --- a/common/frame.c +++ b/common/frame.c @@ -143,6 +143,7 @@ x264_frame_t *x264_frame_new( x264_t *h ) { CHECKED_MALLOC( frame->f_qp_offset, h->mb.i_mb_count * sizeof(float) ); CHECKED_MALLOC( frame->f_qp_offset_aq, h->mb.i_mb_count * sizeof(float) ); + CHECKED_MALLOC( frame->f_aq_energy, h->mb.i_mb_count * sizeof(float) ); if( h->frames.b_have_lowres ) /* shouldn't really be initialized, just silences a valgrind false-positive in x264_mbtree_propagate_cost_sse2 */ CHECKED_MALLOCZERO( frame->i_inv_qscale_factor, (h->mb.i_mb_count+3) * sizeof(uint16_t) ); @@ -185,6 +186,7 @@ void x264_frame_delete( x264_frame_t *frame ) } x264_free( frame->f_qp_offset ); x264_free( frame->f_qp_offset_aq ); + x264_free( frame->f_aq_energy ); x264_free( frame->i_inv_qscale_factor ); x264_free( frame->i_row_bits ); x264_free( frame->i_row_qp ); diff --git a/common/frame.h b/common/frame.h index 9ca83f9..c766b3c 100644 --- a/common/frame.h +++ b/common/frame.h @@ -87,6 +87,7 @@ typedef struct int *i_row_qp; float *f_qp_offset; float *f_qp_offset_aq; + float *f_aq_energy; int b_intra_calculated; uint16_t *i_intra_cost; uint16_t *i_propagate_cost; diff --git a/common/pixel.c b/common/pixel.c index 292cdf5..2c2d9de 100644 --- a/common/pixel.c +++ b/common/pixel.c @@ -67,6 +67,14 @@ PIXEL_SAD_C( x264_pixel_sad_8x4, 8, 4 ) PIXEL_SAD_C( x264_pixel_sad_4x8, 4, 8 ) PIXEL_SAD_C( x264_pixel_sad_4x4, 4, 4 ) +static int x264_pixel_count_8x8( uint8_t *pix, int i_pix, uint32_t threshold ) +{ + int x, y, sum = 0; + for( y=0; y<8; y++, pix += i_pix ) + for( x=0; x<8; x++ ) + sum += pix[x] > (uint8_t)threshold; + return sum; +} /**************************************************************************** * pixel_ssd_WxH @@ -643,6 +651,7 @@ void x264_pixel_init( int cpu, x264_pixel_function_t *pixf ) pixf->ssim_4x4x2_core = ssim_4x4x2_core; pixf->ssim_end4 = ssim_end4; pixf->var2_8x8 = pixel_var2_8x8; + pixf->count_8x8 = x264_pixel_count_8x8; #ifdef HAVE_MMX if( cpu&X264_CPU_MMX ) diff --git a/common/pixel.h b/common/pixel.h index 53f9956..bfb178c 100644 --- a/common/pixel.h +++ b/common/pixel.h @@ -93,6 +93,8 @@ typedef struct int (*ads[7])( int enc_dc[4], uint16_t *sums, int delta, uint16_t *cost_mvx, int16_t *mvs, int width, int thresh ); + int (*count_8x8)( uint8_t *pix, int i_pix, uint32_t threshold ); + /* calculate satd or sad of V, H, and DC modes. * may be NULL, in which case just use pred+satd instead. */ void (*intra_mbcmp_x3_16x16)( uint8_t *fenc, uint8_t *fdec , int res[3] ); diff --git a/encoder/encoder.c b/encoder/encoder.c index d84457d..b429718 100644 --- a/encoder/encoder.c +++ b/encoder/encoder.c @@ -450,6 +450,7 @@ static int x264_validate_parameters( x264_t *h ) h->param.rc.i_qp_min = x264_clip3( (int)(X264_MIN3( qp_p, qp_i, qp_b )), 0, 51 ); h->param.rc.i_qp_max = x264_clip3( (int)(X264_MAX3( qp_p, qp_i, qp_b ) + .999), 0, 51 ); h->param.rc.i_aq_mode = 0; + h->param.rc.b_aq2 = 0; h->param.rc.b_mb_tree = 0; } h->param.rc.i_qp_max = x264_clip3( h->param.rc.i_qp_max, 0, 51 ); @@ -569,9 +570,21 @@ static int x264_validate_parameters( x264_t *h ) 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 ); - if( h->param.rc.f_aq_strength == 0 ) + h->param.rc.i_aq_metric = x264_clip3( h->param.rc.i_aq_metric, 0, 1 ); + h->param.rc.f_aq_strength = x264_clip3f( h->param.rc.f_aq_strength, -3, 3 ); + h->param.rc.b_aq2 = h->param.rc.b_aq2 && h->param.rc.f_aq2_strength > 0; + if( h->param.rc.f_aq_strength == 0 && ( h->param.rc.i_aq_mode == 1 ? !h->param.rc.b_aq2 : 1 ) ) 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.f_aq_ifactor = x264_clip3f( h->param.rc.f_aq_ifactor, -10, 10 ); + h->param.rc.f_aq_pfactor = x264_clip3f( h->param.rc.f_aq_pfactor, -10, 10 ); + h->param.rc.f_aq_bfactor = x264_clip3f( h->param.rc.f_aq_bfactor, -10, 10 ); + if( h->param.rc.b_aq_debug && h->param.rc.b_mb_tree ) + { + x264_log( h, X264_LOG_WARNING, "aq-debug + mb-tree is not supported\n" ); + h->param.rc.b_mb_tree = 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 ) { @@ -922,6 +935,16 @@ int x264_encoder_reconfig( x264_t *h, x264_param_t *param ) COPY( analyse.b_mixed_references ); COPY( analyse.f_psy_rd ); COPY( analyse.f_psy_trellis ); + COPY( rc.i_aq_mode ); + COPY( rc.i_aq_metric ); + COPY( rc.f_aq_strength ); + COPY( rc.f_aq_sensitivity ); + COPY( rc.f_aq_ifactor ); + COPY( rc.f_aq_pfactor ); + COPY( rc.f_aq_bfactor ); + COPY( rc.b_aq2 ); + COPY( rc.f_aq2_strength ); + COPY( rc.f_aq2_sensitivity ); // can only twiddle these if they were enabled to begin with: if( h->param.analyse.i_me_method >= X264_ME_ESA || param->analyse.i_me_method < X264_ME_ESA ) COPY( analyse.i_me_method ); diff --git a/encoder/ratecontrol.c b/encoder/ratecontrol.c index fd9aa94..c7f4e7e 100644 --- a/encoder/ratecontrol.c +++ b/encoder/ratecontrol.c @@ -61,6 +61,8 @@ typedef struct double offset; } predictor_t; +typedef uint32_t (*x264_aq_metric_t)( x264_t *h, int mb_x, int mb_y, x264_frame_t *frame ); + struct x264_ratecontrol_t { /* constants */ @@ -135,11 +137,16 @@ struct x264_ratecontrol_t int bframes; /* # consecutive B-frames before this P-frame */ int bframe_bits; /* total cost of those frames */ + /* AQ stuff */ + FILE *p_aq_debug; + void* aqlog; + int i_zones; x264_zone_t *zones; x264_zone_t *prev_zone; }; +#include "AQDebugLog.h" static int parse_zones( x264_t *h ); static int init_pass2(x264_t *); @@ -198,6 +205,39 @@ static NOINLINE uint32_t ac_energy_mb( x264_t *h, int mb_x, int mb_y, x264_frame return var; } +static NOINLINE uint32_t aqm_mod( x264_t *h, int mb_x, int mb_y, x264_frame_t *frame ) +{ + /* FIXME: This array is larger than necessary because a bug in GCC causes an all-zero + * array to be placed in .bss despite .bss not being correctly aligned on some platforms (win32?) */ + ALIGNED_16( static uint8_t zero[17] ) = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}; + ALIGNED_16( static uint8_t avg_flat[16] ); + uint32_t 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 ); + } + x264_emms(); + return var; +} + +static int x264_sum_dctq( int16_t dct[8][8] ) +{ + int i, t = 0; + int16_t *p = &dct[0][0]; + for( i=1; i<64; i++ ) + t += abs(p[i]) * x264_dct8_weight_tab[i]; + return t; +} + 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. @@ -205,24 +245,32 @@ void x264_adaptive_quant_frame( x264_t *h, x264_frame_t *frame ) int mb_x, mb_y; float strength; float avg_adj = 0.f; + x264_aq_metric_t aq_metric_func; + /* Need to init it anyways for MB tree. */ if( h->param.rc.f_aq_strength == 0 ) { int mb_xy; memset( frame->f_qp_offset, 0, h->mb.i_mb_count * sizeof(float) ); memset( frame->f_qp_offset_aq, 0, h->mb.i_mb_count * sizeof(float) ); + memset( frame->f_aq_energy, 0, h->mb.i_mb_count * sizeof(float) ); if( h->frames.b_have_lowres ) for( mb_xy = 0; mb_xy < h->mb.i_mb_count; mb_xy++ ) frame->i_inv_qscale_factor[mb_xy] = 256; return; } + if( h->param.rc.i_aq_metric == 0 ) + aq_metric_func = ac_energy_mb; + else + aq_metric_func = aqm_mod; + 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++ ) { - uint32_t energy = ac_energy_mb( h, mb_x, mb_y, frame ); + uint32_t energy = aq_metric_func( h, mb_x, mb_y, frame ); float qp_adj = x264_log2( energy + 2 ); qp_adj *= qp_adj; frame->f_qp_offset[mb_x + mb_y*h->mb.i_mb_stride] = qp_adj; @@ -245,8 +293,10 @@ void x264_adaptive_quant_frame( x264_t *h, x264_frame_t *frame ) } 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 = aq_metric_func( h, mb_x, mb_y, frame ); + float f_aq_energy = x264_log2( X264_MAX(energy, 1) ) - 4.427f; + qp_adj = strength * (f_aq_energy - h->param.rc.f_aq_sensitivity); + frame->f_aq_energy[mb_x + mb_y*h->mb.i_mb_stride] = f_aq_energy; } 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; @@ -257,6 +307,71 @@ void x264_adaptive_quant_frame( x264_t *h, x264_frame_t *frame ) /***************************************************************************** + * x264_adaptive_quant: + * check if mb is "flat", i.e. has most energy in low frequency components, and + * adjust qp down if it is + *****************************************************************************/ +float x264_haali_adaptive_quant( x264_t *h, float *_energy ) +{ + ALIGNED_16( static uint8_t zero[FDEC_STRIDE*8] ); + ALIGNED_16( int16_t dct[8][8] ); + float fc, qp_adj; + int total = 0; + int new_qp; + int i; + + if( h->mb.i_qp <= 10 ) /* AQ is probably not needed at such low QP */ + { + *_energy = 0.0; + return 0; + } + + if( h->pixf.sad[PIXEL_16x16](h->mb.pic.p_fenc[0], FENC_STRIDE, zero, 16) > 64*16*16 ) + { /* light places */ + if( h->pixf.count_8x8(h->mb.pic.p_fenc[1], FENC_STRIDE, 0x81818181) < 40 ) + { + /* not enough "blue" pixels */ + x264_emms(); + *_energy = 0.0; + return 0; + } + + if( h->pixf.count_8x8(h->mb.pic.p_fenc[2], FENC_STRIDE, 0x87878787) > 24 ) + { + /* too many "red" pixels */ + x264_emms(); + *_energy = 0.0; + return 0; + } + } + + for( i=0; i<4; i++ ) + { + h->dctf.sub8x8_dct8( dct, h->mb.pic.p_fenc[0] + (i&1)*8 + (i>>1)*FENC_STRIDE, zero ); + total += x264_sum_dctq( dct ); + } + + x264_emms(); + *_energy = 0.0; + + if( total == 0 ) /* no AC coefficients, nothing to do */ + return 0; + + *_energy = fc = expf(-5e-13 * total * total); + + /* the function is chosen such that it stays close to 0 in almost all + * range of 0..1, and rapidly goes up to 1 near 1.0 */ + qp_adj = (h->rc->f_qpm * h->param.rc.f_aq2_strength / pow(2 - fc, h->param.rc.f_aq2_sensitivity)); + + /* don't adjust by more than this amount */ + qp_adj = X264_MIN(qp_adj, h->rc->f_qpm/2.0); + + new_qp = x264_clip3( h->rc->f_qpm - qp_adj, h->param.rc.i_qp_min, h->param.rc.i_qp_max); + + return (new_qp - h->rc->f_qpm); +} + +/***************************************************************************** * x264_adaptive_quant: * adjust macroblock QP based on variance (AC energy) of the MB. * high variance = higher QP @@ -265,8 +380,58 @@ void x264_adaptive_quant_frame( x264_t *h, x264_frame_t *frame ) *****************************************************************************/ void x264_adaptive_quant( x264_t *h ) { + float vaq_adj; + float haq_adj; + float vaq_energy; + float haq_energy; + float qp_adj; + float factor; x264_emms(); - h->mb.i_qp = x264_clip3( h->rc->f_qpm + h->fenc->f_qp_offset[h->mb.i_mb_xy] + .5, h->param.rc.i_qp_min, h->param.rc.i_qp_max ); + + if( h->sh.i_type == SLICE_TYPE_I ) + factor = h->param.rc.f_aq_ifactor; + else if( h->sh.i_type == SLICE_TYPE_P ) + factor = h->param.rc.f_aq_pfactor; + else if( h->sh.i_type == SLICE_TYPE_B ) + factor = h->param.rc.f_aq_bfactor; + else + factor = 1.0; + + if( h->param.rc.i_aq_mode == X264_AQ_MIX ) + { + // VAQ、ホシツケヤ + vaq_adj = h->fenc->f_qp_offset[h->mb.i_mb_xy]; + vaq_energy = h->fenc->f_aq_energy[h->mb.i_mb_xy]; + // HAQ、ホシツケヤ + if( h->param.rc.b_aq2 ) + { + haq_adj = x264_haali_adaptive_quant( h, &haq_energy ); + } + else + { + haq_adj = 0.0; + haq_energy = 0.0; + } + + if(h->param.rc.b_aq_debug) + x264_write_aqlog_body( h, h->mb.i_mb_xy, h->fenc, h->param.rc.i_aq_mode, h->param.rc.b_aq2, vaq_energy, haq_energy ); + + if(vaq_adj >= 0.0) + qp_adj = vaq_adj + haq_adj; + else + qp_adj = X264_MIN( vaq_adj, haq_adj ); + } + else if( h->param.rc.i_aq_mode == X264_AQ_AUTOVARIANCE ) + { + // AutoVAQ、ホキ・フシ霹タ + qp_adj = h->fenc->f_qp_offset[h->mb.i_mb_xy]; + } + else + { + qp_adj = 0; + } + + h->mb.i_qp = x264_clip3( h->rc->f_qpm + factor * qp_adj + .5, h->param.rc.i_qp_min, h->param.rc.i_qp_max ); } int x264_macroblock_tree_read( x264_t *h, x264_frame_t *frame ) @@ -293,6 +458,8 @@ int x264_macroblock_tree_read( x264_t *h, x264_frame_t *frame ) for( i = 0; i < h->mb.i_mb_count; i++ ) frame->f_qp_offset[i] = ((float)(int16_t)endian_fix16( rc->qp_buffer[i] )) * (1/256.0); + + memset( frame->f_aq_energy, 0, h->mb.i_mb_count * sizeof(float) ); } else x264_adaptive_quant_frame( h, frame ); @@ -665,6 +832,20 @@ int x264_ratecontrol_new( x264_t *h ) if( h->param.rc.b_mb_tree && (h->param.rc.b_stat_read || h->param.rc.b_stat_write) ) CHECKED_MALLOC( rc->qp_buffer, h->mb.i_mb_count * sizeof(uint16_t) ); + /* Open AQ Log file */ + if( h->param.rc.b_aq_debug ) + { + rc->p_aq_debug = fopen( h->param.rc.psz_aq_debug_name, "wb" ); + if( rc->p_aq_debug == NULL ) + { + x264_log(h, X264_LOG_ERROR, "ratecontrol_init: can't open AQ debug file\n"); + return -1; + } + setvbuf( rc->p_aq_debug, NULL, _IOFBF, 1024*1024*8 ); // 8M Buffer + x264_write_aqlog_header( h, "MixAQ03", h->param.rc.i_aq_metric, + h->param.rc.f_aq_strength, h->param.rc.f_aq2_strength, h->param.rc.f_aq_sensitivity, h->param.rc.f_aq2_sensitivity ); + } + for( i=0; iparam.i_threads; i++ ) { h->thread[i]->rc = rc+i; @@ -855,6 +1036,8 @@ void x264_ratecontrol_delete( x264_t *h ) rc->zones[i].param->param_free( rc->zones[i].param ); x264_free( rc->zones ); } + if( rc->p_aq_debug ) + fclose( rc->p_aq_debug ); x264_free( rc ); } diff --git a/x264.c b/x264.c index 32e6570..2dcd35f 100644 --- a/x264.c +++ b/x264.c @@ -222,6 +222,20 @@ static void Help( x264_param_t *defaults, int b_longhelp ) " 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 ); + H1( " --aq-ifactor AQ strength factor of I-frames [%.2f]\n", defaults->rc.f_aq_ifactor ); + H1( " --aq-pfactor AQ strength factor of P-frames [%.2f]\n", defaults->rc.f_aq_pfactor ); + H1( " --aq-bfactor AQ strength factor of B-frames [%.2f]\n", defaults->rc.f_aq_bfactor ); + H0( " --aq2-strength Use 2nd AQ (Haali's AQ) algorithm for support. [%.1f]\n" + " 0.0: no 2nd AQ\n" + " 1.1: strong 2nd AQ\n", defaults->rc.f_aq2_strength ); + H0( " --aq2-sensitivity \"Flatness\" threshold to trigger 2nd AQ [%.1f]\n" + " 5: applies to almost all blocks\n" + " 22: only flat blocks\n", defaults->rc.f_aq2_sensitivity ); + H0( " --aq-debug Filename for AQ debug log [\"%s\"]\n", defaults->rc.psz_aq_debug_name ); H0( "\n" ); H0( " -p, --pass <1|2|3> Enable multipass ratecontrol\n" " - 1: First pass, creates stats file\n" @@ -438,7 +452,15 @@ static struct option long_options[] = { "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-ifactor", required_argument, NULL, 0 }, + { "aq-pfactor", required_argument, NULL, 0 }, + { "aq-bfactor", required_argument, NULL, 0 }, { "aq-mode", required_argument, NULL, 0 }, + { "aq-metric", required_argument, NULL, 0 }, + { "aq2-strength", required_argument, NULL, 0 }, + { "aq2-sensitivity", required_argument, NULL, 0 }, + { "aq-debug", required_argument, NULL, 0 }, { "deadzone-inter", required_argument, NULL, '0' }, { "deadzone-intra", required_argument, NULL, '0' }, { "level", required_argument, NULL, 0 }, diff --git a/x264.h b/x264.h index 7fa508d..e963a16 100644 --- a/x264.h +++ b/x264.h @@ -36,6 +36,7 @@ #include #define X264_BUILD 72 +#define X264_SUB_BUILD 1 // MixAQ /* x264_t: * opaque handler for encoder */ @@ -90,7 +91,7 @@ typedef struct x264_t x264_t; #define X264_RC_CRF 1 #define X264_RC_ABR 2 #define X264_AQ_NONE 0 -#define X264_AQ_VARIANCE 1 +#define X264_AQ_MIX 1 #define X264_AQ_AUTOVARIANCE 2 #define X264_B_ADAPT_NONE 0 #define X264_B_ADAPT_FAST 1 @@ -274,7 +275,17 @@ typedef struct x264_param_t 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; + float f_aq_ifactor; + float f_aq_pfactor; + float f_aq_bfactor; + int b_aq2; /* psy 2nd adaptive QP */ + float f_aq2_strength; + float f_aq2_sensitivity; + int b_aq_debug; + char *psz_aq_debug_name; int b_mb_tree; /* Macroblock-tree ratecontrol. */ int i_lookahead;