Merge "decode_test_driver: Use size_t for size arg to DecodeFrame()."
diff --git a/build/make/gen_msvs_vcxproj.sh b/build/make/gen_msvs_vcxproj.sh
index 359157c..a6315b9 100755
--- a/build/make/gen_msvs_vcxproj.sh
+++ b/build/make/gen_msvs_vcxproj.sh
@@ -174,6 +174,10 @@
                         Include=".\\$f"
                     # Separate file names with Condition?
                     tag_content ObjectFileName "\$(IntDir)$objf"
+                    # Check for AVX and turn it on to avoid warnings.
+                    if [[ $f =~ avx.?\.c$ ]]; then
+                        tag_content AdditionalOptions "/arch:AVX"
+                    fi
                     close_tag ClCompile
                 elif [ "$pat" == "h" ] ; then
                     tag ClInclude \
diff --git a/examples.mk b/examples.mk
index 24b5c37..5f12b6b 100644
--- a/examples.mk
+++ b/examples.mk
@@ -58,6 +58,8 @@
 vp9_spatial_scalable_encoder.SRCS += args.c args.h
 vp9_spatial_scalable_encoder.SRCS += ivfenc.c ivfenc.h
 vp9_spatial_scalable_encoder.SRCS += tools_common.c tools_common.h
+vp9_spatial_scalable_encoder.SRCS += video_common.h
+vp9_spatial_scalable_encoder.SRCS += video_writer.h video_writer.c
 vp9_spatial_scalable_encoder.GUID   = 4A38598D-627D-4505-9C7B-D4020C84100D
 vp9_spatial_scalable_encoder.DESCRIPTION = Spatial Scalable Encoder
 
diff --git a/examples/decode_to_md5.c b/examples/decode_to_md5.c
index 077513c..aabac60 100644
--- a/examples/decode_to_md5.c
+++ b/examples/decode_to_md5.c
@@ -82,9 +82,9 @@
   int frame_cnt = 0;
   FILE *outfile = NULL;
   vpx_codec_ctx_t codec;
-  vpx_codec_iface_t *iface = NULL;
   VpxVideoReader *reader = NULL;
   const VpxVideoInfo *info = NULL;
+  const VpxInterface *decoder = NULL;
 
   exec_name = argv[0];
 
@@ -100,13 +100,13 @@
 
   info = vpx_video_reader_get_info(reader);
 
-  iface = get_codec_interface(info->codec_fourcc);
-  if (!iface)
+  decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc);
+  if (!decoder)
     die("Unknown input codec.");
 
-  printf("Using %s\n", vpx_codec_iface_name(iface));
+  printf("Using %s\n", vpx_codec_iface_name(decoder->interface()));
 
-  if (vpx_codec_dec_init(&codec, iface, NULL, 0))
+  if (vpx_codec_dec_init(&codec, decoder->interface(), NULL, 0))
     die_codec(&codec, "Failed to initialize decoder");
 
   while (vpx_video_reader_read_frame(reader)) {
diff --git a/examples/decode_with_drops.c b/examples/decode_with_drops.c
index e8fc076..c6f7d43 100644
--- a/examples/decode_with_drops.c
+++ b/examples/decode_with_drops.c
@@ -76,7 +76,7 @@
   int frame_cnt = 0;
   FILE *outfile = NULL;
   vpx_codec_ctx_t codec;
-  vpx_codec_iface_t *iface = NULL;
+  const VpxInterface *decoder = NULL;
   VpxVideoReader *reader = NULL;
   const VpxVideoInfo *info = NULL;
   int n = 0;
@@ -104,13 +104,13 @@
 
   info = vpx_video_reader_get_info(reader);
 
-  iface = get_codec_interface(info->codec_fourcc);
-  if (!iface)
+  decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc);
+  if (!decoder)
     die("Unknown input codec.");
 
-  printf("Using %s\n", vpx_codec_iface_name(iface));
+  printf("Using %s\n", vpx_codec_iface_name(decoder->interface()));
 
-  if (vpx_codec_dec_init(&codec, iface, NULL, 0))
+  if (vpx_codec_dec_init(&codec, decoder->interface(), NULL, 0))
     die_codec(&codec, "Failed to initialize decoder.");
 
   while (vpx_video_reader_read_frame(reader)) {
diff --git a/examples/postproc.c b/examples/postproc.c
index 7281f1e..2912fe6 100644
--- a/examples/postproc.c
+++ b/examples/postproc.c
@@ -64,8 +64,8 @@
   FILE *outfile = NULL;
   vpx_codec_ctx_t codec;
   vpx_codec_err_t res;
-  vpx_codec_iface_t *iface = NULL;
   VpxVideoReader *reader = NULL;
+  const VpxInterface *decoder = NULL;
   const VpxVideoInfo *info = NULL;
 
   exec_name = argv[0];
@@ -82,17 +82,16 @@
 
   info = vpx_video_reader_get_info(reader);
 
-  iface = get_codec_interface(info->codec_fourcc);
-  if (!iface)
+  decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc);
+  if (!decoder)
     die("Unknown input codec.");
 
-  printf("Using %s\n", vpx_codec_iface_name(iface));
+  printf("Using %s\n", vpx_codec_iface_name(decoder->interface()));
 
-  res = vpx_codec_dec_init(&codec, iface, NULL, VPX_CODEC_USE_POSTPROC);
-  if (res == VPX_CODEC_INCAPABLE) {
-    printf("NOTICE: Postproc not supported.\n");
-    res = vpx_codec_dec_init(&codec, iface, NULL, 0);
-  }
+  res = vpx_codec_dec_init(&codec, decoder->interface(), NULL,
+                           VPX_CODEC_USE_POSTPROC);
+  if (res == VPX_CODEC_INCAPABLE)
+    die_codec(&codec, "Postproc not supported by this decoder.");
 
   if (res)
     die_codec(&codec, "Failed to initialize decoder.");
diff --git a/examples/simple_decoder.c b/examples/simple_decoder.c
index 4dc9308..b0ca77d 100644
--- a/examples/simple_decoder.c
+++ b/examples/simple_decoder.c
@@ -101,8 +101,8 @@
   int frame_cnt = 0;
   FILE *outfile = NULL;
   vpx_codec_ctx_t codec;
-  vpx_codec_iface_t *iface = NULL;
   VpxVideoReader *reader = NULL;
+  const VpxInterface *decoder = NULL;
   const VpxVideoInfo *info = NULL;
 
   exec_name = argv[0];
@@ -119,13 +119,13 @@
 
   info = vpx_video_reader_get_info(reader);
 
-  iface = get_codec_interface(info->codec_fourcc);
-  if (!iface)
+  decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc);
+  if (!decoder)
     die("Unknown input codec.");
 
-  printf("Using %s\n", vpx_codec_iface_name(iface));
+  printf("Using %s\n", vpx_codec_iface_name(decoder->interface()));
 
-  if (vpx_codec_dec_init(&codec, iface, NULL, 0))
+  if (vpx_codec_dec_init(&codec, decoder->interface(), NULL, 0))
     die_codec(&codec, "Failed to initialize decoder.");
 
   while (vpx_video_reader_read_frame(reader)) {
diff --git a/examples/simple_encoder.c b/examples/simple_encoder.c
index 5076054..2e7c7a6 100644
--- a/examples/simple_encoder.c
+++ b/examples/simple_encoder.c
@@ -86,18 +86,16 @@
 #include <string.h>
 
 #define VPX_CODEC_DISABLE_COMPAT 1
-#include "vpx/vp8cx.h"
 #include "vpx/vpx_encoder.h"
 
 #include "./tools_common.h"
 #include "./video_writer.h"
 
-#define interface (vpx_codec_vp8_cx())
-
 static const char *exec_name;
 
 void usage_exit() {
-  fprintf(stderr, "Usage: %s <width> <height> <infile> <outfile>\n", exec_name);
+  fprintf(stderr, "Usage: %s <codec> <width> <height> <infile> <outfile>\n",
+          exec_name);
   exit(EXIT_FAILURE);
 }
 
@@ -110,17 +108,27 @@
   vpx_codec_err_t res;
   VpxVideoInfo info = {0};
   VpxVideoWriter *writer = NULL;
+  const VpxInterface *encoder = NULL;
   const int fps = 30;        // TODO(dkovalev) add command line argument
   const int bitrate = 200;   // kbit/s TODO(dkovalev) add command line argument
+  const char *const codec_arg = argv[1];
+  const char *const width_arg = argv[2];
+  const char *const height_arg = argv[3];
+  const char *const infile_arg = argv[4];
+  const char *const outfile_arg = argv[5];
 
   exec_name = argv[0];
 
-  if (argc != 5)
+  if (argc != 6)
     die("Invalid number of arguments");
 
-  info.codec_fourcc = VP8_FOURCC;
-  info.frame_width = strtol(argv[1], NULL, 0);
-  info.frame_height = strtol(argv[2], NULL, 0);
+  encoder = get_vpx_encoder_by_name(codec_arg);
+  if (!encoder)
+     die("Unsupported codec.");
+
+  info.codec_fourcc = encoder->fourcc;
+  info.frame_width = strtol(width_arg, NULL, 0);
+  info.frame_height = strtol(height_arg, NULL, 0);
   info.time_base.numerator = 1;
   info.time_base.denominator = fps;
 
@@ -136,9 +144,9 @@
     die("Failed to allocate image.");
   }
 
