avformat: Add tee protocol
authorMichael Niedermayer <michael@niedermayer.cc>
Mon, 18 Jul 2016 12:42:22 +0000 (14:42 +0200)
committerMichael Niedermayer <michael@niedermayer.cc>
Tue, 19 Jul 2016 16:41:19 +0000 (18:41 +0200)
Option passing support will be submitted seperately to the ML

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
Changelog
doc/protocols.texi
libavformat/Makefile
libavformat/protocols.c
libavformat/teeproto.c [new file with mode: 0644]
libavformat/version.h

index f2a1dcd..f545d91 100644 (file)
--- a/Changelog
+++ b/Changelog
@@ -3,6 +3,7 @@ releases are sorted from youngest to oldest.
 
 version <next>:
 - libopenmpt demuxer
+- tee protocol
 
 
 version 3.1:
index 9bbd131..4bc554b 100644 (file)
@@ -1159,6 +1159,15 @@ Play an AVI file directly from a TAR archive:
 subfile,,start,183241728,end,366490624,,:archive.tar
 @end example
 
+@section tee
+
+Writes the output to multiple protocols. The individual outputs are seperated
+by |
+
+@example
+tee:file://path/to/local/this.avi|file://path/to/local/that.avi
+@end example
+
 @section tcp
 
 Transmission Control Protocol.
index 6451c1c..52f35f0 100644 (file)
@@ -564,6 +564,7 @@ OBJS-$(CONFIG_RTP_PROTOCOL)              += rtpproto.o
 OBJS-$(CONFIG_SCTP_PROTOCOL)             += sctp.o
 OBJS-$(CONFIG_SRTP_PROTOCOL)             += srtpproto.o srtp.o
 OBJS-$(CONFIG_SUBFILE_PROTOCOL)          += subfile.o
+OBJS-$(CONFIG_TEE_PROTOCOL)              += teeproto.o
 OBJS-$(CONFIG_TCP_PROTOCOL)              += tcp.o
 OBJS-$(CONFIG_TLS_GNUTLS_PROTOCOL)       += tls_gnutls.o tls.o
 OBJS-$(CONFIG_TLS_OPENSSL_PROTOCOL)      += tls_openssl.o tls.o
index 124010c..b250f49 100644 (file)
@@ -53,6 +53,7 @@ extern const URLProtocol ff_rtp_protocol;
 extern const URLProtocol ff_sctp_protocol;
 extern const URLProtocol ff_srtp_protocol;
 extern const URLProtocol ff_subfile_protocol;
+extern const URLProtocol ff_tee_protocol;
 extern const URLProtocol ff_tcp_protocol;
 extern const URLProtocol ff_tls_gnutls_protocol;
 extern const URLProtocol ff_tls_schannel_protocol;
diff --git a/libavformat/teeproto.c b/libavformat/teeproto.c
new file mode 100644 (file)
index 0000000..62055de
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Tee 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 TeeContext {
+    const AVClass *class;
+    int child_count;
+    ChildContext *child;
+} TeeContext;
+
+static const AVOption tee_options[] = {
+    { NULL }
+};
+
+static const AVClass tee_class = {
+    .class_name = "tee",
+    .item_name  = av_default_item_name,
+    .option     = tee_options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+static const char *const child_delim = "|";
+
+static int tee_write(URLContext *h, const unsigned char *buf, int size)
+{
+    TeeContext *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 tee_close(URLContext *h)
+{
+    TeeContext *c = h->priv_data;
+    int i;
+    int main_ret = 0;
+
+    for (i=0; i<c->child_count; i++) {
+        int ret = ffurl_closep(&c->child[i].url_context);
+        if (ret < 0)
+            main_ret = ret;
+    }
+
+    av_freep(&c->child);
+    c->child_count = 0;
+    return main_ret;
+}
+
+static int tee_open(URLContext *h, const char *filename, int flags)
+{
+    TeeContext *c = h->priv_data;
+    int ret, i;
+
+    av_strstart(filename, "tee:", &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:
+    tee_close(h);
+    return ret;
+}
+const URLProtocol ff_tee_protocol = {
+    .name                = "tee",
+    .url_open            = tee_open,
+    .url_write           = tee_write,
+    .priv_data_size      = sizeof(TeeContext),
+    .priv_data_class     = &tee_class,
+    .default_whitelist   = "crypto,file,http,https,httpproxy,rtmp,tcp,tls"
+};
index 3921ee5..307542e 100644 (file)
@@ -32,7 +32,7 @@
 // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium)
 // Also please add any ticket numbers that you belive might be affected here
 #define LIBAVFORMAT_VERSION_MAJOR  57
-#define LIBAVFORMAT_VERSION_MINOR  42
+#define LIBAVFORMAT_VERSION_MINOR  43
 #define LIBAVFORMAT_VERSION_MICRO 100
 
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \