Commit 9116d300 authored by Laurent Aimar's avatar Laurent Aimar

* all: 2pass patch by Loren Merritt <lorenm AT u.washington DOT edu>

 "Mostly borrowed from libavcodec.
 There is not much theoretical basis behind my choice of defaults for
 rc_eq, qcompress, qblur, and ip_factor."
 


git-svn-id: svn://svn.videolan.org/x264/trunk@40 df754926-b1dd-0310-bc7b-ec298dee348c
parent 67b67300
......@@ -24,7 +24,7 @@ SOURCES_C = core/mc.c core/predict.c core/pixel.c core/macroblock.c
core/common.c core/mdate.c core/csp.c
encoder/analyse.c encoder/me.c encoder/ratecontrol.c
encoder/set.c encoder/macroblock.c encoder/cabac.c encoder/cavlc.c
encoder/encoder.c ;
encoder/encoder.c encoder/eval.c ;
SOURCES_X86 = core/i386/cpu.asm ;
SOURCES_MMX = core/i386/mc-c.c core/i386/dct-c.c core/i386/predict.c core/i386/dct.asm core/i386/pixel.asm core/i386/mc.asm ;
......
......@@ -68,17 +68,25 @@ void x264_param_default( x264_param_t *param )
param->b_cabac = 0;
param->i_cabac_init_idc = -1;
param->b_cbr = 0;
param->i_bitrate = 3000;
param->i_rc_buffer_size = 0;
param->i_rc_init_buffer = 0;
param->i_rc_sens = 100;
param->i_qp_constant = 26;
param->i_qp_min = 0;
param->i_qp_max = 51;
param->i_qp_step = 4;
param->f_ip_factor = 2.0;
param->f_pb_factor = 2.0;
param->rc.b_cbr = 0;
param->rc.i_bitrate = 3000;
param->rc.i_rc_buffer_size = 0;
param->rc.i_rc_init_buffer = 0;
param->rc.i_rc_sens = 100;
param->rc.i_qp_constant = 26;
param->rc.i_qp_min = 0;
param->rc.i_qp_max = 51;
param->rc.i_qp_step = 4;
param->rc.f_ip_factor = 2.0;
param->rc.f_pb_factor = 2.0;
param->rc.b_stat_write = 0;
param->rc.psz_stat_out = "x264_2pass.log";
param->rc.b_stat_read = 0;
param->rc.psz_stat_in = "x264_2pass.log";
param->rc.psz_rc_eq = "(tex^qComp)*(avgTex^(1-qComp))";
param->rc.f_qcompress = 0.6;
param->rc.f_qblur = 0.5;
/* Log */
param->pf_log = x264_log_default;
......
......@@ -224,6 +224,8 @@ struct x264_t
int i_last_idr; /* How many I non IDR frames from last IDR */
int i_last_i; /* How many P/B frames from last I */
int i_input; /* Number of input frames already accepted */
} frames;
/* current frame being encoded */
......
......@@ -68,6 +68,8 @@ x264_frame_t *x264_frame_new( x264_t *h )
frame->i_poc = -1;
frame->i_type = X264_TYPE_AUTO;
frame->i_qpplus1 = 0;
frame->i_pts = -1;
frame->i_frame = -1;
return frame;
}
......
......@@ -31,6 +31,7 @@ typedef struct
int i_type;
int i_qpplus1;
int64_t i_pts;
int i_frame; /* Presentation frame number */
/* YUV buffer */
int i_plane;
......
......@@ -298,8 +298,14 @@ x264_t *x264_encoder_open ( x264_param_t *param )
x264_t *h = x264_malloc( sizeof( x264_t ) );
int i;
/* */
/* Create a copy of param */
memcpy( &h->param, param, sizeof( x264_param_t ) );
if( h->param.rc.psz_stat_out )
h->param.rc.psz_stat_out = strdup( h->param.rc.psz_stat_out );
if( h->param.rc.psz_stat_in )
h->param.rc.psz_stat_in = strdup( h->param.rc.psz_stat_in );
if( h->param.rc.psz_rc_eq )
h->param.rc.psz_rc_eq = strdup( h->param.rc.psz_rc_eq );
/* Check parameters validity */
if( param->i_width <= 0 || param->i_height <= 0 )
......@@ -417,6 +423,7 @@ x264_t *x264_encoder_open ( x264_param_t *param )
}
h->frames.i_last_idr = h->param.i_idrframe;
h->frames.i_last_i = h->param.i_iframe;
h->frames.i_input = 0;
h->i_ref0 = 0;
h->i_ref1 = 0;
......@@ -896,8 +903,22 @@ int x264_encoder_encode( x264_t *h,
x264_frame_copy_picture( h, fenc, pic );
fenc->i_frame = h->frames.i_input++;
/* 2: get its type */
if( ( h->frames.i_last_i + 1 >= h->param.i_iframe && h->frames.i_last_idr + 1 >= h->param.i_idrframe ) ||
if( h->param.rc.b_stat_read )
{
/* XXX: trusts that the first pass used compatible B and IDR frequencies */
fenc->i_type = x264_ratecontrol_slice_type( h, fenc->i_frame );
if( fenc->i_type == X264_TYPE_I && h->frames.next[0] == NULL &&
h->frames.i_last_idr + 1 >= h->param.i_idrframe )
{
fenc->i_type = X264_TYPE_IDR;
h->i_poc = 0;
h->i_frame_num = 0;
}
}
else if( ( h->frames.i_last_i + 1 >= h->param.i_iframe && h->frames.i_last_idr + 1 >= h->param.i_idrframe ) ||
pic->i_type == X264_TYPE_IDR )
{
/* IDR */
......@@ -1101,7 +1122,7 @@ do_encode:
x264_slice_write( h, i_nal_type, i_nal_ref_idc );
/* XXX: this scene cut won't work with B frame (it may never create IDR -> bad) */
if( i_slice_type != SLICE_TYPE_I)
if( i_slice_type != SLICE_TYPE_I && !h->param.rc.b_stat_read )
{
int i_bias;
......@@ -1127,7 +1148,7 @@ do_encode:
h->i_frame - 1,
h->out.nal[h->out.i_nal-1].i_payload,
h->i_last_intra_size, h->i_last_inter_size,
i_mb_i, i_mb, 100 * i_mb_i / i_mb, i_bias,
i_mb_i, i_mb - i_mb_i, 100 * i_mb_i / i_mb, i_bias,
h->stat.frame.i_mb_count[P_SKIP],
h->stat.frame.i_mb_count[P_L0] );
......@@ -1416,6 +1437,14 @@ void x264_encoder_close ( x264_t *h )
x264_frame_delete( h->frames.reference[i] );
}
/* param */
if( h->param.rc.psz_stat_out )
free( h->param.rc.psz_stat_out );
if( h->param.rc.psz_stat_in )
free( h->param.rc.psz_stat_in );
if( h->param.rc.psz_rc_eq )
free( h->param.rc.psz_rc_eq );
/* rc */
x264_ratecontrol_delete( h );
......
......@@ -5,6 +5,8 @@
* $Id: ratecontrol.c,v 1.1 2004/06/03 19:27:08 fenrir Exp $
*
* Authors: Mns Rullgrd <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
......@@ -22,32 +24,55 @@
*****************************************************************************/
#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 */
......@@ -67,13 +92,71 @@ struct x264_ratecontrol_t
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 */
......@@ -83,15 +166,15 @@ int x264_ratecontrol_new( x264_t *h )
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){
......@@ -125,7 +208,108 @@ int x264_ratecontrol_new( x264_t *h )
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;
}
......@@ -133,6 +317,11 @@ int x264_ratecontrol_new( x264_t *h )
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 );
}
......@@ -146,12 +335,26 @@ void x264_ratecontrol_start( x264_t *h, int i_slice_type )
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:
......@@ -170,13 +373,13 @@ void x264_ratecontrol_start( x264_t *h, int i_slice_type )
#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);
......@@ -188,7 +391,7 @@ void x264_ratecontrol_start( x264_t *h, int i_slice_type )
break;
case SLICE_TYPE_P:
kp = h->param.f_pb_factor;
kp = h->param.rc.f_pb_factor;
break;
case SLICE_TYPE_B:
......@@ -209,8 +412,8 @@ void x264_ratecontrol_start( x264_t *h, int i_slice_type )
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)
......@@ -231,9 +434,9 @@ void x264_ratecontrol_start( x264_t *h, int i_slice_type )
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;
}
......@@ -246,7 +449,7 @@ void x264_ratecontrol_start( x264_t *h, int i_slice_type )
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",
......@@ -269,7 +472,7 @@ void x264_ratecontrol_mb( x264_t *h, int bits )
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 );
......@@ -302,12 +505,12 @@ void x264_ratecontrol_mb( x264_t *h, int bits )
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 )
......@@ -315,11 +518,48 @@ 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;
......@@ -352,3 +592,292 @@ void x264_ratecontrol_end( x264_t *h, int 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{