-  printf("Using %s\n", vpx_codec_iface_name(interface));
+  printf("Using %s\n", vpx_codec_iface_name(encoder->interface()));
 
-  res = vpx_codec_enc_config_default(interface, &cfg, 0);
+  res = vpx_codec_enc_config_default(encoder->interface(), &cfg, 0);
   if (res)
     die_codec(&codec, "Failed to get default codec config.");
 
@@ -148,14 +156,14 @@
   cfg.g_timebase.den = info.time_base.denominator;
   cfg.rc_target_bitrate = bitrate;
 
-  writer = vpx_video_writer_open(argv[4], kContainerIVF, &info);
+  writer = vpx_video_writer_open(outfile_arg, kContainerIVF, &info);
   if (!writer)
-    die("Failed to open %s for writing.", argv[4]);
+    die("Failed to open %s for writing.", outfile_arg);
 
-  if (!(infile = fopen(argv[3], "rb")))
-    die("Failed to open %s for reading.", argv[3]);
+  if (!(infile = fopen(infile_arg, "rb")))
+    die("Failed to open %s for reading.", infile_arg);
 
-  if (vpx_codec_enc_init(&codec, interface, &cfg, 0))
+  if (vpx_codec_enc_init(&codec, encoder->interface(), &cfg, 0))
     die_codec(&codec, "Failed to initialize encoder");
 
   while (vpx_img_read(&raw, infile)) {
diff --git a/examples/twopass_encoder.c b/examples/twopass_encoder.c
index 93b6150..f16db66 100644
--- a/examples/twopass_encoder.c
+++ b/examples/twopass_encoder.c
@@ -53,18 +53,16 @@
 #include <string.h>
 
 #define VPX_CODEC_DISABLE_COMPAT 1
-#include "vpx/vp8cx.h"
 #include "vpx/vpx_encoder.h"
 
 #include "./tools_common.h"
 #include "./video_writer.h"
 
-#define interface (vpx_codec_vp8_cx())
-
 static const char *exec_name;
 
 void usage_exit() {
-  fprintf(stderr, "Usage: %s <width> <height> <infile> <outfile>\n", exec_name);
+  fprintf(stderr, "Usage: %s <codec> <width> <height> <infile> <outfile>\n",
+          exec_name);
   exit(EXIT_FAILURE);
 }
 
@@ -130,18 +128,29 @@
   vpx_codec_err_t res;
   vpx_fixed_buf_t stats = {0};
   VpxVideoInfo info = {0};
+  const VpxInterface *encoder = NULL;
   int pass;
   const int fps = 30;        // TODO(dkovalev) add command line argument
   const int bitrate = 200;   // kbit/s TODO(dkovalev) add command line argument
+  const char *const codec_arg = argv[1];
+  const char *const width_arg = argv[2];
+  const char *const height_arg = argv[3];
+  const char *const infile_arg = argv[4];
+  const char *const outfile_arg = argv[5];
+  exec_name = argv[0];
 
-  if (argc != 5)
+  if (argc != 6)
     die("Invalid number of arguments.");
 
-  info.codec_fourcc = VP8_FOURCC;
+  encoder = get_vpx_encoder_by_name(codec_arg);
+  if (!encoder)
+    die("Unsupported codec.");
+
+  info.codec_fourcc = encoder->fourcc;
   info.time_base.numerator = 1;
   info.time_base.denominator = fps;
-  info.frame_width = strtol(argv[1], NULL, 0);
-  info.frame_height = strtol(argv[2], NULL, 0);
+  info.frame_width = strtol(width_arg, NULL, 0);
+  info.frame_height = strtol(height_arg, NULL, 0);
 
   if (info.frame_width <= 0 ||
       info.frame_height <= 0 ||
@@ -155,13 +164,13 @@
     die("Failed to allocate image", info.frame_width, info.frame_height);
   }
 
-  writer = vpx_video_writer_open(argv[4], kContainerIVF, &info);
+  writer = vpx_video_writer_open(outfile_arg, kContainerIVF, &info);
   if (!writer)
-    die("Failed to open %s for writing", argv[4]);
+    die("Failed to open %s for writing", outfile_arg);
 
-  printf("Using %s\n", vpx_codec_iface_name(interface));
+  printf("Using %s\n", vpx_codec_iface_name(encoder->interface()));
 
-  res = vpx_codec_enc_config_default(interface, &cfg, 0);
+  res = vpx_codec_enc_config_default(encoder->interface(), &cfg, 0);
   if (res)
     die_codec(&codec, "Failed to get default codec config.");
 
@@ -181,10 +190,10 @@
       cfg.rc_twopass_stats_in = stats;
     }
 
-    if (!(infile = fopen(argv[3], "rb")))
-      die("Failed to open %s for reading", argv[3]);
+    if (!(infile = fopen(infile_arg, "rb")))
+      die("Failed to open %s for reading", infile_arg);
 
-    if (vpx_codec_enc_init(&codec, interface, &cfg, 0))
+    if (vpx_codec_enc_init(&codec, encoder->interface(), &cfg, 0))
       die_codec(&codec, "Failed to initialize encoder");
 
     while (vpx_img_read(&raw, infile)) {
diff --git a/examples/vpx_temporal_scalable_patterns.c b/examples/vpx_temporal_scalable_patterns.c
index 11d331b..c40450e 100644
--- a/examples/vpx_temporal_scalable_patterns.c
+++ b/examples/vpx_temporal_scalable_patterns.c
@@ -360,9 +360,7 @@
   int flag_periodicity = 1;
   int max_intra_size_pct;
   vpx_svc_layer_id_t layer_id = {0, 0};
-  char *codec_type;
-  vpx_codec_iface_t *(*interface)(void);
-  unsigned int fourcc;
+  const VpxInterface *encoder = NULL;
   struct VpxInputContext input_ctx = {0};
 
   exec_name = argv[0];
@@ -373,23 +371,11 @@
         argv[0]);
   }
 
-  codec_type = argv[3];
-  if (strncmp(codec_type, "vp9", 3) == 0) {
-#if CONFIG_VP9_ENCODER
-    interface = vpx_codec_vp9_cx;
-    fourcc = VP9_FOURCC;
-#else
-    die("Encoder vp9 selected but not configured");
-#endif
-  } else  {
-#if CONFIG_VP8_ENCODER
-    interface = vpx_codec_vp8_cx;
-    fourcc = VP8_FOURCC;
-#else
-    die("Encoder vp8 selected but not configured");
-#endif
-  }
-  printf("Using %s\n", vpx_codec_iface_name(interface()));
+  encoder = get_vpx_encoder_by_name(argv[3]);
+  if (!encoder)
+    die("Unsupported codec.");
+
+  printf("Using %s\n", vpx_codec_iface_name(encoder->interface()));
 
   width = strtol(argv[4], NULL, 0);
   height = strtol(argv[5], NULL, 0);
@@ -411,7 +397,7 @@
   }
 
   // Populate encoder configuration.
