[x264-devel] Improve support for varying resolution between passes
Jason Garrett-Glaser
git at videolan.org
Wed Aug 10 05:15:15 CEST 2011
x264 | branch: master | Jason Garrett-Glaser <jason at x264.com> | Sat Aug 6 10:45:47 2011 -0700| [0ba8a9c6973897ec35e1a5d241a71f4f5a4f81aa] | committer: Jason Garrett-Glaser
Improve support for varying resolution between passes
Should give much better quality, but still doesn't support MB-tree yet.
Also check for the same interlaced options between passes.
Various minor ratecontrol cosmetics.
> http://git.videolan.org/gitweb.cgi/x264.git/?a=commit;h=0ba8a9c6973897ec35e1a5d241a71f4f5a4f81aa
---
encoder/ratecontrol.c | 56 ++++++++++++++++++++++++++++++++++++------------
1 files changed, 42 insertions(+), 14 deletions(-)
diff --git a/encoder/ratecontrol.c b/encoder/ratecontrol.c
index 16901d7..2d1f8be 100644
--- a/encoder/ratecontrol.c
+++ b/encoder/ratecontrol.c
@@ -407,7 +407,7 @@ int x264_macroblock_tree_read( x264_t *h, x264_frame_t *frame, float *quant_offs
if( i_type != i_type_actual && rc->qpbuf_pos == 1 )
{
- x264_log(h, X264_LOG_ERROR, "MB-tree frametype %d doesn't match actual frametype %d.\n", i_type, i_type_actual);
+ x264_log( h, X264_LOG_ERROR, "MB-tree frametype %d doesn't match actual frametype %d.\n", i_type, i_type_actual );
return -1;
}
} while( i_type != i_type_actual );
@@ -425,7 +425,7 @@ int x264_macroblock_tree_read( x264_t *h, x264_frame_t *frame, float *quant_offs
x264_stack_align( x264_adaptive_quant_frame, h, frame, quant_offsets );
return 0;
fail:
- x264_log(h, X264_LOG_ERROR, "Incomplete MB-tree stats file.\n");
+ x264_log( h, X264_LOG_ERROR, "Incomplete MB-tree stats file.\n" );
return -1;
}
@@ -622,7 +622,7 @@ int x264_ratecontrol_new( x264_t *h )
if( h->param.rc.i_rc_method == X264_RC_CRF && h->param.rc.b_stat_read )
{
- x264_log(h, X264_LOG_ERROR, "constant rate-factor is incompatible with 2pass.\n");
+ x264_log( h, X264_LOG_ERROR, "constant rate-factor is incompatible with 2pass.\n" );
return -1;
}
@@ -647,7 +647,7 @@ int x264_ratecontrol_new( x264_t *h )
if( rc->rate_tolerance < 0.01 )
{
- x264_log(h, X264_LOG_WARNING, "bitrate tolerance too small, using .01\n");
+ x264_log( h, X264_LOG_WARNING, "bitrate tolerance too small, using .01\n" );
rc->rate_tolerance = 0.01;
}
@@ -715,7 +715,7 @@ int x264_ratecontrol_new( x264_t *h )
stats_buf = stats_in = x264_slurp_file( h->param.rc.psz_stat_in );
if( !stats_buf )
{
- x264_log(h, X264_LOG_ERROR, "ratecontrol_init: can't open stats file\n");
+ x264_log( h, X264_LOG_ERROR, "ratecontrol_init: can't open stats file\n" );
return -1;
}
if( h->param.rc.b_mb_tree )
@@ -727,13 +727,19 @@ int x264_ratecontrol_new( x264_t *h )
x264_free( mbtree_stats_in );
if( !rc->p_mbtree_stat_file_in )
{
- x264_log(h, X264_LOG_ERROR, "ratecontrol_init: can't open mbtree stats file\n");
+ x264_log( h, X264_LOG_ERROR, "ratecontrol_init: can't open mbtree stats file\n" );
return -1;
}
}
/* check whether 1st pass options were compatible with current options */
- if( !strncmp( stats_buf, "#options:", 9 ) )
+ if( strncmp( stats_buf, "#options:", 9 ) )
+ {
+ x264_log( h, X264_LOG_ERROR, "options list in stats file not valid\n" );
+ return -1;
+ }
+
+ float res_factor, res_factor_bits;
{
int i, j;
uint32_t k, l;
@@ -754,6 +760,10 @@ int x264_ratecontrol_new( x264_t *h )
h->param.i_width, h->param.i_height, i, j );
return -1;
}
+ res_factor = (float)h->param.i_width * h->param.i_height / (i*j);
+ /* Change in bits relative to resolution isn't quite linear on typical sources,
+ * so we'll at least try to roughly approximate this effect. */
+ res_factor_bits = powf( res_factor, 0.7 );
if( ( p = strstr( opts, "timebase=" ) ) && sscanf( p, "timebase=%u/%u", &k, &l ) != 2 )
{
@@ -774,6 +784,18 @@ int x264_ratecontrol_new( x264_t *h )
CMP_OPT_FIRST_PASS( "intra_refresh", h->param.b_intra_refresh );
CMP_OPT_FIRST_PASS( "open_gop", h->param.b_open_gop );
CMP_OPT_FIRST_PASS( "bluray_compat", h->param.b_bluray_compat );
+
+ if( (p = strstr( opts, "interlaced=" )) )
+ {
+ char *current = h->param.b_interlaced ? h->param.b_tff ? "tff" : "bff" : h->param.b_fake_interlaced ? "fake" : "0";
+ char buf[5];
+ sscanf( p, "interlaced=%4s", buf );
+ if( strcmp( current, buf ) )
+ {
+ x264_log( h, X264_LOG_ERROR, "different interlaced setting than first pass (%s vs %s)\n", current, buf );
+ return -1;
+ }
+ }
if( (p = strstr( opts, "keyint=" )) )
{
@@ -817,7 +839,7 @@ int x264_ratecontrol_new( x264_t *h )
p = strchr( p + 1, ';' );
if( !num_entries )
{
- x264_log(h, X264_LOG_ERROR, "empty stats file\n");
+ x264_log( h, X264_LOG_ERROR, "empty stats file\n" );
return -1;
}
rc->num_entries = num_entries;
@@ -875,6 +897,12 @@ int x264_ratecontrol_new( x264_t *h )
&pict_type, &rce->i_duration, &rce->i_cpb_duration, &qp, &rce->tex_bits,
&rce->mv_bits, &rce->misc_bits, &rce->i_count, &rce->p_count,
&rce->s_count, &rce->direct_mode );
+ rce->tex_bits *= res_factor_bits;
+ rce->mv_bits *= res_factor_bits;
+ rce->misc_bits *= res_factor_bits;
+ rce->i_count *= res_factor;
+ rce->p_count *= res_factor;
+ rce->s_count *= res_factor;
p = strstr( p, "ref:" );
if( !p )
@@ -963,7 +991,7 @@ parse_error:
rc->p_stat_file_out = fopen( rc->psz_stat_file_tmpname, "wb" );
if( rc->p_stat_file_out == NULL )
{
- x264_log(h, X264_LOG_ERROR, "ratecontrol_init: can't open stats file\n");
+ x264_log( h, X264_LOG_ERROR, "ratecontrol_init: can't open stats file\n" );
return -1;
}
@@ -981,7 +1009,7 @@ parse_error:
rc->p_mbtree_stat_file_out = fopen( rc->psz_mbtree_stat_file_tmpname, "wb" );
if( rc->p_mbtree_stat_file_out == NULL )
{
- x264_log(h, X264_LOG_ERROR, "ratecontrol_init: can't open mbtree stats file\n");
+ x264_log( h, X264_LOG_ERROR, "ratecontrol_init: can't open mbtree stats file\n" );
return -1;
}
}
@@ -1520,10 +1548,10 @@ int x264_ratecontrol_slice_type( x264_t *h, int frame_num )
rc->qp_constant[SLICE_TYPE_I] = x264_clip3( (int)( qscale2qp( qp2qscale( h->param.rc.i_qp_constant ) / fabs( h->param.rc.f_ip_factor )) + 0.5 ), 0, QP_MAX );
rc->qp_constant[SLICE_TYPE_B] = x264_clip3( (int)( qscale2qp( qp2qscale( h->param.rc.i_qp_constant ) * fabs( h->param.rc.f_pb_factor )) + 0.5 ), 0, QP_MAX );
- x264_log(h, X264_LOG_ERROR, "2nd pass has more frames than 1st pass (%d)\n", rc->num_entries);
- x264_log(h, X264_LOG_ERROR, "continuing anyway, at constant QP=%d\n", h->param.rc.i_qp_constant);
+ x264_log( h, X264_LOG_ERROR, "2nd pass has more frames than 1st pass (%d)\n", rc->num_entries );
+ x264_log( h, X264_LOG_ERROR, "continuing anyway, at constant QP=%d\n", h->param.rc.i_qp_constant );
if( h->param.i_bframe_adaptive )
- x264_log(h, X264_LOG_ERROR, "disabling adaptive B-frames\n");
+ x264_log( h, X264_LOG_ERROR, "disabling adaptive B-frames\n" );
for( int i = 0; i < h->param.i_threads; i++ )
{
@@ -1724,7 +1752,7 @@ int x264_ratecontrol_end( x264_t *h, int bits, int *filler )
return 0;
fail:
- x264_log(h, X264_LOG_ERROR, "ratecontrol_end: stats file could not be written to\n");
+ x264_log( h, X264_LOG_ERROR, "ratecontrol_end: stats file could not be written to\n" );
return -1;
}
More information about the x264-devel
mailing list