diff options
-rw-r--r-- | contrib/Jamfile | 2 | ||||
-rw-r--r-- | contrib/patch-x264-aq.patch | 430 |
2 files changed, 251 insertions, 181 deletions
diff --git a/contrib/Jamfile b/contrib/Jamfile index 262ed0b0c..06cb557ec 100644 --- a/contrib/Jamfile +++ b/contrib/Jamfile @@ -348,7 +348,7 @@ rule LibX264 { LIBX264_PATCH += " $(PATCH) -p1 < ../patch-x264-solaris.patch && " ; } - # AQ is temporarily disabled LIBX264_PATCH += "$(PATCH) -p0 < ../patch-x264-aq.patch && " ; + LIBX264_PATCH += "$(PATCH) -p0 < ../patch-x264-aq.patch && " ; LIBX264_PATCH += "$(PATCH) -p0 < ../patch-x264-idr.patch && " ; LIBX264_PATCH += "$(PATCH) -p0 < ../patch-x264-vbv-1pass.patch && " ; LIBX264_PATCH += "$(PATCH) -p0 < ../patch-x264-vbv-2pass.patch && " ; diff --git a/contrib/patch-x264-aq.patch b/contrib/patch-x264-aq.patch index ec624ee4d..79d8dca54 100644 --- a/contrib/patch-x264-aq.patch +++ b/contrib/patch-x264-aq.patch @@ -1,210 +1,241 @@ -Index: common/common.c
-===================================================================
---- common/common.c (revision 669)
-+++ common/common.c (working copy)
-@@ -123,6 +123,9 @@
- param->analyse.i_chroma_qp_offset = 0; - param->analyse.b_fast_pskip = 1; - param->analyse.b_dct_decimate = 1; -+ param->analyse.b_aq = 0; -+ param->analyse.f_aq_strength = 0.0; -+ param->analyse.f_aq_sensitivity = 15; - param->analyse.i_luma_deadzone[0] = 21; - param->analyse.i_luma_deadzone[1] = 11; - param->analyse.b_psnr = 1; -@@ -455,6 +458,13 @@
- p->analyse.b_fast_pskip = atobool(value); - OPT("dct-decimate") - p->analyse.b_dct_decimate = atobool(value); -+ OPT("aq-strength") -+ { -+ p->analyse.f_aq_strength = atof(value); -+ p->analyse.b_aq = (p->analyse.f_aq_strength > 0.0); -+ } -+ OPT("aq-sensitivity") -+ p->analyse.f_aq_sensitivity = atof(value); - OPT("deadzone-inter") - p->analyse.i_luma_deadzone[0] = atoi(value); - OPT("deadzone-intra") -@@ -939,6 +949,9 @@
- s += sprintf( s, " zones" ); - } +Index: encoder/ratecontrol.h +=================================================================== +--- encoder/ratecontrol.h (revision 736) ++++ encoder/ratecontrol.h (working copy) +@@ -34,6 +34,7 @@ + int x264_ratecontrol_qp( x264_t * ); + void x264_ratecontrol_end( x264_t *, int bits ); + void x264_ratecontrol_summary( x264_t * ); ++void x264_adaptive_quant ( x264_t * ); -+ if( p->analyse.b_aq ) -+ s += sprintf( s, " aq=1:%.1f:%.1f", p->analyse.f_aq_strength, p->analyse.f_aq_sensitivity ); -+ - return buf; - } - -Index: common/pixel.c
-===================================================================
---- common/pixel.c (revision 669)
-+++ common/pixel.c (working copy)
-@@ -213,6 +213,14 @@
- PIXEL_SATD_C( x264_pixel_satd_4x8, 4, 8 ) - PIXEL_SATD_C( x264_pixel_satd_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; -+} + #endif - /**************************************************************************** - * pixel_sa8d_WxH: sum of 8x8 Hadamard transformed differences -@@ -470,6 +478,8 @@
- pixf->ads[PIXEL_16x8] = pixel_ads2; - pixf->ads[PIXEL_8x8] = pixel_ads1; +Index: encoder/encoder.c +=================================================================== +--- encoder/encoder.c (revision 736) ++++ encoder/encoder.c (working copy) +@@ -401,6 +401,7 @@ + h->param.analyse.b_fast_pskip = 0; + h->param.analyse.i_noise_reduction = 0; + h->param.analyse.i_subpel_refine = x264_clip3( h->param.analyse.i_subpel_refine, 1, 6 ); ++ h->param.analyse.b_aq = 0; + } + if( h->param.rc.i_rc_method == X264_RC_CQP ) + { +@@ -475,6 +476,10 @@ + if( !h->param.b_cabac ) + h->param.analyse.i_trellis = 0; + h->param.analyse.i_trellis = x264_clip3( h->param.analyse.i_trellis, 0, 2 ); ++ h->param.analyse.b_aq = h->param.analyse.b_aq && h->param.analyse.f_aq_strength > 0; ++ /* VAQ on static sensitivity mode effectively replaces qcomp, so qcomp is raised towards 1 to compensate. */ ++ if(h->param.analyse.b_aq && h->param.analyse.f_aq_sensitivity != 0) ++ h->param.rc.f_qcompress = x264_clip3f(h->param.rc.f_qcompress + h->param.analyse.f_aq_strength * 0.4 / 0.28, 0, 1); + h->param.analyse.i_noise_reduction = x264_clip3( h->param.analyse.i_noise_reduction, 0, 1<<16 ); -+ pixf->count_8x8 = x264_pixel_count_8x8; -+ - #ifdef HAVE_MMX - if( cpu&X264_CPU_MMX ) { -Index: common/pixel.h
-===================================================================
---- common/pixel.h (revision 669)
-+++ common/pixel.h (working copy)
-@@ -90,6 +90,8 @@
- void (*ads[7])( int enc_dc[4], uint16_t *sums, int delta, - uint16_t *res, int width ); - -+ int (*count_8x8)( uint8_t *pix, int i_pix, uint32_t threshold ); -+ - /* calculate satd of V, H, and DC modes. - * may be NULL, in which case just use pred+satd instead. */ - void (*intra_satd_x3_16x16)( uint8_t *fenc, uint8_t *fdec, int res[3] ); -Index: encoder/analyse.c
-===================================================================
---- encoder/analyse.c (revision 669)
-+++ encoder/analyse.c (working copy)
-@@ -29,6 +29,7 @@
- #endif +Index: encoder/ratecontrol.c +=================================================================== +--- encoder/ratecontrol.c (revision 736) ++++ encoder/ratecontrol.c (working copy) +@@ -127,6 +127,10 @@ + predictor_t *pred_b_from_p; /* predict B-frame size from P-frame satd */ + int bframes; /* # consecutive B-frames before this P-frame */ + int bframe_bits; /* total cost of those frames */ ++ ++ /* AQ stuff */ ++ float aq_threshold; ++ int *ac_energy; - #include "common/common.h" -+#include "common/cpu.h" - #include "macroblock.h" - #include "me.h" - #include "ratecontrol.h" -@@ -2029,8 +2030,68 @@
- } + int i_zones; + x264_zone_t *zones; +@@ -169,7 +173,97 @@ + + rce->misc_bits; } -+static int x264_sum_dctq( int16_t dct[8][8] ) ++// Find the total AC energy of the block in all planes. ++static int ac_energy_mb( x264_t *h, int mb_x, int mb_y, int *satd ) +{ -+ 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; ++ DECLARE_ALIGNED( static uint8_t, flat[16], 16 ) = {128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128}; ++// DECLARE_ALIGNED( static uint8_t, flat[16], 16 ); ++ unsigned int var=0, sad, ssd, i; ++ for( i=0; i<3; i++ ) ++ { ++ int w = i ? 8 : 16; ++ int stride = h->fenc->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](flat, 0, h->fenc->plane[i]+offset, stride); ++ ssd = h->pixf.ssd[pix](flat, 0, h->fenc->plane[i]+offset, stride); ++ var += ssd - (sad * sad >> (i?6:8)); ++ // SATD to represent the block's overall complexity (bit cost) for intra encoding. ++ // exclude the DC coef, because nothing short of an actual intra prediction will estimate DC cost. ++ if( var && satd ) ++ *satd += h->pixf.satd[pix](flat, 0, h->fenc->plane[i]+offset, stride) - sad/2; ++ } ++ return var; ++} ++ ++void x264_autosense_aq( x264_t *h ) ++{ ++ double total = 0; ++ double n = 0; ++ int mb_x, mb_y; ++ /* FIXME: Some of the SATDs might be already calculated elsewhere (ratecontrol?). Can we reuse them? */ ++ /* FIXME: Is chroma SATD necessary? */ ++ 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++ ) ++ { ++ int energy, satd=0; ++ energy = ac_energy_mb( h, mb_x, mb_y, &satd ); ++ h->rc->ac_energy[mb_x + mb_y * h->sps->i_mb_width] = energy; ++ /* Weight the energy value by the SATD value of the MB. This represents the fact that ++ the more complex blocks in a frame should be weighted more when calculating the optimal sensitivity. ++ This also helps diminish the negative effect of large numbers of simple blocks in a frame, such as in the case ++ of a letterboxed film. */ ++ if( energy ) ++ { ++ x264_cpu_restore(h->param.cpu); ++ total += logf(energy) * satd; ++ n += satd; ++ } ++ } ++ x264_cpu_restore(h->param.cpu); ++ /* Calculate and store the threshold. */ ++ h->rc->aq_threshold = n ? total/n : 15; +} - /***************************************************************************** -+ * x264_adaptive_quant: -+ * check if mb is "flat", i.e. has most energy in low frequency components, and -+ * adjust qp down if it is -+ *****************************************************************************/ -+void x264_adaptive_quant( x264_t *h, x264_mb_analysis_t *a ) ++/***************************************************************************** ++* x264_adaptive_quant: ++ * adjust macroblock QP based on variance (AC energy) of the MB. ++ * high variance = higher QP ++ * low variance = lower QP ++ * This generally increases SSIM and lowers PSNR. ++*****************************************************************************/ ++void x264_adaptive_quant( x264_t *h ) +{ -+ DECLARE_ALIGNED( static uint8_t, zero[FDEC_STRIDE*8], 16 ); -+ DECLARE_ALIGNED( int16_t, dct[8][8], 16 ); -+ float fc; -+ int total = 0; -+ int qp = h->mb.i_qp, qp_adj; -+ int i; -+ -+ if( qp <= 10 ) /* AQ is probably not needed at such low QP */ -+ return; -+ -+ 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 */ -+ return; -+ -+ if( h->pixf.count_8x8(h->mb.pic.p_fenc[2], FENC_STRIDE, 0x87878787) > 24 ) -+ /* too many "red" pixels */ -+ return; ++ int qp = h->mb.i_qp; ++ int energy; ++ x264_cpu_restore(h->param.cpu); ++ if(h->param.analyse.f_aq_sensitivity != 0) ++ energy = ac_energy_mb( h, h->mb.i_mb_x, h->mb.i_mb_y, NULL ); ++ else ++ energy = h->rc->ac_energy[h->mb.i_mb_xy]; ++ if(energy == 0) ++ { ++ h->mb.i_qp = h->mb.i_last_qp; + } -+ -+ for( i=0; i<4; i++ ) ++ else + { -+ 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_cpu_restore(h->param.cpu); ++ float result = energy; ++ /* Adjust the QP based on the AC energy of the macroblock. */ ++ float qp_adj = 3 * (logf(result) - h->rc->aq_threshold); ++ if(h->param.analyse.f_aq_sensitivity == 0) qp_adj = x264_clip3f(qp_adj, -5, 5); ++ int new_qp = x264_clip3(qp + qp_adj * h->param.analyse.f_aq_strength + .5, h->param.rc.i_qp_min, h->param.rc.i_qp_max); ++ /* If the QP of this MB is within 1 of the previous MB, code the same QP as the previous MB, ++ * to lower the bit cost of the qp_delta. */ ++ if(abs(new_qp - h->mb.i_last_qp) == 1) new_qp = h->mb.i_last_qp; ++ h->mb.i_qp = new_qp; + } -+ -+ if( total == 0 ) /* no AC coefficients, nothing to do */ -+ return; -+ -+ x264_cpu_restore( h->param.cpu ); -+ -+ 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 = (int)(qp * h->param.analyse.f_aq_strength / pow(2 - fc, h->param.analyse.f_aq_sensitivity)); -+ -+ /* don't adjust by more than this amount */ -+ qp_adj = X264_MIN(qp_adj, qp/2); -+ -+ h->mb.i_qp = a->i_qp = qp - qp_adj; + h->mb.i_chroma_qp = i_chroma_qp_table[x264_clip3( h->mb.i_qp + h->pps->i_chroma_qp_index_offset, 0, 51 )]; +} + -+/***************************************************************************** - * x264_macroblock_analyse: - *****************************************************************************/ - void x264_macroblock_analyse( x264_t *h ) -@@ -2038,9 +2099,14 @@
- x264_mb_analysis_t analysis; + int x264_ratecontrol_new( x264_t *h ) + { + x264_ratecontrol_t *rc; +@@ -244,7 +338,7 @@ + rc->rate_tolerance = 0.01; + } + +- h->mb.b_variable_qp = rc->b_vbv && !rc->b_2pass; ++ h->mb.b_variable_qp = (rc->b_vbv && !rc->b_2pass) || h->param.analyse.b_aq; + + if( rc->b_abr ) + { +@@ -458,10 +552,13 @@ + x264_free( p ); + } + +- for( i=1; i<h->param.i_threads; i++ ) ++ for( i=0; i<h->param.i_threads; i++ ) + { + h->thread[i]->rc = rc+i; +- rc[i] = rc[0]; ++ if( i ) ++ rc[i] = rc[0]; ++ if( h->param.analyse.b_aq ) ++ rc[i].ac_energy = x264_malloc( h->mb.i_mb_count * sizeof(int) ); + } + + return 0; +@@ -623,6 +720,8 @@ + x264_free( rc->zones[i].param ); + x264_free( rc->zones ); + } ++ for( i=0; i<h->param.i_threads; i++ ) ++ x264_free( rc[i].ac_energy ); + x264_free( rc ); + } + +@@ -729,6 +828,15 @@ + + if( h->sh.i_type != SLICE_TYPE_B ) + rc->last_non_b_pict_type = h->sh.i_type; ++ ++ /* Adaptive AQ sensitivity algorithm. */ ++ if( h->param.analyse.b_aq ) ++ { ++ if( h->param.analyse.f_aq_sensitivity > 0 ) ++ h->rc->aq_threshold = logf(powf(h->param.analyse.f_aq_sensitivity,4)/2); //FIXME simplify ++ else ++ x264_autosense_aq(h); ++ } + } + + double predict_row_size( x264_t *h, int y, int qp ) +Index: encoder/analyse.c +=================================================================== +--- encoder/analyse.c (revision 736) ++++ encoder/analyse.c (working copy) +@@ -2047,8 +2047,13 @@ int i_cost = COST_MAX; int i; -+ -+ h->mb.i_qp = x264_ratecontrol_qp( h ); -+ if( h->param.analyse.b_aq ) -+ x264_adaptive_quant( h, &analysis ); -+ - /* init analysis */ +- /* init analysis */ - x264_mb_analyse_init( h, &analysis, x264_ratecontrol_qp( h ) ); ++ h->mb.i_qp = x264_ratecontrol_qp( h ); ++ ++ if( h->param.analyse.b_aq ) ++ x264_adaptive_quant( h ); ++ ++ /* init analysis */ + x264_mb_analyse_init( h, &analysis, h->mb.i_qp ); /*--------------------------- Do the analysis ---------------------------*/ if( h->sh.i_type == SLICE_TYPE_I ) -Index: encoder/encoder.c
-===================================================================
---- encoder/encoder.c (revision 669)
-+++ encoder/encoder.c (working copy)
-@@ -477,6 +477,8 @@
- if( !h->param.b_cabac ) - h->param.analyse.i_trellis = 0; - h->param.analyse.i_trellis = x264_clip3( h->param.analyse.i_trellis, 0, 2 ); -+ if( h->param.analyse.b_aq && h->param.analyse.f_aq_strength <= 0 ) -+ h->param.analyse.b_aq = 0; - h->param.analyse.i_noise_reduction = x264_clip3( h->param.analyse.i_noise_reduction, 0, 1<<16 ); - - { -Index: x264.c
-===================================================================
---- x264.c (revision 669)
-+++ x264.c (working copy)
-@@ -243,6 +243,12 @@
+Index: x264.c +=================================================================== +--- x264.c (revision 736) ++++ x264.c (working copy) +@@ -244,6 +244,14 @@ " - 2: enabled on all mode decisions\n", defaults->analyse.i_trellis ); H0( " --no-fast-pskip Disables early SKIP detection on P-frames\n" ); H0( " --no-dct-decimate Disables coefficient thresholding on P-frames\n" ); -+ H0( " --aq-strength <float> Amount to adjust QP per MB [%.1f]\n" ++ H0( " --aq-strength <float> Amount to adjust QP/lambda per MB [%.1f]\n" + " 0.0: no AQ\n" -+ " 1.1: strong AQ\n", defaults->analyse.f_aq_strength ); -+ H0( " --aq-sensitivity <float> \"Flatness\" threshold to trigger AQ [%.1f]\n" -+ " 5: applies to almost all blocks\n" -+ " 22: only flat blocks\n", defaults->analyse.f_aq_sensitivity ); ++ " 1.0: medium AQ\n", defaults->analyse.f_aq_strength ); ++ H0( " --aq-sensitivity <float> \"Center\" of AQ curve. [%.1f]\n" ++ " 0: automatic sensitivity (avoids moving bits between frames)\n" ++ " 10: most QPs are raised\n" ++ " 20: good general-use sensitivity\n" ++ " 30: most QPs are lowered\n", defaults->analyse.f_aq_sensitivity ); H0( " --nr <integer> Noise reduction [%d]\n", defaults->analyse.i_noise_reduction ); H1( "\n" ); H1( " --deadzone-inter <int> Set the size of the inter luma quantization deadzone [%d]\n", defaults->analyse.i_luma_deadzone[0] ); -@@ -406,6 +412,8 @@
+@@ -407,6 +415,8 @@ { "trellis", required_argument, NULL, 't' }, { "no-fast-pskip", no_argument, NULL, 0 }, { "no-dct-decimate", no_argument, NULL, 0 }, @@ -213,11 +244,50 @@ Index: x264.c { "deadzone-inter", required_argument, NULL, '0' }, { "deadzone-intra", required_argument, NULL, '0' }, { "level", required_argument, NULL, 0 }, -Index: x264.h
-===================================================================
---- x264.h (revision 669)
-+++ x264.h (working copy)
-@@ -227,6 +227,9 @@
+Index: common/common.c +=================================================================== +--- common/common.c (revision 736) ++++ common/common.c (working copy) +@@ -123,6 +123,9 @@ + param->analyse.i_chroma_qp_offset = 0; + param->analyse.b_fast_pskip = 1; + param->analyse.b_dct_decimate = 1; ++ param->analyse.b_aq = 1; ++ param->analyse.f_aq_strength = 0.5; ++ param->analyse.f_aq_sensitivity = 13; + param->analyse.i_luma_deadzone[0] = 21; + param->analyse.i_luma_deadzone[1] = 11; + param->analyse.b_psnr = 1; +@@ -455,6 +458,13 @@ + p->analyse.b_fast_pskip = atobool(value); + OPT("dct-decimate") + p->analyse.b_dct_decimate = atobool(value); ++ OPT("aq-strength") ++ { ++ p->analyse.f_aq_strength = atof(value); ++ p->analyse.b_aq = 1; ++ } ++ OPT("aq-sensitivity") ++ p->analyse.f_aq_sensitivity = atof(value); + OPT("deadzone-inter") + p->analyse.i_luma_deadzone[0] = atoi(value); + OPT("deadzone-intra") +@@ -883,6 +893,10 @@ + s += sprintf( s, " ip_ratio=%.2f", p->rc.f_ip_factor ); + if( p->i_bframe ) + s += sprintf( s, " pb_ratio=%.2f", p->rc.f_pb_factor ); ++ if( p->analyse.b_aq ) ++ s += sprintf( s, " aq=1:%.1f:%.1f", p->analyse.f_aq_strength, p->analyse.f_aq_sensitivity ); ++ else ++ s += sprintf( s, " aq=0" ); + if( p->rc.psz_zones ) + s += sprintf( s, " zones=%s", p->rc.psz_zones ); + else if( p->rc.i_zones ) +Index: x264.h +=================================================================== +--- x264.h (revision 736) ++++ x264.h (working copy) +@@ -232,6 +232,9 @@ int i_trellis; /* trellis RD quantization */ int b_fast_pskip; /* early SKIP detection on P-frames */ int b_dct_decimate; /* transform coefficient thresholding on P-frames */ |