blind-to-video.c (3463B)
1 /* See LICENSE file for copyright and license details. */ 2 #ifndef TYPE 3 #include "common.h" 4 5 USAGE("[-d] frame-rate ffmpeg-arguments ...") 6 7 static int draft = 0; 8 static int fd; 9 10 #define FILE "blind-to-video.c" 11 #include "define-functions.h" 12 13 int 14 main(int argc, char *argv[]) 15 { 16 struct stream stream; 17 char geometry[2 * INTSTRLEN(size_t) + 2]; 18 char *frame_rate; 19 const char **cmd; 20 size_t n = 0; 21 int status, pipe_rw[2]; 22 pid_t pid; 23 void (*process)(struct stream *stream, size_t n); 24 25 ARGBEGIN { 26 case 'd': 27 draft = 1; 28 break; 29 default: 30 usage(); 31 } ARGEND; 32 33 if (argc < 2) 34 usage(); 35 36 frame_rate = *argv++, argc--; 37 cmd = ecalloc((size_t)argc + 12, sizeof(*cmd)); 38 cmd[n++] = "ffmpeg"; 39 cmd[n++] = "-f", cmd[n++] = "rawvideo"; 40 cmd[n++] = "-pix_fmt", cmd[n++] = "ayuv64le"; 41 cmd[n++] = "-r", cmd[n++] = frame_rate; 42 cmd[n++] = "-s:v", cmd[n++] = geometry; 43 cmd[n++] = "-i", cmd[n++] = "-"; 44 memcpy(cmd + n, argv, (size_t)argc * sizeof(*cmd)); 45 46 eopen_stream(&stream, NULL); 47 48 sprintf(geometry, "%zux%zu", stream.width, stream.height); 49 50 if (!strcmp(stream.pixfmt, "xyza")) 51 process = process_lf; 52 else if (!strcmp(stream.pixfmt, "xyza f")) 53 process = process_f; 54 else if (!strcmp(stream.pixfmt, "raw0")) 55 process = NULL; 56 else 57 eprintf("pixel format %s is not supported, try converting to " 58 "raw0 or xyza with blind-convert\n", stream.pixfmt); 59 60 epipe(pipe_rw); 61 pid = efork(); 62 63 if (!pid) { 64 pdeath(SIGKILL); 65 close(pipe_rw[1]); 66 edup2(pipe_rw[0], STDIN_FILENO); 67 close(pipe_rw[0]); 68 eexecvp("ffmpeg", (char **)(void *)cmd); 69 } 70 71 free(cmd); 72 73 close(pipe_rw[0]); 74 fd = pipe_rw[1]; 75 if (process) 76 process_stream(&stream, process); 77 else 78 esend_stream(&stream, fd, "<subprocess>"); 79 close(fd); 80 81 ewaitpid(pid, &status, 0); 82 return !!status; 83 } 84 85 #else 86 87 static void 88 PROCESS(struct stream *stream, size_t n) 89 { 90 char *buf = stream->buf; 91 TYPE *pixel, r, g, b; 92 uint16_t *pixels, *end; 93 uint16_t pixbuf[BUFSIZ / sizeof(uint16_t)]; 94 long int a, y, u, v; 95 size_t ptr; 96 pixels = pixbuf; 97 end = pixbuf + ELEMENTSOF(pixbuf); 98 if (draft) { 99 for (ptr = 0; ptr < n; ptr += 4 * sizeof(TYPE)) { 100 pixel = (TYPE *)(buf + ptr); 101 ciexyz_to_scaled_yuv(pixel[0], pixel[1], pixel[2], &r, &g, &b); 102 y = (long int)r + 0x1001L; 103 u = (long int)g + 0x8000L; 104 v = (long int)b + 0x8000L; 105 *pixels++ = 0xFFFFU; 106 *pixels++ = htole((uint16_t)CLIP(0, y, 0xFFFFL)); 107 *pixels++ = htole((uint16_t)CLIP(0, u, 0xFFFFL)); 108 *pixels++ = htole((uint16_t)CLIP(0, v, 0xFFFFL)); 109 if (pixels == end) 110 ewriteall(fd, pixels = pixbuf, sizeof(pixbuf), "<subprocess>"); 111 } 112 } else { 113 for (ptr = 0; ptr < n; ptr += 4 * sizeof(TYPE)) { 114 pixel = (TYPE *)(buf + ptr); 115 a = (long int)(pixel[3] * 0xFFFFL); 116 ciexyz_to_srgb(pixel[0], pixel[1], pixel[2], &r, &g, &b); 117 r = srgb_encode(r); 118 g = srgb_encode(g); 119 b = srgb_encode(b); 120 srgb_to_yuv(r, g, b, pixel + 0, pixel + 1, pixel + 2); 121 y = (long int)(pixel[0] * 0xDAF4L) + 0x1001L; 122 u = (long int)(pixel[1] * 0xFF00L) + 0x8000L; 123 v = (long int)(pixel[2] * 0xFF00L) + 0x8000L; 124 *pixels++ = htole((uint16_t)CLIP(0, a, 0xFFFFL)); 125 *pixels++ = htole((uint16_t)CLIP(0, y, 0xFFFFL)); 126 *pixels++ = htole((uint16_t)CLIP(0, u, 0xFFFFL)); 127 *pixels++ = htole((uint16_t)CLIP(0, v, 0xFFFFL)); 128 if (pixels == end) 129 ewriteall(fd, pixels = pixbuf, sizeof(pixbuf), "<subprocess>"); 130 } 131 } 132 ewriteall(fd, pixbuf, (size_t)(pixels - pixbuf) * sizeof(*pixels), "<subprocess>"); 133 } 134 135 #endif