blind-reverse.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-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 }