diff -uNrp a/cli_common.h b/cli_common.h --- a/cli_common.h 1970-01-01 02:00:00 +0200 +++ b/cli_common.h 2009-10-26 12:21:28 +0200 @@ -0,0 +1,29 @@ +#ifndef X264_CLI_H +#define X264_CLI_H + +/** + * Contains necessities common to CLI elements but not the library. + */ + +/* log macros */ +FILE *f_log_file; +#define OPEN_LOG(prm,mode) \ +{\ + if( prm->psz_log_file )\ + f_log_file = fopen( prm->psz_log_file, mode );\ +} +#define CLOSE_LOG \ +{\ + if( f_log_file )\ + fclose( f_log_file );\ + f_log_file = NULL;\ +} +#define LOG(prm,lvl1,lvl2,...) \ +{\ + if( prm->i_log_level>=X264_LOG_##lvl1 )\ + fprintf( stderr, __VA_ARGS__ );\ + if( f_log_file && prm->i_log_file_level>=X264_LOG_##lvl2 )\ + fprintf( f_log_file, __VA_ARGS__ );\ +} + +#endif diff -uNrp a/common/common.c b/common/common.c --- a/common/common.c 2009-10-26 11:18:13 +0200 +++ b/common/common.c 2009-10-26 12:22:38 +0200 @@ -117,6 +117,7 @@ void x264_param_default( x264_param_t param->pf_log = x264_log_default; param->p_log_private = NULL; param->i_log_level = X264_LOG_INFO; + param->i_log_file_level = X264_LOG_INFO; /* */ param->analyse.intra = X264_ANALYSE_I4x4 | X264_ANALYSE_I8x8; @@ -467,6 +468,10 @@ int x264_param_parse( x264_param_t *p, c } OPT("log") p->i_log_level = atoi(value); + OPT("log-file") + p->psz_log_file = strdup(value); + OPT("log-file-level") + p->i_log_file_level = x264_clip3( atoi(value), -1, 3 ); #ifdef VISUALIZE OPT("visualize") p->b_visualize = atobool(value); @@ -625,6 +630,32 @@ int x264_param_parse( x264_param_t *p, c return b_error ? X264_PARAM_BAD_VALUE : 0; } +static void x264_log_file( FILE *p_file, int i_level, const char *psz_fmt, va_list arg ) +{ + char *psz_prefix; + switch( i_level ) + { + case X264_LOG_ERROR: + psz_prefix = "error"; + break; + case X264_LOG_WARNING: + psz_prefix = "warning"; + break; + case X264_LOG_INFO: + psz_prefix = "info"; + break; + case X264_LOG_DEBUG: + psz_prefix = "debug"; + break; + default: + psz_prefix = "unknown"; + break; + } + fprintf( p_file, "x264 [%s]: ", psz_prefix ); + vfprintf( p_file, psz_fmt, arg ); + fflush( p_file ); +} + /**************************************************************************** * x264_log: ****************************************************************************/ @@ -640,6 +671,14 @@ void x264_log( x264_t *h, int i_level, c h->param.pf_log( h->param.p_log_private, i_level, psz_fmt, arg ); va_end( arg ); } + if( i_level <= h->param.i_log_file_level ) + { + va_list arg; + va_start( arg, psz_fmt ); + if( h->p_log_file ) + x264_log_file( h->p_log_file, i_level, psz_fmt, arg ); + va_end( arg ); + } } static void x264_log_default( void *p_unused, int i_level, const char *psz_fmt, va_list arg ) diff -uNrp a/common/common.h b/common/common.h --- a/common/common.h 2009-10-26 11:18:13 +0200 +++ b/common/common.h 2009-10-26 12:23:00 +0200 @@ -416,7 +416,8 @@ struct x264_t x264_frame_t *fref1[16+3]; /* ref list 1 */ int b_ref_reorder[2]; - + /* log */ + FILE *p_log_file; /* Current MB DCT coeffs */ struct diff -uNrp a/encoder/encoder.c b/encoder/encoder.c --- a/encoder/encoder.c 2009-10-26 11:18:13 +0200 +++ b/encoder/encoder.c 2009-10-26 12:24:03 +0200 @@ -760,6 +760,16 @@ x264_t *x264_encoder_open( x264_param_t if( param->param_free ) param->param_free( param ); + if( h->param.psz_log_file ) + { + h->p_log_file = fopen( h->param.psz_log_file, "ab" ); + if( !h->p_log_file ) + { + x264_log( h, X264_LOG_ERROR, "can't write log to \"%s\"\n", h->param.psz_log_file ); + goto fail; + } + } + if( x264_validate_parameters( h ) < 0 ) goto fail; @@ -937,6 +947,11 @@ x264_t *x264_encoder_open( x264_param_t return h; fail: + if( h && h->p_log_file ) + { + fclose( h->p_log_file ); + h->p_log_file = NULL; + } x264_free( h ); return NULL; } @@ -2403,6 +2418,13 @@ void x264_encoder_close ( x264_t *h x264_free( h->nal_buffer ); x264_analyse_free_costs( h ); + if( h->p_log_file ) + { + fflush( h->p_log_file ); + fclose( h->p_log_file ); + h->p_log_file = NULL; + } + if( h->param.i_threads > 1) h = h->thread[h->i_thread_phase]; diff -uNrp a/input/avis.c b/input/avis.c --- a/input/avis.c 2009-10-26 11:18:13 +0200 +++ b/input/avis.c 2009-10-26 12:29:20 +0200 @@ -22,6 +22,7 @@ *****************************************************************************/ #include "muxers.h" +#include "cli_common.h" #include #include @@ -58,7 +59,7 @@ static int open_file( char *psz_filename // check input format if( info.fccHandler != MAKEFOURCC('Y', 'V', '1', '2') ) { - fprintf( stderr, "avis [error]: unsupported input format (%c%c%c%c)\n", + LOG( p_param, NONE, ERROR, "avis [error]: unsupported input format (%c%c%c%c)\n", (char)(info.fccHandler & 0xff), (char)((info.fccHandler >> 8) & 0xff), (char)((info.fccHandler >> 16) & 0xff), (char)((info.fccHandler >> 24)) ); @@ -76,11 +77,12 @@ static int open_file( char *psz_filename p_param->i_fps_den = info.dwScale / i; p_param->i_fps_num = info.dwRate / i; - fprintf( stderr, "avis [info]: %dx%d @ %.2f fps (%d frames)\n", + LOG( p_param, INFO, INFO, "avis [info]: %dx%d @ %.2f fps (%d frames)\n", p_param->i_width, p_param->i_height, (double)p_param->i_fps_num / (double)p_param->i_fps_den, (int)info.dwLength ); + CLOSE_LOG; return 0; } diff -uNrp a/input/thread.c b/input/thread.c --- a/input/thread.c 2009-10-26 11:18:13 +0200 +++ b/input/thread.c 2009-10-26 12:28:19 +0200 @@ -22,6 +22,7 @@ *****************************************************************************/ #include "muxers.h" +#include "cli_common.h" extern cli_input_t input; @@ -50,7 +51,7 @@ static int open_file( char *psz_filename thread_hnd_t *h = malloc( sizeof(thread_hnd_t) ); if( !h || x264_picture_alloc( &h->pic, X264_CSP_I420, p_param->i_width, p_param->i_height ) < 0 ) { - fprintf( stderr, "x264 [error]: malloc failed\n" ); + LOG( p_param, NONE, ERROR, "x264 [error]: malloc failed\n" ); return -1; } h->input = input; diff -uNrp a/input/y4m.c b/input/y4m.c --- a/input/y4m.c 2009-10-26 11:18:13 +0200 +++ b/input/y4m.c 2009-10-26 12:26:47 +0200 @@ -22,6 +22,7 @@ *****************************************************************************/ #include "muxers.h" +#include "cli_common.h" typedef struct { @@ -93,7 +94,7 @@ static int open_file( char *psz_filename case 'C': /* Color space */ if( strncmp( "420", tokstart, 3 ) ) { - fprintf( stderr, "Colorspace unhandled\n" ); + LOG( p_param, NONE, ERROR, "Colorspace unhandled\n"); return -1; } tokstart = strchr( tokstart, 0x20 ); @@ -107,7 +108,7 @@ static int open_file( char *psz_filename case 'b': case 'm': default: - fprintf( stderr, "Warning, this sequence might be interlaced\n" ); + LOG( p_param, WARNING, WARNING, "Warning, this sequence might be interlaced\n" ); } break; case 'F': /* Frame rate - 0:0 if unknown */ @@ -138,7 +139,7 @@ static int open_file( char *psz_filename strncmp( "420MPEG2",tokstart, 8 ) && strncmp( "420PALDV",tokstart, 8 ) ) { - fprintf( stderr, "Unsupported extended colorspace\n" ); + LOG( p_param, NONE, ERROR, "Unsupported extended colorspace\n"); return -1; } } @@ -147,11 +148,12 @@ static int open_file( char *psz_filename } } - fprintf( stderr, "yuv4mpeg: %ix%i@%i/%ifps, %i:%i\n", + LOG( p_param, INFO, INFO, "yuv4mpeg: %ix%i@%i/%ifps, %i:%i\n", h->width, h->height, p_param->i_fps_num, p_param->i_fps_den, p_param->vui.i_sar_width, p_param->vui.i_sar_height ); *p_handle = h; + CLOSE_LOG; return 0; } diff -uNrp a/input/yuv.c b/input/yuv.c --- a/input/yuv.c 2009-10-26 11:18:13 +0200 +++ b/input/yuv.c 2009-10-26 12:25:14 +0200 @@ -22,6 +22,7 @@ *****************************************************************************/ #include "muxers.h" +#include "cli_common.h" typedef struct { @@ -47,6 +48,7 @@ static int open_file( char *psz_filename return -1; *p_handle = h; + CLOSE_LOG; return 0; } diff -uNrp a/output/mp4.c b/output/mp4.c --- a/output/mp4.c 2009-10-26 11:18:13 +0200 +++ b/output/mp4.c 2009-10-26 12:31:11 +0200 @@ -22,6 +22,7 @@ *****************************************************************************/ #include "muxers.h" +#include "cli_common.h" #include typedef struct @@ -182,9 +183,10 @@ static int set_param( hnd_t handle, x264 p_mp4->i_time_inc = p_param->i_fps_den; p_mp4->i_init_delay = p_param->i_bframe ? (p_param->i_bframe_pyramid ? 2 : 1) : 0; p_mp4->i_init_delay *= p_mp4->i_time_inc; - fprintf( stderr, "mp4 [info]: initial delay %d (scale %d)\n", + LOG( p_param, INFO, INFO, "mp4 [info]: initial delay %d (scale %d)\n", p_mp4->i_init_delay, p_mp4->i_time_res ); + CLOSE_LOG; return 0; } diff -uNrp a/x264.c b/x264.c --- a/x264.c 2009-10-26 11:18:13 +0200 +++ b/x264.c 2009-10-26 12:38:49 +0200 @@ -32,6 +32,7 @@ #include "common/cpu.h" #include "x264.h" #include "muxers.h" +#include "cli_common.h" #include "config.h" #ifdef _WIN32 @@ -75,6 +76,7 @@ static int Encode( x264_param_t *param, ****************************************************************************/ int main( int argc, char **argv ) { + f_log_file = NULL; x264_param_t param; cli_opt_t opt; int ret; @@ -367,6 +369,9 @@ static void Help( x264_param_t *defaults H0( " --quiet Quiet Mode\n" ); H1( " --psnr Enable PSNR computation\n" ); H1( " --ssim Enable SSIM computation\n" ); + H0( " --log-file Save log to file\n" ); + H1( " --log-file-level Log-file level information [%d]\n", + defaults->i_log_file_level ); H1( " --threads Force a specific number of threads\n" ); H2( " --thread-input Run Avisynth in its own thread\n" ); H2( " --sync-lookahead Number of buffer frames for threaded lookahead\n" ); @@ -493,6 +498,8 @@ static struct option long_options[] = { "quiet", no_argument, NULL, OPT_QUIET }, { "verbose", no_argument, NULL, 'v' }, { "no-progress", no_argument, NULL, OPT_NOPROGRESS }, + { "log-file" ,required_argument, NULL, 0 }, + { "log-file-level",required_argument, NULL, 0 }, { "visualize", no_argument, NULL, OPT_VISUALIZE }, { "dump-yuv", required_argument, NULL, 0 }, { "sps-id", required_argument, NULL, 0 }, @@ -649,7 +656,7 @@ static int Parse( int argc, char **argv } else { - fprintf( stderr, "x264 [error]: invalid preset: %s\n", optarg ); + LOG( param, NONE, ERROR, "x264 [error]: invalid preset: %s\n", optarg ); return -1; } } @@ -722,7 +729,7 @@ static int Parse( int argc, char **argv } else { - fprintf( stderr, "x264 [error]: invalid tune: %s\n", optarg ); + LOG( param, NONE, ERROR, "x264 [error]: invalid tune: %s\n", optarg ); return -1; } } @@ -779,7 +786,7 @@ static int Parse( int argc, char **argv #ifdef MP4_OUTPUT output = mp4_output; #else - fprintf( stderr, "x264 [error]: not compiled with MP4 output support\n" ); + LOG( param, NONE, ERROR, "x264 [error]: not compiled with MP4 output support\n" ); return -1; #endif } @@ -789,7 +796,7 @@ static int Parse( int argc, char **argv opt->hout = stdout; else if( output.open_file( optarg, &opt->hout ) ) { - fprintf( stderr, "x264 [error]: can't open output file `%s'\n", optarg ); + LOG( param, NONE, ERROR, "x264 [error]: can't open output file `%s'\n", optarg ); return -1; } break; @@ -797,7 +804,7 @@ static int Parse( int argc, char **argv opt->qpfile = fopen( optarg, "rb" ); if( !opt->qpfile ) { - fprintf( stderr, "x264 [error]: can't open `%s'\n", optarg ); + LOG( param, NONE, ERROR, "x264 [error]: can't open `%s'\n", optarg ); return -1; } break; @@ -818,7 +825,7 @@ static int Parse( int argc, char **argv param->b_visualize = 1; b_exit_on_ctrl_c = 1; #else - fprintf( stderr, "x264 [warning]: not compiled with visualization support\n" ); + LOG( param, WARNING, WARNING, "x264 [warning]: not compiled with visualization support\n" ); #endif break; case OPT_TUNE: @@ -865,7 +872,7 @@ generic_option: if( b_error ) { const char *name = long_options_index > 0 ? long_options[long_options_index].name : argv[optind-2]; - fprintf( stderr, "x264 [error]: invalid argument: %s = %s\n", name, optarg ); + LOG( param, NONE, ERROR, "x264 [error]: invalid argument: %s = %s\n", name, optarg ); return -1; } } @@ -892,7 +899,7 @@ generic_option: param->i_bframe = 0; if( param->b_interlaced ) { - fprintf( stderr, "x264 [error]: baseline profile doesn't support interlacing\n" ); + LOG( param, NONE, ERROR, "x264 [error]: baseline profile doesn't support interlacing\n" ); return -1; } } @@ -907,13 +914,13 @@ generic_option: } else { - fprintf( stderr, "x264 [error]: invalid profile: %s\n", profile ); + LOG( param, NONE, ERROR, "x264 [error]: invalid profile: %s\n", profile ); return -1; } if( (param->rc.i_rc_method == X264_RC_CQP && param->rc.i_qp_constant == 0) || (param->rc.i_rc_method == X264_RC_CRF && param->rc.f_rf_constant == 0) ) { - fprintf( stderr, "x264 [error]: %s profile doesn't support lossless\n", profile ); + LOG( param, NONE, ERROR, "x264 [error]: %s profile doesn't support lossless\n", profile ); return -1; } } @@ -921,7 +928,7 @@ generic_option: /* Get the file name */ if( optind > argc - 1 || !opt->hout ) { - fprintf( stderr, "x264 [error]: No %s file. Run x264 --help for a list of options.\n", + LOG( param, NONE, ERROR, "x264 [error]: No %s file. Run x264 --help for a list of options.\n", optind > argc - 1 ? "input" : "output" ); return -1; } @@ -936,6 +943,8 @@ generic_option: if( !strncasecmp( psz, ".y4m", 4 ) ) b_y4m = 1; + OPEN_LOG( param, "wb"); + if( !(b_avis || b_y4m) ) // raw yuv { if( optind > argc - 1 ) @@ -946,8 +955,7 @@ generic_option: if( *psz >= '0' && *psz <= '9' && sscanf( psz, "%ux%u", ¶m->i_width, ¶m->i_height ) == 2 ) { - if( param->i_log_level >= X264_LOG_INFO ) - fprintf( stderr, "x264 [info]: %dx%d (given by file name) @ %.2f fps\n", param->i_width, param->i_height, (double)param->i_fps_num / (double)param->i_fps_den); + LOG( param, INFO, INFO, "x264 [info]: %dx%d (given by file name) @ %.2f fps\n", param->i_width, param->i_height, (double)param->i_fps_num / (double)param->i_fps_den); break; } } @@ -955,14 +963,13 @@ generic_option: else { sscanf( argv[optind++], "%ux%u", ¶m->i_width, ¶m->i_height ); - if( param->i_log_level >= X264_LOG_INFO ) - fprintf( stderr, "x264 [info]: %dx%d @ %.2f fps\n", param->i_width, param->i_height, (double)param->i_fps_num / (double)param->i_fps_den); + LOG( param, INFO, INFO, "x264 [info]: %dx%d @ %.2f fps\n", param->i_width, param->i_height, (double)param->i_fps_num / (double)param->i_fps_den); } } if( !(b_avis || b_y4m) && ( !param->i_width || !param->i_height ) ) { - fprintf( stderr, "x264 [error]: Rawyuv input requires a resolution.\n" ); + LOG( param, NONE, ERROR, "x264 [error]: Rawyuv input requires a resolution.\n" ); return -1; } @@ -975,7 +982,7 @@ generic_option: #ifdef AVIS_INPUT input = avis_input; #else - fprintf( stderr, "x264 [error]: not compiled with AVIS input support\n" ); + LOG( param, ERROR, ERROR, "x264 [error]: not compiled with AVIS input support\n" ); return -1; #endif } @@ -984,7 +991,7 @@ generic_option: if( input.open_file( psz_filename, &opt->hin, param ) ) { - fprintf( stderr, "x264 [error]: could not open input file '%s'\n", psz_filename ); + LOG( param, NONE, ERROR, "x264 [error]: could not open input file '%s'\n", psz_filename ); return -1; } /* Restore the user's frame rate if fps has been explicitly set on the commandline. */ @@ -1001,7 +1008,7 @@ generic_option: { if( thread_input.open_file( NULL, &opt->hin, param ) ) { - fprintf( stderr, "x264 [error]: threaded input failed\n" ); + LOG( param, NONE, ERROR, "x264 [error]: threaded input failed\n" ); return -1; } else @@ -1082,7 +1089,7 @@ static int Encode_frame( x264_t *h, hnd if( x264_encoder_encode( h, &nal, &i_nal, pic, &pic_out ) < 0 ) { - fprintf( stderr, "x264 [error]: x264_encoder_encode failed\n" ); + LOG( (&h->param), NONE, ERROR, "x264 [error]: x264_encoder_encode failed\n" ); return -1; } @@ -1143,25 +1150,28 @@ static int Encode( x264_param_t *param, if( ( h = x264_encoder_open( param ) ) == NULL ) { - fprintf( stderr, "x264 [error]: x264_encoder_open failed\n" ); + LOG( param, NONE, ERROR, "x264 [error]: x264_encoder_open failed\n" ); input.close_file( opt->hin ); return -1; } if( output.set_param( opt->hout, param ) ) { - fprintf( stderr, "x264 [error]: can't set outfile param\n" ); + LOG( param, NONE, ERROR, "x264 [error]: can't set outfile param\n" ); input.close_file( opt->hin ); output.close_file( opt->hout ); + CLOSE_LOG; return -1; } /* Create a new pic */ if( x264_picture_alloc( &pic, X264_CSP_I420, param->i_width, param->i_height ) < 0 ) { - fprintf( stderr, "x264 [error]: malloc failed\n" ); + LOG( param, NONE, ERROR, "x264 [error]: malloc failed\n" ); + CLOSE_LOG; return -1; } + CLOSE_LOG; i_start = x264_mdate(); @@ -1217,8 +1227,9 @@ static int Encode( x264_param_t *param, x264_free( mux_buffer ); fprintf( stderr, "\n" ); + OPEN_LOG( param, "ab" ); if( b_ctrl_c ) - fprintf( stderr, "aborted at input frame %d, output frame %d\n", opt->i_seek + i_frame, i_frame_output ); + LOG( param, NONE, INFO, "aborted at input frame %d, output frame %d\n", opt->i_seek + i_frame, i_frame_output ); input.close_file( opt->hin ); output.close_file( opt->hout ); @@ -1228,10 +1239,11 @@ static int Encode( x264_param_t *param, double fps = (double)i_frame_output * (double)1000000 / (double)( i_end - i_start ); - fprintf( stderr, "encoded %d frames, %.2f fps, %.2f kb/s\n", i_frame_output, fps, + LOG( param, NONE, INFO, "encoded %d frames, %.2f fps, %.2f kb/s\n", i_frame_output, fps, (double) i_file * 8 * param->i_fps_num / ( (double) param->i_fps_den * i_frame_output * 1000 ) ); } + CLOSE_LOG; return 0; } diff -uNrp a/x264.h b/x264.h --- a/x264.h 2009-10-26 11:18:13 +0200 +++ b/x264.h 2009-10-26 12:39:04 +0200 @@ -225,6 +225,8 @@ typedef struct x264_param_t void (*pf_log)( void *, int i_level, const char *psz, va_list ); void *p_log_private; int i_log_level; + int i_log_file_level; + char *psz_log_file; int b_visualize; char *psz_dump_yuv; /* filename for reconstructed frames */