commit 3e0822a8a5127a5ba395bc506622af73d75af0ab
Author:     Mattias Andrée <[email protected]>
AuthorDate: Sat Jun 3 18:38:37 2017 +0200
Commit:     Mattias Andrée <[email protected]>
CommitDate: Sat Jun 3 18:38:37 2017 +0200

    blind-repeat: add -f and fix reading from file bug
    
    Signed-off-by: Mattias Andrée <[email protected]>

diff --git a/TODO b/TODO
index 1d59c23..e279eee 100644
--- 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
index ce5a8c0..bbd54b6 100644
--- 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
index b7763eb..e56586d 100644
--- 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>:");
 

Reply via email to