blind

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

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:
MMakefile | 1+
Msrc/stream.c | 6+++---
Asrc/vu-rewrite-head.c | 127+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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; +}