diff options
author | Michael Niedermayer <michael@niedermayer.cc> | 2016-07-18 14:42:22 +0200 |
---|---|---|
committer | Michael Niedermayer <michael@niedermayer.cc> | 2016-07-19 18:41:19 +0200 |
commit | 64caafaeb18ac68eebbb3adccbd87cabc53ba9cc (patch) | |
tree | 2ec830c064d73351f3b4096e5d606e6367e293b1 /libavformat/teeproto.c | |
parent | 21c081a2465172a8ea6c6598deea1872d0a7a045 (diff) | |
download | ffmpeg-64caafaeb18ac68eebbb3adccbd87cabc53ba9cc.tar.gz |
avformat: Add tee protocol
Option passing support will be submitted seperately to the ML
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
Diffstat (limited to 'libavformat/teeproto.c')
-rw-r--r-- | libavformat/teeproto.c | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/libavformat/teeproto.c b/libavformat/teeproto.c new file mode 100644 index 0000000000..62055de990 --- /dev/null +++ b/libavformat/teeproto.c @@ -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" +}; |