Introduction
Introduction Statistics Contact Development Disclaimer Help
stream.c - blind - suckless command-line video editing utility
git clone git://git.suckless.org/blind
Log
Files
Refs
README
LICENSE
---
stream.c (22533B)
---
1 /* See LICENSE file for copyright and license details. */
2 #include "common.h"
3
4 static inline int
5 get_dimension(int status, size_t *out, const char *s, const char *fname,…
6 {
7 char *end;
8 errno = 0;
9 *out = strtoul(s, &end, 10);
10 if (errno == ERANGE && *s != '-')
11 enprintf(status, "%s: video is too %s\n", fname, dim);
12 return -(errno || *end);
13 }
14
15 static inline int
16 sread(int status, struct stream *stream)
17 {
18 ssize_t r;
19 r = read(stream->fd, stream->buf + stream->ptr, sizeof(stream->b…
20 if (r < 0)
21 enprintf(status, "read %s:", stream->file);
22 if (r == 0)
23 return 0;
24 stream->ptr += (size_t)r;
25 return 1;
26 }
27
28 void
29 eninit_stream(int status, struct stream *stream)
30 {
31 size_t n;
32 char *p = NULL, *w, *h, *f;
33
34 fadvise_sequential(stream->fd, 0, 0);
35
36 if (stream->fd >= 0) {
37 for (stream->ptr = 0; !p; p = memchr(stream->buf, '\n', …
38 if (!sread(status, stream))
39 goto bad_format;
40 } else {
41 p = memchr(stream->buf, '\n', stream->ptr);
42 }
43
44 *p = '\0';
45 if (!(w = strchr(stream->buf, ' ')) ||
46 !(h = strchr(w + 1, ' ')) ||
47 !(f = strchr(h + 1, ' ')))
48 goto bad_format;
49 *w++ = *h++ = *f++ = '\0';
50
51 if (strlen(f) >= sizeof(stream->pixfmt))
52 goto bad_format;
53 strcpy(stream->pixfmt, f);
54 if (get_dimension(status, &stream->frames, stream->buf, stream->…
55 get_dimension(status, &stream->width, w, stream->…
56 get_dimension(status, &stream->height, h, stream->…
57 goto bad_format;
58
59 if (!stream->width)
60 eprintf("%s: width is zero\n", stream->file);
61 if (!stream->height)
62 eprintf("%s: height is zero\n", stream->file);
63
64 n = (size_t)(p - stream->buf) + 1;
65 memmove(stream->buf, stream->buf + n, stream->ptr -= n);
66 while (stream->ptr < 5)
67 if (!sread(status, stream))
68 goto bad_format;
69 if (stream->buf[0] != '\0' ||
70 stream->buf[1] != 'u' || stream->buf[2] != 'i' ||
71 stream->buf[3] != 'v' || stream->buf[4] != 'f')
72 goto bad_format;
73 memmove(stream->buf, stream->buf + 5, stream->ptr -= 5);
74 stream->headlen = n + 5;
75
76 enset_pixel_format(status, stream, NULL);
77
78 stream->xptr = 0;
79
80 return;
81 bad_format:
82 enprintf(status, "%s: file format not supported\n", stream->file…
83 }
84
85
86 void
87 enopen_stream(int status, struct stream *stream, const char *file)
88 {
89 stream->file = file ? file : "<stdin>";
90 stream->fd = file ? enopen(status, file, O_RDONLY) : STDIN_FILEN…
91 eninit_stream(status, stream);
92 }
93
94
95 int
96 set_pixel_format(struct stream *stream, const char *pixfmt)
97 {
98 #define TEST_ENCODING_AGNOSTIC(FMT) (!strcmp(stream->pixfmt, FMT) || !st…
99
100 if (pixfmt) {
101 pixfmt = get_pixel_format(pixfmt, stream->pixfmt[0] ? st…
102 if (strlen(pixfmt) >= sizeof(stream->pixfmt))
103 return -1;
104 strcpy(stream->pixfmt, pixfmt);
105 }
106
107 stream->n_chan = 4;
108 stream->alpha = UNPREMULTIPLIED;
109 stream->encoding = DOUBLE;
110 stream->endian = HOST;
111 stream->alpha_chan = 3;
112 stream->luma_chan = -1;
113
114 if (!strcmp(stream->pixfmt, "xyza")) {
115 stream->space = CIEXYZ;
116 } else if (!strcmp(stream->pixfmt, "xyza f")) {
117 stream->space = CIEXYZ;
118 stream->encoding = FLOAT;
119 } else if (!strcmp(stream->pixfmt, "raw0")) {
120 stream->space = YUV_NONLINEAR;
121 stream->encoding = UINT16;
122 stream->endian = LITTLE;
123 stream->alpha_chan = 0;
124 stream->luma_chan = 1;
125 } else if (!strcmp(stream->pixfmt, "raw1")) {
126 stream->space = YUV_NONLINEAR;
127 stream->encoding = UINT16;
128 stream->endian = LITTLE;
129 } else if (!strcmp(stream->pixfmt, "raw2a") || !strcmp(stream->p…
130 stream->space = YUV_NONLINEAR;
131 stream->alpha = stream->pixfmt[4] == 'a' ? UNPREMULTIPLI…
132 stream->encoding = UINT16;
133 } else if (TEST_ENCODING_AGNOSTIC("raw3") || TEST_ENCODING_AGNOS…
134 stream->space = YUV_NONLINEAR;
135 stream->alpha = stream->pixfmt[4] == 'a' ? UNPREMULTIPLI…
136 stream->encoding = strlen(stream->pixfmt) > 5 ? FLOAT : …
137 } else if (TEST_ENCODING_AGNOSTIC("raw4") || TEST_ENCODING_AGNOS…
138 stream->space = SRGB_NONLINEAR;
139 stream->alpha = stream->pixfmt[4] == 'a' ? UNPREMULTIPLI…
140 stream->encoding = strlen(stream->pixfmt) > 5 ? FLOAT : …
141 } else if (TEST_ENCODING_AGNOSTIC("raw5") || TEST_ENCODING_AGNOS…
142 stream->space = SRGB;
143 stream->alpha = stream->pixfmt[4] == 'a' ? UNPREMULTIPLI…
144 stream->encoding = strlen(stream->pixfmt) > 5 ? FLOAT : …
145 } else {
146 return -1;
147 }
148
149 if (stream->alpha == NO_ALPHA) {
150 stream->n_chan -= 1;
151 stream->alpha_chan = -1;
152 }
153
154 if (stream->luma_chan == -1) {
155 if (stream->space == CIEXYZ)
156 stream->luma_chan = 1;
157 else if (stream->space == YUV_NONLINEAR)
158 stream->luma_chan = 0;
159 }
160
161 switch (stream->encoding) {
162 case FLOAT:
163 stream->chan_size = sizeof(float);
164 break;
165 case DOUBLE:
166 stream->chan_size = sizeof(double);
167 break;
168 case LONG_DOUBLE:
169 stream->chan_size = sizeof(long double);
170 break;
171 case UINT8:
172 stream->chan_size = sizeof(uint8_t);
173 break;
174 case UINT16:
175 stream->chan_size = sizeof(uint16_t);
176 break;
177 case UINT32:
178 stream->chan_size = sizeof(uint32_t);
179 break;
180 case UINT64:
181 stream->chan_size = sizeof(uint64_t);
182 break;
183 default:
184 abort();
185 }
186
187 stream->pixel_size = stream->n_chan * stream->chan_size;
188 stream->row_size = stream->pixel_size * stream->width;
189 stream->col_size = stream->pixel_size * stream->height;
190 stream->frame_size = stream->pixel_size * stream->height * strea…
191 return 0;
192
193 #undef TEST_ENCODING_AGNOSTIC
194 }
195
196 void
197 enset_pixel_format(int status, struct stream *stream, const char *pixfmt)
198 {
199 if (set_pixel_format(stream, pixfmt)) {
200 if (pixfmt)
201 enprintf(status, "pixel format %s is not support…
202 else
203 enprintf(status, "%s: unsupported pixel format: …
204 stream->file, stream->pixfmt);
205 }
206 }
207
208
209 void
210 fprint_stream_head(FILE *fp, struct stream *stream)
211 {
212 FPRINTF_HEAD(fp, stream->frames, stream->width, stream->height, …
213 }
214
215
216 int
217 dprint_stream_head(int fd, struct stream *stream)
218 {
219 return DPRINTF_HEAD(fd, stream->frames, stream->width, stream->h…
220 }
221
222
223 size_t
224 enread_stream(int status, struct stream *stream, size_t n)
225 {
226 ssize_t r = read(stream->fd, stream->buf + stream->ptr,
227 MIN(sizeof(stream->buf) - stream->ptr, n));
228 if (r < 0)
229 enprintf(status, "read %s:", stream->file);
230 stream->ptr += (size_t)r;
231 return (size_t)r;
232 }
233
234
235 void
236 eninf_check_fd(int status, int fd, const char *file)
237 {
238 struct stat st;
239 if (fstat(fd, &st))
240 enprintf(status, "fstat %s:", file);
241 if (S_ISREG(st.st_mode))
242 enprintf(status, "%s is a regular file, refusing infinit…
243 }
244
245
246 void
247 encheck_dimensions(int status, const struct stream *stream, enum dimensi…
248 {
249 size_t n;
250
251 if (!stream->pixel_size)
252 enprintf(status, "%s: %s%svideo frame doesn't have a pix…
253 stream->file, prefix ? prefix : "",
254 (prefix && *prefix) ? " " : "");
255
256 n = SIZE_MAX / stream->pixel_size;
257
258 if ((dimensions & WIDTH) && stream->width > n)
259 enprintf(status, "%s: %s%svideo frame is too wide\n",
260 stream->file, prefix ? prefix : "",
261 (prefix && *prefix) ? " " : "");
262
263 if ((dimensions & HEIGHT) && stream->height > n)
264 enprintf(status, "%s: %s%svideo frame is too wide\n",
265 stream->file, prefix ? prefix : "",
266 (prefix && *prefix) ? " " : "");
267
268 if (!stream->width || !stream->height)
269 return;
270
271 if ((dimensions & (WIDTH | HEIGHT)) == (WIDTH | HEIGHT)) {
272 if (stream->width > n / stream->height)
273 enprintf(status, "%s: %s%svideo frame is too lar…
274 stream->file, prefix ? prefix : "",
275 (prefix && *prefix) ? " " : "");
276 }
277
278 if (!(dimensions & LENGTH))
279 return;
280 if (dimensions & WIDTH)
281 n /= stream->width;
282 if (dimensions & HEIGHT)
283 n /= stream->height;
284
285 if (stream->frames > n)
286 enprintf(status, "%s: %s%svideo is too large\n",
287 stream->file, prefix ? prefix : "",
288 (prefix && *prefix) ? " " : "");
289 }
290
291
292 void
293 encheck_compat(int status, const struct stream *a, const struct stream *…
294 {
295 if (a->width != b->width || a->height != b->height)
296 enprintf(status, "videos do not have the same geometry\n…
297 if (strcmp(a->pixfmt, b->pixfmt))
298 enprintf(status, "videos use incompatible pixel formats\…
299 }
300
301
302 const char *
303 get_pixel_format(const char *specified, const char *current)
304 {
305 enum colour_space space = CIEXYZ;
306 enum alpha alpha = UNPREMULTIPLIED;
307 enum encoding encoding = UINT16;
308 int level = -1;
309 size_t n = strlen(specified);
310
311 if ((n >= 2 && !strcmp(specified - 2, " f")) ||
312 !strcmp(specified, "raw0") || !strcmp(specified, "raw1") ||
313 !strcmp(specified, "raw2") || !strcmp(specified, "raw2a"))
314 return specified;
315
316 if (!strcmp(current, "xyza")) space = CIEXYZ, encoding =…
317 else if (!strcmp(current, "xyza f")) space = CIEXYZ, encoding =…
318 else if (!strcmp(current, "raw0")) level = 0;
319 else if (!strcmp(current, "raw1")) level = 1;
320 else if (!strcmp(current, "raw2")) level = 2, alpha = NO_ALPH…
321 else if (!strcmp(current, "raw2a")) level = 2;
322 else if (!strcmp(current, "raw3")) level = 3, encoding = DOUB…
323 else if (!strcmp(current, "raw3a")) level = 3, encoding = DOUB…
324 else if (!strcmp(current, "raw3 f")) level = 3, encoding = FLOA…
325 else if (!strcmp(current, "raw3a f")) level = 3, encoding = FLOA…
326 else if (!strcmp(current, "raw4")) level = 4, encoding = DOUB…
327 else if (!strcmp(current, "raw4a")) level = 4, encoding = DOUB…
328 else if (!strcmp(current, "raw4 f")) level = 4, encoding = FLOA…
329 else if (!strcmp(current, "raw4a f")) level = 4, encoding = FLOA…
330 else if (!strcmp(current, "raw5")) level = 5, encoding = DOUB…
331 else if (!strcmp(current, "raw5a")) level = 5, encoding = DOUB…
332 else if (!strcmp(current, "raw5 f")) level = 5, encoding = FLOA…
333 else if (!strcmp(current, "raw5a f")) level = 5, encoding = FLOA…
334 else
335 return specified;
336
337 if (!strcmp(specified, "f")) encoding = FLOAT;
338 else if (!strcmp(specified, "!f")) encoding = DOUBLE;
339 else if (!strcmp(specified, "xyza")) level = -1, alpha = UNP…
340 else if (!strcmp(specified, "raw3")) level = 3, alpha = NO_A…
341 else if (!strcmp(specified, "raw3a")) level = 3, alpha = UNPR…
342 else if (!strcmp(specified, "raw4")) level = 4, alpha = NO_A…
343 else if (!strcmp(specified, "raw4a")) level = 4, alpha = UNPR…
344 else if (!strcmp(specified, "raw5")) level = 5, alpha = NO_A…
345 else if (!strcmp(specified, "raw5a")) level = 5, alpha = UNPR…
346 else if (!strcmp(specified, "xyza !f")) return "xyza";
347 else if (!strcmp(specified, "raw3 !f")) return "raw3";
348 else if (!strcmp(specified, "raw3a !f")) return "raw3a";
349 else if (!strcmp(specified, "raw4 !f")) return "raw4";
350 else if (!strcmp(specified, "raw4a !f")) return "raw4a";
351 else if (!strcmp(specified, "raw5 !f")) return "raw5";
352 else if (!strcmp(specified, "raw5a !f")) return "raw5a";
353 else
354 return specified;
355
356 if (level == 0 && encoding == UINT16) return "raw0";
357 else if (level == 1 && encoding == UINT16) return "raw1";
358 else if (level == 2 && encoding == UINT16) return alpha ? "raw2a…
359 else if (level == 3 && encoding == DOUBLE) return alpha ? "raw3a…
360 else if (level == 3 && encoding == FLOAT) return alpha ? "raw3a…
361 else if (level == 4 && encoding == DOUBLE) return alpha ? "raw4a…
362 else if (level == 4 && encoding == FLOAT) return alpha ? "raw4a…
363 else if (level == 5 && encoding == DOUBLE) return alpha ? "raw5a…
364 else if (level == 5 && encoding == FLOAT) return alpha ? "raw5a…
365 else if (level < 0 && space == CIEXYZ && alpha == UNPREMULTIPLIE…
366 return encoding == FLOAT ? "xyza f" : encoding == DOUBLE…
367 else
368 return specified;
369 }
370
371
372 const char *
373 nselect_print_format(int status, const char *format, enum encoding encod…
374 {
375 static char retbuf[512];
376 int with_plus = 0, inttyped = -1;
377 const char *f = "", *orig = fmt;
378 char *proto = alloca((fmt ? strlen(fmt) : 0) + sizeof("%+#.50llx…
379 char *ret = retbuf;
380 size_t n, len;
381
382 if (!orig)
383 goto check_done;
384
385 for (; *fmt == '+'; fmt++)
386 with_plus = 1;
387 f = fmt + strspn(fmt, "0123456789");
388 if (f[0] && f[1])
389 enprintf(status, "invalid format: %s\n", orig);
390
391 switch (*f) {
392 case '\0':
393 inttyped = -1;
394 break;
395 case 'd': case 'i':
396 inttyped = 1;
397 break;
398 case 'a': case 'A':
399 case 'e': case 'E':
400 case 'f': case 'F':
401 case 'g': case 'G':
402 inttyped = 0;
403 break;
404 default:
405 enprintf(status, "invalid format: %s\n", orig);
406 }
407
408 switch (encoding) {
409 case FLOAT:
410 case DOUBLE:
411 case LONG_DOUBLE:
412 if (inttyped == 1)
413 enprintf(status, "invalid format `%s' is incompa…
414 inttyped = 0;
415 break;
416 case UINT8:
417 case UINT16:
418 case UINT32:
419 case UINT64:
420 if (*f != *fmt)
421 enprintf(status, "invalid format: %s\n", orig);
422 if (inttyped == 0)
423 enprintf(status, "invalid format `%s' is incompa…
424 inttyped = 1;
425 break;
426 default:
427 abort();
428 }
429 check_done:
430
431 p = proto;
432 *p++ = '%';
433 if (with_plus)
434 *p++ = '+';
435
436 if (orig && *f != *fmt) {
437 *p++ = '.';
438 p = stpncpy(p, fmt, (size_t)(f - fmt));
439 } else if (orig && inttyped && *f != 'a' && *f != 'A') {
440 *p++ = '.';
441 *p++ = '2';
442 *p++ = '5';
443 }
444
445 inttyped = 1;
446 switch (encoding) {
447 case FLOAT:
448 inttyped = 0;
449 break;
450 case DOUBLE:
451 *p++ = 'l';
452 inttyped = 0;
453 break;
454 case LONG_DOUBLE:
455 *p++ = 'L';
456 inttyped = 0;
457 break;
458 case UINT8:
459 fmt = PRIi8;
460 break;
461 case UINT16:
462 fmt = PRIi16;
463 break;
464 case UINT32:
465 fmt = PRIi32;
466 break;
467 case UINT64:
468 fmt = PRIi64;
469 break;
470 default:
471 abort();
472 }
473
474 if (inttyped)
475 while (*fmt == 'l' || *fmt == 'L')
476 *p++ = *fmt++;
477
478 switch (orig ? *f : '\0') {
479 case '\0':
480 *p++ = inttyped ? 'i' : 'f';
481 break;
482 case 'd': case 'i':
483 *p++ = 'i';
484 break;
485 case 'a': case 'A':
486 *p++ = 'a';
487 break;
488 case 'e': case 'E':
489 *p++ = 'e';
490 break;
491 case 'f': case 'F':
492 *p++ = 'f';
493 break;
494 case 'g': case 'G':
495 *p++ = 'g';
496 break;
497 }
498
499 *p = '\0';
500
501 len = strlen(proto);
502 for (n = 1, f = format; *f; f++) {
503 if (f[0] == '%' && f[1] == '!') {
504 f++;
505 n += len;
506 } else {
507 n++;
508 }
509 }
510
511 if (n > sizeof(retbuf))
512 ret = enmalloc(status, n);
513 for (p = ret, f = format; *f; f++) {
514 if (f[0] == '%' && f[1] == '!') {
515 f++;
516 p = stpcpy(p, proto);
517 } else {
518 *p++ = *f;
519 }
520 }
521
522 return ret;
523 }
524
525
526 int
527 enread_segment(int status, struct stream *stream, void *buf, size_t n)
528 {
529 char *buffer = buf;
530 ssize_t r;
531 size_t m;
532
533 if (stream->ptr) {
534 m = MIN(stream->ptr, n);
535 memcpy(buffer + stream->xptr, stream->buf, m);
536 memmove(stream->buf, stream->buf + m, stream->ptr -= m);
537 stream->xptr += m;
538 }
539
540 for (; stream->xptr < n; stream->xptr += (size_t)r) {
541 r = read(stream->fd, buffer + stream->xptr, n - stream->…
542 if (r < 0) {
543 enprintf(status, "read %s:", stream->file);
544 } else if (r == 0) {
545 if (!stream->xptr)
546 break;
547 enprintf(status, "%s: incomplete frame", stream-…
548 }
549 }
550
551 if (!stream->xptr)
552 return 0;
553 stream->xptr -= n;
554 return 1;
555 }
556
557
558 size_t
559 ensend_frames(int status, struct stream *stream, int outfd, size_t frame…
560 {
561 size_t h, w, p, n, ret;
562
563 for (ret = 0; ret < frames; ret++) {
564 for (p = stream->pixel_size; p; p--) {
565 for (h = stream->height; h; h--) {
566 for (w = stream->width; w; w -= n) {
567 if (!stream->ptr && !enread_stre…
568 goto done;
569 n = MIN(stream->ptr, w);
570 if (outfd >= 0)
571 enwriteall(status, outfd…
572 memmove(stream->buf, stream->buf…
573 }
574 }
575 }
576 }
577
578 return ret;
579 done:
580 if (p != stream->pixel_size || h != stream->height || w != strea…
581 enprintf(status, "%s: incomplete frame", stream->file);
582 return ret;
583 }
584
585
586 size_t
587 ensend_rows(int status, struct stream *stream, int outfd, size_t rows, c…
588 {
589 size_t w, p, n, ret;
590
591 for (ret = 0; ret < rows; ret++) {
592 for (p = stream->pixel_size; p; p--) {
593 for (w = stream->width; w; w -= n) {
594 if (!stream->ptr && !enread_stream(statu…
595 goto done;
596 n = MIN(stream->ptr, w);
597 if (outfd >= 0)
598 enwriteall(status, outfd, stream…
599 memmove(stream->buf, stream->buf + n, st…
600 }
601 }
602 }
603
604 return ret;
605 done:
606 if (p != stream->pixel_size || w != stream->width)
607 enprintf(status, "%s: incomplete row", stream->file);
608 return ret;
609 }
610
611
612 size_t
613 ensend_pixels(int status, struct stream *stream, int outfd, size_t pixel…
614 {
615 size_t p, n, ret;
616
617 for (ret = 0; ret < pixels; ret++) {
618 for (p = stream->pixel_size; p; p -= n) {
619 if (!stream->ptr && !enread_stream(status, strea…
620 goto done;
621 n = MIN(stream->ptr, p);
622 if (outfd >= 0)
623 enwriteall(status, outfd, stream->buf, n…
624 memmove(stream->buf, stream->buf + n, stream->pt…
625 }
626 }
627
628 return ret;
629 done:
630 if (p != stream->pixel_size)
631 enprintf(status, "%s: incomplete pixel", stream->file);
632 return ret;
633 }
634
635
636 int
637 ensend_stream(int status, struct stream *stream, int outfd, const char *…
638 {
639 do {
640 if (writeall(outfd, stream->buf, stream->ptr)) {
641 if (outfname)
642 eprintf("write %s:", outfname);
643 return -1;
644 }
645 stream->ptr = 0;
646 } while (enread_stream(status, stream, SIZE_MAX));
647 return 0;
648 }
649
650
651 void
652 nprocess_stream(int status, struct stream *stream, void (*process)(struc…
653 {
654 size_t n;
655 do {
656 n = stream->ptr - (stream->ptr % stream->pixel_size);
657 process(stream, n);
658 memmove(stream->buf, stream->buf + n, stream->ptr -= n);
659 } while (enread_stream(status, stream, SIZE_MAX));
660 }
661
662
663 void
664 nprocess_each_frame_segmented(int status, struct stream *stream, int out…
665 void (*process)(struct stream *stream, siz…
666 {
667 size_t frame, r, n;
668 encheck_dimensions(status, stream, WIDTH | HEIGHT, NULL);
669 for (frame = 0; frame < stream->frames; frame++) {
670 for (n = stream->frame_size; n; n -= r) {
671 if (stream->ptr < n && !enread_stream(status, st…
672 enprintf(status, "%s: file is shorter th…
673 r = stream->ptr - (stream->ptr % stream->pixel_s…
674 r = MIN(r, n);
675 process(stream, r, frame);
676 enwriteall(status, output_fd, stream->buf, r, ou…
677 memmove(stream->buf, stream->buf + r, stream->pt…
678 }
679 }
680 }
681
682
683 void
684 nprocess_two_streams(int status, struct stream *left, struct stream *rig…
685 void (*process)(struct stream *left, struct stream …
686 {
687 size_t n;
688 int have_both = 1;
689
690 encheck_compat(status, left, right);
691
692 while (have_both) {
693 if (left->ptr < sizeof(left->buf) && !enread_stream(stat…
694 close(left->fd);
695 left->fd = -1;
696 have_both = 0;
697 }
698 if (right->ptr < sizeof(right->buf) && !enread_stream(st…
699 close(right->fd);
700 right->fd = -1;
701 have_both = 0;
702 }
703
704 n = MIN(left->ptr, right->ptr);
705 n -= n % left->pixel_size;
706 left->ptr -= n;
707 right->ptr -= n;
708
709 process(left, right, n);
710
711 enwriteall(status, output_fd, left->buf, n, output_fname…
712 if ((n & 3) || left->ptr != right->ptr) {
713 memmove(left->buf, left->buf + n, left->ptr);
714 memmove(right->buf, right->buf + n, right->ptr);
715 }
716 }
717
718 if (right->fd >= 0)
719 close(right->fd);
720
721 enwriteall(status, output_fd, left->buf, left->ptr, output_fname…
722
723 if (left->fd >= 0) {
724 for (;;) {
725 left->ptr = 0;
726 if (!enread_stream(status, left, SIZE_MAX)) {
727 close(left->fd);
728 left->fd = -1;
729 break;
730 }
731 enwriteall(status, output_fd, left->buf, left->p…
732 }
733 }
734 }
735
736
737 void
738 nprocess_multiple_streams(int status, struct stream *streams, size_t n_s…
739 int shortest, void (*process)(struct stream *s…
740 {
741 size_t closed, i, j, n;
742
743 for (i = 1; i < n_streams; i++)
744 encheck_compat(status, streams + i, streams);
745
746 while (n_streams) {
747 n = SIZE_MAX;
748 for (i = 0; i < n_streams; i++) {
749 if (streams[i].ptr < streams->pixel_size && !enr…
750 close(streams[i].fd);
751 streams[i].fd = -1;
752 if (shortest)
753 return;
754 }
755 if (streams[i].ptr && streams[i].ptr < n)
756 n = streams[i].ptr;
757 }
758 if (n == SIZE_MAX)
759 break;
760 n -= n % streams->pixel_size;
761
762 process(streams, n_streams, n);
763 enwriteall(status, output_fd, streams->buf, n, output_fn…
764
765 closed = SIZE_MAX;
766 for (i = 0; i < n_streams; i++) {
767 if (streams[i].ptr)
768 memmove(streams[i].buf, streams[i].buf +…
769 if (streams[i].ptr < streams->pixel_size && stre…
770 closed = i;
771 }
772 if (closed != SIZE_MAX) {
773 for (i = (j = closed) + 1; i < n_streams; i++)
774 if (streams[i].ptr >= streams->pixel_siz…
775 streams[j++] = streams[i];
776 n_streams = j;
777 }
778 }
779 }
780
781
782 void
783 nprocess_each_frame_two_streams(int status, struct stream *left, struct …
784 void (*process)(char *restrict output, c…
785 struct stream *left, str…
786 {
787 char *lbuf, *rbuf, *image;
788
789 encheck_dimensions(status, left, WIDTH | HEIGHT, NULL);
790 encheck_dimensions(status, right, WIDTH | HEIGHT, NULL);
791
792 if (left->frame_size > SIZE_MAX - left->frame_size ||
793 2 * left->frame_size > SIZE_MAX - right->frame_size)
794 enprintf(status, "video frame is too large\n");
795
796 image = mmap(0, 2 * left->frame_size + right->frame_size,
797 PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED,…
798 if (image == MAP_FAILED)
799 enprintf(status, "mmap:");
800 lbuf = image + 1 * left->frame_size;
801 rbuf = image + 2 * left->frame_size;
802
803 for (;;) {
804 if (!enread_frame(status, left, lbuf)) {
805 close(left->fd);
806 left->fd = -1;
807 break;
808 }
809 if (!enread_frame(status, right, rbuf)) {
810 close(right->fd);
811 right->fd = -1;
812 break;
813 }
814
815 process(image, lbuf, rbuf, left, right);
816 enwriteall(status, output_fd, image, left->frame_size, o…
817 }
818
819 if (right->fd >= 0)
820 close(right->fd);
821
822 if (left->fd >= 0) {
823 memcpy(image, lbuf, left->ptr);
824 while (enread_frame(status, left, lbuf))
825 enwriteall(status, output_fd, image, left->frame…
826 }
827
828 munmap(image, 2 * left->frame_size + right->frame_size);
829 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.