Add encoder options for cost update frequency

Two new paramters are added that allow selecting costing update
frequencies at the encoder side for coefficeint and mode/mv costs
to SB level (0), SB row level in tile (1) and Tile level (2):
--mode-cost-upd-freq=<n>
--coeff-cost-upd-freq=<n>
where n = 0, 1, 2.

Change-Id: I98d648064b535648bde5cc2effbbcf28e8a2156c
diff --git a/aom/aomcx.h b/aom/aomcx.h
index ec5455a..37c9ea4 100644
--- a/aom/aomcx.h
+++ b/aom/aomcx.h
@@ -990,6 +990,22 @@
   /*!\brief Control to select maximum reference frames allowed per frame
    * (valid values: 3 - 7) */
   AV1E_SET_MAX_REFERENCE_FRAMES,
+
+  /*!\brief Control to set frequency of the cost updates for coefficients
+   * Possible values are:
+   * 0: Update at SB level (default)
+   * 1: Update at SB row level in tile
+   * 2: Update at tile level
+   */
+  AV1E_SET_COEFF_COST_UPD_FREQ,
+
+  /*!\brief Control to set frequency of the cost updates for mode
+   * Possible values are:
+   * 0: Update at SB level (default)
+   * 1: Update at SB row level in tile
+   * 2: Update at tile level
+   */
+  AV1E_SET_MODE_COST_UPD_FREQ,
 };
 
 /*!\brief aom 1-D scaling mode
@@ -1379,6 +1395,12 @@
 AOM_CTRL_USE_TYPE(AV1E_SET_MAX_REFERENCE_FRAMES, unsigned int)
 #define AOM_CTRL_AV1E_SET_MAX_REFERENCE_FRAMES
 
+AOM_CTRL_USE_TYPE(AV1E_SET_COEFF_COST_UPD_FREQ, unsigned int)
+#define AOM_CTRL_AV1E_SET_COEFF_COST_UPD_FREQ
+
+AOM_CTRL_USE_TYPE(AV1E_SET_MODE_COST_UPD_FREQ, unsigned int)
+#define AOM_CTRL_AV1E_SET_MODE_COST_UPD_FREQ
+
 /*!\endcond */
 /*! @} - end defgroup aom_encoder */
 #ifdef __cplusplus
diff --git a/apps/aomenc.c b/apps/aomenc.c
index 2574477..6efe123 100644
--- a/apps/aomenc.c
+++ b/apps/aomenc.c
@@ -541,6 +541,14 @@
     ARG_DEF(NULL, "use-inter-dct-only", 1, "Use DCT only for INTER modes");
 static const arg_def_t quant_b_adapt =
     ARG_DEF(NULL, "quant-b-adapt", 1, "Use adaptive quantize_b");
+static const arg_def_t coeff_cost_upd_freq =
+    ARG_DEF(NULL, "coeff-cost-upd-freq", 1,
+            "Update freq for coeff costs"
+            "0: SB, 1: SB Row per Tile, 2: Tile");
+static const arg_def_t mode_cost_upd_freq =
+    ARG_DEF(NULL, "mode-cost-upd-freq", 1,
+            "Update freq for mode costs"
+            "0: SB, 1: SB Row per Tile, 2: Tile");
 #if CONFIG_DIST_8X8
 static const arg_def_t enable_dist_8x8 =
     ARG_DEF(NULL, "enable-dist-8x8", 1,
@@ -767,6 +775,8 @@
                                        &use_intra_dct_only,
                                        &use_inter_dct_only,
                                        &quant_b_adapt,
+                                       &coeff_cost_upd_freq,
+                                       &mode_cost_upd_freq,
 #if CONFIG_DIST_8X8
                                        &enable_dist_8x8,
 #endif
@@ -853,6 +863,8 @@
                                         AV1E_SET_INTRA_DCT_ONLY,
                                         AV1E_SET_INTER_DCT_ONLY,
                                         AV1E_SET_QUANT_B_ADAPT,
+                                        AV1E_SET_COEFF_COST_UPD_FREQ,
+                                        AV1E_SET_MODE_COST_UPD_FREQ,
 #if CONFIG_DIST_8X8
                                         AV1E_SET_ENABLE_DIST_8X8,
 #endif
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c
index 987a478..0b6b61c 100644
--- a/av1/av1_cx_iface.c
+++ b/av1/av1_cx_iface.c
@@ -127,6 +127,8 @@
   int use_intra_dct_only;
   int use_inter_dct_only;
   int quant_b_adapt;
+  COST_UPDATE_TYPE coeff_cost_upd_freq;
+  COST_UPDATE_TYPE mode_cost_upd_freq;
 };
 
 static struct av1_extracfg default_extra_cfg = {
@@ -218,12 +220,14 @@
   0,   // noise_level
   32,  // noise_block_size
 #endif
-  0,  // chroma_subsampling_x
-  0,  // chroma_subsampling_y
-  0,  // reduced_tx_type_set
-  0,  // use_intra_dct_only
-  0,  // use_inter_dct_only
-  0,  // quant_b_adapt
+  0,            // chroma_subsampling_x
+  0,            // chroma_subsampling_y
+  0,            // reduced_tx_type_set
+  0,            // use_intra_dct_only
+  0,            // use_inter_dct_only
+  0,            // quant_b_adapt
+  COST_UPD_SB,  // coeff_cost_upd_freq
+  COST_UPD_SB,  // mode_cost_upd_freq
 };
 
 struct aom_codec_alg_priv {
@@ -433,6 +437,8 @@
   RANGE_CHECK_HI(extra_cfg, chroma_subsampling_y, 1);
 
   RANGE_CHECK_HI(extra_cfg, disable_trellis_quant, 2);
+  RANGE_CHECK(extra_cfg, coeff_cost_upd_freq, 0, 2);
+  RANGE_CHECK(extra_cfg, mode_cost_upd_freq, 0, 2);
 
   return AOM_CODEC_OK;
 }
