param->rc.f_qcompress = 0.6;
param->rc.f_qblur = 0.5;
param->rc.f_complexity_blur = 20;
+ param->rc.i_zones = 0;
/* Log */
param->pf_log = x264_log_default;
double p_cplx_sum[5];
double mv_bits_sum[5];
int frame_count[5]; /* number of frames of each type */
+
+ int i_zones;
+ x264_zone_t *zones;
};
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) );
+ }
+
/* Load stat file and init 2pass algo */
if( h->param.rc.b_stat_read )
{
}
x264_free( rc->psz_stat_file_tmpname );
}
- if( rc->entry )
- x264_free(rc->entry);
+ x264_free( rc->entry );
+ x264_free( rc->zones );
x264_free( rc );
}
/**
* modify the bitrate curve from pass1 for one frame
*/
-static double get_qscale(x264_t *h, ratecontrol_entry_t *rce, double rate_factor)
+static double get_qscale(x264_t *h, ratecontrol_entry_t *rce, double rate_factor, int frame_num)
{
x264_ratecontrol_t *rcc= h->rc;
const int pict_type = rce->pict_type;
double q;
+ int i;
double const_values[]={
rce->i_tex_bits * rce->qscale,
};
q = x264_eval((char*)h->param.rc.psz_rc_eq, const_values, const_names, func1, func1_names, NULL, NULL, rce);
- q /= rate_factor;
// avoid NaN's in the rc_eq
if(q != q || rce->i_tex_bits + rce->p_tex_bits + rce->mv_bits == 0)
q = rcc->last_qscale;
- else
+ else {
+ rcc->last_rceq = q;
+ q /= rate_factor;
rcc->last_qscale = q;
+ }
+
+ for( i = rcc->i_zones-1; i >= 0; i-- )
+ {
+ x264_zone_t *z = &rcc->zones[i];
+ if( frame_num >= z->i_start && frame_num <= z->i_end )
+ {
+ if( z->b_force_qp )
+ q = qp2qscale(z->i_qp);
+ else
+ q /= z->f_bitrate_factor;
+ break;
+ }
+ }
return q;
}
rce.s_count = 0;
rce.qscale = 1;
rce.pict_type = pict_type;
- rcc->last_rceq = get_qscale(h, &rce, 1);
+ q = get_qscale(h, &rce, rcc->wanted_bits_window / rcc->cplxr_sum, h->fenc->i_frame);
wanted_bits = h->fenc->i_frame * rcc->bitrate / rcc->fps;
abr_buffer *= X264_MAX( 1, sqrt(h->fenc->i_frame/25) );
overflow = x264_clip3f( 1.0 + (total_bits - wanted_bits) / abr_buffer, .5, 2 );
-
- q = rcc->last_rceq * overflow * rcc->cplxr_sum / rcc->wanted_bits_window;
+ q *= overflow;
if( pict_type == SLICE_TYPE_I
/* should test _next_ pict type, but that isn't decided yet */
expected_bits = 1;
for(i=0; i<rcc->num_entries; i++)
- expected_bits += qscale2bits(&rcc->entry[i], get_qscale(h, &rcc->entry[i], 1.0));
+ expected_bits += qscale2bits(&rcc->entry[i], get_qscale(h, &rcc->entry[i], 1.0, i));
step_mult = all_available_bits / expected_bits;
rate_factor = 0;
/* find qscale */
for(i=0; i<rcc->num_entries; i++){
- qscale[i] = get_qscale(h, &rcc->entry[i], rate_factor);
+ qscale[i] = get_qscale(h, &rcc->entry[i], rate_factor, i);
}
/* fixed I/B qscale relative to P */
"\n"
" -h, --help Print this help\n"
"\n"
+ "Frame-type options:\n"
+ "\n"
" -I, --keyint <integer> Maximum GOP size [%d]\n"
" -i, --min-keyint <integer> Minimum GOP size [%d]\n"
" --scenecut <integer> How aggressively to insert extra I-frames [%d]\n"
" --nf Disable loop filter\n"
" -f, --filter <alpha:beta> Loop filter AlphaC0 and Beta parameters [%d:%d]\n"
"\n"
+ "Ratecontrol:\n"
+ "\n"
" -q, --qp <integer> Set QP [%d]\n"
" -B, --bitrate <integer> Set bitrate\n"
" --qpmin <integer> Set min QP [%d]\n"
" --cplxblur <float> Reduce fluctuations in QP (before curve compression) [%.1f]\n"
" --qblur <float> Reduce fluctuations in QP (after curve compression) [%.1f]\n"
"\n"
+ " --zones <zone0>/<zone1>/...\n"
+ " Tweak the bitrate of some regions of the video\n"
+ " Each zone is of the form\n"
+ " <start frame>,<end frame>,<option>\n"
+ " where <option> is either\n"
+ " q=<integer> (force QP)\n"
+ " or b=<float> (bitrate multiplier)\n"
+ "\n"
+ "Analysis:\n"
+ "\n"
" -A, --analyse <string> Analyse options: [\"i4x4,p8x8,b8x8\"]\n"
- " - i4x4\n"
- " - p8x8, p4x4, b8x8\n"
+ " - i4x4, p8x8, p4x4, b8x8\n"
" - none, all\n"
" --direct <string> Direct MV prediction mode [\"temporal\"]\n"
" - none, spatial, temporal\n"
" -m, --subme <integer> Subpixel motion estimation quality: 1=fast, 5=best. [%d]\n"
" --no-chroma-me Ignore chroma in motion estimation\n"
"\n"
+ "Input/Output:\n"
+ "\n"
" --level <integer> Specify level (as defined by Annex A)\n"
" --sar width:height Specify Sample Aspect Ratio\n"
" --fps <float|rational> Specify framerate\n"
#define OPT_VBVINIT 289
#define OPT_VISUALIZE 290
#define OPT_SEEK 291
+#define OPT_ZONES 292
static struct option long_options[] =
{
{ "qcomp", required_argument, NULL, OPT_QCOMP },
{ "qblur", required_argument, NULL, OPT_QBLUR },
{ "cplxblur",required_argument, NULL, OPT_CPLXBLUR },
+ { "zones", required_argument, NULL, OPT_ZONES },
{ "no-psnr", no_argument, NULL, OPT_NOPSNR },
{ "quiet", no_argument, NULL, OPT_QUIET },
{ "verbose", no_argument, NULL, 'v' },
case OPT_CPLXBLUR:
param->rc.f_complexity_blur = atof(optarg);
break;
+ case OPT_ZONES:
+ {
+ int i;
+ char *p;
+ param->rc.i_zones = 1;
+ for( p = optarg; *p; p++ )
+ param->rc.i_zones += (*p == '/');
+ param->rc.zones = (x264_zone_t*)malloc( param->rc.i_zones * sizeof(x264_zone_t) );
+ p = optarg;
+ for( i = 0; i < param->rc.i_zones; i++)
+ {
+ x264_zone_t *z = ¶m->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';
+ fprintf( stderr, "invalid zone: \"%s\"\n", p );
+ return -1;
+ }
+ p = strchr(p, '/') + 1;
+ }
+ }
+ break;
case OPT_NOPSNR:
param->analyse.b_psnr = 0;
break;
#include <stdarg.h>
-#define X264_BUILD 25
+#define X264_BUILD 26
/* x264_t:
* opaque handler for decoder and encoder */
#define X264_LOG_INFO 2
#define X264_LOG_DEBUG 3
+typedef struct
+{
+ int i_start, i_end;
+ int b_force_qp;
+ int i_qp;
+ float f_bitrate_factor;
+} x264_zone_t;
+
typedef struct
{
/* CPU flags */
int b_stat_read; /* Read stat from psz_stat_in and use it */
char *psz_stat_in;
- /* 2pass params (same than ffmpeg ones) */
+ /* 2pass params (same as ffmpeg ones) */
char *psz_rc_eq; /* 2 pass rate control equation */
float f_qcompress; /* 0.0 => cbr, 1.0 => constant qp */
float f_qblur; /* temporally blur quants */
float f_complexity_blur; /* temporally blur complexity */
+ int i_zones;
+ x264_zone_t *zones; /* ratecontrol overrides */
} rc;
int b_aud; /* generate access unit delimiters */