blind

suckless command-line video editing utility
git clone git://git.suckless.org/blind
Log | Files | Refs | README | 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 }