From patchwork Tue Apr 11 04:12:08 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Timothy Lee X-Patchwork-Id: 3360 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.44.195 with SMTP id s186csp1691068vss; Mon, 10 Apr 2017 21:12:30 -0700 (PDT) X-Received: by 10.223.132.35 with SMTP id 32mr26917232wrf.58.1491883950493; Mon, 10 Apr 2017 21:12:30 -0700 (PDT) Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id r135si1103466wmf.30.2017.04.10.21.12.29; Mon, 10 Apr 2017 21:12:30 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 01B5C689812; Tue, 11 Apr 2017 07:12:22 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-pg0-f48.google.com (mail-pg0-f48.google.com [74.125.83.48]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 0D341689883 for ; Tue, 11 Apr 2017 07:12:15 +0300 (EEST) Received: by mail-pg0-f48.google.com with SMTP id 81so115933454pgh.2 for ; Mon, 10 Apr 2017 21:12:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id; bh=0AAdAcy6nA/Ru1q6EwB4UyNSk0g+K2wYVK+GRVBYodo=; b=UXCIrbcfVItZhDZyXri6uzBK/C25yub8qX3b+XVIjAZz/dlbtL3nqLsrJ2x6p75tcE 4idyOHO4+XPMen8bdojCVzn5uJL/dW4a32cCqY6RInYO4EYFkPL7yWxd+DypQWZNwLow Vf8pUURe38/Poj6ZKxcgRMkAuHL6BF2flgs2kNb1K/prnl/aRhi7XJ+qOAZ5QS0GysZC LceYD9qf+fXlIS1/ptju3Oltqom6lZqH/bR8NXnQtWJBXWAff7NlIZFRxoLWZwViX+PQ 7C63bPhafs0G8hP94XbN5VFrgyz32m9+Hx3lE+UkVNS4j+fRG81op6/nQ3ZwfES1gyQW OP9A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id; bh=0AAdAcy6nA/Ru1q6EwB4UyNSk0g+K2wYVK+GRVBYodo=; b=E+R0omtx3x9lPDfWpsLpGw/TKjzaOWZiPmdnzaozSA/YQZhw9p82ET/FF2yqTOSstT tLPCTmtB4QY6Dzqi/RU1eCmoUxjGbNYqlJyBCPhtecxvKnBZzzJrZ8btWOPEoCsaA2VS 81T1nug658satS2oKXLiYDKlv07VxxXDj/9sqXuRVYk5vdX2Jo0TweJohpFp+P44q+NT mIKnTlQRCxfBEudhs/TctOMeLf1B14nvw1kzuJznTugcH3IlXX7nx7d3nMBlEsv2aZ0f /9Uk2x8vul5dGRxamf5fpDwmcgglwy467GYrEVPBjDQYPjD2JoaX1DaI14QWmfv7LZOz b5Xw== X-Gm-Message-State: AN3rC/7gJPPy9ontzkHs7aEAgsXm4TtXazFqtzRjOLSlVkewliNS1Hp7myEayaFXMh7vyQ== X-Received: by 10.98.10.25 with SMTP id s25mr6119075pfi.78.1491883938321; Mon, 10 Apr 2017 21:12:18 -0700 (PDT) Received: from localhost.localdomain (59-100-13-146.mel.static-ipl.aapt.com.au. [59.100.13.146]) by smtp.gmail.com with ESMTPSA id e67sm27208847pfe.64.2017.04.10.21.12.16 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 10 Apr 2017 21:12:17 -0700 (PDT) From: Timothy Lee To: ffmpeg-devel@ffmpeg.org Date: Tue, 11 Apr 2017 14:12:08 +1000 Message-Id: <20170411041208.12551-1-timothy.ty.lee@gmail.com> X-Mailer: git-send-email 2.12.2 Subject: [FFmpeg-devel] [PATCH] libavformat: add "capture:" protocol using AVIO X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" 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 +#if HAVE_IO_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#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;