int p_tex_bits;
int misc_bits;
uint64_t expected_bits;
+ double expected_vbv;
float new_qscale;
int new_qp;
int i_count;
int frame_count[5]; /* number of frames of each type */
/* MBRC stuff */
+ double frame_size_estimated;
double frame_size_planned;
predictor_t *row_pred;
predictor_t row_preds[5];
rc->rate_tolerance = 0.01;
}
- h->mb.b_variable_qp = (rc->b_vbv && !rc->b_2pass) || h->param.rc.i_aq_mode;
+ h->mb.b_variable_qp = rc->b_vbv || h->param.rc.i_aq_mode;
if( rc->b_abr )
{
x264_free( rc );
}
+void x264_ratecontrol_set_estimated_size( x264_t *h, int bits )
+{
+ h->rc->frame_size_estimated = bits;
+}
+
+int x264_ratecontrol_get_estimated_size( x264_t const *h)
+{
+ return h->rc->frame_size_estimated;
+}
+
static void accum_p_qp_update( x264_t *h, float qp )
{
x264_ratecontrol_t *rc = h->rc;
return (pred_s + pred_t) / 2;
}
-double predict_row_size_sum( x264_t *h, int y, int qp )
+double row_bits_so_far( x264_t *h, int y )
{
int i;
double bits = 0;
for( i = 0; i <= y; i++ )
bits += h->fdec->i_row_bits[i];
+ return bits;
+}
+
+double predict_row_size_sum( x264_t *h, int y, int qp )
+{
+ int i;
+ double bits = row_bits_so_far(h, y);
for( i = y+1; i < h->sps->i_mb_height; i++ )
bits += predict_row_size( h, i, qp );
return bits;
}
+
void x264_ratecontrol_mb( x264_t *h, int bits )
{
x264_ratecontrol_t *rc = h->rc;
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 || rc->b_2pass )
+ if( h->mb.i_mb_x != h->sps->i_mb_width - 1 || !rc->b_vbv)
return;
h->fdec->i_row_qp[y] = rc->qpm;
if( h->sh.i_type == SLICE_TYPE_B )
{
- /* B-frames shouldn't use lower QP than their reference frames */
+ /* B-frames shouldn't use lower QP than their reference frames.
+ * This code is a bit overzealous in limiting B-frame quantizers, but it helps avoid
+ * underflows due to the fact that B-frames are not explicitly covered by VBV. */
if( y < h->sps->i_mb_height-1 )
{
- rc->qpm = X264_MAX( rc->qp,
- X264_MIN( h->fref0[0]->i_row_qp[y+1],
- h->fref1[0]->i_row_qp[y+1] ));
+ int i_estimated;
+ int avg_qp = X264_MAX(h->fref0[0]->i_row_qp[y+1], h->fref1[0]->i_row_qp[y+1])
+ + rc->pb_offset * ((h->fenc->i_type == X264_TYPE_BREF) ? 0.5 : 1);
+ rc->qpm = X264_MIN(X264_MAX( rc->qp, avg_qp), 51); //avg_qp could go higher than 51 due to pb_offset
+ i_estimated = row_bits_so_far(h, y); //FIXME: compute full estimated size
+ if (i_estimated > h->rc->frame_size_planned)
+ x264_frame_size_estimated_set(h, i_estimated);
}
}
else
int i_qp_max = X264_MIN( prev_row_qp + h->param.rc.i_qp_step, h->param.rc.i_qp_max );
int i_qp_min = X264_MAX( prev_row_qp - h->param.rc.i_qp_step, h->param.rc.i_qp_min );
float buffer_left_planned = rc->buffer_fill - rc->frame_size_planned;
+ float rc_tol = 1;
+ float headroom = 0;
+
+ /* Don't modify the row QPs until a sufficent amount of the bits of the frame have been processed, in case a flat */
+ /* area at the top of the frame was measured inaccurately. */
+ if(row_bits_so_far(h,y) < 0.05 * rc->frame_size_planned)
+ return;
+
+ headroom = buffer_left_planned/rc->buffer_size;
+ if(h->sh.i_type != SLICE_TYPE_I)
+ headroom /= 2;
+ rc_tol += headroom;
if( !rc->b_vbv_min_rate )
i_qp_min = X264_MAX( i_qp_min, h->sh.i_qp );
while( rc->qpm < i_qp_max
- && (b1 > rc->frame_size_planned * 1.15
+ && (b1 > rc->frame_size_planned * rc_tol
|| (rc->buffer_fill - b1 < buffer_left_planned * 0.5)))
{
rc->qpm ++;
b1 = predict_row_size_sum( h, y, rc->qpm );
}
+ /* avoid VBV underflow */
+ while( (rc->qpm < h->param.rc.i_qp_max)
+ && (rc->buffer_fill - b1 < rc->buffer_size * 0.005))
+ {
+ rc->qpm ++;
+ b1 = predict_row_size_sum( h, y, rc->qpm );
+ }
+
while( rc->qpm > i_qp_min
- && buffer_left_planned > rc->buffer_size * 0.4
+ && ((buffer_left_planned > rc->buffer_size * 0.4) || rc->qpm > h->fdec->i_row_qp[0])
&& ((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 --;
b1 = predict_row_size_sum( h, y, rc->qpm );
}
+ x264_frame_size_estimated_set(h, b1);
}
}
}
return;
rct->buffer_fill_final += rct->buffer_rate - bits;
- if( rct->buffer_fill_final < 0 && !rct->b_2pass )
+ if( rct->buffer_fill_final < 0 )
x264_log( h, X264_LOG_WARNING, "VBV underflow (%.0f bits)\n", rct->buffer_fill_final );
rct->buffer_fill_final = x264_clip3f( rct->buffer_fill_final, 0, rct->buffer_size );
}
double bits = t->rc->frame_size_planned;
if( !t->b_thread_active )
continue;
+ bits = X264_MAX(bits, x264_frame_size_estimated_get(t));
rcc->buffer_fill += rcc->buffer_rate - bits;
rcc->buffer_fill = x264_clip3( rcc->buffer_fill, 0, rcc->buffer_size );
}
q += rcc->pb_offset;
rcc->frame_size_planned = predict_size( rcc->pred_b_from_p, q, h->fref1[h->i_ref1-1]->i_satd );
+ x264_frame_size_estimated_set(h, rcc->frame_size_planned);
rcc->last_satd = 0;
return qp2qscale(q);
}
double w = x264_clip3f( time*100, 0.0, 1.0 );
q *= pow( (double)total_bits / rcc->expected_bits_sum, w );
}
+ if( rcc->b_vbv )
+ {
+ double expected_size = qscale2bits(&rce, q);
+ double expected_vbv = rcc->buffer_fill + rcc->buffer_rate - expected_size;
+ double expected_fullness = rce.expected_vbv / rcc->buffer_size;
+ double qmax = q*(2 - expected_fullness);
+ double size_constraint = 1 + expected_fullness;
+ if (expected_fullness < .05)
+ qmax = lmax;
+ qmax = X264_MIN(qmax, lmax);
+ while( (expected_vbv < rce.expected_vbv/size_constraint) && (q < qmax) )
+ {
+ q *= 1.05;
+ expected_size = qscale2bits(&rce, q);
+ expected_vbv = rcc->buffer_fill + rcc->buffer_rate - expected_size;
+ }
+ rcc->last_satd = x264_rc_analyse_slice( h );
+ }
q = x264_clip3f( q, lmin, lmax );
}
else /* 1pass ABR */
rcc->last_qscale_for[pict_type] =
rcc->last_qscale = q;
- if( !rcc->b_2pass && h->fenc->i_frame == 0 )
+ if( !(rcc->b_2pass && !rcc->b_vbv) && h->fenc->i_frame == 0 )
rcc->last_qscale_for[SLICE_TYPE_P] = q;
- rcc->frame_size_planned = predict_size( &rcc->pred[h->sh.i_type], q, rcc->last_satd );
+ if( rcc->b_2pass && rcc->b_vbv)
+ rcc->frame_size_planned = qscale2bits(&rce, q);
+ else
+ rcc->frame_size_planned = predict_size( &rcc->pred[h->sh.i_type], q, rcc->last_satd );
+ x264_frame_size_estimated_set(h, rcc->frame_size_planned);
return q;
}
}
/* the rest of the variables are either constant or thread-local */
}
+static int find_underflow( x264_t *h, double *fills, int *t0, int *t1, int over )
+{
+ /* find an interval ending on an overflow or underflow (depending on whether
+ * we're adding or removing bits), and starting on the earliest frame that
+ * can influence the buffer fill of that end frame. */
+ x264_ratecontrol_t *rcc = h->rc;
+ const double buffer_min = (over ? .1 : .1) * rcc->buffer_size;
+ const double buffer_max = .9 * rcc->buffer_size;
+ double fill = fills[*t0-1];
+ double parity = over ? 1. : -1.;
+ int i, start=-1, end=-1;
+ for(i = *t0; i < rcc->num_entries; i++)
+ {
+ fill += (rcc->buffer_rate - qscale2bits(&rcc->entry[i], rcc->entry[i].new_qscale)) * parity;
+ fill = x264_clip3f(fill, 0, rcc->buffer_size);
+ fills[i] = fill;
+ if(fill <= buffer_min || i == 0)
+ {
+ if(end >= 0)
+ break;
+ start = i;
+ }
+ else if(fill >= buffer_max && start >= 0)
+ end = i;
+ }
+ *t0 = start;
+ *t1 = end;
+ return start>=0 && end>=0;
+}
+
+static int fix_underflow( x264_t *h, int t0, int t1, double adjustment, double qscale_min, double qscale_max)
+{
+ x264_ratecontrol_t *rcc = h->rc;
+ double qscale_orig, qscale_new;
+ int i;
+ int adjusted = 0;
+ if(t0 > 0)
+ t0++;
+ for(i = t0; i <= t1; i++)
+ {
+ qscale_orig = rcc->entry[i].new_qscale;
+ qscale_orig = x264_clip3f(qscale_orig, qscale_min, qscale_max);
+ qscale_new = qscale_orig * adjustment;
+ qscale_new = x264_clip3f(qscale_new, qscale_min, qscale_max);
+ rcc->entry[i].new_qscale = qscale_new;
+ adjusted = adjusted || (qscale_new != qscale_orig);
+ }
+ return adjusted;
+}
+
+static double count_expected_bits( x264_t *h )
+{
+ x264_ratecontrol_t *rcc = h->rc;
+ double expected_bits = 0;
+ int i;
+ for(i = 0; i < rcc->num_entries; i++)
+ {
+ ratecontrol_entry_t *rce = &rcc->entry[i];
+ rce->expected_bits = expected_bits;
+ expected_bits += qscale2bits(rce, rce->new_qscale);
+ }
+ return expected_bits;
+}
+
+static void vbv_pass2( x264_t *h )
+{
+ /* for each interval of buffer_full .. underflow, uniformly increase the qp of all
+ * frames in the interval until either buffer is full at some intermediate frame or the
+ * last frame in the interval no longer underflows. Recompute intervals and repeat.
+ * Then do the converse to put bits back into overflow areas until target size is met */
+
+ x264_ratecontrol_t *rcc = h->rc;
+ double *fills = x264_malloc((rcc->num_entries+1)*sizeof(double));
+ double all_available_bits = h->param.rc.i_bitrate * 1000. * rcc->num_entries / rcc->fps;
+ double expected_bits = 0;
+ double adjustment;
+ double prev_bits = 0;
+ int i, t0, t1;
+ double qscale_min = qp2qscale(h->param.rc.i_qp_min);
+ double qscale_max = qp2qscale(h->param.rc.i_qp_max);
+ int iterations = 0;
+ int adj_min, adj_max;
+
+ fills++;
+
+ /* adjust overall stream size */
+ do
+ {
+ iterations++;
+ prev_bits = expected_bits;
+
+ if(expected_bits != 0)
+ { /* not first iteration */
+ adjustment = X264_MAX(X264_MIN(expected_bits / all_available_bits, 0.999), 0.9);
+ fills[-1] = rcc->buffer_size * h->param.rc.f_vbv_buffer_init;
+ t0 = 0;
+ /* fix overflows */
+ adj_min = 1;
+ while(adj_min && find_underflow(h, fills, &t0, &t1, 1))
+ {
+ adj_min = fix_underflow(h, t0, t1, adjustment, qscale_min, qscale_max);
+ t0 = t1;
+ }
+ }
+
+ fills[-1] = rcc->buffer_size * (1. - h->param.rc.f_vbv_buffer_init);
+ t0 = 0;
+ /* fix underflows -- should be done after overflow, as we'd better undersize target than underflowing VBV */
+ adj_max = 1;
+ while(adj_max && find_underflow(h, fills, &t0, &t1, 0))
+ adj_max = fix_underflow(h, t0, t1, 1.001, qscale_min, qscale_max);
+
+ expected_bits = count_expected_bits(h);
+ } while(expected_bits < .995 * all_available_bits && expected_bits > prev_bits);
+
+ if (!adj_max)
+ x264_log( h, X264_LOG_WARNING, "vbv-maxrate issue, qpmax or vbv-maxrate too low\n");
+
+ /* store expected vbv filling values for tracking when encoding */
+ for(i = 0; i < rcc->num_entries; i++)
+ rcc->entry[i].expected_vbv = rcc->buffer_size - fills[i];
+
+ x264_free(fills-1);
+}
+
static int init_pass2( x264_t *h )
{
x264_ratecontrol_t *rcc = h->rc;
rcc->last_non_b_pict_type = -1;
rcc->last_accum_p_norm = 1;
rcc->accum_p_norm = 0;
- rcc->buffer_fill = rcc->buffer_size * h->param.rc.f_vbv_buffer_init;
/* find qscale */
for(i=0; i<rcc->num_entries; i++){
/* find expected bits */
for(i=0; i<rcc->num_entries; i++){
ratecontrol_entry_t *rce = &rcc->entry[i];
- double bits;
rce->new_qscale = clip_qscale(h, rce->pict_type, blurred_qscale[i]);
assert(rce->new_qscale >= 0);
- bits = qscale2bits(rce, rce->new_qscale);
-
- rce->expected_bits = expected_bits;
- expected_bits += bits;
- update_vbv(h, bits);
- rcc->buffer_fill = rcc->buffer_fill_final;
+ expected_bits += qscale2bits(rce, rce->new_qscale);
}
-//printf("expected:%llu available:%llu factor:%lf avgQ:%lf\n", (uint64_t)expected_bits, all_available_bits, rate_factor);
if(expected_bits > all_available_bits) rate_factor -= step;
}
if(filter_size > 1)
x264_free(blurred_qscale);
+ if(rcc->b_vbv)
+ vbv_pass2(h);
+ expected_bits = count_expected_bits(h);
+
if(fabs(expected_bits/all_available_bits - 1.0) > 0.01)
{
double avgq = 0;
avgq += rcc->entry[i].new_qscale;
avgq = qscale2qp(avgq / rcc->num_entries);
- x264_log(h, X264_LOG_WARNING, "Error: 2pass curve failed to converge\n");
+ if ((expected_bits > all_available_bits) || (!rcc->b_vbv))
+ x264_log(h, X264_LOG_WARNING, "Error: 2pass curve failed to converge\n");
x264_log(h, X264_LOG_WARNING, "target: %.2f kbit/s, expected: %.2f kbit/s, avg QP: %.4f\n",
(float)h->param.rc.i_bitrate,
expected_bits * rcc->fps / (rcc->num_entries * 1000.),
else
x264_log(h, X264_LOG_WARNING, "try increasing target bitrate\n");
}
- else
+ else if(!(rcc->b_2pass && rcc->b_vbv))
x264_log(h, X264_LOG_WARNING, "internal error\n");
}