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 }