Quite low latency streaming would enjoy sparing the muxer setup time
when possible.
The segment muxer would be simplified a lot and the mpegts corner case
would be solved clearly.
Any application using more than once a muxer could spare a deinit/init
cycle.
---

Now with documentation and both ends covered

 libavformat/avformat.h |  73 +++++++++++++++++++++++++++++++
 libavformat/mux.c      | 115 ++++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 177 insertions(+), 11 deletions(-)

diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index f9f39a6..32db1b3 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -407,7 +407,22 @@ typedef struct AVOutputFormat {
      */
     int priv_data_size;
 
+    /**
+     * Initialize the muxer context and write the header.
+     * @deprecated implement the split functions below.
+     */
     int (*write_header)(struct AVFormatContext *);
+
+    /**
+     * Initialize the muxer context.
+     */
+    int (*init)(struct AVFormatContext *);
+
+    /**
+     * Write the header, requires an initialized context.
+     */
+    int (*write_header2)(struct AVFormatContext *);
+
     /**
      * Write a packet. If AVFMT_ALLOW_FLUSH is set in flags,
      * pkt can be NULL in order to flush data buffered in the muxer.
@@ -416,7 +431,13 @@ typedef struct AVOutputFormat {
      * data.
      */
     int (*write_packet)(struct AVFormatContext *, AVPacket *pkt);
+
     int (*write_trailer)(struct AVFormatContext *);
+
+    int (*write_trailer2)(struct AVFormatContext *);
+
+    int (*deinit)(struct AVFormatContext *);
+
     /**
      * Currently only used to set pixel format if not YUV420P.
      */
@@ -1427,6 +1448,35 @@ void avformat_close_input(AVFormatContext **s);
 int avformat_write_header(AVFormatContext *s, AVDictionary **options);
 
 /**
+ * Allocate the stream private data.
+ *
+ * @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 openened 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 0 on success, negative AVERROR on failure.
+ *
+ * @see av_opt_find, av_dict_set, avio_open, av_oformat_next.
+ */
+int avformat_mux_init(AVFormatContext *s, AVDictionary **options);
+
+/**
+ * Write the stream header to an output media file.
+ *
+ * @param s Media file handle, must be initialized by avformat_mux_init().
+ *          Its oformat field must be set to the desired output format;
+ *          Its pb field must be set to an already openened AVIOContext.
+ *
+ * @return 0 on success, negative AVERROR on failure.
+ *
+ * @see avio_open, av_oformat_next, avformat_mux_init.
+ */
+int avformat_mux_header(AVFormatContext *s);
+
+/**
  * Write a packet to an output media file.
  *
  * The packet shall contain one audio or video frame.
@@ -1494,6 +1544,29 @@ int av_interleave_packet_per_dts(AVFormatContext *s, 
AVPacket *out,
 int av_write_trailer(AVFormatContext *s);
 
 /**
+ * Write the stream trailer to an output media file.
+ *
+ * May only be called after a successful call to av_write_header or
+ * avformat_mux_init.
+ *
+ * Can be safely called multiple times.
+ *
+ * @param s media file handle
+ * @return 0 if OK, AVERROR_xxx on error
+ */
+int avformat_mux_trailer(AVFormatContext *s);
+
+/**
+ * Free the file private data.
+ *
+ * May only be called after a successful call to av_write_header or
+ * avformat_mux_init.
+ *
+ * @param s media file handle
+ */
+void avformat_mux_deinit(AVFormatContext *s);
+
+/**
  * Return the output format in the list of registered output formats
  * which best matches the provided parameters, or return NULL if
  * there is no match.
diff --git a/libavformat/mux.c b/libavformat/mux.c
index 96eecb5..28074fa 100644
--- a/libavformat/mux.c
+++ b/libavformat/mux.c
@@ -303,6 +303,17 @@ int avformat_write_header(AVFormatContext *s, AVDictionary 
**options)
         ret = s->oformat->write_header(s);
         if (ret < 0)
             return ret;
+    } else {
+        if (s->oformat->init) {
+            ret = s->oformat->init(s);
+            if (ret < 0)
+                return ret;
+        }
+        if (s->oformat->write_header2) {
+            ret = s->oformat->write_header2(s);
+            if (ret < 0)
+                return ret;
+        }
     }
 
     if ((ret = init_pts(s) < 0))
@@ -311,6 +322,38 @@ int avformat_write_header(AVFormatContext *s, AVDictionary 
**options)
     return 0;
 }
 
+int avformat_mux_init(AVFormatContext *s, AVDictionary **options)
+{
+    int ret = 0;
+
+    if (ret = init_muxer(s, options))
+        return ret;
+
+    if (s->oformat->init) {
+        ret = s->oformat->init(s);
+        if (ret < 0)
+            return ret;
+    }
+
+    if ((ret = init_pts(s) < 0))
+        return ret;
+
+    return 0;
+}
+
+int avformat_mux_header(AVFormatContext *s)
+{
+    int ret = 0;
+
+    if (s->oformat->write_header2) {
+        ret = s->oformat->write_header2(s);
+        if (ret < 0)
+            return ret;
+    }
+
+    return 0;
+}
+
 //FIXME merge with compute_pkt_fields
 static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt)
 {
@@ -562,15 +605,14 @@ int av_interleaved_write_frame(AVFormatContext *s, 
AVPacket *pkt)
     }
 }
 
-int av_write_trailer(AVFormatContext *s)
+static int flush_trailing_packets(AVFormatContext *s)
 {
-    int ret, i;
+    int ret = 0;
 
-    for (;; ) {
+    for (;;) {
         AVPacket pkt;
         ret = interleave_packet(s, &pkt, NULL, 1);
-        if (ret < 0) //FIXME cleanup needed for ret<0 ?
-            goto fail;
+        //FIXME cleanup needed for ret < 0 ?
         if (!ret)
             break;
 
@@ -581,22 +623,73 @@ int av_write_trailer(AVFormatContext *s)
         av_free_packet(&pkt);
 
         if (ret < 0)
-            goto fail;
+            break;
     }
 
-    if (s->oformat->write_trailer)
-        ret = s->oformat->write_trailer(s);
+    return ret;
+}
 
-    if (!(s->oformat->flags & AVFMT_NOFILE))
-        avio_flush(s->pb);
+void avformat_mux_deinit(AVFormatContext *s)
+{
+    int i;
+
+    if (s->oformat->deinit) {
+        s->oformat->deinit(s);
+    }
 
-fail:
     for (i = 0; i < s->nb_streams; i++) {
         av_freep(&s->streams[i]->priv_data);
         av_freep(&s->streams[i]->index_entries);
     }
+
     if (s->oformat->priv_class)
         av_opt_free(s->priv_data);
     av_freep(&s->priv_data);
+}
+
+int avformat_mux_trailer(AVFormatContext *s)
+{
+    int ret;
+
+    ret = flush_trailing_packets(s);
+    if (ret < 0)
+        return ret;
+
+    if (s->oformat->write_trailer2) {
+        ret = s->oformat->write_trailer2(s);
+        if (ret < 0)
+            return ret;
+    }
+
+    if (!(s->oformat->flags & AVFMT_NOFILE))
+        avio_flush(s->pb);
+
     return ret;
 }
+
+int av_write_trailer(AVFormatContext *s)
+{
+    int ret;
+
+    ret = flush_trailing_packets(s);
+    if (ret < 0)
+        goto fail;
+
+    if (s->oformat->write_trailer)
+        ret = s->oformat->write_trailer(s);
+    else {
+        if (s->oformat->write_trailer2) {
+            ret = s->oformat->write_trailer2(s);
+            if (ret < 0)
+                goto fail;
+        }
+    }
+
+    if (!(s->oformat->flags & AVFMT_NOFILE))
+        avio_flush(s->pb);
+
+fail:
+    avformat_mux_deinit(s);
+    return ret;
+}
+
-- 
1.7.12

_______________________________________________
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to