-  res = vpx_codec_enc_config_default(interface(), &cfg, 0);
+  res = vpx_codec_enc_config_default(encoder->interface(), &cfg, 0);
   if (res) {
     printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
     return EXIT_FAILURE;
@@ -467,7 +453,7 @@
   for (i = 0; i < cfg.ts_number_layers; ++i) {
     char file_name[PATH_MAX];
     VpxVideoInfo info;
-    info.codec_fourcc = fourcc;
+    info.codec_fourcc = encoder->fourcc;
     info.frame_width = cfg.g_w;
     info.frame_height = cfg.g_h;
     info.time_base.numerator = cfg.g_timebase.num;
@@ -482,12 +468,12 @@
   cfg.ss_number_layers = 1;
 
   // Initialize codec.
-  if (vpx_codec_enc_init(&codec, interface(), &cfg, 0))
+  if (vpx_codec_enc_init(&codec, encoder->interface(), &cfg, 0))
     die_codec(&codec, "Failed to initialize encoder");
 
   vpx_codec_control(&codec, VP8E_SET_CPUUSED, -6);
   vpx_codec_control(&codec, VP8E_SET_NOISE_SENSITIVITY, 1);
-  if (strncmp(codec_type, "vp9", 3) == 0) {
+  if (strncmp(encoder->name, "vp9", 3) == 0) {
     vpx_codec_control(&codec, VP8E_SET_CPUUSED, 3);
     vpx_codec_control(&codec, VP8E_SET_NOISE_SENSITIVITY, 0);
     if (vpx_codec_control(&codec, VP9E_SET_SVC, 1)) {
diff --git a/test/datarate_test.cc b/test/datarate_test.cc
index 31b8239..5b0a548 100644
--- a/test/datarate_test.cc
+++ b/test/datarate_test.cc
@@ -489,7 +489,7 @@
 }
 
 // Check basic rate targeting for 3 temporal layers.
-TEST_P(DatarateTestVP9, DISABLED_BasicRateTargeting3TemporalLayers) {
+TEST_P(DatarateTestVP9, BasicRateTargeting3TemporalLayers) {
   cfg_.rc_buf_initial_sz = 500;
   cfg_.rc_buf_optimal_sz = 500;
   cfg_.rc_buf_sz = 1000;
diff --git a/tools_common.c b/tools_common.c
index 5354687..5a1b701 100644
--- a/tools_common.c
+++ b/tools_common.c
@@ -15,6 +15,10 @@
 #include <stdlib.h>
 #include <string.h>
 
+#if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER
+#include "vpx/vp8cx.h"
+#endif
+
 #if CONFIG_VP8_DECODER || CONFIG_VP9_DECODER
 #include "vpx/vp8dx.h"
 #endif
@@ -144,19 +148,75 @@
   return shortread;
 }
 
-vpx_codec_iface_t *get_codec_interface(unsigned int fourcc) {
-  switch (fourcc) {
-#if CONFIG_VP8_DECODER
-    case VP8_FOURCC:
-      return vpx_codec_vp8_dx();
+static const VpxInterface vpx_encoders[] = {
+#if CONFIG_VP8_ENCODER
+  {"vp8", VP8_FOURCC, &vpx_codec_vp8_cx},
 #endif
-#if CONFIG_VP9_DECODER
-    case VP9_FOURCC:
-      return vpx_codec_vp9_dx();
+
+#if CONFIG_VP9_ENCODER
+  {"vp9", VP9_FOURCC, &vpx_codec_vp9_cx},
 #endif
-    default:
-      return NULL;
+};
+
+int get_vpx_encoder_count() {
+  return sizeof(vpx_encoders) / sizeof(vpx_encoders[0]);
+}
+
+const VpxInterface *get_vpx_encoder_by_index(int i) {
+  return &vpx_encoders[i];
+}
+
+const VpxInterface *get_vpx_encoder_by_name(const char *name) {
+  int i;
+
+  for (i = 0; i < get_vpx_encoder_count(); ++i) {
+    const VpxInterface *encoder = get_vpx_encoder_by_index(i);
+    if (strcmp(encoder->name, name) == 0)
+      return encoder;
   }
+
+  return NULL;
+}
+
+static const VpxInterface vpx_decoders[] = {
+#if CONFIG_VP8_DECODER
+  {"vp8", VP8_FOURCC, &vpx_codec_vp8_dx},
+#endif
+
+#if CONFIG_VP9_DECODER
+  {"vp9", VP9_FOURCC, &vpx_codec_vp9_dx},
+#endif
+};
+
+int get_vpx_decoder_count() {
+  return sizeof(vpx_decoders) / sizeof(vpx_decoders[0]);
+}
+
+const VpxInterface *get_vpx_decoder_by_index(int i) {
+  return &vpx_decoders[i];
+}
+
+const VpxInterface *get_vpx_decoder_by_name(const char *name) {
+  int i;
+
+  for (i = 0; i < get_vpx_decoder_count(); ++i) {
+     const VpxInterface *const decoder = get_vpx_decoder_by_index(i);
+     if (strcmp(decoder->name, name) == 0)
+       return decoder;
+  }
+
+  return NULL;
+}
+
+const VpxInterface *get_vpx_decoder_by_fourcc(uint32_t fourcc) {
+  int i;
+
+  for (i = 0; i < get_vpx_decoder_count(); ++i) {
+    const VpxInterface *const decoder = get_vpx_decoder_by_index(i);
+    if (decoder->fourcc == fourcc)
+      return decoder;
+  }
+
   return NULL;
 }
 
diff --git a/tools_common.h b/tools_common.h
index 0f60c4c..da87b6d 100644
--- a/tools_common.h
+++ b/tools_common.h
@@ -123,7 +123,20 @@
 
 int read_yuv_frame(struct VpxInputContext *input_ctx, vpx_image_t *yuv_frame);
 
-vpx_codec_iface_t *get_codec_interface(unsigned int fourcc);
+typedef struct VpxInterface {
+  const char *const name;
+  const uint32_t fourcc;
+  vpx_codec_iface_t *(*const interface)();
+} VpxInterface;
+
+int get_vpx_encoder_count();
+const VpxInterface *get_vpx_encoder_by_index(int i);
+const VpxInterface *get_vpx_encoder_by_name(const char *name);
+
+int get_vpx_decoder_count();
+const VpxInterface *get_vpx_decoder_by_index(int i);
+const VpxInterface *get_vpx_decoder_by_name(const char *name);
+const VpxInterface *get_vpx_decoder_by_fourcc(uint32_t fourcc);
 
 // TODO(dkovalev): move this function to vpx_image.{c, h}, so it will be part
 // of vpx_image_t support
diff --git a/vp9/common/vp9_rtcd_defs.sh b/vp9/common/vp9_rtcd_defs.sh
index 7bdd11e..878c751 100644
--- a/vp9/common/vp9_rtcd_defs.sh
+++ b/vp9/common/vp9_rtcd_defs.sh
@@ -737,20 +737,20 @@
 #
 # Motion search
 #
-prototype int vp9_full_search_sad "const struct macroblock *x, struct mv *ref_mv, int sad_per_bit, int distance, struct vp9_variance_vtable *fn_ptr, DEC_MVCOSTS, const struct mv *center_mv, int n"
+prototype int vp9_full_search_sad "const struct macroblock *x, const struct mv *ref_mv, int sad_per_bit, int distance, const struct vp9_variance_vtable *fn_ptr, DEC_MVCOSTS, const struct mv *center_mv, int n"
 specialize vp9_full_search_sad sse3 sse4_1
 vp9_full_search_sad_sse3=vp9_full_search_sadx3
 vp9_full_search_sad_sse4_1=vp9_full_search_sadx8
 
-prototype int vp9_refining_search_sad "const struct macroblock *x, struct mv *ref_mv, int sad_per_bit, int distance, struct vp9_variance_vtable *fn_ptr, DEC_MVCOSTS, const struct mv *center_mv"
+prototype int vp9_refining_search_sad "const struct macroblock *x, struct mv *ref_mv, int sad_per_bit, int distance, const struct vp9_variance_vtable *fn_ptr, DEC_MVCOSTS, const struct mv *center_mv"
 specialize vp9_refining_search_sad sse3
 vp9_refining_search_sad_sse3=vp9_refining_search_sadx4
 
-prototype int vp9_diamond_search_sad "const struct macroblock *x, struct mv *ref_mv, struct mv *best_mv, int search_param, int sad_per_bit, int *num00, struct vp9_variance_vtable *fn_ptr, DEC_MVCOSTS, const struct mv *center_mv"
+prototype int vp9_diamond_search_sad "const struct macroblock *x, struct mv *ref_mv, struct mv *best_mv, int search_param, int sad_per_bit, int *num00, const struct vp9_variance_vtable *fn_ptr, DEC_MVCOSTS, const struct mv *center_mv"
 specialize vp9_diamond_search_sad sse3
 vp9_diamond_search_sad_sse3=vp9_diamond_search_sadx4
 
-prototype int vp9_full_range_search "const struct macroblock *x, struct mv *ref_mv, struct mv *best_mv, int search_param, int sad_per_bit, int *num00, struct vp9_variance_vtable *fn_ptr, DEC_MVCOSTS, const struct mv *center_mv"
+prototype int vp9_full_range_search "const struct macroblock *x, struct mv *ref_mv, struct mv *best_mv, int search_param, int sad_per_bit, int *num00, const struct vp9_variance_vtable *fn_ptr, DEC_MVCOSTS, const struct mv *center_mv"
 specialize vp9_full_range_search
 
 prototype void vp9_temporal_filter_apply "uint8_t *frame1, unsigned int stride, uint8_t *frame2, unsigned int block_size, int strength, int filter_weight, unsigned int *accumulator, uint16_t *count"
diff --git a/vp9/decoder/vp9_onyxd_if.c b/vp9/decoder/vp9_onyxd_if.c
index fd34883..1d3522e 100644
--- a/vp9/decoder/vp9_onyxd_if.c
+++ b/vp9/decoder/vp9_onyxd_if.c
@@ -342,6 +342,10 @@
       cm->frame_refs[0].buf->corrupted = 1;
   }
 
+  // Check if the previous frame was a frame without any references to it.
+  if (cm->new_fb_idx >= 0 && cm->frame_bufs[cm->new_fb_idx].ref_count == 0)
+    cm->release_fb_cb(cm->cb_priv,
+                      &cm->frame_bufs[cm->new_fb_idx].raw_frame_buffer);
   cm->new_fb_idx = get_free_fb(cm);
 
   if (setjmp(cm->error.jmp)) {
diff --git a/vp9/encoder/vp9_block.h b/vp9/encoder/vp9_block.h
index 713cc51..7cbdfce 100644
--- a/vp9/encoder/vp9_block.h
+++ b/vp9/encoder/vp9_block.h
@@ -172,9 +172,7 @@
   int skip_encode;
 
   // Used to store sub partition's choices.
-  int fast_ms;
   int_mv pred_mv[MAX_REF_FRAMES];
-  int subblock_ref;
 
   // TODO(jingning): Need to refactor the structure arrays that buffers the
   // coding mode decisions of each partition type.
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c
index 1b106f4..879436a 100644
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -1253,9 +1253,6 @@
     x->mb_energy = vp9_block_energy(cpi, x, bsize);
   }
 
-  x->fast_ms = 0;
-  x->subblock_ref = 0;
-
   if (cpi->sf.adjust_partitioning_from_last_frame) {
     // Check if any of the sub blocks are further split.
     if (partition == PARTITION_SPLIT && subsize > BLOCK_8X8) {
@@ -1613,80 +1610,6 @@
   }
 }
 
-static void compute_fast_motion_search_level(VP9_COMP *cpi, BLOCK_SIZE bsize) {
-  VP9_COMMON *const cm = &cpi->common;
-  MACROBLOCK *const x = &cpi->mb;
-
-  if (cm->frame_type == INTER_FRAME &&
-      !cpi->rc.is_src_frame_alt_ref &&
-      (bsize == BLOCK_16X16 || bsize == BLOCK_32X32 || bsize == BLOCK_64X64)) {
-    const PICK_MODE_CONTEXT *block_context = get_block_context(x, bsize);
-    const int ref0 = block_context[0].mic.mbmi.ref_frame[0];
-    const int ref1 = block_context[1].mic.mbmi.ref_frame[0];
-    const int ref2 = block_context[2].mic.mbmi.ref_frame[0];
-    const int ref3 = block_context[3].mic.mbmi.ref_frame[0];
-
-    // Currently, only consider 4 inter reference frames.
-    if (ref0 && ref1 && ref2 && ref3) {
-      int d01, d23, d02, d13;
-
-      // Motion vectors for the four subblocks.
-      int16_t mvr0 = block_context[0].mic.mbmi.mv[0].as_mv.row;
-      int16_t mvc0 = block_context[0].mic.mbmi.mv[0].as_mv.col;
-      int16_t mvr1 = block_context[1].mic.mbmi.mv[0].as_mv.row;
-      int16_t mvc1 = block_context[1].mic.mbmi.mv[0].as_mv.col;
-      int16_t mvr2 = block_context[2].mic.mbmi.mv[0].as_mv.row;
-      int16_t mvc2 = block_context[2].mic.mbmi.mv[0].as_mv.col;
-      int16_t mvr3 = block_context[3].mic.mbmi.mv[0].as_mv.row;
-      int16_t mvc3 = block_context[3].mic.mbmi.mv[0].as_mv.col;
-
-      // Adjust sign if ref is alt_ref.
-      if (cm->ref_frame_sign_bias[ref0]) {
-        mvr0 *= -1;
-        mvc0 *= -1;
-      }
-
-      if (cm->ref_frame_sign_bias[ref1]) {
-        mvr1 *= -1;
-        mvc1 *= -1;
-      }
-
-      if (cm->ref_frame_sign_bias[ref2]) {
-        mvr2 *= -1;
-        mvc2 *= -1;
-      }
-
-      if (cm->ref_frame_sign_bias[ref3]) {
-        mvr3 *= -1;
-        mvc3 *= -1;
-      }
-
-      // Calculate mv distances.
-      d01 = MAX(abs(mvr0 - mvr1), abs(mvc0 - mvc1));
-      d23 = MAX(abs(mvr2 - mvr3), abs(mvc2 - mvc3));
-      d02 = MAX(abs(mvr0 - mvr2), abs(mvc0 - mvc2));
-      d13 = MAX(abs(mvr1 - mvr3), abs(mvc1 - mvc3));
-
-      if (d01 < FAST_MOTION_MV_THRESH && d23 < FAST_MOTION_MV_THRESH &&
-          d02 < FAST_MOTION_MV_THRESH && d13 < FAST_MOTION_MV_THRESH) {
-        // Set fast motion search level.
-        x->fast_ms = 1;
-
-        if (ref0 == ref1 && ref1 == ref2 && ref2 == ref3 &&
-            d01 < 2 && d23 < 2 && d02 < 2 && d13 < 2) {
-          // Set fast motion search level.
-          x->fast_ms = 2;
-
-          if (!d01 && !d23 && !d02 && !d13) {
-            x->fast_ms = 3;
-            x->subblock_ref = ref0;
-          }
-        }
-      }
-    }
-  }
-}
-
 static INLINE void store_pred_mv(MACROBLOCK *x, PICK_MODE_CONTEXT *ctx) {
   vpx_memcpy(ctx->pred_mv, x->pred_mv, sizeof(x->pred_mv));
 }
@@ -1726,8 +1649,6 @@
                                bsize >= BLOCK_8X8;
   int partition_vert_allowed = !force_horz_split && xss <= yss &&
                                bsize >= BLOCK_8X8;
-
-  int partition_split_done = 0;
   (void) *tp_orig;
 
   if (bsize < BLOCK_8X8) {
@@ -1869,18 +1790,9 @@
       if (cpi->sf.less_rectangular_check)
         do_rect &= !partition_none_allowed;
     }
-    partition_split_done = 1;
     restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
   }
 
-  x->fast_ms = 0;
-  x->subblock_ref = 0;
-
-  if (partition_split_done &&
-      cpi->sf.using_small_partition_info) {
-    compute_fast_motion_search_level(cpi, bsize);
-  }
-
   // PARTITION_HORZ
   if (partition_horz_allowed && do_rect) {
     subsize = get_subsize(bsize, PARTITION_HORZ);
@@ -2009,41 +1921,6 @@
   }
 }
 
-// Examines 64x64 block and chooses a best reference frame
-static void rd_pick_reference_frame(VP9_COMP *cpi, const TileInfo *const tile,
-                                    int mi_row, int mi_col) {
-  VP9_COMMON * const cm = &cpi->common;
-  MACROBLOCK * const x = &cpi->mb;
-  int bsl = b_width_log2(BLOCK_64X64), bs = 1 << bsl;
-  int ms = bs / 2;
-  ENTROPY_CONTEXT l[16 * MAX_MB_PLANE], a[16 * MAX_MB_PLANE];
-  PARTITION_CONTEXT sl[8], sa[8];
-  int pl;
-  int r;
-  int64_t d;
-
-  save_context(cpi, mi_row, mi_col, a, l, sa, sl, BLOCK_64X64);
-
-  // Default is non mask (all reference frames allowed.
-  cpi->ref_frame_mask = 0;
-
-  // Do RD search for 64x64.
-  if ((mi_row + (ms >> 1) < cm->mi_rows) &&
-      (mi_col + (ms >> 1) < cm->mi_cols)) {
-    cpi->set_ref_frame_mask = 1;
-    rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &r, &d, BLOCK_64X64,
-                     get_block_context(x, BLOCK_64X64), INT64_MAX);
-    pl = partition_plane_context(cpi->above_seg_context, cpi->left_seg_context,
-                                 mi_row, mi_col, BLOCK_64X64);
-    r += x->partition_cost[pl][PARTITION_NONE];
-
-    *(get_sb_partitioning(x, BLOCK_64X64)) = BLOCK_64X64;
-    cpi->set_ref_frame_mask = 0;
-  }
-
-  restore_context(cpi, mi_row, mi_col, a, l, sa, sl, BLOCK_64X64);
-}
-
 static void encode_sb_row(VP9_COMP *cpi, const TileInfo *const tile,
                           int mi_row, TOKENEXTRA **tp) {
   VP9_COMMON *const cm = &cpi->common;
@@ -2337,6 +2214,7 @@
     }
   }
 }
+
 // Start RTC Exploration
 typedef enum {
   BOTH_ZERO = 0,
@@ -2368,12 +2246,15 @@
   mbmi->sb_type = bsize;
   mbmi->segment_id = 0;
 }
+
 static INLINE int get_block_row(int b32i, int b16i, int b8i) {
   return ((b32i >> 1) << 2) + ((b16i >> 1) << 1) + (b8i >> 1);
 }
+
 static INLINE int get_block_col(int b32i, int b16i, int b8i) {
   return ((b32i & 1) << 2) + ((b16i & 1) << 1) + (b8i & 1);
 }
+
 static void rtc_use_partition(VP9_COMP *cpi,
                              const TileInfo *const tile,
                              MODE_INFO **mi_8x8,
@@ -2393,8 +2274,6 @@
   int row8x8_remaining = tile->mi_row_end - mi_row;
   int col8x8_remaining = tile->mi_col_end - mi_col;
   int b32i;
-  x->fast_ms = 0;
-  x->subblock_ref = 0;
   for (b32i = 0; b32i < 4; b32i++) {
     int b16i;
     for (b16i = 0; b16i < 4; b16i++) {
@@ -2405,10 +2284,6 @@
       int rate;
       int64_t dist;
 
-      int_mv frame_nearest_mv[MAX_REF_FRAMES];
-      int_mv frame_near_mv[MAX_REF_FRAMES];
-      struct buf_2d yv12_mb[MAX_REF_FRAMES][MAX_MB_PLANE];
-
       // Find a partition size that fits
       bsize = find_partition_size(cpi->sf.always_this_block_size,
                                   (row8x8_remaining - block_row),
@@ -2430,10 +2305,6 @@
       } else {
         set_mode_info(&mi_8x8[index]->mbmi, bsize, mode,
                       mi_row + block_row, mi_col + block_col);
-        vp9_setup_buffer_inter(cpi, x, tile,
-                               LAST_FRAME, cpi->sf.always_this_block_size,
-                               mi_row + block_row, mi_col + block_col,
-                               frame_nearest_mv, frame_near_mv, yv12_mb);
       }
 
       for (j = 0; j < mi_height; j++)
diff --git a/vp9/encoder/vp9_mcomp.c b/vp9/encoder/vp9_mcomp.c
index b2555e6..3b8ec18 100644
--- a/vp9/encoder/vp9_mcomp.c
+++ b/vp9/encoder/vp9_mcomp.c
@@ -850,8 +850,9 @@
 
 int vp9_full_range_search_c(const MACROBLOCK *x, MV *ref_mv, MV *best_mv,
                             int search_param, int sad_per_bit, int *num00,
-                            vp9_variance_fn_ptr_t *fn_ptr, int *mvjcost,
-                            int *mvcost[2], const MV *center_mv) {
+                            const vp9_variance_fn_ptr_t *fn_ptr,
+                            int *mvjcost, int *mvcost[2],
+                            const MV *center_mv) {
   const MACROBLOCKD *const xd = &x->e_mbd;
   const uint8_t *what = x->plane[0].src.buf;
   const int what_stride = x->plane[0].src.stride;
@@ -965,8 +966,9 @@
 int vp9_diamond_search_sad_c(const MACROBLOCK *x,
                              MV *ref_mv, MV *best_mv,
                              int search_param, int sad_per_bit, int *num00,
-                             vp9_variance_fn_ptr_t *fn_ptr, int *mvjcost,
-                             int *mvcost[2], const MV *center_mv) {
+                             const vp9_variance_fn_ptr_t *fn_ptr,
+                             int *mvjcost, int *mvcost[2],
+                             const MV *center_mv) {
   int i, j, step;
 
   const MACROBLOCKD *const xd = &x->e_mbd;
@@ -1099,7 +1101,7 @@
 int vp9_diamond_search_sadx4(const MACROBLOCK *x,
                              MV *ref_mv, MV *best_mv, int search_param,
                              int sad_per_bit, int *num00,
-                             vp9_variance_fn_ptr_t *fn_ptr,
+                             const vp9_variance_fn_ptr_t *fn_ptr,
                              int *mvjcost, int *mvcost[2],
                              const MV *center_mv) {
   int i, j, step;
@@ -1279,7 +1281,8 @@
 int vp9_full_pixel_diamond(VP9_COMP *cpi, MACROBLOCK *x,
                            MV *mvp_full, int step_param,
                            int sadpb, int further_steps,
-                           int do_refine, vp9_variance_fn_ptr_t *fn_ptr,
+                           int do_refine,
+                           const vp9_variance_fn_ptr_t *fn_ptr,
                            const MV *ref_mv, int_mv *dst_mv) {
   int_mv temp_mv;
   int thissme, n, num00;
@@ -1336,9 +1339,9 @@
   return bestsme;
 }
 
-int vp9_full_search_sad_c(const MACROBLOCK *x, MV *ref_mv,
+int vp9_full_search_sad_c(const MACROBLOCK *x, const MV *ref_mv,
                           int sad_per_bit, int distance,
-                          vp9_variance_fn_ptr_t *fn_ptr,
+                          const vp9_variance_fn_ptr_t *fn_ptr,
                           int *mvjcost, int *mvcost[2],
                           const MV *center_mv, int block) {
   int r, c;
@@ -1389,10 +1392,11 @@
   }
 }
 
-int vp9_full_search_sadx3(const MACROBLOCK *x, MV *ref_mv,
+int vp9_full_search_sadx3(const MACROBLOCK *x, const MV *ref_mv,
                           int sad_per_bit, int distance,
-                          vp9_variance_fn_ptr_t *fn_ptr, int *mvjcost,
-                          int *mvcost[2], const MV *center_mv, int n) {
+                          const vp9_variance_fn_ptr_t *fn_ptr,
+                          int *mvjcost, int *mvcost[2],
+                          const MV *center_mv, int n) {
   const MACROBLOCKD *const xd = &x->e_mbd;
   const uint8_t *const what = x->plane[0].src.buf;
   const int what_stride = x->plane[0].src.stride;
@@ -1494,9 +1498,9 @@
     return INT_MAX;
 }
 
-int vp9_full_search_sadx8(const MACROBLOCK *x, MV *ref_mv,
+int vp9_full_search_sadx8(const MACROBLOCK *x, const MV *ref_mv,
                           int sad_per_bit, int distance,
-                          vp9_variance_fn_ptr_t *fn_ptr,
+                          const vp9_variance_fn_ptr_t *fn_ptr,
                           int *mvjcost, int *mvcost[2],
                           const MV *center_mv, int n) {
   const MACROBLOCKD *const xd = &x->e_mbd;
@@ -1630,7 +1634,8 @@
 
 int vp9_refining_search_sad_c(const MACROBLOCK *x,
                               MV *ref_mv, int error_per_bit,
-                              int search_range, vp9_variance_fn_ptr_t *fn_ptr,
+                              int search_range,
+                              const vp9_variance_fn_ptr_t *fn_ptr,
                               int *mvjcost, int *mvcost[2],
                               const MV *center_mv) {
   const MACROBLOCKD *const xd = &x->e_mbd;
@@ -1702,7 +1707,8 @@
 
 int vp9_refining_search_sadx4(const MACROBLOCK *x,
                               MV *ref_mv, int error_per_bit,
-                              int search_range, vp9_variance_fn_ptr_t *fn_ptr,
+                              int search_range,
+                              const vp9_variance_fn_ptr_t *fn_ptr,
                               int *mvjcost, int *mvcost[2],
                               const MV *center_mv) {
   const MACROBLOCKD *const xd = &x->e_mbd;
@@ -1815,8 +1821,10 @@
 // mode.
 int vp9_refining_search_8p_c(const MACROBLOCK *x,
                              MV *ref_mv, int error_per_bit,
-                             int search_range, vp9_variance_fn_ptr_t *fn_ptr,
-                             int *mvjcost, int *mvcost[2], const MV *center_mv,
+                             int search_range,
+                             const vp9_variance_fn_ptr_t *fn_ptr,
+                             int *mvjcost, int *mvcost[2],
+                             const MV *center_mv,
                              const uint8_t *second_pred, int w, int h) {
   const MACROBLOCKD *const xd = &x->e_mbd;
   const MV neighbors[8] = {{-1, 0}, {0, -1}, {0, 1}, {1, 0},
diff --git a/vp9/encoder/vp9_mcomp.h b/vp9/encoder/vp9_mcomp.h
index 28b46b5..e1d6abe 100644
--- a/vp9/encoder/vp9_mcomp.h
+++ b/vp9/encoder/vp9_mcomp.h
@@ -45,7 +45,7 @@
 int vp9_full_pixel_diamond(struct VP9_COMP *cpi, MACROBLOCK *x,
                            MV *mvp_full, int step_param,
                            int sadpb, int further_steps, int do_refine,
-                           vp9_variance_fn_ptr_t *fn_ptr,
+                           const vp9_variance_fn_ptr_t *fn_ptr,
                            const MV *ref_mv, int_mv *dst_mv);
 
 int vp9_hex_search(const MACROBLOCK *x,
@@ -107,15 +107,16 @@
 extern fractional_mv_step_comp_fp vp9_find_best_sub_pixel_comp_tree;
 
 typedef int (*vp9_full_search_fn_t)(const MACROBLOCK *x,
-                                    MV *ref_mv, int sad_per_bit,
-                                    int distance, vp9_variance_fn_ptr_t *fn_ptr,
+                                    const MV *ref_mv, int sad_per_bit,
+                                    int distance,
+                                    const vp9_variance_fn_ptr_t *fn_ptr,
                                     int *mvjcost, int *mvcost[2],
                                     const MV *center_mv, int n);
 
 typedef int (*vp9_refining_search_fn_t)(const MACROBLOCK *x,
                                         MV *ref_mv, int sad_per_bit,
                                         int distance,
-                                        vp9_variance_fn_ptr_t *fn_ptr,
+                                        const vp9_variance_fn_ptr_t *fn_ptr,
                                         int *mvjcost, int *mvcost[2],
                                         const MV *center_mv);
 
@@ -123,13 +124,14 @@
                                        MV *ref_mv, MV *best_mv,
                                        int search_param, int sad_per_bit,
                                        int *num00,
-                                       vp9_variance_fn_ptr_t *fn_ptr,
+                                       const vp9_variance_fn_ptr_t *fn_ptr,
                                        int *mvjcost, int *mvcost[2],
                                        const MV *center_mv);
 
 int vp9_refining_search_8p_c(const MACROBLOCK *x,
                              MV *ref_mv, int error_per_bit,
-                             int search_range, vp9_variance_fn_ptr_t *fn_ptr,
+                             int search_range,
+                             const vp9_variance_fn_ptr_t *fn_ptr,
                              int *mvjcost, int *mvcost[2],
                              const MV *center_mv, const uint8_t *second_pred,
                              int w, int h);
diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c
index 9f4d47b..e972355 100644
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -911,7 +911,6 @@
   sf->use_uv_intra_rd_estimate = 0;
   sf->use_fast_lpf_pick = 0;
   sf->use_fast_coef_updates = 0;
-  sf->using_small_partition_info = 0;
   sf->mode_skip_start = MAX_MODES;  // Mode index at which mode skip mask set
   sf->use_pick_mode = 0;
   sf->encode_breakout_thresh = 0;
diff --git a/vp9/encoder/vp9_onyx_int.h b/vp9/encoder/vp9_onyx_int.h
index 88a0419..1ab1814 100644
--- a/vp9/encoder/vp9_onyx_int.h
+++ b/vp9/encoder/vp9_onyx_int.h
@@ -346,11 +346,6 @@
   // inter modes or to enable it always.
   int disable_split_mask;
 
-  // TODO(jbb): Remove this and everything that uses it. It's only valid if
-  // we were doing small to large partition checks. We currently do the
-  // reverse.
-  int using_small_partition_info;
-
   // TODO(jingning): combine the related motion search speed features
   // This allows us to use motion search at other sizes as a starting
   // point for this motion search and limits the search range around it.
diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c
index cae7884..6d26e64 100644
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -1604,13 +1604,11 @@
   int mvthresh;
 } BEST_SEG_INFO;
 
-static INLINE int mv_check_bounds(MACROBLOCK *x, int_mv *mv) {
-  int r = 0;
-  r |= (mv->as_mv.row >> 3) < x->mv_row_min;
-  r |= (mv->as_mv.row >> 3) > x->mv_row_max;
-  r |= (mv->as_mv.col >> 3) < x->mv_col_min;
-  r |= (mv->as_mv.col >> 3) > x->mv_col_max;
-  return r;
+static INLINE int mv_check_bounds(const MACROBLOCK *x, const MV *mv) {
+  return (mv->row >> 3) < x->mv_row_min ||
+         (mv->row >> 3) > x->mv_row_max ||
+         (mv->col >> 3) < x->mv_col_min ||
+         (mv->col >> 3) > x->mv_col_max;
 }
 
 static INLINE void mi_buf_shift(MACROBLOCK *x, int i) {
@@ -1924,10 +1922,9 @@
         }
 
         // Trap vectors that reach beyond the UMV borders
-        if (mv_check_bounds(x, &mode_mv[this_mode]))
-          continue;
-        if (has_second_rf &&
-            mv_check_bounds(x, &second_mode_mv[this_mode]))
+        if (mv_check_bounds(x, &mode_mv[this_mode].as_mv) ||
+            (has_second_rf &&
+             mv_check_bounds(x, &second_mode_mv[this_mode].as_mv)))
           continue;
 
         if (filter_idx > 0) {
@@ -2380,24 +2377,16 @@
 
   vp9_set_mv_search_range(x, &ref_mv.as_mv);
 
-  // Adjust search parameters based on small partitions' result.
-  if (x->fast_ms) {
-    // adjust search range
-    step_param = 6;
-    if (x->fast_ms > 1)
-      step_param = 8;
+  // Work out the size of the first step in the mv step search.
+  // 0 here is maximum length first step. 1 is MAX >> 1 etc.
+  if (cpi->sf.auto_mv_step_size && cpi->common.show_frame) {
+    // Take wtd average of the step_params based on the last frame's
+    // max mv magnitude and that based on the best ref mvs of the current
+    // block for the given reference.
+    step_param = (vp9_init_search_range(cpi, x->max_mv_context[ref]) +
+                  cpi->mv_step_param) >> 1;
   } else {
-    // Work out the size of the first step in the mv step search.
-    // 0 here is maximum length first step. 1 is MAX >> 1 etc.
-    if (cpi->sf.auto_mv_step_size && cpi->common.show_frame) {
-      // Take wtd average of the step_params based on the last frame's
-      // max mv magnitude and that based on the best ref mvs of the current
-      // block for the given reference.
-      step_param = (vp9_init_search_range(cpi, x->max_mv_context[ref]) +
-                    cpi->mv_step_param) >> 1;
-    } else {
-      step_param = cpi->mv_step_param;
-    }
+    step_param = cpi->mv_step_param;
   }
 
   if (cpi->sf.adaptive_motion_search && bsize < BLOCK_64X64 &&
@@ -2750,7 +2739,7 @@
     if (this_mode != NEWMV)
       clamp_mv2(&cur_mv[i].as_mv, xd);
 
-    if (mv_check_bounds(x, &cur_mv[i]))
+    if (mv_check_bounds(x, &cur_mv[i].as_mv))
       return INT64_MAX;
     mbmi->mv[i].as_int = cur_mv[i].as_int;
   }
@@ -3260,12 +3249,6 @@
          vp9_segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME))
       continue;
 
-    // Skip some checking based on small partitions' result.
-    if (x->fast_ms > 1 && !ref_frame)
-      continue;
-    if (x->fast_ms > 2 && ref_frame != x->subblock_ref)
-      continue;
-
     mbmi->ref_frame[0] = ref_frame;
     mbmi->ref_frame[1] = second_ref_frame;
 
diff --git a/vp9/encoder/vp9_tokenize.c b/vp9/encoder/vp9_tokenize.c
index ed1301a..0f68d83 100644
--- a/vp9/encoder/vp9_tokenize.c
+++ b/vp9/encoder/vp9_tokenize.c
@@ -160,7 +160,6 @@
   VP9_COMP *cpi;
   MACROBLOCKD *xd;
   TOKENEXTRA **tp;
-  TX_SIZE tx_size;
   uint8_t *token_cache;
 };
 
@@ -188,6 +187,18 @@
   ++counts[token];
 }
 
+static INLINE void add_token_no_extra(TOKENEXTRA **t,
+                                      const vp9_prob *context_tree,
+                                      uint8_t token,
+                                      uint8_t skip_eob_node,
+                                      unsigned int *counts) {
+  (*t)->token = token;
+  (*t)->context_tree = context_tree;
+  (*t)->skip_eob_node = skip_eob_node;
+  (*t)++;
+  ++counts[token];
+}
+
 static void tokenize_b(int plane, int block, BLOCK_SIZE plane_bsize,
                        TX_SIZE tx_size, void *arg) {
   struct tokenize_b_args* const args = arg;
@@ -199,7 +210,7 @@
   struct macroblockd_plane *pd = &xd->plane[plane];
   MB_MODE_INFO *mbmi = &xd->mi_8x8[0]->mbmi;
   int pt; /* near block/prev token context index */
-  int c = 0;
+  int c;
   TOKENEXTRA *t = *tp;        /* store tokens starting here */
   int eob = p->eobs[block];
   const PLANE_TYPE type = pd->plane_type;
@@ -207,9 +218,14 @@
   const int segment_id = mbmi->segment_id;
   const int16_t *scan, *nb;
   const scan_order *so;
-  vp9_coeff_count *const counts = cpi->coef_counts[tx_size];
-  vp9_coeff_probs_model *const coef_probs = cpi->common.fc.coef_probs[tx_size];
   const int ref = is_inter_block(mbmi);
+  unsigned int (*const counts)[COEFF_CONTEXTS][ENTROPY_TOKENS] =
+      cpi->coef_counts[tx_size][type][ref];
+  vp9_prob (*const coef_probs)[COEFF_CONTEXTS][UNCONSTRAINED_NODES] =
+      cpi->common.fc.coef_probs[tx_size][type][ref];
+  unsigned int (*const eob_branch)[COEFF_CONTEXTS] =
+      cpi->common.counts.eob_branch[tx_size][type][ref];
+
   const uint8_t *const band = get_band_translate(tx_size);
   const int seg_eob = get_tx_eob(&cpi->common.seg, segment_id, tx_size);
 
@@ -228,11 +244,9 @@
     v = qcoeff_ptr[scan[c]];
 
     while (!v) {
-      add_token(&t, coef_probs[type][ref][band[c]][pt], 0, ZERO_TOKEN, skip_eob,
-                counts[type][ref][band[c]][pt]);
-
-      cpi->common.counts.eob_branch[tx_size][type][ref][band[c]][pt] +=
-          !skip_eob;
+      add_token_no_extra(&t, coef_probs[band[c]][pt], ZERO_TOKEN, skip_eob,
+                         counts[band[c]][pt]);
+      eob_branch[band[c]][pt] += !skip_eob;
 
       skip_eob = 1;
       token_cache[scan[c]] = 0;
@@ -240,12 +254,12 @@
       pt = get_coef_context(nb, token_cache, c);
       v = qcoeff_ptr[scan[c]];
     }
-    add_token(&t, coef_probs[type][ref][band[c]][pt],
+
+    add_token(&t, coef_probs[band[c]][pt],
               vp9_dct_value_tokens_ptr[v].extra,
               vp9_dct_value_tokens_ptr[v].token, skip_eob,
-              counts[type][ref][band[c]][pt]);
-
-    cpi->common.counts.eob_branch[tx_size][type][ref][band[c]][pt] += !skip_eob;
+              counts[band[c]][pt]);
+    eob_branch[band[c]][pt] += !skip_eob;
 
     token_cache[scan[c]] =
         vp9_pt_energy_class[vp9_dct_value_tokens_ptr[v].token];
@@ -253,9 +267,9 @@
     pt = get_coef_context(nb, token_cache, c);
   }
   if (c < seg_eob) {
-    add_token(&t, coef_probs[type][ref][band[c]][pt], 0, EOB_TOKEN, 0,
-              counts[type][ref][band[c]][pt]);
-    ++cpi->common.counts.eob_branch[tx_size][type][ref][band[c]][pt];
+    add_token_no_extra(&t, coef_probs[band[c]][pt], EOB_TOKEN, 0,
+                       counts[band[c]][pt]);
+    ++eob_branch[band[c]][pt];
   }
 
   *tp = t;
@@ -299,7 +313,7 @@
   const int ctx = vp9_get_skip_context(xd);
   const int skip_inc = !vp9_segfeature_active(&cm->seg, mbmi->segment_id,
                                               SEG_LVL_SKIP);
-  struct tokenize_b_args arg = {cpi, xd, t, mbmi->tx_size, cpi->mb.token_cache};
+  struct tokenize_b_args arg = {cpi, xd, t, cpi->mb.token_cache};
   if (mbmi->skip_coeff) {
     if (!dry_run)
       cm->counts.skip[ctx][1] += skip_inc;
diff --git a/vp9/vp9_dx_iface.c b/vp9/vp9_dx_iface.c
index 881a7d1..41750de 100644
--- a/vp9/vp9_dx_iface.c
+++ b/vp9/vp9_dx_iface.c
@@ -303,6 +303,9 @@
         cm->get_fb_cb = vp9_get_frame_buffer;
         cm->release_fb_cb = vp9_release_frame_buffer;
 
+        // Set index to not initialized.
+        cm->new_fb_idx = -1;
+
         if (vp9_alloc_internal_frame_buffers(&cm->int_frame_buffers))
           vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
                              "Failed to initialize internal frame buffers");
diff --git a/vp9_spatial_scalable_encoder.c b/vp9_spatial_scalable_encoder.c
index 50f45c2..bbbe7ed 100644
--- a/vp9_spatial_scalable_encoder.c
+++ b/vp9_spatial_scalable_encoder.c
@@ -18,9 +18,11 @@
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
+
 #include "./args.h"
-#include "./ivfenc.h"
 #include "./tools_common.h"
+#include "./video_writer.h"
+
 #include "vpx/svc_context.h"
 #include "vpx/vp8cx.h"
 #include "vpx/vpx_encoder.h"
@@ -183,7 +185,8 @@
 
 int main(int argc, const char **argv) {
   AppInput app_input = {0};
-  FILE *outfile;
+  VpxVideoWriter *writer = NULL;
+  VpxVideoInfo info = {0};
   vpx_codec_ctx_t codec;
   vpx_codec_enc_cfg_t enc_cfg;
   SvcContext svc_ctx;
@@ -206,15 +209,24 @@
   if (!(app_input.input_ctx.file = fopen(app_input.input_ctx.filename, "rb")))
     die("Failed to open %s for reading\n", app_input.input_ctx.filename);
 
-  if (!(outfile = fopen(app_input.output_filename, "wb")))
-    die("Failed to open %s for writing\n", app_input.output_filename);
-
   // Initialize codec
   if (vpx_svc_init(&svc_ctx, &codec, vpx_codec_vp9_cx(), &enc_cfg) !=
       VPX_CODEC_OK)
     die("Failed to initialize encoder\n");
 
-  ivf_write_file_header(outfile, &enc_cfg, VP9_FOURCC, 0);
+  info.codec_fourcc = VP9_FOURCC;
+  info.time_base.numerator = enc_cfg.g_timebase.num;
+  info.time_base.denominator = enc_cfg.g_timebase.den;
+  if (vpx_svc_get_layer_resolution(&svc_ctx, svc_ctx.spatial_layers - 1,
+                                   (unsigned int *)&info.frame_width,
+                                   (unsigned int *)&info.frame_height) !=
+      VPX_CODEC_OK) {
+    die("Failed to get output resolution");
+  }
+  writer = vpx_video_writer_open(app_input.output_filename, kContainerIVF,
+                                 &info);
+  if (!writer)
+    die("Failed to open %s for writing\n", app_input.output_filename);
 
   // skip initial frames
   for (i = 0; i < app_input.frames_to_skip; ++i) {
@@ -232,9 +244,10 @@
       die_codec(&codec, "Failed to encode frame");
     }
     if (vpx_svc_get_frame_size(&svc_ctx) > 0) {
-      ivf_write_frame_header(outfile, pts, vpx_svc_get_frame_size(&svc_ctx));
-      (void)fwrite(vpx_svc_get_buffer(&svc_ctx), 1,
-                   vpx_svc_get_frame_size(&svc_ctx), outfile);
+      vpx_video_writer_write_frame(writer,
+                                   vpx_svc_get_buffer(&svc_ctx),
+                                   vpx_svc_get_frame_size(&svc_ctx),
+                                   pts);
     }
     ++frame_cnt;
     pts += frame_duration;
@@ -245,19 +258,8 @@
   fclose(app_input.input_ctx.file);
   if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec");
 
-  // rewrite the output file headers with the actual frame count, and
-  // resolution of the highest layer
-  if (!fseek(outfile, 0, SEEK_SET)) {
-    // get resolution of highest layer
-    if (VPX_CODEC_OK != vpx_svc_get_layer_resolution(&svc_ctx,
-                                                     svc_ctx.spatial_layers - 1,
-                                                     &enc_cfg.g_w,
-                                                     &enc_cfg.g_h)) {
-      die("Failed to get output resolution");
-    }
-    ivf_write_file_header(outfile, &enc_cfg, VP9_FOURCC, frame_cnt);
-  }
-  fclose(outfile);
+  vpx_video_writer_close(writer);
+
   vpx_img_free(&raw);
 
   // display average size, psnr
diff --git a/vpxdec.c b/vpxdec.c
index 98d1550..7f85fc9 100644
--- a/vpxdec.c
+++ b/vpxdec.c
@@ -37,19 +37,6 @@
 
 static const char *exec_name;
 
-static const struct {
-  char const *name;
-  vpx_codec_iface_t *(*iface)(void);
-  uint32_t fourcc;
-} ifaces[] = {
-#if CONFIG_VP8_DECODER
-  {"vp8",  vpx_codec_vp8_dx,   VP8_FOURCC},
-#endif
-#if CONFIG_VP9_DECODER
-  {"vp9",  vpx_codec_vp9_dx,   VP9_FOURCC},
-#endif
-};
-
 struct VpxDecInputContext {
   struct VpxInputContext *vpx_input_ctx;
   struct WebmInputContext *webm_ctx;
@@ -170,10 +157,11 @@
          );
   fprintf(stderr, "\nIncluded decoders:\n\n");
 
-  for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++)
+  for (i = 0; i < get_vpx_decoder_count(); ++i) {
+    const VpxInterface *const decoder = get_vpx_decoder_by_index(i);
     fprintf(stderr, "    %-6s - %s\n",
-            ifaces[i].name,
-            vpx_codec_iface_name(ifaces[i].iface()));
+            decoder->name, vpx_codec_iface_name(decoder->interface()));
+  }
 
   exit(EXIT_FAILURE);
 }
@@ -300,11 +288,12 @@
     int i;
 
     if (mem_get_le32(buf) < 256 * 1024 * 1024) {
-      for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++) {
-        if (!vpx_codec_peek_stream_info(ifaces[i].iface(),
+      for (i = 0; i < get_vpx_decoder_count(); ++i) {
+        const VpxInterface *const decoder = get_vpx_decoder_by_index(i);
+        if (!vpx_codec_peek_stream_info(decoder->interface(),
                                         buf + 4, 32 - 4, &si)) {
           is_raw = 1;
-          input->fourcc = ifaces[i].fourcc;
+          input->fourcc = decoder->fourcc;
           input->width = si.w;
           input->height = si.h;
           input->framerate.numerator = 30;
@@ -441,7 +430,6 @@
 int main_loop(int argc, const char **argv_) {
   vpx_codec_ctx_t       decoder;
   char                  *fn = NULL;
-  int                    i;
   uint8_t               *buf = NULL;
   size_t                 bytes_in_buffer = 0, buffer_size = 0;
   FILE                  *infile;
@@ -450,7 +438,8 @@
   int                    stop_after = 0, postproc = 0, summary = 0, quiet = 1;
   int                    arg_skip = 0;
   int                    ec_enabled = 0;
-  vpx_codec_iface_t       *iface = NULL;
+  const VpxInterface *interface = NULL;
+  const VpxInterface *fourcc_interface = NULL;
   unsigned long          dx_time = 0;
   struct arg               arg;
   char                   **argv, **argi, **argj;
@@ -493,17 +482,9 @@
     arg.argv_step = 1;
 
     if (arg_match(&arg, &codecarg, argi)) {
-      int j, k = -1;
-
-      for (j = 0; j < sizeof(ifaces) / sizeof(ifaces[0]); j++)
-        if (!strcmp(ifaces[j].name, arg.val))
-          k = j;
-
-      if (k >= 0)
-        iface = ifaces[k].iface();
-      else
-        die("Error: Unrecognized argument (%s) to --codec\n",
-            arg.val);
+      interface = get_vpx_decoder_by_name(arg.val);
+      if (!interface)
+        die("Error: Unrecognized argument (%s) to --codec\n", arg.val);
     } else if (arg_match(&arg, &looparg, argi)) {
       // no-op
     } else if (arg_match(&arg, &outputfile, argi))
@@ -660,24 +641,20 @@
     }
   }
 
-  /* Try to determine the codec from the fourcc. */
-  for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++)
-    if (vpx_input_ctx.fourcc == ifaces[i].fourcc) {
-      vpx_codec_iface_t *vpx_iface = ifaces[i].iface();
+  fourcc_interface = get_vpx_decoder_by_fourcc(vpx_input_ctx.fourcc);
+  if (interface && fourcc_interface && interface != fourcc_interface)
+    warn("Header indicates codec: %s\n", fourcc_interface->name);
+  else
+    interface = fourcc_interface;
 
-      if (iface && iface != vpx_iface)
-        warn("Header indicates codec: %s\n", ifaces[i].name);
-      else
-        iface = vpx_iface;
-
-      break;
-    }
+  if (!interface)
+    interface = get_vpx_decoder_by_index(0);
 
   dec_flags = (postproc ? VPX_CODEC_USE_POSTPROC : 0) |
               (ec_enabled ? VPX_CODEC_USE_ERROR_CONCEALMENT : 0);
-  if (vpx_codec_dec_init(&decoder, iface ? iface :  ifaces[0].iface(), &cfg,
-                         dec_flags)) {
-    fprintf(stderr, "Failed to initialize decoder: %s\n", vpx_codec_error(&decoder));
+  if (vpx_codec_dec_init(&decoder, interface->interface(), &cfg, dec_flags)) {
+    fprintf(stderr, "Failed to initialize decoder: %s\n",
+            vpx_codec_error(&decoder));
     return EXIT_FAILURE;
   }
 
diff --git a/vpxenc.c b/vpxenc.c
index 5e36fd9..73b3144 100644
--- a/vpxenc.c
+++ b/vpxenc.c
@@ -61,24 +61,6 @@
 
 static const char *exec_name;
 
-static const struct codec_item {
-  char const              *name;
-  vpx_codec_iface_t *(*iface)(void);
-  vpx_codec_iface_t *(*dx_iface)(void);
-  unsigned int             fourcc;
-} codecs[] = {
-#if CONFIG_VP8_ENCODER && CONFIG_VP8_DECODER
-  {"vp8", &vpx_codec_vp8_cx, &vpx_codec_vp8_dx, VP8_FOURCC},
-#elif CONFIG_VP8_ENCODER && !CONFIG_VP8_DECODER
-  {"vp8", &vpx_codec_vp8_cx, NULL, VP8_FOURCC},
-#endif
-#if CONFIG_VP9_ENCODER && CONFIG_VP9_DECODER
-  {"vp9", &vpx_codec_vp9_cx, &vpx_codec_vp9_dx, VP9_FOURCC},
-#elif CONFIG_VP9_ENCODER && !CONFIG_VP9_DECODER
-  {"vp9", &vpx_codec_vp9_cx, NULL, VP9_FOURCC},
-#endif
-};
-
 static void warn_or_exit_on_errorv(vpx_codec_ctx_t *ctx, int fatal,
                                    const char *s, va_list ap) {
   if (ctx->err) {
@@ -462,14 +444,13 @@
   fprintf(stderr, "\nStream timebase (--timebase):\n"
           "  The desired precision of timestamps in the output, expressed\n"
           "  in fractional seconds. Default is 1/1000.\n");
-  fprintf(stderr, "\n"
-          "Included encoders:\n"
-          "\n");
+  fprintf(stderr, "\nIncluded encoders:\n\n");
 
-  for (i = 0; i < sizeof(codecs) / sizeof(codecs[0]); i++)
+  for (i = 0; i < get_vpx_encoder_count(); ++i) {
+    const VpxInterface *const encoder = get_vpx_encoder_by_index(i);
     fprintf(stderr, "    %-6s - %s\n",
-            codecs[i].name,
-            vpx_codec_iface_name(codecs[i].iface()));
+            encoder->name, vpx_codec_iface_name(encoder->interface()));
+  }
 
   exit(EXIT_FAILURE);
 }
@@ -666,7 +647,7 @@
 
   /* Initialize default parameters */
   memset(global, 0, sizeof(*global));
-  global->codec = codecs;
+  global->codec = get_vpx_encoder_by_index(0);
   global->passes = 0;
   global->use_i420 = 1;
   /* Assign default deadline to good quality */
@@ -676,18 +657,9 @@
     arg.argv_step = 1;
 
     if (arg_match(&arg, &codecarg, argi)) {
-      int j, k = -1;
-
-      for (j = 0; j < sizeof(codecs) / sizeof(codecs[0]); j++)
-        if (!strcmp(codecs[j].name, arg.val))
-          k = j;
-
-      if (k >= 0)
-        global->codec = codecs + k;
-      else
-        die("Error: Unrecognized argument (%s) to --codec\n",
-            arg.val);
-
+      global->codec = get_vpx_encoder_by_name(arg.val);
+      if (!global->codec)
+        die("Error: Unrecognized argument (%s) to --codec\n", arg.val);
     } else if (arg_match(&arg, &passes, argi)) {
       global->passes = arg_parse_uint(&arg);
 
@@ -750,7 +722,7 @@
 #if CONFIG_VP9_ENCODER
     // Make default VP9 passes = 2 until there is a better quality 1-pass
     // encoder
-    global->passes = (global->codec->iface == vpx_codec_vp9_cx ? 2 : 1);
+    global->passes = strcmp(global->codec->name, "vp9") == 0 ? 2 : 1;
 #else
     global->passes = 1;
 #endif
@@ -830,7 +802,7 @@
     vpx_codec_err_t  res;
 
     /* Populate encoder configuration */
-    res = vpx_codec_enc_config_default(global->codec->iface(),
+    res = vpx_codec_enc_config_default(global->codec->interface(),
                                        &stream->config.cfg,
                                        global->usage);
     if (res)
@@ -874,15 +846,15 @@
   struct stream_config    *config = &stream->config;
   int                      eos_mark_found = 0;
 
-  /* Handle codec specific options */
+  // Handle codec specific options
   if (0) {
 #if CONFIG_VP8_ENCODER
-  } else if (global->codec->iface == vpx_codec_vp8_cx) {
+  } else if (strcmp(global->codec->name, "vp8") == 0) {
     ctrl_args = vp8_args;
     ctrl_args_map = vp8_arg_ctrl_map;
 #endif
 #if CONFIG_VP9_ENCODER
-  } else if (global->codec->iface == vpx_codec_vp9_cx) {
+  } else if (strcmp(global->codec->name, "vp9") == 0) {
     ctrl_args = vp9_args;
     ctrl_args_map = vp9_arg_ctrl_map;
 #endif
@@ -1090,7 +1062,7 @@
 
   if (stream->index == 0) {
     fprintf(stderr, "Codec: %s\n",
-            vpx_codec_iface_name(global->codec->iface()));
+            vpx_codec_iface_name(global->codec->interface()));
     fprintf(stderr, "Source file: %s Format: %s\n", input->filename,
             input->use_i420 ? "I420" : "YV12");
   }
@@ -1214,7 +1186,7 @@
   flags |= global->out_part ? VPX_CODEC_USE_OUTPUT_PARTITION : 0;
 
   /* Construct Encoder Context */
-  vpx_codec_enc_init(&stream->encoder, global->codec->iface(),
+  vpx_codec_enc_init(&stream->encoder, global->codec->interface(),
                      &stream->config.cfg, flags);
   ctx_exit_on_error(&stream->encoder, "Failed to initialize encoder");
 
@@ -1234,7 +1206,8 @@
 
 #if CONFIG_DECODERS
   if (global->test_decode != TEST_DECODE_OFF) {
-    vpx_codec_dec_init(&stream->decoder, global->codec->dx_iface(), NULL, 0);
+    const VpxInterface *decoder = get_vpx_decoder_by_name(global->codec->name);
+    vpx_codec_dec_init(&stream->decoder, decoder->interface(), NULL, 0);
   }
 #endif
 }
@@ -1420,14 +1393,14 @@
 
 static void test_decode(struct stream_state  *stream,
                         enum TestDecodeFatality fatal,
-                        const struct codec_item *codec) {
+                        const VpxInterface *codec) {
   vpx_image_t enc_img, dec_img;
 
   if (stream->mismatch_seen)
     return;
 
   /* Get the internal reference frame */
-  if (codec->fourcc == VP8_FOURCC) {
+  if (strcmp(codec->name, "vp8") == 0) {
     struct vpx_ref_frame ref_enc, ref_dec;
     int width, height;
 
diff --git a/vpxenc.h b/vpxenc.h
index 5103ee6..1e6acaa 100644
--- a/vpxenc.h
+++ b/vpxenc.h
@@ -22,9 +22,11 @@
   TEST_DECODE_WARN,
 };
 
+struct VpxInterface;
+
 /* Configuration elements common to all streams. */
 struct VpxEncoderConfig {
-  const struct codec_item *codec;
+  const struct VpxInterface *codec;
   int passes;
   int pass;
   int usage;