From 0eafb6f5abc61a8c08cd27c649c935b40f25fe70 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Fri, 23 Nov 2018 21:07:17 +0100 Subject: API/scalable: add operating point Dav1dSetting Refs #188, adds a corrosponding dav1d CLI option and skips not required temporal and spatial layers based on the selected operating point. --- include/dav1d/dav1d.h | 1 + src/internal.h | 2 ++ src/lib.c | 4 ++++ src/obu.c | 20 ++++++++++++++++++-- tools/dav1d_cli_parse.c | 7 +++++++ 5 files changed, 32 insertions(+), 2 deletions(-) diff --git a/include/dav1d/dav1d.h b/include/dav1d/dav1d.h index 5bf7a2b..64b9042 100644 --- a/include/dav1d/dav1d.h +++ b/include/dav1d/dav1d.h @@ -46,6 +46,7 @@ typedef struct Dav1dSettings { int n_tile_threads; Dav1dPicAllocator allocator; int apply_grain; + int operating_point; ///< select an operating point for scalable AV1 bitstreams (0 - 31) } Dav1dSettings; /** diff --git a/src/internal.h b/src/internal.h index 9149c12..5332200 100644 --- a/src/internal.h +++ b/src/internal.h @@ -116,6 +116,8 @@ struct Dav1dContext { Dav1dPicAllocator allocator; int apply_grain; + int operating_point; + unsigned operating_point_idc; }; struct Dav1dFrameContext { diff --git a/src/lib.c b/src/lib.c index 98aa2a1..22fab5e 100644 --- a/src/lib.c +++ b/src/lib.c @@ -62,6 +62,7 @@ void dav1d_default_settings(Dav1dSettings *const s) { s->allocator.cookie = NULL; s->allocator.alloc_picture_callback = default_picture_allocator; s->allocator.release_picture_callback = default_picture_release; + s->operating_point = 0; } int dav1d_open(Dav1dContext **const c_out, @@ -80,6 +81,8 @@ int dav1d_open(Dav1dContext **const c_out, -EINVAL); validate_input_or_ret(s->allocator.release_picture_callback != NULL, -EINVAL); + validate_input_or_ret(s->operating_point >= 0 && + s->operating_point <= 31, -EINVAL); Dav1dContext *const c = *c_out = dav1d_alloc_aligned(sizeof(*c), 32); if (!c) goto error; @@ -87,6 +90,7 @@ int dav1d_open(Dav1dContext **const c_out, c->allocator = s->allocator; c->apply_grain = s->apply_grain; + c->operating_point = s->operating_point; c->n_fc = s->n_frame_threads; c->fc = dav1d_alloc_aligned(sizeof(*c->fc) * s->n_frame_threads, 32); if (!c->fc) goto error; diff --git a/src/obu.c b/src/obu.c index 53469c4..b1091ec 100644 --- a/src/obu.c +++ b/src/obu.c @@ -126,6 +126,10 @@ static int parse_seq_hdr(Dav1dContext *const c, GetBits *const gb, op->initial_display_delay = dav1d_get_bits(gb, 4) + 1; } } + if (c->operating_point < hdr->num_operating_points) + c->operating_point_idc = hdr->operating_points[c->operating_point].idc; + else + c->operating_point_idc = hdr->operating_points[0].idc; #if DEBUG_SEQ_HDR printf("SEQHDR: post-operating-points: off=%ld\n", dav1d_get_bits_pos(gb) - init_bit_pos); @@ -1145,9 +1149,11 @@ int dav1d_parse_obus(Dav1dContext *const c, Dav1dData *const in) { const int has_extension = dav1d_get_bits(&gb, 1); const int has_length_field = dav1d_get_bits(&gb, 1); dav1d_get_bits(&gb, 1); // reserved + + int temporal_id, spatial_id; if (has_extension) { - dav1d_get_bits(&gb, 3); // temporal_layer_id - dav1d_get_bits(&gb, 2); // enhancement_layer_id + temporal_id = dav1d_get_bits(&gb, 3); + spatial_id = dav1d_get_bits(&gb, 2); dav1d_get_bits(&gb, 3); // reserved } @@ -1185,6 +1191,16 @@ int dav1d_parse_obus(Dav1dContext *const c, Dav1dData *const in) { // rest of the OBU. if (len > in->sz - init_byte_pos) goto error; + // skip obu not belonging to the selected temporal/spatial layer + if (type != OBU_SEQ_HDR && type != OBU_TD && + has_extension && c->operating_point_idc != 0) + { + const int in_temporal_layer = (c->operating_point_idc >> temporal_id) & 1; + const int in_spatial_layer = (c->operating_point_idc >> (spatial_id + 8)) & 1; + if (!in_temporal_layer || !in_spatial_layer) + return len + init_byte_pos; + } + switch (type) { case OBU_SEQ_HDR: { Av1SequenceHeader hdr, *const hdr_ptr = c->have_seq_hdr ? &hdr : &c->seq_hdr; diff --git a/tools/dav1d_cli_parse.c b/tools/dav1d_cli_parse.c index d60ebe8..affd75c 100644 --- a/tools/dav1d_cli_parse.c +++ b/tools/dav1d_cli_parse.c @@ -49,6 +49,7 @@ enum { ARG_TILE_THREADS, ARG_VERIFY, ARG_FILM_GRAIN, + ARG_OPPOINT, }; static const struct option long_opts[] = { @@ -64,6 +65,7 @@ static const struct option long_opts[] = { { "tilethreads", 1, NULL, ARG_TILE_THREADS }, { "verify", 1, NULL, ARG_VERIFY }, { "filmgrain", 1, NULL, ARG_FILM_GRAIN }, + { "oppoint", 1, NULL, ARG_OPPOINT }, { NULL, 0, NULL, 0 }, }; @@ -89,6 +91,7 @@ static void usage(const char *const app, const char *const reason, ...) { " --framethreads $num: number of frame threads (default: 1)\n" " --tilethreads $num: number of tile threads (default: 1)\n" " --filmgrain enable film grain application (default: 1, except if muxer is md5)\n" + " --oppoint $num: select an operating point for scalable AV1 (0 - 32)\n" " --verify $md5: verify decoded md5. implies --muxer md5, no output\n"); exit(1); } @@ -168,6 +171,10 @@ void parse(const int argc, char *const *const argv, !!parse_unsigned(optarg, ARG_FILM_GRAIN, argv[0]); grain_specified = 1; break; + case ARG_OPPOINT: + lib_settings->operating_point = + parse_unsigned(optarg, ARG_OPPOINT, argv[0]); + break; case 'v': fprintf(stderr, "%s\n", dav1d_version()); exit(0); -- cgit v1.2.3