Add control call in decoder to facilitate sub-gop unit test

This patch includes control call for sub-gop stats collection
from decoder, in order to facilitate sub-gop unit test.

Change-Id: I8bfcea7f5be777fec8ee64c420cab5be22b2dc96
diff --git a/aom/aomdx.h b/aom/aomdx.h
index aa4f435..810709e 100644
--- a/aom/aomdx.h
+++ b/aom/aomdx.h
@@ -426,6 +426,14 @@
   /*!\brief Codec control function to get the S_FRAME coding information
    */
   AOMD_GET_S_FRAME_INFO,
+
+  /*!\brief Codec control function to get the frame information
+   */
+  AOMD_GET_FRAME_INFO,
+
+  /*!\brief Codec control function to enable subgop stats
+   */
+  AV1D_ENABLE_SUBGOP_STATS,
 };
 
 /*!\cond */
@@ -480,6 +488,12 @@
 AOM_CTRL_USE_TYPE(AOMD_GET_S_FRAME_INFO, aom_s_frame_info *)
 #define AOMD_CTRL_AOMD_GET_S_FRAME_INFO
 
+AOM_CTRL_USE_TYPE(AOMD_GET_FRAME_INFO, void *)
+#define AOMD_CTRL_AOMD_GET_FRAME_INFO
+
+AOM_CTRL_USE_TYPE(AV1D_ENABLE_SUBGOP_STATS, unsigned int)
+#define AOMD_CTRL_AV1D_ENABLE_SUBGOP_STATS
+
 AOM_CTRL_USE_TYPE(AV1D_GET_DISPLAY_SIZE, int *)
 #define AOM_CTRL_AV1D_GET_DISPLAY_SIZE
 
diff --git a/av1/av1_dx_iface.c b/av1/av1_dx_iface.c
index 2239478..ec920db 100644
--- a/av1/av1_dx_iface.c
+++ b/av1/av1_dx_iface.c
@@ -71,6 +71,8 @@
   aom_get_frame_buffer_cb_fn_t get_ext_fb_cb;
   aom_release_frame_buffer_cb_fn_t release_ext_fb_cb;
 
+  // To collect stats for sub-gop unit test case
+  unsigned int enable_subgop_stats;
 #if CONFIG_INSPECTION
   aom_inspect_cb inspect_cb;
   void *inspect_ctx;
@@ -468,6 +470,7 @@
   frame_worker_data->pbi->ext_tile_debug = ctx->ext_tile_debug;
   frame_worker_data->pbi->row_mt = ctx->row_mt;
   frame_worker_data->pbi->is_fwd_kf_present = 0;
+  frame_worker_data->pbi->enable_subgop_stats = ctx->enable_subgop_stats;
   frame_worker_data->pbi->is_arf_frame_present = 0;
   worker->hook = frame_worker_hook;
 
@@ -593,6 +596,8 @@
     AVxWorker *const worker = ctx->frame_worker;
     FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1;
     struct AV1Decoder *pbi = frame_worker_data->pbi;
+    if (ctx->enable_subgop_stats)
+      memset(&pbi->subgop_stats, 0, sizeof(pbi->subgop_stats));
     for (size_t j = 0; j < pbi->num_output_frames; j++) {
       decrease_ref_count(pbi->output_frames[j], pool);
     }
@@ -1148,6 +1153,37 @@
   return AOM_CODEC_OK;
 }
 
