blind

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

blind-reverse.c (2377B)


      1 /* See LICENSE file for copyright and license details. */
      2 #include "common.h"
      3 
      4 USAGE("[-i] file")
      5 
      6 static void
      7 to_stdout(struct stream *stream)
      8 {
      9 	size_t ptr, end, n;
     10 	char buf[BUFSIZ];
     11 
     12 	while (stream->frames--) {
     13 		ptr = stream->frames * stream->frame_size + stream->headlen;
     14 		end = ptr + stream->frame_size;
     15 		while (ptr < end) {
     16 			if (!(n = epread(stream->fd, buf, MIN(sizeof(buf), end - ptr),
     17 					 (off_t)ptr, stream->file)))
     18 				eprintf("%s: file is shorter than expected\n", stream->file);
     19 			ptr += n;
     20 			ewriteall(STDOUT_FILENO, buf, n, "<stdout>");
     21 		}
     22 	}
     23 }
     24 
     25 static void
     26 elseek_set(int fd, off_t offset, const char *fname)
     27 {
     28 	off_t r = elseek(fd, offset, SEEK_SET, fname);
     29 	if (r != offset)
     30 		eprintf("%s: file is shorter than expected\n", fname);
     31 }
     32 
     33 static void
     34 epread_frame(struct stream *stream, char *buf, off_t off)
     35 {
     36 	stream->ptr = stream->xptr = 0;
     37 	elseek_set(stream->fd, off, stream->file);
     38 	eread_frame(stream, buf);
     39 }
     40 
     41 static void
     42 epwrite_frame(struct stream *stream, char *buf, off_t off)
     43 {
     44 	elseek_set(stream->fd, off, stream->file);
     45 	ewriteall(stream->fd, buf, stream->frame_size, stream->file);
     46 }
     47 
     48 static void
     49 in_place(struct stream *stream)
     50 {
     51 	size_t f, fm = stream->frames - 1;
     52 	off_t pa, pb;
     53 	char *bufa, *bufb;
     54 
     55 	bufa = emalloc(stream->frame_size);
     56 	bufb = emalloc(stream->frame_size);
     57 
     58 	for (f = 0; f < stream->frames >> 1; f++) {
     59 		pa = (off_t)f        * (off_t)(stream->frame_size) + (off_t)(stream->headlen);
     60 		pb = (off_t)(fm - f) * (off_t)(stream->frame_size) + (off_t)(stream->headlen);
     61 
     62 		epread_frame(stream, bufa, pa);
     63 		epread_frame(stream, bufb, pb);
     64 
     65 		epwrite_frame(stream, bufa, pb);
     66 		epwrite_frame(stream, bufb, pa);
     67 	}
     68 
     69 	free(bufa);
     70 	free(bufb);
     71 }
     72 
     73 int
     74 main(int argc, char *argv[])
     75 {
     76 	struct stream stream;
     77 	int inplace = 0;
     78 
     79 	ARGBEGIN {
     80 	case 'i':
     81 		inplace = 1;
     82 		break;
     83 	default:
     84 		usage();
     85 	} ARGEND;
     86 	
     87 	if (argc != 1)
     88 		usage();
     89 
     90 	stream.file = argv[0];
     91 	stream.fd = eopen(stream.file, inplace ? O_RDWR : O_RDONLY);
     92 	einit_stream(&stream);
     93 	if (!inplace) {
     94 		fprint_stream_head(stdout, &stream);
     95 		efflush(stdout, "<stdout>");
     96 	}
     97 	echeck_dimensions(&stream, WIDTH | HEIGHT, NULL);
     98 	if (stream.frames * stream.frame_size > (size_t)SSIZE_MAX - stream.headlen)
     99 		eprintf("%s: video is too large\n", stream.file);
    100 
    101 	fadvise_random(stream.fd, 0, 0);
    102 
    103 	(inplace ? in_place : to_stdout)(&stream);
    104 	close(stream.fd);
    105 	return 0;
    106 }