commit 71a9b4ac439c4e354432a8f828632f39c0dd6c29
parent d7a0f85091578faae3e0ace1ca8b32ca0a92c087
Author: Mattias Andrée <maandree@kth.se>
Date: Tue, 10 Jan 2017 07:30:36 +0100
Add vu-split
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat:
3 files changed, 93 insertions(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
@@ -19,6 +19,7 @@ BIN =\
vu-set-luma\
vu-set-saturation\
vu-single-colour\
+ vu-split\
vu-stack\
vu-to-image\
vu-write-head
diff --git a/TODO b/TODO
@@ -1,5 +1,4 @@
vu-transpose transpose frames
-vu-split split a video into multiple vidoes
vu-blur gaussian blur, -c to only blur chroma
vu-transform transformation by matrix multiplication, -t for tiling, -s for improve quality
on downscaling (pixels' neighbours must not change)
diff --git a/src/vu-split.c b/src/vu-split.c
@@ -0,0 +1,92 @@
+/* See LICENSE file for copyright and license details. */
+#include "arg.h"
+#include "stream.h"
+#include "util.h"
+
+#include <alloca.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <string.h>
+#include <unistd.h>
+
+static void
+usage(void)
+{
+ eprintf("usage: %s (file end-point) ...\n", argv0);
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct stream stream;
+ size_t *ends, i, parts, ptr, end, frame_size, max, ptw, n;
+ FILE *fp;
+ int fd;
+ ssize_t r;
+
+ ARGBEGIN {
+ default:
+ usage();
+ } ARGEND;
+
+ if (argc < 2 || argc % 2)
+ usage();
+
+ stream.file = "<stdin>";
+ stream.fd = STDIN_FILENO;
+ einit_stream(&stream);
+ if (stream.width > SIZE_MAX / stream.height)
+ eprintf("%s: video is too large\n", stream.file);
+ frame_size = stream.width * stream.height;
+ if (stream.frames > SSIZE_MAX / frame_size)
+ eprintf("%s: video is too large\n", stream.file);
+
+ parts = (size_t)argc / 2;
+ ends = alloca(parts * sizeof(*ends));
+
+ for (i = 0; i < parts; i++) {
+ if (!strcmp(argv[i * 2 + 1], "end"))
+ ends[i] = stream.frames;
+ else if (tozu(argv[i * 2 + 1], 0, SIZE_MAX, ends + i))
+ eprintf("the end point must be an integer in [0, %zu]\n", SIZE_MAX);
+ if (i && ends[i] <= ends[i - 1])
+ eprintf("the end points must be in strictly ascending order\n");
+ if (ends[i] > stream.frames)
+ eprintf("frame %zu is beyond the end of the video\n", ends[i]);
+ }
+
+ ptr = 0;
+ for (i = 0; i < parts; i++) {
+ fd = open(argv[i * 2], O_WRONLY);
+ if (fd < 0)
+ eprintf("open %s:", argv[i * 2]);
+ fp = fdopen(fd, "wb");
+
+ stream.frames = ends[i] - (i ? ends[i - 1] : 0);
+ fprint_stream_head(fp, &stream);
+ fflush(fp);
+ if (ferror(fp))
+ eprintf("%s:", argv[i * 2]);
+
+ for (end = ends[i] * frame_size; ptr < end; ptr += n) {
+ for (ptw = ptr; stream.ptr && ptw < end;) {
+ max = end - ptw;
+ max = max < stream.ptr ? max : stream.ptr;
+ r = write(fd, stream.buf, max);
+ if (r < 0)
+ eprintf("write %s:\n", argv[i * 2]);
+ memmove(stream.buf, stream.buf + r, stream.ptr - (size_t)r);
+ }
+ n = eread_stream(&stream, end - ptr);
+ if (n == 0)
+ eprintf("%s: file is shorter than expected\n", stream.file);
+ }
+
+ if (fclose(fp))
+ eprintf("%s:", argv[i * 2]);
+ close(fd);
+ }
+
+ return 0;
+}