diff --git a/ffmpeg.c b/ffmpeg.c index e2b24b17d4..a3f9ca2f0b 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -141,6 +141,10 @@ static int do_play = 0; static int do_psnr = 0; static int do_vstats = 0; static int mpeg_vcd = 0; +static int do_pass = 0; +static char *pass_logfilename = NULL; + +#define DEFAULT_PASS_LOGFILENAME "ffmpeg2pass" #ifndef CONFIG_AUDIO_OSS const char *audio_device = "none"; @@ -165,6 +169,7 @@ typedef struct AVOutputStream { int audio_resample; ReSampleContext *resample; /* for audio resampling */ FifoBuffer fifo; /* for compression: one audio fifo per codec */ + FILE *logfile; } AVOutputStream; typedef struct AVInputStream { @@ -546,6 +551,10 @@ static void do_video_out(AVFormatContext *s, //fprintf(stderr,"\nFrame: %3d %3d size: %5d type: %d", // enc->frame_number-1, enc->real_pict_num, ret, // enc->pict_type); + /* if two pass, output log */ + if (ost->logfile && enc->stats_out) { + fprintf(ost->logfile, "%s", enc->stats_out); + } } else { write_picture(s, ost->index, picture, enc->pix_fmt, enc->width, enc->height); } @@ -842,6 +851,45 @@ static int av_encode(AVFormatContext **output_files, default: av_abort(); } + /* two pass mode */ + if (ost->encoding_needed && + (codec->flags & (CODEC_FLAG_PASS1 | CODEC_FLAG_PASS2))) { + char logfilename[1024]; + FILE *f; + int size; + char *logbuffer; + + snprintf(logfilename, sizeof(logfilename), "%s-%d.log", + pass_logfilename ? + pass_logfilename : DEFAULT_PASS_LOGFILENAME, i); + if (codec->flags & CODEC_FLAG_PASS1) { + f = fopen(logfilename, "w"); + if (!f) { + perror(logfilename); + exit(1); + } + ost->logfile = f; + } else { + /* read the log file */ + f = fopen(logfilename, "r"); + if (!f) { + perror(logfilename); + exit(1); + } + fseek(f, 0, SEEK_END); + size = ftell(f); + fseek(f, 0, SEEK_SET); + logbuffer = av_malloc(size + 1); + if (!logbuffer) { + fprintf(stderr, "Could not allocate log buffer\n"); + exit(1); + } + fread(logbuffer, 1, size, f); + fclose(f); + logbuffer[size] = '\0'; + codec->stats_in = logbuffer; + } + } } /* open each encoder */ @@ -1245,6 +1293,7 @@ static int av_encode(AVFormatContext **output_files, for(i=0;iencoding_needed) { + av_freep(&ost->st->codec.stats_in); avcodec_close(&ost->st->codec); } } @@ -1280,6 +1329,10 @@ static int av_encode(AVFormatContext **output_files, for(i=0;ilogfile) { + fclose(ost->logfile); + ost->logfile = NULL; + } fifo_free(&ost->fifo); /* works even if fifo is not initialized but set to zero */ av_free(ost->pict_tmp.data[0]); @@ -1942,6 +1995,15 @@ void opt_output_file(const char *filename) video_enc->get_psnr = 0; video_enc->me_method = me_method; + + /* two pass mode */ + if (do_pass) { + if (do_pass == 1) { + video_enc->flags |= CODEC_FLAG_PASS1; + } else { + video_enc->flags |= CODEC_FLAG_PASS2; + } + } /* XXX: need to find a way to set codec parameters */ if (oc->oformat->flags & AVFMT_RGB24) { @@ -2128,6 +2190,17 @@ void prepare_play(void) opt_output_file(audio_device); } +/* same option as mencoder */ +void opt_pass(const char *pass_str) +{ + int pass; + pass = atoi(pass_str); + if (pass != 1 && pass != 2) { + fprintf(stderr, "pass number can be only 1 or 2\n"); + exit(1); + } + do_pass = pass; +} #ifndef CONFIG_WIN32 INT64 getutime(void) @@ -2265,6 +2338,8 @@ const OptionDef options[] = { { "author", HAS_ARG | OPT_STRING, {(void*)&str_author}, "set the author", "string" }, { "copyright", HAS_ARG | OPT_STRING, {(void*)&str_copyright}, "set the copyright", "string" }, { "comment", HAS_ARG | OPT_STRING, {(void*)&str_comment}, "set the comment", "string" }, + { "pass", HAS_ARG, {(void*)&opt_pass}, "select the pass number (1 or 2)", "n" }, + { "passlogfile", HAS_ARG | OPT_STRING, {(void*)&pass_logfilename}, "select two pass log file name", "file" }, /* video options */ { "b", HAS_ARG, {(void*)opt_video_bitrate}, "set video bitrate (in kbit/s)", "bitrate" }, { "r", HAS_ARG, {(void*)opt_frame_rate}, "set frame rate (in Hz)", "rate" },