Don't force row QPs to integer values with VBV
authorJason Garrett-Glaser <darkshikari@gmail.com>
Tue, 4 May 2010 04:27:16 +0000 (21:27 -0700)
committerJason Garrett-Glaser <darkshikari@gmail.com>
Thu, 6 May 2010 05:08:29 +0000 (22:08 -0700)
VBV should no longer raise the bitrate of the video.  That is, at a given quality level or average bitrate, turning on VBV should only lower the bitrate.
This isn't quite true if adaptive quant is off, but nobody should be doing that anyways.
Also may result in slightly more accurate per-row VBV ratecontrol.

common/frame.c
common/frame.h
encoder/analyse.c
encoder/ratecontrol.c
encoder/ratecontrol.h

index 5d2cd57..aa10773 100644 (file)
@@ -118,7 +118,7 @@ x264_frame_t *x264_frame_new( x264_t *h, int b_fdec )
             frame->ref[1] = NULL;
         }
         CHECKED_MALLOC( frame->i_row_bits, i_lines/16 * sizeof(int) );
-        CHECKED_MALLOC( frame->i_row_qp, i_lines/16 * sizeof(int) );
+        CHECKED_MALLOC( frame->f_row_qp, i_lines/16 * sizeof(float) );
         if( h->param.analyse.i_me_method >= X264_ME_ESA )
         {
             CHECKED_MALLOC( frame->buffer[3],
@@ -202,7 +202,7 @@ void x264_frame_delete( x264_frame_t *frame )
         x264_free( frame->f_qp_offset_aq );
         x264_free( frame->i_inv_qscale_factor );
         x264_free( frame->i_row_bits );
-        x264_free( frame->i_row_qp );
+        x264_free( frame->f_row_qp );
         x264_free( frame->mb_type );
         x264_free( frame->mb_partition );
         x264_free( frame->mv[0] );
index 6093075..357929e 100644 (file)
@@ -109,7 +109,7 @@ typedef struct x264_frame
     int     *i_row_satds[X264_BFRAME_MAX+2][X264_BFRAME_MAX+2];
     int     *i_row_satd;
     int     *i_row_bits;
-    int     *i_row_qp;
+    float   *f_row_qp;
     float   *f_qp_offset;
     float   *f_qp_offset_aq;
     int     b_intra_calculated;
index 5f7c66d..8868012 100644 (file)
@@ -2568,15 +2568,11 @@ void x264_macroblock_analyse( x264_t *h )
     x264_mb_analysis_t analysis;
     int i_cost = COST_MAX;
 
-    h->mb.i_qp = x264_ratecontrol_qp( h );
-    if( h->param.rc.i_aq_mode )
-    {
-        x264_adaptive_quant( h );
-        /* 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.  Don't do this if QPRD is enabled. */
-        if( h->param.analyse.i_subpel_refine < 10 && abs(h->mb.i_qp - h->mb.i_last_qp) == 1 )
-            h->mb.i_qp = h->mb.i_last_qp;
-    }
+    h->mb.i_qp = x264_ratecontrol_mb_qp( h );
+    /* 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.  Don't do this if QPRD is enabled. */
+    if( h->param.rc.i_aq_mode && h->param.analyse.i_subpel_refine < 10 && abs(h->mb.i_qp - h->mb.i_last_qp) == 1 )
+        h->mb.i_qp = h->mb.i_last_qp;
 
     x264_mb_analyse_init( h, &analysis, h->mb.i_qp );
 
index 1e11120..7f18c7f 100644 (file)
@@ -83,8 +83,7 @@ struct x264_ratecontrol_t
     /* current frame */
     ratecontrol_entry_t *rce;
     int qp;                     /* qp for current frame */
-    int qpm;                    /* qp for current macroblock */
-    float f_qpm;                /* qp for current macroblock: precise float for AQ */
+    float qpm;                  /* qp for current macroblock: precise float for AQ */
     float qpa_rc;               /* average of macroblocks' qp before aq */
     float qpa_aq;               /* average of macroblocks' qp after aq */
     float qp_novbv;             /* QP for the current frame if 1-pass VBV was disabled. */
@@ -292,22 +291,6 @@ void x264_adaptive_quant_frame( x264_t *h, x264_frame_t *frame )
         }
 }
 
-
-/*****************************************************************************
-* 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 )
-{
-    x264_emms();
-    /* MB-tree currently doesn't adjust quantizers in unreferenced frames. */
-    float qp_offset = h->fdec->b_kept_as_ref ? h->fenc->f_qp_offset[h->mb.i_mb_xy] : h->fenc->f_qp_offset_aq[h->mb.i_mb_xy];
-    h->mb.i_qp = x264_clip3( h->rc->f_qpm + qp_offset + .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 )
 {
     x264_ratecontrol_t *rc = h->rc;
@@ -1179,28 +1162,27 @@ void x264_ratecontrol_start( x264_t *h, int i_force_qp, int overhead )
 
     rc->qpa_rc =
     rc->qpa_aq = 0;
-    rc->qpm =
     rc->qp = x264_clip3( (int)(q + 0.5), 0, 51 );
     h->fdec->f_qp_avg_rc =
     h->fdec->f_qp_avg_aq =
-    rc->f_qpm = q;
+    rc->qpm = q;
     if( rce )
         rce->new_qp = rc->qp;
 
-    accum_p_qp_update( h, rc->f_qpm );
+    accum_p_qp_update( h, rc->qpm );
 
     if( h->sh.i_type != SLICE_TYPE_B )
         rc->last_non_b_pict_type = h->sh.i_type;
 }
 
