Index: encoder/ratecontrol.c =================================================================== --- encoder/ratecontrol.c (revision 3) +++ encoder/ratecontrol.c (revision 16) @@ -1453,6 +1453,160 @@ /* the rest of the variables are either constant or thread-local */ } +FILE *fh_vbv; + +static int find_underflow( x264_t *h, double *fills, int *t0, int *t1, int over ) +{ + x264_ratecontrol_t *rcc = h->rc; + const double buffer_min = (over ? .1 : .001) * rcc->buffer_size; + const double buffer_max = .999 * rcc->buffer_size; + double fill = fills[*t0-1]; + double parity = over ? 1. : -1.; + int i, start=-1, end=-1; + for(i=*t0; inum_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; +// fprintf(fh_vbv, "%d %.0f\n", 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 void fix_underflow( x264_t *h, double *fills, int t0, int t1, int over, double adjustment_limit ) +{ + x264_ratecontrol_t *rcc = h->rc; + double interval_size = 0; + double min_slope = 0; + double slope, frac; + int t_slope = 0; //debug only + int i; + for(i=t0+1; i<=t1; i++) + { + interval_size += qscale2bits(&rcc->entry[i], rcc->entry[i].new_qscale); + slope = fills[i] / interval_size; + if(slope < min_slope || i == t0+1) + { + t_slope = i; + min_slope = slope; + } + } + printf("interval [%d,%d] size:%.0f slope:%.4f @ %d\n", t0, t1, interval_size, min_slope, t_slope); + if(over) + frac = X264_MAX(1. - min_slope, adjustment_limit); + else + frac = X264_MIN(1.001 / (1. - min_slope), adjustment_limit); + for(i=t0+1; i<=t1; i++) + rcc->entry[i].new_qscale *= frac; + + // due to nonlinearities in qp2bits, the above code might have added slightly too many bits. + // make sure the buffer is still full at the end, so any error doesn't cary over into future frames. + if(over) + { + double fill = fills[t0]; + interval_size = 0; + for(i=t0+1; i<=t1; i++) + { + double bits = qscale2bits(&rcc->entry[i], rcc->entry[i].new_qscale); + interval_size += bits; + fill += rcc->buffer_rate - bits; + fills[i] = fill; + if(fill > rcc->buffer_size) + { + fill = rcc->buffer_size; + interval_size = 0; + } + } + if(fill < rcc->buffer_size*.999) + { + frac = 1. + (rcc->buffer_size*.999 - fill) / interval_size; + printf("adjust %.4f\n", frac-1.); + for(i=t0+1; i<=t1; i++) + rcc->entry[i].new_qscale *= frac; + } + } +} + +static double count_expected_bits( x264_t *h ) +{ + x264_ratecontrol_t *rcc = h->rc; + double expected_bits = 0; + int i; + for(i=0; inum_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 debug_dump_vbv( x264_t *h, double *fills ) +{ + x264_ratecontrol_t *rcc = h->rc; + double fill = rcc->buffer_size * h->param.rc.f_vbv_buffer_init; + int i; + for(i=0; inum_entries; i++) + { + fill += rcc->buffer_rate - qscale2bits(&rcc->entry[i], rcc->entry[i].new_qscale); + fill = x264_clip3f(fill, rcc->buffer_size*-.5, rcc->buffer_size); + fprintf(fh_vbv, "%d %.0f\n", i, fill); + } +} + +static void vbv_pass2( x264_t *h ) +{ + 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, prev_bits, adjustment_limit; + int t0, t1, space; + + fills++; + fills[-1] = rcc->buffer_size * (1. - h->param.rc.f_vbv_buffer_init); + fh_vbv = fopen("vbv.log", "w"); + + debug_dump_vbv(h, fills); + + t0 = 0; + while(find_underflow(h, fills, &t0, &t1, 0)) + fix_underflow(h, fills, t0, t1, 0, 1.1); + + debug_dump_vbv(h, fills); + + fills[-1] = rcc->buffer_size * h->param.rc.f_vbv_buffer_init; + expected_bits = count_expected_bits(h); + do { + adjustment_limit = X264_MAX(expected_bits / all_available_bits, 0.9); + space = 0; + t0 = 0; + while(find_underflow(h, fills, &t0, &t1, 1)) + { + fix_underflow(h, fills, t0, t1, 1, adjustment_limit); + t0 = t1; + space = 1; + } + prev_bits = expected_bits; + expected_bits = count_expected_bits(h); + } while(space && expected_bits < .995*all_available_bits && expected_bits >= prev_bits+1); + + debug_dump_vbv(h, fills); + + fclose(fh_vbv); + fflush(stdout); + x264_free(fills-1); +} + static int init_pass2( x264_t *h ) { x264_ratecontrol_t *rcc = h->rc; @@ -1541,7 +1695,6 @@ 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; inum_entries; i++){ @@ -1578,15 +1731,9 @@ /* find expected bits */ for(i=0; inum_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); @@ -1597,6 +1744,10 @@ 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;