[NORMATIVE] ext_tile: set external references at the tile level

This patch implemented the external reference setting before decoding
decode a tile in the tile list OBU.

BUG=aomedia:1938

Change-Id: I4dcad505dc365b26acaeaf6efdda8ea227c309a2
diff --git a/aom/aomdx.h b/aom/aomdx.h
index 8e0284b..f463b62 100644
--- a/aom/aomdx.h
+++ b/aom/aomdx.h
@@ -71,6 +71,17 @@
   const void *coded_tile_data;
 } aom_tile_data;
 
+/*!\brief Structure to hold the external reference frame pointer.
+ *
+ * Define a structure to hold the external reference frame pointer.
+ */
+typedef struct av1_ext_ref_frame {
+  /*! Start pointer of external references. */
+  aom_image_t *img;
+  /*! Number of available external references. */
+  int num;
+} av1_ext_ref_frame_t;
+
 /*!\enum aom_dec_control_id
  * \brief AOM decoder control functions
  *
@@ -160,6 +171,11 @@
    * bitstream. This provides a way to access a specific tile's bitstream data.
    */
   AV1D_GET_TILE_DATA,
+  /** control function to set the external references' pointers in the decoder.
+   *  This is used while decoding the tile list OBU in large-scale tile coding
+   *  mode.
+   */
+  AV1D_SET_EXT_REF_PTR,
   /** control function to enable the ext-tile software debug and testing code in
    * the decoder.
    */
@@ -219,6 +235,8 @@
 #define AOM_CTRL_AV1_SET_TILE_MODE
 AOM_CTRL_USE_TYPE(AV1D_GET_TILE_DATA, aom_tile_data *)
 #define AOM_CTRL_AV1D_GET_TILE_DATA
+AOM_CTRL_USE_TYPE(AV1D_SET_EXT_REF_PTR, av1_ext_ref_frame_t *)
+#define AOM_CTRL_AV1D_SET_EXT_REF_PTR
 AOM_CTRL_USE_TYPE(AV1D_EXT_TILE_DEBUG, unsigned int)
 #define AOM_CTRL_AV1D_EXT_TILE_DEBUG
 AOM_CTRL_USE_TYPE(AV1D_SET_IS_ANNEXB, unsigned int)
diff --git a/av1/av1_dx_iface.c b/av1/av1_dx_iface.c
index f99dacf..c440fed 100644
--- a/av1/av1_dx_iface.c
+++ b/av1/av1_dx_iface.c
@@ -59,9 +59,10 @@
   int decode_tile_row;
   int decode_tile_col;
   unsigned int tile_mode;
+  unsigned int ext_tile_debug;
+  EXTERNAL_REFERENCES ext_refs;
   unsigned int is_annexb;
   int operating_point;
-  unsigned int ext_tile_debug;
 
   AVxWorker *frame_workers;
   int num_frame_workers;
@@ -480,6 +481,8 @@
   frame_worker_data->pbi->dec_tile_row = ctx->decode_tile_row;
   frame_worker_data->pbi->dec_tile_col = ctx->decode_tile_col;
   frame_worker_data->pbi->ext_tile_debug = ctx->ext_tile_debug;
+  frame_worker_data->pbi->ext_refs = ctx->ext_refs;
+
   frame_worker_data->pbi->common.is_annexb = ctx->is_annexb;
 
   worker->had_error = 0;
@@ -896,6 +899,22 @@
   return AOM_CODEC_INVALID_PARAM;
 }
 
+static aom_codec_err_t ctrl_set_ext_ref_ptr(aom_codec_alg_priv_t *ctx,
+                                            va_list args) {
+  av1_ext_ref_frame_t *const data = va_arg(args, av1_ext_ref_frame_t *);
+
+  if (data) {
+    av1_ext_ref_frame_t *const ext_frames = data;
+    ctx->ext_refs.num = ext_frames->num;
+    for (int i = 0; i < ctx->ext_refs.num; i++) {
+      image2yuvconfig(ext_frames->img++, &ctx->ext_refs.refs[i]);
+    }
+    return AOM_CODEC_OK;
+  } else {
+    return AOM_CODEC_INVALID_PARAM;
+  }
+}
+
 static aom_codec_err_t ctrl_get_render_size(aom_codec_alg_priv_t *ctx,
                                             va_list args) {
   int *const render_size = va_arg(args, int *);
@@ -1066,6 +1085,7 @@
   { AV1D_SET_OPERATING_POINT, ctrl_set_operating_point },
   { AV1_SET_INSPECTION_CALLBACK, ctrl_set_inspection_callback },
   { AV1D_EXT_TILE_DEBUG, ctrl_ext_tile_debug },
+  { AV1D_SET_EXT_REF_PTR, ctrl_set_ext_ref_ptr },
 
   // Getters
   { AOMD_GET_FRAME_CORRUPTED, ctrl_get_frame_corrupted },
diff --git a/av1/common/enums.h b/av1/common/enums.h
index e1feec4..6e0fc55 100644
--- a/av1/common/enums.h
+++ b/av1/common/enums.h
@@ -606,6 +606,9 @@
 #define SUPERRES_SCALE_BITS 3
 #define SUPERRES_SCALE_DENOMINATOR_MIN (SCALE_NUMERATOR + 1)
 
+// In large_scale_tile coding, external references are used.
+#define MAX_EXTERNAL_REFERENCES 128
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif
diff --git a/av1/decoder/decoder.h b/av1/decoder/decoder.h
index 4d7b5fa..d85b3d5 100644
--- a/av1/decoder/decoder.h
+++ b/av1/decoder/decoder.h
@@ -52,6 +52,11 @@
   size_t size;
 } TileBufferDec;
 
