commit 3e0822a8a5127a5ba395bc506622af73d75af0ab
parent bbd8ee77641288bb9051c99bc90d294ec1baa7cb
Author: Mattias Andrée <maandree@kth.se>
Date: Sat, 3 Jun 2017 18:38:37 +0200
blind-repeat: add -f and fix reading from file bug
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat:
3 files changed, 68 insertions(+), 9 deletions(-)
diff --git a/TODO b/TODO
@@ -56,8 +56,6 @@ bug: blind-stack: cannot use file outside /dev/fd/
Add [-j jobs] to blind-from-video and blind-to-video.
-Add -f (framewise) to blind-repeat
-
Generate a header file with the appropriate values for USING_BINARY32, USING_BINARY64.
long double is slightly faster than long.
long double (xyza q) could be added as another format.
diff --git a/man/blind-repeat.1 b/man/blind-repeat.1
@@ -3,7 +3,8 @@
blind-repeat - Repeat a video
.SH SYNOPSIS
.B blind-repeat
-.RI ( count
+([-f]
+.I count
|
.RB ' inf ')
.I file
@@ -33,12 +34,25 @@ will read stdin into memory; you are highly discouraged
from using this unless stdin is a single frame, or known
to only be a very small number of frames, is it can
potentially use all of the computer's memory.
+.SH OPTIONS
+.TP
+.B -f
+Repeat each frames
+.B count
+times before copying the next frame, rather than
+copying the entire video
+.B count
+times.
.SH REQUIREMENTS
.B blind-repeat
requires enough free memory to load the entire video
into memory if it is read from stdin. A frame requires
32 bytes per pixel it contains. So for a 720p video at
25 Hz, 1 GB is reached in just below 1.5 seconds.
+However, if
+.B -f
+is used, only a full video frame will be loaded into
+memory rather than an entire video, if reading from stdin.
.SH SEE ALSO
.BR blind (7),
.BR blind-from-image (1)
diff --git a/src/blind-repeat.c b/src/blind-repeat.c
@@ -1,7 +1,7 @@
/* See LICENSE file for copyright and license details. */
#include "common.h"
-USAGE("(count | 'inf') file")
+USAGE("([-f] count | 'inf') file")
static size_t count = 0;
static int inf;
@@ -10,6 +10,7 @@ static struct stream stream;
static int
repeat_regular_file(void)
{
+ stream.ptr = 0;
while (inf || count--) {
fadvise_sequential(stream.fd, (off_t)(stream.headlen), 0);
elseek(stream.fd, (off_t)(stream.headlen), SEEK_SET, stream.file);
@@ -20,6 +21,22 @@ repeat_regular_file(void)
}
static int
+repeat_regular_file_framewise(void)
+{
+ size_t i;
+ off_t off = (off_t)(stream.headlen);
+ stream.ptr = 0;
+ echeck_dimensions(&stream, WIDTH | HEIGHT | LENGTH, "input");
+ for (;; off += (off_t)(stream.frame_size)) {
+ for (i = 0; i < count; i++) {
+ elseek(stream.fd, off, SEEK_SET, stream.file);
+ if (!esend_frames(&stream, STDOUT_FILENO, 1, "<stdout>"))
+ return 0;
+ }
+ }
+}
+
+static int
repeat_stdin(void)
{
size_t ptr = stream.ptr;
@@ -32,24 +49,54 @@ repeat_stdin(void)
return free(buf), 0;
}
+static int
+repeat_stdin_framewise(void)
+{
+ char *buf;
+ size_t i;
+ echeck_dimensions(&stream, WIDTH | HEIGHT, "input");
+ buf = emalloc(stream.frame_size);
+ while (eread_frame(&stream, buf))
+ for (i = 0; i < count; i++)
+ if (writeall(STDOUT_FILENO, buf, stream.frame_size))
+ return free(buf), -1;
+ return free(buf), 0;
+}
+
int
main(int argc, char *argv[])
{
- UNOFLAGS(argc != 2);
+ int framewise = 0;
- if ((inf = !strcmp(argv[0], "inf")))
+ ARGBEGIN {
+ case 'f':
+ framewise = 1;
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ if (argc != 2)
+ usage();
+
+ if ((inf = !strcmp(argv[0], "inf"))) {
+ if (framewise)
+ usage();
einf_check_fd(STDOUT_FILENO, "<stdout>");
- else
+ } else {
count = etozu_arg("the count", argv[0], 0, SIZE_MAX);
+ }
eopen_stream(&stream, !strcmp(argv[1], "-") ? NULL : argv[1]);
- if (count > SIZE_MAX / stream.frames)
+ if (stream.frames && count > SIZE_MAX / stream.frames)
eprintf("%s: video is too long\n", stream.file);
stream.frames *= count;
fprint_stream_head(stdout, &stream);
efflush(stdout, "<stdout>");
- if (!strcmp(argv[1], "-") ? repeat_stdin() : repeat_regular_file())
+ if (!strcmp(argv[1], "-")
+ ? (framewise ? repeat_stdin_framewise() : repeat_stdin())
+ : (framewise ? repeat_regular_file_framewise(): repeat_regular_file()))
if (!inf || errno != EPIPE)
eprintf("write <stdout>:");