All pastes #1547857 Raw Edit

x264_OreAQ12_r1240.diff

public diff v1 · immutable
#1547857 ·published 2009-08-30 01:53 UTC
rendered paste body
diff --git a/common/common.c b/common/common.cindex 1f01030..5d3db7c 100644--- a/common/common.c+++ b/common/common.c@@ -93,8 +93,29 @@ 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.f_aq_strength = 1.0;+    param->rc.i_aq_mode = X264_AQ_ORE;+    param->rc.i_aq_metric = 0;+    param->rc.f_aq_strength = 0.5;+    param->rc.f_aq_strength_up[0] = 0;+    param->rc.f_aq_strength_up[1] = 0;+    param->rc.f_aq_strength_up[2] = 0;+    param->rc.f_aq_strength_up[3] = 0;+    param->rc.f_aq_strength_down[0] = 0;+    param->rc.f_aq_strength_down[1] = 0;+    param->rc.f_aq_strength_down[2] = 0;+    param->rc.f_aq_strength_down[3] = 0;+    param->rc.f_aq_sensitivity = 10;+    param->rc.f_aq_ifactor[0] = 1.0;+    param->rc.f_aq_ifactor[1] = 1.0;+    param->rc.f_aq_pfactor[0] = 1.0;+    param->rc.f_aq_pfactor[1] = 1.0;+    param->rc.f_aq_bfactor[0] = 1.0;+    param->rc.f_aq_bfactor[1] = 1.0;+    param->rc.b_aq_boundary = 0;+    param->rc.i_aq_boundary[0] = 192;+    param->rc.i_aq_boundary[1] = 64;+    param->rc.i_aq_boundary[2] = 24;+    param->rc.b_aq_debug = 0;     param->rc.i_lookahead = 40;      param->rc.b_stat_write = 0;@@ -551,8 +572,93 @@ 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);+    {+        if( 7 == sscanf( value, "%f:%f:%f:%f:%f:%f:%f",+                         &p->rc.f_aq_strength_up[0], &p->rc.f_aq_strength_down[0], &p->rc.f_aq_strength_up[1], &p->rc.f_aq_strength_down[1],+                         &p->rc.f_aq_strength_up[2], &p->rc.f_aq_strength_down[2], &p->rc.f_aq_strength_up[3] ) ||+            7 == sscanf( value, "%f,%f,%f,%f,%f,%f,%f",+                         &p->rc.f_aq_strength_up[0], &p->rc.f_aq_strength_down[0], &p->rc.f_aq_strength_up[1], &p->rc.f_aq_strength_down[1],+                         &p->rc.f_aq_strength_up[2], &p->rc.f_aq_strength_down[2], &p->rc.f_aq_strength_up[3] ) )+        {+            p->rc.f_aq_strength = 0.0;+        }+        else if( 2 == sscanf( value, "%f:%f", &p->rc.f_aq_strength_up[0], &p->rc.f_aq_strength_down[0] ) ||+                 2 == sscanf( value, "%f,%f", &p->rc.f_aq_strength_up[0], &p->rc.f_aq_strength_down[0] ) )+        {+            p->rc.f_aq_strength = 0.0;+            for( i=1; i<4; i++ )+            {+                p->rc.f_aq_strength_up[i] = p->rc.f_aq_strength_up[0];+                p->rc.f_aq_strength_down[i] = p->rc.f_aq_strength_down[0];+            }+        }+        else if( sscanf( value, "%f", &p->rc.f_aq_strength ) )+        {+            for( i=0; i<4; i++ )+            {+                p->rc.f_aq_strength_up[i] = p->rc.f_aq_strength;+                p->rc.f_aq_strength_down[i] = p->rc.f_aq_strength;+            }+        }+    }+    OPT("aq-sensitivity")+        p->rc.f_aq_sensitivity = atof(value);+    OPT("aq-ifactor")+        if( 2 == sscanf( value, "%f:%f", &p->rc.f_aq_ifactor[0], &p->rc.f_aq_ifactor[1] ) ||+            2 == sscanf( value, "%f,%f", &p->rc.f_aq_ifactor[0], &p->rc.f_aq_ifactor[1] ) )+        { }+        else if( sscanf( value, "%f", &p->rc.f_aq_ifactor[0] ) )+        {+            p->rc.f_aq_ifactor[1] = p->rc.f_aq_ifactor[0];+        }+        else+        {+            p->rc.f_aq_ifactor[1] = p->rc.f_aq_ifactor[0] = 1.0;+        }+    OPT("aq-pfactor")+        if( 2 == sscanf( value, "%f:%f", &p->rc.f_aq_pfactor[0], &p->rc.f_aq_pfactor[1] ) ||+            2 == sscanf( value, "%f,%f", &p->rc.f_aq_pfactor[0], &p->rc.f_aq_pfactor[1] ) )+        { }+        else if( sscanf( value, "%f", &p->rc.f_aq_pfactor[0] ) )+        {+            p->rc.f_aq_pfactor[1] = p->rc.f_aq_pfactor[0];+        }+        else+        {+            p->rc.f_aq_pfactor[1] = p->rc.f_aq_pfactor[0] = 1.0;+        }+    OPT("aq-bfactor")+        if( 2 == sscanf( value, "%f:%f", &p->rc.f_aq_bfactor[0], &p->rc.f_aq_bfactor[1] ) ||+            2 == sscanf( value, "%f,%f", &p->rc.f_aq_bfactor[0], &p->rc.f_aq_bfactor[1] ) )+        { }+        else if( sscanf( value, "%f", &p->rc.f_aq_bfactor[0] ) )+        {+            p->rc.f_aq_bfactor[1] = p->rc.f_aq_bfactor[0];+        }+        else+        {+            p->rc.f_aq_bfactor[1] = p->rc.f_aq_bfactor[0] = 1.0;+        }+    OPT("aq-boundary")+    {+        if( 3 == sscanf( value, "%d:%d:%d", &p->rc.i_aq_boundary[0], &p->rc.i_aq_boundary[1], &p->rc.i_aq_boundary[2] ) ||+            3 == sscanf( value, "%d,%d,%d", &p->rc.i_aq_boundary[0], &p->rc.i_aq_boundary[1], &p->rc.i_aq_boundary[2] ) )+        {+            p->rc.b_aq_boundary = 1;+        }+        else+        {+            p->rc.i_aq_boundary[0] = p->rc.i_aq_boundary[1] = p->rc.i_aq_boundary[2] = 0;+        }+    }+    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 +1003,17 @@ 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:%.2f:%.2f:%.2f:%.2f:%.2f:%.2f",+                          p->rc.f_aq_strength_up[0], p->rc.f_aq_strength_down[0], p->rc.f_aq_strength_up[1], p->rc.f_aq_strength_down[1],+                          p->rc.f_aq_strength_up[2], p->rc.f_aq_strength_down[2], p->rc.f_aq_strength_up[3] );+            s += sprintf( s, " aq-sensitivity=%.2f", p->rc.f_aq_sensitivity );+            s += sprintf( s, " aq-ifactor=%.2f:%.2f", p->rc.f_aq_ifactor[0], p->rc.f_aq_ifactor[1] );+            s += sprintf( s, " aq-pfactor=%.2f:%.2f", p->rc.f_aq_pfactor[0], p->rc.f_aq_pfactor[1] );+            s += sprintf( s, " aq-bfactor=%.2f:%.2f", p->rc.f_aq_bfactor[0], p->rc.f_aq_bfactor[1] );+            s += sprintf( s, " aq-boundary=%d:%d:%d", p->rc.i_aq_boundary[0], p->rc.i_aq_boundary[1], p->rc.i_aq_boundary[2] );+        }         if( p->rc.psz_zones )             s += sprintf( s, " zones=%s", p->rc.psz_zones );         else if( p->rc.i_zones )diff --git a/common/common.h b/common/common.hindex fa0f9c8..0dc761f 100644--- a/common/common.h+++ b/common/common.h@@ -618,6 +618,13 @@ struct x264_t             /* Metrics */             int64_t i_ssd[3];             double f_ssim;++            /* AQ stats per frame */+            uint64_t i_aq_count[5];+            uint64_t i_aq_result[5][3];+            uint64_t i_aq_change[101];+            int i_aq_change_min;+            int i_aq_change_max;         } frame;          /* Cumulated stats */@@ -643,7 +650,13 @@ struct x264_t         /* */         int     i_direct_score[2];         int     i_direct_frames[2];-+        /* */+        uint64_t i_aq_count_total;+        uint64_t i_aq_count[5];+        uint64_t i_aq_result[5][3];+        uint64_t i_aq_change[101];+        int i_aq_change_min;+        int i_aq_change_max;     } stat;      void *scratch_buffer; /* for any temporary storage that doesn't want repeated malloc */diff --git a/common/frame.c b/common/frame.cindex 2e5ba44..0490d7e 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->i_aq_type, h->mb.i_mb_count * sizeof(uint8_t) );         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->i_aq_type );     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.hindex 9ca83f9..1e08785 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;+    uint8_t *i_aq_type;        // OreAQ mode type     int     b_intra_calculated;     uint16_t *i_intra_cost;     uint16_t *i_propagate_cost;diff --git a/common/pixel.c b/common/pixel.cindex 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.hindex 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/analyse.c b/encoder/analyse.cindex a2e64fe..146ece7 100644--- a/encoder/analyse.c+++ b/encoder/analyse.c@@ -184,7 +184,10 @@ const float x264_log2_lut[128] = {  /* Avoid an int/float conversion. */ const float x264_log2_lz_lut[32] = {-    31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0+    31.00024, 30.00024, 29.00024, 28.00024, 27.00024, 26.00024, 25.00024, 24.00024,+    23.00024, 22.00024, 21.00024, 20.00024, 19.00024, 18.00024, 17.00024, 16.00024,+    15.00024, 14.00024, 13.00024, 12.00024, 11.00024, 10.00024,  9.00024,  8.00024,+     7.00024,  6.00024,  5.00024,  4.00024,  3.00024,  2.00024,  1.00024,  0.00024 };  // should the intra and inter lambdas be different?diff --git a/encoder/encoder.c b/encoder/encoder.cindex d84457d..a55a394 100644--- a/encoder/encoder.c+++ b/encoder/encoder.c@@ -337,6 +337,8 @@ fail:  static int x264_validate_parameters( x264_t *h ) {+    int i;+ #ifdef HAVE_MMX     if( !(x264_cpu_detect() & X264_CPU_SSE) )     {@@ -569,9 +571,52 @@ 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_mode = 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 );+    for( i=0; i<4; i++ )+    {+        h->param.rc.f_aq_strength_up[i] = x264_clip3f( h->param.rc.f_aq_strength_up[i], -3, 3 );+        h->param.rc.f_aq_strength_down[i] = x264_clip3f( h->param.rc.f_aq_strength_down[i], -3, 3 );+    }+    if( h->param.rc.f_aq_strength_up[0] == 0 && h->param.rc.f_aq_strength_down[0] == 0 &&+        h->param.rc.f_aq_strength_up[1] == 0 && h->param.rc.f_aq_strength_down[1] == 0 &&+        h->param.rc.f_aq_strength_up[2] == 0 && h->param.rc.f_aq_strength_down[2] == 0 &&+        h->param.rc.f_aq_strength_up[3] == 0 )+    {+        if( h->param.rc.f_aq_strength == 0 )+            h->param.rc.i_aq_mode = 0;+        else+        {+            for( i=0; i<4; i++ )+            {+                h->param.rc.f_aq_strength_up[i] = h->param.rc.f_aq_strength;+                h->param.rc.f_aq_strength_down[i] = h->param.rc.f_aq_strength;+            }+        }+    }+    if( h->param.rc.f_aq_sensitivity < 0 )+        h->param.rc.f_aq_sensitivity = 0;+    h->param.rc.f_aq_ifactor[0] = x264_clip3f( h->param.rc.f_aq_ifactor[0], -10, 10 );+    h->param.rc.f_aq_ifactor[1] = x264_clip3f( h->param.rc.f_aq_ifactor[1], -10, 10 );+    h->param.rc.f_aq_pfactor[0] = x264_clip3f( h->param.rc.f_aq_pfactor[0], -10, 10 );+    h->param.rc.f_aq_pfactor[1] = x264_clip3f( h->param.rc.f_aq_pfactor[1], -10, 10 );+    h->param.rc.f_aq_bfactor[0] = x264_clip3f( h->param.rc.f_aq_bfactor[0], -10, 10 );+    h->param.rc.f_aq_bfactor[1] = x264_clip3f( h->param.rc.f_aq_bfactor[1], -10, 10 );+    h->param.rc.i_aq_boundary[0] = x264_clip3( h->param.rc.i_aq_boundary[0], 0, 255 );+    h->param.rc.i_aq_boundary[1] = x264_clip3( h->param.rc.i_aq_boundary[1], 0, 255 );+    h->param.rc.i_aq_boundary[2] = x264_clip3( h->param.rc.i_aq_boundary[2], 0, 255 );+    if( !h->param.rc.b_aq_boundary ||+        h->param.rc.i_aq_boundary[0] <= h->param.rc.i_aq_boundary[1] || h->param.rc.i_aq_boundary[1] <= h->param.rc.i_aq_boundary[2] )+    {+        h->param.rc.i_aq_boundary[0] = h->param.vui.b_fullrange ? 205 : 192;+        h->param.rc.i_aq_boundary[1] = h->param.vui.b_fullrange ? 56 : 64;+        h->param.rc.i_aq_boundary[2] = h->param.vui.b_fullrange ? 9 : 24;+    }+    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 +967,27 @@ 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_strength_up[0] );+    COPY( rc.f_aq_strength_up[1] );+    COPY( rc.f_aq_strength_up[2] );+    COPY( rc.f_aq_strength_up[3] );+    COPY( rc.f_aq_strength_down[0] );+    COPY( rc.f_aq_strength_down[1] );+    COPY( rc.f_aq_strength_down[2] );+    COPY( rc.f_aq_sensitivity );+    COPY( rc.f_aq_ifactor[0] );+    COPY( rc.f_aq_ifactor[1] );+    COPY( rc.f_aq_pfactor[0] );+    COPY( rc.f_aq_pfactor[1] );+    COPY( rc.f_aq_bfactor[0] );+    COPY( rc.f_aq_bfactor[1] );+    COPY( rc.b_aq_boundary );+    COPY( rc.i_aq_boundary[0] );+    COPY( rc.i_aq_boundary[1] );+    COPY( rc.i_aq_boundary[2] );     // 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 );@@ -1844,6 +1910,23 @@ static int x264_encoder_frame_end( x264_t *h, x264_t *thread_current,         snprintf( psz_message + strlen(psz_message), 80 - strlen(psz_message),                   " SSIM Y:%.5f", ssim_y );     }++    if( h->param.rc.i_aq_mode == X264_AQ_ORE )+    {+        h->stat.i_aq_count_total += h->mb.i_mb_count;+        for( i=0; i<5; i++ )+        {+            h->stat.i_aq_count[i] += h->stat.frame.i_aq_count[i];+            h->stat.i_aq_result[i][0] += h->stat.frame.i_aq_result[i][0];+            h->stat.i_aq_result[i][1] += h->stat.frame.i_aq_result[i][1];+            h->stat.i_aq_result[i][2] += h->stat.frame.i_aq_result[i][2];+        }+        for( i=h->stat.frame.i_aq_change_min+50; i<=h->stat.frame.i_aq_change_max+50; i++ )+            h->stat.i_aq_change[i] += h->stat.frame.i_aq_change[i];+        h->stat.i_aq_change_min = X264_MIN(h->stat.i_aq_change_min, h->stat.frame.i_aq_change_min);+        h->stat.i_aq_change_max = X264_MAX(h->stat.i_aq_change_max, h->stat.frame.i_aq_change_max);+    }+     psz_message[79] = '\0';      x264_log( h, X264_LOG_DEBUG,@@ -2095,6 +2178,46 @@ void    x264_encoder_close  ( x264_t *h )             }         } +        if( h->stat.i_aq_count_total )+        {+#define GET_AQ_RESULT(x) \+            100.0 / h->stat.i_aq_count_total * h->stat.i_aq_count[x], \+            h->stat.i_aq_count[x] ? (100.0 / h->stat.i_aq_count[x] * h->stat.i_aq_result[x][0]) : 0, \+            h->stat.i_aq_count[x] ? (100.0 / h->stat.i_aq_count[x] * h->stat.i_aq_result[x][1]) : 0, \+            h->stat.i_aq_count[x] ? (100.0 / h->stat.i_aq_count[x] * h->stat.i_aq_result[x][2]) : 0+            char buf[1500];+            char *p = buf;++            if( h->stat.i_aq_count[0] )+                x264_log( h, X264_LOG_INFO,+                    "AQ Result  MBTree MB:%5.2f%%  QP Up:%5.2f%% Down:%5.2f%% Even:%5.2f%%\n",+                    GET_AQ_RESULT(0));++            if( h->stat.i_aq_count[1] || h->stat.i_aq_count[2] || h->stat.i_aq_count[3] || h->stat.i_aq_count[4] )+            {+                x264_log( h, X264_LOG_INFO,+                    "AQ Result  Bright MB:%5.2f%%  QP Up:%5.2f%% Down:%5.2f%% Even:%5.2f%%\n",+                    GET_AQ_RESULT(1));++                x264_log( h, X264_LOG_INFO,+                    "AQ Result  Middle MB:%5.2f%%  QP Up:%5.2f%% Down:%5.2f%% Even:%5.2f%%\n",+                    GET_AQ_RESULT(2));++                x264_log( h, X264_LOG_INFO,+                    "AQ Result    Dark MB:%5.2f%%  QP Up:%5.2f%% Down:%5.2f%% Even:%5.2f%%\n",+                    GET_AQ_RESULT(3));++                x264_log( h, X264_LOG_INFO,+                    "AQ Result  M.Dark MB:%5.2f%%  QP Up:%5.2f%% Down:%5.2f%% Even:%5.2f%%\n",+                    GET_AQ_RESULT(4));+            }++            for(i = h->stat.i_aq_change_min; i<=h->stat.i_aq_change_max; i++)+                p += sprintf(p, " %d:%.2f%%", -i, 100.0 / h->stat.i_aq_count_total * h->stat.i_aq_change[i+50]);+            x264_log( h, X264_LOG_INFO, "AQ change value %s\n", buf);++        }+         if( h->param.analyse.b_ssim )         {             x264_log( h, X264_LOG_INFO,diff --git a/encoder/ratecontrol.c b/encoder/ratecontrol.cindex fd9aa94..a25aaf3 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, uint32_t *energy );+ struct x264_ratecontrol_t {     /* constants */@@ -135,11 +137,17 @@ struct x264_ratecontrol_t     int bframes;                /* # consecutive B-frames before this P-frame */     int bframe_bits;            /* total cost of those frames */ +    /* AQ stuff */+    float aq_threshold;+    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 *);@@ -176,7 +184,7 @@ static inline double qscale2bits(ratecontrol_entry_t *rce, double qscale) }  // Find the total AC energy of the block in all planes.-static NOINLINE uint32_t ac_energy_mb( x264_t *h, int mb_x, int mb_y, x264_frame_t *frame )+static NOINLINE uint32_t ac_energy_mb( x264_t *h, int mb_x, int mb_y, x264_frame_t *frame, uint32_t *energy ) {     /* This function contains annoying hacks because GCC has a habit of reordering emms      * and putting it after floating point ops.  As a result, we put the emms at the end of the@@ -192,37 +200,205 @@ static NOINLINE uint32_t ac_energy_mb( x264_t *h, int mb_x, int mb_y, x264_frame             : w * (mb_x + mb_y * stride);         int pix = i ? PIXEL_8x8 : PIXEL_16x16;         stride <<= h->mb.b_interlaced;-        var += h->pixf.var[pix]( frame->plane[i]+offset, stride );+        energy[i] = h->pixf.var[pix]( frame->plane[i]+offset, stride );+        var += energy[i];     }     x264_emms();     return var; } +static NOINLINE uint32_t aqm_mod( x264_t *h, int mb_x, int mb_y, x264_frame_t *frame, uint32_t *energy )+{+    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) );+        energy[i] = h->pixf.ssd[pix]( avg_flat, 0, frame->plane[i]+offset, stride );+        var += energy[i];+    }+    x264_emms();+    return var;+}++static NOINLINE void get_image_mb( x264_t *h, int mb_x, int mb_y, x264_frame_t *frame, int *luma, int *bluePoint )+{+    ALIGNED_16( static uint8_t zero[17] ) = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};+    int stride[3];+    int offset[3];+    int i;++    for( i=0; i<3; i++ )+    {+        int w = i ? 8 : 16;+        stride[i] = frame->i_stride[i];+        offset[i] = h->mb.b_interlaced+            ? w * (mb_x + (mb_y&~1) * stride[i]) + (mb_y&1) * stride[i]+            : w * (mb_x + mb_y * stride[i]);+        stride[i] <<= h->mb.b_interlaced;+    }++    *luma = h->pixf.sad[PIXEL_16x16](frame->plane[0]+offset[0], stride[0], zero, 0)>>8;+    *bluePoint =+        (h->pixf.count_8x8(frame->plane[1]+offset[1], stride[1], 0x81818181) >= 40) &&+        (h->pixf.count_8x8(frame->plane[2]+offset[2], stride[2], 0x87878787) <= 24);+}++static NOINLINE int x264_adjust_OreAQ( x264_t *h, int mb_x, int mb_y, x264_frame_t *frame, uint32_t *energy )+{+    uint8_t mode;+    int bluePoint = 0;+    int luma = 0;+    float energy_y, energy_uv, f_qp_adj;+    uint32_t _energy_y, _energy_uv;++    get_image_mb( h, mb_x, mb_y, frame, &luma, &bluePoint );+    x264_emms();++    _energy_y = X264_MAX( energy[0], 1 );+    _energy_uv = X264_MAX( energy[1] + energy[2], 1 );++    if(h->param.rc.b_aq_debug)+        x264_write_aqlog_body( h, mb_x + mb_y*h->mb.i_mb_stride, frame, luma, bluePoint, (float)_energy_y, (float)_energy_uv );++    // logf(energy) = (1.0397 * (log2_lut[(energy<<lz>>24)&0x7f] - lz + 31.00024f) / 1.5+    // energy_y  = 1.2 * (logf(_energy_y ) - (h->rc->aq_threshold * .91) + .5);+    // energy_uv = 0.8 * (logf(_energy_uv) - (h->rc->aq_threshold * .91) + .5);+    energy_y  = 0.83176f * x264_log2( _energy_y ) - (h->rc->aq_threshold * 1.092f) + .5f;+    energy_uv = 0.55451f * x264_log2( _energy_uv ) - (h->rc->aq_threshold * 0.728f) + .5f;+    f_qp_adj = 0.0;++    // lumaの平均値から処理分岐+    if(luma > h->param.rc.i_aq_boundary[0]){+        // *** 明部 ***+        // Y & UV Flat      -> qp up+        // Y Flat / UV Bump -> qp y up+        // Y Bump / UV Flat -> even+        // Y & UV Bump      -> qp down+        mode = 0x00;++        // qp up+        if(!bluePoint && energy_y < 0 && energy_uv < 0)+            f_qp_adj = X264_MIN(energy_y, energy_uv);+        // qp y up+        else if(!bluePoint && energy_y < 0 && energy_uv >= 0)+            f_qp_adj = energy_y;+        // qp down+        else if (energy_y >= 0 && energy_uv >= 0)+            f_qp_adj = X264_MAX(energy_y, energy_uv) * .5;+    } else if(luma > h->param.rc.i_aq_boundary[1]){+        // *** 中間部 ***+        // Y & UV Flat      -> qp up+        // Y Flat / UV Bump -> even+        // Y Bump / UV Flat -> qp mix down+        // Y & UV Bump      -> qp down+        mode = 0x01;++        // qp up+        if(!bluePoint && energy_y < 0 && energy_uv < 0)+            f_qp_adj = X264_MAX(energy_y, energy_uv);+        // qp mix down+        else if (energy_y >= 0 && energy_uv < 0)+            f_qp_adj = X264_MAX(energy_y + (!bluePoint * energy_uv), 0) * .5;+        // qp down+        else if (energy_y >= 0 && energy_uv >= 0)+            f_qp_adj = X264_MAX(energy_y, bluePoint * energy_uv);+    } else if(luma > h->param.rc.i_aq_boundary[2]){+        // *** 暗部 ***+        // Y & UV Flat      -> qp up+        // Y Flat / UV Bump -> qp uv down+        // Y Bump / UV Flat -> qp y down+        // Y & UV Bump      -> qp down+        mode = 0x02;++        // qp up+        if(energy_y < 0 && energy_uv < 0)+            f_qp_adj = X264_MAX(energy_y, energy_uv) * .5;+        // qp uv down+        else if (energy_y < 0 && energy_uv >= 0)+            f_qp_adj = energy_uv * 1.25;+        // qp y down+        else if (energy_y >= 0 && energy_uv < 0)+            f_qp_adj = energy_y * 1.25;+        // qp down+        else if (energy_y >= 0 && energy_uv >= 0)+            f_qp_adj = X264_MAX(energy_y, energy_uv) * 1.25;+    } else {+        // *** 超暗部 ***+        // Y & UV Flat      -> qp double up+        // Y Flat / UV Bump -> qp y up+        // Y Bump / UV Flat -> qp uv up+        // Y & UV Bump      -> even+        mode = 0x03;++        // qp double up+        if(energy_y < 0 && energy_uv < 0)+            f_qp_adj = energy_y + energy_uv;+        // qp mix up+        else if (energy_y < 0 && energy_uv >= 0)+            f_qp_adj = energy_y;+        // qp uv down+        else if (energy_y >= 0 && energy_uv < 0)+            f_qp_adj = energy_uv * .5;+    }++    // qp down+    if(f_qp_adj > 0)+        f_qp_adj *= h->param.rc.f_aq_strength_down[mode];+    else+        f_qp_adj *= h->param.rc.f_aq_strength_up[mode];++    frame->i_aq_type[mb_x + mb_y*h->mb.i_mb_stride] = mode + 0x01;++    return -f_qp_adj;+}+ 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.      * FIXME: while they're written in 5 significant digits, they're only tuned to 2. */     int mb_x, mb_y;-    float strength;+    float strength = 0.f;     float avg_adj = 0.f;+    uint32_t energy_yuv[3] = {0, 0, 0};+    x264_aq_metric_t aq_metric_func;+     /* Need to init it anyways for MB tree. */-    if( h->param.rc.f_aq_strength == 0 )+    if( h->param.rc.f_aq_strength_up[0] == 0 && h->param.rc.f_aq_strength_down[0] == 0 &&+        h->param.rc.f_aq_strength_up[1] == 0 && h->param.rc.f_aq_strength_down[1] == 0 &&+        h->param.rc.f_aq_strength_up[2] == 0 && h->param.rc.f_aq_strength_down[2] == 0 &&+        h->param.rc.f_aq_strength_up[3] == 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->i_aq_type, 0, h->mb.i_mb_count * sizeof(uint8_t) );         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, energy_yuv );                 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;@@ -232,7 +408,7 @@ void x264_adaptive_quant_frame( x264_t *h, x264_frame_t *frame )         strength = h->param.rc.f_aq_strength * avg_adj * (1.f / 6000.f);     }     else-        strength = h->param.rc.f_aq_strength * 1.0397f;+        h->rc->aq_threshold = logf(powf(h->param.rc.f_aq_sensitivity,4)/2.0);      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++ )@@ -245,8 +421,8 @@ 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, energy_yuv );+                qp_adj = x264_adjust_OreAQ( h, mb_x, mb_y, frame, energy_yuv );             }             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;@@ -265,8 +441,38 @@ void x264_adaptive_quant_frame( x264_t *h, x264_frame_t *frame ) *****************************************************************************/ void x264_adaptive_quant( x264_t *h ) {+    int i_qp_adj;+    float factor, f_qp_adj;+     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 );++    f_qp_adj = h->fenc->f_qp_offset[h->mb.i_mb_xy];+    if( h->sh.i_type == SLICE_TYPE_I )+        factor = h->param.rc.f_aq_ifactor[f_qp_adj<0];+    else if( h->sh.i_type == SLICE_TYPE_P )+        factor = h->param.rc.f_aq_pfactor[f_qp_adj<0];+    else if( h->sh.i_type == SLICE_TYPE_B )+        factor = h->param.rc.f_aq_bfactor[f_qp_adj<0];+    else+        factor = 1.0;++    if( h->param.rc.i_aq_mode == X264_AQ_ORE )+    {+        h->mb.i_qp = (int)(h->rc->f_qpm + factor * f_qp_adj + .5);+        i_qp_adj = x264_clip3( h->rc->f_qpm - h->mb.i_qp + .5, -50, 50 );++        h->stat.frame.i_aq_change[i_qp_adj + 50] += 1;+        h->stat.frame.i_aq_count[ h->fenc->i_aq_type[h->mb.i_mb_xy] ] += 1;+        h->stat.frame.i_aq_result[ h->fenc->i_aq_type[h->mb.i_mb_xy] ][ (i_qp_adj<0?0:(i_qp_adj>0?1:2)) ] += 1;+        h->stat.frame.i_aq_change_min = X264_MIN(h->stat.frame.i_aq_change_min, i_qp_adj);+        h->stat.frame.i_aq_change_max = X264_MAX(h->stat.frame.i_aq_change_max, i_qp_adj);++        h->mb.i_qp = x264_clip3( h->mb.i_qp, h->param.rc.i_qp_min, h->param.rc.i_qp_max );+    }+    else if( h->param.rc.i_aq_mode == X264_AQ_AUTOVARIANCE )+    {+        h->mb.i_qp = x264_clip3( h->rc->f_qpm + factor * f_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 )@@ -290,6 +496,8 @@ int x264_macroblock_tree_read( x264_t *h, x264_frame_t *frame )          if( fread( rc->qp_buffer, sizeof(uint16_t), h->mb.i_mb_count, rc->p_mbtree_stat_file_in ) != h->mb.i_mb_count )             goto fail;+        if( fread( frame->i_aq_type, sizeof(uint8_t), h->mb.i_mb_count, rc->p_mbtree_stat_file_in ) != h->mb.i_mb_count )+            goto fail;          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);@@ -665,6 +873,21 @@ 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, "OreAQ04", 0,+           h->param.rc.f_aq_strength_up, h->param.rc.f_aq_strength_down, h->param.rc.f_aq_sensitivity, 0,+           h->param.rc.i_aq_boundary );+    }+     for( i=0; i<h->param.i_threads; i++ )     {         h->thread[i]->rc = rc+i;@@ -855,6 +1078,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 ); } @@ -1224,6 +1449,8 @@ int x264_ratecontrol_end( x264_t *h, int bits )                 goto fail;             if( fwrite( rc->qp_buffer, sizeof(uint16_t), h->mb.i_mb_count, rc->p_mbtree_stat_file_out ) < h->mb.i_mb_count )                 goto fail;+            if( fwrite( h->fenc->i_aq_type, sizeof(uint8_t), h->mb.i_mb_count, rc->p_mbtree_stat_file_out ) < h->mb.i_mb_count )+                goto fail;         }     } diff --git a/x264.c b/x264.cindex 32e6570..c3de42c 100644--- a/x264.c+++ b/x264.c@@ -216,12 +216,28 @@ static void Help( x264_param_t *defaults, int b_longhelp )     H1( "      --chroma-qp-offset <integer>  QP difference between chroma and luma [%d]\n", defaults->analyse.i_chroma_qp_offset );     H1( "      --aq-mode <integer>     AQ method [%d]\n"         "                                  - 0: Disabled\n"-        "                                  - 1: Variance AQ (complexity mask)\n"+        "                                  - 1: OreAQ\n"         "                                  - 2: Auto-variance AQ (experimental)\n", defaults->rc.i_aq_mode );     H0( "      --aq-strength <float>   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 );+        "                                  - 1.5: strong AQ\n"+        "                    <Up:Down> or <Up1:Down1:Up2:Down2:Up3:Down3:Up4>\n"+        "                              Set QP up/down strength.\n", defaults->rc.f_aq_strength );+    H0( "      --aq-sensitivity <float> \"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 <Up:Down>  AQ strength factor of I-frames [%.1f:%.1f]\n", defaults->rc.f_aq_ifactor[0], defaults->rc.f_aq_ifactor[1] );+    H1( "      --aq-pfactor <Up:Down>  AQ strength factor of P-frames [%.1f:%.1f]\n", defaults->rc.f_aq_pfactor[0], defaults->rc.f_aq_pfactor[1] );+    H1( "      --aq-bfactor <Up:Down>  AQ strength factor of B-frames [%.1f:%.1f]\n", defaults->rc.f_aq_bfactor[0], defaults->rc.f_aq_bfactor[1] );+    H1( "      --aq-boundary <int:int:int>  AQ boundary. \n"+        "                                  fullrange=off: [192:64:24]\n"+        "                                  fullrange=on : [205:56:9]\n"+        "                                  #1: Bright-Middle\n"+        "                                  #2: Middle-Dark\n"+        "                                  #3: Dark-M.Dark\n" );+    H0( "      --aq-debug <string>     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 +454,13 @@ 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-boundary", 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.hindex 7fa508d..ed82787 100644--- a/x264.h+++ b/x264.h@@ -36,6 +36,7 @@ #include <stdarg.h>  #define X264_BUILD 72+#define X264_SUB_BUILD 2 // OreAQ  /* 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_ORE                  1 #define X264_AQ_AUTOVARIANCE         2 #define X264_B_ADAPT_NONE            0 #define X264_B_ADAPT_FAST            1@@ -274,7 +275,18 @@ 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_strength_up[4];   /* { Bright, Middle, Dark, M.Dark } */+        float       f_aq_strength_down[4]; /* { Bright, Middle, Dark, NULL } */+        float       f_aq_sensitivity;+        float       f_aq_ifactor[2]; /* { Up, Down } */+        float       f_aq_pfactor[2]; /* { Up, Down } */+        float       f_aq_bfactor[2]; /* { Up, Down } */+        int         b_aq_boundary;+        int         i_aq_boundary[3];+        int         b_aq_debug;+        char        *psz_aq_debug_name;         int         b_mb_tree;      /* Macroblock-tree ratecontrol. */         int         i_lookahead;