Commit 78d2f605 authored by Loren Merritt's avatar Loren Merritt
Browse files

write encoding options to the userdata SEI and to the 2pass statsfile.

check for incompatible options in the 2nd pass.



git-svn-id: svn://svn.videolan.org/x264/trunk@374 df754926-b1dd-0310-bc7b-ec298dee348c
parent c010ba1d
......@@ -425,3 +425,78 @@ char *x264_slurp_file( const char *filename )
}
return buf;
}
/****************************************************************************
* x264_param2string:
****************************************************************************/
char *x264_param2string( x264_param_t *p, int b_res )
{
char *buf = x264_malloc( 1000 );
char *s = buf;
if( b_res )
{
s += sprintf( s, "%dx%d ", p->i_width, p->i_height );
s += sprintf( s, "fps=%d/%d ", p->i_fps_num, p->i_fps_den );
}
s += sprintf( s, "cabac=%d", p->b_cabac );
s += sprintf( s, " ref=%d", p->i_frame_reference );
s += sprintf( s, " deblock=%d:%d:%d", p->b_deblocking_filter,
p->i_deblocking_filter_alphac0, p->i_deblocking_filter_beta );
s += sprintf( s, " analyse=%#x:%#x", p->analyse.intra, p->analyse.inter );
s += sprintf( s, " me=%s", x264_motion_est_names[ p->analyse.i_me_method ] );
s += sprintf( s, " subme=%d", p->analyse.i_subpel_refine );
s += sprintf( s, " brdo=%d", p->analyse.b_bframe_rdo );
s += sprintf( s, " mixed_ref=%d", p->analyse.b_mixed_references );
s += sprintf( s, " me_range=%d", p->analyse.i_me_range );
s += sprintf( s, " chroma_me=%d", p->analyse.b_chroma_me );
s += sprintf( s, " trellis=%d", p->analyse.i_trellis );
s += sprintf( s, " 8x8dct=%d", p->analyse.b_transform_8x8 );
s += sprintf( s, " cqm=%d", p->i_cqm_preset );
s += sprintf( s, " chroma_qp_offset=%d", p->analyse.i_chroma_qp_offset );
s += sprintf( s, " slices=%d", p->i_threads );
s += sprintf( s, " bframes=%d", p->i_bframe );
if( p->i_bframe )
{
s += sprintf( s, " b_pyramid=%d b_adapt=%d b_bias=%d direct=%d wpredb=%d",
p->b_bframe_pyramid, p->b_bframe_adaptive, p->i_bframe_bias,
p->analyse.i_direct_mv_pred, p->analyse.b_weighted_bipred );
}
s += sprintf( s, " keyint=%d keyint_min=%d scenecut=%d",
p->i_keyint_max, p->i_keyint_min, p->i_scenecut_threshold );
s += sprintf( s, " pass=%d", p->rc.b_stat_read ? 2 : 1 );
if( p->rc.b_cbr || p->rc.i_rf_constant )
{
if( p->rc.i_rf_constant )
s += sprintf( s, " crf=%d", p->rc.i_rf_constant );
else
s += sprintf( s, " bitrate=%d ratetol=%.1f",
p->rc.i_bitrate, p->rc.f_rate_tolerance );
s += sprintf( s, " rceq='%s' qcomp=%.2f qpmin=%d qpmax=%d qpstep=%d",
p->rc.psz_rc_eq, p->rc.f_qcompress,
p->rc.i_qp_min, p->rc.i_qp_max, p->rc.i_qp_step );
if( p->rc.b_stat_read )
s += sprintf( s, " cplxblur=%.1f qblur=%.1f",
p->rc.f_complexity_blur, p->rc.f_qblur );
if( p->rc.i_vbv_max_bitrate && p->rc.i_vbv_buffer_size )
s += sprintf( s, " vbv_maxrate=%d vbv_bufsize=%d",
p->rc.i_vbv_max_bitrate, p->rc.i_vbv_buffer_size );
}
else
s += sprintf( s, " qp=%d", p->rc.i_qp_constant );
if( p->rc.b_cbr || p->rc.i_qp_constant != 0 )
{
s += sprintf( s, " ip_ratio=%.2f", p->rc.f_ip_factor );
if( p->i_bframe )
s += sprintf( s, " pb_ratio=%.2f", p->rc.f_pb_factor );
if( p->rc.i_zones )
s += sprintf( s, " zones" );
}
return buf;
}
......@@ -80,6 +80,10 @@ char *x264_slurp_file( const char *filename );
/* mdate: return the current date in microsecond */
int64_t x264_mdate( void );
/* x264_param2string: return a (malloced) string containing most of
* the encoding options */
char *x264_param2string( x264_param_t *p, int b_res );
/* log */
void x264_log( x264_t *h, int i_level, const char *psz_fmt, ... );
......
......@@ -366,6 +366,7 @@ static int x264_validate_parameters( x264_t *h )
h->param.rc.f_pb_factor = 1;
h->param.analyse.b_psnr = 0;
h->param.analyse.i_chroma_qp_offset = 0;
h->param.analyse.i_trellis = 0;
}
if( ( h->param.i_width % 16 || h->param.i_height % 16 ) && !h->mb.b_lossless )
......@@ -401,6 +402,11 @@ static int x264_validate_parameters( x264_t *h )
if( h->param.analyse.i_me_range > 16 && h->param.analyse.i_me_method <= X264_ME_HEX )
h->param.analyse.i_me_range = 16;
h->param.analyse.i_subpel_refine = x264_clip3( h->param.analyse.i_subpel_refine, 1, 6 );
h->param.analyse.b_bframe_rdo = h->param.analyse.b_bframe_rdo && h->param.analyse.i_subpel_refine >= 6;
h->param.analyse.b_mixed_references = h->param.analyse.b_mixed_references && h->param.i_frame_reference > 1;
h->param.analyse.inter &= X264_ANALYSE_PSUB16x16|X264_ANALYSE_PSUB8x8|X264_ANALYSE_BSUB16x16|
X264_ANALYSE_I4x4|X264_ANALYSE_I8x8;
h->param.analyse.intra &= X264_ANALYSE_I4x4|X264_ANALYSE_I8x8;
if( !(h->param.analyse.inter & X264_ANALYSE_PSUB16x16) )
h->param.analyse.inter &= ~X264_ANALYSE_PSUB8x8;
if( !h->param.analyse.b_transform_8x8 )
......@@ -667,7 +673,7 @@ int x264_encoder_headers( x264_t *h, x264_nal_t **pp_nal, int *pi_nal )
{
/* identify ourself */
x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
x264_sei_version_write( &h->out.bs );
x264_sei_version_write( h, &h->out.bs );
x264_nal_end( h );
/* generate sequence parameters */
......@@ -1325,7 +1331,7 @@ do_encode:
{
/* identify ourself */
x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
x264_sei_version_write( &h->out.bs );
x264_sei_version_write( h, &h->out.bs );
x264_nal_end( h );
}
......
......@@ -259,17 +259,50 @@ int x264_ratecontrol_new( x264_t *h )
/* Load stat file and init 2pass algo */
if( h->param.rc.b_stat_read )
{
char *p, *stats_in;
char *p, *stats_in, *stats_buf;
/* read 1st pass stats */
assert( h->param.rc.psz_stat_in );
stats_in = x264_slurp_file( h->param.rc.psz_stat_in );
if( !stats_in )
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");
return -1;
}
/* check whether 1st pass options were compatible with current options */
if( !strncmp( stats_buf, "#options:", 9 ) )
{
int i;
char *opts = stats_buf;
stats_in = strchr( stats_buf, '\n' );
if( !stats_in )
return -1;
*stats_in = '\0';
stats_in++;
if( ( p = strstr( opts, "bframes=" ) ) && sscanf( p, "bframes=%d", &i )
&& h->param.i_bframe != i )
{
x264_log( h, X264_LOG_ERROR, "different number of B-frames than 1st pass (%d vs %d)\n",
h->param.i_bframe, i );
return -1;
}
/* since B-adapt doesn't (yet) take into account B-pyramid,
* the converse is not a problem */
if( strstr( opts, "b_pyramid=1" ) && !h->param.b_bframe_pyramid )
x264_log( h, X264_LOG_WARNING, "1st pass used B-pyramid, 2nd doesn't\n" );
if( ( p = strstr( opts, "keyint=" ) ) && sscanf( p, "keyint=%d", &i )
&& h->param.i_keyint_max != i )
x264_log( h, X264_LOG_WARNING, "different keyint than 1st pass (%d vs %d)\n",
h->param.i_keyint_max, i );
if( strstr( opts, "qp=0" ) && h->param.rc.b_cbr )
x264_log( h, X264_LOG_WARNING, "1st pass was lossless, bitrate prediction will be inaccurate\n" );
}
/* find number of pics */
p = stats_in;
for(i=-1; p; i++)
......@@ -352,7 +385,7 @@ int x264_ratecontrol_new( x264_t *h )
p = next;
}
x264_free(stats_in);
x264_free(stats_buf);
if(h->param.rc.b_cbr)
{
......@@ -365,6 +398,8 @@ int x264_ratecontrol_new( x264_t *h )
* and move it to the real name only when it's complete */
if( h->param.rc.b_stat_write )
{
char *p;
rc->psz_stat_file_tmpname = x264_malloc( strlen(h->param.rc.psz_stat_out) + 6 );
strcpy( rc->psz_stat_file_tmpname, h->param.rc.psz_stat_out );
strcat( rc->psz_stat_file_tmpname, ".temp" );
......@@ -375,6 +410,10 @@ int x264_ratecontrol_new( x264_t *h )
x264_log(h, X264_LOG_ERROR, "ratecontrol_init: can't open stats file\n");
return -1;
}
p = x264_param2string( &h->param, 1 );
fprintf( rc->p_stat_file_out, "#options: %s\n", p );
x264_free( p );
}
return 0;
......
......@@ -447,7 +447,7 @@ void x264_pps_write( bs_t *s, x264_pps_t *pps )
bs_rbsp_trailing( s );
}
void x264_sei_version_write( bs_t *s )
void x264_sei_version_write( x264_t *h, bs_t *s )
{
int i;
// random ID number generated according to ISO-11578
......@@ -455,16 +455,21 @@ void x264_sei_version_write( bs_t *s )
0xdc, 0x45, 0xe9, 0xbd, 0xe6, 0xd9, 0x48, 0xb7,
0x96, 0x2c, 0xd8, 0x20, 0xd9, 0x23, 0xee, 0xef
};
char version[256];
char version[1200];
int length;
sprintf( version, "x264 - core %d%s - H.264/MPEG-4 AVC codec - Copyleft 2005 - http://www.videolan.org/x264.html",
X264_BUILD, X264_VERSION );
char *opts = x264_param2string( &h->param, 0 );
sprintf( version, "x264 - core %d%s - H.264/MPEG-4 AVC codec - "
"Copyleft 2005 - http://www.videolan.org/x264.html - options: %s",
X264_BUILD, X264_VERSION, opts );
x264_free( opts );
length = strlen(version)+1+16;
bs_write( s, 8, 0x5 ); // payload_type = user_data_unregistered
while( length > 255 )
bs_write( s, 8, 255 ), length -= 255;
bs_write( s, 8, length ); // payload_size
// payload_size
for( i = 0; i <= length-255; i += 255 )
bs_write( s, 8, 255 );
bs_write( s, 8, length-i );
for( i = 0; i < 16; i++ )
bs_write( s, 8, uuid[i] );
......
......@@ -28,7 +28,7 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param );
void x264_sps_write( bs_t *s, x264_sps_t *sps );
void x264_pps_init( x264_pps_t *pps, int i_id, x264_param_t *param, x264_sps_t *sps );
void x264_pps_write( bs_t *s, x264_pps_t *pps );
void x264_sei_version_write( bs_t *s );
void x264_sei_version_write( x264_t *h, bs_t *s );
void x264_validate_levels( x264_t *h );
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment