diff options
| author | Mattias Andrée <maandree@kth.se> | 2017-01-12 01:37:54 +0100 |
|---|---|---|
| committer | Mattias Andrée <maandree@kth.se> | 2017-01-12 01:38:44 +0100 |
| commit | c8c0993707b0780cb362892b2f78decaabce5f72 (patch) | |
| tree | 88b972b3ffafd31ffdeb0417499a896dd0700fd8 /src | |
| parent | Free all allocations at end + use calloc instead of memset (diff) | |
| download | blind-c8c0993707b0780cb362892b2f78decaabce5f72.tar.gz blind-c8c0993707b0780cb362892b2f78decaabce5f72.tar.bz2 blind-c8c0993707b0780cb362892b2f78decaabce5f72.tar.xz | |
Add vu-rewrite-head
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to 'src')
| -rw-r--r-- | src/stream.c | 6 | ||||
| -rw-r--r-- | src/vu-rewrite-head.c | 127 |
2 files changed, 130 insertions, 3 deletions
diff --git a/src/stream.c b/src/stream.c index c863c23..b4541b0 100644 --- 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 new file mode 100644 index 0000000..e7663c8 --- /dev/null +++ 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; +} |
