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-08-09 22:01:55 +0300 @@ -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-08-09 21:39:02 +0300 +++ b/common/common.c 2009-08-09 22:03:16 +0300 @@ -111,6 +111,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; @@ -445,6 +446,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); @@ -601,6 +606,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: ****************************************************************************/ @@ -616,6 +647,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-08-09 21:39:02 +0300 +++ b/common/common.h 2009-08-09 22:03:38 +0300 @@ -408,7 +408,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-08-09 21:39:02 +0300 +++ b/encoder/encoder.c 2009-08-09 22:08:29 +0300 @@ -682,12 +682,36 @@ x264_t *x264_encoder_open ( x264_param /* Create a copy of param */ memcpy( &h->param, param, sizeof(x264_param_t) ); + 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 ) + { + if( h->p_log_file ) + { + fclose( h->p_log_file ); + h->p_log_file = NULL; + } goto fail; + } if( h->param.psz_cqm_file ) if( x264_cqm_parse_file( h, h->param.psz_cqm_file ) < 0 ) + { + if( h->p_log_file ) + { + fclose( h->p_log_file ); + h->p_log_file = NULL; + } goto fail; + } if( h->param.rc.psz_stat_out ) h->param.rc.psz_stat_out = strdup( h->param.rc.psz_stat_out ); @@ -738,7 +762,14 @@ x264_t *x264_encoder_open ( x264_param x264_validate_levels( h, 1 ); if( x264_cqm_init( h ) < 0 ) + { + if( h->p_log_file ) + { + fclose( h->p_log_file ); + h->p_log_file = NULL; + } goto fail; + } h->mb.i_mb_count = h->sps->i_mb_width * h->sps->i_mb_height; @@ -849,6 +880,11 @@ x264_t *x264_encoder_open ( x264_param else { x264_log( h, X264_LOG_ERROR, "can't write to fdec.yuv\n" ); + if( h->p_log_file ) + { + fclose( h->p_log_file ); + h->p_log_file = NULL; + } goto fail; } } @@ -2075,8 +2111,8 @@ void x264_encoder_close ( x264_t *h x264_psnr( SUM3( h->stat.i_ssd_global ), i_count * i_yuv_size ), f_bitrate ); } - else - x264_log( h, X264_LOG_INFO, "kb/s:%.1f\n", f_bitrate ); +// else +// x264_log( h, X264_LOG_INFO, "kb/s:%.1f\n", f_bitrate ); } /* rc */ @@ -2090,6 +2126,13 @@ void x264_encoder_close ( x264_t *h x264_cqm_delete( 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 % h->param.i_threads ]; diff -uNrp a/muxers.c b/muxers.c --- a/muxers.c 2009-08-09 21:39:02 +0300 +++ b/muxers.c 2009-08-09 22:11:14 +0300 @@ -25,6 +25,7 @@ #include "x264.h" #include "matroska.h" #include "muxers.h" +#include "cli_common.h" #ifndef _MSC_VER #include "config.h" @@ -77,6 +78,7 @@ int open_file_yuv( char *psz_filename, h return -1; *p_handle = (hnd_t)h; + CLOSE_LOG; return 0; } @@ -192,7 +194,7 @@ int open_file_y4m( char *psz_filename, h 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); @@ -206,7 +208,7 @@ int open_file_y4m( char *psz_filename, h 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 */ @@ -237,7 +239,7 @@ int open_file_y4m( char *psz_filename, h 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; } } @@ -246,11 +248,12 @@ int open_file_y4m( char *psz_filename, h } } - 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 = (hnd_t)h; + CLOSE_LOG; return 0; } @@ -363,7 +366,7 @@ int open_file_avis( 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)) ); @@ -381,11 +384,12 @@ int open_file_avis( 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; } @@ -718,13 +722,13 @@ int set_param_mp4( hnd_t handle, x264_pa p_mp4->i_time_inc = p_param->i_fps_den; p_mp4->i_init_delay = p_param->i_bframe ? (p_param->b_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; } - int write_nalu_mp4( hnd_t handle, uint8_t *p_nalu, int i_size ) { mp4_t *p_mp4 = (mp4_t *)handle; diff -uNrp a/x264.c b/x264.c --- a/x264.c 2009-08-09 21:39:02 +0300 +++ b/x264.c 2009-08-09 22:17:44 +0300 @@ -31,6 +31,7 @@ #include "common/common.h" #include "common/cpu.h" #include "x264.h" +#include "cli_common.h" #include "muxers.h" #ifndef _MSC_VER @@ -87,6 +88,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; @@ -349,6 +351,9 @@ static void Help( x264_param_t *defaults H0( " --quiet Quiet Mode\n" ); H0( " --psnr Enable PSNR computation\n" ); H0( " --ssim Enable SSIM computation\n" ); + H0( " --log-file Save log to file\n" ); + H0( " --log-file-level Log-file level information [%d]\n", + defaults->i_log_file_level ); H0( " --threads Force a specific number of threads\n" ); H1( " --thread-input Run Avisynth in its own thread\n" ); H1( " --non-deterministic Slightly improve quality of SMP, at the cost of repeatability\n" ); @@ -466,6 +471,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 }, @@ -760,7 +767,7 @@ static int Parse( int argc, char **argv p_set_eop = set_eop_mp4; p_close_outfile = close_file_mp4; #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 } @@ -776,7 +783,7 @@ static int Parse( int argc, char **argv opt->hout = stdout; else if( p_open_outfile( 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; @@ -784,7 +791,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; @@ -805,7 +812,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: @@ -849,7 +856,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; } } @@ -905,7 +912,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; } @@ -920,6 +927,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 ) @@ -930,8 +939,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; } } @@ -939,14 +947,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; } @@ -960,7 +967,7 @@ generic_option: p_read_frame = read_frame_avis; p_close_infile = close_file_avis; #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 } @@ -974,7 +981,7 @@ generic_option: if( p_open_infile( 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; } } @@ -985,7 +992,7 @@ generic_option: { if( open_file_thread( NULL, &opt->hin, param ) ) { - fprintf( stderr, "x264 [error]: threaded input failed\n" ); + LOG( param, WARNING, WARNING, "x264 [warning]: threaded input failed\n" ); return -1; } else @@ -1071,7 +1078,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; } @@ -1124,23 +1131,24 @@ 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" ); p_close_infile( opt->hin ); return -1; } if( p_set_outfile_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" ); p_close_infile( opt->hin ); p_close_outfile( opt->hout ); return -1; } + CLOSE_LOG; /* 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" ); return -1; } @@ -1209,8 +1217,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\n", opt->i_seek + i_frame ); + LOG( param, NONE, INFO, "aborted at input frame %d\n", opt->i_seek + i_frame ); p_close_infile( opt->hin ); p_close_outfile( opt->hout ); @@ -1220,10 +1229,11 @@ static int Encode( x264_param_t *param, double fps = (double)i_frame * (double)1000000 / (double)( i_end - i_start ); - fprintf( stderr, "encoded %d frames, %.2f fps, %.2f kb/s\n", i_frame, fps, + LOG( param, NONE, INFO, "encoded %d frames, %.2f fps, %.2f kb/s\n", i_frame, fps, (double) i_file * 8 * param->i_fps_num / ( (double) param->i_fps_den * i_frame * 1000 ) ); } + CLOSE_LOG; return 0; } diff -uNrp a/x264.h b/x264.h --- a/x264.h 2009-08-09 21:39:02 +0300 +++ b/x264.h 2009-08-09 22:17:59 +0300 @@ -215,6 +215,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 */