Reduce svc layer context memory conditionally

In case of non svc, allocate only one instance of
layer context memory. For svc, allocate number of
spatial layers times number of temporal layers
instances.

              Peak Memory Reduction (%)
Resolution    single thread (rt speed 10)
320x180          5.16
320x240          4.64
640x360          2.49
640x480          2.06
1280x720         0.84

HEAP memory reduction was measured using the following command.
$valgrind --tool=massif ./aomenc ...

Change-Id: I528f65598f530bb27da09657ba1cd07a5f4430ed
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c
index b05f45f..472200c 100644
--- a/av1/av1_cx_iface.c
+++ b/av1/av1_cx_iface.c
@@ -2850,6 +2850,10 @@
   if (res == AOM_CODEC_OK) {
     AV1_COMP *cpi = ppi->cpi;
 
+    const int num_layers =
+        cpi->svc.number_spatial_layers * cpi->svc.number_temporal_layers;
+    av1_alloc_layer_context(cpi, num_layers);
+
     // Set up internal flags
     if (ctx->base.init_flags & AOM_CODEC_USE_PSNR) ppi->b_calculate_psnr = 1;
 
@@ -3371,6 +3375,10 @@
   if (ppi->number_spatial_layers > 1 || ppi->number_temporal_layers > 1) {
     unsigned int sl, tl;
     ctx->ppi->use_svc = 1;
+    const int num_layers =
+        ppi->number_spatial_layers * ppi->number_temporal_layers;
+    av1_alloc_layer_context(cpi, num_layers);
+
     for (sl = 0; sl < ppi->number_spatial_layers; ++sl) {
       for (tl = 0; tl < ppi->number_temporal_layers; ++tl) {
         const int layer = LAYER_IDS_TO_IDX(sl, tl, ppi->number_temporal_layers);
diff --git a/av1/encoder/encoder_alloc.h b/av1/encoder/encoder_alloc.h
index 72c823e..fd350f0 100644
--- a/av1/encoder/encoder_alloc.h
+++ b/av1/encoder/encoder_alloc.h
@@ -294,6 +294,8 @@
   }
 
   if (cpi->ppi->use_svc) av1_free_svc_cyclic_refresh(cpi);
+  aom_free(cpi->svc.layer_context);
+  cpi->svc.layer_context = NULL;
 
   if (cpi->consec_zero_mv) {
     aom_free(cpi->consec_zero_mv);
diff --git a/av1/encoder/svc_layercontext.c b/av1/encoder/svc_layercontext.c
index cb396b4..2575b1b 100644
--- a/av1/encoder/svc_layercontext.c
+++ b/av1/encoder/svc_layercontext.c
@@ -81,6 +81,18 @@
   }
 }
 
+void av1_alloc_layer_context(AV1_COMP *cpi, int num_layers) {
+  AV1_COMMON *const cm = &cpi->common;
+  SVC *const svc = &cpi->svc;
+  if (svc->layer_context == NULL || svc->num_allocated_layers < num_layers) {
+    aom_free(svc->layer_context);
+    CHECK_MEM_ERROR(
+        cm, svc->layer_context,
+        (LAYER_CONTEXT *)aom_calloc(num_layers, sizeof(*svc->layer_context)));
+    svc->num_allocated_layers = num_layers;
+  }
+}
+
 // Update the layer context from a change_config() call.
 void av1_update_layer_context_change_config(AV1_COMP *const cpi,
                                             const int64_t target_bandwidth) {
diff --git a/av1/encoder/svc_layercontext.h b/av1/encoder/svc_layercontext.h
index 844d393..a27d768 100644
--- a/av1/encoder/svc_layercontext.h
+++ b/av1/encoder/svc_layercontext.h
@@ -112,7 +112,12 @@
   /*!
    * Layer context used for rate control in CBR mode.
    */
-  LAYER_CONTEXT layer_context[AOM_MAX_LAYERS];
+  LAYER_CONTEXT *layer_context;
+
+  /*!
+   * Number of layers allocated for layer_context.
+   */
+  int num_allocated_layers;
 
   /*!
    * EIGHTTAP_SMOOTH or BILINEAR
@@ -145,6 +150,19 @@
  */
 void av1_init_layer_context(struct AV1_COMP *const cpi);
 
+/*!\brief Allocate layer context data.
+ *
+ * \ingroup SVC
+ * \callgraph
+ * \callergraph
+ *
+ * \param[in]       cpi  Top level encoder structure
+ * \param[in]       num_layers  Number of layers to be allocated
+ *
+ * \remark  Nothing returned. Allocates memory for cpi->svc.layer_context.
+ */
+void av1_alloc_layer_context(struct AV1_COMP *cpi, int num_layers);
+
 /*!\brief Update the layer context from a change_config() call.
  *
  * \ingroup SVC
diff --git a/av1/ratectrl_rtc.cc b/av1/ratectrl_rtc.cc
index feaa403..db6fbcd 100644
--- a/av1/ratectrl_rtc.cc
+++ b/av1/ratectrl_rtc.cc
@@ -68,6 +68,8 @@
   av1_zero(*rc_api->cpi_->ppi);
   rc_api->cpi_->common.seq_params = &rc_api->cpi_->ppi->seq_params;
   av1_zero(*rc_api->cpi_->common.seq_params);
+  const int num_layers = cfg.ss_number_layers * cfg.ts_number_layers;
+  av1_alloc_layer_context(rc_api->cpi_, num_layers);
   rc_api->InitRateControl(cfg);
   if (cfg.aq_mode) {
     AV1_COMP *const cpi = rc_api->cpi_;
@@ -95,6 +97,9 @@
         }
       }
     }
+    aom_free(cpi_->svc.layer_context);
+    cpi_->svc.layer_context = nullptr;
+
     if (cpi_->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ) {
       aom_free(cpi_->enc_seg.map);
       cpi_->enc_seg.map = nullptr;