[FFmpeg-devel] [PATCH] avformat: Add multi protocol

Michael Niedermayer michael at niedermayer.cc
Mon Jul 18 15:42:22 EEST 2016


TODO: docs, version bump,
TODO: option passing support (as seperate commit/patch)

Signed-off-by: Michael Niedermayer <michael at niedermayer.cc>
---
 libavformat/Makefile    |    1 +
 libavformat/multi.c     |  134 +++++++++++++++++++++++++++++++++++++++++++++++
 libavformat/protocols.c |    1 +
 3 files changed, 136 insertions(+)
 create mode 100644 libavformat/multi.c

diff --git a/libavformat/Makefile b/libavformat/Makefile
index 6451c1c..b4dd6df 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -553,6 +553,7 @@ OBJS-$(CONFIG_ICECAST_PROTOCOL)          += icecast.o
 OBJS-$(CONFIG_MD5_PROTOCOL)              += md5proto.o
 OBJS-$(CONFIG_MMSH_PROTOCOL)             += mmsh.o mms.o asf.o
 OBJS-$(CONFIG_MMST_PROTOCOL)             += mmst.o mms.o asf.o
+OBJS-$(CONFIG_MULTI_PROTOCOL)            += multi.o
 OBJS-$(CONFIG_PIPE_PROTOCOL)             += file.o
 OBJS-$(CONFIG_RTMP_PROTOCOL)             += rtmpproto.o rtmppkt.o
 OBJS-$(CONFIG_RTMPE_PROTOCOL)            += rtmpproto.o rtmppkt.o
diff --git a/libavformat/multi.c b/libavformat/multi.c
new file mode 100644
index 0000000..f2e4243
--- /dev/null
+++ b/libavformat/multi.c
@@ -0,0 +1,134 @@
+/*
+ * Multi output protocol
+ * Copyright (c) 2016 Michael Niedermayer
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/avstring.h"
+#include "libavutil/opt.h"
+#include "avformat.h"
+#include "avio_internal.h"
+
+typedef struct ChildContext {
+    URLContext *url_context;
+} ChildContext;
+
+typedef struct MultiContext {
+    const AVClass *class;
+    int child_count;
+    ChildContext *child;
+} MultiContext;
+
+static const AVOption multi_options[] = {
+    { NULL }
+};
+
+static const AVClass multi_class = {
+    .class_name = "multi",
+    .item_name  = av_default_item_name,
+    .option     = multi_options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+static const char *const child_delim = "|";
+
+static int multi_write(URLContext *h, const unsigned char *buf, int size)
+{
+    MultiContext *c = h->priv_data;
+    int i;
+    int main_ret = size;
+
+    for (i=0; i<c->child_count; i++) {
+        int ret = ffurl_write(c->child[i].url_context, buf, size);
+        if (ret < 0)
+            main_ret = ret;
+    }
+    return main_ret;
+}
+
+static int multi_close(URLContext *h)
+{
+    MultiContext *c = h->priv_data;
+    int i;
+
+    for (i=0; i<c->child_count; i++) {
+        ffurl_closep(&c->child[i].url_context);
+    }
+
+    av_freep(&c->child);
+    c->child_count = 0;
+    return 0;
+}
+
+static int multi_open(URLContext *h, const char *filename, int flags)
+{
+    MultiContext *c = h->priv_data;
+    int ret, i;
+
+    av_strstart(filename, "multi:", &filename);
+
+    if (flags & AVIO_FLAG_READ)
+        return AVERROR(ENOSYS);
+
+    while (*filename) {
+        char *child_name = av_get_token(&filename, child_delim);
+        void *tmp;
+        if (!child_name) {
+            ret = AVERROR(ENOMEM);
+            goto fail;
+        }
+
+        tmp = av_realloc_array(c->child, c->child_count + 1, sizeof(*c->child));
+        if (!tmp) {
+            ret = AVERROR(ENOMEM);
+            goto fail;
+        }
+        c->child = tmp;
+        memset(&c->child[c->child_count], 0, sizeof(&c->child[c->child_count]));
+
+        ret = ffurl_open_whitelist(&c->child[c->child_count].url_context, child_name, flags,
+                                   &h->interrupt_callback, /*AVDictionary **options*/NULL,
+                                   h->protocol_whitelist, h->protocol_blacklist,
+                                   h);
+        av_free(child_name);
+        if (ret < 0)
+            goto fail;
+        c->child_count++;
+
+        if (strspn(filename, child_delim))
+            filename++;
+    }
+
+    h->is_streamed = 0;
+    for (i=0; i<c->child_count; i++) {
+        h->is_streamed |= c->child[i].url_context->is_streamed;
+    }
+
+    return 0;
+fail:
+    multi_close(h);
+    return ret;
+}
+const URLProtocol ff_multi_protocol = {
+    .name                = "multi",
+    .url_open            = multi_open,
+    .url_write           = multi_write,
+    .priv_data_size      = sizeof(MultiContext),
+    .priv_data_class     = &multi_class,
+    .default_whitelist   = "crypto,file,http,https,httpproxy,tcp,tls"
+};
\ No newline at end of file
diff --git a/libavformat/protocols.c b/libavformat/protocols.c
index 124010c..13d6621 100644
--- a/libavformat/protocols.c
+++ b/libavformat/protocols.c
@@ -42,6 +42,7 @@ extern const URLProtocol ff_icecast_protocol;
 extern const URLProtocol ff_mmsh_protocol;
 extern const URLProtocol ff_mmst_protocol;
 extern const URLProtocol ff_md5_protocol;
+extern const URLProtocol ff_multi_protocol;
 extern const URLProtocol ff_pipe_protocol;
 extern const URLProtocol ff_rtmp_protocol;
 extern const URLProtocol ff_rtmpe_protocol;
-- 
1.7.9.5



More information about the ffmpeg-devel mailing list