Move some vars from AV1_COMMON to SequenceHeader

These are part of the sequence header OBU and so belong in the
SequenceHeader struct.

Related:
- Use SequenceHeader / other small structs in function params when we
can, instead of passing whole AV1_COMMON struct.
- Update to are_seq_headers_consistent() function.
- Remove aom_op_timing_info_t struct that had a single member to
reduce indirection
- Documentation for these vars.

BUG=aomedia:2610

Change-Id: I33f1c4492eabd67d9f4dde54e482cecce38db9d3
diff --git a/av1/common/av1_common_int.h b/av1/common/av1_common_int.h
index 942edf2..a078149 100644
--- a/av1/common/av1_common_int.h
+++ b/av1/common/av1_common_int.h
@@ -223,6 +223,8 @@
 // Note: All syntax elements of sequence_header_obu that need to be
 // bit-identical across multiple sequence headers must be part of this struct,
 // so that consistency is checked by are_seq_headers_consistent() function.
+// One exception is the last member 'op_params' that is ignored by
+// are_seq_headers_consistent() function.
 typedef struct SequenceHeader {
   int num_bits_width;
   int num_bits_height;
@@ -261,15 +263,6 @@
   uint8_t enable_restoration;          // To turn on/off loop restoration
   BITSTREAM_PROFILE profile;
 
-  // Operating point info.
-  int operating_points_cnt_minus_1;
-  int operating_point_idc[MAX_NUM_OPERATING_POINTS];
-  uint8_t display_model_info_present_flag;
-  uint8_t decoder_model_info_present_flag;
-  AV1_LEVEL seq_level_idx[MAX_NUM_OPERATING_POINTS];
-  uint8_t tier[MAX_NUM_OPERATING_POINTS];  // seq_tier in the spec. One bit: 0
-                                           // or 1.
-
   // Color config.
   aom_bit_depth_t bit_depth;  // AOM_BITS_8 in profile 0 or 1,
                               // AOM_BITS_10 or AOM_BITS_12 in profile 2 or 3.
@@ -284,6 +277,22 @@
   aom_chroma_sample_position_t chroma_sample_position;
   uint8_t separate_uv_delta_q;
   uint8_t film_grain_params_present;
+
+  // Operating point info.
+  int operating_points_cnt_minus_1;
+  int operating_point_idc[MAX_NUM_OPERATING_POINTS];
+  int timing_info_present;
+  aom_timing_info_t timing_info;
+  uint8_t decoder_model_info_present_flag;
+  aom_dec_model_info_t decoder_model_info;
+  uint8_t display_model_info_present_flag;
+  AV1_LEVEL seq_level_idx[MAX_NUM_OPERATING_POINTS];
+  uint8_t tier[MAX_NUM_OPERATING_POINTS];  // seq_tier in spec. One bit: 0 or 1.
+
+  // IMPORTANT: the op_params member must be at the end of the struct so that
+  // are_seq_headers_consistent() can be implemented with a memcmp() call.
+  // TODO(urvang): We probably don't need the +1 here.
+  aom_dec_model_op_parameters_t op_params[MAX_NUM_OPERATING_POINTS + 1];
 } SequenceHeader;
 
 typedef struct {
@@ -520,12 +529,16 @@
   // Note: The numerator is fixed to be SCALE_NUMERATOR.
   uint8_t superres_scale_denominator;
 
-  int timing_info_present;
-  aom_timing_info_t timing_info;
-  int buffer_removal_time_present;
-  aom_dec_model_info_t buffer_model;
-  aom_dec_model_op_parameters_t op_params[MAX_NUM_OPERATING_POINTS + 1];
-  aom_op_timing_info_t op_frame_timing[MAX_NUM_OPERATING_POINTS + 1];
+  // If true, buffer removal times are present.
+  bool buffer_removal_time_present;
+  // buffer_removal_times[op_num] specifies the frame removal time in units of
+  // DecCT clock ticks counted from the removal time of the last random access
+  // point for operating point op_num.
+  // TODO(urvang): We probably don't need the +1 here.
+  uint32_t buffer_removal_times[MAX_NUM_OPERATING_POINTS + 1];
+  // Presentation time of the frame in clock ticks DispCT counted from the
+  // removal time of the last random access point for the operating point that
+  // is being decoded.
   uint32_t frame_presentation_time;
 
   // Buffer where previous frame is stored.
diff --git a/av1/common/timing.h b/av1/common/timing.h
index 9aca58f..9192124 100644
--- a/av1/common/timing.h
+++ b/av1/common/timing.h
@@ -42,10 +42,6 @@
   int initial_display_delay;
 } aom_dec_model_op_parameters_t;
 
-typedef struct aom_op_timing_info_t {
-  uint32_t buffer_removal_time;
-} aom_op_timing_info_t;
-
 void av1_set_aom_dec_model_info(aom_dec_model_info_t *decoder_model);
 
 void av1_set_dec_model_op_parameters(aom_dec_model_op_parameters_t *op_params);
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c
index 3634dec..84fda91 100644
--- a/av1/decoder/decodeframe.c
+++ b/av1/decoder/decodeframe.c
@@ -4327,64 +4327,59 @@
   seq_params->separate_uv_delta_q = aom_rb_read_bit(rb);
 }
 
