]> git.sesse.net Git - x264/blobdiff - encoder/ratecontrol.c
SATD-based decision for 8x8 transform in inter-MBs.
[x264] / encoder / ratecontrol.c
index f79e925c4a69d6711a64426c5df53810b3444ac0..0360654926a318f14b17f185bc3140a39cc46714 100644 (file)
@@ -132,6 +132,7 @@ struct x264_ratecontrol_t
 };
 
 
+static int parse_zones( x264_t *h );
 static int init_pass2(x264_t *);
 static float rate_estimate_qscale( x264_t *h, int pict_type );
 static void update_vbv( x264_t *h, int bits );
@@ -218,6 +219,10 @@ int x264_ratecontrol_new( x264_t *h )
     }
     else if( h->param.rc.i_vbv_max_bitrate || h->param.rc.i_vbv_buffer_size )
         x264_log(h, X264_LOG_ERROR, "VBV maxrate or buffer size specified, but not both.\n");
+    if(rc->rate_tolerance < 0.01) {
+        x264_log(h, X264_LOG_ERROR, "bitrate tolerance too small, using .01\n");
+        rc->rate_tolerance = 0.01;
+    }
 
     if( rc->b_abr )
     {
@@ -252,29 +257,8 @@ int x264_ratecontrol_new( x264_t *h )
     rc->lmax[SLICE_TYPE_B] *= fabs(h->param.f_pb_factor);
 #endif
 
-    if( h->param.rc.i_zones > 0 )
-    {
-        for( i = 0; i < h->param.rc.i_zones; i++ )
-        {
-            x264_zone_t z = h->param.rc.zones[i];
-            if( z.i_start < 0 || z.i_start > z.i_end )
-            {
-                x264_log( h, X264_LOG_ERROR, "invalid zone: start=%d end=%d\n",
-                          z.i_start, z.i_end );
-                return -1;
-            }
-            else if( !z.b_force_qp && z.f_bitrate_factor <= 0 )
-            {
-                x264_log( h, X264_LOG_ERROR, "invalid zone: bitrate_factor=%f\n",
-                          z.f_bitrate_factor );
-                return -1;
-            }
-        }
-
-        rc->i_zones = h->param.rc.i_zones;
-        rc->zones = x264_malloc( rc->i_zones * sizeof(x264_zone_t) );
-        memcpy( rc->zones, h->param.rc.zones, rc->i_zones * sizeof(x264_zone_t) );
-    }
+    if( parse_zones( h ) < 0 )
+        return -1;
 
     /* Load stat file and init 2pass algo */
     if( h->param.rc.b_stat_read )
@@ -395,6 +379,63 @@ int x264_ratecontrol_new( x264_t *h )
     return 0;
 }
 
+static int parse_zones( x264_t *h )
+{
+    x264_ratecontrol_t *rc = h->rc;
+    int i;
+    if( h->param.rc.psz_zones && !h->param.rc.i_zones )
+    {
+        char *p;
+        h->param.rc.i_zones = 1;
+        for( p = h->param.rc.psz_zones; *p; p++ )
+            h->param.rc.i_zones += (*p == '/');
+        h->param.rc.zones = x264_malloc( h->param.rc.i_zones * sizeof(x264_zone_t) );
+        p = h->param.rc.psz_zones;
+        for( i = 0; i < h->param.rc.i_zones; i++)
+        {
+            x264_zone_t *z = &h->param.rc.zones[i];
+            if( 3 == sscanf(p, "%u,%u,q=%u", &z->i_start, &z->i_end, &z->i_qp) )
+                z->b_force_qp = 1;
+            else if( 3 == sscanf(p, "%u,%u,b=%f", &z->i_start, &z->i_end, &z->f_bitrate_factor) )
+                z->b_force_qp = 0;
+            else
+            {
+                char *slash = strchr(p, '/');
+                if(slash) *slash = '\0';
+                x264_log( h, X264_LOG_ERROR, "invalid zone: \"%s\"\n", p );
+                return -1;
+            }
+            p = strchr(p, '/') + 1;
+        }
+    }
+
+    if( h->param.rc.i_zones > 0 )
+    {
+        for( i = 0; i < h->param.rc.i_zones; i++ )
+        {
+            x264_zone_t z = h->param.rc.zones[i];
+            if( z.i_start < 0 || z.i_start > z.i_end )
+            {
+                x264_log( h, X264_LOG_ERROR, "invalid zone: start=%d end=%d\n",
+                          z.i_start, z.i_end );
+                return -1;
+            }
+            else if( !z.b_force_qp && z.f_bitrate_factor <= 0 )
+            {
+                x264_log( h, X264_LOG_ERROR, "invalid zone: bitrate_factor=%f\n",
+                          z.f_bitrate_factor );
+                return -1;
+            }
+        }
+
+        rc->i_zones = h->param.rc.i_zones;
+        rc->zones = x264_malloc( rc->i_zones * sizeof(x264_zone_t) );
+        memcpy( rc->zones, h->param.rc.zones, rc->i_zones * sizeof(x264_zone_t) );
+    }
+
+    return 0;
+}
+
 void x264_ratecontrol_delete( x264_t *h )
 {
     x264_ratecontrol_t *rc = h->rc;
@@ -499,14 +540,16 @@ int x264_ratecontrol_slice_type( x264_t *h, int frame_num )
 void x264_ratecontrol_end( x264_t *h, int bits )
 {
     x264_ratecontrol_t *rc = h->rc;
+    const int *mbs = h->stat.frame.i_mb_count;
     int i;
 
     x264_cpu_restore( h->param.cpu );
 
-    h->stat.frame.i_mb_count_skip = h->stat.frame.i_mb_count[P_SKIP] + h->stat.frame.i_mb_count[B_SKIP];
-    h->stat.frame.i_mb_count_p = h->stat.frame.i_mb_count[P_L0] + h->stat.frame.i_mb_count[P_8x8];
+    h->stat.frame.i_mb_count_skip = mbs[P_SKIP] + mbs[B_SKIP];
+    h->stat.frame.i_mb_count_i = mbs[I_16x16] + mbs[I_8x8] + mbs[I_4x4];
+    h->stat.frame.i_mb_count_p = mbs[P_L0] + mbs[P_8x8];
     for( i = B_DIRECT; i < B_8x8; i++ )
-        h->stat.frame.i_mb_count_p += h->stat.frame.i_mb_count[i];
+        h->stat.frame.i_mb_count_p += mbs[i];
 
     if( h->param.rc.b_stat_write )
     {
@@ -519,7 +562,7 @@ void x264_ratecontrol_end( x264_t *h, int bits )
                  c_type, rc->qpa,
                  h->stat.frame.i_itex_bits, h->stat.frame.i_ptex_bits,
                  h->stat.frame.i_hdr_bits, h->stat.frame.i_misc_bits,
-                 h->stat.frame.i_mb_count[I_4x4] + h->stat.frame.i_mb_count[I_16x16],
+                 h->stat.frame.i_mb_count_i,
                  h->stat.frame.i_mb_count_p,
                  h->stat.frame.i_mb_count_skip);
     }