diff options
Diffstat (limited to 'third_party/dav1d/tools/output')
-rw-r--r-- | third_party/dav1d/tools/output/md5.c | 317 | ||||
-rw-r--r-- | third_party/dav1d/tools/output/muxer.h | 52 | ||||
-rw-r--r-- | third_party/dav1d/tools/output/null.c | 44 | ||||
-rw-r--r-- | third_party/dav1d/tools/output/output.c | 145 | ||||
-rw-r--r-- | third_party/dav1d/tools/output/output.h | 48 | ||||
-rw-r--r-- | third_party/dav1d/tools/output/y4m2.c | 151 | ||||
-rw-r--r-- | third_party/dav1d/tools/output/yuv.c | 104 |
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, +}; |