[NORMATIVE] add code for operating_points experiment

Normative changes only in the sequence header

BUG=aomedia:1615

Change-Id: I6f8f87c3834998f15b89dec8c5d7f60ab0900851
diff --git a/av1/common/onyxc_int.h b/av1/common/onyxc_int.h
index 652a9cd..0a5c504 100644
--- a/av1/common/onyxc_int.h
+++ b/av1/common/onyxc_int.h
@@ -77,6 +77,17 @@
 
 #define NUM_PING_PONG_BUFFERS 2
 
+#if CONFIG_OPERATING_POINTS
+#if CONFIG_SCALABILITY
+#define MAX_NUM_TEMPORAL_LAYERS 8
+#define MAX_NUM_SPATIAL_LAYERS 4
+#define MAX_NUM_OPERATING_POINTS \
+  MAX_NUM_TEMPORAL_LAYERS + MAX_NUM_SPATIAL_LAYERS
+#else
+#define MAX_NUM_OPERATING_POINTS 1
+#endif
+#endif
+
 // TODO(jingning): Turning this on to set up transform coefficient
 // processing timer.
 #define TXCOEFF_TIMER 0
@@ -225,6 +236,14 @@
                            // 1 - Enable superres for the sequence, and also
                            //     enable per-frame flag to denote if superres is
                            //     enabled for that frame.
+#if CONFIG_OPERATING_POINTS
+  int operating_point_idc[MAX_NUM_OPERATING_POINTS];
+  int level[MAX_NUM_OPERATING_POINTS];
+  int decoder_rate_model_param_present_flag[MAX_NUM_OPERATING_POINTS];
+  int decode_to_display_rate_ratio[MAX_NUM_OPERATING_POINTS];
+  int initial_display_delay[MAX_NUM_OPERATING_POINTS];
+  int extra_frame_buffers[MAX_NUM_OPERATING_POINTS];
+#endif  // CONFIG_OPERATING_POINTS
 } SequenceHeader;
 
 typedef struct AV1Common {
diff --git a/av1/decoder/decoder.h b/av1/decoder/decoder.h
index 1626645..e9fa260 100644
--- a/av1/decoder/decoder.h
+++ b/av1/decoder/decoder.h
@@ -97,6 +97,9 @@
   aom_inspect_cb inspect_cb;
   void *inspect_ctx;
 #endif
+#if CONFIG_OPERATING_POINTS
+  int current_operating_point;
+#endif
 } AV1Decoder;
 
 int av1_receive_compressed_data(struct AV1Decoder *pbi, size_t size,
diff --git a/av1/decoder/obu.c b/av1/decoder/obu.c
index 1f46d6c..6dbe328 100644
--- a/av1/decoder/obu.c
+++ b/av1/decoder/obu.c
@@ -149,6 +149,22 @@
 }
 #endif
 
+#if CONFIG_OPERATING_POINTS
+static int is_obu_in_current_operating_point(AV1Decoder *pbi,
+                                             ObuHeader obu_header) {
+  if (!pbi->current_operating_point) {
+    return 1;
+  }
+
+  if ((pbi->current_operating_point >> obu_header.temporal_layer_id) & 0x1 &&
+      (pbi->current_operating_point >> (obu_header.enhancement_layer_id + 8)) &
+          0x1) {
+    return 1;
+  }
+  return 0;
+}
+#endif
+
 static uint32_t read_temporal_delimiter_obu() { return 0; }
 
 static uint32_t read_sequence_header_obu(AV1Decoder *pbi,
@@ -157,6 +173,8 @@
   uint32_t saved_bit_offset = rb->bit_offset;
 
   cm->profile = av1_read_profile(rb);
+
+#if !CONFIG_OPERATING_POINTS
 #if !CONFIG_SCALABILITY
   aom_rb_read_literal(rb, 4);  // level
 #else
@@ -166,6 +184,29 @@
     aom_rb_read_literal(rb, 4);  // level for each enhancement layer
   }
 #endif
