blind

suckless command-line video editing utility
git clone git://git.suckless.org/blind
Log | Files | Refs | README | LICENSE

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:
MTODO | 2--
Mman/blind-repeat.1 | 16+++++++++++++++-
Msrc/blind-repeat.c | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++------
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>:");