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 }