+static aom_codec_err_t ctrl_enable_subgop_stats(aom_codec_alg_priv_t *ctx,
+                                                va_list args) {
+  const unsigned int arg = va_arg(args, unsigned int);
+  ctx->enable_subgop_stats = arg;
+  return AOM_CODEC_OK;
+}
+
+static aom_codec_err_t ctrl_get_dec_frame_info(aom_codec_alg_priv_t *ctx,
+                                               va_list args) {
+  SubGOPData *subgop_data = va_arg(args, SubGOPData *);
+  if (!ctx->frame_worker) return AOM_CODEC_ERROR;
+  const AVxWorker *const worker = ctx->frame_worker;
+  FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1;
+  const AV1Decoder *const pbi = frame_worker_data->pbi;
+  const SubGOPStatsDec *const subgop_stats = &pbi->subgop_stats;
+  SubGOPStepData *step_data = subgop_data->step;
+  const int stat_count = subgop_stats->stat_count;
+
+  // Collects already decoded out of order frames info along with in-order
+  // frame
+  step_data += subgop_data->step_idx_dec;
+  for (int step_idx = 0; step_idx < stat_count; step_idx++) {
+    step_data[step_idx].disp_frame_idx = subgop_stats->disp_frame_idx[step_idx];
+    step_data[step_idx].show_existing_frame =
+        subgop_stats->show_existing_frame[step_idx];
+    step_data[step_idx].show_frame = subgop_stats->show_frame[step_idx];
+    subgop_data->step_idx_dec++;
+  }
+  return AOM_CODEC_OK;
+}
+
 static aom_codec_err_t ctrl_get_frame_corrupted(aom_codec_alg_priv_t *ctx,
                                                 va_list args) {
   int *corrupted = va_arg(args, int *);
@@ -1523,6 +1559,7 @@
   { AV1D_SET_ROW_MT, ctrl_set_row_mt },
   { AV1D_SET_EXT_REF_PTR, ctrl_set_ext_ref_ptr },
   { AV1D_SET_SKIP_FILM_GRAIN, ctrl_set_skip_film_grain },
+  { AV1D_ENABLE_SUBGOP_STATS, ctrl_enable_subgop_stats },
 
   // Getters
   { AOMD_GET_FRAME_CORRUPTED, ctrl_get_frame_corrupted },
@@ -1549,6 +1586,7 @@
   { AOMD_GET_SB_SIZE, ctrl_get_sb_size },
   { AOMD_GET_SHOW_EXISTING_FRAME_FLAG, ctrl_get_show_existing_frame_flag },
   { AOMD_GET_S_FRAME_INFO, ctrl_get_s_frame_info },
+  { AOMD_GET_FRAME_INFO, ctrl_get_dec_frame_info },
 
   CTRL_MAP_END,
 };
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c
index bf25048..863eaae 100644
--- a/av1/decoder/decodeframe.c
+++ b/av1/decoder/decodeframe.c
@@ -535,6 +535,19 @@
   }
 }
 
+static AOM_INLINE void update_subgop_stats(const AV1_COMMON *const cm,
+                                           SubGOPStatsDec *const subgop_stats,
+                                           unsigned int display_order_hint,
+                                           unsigned int enable_subgop_stats) {
+  if (!enable_subgop_stats) return;
+  subgop_stats->disp_frame_idx[subgop_stats->stat_count] = display_order_hint;
+  subgop_stats->show_existing_frame[subgop_stats->stat_count] =
+      cm->show_existing_frame;
+  subgop_stats->show_frame[subgop_stats->stat_count] = cm->show_frame;
+  assert(subgop_stats->stat_count < MAX_SUBGOP_STATS_SIZE);
+  subgop_stats->stat_count++;
+}
+
 static void dec_calc_subpel_params(const MV *const src_mv,
                                    InterPredParams *const inter_pred_params,
                                    const MACROBLOCKD *const xd, int mi_x,
@@ -4506,6 +4519,9 @@
       cm->lf.filter_level[1] = 0;
       cm->show_frame = 1;
 
+      update_subgop_stats(cm, &pbi->subgop_stats, frame_to_show->order_hint,
+                          pbi->enable_subgop_stats);
+
       // Section 6.8.2: It is a requirement of bitstream conformance that when
       // show_existing_frame is used to show a previous frame, that the value
       // of showable_frame for the previous frame was equal to 1.
@@ -4905,6 +4921,9 @@
     }
   }
 
+  update_subgop_stats(cm, &pbi->subgop_stats, cm->current_frame.order_hint,
+                      pbi->enable_subgop_stats);
+
   av1_setup_frame_buf_refs(cm);
 
   av1_setup_frame_sign_bias(cm);
diff --git a/av1/decoder/decoder.h b/av1/decoder/decoder.h
index b20e9c1..b4dabce 100644
--- a/av1/decoder/decoder.h
+++ b/av1/decoder/decoder.h
@@ -218,6 +218,17 @@
   int alloc_tile_cols;
 } AV1DecTileMT;
 
+/*!
+ * \Holds subgop related info.
+ */
+typedef struct {
+  unsigned char disp_frame_idx[MAX_SUBGOP_STATS_SIZE];
+  int show_existing_frame[MAX_SUBGOP_STATS_SIZE];
+  int show_frame[MAX_SUBGOP_STATS_SIZE];
+  int refresh_frame_flags[MAX_SUBGOP_STATS_SIZE];
+  unsigned char stat_count;
+} SubGOPStatsDec;
+
 typedef struct AV1Decoder {
   DecoderCodingBlock dcb;
 
@@ -330,6 +341,8 @@
   int is_arf_frame_present;
   int num_tile_groups;
   aom_s_frame_info sframe_info;
+  unsigned int enable_subgop_stats;
+  SubGOPStatsDec subgop_stats;
 } AV1Decoder;
 
 // Returns 0 on success. Sets pbi->common.error.error_code to a nonzero error