+typedef struct EXTERNAL_REFERENCES {
+  YV12_BUFFER_CONFIG refs[MAX_EXTERNAL_REFERENCES];
+  int num;
+} EXTERNAL_REFERENCES;
+
 typedef struct AV1Decoder {
   DECLARE_ALIGNED(32, MACROBLOCKD, mb);
 
@@ -115,7 +120,8 @@
   int output_frame_height_in_tiles_minus_1;
   int tile_count_minus_1;
   uint32_t coded_tile_data_size;
-  int ext_tile_debug;  // for ext-tile software debug & testing
+  unsigned int ext_tile_debug;  // for ext-tile software debug & testing
+  EXTERNAL_REFERENCES ext_refs;
 } 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 cb17925..42c92cc 100644
--- a/av1/decoder/obu.c
+++ b/av1/decoder/obu.c
@@ -394,13 +394,13 @@
 
     // Read out the tile info.
     uint32_t tile_info_bytes = 5;
-    // TODO(yunqing): set reference here.
+    // Set reference for each tile.
     int ref_idx = aom_rb_read_literal(rb, 8);
     if (ref_idx > 127) {
       cm->error.error_code = AOM_CODEC_CORRUPT_FRAME;
       return 0;
     }
-    (void)ref_idx;
+    av1_set_reference_dec(cm, 0, 1, &pbi->ext_refs.refs[ref_idx]);
 
     pbi->dec_tile_row = aom_rb_read_literal(rb, 8);
     pbi->dec_tile_col = aom_rb_read_literal(rb, 8);
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 61a3058..bb2767d 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -6036,8 +6036,9 @@
              (b->flags & YV12_FLAG_HIGHBITDEPTH);
 }
 
