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

2017-04-11 Thread Moritz Barsnick
On Tue, Apr 11, 2017 at 14:12:08 +1000, Timothy Lee wrote:
> 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.

Nice!

> +Input stream capturing protocol.

Probably worth pointing out more exactly what it does. Even I can only
guess: Dumps the raw payload, in *addition* to demuxing the input as
normal.

> +A capture URL has the form:
> +@example
> +capture:@var{URL}

That makes it an additional protocol prefix, right? So you can end up
having two (or more?). "capture:file:/path/bla"
(Confusing to me as a user at first sight, but ingenious if it works.
Yes, I did test it.)

> +For example, to capture the input stream as @file{stream.sav} during 
> playback:
> +@example
> +ffplay -capture_file stream.sav capture:@var{URL}

So, is this the perfect replacement for "mplayer -dumpstream [-dumpfile
capture.dat]"? :-) Probably also worth noting somewhere.

If you go with Nicolas's suggestions, this comment is obsolete, but:

> +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");

If you're going to print a message, please also evaluate errno, for the
sake of the user.

Moritz
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


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

2017-04-11 Thread Nicolas George
Le duodi 22 germinal, an CCXXV, Timothy Lee a écrit :
> 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

Thanks, I like this version much better. See comments below.

> 
> 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 00..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

Is there a reason you use direct I/O, and have to suffer all that
boilerplate code? You could achieve the same result with
avio_open2(&c->capture, c->capture_file), with extra features and less
code.

> +
> +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");

I think it would be better to return an error than test fd everywhere.

> +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))
> +{

Nit: br

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

2017-04-10 Thread Timothy Lee
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 00..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",