shithub: dav1d

Download patch

ref: 0eafb6f5abc61a8c08cd27c649c935b40f25fe70
parent: 0e3c21979b5e2e6e7e49968b1377e38220c58774
author: Janne Grunau <janne-vlc@jannau.net>
date: Fri Nov 23 16:07:17 EST 2018

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.

--- a/include/dav1d/dav1d.h
+++ b/include/dav1d/dav1d.h
@@ -46,6 +46,7 @@
     int n_tile_threads;
     Dav1dPicAllocator allocator;
     int apply_grain;
+    int operating_point; ///< select an operating point for scalable AV1 bitstreams (0 - 31)
 } Dav1dSettings;
 
 /**
--- a/src/internal.h
+++ b/src/internal.h
@@ -116,6 +116,8 @@
 
     Dav1dPicAllocator allocator;
     int apply_grain;
+    int operating_point;
+    unsigned operating_point_idc;
 };
 
 struct Dav1dFrameContext {
--- a/src/lib.c
+++ b/src/lib.c
@@ -62,6 +62,7 @@
     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 @@
                           -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 @@
 
     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;
--- a/src/obu.c
+++ b/src/obu.c
@@ -126,6 +126,10 @@
                 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 @@
     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
     }
 
@@ -1184,6 +1190,16 @@
     // Make sure that there are enough bits left in the buffer for the
     // 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: {
--- a/tools/dav1d_cli_parse.c
+++ b/tools/dav1d_cli_parse.c
@@ -49,6 +49,7 @@
     ARG_TILE_THREADS,
     ARG_VERIFY,
     ARG_FILM_GRAIN,
+    ARG_OPPOINT,
 };
 
 static const struct option long_opts[] = {
@@ -64,6 +65,7 @@
     { "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 @@
             " --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);
 }
@@ -167,6 +170,10 @@
             lib_settings->apply_grain =
                 !!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());