-int av1_copy_new_frame_enc(AV1_COMMON *cm, YV12_BUFFER_CONFIG *new_frame,
-                           YV12_BUFFER_CONFIG *sd) {
+aom_codec_err_t av1_copy_new_frame_enc(AV1_COMMON *cm,
+                                       YV12_BUFFER_CONFIG *new_frame,
+                                       YV12_BUFFER_CONFIG *sd) {
   const int num_planes = av1_num_planes(cm);
   if (!equal_dimensions_and_border(new_frame, sd))
     aom_internal_error(&cm->error, AOM_CODEC_ERROR,
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index 0b818fc..42752d0 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -712,8 +712,9 @@
 
 int av1_get_last_show_frame(AV1_COMP *cpi, YV12_BUFFER_CONFIG *frame);
 
-int av1_copy_new_frame_enc(AV1_COMMON *cm, YV12_BUFFER_CONFIG *new_frame,
-                           YV12_BUFFER_CONFIG *sd);
+aom_codec_err_t av1_copy_new_frame_enc(AV1_COMMON *cm,
+                                       YV12_BUFFER_CONFIG *new_frame,
+                                       YV12_BUFFER_CONFIG *sd);
 
 int av1_use_as_reference(AV1_COMP *cpi, int ref_frame_flags);
 
diff --git a/examples/lightfield_bitstream_parsing.c b/examples/lightfield_bitstream_parsing.c
index 8ca630e..8ecc0ee 100644
--- a/examples/lightfield_bitstream_parsing.c
+++ b/examples/lightfield_bitstream_parsing.c
@@ -259,7 +259,7 @@
       aom_wb_write_literal(&wb, tr, 8);
       aom_wb_write_literal(&wb, tc, 8);
       aom_wb_write_literal(&wb, tile_data.coded_tile_data_size - 1, 16);
-      tl += 5;
+      tl += tile_info_bytes;
 
       memcpy(tl, (uint8_t *)tile_data.coded_tile_data,
              tile_data.coded_tile_data_size);
@@ -269,13 +269,10 @@
           tile_info_bytes + (uint32_t)tile_data.coded_tile_data_size;
     }
 
-    printf("\n tile_list_obu_size: %d\n", tile_list_obu_size);
-
     // Write tile list OBU size.
     size_t bytes_written = 0;
-    aom_uleb_encode_fixed_size(tile_list_obu_size, 4, 4, saved_obu_size_loc,
-                               &bytes_written);
-    if (bytes_written != 4)
+    if (aom_uleb_encode_fixed_size(tile_list_obu_size, 4, 4, saved_obu_size_loc,
+                                   &bytes_written))
       die_codec(&codec, "Failed to encode the tile list obu size.");
 
     // Copy camera frame bitstream directly to get the header.
diff --git a/examples/lightfield_decoder.c b/examples/lightfield_decoder.c
index 4f5da22..ed61923 100644
--- a/examples/lightfield_decoder.c
+++ b/examples/lightfield_decoder.c
@@ -32,6 +32,7 @@
 #include "common/tools_common.h"
 #include "common/video_reader.h"
 
+#define MAX_EXTERNAL_REFERENCES 128
 #define AOM_BORDER_IN_PIXELS 288
 
 static const char *exec_name;
@@ -63,7 +64,7 @@
   int lf_blocksize;
   int u_blocks;
   int v_blocks;
-  aom_image_t reference_images[128];
+  aom_image_t reference_images[MAX_EXTERNAL_REFERENCES];
   size_t frame_size = 0;
   const unsigned char *frame = NULL;
   int i;
diff --git a/examples/lightfield_encoder.c b/examples/lightfield_encoder.c
index d182c94..edcdff9 100644
--- a/examples/lightfield_encoder.c
+++ b/examples/lightfield_encoder.c
@@ -42,6 +42,7 @@
 #include "common/tools_common.h"
 #include "common/video_writer.h"
 
+#define MAX_EXTERNAL_REFERENCES 128
 #define AOM_BORDER_IN_PIXELS 288
 
 static const char *exec_name;
@@ -247,7 +248,7 @@
   int bu, bv;
   int u_blocks, v_blocks;
   aom_image_t *frame_to_encode;
-  aom_image_t reference_images[128];
+  aom_image_t reference_images[MAX_EXTERNAL_REFERENCES];
   int reference_image_num = 0;
   int i;
 
diff --git a/examples/lightfield_tile_list_decoder.c b/examples/lightfield_tile_list_decoder.c
index 3ce01e6..1b48fa1 100644
--- a/examples/lightfield_tile_list_decoder.c
+++ b/examples/lightfield_tile_list_decoder.c
@@ -33,6 +33,7 @@
 #include "common/tools_common.h"
 #include "common/video_reader.h"
 
+#define MAX_EXTERNAL_REFERENCES 128
 #define AOM_BORDER_IN_PIXELS 288
 
 static const char *exec_name;
@@ -58,7 +59,7 @@
   int lf_width, lf_height, lf_blocksize;
   int u_blocks, v_blocks;
   int num_tile_lists;
-  aom_image_t reference_images[128];
+  aom_image_t reference_images[MAX_EXTERNAL_REFERENCES];
   size_t frame_size = 0;
   const unsigned char *frame = NULL;
   int i, n;
@@ -138,27 +139,21 @@
   // Decode the lightfield.
   aom_codec_control_(&codec, AV1_SET_TILE_MODE, 1);
 
+  // Set external references.
+  av1_ext_ref_frame_t set_ext_ref = { &reference_images[0], num_references };
+  aom_codec_control_(&codec, AV1D_SET_EXT_REF_PTR, &set_ext_ref);
+
   // Must decode the camera frame header first.
   aom_video_reader_read_frame(reader);
   frame = aom_video_reader_get_frame(reader, &frame_size);
   if (aom_codec_decode(&codec, frame, frame_size, NULL))
     die_codec(&codec, "Failed to decode the frame.");
 
-  printf("\nCamera frame header is decoded.\n");
-
   // Decode tile lists one by one.
   for (n = 0; n < num_tile_lists; n++) {
     aom_video_reader_read_frame(reader);
     frame = aom_video_reader_get_frame(reader, &frame_size);
 
-    // TODO(yunqing): need to implement this at tile level.
-    av1_ref_frame_t ref;
-    ref.idx = 0;
-    ref.use_external_ref = 1;
-    ref.img = reference_images[0];  // hard-coded for now.
-    if (aom_codec_control(&codec, AV1_SET_REFERENCE, &ref))
-      die_codec(&codec, "Failed to set reference frame");
-
     if (aom_codec_decode(&codec, frame, frame_size, NULL))
       die_codec(&codec, "Failed to decode the tile list.");