shithub: libvpx

Download patch

ref: cd74a901a757a3660887e74d6581fa69277cb9a6
parent: a82001b1cfd688601bbda9b08b3d20e9b46b14d4
author: James Zern <jzern@google.com>
date: Tue Oct 22 07:04:51 EDT 2013

Revert "Merge "SVC improvements""

This reverts commit a82001b1cfd688601bbda9b08b3d20e9b46b14d4, reversing
changes made to f6d870f7ae6f968bdbc342af80c8f71fa98f2ac2.

This commit breaks windows builds and needs some work to fix those and
some additional comments.

Change-Id: Ic0b0228e36704b127e5e399ce59db26182cfffe7

--- a/libs.mk
+++ b/libs.mk
@@ -122,7 +122,6 @@
   CODEC_EXPORTS-yes += $(addprefix $(VP9_PREFIX),$(VP9_CX_EXPORTS))
   CODEC_SRCS-yes += $(VP9_PREFIX)vp9cx.mk vpx/vp8.h vpx/vp8cx.h
   INSTALL-LIBS-yes += include/vpx/vp8.h include/vpx/vp8cx.h
-  INSTALL-LIBS-yes += include/vpx/svc_context.h
   INSTALL_MAPS += include/vpx/% $(SRC_PATH_BARE)/$(VP9_PREFIX)/%
   CODEC_DOC_SRCS += vpx/vp8.h vpx/vp8cx.h
   CODEC_DOC_SECTIONS += vp9 vp9_encoder
--- a/test/svc_test.cc
+++ /dev/null
@@ -1,190 +1,0 @@
-#include <string>
-#include "third_party/googletest/src/include/gtest/gtest.h"
-#include "test/i420_video_source.h"
-#include "test/decode_test_driver.h"
-#include "vpx/vpx_encoder.h"
-#include "vpx/vp8cx.h"
-#include "test/codec_factory.h"
-
-extern "C" {
-#include "vpx/svc_context.h"
-}
-
-namespace {
-
-using libvpx_test::CodecFactory;
-using libvpx_test::VP9CodecFactory;
-using libvpx_test::Decoder;
-
-class SvcTest : public ::testing::Test {
- protected:
-  SvcTest()
-      : codec_iface_(0),
-        test_file_name("hantro_collage_w352h288.yuv"),
-        decoder_(0) {}
-
-  virtual void SetUp() {
-    memset(&svc_, 0, sizeof(svc_));
-    svc_.first_frame_full_size = 1;
-    svc_.encoding_mode = INTER_LAYER_PREDICTION_IP;
-    svc_.log_level = SVC_LOG_DEBUG;
-    svc_.log_print = 1;
-    svc_.gop_size = 100;
-
-    codec_iface_ = vpx_codec_vp9_cx();
-    vpx_codec_err_t res =
-        vpx_codec_enc_config_default(codec_iface_, &codec_enc_, 0);
-    EXPECT_EQ(res, VPX_CODEC_OK);
-
-    codec_enc_.g_w = kWidth;
-    codec_enc_.g_h = kHeight;
-    codec_enc_.g_timebase.num = 1;
-    codec_enc_.g_timebase.den = 60;
-
-    vpx_codec_dec_cfg_t dec_cfg = {0};
-    VP9CodecFactory codec_factory;
-    decoder_ = codec_factory.CreateDecoder(dec_cfg, 0);
-  }
-
-  SvcContext svc_;
-  vpx_codec_ctx_t codec_;
-  struct vpx_codec_enc_cfg codec_enc_;
-  vpx_codec_iface_t* codec_iface_;
-  std::string test_file_name;
-  enum {
-    kWidth = 352,
-    kHeight = 288,
-  };
-
-  Decoder* decoder_;
-};
-
-TEST_F(SvcTest, SvcInit) {
-  svc_.spatial_layers = 0;  // not enough layers
-  vpx_codec_err_t res = vpx_svc_init(&svc_, &codec_, codec_iface_, &codec_enc_);
-  EXPECT_EQ(res, VPX_CODEC_INVALID_PARAM);
-
-  svc_.spatial_layers = 6;  // too many layers
-  res = vpx_svc_init(&svc_, &codec_, codec_iface_, &codec_enc_);
-  EXPECT_EQ(res, VPX_CODEC_INVALID_PARAM);
-
-  svc_.spatial_layers = 2;
-  svc_.scale_factors = "4/16,16*16";  // invalid scale values
-  res = vpx_svc_init(&svc_, &codec_, codec_iface_, &codec_enc_);
-  EXPECT_EQ(res, VPX_CODEC_INVALID_PARAM);
-
-  svc_.scale_factors = "4/16,16/16";  // valid scale values
-
-  res = vpx_svc_init(&svc_, &codec_, codec_iface_, &codec_enc_);
-  EXPECT_EQ(res, VPX_CODEC_OK);
-}
-
-// test that decoder can handle an svc frame as the first frame in a sequence
-// this test is disabled since it with the deco
-TEST_F(SvcTest, DISABLED_FirstFrameHasLayers) {
-  svc_.first_frame_full_size = 0;
-  svc_.spatial_layers = 2;
-  svc_.scale_factors = "4/16,16/16";
-  svc_.quantizer_values = "40,30";
-
-  vpx_codec_err_t res =
-      vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
-  EXPECT_EQ(res, VPX_CODEC_OK);
-
-  libvpx_test::I420VideoSource video(test_file_name, kWidth, kHeight,
-                                     codec_enc_.g_timebase.den,
-                                     codec_enc_.g_timebase.num, 0, 30);
-  video.Begin();
-
-  res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
-                       video.duration(), VPX_DL_REALTIME);
-  EXPECT_EQ(res, VPX_CODEC_OK);
-
-  vpx_codec_err_t res_dec = decoder_->DecodeFrame(
-      (const uint8_t*)svc_get_buffer(&svc_), svc_get_frame_size(&svc_));
-
-  // this test fails with a decoder error
-  ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
-}
-
-TEST_F(SvcTest, EncodeThreeFrames) {
-  svc_.first_frame_full_size = 1;
-  svc_.spatial_layers = 2;
-  svc_.scale_factors = "4/16,16/16";
-  svc_.quantizer_values = "40,30";
-
-  vpx_codec_err_t res =
-      vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
-  ASSERT_EQ(res, VPX_CODEC_OK);
-
-  libvpx_test::I420VideoSource video(test_file_name, kWidth, kHeight,
-                                     codec_enc_.g_timebase.den,
-                                     codec_enc_.g_timebase.num, 0, 30);
-  // FRAME 1
-  video.Begin();
-  // this frame is full size, with only one layer
-  res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
-                       video.duration(), VPX_DL_REALTIME);
-  ASSERT_EQ(res, VPX_CODEC_OK);
-  EXPECT_EQ(1, svc_is_keyframe(&svc_));
-
-  vpx_codec_err_t res_dec = decoder_->DecodeFrame(
-      (const uint8_t*)svc_get_buffer(&svc_), svc_get_frame_size(&svc_));
-  ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
-
-  // FRAME 2
-  video.Next();
-  // this is an I-frame
-  res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
-                       video.duration(), VPX_DL_REALTIME);
-  ASSERT_EQ(res, VPX_CODEC_OK);
-  EXPECT_EQ(1, svc_is_keyframe(&svc_));
-
-  res_dec = decoder_->DecodeFrame((const uint8_t*)svc_get_buffer(&svc_),
-                                  svc_get_frame_size(&svc_));
-  ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
-
-  // FRAME 2
-  video.Next();
-  // this is a P-frame
-  res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
-                       video.duration(), VPX_DL_REALTIME);
-  ASSERT_EQ(res, VPX_CODEC_OK);
-  EXPECT_EQ(0, svc_is_keyframe(&svc_));
-
-  res_dec = decoder_->DecodeFrame((const uint8_t*)svc_get_buffer(&svc_),
-                                  svc_get_frame_size(&svc_));
-  ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
-}
-
-TEST_F(SvcTest, GetLayerResolution) {
-  unsigned int layer_width, layer_height;
-
-  svc_.first_frame_full_size = 0;
-  svc_.spatial_layers = 2;
-  svc_.scale_factors = "4/16,8/16";
-  svc_.quantizer_values = "40,30";
-
-  vpx_codec_err_t res =
-      vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
-  EXPECT_EQ(res, VPX_CODEC_OK);
-
-  // ensure that requested layer is a valid layer
-  res = svc_get_layer_resolution(&svc_, svc_.spatial_layers, &layer_width,
-                                 &layer_height);
-  EXPECT_EQ(res, VPX_CODEC_INVALID_PARAM);
-
-  res = svc_get_layer_resolution(&svc_, 0, &layer_width,
-                                 &layer_height);
-  EXPECT_EQ(res, VPX_CODEC_OK);
-  EXPECT_EQ((unsigned int)(kWidth * 4 / 16), layer_width);
-  EXPECT_EQ((unsigned int)(kHeight * 4 / 16), layer_height);
-
-  res = svc_get_layer_resolution(&svc_, 1, &layer_width,
-                                 &layer_height);
-  EXPECT_EQ(res, VPX_CODEC_OK);
-  EXPECT_EQ((unsigned int)(kWidth * 8 / 16), layer_width);
-  EXPECT_EQ((unsigned int)(kHeight * 8 / 16), layer_height);
-}
-
-}  // namespace
--- a/test/test.mk
+++ b/test/test.mk
@@ -96,7 +96,6 @@
 LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += dct16x16_test.cc
 LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += variance_test.cc
 LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += dct32x32_test.cc
-LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += svc_test.cc
 
 endif # VP9
 
--- a/vp9/common/vp9_onyx.h
+++ b/vp9/common/vp9_onyx.h
@@ -221,6 +221,8 @@
   int vp9_set_size_literal(VP9_PTR comp, unsigned int width,
                            unsigned int height);
 