+#else  // CONFIG_OPERATING_POINTS
+#if CONFIG_SCALABILITY
+  uint8_t operating_points_minus1_cnt = aom_rb_read_literal(rb, 5);
+  pbi->common.enhancement_layers_cnt = operating_points_minus1_cnt + 1;
+#else
+  uint8_t operating_points_minus1_cnt = 0;
+#endif
+  int i;
+  SequenceHeader *seq_params = &cm->seq_params;
+  for (i = 0; i < operating_points_minus1_cnt + 1; i++) {
+    seq_params->operating_point_idc[i] = aom_rb_read_literal(rb, 12);
+    seq_params->level[i] = aom_rb_read_literal(rb, 4);
+    seq_params->decoder_rate_model_param_present_flag[i] =
+        aom_rb_read_literal(rb, 1);
+    if (seq_params->decoder_rate_model_param_present_flag[i]) {
+      seq_params->decode_to_display_rate_ratio[i] = aom_rb_read_literal(rb, 12);
+      seq_params->initial_display_delay[i] = aom_rb_read_literal(rb, 24);
+      seq_params->extra_frame_buffers[i] = aom_rb_read_literal(rb, 4);
+    }
+  }
+  // This decoder supports all levels.  Choose the first operating point
+  pbi->current_operating_point = seq_params->operating_point_idc[0];
+#endif  // CONFIG_OPERATING_POINTS
 
   read_sequence_header(cm, rb);
 
@@ -445,6 +486,13 @@
 #if CONFIG_OBU_FRAME
       case OBU_FRAME:
 #endif  // CONFIG_OBU_FRAME
+#if CONFIG_OPERATING_POINTS
+        // don't decode obu if it's not in current operating mode
+        if (!is_obu_in_current_operating_point(pbi, obu_header)) {
+          decoded_payload_size = payload_size;
+          break;
+        }
+#endif
         // Only decode first frame header received
         if (!frame_header_received) {
 #if CONFIG_TRAILING_BITS
@@ -486,12 +534,26 @@
           cm->error.error_code = AOM_CODEC_CORRUPT_FRAME;
           return;
         }
+#if CONFIG_OPERATING_POINTS
+        // don't decode obu if it's not in current operating mode
+        if (!is_obu_in_current_operating_point(pbi, obu_header)) {
+          decoded_payload_size = payload_size;
+          break;
+        }
+#endif
         decoded_payload_size += read_one_tile_group_obu(
             pbi, &rb, is_first_tg_obu_received, data + obu_payload_offset,
             data + payload_size, p_data_end, &frame_decoding_finished);
         is_first_tg_obu_received = 0;
         break;
       case OBU_METADATA:
+#if CONFIG_OPERATING_POINTS
+        // don't decode obu if it's not in current operating mode
+        if (!is_obu_in_current_operating_point(pbi, obu_header)) {
+          decoded_payload_size = payload_size;
+          break;
+        }
+#endif
         decoded_payload_size = read_metadata(data, payload_size);
         break;
       case OBU_PADDING:
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index bf93c48..8d273e2 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -3495,6 +3495,8 @@
   uint32_t size = 0;
 
   write_profile(cm->profile, &wb);
+
+#if !CONFIG_OPERATING_POINTS
 #if !CONFIG_SCALABILITY
   aom_wb_write_literal(&wb, 0, 4);
 #else
@@ -3504,6 +3506,20 @@
     aom_wb_write_literal(&wb, 0, 4);
   }
 #endif
+#else  // CONFIG_OPERATING_POINTS
+#if !CONFIG_SCALABILITY
+  uint8_t operating_points_minus1_cnt = 0;
+#else
+  uint8_t operating_points_minus1_cnt = enhancement_layers_cnt;
+#endif
+  aom_wb_write_literal(&wb, operating_points_minus1_cnt, 5);
+  int i;
+  for (i = 0; i < operating_points_minus1_cnt + 1; i++) {
+    aom_wb_write_literal(&wb, 0, 12);  // operating_point_idc[i]
+    aom_wb_write_literal(&wb, 0, 4);   // level[i]
+    aom_wb_write_literal(&wb, 0, 1);   // decoder_rate_model_present_flag[i]
+  }
+#endif  // CONFIG_OPERATING_POINTS
 
   write_sequence_header(cpi, &wb);
 
diff --git a/build/cmake/aom_config_defaults.cmake b/build/cmake/aom_config_defaults.cmake
index b497aee..6ba1430 100644
--- a/build/cmake/aom_config_defaults.cmake
+++ b/build/cmake/aom_config_defaults.cmake
@@ -106,6 +106,7 @@
 set(CONFIG_OBU_FRAME 1 CACHE NUMBER "AV1 experiment flag.")
 set(CONFIG_OBU_NO_IVF 0 CACHE NUMBER "AV1 experiment flag.")
 set(CONFIG_OBU_REDUNDANT_FRAME_HEADER 0 CACHE NUMBER "AV1 experiment flag.")
+set(CONFIG_OPERATING_POINTS 0 CACHE NUMBER "AV1 experiment flag.")
 set(CONFIG_RD_DEBUG 0 CACHE NUMBER "AV1 experiment flag.")
 set(CONFIG_SCALABILITY 1 CACHE NUMBER "AV1 experiment flag.")
 set(CONFIG_SHORT_FILTER 1 CACHE NUMBER "AV1 experiment flag.")