TODO: docs, version bump, TODO: option passing support (as seperate commit/patch)
Signed-off-by: Michael Niedermayer <mich...@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 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel