[x264-devel] [Git][videolan/x264][master] Fix VBV with sliced threads

Anton Mitrofanov (@BugMaster) gitlab at videolan.org
Sat Oct 28 14:51:01 UTC 2023



Anton Mitrofanov pushed to branch master at VideoLAN / x264


Commits:
d46938de by Anton Mitrofanov at 2023-10-24T22:07:14+03:00
Fix VBV with sliced threads

- - - - -


1 changed file:

- encoder/ratecontrol.c


Changes:

=====================================
encoder/ratecontrol.c
=====================================
@@ -156,6 +156,7 @@ struct x264_ratecontrol_t
     /* MBRC stuff */
     volatile float frame_size_estimated; /* Access to this variable must be atomic: double is
                                           * not atomic on all arches we care about */
+    volatile float bits_so_far;
     double frame_size_maximum;  /* Maximum frame size due to MinCR */
     double frame_size_planned;
     double slice_size_planned;
@@ -1629,20 +1630,24 @@ int x264_ratecontrol_mb( x264_t *h, int bits )
     float step_size = 0.5f;
     float slice_size_planned = h->param.b_sliced_threads ? rc->slice_size_planned : rc->frame_size_planned;
     float bits_so_far = row_bits_so_far( h, y );
+    rc->bits_so_far = bits_so_far;
     float max_frame_error = x264_clip3f( 1.0 / h->mb.i_mb_height, 0.05, 0.25 );
     float max_frame_size = rc->frame_size_maximum - rc->frame_size_maximum * max_frame_error;
     max_frame_size = X264_MIN( max_frame_size, rc->buffer_fill - rc->buffer_rate * max_frame_error );
     float size_of_other_slices = 0;
     if( h->param.b_sliced_threads )
     {
-        float size_of_other_slices_planned = 0;
+        float bits_so_far_of_other_slices = 0;
         for( int i = 0; i < h->param.i_threads; i++ )
             if( h != h->thread[i] )
             {
                 size_of_other_slices += h->thread[i]->rc->frame_size_estimated;
-                size_of_other_slices_planned += h->thread[i]->rc->slice_size_planned;
+                bits_so_far_of_other_slices += h->thread[i]->rc->bits_so_far;
             }
-        float weight = rc->slice_size_planned / rc->frame_size_planned;
+        float weight = x264_clip3f( (bits_so_far_of_other_slices + rc->frame_size_estimated) / (size_of_other_slices + rc->frame_size_estimated), 0.0, 1.0 );
+        float frame_size_planned = rc->frame_size_planned - rc->frame_size_planned * max_frame_error;
+        float size_of_other_slices_planned = X264_MIN( frame_size_planned, max_frame_size ) - rc->slice_size_planned;
+        size_of_other_slices_planned = X264_MAX( size_of_other_slices_planned, bits_so_far_of_other_slices );
         size_of_other_slices = (size_of_other_slices - size_of_other_slices_planned) * weight + size_of_other_slices_planned;
     }
     if( y < h->i_threadslice_end-1 )
@@ -2233,7 +2238,7 @@ static void update_vbv_plan( x264_t *h, int overhead )
     rcc->buffer_fill -= overhead;
 }
 
-// apply VBV constraints and clip qscale to between lmin and lmax
+// clip qscale to between lmin and lmax
 static double clip_qscale( x264_t *h, int pict_type, double q )
 {
     x264_ratecontrol_t *rcc = h->rc;
@@ -2241,13 +2246,32 @@ static double clip_qscale( x264_t *h, int pict_type, double q )
     double lmax = rcc->lmax[pict_type];
     if( rcc->rate_factor_max_increment )
         lmax = X264_MIN( lmax, qp2qscale( rcc->qp_novbv + rcc->rate_factor_max_increment ) );
-    double q0 = q;
 
+    if( lmin==lmax )
+        return lmin;
+    else if( rcc->b_2pass )
+    {
+        double min2 = log( lmin );
+        double max2 = log( lmax );
+        q = (log(q) - min2)/(max2-min2) - 0.5;
+        q = 1.0/(1.0 + exp( -4*q ));
+        q = q*(max2-min2) + min2;
+        return exp( q );
+    }
+    else
+        return x264_clip3f( q, lmin, lmax );
+}
+
+// apply VBV constraints
+static double vbv_pass1( x264_t *h, int pict_type, double q )
+{
+    x264_ratecontrol_t *rcc = h->rc;
     /* B-frames are not directly subject to VBV,
      * since they are controlled by the P-frames' QPs. */
 
     if( rcc->b_vbv && rcc->last_satd > 0 )
     {
+        double q0 = q;
         double fenc_cpb_duration = (double)h->fenc->i_cpb_duration *
                                    h->sps->vui.i_num_units_in_tick / h->sps->vui.i_time_scale;
         /* Lookahead VBV: raise the quantizer as necessary such that no frames in
@@ -2365,29 +2389,11 @@ static double clip_qscale( x264_t *h, int pict_type, double q )
             q = X264_MAX( q0/2, q );
         }
 
-        /* Apply MinCR and buffer fill restrictions */
-        double bits = predict_size( &rcc->pred[h->sh.i_type], q, rcc->last_satd );
-        double frame_size_maximum = X264_MIN( rcc->frame_size_maximum, X264_MAX( rcc->buffer_fill, 0.001 ) );
-        if( bits > frame_size_maximum )
-            q *= bits / frame_size_maximum;
-
         if( !rcc->b_vbv_min_rate )
             q = X264_MAX( q0, q );
     }
 
-    if( lmin==lmax )
-        return lmin;
-    else if( rcc->b_2pass )
-    {
-        double min2 = log( lmin );
-        double max2 = log( lmax );
-        q = (log(q) - min2)/(max2-min2) - 0.5;
-        q = 1.0/(1.0 + exp( -4*q ));
-        q = q*(max2-min2) + min2;
-        return exp( q );
-    }
-    else
-        return x264_clip3f( q, lmin, lmax );
+    return clip_qscale( h, pict_type, q );
 }
 
 // update qscale for 1 frame based on actual bits used so far
@@ -2449,9 +2455,18 @@ static float rate_estimate_qscale( x264_t *h )
             rcc->frame_size_planned = qscale2bits( &rce, q );
         else
             rcc->frame_size_planned = predict_size( rcc->pred_b_from_p, q, h->fref[1][h->i_ref[1]-1]->i_satd );
-        /* Limit planned size by MinCR */
+
+        /* Apply MinCR and buffer fill restrictions */
         if( rcc->b_vbv )
-            rcc->frame_size_planned = X264_MIN( rcc->frame_size_planned, rcc->frame_size_maximum );
+        {
+            double frame_size_maximum = X264_MIN( rcc->frame_size_maximum, X264_MAX( rcc->buffer_fill, 0.001 ) );
+            if( rcc->frame_size_planned > frame_size_maximum )
+            {
+                q *= rcc->frame_size_planned / frame_size_maximum;
+                rcc->frame_size_planned = frame_size_maximum;
+            }
+        }
+
         rcc->frame_size_estimated = rcc->frame_size_planned;
 
         /* For row SATDs */
@@ -2613,8 +2628,7 @@ static float rate_estimate_qscale( x264_t *h )
             }
             rcc->qp_novbv = qscale2qp( q );
 
-            //FIXME use get_diff_limited_q() ?
-            q = clip_qscale( h, pict_type, q );
+            q = vbv_pass1( h, pict_type, q );
         }
 
         rcc->last_qscale_for[pict_type] =
@@ -2628,12 +2642,21 @@ static float rate_estimate_qscale( x264_t *h )
         else
             rcc->frame_size_planned = predict_size( &rcc->pred[h->sh.i_type], q, rcc->last_satd );
 
-        /* Always use up the whole VBV in this case. */
-        if( rcc->single_frame_vbv )
-            rcc->frame_size_planned = rcc->buffer_rate;
-        /* Limit planned size by MinCR */
+        /* Apply MinCR and buffer fill restrictions */
         if( rcc->b_vbv )
-            rcc->frame_size_planned = X264_MIN( rcc->frame_size_planned, rcc->frame_size_maximum );
+        {
+            double frame_size_maximum = X264_MIN( rcc->frame_size_maximum, X264_MAX( rcc->buffer_fill, 0.001 ) );
+            if( rcc->frame_size_planned > frame_size_maximum )
+            {
+                q *= rcc->frame_size_planned / frame_size_maximum;
+                rcc->frame_size_planned = frame_size_maximum;
+            }
+
+            /* Always use up the whole VBV in this case. */
+            if( rcc->single_frame_vbv )
+                rcc->frame_size_planned = X264_MIN( rcc->buffer_rate, frame_size_maximum );
+        }
+
         rcc->frame_size_estimated = rcc->frame_size_planned;
         return q;
     }



View it on GitLab: https://code.videolan.org/videolan/x264/-/commit/d46938dec10ceab74eb26d281d434fa284c7fbb9

-- 
View it on GitLab: https://code.videolan.org/videolan/x264/-/commit/d46938dec10ceab74eb26d281d434fa284c7fbb9
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the x264-devel mailing list