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

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