diff options
author | Ronald S. Bultje <rsbultje@gmail.com> | 2019-11-15 18:36:22 +0300 |
---|---|---|
committer | Ronald S. Bultje <rsbultje@gmail.com> | 2019-11-21 21:12:59 +0300 |
commit | eb4a8f6d076225fc5e75eed585535eccca1b3ace (patch) | |
tree | b7ab00e32fa48e062b01e12e8145c7fe7cee474b /tools/input | |
parent | 4bf52cb5f211772d3755b8219b635d04f767d979 (diff) |
Add section-5 raw OBU demuxer
Fixes #304.
Diffstat (limited to 'tools/input')
-rw-r--r-- | tools/input/annexb.c | 27 | ||||
-rw-r--r-- | tools/input/input.c | 3 | ||||
-rw-r--r-- | tools/input/parse.h | 51 | ||||
-rw-r--r-- | tools/input/section5.c | 139 |
4 files changed, 197 insertions, 23 deletions
diff --git a/tools/input/annexb.c b/tools/input/annexb.c index 4567f94..a36536b 100644 --- a/tools/input/annexb.c +++ b/tools/input/annexb.c @@ -27,13 +27,13 @@ #include "config.h" -#include <errno.h> #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include "input/demuxer.h" +#include "input/parse.h" typedef struct DemuxerPriv { FILE *f; @@ -41,23 +41,6 @@ typedef struct DemuxerPriv { size_t frame_unit_size; } AnnexbInputContext; -static int leb128(AnnexbInputContext *const c, size_t *const len) { - unsigned more, i = 0; - uint8_t byte; - *len = 0; - do { - if (fread(&byte, 1, 1, c->f) < 1) - return -1; - more = byte & 0x80; - unsigned bits = byte & 0x7f; - if (i <= 3 || (i == 4 && bits < (1 << 4))) - *len |= bits << (i * 7); - else if (bits) return -1; - if (++i == 8 && more) return -1; - } while (more); - return i; -} - static int annexb_open(AnnexbInputContext *const c, const char *const file, unsigned fps[2], unsigned *const num_frames, unsigned timebase[2]) { @@ -75,7 +58,7 @@ static int annexb_open(AnnexbInputContext *const c, const char *const file, timebase[0] = 25; timebase[1] = 1; for (*num_frames = 0;; (*num_frames)++) { - res = leb128(c, &len); + res = leb128(c->f, &len); if (res < 0) break; fseeko(c->f, len, SEEK_CUR); @@ -90,15 +73,15 @@ static int annexb_read(AnnexbInputContext *const c, Dav1dData *const data) { int res; if (!c->temporal_unit_size) { - res = leb128(c, &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, &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, &len); + 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; diff --git a/tools/input/input.c b/tools/input/input.c index 53e77bd..5dc4cef 100644 --- a/tools/input/input.c +++ b/tools/input/input.c @@ -42,7 +42,7 @@ struct DemuxerContext { const Demuxer *impl; }; -#define MAX_NUM_DEMUXERS 2 +#define MAX_NUM_DEMUXERS 3 static const Demuxer *demuxers[MAX_NUM_DEMUXERS]; static int num_demuxers = 0; @@ -55,6 +55,7 @@ static int num_demuxers = 0; void init_demuxers(void) { register_demuxer(ivf_demuxer); register_demuxer(annexb_demuxer); + register_demuxer(section5_demuxer); } static const char *find_extension(const char *const f) { diff --git a/tools/input/parse.h b/tools/input/parse.h new file mode 100644 index 0000000..6ed3347 --- /dev/null +++ b/tools/input/parse.h @@ -0,0 +1,51 @@ +/* + * 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 "dav1d/headers.h" + +static int leb128(FILE *const f, size_t *const len) { + unsigned i = 0, more; + *len = 0; + do { + uint8_t byte; + if (fread(&byte, 1, 1, f) < 1) + return -1; + more = byte & 0x80; + const unsigned bits = byte & 0x7f; + if (i <= 3 || (i == 4 && bits < (1 << 4))) + *len |= bits << (i * 7); + else if (bits) return -1; + if (++i == 8 && more) return -1; + } while (more); + return i; +} + +#endif /* DAV1D_INPUT_PARSE_H */ diff --git a/tools/input/section5.c b/tools/input/section5.c new file mode 100644 index 0000000..7df49a9 --- /dev/null +++ b/tools/input/section5.c @@ -0,0 +1,139 @@ +/* + * Copyright © 2019, VideoLAN and dav1d authors + * Copyright © 2019, 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 <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#include "input/demuxer.h" +#include "input/parse.h" + +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, -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", + .extension = "obu", + .open = section5_open, + .read = section5_read, + .close = section5_close, +}; |