shithub: dav1d

Download patch

ref: 2abc436e7ed8c5dadc24973a6891782fc105212e
parent: 791ec2199a6773eaef6abd6457b492fb40207422
author: Janne Grunau <janne-vlc@jannau.net>
date: Fri Feb 15 16:21:00 EST 2019

obu: ignore operating_parameter_info in new sequence check

The operating_parameter_info is allowed to change in a single sequence.
Reorder Dav1dSequenceHeader so the check for new sequence can still be
done with memcmp and pffsetof.

--- a/include/dav1d/headers.h
+++ b/include/dav1d/headers.h
@@ -215,9 +215,6 @@
         int idc;
         int tier;
         int decoder_model_param_present;
-        int decoder_buffer_delay;
-        int encoder_buffer_delay;
-        int low_delay_mode;
         int display_model_param_present;
     } operating_points[DAV1D_MAX_OPERATING_POINTS];
 
@@ -258,6 +255,18 @@
     int color_description_present;
     int separate_uv_delta_q;
     int film_grain_present;
+
+    // Dav1dSequenceHeaders of the same sequence are required to be
+    // bit-identical until this offset. See 7.5 "Ordering of OBUs":
+    //   Within a particular coded video sequence, the contents of
+    //   sequence_header_obu must be bit-identical each time the
+    //   sequence header appears except for the contents of
+    //   operating_parameters_info.
+    struct Dav1dSequenceHeaderOperatingParameterInfo {
+        int decoder_buffer_delay;
+        int encoder_buffer_delay;
+        int low_delay_mode;
+    } operating_parameter_info[DAV1D_MAX_OPERATING_POINTS];
 } Dav1dSequenceHeader;
 
 typedef struct Dav1dSegmentationData {
--- a/src/obu.c
+++ b/src/obu.c
@@ -112,6 +112,8 @@
         for (int i = 0; i < hdr->num_operating_points; i++) {
             struct Dav1dSequenceHeaderOperatingPoint *const op =
                 &hdr->operating_points[i];
+            struct Dav1dSequenceHeaderOperatingParameterInfo *const opi =
+                &hdr->operating_parameter_info[i];
             op->idc = dav1d_get_bits(gb, 12);
             op->major_level = 2 + dav1d_get_bits(gb, 3);
             op->minor_level = dav1d_get_bits(gb, 2);
@@ -119,11 +121,11 @@
             op->decoder_model_param_present =
                 hdr->decoder_model_info_present && dav1d_get_bits(gb, 1);
             if (op->decoder_model_param_present) {
-                op->decoder_buffer_delay =
+                opi->decoder_buffer_delay =
                     dav1d_get_bits(gb, hdr->encoder_decoder_buffer_delay_length);
-                op->encoder_buffer_delay =
+                opi->encoder_buffer_delay =
                     dav1d_get_bits(gb, hdr->encoder_decoder_buffer_delay_length);
-                op->low_delay_mode = dav1d_get_bits(gb, 1);
+                opi->low_delay_mode = dav1d_get_bits(gb, 1);
             }
             op->display_model_param_present =
                 hdr->display_model_info_present && dav1d_get_bits(gb, 1);
@@ -1241,7 +1243,9 @@
         // previous state. Free that state.
         if (!c->seq_hdr)
             c->frame_hdr = NULL;
-        else if (memcmp(seq_hdr, c->seq_hdr, sizeof(*seq_hdr))) {
+        // see 7.5, operating_parameter_info is allowed to change in
+        // sequence headers of a single sequence
+        else if (memcmp(seq_hdr, c->seq_hdr, offsetof(Dav1dSequenceHeader, operating_parameter_info))) {
             c->frame_hdr = NULL;
             c->mastering_display = NULL;
             c->content_light = NULL;