[FFmpeg-devel] [PATCH] libavformat: add "capture:" protocol using AVIO

Timothy Lee timothy.ty.lee at gmail.com
Tue Apr 11 07:12:08 EEST 2017


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
 
+ at section capture
+
+Input stream capturing protocol.
+
+A capture URL has the form:
+ at example
+capture:@var{URL}
+ at end example
+
+This protocol accepts the following option:
+ at table @option
+
+ at item capture_file
+Name of the capture file.
+If not specified, the input stream will be written into @file{capture.dat}.
+
+ at end table
+
+For example, to capture the input stream as @file{stream.sav} during playback:
+ at example
+ffplay -capture_file stream.sav capture:@var{URL}
+ at 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



More information about the ffmpeg-devel mailing list