summaryrefslogtreecommitdiffstats
path: root/third_party/dav1d/tools/output
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /third_party/dav1d/tools/output
parentInitial commit. (diff)
downloadfirefox-upstream.tar.xz
firefox-upstream.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/dav1d/tools/output')
-rw-r--r--third_party/dav1d/tools/output/md5.c317
-rw-r--r--third_party/dav1d/tools/output/muxer.h52
-rw-r--r--third_party/dav1d/tools/output/null.c44
-rw-r--r--third_party/dav1d/tools/output/output.c145
-rw-r--r--third_party/dav1d/tools/output/output.h48
-rw-r--r--third_party/dav1d/tools/output/y4m2.c151
-rw-r--r--third_party/dav1d/tools/output/yuv.c104
7 files changed, 861 insertions, 0 deletions
diff --git a/third_party/dav1d/tools/output/md5.c b/third_party/dav1d/tools/output/md5.c
new file mode 100644
index 0000000000..6555de83ad
--- /dev/null
+++ b/third_party/dav1d/tools/output/md5.c
@@ -0,0 +1,317 @@
+/*
+ * Copyright © 2018, VideoLAN and dav1d authors
+ * Copyright © 2018, Two Orioles, LLC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "common/intops.h"
+
+#include "output/muxer.h"
+
+static const uint8_t s[][4] = {
+ { 7, 12, 17, 22, },
+ { 5, 9, 14, 20, },
+ { 4, 11, 16, 23, },
+ { 6, 10, 15, 21, },
+};
+
+static const unsigned k[] = {
+ 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
+ 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
+ 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
+ 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
+ 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
+ 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
+ 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
+ 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
+ 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
+ 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
+ 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
+ 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
+ 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
+ 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
+ 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
+ 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
+};
+
+
+#if ENDIANNESS_BIG
+#define NE2LE_32(x) (((x & 0x00ff) << 24) |\
+ ((x & 0xff00) << 8) |\
+ ((x >> 8) & 0xff00) |\
+ ((x >> 24) & 0x00ff))
+
+#define NE2LE_64(x) (((x & 0x000000ff) << 56) |\
+ ((x & 0x0000ff00) << 40) |\
+ ((x & 0x00ff0000) << 24) |\
+ ((x & 0xff000000) << 8) |\
+ ((x >> 8) & 0xff000000) |\
+ ((x >> 24) & 0x00ff0000) |\
+ ((x >> 40) & 0x0000ff00) |\
+ ((x >> 56) & 0x000000ff))
+
+#else
+#define NE2LE_32(x) (x)
+#define NE2LE_64(x) (x)
+#endif
+
+typedef struct MuxerPriv {
+ unsigned abcd[4];
+ uint8_t data[64];
+ uint64_t len;
+ FILE *f;
+#if ENDIANNESS_BIG
+ uint8_t *bswap;
+ int bswap_w;
+#endif
+} MD5Context;
+
+static int md5_open(MD5Context *const md5, const char *const file,
+ const Dav1dPictureParameters *const p,
+ const unsigned fps[2])
+{
+ if (!strcmp(file, "-")) {
+ md5->f = stdout;
+ } else if (!(md5->f = fopen(file, "wb"))) {
+ fprintf(stderr, "Failed to open %s: %s\n", file, strerror(errno));
+ return -1;
+ }
+
+#if ENDIANNESS_BIG
+ md5->bswap = NULL;
+ md5->bswap_w = 0;
+#endif
+
+ md5->abcd[0] = 0x67452301;
+ md5->abcd[1] = 0xefcdab89;
+ md5->abcd[2] = 0x98badcfe;
+ md5->abcd[3] = 0x10325476;
+ md5->len = 0;
+
+ return 0;
+}
+
+static inline unsigned leftrotate(const unsigned x, const unsigned c) {
+ return (x << c) | (x >> (32 - c));
+}
+
+static void md5_body(MD5Context *md5, const uint8_t *const _data) {
+ const uint32_t *data = (uint32_t *) _data;
+
+ unsigned a = md5->abcd[0];
+ unsigned b = md5->abcd[1];
+ unsigned c = md5->abcd[2];
+ unsigned d = md5->abcd[3];
+ unsigned i;
+
+ for (i = 0; i < 64; i++) {
+ unsigned f, g, tmp;
+
+ if (i < 16) {
+ f = (b & c) | (~b & d);
+ g = i;
+ } else if (i < 32) {
+ f = (d & b) | (~d & c);
+ g = (5 * i + 1) & 15;
+ } else if (i < 48) {
+ f = b ^ c ^ d;
+ g = (3 * i + 5) & 15;
+ } else {
+ f = c ^ (b | ~d);
+ g = (7 * i) & 15;
+ }
+
+ tmp = d;
+ d = c;
+ c = b;
+ b += leftrotate(a + f + k[i] + NE2LE_32(data[g]), s[i >> 4][i & 3]);
+ a = tmp;
+ }
+
+ md5->abcd[0] += a;
+ md5->abcd[1] += b;
+ md5->abcd[2] += c;
+ md5->abcd[3] += d;
+}
+
+static void md5_update(MD5Context *const md5, const uint8_t *data, unsigned len) {
+ if (!len) return;
+
+ if (md5->len & 63) {
+ const unsigned tmp = imin(len, 64 - (md5->len & 63));
+
+ memcpy(&md5->data[md5->len & 63], data, tmp);
+ len -= tmp;
+ data += tmp;
+ md5->len += tmp;
+ if (!(md5->len & 63))
+ md5_body(md5, md5->data);
+ }
+
+ while (len >= 64) {
+ memcpy(md5->data, data, 64);
+ md5_body(md5, md5->data);
+ md5->len += 64;
+ data += 64;
+ len -= 64;
+ }
+
+ if (len) {
+ memcpy(md5->data, data, len);
+ md5->len += len;
+ }
+}
+
+static int md5_write(MD5Context *const md5, Dav1dPicture *const p) {
+ const int hbd = p->p.bpc > 8;
+ const int w = p->p.w, h = p->p.h;
+ uint8_t *yptr = p->data[0];
+
+#if ENDIANNESS_BIG
+ if (hbd && (!md5->bswap || md5->bswap_w < p->p.w)) {
+ free(md5->bswap);
+ md5->bswap_w = 0;
+ md5->bswap = malloc(p->p.w << 1);
+ if (!md5->bswap) return -1;
+ md5->bswap_w = p->p.w;
+ }
+#endif
+
+ for (int y = 0; y < h; y++) {
+#if ENDIANNESS_BIG
+ if (hbd) {
+ for (int x = 0; x < w; x++) {
+ md5->bswap[2 * x + 1] = yptr[2 * x];
+ md5->bswap[2 * x] = yptr[2 * x + 1];
+ }
+ md5_update(md5, md5->bswap, w << hbd);
+ } else
+#endif
+ md5_update(md5, yptr, w << hbd);
+ yptr += p->stride[0];
+ }
+
+ if (p->p.layout != DAV1D_PIXEL_LAYOUT_I400) {
+ const int ss_ver = p->p.layout == DAV1D_PIXEL_LAYOUT_I420;
+ const int ss_hor = p->p.layout != DAV1D_PIXEL_LAYOUT_I444;
+ const int cw = (w + ss_hor) >> ss_hor;
+ const int ch = (h + ss_ver) >> ss_ver;
+ for (int pl = 1; pl <= 2; pl++) {
+ uint8_t *uvptr = p->data[pl];
+
+ for (int y = 0; y < ch; y++) {
+#if ENDIANNESS_BIG
+ if (hbd) {
+ for (int x = 0; x < cw; x++){
+ md5->bswap[2 * x + 1] = uvptr[2 * x];
+ md5->bswap[2 * x] = uvptr[2 * x + 1];
+ }
+ md5_update(md5, md5->bswap, cw << hbd);
+ } else
+#endif
+ md5_update(md5, uvptr, cw << hbd);
+ uvptr += p->stride[1];
+ }
+ }
+ }
+
+ dav1d_picture_unref(p);
+
+ return 0;
+}
+
+static void md5_finish(MD5Context *const md5) {
+ static const uint8_t bit[2] = { 0x80, 0x00 };
+ uint64_t len = NE2LE_64(md5->len << 3);
+
+ md5_update(md5, &bit[0], 1);
+ while ((md5->len & 63) != 56)
+ md5_update(md5, &bit[1], 1);
+ md5_update(md5, (uint8_t *) &len, 8);
+}
+
+static void md5_close(MD5Context *const md5) {
+ md5_finish(md5);
+ for (int i = 0; i < 4; i++)
+ fprintf(md5->f, "%2.2x%2.2x%2.2x%2.2x",
+ md5->abcd[i] & 0xff,
+ (md5->abcd[i] >> 8) & 0xff,
+ (md5->abcd[i] >> 16) & 0xff,
+ md5->abcd[i] >> 24);
+ fprintf(md5->f, "\n");
+
+#if ENDIANNESS_BIG
+ free(md5->bswap);
+ md5->bswap_w = 0;
+#endif
+
+ if (md5->f != stdout)
+ fclose(md5->f);
+}
+
+static int md5_verify(MD5Context *const md5, const char *const md5_str) {
+ md5_finish(md5);
+
+ if (strlen(md5_str) < 32)
+ return 0;
+
+ const char *p = md5_str;
+ unsigned abcd[4] = { 0 };
+ char t[3] = { 0 };
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ unsigned val;
+ char *ignore;
+ memcpy(t, p, 2);
+ p += 2;
+ val = (unsigned) strtoul(t, &ignore, 16);
+ abcd[i] |= val << (8 * j);
+ }
+ }
+
+#if ENDIANNESS_BIG
+ free(md5->bswap);
+ md5->bswap_w = 0;
+#endif
+
+ return !!memcmp(abcd, md5->abcd, sizeof(abcd));
+}
+
+const Muxer md5_muxer = {
+ .priv_data_size = sizeof(MD5Context),
+ .name = "md5",
+ .extension = "md5",
+ .write_header = md5_open,
+ .write_picture = md5_write,
+ .write_trailer = md5_close,
+ .verify = md5_verify,
+};
diff --git a/third_party/dav1d/tools/output/muxer.h b/third_party/dav1d/tools/output/muxer.h
new file mode 100644
index 0000000000..54b3f6aa13
--- /dev/null
+++ b/third_party/dav1d/tools/output/muxer.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright © 2018, VideoLAN and dav1d authors
+ * Copyright © 2018, Two Orioles, LLC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DAV1D_OUTPUT_MUXER_H
+#define DAV1D_OUTPUT_MUXER_H
+
+#include "picture.h"
+
+typedef struct MuxerPriv MuxerPriv;
+typedef struct Muxer {
+ int priv_data_size;
+ const char *name;
+ const char *extension;
+ int (*write_header)(MuxerPriv *ctx, const char *filename,
+ const Dav1dPictureParameters *p, const unsigned fps[2]);
+ int (*write_picture)(MuxerPriv *ctx, Dav1dPicture *p);
+ void (*write_trailer)(MuxerPriv *ctx);
+ /**
+ * Verifies the muxed data (for example in the md5 muxer). Replaces write_trailer.
+ *
+ * @param hash_string Muxer specific reference value.
+ *
+ * @return 0 on success.
+ */
+ int (*verify)(MuxerPriv *ctx, const char *hash_string);
+} Muxer;
+
+#endif /* DAV1D_OUTPUT_MUXER_H */
diff --git a/third_party/dav1d/tools/output/null.c b/third_party/dav1d/tools/output/null.c
new file mode 100644
index 0000000000..f8633f3e67
--- /dev/null
+++ b/third_party/dav1d/tools/output/null.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright © 2018, VideoLAN and dav1d authors
+ * Copyright © 2018, Two Orioles, LLC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "output/muxer.h"
+
+typedef struct MuxerPriv NullOutputContext;
+
+static int null_write(NullOutputContext *const c, Dav1dPicture *const p) {
+ dav1d_picture_unref(p);
+ return 0;
+}
+
+const Muxer null_muxer = {
+ .priv_data_size = 0,
+ .name = "null",
+ .extension = "null",
+ .write_picture = null_write,
+};
diff --git a/third_party/dav1d/tools/output/output.c b/third_party/dav1d/tools/output/output.c
new file mode 100644
index 0000000000..368d079156
--- /dev/null
+++ b/third_party/dav1d/tools/output/output.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright © 2018, VideoLAN and dav1d authors
+ * Copyright © 2018, Two Orioles, LLC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "common/attributes.h"
+
+#include "output/output.h"
+#include "output/muxer.h"
+
+struct MuxerContext {
+ MuxerPriv *data;
+ const Muxer *impl;
+};
+
+extern const Muxer null_muxer;
+extern const Muxer md5_muxer;
+extern const Muxer yuv_muxer;
+extern const Muxer y4m2_muxer;
+static const Muxer *muxers[] = {
+ &null_muxer,
+ &md5_muxer,
+ &yuv_muxer,
+ &y4m2_muxer,
+ NULL
+};
+
+static const char *find_extension(const char *const f) {
+ const size_t l = strlen(f);
+
+ if (l == 0) return NULL;
+
+ const char *const end = &f[l - 1], *step = end;
+ while ((*step >= 'a' && *step <= 'z') ||
+ (*step >= 'A' && *step <= 'Z') ||
+ (*step >= '0' && *step <= '9'))
+ {
+ step--;
+ }
+
+ return (step < end && step > f && *step == '.' && step[-1] != '/') ?
+ &step[1] : NULL;
+}
+
+int output_open(MuxerContext **const c_out,
+ const char *const name, const char *const filename,
+ const Dav1dPictureParameters *const p, const unsigned fps[2])
+{
+ const Muxer *impl;
+ MuxerContext *c;
+ unsigned i;
+ int res;
+
+ if (name) {
+ for (i = 0; muxers[i]; i++) {
+ if (!strcmp(muxers[i]->name, name)) {
+ impl = muxers[i];
+ break;
+ }
+ }
+ if (!muxers[i]) {
+ fprintf(stderr, "Failed to find muxer named \"%s\"\n", name);
+ return DAV1D_ERR(ENOPROTOOPT);
+ }
+ } else if (!strcmp(filename, "/dev/null")) {
+ impl = muxers[0];
+ } else {
+ const char *const ext = find_extension(filename);
+ if (!ext) {
+ fprintf(stderr, "No extension found for file %s\n", filename);
+ return -1;
+ }
+ for (i = 0; muxers[i]; i++) {
+ if (!strcmp(muxers[i]->extension, ext)) {
+ impl = muxers[i];
+ break;
+ }
+ }
+ if (!muxers[i]) {
+ fprintf(stderr, "Failed to find muxer for extension \"%s\"\n", ext);
+ return DAV1D_ERR(ENOPROTOOPT);
+ }
+ }
+
+ if (!(c = malloc(sizeof(MuxerContext) + impl->priv_data_size))) {
+ fprintf(stderr, "Failed to allocate memory\n");
+ return DAV1D_ERR(ENOMEM);
+ }
+ c->impl = impl;
+ c->data = (MuxerPriv *) &c[1];
+ if (impl->write_header && (res = impl->write_header(c->data, filename, p, fps)) < 0) {
+ free(c);
+ return res;
+ }
+ *c_out = c;
+
+ return 0;
+}
+
+int output_write(MuxerContext *const ctx, Dav1dPicture *const p) {
+ const int res = ctx->impl->write_picture(ctx->data, p);
+ return res < 0 ? res : 0;
+}
+
+void output_close(MuxerContext *const ctx) {
+ if (ctx->impl->write_trailer)
+ ctx->impl->write_trailer(ctx->data);
+ free(ctx);
+}
+
+int output_verify(MuxerContext *const ctx, const char *const md5_str) {
+ const int res = ctx->impl->verify ?
+ ctx->impl->verify(ctx->data, md5_str) : 0;
+ free(ctx);
+ return res;
+}
diff --git a/third_party/dav1d/tools/output/output.h b/third_party/dav1d/tools/output/output.h
new file mode 100644
index 0000000000..6111c8682b
--- /dev/null
+++ b/third_party/dav1d/tools/output/output.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright © 2018, VideoLAN and dav1d authors
+ * Copyright © 2018, Two Orioles, LLC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DAV1D_OUTPUT_OUTPUT_H
+#define DAV1D_OUTPUT_OUTPUT_H
+
+#include "picture.h"
+
+typedef struct MuxerContext MuxerContext;
+
+int output_open(MuxerContext **c, const char *name, const char *filename,
+ const Dav1dPictureParameters *p, const unsigned fps[2]);
+int output_write(MuxerContext *ctx, Dav1dPicture *pic);
+void output_close(MuxerContext *ctx);
+/**
+ * Verifies the muxed data (for example in the md5 muxer). Replaces output_close.
+ *
+ * @param hash_string Muxer specific reference value.
+ *
+ * @return 0 on success.
+ */
+int output_verify(MuxerContext *ctx, const char *hash_string);
+
+#endif /* DAV1D_OUTPUT_OUTPUT_H */
diff --git a/third_party/dav1d/tools/output/y4m2.c b/third_party/dav1d/tools/output/y4m2.c
new file mode 100644
index 0000000000..8766f64868
--- /dev/null
+++ b/third_party/dav1d/tools/output/y4m2.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright © 2018, VideoLAN and dav1d authors
+ * Copyright © 2018, Two Orioles, LLC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "output/muxer.h"
+
+typedef struct MuxerPriv {
+ FILE *f;
+ int first;
+ unsigned fps[2];
+} Y4m2OutputContext;
+
+static int y4m2_open(Y4m2OutputContext *const c, const char *const file,
+ const Dav1dPictureParameters *p, const unsigned fps[2])
+{
+ if (!strcmp(file, "-")) {
+ c->f = stdout;
+ } else if (!(c->f = fopen(file, "wb"))) {
+ fprintf(stderr, "Failed to open %s: %s\n", file, strerror(errno));
+ return -1;
+ }
+
+ c->first = 1;
+ c->fps[0] = fps[0];
+ c->fps[1] = fps[1];
+
+ return 0;
+}
+
+static int write_header(Y4m2OutputContext *const c, const Dav1dPicture *const p) {
+ static const char *const ss_names[][3] = {
+ [DAV1D_PIXEL_LAYOUT_I400] = { "mono", "mono10", "mono12" },
+ [DAV1D_PIXEL_LAYOUT_I420] = { NULL, "420p10", "420p12" },
+ [DAV1D_PIXEL_LAYOUT_I422] = { "422", "422p10", "422p12" },
+ [DAV1D_PIXEL_LAYOUT_I444] = { "444", "444p10", "444p12" }
+ };
+
+ static const char *const chr_names_8bpc_i420[] = {
+ [DAV1D_CHR_UNKNOWN] = "420jpeg",
+ [DAV1D_CHR_VERTICAL] = "420mpeg2",
+ [DAV1D_CHR_COLOCATED] = "420"
+ };
+
+ const char *const ss_name =
+ p->p.layout == DAV1D_PIXEL_LAYOUT_I420 && p->p.bpc == 8 ?
+ chr_names_8bpc_i420[p->seq_hdr->chr > 2 ? DAV1D_CHR_UNKNOWN : p->seq_hdr->chr] :
+ ss_names[p->p.layout][p->seq_hdr->hbd];
+
+ const unsigned fw = p->p.w;
+ const unsigned fh = p->p.h;
+ uint64_t aw = (uint64_t)fh * p->frame_hdr->render_width;
+ uint64_t ah = (uint64_t)fw * p->frame_hdr->render_height;
+ uint64_t gcd = ah;
+ for (uint64_t a = aw, b; (b = a % gcd); a = gcd, gcd = b);
+ aw /= gcd;
+ ah /= gcd;
+
+ fprintf(c->f, "YUV4MPEG2 W%u H%u F%u:%u Ip A%"PRIu64":%"PRIu64" C%s\n",
+ fw, fh, c->fps[0], c->fps[1], aw, ah, ss_name);
+
+ return 0;
+}
+
+static int y4m2_write(Y4m2OutputContext *const c, Dav1dPicture *const p) {
+ if (c->first) {
+ c->first = 0;
+ const int res = write_header(c, p);
+ if (res < 0) return res;
+ }
+ fprintf(c->f, "FRAME\n");
+
+ uint8_t *ptr;
+ const int hbd = p->p.bpc > 8;
+
+ ptr = p->data[0];
+ for (int y = 0; y < p->p.h; y++) {
+ if (fwrite(ptr, p->p.w << hbd, 1, c->f) != 1)
+ goto error;
+ ptr += p->stride[0];
+ }
+
+ if (p->p.layout != DAV1D_PIXEL_LAYOUT_I400) {
+ // u/v
+ const int ss_ver = p->p.layout == DAV1D_PIXEL_LAYOUT_I420;
+ const int ss_hor = p->p.layout != DAV1D_PIXEL_LAYOUT_I444;
+ const int cw = (p->p.w + ss_hor) >> ss_hor;
+ const int ch = (p->p.h + ss_ver) >> ss_ver;
+ for (int pl = 1; pl <= 2; pl++) {
+ ptr = p->data[pl];
+ for (int y = 0; y < ch; y++) {
+ if (fwrite(ptr, cw << hbd, 1, c->f) != 1)
+ goto error;
+ ptr += p->stride[1];
+ }
+ }
+ }
+
+ dav1d_picture_unref(p);
+ return 0;
+
+error:
+ dav1d_picture_unref(p);
+ fprintf(stderr, "Failed to write frame data: %s\n", strerror(errno));
+ return -1;
+}
+
+static void y4m2_close(Y4m2OutputContext *const c) {
+ if (c->f != stdout)
+ fclose(c->f);
+}
+
+const Muxer y4m2_muxer = {
+ .priv_data_size = sizeof(Y4m2OutputContext),
+ .name = "yuv4mpeg2",
+ .extension = "y4m",
+ .write_header = y4m2_open,
+ .write_picture = y4m2_write,
+ .write_trailer = y4m2_close,
+};
diff --git a/third_party/dav1d/tools/output/yuv.c b/third_party/dav1d/tools/output/yuv.c
new file mode 100644
index 0000000000..406f284188
--- /dev/null
+++ b/third_party/dav1d/tools/output/yuv.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright © 2018, VideoLAN and dav1d authors
+ * Copyright © 2018, Two Orioles, LLC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "output/muxer.h"
+
+typedef struct MuxerPriv {
+ FILE *f;
+} YuvOutputContext;
+
+static int yuv_open(YuvOutputContext *const c, const char *const file,
+ const Dav1dPictureParameters *const p,
+ const unsigned fps[2])
+{
+ if (!strcmp(file, "-")) {
+ c->f = stdout;
+ } else if (!(c->f = fopen(file, "wb"))) {
+ fprintf(stderr, "Failed to open %s: %s\n", file, strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+static int yuv_write(YuvOutputContext *const c, Dav1dPicture *const p) {
+ uint8_t *ptr;
+ const int hbd = p->p.bpc > 8;
+
+ ptr = p->data[0];
+ for (int y = 0; y < p->p.h; y++) {
+ if (fwrite(ptr, p->p.w << hbd, 1, c->f) != 1)
+ goto error;
+ ptr += p->stride[0];
+ }
+
+ if (p->p.layout != DAV1D_PIXEL_LAYOUT_I400) {
+ // u/v
+ const int ss_ver = p->p.layout == DAV1D_PIXEL_LAYOUT_I420;
+ const int ss_hor = p->p.layout != DAV1D_PIXEL_LAYOUT_I444;
+ const int cw = (p->p.w + ss_hor) >> ss_hor;
+ const int ch = (p->p.h + ss_ver) >> ss_ver;
+ for (int pl = 1; pl <= 2; pl++) {
+ ptr = p->data[pl];
+ for (int y = 0; y < ch; y++) {
+ if (fwrite(ptr, cw << hbd, 1, c->f) != 1)
+ goto error;
+ ptr += p->stride[1];
+ }
+ }
+ }
+
+ dav1d_picture_unref(p);
+ return 0;
+
+error:
+ dav1d_picture_unref(p);
+ fprintf(stderr, "Failed to write frame data: %s\n", strerror(errno));
+ return -1;
+}
+
+static void yuv_close(YuvOutputContext *const c) {
+ if (c->f != stdout)
+ fclose(c->f);
+}
+
+const Muxer yuv_muxer = {
+ .priv_data_size = sizeof(YuvOutputContext),
+ .name = "yuv",
+ .extension = "yuv",
+ .write_header = yuv_open,
+ .write_picture = yuv_write,
+ .write_trailer = yuv_close,
+};