commit c8c0993707b0780cb362892b2f78decaabce5f72
parent ec4ee45678679fd1a2b64bebe59b0612eaff2d6e
Author: Mattias Andrée <maandree@kth.se>
Date: Thu, 12 Jan 2017 01:37:54 +0100
Add vu-rewrite-head
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat:
3 files changed, 131 insertions(+), 3 deletions(-)
diff --git a/Makefile b/Makefile
@@ -17,6 +17,7 @@ BIN =\
vu-read-head\
vu-repeat\
vu-reverse\
+ vu-rewrite-head\
vu-set-alpha\
vu-set-luma\
vu-set-saturation\
diff --git a/src/stream.c b/src/stream.c
@@ -44,19 +44,19 @@ eninit_stream(int status, struct stream *stream)
errno = 0;
stream->frames = strtoul(stream->buf, &end, 10);
if (errno == ERANGE && *stream->buf != '-')
- eprintf("%s: too long\n", stream->file);
+ eprintf("%s: video is too long\n", stream->file);
if (errno || *end)
goto bad_format;
errno = 0;
stream->width = strtoul(w, &end, 10);
if (errno == ERANGE && *stream->buf != '-')
- eprintf("%s: too wide\n", stream->file);
+ eprintf("%s: video is too wide\n", stream->file);
if (errno || *end)
goto bad_format;
errno = 0;
stream->height = strtoul(h, &end, 10);
if (errno == ERANGE && *stream->buf != '-')
- eprintf("%s: too tall\n", stream->file);
+ eprintf("%s: video is too tall\n", stream->file);
if (errno || *end)
goto bad_format;
diff --git a/src/vu-rewrite-head.c b/src/vu-rewrite-head.c
@@ -0,0 +1,127 @@
+/* See LICENSE file for copyright and license details. */
+#include "stream.h"
+#include "util.h"
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <inttypes.h>
+#include <string.h>
+#include <unistd.h>
+
+USAGE("[-h] file [(frames | 'auto') [(width | 'same') (height | 'same') [format | 'same']]]")
+
+static void
+rewrite(struct stream *stream, int frames_auto)
+{
+ char head[3 * sizeof(size_t) + 4 + sizeof(stream->pixfmt) + 6];
+ ssize_t headlen;
+ size_t frame_size, frame_count, length;
+ struct stat st;
+ char *data;
+
+ echeck_frame_size(stream->width, stream->height, stream->pixel_size, 0, stream->file);
+ frame_size = stream->width * stream->height * stream->pixel_size;
+
+ if (fstat(stream->fd, &st))
+ eprintf("fstat %s:", stream->file);
+ if (!S_ISREG(st.st_mode))
+ eprintf("%s: not a regular file\n", stream->file);
+
+ frame_count = (size_t)(st.st_size) / frame_size;
+ if (frame_count * frame_size != (size_t)(st.st_size))
+ eprintf("%s: given the select width and height, "
+ "the file has an incomplete frame\n", stream->file);
+ if (frames_auto)
+ stream->frames = frame_count;
+ else if (stream->frames != frame_count)
+ eprintf("%s: frame count mismatch\n", stream->file);
+
+ sprintf(head, "%zu %zu %zu %s\n%cuivf%zn",
+ stream->frames, stream->width, stream->height, stream->pixfmt, 0, &headlen);
+
+ length = stream->frames * frame_size;
+ if (length > (size_t)SSIZE_MAX || headlen > (size_t)SSIZE_MAX - length)
+ eprintf("%s: video is too long\n", stream->file);
+
+ if (headlen > stream->headlen)
+ if (ftruncate(stream->fd, length + headlen))
+ eprintf("ftruncate %s:", stream->file);
+
+ data = mmap(0, length + (size_t)headlen, PROT_READ | PROT_WRITE, MAP_PRIVATE, stream->fd, 0);
+ if (headlen != stream->headlen)
+ memmove(data + headlen, data + stream->headlen, length);
+ memcpy(data, head, (size_t)headlen);
+ munmap(data, length + (size_t)headlen);
+
+ if (headlen < stream->headlen)
+ if (ftruncate(stream->fd, length + headlen))
+ eprintf("ftruncate %s:", stream->file);
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct stream stream;
+ int headless = 0, frames_auto = 0;
+
+ ARGBEGIN {
+ case 'h':
+ headless = 1;
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+
+ if (headless) {
+ if (argc != 5)
+ eprintf("all positional arguments are mandatory unless -h is used\n");
+ } else if (argc != 1 || argc != 2 || argc != 4 || argc != 5) {
+ usage();
+ }
+
+
+ memset(&stream, 0, sizeof(stream));
+ stream.file = argv[0];
+ stream.fd = eopen(stream.file, O_RDWR);
+ if (!headless)
+ einit_stream(&stream);
+
+
+ if (argc < 2 || !strcmp(argv[1], "auto"))
+ frames_auto = 1;
+ else
+ stream.frames = etozu_arg("the frame count", argv[1], 0, SIZE_MAX);
+
+ if (argc < 4);
+ else if (strcmp(argv[2], "same"))
+ stream.width = etozu_arg("the width", argv[2], 1, SIZE_MAX);
+ else if (headless)
+ eprintf("cannot use both 'same' and -h\n");
+
+ if (argc < 4);
+ else if (strcmp(argv[3], "same"))
+ stream.height = etozu_arg("the height", argv[3], 1, SIZE_MAX);
+ else if (headless)
+ eprintf("cannot use both 'same' and -h\n");
+
+ if (argc < 5);
+ else if (strcmp(argv[4], "same")) {
+ if (strlen(argv[4]) >= sizeof(stream.pixfmt))
+ eprintf("choosen pixel format is unsupported\n");
+ strcpy(stream.pixfmt, argv[5]);
+ if (set_pixel_size(&stream))
+ eprintf("choosen pixel format is unsupported\n");
+ } else if (headless) {
+ eprintf("cannot use both 'same' and -h\n");
+ } else if (argc > 1) {
+ usage();
+ }
+
+
+ rewrite(&stream, frames_auto);
+ close(stream.fd);
+ return 0;
+}