[FFmpeg-cvslog] avconv: explicitly postpone writing the header until all streams are initialized

Anton Khirnov git at videolan.org
Fri Oct 7 15:45:28 EEST 2016


ffmpeg | branch: master | Anton Khirnov <anton at khirnov.net> | Mon May 23 09:19:25 2016 +0200| [1c169782cae6c5c430ff62e7d7272dc9d0e8d527] | committer: Anton Khirnov

avconv: explicitly postpone writing the header until all streams are initialized

This should have no practical effect for now, but will make a difference
in the following commits.

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=1c169782cae6c5c430ff62e7d7272dc9d0e8d527
---

 avconv.c | 97 +++++++++++++++++++++++++++++++++++++++++-----------------------
 avconv.h |  8 ++++++
 2 files changed, 71 insertions(+), 34 deletions(-)

diff --git a/avconv.c b/avconv.c
index bd84d9b..6c100ff 100644
--- a/avconv.c
+++ b/avconv.c
@@ -87,7 +87,7 @@ static FILE *vstats_file;
 
 static int nb_frames_drop = 0;
 
-
+static int want_sdp = 1;
 
 #if HAVE_PTHREADS
 /* signal to input threads that they should exit; set by the main thread */
@@ -1487,8 +1487,14 @@ static void print_sdp(void)
 {
     char sdp[16384];
     int i;
-    AVFormatContext **avc = av_malloc(sizeof(*avc) * nb_output_files);
+    AVFormatContext **avc;
 
+    for (i = 0; i < nb_output_files; i++) {
+        if (!output_files[i]->header_written)
+            return;
+    }
+
+    avc = av_malloc(sizeof(*avc) * nb_output_files);
     if (!avc)
         exit_program(1);
     for (i = 0; i < nb_output_files; i++)
@@ -1618,6 +1624,42 @@ static InputStream *get_input_stream(OutputStream *ost)
     return NULL;
 }
 
+/* open the muxer when all the streams are initialized */
+static int check_init_output_file(OutputFile *of, int file_index)
+{
+    int ret, i;
+
+    for (i = 0; i < of->ctx->nb_streams; i++) {
+        OutputStream *ost = output_streams[of->ost_index + i];
+        if (!ost->initialized)
+            return 0;
+    }
+
+    of->ctx->interrupt_callback = int_cb;
+
+    ret = avformat_write_header(of->ctx, &of->opts);
+    if (ret < 0) {
+        char errbuf[128];
+
+        av_strerror(ret, errbuf, sizeof(errbuf));
+
+        av_log(NULL, AV_LOG_ERROR,
+               "Could not write header for output file #%d "
+               "(incorrect codec parameters ?): %s",
+               file_index, errbuf);
+        return ret;
+    }
+    assert_avoptions(of->opts);
+    of->header_written = 1;
+
+    av_dump_format(of->ctx, file_index, of->ctx->filename, 1);
+
+    if (want_sdp)
+        print_sdp();
+
+    return 0;
+}
+
 static int init_output_bsfs(OutputStream *ost)
 {
     AVBSFContext *ctx;
@@ -1860,6 +1902,12 @@ static int init_output_stream(OutputStream *ost, char *error, int error_len)
     if (ret < 0)
         return ret;
 
+    ost->initialized = 1;
+
+    ret = check_init_output_file(output_files[ost->file_index], ost->file_index);
+    if (ret < 0)
+        return ret;
+
     return ret;
 }
 
@@ -1929,7 +1977,6 @@ static int transcode_init(void)
     OutputStream *ost;
     InputStream *ist;
     char error[1024];
-    int want_sdp = 1;
 
     /* init framerate emulation */
     for (i = 0; i < nb_input_files; i++) {
@@ -2051,33 +2098,7 @@ static int transcode_init(void)
         }
     }
 
-    /* open files and write file headers */
-    for (i = 0; i < nb_output_files; i++) {
-        oc = output_files[i]->ctx;
-        oc->interrupt_callback = int_cb;
-        if ((ret = avformat_write_header(oc, &output_files[i]->opts)) < 0) {
-            char errbuf[128];
-            av_strerror(ret, errbuf, sizeof(errbuf));
-            snprintf(error, sizeof(error),
-                     "Could not write header for output file #%d "
-                     "(incorrect codec parameters ?): %s",
-                     i, errbuf);
-            ret = AVERROR(EINVAL);
-            goto dump_format;
-        }
-        assert_avoptions(output_files[i]->opts);
-        if (strcmp(oc->oformat->name, "rtp")) {
-            want_sdp = 0;
-        }
-    }
-
  dump_format:
-    /* dump the file output parameters - cannot be done before in case
-       of stream copy */
-    for (i = 0; i < nb_output_files; i++) {
-        av_dump_format(output_files[i]->ctx, i, output_files[i]->ctx->filename, 1);
-    }
-
     /* dump the stream mapping */
     av_log(NULL, AV_LOG_INFO, "Stream mapping:\n");
     for (i = 0; i < nb_input_streams; i++) {
@@ -2166,10 +2187,6 @@ static int transcode_init(void)
         return ret;
     }
 
-    if (want_sdp) {
-        print_sdp();
-    }
-
     return 0;
 }
 
@@ -2672,6 +2689,13 @@ static int transcode(void)
     /* write the trailer if needed and close file */
     for (i = 0; i < nb_output_files; i++) {
         os = output_files[i]->ctx;
+        if (!output_files[i]->header_written) {
+            av_log(NULL, AV_LOG_ERROR,
+                   "Nothing was written into output file %d (%s), because "
+                   "at least one of its streams received no packets.\n",
+                   i, os->filename);
+            continue;
+        }
         av_write_trailer(os);
     }
 
@@ -2761,7 +2785,7 @@ static int64_t getmaxrss(void)
 
 int main(int argc, char **argv)
 {
-    int ret;
+    int i, ret;
     int64_t ti;
 
     register_exit(avconv_cleanup);
@@ -2796,6 +2820,11 @@ int main(int argc, char **argv)
         exit_program(1);
     }
 
+    for (i = 0; i < nb_output_files; i++) {
+        if (strcmp(output_files[i]->ctx->oformat->name, "rtp"))
+            want_sdp = 0;
+    }
+
     ti = getutime();
     if (transcode() < 0)
         exit_program(1);
diff --git a/avconv.h b/avconv.h
index 78dbbdd..bc3b6c3 100644
--- a/avconv.h
+++ b/avconv.h
@@ -366,6 +366,12 @@ typedef struct OutputStream {
     AVDictionary *resample_opts;
     int finished;        /* no more packets should be written for this stream */
     int stream_copy;
+
+    // init_output_stream() has been called for this stream
+    // The encoder and the bistream filters have been initialized and the stream
+    // parameters are set in the AVStream.
+    int initialized;
+
     const char *attachment_filename;
     int copy_initial_nonkeyframes;
 
@@ -396,6 +402,8 @@ typedef struct OutputFile {
     uint64_t limit_filesize;
 
     int shortest;
+
+    int header_written;
 } OutputFile;
 
 extern InputStream **input_streams;



More information about the ffmpeg-cvslog mailing list