blind-rewrite-head.c - blind - suckless command-line video editing utility
 (HTM) git clone git://git.suckless.org/blind
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       blind-rewrite-head.c (3241B)
       ---
            1 /* See LICENSE file for copyright and license details. */
            2 #include "common.h"
            3 
            4 USAGE("[-h] file [(frames | 'auto') [(width | 'same') (height | 'same') [format | 'same']]]")
            5 
            6 static void
            7 rewrite(struct stream *stream, int frames_auto)
            8 {
            9         char head[STREAM_HEAD_MAX];
           10         ssize_t headlen;
           11         size_t frame_count, length;
           12         struct stat st;
           13         char *data;
           14 
           15         echeck_dimensions(stream, WIDTH | HEIGHT, NULL);
           16 
           17         if (fstat(stream->fd, &st))
           18                 eprintf("fstat %s:", stream->file);
           19         if (!S_ISREG(st.st_mode))
           20                 eprintf("%s: not a regular file\n", stream->file);
           21 
           22         frame_count = (size_t)(st.st_size) / stream->frame_size;
           23         if (frame_count * stream->frame_size != (size_t)(st.st_size) - stream->headlen)
           24                 eprintf("%s: given the select width and height, "
           25                         "the file has an incomplete frame\n", stream->file);
           26         if (frames_auto)
           27                 stream->frames = frame_count;
           28         else if (stream->frames != frame_count)
           29                 eprintf("%s: frame count mismatch\n", stream->file);
           30 
           31         SPRINTF_HEAD_ZN(head, stream->frames, stream->width, stream->height, stream->pixfmt, &headlen);
           32 
           33         length = stream->frames * stream->frame_size;
           34         if (length > (size_t)SSIZE_MAX || (size_t)headlen > (size_t)SSIZE_MAX - length)
           35                 eprintf("%s: video is too long\n", stream->file);
           36 
           37         if ((size_t)headlen > stream->headlen)
           38                 if (ftruncate(stream->fd, (off_t)length + (off_t)headlen))
           39                         eprintf("ftruncate %s:", stream->file);
           40 
           41         data = mmap(0, length + (size_t)headlen, PROT_READ | PROT_WRITE, MAP_SHARED, stream->fd, 0);
           42         if (data == MAP_FAILED)
           43                 eprintf("mmap %s:", stream->file);
           44         if ((size_t)headlen != stream->headlen)
           45                 memmove(data + headlen, data + stream->headlen, length);
           46         memcpy(data, head, (size_t)headlen);
           47         munmap(data, length + (size_t)headlen);
           48 
           49         if ((size_t)headlen < stream->headlen)
           50                 if (ftruncate(stream->fd, (off_t)length + (off_t)headlen))
           51                         eprintf("ftruncate %s:", stream->file);
           52 }
           53 
           54 int
           55 main(int argc, char *argv[])
           56 {
           57         struct stream stream;
           58         int headless = 0, frames_auto = 0;
           59 
           60         ARGBEGIN {
           61         case 'h':
           62                 headless = 1;
           63                 break;
           64         default:
           65                 usage();
           66         } ARGEND;
           67 
           68         if (headless) {
           69                 if (argc != 5)
           70                         eprintf("all positional arguments are mandatory unless -h is used\n");
           71         } else if (argc != 1 && argc != 2 && argc != 4 && argc != 5) {
           72                 usage();
           73         }
           74 
           75         memset(&stream, 0, sizeof(stream));
           76         stream.file = argv[0];
           77         stream.fd = eopen(stream.file, O_RDWR);
           78         if (!headless)
           79                 einit_stream(&stream);
           80 
           81         if (argc < 2 || !strcmp(argv[1], "auto"))
           82                 frames_auto = 1;
           83         else
           84                 stream.frames = etozu_arg("the frame count", argv[1], 0, SIZE_MAX);
           85 
           86         if (argc < 4);
           87         else if (strcmp(argv[2], "same"))
           88                 stream.width = etozu_arg("the width",  argv[2], 1, SIZE_MAX);
           89         else if (headless)
           90                 eprintf("cannot use both 'same' and -h\n");
           91 
           92         if (argc < 4);
           93         else if (strcmp(argv[3], "same"))
           94                 stream.height = etozu_arg("the height", argv[3], 1, SIZE_MAX);
           95         else if (headless)
           96                 eprintf("cannot use both 'same' and -h\n");
           97 
           98         if (argc < 5);
           99         else if (strcmp(argv[4], "same")) {
          100                 if (strlen(argv[4]) >= sizeof(stream.pixfmt))
          101                         eprintf("choosen pixel format is unsupported\n");
          102                 if (set_pixel_format(&stream, argv[5]))
          103                         eprintf("choosen pixel format is unsupported\n");
          104         } else if (headless) {
          105                 eprintf("cannot use both 'same' and -h\n");
          106         }
          107 
          108         rewrite(&stream, frames_auto);
          109         close(stream.fd);
          110         return 0;
          111 }