+  int vp9_switch_layer(VP9_PTR comp, int layer);
+
   void vp9_set_svc(VP9_PTR comp, int use_svc);
 
   int vp9_get_quantizer(VP9_PTR c);
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -4226,9 +4226,37 @@
   return 0;
 }
 
+int vp9_switch_layer(VP9_PTR comp, int layer) {
+  VP9_COMP *cpi = (VP9_COMP *)comp;
+
+  if (cpi->use_svc) {
+    cpi->current_layer = layer;
+
+    // Use buffer i for layer i LST
+    cpi->lst_fb_idx = layer;
+
+    // Use buffer i-1 for layer i Alt (Inter-layer prediction)
+    if (layer != 0) cpi->alt_fb_idx = layer - 1;
+
+    // Use the rest for Golden
+    if (layer < 2 * cpi->number_spatial_layers - NUM_REF_FRAMES)
+      cpi->gld_fb_idx = cpi->lst_fb_idx;
+    else
+      cpi->gld_fb_idx = 2 * cpi->number_spatial_layers - 1 - layer;
+
+    printf("Switching to layer %d:\n", layer);
+    printf("Using references: LST/GLD/ALT [%d|%d|%d]\n", cpi->lst_fb_idx,
+           cpi->gld_fb_idx, cpi->alt_fb_idx);
+  } else {
+    printf("Switching layer not supported. Enable SVC first \n");
+  }
+  return 0;
+}
+
 void vp9_set_svc(VP9_PTR comp, int use_svc) {
   VP9_COMP *cpi = (VP9_COMP *)comp;
   cpi->use_svc = use_svc;
+  if (cpi->use_svc) printf("Enabled SVC encoder \n");
   return;
 }
 
--- a/vp9/vp9_cx_iface.c
+++ b/vp9/vp9_cx_iface.c
@@ -442,6 +442,8 @@
       MAP(VP8E_SET_ARNR_TYPE,               xcfg.arnr_type);
       MAP(VP8E_SET_TUNING,                  xcfg.tuning);
       MAP(VP8E_SET_CQ_LEVEL,                xcfg.cq_level);
+      MAP(VP9E_SET_MAX_Q,                   ctx->cfg.rc_max_quantizer);
+      MAP(VP9E_SET_MIN_Q,                   ctx->cfg.rc_min_quantizer);
       MAP(VP8E_SET_MAX_INTRA_BITRATE_PCT,   xcfg.rc_max_intra_bitrate_pct);
       MAP(VP9E_SET_LOSSLESS,                xcfg.lossless);
       MAP(VP9E_SET_FRAME_PARALLEL_DECODING, xcfg.frame_parallel_decoding_mode);
@@ -1027,40 +1029,66 @@
   }
 }
 
-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);
-  return VPX_CODEC_OK;
+static vpx_codec_err_t vp9e_set_width(vpx_codec_alg_priv_t *ctx, int ctr_id,
+                                      va_list args) {
+  unsigned int *data = va_arg(args, unsigned int *);
+  if (data) {
+    int res;
+    res = vp9_set_size_literal(ctx->cpi, *data, 0);
+    if (!res) {
+      return VPX_CODEC_OK;
+    } else {
+      return VPX_CODEC_INVALID_PARAM;
+    }
+  } else {
+    return VPX_CODEC_INVALID_PARAM;
+  }
 }
 
-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;
+static vpx_codec_err_t vp9e_set_height(vpx_codec_alg_priv_t *ctx,
+                                       int ctr_id,
+                                       va_list args) {
+  unsigned int *data =  va_arg(args, unsigned int *);
 
-  if (!data) {
+  if (data) {
+    int res;
+    res = vp9_set_size_literal(ctx->cpi, 0, *data);
+
+    if (!res) {
+      return VPX_CODEC_OK;
+    } else {
+      return VPX_CODEC_INVALID_PARAM;
+    }
+  } else {
     return VPX_CODEC_INVALID_PARAM;
   }
+}
 
-  params = *(vpx_svc_parameters_t *)data;
+static vpx_codec_err_t vp9e_set_layer(vpx_codec_alg_priv_t *ctx,
+                                      int ctr_id,
+                                      va_list args) {
+  unsigned int *data =  va_arg(args, unsigned int *);
 
-  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;
+  if (data) {
+    int res;
+    res = 0;
 
-  if (vp9_set_size_literal(ctx->cpi, params.width, params.height) != 0) {
+    res = vp9_switch_layer(ctx->cpi, *data);
+
+    if (!res) {
+      return VPX_CODEC_OK;
+    } else {
+      return VPX_CODEC_INVALID_PARAM;
+    }
+  } else {
     return VPX_CODEC_INVALID_PARAM;
   }
+}
 
-  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);
-
+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);
   return VPX_CODEC_OK;
 }
 
@@ -1088,12 +1116,16 @@
   {VP8E_SET_ARNR_TYPE,                set_param},
   {VP8E_SET_TUNING,                   set_param},
   {VP8E_SET_CQ_LEVEL,                 set_param},
+  {VP9E_SET_MAX_Q,                    set_param},
+  {VP9E_SET_MIN_Q,                    set_param},
   {VP8E_SET_MAX_INTRA_BITRATE_PCT,    set_param},
   {VP9E_SET_LOSSLESS,                 set_param},
   {VP9E_SET_FRAME_PARALLEL_DECODING,  set_param},
   {VP9_GET_REFERENCE,                 get_reference},
+  {VP9E_SET_WIDTH,                    vp9e_set_width},
+  {VP9E_SET_HEIGHT,                   vp9e_set_height},
+  {VP9E_SET_LAYER,                    vp9e_set_layer},
   {VP9E_SET_SVC,                      vp9e_set_svc},
-  {VP9E_SET_SVC_PARAMETERS,           vp9e_set_svc_parameters},
   { -1, NULL},
 };
 
--- a/vp9_spatial_scalable_encoder.c
+++ b/vp9_spatial_scalable_encoder.c
@@ -23,22 +23,24 @@
 #define VPX_CODEC_DISABLE_COMPAT 1
 #include "vpx/vpx_encoder.h"
 #include "vpx/vp8cx.h"
-#include "vpx/svc_context.h"
-
 #define interface (vpx_codec_vp9_cx())
 #define fourcc 0x30395056
 #define IVF_FILE_HDR_SZ (32)
 #define IVF_FRAME_HDR_SZ (12)
+#define NUM_BUFFERS 8
 
 char *input_filename;
 char *output_filename;
 unsigned int number_frames_to_code = 60 * 60;
 unsigned int number_frames_to_skip = 0;
-unsigned int gop_size = 100;
+unsigned int number_spatial_layers = 5;
+unsigned int key_period = 100;
 
