Add an encoder control for error_resilient_mode

error_resilient_mode is now an encoder control in extra_cfg
which can be used to turn the mode on or off for certain frames
but not all. This control will also be subsequently used to write
better tests.

The global g_error_resilient config flag now represents the
case where all frames are coded in error_resilient_mode. The
command-line option for setting this now is --global-error-resilient.
The new control in extra_cfg is set with --error-resilient, and both
currently will have the same effect. However, it is likely that
global-error-resilient may mean something else in the future
such as also turning off order hints or mfmv. Or we can remove
the opton and the g_error_resilient config flag entirely in the
future.

Change-Id: Iae4f03014655580ab97a7e33dedad6893a89e9bb
diff --git a/aom/aomcx.h b/aom/aomcx.h
index 5b9cf66..098b258 100644
--- a/aom/aomcx.h
+++ b/aom/aomcx.h
@@ -313,6 +313,16 @@
    */
   AV1E_SET_FRAME_PARALLEL_DECODING,
 
+  /*!\brief Codec control function to enable error_resilient_mode
+   *
+   * AV1 has a bitstream feature to guarantee parseability of a frame
+   * by turning on the error_resilient_decoding mode, even though the
+   * reference buffers are unreliable or not received.
+   *
+   * By default, this feature is off.
+   */
+  AV1E_SET_ERROR_RESILIENT_MODE,
+
   /*!\brief Codec control function to set adaptive quantization mode.
    *
    * AV1 has a segment based feature that allows encoder to adaptively change
@@ -1016,6 +1026,9 @@
 AOM_CTRL_USE_TYPE(AV1E_SET_FRAME_PARALLEL_DECODING, unsigned int)
 #define AOM_CTRL_AV1E_SET_FRAME_PARALLEL_DECODING
 
+AOM_CTRL_USE_TYPE(AV1E_SET_ERROR_RESILIENT_MODE, unsigned int)
+#define AOM_CTRL_AV1E_SET_ERROR_RESILIENT_MODE
+
 AOM_CTRL_USE_TYPE(AV1E_SET_AQ_MODE, unsigned int)
 #define AOM_CTRL_AV1E_SET_AQ_MODE
 
diff --git a/aomenc.c b/aomenc.c
index 57b0fe5..1b6a741 100644
--- a/aomenc.c
+++ b/aomenc.c
@@ -261,8 +261,9 @@
 #endif
 static const arg_def_t timebase = ARG_DEF(
     NULL, "timebase", 1, "Output timestamp precision (fractional seconds)");
-static const arg_def_t error_resilient =
-    ARG_DEF(NULL, "error-resilient", 1, "Enable error resiliency features");
+static const arg_def_t global_error_resilient =
+    ARG_DEF(NULL, "global-error-resilient", 1,
+            "Enable global error resiliency features");
 static const arg_def_t lag_in_frames =
     ARG_DEF(NULL, "lag-in-frames", 1, "Max number of frames to lag");
 static const arg_def_t large_scale_tile =
@@ -290,7 +291,7 @@
 #endif
                                           &timebase,
                                           &framerate,
-                                          &error_resilient,
+                                          &global_error_resilient,
                                           &bitdeptharg,
                                           &lag_in_frames,
                                           &large_scale_tile,
@@ -479,6 +480,10 @@
     ARG_DEF(NULL, "frame-parallel", 1,
             "Enable frame parallel decodability features "
             "(0: false (default), 1: true)");
+static const arg_def_t error_resilient_mode =
+    ARG_DEF(NULL, "error-resilient", 1,
+            "Enable error resilient features "
+            "(0: false (default), 1: true)");
 #if !CONFIG_EXT_DELTA_Q
 static const arg_def_t aq_mode = ARG_DEF(
     NULL, "aq-mode", 1,
@@ -640,6 +645,7 @@
                                        &enable_dist_8x8,
 #endif
                                        &frame_parallel_decoding,
+                                       &error_resilient_mode,
                                        &aq_mode,
 #if CONFIG_EXT_DELTA_Q
                                        &deltaq_mode,
@@ -695,6 +701,7 @@
                                         AV1E_SET_ENABLE_DIST_8X8,
 #endif
                                         AV1E_SET_FRAME_PARALLEL_DECODING,
+                                        AV1E_SET_ERROR_RESILIENT_MODE,
                                         AV1E_SET_AQ_MODE,
 #if CONFIG_EXT_DELTA_Q
                                         AV1E_SET_DELTAQ_MODE,
@@ -1178,7 +1185,7 @@
     } else if (arg_match(&arg, &timebase, argi)) {
       config->cfg.g_timebase = arg_parse_rational(&arg);
       validate_positive_rational(arg.name, &config->cfg.g_timebase);
-    } else if (arg_match(&arg, &error_resilient, argi)) {
+    } else if (arg_match(&arg, &global_error_resilient, argi)) {
       config->cfg.g_error_resilient = arg_parse_uint(&arg);
     } else if (arg_match(&arg, &lag_in_frames, argi)) {
       config->cfg.g_lag_in_frames = arg_parse_uint(&arg);
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c
index 3e29595..d5dbcfc 100644
--- a/av1/av1_cx_iface.c
+++ b/av1/av1_cx_iface.c
@@ -86,6 +86,7 @@
   int render_height;
   aom_superblock_size_t superblock_size;
   unsigned int single_tile_decoding;
+  int error_resilient_mode;
 
 #if CONFIG_FILM_GRAIN
   int film_grain_test_vector;
@@ -155,6 +156,7 @@
   0,                            // render height
   AOM_SUPERBLOCK_SIZE_DYNAMIC,  // superblock_size
   0,                            // Single tile decoding is off by default.
+  0,                            // error_resilient_mode off by default.
 
 #if CONFIG_FILM_GRAIN
   0,  // film_grain_test_vector
@@ -670,7 +672,8 @@
   for (int i = 0; i < oxcf->tile_height_count; i++) {
     oxcf->tile_heights[i] = AOMMAX(cfg->tile_heights[i], 1);
   }
-  oxcf->error_resilient_mode = cfg->g_error_resilient;
+  oxcf->error_resilient_mode =
+      cfg->g_error_resilient | extra_cfg->error_resilient_mode;
   oxcf->frame_parallel_decoding_mode = extra_cfg->frame_parallel_decoding_mode;
 
   oxcf->aq_mode = extra_cfg->aq_mode;
@@ -979,6 +982,13 @@
   return update_extra_cfg(ctx, &extra_cfg);
 }
 
+static aom_codec_err_t ctrl_set_error_resilient_mode(aom_codec_alg_priv_t *ctx,
+                                                     va_list args) {
+  struct av1_extracfg extra_cfg = ctx->extra_cfg;
+  extra_cfg.error_resilient_mode = CAST(AV1E_SET_ERROR_RESILIENT_MODE, args);
+  return update_extra_cfg(ctx, &extra_cfg);
+}
+
 static aom_codec_err_t ctrl_set_frame_parallel_decoding_mode(
     aom_codec_alg_priv_t *ctx, va_list args) {
   struct av1_extracfg extra_cfg = ctx->extra_cfg;
@@ -1625,6 +1635,7 @@
   { AV1E_SET_TIMING_INFO, ctrl_set_timing_info },
   { AV1E_SET_DISABLE_TEMPMV, ctrl_set_disable_tempmv },
   { AV1E_SET_FRAME_PARALLEL_DECODING, ctrl_set_frame_parallel_decoding_mode },
+  { AV1E_SET_ERROR_RESILIENT_MODE, ctrl_set_error_resilient_mode },
   { AV1E_SET_ENABLE_DF, ctrl_set_enable_df },
   { AV1E_SET_ENABLE_ORDER_HINT, ctrl_set_enable_order_hint },
   { AV1E_SET_ENABLE_JNT_COMP, ctrl_set_enable_jnt_comp },