* $Id: ratecontrol.c,v 1.1 2004/06/03 19:27:08 fenrir Exp $
*
* Authors: Måns Rullgård <mru@mru.ath.cx>
+ * 2 pass code: Michael Niedermayer <michaelni@gmx.at>
+ * Loren Merritt
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
*****************************************************************************/
#define _ISOC99_SOURCE
-
+#undef NDEBUG // always check asserts, the speed effect is far too small to disable them
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <limits.h>
+#include <assert.h>
#include "../core/common.h"
#include "../core/cpu.h"
+#include "../core/macroblock.h"
#include "ratecontrol.h"
#ifdef SYS_MACOSX
#define exp2f(x) ( (float) exp2( (x) ) )
#endif
+
+typedef struct
+{
+ int pict_type;
+ float qscale;
+ int mv_bits;
+ int i_tex_bits;
+ int p_tex_bits;
+ int misc_bits;
+ uint64_t expected_bits;
+ int new_pict_type;
+ float new_qscale;
+ int new_qp;
+ int i_count;
+ int p_count;
+ int s_count;
+ int f_code;
+ int b_code;
+} ratecontrol_entry_t;
+
struct x264_ratecontrol_t
{
/* constants */
- float fps;
+ double fps;
int gop_size;
int bitrate;
- int nmb; /* number of MBs */
+ int nmb; /* number of macroblocks in a frame */
int buffer_size;
int rcbufrate;
int init_qp;
+ /* 1st pass stuff */
int gop_qp;
int buffer_fullness;
int frames; /* frames in current gop */
int nzcoeffs; /* # of 0-quantized coefficients */
int ncoeffs; /* total # of coefficients */
int overhead;
+
+ /* 2pass stuff */
+ FILE *p_stat_file_out;
+
+ int num_entries; /* number of ratecontrol_entry_ts */
+ ratecontrol_entry_t *entry;
+ double last_qscale;
+ double last_qscale_for[5]; /* last qscale for a specific pict type, used for max_diff & ipb factor stuff */
+ int last_non_b_pict_type;
+ double lmin[5]; /* min qscale by frame type */
+ double lmax[5];
+ double i_cplx_sum[5]; /* estimated total texture bits in intra MBs at qscale=1 */
+ double p_cplx_sum[5];
+ double mv_bits_sum[5];
+ int frame_count[5]; /* number of frames of each type */
};
+
+static int init_pass2(x264_t *);
+static float rate_estimate_qscale( x264_t *h, int pict_type );
+
+/* Terminology:
+ * qp = h.264's quantizer
+ * qscale = an arbitrary linear scale, mappable to qp
+ */
+static inline double qp2qscale(double qp)
+{
+ return 0.85 * pow(2.0, ( qp - 12.0 ) / 6.0);
+}
+static inline double qscale2qp(double qscale)
+{
+ return 12.0 + 6.0 * log(qscale/0.85) / log(2.0);
+}
+
+static inline double qscale2bits(ratecontrol_entry_t *rce, double qscale)
+{
+ if(qscale<=0.0)
+ {
+ fprintf(stderr, "qscale<=0.0\n");
+ qscale = 0.1;
+ }
+ return (double)(rce->i_tex_bits + rce->p_tex_bits + 1) * rce->qscale / qscale;
+}
+
+static inline double bits2qscale(ratecontrol_entry_t *rce, double bits)
+{
+ if(bits<0.9)
+ {
+ fprintf(stderr, "bits<0.9\n");
+ bits = 1.0;
+ }
+ return rce->qscale * (double)(rce->i_tex_bits + rce->p_tex_bits + 1) / bits;
+}
+
+
int x264_ratecontrol_new( x264_t *h )
{
- x264_ratecontrol_t *rc = x264_malloc( sizeof( x264_ratecontrol_t ) );
+ x264_ratecontrol_t *rc;
float bpp;
+ int i;
+ /* Needed(?) for 2 pass */
+ x264_cpu_restore( h->param.cpu );
+
+ h->rc = rc = x264_malloc( sizeof( x264_ratecontrol_t ) );
memset(rc, 0, sizeof(*rc));
/* FIXME: use integers */
rc->fps = 25.0;
rc->gop_size = h->param.i_iframe;
- rc->bitrate = h->param.i_bitrate * 1000;
+ rc->bitrate = h->param.rc.i_bitrate * 1000;
rc->nmb = ((h->param.i_width + 15) / 16) * ((h->param.i_height + 15) / 16);
- rc->qp = h->param.i_qp_constant;
+ rc->qp = h->param.rc.i_qp_constant;
rc->qpa = rc->qp;
rc->qpm = rc->qp;
- rc->buffer_size = h->param.i_rc_buffer_size * 1000;
- rc->buffer_fullness = h->param.i_rc_init_buffer;
+ rc->buffer_size = h->param.rc.i_rc_buffer_size * 1000;
+ rc->buffer_fullness = h->param.rc.i_rc_init_buffer;
rc->rcbufrate = rc->bitrate / rc->fps;
if(rc->buffer_size < rc->rcbufrate){
x264_log(h, X264_LOG_DEBUG, "%f fps, %i bps, bufsize %i\n",
rc->fps, rc->bitrate, rc->buffer_size);
- h->rc = rc;
+
+ for( i = 0; i < 5; i++ )
+ {
+ rc->last_qscale_for[i] = qp2qscale(26);
+ rc->lmin[i] = qp2qscale( h->param.rc.i_qp_min );
+ rc->lmax[i] = qp2qscale( h->param.rc.i_qp_max );
+ }
+#if 0 // FIXME: do we want to assign lmin/lmax based on ip_factor, or leave them all the same?
+ rc->lmin[SLICE_TYPE_I] /= fabs(h->param.f_ip_factor);
+ rc->lmax[SLICE_TYPE_I] /= fabs(h->param.f_ip_factor);
+ rc->lmin[SLICE_TYPE_B] *= fabs(h->param.f_pb_factor);
+ rc->lmax[SLICE_TYPE_B] *= fabs(h->param.f_pb_factor);
+#endif
+
+ /* Load stat file and init 2pass algo */
+ if( h->param.rc.b_stat_read )
+ {
+ int stats_size;
+ char *p, *stats_in;
+ FILE *stats_file;
+
+ /* read 1st pass stats */
+ assert( h->param.rc.psz_stat_in );
+ stats_file = fopen( h->param.rc.psz_stat_in, "r");
+ if(!stats_file)
+ {
+ x264_log(h, X264_LOG_ERROR, "ratecontrol_init: can't open stats file\n");
+ return -1;
+ }
+ // FIXME: error checking
+ fseek(stats_file, 0, SEEK_END);
+ stats_size = ftell(stats_file);
+ fseek(stats_file, 0, SEEK_SET);
+ stats_in = x264_malloc(stats_size+10);
+ fread(stats_in, 1, stats_size, stats_file);
+ fclose(stats_file);
+
+ /* find number of pics */
+ p = stats_in;
+ for(i=-1; p; i++){
+ p = strchr(p+1, ';');
+ }
+ i += h->param.i_bframe;
+ rc->entry = (ratecontrol_entry_t*) x264_malloc(i*sizeof(ratecontrol_entry_t));
+ memset(rc->entry, 0, i*sizeof(ratecontrol_entry_t));
+ rc->num_entries= i;
+
+ /* init all to skipped p frames */
+ for(i=0; i<rc->num_entries; i++){
+ ratecontrol_entry_t *rce = &rc->entry[i];
+ rce->pict_type = rce->new_pict_type = SLICE_TYPE_P;
+ rce->qscale = rce->new_qscale = qp2qscale(20);
+ rce->misc_bits = rc->nmb + 10;
+ rce->new_qp = 0;
+ }
+
+ /* read stats */
+ p = stats_in;
+ for(i=0; i < rc->num_entries - h->param.i_bframe; i++){
+ ratecontrol_entry_t *rce;
+ int picture_number;
+ int e;
+ char *next;
+ float qp;
+
+ next= strchr(p, ';');
+ if(next){
+ (*next)=0; //sscanf is unbelievably slow on looong strings
+ next++;
+ }
+ e = sscanf(p, " in:%d ", &picture_number);
+
+ assert(picture_number >= 0);
+ assert(picture_number < rc->num_entries);
+ rce = &rc->entry[picture_number];
+
+ e += sscanf(p, " in:%*d out:%*d type:%d q:%f itex:%d ptex:%d mv:%d misc:%d imb:%d pmb:%d smb:%d",
+ &rce->pict_type, &qp, &rce->i_tex_bits, &rce->p_tex_bits,
+ &rce->mv_bits, &rce->misc_bits, &rce->i_count, &rce->p_count, &rce->s_count);
+ if(e != 10){
+ x264_log(h, X264_LOG_ERROR, "statistics are damaged at line %d, parser out=%d\n", i, e);
+ return -1;
+ }
+ rce->qscale = qp2qscale(qp);
+ p = next;
+ }
+
+ x264_free(stats_in);
+
+ if(init_pass2(h) < 0) return -1;
+ }
+
+ /* Open output file */
+ if( h->param.rc.b_stat_write )
+ {
+ rc->p_stat_file_out = fopen( h->param.rc.psz_stat_out, "w" );
+ if( rc->p_stat_file_out == NULL )
+ {
+ x264_log(h, X264_LOG_ERROR, "ratecontrol_init: can't open stats file\n");
+ return -1;
+ }
+ }
return 0;
}
void x264_ratecontrol_delete( x264_t *h )
{
x264_ratecontrol_t *rc = h->rc;
+
+ if( rc->p_stat_file_out )
+ fclose( rc->p_stat_file_out );
+ if( rc->entry )
+ x264_free(rc->entry);
x264_free( rc );
}
float kp;
int gbuf;
- if(!h->param.b_cbr)
- return;
+ rc->slice_type = i_slice_type;
+ /* Needed ? */
x264_cpu_restore( h->param.cpu );
- rc->slice_type = i_slice_type;
+ if( h->param.rc.b_stat_read )
+ {
+ int frame = h->fenc->i_frame;
+ ratecontrol_entry_t *rce = &h->rc->entry[frame];
+
+ assert( frame >= 0 && frame < rc->num_entries );
+
+ rce->new_qscale = rate_estimate_qscale( h, i_slice_type );
+ rc->qpm = rc->qp = rce->new_qp = (int)(qscale2qp(rce->new_qscale) + 0.5);
+ return;
+ }
+ else if( !h->param.rc.b_cbr )
+ {
+ return;
+ }
switch(i_slice_type){
case SLICE_TYPE_I:
#endif
qp = x264_clip3(qp, rc->gop_qp - 4, rc->gop_qp + 4);
qp =
- x264_clip3(qp, h->param.i_qp_min, h->param.i_qp_max);
+ x264_clip3(qp, h->param.rc.i_qp_min, h->param.rc.i_qp_max);
rc->gop_qp = qp;
} else if(rc->frames > 4){
rc->gop_qp = rc->init_qp;
}
- kp = h->param.f_ip_factor * h->param.f_pb_factor;
+ kp = h->param.rc.f_ip_factor * h->param.rc.f_pb_factor;
x264_log(h, X264_LOG_DEBUG,"gbuf=%i bits_gop=%i frames=%i gop_qp=%i\n",
gbuf, rc->bits_gop, rc->frames, rc->gop_qp);
break;
case SLICE_TYPE_P:
- kp = h->param.f_pb_factor;
+ kp = h->param.rc.f_pb_factor;
break;
case SLICE_TYPE_B:
gbits = rc->bits_gop - rc->bits_last_gop;
fbits = kp * gbits /
- (h->param.f_ip_factor * h->param.f_pb_factor * iframes +
- h->param.f_pb_factor * pframes + bframes);
+ (h->param.rc.f_ip_factor * h->param.rc.f_pb_factor * iframes +
+ h->param.rc.f_pb_factor * pframes + bframes);
minbits = rc->buffer_fullness + rc->rcbufrate - rc->buffer_size;
if(minbits < 0)
else
zn = 0;
zn = x264_clip3(zn, 0, rc->ncoeffs);
- dqp = h->param.i_rc_sens * exp2f((float) rc->qpa / 6) *
+ dqp = h->param.rc.i_rc_sens * exp2f((float) rc->qpa / 6) *
(zn - rc->nzcoeffs) / rc->nzcoeffs;
- dqp = x264_clip3(dqp, -h->param.i_qp_step, h->param.i_qp_step);
+ dqp = x264_clip3(dqp, -h->param.rc.i_qp_step, h->param.rc.i_qp_step);
rc->qp = rc->qpa + dqp;
}
else if(rc->fbits < 1.2 * minbits)
rc->qp -= 1;
- rc->qp = x264_clip3(rc->qp, h->param.i_qp_min, h->param.i_qp_max);
+ rc->qp = x264_clip3(rc->qp, h->param.rc.i_qp_min, h->param.rc.i_qp_max);
rc->qpm = rc->qp;
x264_log(h, X264_LOG_DEBUG, "fbits=%i, qp=%i, z=%i, min=%i, max=%i\n",
int dqp;
int i;
- if( !h->param.b_cbr )
+ if( !h->param.rc.b_cbr || h->param.rc.b_stat_read )
return;
x264_cpu_restore( h->param.cpu );
zn = 0;
zn = x264_clip3(zn, 0, rcoeffs);
enz = rc->nzcoeffs * (rc->nmb - rc->mb) / rc->mb;
- dqp = (float) 2*h->param.i_rc_sens * exp2f((float) rc->qps / rc->mb / 6) *
+ dqp = (float) 2*h->param.rc.i_rc_sens * exp2f((float) rc->qps / rc->mb / 6) *
(zn - enz) / enz;
rc->qpm = x264_clip3(rc->qpm + dqp, rc->qp - 3, rc->qp + 3);
if(rbits <= 0)
rc->qpm++;
- rc->qpm = x264_clip3(rc->qpm, h->param.i_qp_min, h->param.i_qp_max);
+ rc->qpm = x264_clip3(rc->qpm, h->param.rc.i_qp_min, h->param.rc.i_qp_max);
}
int x264_ratecontrol_qp( x264_t *h )
return h->rc->qpm;
}
+int x264_ratecontrol_slice_type( x264_t *h, int frame_num )
+{
+ if( h->param.rc.b_stat_read )
+ {
+ assert(frame_num < h->rc->num_entries);
+ switch( h->rc->entry[frame_num].new_pict_type )
+ {
+ case SLICE_TYPE_I:
+ return X264_TYPE_I;
+
+ case SLICE_TYPE_B:
+ return X264_TYPE_B;
+
+ case SLICE_TYPE_P:
+ default:
+ return X264_TYPE_P;
+ }
+ }
+ else
+ {
+ return X264_TYPE_AUTO;
+ }
+}
+
void x264_ratecontrol_end( x264_t *h, int bits )
{
x264_ratecontrol_t *rc = h->rc;
- if(!h->param.b_cbr)
+ if( h->param.rc.b_stat_write )
+ {
+ fprintf( rc->p_stat_file_out,
+ "in:%d out:%d type:%d q:%.3f itex:%d ptex:%d mv:%d misc:%d imb:%d pmb:%d smb:%d;\n",
+ h->fenc->i_frame, h->i_frame-1,
+ rc->slice_type, (float)rc->qpm,
+ 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[P_L0] + h->stat.frame.i_mb_count[P_8x8],
+ h->stat.frame.i_mb_count[P_SKIP]);
+ }
+
+ if( !h->param.rc.b_cbr || h->param.rc.b_stat_read )
return;
rc->buffer_fullness += rc->rcbufrate - bits;
rc->frames++;
rc->mb = 0;
}
+
+/****************************************************************************
+ * 2 pass functions
+ ***************************************************************************/
+double x264_eval( char *s, double *const_value, const char **const_name,
+ double (**func1)(void *, double), const char **func1_name,
+ double (**func2)(void *, double, double), char **func2_name,
+ void *opaque );
+
+/**
+ * modifies the bitrate curve from pass1 for one frame
+ */
+static double get_qscale(x264_t *h, ratecontrol_entry_t *rce, double rate_factor)
+{
+ x264_ratecontrol_t *rcc= h->rc;
+ double bits;
+ //double q, avg_cplx;
+ const int pict_type = rce->new_pict_type;
+
+ x264_cpu_restore( h->param.cpu );
+
+ //avg_cplx = (rcc->i_cplx_sum[pict_type] + rcc->p_cplx_sum[pict_type]) / rcc->frame_count[pict_type];
+
+ double const_values[]={
+ rce->i_tex_bits * rce->qscale,
+ rce->p_tex_bits * rce->qscale,
+ (rce->i_tex_bits + rce->p_tex_bits) * rce->qscale,
+ rce->mv_bits / rcc->nmb,
+ (double)rce->i_count / rcc->nmb,
+ (double)rce->p_count / rcc->nmb,
+ (double)rce->s_count / rcc->nmb,
+ rce->pict_type == SLICE_TYPE_I,
+ rce->pict_type == SLICE_TYPE_P,
+ rce->pict_type == SLICE_TYPE_B,
+ h->param.rc.f_qcompress,
+ rcc->i_cplx_sum[SLICE_TYPE_I] / rcc->frame_count[SLICE_TYPE_I],
+ rcc->i_cplx_sum[SLICE_TYPE_P] / rcc->frame_count[SLICE_TYPE_P],
+ rcc->p_cplx_sum[SLICE_TYPE_P] / rcc->frame_count[SLICE_TYPE_P],
+ rcc->p_cplx_sum[SLICE_TYPE_B] / rcc->frame_count[SLICE_TYPE_B],
+ (rcc->i_cplx_sum[pict_type] + rcc->p_cplx_sum[pict_type]) / rcc->frame_count[pict_type],
+ 0
+ };
+ static const char *const_names[]={
+ "iTex",
+ "pTex",
+ "tex",
+ "mv",
+ "iCount",
+ "pCount",
+ "sCount",
+ "isI",
+ "isP",
+ "isB",
+ "qComp",
+ "avgIITex",
+ "avgPITex",
+ "avgPPTex",
+ "avgBPTex",
+ "avgTex",
+ NULL
+ };
+ static double (*func1[])(void *, double)={
+ (void *)bits2qscale,
+ (void *)qscale2bits,
+ NULL
+ };
+ static const char *func1_names[]={
+ "bits2qp",
+ "qp2bits",
+ NULL
+ };
+
+ bits = x264_eval((char*)h->param.rc.psz_rc_eq, const_values, const_names, func1, func1_names, NULL, NULL, rce);
+
+ bits *= rate_factor;
+ if(bits<0.0) bits=0.0;
+ bits += 1.0; //avoid 1/0 issues
+
+ /* I/B difference */
+ if( pict_type==SLICE_TYPE_I && h->param.rc.f_ip_factor > 0 )
+ bits *= h->param.rc.f_ip_factor;
+ else if( pict_type==SLICE_TYPE_B && h->param.rc.f_pb_factor > 0 )
+ bits /= h->param.rc.f_pb_factor;
+
+ return bits2qscale(rce, bits);
+}
+
+static double get_diff_limited_q(x264_t *h, ratecontrol_entry_t *rce, double q)
+{
+ x264_ratecontrol_t *rcc = h->rc;
+ const int pict_type = rce->new_pict_type;
+
+ // force I/B quants as a function of P quants
+ const double last_p_q = rcc->last_qscale_for[SLICE_TYPE_P];
+ const double last_non_b_q= rcc->last_qscale_for[rcc->last_non_b_pict_type];
+ if( pict_type == SLICE_TYPE_I && h->param.rc.f_ip_factor < 0 )
+ q = last_p_q / -h->param.rc.f_ip_factor;
+ else if(pict_type==SLICE_TYPE_B && h->param.rc.f_pb_factor < 0)
+ q = last_non_b_q * -h->param.rc.f_pb_factor;
+
+ /* last qscale / qdiff stuff */
+ if(rcc->last_non_b_pict_type==pict_type || pict_type!=SLICE_TYPE_I)
+ {
+ double last_q = rcc->last_qscale_for[pict_type];
+ const double max_qscale = qp2qscale(qscale2qp(last_q) + h->param.rc.i_qp_step);
+ const double min_qscale = qp2qscale(qscale2qp(last_q) - h->param.rc.i_qp_step);
+
+ if (q > max_qscale) q = max_qscale;
+ else if(q < min_qscale) q = min_qscale;
+ }
+
+ rcc->last_qscale_for[pict_type] = q; //Note we can't do that after blurring
+ if(pict_type!=SLICE_TYPE_B)
+ rcc->last_non_b_pict_type = pict_type;
+ return q;
+}
+
+static double modify_qscale( x264_t *h, ratecontrol_entry_t *rce, double q )
+{
+ x264_ratecontrol_t *rcc = h->rc;
+ const int pict_type = rce->new_pict_type;
+ double lmin = rcc->lmin[pict_type];
+ double lmax = rcc->lmax[pict_type];
+
+ if(lmin==lmax /* || !h->param.b_qsquish */){
+ if (q<lmin) q = lmin;
+ else if(q>lmax) q = lmax;
+ }else{
+ double min2 = log(lmin);
+ double max2 = log(lmax);
+
+ q = log(q);
+ q = (q - min2)/(max2-min2) - 0.5;
+ q *= -4.0;
+ q = 1.0/(1.0 + exp(q));
+ q = q*(max2-min2) + min2;
+
+ q = exp(q);
+ }
+ return q;
+}
+
+// update qscale for 1 frame based on actual bits used so far
+static float rate_estimate_qscale(x264_t *h, int pict_type)
+{
+ float q;
+ float br_compensation;
+ double diff;
+ int picture_number = h->fenc->i_frame;
+ x264_ratecontrol_t *rcc = h->rc;
+ ratecontrol_entry_t *rce;
+ double lmin = rcc->lmin[pict_type];
+ double lmax = rcc->lmax[pict_type];
+ int64_t wanted_bits;
+ int64_t total_bits = 8*(h->stat.i_slice_size[SLICE_TYPE_I]
+ + h->stat.i_slice_size[SLICE_TYPE_P]
+ + h->stat.i_slice_size[SLICE_TYPE_B]);
+
+//printf("input_pic_num:%d pic_num:%d frame_rate:%d\n", s->input_picture_number, s->picture_number, s->frame_rate);
+
+ rce = &rcc->entry[picture_number];
+
+ if(pict_type!=SLICE_TYPE_I)
+ assert(pict_type == rce->new_pict_type);
+
+ wanted_bits = rce->expected_bits;
+
+ diff = total_bits - wanted_bits;
+ br_compensation = (rcc->buffer_size - diff) / rcc->buffer_size;
+ if(br_compensation<=0.0) br_compensation=0.001;
+
+ q = rce->new_qscale / br_compensation;
+
+ if (q<lmin) q=lmin;
+ else if(q>lmax) q=lmax;
+
+ rcc->last_qscale = q;
+ return q;
+}
+
+static int init_pass2( x264_t *h )
+{
+ x264_ratecontrol_t *rcc = h->rc;
+ uint64_t all_const_bits = 0;
+ uint64_t all_available_bits = (uint64_t)(h->param.rc.i_bitrate * 1000 * (double)rcc->num_entries / rcc->fps);
+ double rate_factor, step, step_mult;
+ double qblur = h->param.rc.f_qblur;
+ const int filter_size = (int)(qblur*4) | 1;
+ double expected_bits;
+ double *qscale, *blurred_qscale;
+ int i;
+
+ /* find total/average complexity & const_bits */
+ for(i=0; i<rcc->num_entries; i++){
+ ratecontrol_entry_t *rce = &rcc->entry[i];
+ rce->new_pict_type = rce->pict_type;
+ all_const_bits += rce->mv_bits + rce->misc_bits;
+ rcc->i_cplx_sum[rce->new_pict_type] += rce->i_tex_bits * rce->qscale;
+ rcc->p_cplx_sum[rce->new_pict_type] += rce->p_tex_bits * rce->qscale;
+ rcc->mv_bits_sum[rce->new_pict_type] += rce->mv_bits;
+ rcc->frame_count[rce->new_pict_type] ++;
+ }
+
+ if( all_available_bits < all_const_bits)
+ {
+ x264_log(h, X264_LOG_ERROR, "requested bitrate is too low. estimated minimum is %d kbps\n",
+ (int)(all_const_bits * rcc->fps / (rcc->num_entries * 1000)));
+ return -1;
+ }
+
+ qscale = x264_malloc(sizeof(double)*rcc->num_entries);
+ if(filter_size > 1)
+ blurred_qscale = x264_malloc(sizeof(double)*rcc->num_entries);
+ else
+ blurred_qscale = qscale;
+
+ expected_bits = 0;
+ for(i=0; i<rcc->num_entries; i++)
+ expected_bits += qscale2bits(&rcc->entry[i], get_qscale(h, &rcc->entry[i], 1.0));
+ step_mult = all_available_bits / expected_bits;
+
+ rate_factor = 0;
+ for(step = 1E4 * step_mult; step > 1E-7 * step_mult; step*=0.5){
+ expected_bits = 0;
+ rate_factor += step;
+
+ /* find qscale */
+ for(i=0; i<rcc->num_entries; i++){
+ qscale[i] = get_qscale(h, &rcc->entry[i], rate_factor);
+ }
+
+ /* fixed I/B QP relative to P mode */
+ for(i=rcc->num_entries-1; i>=0; i--){
+ qscale[i] = get_diff_limited_q(h, &rcc->entry[i], qscale[i]);
+ assert(qscale[i] >= 0);
+ }
+
+ /* smooth curve */
+ if(filter_size > 1){
+ assert(filter_size%2==1);
+ for(i=0; i<rcc->num_entries; i++){
+ ratecontrol_entry_t *rce = &rcc->entry[i];
+ const int pict_type = rce->new_pict_type;
+ int j;
+ double q=0.0, sum=0.0;
+
+ for(j=0; j<filter_size; j++){
+ int index = i+j-filter_size/2;
+ double d = index-i;
+ double coeff = qblur==0 ? 1.0 : exp(-d*d/(qblur*qblur));
+ if(index < 0 || index >= rcc->num_entries) continue;
+ if(pict_type != rcc->entry[index].new_pict_type) continue;
+ q += qscale[index] * coeff;
+ sum += coeff;
+ }
+ blurred_qscale[i] = q/sum;
+ }
+ }
+
+ /* find expected bits */
+ for(i=0; i<rcc->num_entries; i++){
+ ratecontrol_entry_t *rce = &rcc->entry[i];
+ double bits;
+ rce->new_qscale = modify_qscale(h, rce, blurred_qscale[i]);
+ assert(rce->new_qscale >= 0);
+ bits = qscale2bits(rce, rce->new_qscale) + rce->mv_bits + rce->misc_bits;
+
+ rce->expected_bits = expected_bits;
+ expected_bits += bits;
+ }
+
+//printf("expected:%f available:%d factor:%f\n", expected_bits, (int)all_available_bits, rate_factor);
+ if(expected_bits > all_available_bits) rate_factor -= step;
+ }
+
+ x264_free(qscale);
+ if(filter_size > 1)
+ x264_free(blurred_qscale);
+
+ if(fabs(expected_bits/all_available_bits - 1.0) > 0.01 )
+ {
+ x264_log( h, X264_LOG_ERROR, "Error: 2pass curve failed to converge\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+