[FFmpeg-cvslog] lavf/mux: add avformat_init_output

Rodger Combs git at videolan.org
Mon Oct 24 11:55:37 EEST 2016


ffmpeg | branch: master | Rodger Combs <rodger.combs at gmail.com> | Fri Jun 24 22:02:50 2016 -0500| [a246fef163387c0d79830a9bdf408443a9aba1c1] | committer: Rodger Combs

lavf/mux: add avformat_init_output

This allows a consumer to run the muxer's init function without actually
writing the header, which is useful in chained muxers that support
automatic bitstream filtering.

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

 doc/APIchanges         |  3 +++
 libavformat/avformat.h | 34 +++++++++++++++++++++++--
 libavformat/internal.h | 10 ++++++++
 libavformat/mux.c      | 68 +++++++++++++++++++++++++++++++++++++++-----------
 libavformat/version.h  |  2 +-
 5 files changed, 100 insertions(+), 17 deletions(-)

diff --git a/doc/APIchanges b/doc/APIchanges
index 502ab3f..5017eb4 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -15,6 +15,9 @@ libavutil:     2015-08-28
 
 API changes, most recent first:
 
+2016-10-24 - xxxxxxx - lavf 57.54.100 - avformat.h
+  Add avformat_init_output() and AVSTREAM_INIT_IN_ macros
+
 2016-10-22 - xxxxxxx - lavu 55.33.100 - avassert.h
   Add av_assert0_fpu() / av_assert2_fpu()
 
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 057f8c5..82ca727 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -618,6 +618,8 @@ typedef struct AVOutputFormat {
      * AVStream parameters that need to be set before packets are sent.
      * This method must not write output.
      *
+     * Return 0 if streams were fully configured, 1 if not, negative AVERROR on failure
+     *
      * Any allocations made here must be freed in deinit().
      */
     int (*init)(struct AVFormatContext *);
@@ -2374,6 +2376,10 @@ void avformat_close_input(AVFormatContext **s);
  * @addtogroup lavf_encoding
  * @{
  */
+
+#define AVSTREAM_INIT_IN_WRITE_HEADER 0 ///< stream parameters initialized in avformat_write_header
+#define AVSTREAM_INIT_IN_INIT_OUTPUT  1 ///< stream parameters initialized in avformat_init_output
+
 /**
  * Allocate the stream private data and write the stream header to
  * an output media file.
@@ -2385,14 +2391,38 @@ void avformat_close_input(AVFormatContext **s);
  *                 On return this parameter will be destroyed and replaced with a dict containing
  *                 options that were not found. May be NULL.
  *
- * @return 0 on success, negative AVERROR on failure.
+ * @return AVSTREAM_INIT_IN_WRITE_HEADER on success if the codec had not already been fully initialized in avformat_init,
+ *         AVSTREAM_INIT_IN_INIT_OUTPUT  on success if the codec had already been fully initialized in avformat_init,
+ *         negative AVERROR on failure.
  *
- * @see av_opt_find, av_dict_set, avio_open, av_oformat_next.
+ * @see av_opt_find, av_dict_set, avio_open, av_oformat_next, avformat_init_output.
  */
 av_warn_unused_result
 int avformat_write_header(AVFormatContext *s, AVDictionary **options);
 
 /**
+ * Allocate the stream private data and initialize the codec, but do not write the header.
+ * May optionally be used before avformat_write_header to initialize stream parameters
+ * before actually writing the header.
+ * If using this function, do not pass the same options to avformat_write_header.
+ *
+ * @param s Media file handle, must be allocated with avformat_alloc_context().
+ *          Its oformat field must be set to the desired output format;
+ *          Its pb field must be set to an already opened AVIOContext.
+ * @param options  An AVDictionary filled with AVFormatContext and muxer-private options.
+ *                 On return this parameter will be destroyed and replaced with a dict containing
+ *                 options that were not found. May be NULL.
+ *
+ * @return AVSTREAM_INIT_IN_WRITE_HEADER on success if the codec requires avformat_write_header to fully initialize,
+ *         AVSTREAM_INIT_IN_INIT_OUTPUT  on success if the codec has been fully initialized,
+ *         negative AVERROR on failure.
+ *
+ * @see av_opt_find, av_dict_set, avio_open, av_oformat_next, avformat_write_header.
+ */
+av_warn_unused_result
+int avformat_init_output(AVFormatContext *s, AVDictionary **options);
+
+/**
  * Write a packet to an output media file.
  *
  * This function passes the packet directly to the muxer, without any buffering
diff --git a/libavformat/internal.h b/libavformat/internal.h
index 95776a0..da64c64 100644
--- a/libavformat/internal.h
+++ b/libavformat/internal.h
@@ -130,6 +130,16 @@ struct AVFormatInternal {
      * Timestamp of the end of the shortest stream.
      */
     int64_t shortest_end;
+
+    /**
+     * Whether or not avformat_init_output has already been called
+     */
+    int initialized;
+
+    /**
+     * Whether or not avformat_init_output fully initialized streams
+     */
+    int streams_initialized;
 };
 
 struct AVStreamInternal {
diff --git a/libavformat/mux.c b/libavformat/mux.c
index bbfc0fc..06d87de 100644
--- a/libavformat/mux.c
+++ b/libavformat/mux.c
@@ -423,10 +423,13 @@ FF_ENABLE_DEPRECATION_WARNINGS
          *options = tmp;
     }
 
-    if (s->oformat->init && (ret = s->oformat->init(s)) < 0) {
-        if (s->oformat->deinit)
-            s->oformat->deinit(s);
-        goto fail;
+    if (s->oformat->init) {
+        if ((ret = s->oformat->init(s)) < 0) {
+            if (s->oformat->deinit)
+                s->oformat->deinit(s);
+            return ret;
+        }
+        return ret == 0;
     }
 
     return 0;
@@ -493,31 +496,64 @@ static int write_header_internal(AVFormatContext *s)
     return 0;
 }
 
-int avformat_write_header(AVFormatContext *s, AVDictionary **options)
+int avformat_init_output(AVFormatContext *s, AVDictionary **options)
 {
     int ret = 0;
 
     if ((ret = init_muxer(s, options)) < 0)
         return ret;
 
+    s->internal->initialized = 1;
+    s->internal->streams_initialized = ret;
+
+    if (s->oformat->init && ret) {
+        if ((ret = init_pts(s)) < 0)
+            return ret;
+
+        if (s->avoid_negative_ts < 0) {
+            av_assert2(s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO);
+            if (s->oformat->flags & (AVFMT_TS_NEGATIVE | AVFMT_NOTIMESTAMPS)) {
+                s->avoid_negative_ts = 0;
+            } else
+                s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE;
+        }
+
+        return AVSTREAM_INIT_IN_INIT_OUTPUT;
+    }
+
+    return AVSTREAM_INIT_IN_WRITE_HEADER;
+}
+
+int avformat_write_header(AVFormatContext *s, AVDictionary **options)
+{
+    int ret = 0;
+    int already_initialized = s->internal->initialized;
+    int streams_already_initialized = s->internal->streams_initialized;
+
+    if (!already_initialized)
+        if ((ret = avformat_init_output(s, options)) < 0)
+            return ret;
+
     if (!(s->oformat->check_bitstream && s->flags & AVFMT_FLAG_AUTO_BSF)) {
         ret = write_header_internal(s);
         if (ret < 0)
             goto fail;
     }
 
-    if ((ret = init_pts(s)) < 0)
-        goto fail;
+    if (!s->internal->streams_initialized) {
+        if ((ret = init_pts(s)) < 0)
+            goto fail;
 
-    if (s->avoid_negative_ts < 0) {
-        av_assert2(s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO);
-        if (s->oformat->flags & (AVFMT_TS_NEGATIVE | AVFMT_NOTIMESTAMPS)) {
-            s->avoid_negative_ts = 0;
-        } else
-            s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE;
+        if (s->avoid_negative_ts < 0) {
+            av_assert2(s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO);
+            if (s->oformat->flags & (AVFMT_TS_NEGATIVE | AVFMT_NOTIMESTAMPS)) {
+                s->avoid_negative_ts = 0;
+            } else
+                s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE;
+        }
     }
 
-    return 0;
+    return streams_already_initialized;
 
 fail:
     if (s->oformat->deinit)
@@ -1292,6 +1328,10 @@ fail:
     if (s->oformat->deinit)
         s->oformat->deinit(s);
 
+    s->internal->header_written =
+    s->internal->initialized =
+    s->internal->streams_initialized = 0;
+
     if (s->pb)
        avio_flush(s->pb);
     if (ret == 0)
diff --git a/libavformat/version.h b/libavformat/version.h
index 88b69e9..addff03 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -32,7 +32,7 @@
 // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium)
 // Also please add any ticket numbers that you believe might be affected here
 #define LIBAVFORMAT_VERSION_MAJOR  57
-#define LIBAVFORMAT_VERSION_MINOR  53
+#define LIBAVFORMAT_VERSION_MINOR  54
 #define LIBAVFORMAT_VERSION_MICRO 100
 
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \



More information about the ffmpeg-cvslog mailing list