-void av1_read_timing_info_header(AV1_COMMON *cm,
+void av1_read_timing_info_header(aom_timing_info_t *timing_info,
+                                 struct aom_internal_error_info *error,
                                  struct aom_read_bit_buffer *rb) {
-  cm->timing_info.num_units_in_display_tick = aom_rb_read_unsigned_literal(
-      rb, 32);  // Number of units in a display tick
-  cm->timing_info.time_scale =
-      aom_rb_read_unsigned_literal(rb, 32);  // Time scale
-  if (cm->timing_info.num_units_in_display_tick == 0 ||
-      cm->timing_info.time_scale == 0) {
+  timing_info->num_units_in_display_tick =
+      aom_rb_read_unsigned_literal(rb,
+                                   32);  // Number of units in a display tick
+  timing_info->time_scale = aom_rb_read_unsigned_literal(rb, 32);  // Time scale
+  if (timing_info->num_units_in_display_tick == 0 ||
+      timing_info->time_scale == 0) {
     aom_internal_error(
-        &cm->error, AOM_CODEC_UNSUP_BITSTREAM,
+        error, AOM_CODEC_UNSUP_BITSTREAM,
         "num_units_in_display_tick and time_scale must be greater than 0.");
   }
-  cm->timing_info.equal_picture_interval =
+  timing_info->equal_picture_interval =
       aom_rb_read_bit(rb);  // Equal picture interval bit
-  if (cm->timing_info.equal_picture_interval) {
+  if (timing_info->equal_picture_interval) {
     const uint32_t num_ticks_per_picture_minus_1 = aom_rb_read_uvlc(rb);
     if (num_ticks_per_picture_minus_1 == UINT32_MAX) {
       aom_internal_error(
-          &cm->error, AOM_CODEC_UNSUP_BITSTREAM,
+          error, AOM_CODEC_UNSUP_BITSTREAM,
           "num_ticks_per_picture_minus_1 cannot be (1 << 32) − 1.");
     }
-    cm->timing_info.num_ticks_per_picture = num_ticks_per_picture_minus_1 + 1;
+    timing_info->num_ticks_per_picture = num_ticks_per_picture_minus_1 + 1;
   }
 }
 
-void av1_read_decoder_model_info(AV1_COMMON *cm,
+void av1_read_decoder_model_info(aom_dec_model_info_t *decoder_model_info,
                                  struct aom_read_bit_buffer *rb) {
-  cm->buffer_model.encoder_decoder_buffer_delay_length =
+  decoder_model_info->encoder_decoder_buffer_delay_length =
       aom_rb_read_literal(rb, 5) + 1;
-  cm->buffer_model.num_units_in_decoding_tick = aom_rb_read_unsigned_literal(
-      rb, 32);  // Number of units in a decoding tick
-  cm->buffer_model.buffer_removal_time_length = aom_rb_read_literal(rb, 5) + 1;
-  cm->buffer_model.frame_presentation_time_length =
+  decoder_model_info->num_units_in_decoding_tick =
+      aom_rb_read_unsigned_literal(rb,
+                                   32);  // Number of units in a decoding tick
+  decoder_model_info->buffer_removal_time_length =
+      aom_rb_read_literal(rb, 5) + 1;
+  decoder_model_info->frame_presentation_time_length =
       aom_rb_read_literal(rb, 5) + 1;
 }
 
-void av1_read_op_parameters_info(AV1_COMMON *const cm,
-                                 struct aom_read_bit_buffer *rb, int op_num) {
-  // The cm->op_params array has MAX_NUM_OPERATING_POINTS + 1 elements.
-  if (op_num > MAX_NUM_OPERATING_POINTS) {
-    aom_internal_error(&cm->error, AOM_CODEC_UNSUP_BITSTREAM,
-                       "AV1 does not support %d decoder model operating points",
-                       op_num + 1);
-  }
-
-  cm->op_params[op_num].decoder_buffer_delay = aom_rb_read_unsigned_literal(
-      rb, cm->buffer_model.encoder_decoder_buffer_delay_length);
-
-  cm->op_params[op_num].encoder_buffer_delay = aom_rb_read_unsigned_literal(
-      rb, cm->buffer_model.encoder_decoder_buffer_delay_length);
-
-  cm->op_params[op_num].low_delay_mode_flag = aom_rb_read_bit(rb);
+void av1_read_op_parameters_info(aom_dec_model_op_parameters_t *op_params,
+                                 int buffer_delay_length,
+                                 struct aom_read_bit_buffer *rb) {
+  op_params->decoder_buffer_delay =
+      aom_rb_read_unsigned_literal(rb, buffer_delay_length);
+  op_params->encoder_buffer_delay =
+      aom_rb_read_unsigned_literal(rb, buffer_delay_length);
+  op_params->low_delay_mode_flag = aom_rb_read_bit(rb);
 }
 
 static AOM_INLINE void read_temporal_point_info(
     AV1_COMMON *const cm, struct aom_read_bit_buffer *rb) {
   cm->frame_presentation_time = aom_rb_read_unsigned_literal(
-      rb, cm->buffer_model.frame_presentation_time_length);
+      rb, cm->seq_params.decoder_model_info.frame_presentation_time_length);
 }
 
 void av1_read_sequence_header(AV1_COMMON *cm, struct aom_read_bit_buffer *rb,
@@ -4703,7 +4698,7 @@
                            "Buffer does not contain a decoded frame");
       }
       if (seq_params->decoder_model_info_present_flag &&
-          cm->timing_info.equal_picture_interval == 0) {
+          seq_params->timing_info.equal_picture_interval == 0) {
         read_temporal_point_info(cm, rb);
       }
       if (seq_params->frame_id_numbers_present_flag) {
@@ -4781,7 +4776,7 @@
     cm->showable_frame = current_frame->frame_type != KEY_FRAME;
     if (cm->show_frame) {
       if (seq_params->decoder_model_info_present_flag &&
-          cm->timing_info.equal_picture_interval == 0)
+          seq_params->timing_info.equal_picture_interval == 0)
         read_temporal_point_info(cm, rb);
     } else {
       // See if this frame can be used as show_existing_frame in future
@@ -4882,7 +4877,7 @@
     if (cm->buffer_removal_time_present) {
       for (int op_num = 0;
            op_num < seq_params->operating_points_cnt_minus_1 + 1; op_num++) {
-        if (cm->op_params[op_num].decoder_model_param_present_flag) {
+        if (seq_params->op_params[op_num].decoder_model_param_present_flag) {
           if ((((seq_params->operating_point_idc[op_num] >>
                  cm->temporal_layer_id) &
                 0x1) &&
@@ -4890,14 +4885,13 @@
                  (cm->spatial_layer_id + 8)) &
                 0x1)) ||
               seq_params->operating_point_idc[op_num] == 0) {
-            cm->op_frame_timing[op_num].buffer_removal_time =
-                aom_rb_read_unsigned_literal(
-                    rb, cm->buffer_model.buffer_removal_time_length);
+            cm->buffer_removal_times[op_num] = aom_rb_read_unsigned_literal(
+                rb, seq_params->decoder_model_info.buffer_removal_time_length);
           } else {
-            cm->op_frame_timing[op_num].buffer_removal_time = 0;
+            cm->buffer_removal_times[op_num] = 0;
           }
         } else {
-          cm->op_frame_timing[op_num].buffer_removal_time = 0;
+          cm->buffer_removal_times[op_num] = 0;
         }
       }
     }
diff --git a/av1/decoder/decodeframe.h b/av1/decoder/decodeframe.h
index 13b9696..95b3c9f 100644
--- a/av1/decoder/decodeframe.h
+++ b/av1/decoder/decodeframe.h
@@ -56,19 +56,21 @@
                            struct aom_internal_error_info *error_info);
 
 // Implements the timing_info() function in the spec. Reports errors by calling
-// rb->error_handler().
-void av1_read_timing_info_header(AV1_COMMON *cm,
+// rb->error_handler() or aom_internal_error().
+void av1_read_timing_info_header(aom_timing_info_t *timing_info,
+                                 struct aom_internal_error_info *error,
                                  struct aom_read_bit_buffer *rb);
 
 // Implements the decoder_model_info() function in the spec. Reports errors by
 // calling rb->error_handler().
-void av1_read_decoder_model_info(AV1_COMMON *cm,
+void av1_read_decoder_model_info(aom_dec_model_info_t *decoder_model_info,
                                  struct aom_read_bit_buffer *rb);
 
 // Implements the operating_parameters_info() function in the spec. Reports
-// errors by calling rb->error_handler() or aom_internal_error().
-void av1_read_op_parameters_info(AV1_COMMON *const cm,
-                                 struct aom_read_bit_buffer *rb, int op_num);
+// errors by calling rb->error_handler().
+void av1_read_op_parameters_info(aom_dec_model_op_parameters_t *op_params,
+                                 int buffer_delay_length,
+                                 struct aom_read_bit_buffer *rb);
 
 struct aom_read_bit_buffer *av1_init_read_bit_buffer(
     struct AV1Decoder *pbi, struct aom_read_bit_buffer *rb, const uint8_t *data,
diff --git a/av1/decoder/obu.c b/av1/decoder/obu.c
index f8f944d..791e596 100644
--- a/av1/decoder/obu.c
+++ b/av1/decoder/obu.c
@@ -87,10 +87,14 @@
 }
 
 // Returns whether two sequence headers are consistent with each other.
-// TODO(huisu,wtc@google.com): make sure the code matches the spec exactly.
+// Note that the 'op_params' field is not compared per Section 7.5 in the spec:
+//   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.
 static int are_seq_headers_consistent(const SequenceHeader *seq_params_old,
                                       const SequenceHeader *seq_params_new) {
-  return !memcmp(seq_params_old, seq_params_new, sizeof(SequenceHeader));
+  return !memcmp(seq_params_old, seq_params_new,
+                 offsetof(SequenceHeader, op_params));
 }
 
 // On success, sets pbi->sequence_header_ready to 1 and returns the number of
@@ -125,7 +129,7 @@
   }
 
   if (seq_params->reduced_still_picture_hdr) {
-    cm->timing_info_present = 0;
+    seq_params->timing_info_present = 0;
     seq_params->decoder_model_info_present_flag = 0;
     seq_params->display_model_info_present_flag = 0;
     seq_params->operating_points_cnt_minus_1 = 0;
@@ -135,16 +139,16 @@
       return 0;
     }
     seq_params->tier[0] = 0;
-    cm->op_params[0].decoder_model_param_present_flag = 0;
-    cm->op_params[0].display_model_param_present_flag = 0;
+    seq_params->op_params[0].decoder_model_param_present_flag = 0;
+    seq_params->op_params[0].display_model_param_present_flag = 0;
   } else {
-    cm->timing_info_present = aom_rb_read_bit(rb);  // timing_info_present_flag
-    if (cm->timing_info_present) {
-      av1_read_timing_info_header(cm, rb);
+    seq_params->timing_info_present = aom_rb_read_bit(rb);
+    if (seq_params->timing_info_present) {
+      av1_read_timing_info_header(&seq_params->timing_info, &cm->error, rb);
 
       seq_params->decoder_model_info_present_flag = aom_rb_read_bit(rb);
       if (seq_params->decoder_model_info_present_flag)
-        av1_read_decoder_model_info(cm, rb);
+        av1_read_decoder_model_info(&seq_params->decoder_model_info, rb);
     } else {
       seq_params->decoder_model_info_present_flag = 0;
     }
@@ -165,51 +169,57 @@
       else
         seq_params->tier[i] = 0;
       if (seq_params->decoder_model_info_present_flag) {
-        cm->op_params[i].decoder_model_param_present_flag = aom_rb_read_bit(rb);
-        if (cm->op_params[i].decoder_model_param_present_flag)
-          av1_read_op_parameters_info(cm, rb, i);
+        seq_params->op_params[i].decoder_model_param_present_flag =
+            aom_rb_read_bit(rb);
+        if (seq_params->op_params[i].decoder_model_param_present_flag)
+          av1_read_op_parameters_info(&seq_params->op_params[i],
+                                      seq_params->decoder_model_info
+                                          .encoder_decoder_buffer_delay_length,
+                                      rb);
       } else {
-        cm->op_params[i].decoder_model_param_present_flag = 0;
+        seq_params->op_params[i].decoder_model_param_present_flag = 0;
       }
-      if (cm->timing_info_present &&
-          (cm->timing_info.equal_picture_interval ||
-           cm->op_params[i].decoder_model_param_present_flag)) {
-        cm->op_params[i].bitrate = av1_max_level_bitrate(
+      if (seq_params->timing_info_present &&
+          (seq_params->timing_info.equal_picture_interval ||
+           seq_params->op_params[i].decoder_model_param_present_flag)) {
+        seq_params->op_params[i].bitrate = av1_max_level_bitrate(
             seq_params->profile, seq_params->seq_level_idx[i],
             seq_params->tier[i]);
         // Level with seq_level_idx = 31 returns a high "dummy" bitrate to pass
         // the check
-        if (cm->op_params[i].bitrate == 0)
+        if (seq_params->op_params[i].bitrate == 0)
           aom_internal_error(&cm->error, AOM_CODEC_UNSUP_BITSTREAM,
                              "AV1 does not support this combination of "
                              "profile, level, and tier.");
         // Buffer size in bits/s is bitrate in bits/s * 1 s
-        cm->op_params[i].buffer_size = cm->op_params[i].bitrate;
+        seq_params->op_params[i].buffer_size = seq_params->op_params[i].bitrate;
       }
-      if (cm->timing_info_present && cm->timing_info.equal_picture_interval &&
-          !cm->op_params[i].decoder_model_param_present_flag) {
+      if (seq_params->timing_info_present &&
+          seq_params->timing_info.equal_picture_interval &&
+          !seq_params->op_params[i].decoder_model_param_present_flag) {
         // When the decoder_model_parameters are not sent for this op, set
         // the default ones that can be used with the resource availability mode
-        cm->op_params[i].decoder_buffer_delay = 70000;
-        cm->op_params[i].encoder_buffer_delay = 20000;
-        cm->op_params[i].low_delay_mode_flag = 0;
+        seq_params->op_params[i].decoder_buffer_delay = 70000;
+        seq_params->op_params[i].encoder_buffer_delay = 20000;
+        seq_params->op_params[i].low_delay_mode_flag = 0;
       }
 
       if (seq_params->display_model_info_present_flag) {
-        cm->op_params[i].display_model_param_present_flag = aom_rb_read_bit(rb);
-        if (cm->op_params[i].display_model_param_present_flag) {
-          cm->op_params[i].initial_display_delay =
+        seq_params->op_params[i].display_model_param_present_flag =
+            aom_rb_read_bit(rb);
+        if (seq_params->op_params[i].display_model_param_present_flag) {
+          seq_params->op_params[i].initial_display_delay =
               aom_rb_read_literal(rb, 4) + 1;
-          if (cm->op_params[i].initial_display_delay > 10)
+          if (seq_params->op_params[i].initial_display_delay > 10)
             aom_internal_error(
                 &cm->error, AOM_CODEC_UNSUP_BITSTREAM,
                 "AV1 does not support more than 10 decoded frames delay");
         } else {
-          cm->op_params[i].initial_display_delay = 10;
+          seq_params->op_params[i].initial_display_delay = 10;
         }
       } else {
-        cm->op_params[i].display_model_param_present_flag = 0;
-        cm->op_params[i].initial_display_delay = 10;
+        seq_params->op_params[i].display_model_param_present_flag = 0;
+        seq_params->op_params[i].initial_display_delay = 10;
       }
     }
   }
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index 324ce4c..24d42e7 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -2425,61 +2425,44 @@
 }
 
 static AOM_INLINE void write_timing_info_header(
-    AV1_COMMON *const cm, struct aom_write_bit_buffer *wb) {
-  aom_wb_write_unsigned_literal(wb, cm->timing_info.num_units_in_display_tick,
-                                32);  // Number of units in tick
-  aom_wb_write_unsigned_literal(wb, cm->timing_info.time_scale,
-                                32);  // Time scale
-  aom_wb_write_bit(
-      wb,
-      cm->timing_info.equal_picture_interval);  // Equal picture interval bit
-  if (cm->timing_info.equal_picture_interval) {
-    aom_wb_write_uvlc(
-        wb,
-        cm->timing_info.num_ticks_per_picture - 1);  // ticks per picture
+    const aom_timing_info_t *const timing_info,
+    struct aom_write_bit_buffer *wb) {
+  aom_wb_write_unsigned_literal(wb, timing_info->num_units_in_display_tick, 32);
+  aom_wb_write_unsigned_literal(wb, timing_info->time_scale, 32);
+  aom_wb_write_bit(wb, timing_info->equal_picture_interval);
+  if (timing_info->equal_picture_interval) {
+    aom_wb_write_uvlc(wb, timing_info->num_ticks_per_picture - 1);
   }
 }
 
 static AOM_INLINE void write_decoder_model_info(
-    AV1_COMMON *const cm, struct aom_write_bit_buffer *wb) {
+    const aom_dec_model_info_t *const decoder_model_info,
+    struct aom_write_bit_buffer *wb) {
   aom_wb_write_literal(
-      wb, cm->buffer_model.encoder_decoder_buffer_delay_length - 1, 5);
-  aom_wb_write_unsigned_literal(wb, cm->buffer_model.num_units_in_decoding_tick,
-                                32);  // Number of units in decoding tick
-  aom_wb_write_literal(wb, cm->buffer_model.buffer_removal_time_length - 1, 5);
-  aom_wb_write_literal(wb, cm->buffer_model.frame_presentation_time_length - 1,
+      wb, decoder_model_info->encoder_decoder_buffer_delay_length - 1, 5);
+  aom_wb_write_unsigned_literal(
+      wb, decoder_model_info->num_units_in_decoding_tick, 32);
+  aom_wb_write_literal(wb, decoder_model_info->buffer_removal_time_length - 1,
                        5);
+  aom_wb_write_literal(
+      wb, decoder_model_info->frame_presentation_time_length - 1, 5);
 }
 
 static AOM_INLINE void write_dec_model_op_parameters(
-    AV1_COMMON *const cm, struct aom_write_bit_buffer *wb, int op_num) {
-  if (op_num > MAX_NUM_OPERATING_POINTS)
-    aom_internal_error(
-        &cm->error, AOM_CODEC_UNSUP_BITSTREAM,
-        "Encoder does not support %d decoder model operating points", op_num);
-
-  //  aom_wb_write_bit(wb, cm->op_params[op_num].has_parameters);
-  //  if (!cm->op_params[op_num].has_parameters) return;
-
-  aom_wb_write_unsigned_literal(
-      wb, cm->op_params[op_num].decoder_buffer_delay,
-      cm->buffer_model.encoder_decoder_buffer_delay_length);
-
-  aom_wb_write_unsigned_literal(
-      wb, cm->op_params[op_num].encoder_buffer_delay,
-      cm->buffer_model.encoder_decoder_buffer_delay_length);
-
-  aom_wb_write_bit(wb, cm->op_params[op_num].low_delay_mode_flag);
-
-  cm->op_frame_timing[op_num].buffer_removal_time =
-      0;  // reset the decoded frame counter
+    const aom_dec_model_op_parameters_t *op_params, int buffer_delay_length,
+    struct aom_write_bit_buffer *wb) {
+  aom_wb_write_unsigned_literal(wb, op_params->decoder_buffer_delay,
+                                buffer_delay_length);
+  aom_wb_write_unsigned_literal(wb, op_params->encoder_buffer_delay,
+                                buffer_delay_length);
+  aom_wb_write_bit(wb, op_params->low_delay_mode_flag);
 }
 
 static AOM_INLINE void write_tu_pts_info(AV1_COMMON *const cm,
                                          struct aom_write_bit_buffer *wb) {
   aom_wb_write_unsigned_literal(
       wb, cm->frame_presentation_time,
-      cm->buffer_model.frame_presentation_time_length);
+      cm->seq_params.decoder_model_info.frame_presentation_time_length);
 }
 
 static AOM_INLINE void write_film_grain_params(
@@ -2844,7 +2827,7 @@
       aom_wb_write_literal(wb, cpi->existing_fb_idx_to_show, 3);
 
       if (seq_params->decoder_model_info_present_flag &&
-          cm->timing_info.equal_picture_interval == 0) {
+          seq_params->timing_info.equal_picture_interval == 0) {
         write_tu_pts_info(cm, wb);
       }
       if (seq_params->frame_id_numbers_present_flag) {
@@ -2862,7 +2845,7 @@
     aom_wb_write_bit(wb, cm->show_frame);
     if (cm->show_frame) {
       if (seq_params->decoder_model_info_present_flag &&
-          cm->timing_info.equal_picture_interval == 0)
+          seq_params->timing_info.equal_picture_interval == 0)
         write_tu_pts_info(cm, wb);
     } else {
       aom_wb_write_bit(wb, cm->showable_frame);
@@ -2932,7 +2915,7 @@
     if (cm->buffer_removal_time_present) {
       for (int op_num = 0;
            op_num < seq_params->operating_points_cnt_minus_1 + 1; op_num++) {
-        if (cm->op_params[op_num].decoder_model_param_present_flag) {
+        if (seq_params->op_params[op_num].decoder_model_param_present_flag) {
           if (((seq_params->operating_point_idc[op_num] >>
                 cm->temporal_layer_id) &
                    0x1 &&
@@ -2941,10 +2924,10 @@
                    0x1) ||
               seq_params->operating_point_idc[op_num] == 0) {
             aom_wb_write_unsigned_literal(
-                wb, cm->op_frame_timing[op_num].buffer_removal_time,
-                cm->buffer_model.buffer_removal_time_length);
-            cm->op_frame_timing[op_num].buffer_removal_time++;
-            if (cm->op_frame_timing[op_num].buffer_removal_time == 0) {
+                wb, cm->buffer_removal_times[op_num],
+                seq_params->decoder_model_info.buffer_removal_time_length);
+            cm->buffer_removal_times[op_num]++;
+            if (cm->buffer_removal_times[op_num] == 0) {
               aom_internal_error(&cm->error, AOM_CODEC_UNSUP_BITSTREAM,
                                  "buffer_removal_time overflowed");
             }
@@ -3331,68 +3314,74 @@
   aom_wb_write_literal(wb, seq_level_idx, LEVEL_BITS);
 }
 
-uint32_t av1_write_sequence_header_obu(AV1_COMP *cpi, uint8_t *const dst) {
-  AV1_COMMON *const cm = &cpi->common;
+uint32_t av1_write_sequence_header_obu(const SequenceHeader *seq_params,
+                                       uint8_t *const dst) {
   struct aom_write_bit_buffer wb = { dst, 0 };
   uint32_t size = 0;
 
-  write_profile(cm->seq_params.profile, &wb);
+  write_profile(seq_params->profile, &wb);
 
   // Still picture or not
-  aom_wb_write_bit(&wb, cm->seq_params.still_picture);
-  assert(IMPLIES(!cm->seq_params.still_picture,
-                 !cm->seq_params.reduced_still_picture_hdr));
+  aom_wb_write_bit(&wb, seq_params->still_picture);
+  assert(IMPLIES(!seq_params->still_picture,
+                 !seq_params->reduced_still_picture_hdr));
   // whether to use reduced still picture header
-  aom_wb_write_bit(&wb, cm->seq_params.reduced_still_picture_hdr);
+  aom_wb_write_bit(&wb, seq_params->reduced_still_picture_hdr);
 
-  if (cm->seq_params.reduced_still_picture_hdr) {
-    assert(cm->timing_info_present == 0);
-    assert(cm->seq_params.decoder_model_info_present_flag == 0);
-    assert(cm->seq_params.display_model_info_present_flag == 0);
-    write_bitstream_level(cm->seq_params.seq_level_idx[0], &wb);
+  if (seq_params->reduced_still_picture_hdr) {
+    assert(seq_params->timing_info_present == 0);
+    assert(seq_params->decoder_model_info_present_flag == 0);
+    assert(seq_params->display_model_info_present_flag == 0);
+    write_bitstream_level(seq_params->seq_level_idx[0], &wb);
   } else {
-    aom_wb_write_bit(&wb, cm->timing_info_present);  // timing info present flag
+    aom_wb_write_bit(
+        &wb, seq_params->timing_info_present);  // timing info present flag
 
-    if (cm->timing_info_present) {
+    if (seq_params->timing_info_present) {
       // timing_info
-      write_timing_info_header(cm, &wb);
-      aom_wb_write_bit(&wb, cm->seq_params.decoder_model_info_present_flag);
-      if (cm->seq_params.decoder_model_info_present_flag) {
-        write_decoder_model_info(cm, &wb);
+      write_timing_info_header(&seq_params->timing_info, &wb);
+      aom_wb_write_bit(&wb, seq_params->decoder_model_info_present_flag);
+      if (seq_params->decoder_model_info_present_flag) {
+        write_decoder_model_info(&seq_params->decoder_model_info, &wb);
       }
     }
-    aom_wb_write_bit(&wb, cm->seq_params.display_model_info_present_flag);
-    aom_wb_write_literal(&wb, cm->seq_params.operating_points_cnt_minus_1,
+    aom_wb_write_bit(&wb, seq_params->display_model_info_present_flag);
+    aom_wb_write_literal(&wb, seq_params->operating_points_cnt_minus_1,
                          OP_POINTS_CNT_MINUS_1_BITS);
     int i;
-    for (i = 0; i < cm->seq_params.operating_points_cnt_minus_1 + 1; i++) {
-      aom_wb_write_literal(&wb, cm->seq_params.operating_point_idc[i],
+    for (i = 0; i < seq_params->operating_points_cnt_minus_1 + 1; i++) {
+      aom_wb_write_literal(&wb, seq_params->operating_point_idc[i],
                            OP_POINTS_IDC_BITS);
-      write_bitstream_level(cm->seq_params.seq_level_idx[i], &wb);
-      if (cm->seq_params.seq_level_idx[i] >= SEQ_LEVEL_4_0)
-        aom_wb_write_bit(&wb, cm->seq_params.tier[i]);
-      if (cm->seq_params.decoder_model_info_present_flag) {
-        aom_wb_write_bit(&wb,
-                         cm->op_params[i].decoder_model_param_present_flag);
-        if (cm->op_params[i].decoder_model_param_present_flag)
-          write_dec_model_op_parameters(cm, &wb, i);
+      write_bitstream_level(seq_params->seq_level_idx[i], &wb);
+      if (seq_params->seq_level_idx[i] >= SEQ_LEVEL_4_0)
+        aom_wb_write_bit(&wb, seq_params->tier[i]);
+      if (seq_params->decoder_model_info_present_flag) {
+        aom_wb_write_bit(
+            &wb, seq_params->op_params[i].decoder_model_param_present_flag);
+        if (seq_params->op_params[i].decoder_model_param_present_flag) {
+          write_dec_model_op_parameters(
+              &seq_params->op_params[i],
+              seq_params->decoder_model_info
+                  .encoder_decoder_buffer_delay_length,
+              &wb);
+        }
       }
-      if (cm->seq_params.display_model_info_present_flag) {
-        aom_wb_write_bit(&wb,
-                         cm->op_params[i].display_model_param_present_flag);
-        if (cm->op_params[i].display_model_param_present_flag) {
-          assert(cm->op_params[i].initial_display_delay <= 10);
-          aom_wb_write_literal(&wb, cm->op_params[i].initial_display_delay - 1,
-                               4);
+      if (seq_params->display_model_info_present_flag) {
+        aom_wb_write_bit(
+            &wb, seq_params->op_params[i].display_model_param_present_flag);
+        if (seq_params->op_params[i].display_model_param_present_flag) {
+          assert(seq_params->op_params[i].initial_display_delay <= 10);
+          aom_wb_write_literal(
+              &wb, seq_params->op_params[i].initial_display_delay - 1, 4);
         }
       }
     }
   }
-  write_sequence_header(&cm->seq_params, &wb);
+  write_sequence_header(seq_params, &wb);
 
-  write_color_config(&cm->seq_params, &wb);
+  write_color_config(seq_params, &wb);
 
-  aom_wb_write_bit(&wb, cm->seq_params.film_grain_params_present);
+  aom_wb_write_bit(&wb, seq_params->film_grain_params_present);
 
   add_trailing_bits(&wb);
 
@@ -3858,7 +3847,7 @@
     obu_header_size = av1_write_obu_header(cpi, OBU_SEQUENCE_HEADER, 0, data);
 
     obu_payload_size =
-        av1_write_sequence_header_obu(cpi, data + obu_header_size);
+        av1_write_sequence_header_obu(&cm->seq_params, data + obu_header_size);
     const size_t length_field_size =
         obu_memmove(obu_header_size, obu_payload_size, data);
     if (av1_write_uleb_obu_size(obu_header_size, obu_payload_size, data) !=
diff --git a/av1/encoder/bitstream.h b/av1/encoder/bitstream.h
index 24530ce..51e0059 100644
--- a/av1/encoder/bitstream.h
+++ b/av1/encoder/bitstream.h
@@ -23,7 +23,8 @@
 // Writes only the OBU Sequence Header payload, and returns the size of the
 // payload written to 'dst'. This function does not write the OBU header, the
 // optional extension, or the OBU size to 'dst'.
-uint32_t av1_write_sequence_header_obu(AV1_COMP *cpi, uint8_t *const dst);
+uint32_t av1_write_sequence_header_obu(const SequenceHeader *seq_params,
+                                       uint8_t *const dst);
 
 // Writes the OBU header byte, and the OBU header extension byte when
 // 'obu_extension' is non-zero. Returns number of bytes written to 'dst'.
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 22b87ee..e67b8ca 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -1285,20 +1285,21 @@
     level = SEQ_LEVEL_6_2;
   }
 
+  SequenceHeader *const seq_params = &cm->seq_params;
   for (int i = 0; i < MAX_NUM_OPERATING_POINTS; ++i) {
     seq->seq_level_idx[i] = level;
     // Set the maximum parameters for bitrate and buffer size for this profile,
     // level, and tier
-    cm->op_params[i].bitrate = av1_max_level_bitrate(
+    seq_params->op_params[i].bitrate = av1_max_level_bitrate(
         cm->seq_params.profile, seq->seq_level_idx[i], seq->tier[i]);
     // Level with seq_level_idx = 31 returns a high "dummy" bitrate to pass the
     // check
-    if (cm->op_params[i].bitrate == 0)
+    if (seq_params->op_params[i].bitrate == 0)
       aom_internal_error(
           &cm->error, AOM_CODEC_UNSUP_BITSTREAM,
           "AV1 does not support this combination of profile, level, and tier.");
     // Buffer size in bits/s is bitrate in bits/s * 1 s
-    cm->op_params[i].buffer_size = cm->op_params[i].bitrate;
+    seq_params->op_params[i].buffer_size = seq_params->op_params[i].bitrate;
   }
 }
 
@@ -1379,78 +1380,79 @@
 
 static void init_config(struct AV1_COMP *cpi, AV1EncoderConfig *oxcf) {
   AV1_COMMON *const cm = &cpi->common;
+  SequenceHeader *const seq_params = &cm->seq_params;
 
   cpi->oxcf = *oxcf;
   cpi->framerate = oxcf->init_framerate;
 
-  cm->seq_params.profile = oxcf->profile;
-  cm->seq_params.bit_depth = oxcf->bit_depth;
-  cm->seq_params.use_highbitdepth = oxcf->use_highbitdepth;
-  cm->seq_params.color_primaries = oxcf->color_primaries;
-  cm->seq_params.transfer_characteristics = oxcf->transfer_characteristics;
-  cm->seq_params.matrix_coefficients = oxcf->matrix_coefficients;
-  cm->seq_params.monochrome = oxcf->monochrome;
-  cm->seq_params.chroma_sample_position = oxcf->chroma_sample_position;
-  cm->seq_params.color_range = oxcf->color_range;
-  cm->timing_info_present = oxcf->timing_info_present;
-  cm->timing_info.num_units_in_display_tick =
+  seq_params->profile = oxcf->profile;
+  seq_params->bit_depth = oxcf->bit_depth;
+  seq_params->use_highbitdepth = oxcf->use_highbitdepth;
+  seq_params->color_primaries = oxcf->color_primaries;
+  seq_params->transfer_characteristics = oxcf->transfer_characteristics;
+  seq_params->matrix_coefficients = oxcf->matrix_coefficients;
+  seq_params->monochrome = oxcf->monochrome;
+  seq_params->chroma_sample_position = oxcf->chroma_sample_position;
+  seq_params->color_range = oxcf->color_range;
+  seq_params->timing_info_present = oxcf->timing_info_present;
+  seq_params->timing_info.num_units_in_display_tick =
       oxcf->timing_info.num_units_in_display_tick;
-  cm->timing_info.time_scale = oxcf->timing_info.time_scale;
-  cm->timing_info.equal_picture_interval =
+  seq_params->timing_info.time_scale = oxcf->timing_info.time_scale;
+  seq_params->timing_info.equal_picture_interval =
       oxcf->timing_info.equal_picture_interval;
-  cm->timing_info.num_ticks_per_picture =
+  seq_params->timing_info.num_ticks_per_picture =
       oxcf->timing_info.num_ticks_per_picture;
 
-  cm->seq_params.display_model_info_present_flag =
+  seq_params->display_model_info_present_flag =
       oxcf->display_model_info_present_flag;
-  cm->seq_params.decoder_model_info_present_flag =
+  seq_params->decoder_model_info_present_flag =
       oxcf->decoder_model_info_present_flag;
   if (oxcf->decoder_model_info_present_flag) {
     // set the decoder model parameters in schedule mode
-    cm->buffer_model.num_units_in_decoding_tick =
+    seq_params->decoder_model_info.num_units_in_decoding_tick =
         oxcf->buffer_model.num_units_in_decoding_tick;
     cm->buffer_removal_time_present = 1;
-    av1_set_aom_dec_model_info(&cm->buffer_model);
-    av1_set_dec_model_op_parameters(&cm->op_params[0]);
-  } else if (cm->timing_info_present &&
-             cm->timing_info.equal_picture_interval &&
-             !cm->seq_params.decoder_model_info_present_flag) {
+    av1_set_aom_dec_model_info(&seq_params->decoder_model_info);
+    av1_set_dec_model_op_parameters(&seq_params->op_params[0]);
+  } else if (seq_params->timing_info_present &&
+             seq_params->timing_info.equal_picture_interval &&
+             !seq_params->decoder_model_info_present_flag) {
     // set the decoder model parameters in resource availability mode
-    av1_set_resource_availability_parameters(&cm->op_params[0]);
+    av1_set_resource_availability_parameters(&seq_params->op_params[0]);
   } else {
-    cm->op_params[0].initial_display_delay =
+    seq_params->op_params[0].initial_display_delay =
         10;  // Default value (not signaled)
   }
 
-  if (cm->seq_params.monochrome) {
-    cm->seq_params.subsampling_x = 1;
-    cm->seq_params.subsampling_y = 1;
-  } else if (cm->seq_params.color_primaries == AOM_CICP_CP_BT_709 &&
-             cm->seq_params.transfer_characteristics == AOM_CICP_TC_SRGB &&
-             cm->seq_params.matrix_coefficients == AOM_CICP_MC_IDENTITY) {
-    cm->seq_params.subsampling_x = 0;
-    cm->seq_params.subsampling_y = 0;
+  if (seq_params->monochrome) {
+    seq_params->subsampling_x = 1;
+    seq_params->subsampling_y = 1;
+  } else if (seq_params->color_primaries == AOM_CICP_CP_BT_709 &&
+             seq_params->transfer_characteristics == AOM_CICP_TC_SRGB &&
+             seq_params->matrix_coefficients == AOM_CICP_MC_IDENTITY) {
+    seq_params->subsampling_x = 0;
+    seq_params->subsampling_y = 0;
   } else {
-    if (cm->seq_params.profile == 0) {
-      cm->seq_params.subsampling_x = 1;
-      cm->seq_params.subsampling_y = 1;
-    } else if (cm->seq_params.profile == 1) {
-      cm->seq_params.subsampling_x = 0;
-      cm->seq_params.subsampling_y = 0;
+    if (seq_params->profile == 0) {
+      seq_params->subsampling_x = 1;
+      seq_params->subsampling_y = 1;
+    } else if (seq_params->profile == 1) {
+      seq_params->subsampling_x = 0;
+      seq_params->subsampling_y = 0;
     } else {
-      if (cm->seq_params.bit_depth == AOM_BITS_12) {
-        cm->seq_params.subsampling_x = oxcf->chroma_subsampling_x;
-        cm->seq_params.subsampling_y = oxcf->chroma_subsampling_y;
+      if (seq_params->bit_depth == AOM_BITS_12) {
+        seq_params->subsampling_x = oxcf->chroma_subsampling_x;
+        seq_params->subsampling_y = oxcf->chroma_subsampling_y;
       } else {
-        cm->seq_params.subsampling_x = 1;
-        cm->seq_params.subsampling_y = 0;
+        seq_params->subsampling_x = 1;
+        seq_params->subsampling_y = 0;
       }
     }
   }
 
   cm->width = oxcf->width;
   cm->height = oxcf->height;
-  set_sb_size(&cm->seq_params,
+  set_sb_size(seq_params,
               select_sb_size(cpi));  // set sb size before allocations
   alloc_compressor_data(cpi);
 
@@ -2775,13 +2777,13 @@
   assert(IMPLIES(seq_params->profile <= PROFILE_1,
                  seq_params->bit_depth <= AOM_BITS_10));
 
-  cm->timing_info_present = oxcf->timing_info_present;
-  cm->timing_info.num_units_in_display_tick =
+  seq_params->timing_info_present = oxcf->timing_info_present;
+  seq_params->timing_info.num_units_in_display_tick =
       oxcf->timing_info.num_units_in_display_tick;
-  cm->timing_info.time_scale = oxcf->timing_info.time_scale;
-  cm->timing_info.equal_picture_interval =
+  seq_params->timing_info.time_scale = oxcf->timing_info.time_scale;
+  seq_params->timing_info.equal_picture_interval =
       oxcf->timing_info.equal_picture_interval;
-  cm->timing_info.num_ticks_per_picture =
+  seq_params->timing_info.num_ticks_per_picture =
       oxcf->timing_info.num_ticks_per_picture;
 
   seq_params->display_model_info_present_flag =
@@ -2790,18 +2792,18 @@
       oxcf->decoder_model_info_present_flag;
   if (oxcf->decoder_model_info_present_flag) {
     // set the decoder model parameters in schedule mode
-    cm->buffer_model.num_units_in_decoding_tick =
+    seq_params->decoder_model_info.num_units_in_decoding_tick =
         oxcf->buffer_model.num_units_in_decoding_tick;
     cm->buffer_removal_time_present = 1;
-    av1_set_aom_dec_model_info(&cm->buffer_model);
-    av1_set_dec_model_op_parameters(&cm->op_params[0]);
-  } else if (cm->timing_info_present &&
-             cm->timing_info.equal_picture_interval &&
+    av1_set_aom_dec_model_info(&seq_params->decoder_model_info);
+    av1_set_dec_model_op_parameters(&seq_params->op_params[0]);
+  } else if (seq_params->timing_info_present &&
+             seq_params->timing_info.equal_picture_interval &&
              !seq_params->decoder_model_info_present_flag) {
     // set the decoder model parameters in resource availability mode
-    av1_set_resource_availability_parameters(&cm->op_params[0]);
+    av1_set_resource_availability_parameters(&seq_params->op_params[0]);
   } else {
-    cm->op_params[0].initial_display_delay =
+    seq_params->op_params[0].initial_display_delay =
         10;  // Default value (not signaled)
   }
 
@@ -6387,7 +6389,7 @@
           (frame_is_intra_only(cm) || !cm->show_frame) ? 0 : 1;
       break;
   }
-  cm->timing_info_present &= !seq_params->reduced_still_picture_hdr;
+  seq_params->timing_info_present &= !seq_params->reduced_still_picture_hdr;
 
   int largest_tile_id = 0;
 #if CONFIG_SUPERRES_IN_RECODE
@@ -7074,7 +7076,7 @@
 
   uint8_t header_buf[512] = { 0 };
   const uint32_t sequence_header_size =
-      av1_write_sequence_header_obu(cpi, &header_buf[0]);
+      av1_write_sequence_header_obu(&cpi->common.seq_params, &header_buf[0]);
   assert(sequence_header_size <= sizeof(header_buf));
   if (sequence_header_size == 0) return NULL;
 
diff --git a/av1/encoder/level.c b/av1/encoder/level.c
index 94d4f55..47d647e 100644
--- a/av1/encoder/level.c
+++ b/av1/encoder/level.c
@@ -507,18 +507,19 @@
   dfg_interval_queue->head = 0;
   dfg_interval_queue->size = 0;
 
-  if (cm->timing_info_present) {
+  if (seq_params->timing_info_present) {
     decoder_model->num_ticks_per_picture =
-        cm->timing_info.num_ticks_per_picture;
+        seq_params->timing_info.num_ticks_per_picture;
     decoder_model->display_clock_tick =
-        cm->timing_info.num_units_in_display_tick / cm->timing_info.time_scale;
+        seq_params->timing_info.num_units_in_display_tick /
+        seq_params->timing_info.time_scale;
   } else {
     decoder_model->num_ticks_per_picture = 1;
     decoder_model->display_clock_tick = 1.0 / cpi->framerate;
   }
 
   decoder_model->initial_display_delay =
-      cm->op_params[op_index].initial_display_delay;
+      seq_params->op_params[op_index].initial_display_delay;
   decoder_model->initial_presentation_delay = INVALID_TIME;
   decoder_model->decode_rate = av1_level_defs[level].max_decode_rate;
 }