};
+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 );
}
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 )
{
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 )
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;
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 )
{
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);
}