commit 1519bc79a4bc7749b0e4808d78f3ee0c171db9e8
parent 836ed8b478c660a2fcb18cb4036da5706afd155c
Author: Mattias Andrée <maandree@kth.se>
Date: Fri, 13 Jan 2017 08:59:01 +0100
vu-from-video: fix Y'UV encoding + add vu-to-video
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat:
4 files changed, 153 insertions(+), 7 deletions(-)
diff --git a/Makefile b/Makefile
@@ -29,6 +29,7 @@ BIN =\
vu-stack\
vu-to-image\
vu-to-text\
+ vu-to-video\
vu-transpose\
vu-write-head
diff --git a/TODO b/TODO
@@ -2,7 +2,6 @@ vu-transform transformation by matrix multiplication, -t for tiling, -s for imp
on downscaling (pixels' neighbours must not change)
vu-chroma-key replace a chroma with transparency
vu-primary-key replace a primary with transparency, -g for greyscaled images
-vu-to-video use ffmpeg to convert to another format
vu-primaries given three selectable primaries split the video into three side-by-side which
only one primary active
vu-apply-map remap pixels (distortion) using the X and Y values, -t for tiling, -s for
diff --git a/src/vu-from-video.c b/src/vu-from-video.c
@@ -112,9 +112,9 @@ convert_segment(char *buf, size_t n, int fd, char *file)
if (draft) {
for (ptr = i = 0; ptr < n; ptr += 8) {
pixels[i][3] = ntohs(((uint16_t *)(buf + ptr))[0]) / max;
- y = ntohs(((uint16_t *)(buf + ptr))[1]);
- u = ntohs(((uint16_t *)(buf + ptr))[2]);
- v = ntohs(((uint16_t *)(buf + ptr))[3]);
+ y = (ntohs(((uint16_t *)(buf + ptr))[1]) - 16 * 256);
+ u = (ntohs(((uint16_t *)(buf + ptr))[2]) - 128 * 256);
+ v = (ntohs(((uint16_t *)(buf + ptr))[3]) - 128 * 256);
scaled_yuv_to_ciexyz(y, u, v, pixels[i] + 0, pixels[i] + 1, pixels[i] + 2);
if (++i == 1024) {
i = 0;
@@ -124,9 +124,9 @@ convert_segment(char *buf, size_t n, int fd, char *file)
} else {
for (ptr = i = 0; ptr < n; ptr += 8) {
pixels[i][3] = ntohs(((uint16_t *)(buf + ptr))[0]) / max;
- y = ntohs(((uint16_t *)(buf + ptr))[1]) / max;
- u = ntohs(((uint16_t *)(buf + ptr))[2]) / max;
- v = ntohs(((uint16_t *)(buf + ptr))[3]) / max;
+ y = (ntohs(((uint16_t *)(buf + ptr))[1]) - 16 * 256) / max;
+ u = (ntohs(((uint16_t *)(buf + ptr))[2]) - 128 * 256) / max;
+ v = (ntohs(((uint16_t *)(buf + ptr))[3]) - 128 * 256) / max;
yuv_to_srgb(y, u, v, &r, &g, &b);
r = srgb_decode(r);
g = srgb_decode(g);
diff --git a/src/vu-to-video.c b/src/vu-to-video.c
@@ -0,0 +1,146 @@
+/* See LICENSE file for copyright and license details. */
+#include "stream.h"
+#include "util.h"
+
+#include <arpa/inet.h>
+#if defined(HAVE_PRCTL)
+# include <sys/prctl.h>
+#endif
+#include <sys/wait.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+USAGE("[-d] frame-rate ffmpeg-arguments ...")
+
+static int draft = 0;
+
+static void
+process_xyza(char *buf, size_t n, int fd, const char *fname)
+{
+ double *pixel, r, g, b;
+ uint16_t *pixels, *end;
+ uint16_t pixbuf[1024];
+ long int a, y, u, v;
+ size_t ptr;
+ pixels = pixbuf;
+ end = pixbuf + ELEMENTSOF(pixbuf);
+ if (draft) {
+ for (ptr = 0; ptr < n; ptr += sizeof(pixel)) {
+ pixel = (double *)(buf + ptr);
+ a = (long int)(pixel[3] * 0xFFFFL);
+ ciexyz_to_scaled_yuv(pixel[0], pixel[1], pixel[2], &r, &g, &b);
+ y = (long int)r + 16 * 256;
+ u = (long int)g + 128 * 256;
+ v = (long int)b + 128 * 256;
+ *pixels++ = htons((uint16_t)(a < 0 ? 0 : a > 0xFFFFL ? 0xFFFFL : a));
+ *pixels++ = htons((uint16_t)(y < 0 ? 0 : y > 0xFFFFL ? 0xFFFFL : y));
+ *pixels++ = htons((uint16_t)(u < 0 ? 0 : u > 0xFFFFL ? 0xFFFFL : u));
+ *pixels++ = htons((uint16_t)(v < 0 ? 0 : v > 0xFFFFL ? 0xFFFFL : v));
+ if (pixels == end)
+ ewriteall(fd, pixels = pixbuf, sizeof(pixbuf), fname);
+ }
+ } else {
+ for (ptr = 0; ptr < n; ptr += sizeof(pixel)) {
+ pixel = (double *)(buf + ptr);
+ a = (long int)(pixel[3] * 0xFFFFL);
+ ciexyz_to_srgb(pixel[0], pixel[1], pixel[2], &r, &g, &b);
+ r = srgb_encode(r);
+ g = srgb_encode(g);
+ b = srgb_encode(b);
+ srgb_to_yuv(r, g, b, pixel + 0, pixel + 1, pixel + 2);
+ y = (long int)(pixel[0] * 0xFFFFL);
+ u = (long int)(pixel[1] * 0xFFFFL);
+ v = (long int)(pixel[2] * 0xFFFFL);
+ y += 16 * 256;
+ u += 128 * 256;
+ v += 128 * 256;
+ *pixels++ = htons((uint16_t)(a < 0 ? 0 : a > 0xFFFFL ? 0xFFFFL : a));
+ *pixels++ = htons((uint16_t)(y < 0 ? 0 : y > 0xFFFFL ? 0xFFFFL : y));
+ *pixels++ = htons((uint16_t)(u < 0 ? 0 : u > 0xFFFFL ? 0xFFFFL : u));
+ *pixels++ = htons((uint16_t)(v < 0 ? 0 : v > 0xFFFFL ? 0xFFFFL : v));
+ if (pixels == end)
+ ewriteall(fd, pixels = pixbuf, sizeof(pixbuf), fname);
+ }
+ }
+ if (pixels != pixbuf)
+ ewriteall(fd, pixels = pixbuf, sizeof(pixbuf), fname);
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct stream stream;
+ char geometry[2 * 3 * sizeof(size_t) + 2];
+ char *frame_rate;
+ const char **cmd;
+ size_t n = 0;
+ int status, pipe_rw[2];
+ pid_t pid;
+ void (*process)(char *buf, size_t n, int fd, const char *fname) = NULL;
+
+ ARGBEGIN {
+ case 'd':
+ draft = 1;
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ if (argc < 2)
+ usage();
+
+ frame_rate = *argv++, argc--;
+ cmd = ecalloc((size_t)argc + 12, sizeof(*cmd));
+ cmd[n++] = "ffmpeg";
+ cmd[n++] = "-f", cmd[n++] = "rawvideo";
+ cmd[n++] = "-pix_fmt", cmd[n++] = "ayuv64le";
+ cmd[n++] = "-r", cmd[n++] = frame_rate;
+ cmd[n++] = "-s:v", cmd[n++] = geometry;
+ cmd[n++] = "-i", cmd[n++] = "-";
+ memcpy(cmd + n, argv, (size_t)argc * sizeof(*cmd));
+
+ stream.file = "<stdin>";
+ stream.fd = STDIN_FILENO;
+ einit_stream(&stream);
+
+ sprintf(geometry, "%zux%zu", stream.width, stream.height);
+
+ if (!strcmp(stream.pixfmt, "xyza"))
+ process = process_xyza;
+ else
+ eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
+
+ if (pipe(pipe_rw))
+ eprintf("pipe:");
+
+ pid = fork();
+ if (pid < 0)
+ eprintf("fork:");
+
+ if (!pid) {
+#if defined(HAVE_PRCTL) && defined(PR_SET_PDEATHSIG)
+ prctl(PR_SET_PDEATHSIG, SIGKILL);
+#endif
+ close(pipe_rw[1]);
+ if (dup2(pipe_rw[0], STDIN_FILENO) == -1)
+ eprintf("dup2:");
+ close(pipe_rw[0]);
+ eprintf("exec ffmpeg:");
+ }
+
+ close(pipe_rw[0]);
+ while (!eread_stream(&stream, SIZE_MAX)) {
+ n = stream.ptr - (stream.ptr % stream.pixel_size);
+ process(stream.buf, n, pipe_rw[1], "<subprocess>");
+ memmove(stream.buf, stream.buf + n, stream.ptr -= n);
+ }
+ close(pipe_rw[1]);
+
+ if (waitpid(pid, &status, 0) == -1)
+ eprintf("waitpid:");
+
+ return !!status;
+}