Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / libvpx / source / libvpx / vp9 / vp9_cx_iface.c
index 5d63dc9..8072f78 100644 (file)
@@ -25,14 +25,13 @@ struct vp9_extracfg {
   int                         cpu_used;  /* available cpu percentage in 1/16 */
   unsigned int                enable_auto_alt_ref;
   unsigned int                noise_sensitivity;
-  unsigned int                Sharpness;
+  unsigned int                sharpness;
   unsigned int                static_thresh;
   unsigned int                tile_columns;
   unsigned int                tile_rows;
   unsigned int                arnr_max_frames;
   unsigned int                arnr_strength;
   unsigned int                arnr_type;
-  unsigned int                experimental;
   vp8e_tuning                 tuning;
   unsigned int                cq_level;         /* constrained quality level */
   unsigned int                rc_max_intra_bitrate_pct;
@@ -54,14 +53,13 @@ static const struct extraconfig_map extracfg_map[] = {
       0,                          /* cpu_used      */
       1,                          /* enable_auto_alt_ref */
       0,                          /* noise_sensitivity */
-      0,                          /* Sharpness */
+      0,                          /* sharpness */
       0,                          /* static_thresh */
       0,                          /* tile_columns */
       0,                          /* tile_rows */
       7,                          /* arnr_max_frames */
       5,                          /* arnr_strength */
       3,                          /* arnr_type*/
-      0,                          /* experimental mode */
       0,                          /* tuning*/
       10,                         /* cq_level */
       0,                          /* rc_max_intra_bitrate_pct */
@@ -177,6 +175,23 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t      *ctx,
 
   RANGE_CHECK(cfg, ss_number_layers,      1,
               VPX_SS_MAX_LAYERS); /*Spatial layers max */
+
+  RANGE_CHECK(cfg, ts_number_layers, 1, VPX_TS_MAX_LAYERS);
+  if (cfg->ts_number_layers > 1) {
+    unsigned int i;
+    for (i = 1; i < cfg->ts_number_layers; ++i) {
+      if (cfg->ts_target_bitrate[i] < cfg->ts_target_bitrate[i-1]) {
+        ERROR("ts_target_bitrate entries are not increasing");
+      }
+    }
+    RANGE_CHECK(cfg, ts_rate_decimator[cfg->ts_number_layers-1], 1, 1);
+    for (i = cfg->ts_number_layers-2; i > 0; --i) {
+      if (cfg->ts_rate_decimator[i-1] != 2*cfg->ts_rate_decimator[i]) {
+        ERROR("ts_rate_decimator factors are not powers of 2");
+      }
+    }
+  }
+
   /* VP8 does not support a lower bound on the keyframe interval in
    * automatic keyframe placement mode.
    */
@@ -192,7 +207,7 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t      *ctx,
 
   RANGE_CHECK(vp8_cfg, tile_columns, 0, 6);
   RANGE_CHECK(vp8_cfg, tile_rows, 0, 2);
-  RANGE_CHECK_HI(vp8_cfg, Sharpness,       7);
+  RANGE_CHECK_HI(vp8_cfg, sharpness, 7);
   RANGE_CHECK(vp8_cfg, arnr_max_frames, 0, 15);
   RANGE_CHECK_HI(vp8_cfg, arnr_strength,   6);
   RANGE_CHECK(vp8_cfg, arnr_type,       1, 3);
@@ -207,7 +222,7 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t      *ctx,
     int              n_packets = (int)(cfg->rc_twopass_stats_in.sz / packet_sz);
     FIRSTPASS_STATS *stats;
 
-    if (!cfg->rc_twopass_stats_in.buf)
+    if (cfg->rc_twopass_stats_in.buf == NULL)
       ERROR("rc_twopass_stats_in.buf not set.");
 
     if (cfg->rc_twopass_stats_in.sz % packet_sz)
@@ -250,7 +265,7 @@ static vpx_codec_err_t validate_img(vpx_codec_alg_priv_t *ctx,
 static vpx_codec_err_t set_vp9e_config(VP9_CONFIG *oxcf,
                                        vpx_codec_enc_cfg_t cfg,
                                        struct vp9_extracfg vp8_cfg) {
-  oxcf->version = cfg.g_profile | (vp8_cfg.experimental ? 0x4 : 0);
+  oxcf->version = cfg.g_profile;
   oxcf->width   = cfg.g_w;
   oxcf->height  = cfg.g_h;
   /* guess a frame rate if out of whack, use 30 */
@@ -263,13 +278,13 @@ static vpx_codec_err_t set_vp9e_config(VP9_CONFIG *oxcf,
 
   switch (cfg.g_pass) {
     case VPX_RC_ONE_PASS:
-      oxcf->Mode = MODE_GOODQUALITY;
+      oxcf->mode = MODE_GOODQUALITY;
       break;
     case VPX_RC_FIRST_PASS:
-      oxcf->Mode = MODE_FIRSTPASS;
+      oxcf->mode = MODE_FIRSTPASS;
       break;
     case VPX_RC_LAST_PASS:
-      oxcf->Mode = MODE_SECONDPASS_BEST;
+      oxcf->mode = MODE_SECONDPASS_BEST;
       break;
   }
 
@@ -281,14 +296,11 @@ static vpx_codec_err_t set_vp9e_config(VP9_CONFIG *oxcf,
     oxcf->lag_in_frames = cfg.g_lag_in_frames;
   }
 
-  // VBR only supported for now.
-  // CBR code has been deprectated for experimental phase.
-  // CQ mode not yet tested
-  oxcf->end_usage        = USAGE_LOCAL_FILE_PLAYBACK;
+  oxcf->end_usage   = USAGE_LOCAL_FILE_PLAYBACK;
   if (cfg.rc_end_usage == VPX_CQ)
-    oxcf->end_usage      = USAGE_CONSTRAINED_QUALITY;
+    oxcf->end_usage = USAGE_CONSTRAINED_QUALITY;
   else if (cfg.rc_end_usage == VPX_Q)
-    oxcf->end_usage      = USAGE_CONSTANT_QUALITY;
+    oxcf->end_usage = USAGE_CONSTANT_QUALITY;
   else if (cfg.rc_end_usage == VPX_CBR)
     oxcf->end_usage = USAGE_STREAM_FROM_SERVER;
 
@@ -318,14 +330,11 @@ static vpx_codec_err_t set_vp9e_config(VP9_CONFIG *oxcf,
   // oxcf->kf_min_dist         = cfg.kf_min_dis;
   oxcf->key_freq               = cfg.kf_max_dist;
 
-  // oxcf->delete_first_pass_file = cfg.g_delete_firstpassfile;
-  // strcpy(oxcf->first_pass_file, cfg.g_firstpass_file);
-
   oxcf->cpu_used               =  vp8_cfg.cpu_used;
   oxcf->encode_breakout        =  vp8_cfg.static_thresh;
   oxcf->play_alternate         =  vp8_cfg.enable_auto_alt_ref;
   oxcf->noise_sensitivity      =  vp8_cfg.noise_sensitivity;
-  oxcf->Sharpness              =  vp8_cfg.Sharpness;
+  oxcf->sharpness              =  vp8_cfg.sharpness;
 
   oxcf->two_pass_stats_in      =  cfg.rc_twopass_stats_in;
   oxcf->output_pkt_list        =  vp8_cfg.pkt_list;
@@ -347,14 +356,26 @@ static vpx_codec_err_t set_vp9e_config(VP9_CONFIG *oxcf,
   oxcf->aq_mode = vp8_cfg.aq_mode;
 
   oxcf->ss_number_layers = cfg.ss_number_layers;
+
+  oxcf->ts_number_layers = cfg.ts_number_layers;
+
+  if (oxcf->ts_number_layers > 1) {
+    memcpy(oxcf->ts_target_bitrate, cfg.ts_target_bitrate,
+           sizeof(cfg.ts_target_bitrate));
+    memcpy(oxcf->ts_rate_decimator, cfg.ts_rate_decimator,
+           sizeof(cfg.ts_rate_decimator));
+  } else if (oxcf->ts_number_layers == 1) {
+    oxcf->ts_target_bitrate[0] = oxcf->target_bandwidth;
+    oxcf->ts_rate_decimator[0] = 1;
+  }
+
   /*
   printf("Current VP9 Settings: \n");
   printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
   printf("noise_sensitivity: %d\n", oxcf->noise_sensitivity);
-  printf("Sharpness: %d\n",    oxcf->Sharpness);
+  printf("sharpness: %d\n",    oxcf->sharpness);
   printf("cpu_used: %d\n",  oxcf->cpu_used);
-  printf("Mode: %d\n",     oxcf->Mode);
-  // printf("delete_first_pass_file: %d\n",  oxcf->delete_first_pass_file);
+  printf("Mode: %d\n",     oxcf->mode);
   printf("auto_key: %d\n",  oxcf->auto_key);
   printf("key_freq: %d\n", oxcf->key_freq);
   printf("end_usage: %d\n", oxcf->end_usage);
@@ -398,7 +419,7 @@ static vpx_codec_err_t vp9e_set_config(vpx_codec_alg_priv_t       *ctx,
 
   res = validate_config(ctx, cfg, &ctx->vp8_cfg);
 
-  if (!res) {
+  if (res == VPX_CODEC_OK) {
     ctx->cfg = *cfg;
     set_vp9e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg);
     vp9_change_config(ctx->cpi, &ctx->oxcf);
@@ -418,8 +439,7 @@ static vpx_codec_err_t get_param(vpx_codec_alg_priv_t *ctx,
 
 #define MAP(id, var) case id: *(RECAST(id, arg)) = var; break
 
-  if (!arg)
-    return VPX_CODEC_INVALID_PARAM;
+  if (arg == NULL) return VPX_CODEC_INVALID_PARAM;
 
   switch (ctrl_id) {
       MAP(VP8E_GET_LAST_QUANTIZER, vp9_get_quantizer(ctx->cpi));
@@ -444,7 +464,7 @@ static vpx_codec_err_t set_param(vpx_codec_alg_priv_t *ctx,
       MAP(VP8E_SET_CPUUSED,                 xcfg.cpu_used);
       MAP(VP8E_SET_ENABLEAUTOALTREF,        xcfg.enable_auto_alt_ref);
       MAP(VP8E_SET_NOISE_SENSITIVITY,       xcfg.noise_sensitivity);
-      MAP(VP8E_SET_SHARPNESS,               xcfg.Sharpness);
+      MAP(VP8E_SET_SHARPNESS,               xcfg.sharpness);
       MAP(VP8E_SET_STATIC_THRESHOLD,        xcfg.static_thresh);
       MAP(VP9E_SET_TILE_COLUMNS,            xcfg.tile_columns);
       MAP(VP9E_SET_TILE_ROWS,               xcfg.tile_rows);
@@ -461,7 +481,7 @@ static vpx_codec_err_t set_param(vpx_codec_alg_priv_t *ctx,
 
   res = validate_config(ctx, &ctx->cfg, &xcfg);
 
-  if (!res) {
+  if (res == VPX_CODEC_OK) {
     ctx->vp8_cfg = xcfg;
     set_vp9e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg);
     vp9_change_config(ctx->cpi, &ctx->oxcf);
@@ -472,8 +492,7 @@ static vpx_codec_err_t set_param(vpx_codec_alg_priv_t *ctx,
 }
 
 
-static vpx_codec_err_t vp9e_common_init(vpx_codec_ctx_t *ctx,
-                                        int              experimental) {
+static vpx_codec_err_t vp9e_common_init(vpx_codec_ctx_t *ctx) {
   vpx_codec_err_t            res = VPX_CODEC_OK;
   struct vpx_codec_alg_priv *priv;
   vpx_codec_enc_cfg_t       *cfg;
@@ -481,12 +500,10 @@ static vpx_codec_err_t vp9e_common_init(vpx_codec_ctx_t *ctx,
 
   VP9_PTR optr;
 
-  if (!ctx->priv) {
+  if (ctx->priv == NULL) {
     priv = calloc(1, sizeof(struct vpx_codec_alg_priv));
 
-    if (!priv) {
-      return VPX_CODEC_MEM_ERROR;
-    }
+    if (priv == NULL) return VPX_CODEC_MEM_ERROR;
 
     ctx->priv = &priv->base;
     ctx->priv->sz = sizeof(*ctx->priv);
@@ -515,32 +532,27 @@ static vpx_codec_err_t vp9e_common_init(vpx_codec_ctx_t *ctx,
 
     priv->vp8_cfg = extracfg_map[i].cfg;
     priv->vp8_cfg.pkt_list = &priv->pkt_list.head;
-    priv->vp8_cfg.experimental = experimental;
 
-    // TODO(agrange) Check the limits set on this buffer, or the check that is
-    // applied in vp9e_encode.
+    // Maximum buffer size approximated based on having multiple ARF.
     priv->cx_data_sz = priv->cfg.g_w * priv->cfg.g_h * 3 / 2 * 8;
-//    priv->cx_data_sz = priv->cfg.g_w * priv->cfg.g_h * 3 / 2 * 2;
 
     if (priv->cx_data_sz < 4096) priv->cx_data_sz = 4096;
 
     priv->cx_data = malloc(priv->cx_data_sz);
 
-    if (!priv->cx_data) {
-      return VPX_CODEC_MEM_ERROR;
-    }
+    if (priv->cx_data == NULL) return VPX_CODEC_MEM_ERROR;
 
     vp9_initialize_enc();
 
     res = validate_config(priv, &priv->cfg, &priv->vp8_cfg);
 
-    if (!res) {
+    if (res == VPX_CODEC_OK) {
       set_vp9e_config(&ctx->priv->alg_priv->oxcf,
                       ctx->priv->alg_priv->cfg,
                       ctx->priv->alg_priv->vp8_cfg);
       optr = vp9_create_compressor(&ctx->priv->alg_priv->oxcf);
 
-      if (!optr)
+      if (optr == NULL)
         res = VPX_CODEC_MEM_ERROR;
       else
         ctx->priv->alg_priv->cpi = optr;
@@ -553,18 +565,9 @@ static vpx_codec_err_t vp9e_common_init(vpx_codec_ctx_t *ctx,
 
 static vpx_codec_err_t vp9e_init(vpx_codec_ctx_t *ctx,
                                  vpx_codec_priv_enc_mr_cfg_t *data) {
-  return vp9e_common_init(ctx, 0);
+  return vp9e_common_init(ctx);
 }
 
-
-#if CONFIG_EXPERIMENTAL
-static vpx_codec_err_t vp9e_exp_init(vpx_codec_ctx_t *ctx,
-                                     vpx_codec_priv_enc_mr_cfg_t *data) {
-  return vp9e_common_init(ctx, 1);
-}
-#endif
-
-
 static vpx_codec_err_t vp9e_destroy(vpx_codec_alg_priv_t *ctx) {
   free(ctx->cx_data);
   vp9_remove_compressor(&ctx->cpi);
@@ -578,10 +581,21 @@ static void pick_quickcompress_mode(vpx_codec_alg_priv_t  *ctx,
   unsigned int new_qc;
 
   /* Use best quality mode if no deadline is given. */
-  if (deadline)
-    new_qc = MODE_GOODQUALITY;
-  else
-    new_qc = MODE_BESTQUALITY;
+  new_qc = MODE_BESTQUALITY;
+
+  if (deadline) {
+      uint64_t     duration_us;
+
+      /* Convert duration parameter from stream timebase to microseconds */
+      duration_us = (uint64_t)duration * 1000000
+                    * (uint64_t)ctx->cfg.g_timebase.num
+                    / (uint64_t)ctx->cfg.g_timebase.den;
+
+      /* If the deadline is more that the duration this frame is to be shown,
+       * use good quality mode. Otherwise use realtime mode.
+       */
+      new_qc = (deadline > duration_us) ? MODE_GOODQUALITY : MODE_REALTIME;
+  }
 
   if (ctx->cfg.g_pass == VPX_RC_FIRST_PASS)
     new_qc = MODE_FIRSTPASS;
@@ -590,8 +604,8 @@ static void pick_quickcompress_mode(vpx_codec_alg_priv_t  *ctx,
              ? MODE_SECONDPASS_BEST
              : MODE_SECONDPASS;
 
-  if (ctx->oxcf.Mode != new_qc) {
-    ctx->oxcf.Mode = new_qc;
+  if (ctx->oxcf.mode != new_qc) {
+    ctx->oxcf.mode = new_qc;
     vp9_change_config(ctx->cpi, &ctx->oxcf);
   }
 }
@@ -705,8 +719,8 @@ static vpx_codec_err_t vp9e_encode(vpx_codec_alg_priv_t  *ctx,
     }
   }
 
-  /* Initialize the encoder instance on the first frame*/
-  if (!res && ctx->cpi) {
+  /* Initialize the encoder instance on the first frame*/
+  if (res == VPX_CODEC_OK && ctx->cpi != NULL) {
     unsigned int lib_flags;
     YV12_BUFFER_CONFIG sd;
     int64_t dst_time_stamp, dst_end_time_stamp;
@@ -717,9 +731,6 @@ static vpx_codec_err_t vp9e_encode(vpx_codec_alg_priv_t  *ctx,
     if (ctx->base.init_flags & VPX_CODEC_USE_PSNR)
       ((VP9_COMP *)ctx->cpi)->b_calculate_psnr = 1;
 
-    // if (ctx->base.init_flags & VPX_CODEC_USE_OUTPUT_PARTITION)
-    //    ((VP9_COMP *)ctx->cpi)->output_partition = 1;
-
     /* Convert API flags to internal codec lib flags */
     lib_flags = (flags & VPX_EFLAG_FORCE_KF) ? FRAMEFLAGS_KEY : 0;
 
@@ -769,8 +780,8 @@ static vpx_codec_err_t vp9e_encode(vpx_codec_alg_priv_t  *ctx,
         VP9_COMP *cpi = (VP9_COMP *)ctx->cpi;
 
         /* Pack invisible frames with the next visible frame */
-        if (!cpi->common.show_frame) {
-          if (!ctx->pending_cx_data)
+        if (cpi->common.show_frame == 0) {
+          if (ctx->pending_cx_data == 0)
             ctx->pending_cx_data = cx_data;
           ctx->pending_cx_data_sz += size;
           ctx->pending_frame_sizes[ctx->pending_frame_count++] = size;
@@ -795,7 +806,7 @@ static vpx_codec_err_t vp9e_encode(vpx_codec_alg_priv_t  *ctx,
         if (lib_flags & FRAMEFLAGS_KEY)
           pkt.data.frame.flags |= VPX_FRAME_IS_KEY;
 
-        if (!cpi->common.show_frame) {
+        if (cpi->common.show_frame == 0) {
           pkt.data.frame.flags |= VPX_FRAME_IS_INVISIBLE;
 
           // This timestamp should be as close as possible to the
@@ -869,10 +880,9 @@ static const vpx_codec_cx_pkt_t *vp9e_get_cxdata(vpx_codec_alg_priv_t  *ctx,
 static vpx_codec_err_t vp9e_set_reference(vpx_codec_alg_priv_t *ctx,
                                           int ctr_id,
                                           va_list args) {
-  vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
+  vpx_ref_frame_t *frame = va_arg(args, vpx_ref_frame_t *);
 
-  if (data) {
-    vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
+  if (frame != NULL) {
     YV12_BUFFER_CONFIG sd;
 
     image2yuvconfig(&frame->img, &sd);
@@ -887,10 +897,9 @@ static vpx_codec_err_t vp9e_set_reference(vpx_codec_alg_priv_t *ctx,
 static vpx_codec_err_t vp9e_copy_reference(vpx_codec_alg_priv_t *ctx,
                                            int ctr_id,
                                            va_list args) {
-  vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
+  vpx_ref_frame_t *frame = va_arg(args, vpx_ref_frame_t *);
 
-  if (data) {
-    vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
+  if (frame != NULL) {
     YV12_BUFFER_CONFIG sd;
 
     image2yuvconfig(&frame->img, &sd);
@@ -905,13 +914,13 @@ static vpx_codec_err_t vp9e_copy_reference(vpx_codec_alg_priv_t *ctx,
 static vpx_codec_err_t get_reference(vpx_codec_alg_priv_t *ctx,
                                      int ctr_id,
                                      va_list args) {
-  vp9_ref_frame_t *data = va_arg(args, vp9_ref_frame_t *);
+  vp9_ref_frame_t *frame = va_arg(args, vp9_ref_frame_t *);
 
-  if (data) {
+  if (frame != NULL) {
     YV12_BUFFER_CONFIG* fb;
 
-    vp9_get_reference_enc(ctx->cpi, data->idx, &fb);
-    yuvconfig2image(&data->img, fb, NULL);
+    vp9_get_reference_enc(ctx->cpi, frame->idx, &fb);
+    yuvconfig2image(&frame->img, fb, NULL);
     return VPX_CODEC_OK;
   } else {
     return VPX_CODEC_INVALID_PARAM;
@@ -922,11 +931,11 @@ static vpx_codec_err_t vp9e_set_previewpp(vpx_codec_alg_priv_t *ctx,
                                           int ctr_id,
                                           va_list args) {
 #if CONFIG_VP9_POSTPROC
-  vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *);
+  vp8_postproc_cfg_t *config = va_arg(args, vp8_postproc_cfg_t *);
   (void)ctr_id;
 
-  if (data) {
-    ctx->preview_ppcfg = *((vp8_postproc_cfg_t *)data);
+  if (config != NULL) {
+    ctx->preview_ppcfg = *config;
     return VPX_CODEC_OK;
   } else {
     return VPX_CODEC_INVALID_PARAM;
@@ -1000,20 +1009,14 @@ static vpx_codec_err_t vp9e_set_activemap(vpx_codec_alg_priv_t *ctx,
 static vpx_codec_err_t vp9e_set_scalemode(vpx_codec_alg_priv_t *ctx,
                                           int ctr_id,
                                           va_list args) {
-  vpx_scaling_mode_t *data =  va_arg(args, vpx_scaling_mode_t *);
+  vpx_scaling_mode_t *scalemode =  va_arg(args, vpx_scaling_mode_t *);
 
-  if (data) {
+  if (scalemode != NULL) {
     int res;
-    vpx_scaling_mode_t scalemode = *(vpx_scaling_mode_t *)data;
     res = vp9_set_internal_size(ctx->cpi,
-                                (VPX_SCALING)scalemode.h_scaling_mode,
-                                (VPX_SCALING)scalemode.v_scaling_mode);
-
-    if (!res) {
-      return VPX_CODEC_OK;
-    } else {
-      return VPX_CODEC_INVALID_PARAM;
-    }
+                                (VPX_SCALING)scalemode->h_scaling_mode,
+                                (VPX_SCALING)scalemode->v_scaling_mode);
+    return (res == 0) ? VPX_CODEC_OK : VPX_CODEC_INVALID_PARAM;
   } else {
     return VPX_CODEC_INVALID_PARAM;
   }
@@ -1023,32 +1026,54 @@ static vpx_codec_err_t vp9e_set_svc(vpx_codec_alg_priv_t *ctx, int ctr_id,
                                     va_list args) {
   int data = va_arg(args, int);
   vp9_set_svc(ctx->cpi, data);
+  // CBR mode for SVC with both temporal and spatial layers not yet supported.
+  if (data == 1 &&
+      ctx->cfg.rc_end_usage == VPX_CBR &&
+      ctx->cfg.ss_number_layers > 1 &&
+      ctx->cfg.ts_number_layers > 1) {
+    return VPX_CODEC_INVALID_PARAM;
+  }
+  return VPX_CODEC_OK;
+}
+
+static vpx_codec_err_t vp9e_set_svc_layer_id(vpx_codec_alg_priv_t *ctx,
+                                             int ctr_id,
+                                             va_list args) {
+  vpx_svc_layer_id_t *data = va_arg(args, vpx_svc_layer_id_t *);
+  VP9_COMP *cpi = (VP9_COMP *)ctx->cpi;
+  cpi->svc.spatial_layer_id = data->spatial_layer_id;
+  cpi->svc.temporal_layer_id = data->temporal_layer_id;
+  // Checks on valid layer_id input.
+  if (cpi->svc.temporal_layer_id < 0 ||
+      cpi->svc.temporal_layer_id >= (int)ctx->cfg.ts_number_layers) {
+    return VPX_CODEC_INVALID_PARAM;
+  }
+  if (cpi->svc.spatial_layer_id < 0 ||
+      cpi->svc.spatial_layer_id >= ctx->cfg.ss_number_layers) {
+    return VPX_CODEC_INVALID_PARAM;
+  }
   return VPX_CODEC_OK;
 }
 
 static vpx_codec_err_t vp9e_set_svc_parameters(vpx_codec_alg_priv_t *ctx,
                                                int ctr_id, va_list args) {
-  vpx_svc_parameters_t *data = va_arg(args, vpx_svc_parameters_t *);
   VP9_COMP *cpi = (VP9_COMP *)ctx->cpi;
-  vpx_svc_parameters_t params;
+  vpx_svc_parameters_t *params = va_arg(args, vpx_svc_parameters_t *);
 
-  if (data == NULL) {
-    return VPX_CODEC_INVALID_PARAM;
-  }
+  if (params == NULL) return VPX_CODEC_INVALID_PARAM;
 
-  params = *(vpx_svc_parameters_t *)data;
+  cpi->svc.spatial_layer_id = params->spatial_layer;
+  cpi->svc.temporal_layer_id = params->temporal_layer;
 
-  cpi->current_layer = params.layer;
-  cpi->lst_fb_idx = params.lst_fb_idx;
-  cpi->gld_fb_idx = params.gld_fb_idx;
-  cpi->alt_fb_idx = params.alt_fb_idx;
+  cpi->lst_fb_idx = params->lst_fb_idx;
+  cpi->gld_fb_idx = params->gld_fb_idx;
+  cpi->alt_fb_idx = params->alt_fb_idx;
 
-  if (vp9_set_size_literal(ctx->cpi, params.width, params.height) != 0) {
+  if (vp9_set_size_literal(ctx->cpi, params->width, params->height) != 0)
     return VPX_CODEC_INVALID_PARAM;
-  }
 
-  ctx->cfg.rc_max_quantizer = params.max_quantizer;
-  ctx->cfg.rc_min_quantizer = params.min_quantizer;
+  ctx->cfg.rc_max_quantizer = params->max_quantizer;
+  ctx->cfg.rc_min_quantizer = params->min_quantizer;
 
   set_vp9e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg);
   vp9_change_config(ctx->cpi, &ctx->oxcf);
@@ -1087,6 +1112,7 @@ static vpx_codec_ctrl_fn_map_t vp9e_ctf_maps[] = {
   {VP9_GET_REFERENCE,                 get_reference},
   {VP9E_SET_SVC,                      vp9e_set_svc},
   {VP9E_SET_SVC_PARAMETERS,           vp9e_set_svc_parameters},
+  {VP9E_SET_SVC_LAYER_ID,             vp9e_set_svc_layer_id},
   { -1, NULL},
 };
 
@@ -1137,9 +1163,12 @@ static vpx_codec_enc_cfg_map_t vp9e_usage_cfg_map[] = {
       9999,               /* kf_max_dist */
 
       VPX_SS_DEFAULT_LAYERS, /* ss_number_layers */
-
+      1,                  /* ts_number_layers */
+      {0},                /* ts_target_bitrate */
+      {0},                /* ts_rate_decimator */
+      0,                  /* ts_periodicity */
+      {0},                /* ts_layer_id */
 #if VPX_ENCODER_ABI_VERSION == (1 + VPX_CODEC_ABI_VERSION)
-      1,                  /* g_delete_first_pass_file */
       "vp8.fpf"           /* first pass filename */
 #endif
     }
@@ -1177,33 +1206,3 @@ CODEC_INTERFACE(vpx_codec_vp9_cx) = {
     vp9e_get_preview,
   } /* encoder functions */
 };
-
-
-#if CONFIG_EXPERIMENTAL
-
-CODEC_INTERFACE(vpx_codec_vp9x_cx) = {
-  "VP8 Experimental Encoder" VERSION_STRING,
-  VPX_CODEC_INTERNAL_ABI_VERSION,
-  VPX_CODEC_CAP_ENCODER | VPX_CODEC_CAP_PSNR,
-  /* vpx_codec_caps_t          caps; */
-  vp9e_exp_init,      /* vpx_codec_init_fn_t       init; */
-  vp9e_destroy,       /* vpx_codec_destroy_fn_t    destroy; */
-  vp9e_ctf_maps,      /* vpx_codec_ctrl_fn_map_t  *ctrl_maps; */
-  NOT_IMPLEMENTED,    /* vpx_codec_get_mmap_fn_t   get_mmap; */
-  NOT_IMPLEMENTED,    /* vpx_codec_set_mmap_fn_t   set_mmap; */
-  {  // NOLINT
-    NOT_IMPLEMENTED,    /* vpx_codec_peek_si_fn_t    peek_si; */
-    NOT_IMPLEMENTED,    /* vpx_codec_get_si_fn_t     get_si; */
-    NOT_IMPLEMENTED,    /* vpx_codec_decode_fn_t     decode; */
-    NOT_IMPLEMENTED,    /* vpx_codec_frame_get_fn_t  frame_get; */
-  },
-  {  // NOLINT
-    vp9e_usage_cfg_map, /* vpx_codec_enc_cfg_map_t    peek_si; */
-    vp9e_encode,        /* vpx_codec_encode_fn_t      encode; */
-    vp9e_get_cxdata,    /* vpx_codec_get_cx_data_fn_t   frame_get; */
-    vp9e_set_config,
-    NOT_IMPLEMENTED,
-    vp9e_get_preview,
-  } /* encoder functions */
-};
-#endif