-static double predict_row_size( x264_t *h, int y, int qp )
+static double predict_row_size( x264_t *h, int y, double qp )
 {
     /* average between two predictors:
      * absolute SATD, and scaled bit cost of the colocated row in the previous frame */
     x264_ratecontrol_t *rc = h->rc;
     double pred_s = predict_size( rc->row_pred[0], qp2qscale( qp ), h->fdec->i_row_satd[y] );
     double pred_t = 0;
-    if( h->sh.i_type == SLICE_TYPE_I || qp >= h->fref0[0]->i_row_qp[y] )
+    if( h->sh.i_type == SLICE_TYPE_I || qp >= h->fref0[0]->f_row_qp[y] )
     {
         if( h->sh.i_type == SLICE_TYPE_P
             && h->fref0[0]->i_type == h->fdec->i_type
@@ -1208,7 +1190,7 @@ static double predict_row_size( x264_t *h, int y, int qp )
             && (abs(h->fref0[0]->i_row_satd[y] - h->fdec->i_row_satd[y]) < h->fdec->i_row_satd[y]/2))
         {
             pred_t = h->fref0[0]->i_row_bits[y] * h->fdec->i_row_satd[y] / h->fref0[0]->i_row_satd[y]
-                     * qp2qscale( h->fref0[0]->i_row_qp[y] ) / qp2qscale( qp );
+                     * qp2qscale( h->fref0[0]->f_row_qp[y] ) / qp2qscale( qp );
         }
         if( pred_t == 0 )
             pred_t = pred_s;
@@ -1231,7 +1213,7 @@ static double row_bits_so_far( x264_t *h, int y )
     return bits;
 }
 
-static double predict_row_size_sum( x264_t *h, int y, int qp )
+static double predict_row_size_sum( x264_t *h, int y, double qp )
 {
     double bits = row_bits_so_far(h, y);
     for( int i = y+1; i < h->i_threadslice_end; i++ )
@@ -1248,33 +1230,34 @@ void x264_ratecontrol_mb( x264_t *h, int bits )
     x264_emms();
 
     h->fdec->i_row_bits[y] += bits;
-    rc->qpa_rc += rc->f_qpm;
+    rc->qpa_rc += rc->qpm;
     rc->qpa_aq += h->mb.i_qp;
 
     if( h->mb.i_mb_x != h->sps->i_mb_width - 1 || !rc->b_vbv )
         return;
 
-    h->fdec->i_row_qp[y] = rc->qpm;
+    h->fdec->f_row_qp[y] = rc->qpm;
 
     update_predictor( rc->row_pred[0], qp2qscale( rc->qpm ), h->fdec->i_row_satd[y], h->fdec->i_row_bits[y] );
-    if( h->sh.i_type == SLICE_TYPE_P && rc->qpm < h->fref0[0]->i_row_qp[y] )
+    if( h->sh.i_type == SLICE_TYPE_P && rc->qpm < h->fref0[0]->f_row_qp[y] )
         update_predictor( rc->row_pred[1], qp2qscale( rc->qpm ), h->fdec->i_row_satds[0][0][y], h->fdec->i_row_bits[y] );
 
     /* tweak quality based on difference from predicted size */
     if( y < h->i_threadslice_end-1 )
     {
-        int prev_row_qp = h->fdec->i_row_qp[y];
-        int i_qp_min = X264_MAX( prev_row_qp - h->param.rc.i_qp_step, h->param.rc.i_qp_min );
-        int i_qp_absolute_max = h->param.rc.i_qp_max;
+        float prev_row_qp = h->fdec->f_row_qp[y];
+        float qp_min = X264_MAX( prev_row_qp - h->param.rc.i_qp_step, h->param.rc.i_qp_min );
+        float qp_absolute_max = h->param.rc.i_qp_max;
         if( rc->rate_factor_max_increment )
-            i_qp_absolute_max = X264_MIN( i_qp_absolute_max, rc->qp_novbv + rc->rate_factor_max_increment );
-        int i_qp_max = X264_MIN( prev_row_qp + h->param.rc.i_qp_step, i_qp_absolute_max );
+            qp_absolute_max = X264_MIN( qp_absolute_max, rc->qp_novbv + rc->rate_factor_max_increment );
+        float qp_max = X264_MIN( prev_row_qp + h->param.rc.i_qp_step, qp_absolute_max );
+        float step_size = 0.5;
 
         /* B-frames shouldn't use lower QP than their reference frames. */
         if( h->sh.i_type == SLICE_TYPE_B )
         {
-            i_qp_min = X264_MAX( i_qp_min, X264_MAX( h->fref0[0]->i_row_qp[y+1], h->fref1[0]->i_row_qp[y+1] ) );
-            rc->qpm = X264_MAX( rc->qpm, i_qp_min );
+            qp_min = X264_MAX( qp_min, X264_MAX( h->fref0[0]->f_row_qp[y+1], h->fref1[0]->f_row_qp[y+1] ) );
+            rc->qpm = X264_MAX( rc->qpm, qp_min );
         }
 
         float buffer_left_planned = rc->buffer_fill - rc->frame_size_planned;
@@ -1302,45 +1285,53 @@ void x264_ratecontrol_mb( x264_t *h, int bits )
             rc_tol /= 2;
 
         if( !rc->b_vbv_min_rate )
-            i_qp_min = X264_MAX( i_qp_min, h->sh.i_qp );
+            qp_min = X264_MAX( qp_min, rc->qp_novbv );
 
-        while( rc->qpm < i_qp_max
+        while( rc->qpm < qp_max
                && ((b1 > rc->frame_size_planned + rc_tol) ||
                    (rc->buffer_fill - b1 < buffer_left_planned * 0.5) ||
                    (b1 > rc->frame_size_planned && rc->qpm < rc->qp_novbv)) )
         {
-            rc->qpm ++;
+            rc->qpm += step_size;
             b1 = predict_row_size_sum( h, y, rc->qpm ) + size_of_other_slices;
         }
 
-        while( rc->qpm > i_qp_min
-               && (rc->qpm > h->fdec->i_row_qp[0] || rc->single_frame_vbv)
+        while( rc->qpm > qp_min
+               && (rc->qpm > h->fdec->f_row_qp[0] || rc->single_frame_vbv)
                && ((b1 < rc->frame_size_planned * 0.8 && rc->qpm <= prev_row_qp)
                || b1 < (rc->buffer_fill - rc->buffer_size + rc->buffer_rate) * 1.1) )
         {
-            rc->qpm --;
+            rc->qpm -= step_size;
             b1 = predict_row_size_sum( h, y, rc->qpm ) + size_of_other_slices;
         }
 
         /* avoid VBV underflow or MinCR violation */
-        while( (rc->qpm < i_qp_absolute_max)
+        while( (rc->qpm < qp_absolute_max)
                && ((rc->buffer_fill - b1 < rc->buffer_rate * rc->max_frame_error) ||
                    (rc->frame_size_maximum - b1 < rc->frame_size_maximum * rc->max_frame_error)))
         {
-            rc->qpm ++;
+            rc->qpm += step_size;
             b1 = predict_row_size_sum( h, y, rc->qpm ) + size_of_other_slices;
         }
 
         h->rc->frame_size_estimated = predict_row_size_sum( h, y, rc->qpm );
     }
-
-    /* loses the fractional part of the frame-wise qp */
-    rc->f_qpm = rc->qpm;
 }
 
 int x264_ratecontrol_qp( x264_t *h )
 {
-    return h->rc->qpm;
+    x264_emms();
+    return x264_clip3( h->rc->qpm + .5, h->param.rc.i_qp_min, h->param.rc.i_qp_max );
+}
+
+int x264_ratecontrol_mb_qp( x264_t *h )
+{
+    x264_emms();
+    float qp = h->rc->qpm;
+    if( h->param.rc.i_aq_mode )
+        /* MB-tree currently doesn't adjust quantizers in unreferenced frames. */
+        qp += h->fdec->b_kept_as_ref ? h->fenc->f_qp_offset[h->mb.i_mb_xy] : h->fenc->f_qp_offset_aq[h->mb.i_mb_xy];
+    return x264_clip3( qp + .5, h->param.rc.i_qp_min, h->param.rc.i_qp_max );
 }
 
 /* In 2pass, force the same frame types as in the 1st pass */
index 181ab23..e052b2a 100644 (file)
@@ -30,7 +30,6 @@ void x264_ratecontrol_delete( x264_t * );
 void x264_ratecontrol_init_reconfigurable( x264_t *h, int b_init );
 
 void x264_adaptive_quant_frame( x264_t *h, x264_frame_t *frame );
-void x264_adaptive_quant( x264_t * );
 int  x264_macroblock_tree_read( x264_t *h, x264_frame_t *frame );
 int  x264_reference_build_list_optimal( x264_t *h );
 void x264_thread_sync_ratecontrol( x264_t *cur, x264_t *prev, x264_t *next );
@@ -39,6 +38,7 @@ int  x264_ratecontrol_slice_type( x264_t *, int i_frame );
 void x264_ratecontrol_set_weights( x264_t *h, x264_frame_t *frm );
 void x264_ratecontrol_mb( x264_t *, int bits );
 int  x264_ratecontrol_qp( x264_t * );
+int  x264_ratecontrol_mb_qp( x264_t *h );
 int  x264_ratecontrol_end( x264_t *, int bits, int *filler );
 void x264_ratecontrol_summary( x264_t * );
 void x264_ratecontrol_set_estimated_size( x264_t *, int bits );