diff options
author | Ronald S. Bultje <rsbultje@gmail.com> | 2018-09-05 00:32:00 +0300 |
---|---|---|
committer | Ronald S. Bultje <rsbultje@gmail.com> | 2018-09-22 14:59:19 +0300 |
commit | e2892ffa2dd1e893d0229c5fcbe0bbbee8e11c20 (patch) | |
tree | 9ba42513c2916db89d47f8b34fa0141d6aeb4dde /tools/input | |
parent | d32eb2d935a31288c34ccaa42b09bc60eacdfd68 (diff) |
Initial decoder implementation.
With minor contributions from:
- Jean-Baptiste Kempf <jb@videolan.org>
- Marvin Scholz <epirat07@gmail.com>
- Hugo Beauzée-Luyssen <hugo@videolan.org>
Diffstat (limited to 'tools/input')
-rw-r--r-- | tools/input/demuxer.h | 44 | ||||
-rw-r--r-- | tools/input/input.c | 124 | ||||
-rw-r--r-- | tools/input/input.h | 41 | ||||
-rw-r--r-- | tools/input/ivf.c | 113 |
4 files changed, 322 insertions, 0 deletions
diff --git a/tools/input/demuxer.h b/tools/input/demuxer.h new file mode 100644 index 0000000..8fdf6ed --- /dev/null +++ b/tools/input/demuxer.h @@ -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. + */ + +#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; + const char *extension; + int (*open)(DemuxerPriv *ctx, const char *filename, + unsigned fps[2], unsigned *num_frames); + int (*read)(DemuxerPriv *ctx, Dav1dData *data); + void (*close)(DemuxerPriv *ctx); +} Demuxer; + +#endif /* __DAV1D_INPUT_DEMUXER_H__ */ diff --git a/tools/input/input.c b/tools/input/input.c new file mode 100644 index 0000000..e00c21c --- /dev/null +++ b/tools/input/input.c @@ -0,0 +1,124 @@ +/* + * 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 <assert.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "input/input.h" +#include "input/demuxer.h" + +struct DemuxerContext { + DemuxerPriv *data; + const Demuxer *impl; +}; + +#define MAX_NUM_DEMUXERS 1 +static const Demuxer *demuxers[MAX_NUM_DEMUXERS]; +static int num_demuxers = 0; + +#define register_demuxer(impl) { \ + extern const Demuxer impl; \ + assert(num_demuxers < MAX_NUM_DEMUXERS); \ + demuxers[num_demuxers++] = &impl; \ +} + +void init_demuxers(void) { + register_demuxer(ivf_demuxer); +} + +static const char *find_extension(const char *const f) { + const int 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 input_open(DemuxerContext **const c_out, const char *const filename, + unsigned fps[2], unsigned *const num_frames) +{ + const Demuxer *impl; + DemuxerContext *c; + int res, i; + + const char *const ext = find_extension(filename); + if (!ext) { + fprintf(stderr, "No extension found for file %s\n", filename); + return -1; + } + + for (i = 0; i < num_demuxers; i++) { + if (!strcmp(demuxers[i]->extension, ext)) { + impl = demuxers[i]; + break; + } + } + if (i == num_demuxers) { + fprintf(stderr, + "Failed to find demuxer for file %s (\"%s\")\n", + filename, ext); + return -ENOPROTOOPT; + } + + if (!(c = malloc(sizeof(DemuxerContext) + impl->priv_data_size))) { + fprintf(stderr, "Failed to allocate memory\n"); + return -ENOMEM; + } + memset(c, 0, sizeof(DemuxerContext) + impl->priv_data_size); + c->impl = impl; + c->data = (DemuxerPriv *) &c[1]; + if ((res = impl->open(c->data, filename, fps, num_frames)) < 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/tools/input/input.h b/tools/input/input.h new file mode 100644 index 0000000..ad0f0ef --- /dev/null +++ b/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; + +void init_demuxers(void); +int input_open(DemuxerContext **c, const char *filename, + unsigned fps[2], unsigned *num_frames); +int input_read(DemuxerContext *ctx, Dav1dData *data); +void input_close(DemuxerContext *ctx); + +#endif /* __DAV1D_INPUT_INPUT_H__ */ diff --git a/tools/input/ivf.c b/tools/input/ivf.c new file mode 100644 index 0000000..2e47d32 --- /dev/null +++ b/tools/input/ivf.c @@ -0,0 +1,113 @@ +/* + * 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 <assert.h> +#include <errno.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#include "common/intops.h" + +#include "input/demuxer.h" + +typedef struct DemuxerPriv { + FILE *f; +} IvfInputContext; + +static int ivf_open(IvfInputContext *const c, const char *const file, + unsigned fps[2], unsigned *const num_frames) +{ + int res; + uint8_t hdr[32]; + + memset(c, 0, sizeof(*c)); + if (!(c->f = fopen(file, "r"))) { + 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; + } + + fps[0] = rl32(&hdr[16]); + fps[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 + fseek(c->f, rl32(data) + 8, SEEK_CUR); + } + fps[0] *= *num_frames; + fps[1] *= duration; + fseek(c->f, 32, SEEK_SET); + + return 0; +} + +static int ivf_read(IvfInputContext *const c, Dav1dData *const buf) { + uint8_t data[4]; + int res; + + if ((res = fread(data, 4, 1, c->f)) != 1) + return -1; // EOF + fseek(c->f, 8, SEEK_CUR); // skip timestamp + const ptrdiff_t sz = rl32(data); + dav1d_data_create(buf, sz); + if ((res = fread(buf->data, sz, 1, c->f)) != 1) + fprintf(stderr, "Failed to read frame data: %s\n", strerror(errno)); + + return 0; +} + +static void ivf_close(IvfInputContext *const c) { + fclose(c->f); +} + +const Demuxer ivf_demuxer = { + .priv_data_size = sizeof(IvfInputContext), + .name = "ivf", + .extension = "ivf", + .open = ivf_open, + .read = ivf_read, + .close = ivf_close, +}; |