@@ -586,6 +592,8 @@
   oxcf->use_intra_dct_only = extra_cfg->use_intra_dct_only;
   oxcf->use_inter_dct_only = extra_cfg->use_inter_dct_only;
   oxcf->quant_b_adapt = extra_cfg->quant_b_adapt;
+  oxcf->coeff_cost_upd_freq = (COST_UPDATE_TYPE)extra_cfg->coeff_cost_upd_freq;
+  oxcf->mode_cost_upd_freq = (COST_UPDATE_TYPE)extra_cfg->mode_cost_upd_freq;
 #if CONFIG_DIST_8X8
   oxcf->using_dist_8x8 = extra_cfg->enable_dist_8x8;
   if (extra_cfg->tuning == AOM_TUNE_CDEF_DIST ||
@@ -1333,6 +1341,20 @@
   return update_extra_cfg(ctx, &extra_cfg);
 }
 
+static aom_codec_err_t ctrl_set_coeff_cost_upd_freq(aom_codec_alg_priv_t *ctx,
+                                                    va_list args) {
+  struct av1_extracfg extra_cfg = ctx->extra_cfg;
+  extra_cfg.coeff_cost_upd_freq = CAST(AV1E_SET_COEFF_COST_UPD_FREQ, args);
+  return update_extra_cfg(ctx, &extra_cfg);
+}
+
+static aom_codec_err_t ctrl_set_mode_cost_upd_freq(aom_codec_alg_priv_t *ctx,
+                                                   va_list args) {
+  struct av1_extracfg extra_cfg = ctx->extra_cfg;
+  extra_cfg.mode_cost_upd_freq = CAST(AV1E_SET_MODE_COST_UPD_FREQ, args);
+  return update_extra_cfg(ctx, &extra_cfg);
+}
+
 static aom_codec_err_t ctrl_set_film_grain_test_vector(
     aom_codec_alg_priv_t *ctx, va_list args) {
   struct av1_extracfg extra_cfg = ctx->extra_cfg;
@@ -2057,6 +2079,8 @@
   { AV1E_SET_INTRA_DCT_ONLY, ctrl_set_intra_dct_only },
   { AV1E_SET_INTER_DCT_ONLY, ctrl_set_inter_dct_only },
   { AV1E_SET_QUANT_B_ADAPT, ctrl_set_quant_b_adapt },
+  { AV1E_SET_COEFF_COST_UPD_FREQ, ctrl_set_coeff_cost_upd_freq },
+  { AV1E_SET_MODE_COST_UPD_FREQ, ctrl_set_mode_cost_upd_freq },
   { AV1E_SET_DELTAQ_MODE, ctrl_set_deltaq_mode },
   { AV1E_SET_FRAME_PERIODIC_BOOST, ctrl_set_frame_periodic_boost },
   { AV1E_SET_TUNE_CONTENT, ctrl_set_tune_content },
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index 0ec8bf3..6f1a296 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -5735,8 +5735,32 @@
                           wt_left, wt_tr);
       }
     }
-    av1_fill_coeff_costs(&td->mb, xd->tile_ctx, num_planes);
-    av1_fill_mode_rates(cm, x, xd->tile_ctx);
+
+    switch (cpi->oxcf.coeff_cost_upd_freq) {
+      case COST_UPD_TILE:  // Tile level
+        if (mi_row != tile_info->mi_row_start) break;
+        AOM_FALLTHROUGH_INTENDED;
+      case COST_UPD_SBROW:  // SB row level in tile
+        if (mi_col != tile_info->mi_col_start) break;
+        AOM_FALLTHROUGH_INTENDED;
+      case COST_UPD_SB:  // SB level
+        av1_fill_coeff_costs(&td->mb, xd->tile_ctx, num_planes);
+        break;
+      default: assert(0);
+    }
+
+    switch (cpi->oxcf.mode_cost_upd_freq) {
+      case COST_UPD_TILE:  // Tile level
+        if (mi_row != tile_info->mi_row_start) break;
+        AOM_FALLTHROUGH_INTENDED;
+      case COST_UPD_SBROW:  // SB row level in tile
+        if (mi_col != tile_info->mi_col_start) break;
+        AOM_FALLTHROUGH_INTENDED;
+      case COST_UPD_SB:  // SB level
+        av1_fill_mode_rates(cm, x, xd->tile_ctx);
+        break;
+      default: assert(0);
+    }
 
     if (sf->adaptive_pred_interp_filter) {
       for (int i = 0; i < leaf_nodes; ++i) {
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index 9050a89..bccaa82 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -170,6 +170,12 @@
   int base_qindex;
 } TplDepFrame;
 
+typedef enum {
+  COST_UPD_SB,
+  COST_UPD_SBROW,
+  COST_UPD_TILE,
+} COST_UPDATE_TYPE;
+
 #define TPL_DEP_COST_SCALE_LOG2 4
 
 typedef struct AV1EncoderConfig {
@@ -378,6 +384,8 @@
   int use_intra_dct_only;
   int use_inter_dct_only;
   int quant_b_adapt;
+  COST_UPDATE_TYPE coeff_cost_upd_freq;
+  COST_UPDATE_TYPE mode_cost_upd_freq;
   int border_in_pixels;
 } AV1EncoderConfig;