summaryrefslogtreecommitdiffstats
path: root/third_party/dav1d/tools/input
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/input
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/input')
-rw-r--r--third_party/dav1d/tools/input/annexb.c195
-rw-r--r--third_party/dav1d/tools/input/demuxer.h45
-rw-r--r--third_party/dav1d/tools/input/input.c134
-rw-r--r--third_party/dav1d/tools/input/input.h41
-rw-r--r--third_party/dav1d/tools/input/ivf.c158
-rw-r--r--third_party/dav1d/tools/input/parse.h109
-rw-r--r--third_party/dav1d/tools/input/section5.c185
7 files changed, 867 insertions, 0 deletions
diff --git a/third_party/dav1d/tools/input/annexb.c b/third_party/dav1d/tools/input/annexb.c
new file mode 100644
index 0000000000..032480d00c
--- /dev/null
+++ b/third_party/dav1d/tools/input/annexb.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright © 2018, VideoLAN and dav1d authors
+ * Copyright © 2018, Two Orioles, LLC
+ * Copyright © 2019, James Almer <jamrial@gmail.com>
+ * 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 <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "common/intops.h"
+
+#include "dav1d/headers.h"
+
+#include "input/demuxer.h"
+#include "input/parse.h"
+
+// these functions are based on an implementation from FFmpeg, and relicensed
+// with author's permission
+
+#define PROBE_SIZE 1024
+
+static int annexb_probe(const uint8_t *data) {
+ int ret, cnt = 0;
+
+ size_t temporal_unit_size;
+ ret = leb(data + cnt, PROBE_SIZE - cnt, &temporal_unit_size);
+ if (ret < 0)
+ return 0;
+ cnt += ret;
+
+ size_t frame_unit_size;
+ ret = leb(data + cnt, PROBE_SIZE - cnt, &frame_unit_size);
+ if (ret < 0 || ((uint64_t)frame_unit_size + ret) > temporal_unit_size)
+ return 0;
+ cnt += ret;
+
+ temporal_unit_size -= ret;
+
+ size_t obu_unit_size;
+ ret = leb(data + cnt, PROBE_SIZE - cnt, &obu_unit_size);
+ if (ret < 0 || ((uint64_t)obu_unit_size + ret) >= frame_unit_size)
+ return 0;
+ cnt += ret;
+
+ temporal_unit_size -= obu_unit_size + ret;
+ frame_unit_size -= obu_unit_size + ret;
+
+ // Check that the first OBU is a Temporal Delimiter.
+ size_t obu_size;
+ enum Dav1dObuType type;
+ ret = parse_obu_header(data + cnt, imin(PROBE_SIZE - cnt, (int) obu_unit_size),
+ &obu_size, &type, 1);
+ if (ret < 0 || type != DAV1D_OBU_TD || obu_size > 0)
+ return 0;
+ cnt += (int)obu_unit_size;
+
+ // look for first frame and accompanying sequence header
+ int seq = 0;
+ while (cnt < PROBE_SIZE) {
+ ret = leb(data + cnt, PROBE_SIZE - cnt, &obu_unit_size);
+ if (ret < 0 || ((uint64_t)obu_unit_size + ret) > frame_unit_size)
+ return 0;
+ cnt += ret;
+ temporal_unit_size -= ret;
+ frame_unit_size -= ret;
+
+ ret = parse_obu_header(data + cnt, imin(PROBE_SIZE - cnt, (int) obu_unit_size),
+ &obu_size, &type, 1);
+ if (ret < 0)
+ return 0;
+ cnt += (int)obu_unit_size;
+
+ switch (type) {
+ case DAV1D_OBU_SEQ_HDR:
+ seq = 1;
+ break;
+ case DAV1D_OBU_FRAME:
+ case DAV1D_OBU_FRAME_HDR:
+ return seq;
+ case DAV1D_OBU_TD:
+ case DAV1D_OBU_TILE_GRP:
+ return 0;
+ default:
+ break;
+ }
+
+ temporal_unit_size -= obu_unit_size;
+ frame_unit_size -= obu_unit_size;
+ if (frame_unit_size <= 0)
+ break;
+ }
+
+ return 0;
+}
+
+typedef struct DemuxerPriv {
+ FILE *f;
+ size_t temporal_unit_size;
+ size_t frame_unit_size;
+} AnnexbInputContext;
+
+static int annexb_open(AnnexbInputContext *const c, const char *const file,
+ unsigned fps[2], unsigned *const num_frames, unsigned timebase[2])
+{
+ int res;
+ size_t len;
+
+ if (!(c->f = fopen(file, "rb"))) {
+ fprintf(stderr, "Failed to open %s: %s\n", file, strerror(errno));
+ return -1;
+ }
+
+ // TODO: Parse sequence header and read timing info if any.
+ fps[0] = 25;
+ fps[1] = 1;
+ timebase[0] = 25;
+ timebase[1] = 1;
+ for (*num_frames = 0;; (*num_frames)++) {
+ res = leb128(c->f, &len);
+ if (res < 0)
+ break;
+ fseeko(c->f, len, SEEK_CUR);
+ }
+ fseeko(c->f, 0, SEEK_SET);
+
+ return 0;
+}
+
+static int annexb_read(AnnexbInputContext *const c, Dav1dData *const data) {
+ size_t len;
+ int res;
+
+ if (!c->temporal_unit_size) {
+ res = leb128(c->f, &c->temporal_unit_size);
+ if (res < 0) return -1;
+ }
+ if (!c->frame_unit_size) {
+ res = leb128(c->f, &c->frame_unit_size);
+ if (res < 0 || (c->frame_unit_size + res) > c->temporal_unit_size) return -1;
+ c->temporal_unit_size -= res;
+ }
+ res = leb128(c->f, &len);
+ if (res < 0 || (len + res) > c->frame_unit_size) return -1;
+ uint8_t *ptr = dav1d_data_create(data, len);
+ if (!ptr) return -1;
+ c->temporal_unit_size -= len + res;
+ c->frame_unit_size -= len + res;
+ if (fread(ptr, len, 1, c->f) != 1) {
+ fprintf(stderr, "Failed to read frame data: %s\n", strerror(errno));
+ dav1d_data_unref(data);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void annexb_close(AnnexbInputContext *const c) {
+ fclose(c->f);
+}
+
+const Demuxer annexb_demuxer = {
+ .priv_data_size = sizeof(AnnexbInputContext),
+ .name = "annexb",
+ .probe = annexb_probe,
+ .probe_sz = PROBE_SIZE,
+ .open = annexb_open,
+ .read = annexb_read,
+ .close = annexb_close,
+};
diff --git a/third_party/dav1d/tools/input/demuxer.h b/third_party/dav1d/tools/input/demuxer.h
new file mode 100644
index 0000000000..c2b88e1480
--- /dev/null
+++ b/third_party/dav1d/tools/input/demuxer.h
@@ -0,0 +1,45 @@
+/*
+ * 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_INPUT_DEMUXER_H
+#define DAV1D_INPUT_DEMUXER_H
+
+#include "data.h"
+
+typedef struct DemuxerPriv DemuxerPriv;
+typedef struct Demuxer {
+ int priv_data_size;
+ const char *name;
+ int probe_sz;
+ int (*probe)(const uint8_t *data);
+ int (*open)(DemuxerPriv *ctx, const char *filename,
+ unsigned fps[2], unsigned *num_frames, unsigned timebase[2]);
+ int (*read)(DemuxerPriv *ctx, Dav1dData *data);
+ void (*close)(DemuxerPriv *ctx);
+} Demuxer;
+
+#endif /* DAV1D_INPUT_DEMUXER_H */
diff --git a/third_party/dav1d/tools/input/input.c b/third_party/dav1d/tools/input/input.c
new file mode 100644
index 0000000000..3ed6983ace
--- /dev/null
+++ b/third_party/dav1d/tools/input/input.c
@@ -0,0 +1,134 @@
+/*
+ * 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 "common/intops.h"
+
+#include "input/input.h"
+#include "input/demuxer.h"
+
+struct DemuxerContext {
+ DemuxerPriv *data;
+ const Demuxer *impl;
+};
+
+extern const Demuxer ivf_demuxer;
+extern const Demuxer annexb_demuxer;
+extern const Demuxer section5_demuxer;
+static const Demuxer *const demuxers[] = {
+ &ivf_demuxer,
+ &annexb_demuxer,
+ &section5_demuxer,
+ NULL
+};
+
+int input_open(DemuxerContext **const c_out,
+ const char *const name, const char *const filename,
+ unsigned fps[2], unsigned *const num_frames, unsigned timebase[2])
+{
+ const Demuxer *impl;
+ DemuxerContext *c;
+ int res, i;
+
+ if (name) {
+ for (i = 0; demuxers[i]; i++) {
+ if (!strcmp(demuxers[i]->name, name)) {
+ impl = demuxers[i];
+ break;
+ }
+ }
+ if (!demuxers[i]) {
+ fprintf(stderr, "Failed to find demuxer named \"%s\"\n", name);
+ return DAV1D_ERR(ENOPROTOOPT);
+ }
+ } else {
+ int probe_sz = 0;
+ for (i = 0; demuxers[i]; i++)
+ probe_sz = imax(probe_sz, demuxers[i]->probe_sz);
+ uint8_t *const probe_data = malloc(probe_sz);
+ if (!probe_data) {
+ fprintf(stderr, "Failed to allocate memory\n");
+ return DAV1D_ERR(ENOMEM);
+ }
+ FILE *f = fopen(filename, "rb");
+ if (!f) {
+ fprintf(stderr, "Failed to open input file %s: %s\n", filename, strerror(errno));
+ return errno ? DAV1D_ERR(errno) : DAV1D_ERR(EIO);
+ }
+ res = !!fread(probe_data, 1, probe_sz, f);
+ fclose(f);
+ if (!res) {
+ free(probe_data);
+ fprintf(stderr, "Failed to read probe data\n");
+ return errno ? DAV1D_ERR(errno) : DAV1D_ERR(EIO);
+ }
+
+ for (i = 0; demuxers[i]; i++) {
+ if (demuxers[i]->probe(probe_data)) {
+ impl = demuxers[i];
+ break;
+ }
+ }
+ free(probe_data);
+ if (!demuxers[i]) {
+ fprintf(stderr,
+ "Failed to probe demuxer for file %s\n",
+ filename);
+ return DAV1D_ERR(ENOPROTOOPT);
+ }
+ }
+
+ if (!(c = calloc(1, sizeof(DemuxerContext) + impl->priv_data_size))) {
+ fprintf(stderr, "Failed to allocate memory\n");
+ return DAV1D_ERR(ENOMEM);
+ }
+ c->impl = impl;
+ c->data = (DemuxerPriv *) &c[1];
+ if ((res = impl->open(c->data, filename, fps, num_frames, timebase)) < 0) {
+ free(c);
+ return res;
+ }
+ *c_out = c;
+
+ return 0;
+}
+
+int input_read(DemuxerContext *const ctx, Dav1dData *const data) {
+ return ctx->impl->read(ctx->data, data);
+}
+
+void input_close(DemuxerContext *const ctx) {
+ ctx->impl->close(ctx->data);
+ free(ctx);
+}
diff --git a/third_party/dav1d/tools/input/input.h b/third_party/dav1d/tools/input/input.h
new file mode 100644
index 0000000000..7b2fdc94c4
--- /dev/null
+++ b/third_party/dav1d/tools/input/input.h
@@ -0,0 +1,41 @@
+/*
+ * 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_INPUT_INPUT_H
+#define DAV1D_INPUT_INPUT_H
+
+#include "data.h"
+
+typedef struct DemuxerContext DemuxerContext;
+
+int input_open(DemuxerContext **const c_out,
+ const char *const name, const char *const filename,
+ unsigned fps[2], unsigned *num_frames, unsigned timebase[2]);
+int input_read(DemuxerContext *ctx, Dav1dData *data);
+void input_close(DemuxerContext *ctx);
+
+#endif /* DAV1D_INPUT_INPUT_H */
diff --git a/third_party/dav1d/tools/input/ivf.c b/third_party/dav1d/tools/input/ivf.c
new file mode 100644
index 0000000000..7b572ee73c
--- /dev/null
+++ b/third_party/dav1d/tools/input/ivf.c
@@ -0,0 +1,158 @@
+/*
+ * 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 <limits.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "input/demuxer.h"
+
+typedef struct DemuxerPriv {
+ FILE *f;
+} IvfInputContext;
+
+static const uint8_t probe_data[] = {
+ 'D', 'K', 'I', 'F',
+ 0, 0, 0x20, 0,
+ 'A', 'V', '0', '1',
+};
+
+static int ivf_probe(const uint8_t *const data) {
+ return !memcmp(data, probe_data, sizeof(probe_data));
+}
+
+static unsigned rl32(const uint8_t *const p) {
+ return ((uint32_t)p[3] << 24U) | (p[2] << 16U) | (p[1] << 8U) | p[0];
+}
+
+static int64_t rl64(const uint8_t *const p) {
+ return (((uint64_t) rl32(&p[4])) << 32) | rl32(p);
+}
+
+static int ivf_open(IvfInputContext *const c, const char *const file,
+ unsigned fps[2], unsigned *const num_frames, unsigned timebase[2])
+{
+ size_t res;
+ uint8_t hdr[32];
+
+ if (!(c->f = fopen(file, "rb"))) {
+ fprintf(stderr, "Failed to open %s: %s\n", file, strerror(errno));
+ return -1;
+ } else if ((res = fread(hdr, 32, 1, c->f)) != 1) {
+ fprintf(stderr, "Failed to read stream header: %s\n", strerror(errno));
+ fclose(c->f);
+ return -1;
+ } else if (memcmp(hdr, "DKIF", 4)) {
+ fprintf(stderr, "%s is not an IVF file [tag=%.4s|0x%02x%02x%02x%02x]\n",
+ file, hdr, hdr[0], hdr[1], hdr[2], hdr[3]);
+ fclose(c->f);
+ return -1;
+ } else if (memcmp(&hdr[8], "AV01", 4)) {
+ fprintf(stderr, "%s is not an AV1 file [tag=%.4s|0x%02x%02x%02x%02x]\n",
+ file, &hdr[8], hdr[8], hdr[9], hdr[10], hdr[11]);
+ fclose(c->f);
+ return -1;
+ }
+
+ timebase[0] = rl32(&hdr[16]);
+ timebase[1] = rl32(&hdr[20]);
+ const unsigned duration = rl32(&hdr[24]);
+
+ uint8_t data[4];
+ for (*num_frames = 0;; (*num_frames)++) {
+ if ((res = fread(data, 4, 1, c->f)) != 1)
+ break; // EOF
+ fseeko(c->f, rl32(data) + 8, SEEK_CUR);
+ }
+
+ uint64_t fps_num = (uint64_t) timebase[0] * *num_frames;
+ uint64_t fps_den = (uint64_t) timebase[1] * duration;
+ if (fps_num && fps_den) { /* Reduce fraction */
+ uint64_t gcd = fps_num;
+ for (uint64_t a = fps_den, b; (b = a % gcd); a = gcd, gcd = b);
+ fps_num /= gcd;
+ fps_den /= gcd;
+
+ while ((fps_num | fps_den) > UINT_MAX) {
+ fps_num >>= 1;
+ fps_den >>= 1;
+ }
+ }
+ if (fps_num && fps_den) {
+ fps[0] = (unsigned) fps_num;
+ fps[1] = (unsigned) fps_den;
+ } else {
+ fps[0] = fps[1] = 0;
+ }
+
+ fseeko(c->f, 32, SEEK_SET);
+
+ return 0;
+}
+
+static int ivf_read(IvfInputContext *const c, Dav1dData *const buf) {
+ uint8_t data[8];
+ uint8_t *ptr;
+ size_t res;
+
+ const int64_t off = ftello(c->f);
+ if ((res = fread(data, 4, 1, c->f)) != 1)
+ return -1; // EOF
+ const ptrdiff_t sz = rl32(data);
+ if ((res = fread(data, 8, 1, c->f)) != 1)
+ return -1; // EOF
+ ptr = dav1d_data_create(buf, sz);
+ if (!ptr) return -1;
+ buf->m.offset = off;
+ buf->m.timestamp = rl64(data);
+ if ((res = fread(ptr, sz, 1, c->f)) != 1) {
+ fprintf(stderr, "Failed to read frame data: %s\n", strerror(errno));
+ dav1d_data_unref(buf);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void ivf_close(IvfInputContext *const c) {
+ fclose(c->f);
+}
+
+const Demuxer ivf_demuxer = {
+ .priv_data_size = sizeof(IvfInputContext),
+ .name = "ivf",
+ .probe = ivf_probe,
+ .probe_sz = sizeof(probe_data),
+ .open = ivf_open,
+ .read = ivf_read,
+ .close = ivf_close,
+};
diff --git a/third_party/dav1d/tools/input/parse.h b/third_party/dav1d/tools/input/parse.h
new file mode 100644
index 0000000000..f5805e8ca4
--- /dev/null
+++ b/third_party/dav1d/tools/input/parse.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright © 2018, VideoLAN and dav1d authors
+ * Copyright © 2018, Two Orioles, LLC
+ * Copyright © 2019, James Almer <jamrial@gmail.com>
+ * 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_INPUT_PARSE_H
+#define DAV1D_INPUT_PARSE_H
+
+#include <limits.h>
+
+#include "dav1d/headers.h"
+
+static int leb128(FILE *const f, size_t *const len) {
+ uint64_t val = 0;
+ unsigned i = 0, more;
+ do {
+ uint8_t v;
+ if (fread(&v, 1, 1, f) < 1)
+ return -1;
+ more = v & 0x80;
+ val |= ((uint64_t) (v & 0x7F)) << (i * 7);
+ i++;
+ } while (more && i < 8);
+ if (val > UINT_MAX || more)
+ return -1;
+ *len = (size_t) val;
+ return i;
+}
+
+// these functions are based on an implementation from FFmpeg, and relicensed
+// with author's permission
+
+static int leb(const uint8_t *ptr, int sz, size_t *const len) {
+ uint64_t val = 0;
+ unsigned i = 0, more;
+ do {
+ if (!sz--) return -1;
+ const int v = *ptr++;
+ more = v & 0x80;
+ val |= ((uint64_t) (v & 0x7F)) << (i * 7);
+ i++;
+ } while (more && i < 8);
+ if (val > UINT_MAX || more)
+ return -1;
+ *len = (size_t) val;
+ return i;
+}
+
+static inline int parse_obu_header(const uint8_t *buf, int buf_size,
+ size_t *const obu_size,
+ enum Dav1dObuType *const type,
+ const int allow_implicit_size)
+{
+ int ret, extension_flag, has_size_flag;
+
+ if (!buf_size)
+ return -1;
+ if (*buf & 0x80) // obu_forbidden_bit
+ return -1;
+
+ *type = (*buf & 0x78) >> 3;
+ extension_flag = (*buf & 0x4) >> 2;
+ has_size_flag = (*buf & 0x2) >> 1;
+ // ignore obu_reserved_1bit
+ buf++;
+ buf_size--;
+
+ if (extension_flag) {
+ buf++;
+ buf_size--;
+ // ignore fields
+ }
+
+ if (has_size_flag) {
+ ret = leb(buf, buf_size, obu_size);
+ if (ret < 0)
+ return -1;
+ return (int) *obu_size + ret + 1 + extension_flag;
+ } else if (!allow_implicit_size)
+ return -1;
+
+ *obu_size = buf_size;
+ return buf_size + 1 + extension_flag;
+}
+
+#endif /* DAV1D_INPUT_PARSE_H */
diff --git a/third_party/dav1d/tools/input/section5.c b/third_party/dav1d/tools/input/section5.c
new file mode 100644
index 0000000000..0c2ce28c63
--- /dev/null
+++ b/third_party/dav1d/tools/input/section5.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright © 2019, VideoLAN and dav1d authors
+ * Copyright © 2019, Two Orioles, LLC
+ * Copyright © 2019, James Almer <jamrial@gmail.com>
+ * 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 <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "dav1d/headers.h"
+
+#include "input/demuxer.h"
+#include "input/parse.h"
+
+#define PROBE_SIZE 1024
+
+static int section5_probe(const uint8_t *data) {
+ int ret, cnt = 0;
+
+ // Check that the first OBU is a Temporal Delimiter.
+ size_t obu_size;
+ enum Dav1dObuType type;
+ ret = parse_obu_header(data + cnt, PROBE_SIZE - cnt,
+ &obu_size, &type, 0);
+ if (ret < 0 || type != DAV1D_OBU_TD || obu_size > 0)
+ return 0;
+ cnt += ret;
+
+ // look for first frame and accompanying sequence header
+ int seq = 0;
+ while (cnt < PROBE_SIZE) {
+ ret = parse_obu_header(data + cnt, PROBE_SIZE - cnt,
+ &obu_size, &type, 0);
+ if (ret < 0)
+ return 0;
+ cnt += ret;
+
+ switch (type) {
+ case DAV1D_OBU_SEQ_HDR:
+ seq = 1;
+ break;
+ case DAV1D_OBU_FRAME:
+ case DAV1D_OBU_FRAME_HDR:
+ return seq;
+ case DAV1D_OBU_TD:
+ case DAV1D_OBU_TILE_GRP:
+ return 0;
+ default:
+ break;
+ }
+ }
+
+ return 0;
+}
+
+typedef struct DemuxerPriv {
+ FILE *f;
+} Section5InputContext;
+
+static int section5_open(Section5InputContext *const c, const char *const file,
+ unsigned fps[2], unsigned *const num_frames, unsigned timebase[2])
+{
+ if (!(c->f = fopen(file, "rb"))) {
+ fprintf(stderr, "Failed to open %s: %s\n", file, strerror(errno));
+ return -1;
+ }
+
+ // TODO: Parse sequence header and read timing info if any.
+ fps[0] = 25;
+ fps[1] = 1;
+ timebase[0] = 25;
+ timebase[1] = 1;
+ *num_frames = 0;
+ for (;;) {
+ uint8_t byte[2];
+
+ if (fread(&byte[0], 1, 1, c->f) < 1)
+ break;
+ const enum Dav1dObuType obu_type = (byte[0] >> 3) & 0xf;
+ if (obu_type == DAV1D_OBU_TD)
+ (*num_frames)++;
+ const int has_length_field = byte[0] & 0x2;
+ if (!has_length_field)
+ return -1;
+ const int has_extension = byte[0] & 0x4;
+ if (has_extension && fread(&byte[1], 1, 1, c->f) < 1)
+ return -1;
+ size_t len;
+ const int res = leb128(c->f, &len);
+ if (res < 0)
+ return -1;
+ fseeko(c->f, len, SEEK_CUR); // skip packet
+ }
+ fseeko(c->f, 0, SEEK_SET);
+
+ return 0;
+}
+
+static int section5_read(Section5InputContext *const c, Dav1dData *const data) {
+ size_t total_bytes = 0;
+
+ for (int first = 1;; first = 0) {
+ uint8_t byte[2];
+
+ if (fread(&byte[0], 1, 1, c->f) < 1) {
+ if (!first && feof(c->f)) break;
+ return -1;
+ }
+ const enum Dav1dObuType obu_type = (byte[0] >> 3) & 0xf;
+ if (first) {
+ if (obu_type != DAV1D_OBU_TD)
+ return -1;
+ } else {
+ if (obu_type == DAV1D_OBU_TD) {
+ // include TD in next packet
+ fseeko(c->f, -1, SEEK_CUR);
+ break;
+ }
+ }
+ const int has_length_field = byte[0] & 0x2;
+ if (!has_length_field)
+ return -1;
+ const int has_extension = !!(byte[0] & 0x4);
+ if (has_extension && fread(&byte[1], 1, 1, c->f) < 1)
+ return -1;
+ size_t len;
+ const int res = leb128(c->f, &len);
+ if (res < 0)
+ return -1;
+ total_bytes += 1 + has_extension + res + len;
+ fseeko(c->f, len, SEEK_CUR); // skip packet, we'll read it below
+ }
+
+ fseeko(c->f, -(off_t)total_bytes, SEEK_CUR);
+ uint8_t *ptr = dav1d_data_create(data, total_bytes);
+ if (!ptr) return -1;
+ if (fread(ptr, total_bytes, 1, c->f) != 1) {
+ fprintf(stderr, "Failed to read frame data: %s\n", strerror(errno));
+ dav1d_data_unref(data);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void section5_close(Section5InputContext *const c) {
+ fclose(c->f);
+}
+
+const Demuxer section5_demuxer = {
+ .priv_data_size = sizeof(Section5InputContext),
+ .name = "section5",
+ .probe = section5_probe,
+ .probe_sz = PROBE_SIZE,
+ .open = section5_open,
+ .read = section5_read,
+ .close = section5_close,
+};