added two pass support (same syntax as mencoder)
authorFabrice Bellard <fabrice@bellard.org>
Thu, 10 Oct 2002 17:09:01 +0000 (17:09 +0000)
committerFabrice Bellard <fabrice@bellard.org>
Thu, 10 Oct 2002 17:09:01 +0000 (17:09 +0000)
Originally committed as revision 1020 to svn://svn.ffmpeg.org/ffmpeg/trunk

ffmpeg.c

index e2b24b17d45507b3573071a9fb47a5735ddaa58b..a3f9ca2f0b31cae6a80ed8d747cda711ca3a5ff4 100644 (file)
--- 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;i<nb_ostreams;i++) {
         ost = ost_table[i];
         if (ost->encoding_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;i<nb_ostreams;i++) {
             ost = ost_table[i];
             if (ost) {
+                if (ost->logfile) {
+                    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" },