-char *scaling_factor;
-char *quantizer;
-SVC_ENCODING_MODE encoding_mode = INTER_LAYER_PREDICTION_IP;
+typedef enum ENCODING_MODE {
+  INTER_LAYER_PREDICTION_I,
+  INTER_LAYER_PREDICTION_IP,
+  USE_GOLDEN_FRAME
+} ENCODING_MODE;
 
 static void mem_put_le16(char *mem, unsigned int val) {
   mem[0] = val;
@@ -55,10 +57,7 @@
 static void usage(char *program_name) {
   printf(
       "Usage: %s [-f frames] [-s skip_frames] [-w width] [-h height] \n\t"
-      "[-n rate_num] [-d rate_den] [-b bitrate] [-l layers] [-g gop_size] \n\t"
-      "[-z dummy_frame (default 1) \n\t"
-      "[-q quantizer (lowest to highest)] \n\t"
-      "[-r 1/16th scale factor (lowest to highest layer)] "
+      "[-n rate_num] [-d rate_den] [-b bitrate] [-l layers] "
       "<input_filename> <output_filename>\n",
       basename(program_name));
   exit(EXIT_FAILURE);
@@ -84,74 +83,56 @@
 static int read_frame(FILE *f, vpx_image_t *img) {
   size_t nbytes, to_read;
   int res = 1;
-  int plane;
 
-  for (plane = 0; plane < 3; plane++) {
-    unsigned char *ptr;
-    int w = (plane ? (1 + img->d_w) / 2 : img->d_w);
-    int h = (plane ? (1 + img->d_h) / 2 : img->d_h);
-    int r;
-
-    switch (plane) {
-      case 1:
-        ptr = img->planes[VPX_PLANE_U];
-        break;
-      case 2:
-        ptr = img->planes[VPX_PLANE_V];
-        break;
-      default:
-        ptr = img->planes[plane];
-    }
-    for (r = 0; r < h; r++) {
-      to_read = w;
-
-      nbytes = fread(ptr, 1, to_read, f);
-      if (nbytes != to_read) {
-        res = 0;
-        if (nbytes > 0)
-          printf("Warning: Read partial frame. Check your width & height!\n");
-        break;
-      }
-      ptr += img->stride[plane];
-    }
-    if (!res) break;
+  to_read = img->w * img->h * 3 / 2;
+  nbytes = fread(img->planes[0], 1, to_read, f);
+  if (nbytes != to_read) {
+    res = 0;
+    if (nbytes > 0)
+      printf("Warning: Read partial frame. Check your width & height!\n");
   }
   return res;
 }
 
-static int create_dummy_frame(vpx_image_t *img) {
-  size_t buf_size;
-  buf_size = img->w * img->h * 3 / 2;
-  memset(img->planes[0], 129, buf_size);
+static int read_dummy_frame(vpx_image_t *img) {
+  size_t to_read;
+
+  to_read = img->w * img->h * 3 / 2;
+  memset(img->planes[0], 129, to_read);
   return 1;
 }
 
-static void write_ivf_file_header(FILE *outfile, unsigned int width,
-                                  unsigned int height, int timebase_num,
-                                  int timebase_den, int frame_cnt) {
+static void write_ivf_file_header(FILE *outfile, const vpx_codec_enc_cfg_t *cfg,
+                                  int frame_cnt) {
   char header[32];
 
+  if (cfg->g_pass != VPX_RC_ONE_PASS && cfg->g_pass != VPX_RC_LAST_PASS) return;
   header[0] = 'D';
   header[1] = 'K';
   header[2] = 'I';
   header[3] = 'F';
-  mem_put_le16(header + 4, 0);             /* version */
-  mem_put_le16(header + 6, 32);            /* headersize */
-  mem_put_le32(header + 8, fourcc);        /* headersize */
-  mem_put_le16(header + 12, width);        /* width */
-  mem_put_le16(header + 14, height);       /* height */
-  mem_put_le32(header + 16, timebase_den); /* rate */
-  mem_put_le32(header + 20, timebase_num); /* scale */
-  mem_put_le32(header + 24, frame_cnt);    /* length */
-  mem_put_le32(header + 28, 0);            /* unused */
+  mem_put_le16(header + 4, 0);                    /* version */
+  mem_put_le16(header + 6, 32);                   /* headersize */
+  mem_put_le32(header + 8, fourcc);               /* headersize */
+  mem_put_le16(header + 12, cfg->g_w);            /* width */
+  mem_put_le16(header + 14, cfg->g_h);            /* height */
+  mem_put_le32(header + 16, cfg->g_timebase.den); /* rate */
+  mem_put_le32(header + 20, cfg->g_timebase.num); /* scale */
+  mem_put_le32(header + 24, frame_cnt);           /* length */
+  mem_put_le32(header + 28, 0);                   /* unused */
 
   (void)fwrite(header, 1, 32, outfile);
 }
 
-static void write_ivf_frame_header(FILE *outfile, vpx_codec_pts_t pts,
-                                   size_t sz) {
+static void write_ivf_frame_header(FILE *outfile,
+                                   const vpx_codec_cx_pkt_t *pkt) {
   char header[12];
-  mem_put_le32(header, sz);
+  vpx_codec_pts_t pts;
+
+  if (pkt->kind != VPX_CODEC_CX_FRAME_PKT) return;
+
+  pts = pkt->data.frame.pts;
+  mem_put_le32(header, pkt->data.frame.sz);
   mem_put_le32(header + 4, pts & 0xFFFFFFFF);
   mem_put_le32(header + 8, pts >> 32);
 
@@ -158,24 +139,22 @@
   (void)fwrite(header, 1, 12, outfile);
 }
 
-static void parse_command_line(int argc, char **argv, SvcContext *svc_ctx,
-                               vpx_codec_enc_cfg_t *enc_cfg) {
+static void check_parameters() {
+  if (number_spatial_layers > 5) die("Cannot support more than 5 layers");
+}
+
+static void parse_command_line(int argc, char **argv,
+                               vpx_codec_enc_cfg_t *cfg) {
   unsigned int width = 1920;
   unsigned int height = 1080;
   unsigned int timebase_num = 1;
   unsigned int timebase_den = 60;
   unsigned int bitrate = 1000;
-  unsigned int number_spatial_layers = 5;
-  int use_dummy_frame = 1;
-
   int c;
   vpx_codec_err_t res;
-  int r = 0;
-  int q = 0;
 
   opterr = 0;
-  while ((c = getopt(argc, argv, "f:w:h:n:d:b:s:l:g:r:q:z:")) != -1)
-    switch (c) {
+  while ((c = getopt(argc, argv, "f:w:h:n:d:b:s:l:p:")) != -1) switch (c) {
       case 'f':
         number_frames_to_code = atoi(optarg);
         break;
@@ -200,18 +179,9 @@
       case 'l':
         number_spatial_layers = atoi(optarg);
         break;
-      case 'g':
-        gop_size = atoi(optarg);
+      case 'p':
+        key_period = atoi(optarg);
         break;
-      case 'r':
-        scaling_factor = optarg;
-        break;
-      case 'q':
-        quantizer = optarg;
-        break;
-      case 'z':
-        use_dummy_frame = atoi(optarg);
-        break;
       case '?':
         usage(argv[0]);
     }
@@ -221,10 +191,6 @@
     usage(argv[0]);
   }
 
-  if ((r != 0 && q != 0 && r != q) || (r != number_spatial_layers && r != 0)) {
-    usage(argv[0]);
-  }
-
   input_filename = argv[optind];
   output_filename = argv[optind + 1];
 
@@ -231,18 +197,8 @@
   if (width < 16 || width % 2 || height < 16 || height % 2)
     die("Invalid resolution: %d x %d", width, height);
 
-  // initialize SvcContext
-  svc_ctx->log_level = SVC_LOG_DEBUG;
-  svc_ctx->spatial_layers = number_spatial_layers;
-  svc_ctx->encoding_mode = encoding_mode;
-  svc_ctx->gop_size = gop_size;
-  svc_ctx->quantizer_values = quantizer;
-  svc_ctx->scale_factors = scaling_factor;
-  // when using a dummy frame, that frame is only encoded to be full size
-  svc_ctx->first_frame_full_size = use_dummy_frame;
-
   /* Populate encoder configuration */
-  res = vpx_codec_enc_config_default(interface, enc_cfg, 0);
+  res = vpx_codec_enc_config_default(interface, cfg, 0);
   if (res) {
     die("Failed to get config: %s\n", vpx_codec_err_to_string(res));
   }
@@ -250,53 +206,201 @@
       "Codec %s\nframes: %d, skip: %d, layers: %d\n"
       "width %d, height: %d, \n"
       "num: %d, den: %d, bitrate: %d, \n"
-      "gop size: %d, use_dummy_frame: %d \n",
+      "key period: %d \n",
       vpx_codec_iface_name(interface), number_frames_to_code,
       number_frames_to_skip, number_spatial_layers, width, height, timebase_num,
-      timebase_den, bitrate, gop_size, use_dummy_frame);
+      timebase_den, bitrate, key_period);
 
-  enc_cfg->rc_target_bitrate = bitrate;
-  enc_cfg->g_w = width;
-  enc_cfg->g_h = height;
-  enc_cfg->g_timebase.num = timebase_num;
-  enc_cfg->g_timebase.den = timebase_den;
+  // Do minimal check at the application level. Encoder parameters will be
+  // checked internally
+  check_parameters();
+
+  cfg->rc_target_bitrate = bitrate;
+  cfg->g_w = width;
+  cfg->g_h = height;
+  cfg->g_timebase.num = timebase_num;
+  cfg->g_timebase.den = timebase_den;
+  cfg->ss_number_layers = number_spatial_layers;
 }
 
+static void set_default_configuration(vpx_codec_enc_cfg_t *cfg) {
+  /* Real time parameters */
+  cfg->rc_dropframe_thresh = 0;
+  cfg->rc_end_usage = VPX_CBR;
+  cfg->rc_resize_allowed = 0;
+  cfg->rc_min_quantizer = 33;
+  cfg->rc_max_quantizer = 33;
+  cfg->rc_undershoot_pct = 100;
+  cfg->rc_overshoot_pct = 15;
+  cfg->rc_buf_initial_sz = 500;
+  cfg->rc_buf_optimal_sz = 600;
+  cfg->rc_buf_sz = 1000;
+
+  /* Enable error resilient mode */
+  cfg->g_error_resilient = 1;
+  cfg->g_lag_in_frames = 0;
+
+  /* Disable automatic keyframe placement */
+  cfg->kf_mode = VPX_KF_DISABLED;
+  cfg->kf_min_dist = cfg->kf_max_dist = 3000;
+}
+
+static void initialize_codec(vpx_codec_ctx_t *codec, vpx_codec_enc_cfg_t *cfg) {
+  int max_intra_size_pct;
+
+  /* Initialize codec */
+  if (vpx_codec_enc_init(codec, interface, cfg, VPX_CODEC_USE_PSNR))
+    die_codec(codec, "Failed to initialize encoder");
+
+  vpx_codec_control(codec, VP9E_SET_SVC, 1);
+  /* Cap CPU & first I-frame size */
+  vpx_codec_control(codec, VP8E_SET_CPUUSED, 1);
+  vpx_codec_control(codec, VP8E_SET_STATIC_THRESHOLD, 1);
+  vpx_codec_control(codec, VP8E_SET_NOISE_SENSITIVITY, 1);
+  vpx_codec_control(codec, VP8E_SET_TOKEN_PARTITIONS, 1);
+
+  max_intra_size_pct =
+      (int)(((double)cfg->rc_buf_optimal_sz * 0.5) *
+            ((double)cfg->g_timebase.den / cfg->g_timebase.num) / 10.0);
+  /* printf ("max_intra_size_pct=%d\n", max_intra_size_pct); */
+
+  vpx_codec_control(codec, VP8E_SET_MAX_INTRA_BITRATE_PCT, max_intra_size_pct);
+}
+
+static int calculate_layer(int frame_cnt, int number_spatial_layers) {
+  if (frame_cnt == 0)
+    return 0;
+  else
+    return (frame_cnt + number_spatial_layers - 1) % number_spatial_layers;
+}
+
+static void switch_to_layer(int layer, unsigned int initial_width,
+                            unsigned int initial_height,
+                            vpx_codec_ctx_t *codec) {
+  // Set layer size
+  int scaling_factor_num[MAX_LAYERS] = {2, 1, 4, 2, 1};
+  int scaling_factor_den[MAX_LAYERS] = {9, 3, 9, 3, 1};
+
+  int quantizer[MAX_LAYERS] = {60, 53, 39, 33, 27};
+
+  unsigned int current_width;
+  unsigned int current_height;
+
+  current_width = initial_width *
+                  scaling_factor_num[layer + 5 - number_spatial_layers] /
+                  scaling_factor_den[layer + 5 - number_spatial_layers];
+  current_height = initial_height *
+                   scaling_factor_num[layer + 5 - number_spatial_layers] /
+                   scaling_factor_den[layer + 5 - number_spatial_layers];
+
+  current_width += current_width % 2;
+  current_height += current_height % 2;
+
+  vpx_codec_control(codec, VP9E_SET_WIDTH, &current_width);
+  vpx_codec_control(codec, VP9E_SET_HEIGHT, &current_height);
+
+  // Set layer context
+  vpx_codec_control(codec, VP9E_SET_LAYER, &layer);
+  vpx_codec_control(codec, VP9E_SET_MAX_Q,
+                    quantizer[layer + 5 - number_spatial_layers]);
+  vpx_codec_control(codec, VP9E_SET_MIN_Q,
+                    quantizer[layer + 5 - number_spatial_layers]);
+}
+
+static int get_flag(int is_I_frame_in_layer, int layer, ENCODING_MODE mode) {
+  // First layer
+  switch (mode) {
+    case INTER_LAYER_PREDICTION_I:
+      if (is_I_frame_in_layer && layer == 0) return VPX_EFLAG_FORCE_KF;
+      if (layer == 0)
+        return VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
+               VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF;
+      else if (is_I_frame_in_layer)
+        return VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
+               VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_LAST;
+      else
+        return VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
+               VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF;
+      break;
+
+    case INTER_LAYER_PREDICTION_IP:
+      if (is_I_frame_in_layer && layer == 0) return VPX_EFLAG_FORCE_KF;
+      if (layer == 0)
+        return VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
+               VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF;
+      else if (is_I_frame_in_layer)
+        return VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
+               VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_LAST;
+      else
+        return VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF;
+      break;
+
+    case USE_GOLDEN_FRAME:
+      if (is_I_frame_in_layer && layer == 0) return VPX_EFLAG_FORCE_KF;
+      if (2 * number_spatial_layers - NUM_BUFFERS <= layer) {
+        if (layer == 0)
+          return VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
+                 VP8_EFLAG_NO_REF_ARF;
+        else if (is_I_frame_in_layer)
+          return VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF |
+                 VP8_EFLAG_NO_REF_LAST;
+        else
+          return VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
+      } else {
+        if (layer == 0)
+          return VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
+                 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF;
+        else if (is_I_frame_in_layer)
+          return VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
+                 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_LAST;
+        else
+          return VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
+                 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF;
+      }
+      break;
+    default:
+      return VPX_EFLAG_FORCE_KF;
+  }
+}
+
 int main(int argc, char **argv) {
-  FILE *infile, *outfile;
+  FILE *infile, *outfile[MAX_LAYERS];
   vpx_codec_ctx_t codec;
-  vpx_codec_enc_cfg_t enc_cfg;
-  SvcContext svc_ctx;
-  int i;
+  vpx_codec_enc_cfg_t cfg;
   int frame_cnt = 0;
   vpx_image_t raw;
+  int frame_avail = 1;
+  int got_data = 0;
+  int i;
+  int frames_in_layer[MAX_LAYERS] = {0};
   clock_t before;
   clock_t after;
-  vpx_codec_err_t res;
   int pts = 0;            /* PTS starts at 0 */
   int frame_duration = 1; /* 1 timebase tick per frame */
 
-  memset(&svc_ctx, 0, sizeof(svc_ctx));
-  svc_ctx.log_print = 1;
-  parse_command_line(argc, argv, &svc_ctx, &enc_cfg);
+  parse_command_line(argc, argv, &cfg);
 
   // Allocate image buffer
-  if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, enc_cfg.g_w, enc_cfg.g_h, 32))
-    die("Failed to allocate image", enc_cfg.g_w, enc_cfg.g_h);
+  if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, cfg.g_w, cfg.g_h, 32))
+    die("Failed to allocate image", cfg.g_w, cfg.g_h);
 
+  set_default_configuration(&cfg);
+
+  /* Open input file */
   if (!(infile = fopen(input_filename, "rb")))
     die("Failed to open %s for reading", argv[1]);
 
-  if (!(outfile = fopen(output_filename, "wb")))
-    die("Failed to open %s for writing", output_filename);
+  /* Open output file  */
+  for (i = 0; i < number_spatial_layers; i++) {
+    char file_name[512];
+    snprintf(file_name, sizeof(file_name), "%s_%d.ivf", output_filename, i);
+    if (!(outfile[i] = fopen(file_name, "wb")))
+      die("Failed to open %s for writing", file_name);
+    write_ivf_file_header(outfile[i], &cfg, 0);
+  }
 
-  // Initialize codec
-  if (vpx_svc_init(&svc_ctx, &codec, interface, &enc_cfg) != VPX_CODEC_OK)
-    die("Failed to initialize encoder");
+  initialize_codec(&codec, &cfg);
 
-  write_ivf_file_header(outfile, enc_cfg.g_w, enc_cfg.g_h,
-                        enc_cfg.g_timebase.num, enc_cfg.g_timebase.den, 0);
-
   // skip initial frames
   for (i = 0; i < number_frames_to_skip; i++) {
     read_frame(infile, &raw);
@@ -303,47 +407,81 @@
   }
 
   before = clock();
-  // Encode frames
-  while (frame_cnt <= number_frames_to_code) {
-    if (frame_cnt == 0 && svc_ctx.first_frame_full_size) {
-      create_dummy_frame(&raw);
-    } else {
-      if (!read_frame(infile, &raw)) break;
+  // Encoding frames
+  while ((frame_avail || got_data) &&
+         frame_cnt <= number_frames_to_code * number_spatial_layers) {
+    int flags = 0;
+    vpx_codec_iter_t iter = NULL;
+    const vpx_codec_cx_pkt_t *pkt;
+
+    int layer = calculate_layer(frame_cnt, number_spatial_layers);
+    int is_I_frame_in_layer =
+        (((frame_cnt - 1) / number_spatial_layers % key_period) == 0);
+    int is_dummy = (frame_cnt == 0);
+
+    if (is_dummy) {  // Dummy frame
+      flags = VPX_EFLAG_FORCE_KF;
+      frame_avail = read_dummy_frame(&raw);
+
+    } else {  // Regular frame
+      // Read a new frame only at the base layer
+      if (layer == 0) frame_avail = read_frame(infile, &raw);
+      switch_to_layer(layer, cfg.g_w, cfg.g_h, &codec);
+      flags = get_flag(is_I_frame_in_layer, layer, INTER_LAYER_PREDICTION_I);
     }
-    res = vpx_svc_encode(&svc_ctx, &codec, &raw, pts, frame_duration,
-                         VPX_DL_REALTIME);
-    printf("%s", svc_get_message(&svc_ctx));
-    if (res != VPX_CODEC_OK) {
+
+    // Actual Encoding
+    if (vpx_codec_encode(&codec, frame_avail ? &raw : NULL, pts, 1, flags,
+                         VPX_DL_REALTIME))
       die_codec(&codec, "Failed to encode frame");
+
+    got_data = 0;
+    // Process data / Get PSNR statistics
+    while ((pkt = vpx_codec_get_cx_data(&codec, &iter))) {
+      got_data = 1;
+      switch (pkt->kind) {
+        case VPX_CODEC_CX_FRAME_PKT:
+          for (i = layer; i < number_spatial_layers; i++) {
+            write_ivf_frame_header(outfile[i], pkt);
+            (void)fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz,
+                         outfile[i]);
+            frames_in_layer[i]++;
+          }
+          break;
+        case VPX_CODEC_PSNR_PKT:
+          if (frame_cnt != 0)
+            printf(
+                "Processed Frame %d, layer %d, PSNR(Total/Y/U/V): "
+                "%2.3f  %2.3f  %2.3f  %2.3f \n",
+                (frame_cnt - 1) / number_spatial_layers + 1, layer,
+                pkt->data.psnr.psnr[0], pkt->data.psnr.psnr[1],
+                pkt->data.psnr.psnr[2], pkt->data.psnr.psnr[3]);
+          break;
+        default:
+          break;
+      }
     }
-    if (svc_get_frame_size(&svc_ctx) > 0) {
-      write_ivf_frame_header(outfile, pts, svc_get_frame_size(&svc_ctx));
-      (void)fwrite(svc_get_buffer(&svc_ctx), 1, svc_get_frame_size(&svc_ctx),
-                   outfile);
-    }
     frame_cnt++;
+    // TODO(ivan): Modify ts later if(!layer)
     pts += frame_duration;
-  }  // end encode frames loop
+  }
+  // end while
 
   after = clock();
   printf("Processed %d frames in different resolutions in %ld ms.\n",
-         frame_cnt - svc_ctx.first_frame_full_size,
-         (int)(after - before) / (CLOCKS_PER_SEC / 1000));
+         frame_cnt - 1, (int)(after - before) / (CLOCKS_PER_SEC / 1000));
 
   fclose(infile);
+
   if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec");
 
-  // rewrite the output file headers with the actual frame count
-  if (!fseek(outfile, 0, SEEK_SET)) {
-    write_ivf_file_header(outfile, enc_cfg.g_w, enc_cfg.g_h,
-                          enc_cfg.g_timebase.num, enc_cfg.g_timebase.den,
-                          frame_cnt);
+  /* Try to rewrite the output file headers with the actual frame count */
+  for (i = 0; i < number_spatial_layers; i++) {
+    if (!fseek(outfile[i], 0, SEEK_SET)) {
+      write_ivf_file_header(outfile[i], &cfg, frames_in_layer[i]);
+    }
+    fclose(outfile[i]);
   }
-  fclose(outfile);
-
-  // display average size, psnr
-  svc_dump_statistics(&svc_ctx);
-  printf("%s", svc_get_message(&svc_ctx));
 
   return EXIT_SUCCESS;
 }
--- a/vpx/exports_enc
+++ b/vpx/exports_enc
@@ -6,12 +6,3 @@
 text vpx_codec_get_global_headers
 text vpx_codec_get_preview_frame
 text vpx_codec_set_cx_data_buf
-text vpx_svc_init
-text vpx_svc_encode
-text svc_dump_statistics
-text svc_get_message
-text svc_get_buffer
-text svc_get_frame_size
-text svc_get_encode_frame_count
-text svc_is_keyframe
-text svc_set_keyframe
\ No newline at end of file
--- a/vpx/src/svc_encodeframe.c
+++ /dev/null
@@ -1,793 +1,0 @@
-/**
- * @file
- * VP9 SVC encoding support via libvpx
- */
-
-#define VPX_DISABLE_CTRL_TYPECHECKS 1
-#define VPX_CODEC_DISABLE_COMPAT 1
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#include "vpx/vpx_encoder.h"
-#include "vpx/vp8cx.h"
-#include "vpx/svc_context.h"
-
-#define SVC_REFERENCE_FRAMES 8
-
-static const char* DEFAULT_QUANTIZER_VALUES = "60,53,39,33,27";
-static const char* DEFAULT_SCALE_FACTORS = "4/16,5/16,7/16,11/16,16/16";
-static char* colors[VPX_SS_MAX_LAYERS] = {"\x1B[35m", "\x1B[32m", "\x1B[33m",
-                                          "\x1B[34m", "\x1B[36m"};
-static char* normal_color = "\x1B[0m";
-
-typedef struct SvcInternal {
-  // values extracted from options
-  int scaling_factor_num[VPX_SS_MAX_LAYERS];
-  int scaling_factor_den[VPX_SS_MAX_LAYERS];
-  int quantizer[VPX_SS_MAX_LAYERS];
-
-  // accumulated statistics
-  double psnr_in_layer[VPX_SS_MAX_LAYERS];
-  int bytes_in_layer[VPX_SS_MAX_LAYERS];
-
-  // codec encoding values
-  int width;
-  int height;
-
-  // state variables
-  int encode_frame_count;
-  int frame_within_gop;
-  vpx_enc_frame_flags_t enc_frame_flags;
-  int layers;
-  int layer;
-  int is_keyframe;
-
-  size_t frame_size;
-  size_t buffer_size;
-  void* buffer;
-
-  char message_buffer[2048];
-  vpx_codec_ctx_t* codec_ctx;
-} SvcInternal;
-
-// One encoded frame layer
-struct LayerData {
-  void* buf;    // compressed data buffer
-  size_t size;  // length of compressed data
-  struct LayerData* next;
-};
-
-// forward references
-static void svc_log_reset(SvcContext* svc_ctx);
-static int svc_log(SvcContext* svc_ctx, int level, char* fmt, ...);
-static vpx_codec_err_t svc_parse_input_parameters(SvcContext* svc_ctx);
-static int vpx_svc_dummy_frame(SvcContext* svc_ctx, SvcInternal* si);
-
-// create LayerData from encoder output
-static struct LayerData* ld_create(void* buf, size_t size) {
-  struct LayerData* layer_data;
-
-  layer_data = malloc(sizeof(struct LayerData));
-  if (layer_data == NULL) {
-    return NULL;
-  }
-  layer_data->buf = malloc(size);
-  if (layer_data->buf == NULL) {
-    return NULL;
-  }
-  memcpy(layer_data->buf, buf, size);
-  layer_data->size = size;
-  return layer_data;
-}
-
-// free LayerData
-static void ld_free(struct LayerData* layer_data) {
-  if (layer_data->buf) {
-    free(layer_data->buf);
-    layer_data->buf = NULL;
-  }
-  free(layer_data);
-}
-
-// add layer data to list
-static void ld_list_add(struct LayerData** list, struct LayerData* layer_data) {
-  struct LayerData** p = list;
-
-  while (*p != NULL) p = &(*p)->next;
-  *p = layer_data;
-  layer_data->next = NULL;
-}
-
-// get accumulated size of layer data
-static size_t ld_list_get_buffer_size(struct LayerData* list) {
-  struct LayerData* p;
-  size_t size = 0;
-
-  for (p = list; p != NULL; p = p->next) {
-    size += p->size;
-  }
-  return size;
-}
-
-// copy layer data to buffer
-static void ld_list_copy_to_buffer(struct LayerData* list, uint8_t* buffer) {
-  struct LayerData* p;
-
-  for (p = list; p != NULL; p = p->next) {
-    buffer[0] = 1;
-    memcpy(buffer, p->buf, p->size);
-    buffer += p->size;
-  }
-}
-
-// free layer data list
-static void ld_list_free(struct LayerData* list) {
-  struct LayerData* p = list;
-
-  while (p) {
-    list = list->next;
-    ld_free(p);
-    p = list;
-  }
-}
-
-// Superframe Index
-#define SUPERFRAME_SLOTS (8)
-#define SUPERFRAME_BUFFER_SIZE (SUPERFRAME_SLOTS * sizeof(uint32_t) + 2)
-
-struct Superframe {
-  int count;
-  uint32_t sizes[SUPERFRAME_SLOTS];
-  uint32_t magnitude;
-  uint8_t buffer[SUPERFRAME_BUFFER_SIZE];
-  size_t index_size;
-};
-
-static void sf_create_index(struct Superframe* sf) {
-  uint8_t marker = 0xc0;
-  int mag, mask;
-  uint8_t* bufp;
-  int i, j;
-  int this_sz;
-
-  if (sf->count == 0 || sf->count >= 8) return;
-
-  /* Add the number of frames to the marker byte */
-  marker |= sf->count - 1;
-
-  /* Choose the magnitude */
-  for (mag = 0, mask = 0xff; mag < 4; mag++) {
-    if (sf->magnitude < mask) break;
-    mask <<= 8;
-    mask |= 0xff;
-  }
-  marker |= mag << 3;
-
-  /* Write the index */
-  sf->index_size = 2 + (mag + 1) * sf->count;
-  bufp = sf->buffer;
-
-  *bufp++ = marker;
-  for (i = 0; i < sf->count; i++) {
-    this_sz = sf->sizes[i];
-
-    for (j = 0; j <= mag; j++) {
-      *bufp++ = this_sz & 0xff;
-      this_sz >>= 8;
-    }
-  }
-  *bufp++ = marker;
-}
-
-static vpx_codec_err_t svc_invalid_scale_factor(SvcContext* svc_ctx) {
-  svc_log(svc_ctx, SVC_LOG_ERROR, "svc-scale-factors: invalid value\n");
-  return VPX_CODEC_INVALID_PARAM;
-}
-
-static vpx_codec_err_t svc_parse_input_parameters(SvcContext* svc_ctx) {
-  char* input_string;
-  char* token;
-  const char* delim = ",";
-  char* save_ptr;
-  int found;
-  int i, q;
-  int64_t num, den;
-  SvcInternal* si = (SvcInternal*)svc_ctx->internal;
-
-  // parse quantizer_values
-  if (svc_ctx->quantizer_values == NULL ||
-      strlen(svc_ctx->quantizer_values) == 0) {
-    input_string = strdup(DEFAULT_QUANTIZER_VALUES);
-  } else {
-    input_string = strdup(svc_ctx->quantizer_values);
-  }
-
-  found = 0;
-  token = strtok_r(input_string, delim, &save_ptr);
-  for (i = 0; i < si->layers; i++) {
-    if (token != NULL) {
-      q = atoi(token);
-      if (q <= 0 || q > 100) {
-        svc_log(svc_ctx, SVC_LOG_ERROR,
-                "svc-quantizer-values: invalid value\n");
-        return VPX_CODEC_INVALID_PARAM;
-      }
-      token = strtok_r(NULL, delim, &save_ptr);
-      found = i + 1;
-    } else {
-      q = 0;
-    }
-    si->quantizer[i + VPX_SS_MAX_LAYERS - si->layers] = q;
-  }
-  free(input_string);
-  if (found != si->layers) {
-    svc_log(svc_ctx, SVC_LOG_ERROR,
-            "svc-quantizer-values: %d values required, but only %d specified\n",
-            si->layers, found);
-    return VPX_CODEC_INVALID_PARAM;
-  }
-
-  // parse scale_factors
-  if (svc_ctx->scale_factors == NULL || strlen(svc_ctx->scale_factors) == 0) {
-    input_string = strdup(DEFAULT_SCALE_FACTORS);
-  } else {
-    input_string = strdup(svc_ctx->scale_factors);
-  }
-  found = 0;
-  token = strtok_r(input_string, delim, &save_ptr);
-  for (i = 0; i < si->layers; i++) {
-    num = den = 1;
-    if (token != NULL) {
-      num = strtol(token, &token, 10);
-      if (num <= 0) return svc_invalid_scale_factor(svc_ctx);
-      if (*token++ != '/') return svc_invalid_scale_factor(svc_ctx);
-      den = strtol(token, &token, 10);
-      if (den <= 0) return svc_invalid_scale_factor(svc_ctx);
-
-      token = strtok_r(NULL, delim, &save_ptr);
-      found = i + 1;
-    }
-    si->scaling_factor_num[i + VPX_SS_MAX_LAYERS - si->layers] = (int)num;
-    si->scaling_factor_den[i + VPX_SS_MAX_LAYERS - si->layers] = (int)den;
-  }
-  free(input_string);
-  if (found != si->layers) {
-    svc_log(svc_ctx, SVC_LOG_ERROR,
-            "svc-scale-factors: %d values required, but only %d specified\n",
-            si->layers, found);
-    return VPX_CODEC_INVALID_PARAM;
-  }
-  return VPX_CODEC_OK;
-}
-
-vpx_codec_err_t vpx_svc_init(SvcContext* svc_ctx, vpx_codec_ctx_t* codec_ctx,
-                             vpx_codec_iface_t* iface,
-                             vpx_codec_enc_cfg_t* enc_cfg) {
-  int max_intra_size_pct;
-  vpx_codec_err_t res;
-  SvcInternal* si;
-
-  if (svc_ctx->internal == NULL) {
-    svc_ctx->internal = malloc(sizeof(SvcInternal));
-  }
-  si = (SvcInternal*)svc_ctx->internal;
-  memset(si, 0, sizeof(SvcInternal));
-  si->codec_ctx = codec_ctx;
-
-  if (svc_ctx->spatial_layers < 1 ||
-      svc_ctx->spatial_layers > VPX_SS_MAX_LAYERS) {
-    svc_log(svc_ctx, SVC_LOG_ERROR, "spatial layers: invalid value: %d\n",
-            svc_ctx->spatial_layers);
-    return VPX_CODEC_INVALID_PARAM;
-  }
-
-  if (svc_ctx->gop_size < 2) {
-    svc_log(svc_ctx, SVC_LOG_ERROR, "gop_size too small: %d\n",
-            svc_ctx->gop_size);
-    return VPX_CODEC_INVALID_PARAM;
-  }
-
-  si->width = enc_cfg->g_w;
-  si->height = enc_cfg->g_h;
-
-  // use SvcInternal value for number of layers to enable forcing one layer
-  // for first frame
-  si->layers = svc_ctx->spatial_layers;
-
-  // parse quantizer values and scale factors
-  res = svc_parse_input_parameters(svc_ctx);
-  if (res != VPX_CODEC_OK) return res;
-
-  // initialize encoder configuration
-  enc_cfg->ss_number_layers = si->layers;
-  // force single pass
-  enc_cfg->g_pass = VPX_RC_ONE_PASS;
-  // Lag in frames not currently supported
-  enc_cfg->g_lag_in_frames = 0;
-
-  // TODO(ivanmaltz): determine if these values need to be set explicitly for
-  // svc, or if the normal default/override mechanism can be used
-  enc_cfg->rc_dropframe_thresh = 0;
-  enc_cfg->rc_end_usage = VPX_CBR;
-  enc_cfg->rc_resize_allowed = 0;
-  enc_cfg->rc_min_quantizer = 33;
-  enc_cfg->rc_max_quantizer = 33;
-  enc_cfg->rc_undershoot_pct = 100;
-  enc_cfg->rc_overshoot_pct = 15;
-  enc_cfg->rc_buf_initial_sz = 500;
-  enc_cfg->rc_buf_optimal_sz = 600;
-  enc_cfg->rc_buf_sz = 1000;
-
-  enc_cfg->g_error_resilient = 1;
-  enc_cfg->kf_mode = VPX_KF_DISABLED;
-  enc_cfg->kf_min_dist = enc_cfg->kf_max_dist = 3000;
-
-  // Initialize codec
-  res = vpx_codec_enc_init(codec_ctx, iface, enc_cfg, VPX_CODEC_USE_PSNR);
-  if (res != VPX_CODEC_OK) {
-    svc_log(svc_ctx, SVC_LOG_ERROR, "svc_enc_init error\n");
-    return res;
-  }
-
-  vpx_codec_control(codec_ctx, VP9E_SET_SVC, 1);
-
-  // Cap CPU & first I-frame size
-  vpx_codec_control(codec_ctx, VP8E_SET_CPUUSED, 1);
-  vpx_codec_control(codec_ctx, VP8E_SET_STATIC_THRESHOLD, 1);
-  vpx_codec_control(codec_ctx, VP8E_SET_NOISE_SENSITIVITY, 1);
-  vpx_codec_control(codec_ctx, VP8E_SET_TOKEN_PARTITIONS, 1);
-
-  max_intra_size_pct =
-      (int)(((double)enc_cfg->rc_buf_optimal_sz * 0.5) *
-            ((double)enc_cfg->g_timebase.den / enc_cfg->g_timebase.num) / 10.0);
-  vpx_codec_control(codec_ctx, VP8E_SET_MAX_INTRA_BITRATE_PCT,
-                    max_intra_size_pct);
-  return VPX_CODEC_OK;
-}
-
-// SVC Algorithm flags - these get mapped to VP8_EFLAG_* defined in vp8cx.h
-
-// encoder should reference the last frame
-#define USE_LAST (1 << 0)
-
-// encoder should reference the alt ref frame
-#define USE_ARF (1 << 1)
-
-// encoder should reference the golden frame
-#define USE_GF (1 << 2)
-
-// encoder should copy current frame to the last frame buffer
-#define UPDATE_LAST (1 << 3)
-
-// encoder should copy current frame to the alt ref frame buffer
-#define UPDATE_ARF (1 << 4)
-
-// encoder should copy current frame to the golden frame
-#define UPDATE_GF (1 << 5)
-
-static int map_vp8_flags(int svc_flags) {
-  int flags = 0;
-
-  if (!(svc_flags & USE_LAST)) flags |= VP8_EFLAG_NO_REF_LAST;
-
-  if (!(svc_flags & USE_ARF)) flags |= VP8_EFLAG_NO_REF_ARF;
-
-  if (!(svc_flags & USE_GF)) flags |= VP8_EFLAG_NO_REF_GF;
-
-  if (svc_flags & UPDATE_LAST) {
-    // last is updated automatically
-  } else {
-    flags |= VP8_EFLAG_NO_UPD_LAST;
-  }
-
-  if (svc_flags & UPDATE_ARF) {
-    flags |= VP8_EFLAG_FORCE_ARF;
-  } else {
-    flags |= VP8_EFLAG_NO_UPD_ARF;
-  }
-
-  if (svc_flags & UPDATE_GF) {
-    flags |= VP8_EFLAG_FORCE_GF;
-  } else {
-    flags |= VP8_EFLAG_NO_UPD_GF;
-  }
-
-  return flags;
-}
-
-static void calculate_enc_frame_flags(SvcContext* svc_ctx) {
-  vpx_enc_frame_flags_t flags = VPX_EFLAG_FORCE_KF;
-  SvcInternal* si = (SvcInternal*)svc_ctx->internal;
-
-  int is_keyframe = (si->frame_within_gop == 0);
-
-  // keyframe layer zero is identical for all modes
-  if ((is_keyframe && si->layer == 0) || vpx_svc_dummy_frame(svc_ctx, si)) {
-    si->enc_frame_flags = VPX_EFLAG_FORCE_KF;
-    return;
-  }
-
-  switch (svc_ctx->encoding_mode) {
-    case ALT_INTER_LAYER_PREDICTION_IP:
-      if (si->layer == 0) {
-        flags = map_vp8_flags(USE_LAST | UPDATE_LAST);
-      } else if (is_keyframe) {
-        if (si->layer == si->layers - 1) {
-          flags = map_vp8_flags(USE_ARF | UPDATE_LAST);
-        } else {
-          flags = map_vp8_flags(USE_ARF | UPDATE_LAST | UPDATE_GF);
-        }
-      } else {
-        flags = map_vp8_flags(USE_LAST | USE_ARF | UPDATE_LAST);
-      }
-      break;
-    case INTER_LAYER_PREDICTION_I:
-      if (si->layer == 0) {
-        flags = map_vp8_flags(USE_LAST | UPDATE_LAST);
-      } else if (is_keyframe) {
-        flags = map_vp8_flags(USE_ARF | UPDATE_LAST);
-      } else {
-        flags = map_vp8_flags(USE_LAST | UPDATE_LAST);
-      }
-      break;
-    case INTER_LAYER_PREDICTION_IP:
-      if (si->layer == 0) {
-        flags = map_vp8_flags(USE_LAST | UPDATE_LAST);
-      } else if (is_keyframe) {
-        flags = map_vp8_flags(USE_ARF | UPDATE_LAST);
-      } else {
-        flags = map_vp8_flags(USE_LAST | USE_ARF | UPDATE_LAST);
-      }
-      break;
-    case USE_GOLDEN_FRAME:
-      if (2 * si->layers - SVC_REFERENCE_FRAMES <= si->layer) {
-        if (si->layer == 0) {
-          flags = map_vp8_flags(USE_LAST | USE_GF | UPDATE_LAST);
-        } else if (is_keyframe) {
-          flags = map_vp8_flags(USE_ARF | UPDATE_LAST | UPDATE_GF);
-        } else {
-          flags = map_vp8_flags(USE_LAST | USE_ARF | USE_GF | UPDATE_LAST);
-        }
-      } else {
-        if (si->layer == 0) {
-          flags = map_vp8_flags(USE_LAST | UPDATE_LAST);
-        } else if (is_keyframe) {
-          flags = map_vp8_flags(USE_ARF | UPDATE_LAST);
-        } else {
-          flags = map_vp8_flags(USE_LAST | UPDATE_LAST);
-        }
-      }
-      break;
-    default:
-      svc_log(svc_ctx, SVC_LOG_ERROR, "unexpected encoding mode: %d\n",
-              svc_ctx->encoding_mode);
-      break;
-  }
-  si->enc_frame_flags = flags;
-}
-
-vpx_codec_err_t svc_get_layer_resolution(SvcContext* svc_ctx, int layer,
-                                         unsigned int* width,
-                                         unsigned int* height) {
-  int w, h, index, num, den;
-  SvcInternal* si = (SvcInternal*)svc_ctx->internal;
-
-  if (layer < 0 || layer >= si->layers) return VPX_CODEC_INVALID_PARAM;
-
-  index = layer + VPX_SS_MAX_LAYERS - si->layers;
-  num = si->scaling_factor_num[index];
-  den = si->scaling_factor_den[index];
-  if (num == 0 || den == 0) return VPX_CODEC_INVALID_PARAM;
-
-  w = si->width * num / den;
-  h = si->height * num / den;
-
-  // make height and width even to make chrome player happy
-  w += w % 2;
-  h += h % 2;
-
-  *width = w;
-  *height = h;
-
-  return VPX_CODEC_OK;
-}
-
-static void set_svc_parameters(SvcContext* svc_ctx,
-                               vpx_codec_ctx_t* codec_ctx) {
-  int layer, layer_index;
-  vpx_svc_parameters_t svc_params;
-  int use_higher_layer;
-  SvcInternal* si = (SvcInternal*)svc_ctx->internal;
-
-  memset(&svc_params, 0, sizeof(svc_params));
-  svc_params.layer = si->layer;
-  svc_params.flags = si->enc_frame_flags;
-
-  layer = si->layer;
-  if (svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP &&
-      si->frame_within_gop == 0) {
-    // layers 1 & 3 don't exist in this mode, use the higher one
-    if (layer == 0 || layer == 2) {
-      layer += 1;
-    }
-  }
-  if (VPX_CODEC_OK != svc_get_layer_resolution(svc_ctx, layer,
-                                               &svc_params.width,
-                                               &svc_params.height)) {
-    svc_log(svc_ctx, SVC_LOG_ERROR, "svc_get_layer_resolution failed\n");
-  }
-  layer_index = layer + VPX_SS_MAX_LAYERS - si->layers;
-  svc_params.min_quantizer = si->quantizer[layer_index];
-  svc_params.max_quantizer = si->quantizer[layer_index];
-  svc_params.distance_from_i_frame = si->frame_within_gop;
-
-  // Use buffer i for layer i LST
-  svc_params.lst_fb_idx = si->layer;
-
-  // Use buffer i-1 for layer i Alt (Inter-layer prediction)
-  if (si->layer != 0) {
-    use_higher_layer =
-        svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP &&
-        si->frame_within_gop == 0;
-    svc_params.alt_fb_idx = use_higher_layer ? si->layer - 2 : si->layer - 1;
-  }
-
-  if (svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP) {
-    svc_params.gld_fb_idx = si->layer + 1;
-  } else {
-    if (si->layer < 2 * si->layers - SVC_REFERENCE_FRAMES)
-      svc_params.gld_fb_idx = svc_params.lst_fb_idx;
-    else
-      svc_params.gld_fb_idx = 2 * si->layers - 1 - si->layer;
-  }
-
-  svc_log(svc_ctx, SVC_LOG_DEBUG, "%sSVC frame: %d, layer: %d, %dx%d, q: %d\n",
-          svc_ctx->log_print ? colors[si->layer] : "",  //
-          si->encode_frame_count, si->layer, svc_params.width,
-          svc_params.height, svc_params.min_quantizer);
-
-  if (svc_params.flags == VPX_EFLAG_FORCE_KF) {
-    svc_log(svc_ctx, SVC_LOG_DEBUG, "flags == VPX_EFLAG_FORCE_KF\n");
-  } else {
-    svc_log(
-        svc_ctx, SVC_LOG_DEBUG, "Using:    LST/GLD/ALT [%2d|%2d|%2d]\n",
-        svc_params.flags & VP8_EFLAG_NO_REF_LAST ? -1 : svc_params.lst_fb_idx,
-        svc_params.flags & VP8_EFLAG_NO_REF_GF ? -1 : svc_params.gld_fb_idx,
-        svc_params.flags & VP8_EFLAG_NO_REF_ARF ? -1 : svc_params.alt_fb_idx);
-    svc_log(
-        svc_ctx, SVC_LOG_DEBUG, "Updating: LST/GLD/ALT [%2d|%2d|%2d]\n",
-        svc_params.flags & VP8_EFLAG_NO_UPD_LAST ? -1 : svc_params.lst_fb_idx,
-        svc_params.flags & VP8_EFLAG_NO_UPD_GF ? -1 : svc_params.gld_fb_idx,
-        svc_params.flags & VP8_EFLAG_NO_UPD_ARF ? -1 : svc_params.alt_fb_idx);
-  }
-
-  vpx_codec_control(codec_ctx, VP9E_SET_SVC_PARAMETERS, &svc_params);
-}
-
-/**
- * Helper to check if the current frame is the first, full resolution dummy.
- */
-static int vpx_svc_dummy_frame(SvcContext* svc_ctx, SvcInternal* si) {
-  return svc_ctx->first_frame_full_size == 1 && si->encode_frame_count == 0;
-}
-
-/**
- * Encode a frame into multiple layers
- * Create a superframe containing the individual layers
- */
-vpx_codec_err_t vpx_svc_encode(SvcContext* svc_ctx, vpx_codec_ctx_t* codec_ctx,
-                               struct vpx_image* rawimg, vpx_codec_pts_t pts,
-                               int64_t duration, int deadline) {
-  vpx_codec_err_t res;
-  vpx_codec_iter_t iter;
-  const vpx_codec_cx_pkt_t* cx_pkt;
-  struct LayerData* cx_layer_list = NULL;
-  struct LayerData* layer_data;
-  size_t frame_pkt_size;
-  struct Superframe superframe;
-  SvcInternal* si = (SvcInternal*)svc_ctx->internal;
-
-  memset(&superframe, 0, sizeof(superframe));
-  svc_log_reset(svc_ctx);
-
-  si->layers = vpx_svc_dummy_frame(svc_ctx, si) ? 1 : svc_ctx->spatial_layers;
-  if (si->frame_within_gop >= svc_ctx->gop_size ||
-      si->encode_frame_count == 0 ||
-      (si->encode_frame_count == 1 && svc_ctx->first_frame_full_size == 1)) {
-    si->frame_within_gop = 0;
-  }
-  si->is_keyframe = (si->frame_within_gop == 0);
-  si->frame_size = 0;
-
-  svc_log(svc_ctx, SVC_LOG_DEBUG,
-          "vpx_svc_encode  layers: %d, frame_count: %d, frame_within_gop: %d\n",
-          si->layers, si->encode_frame_count, si->frame_within_gop);
-
-  // encode each layer
-  for (si->layer = 0; si->layer < si->layers; si->layer++) {
-    if (svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP &&
-        si->is_keyframe && (si->layer == 1 || si->layer == 3)) {
-      svc_log(svc_ctx, SVC_LOG_DEBUG, "Skip encoding layer %d\n", si->layer);
-      continue;
-    }
-    calculate_enc_frame_flags(svc_ctx);
-
-    if (vpx_svc_dummy_frame(svc_ctx, si)) {
-      // do not set svc parameters, use normal encode
-      svc_log(svc_ctx, SVC_LOG_DEBUG, "encoding full size first frame\n");
-    } else {
-      set_svc_parameters(svc_ctx, codec_ctx);
-    }
-    res = vpx_codec_encode(codec_ctx, rawimg, pts, duration,
-                           si->enc_frame_flags, deadline);
-    if (res != VPX_CODEC_OK) {
-      return res;
-    }
-    // save compressed data
-    iter = NULL;
-    while ((cx_pkt = vpx_codec_get_cx_data(codec_ctx, &iter))) {
-      switch (cx_pkt->kind) {
-        case VPX_CODEC_CX_FRAME_PKT:
-          frame_pkt_size = cx_pkt->data.frame.sz;
-          if (!vpx_svc_dummy_frame(svc_ctx, si)) {
-            si->bytes_in_layer[si->layer] += frame_pkt_size;
-
-            svc_log(svc_ctx, SVC_LOG_DEBUG,
-                    "SVC frame: %d, layer: %d, size: %ld%s\n",
-                    si->encode_frame_count, si->layer, frame_pkt_size,
-                    svc_ctx->log_print ? normal_color : "");
-          }
-          layer_data = ld_create(cx_pkt->data.frame.buf, frame_pkt_size);
-          if (layer_data == NULL) {
-            svc_log(svc_ctx, SVC_LOG_ERROR, "Error allocating LayerData\n");
-            return 0;
-          }
-          ld_list_add(&cx_layer_list, layer_data);
-
-          // save layer size in superframe index
-          superframe.sizes[superframe.count++] = frame_pkt_size;
-          superframe.magnitude |= frame_pkt_size;
-          break;
-        case VPX_CODEC_PSNR_PKT:
-          if (!vpx_svc_dummy_frame(svc_ctx, si)) {
-            svc_log(svc_ctx, SVC_LOG_DEBUG,
-                    "%sSVC frame: %d, layer: %d, PSNR(Total/Y/U/V): "
-                    "%2.3f  %2.3f  %2.3f  %2.3f \n",
-                    svc_ctx->log_print ? colors[si->layer] : "",
-                    si->encode_frame_count, si->layer,
-                    cx_pkt->data.psnr.psnr[0], cx_pkt->data.psnr.psnr[1],
-                    cx_pkt->data.psnr.psnr[2], cx_pkt->data.psnr.psnr[3]);
-            si->psnr_in_layer[si->layer] += cx_pkt->data.psnr.psnr[0];
-          }
-          break;
-        default:
-          break;
-      }
-    }
-  }
-  // add superframe index to layer data list
-  if (!vpx_svc_dummy_frame(svc_ctx, si)) {
-    sf_create_index(&superframe);
-    layer_data = ld_create(superframe.buffer, superframe.index_size);
-    ld_list_add(&cx_layer_list, layer_data);
-  }
-  // get accumulated size of layer data
-  si->frame_size = ld_list_get_buffer_size(cx_layer_list);
-  if (si->frame_size == 0) return VPX_CODEC_ERROR;
-
-  // all layers encoded, create single buffer with concatenated layers
-  if (si->frame_size > si->buffer_size) {
-    free(si->buffer);
-    si->buffer = malloc(si->frame_size);
-    si->buffer_size = si->frame_size;
-  }
-  // copy layer data into packet
-  ld_list_copy_to_buffer(cx_layer_list, si->buffer);
-
-  ld_list_free(cx_layer_list);
-
-  svc_log(svc_ctx, SVC_LOG_DEBUG,
-          "SVC frame: %d, kf: %d, size: %ld, pts: %ld\n",
-          si->encode_frame_count, si->is_keyframe, si->frame_size, pts);
-  si->frame_within_gop++;
-  si->encode_frame_count++;
-
-  return VPX_CODEC_OK;
-}
-
-char* svc_get_message(SvcContext* svc_ctx) {
-  SvcInternal* si = (SvcInternal*)svc_ctx->internal;
-  return si->message_buffer;
-}
-
-void* svc_get_buffer(SvcContext* svc_ctx) {
-  SvcInternal* si = (SvcInternal*)svc_ctx->internal;
-  return si->buffer;
-}
-
-int svc_get_frame_size(SvcContext* svc_ctx) {
-  SvcInternal* si = (SvcInternal*)svc_ctx->internal;
-  return si->frame_size;
-}
-
-int svc_get_encode_frame_count(SvcContext* svc_ctx) {
-  SvcInternal* si = (SvcInternal*)svc_ctx->internal;
-  return si->encode_frame_count;
-}
-
-int svc_is_keyframe(SvcContext* svc_ctx) {
-  SvcInternal* si = (SvcInternal*)svc_ctx->internal;
-  return (si->is_keyframe);
-}
-
-void svc_set_keyframe(SvcContext* svc_ctx) {
-  SvcInternal* si = (SvcInternal*)svc_ctx->internal;
-  si->frame_within_gop = 0;
-}
-
-void svc_dump_statistics(SvcContext* svc_ctx) {
-  int number_of_frames, number_of_keyframes, encode_frame_count;
-  int i;
-  int bytes_total = 0;
-  SvcInternal* si = (SvcInternal*)svc_ctx->internal;
-
-  svc_log_reset(svc_ctx);
-
-  encode_frame_count = si->encode_frame_count;
-  if (svc_ctx->first_frame_full_size) encode_frame_count--;
-  if (si->encode_frame_count <= 0) return;
-
-  svc_log(svc_ctx, SVC_LOG_INFO, "\n");
-  number_of_keyframes = encode_frame_count / svc_ctx->gop_size + 1;
-  for (i = 0; i < si->layers; i++) {
-    number_of_frames = encode_frame_count;
-
-    if (svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP &&
-        (i == 1 || i == 3)) {
-      number_of_frames -= number_of_keyframes;
-    }
-    svc_log(svc_ctx, SVC_LOG_INFO, "Layer %d PSNR=[%2.3f], Bytes=[%d]\n", i,
-            (double)si->psnr_in_layer[i] / number_of_frames,
-            si->bytes_in_layer[i]);
-    bytes_total += si->bytes_in_layer[i];
-  }
-
-  // only display statistics once
-  si->encode_frame_count = 0;
-
-  svc_log(svc_ctx, SVC_LOG_INFO, "Total Bytes=[%d]\n", bytes_total);
-}
-
-static void svc_log_reset(SvcContext* svc_ctx) {
-  SvcInternal* si = (SvcInternal*)svc_ctx->internal;
-  si->message_buffer[0] = '\0';
-}
-
-static int svc_log(SvcContext* svc_ctx, int level, char* fmt, ...) {
-  char buf[512];
-  int retval = 0;
-  va_list ap;
-  SvcInternal* si = (SvcInternal*)svc_ctx->internal;
-
-  if (level > svc_ctx->log_level) {
-    return retval;
-  }
-
-  va_start(ap, fmt);
-  retval = vsnprintf(buf, sizeof(buf), fmt, ap);
-  va_end(ap);
-
-  if (svc_ctx->log_print) {
-    printf("%s", buf);
-  } else {
-    strncat(si->message_buffer, buf,
-            sizeof(si->message_buffer) - strlen(si->message_buffer) - 1);
-  }
-
-  if (level == SVC_LOG_ERROR) {
-    si->codec_ctx->err_detail = si->message_buffer;
-  }
-  return retval;
-}
--- a/vpx/svc_context.h
+++ /dev/null
@@ -1,62 +1,0 @@
-/**
- * SvcContext - input parameters and state to encode a multi-layered
- * spatial SVC frame
- */
-
-#ifndef VPX_SVC_CONTEXT_H_
-#define VPX_SVC_CONTEXT_H_
-
-typedef enum SVC_ENCODING_MODE {
-  INTER_LAYER_PREDICTION_I,
-  ALT_INTER_LAYER_PREDICTION_IP,
-  INTER_LAYER_PREDICTION_IP,
-  USE_GOLDEN_FRAME
-} SVC_ENCODING_MODE;
-
-typedef enum SVC_LOG_LEVEL {
-  SVC_LOG_ERROR,
-  SVC_LOG_INFO,
-  SVC_LOG_DEBUG,
-} SVC_LOG_LEVEL;
-
-typedef struct {
-  // public interface to svc_command options
-  int enabled;                      // set to non-zero to enable svc encoding
-  int spatial_layers;               // number of layers
-  int first_frame_full_size;        // set to one to force first frame full size
-  SVC_ENCODING_MODE encoding_mode;  // svc encoding strategy
-
-  // the following lists are ordered from highest resolution to lowest
-  // if the strings are null, default values are used
-  const char* quantizer_values;  // quantizer values, e.g., "27,33,39,53,60"
-  const char* scale_factors;     // layer scale factors, e.g.,
-                                 // "16/16,11/16,7/16,5/16,4/16"
-  int gop_size;                  // distance between keyframes
-
-  SVC_LOG_LEVEL log_level;  // amount of information to display
-  int log_print;  // when set, printf log messages instead of returning the
-                  // message with svc_get_message
-
-  // private storage for vpx_svc_encode
-  void* internal;
-} SvcContext;
-
-vpx_codec_err_t vpx_svc_init(SvcContext* svc_ctx, vpx_codec_ctx_t* codec_ctx,
-                             vpx_codec_iface_t* iface,
-                             vpx_codec_enc_cfg_t* cfg);
-
-vpx_codec_err_t vpx_svc_encode(SvcContext* svc_ctx, vpx_codec_ctx_t* codec_ctx,
-                               struct vpx_image* rawimg, vpx_codec_pts_t pts,
-                               int64_t duration, int deadline);
-
-void svc_dump_statistics(SvcContext* svc_ctx);
-char* svc_get_message(SvcContext* svc_ctx);
-void* svc_get_buffer(SvcContext* svc_ctx);
-vpx_codec_err_t svc_get_layer_resolution(SvcContext* svc_ctx, int layer,
-                              unsigned int* width, unsigned int* height);
-int svc_get_frame_size(SvcContext* svc_ctx);
-int svc_get_encode_frame_count(SvcContext* svc_ctx);
-int svc_is_keyframe(SvcContext* svc_ctx);
-void svc_set_keyframe(SvcContext* svc_ctx);
-
-#endif /* VPX_SVC_CONTEXT_H_ */
--- a/vpx/vp8cx.h
+++ b/vpx/vp8cx.h
@@ -195,8 +195,13 @@
   VP9E_SET_TILE_ROWS,
   VP9E_SET_FRAME_PARALLEL_DECODING,
 
+  VP9E_SET_WIDTH              = 99,
+  VP9E_SET_HEIGHT,
+  VP9E_SET_LAYER,
   VP9E_SET_SVC,
-  VP9E_SET_SVC_PARAMETERS
+
+  VP9E_SET_MAX_Q,
+  VP9E_SET_MIN_Q
 };
 
 /*!\brief vpx 1-D scaling mode
@@ -278,23 +283,6 @@
   VP8_TUNE_SSIM
 } vp8e_tuning;
 
-/*!\brief  vp9 svc parameters
- *
- * This defines parameters for svc encoding.
- *
- */
-typedef struct vpx_svc_parameters {
-  unsigned int width;         /**<  width of current spatial layer */
-  unsigned int height;        /**< height of current spatial layer */
-  int layer;                  /**< current layer number - 0 = base */
-  int flags;                  /**<  encode frame flags */
-  int max_quantizer;          /**< max quantizer for current layer */
-  int min_quantizer;          /**< min quantizer for current layer */
-  int distance_from_i_frame;  /**< frame number within current gop */
-  int lst_fb_idx;             /**< last frame frame buffer index */
-  int gld_fb_idx;             /**< golden frame frame buffer index */
-  int alt_fb_idx;             /**< alt reference frame frame buffer index */
-} vpx_svc_parameters_t;
 
 /*!\brief VP8 encoder control function parameter type
  *
@@ -315,9 +303,12 @@
 VPX_CTRL_USE_TYPE(VP8E_SET_ACTIVEMAP,          vpx_active_map_t *)
 VPX_CTRL_USE_TYPE(VP8E_SET_SCALEMODE,          vpx_scaling_mode_t *)
 
+VPX_CTRL_USE_TYPE(VP9E_SET_LAYER,              int *)
 VPX_CTRL_USE_TYPE(VP9E_SET_SVC,                int)
-VPX_CTRL_USE_TYPE(VP9E_SET_SVC_PARAMETERS,     vpx_svc_parameters_t *)
 
+VPX_CTRL_USE_TYPE(VP9E_SET_WIDTH,              unsigned int *)
+VPX_CTRL_USE_TYPE(VP9E_SET_HEIGHT,             unsigned int *)
+
 VPX_CTRL_USE_TYPE(VP8E_SET_CPUUSED,            int)
 VPX_CTRL_USE_TYPE(VP8E_SET_ENABLEAUTOALTREF,   unsigned int)
 VPX_CTRL_USE_TYPE(VP8E_SET_NOISE_SENSITIVITY,  unsigned int)
@@ -343,6 +334,8 @@
 
 VPX_CTRL_USE_TYPE(VP9E_SET_FRAME_PARALLEL_DECODING, unsigned int)
 
+VPX_CTRL_USE_TYPE(VP9E_SET_MAX_Q,      unsigned int)
+VPX_CTRL_USE_TYPE(VP9E_SET_MIN_Q,      unsigned int)
 /*! @} - end defgroup vp8_encoder */
 #ifdef __cplusplus
 }  // extern "C"
--- a/vpx/vpx_codec.mk
+++ b/vpx/vpx_codec.mk
@@ -15,8 +15,6 @@
 API_SRCS-$(CONFIG_VP8_ENCODER) += vp8cx.h
 API_DOC_SRCS-$(CONFIG_VP8_ENCODER) += vp8.h
 API_DOC_SRCS-$(CONFIG_VP8_ENCODER) += vp8cx.h
-API_SRCS-$(CONFIG_VP9_ENCODER) += src/svc_encodeframe.c
-API_SRCS-$(CONFIG_VP9_ENCODER) += svc_context.h
 
 API_SRCS-$(CONFIG_VP8_DECODER) += vp8.h
 API_SRCS-$(CONFIG_VP8_DECODER) += vp8dx.h