Capture is an input stream capture protocol that dumps the input stream to a file. The default name of the output file is "capture.dat", but it can be changed using the "capture_file" option. --- Changelog | 1 + doc/protocols.texi | 23 ++++++++++ libavformat/Makefile | 1 + libavformat/capture.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++ libavformat/protocols.c | 1 + 5 files changed, 138 insertions(+) create mode 100644 libavformat/capture.c
diff --git a/Changelog b/Changelog index e76b324f61..3c06e84185 100644 --- a/Changelog +++ b/Changelog @@ -36,6 +36,7 @@ version 3.3: - MPEG-7 Video Signature filter - Removed asyncts filter (use af_aresample instead) - Intel QSV-accelerated VP8 video decoding +- capture protocol version 3.2: diff --git a/doc/protocols.texi b/doc/protocols.texi index a7968ff56e..89a1f2afa8 100644 --- a/doc/protocols.texi +++ b/doc/protocols.texi @@ -103,6 +103,29 @@ Cache the input stream to temporary file. It brings seeking capability to live s cache:@var{URL} @end example +@section capture + +Input stream capturing protocol. + +A capture URL has the form: +@example +capture:@var{URL} +@end example + +This protocol accepts the following option: +@table @option + +@item capture_file +Name of the capture file. +If not specified, the input stream will be written into @file{capture.dat}. + +@end table + +For example, to capture the input stream as @file{stream.sav} during playback: +@example +ffplay -capture_file stream.sav capture:@var{URL} +@end example + @section concat Physical concatenation protocol. diff --git a/libavformat/Makefile b/libavformat/Makefile index a1dae894fe..08d23baf95 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -549,6 +549,7 @@ OBJS-$(CONFIG_ASYNC_PROTOCOL) += async.o OBJS-$(CONFIG_APPLEHTTP_PROTOCOL) += hlsproto.o OBJS-$(CONFIG_BLURAY_PROTOCOL) += bluray.o OBJS-$(CONFIG_CACHE_PROTOCOL) += cache.o +OBJS-$(CONFIG_CAPTURE_PROTOCOL) += capture.o OBJS-$(CONFIG_CONCAT_PROTOCOL) += concat.o OBJS-$(CONFIG_CRYPTO_PROTOCOL) += crypto.o OBJS-$(CONFIG_DATA_PROTOCOL) += data_uri.o diff --git a/libavformat/capture.c b/libavformat/capture.c new file mode 100644 index 0000000000..90daf40877 --- /dev/null +++ b/libavformat/capture.c @@ -0,0 +1,112 @@ +/* + * Input capture protocol. + * Copyright (c) 2017 Timothy Lee + * + * 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.h" +#include <fcntl.h> +#if HAVE_IO_H +#include <io.h> +#endif +#if HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <sys/stat.h> +#include <stdlib.h> +#include "os_support.h" +#include "url.h" + +#ifndef O_BINARY +# define O_BINARY 0 +#endif + +typedef struct Context { + AVClass *class; + int fd; + int64_t count; + AVIOContext *io; + const char *capture_file; +} Context; + +static int capture_open(URLContext *h, const char *arg, int flags, AVDictionary **options) +{ + Context *c= h->priv_data; + c->fd = avpriv_open(c->capture_file, O_WRONLY|O_BINARY|O_TRUNC|O_CREAT, 0666); + if (c->fd < 0) + av_log(h, AV_LOG_ERROR, "Failed to create capture file\n"); + av_strstart(arg, "capture:", &arg); + return avio_open2(&c->io, arg, flags, &h->interrupt_callback, options); +} + +static int capture_read(URLContext *h, unsigned char *buf, int size) +{ + Context *c = h->priv_data; + int r = avio_read(c->io, buf, size); + if ((r > 0) && (c->fd >= 0)) + { + if (write(c->fd, buf, r) == r) + c->count += r; + else + av_log(h, AV_LOG_ERROR, "Cannot write to capture file\n"); + } + return r; +} + +static int64_t capture_seek(URLContext *h, int64_t pos, int whence) +{ + Context *c = h->priv_data; + return avio_seek(c->io, pos, whence); +} + +static int capture_close(URLContext *h) +{ + Context *c = h->priv_data; + av_log(h, AV_LOG_INFO, "Captured %"PRId64" bytes\n", c->count); + if (c->fd >= 0) + close(c->fd); + return avio_closep(&c->io); +} + +#define OFFSET(x) offsetof(Context, x) +#define D AV_OPT_FLAG_DECODING_PARAM + +static const AVOption options[] = { + { "capture_file", "Name of capture file", OFFSET(capture_file), AV_OPT_TYPE_STRING, { .str = "capture.dat" }, CHAR_MIN, CHAR_MAX, D }, + {NULL}, +}; + +static const AVClass capture_context_class = { + .class_name = "Capture", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const URLProtocol ff_capture_protocol = { + .name = "capture", + .url_open2 = capture_open, + .url_read = capture_read, + .url_seek = capture_seek, + .url_close = capture_close, + .priv_data_size = sizeof(Context), + .priv_data_class = &capture_context_class, +}; diff --git a/libavformat/protocols.c b/libavformat/protocols.c index 8d3555ed52..0855588740 100644 --- a/libavformat/protocols.c +++ b/libavformat/protocols.c @@ -26,6 +26,7 @@ extern const URLProtocol ff_async_protocol; extern const URLProtocol ff_bluray_protocol; extern const URLProtocol ff_cache_protocol; +extern const URLProtocol ff_capture_protocol; extern const URLProtocol ff_concat_protocol; extern const URLProtocol ff_crypto_protocol; extern const URLProtocol ff_data_protocol; -- 2.12.2 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel