Merge "Replacing CHECK_BOUNDS macro with inline check_bounds function."
diff --git a/args.h b/args.h
index ad591af..ea909cb 100644
--- a/args.h
+++ b/args.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef ARGS_H
-#define ARGS_H
+#ifndef ARGS_H_
+#define ARGS_H_
 #include <stdio.h>
 
 struct arg {
@@ -48,4 +48,4 @@
 int arg_parse_int(const struct arg *arg);
 struct vpx_rational arg_parse_rational(const struct arg *arg);
 int arg_parse_enum_or_int(const struct arg *arg);
-#endif
+#endif  // ARGS_H_
diff --git a/build/make/obj_int_extract.c b/build/make/obj_int_extract.c
index feed9d9..495e9d7 100644
--- a/build/make/obj_int_extract.c
+++ b/build/make/obj_int_extract.c
@@ -321,7 +321,7 @@
   return 1;
 }
 
-char *parse_elf_string_table(elf_obj_t *elf, int s_idx, int idx) {
+const char *parse_elf_string_table(elf_obj_t *elf, int s_idx, int idx) {
   if (elf->bits == 32) {
     Elf32_Shdr shdr;
 
diff --git a/configure b/configure
index f9454ba..9f5a435 100755
--- a/configure
+++ b/configure
@@ -32,7 +32,6 @@
                                   supported by hardware [auto]
   ${toggle_codec_srcs}            in/exclude codec library source code
   ${toggle_debug_libs}            in/exclude debug version of libraries
-  ${toggle_md5}                   support for output of checksum data
   ${toggle_static_msvcrt}         use static MSVCRT (VS builds only)
   ${toggle_vp8}                   VP8 codec support
   ${toggle_vp9}                   VP9 codec support
@@ -184,7 +183,6 @@
 enable_feature static
 enable_feature optimizations
 enable_feature fast_unaligned #allow unaligned accesses, if supported by hw
-enable_feature md5
 enable_feature spatial_resampling
 enable_feature multithread
 enable_feature os_support
@@ -279,7 +277,6 @@
     mem_manager
     mem_tracker
     mem_checks
-    md5
 
     dequant_tokens
     dc_recon
@@ -336,7 +333,6 @@
     fast_unaligned
     codec_srcs
     debug_libs
-    md5
 
     dequant_tokens
     dc_recon
diff --git a/ivfdec.h b/ivfdec.h
index b1468a9..5da9acc 100644
--- a/ivfdec.h
+++ b/ivfdec.h
@@ -27,4 +27,4 @@
 }  /* extern "C" */
 #endif
 
-#endif  /* IVFDEC_H_ */
+#endif  // IVFDEC_H_
diff --git a/ivfenc.h b/ivfenc.h
index a332c7d..b486bc8 100644
--- a/ivfenc.h
+++ b/ivfenc.h
@@ -30,4 +30,4 @@
 }  /* extern "C" */
 #endif
 
-#endif  /* IVFENC_H_ */
+#endif  // IVFENC_H_
diff --git a/libs.mk b/libs.mk
index 4062833..8340eee 100644
--- a/libs.mk
+++ b/libs.mk
@@ -183,6 +183,7 @@
 
 INSTALL-LIBS-yes += include/vpx/vpx_codec.h
 INSTALL-LIBS-yes += include/vpx/vpx_image.h
+INSTALL-LIBS-yes += include/vpx/vpx_external_frame_buffer.h
 INSTALL-LIBS-yes += include/vpx/vpx_integer.h
 INSTALL-LIBS-$(CONFIG_DECODERS) += include/vpx/vpx_decoder.h
 INSTALL-LIBS-$(CONFIG_ENCODERS) += include/vpx/vpx_encoder.h
diff --git a/md5_utils.h b/md5_utils.h
index 81792c4..9935eae 100644
--- a/md5_utils.h
+++ b/md5_utils.h
@@ -20,8 +20,8 @@
  * Still in the public domain.
  */
 
-#ifndef MD5_H
-#define MD5_H
+#ifndef MD5_UTILS_H_
+#define MD5_UTILS_H_
 
 #define md5byte unsigned char
 #define UWORD32 unsigned int
@@ -38,4 +38,4 @@
 void MD5Final(unsigned char digest[16], struct MD5Context *context);
 void MD5Transform(UWORD32 buf[4], UWORD32 const in[16]);
 
-#endif /* !MD5_H */
+#endif  // MD5_UTILS_H_
diff --git a/test/acm_random.h b/test/acm_random.h
index de94186..496dae3 100644
--- a/test/acm_random.h
+++ b/test/acm_random.h
@@ -26,6 +26,11 @@
   void Reset(int seed) {
     random_.Reseed(seed);
   }
+  uint16_t Rand16(void) {
+    const uint32_t value =
+        random_.Generate(testing::internal::Random::kMaxRange);
+    return (value >> 16) & 0xffff;
+  }
 
   uint8_t Rand8(void) {
     const uint32_t value =
diff --git a/test/borders_test.cc b/test/borders_test.cc
index dcdedcf..5071541 100644
--- a/test/borders_test.cc
+++ b/test/borders_test.cc
@@ -67,7 +67,7 @@
 
   cfg_.g_lag_in_frames = 25;
   cfg_.rc_2pass_vbr_minsection_pct = 5;
-  cfg_.rc_2pass_vbr_minsection_pct = 2000;
+  cfg_.rc_2pass_vbr_maxsection_pct = 2000;
   cfg_.rc_target_bitrate = 200;
   cfg_.rc_min_quantizer = 40;
 
diff --git a/test/codec_factory.h b/test/codec_factory.h
index cc7b53f..2ca6ff0 100644
--- a/test/codec_factory.h
+++ b/test/codec_factory.h
@@ -26,6 +26,8 @@
 #include "test/encode_test_driver.h"
 namespace libvpx_test {
 
+const int kCodecFactoryParam = 0;
+
 class CodecFactory {
  public:
   CodecFactory() {}
diff --git a/test/datarate_test.cc b/test/datarate_test.cc
index 5785a0a..40a968c 100644
--- a/test/datarate_test.cc
+++ b/test/datarate_test.cc
@@ -193,7 +193,10 @@
 
   virtual void ResetModel() {
     last_pts_ = 0;
+    bits_in_buffer_model_ = cfg_.rc_target_bitrate * cfg_.rc_buf_initial_sz;
     frame_number_ = 0;
+    first_drop_ = 0;
+    num_drops_ = 0;
     bits_total_ = 0;
     duration_ = 0.0;
   }
@@ -209,8 +212,29 @@
   }
 
   virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+    // Time since last timestamp = duration.
+    vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_;
+
+    // Add to the buffer the bits we'd expect from a constant bitrate server.
+    bits_in_buffer_model_ += duration * timebase_ * cfg_.rc_target_bitrate
+        * 1000;
+
+    // Buffer should not go negative.
+    ASSERT_GE(bits_in_buffer_model_, 0) << "Buffer Underrun at frame "
+        << pkt->data.frame.pts;
+
     const int frame_size_in_bits = pkt->data.frame.sz * 8;
     bits_total_ += frame_size_in_bits;
+
+    // If first drop not set and we have a drop set it to this time.
+    if (!first_drop_ && duration > 1)
+      first_drop_ = last_pts_ + 1;
+
+    // Update the number of frame drops.
+    if (duration > 1) {
+      num_drops_+= (duration - 1);
+    }
+
     // Update the most recent pts.
     last_pts_ = pkt->data.frame.pts;
     ++frame_number_;
@@ -231,13 +255,17 @@
   double duration_;
   double effective_datarate_;
   int set_cpu_used_;
+  int bits_in_buffer_model_;
+  int first_drop_;
+  int num_drops_;
 };
 
-// There is no buffer model/frame dropper in VP9 currently, so for now we
-// have separate test for VP9 rate targeting for 1-pass CBR. We only check
-// that effective datarate is within some range of target bitrate.
-// No frame dropper, so we can't go to low bitrates.
+// Check basic rate targeting,
 TEST_P(DatarateTestVP9, BasicRateTargeting) {
+  cfg_.rc_buf_initial_sz = 500;
+  cfg_.rc_buf_optimal_sz = 500;
+  cfg_.rc_buf_sz = 1000;
+  cfg_.rc_dropframe_thresh = 1;
   cfg_.rc_min_quantizer = 0;
   cfg_.rc_max_quantizer = 63;
   cfg_.rc_end_usage = VPX_CBR;
@@ -248,13 +276,58 @@
     cfg_.rc_target_bitrate = i;
     ResetModel();
     ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
-    ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.9)
+    ASSERT_GE(static_cast<double>(cfg_.rc_target_bitrate),
+              effective_datarate_ * 0.85)
         << " The datarate for the file exceeds the target by too much!";
-    ASSERT_LE(cfg_.rc_target_bitrate, effective_datarate_ * 1.1)
+    ASSERT_LE(static_cast<double>(cfg_.rc_target_bitrate),
+              effective_datarate_ * 1.15)
         << " The datarate for the file missed the target!";
   }
 }
 
+// Check that (1) the first dropped frame gets earlier and earlier
+// as the drop frame threshold is increased, and (2) that the total number of
+// frame drops does not decrease as we increase frame drop threshold.
+// Use a lower qp-max to force some frame drops.
+TEST_P(DatarateTestVP9, ChangingDropFrameThresh) {
+  cfg_.rc_buf_initial_sz = 500;
+  cfg_.rc_buf_optimal_sz = 500;
+  cfg_.rc_buf_sz = 1000;
+  cfg_.rc_undershoot_pct = 20;
+  cfg_.rc_undershoot_pct = 20;
+  cfg_.rc_dropframe_thresh = 10;
+  cfg_.rc_min_quantizer = 0;
+  cfg_.rc_max_quantizer = 50;
+  cfg_.rc_end_usage = VPX_CBR;
+  cfg_.rc_target_bitrate = 200;
+
+  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                       30, 1, 0, 140);
+
+  const int kDropFrameThreshTestStep = 30;
+  int last_drop = 140;
+  int last_num_drops = 0;
+  for (int i = 10; i < 100; i += kDropFrameThreshTestStep) {
+    cfg_.rc_dropframe_thresh = i;
+    ResetModel();
+    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+    ASSERT_GE(effective_datarate_, cfg_.rc_target_bitrate * 0.85)
+           << " The datarate for the file is lower than target by too much!";
+    ASSERT_LE(effective_datarate_, cfg_.rc_target_bitrate * 1.15)
+           << " The datarate for the file is greater than target by too much!";
+    ASSERT_LE(first_drop_, last_drop)
+        << " The first dropped frame for drop_thresh " << i
+        << " > first dropped frame for drop_thresh "
+        << i - kDropFrameThreshTestStep;
+    ASSERT_GE(num_drops_, last_num_drops)
+        << " The number of dropped frames for drop_thresh " << i
+        << " < number of dropped frames for drop_thresh "
+        << i - kDropFrameThreshTestStep;
+    last_drop = first_drop_;
+    last_num_drops = num_drops_;
+  }
+}
+
 VP8_INSTANTIATE_TEST_CASE(DatarateTest, ALL_TEST_MODES);
 VP9_INSTANTIATE_TEST_CASE(DatarateTestVP9,
                           ::testing::Values(::libvpx_test::kOnePassGood),
diff --git a/test/decode_perf_test.cc b/test/decode_perf_test.cc
index 95600db..a438261 100644
--- a/test/decode_perf_test.cc
+++ b/test/decode_perf_test.cc
@@ -29,7 +29,7 @@
 /*
  DecodePerfTest takes a tuple of filename + number of threads to decode with
  */
-typedef std::tr1::tuple<const char *const, unsigned> decode_perf_param_t;
+typedef std::tr1::tuple<const char *, unsigned> decode_perf_param_t;
 
 const decode_perf_param_t kVP9DecodePerfVectors[] = {
   make_tuple("vp90-2-bbb_426x240_tile_1x1_180kbps.webm", 1),
diff --git a/test/decode_test_driver.cc b/test/decode_test_driver.cc
index 1f6d54064..7a93e50 100644
--- a/test/decode_test_driver.cc
+++ b/test/decode_test_driver.cc
@@ -30,6 +30,7 @@
 
   // Decode frames.
   for (video->Begin(); video->cxdata(); video->Next()) {
+    PreDecodeFrameHook(*video, decoder);
     vpx_codec_err_t res_dec = decoder->DecodeFrame(video->cxdata(),
                                                    video->frame_size());
     ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder->DecodeError();
diff --git a/test/decode_test_driver.h b/test/decode_test_driver.h
index 055c45e..79db6e1 100644
--- a/test/decode_test_driver.h
+++ b/test/decode_test_driver.h
@@ -76,6 +76,16 @@
     return detail ? detail : vpx_codec_error(&decoder_);
   }
 
+  // Passes the external frame buffer information to libvpx.
+  vpx_codec_err_t SetExternalFrameBuffers(
+      vpx_codec_frame_buffer_t *fb_list, int fb_count,
+      vpx_realloc_frame_buffer_cb_fn_t cb, void *user_priv) {
+    InitOnce();
+    return vpx_codec_set_frame_buffers(&decoder_,
+                                       fb_list, fb_count,
+                                       cb, user_priv);
+  }
+
  protected:
   virtual const vpx_codec_iface_t* CodecInterface() const = 0;
 
@@ -101,6 +111,10 @@
   // Main decoding loop
   virtual void RunLoop(CompressedVideoSource *video);
 
+  // Hook to be called before decompressing every frame.
+  virtual void PreDecodeFrameHook(const CompressedVideoSource& video,
+                                  Decoder *decoder) {}
+
   // Hook to be called on every decompressed frame.
   virtual void DecompressedFrameHook(const vpx_image_t& img,
                                      const unsigned int frame_number) {}
diff --git a/test/error_resilience_test.cc b/test/error_resilience_test.cc
index 16d250c..30c20e9 100644
--- a/test/error_resilience_test.cc
+++ b/test/error_resilience_test.cc
@@ -1,12 +1,12 @@
 /*
-  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
-
-  Use of this source code is governed by a BSD-style license
-  that can be found in the LICENSE file in the root of the source
-  tree. An additional intellectual property rights grant can be found
-  in the file PATENTS.  All contributing project authors may
-  be found in the AUTHORS file in the root of the source tree.
-*/
+ *  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
 
 #include "third_party/googletest/src/include/gtest/gtest.h"
 #include "test/codec_factory.h"
diff --git a/test/external_frame_buffer_test.cc b/test/external_frame_buffer_test.cc
new file mode 100644
index 0000000..48eb853
--- /dev/null
+++ b/test/external_frame_buffer_test.cc
@@ -0,0 +1,322 @@
+/*
+ *  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <string>
+
+#include "test/codec_factory.h"
+#include "test/decode_test_driver.h"
+#include "test/ivf_video_source.h"
+#include "test/md5_helper.h"
+#include "test/test_vectors.h"
+#include "test/util.h"
+#include "test/webm_video_source.h"
+
+namespace {
+
+const int kVideoNameParam = 1;
+const char kVP9TestFile[] = "vp90-2-02-size-lf-1920x1080.webm";
+
+// Callback used by libvpx to request the application to allocate a frame
+// buffer of at least |new_size| in bytes.
+int realloc_vp9_frame_buffer(void *user_priv, size_t new_size,
+                             vpx_codec_frame_buffer_t *fb) {
+  (void)user_priv;
+  if (fb == NULL)
+    return -1;
+
+  delete [] fb->data;
+  fb->data = new uint8_t[new_size];
+  fb->size = new_size;
+  return 0;
+}
+
+// Callback will not allocate data for frame buffer.
+int zero_realloc_vp9_frame_buffer(void *user_priv, size_t new_size,
+                                  vpx_codec_frame_buffer_t *fb) {
+  (void)user_priv;
+  if (fb == NULL)
+    return -1;
+
+  delete [] fb->data;
+  fb->data = NULL;
+  fb->size = new_size;
+  return 0;
+}
+
+// Callback will allocate one less byte.
+int one_less_byte_realloc_vp9_frame_buffer(void *user_priv, size_t new_size,
+                                           vpx_codec_frame_buffer_t *fb) {
+  (void)user_priv;
+  if (fb == NULL)
+    return -1;
+
+  delete [] fb->data;
+
+  const size_t error_size = new_size - 1;
+  fb->data = new uint8_t[error_size];
+  fb->size = error_size;
+  return 0;
+}
+
+// Class for testing passing in external frame buffers to libvpx.
+class ExternalFrameBufferMD5Test
+    : public ::libvpx_test::DecoderTest,
+      public ::libvpx_test::CodecTestWithParam<const char*> {
+ protected:
+  ExternalFrameBufferMD5Test()
+      : DecoderTest(GET_PARAM(::libvpx_test::kCodecFactoryParam)),
+        md5_file_(NULL),
+        num_buffers_(0),
+        frame_buffers_(NULL) {}
+
+  virtual ~ExternalFrameBufferMD5Test() {
+    for (int i = 0; i < num_buffers_; ++i) {
+      delete [] frame_buffers_[i].data;
+    }
+    delete [] frame_buffers_;
+
+    if (md5_file_ != NULL)
+      fclose(md5_file_);
+  }
+
+  virtual void PreDecodeFrameHook(
+      const libvpx_test::CompressedVideoSource &video,
+      libvpx_test::Decoder *decoder) {
+    if (num_buffers_ > 0 && video.frame_number() == 0) {
+      // Have libvpx use frame buffers we create.
+      frame_buffers_ = new vpx_codec_frame_buffer_t[num_buffers_];
+      memset(frame_buffers_, 0, sizeof(frame_buffers_[0]) * num_buffers_);
+
+      ASSERT_EQ(VPX_CODEC_OK,
+                decoder->SetExternalFrameBuffers(
+                    frame_buffers_, num_buffers_,
+                    realloc_vp9_frame_buffer, NULL));
+    }
+  }
+
+  void OpenMD5File(const std::string &md5_file_name_) {
+    md5_file_ = libvpx_test::OpenTestDataFile(md5_file_name_);
+    ASSERT_TRUE(md5_file_ != NULL) << "Md5 file open failed. Filename: "
+        << md5_file_name_;
+  }
+
+  virtual void DecompressedFrameHook(const vpx_image_t &img,
+                                     const unsigned int frame_number) {
+    ASSERT_TRUE(md5_file_ != NULL);
+    char expected_md5[33];
+    char junk[128];
+
+    // Read correct md5 checksums.
+    const int res = fscanf(md5_file_, "%s  %s", expected_md5, junk);
+    ASSERT_NE(EOF, res) << "Read md5 data failed";
+    expected_md5[32] = '\0';
+
+    ::libvpx_test::MD5 md5_res;
+    md5_res.Add(&img);
+    const char *const actual_md5 = md5_res.Get();
+
+    // Check md5 match.
+    ASSERT_STREQ(expected_md5, actual_md5)
+        << "Md5 checksums don't match: frame number = " << frame_number;
+  }
+
+  void set_num_buffers(int num_buffers) { num_buffers_ = num_buffers; }
+  int num_buffers() const { return num_buffers_; }
+
+ private:
+  FILE *md5_file_;
+  int num_buffers_;
+  vpx_codec_frame_buffer_t *frame_buffers_;
+};
+
+class ExternalFrameBufferTest : public ::testing::Test {
+ protected:
+  ExternalFrameBufferTest()
+      : video_(NULL),
+        decoder_(NULL),
+        num_buffers_(0),
+        frame_buffers_(NULL) {}
+
+  virtual void SetUp() {
+    video_ = new libvpx_test::WebMVideoSource(kVP9TestFile);
+    video_->Init();
+    video_->Begin();
+
+    vpx_codec_dec_cfg_t cfg = {0};
+    decoder_ = new libvpx_test::VP9Decoder(cfg, 0);
+  }
+
+  virtual void TearDown() {
+    for (int i = 0; i < num_buffers_; ++i) {
+      delete [] frame_buffers_[i].data;
+    }
+    delete [] frame_buffers_;
+    delete decoder_;
+    delete video_;
+  }
+
+  // Passes the external frame buffer information to libvpx.
+  vpx_codec_err_t SetExternalFrameBuffers(
+      int num_buffers,
+      vpx_realloc_frame_buffer_cb_fn_t cb) {
+    if (num_buffers > 0) {
+      num_buffers_ = num_buffers;
+
+      // Have libvpx use frame buffers we create.
+      frame_buffers_ = new vpx_codec_frame_buffer_t[num_buffers_];
+      memset(frame_buffers_, 0, sizeof(frame_buffers_[0]) * num_buffers_);
+    }
+
+    return decoder_->SetExternalFrameBuffers(frame_buffers_, num_buffers_,
+                                             cb, NULL);
+  }
+
+  // Pass Null frame buffer list to libvpx.
+  vpx_codec_err_t SetNullFrameBuffers(
+      int num_buffers,
+      vpx_realloc_frame_buffer_cb_fn_t cb) {
+    return decoder_->SetExternalFrameBuffers(NULL, num_buffers,
+                                             cb, NULL);
+  }
+
+  vpx_codec_err_t DecodeOneFrame() {
+    const vpx_codec_err_t res =
+        decoder_->DecodeFrame(video_->cxdata(), video_->frame_size());
+    if (res == VPX_CODEC_OK)
+      video_->Next();
+    return res;
+  }
+
+  vpx_codec_err_t DecodeRemainingFrames() {
+    for (; video_->cxdata(); video_->Next()) {
+      const vpx_codec_err_t res =
+          decoder_->DecodeFrame(video_->cxdata(), video_->frame_size());
+      if (res != VPX_CODEC_OK)
+        return res;
+
+      libvpx_test::DxDataIterator dec_iter = decoder_->GetDxData();
+      const vpx_image_t *img = NULL;
+
+      // Get decompressed data
+      while ((img = dec_iter.Next())) {
+      }
+    }
+    return VPX_CODEC_OK;
+  }
+
+  libvpx_test::WebMVideoSource *video_;
+  libvpx_test::VP9Decoder *decoder_;
+  int num_buffers_;
+  vpx_codec_frame_buffer_t *frame_buffers_;
+};
+
+
+// This test runs through the set of test vectors, and decodes them.
+// Libvpx will call into the application to allocate a frame buffer when
+// needed. The md5 checksums are computed for each frame in the video file.
+// If md5 checksums match the correct md5 data, then the test is passed.
+// Otherwise, the test failed.
+TEST_P(ExternalFrameBufferMD5Test, ExtFBMD5Match) {
+  const std::string filename = GET_PARAM(kVideoNameParam);
+  libvpx_test::CompressedVideoSource *video = NULL;
+
+  // Number of buffers equals number of possible reference buffers(8), plus
+  // one working buffer, plus four jitter buffers.
+  const int num_buffers = 13;
+  set_num_buffers(num_buffers);
+
+#if CONFIG_VP8_DECODER
+  // Tell compiler we are not using kVP8TestVectors.
+  (void)libvpx_test::kVP8TestVectors;
+#endif
+
+  // Open compressed video file.
+  if (filename.substr(filename.length() - 3, 3) == "ivf") {
+    video = new libvpx_test::IVFVideoSource(filename);
+  } else if (filename.substr(filename.length() - 4, 4) == "webm") {
+    video = new libvpx_test::WebMVideoSource(filename);
+  }
+  video->Init();
+
+  // Construct md5 file name.
+  const std::string md5_filename = filename + ".md5";
+  OpenMD5File(md5_filename);
+
+  // Decode frame, and check the md5 matching.
+  ASSERT_NO_FATAL_FAILURE(RunLoop(video));
+  delete video;
+}
+
+TEST_F(ExternalFrameBufferTest, NineFrameBuffers) {
+  // Minimum number of external frame buffers for VP9 is
+  // #VP9_MAXIMUM_REF_BUFFERS + #VPX_MAXIMUM_WORK_BUFFERS.
+  const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
+  ASSERT_EQ(VPX_CODEC_OK,
+            SetExternalFrameBuffers(num_buffers, realloc_vp9_frame_buffer));
+  ASSERT_EQ(VPX_CODEC_OK, DecodeRemainingFrames());
+}
+
+TEST_F(ExternalFrameBufferTest, EightJitterBuffers) {
+  // Number of buffers equals #VP9_MAXIMUM_REF_BUFFERS +
+  // #VPX_MAXIMUM_WORK_BUFFERS + eight jitter buffers.
+  const int jitter_buffers = 8;
+  const int num_buffers =
+      VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS + jitter_buffers;
+  ASSERT_EQ(VPX_CODEC_OK,
+            SetExternalFrameBuffers(num_buffers, realloc_vp9_frame_buffer));
+  ASSERT_EQ(VPX_CODEC_OK, DecodeRemainingFrames());
+}
+
+TEST_F(ExternalFrameBufferTest, NotEnoughBuffers) {
+  // Minimum number of external frame buffers for VP9 is
+  // #VP9_MAXIMUM_REF_BUFFERS + #VPX_MAXIMUM_WORK_BUFFERS. Set one less.
+  const int num_buffers =
+      VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS - 1;
+  ASSERT_EQ(VPX_CODEC_INVALID_PARAM,
+            SetExternalFrameBuffers(num_buffers, realloc_vp9_frame_buffer));
+}
+
+TEST_F(ExternalFrameBufferTest, NullFrameBufferList) {
+  // Number of buffers equals #VP9_MAXIMUM_REF_BUFFERS +
+  // #VPX_MAXIMUM_WORK_BUFFERS + four jitter buffers.
+  const int jitter_buffers = 4;
+  const int num_buffers =
+      VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS + jitter_buffers;
+  ASSERT_EQ(VPX_CODEC_INVALID_PARAM,
+            SetNullFrameBuffers(num_buffers, realloc_vp9_frame_buffer));
+}
+
+TEST_F(ExternalFrameBufferTest, NullRealloc) {
+  // Number of buffers equals #VP9_MAXIMUM_REF_BUFFERS +
+  // #VPX_MAXIMUM_WORK_BUFFERS + four jitter buffers.
+  const int jitter_buffers = 4;
+  const int num_buffers =
+      VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS + jitter_buffers;
+  ASSERT_EQ(VPX_CODEC_OK,
+            SetExternalFrameBuffers(num_buffers,
+                                    zero_realloc_vp9_frame_buffer));
+  ASSERT_EQ(VPX_CODEC_MEM_ERROR, DecodeOneFrame());
+}
+
+TEST_F(ExternalFrameBufferTest, ReallocOneLessByte) {
+  // Number of buffers equals #VP9_MAXIMUM_REF_BUFFERS +
+  // #VPX_MAXIMUM_WORK_BUFFERS + four jitter buffers.
+  const int jitter_buffers = 4;
+  const int num_buffers =
+      VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS + jitter_buffers;
+  ASSERT_EQ(VPX_CODEC_OK,
+            SetExternalFrameBuffers(num_buffers,
+                                    one_less_byte_realloc_vp9_frame_buffer));
+  ASSERT_EQ(VPX_CODEC_MEM_ERROR, DecodeOneFrame());
+}
+
+VP9_INSTANTIATE_TEST_CASE(ExternalFrameBufferMD5Test,
+                          ::testing::ValuesIn(libvpx_test::kVP9TestVectors));
+}  // namespace
diff --git a/test/lru_frame_buffer_test.cc b/test/lru_frame_buffer_test.cc
new file mode 100644
index 0000000..cd6b432
--- /dev/null
+++ b/test/lru_frame_buffer_test.cc
@@ -0,0 +1,207 @@
+/*
+ *  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <queue>
+#include <string>
+
+#include "test/codec_factory.h"
+#include "test/decode_test_driver.h"
+#include "test/ivf_video_source.h"
+#include "test/md5_helper.h"
+#include "test/util.h"
+#include "test/webm_video_source.h"
+
+namespace {
+
+const int kVideoNameParam = 1;
+
+const char *kLRUTestVectors[] = {
+  "vp90-2-02-size-lf-1920x1080.webm",
+  "vp90-2-05-resize.ivf",
+};
+
+// Callback used by libvpx to request the application to allocate a frame
+// buffer of at least |new_size| in bytes.
+int realloc_vp9_frame_buffer(void *user_priv, size_t new_size,
+                             vpx_codec_frame_buffer_t *fb) {
+  (void)user_priv;
+  if (fb == NULL)
+    return -1;
+
+  delete [] fb->data;
+  fb->data = new uint8_t[new_size];
+  fb->size = new_size;
+
+  return 0;
+}
+
+// Class for testing libvpx is using the least recently
+// used frame buffer when a new buffer is requested.
+class LRUFrameBufferTest
+    : public ::libvpx_test::DecoderTest,
+      public ::libvpx_test::CodecTestWithParam<const char*> {
+ protected:
+  struct FrameBufferMD5Sum {
+    int frame_buffer_index;
+    vpx_image_t img;
+    std::string md5;
+  };
+
+  LRUFrameBufferTest()
+      : DecoderTest(GET_PARAM(::libvpx_test::kCodecFactoryParam)),
+        num_buffers_(0),
+        num_jitter_buffers_(0),
+        frame_buffers_(NULL) {}
+
+  virtual ~LRUFrameBufferTest() {
+    for (int i = 0; i < num_buffers_; ++i) {
+      delete [] frame_buffers_[i].data;
+    }
+    delete [] frame_buffers_;
+  }
+
+  virtual void PreDecodeFrameHook(
+      const libvpx_test::CompressedVideoSource &video,
+      libvpx_test::Decoder *decoder) {
+    // Use external buffers for testing jitter buffers.
+    if (num_jitter_buffers_ > 0 && video.frame_number() == 0) {
+      const int max_reference_buffers = 8;
+
+      // Add 1 for a work buffer.
+      num_buffers_ = max_reference_buffers + 1 + num_jitter_buffers_;
+
+      // Have libvpx use frame buffers we create.
+      frame_buffers_ = new vpx_codec_frame_buffer_t[num_buffers_];
+      memset(frame_buffers_, 0, sizeof(frame_buffers_[0]) * num_buffers_);
+
+      decoder->SetExternalFrameBuffers(frame_buffers_, num_buffers_,
+                                       realloc_vp9_frame_buffer, NULL);
+    }
+
+    // Turn on frame buffer LRU cache.
+    decoder->Control(VP9D_SET_FRAME_BUFFER_LRU_CACHE, 1);
+  }
+
+  virtual void DecompressedFrameHook(const vpx_image_t &img,
+                                     const unsigned int frame_number) {
+    const uint32_t ximg_y_plane = 0;
+    const uint8_t *const y_buffer = img.planes[ximg_y_plane];
+
+    // Find which external buffer contains the y_buffer.
+    int i = 0;
+    for (i = 0; i < num_buffers_; ++i) {
+      if (y_buffer >= frame_buffers_[i].data &&
+          y_buffer < (frame_buffers_[i].data + frame_buffers_[i].size)) {
+        break;
+      }
+    }
+
+    FrameBufferMD5Sum fb_md5;
+    fb_md5.frame_buffer_index = i;
+    fb_md5.img = img;
+
+    libvpx_test::MD5 md5;
+    md5.Add(&img);
+    fb_md5.md5 = md5.Get();
+    jitter_buffer_md5_sums_.push(fb_md5);
+
+    // Check to see if any of the reconstructed image changed.
+    if (jitter_buffer_md5_sums_.size() >
+        static_cast<size_t>(num_jitter_buffers_)) {
+      fb_md5 = jitter_buffer_md5_sums_.front();
+
+      libvpx_test::MD5 md5;
+      md5.Add(&fb_md5.img);
+      const std::string check_str = md5.Get();
+
+      ASSERT_EQ(fb_md5.md5, check_str);
+      jitter_buffer_md5_sums_.pop();
+    }
+  }
+
+  libvpx_test::CompressedVideoSource *OpenCompressedFile(
+      const std::string &filename) {
+    if (filename.substr(filename.length() - 3, 3) == "ivf") {
+      return new libvpx_test::IVFVideoSource(filename);
+    } else if (filename.substr(filename.length() - 4, 4) == "webm") {
+      return new libvpx_test::WebMVideoSource(filename);
+    }
+    return NULL;
+  }
+
+  void set_num_jitter_buffers(int num_buffers) {
+    num_jitter_buffers_ = num_buffers;
+  }
+
+ private:
+  // Total number of external frame buffers.
+  int num_buffers_;
+  int num_jitter_buffers_;
+
+  // External frame buffers used by libvpx.
+  vpx_codec_frame_buffer_t *frame_buffers_;
+
+  // Save the md5 checksums for later comparison.
+  std::queue<FrameBufferMD5Sum> jitter_buffer_md5_sums_;
+};
+
+// This test runs through a set of test vectors, and decodes them.
+// Libvpx will call into the application to allocate a frame buffer when
+// needed. The md5 checksums are computed for each frame after it is
+// decoded and stored to be checked later. After a jitter frame buffer
+// has expired, the md5 checksum is computed again for the expired jitter
+// buffer frame and checked against the md5 checksum after the frame was
+// decoded. If md5 checksums match, then the test is passed. Otherwise,
+// the test failed.
+TEST_P(LRUFrameBufferTest, CheckLRUOneJitterBuffer) {
+  const std::string filename = GET_PARAM(kVideoNameParam);
+
+  set_num_jitter_buffers(1);
+
+  libvpx_test::CompressedVideoSource *const video =
+      OpenCompressedFile(filename);
+  video->Init();
+
+  // Decode frame, and check the md5 matching.
+  ASSERT_NO_FATAL_FAILURE(RunLoop(video));
+  delete video;
+}
+
+TEST_P(LRUFrameBufferTest, CheckLRUFourJitterBuffers) {
+  const std::string filename = GET_PARAM(kVideoNameParam);
+
+  set_num_jitter_buffers(4);
+
+  libvpx_test::CompressedVideoSource *const video =
+      OpenCompressedFile(filename);
+  video->Init();
+
+  // Decode frame, and check the md5 matching.
+  ASSERT_NO_FATAL_FAILURE(RunLoop(video));
+  delete video;
+}
+
+TEST_P(LRUFrameBufferTest, CheckLRUEightJitterBuffers) {
+  const std::string filename = GET_PARAM(kVideoNameParam);
+
+  set_num_jitter_buffers(8);
+
+  libvpx_test::CompressedVideoSource *const video =
+      OpenCompressedFile(filename);
+  video->Init();
+
+  // Decode frame, and check the md5 matching.
+  ASSERT_NO_FATAL_FAILURE(RunLoop(video));
+  delete video;
+}
+
+VP9_INSTANTIATE_TEST_CASE(LRUFrameBufferTest,
+                          ::testing::ValuesIn(kLRUTestVectors));
+}  // namespace
diff --git a/test/partial_idct_test.cc b/test/partial_idct_test.cc
new file mode 100644
index 0000000..a6569c0
--- /dev/null
+++ b/test/partial_idct_test.cc
@@ -0,0 +1,172 @@
+/*
+ *  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+
+extern "C" {
+#include "./vp9_rtcd.h"
+#include "vp9/common/vp9_blockd.h"
+#include "vp9/common/vp9_scan.h"
+}
+
+#include "vpx/vpx_integer.h"
+
+using libvpx_test::ACMRandom;
+
+namespace {
+typedef void (*fwd_txfm_t)(const int16_t *in, int16_t *out, int stride);
+typedef void (*inv_txfm_t)(const int16_t *in, uint8_t *out, int stride);
+typedef std::tr1::tuple<inv_txfm_t,
+                        inv_txfm_t,
+                        TX_SIZE, int> partial_itxfm_param_t;
+const int kMaxNumCoeffs = 1024;
+class PartialIDctTest : public ::testing::TestWithParam<partial_itxfm_param_t> {
+ public:
+  virtual ~PartialIDctTest() {}
+  virtual void SetUp() {
+    full_itxfm_ = GET_PARAM(0);
+    partial_itxfm_ = GET_PARAM(1);
+    tx_size_  = GET_PARAM(2);
+    last_nonzero_ = GET_PARAM(3);
+  }
+
+  virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+  int last_nonzero_;
+  TX_SIZE tx_size_;
+  inv_txfm_t full_itxfm_;
+  inv_txfm_t partial_itxfm_;
+};
+
+TEST_P(PartialIDctTest, ResultsMatch) {
+  ACMRandom rnd(ACMRandom::DeterministicSeed());
+  int size;
+  switch (tx_size_) {
+    case TX_4X4:
+      size = 4;
+      break;
+    case TX_8X8:
+      size = 8;
+      break;
+    case TX_16X16:
+      size = 16;
+      break;
+    case TX_32X32:
+      size = 32;
+      break;
+    default:
+      FAIL() << "Wrong Size!";
+      break;
+  }
+  DECLARE_ALIGNED_ARRAY(16, int16_t, test_coef_block1, kMaxNumCoeffs);
+  DECLARE_ALIGNED_ARRAY(16, int16_t, test_coef_block2, kMaxNumCoeffs);
+  DECLARE_ALIGNED_ARRAY(16, uint8_t, dst1, kMaxNumCoeffs);
+  DECLARE_ALIGNED_ARRAY(16, uint8_t, dst2, kMaxNumCoeffs);
+  const int count_test_block = 1000;
+  const int max_coeff = 32766 / 4;
+  const int block_size = size * size;
+  int max_error = 0;
+  for (int i = 0; i < count_test_block; ++i) {
+    // clear out destination buffer
+    memset(dst1, 0, sizeof(*dst1) * block_size);
+    memset(dst2, 0, sizeof(*dst2) * block_size);
+    memset(test_coef_block1, 0, sizeof(*test_coef_block1) * block_size);
+    memset(test_coef_block2, 0, sizeof(*test_coef_block2) * block_size);
+    int max_energy_leftover = max_coeff * max_coeff;
+    for (int j = 0; j < last_nonzero_; ++j) {
+      int16_t coef = static_cast<int16_t>(sqrt(1.0 * max_energy_leftover) *
+                                          (rnd.Rand16() - 32768) / 65536);
+      max_energy_leftover -= coef * coef;
+      if (max_energy_leftover < 0) {
+        max_energy_leftover = 0;
+        coef = 0;
+      }
+      test_coef_block1[vp9_default_scan_orders[tx_size_].scan[j]] = coef;
+    }
+
+    memcpy(test_coef_block2, test_coef_block1,
+           sizeof(*test_coef_block2) * block_size);
+
+    REGISTER_STATE_CHECK(full_itxfm_(test_coef_block1, dst1, size));
+    REGISTER_STATE_CHECK(partial_itxfm_(test_coef_block2, dst2, size));
+
+    for (int j = 0; j < block_size; ++j) {
+      const int diff = dst1[j] - dst2[j];
+      const int error = diff * diff;
+      if (max_error < error)
+        max_error = error;
+    }
+  }
+
+  EXPECT_EQ(0, max_error)
+      << "Error: partial inverse transform produces different results";
+}
+using std::tr1::make_tuple;
+
+INSTANTIATE_TEST_CASE_P(
+    C, PartialIDctTest,
+    ::testing::Values(
+        make_tuple(&vp9_idct32x32_1024_add_c,
+                   &vp9_idct32x32_34_add_c,
+                   TX_32X32, 34),
+        make_tuple(&vp9_idct32x32_1024_add_c,
+                   &vp9_idct32x32_1_add_c,
+                   TX_32X32, 1),
+        make_tuple(&vp9_idct16x16_256_add_c,
+                   &vp9_idct16x16_10_add_c,
+                   TX_16X16, 10),
+        make_tuple(&vp9_idct16x16_256_add_c,
+                   &vp9_idct16x16_1_add_c,
+                   TX_16X16, 1),
+        make_tuple(&vp9_idct8x8_64_add_c,
+                   &vp9_idct8x8_10_add_c,
+                   TX_8X8, 10),
+        make_tuple(&vp9_idct8x8_64_add_c,
+                   &vp9_idct8x8_1_add_c,
+                   TX_8X8, 1),
+        make_tuple(&vp9_idct4x4_16_add_c,
+                   &vp9_idct4x4_1_add_c,
+                   TX_4X4, 1)));
+#if HAVE_SSE2
+INSTANTIATE_TEST_CASE_P(
+    SSE2, PartialIDctTest,
+    ::testing::Values(
+        make_tuple(&vp9_idct32x32_1024_add_c,
+                   &vp9_idct32x32_34_add_sse2,
+                   TX_32X32, 34),
+        make_tuple(&vp9_idct32x32_1024_add_c,
+                   &vp9_idct32x32_1_add_sse2,
+                   TX_32X32, 1),
+        make_tuple(&vp9_idct16x16_256_add_c,
+                   &vp9_idct16x16_10_add_sse2,
+                   TX_16X16, 10),
+        make_tuple(&vp9_idct16x16_256_add_c,
+                   &vp9_idct16x16_1_add_sse2,
+                   TX_16X16, 1),
+        make_tuple(&vp9_idct8x8_64_add_c,
+                   &vp9_idct8x8_10_add_sse2,
+                   TX_8X8, 10),
+        make_tuple(&vp9_idct8x8_64_add_c,
+                   &vp9_idct8x8_1_add_sse2,
+                   TX_8X8, 1),
+        make_tuple(&vp9_idct4x4_16_add_c,
+                   &vp9_idct4x4_1_add_sse2,
+                   TX_4X4, 1)));
+#endif
+}  // namespace
diff --git a/test/sixtap_predict_test.cc b/test/sixtap_predict_test.cc
index 655146d..0f5c0a5 100644
--- a/test/sixtap_predict_test.cc
+++ b/test/sixtap_predict_test.cc
@@ -1,12 +1,12 @@
 /*
-*  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
-*
-*  Use of this source code is governed by a BSD-style license
-*  that can be found in the LICENSE file in the root of the source
-*  tree. An additional intellectual property rights grant can be found
-*  in the file PATENTS.  All contributing project authors may
-*  be found in the AUTHORS file in the root of the source tree.
-*/
+ *  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
 
 #include <math.h>
 #include <stdlib.h>
diff --git a/test/test-data.sha1 b/test/test-data.sha1
index 4451479..4927059 100644
--- a/test/test-data.sha1
+++ b/test/test-data.sha1
@@ -567,3 +567,9 @@
 c9b6850af28579b031791066457f4cb40df6e1c7  vp90-2-08-tile_1x8_frame_parallel.webm.md5
 e448b6e83490bca0f8d58b4f4b1126a17baf4b0c  vp90-2-08-tile_1x8.webm
 5e524165f0397e6141d914f4f0a66267d7658376  vp90-2-08-tile_1x8.webm.md5
+a34e14923d6d17b1144254d8187d7f85b700a63c  vp90-2-02-size-lf-1920x1080.webm
+e3b28ddcfaeb37fb4d132b93f92642a9ad17c22d  vp90-2-02-size-lf-1920x1080.webm.md5
+d48c5db1b0f8e60521a7c749696b8067886033a3  vp90-2-09-aq2.webm
+84c1599298aac78f2fc05ae2274575d10569dfa0  vp90-2-09-aq2.webm.md5
+55fc55ed73d578ed60fad05692579873f8bad758  vp90-2-09-lf_deltas.webm
+54638c38009198c38c8f3b25c182b709b6c1fd2e  vp90-2-09-lf_deltas.webm.md5
diff --git a/test/test.mk b/test/test.mk
index 98e5c7b..5a1d39d 100644
--- a/test/test.mk
+++ b/test/test.mk
@@ -7,6 +7,8 @@
 LIBVPX_TEST_SRCS-yes += test_libvpx.cc
 LIBVPX_TEST_SRCS-yes += util.h
 LIBVPX_TEST_SRCS-yes += video_source.h
+LIBVPX_TEST_SRCS-yes += test_vectors.h
+LIBVPX_TEST_SRCS-yes += test_vectors.cc
 
 ##
 ## BLACK BOX TESTS
@@ -32,6 +34,8 @@
 LIBVPX_TEST_SRCS-yes                   += decode_test_driver.cc
 LIBVPX_TEST_SRCS-yes                   += decode_test_driver.h
 LIBVPX_TEST_SRCS-$(CONFIG_DECODERS)    += ivf_video_source.h
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += external_frame_buffer_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += lru_frame_buffer_test.cc
 
 ## WebM Parsing
 NESTEGG_SRCS                           += ../nestegg/halloc/halloc.h
@@ -88,6 +92,7 @@
 
 # IDCT test currently depends on FDCT function
 LIBVPX_TEST_SRCS-yes                   += idct8x8_test.cc
+LIBVPX_TEST_SRCS-yes                   += partial_idct_test.cc
 LIBVPX_TEST_SRCS-yes                   += superframe_test.cc
 LIBVPX_TEST_SRCS-yes                   += tile_independence_test.cc
 endif
@@ -664,6 +669,10 @@
 LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile-4x1.webm.md5
 LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-09-subpixel-00.ivf
 LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-09-subpixel-00.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-09-aq2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-09-aq2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-09-lf_deltas.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-09-lf_deltas.webm.md5
 LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp91-2-04-yv444.webm
 LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp91-2-04-yv444.webm.md5
 
diff --git a/test/test_vector_test.cc b/test/test_vector_test.cc
index ee610fa..6d93bb8 100644
--- a/test/test_vector_test.cc
+++ b/test/test_vector_test.cc
@@ -1,11 +1,11 @@
 /*
- Copyright (c) 2012 The WebM project authors. All Rights Reserved.
-
- Use of this source code is governed by a BSD-style license
- that can be found in the LICENSE file in the root of the source
- tree. An additional intellectual property rights grant can be found
- in the file PATENTS.  All contributing project authors may
- be found in the AUTHORS file in the root of the source tree.
+ *  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
  */
 
 #include <cstdio>
@@ -15,165 +15,15 @@
 #include "test/codec_factory.h"
 #include "test/decode_test_driver.h"
 #include "test/ivf_video_source.h"
-#include "test/webm_video_source.h"
-#include "test/util.h"
 #include "test/md5_helper.h"
+#include "test/test_vectors.h"
+#include "test/util.h"
+#include "test/webm_video_source.h"
 extern "C" {
 #include "vpx_mem/vpx_mem.h"
 }
 
 namespace {
-#if CONFIG_VP8_DECODER
-const char *kVP8TestVectors[] = {
-  "vp80-00-comprehensive-001.ivf",
-  "vp80-00-comprehensive-002.ivf", "vp80-00-comprehensive-003.ivf",
-  "vp80-00-comprehensive-004.ivf", "vp80-00-comprehensive-005.ivf",
-  "vp80-00-comprehensive-006.ivf", "vp80-00-comprehensive-007.ivf",
-  "vp80-00-comprehensive-008.ivf", "vp80-00-comprehensive-009.ivf",
-  "vp80-00-comprehensive-010.ivf", "vp80-00-comprehensive-011.ivf",
-  "vp80-00-comprehensive-012.ivf", "vp80-00-comprehensive-013.ivf",
-  "vp80-00-comprehensive-014.ivf", "vp80-00-comprehensive-015.ivf",
-  "vp80-00-comprehensive-016.ivf", "vp80-00-comprehensive-017.ivf",
-  "vp80-00-comprehensive-018.ivf", "vp80-01-intra-1400.ivf",
-  "vp80-01-intra-1411.ivf", "vp80-01-intra-1416.ivf",
-  "vp80-01-intra-1417.ivf", "vp80-02-inter-1402.ivf",
-  "vp80-02-inter-1412.ivf", "vp80-02-inter-1418.ivf",
-  "vp80-02-inter-1424.ivf", "vp80-03-segmentation-01.ivf",
-  "vp80-03-segmentation-02.ivf", "vp80-03-segmentation-03.ivf",
-  "vp80-03-segmentation-04.ivf", "vp80-03-segmentation-1401.ivf",
-  "vp80-03-segmentation-1403.ivf", "vp80-03-segmentation-1407.ivf",
-  "vp80-03-segmentation-1408.ivf", "vp80-03-segmentation-1409.ivf",
-  "vp80-03-segmentation-1410.ivf", "vp80-03-segmentation-1413.ivf",
-  "vp80-03-segmentation-1414.ivf", "vp80-03-segmentation-1415.ivf",
-  "vp80-03-segmentation-1425.ivf", "vp80-03-segmentation-1426.ivf",
-  "vp80-03-segmentation-1427.ivf", "vp80-03-segmentation-1432.ivf",
-  "vp80-03-segmentation-1435.ivf", "vp80-03-segmentation-1436.ivf",
-  "vp80-03-segmentation-1437.ivf", "vp80-03-segmentation-1441.ivf",
-  "vp80-03-segmentation-1442.ivf", "vp80-04-partitions-1404.ivf",
-  "vp80-04-partitions-1405.ivf", "vp80-04-partitions-1406.ivf",
-  "vp80-05-sharpness-1428.ivf", "vp80-05-sharpness-1429.ivf",
-  "vp80-05-sharpness-1430.ivf", "vp80-05-sharpness-1431.ivf",
-  "vp80-05-sharpness-1433.ivf", "vp80-05-sharpness-1434.ivf",
-  "vp80-05-sharpness-1438.ivf", "vp80-05-sharpness-1439.ivf",
-  "vp80-05-sharpness-1440.ivf", "vp80-05-sharpness-1443.ivf",
-  "vp80-06-smallsize.ivf"
-};
-#endif
-#if CONFIG_VP9_DECODER
-const char *kVP9TestVectors[] = {
-  "vp90-2-00-quantizer-00.webm", "vp90-2-00-quantizer-01.webm",
-  "vp90-2-00-quantizer-02.webm", "vp90-2-00-quantizer-03.webm",
-  "vp90-2-00-quantizer-04.webm", "vp90-2-00-quantizer-05.webm",
-  "vp90-2-00-quantizer-06.webm", "vp90-2-00-quantizer-07.webm",
-  "vp90-2-00-quantizer-08.webm", "vp90-2-00-quantizer-09.webm",
-  "vp90-2-00-quantizer-10.webm", "vp90-2-00-quantizer-11.webm",
-  "vp90-2-00-quantizer-12.webm", "vp90-2-00-quantizer-13.webm",
-  "vp90-2-00-quantizer-14.webm", "vp90-2-00-quantizer-15.webm",
-  "vp90-2-00-quantizer-16.webm", "vp90-2-00-quantizer-17.webm",
-  "vp90-2-00-quantizer-18.webm", "vp90-2-00-quantizer-19.webm",
-  "vp90-2-00-quantizer-20.webm", "vp90-2-00-quantizer-21.webm",
-  "vp90-2-00-quantizer-22.webm", "vp90-2-00-quantizer-23.webm",
-  "vp90-2-00-quantizer-24.webm", "vp90-2-00-quantizer-25.webm",
-  "vp90-2-00-quantizer-26.webm", "vp90-2-00-quantizer-27.webm",
-  "vp90-2-00-quantizer-28.webm", "vp90-2-00-quantizer-29.webm",
-  "vp90-2-00-quantizer-30.webm", "vp90-2-00-quantizer-31.webm",
-  "vp90-2-00-quantizer-32.webm", "vp90-2-00-quantizer-33.webm",
-  "vp90-2-00-quantizer-34.webm", "vp90-2-00-quantizer-35.webm",
-  "vp90-2-00-quantizer-36.webm", "vp90-2-00-quantizer-37.webm",
-  "vp90-2-00-quantizer-38.webm", "vp90-2-00-quantizer-39.webm",
-  "vp90-2-00-quantizer-40.webm", "vp90-2-00-quantizer-41.webm",
-  "vp90-2-00-quantizer-42.webm", "vp90-2-00-quantizer-43.webm",
-  "vp90-2-00-quantizer-44.webm", "vp90-2-00-quantizer-45.webm",
-  "vp90-2-00-quantizer-46.webm", "vp90-2-00-quantizer-47.webm",
-  "vp90-2-00-quantizer-48.webm", "vp90-2-00-quantizer-49.webm",
-  "vp90-2-00-quantizer-50.webm", "vp90-2-00-quantizer-51.webm",
-  "vp90-2-00-quantizer-52.webm", "vp90-2-00-quantizer-53.webm",
-  "vp90-2-00-quantizer-54.webm", "vp90-2-00-quantizer-55.webm",
-  "vp90-2-00-quantizer-56.webm", "vp90-2-00-quantizer-57.webm",
-  "vp90-2-00-quantizer-58.webm", "vp90-2-00-quantizer-59.webm",
-  "vp90-2-00-quantizer-60.webm", "vp90-2-00-quantizer-61.webm",
-  "vp90-2-00-quantizer-62.webm", "vp90-2-00-quantizer-63.webm",
-  "vp90-2-01-sharpness-1.webm", "vp90-2-01-sharpness-2.webm",
-  "vp90-2-01-sharpness-3.webm", "vp90-2-01-sharpness-4.webm",
-  "vp90-2-01-sharpness-5.webm", "vp90-2-01-sharpness-6.webm",
-  "vp90-2-01-sharpness-7.webm", "vp90-2-02-size-08x08.webm",
-  "vp90-2-02-size-08x10.webm", "vp90-2-02-size-08x16.webm",
-  "vp90-2-02-size-08x18.webm", "vp90-2-02-size-08x32.webm",
-  "vp90-2-02-size-08x34.webm", "vp90-2-02-size-08x64.webm",
-  "vp90-2-02-size-08x66.webm", "vp90-2-02-size-10x08.webm",
-  "vp90-2-02-size-10x10.webm", "vp90-2-02-size-10x16.webm",
-  "vp90-2-02-size-10x18.webm", "vp90-2-02-size-10x32.webm",
-  "vp90-2-02-size-10x34.webm", "vp90-2-02-size-10x64.webm",
-  "vp90-2-02-size-10x66.webm", "vp90-2-02-size-16x08.webm",
-  "vp90-2-02-size-16x10.webm", "vp90-2-02-size-16x16.webm",
-  "vp90-2-02-size-16x18.webm", "vp90-2-02-size-16x32.webm",
-  "vp90-2-02-size-16x34.webm", "vp90-2-02-size-16x64.webm",
-  "vp90-2-02-size-16x66.webm", "vp90-2-02-size-18x08.webm",
-  "vp90-2-02-size-18x10.webm", "vp90-2-02-size-18x16.webm",
-  "vp90-2-02-size-18x18.webm", "vp90-2-02-size-18x32.webm",
-  "vp90-2-02-size-18x34.webm", "vp90-2-02-size-18x64.webm",
-  "vp90-2-02-size-18x66.webm", "vp90-2-02-size-32x08.webm",
-  "vp90-2-02-size-32x10.webm", "vp90-2-02-size-32x16.webm",
-  "vp90-2-02-size-32x18.webm", "vp90-2-02-size-32x32.webm",
-  "vp90-2-02-size-32x34.webm", "vp90-2-02-size-32x64.webm",
-  "vp90-2-02-size-32x66.webm", "vp90-2-02-size-34x08.webm",
-  "vp90-2-02-size-34x10.webm", "vp90-2-02-size-34x16.webm",
-  "vp90-2-02-size-34x18.webm", "vp90-2-02-size-34x32.webm",
-  "vp90-2-02-size-34x34.webm", "vp90-2-02-size-34x64.webm",
-  "vp90-2-02-size-34x66.webm", "vp90-2-02-size-64x08.webm",
-  "vp90-2-02-size-64x10.webm", "vp90-2-02-size-64x16.webm",
-  "vp90-2-02-size-64x18.webm", "vp90-2-02-size-64x32.webm",
-  "vp90-2-02-size-64x34.webm", "vp90-2-02-size-64x64.webm",
-  "vp90-2-02-size-64x66.webm", "vp90-2-02-size-66x08.webm",
-  "vp90-2-02-size-66x10.webm", "vp90-2-02-size-66x16.webm",
-  "vp90-2-02-size-66x18.webm", "vp90-2-02-size-66x32.webm",
-  "vp90-2-02-size-66x34.webm", "vp90-2-02-size-66x64.webm",
-  "vp90-2-02-size-66x66.webm", "vp90-2-03-size-196x196.webm",
-  "vp90-2-03-size-196x198.webm", "vp90-2-03-size-196x200.webm",
-  "vp90-2-03-size-196x202.webm", "vp90-2-03-size-196x208.webm",
-  "vp90-2-03-size-196x210.webm", "vp90-2-03-size-196x224.webm",
-  "vp90-2-03-size-196x226.webm", "vp90-2-03-size-198x196.webm",
-  "vp90-2-03-size-198x198.webm", "vp90-2-03-size-198x200.webm",
-  "vp90-2-03-size-198x202.webm", "vp90-2-03-size-198x208.webm",
-  "vp90-2-03-size-198x210.webm", "vp90-2-03-size-198x224.webm",
-  "vp90-2-03-size-198x226.webm", "vp90-2-03-size-200x196.webm",
-  "vp90-2-03-size-200x198.webm", "vp90-2-03-size-200x200.webm",
-  "vp90-2-03-size-200x202.webm", "vp90-2-03-size-200x208.webm",
-  "vp90-2-03-size-200x210.webm", "vp90-2-03-size-200x224.webm",
-  "vp90-2-03-size-200x226.webm", "vp90-2-03-size-202x196.webm",
-  "vp90-2-03-size-202x198.webm", "vp90-2-03-size-202x200.webm",
-  "vp90-2-03-size-202x202.webm", "vp90-2-03-size-202x208.webm",
-  "vp90-2-03-size-202x210.webm", "vp90-2-03-size-202x224.webm",
-  "vp90-2-03-size-202x226.webm", "vp90-2-03-size-208x196.webm",
-  "vp90-2-03-size-208x198.webm", "vp90-2-03-size-208x200.webm",
-  "vp90-2-03-size-208x202.webm", "vp90-2-03-size-208x208.webm",
-  "vp90-2-03-size-208x210.webm", "vp90-2-03-size-208x224.webm",
-  "vp90-2-03-size-208x226.webm", "vp90-2-03-size-210x196.webm",
-  "vp90-2-03-size-210x198.webm", "vp90-2-03-size-210x200.webm",
-  "vp90-2-03-size-210x202.webm", "vp90-2-03-size-210x208.webm",
-  "vp90-2-03-size-210x210.webm", "vp90-2-03-size-210x224.webm",
-  "vp90-2-03-size-210x226.webm", "vp90-2-03-size-224x196.webm",
-  "vp90-2-03-size-224x198.webm", "vp90-2-03-size-224x200.webm",
-  "vp90-2-03-size-224x202.webm", "vp90-2-03-size-224x208.webm",
-  "vp90-2-03-size-224x210.webm", "vp90-2-03-size-224x224.webm",
-  "vp90-2-03-size-224x226.webm", "vp90-2-03-size-226x196.webm",
-  "vp90-2-03-size-226x198.webm", "vp90-2-03-size-226x200.webm",
-  "vp90-2-03-size-226x202.webm", "vp90-2-03-size-226x208.webm",
-  "vp90-2-03-size-226x210.webm", "vp90-2-03-size-226x224.webm",
-  "vp90-2-03-size-226x226.webm", "vp90-2-03-deltaq.webm",
-  "vp90-2-05-resize.ivf",        "vp90-2-06-bilinear.webm",
-  "vp90-2-07-frame_parallel.webm",
-  "vp90-2-08-tile_1x2_frame_parallel.webm", "vp90-2-08-tile_1x2.webm",
-  "vp90-2-08-tile_1x4_frame_parallel.webm", "vp90-2-08-tile_1x4.webm",
-  "vp90-2-08-tile_1x8_frame_parallel.webm", "vp90-2-08-tile_1x8.webm",
-  "vp90-2-08-tile-4x4.webm", "vp90-2-08-tile-4x1.webm",
-  "vp90-2-09-subpixel-00.ivf",
-  "vp90-2-02-size-lf-1920x1080.webm",
-#if CONFIG_NON420
-  "vp91-2-04-yv444.webm"
-#endif
-};
-#endif
 
 class TestVectorTest : public ::libvpx_test::DecoderTest,
     public ::libvpx_test::CodecTestWithParam<const char*> {
@@ -241,8 +91,8 @@
 }
 
 VP8_INSTANTIATE_TEST_CASE(TestVectorTest,
-                          ::testing::ValuesIn(kVP8TestVectors));
+                          ::testing::ValuesIn(libvpx_test::kVP8TestVectors));
 VP9_INSTANTIATE_TEST_CASE(TestVectorTest,
-                          ::testing::ValuesIn(kVP9TestVectors));
+                          ::testing::ValuesIn(libvpx_test::kVP9TestVectors));
 
 }  // namespace
diff --git a/test/test_vectors.cc b/test/test_vectors.cc
new file mode 100644
index 0000000..16298d0
--- /dev/null
+++ b/test/test_vectors.cc
@@ -0,0 +1,169 @@
+/*
+ *  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/test_vectors.h"
+
+namespace libvpx_test {
+
+#if CONFIG_VP8_DECODER
+const char *kVP8TestVectors[kNumVp8TestVectors] = {
+  "vp80-00-comprehensive-001.ivf",
+  "vp80-00-comprehensive-002.ivf", "vp80-00-comprehensive-003.ivf",
+  "vp80-00-comprehensive-004.ivf", "vp80-00-comprehensive-005.ivf",
+  "vp80-00-comprehensive-006.ivf", "vp80-00-comprehensive-007.ivf",
+  "vp80-00-comprehensive-008.ivf", "vp80-00-comprehensive-009.ivf",
+  "vp80-00-comprehensive-010.ivf", "vp80-00-comprehensive-011.ivf",
+  "vp80-00-comprehensive-012.ivf", "vp80-00-comprehensive-013.ivf",
+  "vp80-00-comprehensive-014.ivf", "vp80-00-comprehensive-015.ivf",
+  "vp80-00-comprehensive-016.ivf", "vp80-00-comprehensive-017.ivf",
+  "vp80-00-comprehensive-018.ivf", "vp80-01-intra-1400.ivf",
+  "vp80-01-intra-1411.ivf", "vp80-01-intra-1416.ivf",
+  "vp80-01-intra-1417.ivf", "vp80-02-inter-1402.ivf",
+  "vp80-02-inter-1412.ivf", "vp80-02-inter-1418.ivf",
+  "vp80-02-inter-1424.ivf", "vp80-03-segmentation-01.ivf",
+  "vp80-03-segmentation-02.ivf", "vp80-03-segmentation-03.ivf",
+  "vp80-03-segmentation-04.ivf", "vp80-03-segmentation-1401.ivf",
+  "vp80-03-segmentation-1403.ivf", "vp80-03-segmentation-1407.ivf",
+  "vp80-03-segmentation-1408.ivf", "vp80-03-segmentation-1409.ivf",
+  "vp80-03-segmentation-1410.ivf", "vp80-03-segmentation-1413.ivf",
+  "vp80-03-segmentation-1414.ivf", "vp80-03-segmentation-1415.ivf",
+  "vp80-03-segmentation-1425.ivf", "vp80-03-segmentation-1426.ivf",
+  "vp80-03-segmentation-1427.ivf", "vp80-03-segmentation-1432.ivf",
+  "vp80-03-segmentation-1435.ivf", "vp80-03-segmentation-1436.ivf",
+  "vp80-03-segmentation-1437.ivf", "vp80-03-segmentation-1441.ivf",
+  "vp80-03-segmentation-1442.ivf", "vp80-04-partitions-1404.ivf",
+  "vp80-04-partitions-1405.ivf", "vp80-04-partitions-1406.ivf",
+  "vp80-05-sharpness-1428.ivf", "vp80-05-sharpness-1429.ivf",
+  "vp80-05-sharpness-1430.ivf", "vp80-05-sharpness-1431.ivf",
+  "vp80-05-sharpness-1433.ivf", "vp80-05-sharpness-1434.ivf",
+  "vp80-05-sharpness-1438.ivf", "vp80-05-sharpness-1439.ivf",
+  "vp80-05-sharpness-1440.ivf", "vp80-05-sharpness-1443.ivf",
+  "vp80-06-smallsize.ivf"
+};
+#endif  // CONFIG_VP8_DECODER
+#if CONFIG_VP9_DECODER
+const char *kVP9TestVectors[kNumVp9TestVectors] = {
+  "vp90-2-00-quantizer-00.webm", "vp90-2-00-quantizer-01.webm",
+  "vp90-2-00-quantizer-02.webm", "vp90-2-00-quantizer-03.webm",
+  "vp90-2-00-quantizer-04.webm", "vp90-2-00-quantizer-05.webm",
+  "vp90-2-00-quantizer-06.webm", "vp90-2-00-quantizer-07.webm",
+  "vp90-2-00-quantizer-08.webm", "vp90-2-00-quantizer-09.webm",
+  "vp90-2-00-quantizer-10.webm", "vp90-2-00-quantizer-11.webm",
+  "vp90-2-00-quantizer-12.webm", "vp90-2-00-quantizer-13.webm",
+  "vp90-2-00-quantizer-14.webm", "vp90-2-00-quantizer-15.webm",
+  "vp90-2-00-quantizer-16.webm", "vp90-2-00-quantizer-17.webm",
+  "vp90-2-00-quantizer-18.webm", "vp90-2-00-quantizer-19.webm",
+  "vp90-2-00-quantizer-20.webm", "vp90-2-00-quantizer-21.webm",
+  "vp90-2-00-quantizer-22.webm", "vp90-2-00-quantizer-23.webm",
+  "vp90-2-00-quantizer-24.webm", "vp90-2-00-quantizer-25.webm",
+  "vp90-2-00-quantizer-26.webm", "vp90-2-00-quantizer-27.webm",
+  "vp90-2-00-quantizer-28.webm", "vp90-2-00-quantizer-29.webm",
+  "vp90-2-00-quantizer-30.webm", "vp90-2-00-quantizer-31.webm",
+  "vp90-2-00-quantizer-32.webm", "vp90-2-00-quantizer-33.webm",
+  "vp90-2-00-quantizer-34.webm", "vp90-2-00-quantizer-35.webm",
+  "vp90-2-00-quantizer-36.webm", "vp90-2-00-quantizer-37.webm",
+  "vp90-2-00-quantizer-38.webm", "vp90-2-00-quantizer-39.webm",
+  "vp90-2-00-quantizer-40.webm", "vp90-2-00-quantizer-41.webm",
+  "vp90-2-00-quantizer-42.webm", "vp90-2-00-quantizer-43.webm",
+  "vp90-2-00-quantizer-44.webm", "vp90-2-00-quantizer-45.webm",
+  "vp90-2-00-quantizer-46.webm", "vp90-2-00-quantizer-47.webm",
+  "vp90-2-00-quantizer-48.webm", "vp90-2-00-quantizer-49.webm",
+  "vp90-2-00-quantizer-50.webm", "vp90-2-00-quantizer-51.webm",
+  "vp90-2-00-quantizer-52.webm", "vp90-2-00-quantizer-53.webm",
+  "vp90-2-00-quantizer-54.webm", "vp90-2-00-quantizer-55.webm",
+  "vp90-2-00-quantizer-56.webm", "vp90-2-00-quantizer-57.webm",
+  "vp90-2-00-quantizer-58.webm", "vp90-2-00-quantizer-59.webm",
+  "vp90-2-00-quantizer-60.webm", "vp90-2-00-quantizer-61.webm",
+  "vp90-2-00-quantizer-62.webm", "vp90-2-00-quantizer-63.webm",
+  "vp90-2-01-sharpness-1.webm", "vp90-2-01-sharpness-2.webm",
+  "vp90-2-01-sharpness-3.webm", "vp90-2-01-sharpness-4.webm",
+  "vp90-2-01-sharpness-5.webm", "vp90-2-01-sharpness-6.webm",
+  "vp90-2-01-sharpness-7.webm", "vp90-2-02-size-08x08.webm",
+  "vp90-2-02-size-08x10.webm", "vp90-2-02-size-08x16.webm",
+  "vp90-2-02-size-08x18.webm", "vp90-2-02-size-08x32.webm",
+  "vp90-2-02-size-08x34.webm", "vp90-2-02-size-08x64.webm",
+  "vp90-2-02-size-08x66.webm", "vp90-2-02-size-10x08.webm",
+  "vp90-2-02-size-10x10.webm", "vp90-2-02-size-10x16.webm",
+  "vp90-2-02-size-10x18.webm", "vp90-2-02-size-10x32.webm",
+  "vp90-2-02-size-10x34.webm", "vp90-2-02-size-10x64.webm",
+  "vp90-2-02-size-10x66.webm", "vp90-2-02-size-16x08.webm",
+  "vp90-2-02-size-16x10.webm", "vp90-2-02-size-16x16.webm",
+  "vp90-2-02-size-16x18.webm", "vp90-2-02-size-16x32.webm",
+  "vp90-2-02-size-16x34.webm", "vp90-2-02-size-16x64.webm",
+  "vp90-2-02-size-16x66.webm", "vp90-2-02-size-18x08.webm",
+  "vp90-2-02-size-18x10.webm", "vp90-2-02-size-18x16.webm",
+  "vp90-2-02-size-18x18.webm", "vp90-2-02-size-18x32.webm",
+  "vp90-2-02-size-18x34.webm", "vp90-2-02-size-18x64.webm",
+  "vp90-2-02-size-18x66.webm", "vp90-2-02-size-32x08.webm",
+  "vp90-2-02-size-32x10.webm", "vp90-2-02-size-32x16.webm",
+  "vp90-2-02-size-32x18.webm", "vp90-2-02-size-32x32.webm",
+  "vp90-2-02-size-32x34.webm", "vp90-2-02-size-32x64.webm",
+  "vp90-2-02-size-32x66.webm", "vp90-2-02-size-34x08.webm",
+  "vp90-2-02-size-34x10.webm", "vp90-2-02-size-34x16.webm",
+  "vp90-2-02-size-34x18.webm", "vp90-2-02-size-34x32.webm",
+  "vp90-2-02-size-34x34.webm", "vp90-2-02-size-34x64.webm",
+  "vp90-2-02-size-34x66.webm", "vp90-2-02-size-64x08.webm",
+  "vp90-2-02-size-64x10.webm", "vp90-2-02-size-64x16.webm",
+  "vp90-2-02-size-64x18.webm", "vp90-2-02-size-64x32.webm",
+  "vp90-2-02-size-64x34.webm", "vp90-2-02-size-64x64.webm",
+  "vp90-2-02-size-64x66.webm", "vp90-2-02-size-66x08.webm",
+  "vp90-2-02-size-66x10.webm", "vp90-2-02-size-66x16.webm",
+  "vp90-2-02-size-66x18.webm", "vp90-2-02-size-66x32.webm",
+  "vp90-2-02-size-66x34.webm", "vp90-2-02-size-66x64.webm",
+  "vp90-2-02-size-66x66.webm", "vp90-2-03-size-196x196.webm",
+  "vp90-2-03-size-196x198.webm", "vp90-2-03-size-196x200.webm",
+  "vp90-2-03-size-196x202.webm", "vp90-2-03-size-196x208.webm",
+  "vp90-2-03-size-196x210.webm", "vp90-2-03-size-196x224.webm",
+  "vp90-2-03-size-196x226.webm", "vp90-2-03-size-198x196.webm",
+  "vp90-2-03-size-198x198.webm", "vp90-2-03-size-198x200.webm",
+  "vp90-2-03-size-198x202.webm", "vp90-2-03-size-198x208.webm",
+  "vp90-2-03-size-198x210.webm", "vp90-2-03-size-198x224.webm",
+  "vp90-2-03-size-198x226.webm", "vp90-2-03-size-200x196.webm",
+  "vp90-2-03-size-200x198.webm", "vp90-2-03-size-200x200.webm",
+  "vp90-2-03-size-200x202.webm", "vp90-2-03-size-200x208.webm",
+  "vp90-2-03-size-200x210.webm", "vp90-2-03-size-200x224.webm",
+  "vp90-2-03-size-200x226.webm", "vp90-2-03-size-202x196.webm",
+  "vp90-2-03-size-202x198.webm", "vp90-2-03-size-202x200.webm",
+  "vp90-2-03-size-202x202.webm", "vp90-2-03-size-202x208.webm",
+  "vp90-2-03-size-202x210.webm", "vp90-2-03-size-202x224.webm",
+  "vp90-2-03-size-202x226.webm", "vp90-2-03-size-208x196.webm",
+  "vp90-2-03-size-208x198.webm", "vp90-2-03-size-208x200.webm",
+  "vp90-2-03-size-208x202.webm", "vp90-2-03-size-208x208.webm",
+  "vp90-2-03-size-208x210.webm", "vp90-2-03-size-208x224.webm",
+  "vp90-2-03-size-208x226.webm", "vp90-2-03-size-210x196.webm",
+  "vp90-2-03-size-210x198.webm", "vp90-2-03-size-210x200.webm",
+  "vp90-2-03-size-210x202.webm", "vp90-2-03-size-210x208.webm",
+  "vp90-2-03-size-210x210.webm", "vp90-2-03-size-210x224.webm",
+  "vp90-2-03-size-210x226.webm", "vp90-2-03-size-224x196.webm",
+  "vp90-2-03-size-224x198.webm", "vp90-2-03-size-224x200.webm",
+  "vp90-2-03-size-224x202.webm", "vp90-2-03-size-224x208.webm",
+  "vp90-2-03-size-224x210.webm", "vp90-2-03-size-224x224.webm",
+  "vp90-2-03-size-224x226.webm", "vp90-2-03-size-226x196.webm",
+  "vp90-2-03-size-226x198.webm", "vp90-2-03-size-226x200.webm",
+  "vp90-2-03-size-226x202.webm", "vp90-2-03-size-226x208.webm",
+  "vp90-2-03-size-226x210.webm", "vp90-2-03-size-226x224.webm",
+  "vp90-2-03-size-226x226.webm", "vp90-2-03-deltaq.webm",
+  "vp90-2-05-resize.ivf",        "vp90-2-06-bilinear.webm",
+  "vp90-2-07-frame_parallel.webm",
+  "vp90-2-08-tile_1x2_frame_parallel.webm", "vp90-2-08-tile_1x2.webm",
+  "vp90-2-08-tile_1x4_frame_parallel.webm", "vp90-2-08-tile_1x4.webm",
+  "vp90-2-08-tile_1x8_frame_parallel.webm", "vp90-2-08-tile_1x8.webm",
+  "vp90-2-08-tile-4x4.webm", "vp90-2-08-tile-4x1.webm",
+  "vp90-2-09-subpixel-00.ivf",
+  "vp90-2-02-size-lf-1920x1080.webm",
+  "vp90-2-09-aq2.webm",
+  "vp90-2-09-lf_deltas.webm",
+#if CONFIG_NON420
+  "vp91-2-04-yv444.webm"
+#endif
+};
+#endif  // CONFIG_VP9_DECODER
+
+}  // namespace libvpx_test
diff --git a/test/test_vectors.h b/test/test_vectors.h
new file mode 100644
index 0000000..5f62e99
--- /dev/null
+++ b/test/test_vectors.h
@@ -0,0 +1,35 @@
+/*
+ *  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef TEST_TEST_VECTORS_H_
+#define TEST_TEST_VECTORS_H_
+
+#include "./vpx_config.h"
+
+namespace libvpx_test {
+
+#if CONFIG_VP8_DECODER
+const int kNumVp8TestVectors = 62;
+extern const char *kVP8TestVectors[kNumVp8TestVectors];
+#endif
+
+#if CONFIG_VP9_DECODER
+#if CONFIG_NON420
+const int kNumVp9TestVectors = 216;
+#else
+const int kNumVp9TestVectors = 215;
+#endif
+
+extern const char *kVP9TestVectors[kNumVp9TestVectors];
+#endif  // CONFIG_VP9_DECODER
+
+}  // namespace libvpx_test
+
+#endif  // TEST_TEST_VECTORS_H_
diff --git a/test/tile_independence_test.cc b/test/tile_independence_test.cc
index 403dbb6..863a366 100644
--- a/test/tile_independence_test.cc
+++ b/test/tile_independence_test.cc
@@ -1,11 +1,11 @@
 /*
- Copyright (c) 2012 The WebM project authors. All Rights Reserved.
-
- Use of this source code is governed by a BSD-style license
- that can be found in the LICENSE file in the root of the source
- tree. An additional intellectual property rights grant can be found
- in the file PATENTS.  All contributing project authors may
- be found in the AUTHORS file in the root of the source tree.
+ *  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
  */
 
 #include <cstdio>
diff --git a/test/vp8_fdct4x4_test.cc b/test/vp8_fdct4x4_test.cc
index c823436..25465c5 100644
--- a/test/vp8_fdct4x4_test.cc
+++ b/test/vp8_fdct4x4_test.cc
@@ -1,13 +1,12 @@
 /*
-*  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
-*
-*  Use of this source code is governed by a BSD-style license
-*  that can be found in the LICENSE file in the root of the source
-*  tree. An additional intellectual property rights grant can be found
-*  in the file PATENTS.  All contributing project authors may
-*  be found in the AUTHORS file in the root of the source tree.
-*/
-
+ *  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
 
 #include <math.h>
 #include <stddef.h>
@@ -16,7 +15,6 @@
 #include <string.h>
 #include <sys/types.h>
 
-
 extern "C" {
 #include "./vp8_rtcd.h"
 }
@@ -25,7 +23,6 @@
 #include "third_party/googletest/src/include/gtest/gtest.h"
 #include "vpx/vpx_integer.h"
 
-
 namespace {
 
 const int cospi8sqrt2minus1 = 20091;
diff --git a/test/vp9_boolcoder_test.cc b/test/vp9_boolcoder_test.cc
index 5edde90..1593c02 100644
--- a/test/vp9_boolcoder_test.cc
+++ b/test/vp9_boolcoder_test.cc
@@ -15,8 +15,8 @@
 #include "third_party/googletest/src/include/gtest/gtest.h"
 
 extern "C" {
-#include "vp9/encoder/vp9_boolhuff.h"
-#include "vp9/decoder/vp9_dboolhuff.h"
+#include "vp9/decoder/vp9_reader.h"
+#include "vp9/encoder/vp9_writer.h"
 }
 
 #include "test/acm_random.h"
diff --git a/test/vp9_lossless_test.cc b/test/vp9_lossless_test.cc
index e8c32b4..03b89f8 100644
--- a/test/vp9_lossless_test.cc
+++ b/test/vp9_lossless_test.cc
@@ -1,12 +1,12 @@
 /*
-  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
-
-  Use of this source code is governed by a BSD-style license
-  that can be found in the LICENSE file in the root of the source
-  tree. An additional intellectual property rights grant can be found
-  in the file PATENTS.  All contributing project authors may
-  be found in the AUTHORS file in the root of the source tree.
-*/
+ *  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
 
 #include "third_party/googletest/src/include/gtest/gtest.h"
 #include "test/codec_factory.h"
diff --git a/test/webm_video_source.h b/test/webm_video_source.h
index 9fc8545..53b0ba2 100644
--- a/test/webm_video_source.h
+++ b/test/webm_video_source.h
@@ -90,8 +90,12 @@
   virtual ~WebMVideoSource() {
     if (input_file_)
       fclose(input_file_);
-    if (nestegg_ctx_)
+    if (nestegg_ctx_ != NULL) {
+      if (pkt_ != NULL) {
+        nestegg_free_packet(pkt_);
+      }
       nestegg_destroy(nestegg_ctx_);
+    }
   }
 
   virtual void Init() {
@@ -136,8 +140,10 @@
 
       do {
         /* End of this packet, get another. */
-        if (pkt_)
+        if (pkt_ != NULL) {
           nestegg_free_packet(pkt_);
+          pkt_ = NULL;
+        }
 
         int again = nestegg_read_packet(nestegg_ctx_, &pkt_);
         ASSERT_GE(again, 0) << "nestegg_read_packet failed";
diff --git a/vp8/common/alloccommon.h b/vp8/common/alloccommon.h
index ea93c25..38f89a0 100644
--- a/vp8/common/alloccommon.h
+++ b/vp8/common/alloccommon.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef __INC_ALLOCCOMMON_H
-#define __INC_ALLOCCOMMON_H
+#ifndef VP8_COMMON_ALLOCCOMMON_H_
+#define VP8_COMMON_ALLOCCOMMON_H_
 
 #include "onyxc_int.h"
 
@@ -20,4 +20,4 @@
 int vp8_alloc_frame_buffers(VP8_COMMON *oci, int width, int height);
 void vp8_setup_version(VP8_COMMON *oci);
 
-#endif
+#endif  // VP8_COMMON_ALLOCCOMMON_H_
diff --git a/vp8/common/arm/bilinearfilter_arm.h b/vp8/common/arm/bilinearfilter_arm.h
index b7155d3..dd3ff14 100644
--- a/vp8/common/arm/bilinearfilter_arm.h
+++ b/vp8/common/arm/bilinearfilter_arm.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef BILINEARFILTER_ARM_H
-#define BILINEARFILTER_ARM_H
+#ifndef VP8_COMMON_ARM_BILINEARFILTER_ARM_H_
+#define VP8_COMMON_ARM_BILINEARFILTER_ARM_H_
 
 extern void vp8_filter_block2d_bil_first_pass_armv6
 (
@@ -32,4 +32,4 @@
     const short         *vp8_filter
 );
 
-#endif /* BILINEARFILTER_ARM_H */
+#endif  // VP8_COMMON_ARM_BILINEARFILTER_ARM_H_
diff --git a/vp8/common/blockd.h b/vp8/common/blockd.h
index f7ff577..c3caee1 100644
--- a/vp8/common/blockd.h
+++ b/vp8/common/blockd.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef __INC_BLOCKD_H
-#define __INC_BLOCKD_H
+#ifndef VP8_COMMON_BLOCKD_H_
+#define VP8_COMMON_BLOCKD_H_
 
 void vpx_log(const char *format, ...);
 
@@ -297,4 +297,4 @@
 extern void vp8_build_block_doffsets(MACROBLOCKD *x);
 extern void vp8_setup_block_dptrs(MACROBLOCKD *x);
 
-#endif  /* __INC_BLOCKD_H */
+#endif  // VP8_COMMON_BLOCKD_H_
diff --git a/vp8/common/coefupdateprobs.h b/vp8/common/coefupdateprobs.h
index 9e194dc..90d290d 100644
--- a/vp8/common/coefupdateprobs.h
+++ b/vp8/common/coefupdateprobs.h
@@ -8,6 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#ifndef VP8_COMMON_COEFUPDATEPROBS_H_
+#define VP8_COMMON_COEFUPDATEPROBS_H_
 
 /* Update probabilities for the nodes in the token entropy tree.
    Generated file included by entropy.c */
@@ -183,3 +185,5 @@
         },
     },
 };
+
+#endif  // VP8_COMMON_COEFUPDATEPROBS_H_
diff --git a/vp8/common/common.h b/vp8/common/common.h
index 2cc1c54..9671da0 100644
--- a/vp8/common/common.h
+++ b/vp8/common/common.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef common_h
-#define common_h 1
+#ifndef VP8_COMMON_COMMON_H_
+#define VP8_COMMON_COMMON_H_
 
 #include <assert.h>
 
@@ -37,4 +37,4 @@
 #define vp8_zero_array( Dest, N)  vpx_memset( Dest, 0, N * sizeof( *Dest));
 
 
-#endif  /* common_h */
+#endif  // VP8_COMMON_COMMON_H_
diff --git a/vp8/common/default_coef_probs.h b/vp8/common/default_coef_probs.h
index 0d19563..8368545 100644
--- a/vp8/common/default_coef_probs.h
+++ b/vp8/common/default_coef_probs.h
@@ -8,6 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
 */
 
+#ifndef VP8_COMMON_DEFAULT_COEF_PROBS_H_
+#define VP8_COMMON_DEFAULT_COEF_PROBS_H_
 
 /*Generated file, included by entropy.c*/
 
@@ -186,3 +188,5 @@
         }
     }
 };
+
+#endif  // VP8_COMMON_DEFAULT_COEF_PROBS_H_
diff --git a/vp8/common/entropy.h b/vp8/common/entropy.h
index 5389bc1..175fa9f 100644
--- a/vp8/common/entropy.h
+++ b/vp8/common/entropy.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef __INC_ENTROPY_H
-#define __INC_ENTROPY_H
+#ifndef VP8_COMMON_ENTROPY_H_
+#define VP8_COMMON_ENTROPY_H_
 
 #include "treecoder.h"
 #include "blockd.h"
@@ -98,4 +98,4 @@
 extern const int vp8_mb_feature_data_bits[MB_LVL_MAX];
 
 void vp8_coef_tree_initialize(void);
-#endif
+#endif  // VP8_COMMON_ENTROPY_H_
diff --git a/vp8/common/entropymode.h b/vp8/common/entropymode.h
index 1df0f64..18af8c0 100644
--- a/vp8/common/entropymode.h
+++ b/vp8/common/entropymode.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef __INC_ENTROPYMODE_H
-#define __INC_ENTROPYMODE_H
+#ifndef VP8_COMMON_ENTROPYMODE_H_
+#define VP8_COMMON_ENTROPYMODE_H_
 
 #include "onyxc_int.h"
 #include "treecoder.h"
@@ -77,4 +77,4 @@
 void vp8_default_bmode_probs(vp8_prob dest [VP8_BINTRAMODES-1]);
 void vp8_kf_default_bmode_probs(vp8_prob dest [VP8_BINTRAMODES] [VP8_BINTRAMODES] [VP8_BINTRAMODES-1]);
 
-#endif
+#endif  // VP8_COMMON_ENTROPYMODE_H_
diff --git a/vp8/common/entropymv.h b/vp8/common/entropymv.h
index 2db1e38..7d16b98 100644
--- a/vp8/common/entropymv.h
+++ b/vp8/common/entropymv.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef __INC_ENTROPYMV_H
-#define __INC_ENTROPYMV_H
+#ifndef VP8_COMMON_ENTROPYMV_H_
+#define VP8_COMMON_ENTROPYMV_H_
 
 #include "treecoder.h"
 
@@ -41,4 +41,4 @@
 
 extern const MV_CONTEXT vp8_mv_update_probs[2], vp8_default_mv_context[2];
 
-#endif
+#endif  // VP8_COMMON_ENTROPYMV_H_
diff --git a/vp8/common/extend.h b/vp8/common/extend.h
index 74a0b17..b7e7040 100644
--- a/vp8/common/extend.h
+++ b/vp8/common/extend.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef __INC_EXTEND_H
-#define __INC_EXTEND_H
+#ifndef VP8_COMMON_EXTEND_H_
+#define VP8_COMMON_EXTEND_H_
 
 #include "vpx_scale/yv12config.h"
 
@@ -22,4 +22,4 @@
                                          int srcy, int srcx,
                                          int srch, int srcw);
 
-#endif
+#endif  // VP8_COMMON_EXTEND_H_
diff --git a/vp8/common/filter.h b/vp8/common/filter.h
index ccda7c8..c2048ee 100644
--- a/vp8/common/filter.h
+++ b/vp8/common/filter.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef FILTER_H
-#define FILTER_H
+#ifndef VP8_COMMON_FILTER_H_
+#define VP8_COMMON_FILTER_H_
 
 #include "vpx_ports/mem.h"
 
@@ -21,4 +21,4 @@
 extern DECLARE_ALIGNED(16, const short, vp8_bilinear_filters[8][2]);
 extern DECLARE_ALIGNED(16, const short, vp8_sub_pel_filters[8][6]);
 
-#endif
+#endif  // VP8_COMMON_FILTER_H_
diff --git a/vp8/common/findnearmv.h b/vp8/common/findnearmv.h
index c60e463..1525db2 100644
--- a/vp8/common/findnearmv.h
+++ b/vp8/common/findnearmv.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef __INC_FINDNEARMV_H
-#define __INC_FINDNEARMV_H
+#ifndef VP8_COMMON_FINDNEARMV_H_
+#define VP8_COMMON_FINDNEARMV_H_
 
 #include "mv.h"
 #include "blockd.h"
@@ -179,4 +179,4 @@
     return (cur_mb->bmi + b - 4)->as_mode;
 }
 
-#endif
+#endif  // VP8_COMMON_FINDNEARMV_H_
diff --git a/vp8/common/header.h b/vp8/common/header.h
index 3e98eeb..61a8f49 100644
--- a/vp8/common/header.h
+++ b/vp8/common/header.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef __INC_HEADER_H
-#define __INC_HEADER_H
+#ifndef VP8_COMMON_HEADER_H_
+#define VP8_COMMON_HEADER_H_
 
 /* 24 bits total */
 typedef struct
@@ -40,4 +40,4 @@
 #endif
 
 
-#endif
+#endif  // VP8_COMMON_HEADER_H_
diff --git a/vp8/common/invtrans.h b/vp8/common/invtrans.h
index 9262640..0186e6b 100644
--- a/vp8/common/invtrans.h
+++ b/vp8/common/invtrans.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef __INC_INVTRANS_H
-#define __INC_INVTRANS_H
+#ifndef VP8_COMMON_INVTRANS_H_
+#define VP8_COMMON_INVTRANS_H_
 
 #include "vpx_config.h"
 #include "vp8_rtcd.h"
@@ -59,4 +59,4 @@
                      xd->dst.y_buffer,
                      xd->dst.y_stride, xd->eobs);
 }
-#endif
+#endif  // VP8_COMMON_INVTRANS_H_
diff --git a/vp8/common/loopfilter.h b/vp8/common/loopfilter.h
index 1e47f34..51825ef 100644
--- a/vp8/common/loopfilter.h
+++ b/vp8/common/loopfilter.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef loopfilter_h
-#define loopfilter_h
+#ifndef VP8_COMMON_LOOPFILTER_H_
+#define VP8_COMMON_LOOPFILTER_H_
 
 #include "vpx_ports/mem.h"
 #include "vpx_config.h"
@@ -102,4 +102,4 @@
                                 int mb_row, int post_ystride, int post_uvstride,
                                 unsigned char *y_ptr, unsigned char *u_ptr,
                                 unsigned char *v_ptr);
-#endif
+#endif  // VP8_COMMON_LOOPFILTER_H_
diff --git a/vp8/common/modecont.h b/vp8/common/modecont.h
index 24db882..875bc27 100644
--- a/vp8/common/modecont.h
+++ b/vp8/common/modecont.h
@@ -9,9 +9,9 @@
  */
 
 
-#ifndef __INC_MODECONT_H
-#define __INC_MODECONT_H
+#ifndef VP8_COMMON_MODECONT_H_
+#define VP8_COMMON_MODECONT_H_
 
 extern const int vp8_mode_contexts[6][4];
 
-#endif
+#endif  // VP8_COMMON_MODECONT_H_
diff --git a/vp8/common/mv.h b/vp8/common/mv.h
index b3f919d..1e4b206 100644
--- a/vp8/common/mv.h
+++ b/vp8/common/mv.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef __INC_MV_H
-#define __INC_MV_H
+#ifndef VP8_COMMON_MV_H_
+#define VP8_COMMON_MV_H_
 #include "vpx/vpx_integer.h"
 
 typedef struct
@@ -25,4 +25,4 @@
     MV        as_mv;
 } int_mv;        /* facilitates faster equality tests and copies */
 
-#endif
+#endif  // VP8_COMMON_MV_H_
diff --git a/vp8/common/onyx.h b/vp8/common/onyx.h
index 30c4cbb..209a25d 100644
--- a/vp8/common/onyx.h
+++ b/vp8/common/onyx.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef __INC_VP8_H
-#define __INC_VP8_H
+#ifndef VP8_COMMON_ONYX_H_
+#define VP8_COMMON_ONYX_H_
 
 #ifdef __cplusplus
 extern "C"
@@ -267,4 +267,4 @@
 }
 #endif
 
-#endif
+#endif  // VP8_COMMON_ONYX_H_
diff --git a/vp8/common/onyxc_int.h b/vp8/common/onyxc_int.h
index e9bb7af..92eb7f9 100644
--- a/vp8/common/onyxc_int.h
+++ b/vp8/common/onyxc_int.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef __INC_VP8C_INT_H
-#define __INC_VP8C_INT_H
+#ifndef VP8_COMMON_ONYXC_INT_H_
+#define VP8_COMMON_ONYXC_INT_H_
 
 #include "vpx_config.h"
 #include "vp8_rtcd.h"
@@ -174,4 +174,4 @@
     int cpu_caps;
 } VP8_COMMON;
 
-#endif
+#endif  // VP8_COMMON_ONYXC_INT_H_
diff --git a/vp8/common/onyxd.h b/vp8/common/onyxd.h
index 97c81c1..e37b29f 100644
--- a/vp8/common/onyxd.h
+++ b/vp8/common/onyxd.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef __INC_VP8D_H
-#define __INC_VP8D_H
+#ifndef VP8_COMMON_ONYXD_H_
+#define VP8_COMMON_ONYXD_H_
 
 
 /* Create/destroy static data structures. */
@@ -60,4 +60,4 @@
 #endif
 
 
-#endif
+#endif  // VP8_COMMON_ONYXD_H_
diff --git a/vp8/common/postproc.h b/vp8/common/postproc.h
index 495a2c9..10baf6c 100644
--- a/vp8/common/postproc.h
+++ b/vp8/common/postproc.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef POSTPROC_H
-#define POSTPROC_H
+#ifndef VP8_COMMON_POSTPROC_H_
+#define VP8_COMMON_POSTPROC_H_
 
 #include "vpx_ports/mem.h"
 struct postproc_state
@@ -47,4 +47,4 @@
 #define MFQE_PRECISION 4
 
 void vp8_multiframe_quality_enhance(struct VP8Common *cm);
-#endif
+#endif  // VP8_COMMON_POSTPROC_H_
diff --git a/vp8/common/ppflags.h b/vp8/common/ppflags.h
index 665e21f..1fb37e1 100644
--- a/vp8/common/ppflags.h
+++ b/vp8/common/ppflags.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef __INC_PPFLAGS_H
-#define __INC_PPFLAGS_H
+#ifndef VP8_COMMON_PPFLAGS_H_
+#define VP8_COMMON_PPFLAGS_H_
 enum
 {
     VP8D_NOFILTERING            = 0,
@@ -38,4 +38,4 @@
     int display_mv_flag;
 } vp8_ppflags_t;
 
-#endif
+#endif  // VP8_COMMON_PPFLAGS_H_
diff --git a/vp8/common/pragmas.h b/vp8/common/pragmas.h
index 99fee5a..be10452 100644
--- a/vp8/common/pragmas.h
+++ b/vp8/common/pragmas.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-
-
+#ifndef VP8_COMMON_PRAGMAS_H_
+#define VP8_COMMON_PRAGMAS_H_
 
 #ifdef __INTEL_COMPILER
 #pragma warning(disable:997 1011 170)
@@ -17,3 +17,5 @@
 #ifdef _MSC_VER
 #pragma warning(disable:4799)
 #endif
+
+#endif  // VP8_COMMON_PRAGMAS_H_
diff --git a/vp8/common/quant_common.h b/vp8/common/quant_common.h
index cb64d8e..4c7457f 100644
--- a/vp8/common/quant_common.h
+++ b/vp8/common/quant_common.h
@@ -8,6 +8,9 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#ifndef VP8_COMMON_QUANT_COMMON_H_
+#define VP8_COMMON_QUANT_COMMON_H_
+
 
 #include "string.h"
 #include "blockd.h"
@@ -19,3 +22,5 @@
 extern int vp8_ac2quant(int QIndex, int Delta);
 extern int vp8_dc_uv_quant(int QIndex, int Delta);
 extern int vp8_ac_uv_quant(int QIndex, int Delta);
+
+#endif  // VP8_COMMON_QUANT_COMMON_H_
diff --git a/vp8/common/reconinter.h b/vp8/common/reconinter.h
index 233c02e..50ebedc 100644
--- a/vp8/common/reconinter.h
+++ b/vp8/common/reconinter.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef __INC_RECONINTER_H
-#define __INC_RECONINTER_H
+#ifndef VP8_COMMON_RECONINTER_H_
+#define VP8_COMMON_RECONINTER_H_
 
 extern void vp8_build_inter_predictors_mb(MACROBLOCKD *x);
 extern void vp8_build_inter16x16_predictors_mb(MACROBLOCKD *x,
@@ -32,4 +32,4 @@
 extern void vp8_build_inter16x16_predictors_mbuv(MACROBLOCKD *x);
 extern void vp8_build_inter4x4_predictors_mbuv(MACROBLOCKD *x);
 
-#endif
+#endif  // VP8_COMMON_RECONINTER_H_
diff --git a/vp8/common/reconintra4x4.h b/vp8/common/reconintra4x4.h
index d2b0d43..cbb06ce 100644
--- a/vp8/common/reconintra4x4.h
+++ b/vp8/common/reconintra4x4.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef __INC_RECONINTRA4x4_H
-#define __INC_RECONINTRA4x4_H
+#ifndef VP8_COMMON_RECONINTRA4X4_H_
+#define VP8_COMMON_RECONINTRA4X4_H_
 #include "vp8/common/blockd.h"
 
 static void intra_prediction_down_copy(MACROBLOCKD *xd,
@@ -29,4 +29,4 @@
     *dst_ptr2 = *src_ptr;
 }
 
-#endif
+#endif  // VP8_COMMON_RECONINTRA4X4_H_
diff --git a/vp8/common/rtcd_defs.sh b/vp8/common/rtcd_defs.sh
index 9ebf389..28e6754 100644
--- a/vp8/common/rtcd_defs.sh
+++ b/vp8/common/rtcd_defs.sh
@@ -535,7 +535,7 @@
 #
 if [ "$CONFIG_TEMPORAL_DENOISING" = "yes" ]; then
     prototype int vp8_denoiser_filter "struct yv12_buffer_config* mc_running_avg, struct yv12_buffer_config* running_avg, struct macroblock* signal, unsigned int motion_magnitude2, int y_offset, int uv_offset"
-    specialize vp8_denoiser_filter sse2
+    specialize vp8_denoiser_filter sse2 neon
 fi
 
 # End of encoder only functions
diff --git a/vp8/common/setupintrarecon.h b/vp8/common/setupintrarecon.h
index 8b6c50b..3db507b 100644
--- a/vp8/common/setupintrarecon.h
+++ b/vp8/common/setupintrarecon.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef SETUPINTRARECON_H
-#define SETUPINTRARECON_H
+#ifndef VP8_COMMON_SETUPINTRARECON_H_
+#define VP8_COMMON_SETUPINTRARECON_H_
 
 #include "vpx_scale/yv12config.h"
 extern void vp8_setup_intra_recon(YV12_BUFFER_CONFIG *ybf);
@@ -34,4 +34,4 @@
         v_buffer[uv_stride *i] = (unsigned char) 129;
 }
 
-#endif
+#endif  // VP8_COMMON_SETUPINTRARECON_H_
diff --git a/vp8/common/swapyv12buffer.h b/vp8/common/swapyv12buffer.h
index a6473ed..ea8977b 100644
--- a/vp8/common/swapyv12buffer.h
+++ b/vp8/common/swapyv12buffer.h
@@ -9,11 +9,11 @@
  */
 
 
-#ifndef SWAPYV12_BUFFER_H
-#define SWAPYV12_BUFFER_H
+#ifndef VP8_COMMON_SWAPYV12BUFFER_H_
+#define VP8_COMMON_SWAPYV12BUFFER_H_
 
 #include "vpx_scale/yv12config.h"
 
 void vp8_swap_yv12_buffer(YV12_BUFFER_CONFIG *new_frame, YV12_BUFFER_CONFIG *last_frame);
 
-#endif
+#endif  // VP8_COMMON_SWAPYV12BUFFER_H_
diff --git a/vp8/common/systemdependent.h b/vp8/common/systemdependent.h
index e6b0456..966cc5d 100644
--- a/vp8/common/systemdependent.h
+++ b/vp8/common/systemdependent.h
@@ -8,8 +8,12 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#ifndef VP8_COMMON_SYSTEMDEPENDENT_H_
+#define VP8_COMMON_SYSTEMDEPENDENT_H_
 
 #include "vpx_config.h"
 
 struct VP8Common;
 void vp8_machine_specific_config(struct VP8Common *);
+
+#endif  // VP8_COMMON_SYSTEMDEPENDENT_H_
diff --git a/vp8/common/threading.h b/vp8/common/threading.h
index ed9e3e6..8cf6d26 100644
--- a/vp8/common/threading.h
+++ b/vp8/common/threading.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef _PTHREAD_EMULATION
-#define _PTHREAD_EMULATION
+#ifndef VP8_COMMON_THREADING_H_
+#define VP8_COMMON_THREADING_H_
 
 #if CONFIG_OS_SUPPORT && CONFIG_MULTITHREAD
 
@@ -183,4 +183,4 @@
 
 #endif /* CONFIG_OS_SUPPORT && CONFIG_MULTITHREAD */
 
-#endif
+#endif  // VP8_COMMON_THREADING_H_
diff --git a/vp8/common/treecoder.h b/vp8/common/treecoder.h
index ebf51c5..edb4b57 100644
--- a/vp8/common/treecoder.h
+++ b/vp8/common/treecoder.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef __INC_TREECODER_H
-#define __INC_TREECODER_H
+#ifndef VP8_COMMON_TREECODER_H_
+#define VP8_COMMON_TREECODER_H_
 
 typedef unsigned char vp8bc_index_t; /* probability index */
 
@@ -87,4 +87,4 @@
 );
 
 
-#endif
+#endif  // VP8_COMMON_TREECODER_H_
diff --git a/vp8/common/variance.h b/vp8/common/variance.h
index 01193b8..12a03d0 100644
--- a/vp8/common/variance.h
+++ b/vp8/common/variance.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef VARIANCE_H
-#define VARIANCE_H
+#ifndef VP8_COMMON_VARIANCE_H_
+#define VP8_COMMON_VARIANCE_H_
 
 #include "vpx_config.h"
 
@@ -112,4 +112,4 @@
 #endif
 } vp8_variance_fn_ptr_t;
 
-#endif
+#endif  // VP8_COMMON_VARIANCE_H_
diff --git a/vp8/common/vp8_entropymodedata.h b/vp8/common/vp8_entropymodedata.h
index 13e9a92..9881148 100644
--- a/vp8/common/vp8_entropymodedata.h
+++ b/vp8/common/vp8_entropymodedata.h
@@ -8,6 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
 */
 
+#ifndef VP8_COMMON_VP8_ENTROPYMODEDATA_H_
+#define VP8_COMMON_VP8_ENTROPYMODEDATA_H_
 
 /*Generated file, included by entropymode.c*/
 
@@ -240,3 +242,5 @@
         { 112,  19,  12,  61, 195, 128,  48,   4,  24 }
     }
 };
+
+#endif  // VP8_COMMON_VP8_ENTROPYMODEDATA_H_
diff --git a/vp8/common/x86/filter_x86.h b/vp8/common/x86/filter_x86.h
index cfadaee..0d537d9 100644
--- a/vp8/common/x86/filter_x86.h
+++ b/vp8/common/x86/filter_x86.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef FILTER_X86_H
-#define FILTER_X86_H
+#ifndef VP8_COMMON_X86_FILTER_X86_H_
+#define VP8_COMMON_X86_FILTER_X86_H_
 
 #include "vpx_ports/mem.h"
 
@@ -22,4 +22,4 @@
 /* duplicated 8x */
 extern DECLARE_ALIGNED(16, const short, vp8_bilinear_filters_x86_8[8][16]);
 
-#endif /* FILTER_X86_H */
+#endif  // VP8_COMMON_X86_FILTER_X86_H_
diff --git a/vp8/decoder/dboolhuff.h b/vp8/decoder/dboolhuff.h
index 4c0ca1c..82de6b8 100644
--- a/vp8/decoder/dboolhuff.h
+++ b/vp8/decoder/dboolhuff.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef DBOOLHUFF_H_
-#define DBOOLHUFF_H_
+#ifndef VP8_DECODER_DBOOLHUFF_H_
+#define VP8_DECODER_DBOOLHUFF_H_
 
 #include <stddef.h>
 #include <limits.h>
@@ -135,4 +135,4 @@
     return 0;
 }
 
-#endif  // DBOOLHUFF_H_
+#endif  // VP8_DECODER_DBOOLHUFF_H_
diff --git a/vp8/decoder/decodemv.h b/vp8/decoder/decodemv.h
index 05a33d2..b5d750c 100644
--- a/vp8/decoder/decodemv.h
+++ b/vp8/decoder/decodemv.h
@@ -8,11 +8,11 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef DECODEMV_H_
-#define DECODEMV_H_
+#ifndef VP8_DECODER_DECODEMV_H_
+#define VP8_DECODER_DECODEMV_H_
 
 #include "onyxd_int.h"
 
 void vp8_decode_mode_mvs(VP8D_COMP *);
 
-#endif  // DECODEMV_H_
+#endif  // VP8_DECODER_DECODEMV_H_
diff --git a/vp8/decoder/decoderthreading.h b/vp8/decoder/decoderthreading.h
index bc716e4..3a8277f 100644
--- a/vp8/decoder/decoderthreading.h
+++ b/vp8/decoder/decoderthreading.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef DECODERTHREADING_H_
-#define DECODERTHREADING_H_
+#ifndef VP8_DECODER_DECODERTHREADING_H_
+#define VP8_DECODER_DECODERTHREADING_H_
 
 #if CONFIG_MULTITHREAD
 void vp8mt_decode_mb_rows(VP8D_COMP *pbi, MACROBLOCKD *xd);
@@ -19,4 +19,4 @@
 void vp8mt_de_alloc_temp_buffers(VP8D_COMP *pbi, int mb_rows);
 #endif
 
-#endif  // DECODERTHREADING_H_
+#endif  // VP8_DECODER_DECODERTHREADING_H_
diff --git a/vp8/decoder/detokenize.h b/vp8/decoder/detokenize.h
index f2130b3..f134df8 100644
--- a/vp8/decoder/detokenize.h
+++ b/vp8/decoder/detokenize.h
@@ -8,12 +8,12 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef DETOKENIZE_H_
-#define DETOKENIZE_H_
+#ifndef VP8_DECODER_DETOKENIZE_H_
+#define VP8_DECODER_DETOKENIZE_H_
 
 #include "onyxd_int.h"
 
 void vp8_reset_mb_tokens_context(MACROBLOCKD *x);
 int vp8_decode_mb_tokens(VP8D_COMP *, MACROBLOCKD *);
 
-#endif  // DETOKENIZE_H
+#endif  // VP8_DECODER_DETOKENIZE_H_
diff --git a/vp8/decoder/ec_types.h b/vp8/decoder/ec_types.h
index b24bfd9..0a3123a 100644
--- a/vp8/decoder/ec_types.h
+++ b/vp8/decoder/ec_types.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef VP8_DEC_EC_TYPES_H
-#define VP8_DEC_EC_TYPES_H
+#ifndef VP8_DECODER_EC_TYPES_H_
+#define VP8_DECODER_EC_TYPES_H_
 
 #define MAX_OVERLAPS 16
 
@@ -47,4 +47,4 @@
     MV_REFERENCE_FRAME ref_frame;
 } EC_BLOCK;
 
-#endif  // VP8_DEC_EC_TYPES_H
+#endif  // VP8_DECODER_EC_TYPES_H_
diff --git a/vp8/decoder/error_concealment.h b/vp8/decoder/error_concealment.h
index fb96b36..10bf870 100644
--- a/vp8/decoder/error_concealment.h
+++ b/vp8/decoder/error_concealment.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef ERROR_CONCEALMENT_H_
-#define ERROR_CONCEALMENT_H_
+#ifndef VP8_DECODER_ERROR_CONCEALMENT_H_
+#define VP8_DECODER_ERROR_CONCEALMENT_H_
 
 #include "onyxd_int.h"
 #include "ec_types.h"
@@ -38,4 +38,4 @@
  */
 void vp8_conceal_corrupt_mb(MACROBLOCKD *xd);
 
-#endif  // ERROR_CONCEALMENT_H_
+#endif  // VP8_DECODER_ERROR_CONCEALMENT_H_
diff --git a/vp8/decoder/onyxd_int.h b/vp8/decoder/onyxd_int.h
index 54a98f7..3728152 100644
--- a/vp8/decoder/onyxd_int.h
+++ b/vp8/decoder/onyxd_int.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef ONYXD_INT_H_
-#define ONYXD_INT_H_
+#ifndef VP8_DECODER_ONYXD_INT_H_
+#define VP8_DECODER_ONYXD_INT_H_
 
 #include "vpx_config.h"
 #include "vp8/common/onyxd.h"
@@ -148,4 +148,4 @@
     } while(0)
 #endif
 
-#endif  // ONYXD_INT_H_
+#endif  // VP8_DECODER_ONYXD_INT_H_
diff --git a/vp8/decoder/treereader.h b/vp8/decoder/treereader.h
index 9393bb4..1d3f672 100644
--- a/vp8/decoder/treereader.h
+++ b/vp8/decoder/treereader.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef TREEREADER_H_
-#define TREEREADER_H_
+#ifndef VP8_DECODER_TREEREADER_H_
+#define VP8_DECODER_TREEREADER_H_
 
 #include "vp8/common/treecoder.h"
 #include "dboolhuff.h"
@@ -37,4 +37,4 @@
     return -i;
 }
 
-#endif  // TREEREADER_H_
+#endif  // VP8_DECODER_TREEREADER_H_
diff --git a/vp8/encoder/arm/neon/denoising_neon.c b/vp8/encoder/arm/neon/denoising_neon.c
new file mode 100644
index 0000000..d517dfa
--- /dev/null
+++ b/vp8/encoder/arm/neon/denoising_neon.c
@@ -0,0 +1,165 @@
+/*
+ *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <arm_neon.h>
+
+#include "vp8/encoder/denoising.h"
+#include "vpx_mem/vpx_mem.h"
+#include "./vp8_rtcd.h"
+
+/*
+ * The filter function was modified to reduce the computational complexity.
+ *
+ * Step 1:
+ *  Instead of applying tap coefficients for each pixel, we calculated the
+ *  pixel adjustments vs. pixel diff value ahead of time.
+ *     adjustment = filtered_value - current_raw
+ *                = (filter_coefficient * diff + 128) >> 8
+ *  where
+ *     filter_coefficient = (255 << 8) / (256 + ((abs_diff * 330) >> 3));
+ *     filter_coefficient += filter_coefficient /
+ *                           (3 + motion_magnitude_adjustment);
+ *     filter_coefficient is clamped to 0 ~ 255.
+ *
+ * Step 2:
+ *  The adjustment vs. diff curve becomes flat very quick when diff increases.
+ *  This allowed us to use only several levels to approximate the curve without
+ *  changing the filtering algorithm too much.
+ *  The adjustments were further corrected by checking the motion magnitude.
+ *  The levels used are:
+ *      diff          level       adjustment w/o       adjustment w/
+ *                               motion correction    motion correction
+ *      [-255, -16]     3              -6                   -7
+ *      [-15, -8]       2              -4                   -5
+ *      [-7, -4]        1              -3                   -4
+ *      [-3, 3]         0              diff                 diff
+ *      [4, 7]          1               3                    4
+ *      [8, 15]         2               4                    5
+ *      [16, 255]       3               6                    7
+ */
+
+int vp8_denoiser_filter_neon(YV12_BUFFER_CONFIG *mc_running_avg,
+                             YV12_BUFFER_CONFIG *running_avg,
+                             MACROBLOCK *signal, unsigned int motion_magnitude,
+                             int y_offset, int uv_offset) {
+    /* If motion_magnitude is small, making the denoiser more aggressive by
+     * increasing the adjustment for each level, level1 adjustment is
+     * increased, the deltas stay the same.
+     */
+    const uint8x16_t v_level1_adjustment = vdupq_n_u8(
+        (motion_magnitude <= MOTION_MAGNITUDE_THRESHOLD) ? 4 : 3);
+    const uint8x16_t v_delta_level_1_and_2 = vdupq_n_u8(1);
+    const uint8x16_t v_delta_level_2_and_3 = vdupq_n_u8(2);
+    const uint8x16_t v_level1_threshold = vdupq_n_u8(4);
+    const uint8x16_t v_level2_threshold = vdupq_n_u8(8);
+    const uint8x16_t v_level3_threshold = vdupq_n_u8(16);
+
+    /* Local variables for array pointers and strides. */
+    unsigned char *sig = signal->thismb;
+    int            sig_stride = 16;
+    unsigned char *mc_running_avg_y = mc_running_avg->y_buffer + y_offset;
+    int            mc_running_avg_y_stride = mc_running_avg->y_stride;
+    unsigned char *running_avg_y = running_avg->y_buffer + y_offset;
+    int            running_avg_y_stride = running_avg->y_stride;
+
+    /* Go over lines. */
+    int i;
+    int sum_diff = 0;
+    for (i = 0; i < 16; ++i) {
+        int8x16_t v_sum_diff = vdupq_n_s8(0);
+        uint8x16_t v_running_avg_y;
+
+        /* Load inputs. */
+        const uint8x16_t v_sig = vld1q_u8(sig);
+        const uint8x16_t v_mc_running_avg_y = vld1q_u8(mc_running_avg_y);
+
+        /* Calculate absolute difference and sign masks. */
+        const uint8x16_t v_abs_diff      = vabdq_u8(v_sig, v_mc_running_avg_y);
+        const uint8x16_t v_diff_pos_mask = vcltq_u8(v_sig, v_mc_running_avg_y);
+        const uint8x16_t v_diff_neg_mask = vcgtq_u8(v_sig, v_mc_running_avg_y);
+
+        /* Figure out which level that put us in. */
+        const uint8x16_t v_level1_mask = vcleq_u8(v_level1_threshold,
+                                                  v_abs_diff);
+        const uint8x16_t v_level2_mask = vcleq_u8(v_level2_threshold,
+                                                  v_abs_diff);
+        const uint8x16_t v_level3_mask = vcleq_u8(v_level3_threshold,
+                                                  v_abs_diff);
+
+        /* Calculate absolute adjustments for level 1, 2 and 3. */
+        const uint8x16_t v_level2_adjustment = vandq_u8(v_level2_mask,
+                                                        v_delta_level_1_and_2);
+        const uint8x16_t v_level3_adjustment = vandq_u8(v_level3_mask,
+                                                        v_delta_level_2_and_3);
+        const uint8x16_t v_level1and2_adjustment = vaddq_u8(v_level1_adjustment,
+            v_level2_adjustment);
+        const uint8x16_t v_level1and2and3_adjustment = vaddq_u8(
+            v_level1and2_adjustment, v_level3_adjustment);
+
+        /* Figure adjustment absolute value by selecting between the absolute
+         * difference if in level0 or the value for level 1, 2 and 3.
+         */
+        const uint8x16_t v_abs_adjustment = vbslq_u8(v_level1_mask,
+            v_level1and2and3_adjustment, v_abs_diff);
+
+        /* Calculate positive and negative adjustments. Apply them to the signal
+         * and accumulate them. Adjustments are less than eight and the maximum
+         * sum of them (7 * 16) can fit in a signed char.
+         */
+        const uint8x16_t v_pos_adjustment = vandq_u8(v_diff_pos_mask,
+                                                     v_abs_adjustment);
+        const uint8x16_t v_neg_adjustment = vandq_u8(v_diff_neg_mask,
+                                                     v_abs_adjustment);
+        v_running_avg_y = vqaddq_u8(v_sig, v_pos_adjustment);
+        v_running_avg_y = vqsubq_u8(v_running_avg_y, v_neg_adjustment);
+        v_sum_diff = vqaddq_s8(v_sum_diff, (int8x16_t)v_pos_adjustment);
+        v_sum_diff = vqsubq_s8(v_sum_diff, (int8x16_t)v_neg_adjustment);
+
+        /* Store results. */
+        vst1q_u8(running_avg_y, v_running_avg_y);
+
+        /* Sum all the accumulators to have the sum of all pixel differences
+         * for this macroblock.
+         */
+        {
+            int s0 = vgetq_lane_s8(v_sum_diff,  0) +
+                     vgetq_lane_s8(v_sum_diff,  1) +
+                     vgetq_lane_s8(v_sum_diff,  2) +
+                     vgetq_lane_s8(v_sum_diff,  3);
+            int s1 = vgetq_lane_s8(v_sum_diff,  4) +
+                     vgetq_lane_s8(v_sum_diff,  5) +
+                     vgetq_lane_s8(v_sum_diff,  6) +
+                     vgetq_lane_s8(v_sum_diff,  7);
+            int s2 = vgetq_lane_s8(v_sum_diff,  8) +
+                     vgetq_lane_s8(v_sum_diff,  9) +
+                     vgetq_lane_s8(v_sum_diff, 10) +
+                     vgetq_lane_s8(v_sum_diff, 11);
+            int s3 = vgetq_lane_s8(v_sum_diff, 12) +
+                     vgetq_lane_s8(v_sum_diff, 13) +
+                     vgetq_lane_s8(v_sum_diff, 14) +
+                     vgetq_lane_s8(v_sum_diff, 15);
+            sum_diff += s0 + s1+ s2 + s3;
+        }
+
+        /* Update pointers for next iteration. */
+        sig += sig_stride;
+        mc_running_avg_y += mc_running_avg_y_stride;
+        running_avg_y += running_avg_y_stride;
+    }
+
+    /* Too much adjustments => copy block. */
+    if (abs(sum_diff) > SUM_DIFF_THRESHOLD)
+        return COPY_BLOCK;
+
+    /* Tell above level that block was filtered. */
+    vp8_copy_mem16x16(running_avg->y_buffer + y_offset, running_avg_y_stride,
+                      signal->thismb, sig_stride);
+    return FILTER_BLOCK;
+}
diff --git a/vp8/encoder/bitstream.h b/vp8/encoder/bitstream.h
index 455a94f..01aa808 100644
--- a/vp8/encoder/bitstream.h
+++ b/vp8/encoder/bitstream.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef __INC_BITSTREAM_H
-#define __INC_BITSTREAM_H
+#ifndef VP8_ENCODER_BITSTREAM_H_
+#define VP8_ENCODER_BITSTREAM_H_
 
 #if HAVE_EDSP
 void vp8cx_pack_tokens_armv5(vp8_writer *w, const TOKENEXTRA *p, int xcount,
@@ -43,4 +43,4 @@
 # define pack_mb_row_tokens(a,b)               pack_mb_row_tokens_c(a,b)
 #endif
 
-#endif
+#endif  // VP8_ENCODER_BITSTREAM_H_
diff --git a/vp8/encoder/block.h b/vp8/encoder/block.h
index cf74c7a..0dc0d86 100644
--- a/vp8/encoder/block.h
+++ b/vp8/encoder/block.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef __INC_BLOCK_H
-#define __INC_BLOCK_H
+#ifndef VP8_ENCODER_BLOCK_H_
+#define VP8_ENCODER_BLOCK_H_
 
 #include "vp8/common/onyx.h"
 #include "vp8/common/blockd.h"
@@ -160,4 +160,4 @@
 } MACROBLOCK;
 
 
-#endif
+#endif  // VP8_ENCODER_BLOCK_H_
diff --git a/vp8/encoder/boolhuff.h b/vp8/encoder/boolhuff.h
index 39ab586..8f451b7 100644
--- a/vp8/encoder/boolhuff.h
+++ b/vp8/encoder/boolhuff.h
@@ -16,8 +16,8 @@
 *   Description  :     Bool Coder header file.
 *
 ****************************************************************************/
-#ifndef __INC_BOOLHUFF_H
-#define __INC_BOOLHUFF_H
+#ifndef VP8_ENCODER_BOOLHUFF_H_
+#define VP8_ENCODER_BOOLHUFF_H_
 
 #include "vpx_ports/mem.h"
 #include "vpx/internal/vpx_codec_internal.h"
@@ -125,4 +125,4 @@
     br->range = range;
 }
 
-#endif
+#endif  // VP8_ENCODER_BOOLHUFF_H_
diff --git a/vp8/encoder/dct_value_cost.h b/vp8/encoder/dct_value_cost.h
index e892765..f754e97 100644
--- a/vp8/encoder/dct_value_cost.h
+++ b/vp8/encoder/dct_value_cost.h
@@ -8,6 +8,9 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#ifndef VP8_ENCODER_DCT_VALUE_COST_H_
+#define VP8_ENCODER_DCT_VALUE_COST_H_
+
 /* Generated file, included by tokenize.c  */
 /* Values generated by fill_value_tokens() */
 
@@ -356,3 +359,5 @@
     8134, 8140, 8148, 8170, 8178, 8184, 8192, 8202, 8210, 8216, 8224, 8243,
     8251, 8257, 8265, 8275
 };
+
+#endif  // VP8_ENCODER_DCT_VALUE_COST_H_
diff --git a/vp8/encoder/dct_value_tokens.h b/vp8/encoder/dct_value_tokens.h
index ef08eed..e4132c6 100644
--- a/vp8/encoder/dct_value_tokens.h
+++ b/vp8/encoder/dct_value_tokens.h
@@ -8,6 +8,9 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#ifndef VP8_ENCODER_DCT_VALUE_TOKENS_H_
+#define VP8_ENCODER_DCT_VALUE_TOKENS_H_
+
 /* Generated file, included by tokenize.c  */
 /* Values generated by fill_value_tokens() */
 
@@ -697,3 +700,5 @@
     {10, 3942}, {10, 3944}, {10, 3946}, {10, 3948}, {10, 3950}, {10, 3952},
     {10, 3954}, {10, 3956}, {10, 3958}, {10, 3960}
 };
+
+#endif  // VP8_ENCODER_DCT_VALUE_TOKENS_H_
diff --git a/vp8/encoder/defaultcoefcounts.h b/vp8/encoder/defaultcoefcounts.h
index 2c0f3dd..3015a58 100644
--- a/vp8/encoder/defaultcoefcounts.h
+++ b/vp8/encoder/defaultcoefcounts.h
@@ -8,6 +8,9 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#ifndef VP8_ENCODER_DEFAULTCOEFCOUNTS_H_
+#define VP8_ENCODER_DEFAULTCOEFCOUNTS_H_
+
 /* Generated file, included by entropy.c */
 
 static const unsigned int default_coef_counts[BLOCK_TYPES]
@@ -221,3 +224,5 @@
         },
     },
 };
+
+#endif  // VP8_ENCODER_DEFAULTCOEFCOUNTS_H_
diff --git a/vp8/encoder/denoising.h b/vp8/encoder/denoising.h
index b025f5c..83fb93a 100644
--- a/vp8/encoder/denoising.h
+++ b/vp8/encoder/denoising.h
@@ -39,4 +39,4 @@
                              int recon_yoffset,
                              int recon_uvoffset);
 
-#endif  /* VP8_ENCODER_DENOISING_H_ */
+#endif  // VP8_ENCODER_DENOISING_H_
diff --git a/vp8/encoder/encodeframe.h b/vp8/encoder/encodeframe.h
index 4dd6ba0..180596b 100644
--- a/vp8/encoder/encodeframe.h
+++ b/vp8/encoder/encodeframe.h
@@ -7,8 +7,8 @@
  *  in the file PATENTS.  All contributing project authors may
  *  be found in the AUTHORS file in the root of the source tree.
  */
-#ifndef ENCODEFRAME_H
-#define ENCODEFRAME_H
+#ifndef VP8_ENCODER_ENCODEFRAME_H_
+#define VP8_ENCODER_ENCODEFRAME_H_
 extern void vp8_activity_masking(VP8_COMP *cpi, MACROBLOCK *x);
 
 extern void vp8_build_block_offsets(MACROBLOCK *x);
@@ -24,4 +24,4 @@
 
 extern int vp8cx_encode_intra_macroblock(VP8_COMP *cpi, MACROBLOCK *x,
         TOKENEXTRA **t);
-#endif
+#endif  // VP8_ENCODER_ENCODEFRAME_H_
diff --git a/vp8/encoder/encodeintra.h b/vp8/encoder/encodeintra.h
index be2141f..c6da43b 100644
--- a/vp8/encoder/encodeintra.h
+++ b/vp8/encoder/encodeintra.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef _ENCODEINTRA_H_
-#define _ENCODEINTRA_H_
+#ifndef VP8_ENCODER_ENCODEINTRA_H_
+#define VP8_ENCODER_ENCODEINTRA_H_
 #include "onyx_int.h"
 
 int vp8_encode_intra(VP8_COMP *cpi, MACROBLOCK *x, int use_dc_pred);
@@ -18,4 +18,4 @@
 void vp8_encode_intra16x16mbuv(MACROBLOCK *x);
 void vp8_encode_intra4x4mby(MACROBLOCK *mb);
 void vp8_encode_intra4x4block(MACROBLOCK *x, int ib);
-#endif
+#endif  // VP8_ENCODER_ENCODEINTRA_H_
diff --git a/vp8/encoder/encodemb.h b/vp8/encoder/encodemb.h
index 6badf7d..cbe62e9 100644
--- a/vp8/encoder/encodemb.h
+++ b/vp8/encoder/encodemb.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef __INC_ENCODEMB_H
-#define __INC_ENCODEMB_H
+#ifndef VP8_ENCODER_ENCODEMB_H_
+#define VP8_ENCODER_ENCODEMB_H_
 
 #include "onyx_int.h"
 void vp8_encode_inter16x16(MACROBLOCK *x);
@@ -23,4 +23,4 @@
 void vp8_optimize_mby(MACROBLOCK *x);
 void vp8_optimize_mbuv(MACROBLOCK *x);
 void vp8_encode_inter16x16y(MACROBLOCK *x);
-#endif
+#endif  // VP8_ENCODER_ENCODEMB_H_
diff --git a/vp8/encoder/encodemv.h b/vp8/encoder/encodemv.h
index a6116c1..65e7ac2 100644
--- a/vp8/encoder/encodemv.h
+++ b/vp8/encoder/encodemv.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef __INC_ENCODEMV_H
-#define __INC_ENCODEMV_H
+#ifndef VP8_ENCODER_ENCODEMV_H_
+#define VP8_ENCODER_ENCODEMV_H_
 
 #include "onyx_int.h"
 
@@ -18,4 +18,4 @@
 void vp8_encode_motion_vector(vp8_writer *, const MV *, const MV_CONTEXT *);
 void vp8_build_component_cost_table(int *mvcost[2], const MV_CONTEXT *mvc, int mvc_flag[2]);
 
-#endif
+#endif  // VP8_ENCODER_ENCODEMV_H_
diff --git a/vp8/encoder/firstpass.h b/vp8/encoder/firstpass.h
index 95e1e54..cf68679 100644
--- a/vp8/encoder/firstpass.h
+++ b/vp8/encoder/firstpass.h
@@ -9,8 +9,8 @@
  */
 
 
-#if !defined __INC_FIRSTPASS_H
-#define      __INC_FIRSTPASS_H
+#ifndef VP8_ENCODER_FIRSTPASS_H_
+#define VP8_ENCODER_FIRSTPASS_H_
 
 extern void vp8_init_first_pass(VP8_COMP *cpi);
 extern void vp8_first_pass(VP8_COMP *cpi);
@@ -21,4 +21,4 @@
 extern void vp8_end_second_pass(VP8_COMP *cpi);
 
 extern size_t vp8_firstpass_stats_sz(unsigned int mb_count);
-#endif
+#endif  // VP8_ENCODER_FIRSTPASS_H_
diff --git a/vp8/encoder/lookahead.h b/vp8/encoder/lookahead.h
index cf56b75..d1904fa 100644
--- a/vp8/encoder/lookahead.h
+++ b/vp8/encoder/lookahead.h
@@ -7,8 +7,8 @@
  *  in the file PATENTS.  All contributing project authors may
  *  be found in the AUTHORS file in the root of the source tree.
  */
-#ifndef LOOKAHEAD_H
-#define LOOKAHEAD_H
+#ifndef VP8_ENCODER_LOOKAHEAD_H_
+#define VP8_ENCODER_LOOKAHEAD_H_
 #include "vpx_scale/yv12config.h"
 #include "vpx/vpx_integer.h"
 
@@ -106,4 +106,4 @@
 vp8_lookahead_depth(struct lookahead_ctx *ctx);
 
 
-#endif
+#endif  // VP8_ENCODER_LOOKAHEAD_H_
diff --git a/vp8/encoder/mcomp.h b/vp8/encoder/mcomp.h
index e36c515..85bc7ad 100644
--- a/vp8/encoder/mcomp.h
+++ b/vp8/encoder/mcomp.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef __INC_MCOMP_H
-#define __INC_MCOMP_H
+#ifndef VP8_ENCODER_MCOMP_H_
+#define VP8_ENCODER_MCOMP_H_
 
 #include "block.h"
 #include "vp8/common/variance.h"
@@ -104,4 +104,4 @@
      int_mv *center_mv
     );
 
-#endif
+#endif  // VP8_ENCODER_MCOMP_H_
diff --git a/vp8/encoder/modecosts.h b/vp8/encoder/modecosts.h
index 99ef119..2df9446 100644
--- a/vp8/encoder/modecosts.h
+++ b/vp8/encoder/modecosts.h
@@ -9,9 +9,9 @@
  */
 
 
-#ifndef __INC_MODECOSTS_H
-#define __INC_MODECOSTS_H
+#ifndef VP8_ENCODER_MODECOSTS_H_
+#define VP8_ENCODER_MODECOSTS_H_
 
 void vp8_init_mode_costs(VP8_COMP *x);
 
-#endif
+#endif  // VP8_ENCODER_MODECOSTS_H_
diff --git a/vp8/encoder/mr_dissim.h b/vp8/encoder/mr_dissim.h
index f8cb135..8b22566 100644
--- a/vp8/encoder/mr_dissim.h
+++ b/vp8/encoder/mr_dissim.h
@@ -9,12 +9,12 @@
  */
 
 
-#ifndef __INC_MR_DISSIM_H
-#define __INC_MR_DISSIM_H
+#ifndef VP8_ENCODER_MR_DISSIM_H_
+#define VP8_ENCODER_MR_DISSIM_H_
 #include "vpx_config.h"
 
 extern void vp8_cal_low_res_mb_cols(VP8_COMP *cpi);
 extern void vp8_cal_dissimilarity(VP8_COMP *cpi);
 extern void vp8_store_drop_frame_info(VP8_COMP *cpi);
 
-#endif
+#endif  // VP8_ENCODER_MR_DISSIM_H_
diff --git a/vp8/encoder/onyx_int.h b/vp8/encoder/onyx_int.h
index 3ab0fe8..2fa6a93 100644
--- a/vp8/encoder/onyx_int.h
+++ b/vp8/encoder/onyx_int.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef __INC_VP8_INT_H
-#define __INC_VP8_INT_H
+#ifndef VP8_ENCODER_ONYX_INT_H_
+#define VP8_ENCODER_ONYX_INT_H_
 
 #include <stdio.h>
 #include "vpx_config.h"
@@ -721,4 +721,4 @@
                                "Failed to allocate "#lval);\
     } while(0)
 #endif
-#endif
+#endif  // VP8_ENCODER_ONYX_INT_H_
diff --git a/vp8/encoder/pickinter.h b/vp8/encoder/pickinter.h
index 35011ca..f74cf3d 100644
--- a/vp8/encoder/pickinter.h
+++ b/vp8/encoder/pickinter.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef __INC_PICKINTER_H
-#define __INC_PICKINTER_H
+#ifndef VP8_ENCODER_PICKINTER_H_
+#define VP8_ENCODER_PICKINTER_H_
 #include "vpx_config.h"
 #include "vp8/common/onyxc_int.h"
 
@@ -24,4 +24,4 @@
                                       const vp8_variance_fn_ptr_t *vfp,
                                       unsigned int *sse,
                                       int_mv this_mv);
-#endif
+#endif  // VP8_ENCODER_PICKINTER_H_
diff --git a/vp8/encoder/psnr.h b/vp8/encoder/psnr.h
index 7f6269a..b210615 100644
--- a/vp8/encoder/psnr.h
+++ b/vp8/encoder/psnr.h
@@ -9,9 +9,9 @@
  */
 
 
-#ifndef __INC_PSNR_H
-#define __INC_PSNR_H
+#ifndef VP8_ENCODER_PSNR_H_
+#define VP8_ENCODER_PSNR_H_
 
 extern double vp8_mse2psnr(double Samples, double Peak, double Mse);
 
-#endif
+#endif  // VP8_ENCODER_PSNR_H_
diff --git a/vp8/encoder/quantize.h b/vp8/encoder/quantize.h
index d55496c..bbad8c7 100644
--- a/vp8/encoder/quantize.h
+++ b/vp8/encoder/quantize.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef __INC_QUANTIZE_H
-#define __INC_QUANTIZE_H
+#ifndef VP8_ENCODER_QUANTIZE_H_
+#define VP8_ENCODER_QUANTIZE_H_
 
 struct VP8_COMP;
 struct macroblock;
@@ -20,4 +20,4 @@
 extern void vp8cx_mb_init_quantizer(struct VP8_COMP *cpi, struct macroblock *x, int ok_to_skip);
 extern void vp8cx_init_quantizer(struct VP8_COMP *cpi);
 
-#endif
+#endif  // VP8_ENCODER_QUANTIZE_H_
diff --git a/vp8/encoder/ratectrl.h b/vp8/encoder/ratectrl.h
index c43f08d..88fe678 100644
--- a/vp8/encoder/ratectrl.h
+++ b/vp8/encoder/ratectrl.h
@@ -9,7 +9,8 @@
  */
 
 
-#if !defined __INC_RATECTRL_H
+#ifndef VP8_ENCODER_RATECTRL_H_
+#define VP8_ENCODER_RATECTRL_H_
 
 #include "onyx_int.h"
 
@@ -25,4 +26,4 @@
 /* return of 0 means drop frame */
 extern int vp8_pick_frame_size(VP8_COMP *cpi);
 
-#endif
+#endif  // VP8_ENCODER_RATECTRL_H_
diff --git a/vp8/encoder/rdopt.h b/vp8/encoder/rdopt.h
index 1e11fa7..c28c373 100644
--- a/vp8/encoder/rdopt.h
+++ b/vp8/encoder/rdopt.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef __INC_RDOPT_H
-#define __INC_RDOPT_H
+#ifndef VP8_ENCODER_RDOPT_H_
+#define VP8_ENCODER_RDOPT_H_
 
 #define RDCOST(RM,DM,R,D) ( ((128+(R)*(RM)) >> 8) + (DM)*(D) )
 
@@ -130,4 +130,4 @@
 );
 void vp8_cal_sad(VP8_COMP *cpi, MACROBLOCKD *xd, MACROBLOCK *x, int recon_yoffset, int near_sadidx[]);
 
-#endif
+#endif  // VP8_ENCODER_RDOPT_H_
diff --git a/vp8/encoder/segmentation.h b/vp8/encoder/segmentation.h
index 12815b0..8811a8b 100644
--- a/vp8/encoder/segmentation.h
+++ b/vp8/encoder/segmentation.h
@@ -8,9 +8,13 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#ifndef VP8_ENCODER_SEGMENTATION_H_
+#define VP8_ENCODER_SEGMENTATION_H_
 
 #include "string.h"
 #include "vp8/common/blockd.h"
 #include "onyx_int.h"
 
 extern void vp8_update_gf_useage_maps(VP8_COMP *cpi, VP8_COMMON *cm, MACROBLOCK *x);
+
+#endif  // VP8_ENCODER_SEGMENTATION_H_
diff --git a/vp8/encoder/tokenize.h b/vp8/encoder/tokenize.h
index 1e6cea1..f85f3c9 100644
--- a/vp8/encoder/tokenize.h
+++ b/vp8/encoder/tokenize.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef tokenize_h
-#define tokenize_h
+#ifndef VP8_ENCODER_TOKENIZE_H_
+#define VP8_ENCODER_TOKENIZE_H_
 
 #include "vp8/common/entropy.h"
 #include "block.h"
@@ -47,4 +47,4 @@
  */
 extern const TOKENVALUE *const vp8_dct_value_tokens_ptr;
 
-#endif  /* tokenize_h */
+#endif  // VP8_ENCODER_TOKENIZE_H_
diff --git a/vp8/encoder/treewriter.h b/vp8/encoder/treewriter.h
index 48574f3..ba03f07 100644
--- a/vp8/encoder/treewriter.h
+++ b/vp8/encoder/treewriter.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef __INC_TREEWRITER_H
-#define __INC_TREEWRITER_H
+#ifndef VP8_ENCODER_TREEWRITER_H_
+#define VP8_ENCODER_TREEWRITER_H_
 
 /* Trees map alphabets into huffman-like codes suitable for an arithmetic
    bit coder.  Timothy S Murphy  11 October 2004 */
@@ -123,4 +123,4 @@
     int *Costs, const vp8_prob *, vp8_tree, int
 );
 
-#endif
+#endif  // VP8_ENCODER_TREEWRITER_H_
diff --git a/vp8/vp8_dx_iface.c b/vp8/vp8_dx_iface.c
index 871b8d3..0b4c4cb 100644
--- a/vp8/vp8_dx_iface.c
+++ b/vp8/vp8_dx_iface.c
@@ -929,6 +929,7 @@
         vp8_get_si,       /* vpx_codec_get_si_fn_t     get_si; */
         vp8_decode,       /* vpx_codec_decode_fn_t     decode; */
         vp8_get_frame,    /* vpx_codec_frame_get_fn_t  frame_get; */
+        NOT_IMPLEMENTED,
     },
     { /* encoder functions */
         NOT_IMPLEMENTED,
diff --git a/vp8/vp8cx_arm.mk b/vp8/vp8cx_arm.mk
index b030ee5..398172a 100644
--- a/vp8/vp8cx_arm.mk
+++ b/vp8/vp8cx_arm.mk
@@ -37,6 +37,7 @@
 # encoder
 VP8_CX_SRCS-$(HAVE_NEON)  += encoder/arm/neon/fastquantizeb_neon$(ASM)
 VP8_CX_SRCS-$(HAVE_NEON)  += encoder/arm/neon/picklpf_arm.c
+VP8_CX_SRCS-$(HAVE_NEON)  += encoder/arm/neon/denoising_neon.c
 VP8_CX_SRCS-$(HAVE_NEON)  += encoder/arm/neon/shortfdct_neon$(ASM)
 VP8_CX_SRCS-$(HAVE_NEON)  += encoder/arm/neon/subtract_neon$(ASM)
 VP8_CX_SRCS-$(HAVE_NEON)  += encoder/arm/neon/vp8_mse16x16_neon$(ASM)
diff --git a/vp9/common/arm/neon/vp9_loopfilter_16_neon.asm b/vp9/common/arm/neon/vp9_loopfilter_16_neon.asm
index 751bc74..5b8ec20 100644
--- a/vp9/common/arm/neon/vp9_loopfilter_16_neon.asm
+++ b/vp9/common/arm/neon/vp9_loopfilter_16_neon.asm
@@ -8,18 +8,18 @@
 ;  be found in the AUTHORS file in the root of the source tree.
 ;
 
-    EXPORT  |vp9_loop_filter_horizontal_edge_16_neon|
+    EXPORT  |vp9_lpf_horizontal_4_dual_neon|
     ARM
 
     AREA ||.text||, CODE, READONLY, ALIGN=2
 
-;void vp9_loop_filter_horizontal_edge_16_neon(uint8_t *s, int p,
-;                                             const uint8_t *blimit0,
-;                                             const uint8_t *limit0,
-;                                             const uint8_t *thresh0,
-;                                             const uint8_t *blimit1,
-;                                             const uint8_t *limit1,
-;                                             const uint8_t *thresh1)
+;void vp9_lpf_horizontal_4_dual_neon(uint8_t *s, int p,
+;                                    const uint8_t *blimit0,
+;                                    const uint8_t *limit0,
+;                                    const uint8_t *thresh0,
+;                                    const uint8_t *blimit1,
+;                                    const uint8_t *limit1,
+;                                    const uint8_t *thresh1)
 ; r0    uint8_t *s,
 ; r1    int p,
 ; r2    const uint8_t *blimit0,
@@ -29,7 +29,7 @@
 ; sp+8  const uint8_t *limit1,
 ; sp+12 const uint8_t *thresh1,
 
-|vp9_loop_filter_horizontal_edge_16_neon| PROC
+|vp9_lpf_horizontal_4_dual_neon| PROC
     push        {lr}
 
     ldr         r12, [sp, #4]              ; load thresh0
@@ -76,7 +76,7 @@
     vpop        {d8-d15}                   ; restore neon registers
 
     pop         {pc}
-    ENDP        ; |vp9_loop_filter_horizontal_edge_16_neon|
+    ENDP        ; |vp9_lpf_horizontal_4_dual_neon|
 
 ; void vp9_loop_filter_neon_16();
 ; This is a helper function for the loopfilters. The invidual functions do the
diff --git a/vp9/common/arm/neon/vp9_loopfilter_16_neon.c b/vp9/common/arm/neon/vp9_loopfilter_16_neon.c
index b97e7aa..0820db2 100644
--- a/vp9/common/arm/neon/vp9_loopfilter_16_neon.c
+++ b/vp9/common/arm/neon/vp9_loopfilter_16_neon.c
@@ -10,44 +10,43 @@
 
 #include "./vp9_rtcd.h"
 
-void vp9_mbloop_filter_horizontal_edge_16_neon(uint8_t *s, int p /* pitch */,
-                                               const uint8_t *blimit0,
-                                               const uint8_t *limit0,
-                                               const uint8_t *thresh0,
-                                               const uint8_t *blimit1,
-                                               const uint8_t *limit1,
-                                               const uint8_t *thresh1) {
-  vp9_mbloop_filter_horizontal_edge(s, p, blimit0, limit0, thresh0, 1);
-  vp9_mbloop_filter_horizontal_edge(s + 8, p, blimit1, limit1, thresh1, 1);
+void vp9_lpf_horizontal_8_dual_neon(uint8_t *s, int p /* pitch */,
+                                    const uint8_t *blimit0,
+                                    const uint8_t *limit0,
+                                    const uint8_t *thresh0,
+                                    const uint8_t *blimit1,
+                                    const uint8_t *limit1,
+                                    const uint8_t *thresh1) {
+  vp9_lpf_horizontal_8(s, p, blimit0, limit0, thresh0, 1);
+  vp9_lpf_horizontal_8(s + 8, p, blimit1, limit1, thresh1, 1);
 }
 
-void vp9_loop_filter_vertical_edge_16_neon(uint8_t *s, int p,
-                                           const uint8_t *blimit0,
-                                           const uint8_t *limit0,
-                                           const uint8_t *thresh0,
-                                           const uint8_t *blimit1,
-                                           const uint8_t *limit1,
-                                           const uint8_t *thresh1) {
-  vp9_loop_filter_vertical_edge_neon(s, p, blimit0, limit0, thresh0, 1);
-  vp9_loop_filter_vertical_edge_neon(s + 8 * p, p, blimit1, limit1, thresh1, 1);
+void vp9_lpf_vertical_4_dual_neon(uint8_t *s, int p,
+                                  const uint8_t *blimit0,
+                                  const uint8_t *limit0,
+                                  const uint8_t *thresh0,
+                                  const uint8_t *blimit1,
+                                  const uint8_t *limit1,
+                                  const uint8_t *thresh1) {
+  vp9_lpf_vertical_4_neon(s, p, blimit0, limit0, thresh0, 1);
+  vp9_lpf_vertical_4_neon(s + 8 * p, p, blimit1, limit1, thresh1, 1);
 }
 
-void vp9_mbloop_filter_vertical_edge_16_neon(uint8_t *s, int p,
-                                             const uint8_t *blimit0,
-                                             const uint8_t *limit0,
-                                             const uint8_t *thresh0,
-                                             const uint8_t *blimit1,
-                                             const uint8_t *limit1,
-                                             const uint8_t *thresh1) {
-  vp9_mbloop_filter_vertical_edge_neon(s, p, blimit0, limit0, thresh0, 1);
-  vp9_mbloop_filter_vertical_edge_neon(s + 8 * p, p, blimit1, limit1, thresh1,
-                                       1);
+void vp9_lpf_vertical_8_dual_neon(uint8_t *s, int p,
+                                  const uint8_t *blimit0,
+                                  const uint8_t *limit0,
+                                  const uint8_t *thresh0,
+                                  const uint8_t *blimit1,
+                                  const uint8_t *limit1,
+                                  const uint8_t *thresh1) {
+  vp9_lpf_vertical_8_neon(s, p, blimit0, limit0, thresh0, 1);
+  vp9_lpf_vertical_8_neon(s + 8 * p, p, blimit1, limit1, thresh1, 1);
 }
 
-void vp9_mb_lpf_vertical_edge_w_16_neon(uint8_t *s, int p,
-                                        const uint8_t *blimit,
-                                        const uint8_t *limit,
-                                        const uint8_t *thresh) {
-  vp9_mb_lpf_vertical_edge_w_neon(s, p, blimit, limit, thresh);
-  vp9_mb_lpf_vertical_edge_w_neon(s + 8 * p, p, blimit, limit, thresh);
+void vp9_lpf_vertical_16_dual_neon(uint8_t *s, int p,
+                                   const uint8_t *blimit,
+                                   const uint8_t *limit,
+                                   const uint8_t *thresh) {
+  vp9_lpf_vertical_16_neon(s, p, blimit, limit, thresh);
+  vp9_lpf_vertical_16_neon(s + 8 * p, p, blimit, limit, thresh);
 }
diff --git a/vp9/common/arm/neon/vp9_loopfilter_neon.asm b/vp9/common/arm/neon/vp9_loopfilter_neon.asm
index 8b4fe5d..4430322 100644
--- a/vp9/common/arm/neon/vp9_loopfilter_neon.asm
+++ b/vp9/common/arm/neon/vp9_loopfilter_neon.asm
@@ -8,10 +8,10 @@
 ;  be found in the AUTHORS file in the root of the source tree.
 ;
 
-    EXPORT  |vp9_loop_filter_horizontal_edge_neon|
-    EXPORT  |vp9_loop_filter_vertical_edge_neon|
-    EXPORT  |vp9_mbloop_filter_horizontal_edge_neon|
-    EXPORT  |vp9_mbloop_filter_vertical_edge_neon|
+    EXPORT  |vp9_lpf_horizontal_4_neon|
+    EXPORT  |vp9_lpf_vertical_4_neon|
+    EXPORT  |vp9_lpf_horizontal_8_neon|
+    EXPORT  |vp9_lpf_vertical_8_neon|
     ARM
 
     AREA ||.text||, CODE, READONLY, ALIGN=2
@@ -21,12 +21,12 @@
 ; TODO(fgalligan): See about removing the count code as this function is only
 ; called with a count of 1.
 ;
-; void vp9_loop_filter_horizontal_edge_neon(uint8_t *s,
-;                                           int p /* pitch */,
-;                                           const uint8_t *blimit,
-;                                           const uint8_t *limit,
-;                                           const uint8_t *thresh,
-;                                           int count)
+; void vp9_lpf_horizontal_4_neon(uint8_t *s,
+;                                int p /* pitch */,
+;                                const uint8_t *blimit,
+;                                const uint8_t *limit,
+;                                const uint8_t *thresh,
+;                                int count)
 ;
 ; r0    uint8_t *s,
 ; r1    int p, /* pitch */
@@ -34,7 +34,7 @@
 ; r3    const uint8_t *limit,
 ; sp    const uint8_t *thresh,
 ; sp+4  int count
-|vp9_loop_filter_horizontal_edge_neon| PROC
+|vp9_lpf_horizontal_4_neon| PROC
     push        {lr}
 
     vld1.8      {d0[]}, [r2]               ; duplicate *blimit
@@ -77,19 +77,19 @@
 
 end_vp9_lf_h_edge
     pop         {pc}
-    ENDP        ; |vp9_loop_filter_horizontal_edge_neon|
+    ENDP        ; |vp9_lpf_horizontal_4_neon|
 
 ; Currently vp9 only works on iterations 8 at a time. The vp8 loop filter
 ; works on 16 iterations at a time.
 ; TODO(fgalligan): See about removing the count code as this function is only
 ; called with a count of 1.
 ;
-; void vp9_loop_filter_vertical_edge_neon(uint8_t *s,
-;                                         int p /* pitch */,
-;                                         const uint8_t *blimit,
-;                                         const uint8_t *limit,
-;                                         const uint8_t *thresh,
-;                                         int count)
+; void vp9_lpf_vertical_4_neon(uint8_t *s,
+;                              int p /* pitch */,
+;                              const uint8_t *blimit,
+;                              const uint8_t *limit,
+;                              const uint8_t *thresh,
+;                              int count)
 ;
 ; r0    uint8_t *s,
 ; r1    int p, /* pitch */
@@ -97,7 +97,7 @@
 ; r3    const uint8_t *limit,
 ; sp    const uint8_t *thresh,
 ; sp+4  int count
-|vp9_loop_filter_vertical_edge_neon| PROC
+|vp9_lpf_vertical_4_neon| PROC
     push        {lr}
 
     vld1.8      {d0[]}, [r2]              ; duplicate *blimit
@@ -158,7 +158,7 @@
 
 end_vp9_lf_v_edge
     pop         {pc}
-    ENDP        ; |vp9_loop_filter_vertical_edge_neon|
+    ENDP        ; |vp9_lpf_vertical_4_neon|
 
 ; void vp9_loop_filter_neon();
 ; This is a helper function for the loopfilters. The invidual functions do the
@@ -276,18 +276,18 @@
     bx          lr
     ENDP        ; |vp9_loop_filter_neon|
 
-; void vp9_mbloop_filter_horizontal_edge_neon(uint8_t *s, int p,
-;                                             const uint8_t *blimit,
-;                                             const uint8_t *limit,
-;                                             const uint8_t *thresh,
-;                                             int count)
+; void vp9_lpf_horizontal_8_neon(uint8_t *s, int p,
+;                                const uint8_t *blimit,
+;                                const uint8_t *limit,
+;                                const uint8_t *thresh,
+;                                int count)
 ; r0    uint8_t *s,
 ; r1    int p, /* pitch */
 ; r2    const uint8_t *blimit,
 ; r3    const uint8_t *limit,
 ; sp    const uint8_t *thresh,
 ; sp+4  int count
-|vp9_mbloop_filter_horizontal_edge_neon| PROC
+|vp9_lpf_horizontal_8_neon| PROC
     push        {r4-r5, lr}
 
     vld1.8      {d0[]}, [r2]               ; duplicate *blimit
@@ -333,14 +333,14 @@
 end_vp9_mblf_h_edge
     pop         {r4-r5, pc}
 
-    ENDP        ; |vp9_mbloop_filter_horizontal_edge_neon|
+    ENDP        ; |vp9_lpf_horizontal_8_neon|
 
-; void vp9_mbloop_filter_vertical_edge_neon(uint8_t *s,
-;                                           int pitch,
-;                                           const uint8_t *blimit,
-;                                           const uint8_t *limit,
-;                                           const uint8_t *thresh,
-;                                           int count)
+; void vp9_lpf_vertical_8_neon(uint8_t *s,
+;                              int pitch,
+;                              const uint8_t *blimit,
+;                              const uint8_t *limit,
+;                              const uint8_t *thresh,
+;                              int count)
 ;
 ; r0    uint8_t *s,
 ; r1    int pitch,
@@ -348,7 +348,7 @@
 ; r3    const uint8_t *limit,
 ; sp    const uint8_t *thresh,
 ; sp+4  int count
-|vp9_mbloop_filter_vertical_edge_neon| PROC
+|vp9_lpf_vertical_8_neon| PROC
     push        {r4-r5, lr}
 
     vld1.8      {d0[]}, [r2]              ; duplicate *blimit
@@ -420,7 +420,7 @@
 
 end_vp9_mblf_v_edge
     pop         {r4-r5, pc}
-    ENDP        ; |vp9_mbloop_filter_vertical_edge_neon|
+    ENDP        ; |vp9_lpf_vertical_8_neon|
 
 ; void vp9_mbloop_filter_neon();
 ; This is a helper function for the loopfilters. The invidual functions do the
diff --git a/vp9/common/arm/neon/vp9_mb_lpf_neon.asm b/vp9/common/arm/neon/vp9_mb_lpf_neon.asm
index 2e8001b..8cb913c 100644
--- a/vp9/common/arm/neon/vp9_mb_lpf_neon.asm
+++ b/vp9/common/arm/neon/vp9_mb_lpf_neon.asm
@@ -8,23 +8,23 @@
 ;  be found in the AUTHORS file in the root of the source tree.
 ;
 
-    EXPORT  |vp9_mb_lpf_horizontal_edge_w_neon|
-    EXPORT  |vp9_mb_lpf_vertical_edge_w_neon|
+    EXPORT  |vp9_lpf_horizontal_16_neon|
+    EXPORT  |vp9_lpf_vertical_16_neon|
     ARM
 
     AREA ||.text||, CODE, READONLY, ALIGN=2
 
-; void vp9_mb_lpf_horizontal_edge_w_neon(uint8_t *s, int p,
-;                                        const uint8_t *blimit,
-;                                        const uint8_t *limit,
-;                                        const uint8_t *thresh
-;                                        int count)
+; void vp9_lpf_horizontal_16_neon(uint8_t *s, int p,
+;                                 const uint8_t *blimit,
+;                                 const uint8_t *limit,
+;                                 const uint8_t *thresh
+;                                 int count)
 ; r0    uint8_t *s,
 ; r1    int p, /* pitch */
 ; r2    const uint8_t *blimit,
 ; r3    const uint8_t *limit,
 ; sp    const uint8_t *thresh,
-|vp9_mb_lpf_horizontal_edge_w_neon| PROC
+|vp9_lpf_horizontal_16_neon| PROC
     push        {r4-r8, lr}
     vpush       {d8-d15}
     ldr         r4, [sp, #88]              ; load thresh
@@ -115,18 +115,18 @@
     vpop        {d8-d15}
     pop         {r4-r8, pc}
 
-    ENDP        ; |vp9_mb_lpf_horizontal_edge_w_neon|
+    ENDP        ; |vp9_lpf_horizontal_16_neon|
 
-; void vp9_mb_lpf_vertical_edge_w_neon(uint8_t *s, int p,
-;                                        const uint8_t *blimit,
-;                                        const uint8_t *limit,
-;                                        const uint8_t *thresh)
+; void vp9_lpf_vertical_16_neon(uint8_t *s, int p,
+;                               const uint8_t *blimit,
+;                               const uint8_t *limit,
+;                               const uint8_t *thresh)
 ; r0    uint8_t *s,
 ; r1    int p, /* pitch */
 ; r2    const uint8_t *blimit,
 ; r3    const uint8_t *limit,
 ; sp    const uint8_t *thresh,
-|vp9_mb_lpf_vertical_edge_w_neon| PROC
+|vp9_lpf_vertical_16_neon| PROC
     push        {r4-r8, lr}
     vpush       {d8-d15}
     ldr         r4, [sp, #88]              ; load thresh
@@ -279,7 +279,7 @@
     vpop        {d8-d15}
     pop         {r4-r8, pc}
 
-    ENDP        ; |vp9_mb_lpf_vertical_edge_w_neon|
+    ENDP        ; |vp9_lpf_vertical_16_neon|
 
 ; void vp9_wide_mbfilter_neon();
 ; This is a helper function for the loopfilters. The invidual functions do the
diff --git a/vp9/common/mips/dspr2/vp9_common_dspr2.h b/vp9/common/mips/dspr2/vp9_common_dspr2.h
index 644264f..e9c6981 100644
--- a/vp9/common/mips/dspr2/vp9_common_dspr2.h
+++ b/vp9/common/mips/dspr2/vp9_common_dspr2.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef VP9_COMMON_VP9_COMMON_DSPR2_H_
-#define VP9_COMMON_VP9_COMMON_DSPR2_H_
+#ifndef VP9_COMMON_MIPS_DSPR2_VP9_COMMON_DSPR2_H_
+#define VP9_COMMON_MIPS_DSPR2_VP9_COMMON_DSPR2_H_
 
 #include <assert.h>
 
@@ -114,4 +114,4 @@
                               int w, int h);
 
 #endif  // #if HAVE_DSPR2
-#endif  // VP9_COMMON_VP9_COMMON_DSPR2_H_
+#endif  // VP9_COMMON_MIPS_DSPR2_VP9_COMMON_DSPR2_H_
diff --git a/vp9/common/mips/dspr2/vp9_loopfilter_filters_dspr2.c b/vp9/common/mips/dspr2/vp9_loopfilter_filters_dspr2.c
index 0c0f155..3df7f4c 100644
--- a/vp9/common/mips/dspr2/vp9_loopfilter_filters_dspr2.c
+++ b/vp9/common/mips/dspr2/vp9_loopfilter_filters_dspr2.c
@@ -20,12 +20,12 @@
 #include "vp9/common/mips/dspr2/vp9_loopfilter_filters_dspr2.h"
 
 #if HAVE_DSPR2
-void vp9_loop_filter_horizontal_edge_dspr2(unsigned char *s,
-                                           int pitch,
-                                           const uint8_t *blimit,
-                                           const uint8_t *limit,
-                                           const uint8_t *thresh,
-                                           int count) {
+void vp9_lpf_horizontal_4_dspr2(unsigned char *s,
+                                int pitch,
+                                const uint8_t *blimit,
+                                const uint8_t *limit,
+                                const uint8_t *thresh,
+                                int count) {
   uint8_t   i;
   uint32_t  mask;
   uint32_t  hev;
@@ -114,12 +114,12 @@
   }
 }
 
-void vp9_loop_filter_vertical_edge_dspr2(unsigned char *s,
-                                         int pitch,
-                                         const uint8_t *blimit,
-                                         const uint8_t *limit,
-                                         const uint8_t *thresh,
-                                         int count) {
+void vp9_lpf_vertical_4_dspr2(unsigned char *s,
+                              int pitch,
+                              const uint8_t *blimit,
+                              const uint8_t *limit,
+                              const uint8_t *thresh,
+                              int count) {
   uint8_t   i;
   uint32_t  mask, hev;
   uint32_t  pm1, p0, p1, p2, p3, p4, p5, p6;
@@ -307,58 +307,56 @@
   }
 }
 
-void vp9_loop_filter_horizontal_edge_16_dspr2(uint8_t *s, int p /* pitch */,
-                                              const uint8_t *blimit0,
-                                              const uint8_t *limit0,
-                                              const uint8_t *thresh0,
-                                              const uint8_t *blimit1,
-                                              const uint8_t *limit1,
-                                              const uint8_t *thresh1) {
-  vp9_loop_filter_horizontal_edge_dspr2(s, p, blimit0, limit0, thresh0, 1);
-  vp9_loop_filter_horizontal_edge_dspr2(s + 8, p, blimit1, limit1, thresh1, 1);
+void vp9_lpf_horizontal_4_dual_dspr2(uint8_t *s, int p /* pitch */,
+                                     const uint8_t *blimit0,
+                                     const uint8_t *limit0,
+                                     const uint8_t *thresh0,
+                                     const uint8_t *blimit1,
+                                     const uint8_t *limit1,
+                                     const uint8_t *thresh1) {
+  vp9_lpf_horizontal_4_dspr2(s, p, blimit0, limit0, thresh0, 1);
+  vp9_lpf_horizontal_4_dspr2(s + 8, p, blimit1, limit1, thresh1, 1);
 }
 
-void vp9_mbloop_filter_horizontal_edge_16_dspr2(uint8_t *s, int p /* pitch */,
-                                                const uint8_t *blimit0,
-                                                const uint8_t *limit0,
-                                                const uint8_t *thresh0,
-                                                const uint8_t *blimit1,
-                                                const uint8_t *limit1,
-                                                const uint8_t *thresh1) {
-  vp9_mbloop_filter_horizontal_edge_dspr2(s, p, blimit0, limit0, thresh0, 1);
-  vp9_mbloop_filter_horizontal_edge_dspr2(s + 8, p, blimit1, limit1, thresh1,
-                                          1);
+void vp9_lpf_horizontal_8_dual_dspr2(uint8_t *s, int p /* pitch */,
+                                     const uint8_t *blimit0,
+                                     const uint8_t *limit0,
+                                     const uint8_t *thresh0,
+                                     const uint8_t *blimit1,
+                                     const uint8_t *limit1,
+                                     const uint8_t *thresh1) {
+  vp9_lpf_horizontal_8_dspr2(s, p, blimit0, limit0, thresh0, 1);
+  vp9_lpf_horizontal_8_dspr2(s + 8, p, blimit1, limit1, thresh1, 1);
 }
 
-void vp9_loop_filter_vertical_edge_16_dspr2(uint8_t *s, int p,
-                                            const uint8_t *blimit0,
-                                            const uint8_t *limit0,
-                                            const uint8_t *thresh0,
-                                            const uint8_t *blimit1,
-                                            const uint8_t *limit1,
-                                            const uint8_t *thresh1) {
-  vp9_loop_filter_vertical_edge_dspr2(s, p, blimit0, limit0, thresh0, 1);
-  vp9_loop_filter_vertical_edge_dspr2(s + 8 * p, p, blimit1, limit1, thresh1,
-                                      1);
+void vp9_lpf_vertical_4_dual_dspr2(uint8_t *s, int p,
+                                   const uint8_t *blimit0,
+                                   const uint8_t *limit0,
+                                   const uint8_t *thresh0,
+                                   const uint8_t *blimit1,
+                                   const uint8_t *limit1,
+                                   const uint8_t *thresh1) {
+  vp9_lpf_vertical_4_dspr2(s, p, blimit0, limit0, thresh0, 1);
+  vp9_lpf_vertical_4_dspr2(s + 8 * p, p, blimit1, limit1, thresh1, 1);
 }
 
-void vp9_mbloop_filter_vertical_edge_16_dspr2(uint8_t *s, int p,
-                                              const uint8_t *blimit0,
-                                              const uint8_t *limit0,
-                                              const uint8_t *thresh0,
-                                              const uint8_t *blimit1,
-                                              const uint8_t *limit1,
-                                              const uint8_t *thresh1) {
-  vp9_mbloop_filter_vertical_edge_dspr2(s, p, blimit0, limit0, thresh0, 1);
-  vp9_mbloop_filter_vertical_edge_dspr2(s + 8 * p, p, blimit1, limit1, thresh1,
+void vp9_lpf_vertical_8_dual_dspr2(uint8_t *s, int p,
+                                   const uint8_t *blimit0,
+                                   const uint8_t *limit0,
+                                   const uint8_t *thresh0,
+                                   const uint8_t *blimit1,
+                                   const uint8_t *limit1,
+                                   const uint8_t *thresh1) {
+  vp9_lpf_vertical_8_dspr2(s, p, blimit0, limit0, thresh0, 1);
+  vp9_lpf_vertical_8_dspr2(s + 8 * p, p, blimit1, limit1, thresh1,
                                        1);
 }
 
-void vp9_mb_lpf_vertical_edge_w_16_dspr2(uint8_t *s, int p,
-                                         const uint8_t *blimit,
-                                         const uint8_t *limit,
-                                         const uint8_t *thresh) {
-  vp9_mb_lpf_vertical_edge_w_dspr2(s, p, blimit, limit, thresh);
-  vp9_mb_lpf_vertical_edge_w_dspr2(s + 8 * p, p, blimit, limit, thresh);
+void vp9_lpf_vertical_16_dual_dspr2(uint8_t *s, int p,
+                                    const uint8_t *blimit,
+                                    const uint8_t *limit,
+                                    const uint8_t *thresh) {
+  vp9_lpf_vertical_16_dspr2(s, p, blimit, limit, thresh);
+  vp9_lpf_vertical_16_dspr2(s + 8 * p, p, blimit, limit, thresh);
 }
 #endif  // #if HAVE_DSPR2
diff --git a/vp9/common/mips/dspr2/vp9_mbloop_loopfilter_dspr2.c b/vp9/common/mips/dspr2/vp9_mbloop_loopfilter_dspr2.c
index adfd755..7cd0b63 100644
--- a/vp9/common/mips/dspr2/vp9_mbloop_loopfilter_dspr2.c
+++ b/vp9/common/mips/dspr2/vp9_mbloop_loopfilter_dspr2.c
@@ -20,12 +20,12 @@
 #include "vp9/common/mips/dspr2/vp9_loopfilter_filters_dspr2.h"
 
 #if HAVE_DSPR2
-void vp9_mbloop_filter_horizontal_edge_dspr2(unsigned char *s,
-                                             int pitch,
-                                             const uint8_t *blimit,
-                                             const uint8_t *limit,
-                                             const uint8_t *thresh,
-                                             int count) {
+void vp9_lpf_horizontal_8_dspr2(unsigned char *s,
+                                int pitch,
+                                const uint8_t *blimit,
+                                const uint8_t *limit,
+                                const uint8_t *thresh,
+                                int count) {
   uint32_t  mask;
   uint32_t  hev, flat;
   uint8_t   i;
@@ -319,12 +319,12 @@
   }
 }
 
-void vp9_mbloop_filter_vertical_edge_dspr2(unsigned char *s,
-                                           int pitch,
-                                           const uint8_t *blimit,
-                                           const uint8_t *limit,
-                                           const uint8_t *thresh,
-                                           int count) {
+void vp9_lpf_vertical_8_dspr2(unsigned char *s,
+                              int pitch,
+                              const uint8_t *blimit,
+                              const uint8_t *limit,
+                              const uint8_t *thresh,
+                              int count) {
   uint8_t   i;
   uint32_t  mask, hev, flat;
   uint8_t   *s1, *s2, *s3, *s4;
diff --git a/vp9/common/mips/dspr2/vp9_mblpf_horiz_loopfilter_dspr2.c b/vp9/common/mips/dspr2/vp9_mblpf_horiz_loopfilter_dspr2.c
index 0759755..6c94674 100644
--- a/vp9/common/mips/dspr2/vp9_mblpf_horiz_loopfilter_dspr2.c
+++ b/vp9/common/mips/dspr2/vp9_mblpf_horiz_loopfilter_dspr2.c
@@ -20,12 +20,12 @@
 #include "vp9/common/mips/dspr2/vp9_loopfilter_filters_dspr2.h"
 
 #if HAVE_DSPR2
-void vp9_mb_lpf_horizontal_edge_w_dspr2(unsigned char *s,
-                                        int pitch,
-                                        const uint8_t *blimit,
-                                        const uint8_t *limit,
-                                        const uint8_t *thresh,
-                                        int count) {
+void vp9_lpf_horizontal_16_dspr2(unsigned char *s,
+                                 int pitch,
+                                 const uint8_t *blimit,
+                                 const uint8_t *limit,
+                                 const uint8_t *thresh,
+                                 int count) {
   uint32_t  mask;
   uint32_t  hev, flat, flat2;
   uint8_t   i;
diff --git a/vp9/common/mips/dspr2/vp9_mblpf_vert_loopfilter_dspr2.c b/vp9/common/mips/dspr2/vp9_mblpf_vert_loopfilter_dspr2.c
index 9e9171c..851fc6c 100644
--- a/vp9/common/mips/dspr2/vp9_mblpf_vert_loopfilter_dspr2.c
+++ b/vp9/common/mips/dspr2/vp9_mblpf_vert_loopfilter_dspr2.c
@@ -20,11 +20,11 @@
 #include "vp9/common/mips/dspr2/vp9_loopfilter_filters_dspr2.h"
 
 #if HAVE_DSPR2
-void vp9_mb_lpf_vertical_edge_w_dspr2(uint8_t *s,
-                                      int pitch,
-                                      const uint8_t *blimit,
-                                      const uint8_t *limit,
-                                      const uint8_t *thresh) {
+void vp9_lpf_vertical_16_dspr2(uint8_t *s,
+                               int pitch,
+                               const uint8_t *blimit,
+                               const uint8_t *limit,
+                               const uint8_t *thresh) {
   uint8_t   i;
   uint32_t  mask, hev, flat, flat2;
   uint8_t   *s1, *s2, *s3, *s4;
diff --git a/vp9/common/vp9_alloccommon.c b/vp9/common/vp9_alloccommon.c
index f567840..6d48542 100644
--- a/vp9/common/vp9_alloccommon.c
+++ b/vp9/common/vp9_alloccommon.c
@@ -15,7 +15,6 @@
 #include "vp9/common/vp9_blockd.h"
 #include "vp9/common/vp9_entropymode.h"
 #include "vp9/common/vp9_entropymv.h"
-#include "vp9/common/vp9_findnearmv.h"
 #include "vp9/common/vp9_onyxc_int.h"
 #include "vp9/common/vp9_systemdependent.h"
 
@@ -34,7 +33,7 @@
 void vp9_free_frame_buffers(VP9_COMMON *cm) {
   int i;
 
-  for (i = 0; i < FRAME_BUFFERS; i++)
+  for (i = 0; i < cm->fb_count; i++)
     vp9_free_frame_buffer(&cm->yv12_fb[i]);
 
   vp9_free_frame_buffer(&cm->post_proc_buffer);
@@ -86,7 +85,7 @@
   int mi_size;
 
   if (vp9_realloc_frame_buffer(&cm->post_proc_buffer, width, height, ss_x, ss_y,
-                             VP9BORDERINPIXELS) < 0)
+                               VP9BORDERINPIXELS, NULL, NULL, NULL) < 0)
     goto fail;
 
   set_mb_mi(cm, aligned_width, aligned_height);
@@ -138,16 +137,28 @@
   const int ss_y = cm->subsampling_y;
   int mi_size;
 
+  if (cm->fb_count == 0) {
+    cm->fb_count = FRAME_BUFFERS;
+    CHECK_MEM_ERROR(cm, cm->yv12_fb,
+                    vpx_calloc(cm->fb_count, sizeof(*cm->yv12_fb)));
+    CHECK_MEM_ERROR(cm, cm->fb_idx_ref_cnt,
+                    vpx_calloc(cm->fb_count, sizeof(*cm->fb_idx_ref_cnt)));
+    if (cm->fb_lru) {
+      CHECK_MEM_ERROR(cm, cm->fb_idx_ref_lru,
+                      vpx_calloc(cm->fb_count, sizeof(*cm->fb_idx_ref_lru)));
+    }
+  }
+
   vp9_free_frame_buffers(cm);
 
-  for (i = 0; i < FRAME_BUFFERS; i++) {
+  for (i = 0; i < cm->fb_count; i++) {
     cm->fb_idx_ref_cnt[i] = 0;
     if (vp9_alloc_frame_buffer(&cm->yv12_fb[i], width, height, ss_x, ss_y,
                                VP9BORDERINPIXELS) < 0)
       goto fail;
   }
 
-  cm->new_fb_idx = FRAME_BUFFERS - 1;
+  cm->new_fb_idx = cm->fb_count - 1;
   cm->fb_idx_ref_cnt[cm->new_fb_idx] = 1;
 
   for (i = 0; i < REFS_PER_FRAME; i++)
@@ -203,6 +214,14 @@
 
 void vp9_remove_common(VP9_COMMON *cm) {
   vp9_free_frame_buffers(cm);
+
+  vpx_free(cm->yv12_fb);
+  vpx_free(cm->fb_idx_ref_cnt);
+  vpx_free(cm->fb_idx_ref_lru);
+
+  cm->yv12_fb = NULL;
+  cm->fb_idx_ref_cnt = NULL;
+  cm->fb_idx_ref_lru = NULL;
 }
 
 void vp9_initialize_common() {
diff --git a/vp9/common/vp9_blockd.h b/vp9/common/vp9_blockd.h
index 93f96c8..38acf1e 100644
--- a/vp9/common/vp9_blockd.h
+++ b/vp9/common/vp9_blockd.h
@@ -24,7 +24,6 @@
 #include "vp9/common/vp9_mv.h"
 #include "vp9/common/vp9_scale.h"
 #include "vp9/common/vp9_seg_common.h"
-#include "vp9/common/vp9_treecoder.h"
 
 #define BLOCK_SIZE_GROUPS 4
 #define MBSKIP_CONTEXTS 3
@@ -216,7 +215,7 @@
 typedef struct macroblockd {
   struct macroblockd_plane plane[MAX_MB_PLANE];
 
-  struct scale_factors scale_factor[2];
+  const struct scale_factors *scale_factors[2];
 
   MODE_INFO *last_mi;
   int mode_info_stride;
@@ -238,6 +237,9 @@
   /* pointers to reference frames */
   const YV12_BUFFER_CONFIG *ref_buf[2];
 
+  /* pointer to current frame */
+  const YV12_BUFFER_CONFIG *cur_buf;
+
   int lossless;
   /* Inverse transform function pointers. */
   void (*itxm_add)(const int16_t *input, uint8_t *dest, int stride, int eob);
@@ -409,44 +411,6 @@
   *y = (raster_mb >> tx_cols_log2) << tx_size;
 }
 
-static void extend_for_intra(MACROBLOCKD *xd, BLOCK_SIZE plane_bsize,
-                             int plane, int aoff, int loff) {
-  struct macroblockd_plane *const pd = &xd->plane[plane];
-  uint8_t *const buf = pd->dst.buf;
-  const int stride = pd->dst.stride;
-  const int x = aoff * 4 - 1;
-  const int y = loff * 4 - 1;
-  // Copy a pixel into the umv if we are in a situation where the block size
-  // extends into the UMV.
-  // TODO(JBB): Should be able to do the full extend in place so we don't have
-  // to do this multiple times.
-  if (xd->mb_to_right_edge < 0) {
-    const int bw = 4 * num_4x4_blocks_wide_lookup[plane_bsize];
-    const int umv_border_start = bw + (xd->mb_to_right_edge >>
-                                       (3 + pd->subsampling_x));
-
-    if (x + bw > umv_border_start)
-      vpx_memset(&buf[y * stride + umv_border_start],
-                 buf[y * stride + umv_border_start - 1], bw);
-  }
-
-  if (xd->mb_to_bottom_edge < 0) {
-    if (xd->left_available || x >= 0) {
-      const int bh = 4 * num_4x4_blocks_high_lookup[plane_bsize];
-      const int umv_border_start =
-          bh + (xd->mb_to_bottom_edge >> (3 + pd->subsampling_y));
-
-      if (y + bh > umv_border_start) {
-        const uint8_t c = buf[(umv_border_start - 1) * stride + x];
-        uint8_t *d = &buf[umv_border_start * stride + x];
-        int i;
-        for (i = 0; i < bh; ++i, d += stride)
-          *d = c;
-      }
-    }
-  }
-}
-
 static void set_contexts(const MACROBLOCKD *xd, struct macroblockd_plane *pd,
                          BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
                          int has_eob, int aoff, int loff) {
diff --git a/vp9/common/vp9_common_data.h b/vp9/common/vp9_common_data.h
index b6fc70a..a367c65 100644
--- a/vp9/common/vp9_common_data.h
+++ b/vp9/common/vp9_common_data.h
@@ -29,4 +29,4 @@
 extern const TX_SIZE tx_mode_to_biggest_tx_size[TX_MODES];
 extern const BLOCK_SIZE ss_size_lookup[BLOCK_SIZES][2][2];
 
-#endif  // VP9_COMMON_VP9_COMMON_DATA_H
+#endif  // VP9_COMMON_VP9_COMMON_DATA_H_
diff --git a/vp9/common/vp9_convolve.c b/vp9/common/vp9_convolve.c
index a2d864c..6edf7ea 100644
--- a/vp9/common/vp9_convolve.c
+++ b/vp9/common/vp9_convolve.c
@@ -18,40 +18,21 @@
 #include "vpx/vpx_integer.h"
 #include "vpx_ports/mem.h"
 
-static void convolve_horiz_c(const uint8_t *src, ptrdiff_t src_stride,
-                             uint8_t *dst, ptrdiff_t dst_stride,
-                             const int16_t *filter_x0, int x_step_q4,
-                             const int16_t *filter_y, int y_step_q4,
-                             int w, int h, int taps) {
-  int x, y, k;
-
-  /* NOTE: This assumes that the filter table is 256-byte aligned. */
-  /* TODO(agrange) Modify to make independent of table alignment. */
-  const int16_t *const filter_x_base =
-      (const int16_t *)(((intptr_t)filter_x0) & ~(intptr_t)0xff);
-
-  /* Adjust base pointer address for this source line */
-  src -= taps / 2 - 1;
-
+static void convolve_horiz(const uint8_t *src, ptrdiff_t src_stride,
+                           uint8_t *dst, ptrdiff_t dst_stride,
+                           const subpel_kernel *x_filters,
+                           int x0_q4, int x_step_q4, int w, int h) {
+  int x, y;
+  src -= SUBPEL_TAPS / 2 - 1;
   for (y = 0; y < h; ++y) {
-    /* Initial phase offset */
-    int x_q4 = (int)(filter_x0 - filter_x_base) / taps;
-
+    int x_q4 = x0_q4;
     for (x = 0; x < w; ++x) {
-      /* Per-pixel src offset */
-      const int src_x = x_q4 >> SUBPEL_BITS;
-      int sum = 0;
-
-      /* Pointer to filter to use */
-      const int16_t *const filter_x = filter_x_base +
-          (x_q4 & SUBPEL_MASK) * taps;
-
-      for (k = 0; k < taps; ++k)
-        sum += src[src_x + k] * filter_x[k];
-
+      const uint8_t *const src_x = &src[x_q4 >> SUBPEL_BITS];
+      const int16_t *const x_filter = x_filters[x_q4 & SUBPEL_MASK];
+      int k, sum = 0;
+      for (k = 0; k < SUBPEL_TAPS; ++k)
+        sum += src_x[k] * x_filter[k];
       dst[x] = clip_pixel(ROUND_POWER_OF_TWO(sum, FILTER_BITS));
-
-      /* Move to the next source pixel */
       x_q4 += x_step_q4;
     }
     src += src_stride;
@@ -59,41 +40,22 @@
   }
 }
 
-static void convolve_avg_horiz_c(const uint8_t *src, ptrdiff_t src_stride,
-                                 uint8_t *dst, ptrdiff_t dst_stride,
-                                 const int16_t *filter_x0, int x_step_q4,
-                                 const int16_t *filter_y, int y_step_q4,
-                                 int w, int h, int taps) {
-  int x, y, k;
-
-  /* NOTE: This assumes that the filter table is 256-byte aligned. */
-  /* TODO(agrange) Modify to make independent of table alignment. */
-  const int16_t *const filter_x_base =
-      (const int16_t *)(((intptr_t)filter_x0) & ~(intptr_t)0xff);
-
-  /* Adjust base pointer address for this source line */
-  src -= taps / 2 - 1;
-
+static void convolve_avg_horiz(const uint8_t *src, ptrdiff_t src_stride,
+                               uint8_t *dst, ptrdiff_t dst_stride,
+                               const subpel_kernel *x_filters,
+                               int x0_q4, int x_step_q4, int w, int h) {
+  int x, y;
+  src -= SUBPEL_TAPS / 2 - 1;
   for (y = 0; y < h; ++y) {
-    /* Initial phase offset */
-    int x_q4 = (int)(filter_x0 - filter_x_base) / taps;
-
+    int x_q4 = x0_q4;
     for (x = 0; x < w; ++x) {
-      /* Per-pixel src offset */
-      const int src_x = x_q4 >> SUBPEL_BITS;
-      int sum = 0;
-
-      /* Pointer to filter to use */
-      const int16_t *const filter_x = filter_x_base +
-          (x_q4 & SUBPEL_MASK) * taps;
-
-      for (k = 0; k < taps; ++k)
-        sum += src[src_x + k] * filter_x[k];
-
+      const uint8_t *const src_x = &src[x_q4 >> SUBPEL_BITS];
+      const int16_t *const x_filter = x_filters[x_q4 & SUBPEL_MASK];
+      int k, sum = 0;
+      for (k = 0; k < SUBPEL_TAPS; ++k)
+        sum += src_x[k] * x_filter[k];
       dst[x] = ROUND_POWER_OF_TWO(dst[x] +
-                   clip_pixel(ROUND_POWER_OF_TWO(sum, FILTER_BITS)), 1);
-
-      /* Move to the next source pixel */
+          clip_pixel(ROUND_POWER_OF_TWO(sum, FILTER_BITS)), 1);
       x_q4 += x_step_q4;
     }
     src += src_stride;
@@ -101,41 +63,22 @@
   }
 }
 
-static void convolve_vert_c(const uint8_t *src, ptrdiff_t src_stride,
-                            uint8_t *dst, ptrdiff_t dst_stride,
-                            const int16_t *filter_x, int x_step_q4,
-                            const int16_t *filter_y0, int y_step_q4,
-                            int w, int h, int taps) {
-  int x, y, k;
-
-  /* NOTE: This assumes that the filter table is 256-byte aligned. */
-  /* TODO(agrange) Modify to make independent of table alignment. */
-  const int16_t *const filter_y_base =
-      (const int16_t *)(((intptr_t)filter_y0) & ~(intptr_t)0xff);
-
-  /* Adjust base pointer address for this source column */
-  src -= src_stride * (taps / 2 - 1);
+static void convolve_vert(const uint8_t *src, ptrdiff_t src_stride,
+                          uint8_t *dst, ptrdiff_t dst_stride,
+                          const subpel_kernel *y_filters,
+                          int y0_q4, int y_step_q4, int w, int h) {
+  int x, y;
+  src -= src_stride * (SUBPEL_TAPS / 2 - 1);
 
   for (x = 0; x < w; ++x) {
-    /* Initial phase offset */
-    int y_q4 = (int)(filter_y0 - filter_y_base) / taps;
-
+    int y_q4 = y0_q4;
     for (y = 0; y < h; ++y) {
-      /* Per-pixel src offset */
-      const int src_y = y_q4 >> SUBPEL_BITS;
-      int sum = 0;
-
-      /* Pointer to filter to use */
-      const int16_t *const filter_y = filter_y_base +
-          (y_q4 & SUBPEL_MASK) * taps;
-
-      for (k = 0; k < taps; ++k)
-        sum += src[(src_y + k) * src_stride] * filter_y[k];
-
-      dst[y * dst_stride] =
-          clip_pixel(ROUND_POWER_OF_TWO(sum, FILTER_BITS));
-
-      /* Move to the next source pixel */
+      const unsigned char *src_y = &src[(y_q4 >> SUBPEL_BITS) * src_stride];
+      const int16_t *const y_filter = y_filters[y_q4 & SUBPEL_MASK];
+      int k, sum = 0;
+      for (k = 0; k < SUBPEL_TAPS; ++k)
+        sum += src_y[k * src_stride] * y_filter[k];
+      dst[y * dst_stride] = clip_pixel(ROUND_POWER_OF_TWO(sum, FILTER_BITS));
       y_q4 += y_step_q4;
     }
     ++src;
@@ -143,41 +86,23 @@
   }
 }
 
-static void convolve_avg_vert_c(const uint8_t *src, ptrdiff_t src_stride,
-                                uint8_t *dst, ptrdiff_t dst_stride,
-                                const int16_t *filter_x, int x_step_q4,
-                                const int16_t *filter_y0, int y_step_q4,
-                                int w, int h, int taps) {
-  int x, y, k;
-
-  /* NOTE: This assumes that the filter table is 256-byte aligned. */
-  /* TODO(agrange) Modify to make independent of table alignment. */
-  const int16_t *const filter_y_base =
-      (const int16_t *)(((intptr_t)filter_y0) & ~(intptr_t)0xff);
-
-  /* Adjust base pointer address for this source column */
-  src -= src_stride * (taps / 2 - 1);
+static void convolve_avg_vert(const uint8_t *src, ptrdiff_t src_stride,
+                              uint8_t *dst, ptrdiff_t dst_stride,
+                              const subpel_kernel *y_filters,
+                              int y0_q4, int y_step_q4, int w, int h) {
+  int x, y;
+  src -= src_stride * (SUBPEL_TAPS / 2 - 1);
 
   for (x = 0; x < w; ++x) {
-    /* Initial phase offset */
-    int y_q4 = (int)(filter_y0 - filter_y_base) / taps;
-
+    int y_q4 = y0_q4;
     for (y = 0; y < h; ++y) {
-      /* Per-pixel src offset */
-      const int src_y = y_q4 >> SUBPEL_BITS;
-      int sum = 0;
-
-      /* Pointer to filter to use */
-      const int16_t *const filter_y = filter_y_base +
-          (y_q4 & SUBPEL_MASK) * taps;
-
-      for (k = 0; k < taps; ++k)
-        sum += src[(src_y + k) * src_stride] * filter_y[k];
-
+      const unsigned char *src_y = &src[(y_q4 >> SUBPEL_BITS) * src_stride];
+      const int16_t *const y_filter = y_filters[y_q4 & SUBPEL_MASK];
+      int k, sum = 0;
+      for (k = 0; k < SUBPEL_TAPS; ++k)
+        sum += src_y[k * src_stride] * y_filter[k];
       dst[y * dst_stride] = ROUND_POWER_OF_TWO(dst[y * dst_stride] +
-           clip_pixel(ROUND_POWER_OF_TWO(sum, FILTER_BITS)), 1);
-
-      /* Move to the next source pixel */
+          clip_pixel(ROUND_POWER_OF_TWO(sum, FILTER_BITS)), 1);
       y_q4 += y_step_q4;
     }
     ++src;
@@ -185,33 +110,42 @@
   }
 }
 
-static void convolve_c(const uint8_t *src, ptrdiff_t src_stride,
-                       uint8_t *dst, ptrdiff_t dst_stride,
-                       const int16_t *filter_x, int x_step_q4,
-                       const int16_t *filter_y, int y_step_q4,
-                       int w, int h, int taps) {
-  /* Fixed size intermediate buffer places limits on parameters.
-   * Maximum intermediate_height is 324, for y_step_q4 == 80,
-   * h == 64, taps == 8.
-   * y_step_q4 of 80 allows for 1/10 scale for 5 layer svc
-   */
+static void convolve(const uint8_t *src, ptrdiff_t src_stride,
+                     uint8_t *dst, ptrdiff_t dst_stride,
+                     const subpel_kernel *const x_filters,
+                     int x0_q4, int x_step_q4,
+                     const subpel_kernel *const y_filters,
+                     int y0_q4, int y_step_q4,
+                     int w, int h) {
+  // Fixed size intermediate buffer places limits on parameters.
+  // Maximum intermediate_height is 324, for y_step_q4 == 80,
+  // h == 64, taps == 8.
+  // y_step_q4 of 80 allows for 1/10 scale for 5 layer svc
   uint8_t temp[64 * 324];
-  int intermediate_height = (((h - 1) * y_step_q4 + 15) >> 4) + taps;
+  int intermediate_height = (((h - 1) * y_step_q4 + 15) >> 4) + SUBPEL_TAPS;
 
   assert(w <= 64);
   assert(h <= 64);
-  assert(taps <= 8);
   assert(y_step_q4 <= 80);
   assert(x_step_q4 <= 80);
 
   if (intermediate_height < h)
     intermediate_height = h;
 
-  convolve_horiz_c(src - src_stride * (taps / 2 - 1), src_stride, temp, 64,
-                   filter_x, x_step_q4, filter_y, y_step_q4, w,
-                   intermediate_height, taps);
-  convolve_vert_c(temp + 64 * (taps / 2 - 1), 64, dst, dst_stride, filter_x,
-                  x_step_q4, filter_y, y_step_q4, w, h, taps);
+  convolve_horiz(src - src_stride * (SUBPEL_TAPS / 2 - 1), src_stride, temp, 64,
+                 x_filters, x0_q4, x_step_q4, w, intermediate_height);
+  convolve_vert(temp + 64 * (SUBPEL_TAPS / 2 - 1), 64, dst, dst_stride,
+                y_filters, y0_q4, y_step_q4, w, h);
+}
+
+static const subpel_kernel *get_filter_base(const int16_t *filter) {
+  // NOTE: This assumes that the filter table is 256-byte aligned.
+  // TODO(agrange) Modify to make independent of table alignment.
+  return (const subpel_kernel *)(((intptr_t)filter) & ~((intptr_t)0xFF));
+}
+
+static int get_filter_offset(const int16_t *f, const subpel_kernel *base) {
+  return (const subpel_kernel *)(intptr_t)f - base;
 }
 
 void vp9_convolve8_horiz_c(const uint8_t *src, ptrdiff_t src_stride,
@@ -219,8 +153,11 @@
                            const int16_t *filter_x, int x_step_q4,
                            const int16_t *filter_y, int y_step_q4,
                            int w, int h) {
-  convolve_horiz_c(src, src_stride, dst, dst_stride,
-                   filter_x, x_step_q4, filter_y, y_step_q4, w, h, 8);
+  const subpel_kernel *const filters_x = get_filter_base(filter_x);
+  const int x0_q4 = get_filter_offset(filter_x, filters_x);
+
+  convolve_horiz(src, src_stride, dst, dst_stride, filters_x,
+                 x0_q4, x_step_q4, w, h);
 }
 
 void vp9_convolve8_avg_horiz_c(const uint8_t *src, ptrdiff_t src_stride,
@@ -228,8 +165,11 @@
                                const int16_t *filter_x, int x_step_q4,
                                const int16_t *filter_y, int y_step_q4,
                                int w, int h) {
-  convolve_avg_horiz_c(src, src_stride, dst, dst_stride,
-                       filter_x, x_step_q4, filter_y, y_step_q4, w, h, 8);
+  const subpel_kernel *const filters_x = get_filter_base(filter_x);
+  const int x0_q4 = get_filter_offset(filter_x, filters_x);
+
+  convolve_avg_horiz(src, src_stride, dst, dst_stride, filters_x,
+                     x0_q4, x_step_q4, w, h);
 }
 
 void vp9_convolve8_vert_c(const uint8_t *src, ptrdiff_t src_stride,
@@ -237,8 +177,10 @@
                           const int16_t *filter_x, int x_step_q4,
                           const int16_t *filter_y, int y_step_q4,
                           int w, int h) {
-  convolve_vert_c(src, src_stride, dst, dst_stride,
-                  filter_x, x_step_q4, filter_y, y_step_q4, w, h, 8);
+  const subpel_kernel *const filters_y = get_filter_base(filter_y);
+  const int y0_q4 = get_filter_offset(filter_y, filters_y);
+  convolve_vert(src, src_stride, dst, dst_stride, filters_y,
+                y0_q4, y_step_q4, w, h);
 }
 
 void vp9_convolve8_avg_vert_c(const uint8_t *src, ptrdiff_t src_stride,
@@ -246,8 +188,10 @@
                               const int16_t *filter_x, int x_step_q4,
                               const int16_t *filter_y, int y_step_q4,
                               int w, int h) {
-  convolve_avg_vert_c(src, src_stride, dst, dst_stride,
-                      filter_x, x_step_q4, filter_y, y_step_q4, w, h, 8);
+  const subpel_kernel *const filters_y = get_filter_base(filter_y);
+  const int y0_q4 = get_filter_offset(filter_y, filters_y);
+  convolve_avg_vert(src, src_stride, dst, dst_stride, filters_y,
+                    y0_q4, y_step_q4, w, h);
 }
 
 void vp9_convolve8_c(const uint8_t *src, ptrdiff_t src_stride,
@@ -255,8 +199,15 @@
                      const int16_t *filter_x, int x_step_q4,
                      const int16_t *filter_y, int y_step_q4,
                      int w, int h) {
-  convolve_c(src, src_stride, dst, dst_stride,
-             filter_x, x_step_q4, filter_y, y_step_q4, w, h, 8);
+  const subpel_kernel *const filters_x = get_filter_base(filter_x);
+  const int x0_q4 = get_filter_offset(filter_x, filters_x);
+
+  const subpel_kernel *const filters_y = get_filter_base(filter_y);
+  const int y0_q4 = get_filter_offset(filter_y, filters_y);
+
+  convolve(src, src_stride, dst, dst_stride,
+           filters_x, x0_q4, x_step_q4,
+           filters_y, y0_q4, y_step_q4, w, h);
 }
 
 void vp9_convolve8_avg_c(const uint8_t *src, ptrdiff_t src_stride,
@@ -269,9 +220,9 @@
   assert(w <= 64);
   assert(h <= 64);
 
-  vp9_convolve8(src, src_stride, temp, 64,
-               filter_x, x_step_q4, filter_y, y_step_q4, w, h);
-  vp9_convolve_avg(temp, 64, dst, dst_stride, NULL, 0, NULL, 0, w, h);
+  vp9_convolve8_c(src, src_stride, temp, 64,
+                  filter_x, x_step_q4, filter_y, y_step_q4, w, h);
+  vp9_convolve_avg_c(temp, 64, dst, dst_stride, NULL, 0, NULL, 0, w, h);
 }
 
 void vp9_convolve_copy_c(const uint8_t *src, ptrdiff_t src_stride,
diff --git a/vp9/common/vp9_entropy.c b/vp9/common/vp9_entropy.c
index adab33f..13e954e 100644
--- a/vp9/common/vp9_entropy.c
+++ b/vp9/common/vp9_entropy.c
@@ -16,25 +16,6 @@
 #include "vpx/vpx_integer.h"
 
 
-DECLARE_ALIGNED(16, const uint8_t, vp9_norm[256]) = {
-  0, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
-  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
 DECLARE_ALIGNED(16, const uint8_t, vp9_coefband_trans_8x8plus[1024]) = {
   0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4,
   4, 4, 4, 4, 4, 5,
diff --git a/vp9/common/vp9_entropy.h b/vp9/common/vp9_entropy.h
index 721917f..f43a85f 100644
--- a/vp9/common/vp9_entropy.h
+++ b/vp9/common/vp9_entropy.h
@@ -16,7 +16,6 @@
 #include "vp9/common/vp9_blockd.h"
 #include "vp9/common/vp9_common.h"
 #include "vp9/common/vp9_scan.h"
-#include "vp9/common/vp9_treecoder.h"
 #include "vp9/common/vp9_entropymode.h"
 
 #define DIFF_UPDATE_PROB 252
@@ -54,7 +53,6 @@
 // indexed by token value
 extern const vp9_extra_bit vp9_extra_bits[ENTROPY_TOKENS];
 
-#define MAX_PROB                255
 #define DCT_MAX_VALUE           16384
 
 /* Coefficients are predicted via a 3-dimensional probability table. */
@@ -166,7 +164,7 @@
       left_ec  = !!*(const uint64_t *)l;
       break;
     default:
-      assert(!"Invalid transform size.");
+      assert(0 && "Invalid transform size.");
   }
 
   return combine_entropy_contexts(above_ec, left_ec);
diff --git a/vp9/common/vp9_entropymode.h b/vp9/common/vp9_entropymode.h
index df58bea..5312553 100644
--- a/vp9/common/vp9_entropymode.h
+++ b/vp9/common/vp9_entropymode.h
@@ -12,7 +12,6 @@
 #define VP9_COMMON_VP9_ENTROPYMODE_H_
 
 #include "vp9/common/vp9_blockd.h"
-#include "vp9/common/vp9_treecoder.h"
 
 #define TX_SIZE_CONTEXTS 2
 #define SWITCHABLE_FILTERS 3   // number of switchable filters
diff --git a/vp9/common/vp9_entropymv.h b/vp9/common/vp9_entropymv.h
index 3175a1e..48cb82d 100644
--- a/vp9/common/vp9_entropymv.h
+++ b/vp9/common/vp9_entropymv.h
@@ -12,7 +12,6 @@
 #ifndef VP9_COMMON_VP9_ENTROPYMV_H_
 #define VP9_COMMON_VP9_ENTROPYMV_H_
 
-#include "vp9/common/vp9_treecoder.h"
 #include "./vpx_config.h"
 #include "vp9/common/vp9_blockd.h"
 
diff --git a/vp9/common/vp9_findnearmv.c b/vp9/common/vp9_findnearmv.c
deleted file mode 100644
index ad97c02..0000000
--- a/vp9/common/vp9_findnearmv.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#include "vp9/common/vp9_findnearmv.h"
-#include "vp9/common/vp9_mvref_common.h"
-
-static void lower_mv_precision(MV *mv, int allow_hp) {
-  const int use_hp = allow_hp && vp9_use_mv_hp(mv);
-  if (!use_hp) {
-    if (mv->row & 1)
-      mv->row += (mv->row > 0 ? -1 : 1);
-    if (mv->col & 1)
-      mv->col += (mv->col > 0 ? -1 : 1);
-  }
-}
-
-
-void vp9_find_best_ref_mvs(MACROBLOCKD *xd, int allow_hp,
-                           int_mv *mvlist, int_mv *nearest, int_mv *near) {
-  int i;
-  // Make sure all the candidates are properly clamped etc
-  for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i) {
-    lower_mv_precision(&mvlist[i].as_mv, allow_hp);
-    clamp_mv2(&mvlist[i].as_mv, xd);
-  }
-  *nearest = mvlist[0];
-  *near = mvlist[1];
-}
-
-void vp9_append_sub8x8_mvs_for_idx(VP9_COMMON *cm, MACROBLOCKD *xd,
-                                   const TileInfo *const tile,
-                                   int_mv *dst_nearest, int_mv *dst_near,
-                                   int block_idx, int ref_idx,
-                                   int mi_row, int mi_col) {
-  int_mv mv_list[MAX_MV_REF_CANDIDATES];
-  MODE_INFO *const mi = xd->mi_8x8[0];
-  b_mode_info *bmi = mi->bmi;
-  int n;
-
-  assert(ref_idx == 0 || ref_idx == 1);
-  assert(MAX_MV_REF_CANDIDATES == 2);
-
-  vp9_find_mv_refs_idx(cm, xd, tile, mi, xd->last_mi,
-                       mi->mbmi.ref_frame[ref_idx],
-                       mv_list, block_idx, mi_row, mi_col);
-
-  dst_near->as_int = 0;
-  if (block_idx == 0) {
-    dst_nearest->as_int = mv_list[0].as_int;
-    dst_near->as_int = mv_list[1].as_int;
-  } else if (block_idx == 1 || block_idx == 2) {
-    dst_nearest->as_int = bmi[0].as_mv[ref_idx].as_int;
-    for (n = 0; n < MAX_MV_REF_CANDIDATES; ++n)
-      if (dst_nearest->as_int != mv_list[n].as_int) {
-        dst_near->as_int = mv_list[n].as_int;
-        break;
-      }
-  } else {
-    int_mv candidates[2 + MAX_MV_REF_CANDIDATES];
-    candidates[0] = bmi[1].as_mv[ref_idx];
-    candidates[1] = bmi[0].as_mv[ref_idx];
-    candidates[2] = mv_list[0];
-    candidates[3] = mv_list[1];
-
-    assert(block_idx == 3);
-    dst_nearest->as_int = bmi[2].as_mv[ref_idx].as_int;
-    for (n = 0; n < 2 + MAX_MV_REF_CANDIDATES; ++n) {
-      if (dst_nearest->as_int != candidates[n].as_int) {
-        dst_near->as_int = candidates[n].as_int;
-        break;
-      }
-    }
-  }
-}
diff --git a/vp9/common/vp9_findnearmv.h b/vp9/common/vp9_findnearmv.h
deleted file mode 100644
index e9d4e11..0000000
--- a/vp9/common/vp9_findnearmv.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-
-#ifndef VP9_COMMON_VP9_FINDNEARMV_H_
-#define VP9_COMMON_VP9_FINDNEARMV_H_
-
-#include "vp9/common/vp9_mv.h"
-#include "vp9/common/vp9_blockd.h"
-#include "vp9/common/vp9_treecoder.h"
-#include "vp9/common/vp9_onyxc_int.h"
-
-#define LEFT_TOP_MARGIN     ((VP9BORDERINPIXELS - VP9_INTERP_EXTEND) << 3)
-#define RIGHT_BOTTOM_MARGIN ((VP9BORDERINPIXELS - VP9_INTERP_EXTEND) << 3)
-
-// check a list of motion vectors by sad score using a number rows of pixels
-// above and a number cols of pixels in the left to select the one with best
-// score to use as ref motion vector
-void vp9_find_best_ref_mvs(MACROBLOCKD *xd, int allow_hp,
-                           int_mv *mvlist, int_mv *nearest, int_mv *near);
-
-// TODO(jingning): this mv clamping function should be block size dependent.
-static void clamp_mv2(MV *mv, const MACROBLOCKD *xd) {
-  clamp_mv(mv, xd->mb_to_left_edge - LEFT_TOP_MARGIN,
-               xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN,
-               xd->mb_to_top_edge - LEFT_TOP_MARGIN,
-               xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN);
-}
-
-void vp9_append_sub8x8_mvs_for_idx(VP9_COMMON *cm, MACROBLOCKD *xd,
-                                   const TileInfo *const tile,
-                                   int_mv *dst_nearest,
-                                   int_mv *dst_near,
-                                   int block_idx, int ref_idx,
-                                   int mi_row, int mi_col);
-
-#endif  // VP9_COMMON_VP9_FINDNEARMV_H_
diff --git a/vp9/common/vp9_loopfilter.c b/vp9/common/vp9_loopfilter.c
index 40d8ffd..2266e0e 100644
--- a/vp9/common/vp9_loopfilter.c
+++ b/vp9/common/vp9_loopfilter.c
@@ -221,23 +221,10 @@
 static const uint16_t left_border_uv =  0x1111;
 static const uint16_t above_border_uv = 0x000f;
 
-
-static void lf_init_lut(loop_filter_info_n *lfi) {
-  lfi->mode_lf_lut[DC_PRED] = 0;
-  lfi->mode_lf_lut[D45_PRED] = 0;
-  lfi->mode_lf_lut[D135_PRED] = 0;
-  lfi->mode_lf_lut[D117_PRED] = 0;
-  lfi->mode_lf_lut[D153_PRED] = 0;
-  lfi->mode_lf_lut[D207_PRED] = 0;
-  lfi->mode_lf_lut[D63_PRED] = 0;
-  lfi->mode_lf_lut[V_PRED] = 0;
-  lfi->mode_lf_lut[H_PRED] = 0;
-  lfi->mode_lf_lut[TM_PRED] = 0;
-  lfi->mode_lf_lut[ZEROMV]  = 0;
-  lfi->mode_lf_lut[NEARESTMV] = 1;
-  lfi->mode_lf_lut[NEARMV] = 1;
-  lfi->mode_lf_lut[NEWMV] = 1;
-}
+static const int mode_lf_lut[MB_MODE_COUNT] = {
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // INTRA_MODES
+  1, 1, 0, 1                     // INTER_MODES (ZEROMV == 0)
+};
 
 static void update_sharpness(loop_filter_info_n *lfi, int sharpness_lvl) {
   int lvl;
@@ -270,9 +257,6 @@
   update_sharpness(lfi, lf->sharpness_level);
   lf->last_sharpness_level = lf->sharpness_level;
 
-  // init LUT for lvl  and hev thr picking
-  lf_init_lut(lfi);
-
   // init hev threshold const vectors
   for (lvl = 0; lvl <= MAX_LOOP_FILTER; lvl++)
     vpx_memset(lfi->lfthr[lvl].hev_thr, (lvl >> 4), SIMD_WIDTH);
@@ -355,56 +339,56 @@
     if (mask & 1) {
       if ((mask_16x16_0 | mask_16x16_1) & 1) {
         if ((mask_16x16_0 & mask_16x16_1) & 1) {
-          vp9_mb_lpf_vertical_edge_w_16(s, pitch, lfi0->mblim, lfi0->lim,
-                                     lfi0->hev_thr);
+          vp9_lpf_vertical_16_dual(s, pitch, lfi0->mblim, lfi0->lim,
+                                   lfi0->hev_thr);
         } else if (mask_16x16_0 & 1) {
-          vp9_mb_lpf_vertical_edge_w(s, pitch, lfi0->mblim, lfi0->lim,
-                                     lfi0->hev_thr);
+          vp9_lpf_vertical_16(s, pitch, lfi0->mblim, lfi0->lim,
+                              lfi0->hev_thr);
         } else {
-          vp9_mb_lpf_vertical_edge_w(s + 8 *pitch, pitch, lfi1->mblim,
-                                     lfi1->lim, lfi1->hev_thr);
+          vp9_lpf_vertical_16(s + 8 *pitch, pitch, lfi1->mblim,
+                              lfi1->lim, lfi1->hev_thr);
         }
       }
 
       if ((mask_8x8_0 | mask_8x8_1) & 1) {
         if ((mask_8x8_0 & mask_8x8_1) & 1) {
-          vp9_mbloop_filter_vertical_edge_16(s, pitch, lfi0->mblim, lfi0->lim,
-                                          lfi0->hev_thr, lfi1->mblim,
-                                          lfi1->lim, lfi1->hev_thr);
+          vp9_lpf_vertical_8_dual(s, pitch, lfi0->mblim, lfi0->lim,
+                                  lfi0->hev_thr, lfi1->mblim, lfi1->lim,
+                                  lfi1->hev_thr);
         } else if (mask_8x8_0 & 1) {
-          vp9_mbloop_filter_vertical_edge(s, pitch, lfi0->mblim, lfi0->lim,
-                                          lfi0->hev_thr, 1);
+          vp9_lpf_vertical_8(s, pitch, lfi0->mblim, lfi0->lim, lfi0->hev_thr,
+                             1);
         } else {
-          vp9_mbloop_filter_vertical_edge(s + 8 *pitch, pitch, lfi1->mblim,
-                                          lfi1->lim, lfi1->hev_thr, 1);
+          vp9_lpf_vertical_8(s + 8 * pitch, pitch, lfi1->mblim, lfi1->lim,
+                             lfi1->hev_thr, 1);
         }
       }
 
       if ((mask_4x4_0 | mask_4x4_1) & 1) {
         if ((mask_4x4_0 & mask_4x4_1) & 1) {
-          vp9_loop_filter_vertical_edge_16(s, pitch, lfi0->mblim, lfi0->lim,
-                                        lfi0->hev_thr, lfi1->mblim,
-                                        lfi1->lim, lfi1->hev_thr);
+          vp9_lpf_vertical_4_dual(s, pitch, lfi0->mblim, lfi0->lim,
+                                  lfi0->hev_thr, lfi1->mblim, lfi1->lim,
+                                  lfi1->hev_thr);
         } else if (mask_4x4_0 & 1) {
-          vp9_loop_filter_vertical_edge(s, pitch, lfi0->mblim, lfi0->lim,
-                                        lfi0->hev_thr, 1);
+          vp9_lpf_vertical_4(s, pitch, lfi0->mblim, lfi0->lim, lfi0->hev_thr,
+                             1);
         } else {
-          vp9_loop_filter_vertical_edge(s + 8 *pitch, pitch, lfi1->mblim,
-                                        lfi1->lim, lfi1->hev_thr, 1);
+          vp9_lpf_vertical_4(s + 8 * pitch, pitch, lfi1->mblim, lfi1->lim,
+                             lfi1->hev_thr, 1);
         }
       }
 
       if ((mask_4x4_int_0 | mask_4x4_int_1) & 1) {
         if ((mask_4x4_int_0 & mask_4x4_int_1) & 1) {
-          vp9_loop_filter_vertical_edge_16(s + 4, pitch, lfi0->mblim, lfi0->lim,
-                                        lfi0->hev_thr, lfi1->mblim,
-                                        lfi1->lim, lfi1->hev_thr);
+          vp9_lpf_vertical_4_dual(s + 4, pitch, lfi0->mblim, lfi0->lim,
+                                  lfi0->hev_thr, lfi1->mblim, lfi1->lim,
+                                  lfi1->hev_thr);
         } else if (mask_4x4_int_0 & 1) {
-          vp9_loop_filter_vertical_edge(s + 4, pitch, lfi0->mblim, lfi0->lim,
-                                        lfi0->hev_thr, 1);
+          vp9_lpf_vertical_4(s + 4, pitch, lfi0->mblim, lfi0->lim,
+                             lfi0->hev_thr, 1);
         } else {
-          vp9_loop_filter_vertical_edge(s + 8 *pitch + 4, pitch, lfi1->mblim,
-                                        lfi1->lim, lfi1->hev_thr, 1);
+          vp9_lpf_vertical_4(s + 8 * pitch + 4, pitch, lfi1->mblim, lfi1->lim,
+                             lfi1->hev_thr, 1);
         }
       }
     }
@@ -440,81 +424,73 @@
     if (mask & 1) {
       if (mask_16x16 & 1) {
         if ((mask_16x16 & 3) == 3) {
-          vp9_mb_lpf_horizontal_edge_w(s, pitch, lfi->mblim, lfi->lim,
-                                       lfi->hev_thr, 2);
+          vp9_lpf_horizontal_16(s, pitch, lfi->mblim, lfi->lim,
+                                lfi->hev_thr, 2);
           count = 2;
         } else {
-          vp9_mb_lpf_horizontal_edge_w(s, pitch, lfi->mblim, lfi->lim,
-                                       lfi->hev_thr, 1);
+          vp9_lpf_horizontal_16(s, pitch, lfi->mblim, lfi->lim,
+                                lfi->hev_thr, 1);
         }
       } else if (mask_8x8 & 1) {
         if ((mask_8x8 & 3) == 3) {
           // Next block's thresholds
           const loop_filter_thresh *lfin = lfi_n->lfthr + *(lfl + 1);
 
-          vp9_mbloop_filter_horizontal_edge_16(s, pitch, lfi->mblim,
-                                               lfi->lim, lfi->hev_thr,
-                                               lfin->mblim, lfin->lim,
-                                               lfin->hev_thr);
+          vp9_lpf_horizontal_8_dual(s, pitch, lfi->mblim, lfi->lim,
+                                    lfi->hev_thr, lfin->mblim, lfin->lim,
+                                    lfin->hev_thr);
 
           if ((mask_4x4_int & 3) == 3) {
-            vp9_loop_filter_horizontal_edge_16(s + 4 * pitch, pitch, lfi->mblim,
-                                               lfi->lim, lfi->hev_thr,
-                                               lfin->mblim, lfin->lim,
-                                               lfin->hev_thr);
+            vp9_lpf_horizontal_4_dual(s + 4 * pitch, pitch, lfi->mblim,
+                                      lfi->lim, lfi->hev_thr, lfin->mblim,
+                                      lfin->lim, lfin->hev_thr);
           } else {
             if (mask_4x4_int & 1)
-              vp9_loop_filter_horizontal_edge(s + 4 * pitch, pitch, lfi->mblim,
-                                              lfi->lim, lfi->hev_thr, 1);
+              vp9_lpf_horizontal_4(s + 4 * pitch, pitch, lfi->mblim, lfi->lim,
+                                   lfi->hev_thr, 1);
             else if (mask_4x4_int & 2)
-              vp9_loop_filter_horizontal_edge(s + 8 + 4 * pitch, pitch,
-                                              lfin->mblim, lfin->lim,
-                                              lfin->hev_thr, 1);
+              vp9_lpf_horizontal_4(s + 8 + 4 * pitch, pitch, lfin->mblim,
+                                   lfin->lim, lfin->hev_thr, 1);
           }
           count = 2;
         } else {
-          vp9_mbloop_filter_horizontal_edge(s, pitch, lfi->mblim, lfi->lim,
-                                            lfi->hev_thr, 1);
+          vp9_lpf_horizontal_8(s, pitch, lfi->mblim, lfi->lim, lfi->hev_thr, 1);
 
           if (mask_4x4_int & 1)
-            vp9_loop_filter_horizontal_edge(s + 4 * pitch, pitch, lfi->mblim,
-                                            lfi->lim, lfi->hev_thr, 1);
+            vp9_lpf_horizontal_4(s + 4 * pitch, pitch, lfi->mblim, lfi->lim,
+                                 lfi->hev_thr, 1);
         }
       } else if (mask_4x4 & 1) {
         if ((mask_4x4 & 3) == 3) {
           // Next block's thresholds
           const loop_filter_thresh *lfin = lfi_n->lfthr + *(lfl + 1);
 
-          vp9_loop_filter_horizontal_edge_16(s, pitch, lfi->mblim,
-                                             lfi->lim, lfi->hev_thr,
-                                             lfin->mblim, lfin->lim,
-                                             lfin->hev_thr);
+          vp9_lpf_horizontal_4_dual(s, pitch, lfi->mblim, lfi->lim,
+                                    lfi->hev_thr, lfin->mblim, lfin->lim,
+                                    lfin->hev_thr);
           if ((mask_4x4_int & 3) == 3) {
-            vp9_loop_filter_horizontal_edge_16(s + 4 * pitch, pitch, lfi->mblim,
-                                               lfi->lim, lfi->hev_thr,
-                                               lfin->mblim, lfin->lim,
-                                               lfin->hev_thr);
+            vp9_lpf_horizontal_4_dual(s + 4 * pitch, pitch, lfi->mblim,
+                                      lfi->lim, lfi->hev_thr, lfin->mblim,
+                                      lfin->lim, lfin->hev_thr);
           } else {
             if (mask_4x4_int & 1)
-              vp9_loop_filter_horizontal_edge(s + 4 * pitch, pitch, lfi->mblim,
-                                              lfi->lim, lfi->hev_thr, 1);
+              vp9_lpf_horizontal_4(s + 4 * pitch, pitch, lfi->mblim, lfi->lim,
+                                   lfi->hev_thr, 1);
             else if (mask_4x4_int & 2)
-              vp9_loop_filter_horizontal_edge(s + 8 + 4 * pitch, pitch,
-                                              lfin->mblim, lfin->lim,
-                                              lfin->hev_thr, 1);
+              vp9_lpf_horizontal_4(s + 8 + 4 * pitch, pitch, lfin->mblim,
+                                   lfin->lim, lfin->hev_thr, 1);
           }
           count = 2;
         } else {
-        vp9_loop_filter_horizontal_edge(s, pitch, lfi->mblim, lfi->lim,
-                                        lfi->hev_thr, 1);
+          vp9_lpf_horizontal_4(s, pitch, lfi->mblim, lfi->lim, lfi->hev_thr, 1);
 
-        if (mask_4x4_int & 1)
-          vp9_loop_filter_horizontal_edge(s + 4 * pitch, pitch, lfi->mblim,
-                                          lfi->lim, lfi->hev_thr, 1);
+          if (mask_4x4_int & 1)
+            vp9_lpf_horizontal_4(s + 4 * pitch, pitch, lfi->mblim, lfi->lim,
+                                 lfi->hev_thr, 1);
         }
       } else if (mask_4x4_int & 1) {
-        vp9_loop_filter_horizontal_edge(s + 4 * pitch, pitch, lfi->mblim,
-                                        lfi->lim, lfi->hev_thr, 1);
+        vp9_lpf_horizontal_4(s + 4 * pitch, pitch, lfi->mblim, lfi->lim,
+                             lfi->hev_thr, 1);
       }
     }
     s += 8 * count;
@@ -543,8 +519,7 @@
   const int skip = mi->mbmi.skip_coeff;
   const int seg = mi->mbmi.segment_id;
   const int ref = mi->mbmi.ref_frame[0];
-  const int mode = lfi_n->mode_lf_lut[mi->mbmi.mode];
-  const int filter_level = lfi_n->lvl[seg][ref][mode];
+  const int filter_level = lfi_n->lvl[seg][ref][mode_lf_lut[mi->mbmi.mode]];
   uint64_t *left_y = &lfm->left_y[tx_size_y];
   uint64_t *above_y = &lfm->above_y[tx_size_y];
   uint64_t *int_4x4_y = &lfm->int_4x4_y;
@@ -625,8 +600,7 @@
   const int skip = mi->mbmi.skip_coeff;
   const int seg = mi->mbmi.segment_id;
   const int ref = mi->mbmi.ref_frame[0];
-  const int mode = lfi_n->mode_lf_lut[mi->mbmi.mode];
-  const int filter_level = lfi_n->lvl[seg][ref][mode];
+  const int filter_level = lfi_n->lvl[seg][ref][mode_lf_lut[mi->mbmi.mode]];
   uint64_t *left_y = &lfm->left_y[tx_size_y];
   uint64_t *above_y = &lfm->above_y[tx_size_y];
   uint64_t *int_4x4_y = &lfm->int_4x4_y;
@@ -919,10 +893,7 @@
                      const MB_MODE_INFO *mbmi) {
   const int seg = mbmi->segment_id;
   const int ref = mbmi->ref_frame[0];
-  const int mode = lfi_n->mode_lf_lut[mbmi->mode];
-  const int filter_level = lfi_n->lvl[seg][ref][mode];
-
-  return filter_level;
+  return lfi_n->lvl[seg][ref][mode_lf_lut[mbmi->mode]];
 }
 
 static void filter_selectively_vert(uint8_t *s, int pitch,
@@ -940,19 +911,15 @@
 
     if (mask & 1) {
       if (mask_16x16 & 1) {
-        vp9_mb_lpf_vertical_edge_w(s, pitch, lfi->mblim, lfi->lim,
-                                   lfi->hev_thr);
+        vp9_lpf_vertical_16(s, pitch, lfi->mblim, lfi->lim, lfi->hev_thr);
       } else if (mask_8x8 & 1) {
-        vp9_mbloop_filter_vertical_edge(s, pitch, lfi->mblim, lfi->lim,
-                                        lfi->hev_thr, 1);
+        vp9_lpf_vertical_8(s, pitch, lfi->mblim, lfi->lim, lfi->hev_thr, 1);
       } else if (mask_4x4 & 1) {
-        vp9_loop_filter_vertical_edge(s, pitch, lfi->mblim, lfi->lim,
-                                      lfi->hev_thr, 1);
+        vp9_lpf_vertical_4(s, pitch, lfi->mblim, lfi->lim, lfi->hev_thr, 1);
       }
     }
     if (mask_4x4_int & 1)
-      vp9_loop_filter_vertical_edge(s + 4, pitch, lfi->mblim, lfi->lim,
-                                    lfi->hev_thr, 1);
+      vp9_lpf_vertical_4(s + 4, pitch, lfi->mblim, lfi->lim, lfi->hev_thr, 1);
     s += 8;
     lfl += 1;
     mask_16x16 >>= 1;
@@ -989,15 +956,16 @@
     // Determine the vertical edges that need filtering
     for (c = 0; c < MI_BLOCK_SIZE && mi_col + c < cm->mi_cols; c += col_step) {
       const MODE_INFO *mi = mi_8x8[c];
+      const BLOCK_SIZE sb_type = mi[0].mbmi.sb_type;
       const int skip_this = mi[0].mbmi.skip_coeff
                             && is_inter_block(&mi[0].mbmi);
       // left edge of current unit is block/partition edge -> no skip
-      const int block_edge_left = b_width_log2(mi[0].mbmi.sb_type) ?
-          !(c & ((1 << (b_width_log2(mi[0].mbmi.sb_type)-1)) - 1)) : 1;
+      const int block_edge_left = (num_4x4_blocks_wide_lookup[sb_type] > 1) ?
+          !(c & (num_8x8_blocks_wide_lookup[sb_type] - 1)) : 1;
       const int skip_this_c = skip_this && !block_edge_left;
       // top edge of current unit is block/partition edge -> no skip
-      const int block_edge_above = b_height_log2(mi[0].mbmi.sb_type) ?
-          !(r & ((1 << (b_height_log2(mi[0].mbmi.sb_type)-1)) - 1)) : 1;
+      const int block_edge_above = (num_4x4_blocks_high_lookup[sb_type] > 1) ?
+          !(r & (num_8x8_blocks_high_lookup[sb_type] - 1)) : 1;
       const int skip_this_r = skip_this && !block_edge_above;
       const TX_SIZE tx_size = (plane->plane_type == PLANE_TYPE_UV)
                             ? get_uv_tx_size(&mi[0].mbmi)
diff --git a/vp9/common/vp9_loopfilter.h b/vp9/common/vp9_loopfilter.h
index 62389ea..98fac96 100644
--- a/vp9/common/vp9_loopfilter.h
+++ b/vp9/common/vp9_loopfilter.h
@@ -54,7 +54,6 @@
 typedef struct {
   loop_filter_thresh lfthr[MAX_LOOP_FILTER + 1];
   uint8_t lvl[MAX_SEGMENTS][MAX_REF_FRAMES][MAX_MODE_LF_DELTAS];
-  uint8_t mode_lf_lut[MB_MODE_COUNT];
 } loop_filter_info_n;
 
 /* assorted loopfilter functions which get used elsewhere */
diff --git a/vp9/common/vp9_loopfilter_filters.c b/vp9/common/vp9_loopfilter_filters.c
index f2e910f..25d3311 100644
--- a/vp9/common/vp9_loopfilter_filters.c
+++ b/vp9/common/vp9_loopfilter_filters.c
@@ -70,7 +70,7 @@
   return hev;
 }
 
-static INLINE void filter4(int8_t mask, uint8_t hev, uint8_t *op1,
+static INLINE void filter4(int8_t mask, uint8_t thresh, uint8_t *op1,
                            uint8_t *op0, uint8_t *oq0, uint8_t *oq1) {
   int8_t filter1, filter2;
 
@@ -78,6 +78,7 @@
   const int8_t ps0 = (int8_t) *op0 ^ 0x80;
   const int8_t qs0 = (int8_t) *oq0 ^ 0x80;
   const int8_t qs1 = (int8_t) *oq1 ^ 0x80;
+  const uint8_t hev = hev_mask(thresh, *op1, *op0, *oq0, *oq1);
 
   // add outer taps if we have high edge variance
   int8_t filter = signed_char_clamp(ps1 - qs1) & hev;
@@ -101,11 +102,9 @@
   *op1 = signed_char_clamp(ps1 + filter) ^ 0x80;
 }
 
-void vp9_loop_filter_horizontal_edge_c(uint8_t *s, int p /* pitch */,
-                                       const uint8_t *blimit,
-                                       const uint8_t *limit,
-                                       const uint8_t *thresh,
-                                       int count) {
+void vp9_lpf_horizontal_4_c(uint8_t *s, int p /* pitch */,
+                            const uint8_t *blimit, const uint8_t *limit,
+                            const uint8_t *thresh, int count) {
   int i;
 
   // loop filter designed to work using chars so that we can make maximum use
@@ -115,28 +114,22 @@
     const uint8_t q0 = s[0 * p],  q1 = s[1 * p],  q2 = s[2 * p],  q3 = s[3 * p];
     const int8_t mask = filter_mask(*limit, *blimit,
                                     p3, p2, p1, p0, q0, q1, q2, q3);
-    const int8_t hev = hev_mask(*thresh, p1, p0, q0, q1);
-    filter4(mask, hev, s - 2 * p, s - 1 * p, s, s + 1 * p);
+    filter4(mask, *thresh, s - 2 * p, s - 1 * p, s, s + 1 * p);
     ++s;
   }
 }
 
-void vp9_loop_filter_horizontal_edge_16_c(uint8_t *s, int p,
-                                          const uint8_t *blimit0,
-                                          const uint8_t *limit0,
-                                          const uint8_t *thresh0,
-                                          const uint8_t *blimit1,
-                                          const uint8_t *limit1,
-                                          const uint8_t *thresh1) {
-  vp9_loop_filter_horizontal_edge_c(s, p, blimit0, limit0, thresh0, 1);
-  vp9_loop_filter_horizontal_edge_c(s + 8, p, blimit1, limit1, thresh1, 1);
+void vp9_lpf_horizontal_4_dual_c(uint8_t *s, int p, const uint8_t *blimit0,
+                                 const uint8_t *limit0, const uint8_t *thresh0,
+                                 const uint8_t *blimit1, const uint8_t *limit1,
+                                 const uint8_t *thresh1) {
+  vp9_lpf_horizontal_4_c(s, p, blimit0, limit0, thresh0, 1);
+  vp9_lpf_horizontal_4_c(s + 8, p, blimit1, limit1, thresh1, 1);
 }
 
-void vp9_loop_filter_vertical_edge_c(uint8_t *s, int pitch,
-                                     const uint8_t *blimit,
-                                     const uint8_t *limit,
-                                     const uint8_t *thresh,
-                                     int count) {
+void vp9_lpf_vertical_4_c(uint8_t *s, int pitch, const uint8_t *blimit,
+                          const uint8_t *limit, const uint8_t *thresh,
+                          int count) {
   int i;
 
   // loop filter designed to work using chars so that we can make maximum use
@@ -146,25 +139,21 @@
     const uint8_t q0 = s[0],  q1 = s[1],  q2 = s[2],  q3 = s[3];
     const int8_t mask = filter_mask(*limit, *blimit,
                                     p3, p2, p1, p0, q0, q1, q2, q3);
-    const int8_t hev = hev_mask(*thresh, p1, p0, q0, q1);
-    filter4(mask, hev, s - 2, s - 1, s, s + 1);
+    filter4(mask, *thresh, s - 2, s - 1, s, s + 1);
     s += pitch;
   }
 }
 
-void vp9_loop_filter_vertical_edge_16_c(uint8_t *s, int pitch,
-                                        const uint8_t *blimit0,
-                                        const uint8_t *limit0,
-                                        const uint8_t *thresh0,
-                                        const uint8_t *blimit1,
-                                        const uint8_t *limit1,
-                                        const uint8_t *thresh1) {
-  vp9_loop_filter_vertical_edge_c(s, pitch, blimit0, limit0, thresh0, 1);
-  vp9_loop_filter_vertical_edge_c(s + 8 * pitch, pitch, blimit1, limit1,
+void vp9_lpf_vertical_4_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0,
+                               const uint8_t *limit0, const uint8_t *thresh0,
+                               const uint8_t *blimit1, const uint8_t *limit1,
+                               const uint8_t *thresh1) {
+  vp9_lpf_vertical_4_c(s, pitch, blimit0, limit0, thresh0, 1);
+  vp9_lpf_vertical_4_c(s + 8 * pitch, pitch, blimit1, limit1,
                                   thresh1, 1);
 }
 
-static INLINE void filter8(int8_t mask, uint8_t hev, uint8_t flat,
+static INLINE void filter8(int8_t mask, uint8_t thresh, uint8_t flat,
                            uint8_t *op3, uint8_t *op2,
                            uint8_t *op1, uint8_t *op0,
                            uint8_t *oq0, uint8_t *oq1,
@@ -181,15 +170,13 @@
     *oq1 = ROUND_POWER_OF_TWO(p1 + p0 + q0 + 2 * q1 + q2 + q3 + q3, 3);
     *oq2 = ROUND_POWER_OF_TWO(p0 + q0 + q1 + 2 * q2 + q3 + q3 + q3, 3);
   } else {
-    filter4(mask, hev, op1,  op0, oq0, oq1);
+    filter4(mask, thresh, op1,  op0, oq0, oq1);
   }
 }
 
-void vp9_mbloop_filter_horizontal_edge_c(uint8_t *s, int p,
-                                         const uint8_t *blimit,
-                                         const uint8_t *limit,
-                                         const uint8_t *thresh,
-                                         int count) {
+void vp9_lpf_horizontal_8_c(uint8_t *s, int p, const uint8_t *blimit,
+                            const uint8_t *limit, const uint8_t *thresh,
+                            int count) {
   int i;
 
   // loop filter designed to work using chars so that we can make maximum use
@@ -200,30 +187,24 @@
 
     const int8_t mask = filter_mask(*limit, *blimit,
                                     p3, p2, p1, p0, q0, q1, q2, q3);
-    const int8_t hev = hev_mask(*thresh, p1, p0, q0, q1);
     const int8_t flat = flat_mask4(1, p3, p2, p1, p0, q0, q1, q2, q3);
-    filter8(mask, hev, flat, s - 4 * p, s - 3 * p, s - 2 * p, s - 1 * p,
-                             s,         s + 1 * p, s + 2 * p, s + 3 * p);
+    filter8(mask, *thresh, flat, s - 4 * p, s - 3 * p, s - 2 * p, s - 1 * p,
+                                 s,         s + 1 * p, s + 2 * p, s + 3 * p);
     ++s;
   }
 }
 
-void vp9_mbloop_filter_horizontal_edge_16_c(uint8_t *s, int p,
-                                            const uint8_t *blimit0,
-                                            const uint8_t *limit0,
-                                            const uint8_t *thresh0,
-                                            const uint8_t *blimit1,
-                                            const uint8_t *limit1,
-                                            const uint8_t *thresh1) {
-  vp9_mbloop_filter_horizontal_edge_c(s, p, blimit0, limit0, thresh0, 1);
-  vp9_mbloop_filter_horizontal_edge_c(s + 8, p, blimit1, limit1, thresh1, 1);
+void vp9_lpf_horizontal_8_dual_c(uint8_t *s, int p, const uint8_t *blimit0,
+                                 const uint8_t *limit0, const uint8_t *thresh0,
+                                 const uint8_t *blimit1, const uint8_t *limit1,
+                                 const uint8_t *thresh1) {
+  vp9_lpf_horizontal_8_c(s, p, blimit0, limit0, thresh0, 1);
+  vp9_lpf_horizontal_8_c(s + 8, p, blimit1, limit1, thresh1, 1);
 }
 
-void vp9_mbloop_filter_vertical_edge_c(uint8_t *s, int pitch,
-                                       const uint8_t *blimit,
-                                       const uint8_t *limit,
-                                       const uint8_t *thresh,
-                                       int count) {
+void vp9_lpf_vertical_8_c(uint8_t *s, int pitch, const uint8_t *blimit,
+                          const uint8_t *limit, const uint8_t *thresh,
+                          int count) {
   int i;
 
   for (i = 0; i < 8 * count; ++i) {
@@ -231,27 +212,23 @@
     const uint8_t q0 = s[0], q1 = s[1], q2 = s[2], q3 = s[3];
     const int8_t mask = filter_mask(*limit, *blimit,
                                     p3, p2, p1, p0, q0, q1, q2, q3);
-    const int8_t hev = hev_mask(thresh[0], p1, p0, q0, q1);
     const int8_t flat = flat_mask4(1, p3, p2, p1, p0, q0, q1, q2, q3);
-    filter8(mask, hev, flat, s - 4, s - 3, s - 2, s - 1,
-                             s,     s + 1, s + 2, s + 3);
+    filter8(mask, *thresh, flat, s - 4, s - 3, s - 2, s - 1,
+                                 s,     s + 1, s + 2, s + 3);
     s += pitch;
   }
 }
 
-void vp9_mbloop_filter_vertical_edge_16_c(uint8_t *s, int pitch,
-                                          const uint8_t *blimit0,
-                                          const uint8_t *limit0,
-                                          const uint8_t *thresh0,
-                                          const uint8_t *blimit1,
-                                          const uint8_t *limit1,
-                                          const uint8_t *thresh1) {
-  vp9_mbloop_filter_vertical_edge_c(s, pitch, blimit0, limit0, thresh0, 1);
-  vp9_mbloop_filter_vertical_edge_c(s + 8 * pitch, pitch, blimit1, limit1,
+void vp9_lpf_vertical_8_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0,
+                               const uint8_t *limit0, const uint8_t *thresh0,
+                               const uint8_t *blimit1, const uint8_t *limit1,
+                               const uint8_t *thresh1) {
+  vp9_lpf_vertical_8_c(s, pitch, blimit0, limit0, thresh0, 1);
+  vp9_lpf_vertical_8_c(s + 8 * pitch, pitch, blimit1, limit1,
                                     thresh1, 1);
 }
 
-static INLINE void filter16(int8_t mask, uint8_t hev,
+static INLINE void filter16(int8_t mask, uint8_t thresh,
                             uint8_t flat, uint8_t flat2,
                             uint8_t *op7, uint8_t *op6,
                             uint8_t *op5, uint8_t *op4,
@@ -298,15 +275,13 @@
     *oq6 = ROUND_POWER_OF_TWO(p0 +
                               q0 + q1 + q2 + q3 + q4 + q5 + q6 * 2 + q7 * 7, 4);
   } else {
-    filter8(mask, hev, flat, op3, op2, op1, op0, oq0, oq1, oq2, oq3);
+    filter8(mask, thresh, flat, op3, op2, op1, op0, oq0, oq1, oq2, oq3);
   }
 }
 
-void vp9_mb_lpf_horizontal_edge_w_c(uint8_t *s, int p,
-                                    const uint8_t *blimit,
-                                    const uint8_t *limit,
-                                    const uint8_t *thresh,
-                                    int count) {
+void vp9_lpf_horizontal_16_c(uint8_t *s, int p, const uint8_t *blimit,
+                             const uint8_t *limit, const uint8_t *thresh,
+                             int count) {
   int i;
 
   // loop filter designed to work using chars so that we can make maximum use
@@ -316,13 +291,12 @@
     const uint8_t q0 = s[0 * p], q1 = s[1 * p], q2 = s[2 * p], q3 = s[3 * p];
     const int8_t mask = filter_mask(*limit, *blimit,
                                     p3, p2, p1, p0, q0, q1, q2, q3);
-    const int8_t hev = hev_mask(*thresh, p1, p0, q0, q1);
     const int8_t flat = flat_mask4(1, p3, p2, p1, p0, q0, q1, q2, q3);
     const int8_t flat2 = flat_mask5(1,
                              s[-8 * p], s[-7 * p], s[-6 * p], s[-5 * p], p0,
                              q0, s[4 * p], s[5 * p], s[6 * p], s[7 * p]);
 
-    filter16(mask, hev, flat, flat2,
+    filter16(mask, *thresh, flat, flat2,
              s - 8 * p, s - 7 * p, s - 6 * p, s - 5 * p,
              s - 4 * p, s - 3 * p, s - 2 * p, s - 1 * p,
              s,         s + 1 * p, s + 2 * p, s + 3 * p,
@@ -343,28 +317,23 @@
     const uint8_t q0 = s[0], q1 = s[1],  q2 = s[2], q3 = s[3];
     const int8_t mask = filter_mask(*limit, *blimit,
                                     p3, p2, p1, p0, q0, q1, q2, q3);
-    const int8_t hev = hev_mask(*thresh, p1, p0, q0, q1);
     const int8_t flat = flat_mask4(1, p3, p2, p1, p0, q0, q1, q2, q3);
     const int8_t flat2 = flat_mask5(1, s[-8], s[-7], s[-6], s[-5], p0,
                                     q0, s[4], s[5], s[6], s[7]);
 
-    filter16(mask, hev, flat, flat2,
+    filter16(mask, *thresh, flat, flat2,
              s - 8, s - 7, s - 6, s - 5, s - 4, s - 3, s - 2, s - 1,
              s,     s + 1, s + 2, s + 3, s + 4, s + 5, s + 6, s + 7);
     s += p;
   }
 }
 
-void vp9_mb_lpf_vertical_edge_w_c(uint8_t *s, int p,
-                                  const uint8_t *blimit,
-                                  const uint8_t *limit,
-                                  const uint8_t *thresh) {
+void vp9_lpf_vertical_16_c(uint8_t *s, int p, const uint8_t *blimit,
+                           const uint8_t *limit, const uint8_t *thresh) {
   mb_lpf_vertical_edge_w(s, p, blimit, limit, thresh, 8);
 }
 
-void vp9_mb_lpf_vertical_edge_w_16_c(uint8_t *s, int p,
-                                     const uint8_t *blimit,
-                                     const uint8_t *limit,
-                                     const uint8_t *thresh) {
+void vp9_lpf_vertical_16_dual_c(uint8_t *s, int p, const uint8_t *blimit,
+                                const uint8_t *limit, const uint8_t *thresh) {
   mb_lpf_vertical_edge_w(s, p, blimit, limit, thresh, 16);
 }
diff --git a/vp9/common/vp9_mv.h b/vp9/common/vp9_mv.h
index 31a79b9..155c3f1 100644
--- a/vp9/common/vp9_mv.h
+++ b/vp9/common/vp9_mv.h
@@ -15,7 +15,7 @@
 
 #include "vp9/common/vp9_common.h"
 
-typedef struct {
+typedef struct mv {
   int16_t row;
   int16_t col;
 } MV;
@@ -25,7 +25,7 @@
   MV as_mv;
 } int_mv; /* facilitates faster equality tests and copies */
 
-typedef struct {
+typedef struct mv32 {
   int32_t row;
   int32_t col;
 } MV32;
diff --git a/vp9/common/vp9_mvref_common.c b/vp9/common/vp9_mvref_common.c
index 8df8aec..ff02622 100644
--- a/vp9/common/vp9_mvref_common.c
+++ b/vp9/common/vp9_mvref_common.c
@@ -13,6 +13,11 @@
 
 #define MVREF_NEIGHBOURS 8
 
+typedef struct position {
+  int row;
+  int col;
+} POSITION;
+
 typedef enum {
   BOTH_ZERO = 0,
   ZERO_PLUS_PREDICTED = 1,
@@ -71,7 +76,7 @@
   BOTH_INTRA  // 18
 };
 
-static const MV mv_ref_blocks[BLOCK_SIZES][MVREF_NEIGHBOURS] = {
+static const POSITION mv_ref_blocks[BLOCK_SIZES][MVREF_NEIGHBOURS] = {
   // 4X4
   {{-1, 0}, {0, -1}, {-1, -1}, {-2, 0}, {0, -2}, {-2, -1}, {-1, -2}, {-2, -2}},
   // 4X8
@@ -172,11 +177,11 @@
 // are inside the borders of the tile.
 static INLINE int is_inside(const TileInfo *const tile,
                             int mi_col, int mi_row, int mi_rows,
-                            const MV *mv) {
-  return !(mi_row + mv->row < 0 ||
-           mi_col + mv->col < tile->mi_col_start ||
-           mi_row + mv->row >= mi_rows ||
-           mi_col + mv->col >= tile->mi_col_end);
+                            const POSITION *mi_pos) {
+  return !(mi_row + mi_pos->row < 0 ||
+           mi_col + mi_pos->col < tile->mi_col_start ||
+           mi_row + mi_pos->row >= mi_rows ||
+           mi_col + mi_pos->col >= tile->mi_col_end);
 }
 
 // This function searches the neighbourhood of a given MB/SB
@@ -190,7 +195,7 @@
                           int mi_row, int mi_col) {
   const int *ref_sign_bias = cm->ref_frame_sign_bias;
   int i, refmv_count = 0;
-  const MV *const mv_ref_search = mv_ref_blocks[mi->mbmi.sb_type];
+  const POSITION *const mv_ref_search = mv_ref_blocks[mi->mbmi.sb_type];
   const MB_MODE_INFO *const prev_mbmi = prev_mi ? &prev_mi->mbmi : NULL;
   int different_ref_found = 0;
   int context_counter = 0;
@@ -202,7 +207,7 @@
   // if the size < 8x8 we get the mv from the bmi substructure,
   // and we also need to keep a mode count.
   for (i = 0; i < 2; ++i) {
-    const MV *const mv_ref = &mv_ref_search[i];
+    const POSITION *const mv_ref = &mv_ref_search[i];
     if (is_inside(tile, mi_col, mi_row, cm->mi_rows, mv_ref)) {
       const MODE_INFO *const candidate_mi = xd->mi_8x8[mv_ref->col + mv_ref->row
                                                    * xd->mode_info_stride];
@@ -229,7 +234,7 @@
   // as before except we don't need to keep track of sub blocks or
   // mode counts.
   for (; i < MVREF_NEIGHBOURS; ++i) {
-    const MV *const mv_ref = &mv_ref_search[i];
+    const POSITION *const mv_ref = &mv_ref_search[i];
     if (is_inside(tile, mi_col, mi_row, cm->mi_rows, mv_ref)) {
       const MB_MODE_INFO *const candidate = &xd->mi_8x8[mv_ref->col +
                                             mv_ref->row
@@ -259,7 +264,7 @@
   // different reference frames.
   if (different_ref_found) {
     for (i = 0; i < MVREF_NEIGHBOURS; ++i) {
-      const MV *mv_ref = &mv_ref_search[i];
+      const POSITION *mv_ref = &mv_ref_search[i];
       if (is_inside(tile, mi_col, mi_row, cm->mi_rows, mv_ref)) {
         const MB_MODE_INFO *const candidate = &xd->mi_8x8[mv_ref->col +
                                                           mv_ref->row
@@ -284,3 +289,75 @@
   for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i)
     clamp_mv_ref(&mv_ref_list[i].as_mv, xd);
 }
+
+static void lower_mv_precision(MV *mv, int allow_hp) {
+  const int use_hp = allow_hp && vp9_use_mv_hp(mv);
+  if (!use_hp) {
+    if (mv->row & 1)
+      mv->row += (mv->row > 0 ? -1 : 1);
+    if (mv->col & 1)
+      mv->col += (mv->col > 0 ? -1 : 1);
+  }
+}
+
+
+void vp9_find_best_ref_mvs(MACROBLOCKD *xd, int allow_hp,
+                           int_mv *mvlist, int_mv *nearest, int_mv *near) {
+  int i;
+  // Make sure all the candidates are properly clamped etc
+  for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i) {
+    lower_mv_precision(&mvlist[i].as_mv, allow_hp);
+    clamp_mv2(&mvlist[i].as_mv, xd);
+  }
+  *nearest = mvlist[0];
+  *near = mvlist[1];
+}
+
+void vp9_append_sub8x8_mvs_for_idx(VP9_COMMON *cm, MACROBLOCKD *xd,
+                                   const TileInfo *const tile,
+                                   int block, int ref, int mi_row, int mi_col,
+                                   int_mv *nearest, int_mv *near) {
+  int_mv mv_list[MAX_MV_REF_CANDIDATES];
+  MODE_INFO *const mi = xd->mi_8x8[0];
+  b_mode_info *bmi = mi->bmi;
+  int n;
+
+  assert(MAX_MV_REF_CANDIDATES == 2);
+
+  vp9_find_mv_refs_idx(cm, xd, tile, mi, xd->last_mi, mi->mbmi.ref_frame[ref],
+                       mv_list, block, mi_row, mi_col);
+
+  near->as_int = 0;
+  switch (block) {
+    case 0:
+      nearest->as_int = mv_list[0].as_int;
+      near->as_int = mv_list[1].as_int;
+      break;
+    case 1:
+    case 2:
+      nearest->as_int = bmi[0].as_mv[ref].as_int;
+      for (n = 0; n < MAX_MV_REF_CANDIDATES; ++n)
+        if (nearest->as_int != mv_list[n].as_int) {
+          near->as_int = mv_list[n].as_int;
+          break;
+        }
+      break;
+    case 3: {
+      int_mv candidates[2 + MAX_MV_REF_CANDIDATES];
+      candidates[0] = bmi[1].as_mv[ref];
+      candidates[1] = bmi[0].as_mv[ref];
+      candidates[2] = mv_list[0];
+      candidates[3] = mv_list[1];
+
+      nearest->as_int = bmi[2].as_mv[ref].as_int;
+      for (n = 0; n < 2 + MAX_MV_REF_CANDIDATES; ++n)
+        if (nearest->as_int != candidates[n].as_int) {
+          near->as_int = candidates[n].as_int;
+          break;
+        }
+      break;
+    }
+    default:
+      assert("Invalid block index.");
+  }
+}
diff --git a/vp9/common/vp9_mvref_common.h b/vp9/common/vp9_mvref_common.h
index ce4c559..06adbab 100644
--- a/vp9/common/vp9_mvref_common.h
+++ b/vp9/common/vp9_mvref_common.h
@@ -32,4 +32,26 @@
                        mv_ref_list, -1, mi_row, mi_col);
 }
 
+#define LEFT_TOP_MARGIN     ((VP9BORDERINPIXELS - VP9_INTERP_EXTEND) << 3)
+#define RIGHT_BOTTOM_MARGIN ((VP9BORDERINPIXELS - VP9_INTERP_EXTEND) << 3)
+
+// check a list of motion vectors by sad score using a number rows of pixels
+// above and a number cols of pixels in the left to select the one with best
+// score to use as ref motion vector
+void vp9_find_best_ref_mvs(MACROBLOCKD *xd, int allow_hp,
+                           int_mv *mvlist, int_mv *nearest, int_mv *near);
+
+// TODO(jingning): this mv clamping function should be block size dependent.
+static void clamp_mv2(MV *mv, const MACROBLOCKD *xd) {
+  clamp_mv(mv, xd->mb_to_left_edge - LEFT_TOP_MARGIN,
+               xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN,
+               xd->mb_to_top_edge - LEFT_TOP_MARGIN,
+               xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN);
+}
+
+void vp9_append_sub8x8_mvs_for_idx(VP9_COMMON *cm, MACROBLOCKD *xd,
+                                   const TileInfo *const tile,
+                                   int block, int ref, int mi_row, int mi_col,
+                                   int_mv *nearest, int_mv *near);
+
 #endif  // VP9_COMMON_VP9_MVREF_COMMON_H_
diff --git a/vp9/common/vp9_onyx.h b/vp9/common/vp9_onyx.h
index c5faf88..be8fedc 100644
--- a/vp9/common/vp9_onyx.h
+++ b/vp9/common/vp9_onyx.h
@@ -129,6 +129,9 @@
     int64_t optimal_buffer_level;
     int64_t maximum_buffer_size;
 
+    // Frame drop threshold.
+    int drop_frames_water_mark;
+
     // controlling quality
     int fixed_q;
     int worst_allowed_q;
@@ -193,7 +196,7 @@
                             int64_t end_time_stamp);
 
   int vp9_get_compressed_data(VP9_PTR comp, unsigned int *frame_flags,
-                              unsigned long *size, unsigned char *dest,
+                              size_t *size, uint8_t *dest,
                               int64_t *time_stamp, int64_t *time_end,
                               int flush);
 
diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h
index a6e5b27..ed4c044 100644
--- a/vp9/common/vp9_onyxc_int.h
+++ b/vp9/common/vp9_onyxc_int.h
@@ -113,8 +113,8 @@
 
   YV12_BUFFER_CONFIG *frame_to_show;
 
-  YV12_BUFFER_CONFIG yv12_fb[FRAME_BUFFERS];
-  int fb_idx_ref_cnt[FRAME_BUFFERS]; /* reference counts */
+  YV12_BUFFER_CONFIG *yv12_fb;
+  int *fb_idx_ref_cnt; /* reference counts */
   int ref_frame_map[REF_FRAMES]; /* maps fb_idx to reference slot */
 
   // TODO(jkoleszar): could expand active_ref_idx to 4, with 0 as intra, and
@@ -123,7 +123,6 @@
   // Each frame can reference REFS_PER_FRAME buffers
   int active_ref_idx[REFS_PER_FRAME];
   struct scale_factors active_ref_scale[REFS_PER_FRAME];
-  struct scale_factors_common active_ref_scale_comm[REFS_PER_FRAME];
   int new_fb_idx;
 
   YV12_BUFFER_CONFIG post_proc_buffer;
@@ -133,6 +132,7 @@
 
   int show_frame;
   int last_show_frame;
+  int show_existing_frame;
 
   // Flag signaling that the frame is encoded using only INTRA modes.
   int intra_only;
@@ -213,6 +213,15 @@
   int frame_parallel_decoding_mode;
 
   int log2_tile_cols, log2_tile_rows;
+
+  vpx_codec_frame_buffer_t *fb_list;  // External frame buffers
+  int fb_count;  // Total number of frame buffers
+  vpx_realloc_frame_buffer_cb_fn_t realloc_fb_cb;
+  void *user_priv;  // Private data associated with the external frame buffers.
+
+  int fb_lru;  // Flag telling if lru is on/off
+  uint32_t *fb_idx_ref_lru;  // Frame buffer lru cache
+  uint32_t fb_idx_ref_lru_count;
 } VP9_COMMON;
 
 // ref == 0 => LAST_FRAME
@@ -228,13 +237,27 @@
 
 static int get_free_fb(VP9_COMMON *cm) {
   int i;
-  for (i = 0; i < FRAME_BUFFERS; i++)
-    if (cm->fb_idx_ref_cnt[i] == 0)
-      break;
+  uint32_t lru_count = cm->fb_idx_ref_lru_count + 1;
+  int free_buffer_idx = cm->fb_count;
+  for (i = 0; i < cm->fb_count; i++) {
+    if (!cm->fb_lru) {
+      if (cm->fb_idx_ref_cnt[i] == 0) {
+        free_buffer_idx = i;
+        break;
+      }
+    } else {
+      if (cm->fb_idx_ref_cnt[i] == 0 && cm->fb_idx_ref_lru[i] < lru_count) {
+        free_buffer_idx = i;
+        lru_count = cm->fb_idx_ref_lru[i];
+      }
+    }
+  }
 
-  assert(i < FRAME_BUFFERS);
-  cm->fb_idx_ref_cnt[i] = 1;
-  return i;
+  assert(free_buffer_idx < cm->fb_count);
+  cm->fb_idx_ref_cnt[free_buffer_idx] = 1;
+  if (cm->fb_lru)
+    cm->fb_idx_ref_lru[free_buffer_idx] = ++cm->fb_idx_ref_lru_count;
+  return free_buffer_idx;
 }
 
 static void ref_cnt_fb(int *buf, int *idx, int new_idx) {
diff --git a/vp9/common/vp9_pred_common.c b/vp9/common/vp9_pred_common.c
index 40cfc81..11b6d93 100644
--- a/vp9/common/vp9_pred_common.c
+++ b/vp9/common/vp9_pred_common.c
@@ -14,14 +14,9 @@
 #include "vp9/common/vp9_common.h"
 #include "vp9/common/vp9_pred_common.h"
 #include "vp9/common/vp9_seg_common.h"
-#include "vp9/common/vp9_treecoder.h"
 
-static INLINE const MB_MODE_INFO *get_above_mbmi(const MODE_INFO *const above) {
-  return (above != NULL) ? &above->mbmi : NULL;
-}
-
-static INLINE const MB_MODE_INFO *get_left_mbmi(const MODE_INFO *const left) {
-  return (left != NULL) ? &left->mbmi : NULL;
+static INLINE const MB_MODE_INFO *get_mbmi(const MODE_INFO *const mi) {
+  return (mi != NULL) ? &mi->mbmi : NULL;
 }
 
 // Returns a context number for the given MB prediction signal
@@ -30,15 +25,13 @@
   // The mode info data structure has a one element border above and to the
   // left of the entries correpsonding to real macroblocks.
   // The prediction flags in these dummy entries are initialised to 0.
-  const MODE_INFO *const left_mi = get_left_mi(xd);
-  const int has_left = left_mi != NULL ? is_inter_block(&left_mi->mbmi) : 0;
-  const int left_type = has_left ? left_mi->mbmi.interp_filter
-                                 : SWITCHABLE_FILTERS;
+  const MB_MODE_INFO *const left_mbmi = get_mbmi(get_left_mi(xd));
+  const int left_type = left_mbmi != NULL && is_inter_block(left_mbmi) ?
+                           left_mbmi->interp_filter : SWITCHABLE_FILTERS;
+  const MB_MODE_INFO *const above_mbmi = get_mbmi(get_above_mi(xd));
+  const int above_type = above_mbmi != NULL && is_inter_block(above_mbmi) ?
+                             above_mbmi->interp_filter : SWITCHABLE_FILTERS;
 
-  const MODE_INFO *const above_mi = get_above_mi(xd);
-  const int has_above = above_mi != NULL ? is_inter_block(&above_mi->mbmi) : 0;
-  const int above_type = has_above ? above_mi->mbmi.interp_filter
-                                   : SWITCHABLE_FILTERS;
   if (left_type == above_type)
     return left_type;
   else if (left_type == SWITCHABLE_FILTERS && above_type != SWITCHABLE_FILTERS)
@@ -48,36 +41,37 @@
   else
     return SWITCHABLE_FILTERS;
 }
-// Returns a context number for the given MB prediction signal
+
+// The mode info data structure has a one element border above and to the
+// left of the entries corresponding to real macroblocks.
+// The prediction flags in these dummy entries are initialized to 0.
+// 0 - inter/inter, inter/--, --/inter, --/--
+// 1 - intra/inter, inter/intra
+// 2 - intra/--, --/intra
+// 3 - intra/intra
 int vp9_get_intra_inter_context(const MACROBLOCKD *xd) {
-  const MB_MODE_INFO *const above_mbmi = get_above_mbmi(get_above_mi(xd));
-  const MB_MODE_INFO *const left_mbmi = get_left_mbmi(get_left_mi(xd));
+  const MB_MODE_INFO *const above_mbmi = get_mbmi(get_above_mi(xd));
+  const MB_MODE_INFO *const left_mbmi = get_mbmi(get_left_mi(xd));
   const int has_above = above_mbmi != NULL;
   const int has_left = left_mbmi != NULL;
-  const int above_intra = has_above ? !is_inter_block(above_mbmi) : 1;
-  const int left_intra = has_left ? !is_inter_block(left_mbmi) : 1;
 
-  // The mode info data structure has a one element border above and to the
-  // left of the entries corresponding to real macroblocks.
-  // The prediction flags in these dummy entries are initialized to 0.
-  // 0 - inter/inter, inter/--, --/inter, --/--
-  // 1 - intra/inter, inter/intra
-  // 2 - intra/--, --/intra
-  // 3 - intra/intra
-  if (has_above && has_left)  // both edges available
+  if (has_above && has_left) {  // both edges available
+    const int above_intra = !is_inter_block(above_mbmi);
+    const int left_intra = !is_inter_block(left_mbmi);
     return left_intra && above_intra ? 3
                                      : left_intra || above_intra;
-  else if (has_above || has_left)  // one edge available
-    return 2 * (has_above ? above_intra : left_intra);
-  else
+  } else if (has_above || has_left) {  // one edge available
+    return 2 * !is_inter_block(has_above ? above_mbmi : left_mbmi);
+  } else {
     return 0;
+  }
 }
 
 int vp9_get_reference_mode_context(const VP9_COMMON *cm,
                                    const MACROBLOCKD *xd) {
   int ctx;
-  const MB_MODE_INFO *const above_mbmi = get_above_mbmi(get_above_mi(xd));
-  const MB_MODE_INFO *const left_mbmi = get_left_mbmi(get_left_mi(xd));
+  const MB_MODE_INFO *const above_mbmi = get_mbmi(get_above_mi(xd));
+  const MB_MODE_INFO *const left_mbmi = get_mbmi(get_left_mi(xd));
   const int has_above = above_mbmi != NULL;
   const int has_left = left_mbmi != NULL;
   // Note:
@@ -119,14 +113,11 @@
 int vp9_get_pred_context_comp_ref_p(const VP9_COMMON *cm,
                                     const MACROBLOCKD *xd) {
   int pred_context;
-  const MODE_INFO *const above_mi = get_above_mi(xd);
-  const MODE_INFO *const left_mi = get_left_mi(xd);
-  const MB_MODE_INFO *const above_mbmi = get_above_mbmi(above_mi);
-  const MB_MODE_INFO *const left_mbmi = get_left_mbmi(left_mi);
-  const int above_in_image = above_mi != NULL;
-  const int left_in_image = left_mi != NULL;
-  const int above_intra = above_in_image ? !is_inter_block(above_mbmi) : 1;
-  const int left_intra = left_in_image ? !is_inter_block(left_mbmi) : 1;
+  const MB_MODE_INFO *const above_mbmi = get_mbmi(get_above_mi(xd));
+  const MB_MODE_INFO *const left_mbmi = get_mbmi(get_left_mi(xd));
+  const int above_in_image = above_mbmi != NULL;
+  const int left_in_image = left_mbmi != NULL;
+
   // Note:
   // The mode info data structure has a one element border above and to the
   // left of the entries correpsonding to real macroblocks.
@@ -135,6 +126,9 @@
   const int var_ref_idx = !fix_ref_idx;
 
   if (above_in_image && left_in_image) {  // both edges available
+    const int above_intra = !is_inter_block(above_mbmi);
+    const int left_intra = !is_inter_block(left_mbmi);
+
     if (above_intra && left_intra) {  // intra/intra (2)
       pred_context = 2;
     } else if (above_intra || left_intra) {  // intra/inter
@@ -148,10 +142,10 @@
     } else {  // inter/inter
       const int l_sg = !has_second_ref(left_mbmi);
       const int a_sg = !has_second_ref(above_mbmi);
-      MV_REFERENCE_FRAME vrfa = a_sg ? above_mbmi->ref_frame[0]
-                                     : above_mbmi->ref_frame[var_ref_idx];
-      MV_REFERENCE_FRAME vrfl = l_sg ? left_mbmi->ref_frame[0]
-                                     : left_mbmi->ref_frame[var_ref_idx];
+      const MV_REFERENCE_FRAME vrfa = a_sg ? above_mbmi->ref_frame[0]
+                                           : above_mbmi->ref_frame[var_ref_idx];
+      const MV_REFERENCE_FRAME vrfl = l_sg ? left_mbmi->ref_frame[0]
+                                           : left_mbmi->ref_frame[var_ref_idx];
 
       if (vrfa == vrfl && cm->comp_var_ref[1] == vrfa) {
         pred_context = 0;
@@ -164,8 +158,8 @@
         else
           pred_context = 1;
       } else if (l_sg || a_sg) {  // single/comp
-        MV_REFERENCE_FRAME vrfc = l_sg ? vrfa : vrfl;
-        MV_REFERENCE_FRAME rfs = a_sg ? vrfa : vrfl;
+        const MV_REFERENCE_FRAME vrfc = l_sg ? vrfa : vrfl;
+        const MV_REFERENCE_FRAME rfs = a_sg ? vrfa : vrfl;
         if (vrfc == cm->comp_var_ref[1] && rfs != cm->comp_var_ref[1])
           pred_context = 1;
         else if (rfs == cm->comp_var_ref[1] && vrfc != cm->comp_var_ref[1])
@@ -200,17 +194,18 @@
 
 int vp9_get_pred_context_single_ref_p1(const MACROBLOCKD *xd) {
   int pred_context;
-  const MB_MODE_INFO *const above_mbmi = get_above_mbmi(get_above_mi(xd));
-  const MB_MODE_INFO *const left_mbmi = get_left_mbmi(get_left_mi(xd));
+  const MB_MODE_INFO *const above_mbmi = get_mbmi(get_above_mi(xd));
+  const MB_MODE_INFO *const left_mbmi = get_mbmi(get_left_mi(xd));
   const int has_above = above_mbmi != NULL;
   const int has_left = left_mbmi != NULL;
-  const int above_intra = has_above ? !is_inter_block(above_mbmi) : 1;
-  const int left_intra = has_left ? !is_inter_block(left_mbmi) : 1;
   // Note:
   // The mode info data structure has a one element border above and to the
   // left of the entries correpsonding to real macroblocks.
   // The prediction flags in these dummy entries are initialised to 0.
   if (has_above && has_left) {  // both edges available
+    const int above_intra = !is_inter_block(above_mbmi);
+    const int left_intra = !is_inter_block(left_mbmi);
+
     if (above_intra && left_intra) {  // intra/intra
       pred_context = 2;
     } else if (above_intra || left_intra) {  // intra/inter or inter/intra
@@ -221,26 +216,29 @@
         pred_context = 1 + (edge_mbmi->ref_frame[0] == LAST_FRAME ||
                             edge_mbmi->ref_frame[1] == LAST_FRAME);
     } else {  // inter/inter
-      if (!has_second_ref(above_mbmi) && !has_second_ref(left_mbmi)) {
-        pred_context = 2 * (above_mbmi->ref_frame[0] == LAST_FRAME) +
-                       2 * (left_mbmi->ref_frame[0] == LAST_FRAME);
-      } else if (has_second_ref(above_mbmi) && has_second_ref(left_mbmi)) {
+      const int above_has_second = has_second_ref(above_mbmi);
+      const int left_has_second = has_second_ref(left_mbmi);
+
+      if (above_has_second && left_has_second) {
         pred_context = 1 + (above_mbmi->ref_frame[0] == LAST_FRAME ||
                             above_mbmi->ref_frame[1] == LAST_FRAME ||
                             left_mbmi->ref_frame[0] == LAST_FRAME ||
                             left_mbmi->ref_frame[1] == LAST_FRAME);
-      } else {
-        const MV_REFERENCE_FRAME rfs = !has_second_ref(above_mbmi) ?
-                  above_mbmi->ref_frame[0] : left_mbmi->ref_frame[0];
-        const MV_REFERENCE_FRAME crf1 = has_second_ref(above_mbmi) ?
-                  above_mbmi->ref_frame[0] : left_mbmi->ref_frame[0];
-        const MV_REFERENCE_FRAME crf2 = has_second_ref(above_mbmi) ?
-                  above_mbmi->ref_frame[1] : left_mbmi->ref_frame[1];
+      } else if (above_has_second || left_has_second) {
+        const MV_REFERENCE_FRAME rfs = !above_has_second ?
+            above_mbmi->ref_frame[0] : left_mbmi->ref_frame[0];
+        const MV_REFERENCE_FRAME crf1 = above_has_second ?
+            above_mbmi->ref_frame[0] : left_mbmi->ref_frame[0];
+        const MV_REFERENCE_FRAME crf2 = above_has_second ?
+            above_mbmi->ref_frame[1] : left_mbmi->ref_frame[1];
 
         if (rfs == LAST_FRAME)
           pred_context = 3 + (crf1 == LAST_FRAME || crf2 == LAST_FRAME);
         else
-          pred_context = crf1 == LAST_FRAME || crf2 == LAST_FRAME;
+          pred_context = (crf1 == LAST_FRAME || crf2 == LAST_FRAME);
+      } else {
+        pred_context = 2 * (above_mbmi->ref_frame[0] == LAST_FRAME) +
+                       2 * (left_mbmi->ref_frame[0] == LAST_FRAME);
       }
     }
   } else if (has_above || has_left) {  // one edge available
@@ -264,18 +262,19 @@
 
 int vp9_get_pred_context_single_ref_p2(const MACROBLOCKD *xd) {
   int pred_context;
-  const MB_MODE_INFO *const above_mbmi = get_above_mbmi(get_above_mi(xd));
-  const MB_MODE_INFO *const left_mbmi = get_left_mbmi(get_left_mi(xd));
+  const MB_MODE_INFO *const above_mbmi = get_mbmi(get_above_mi(xd));
+  const MB_MODE_INFO *const left_mbmi = get_mbmi(get_left_mi(xd));
   const int has_above = above_mbmi != NULL;
   const int has_left = left_mbmi != NULL;
-  const int above_intra = has_above ? !is_inter_block(above_mbmi) : 1;
-  const int left_intra = has_left ? !is_inter_block(left_mbmi) : 1;
 
   // Note:
   // The mode info data structure has a one element border above and to the
   // left of the entries correpsonding to real macroblocks.
   // The prediction flags in these dummy entries are initialised to 0.
   if (has_above && has_left) {  // both edges available
+    const int above_intra = !is_inter_block(above_mbmi);
+    const int left_intra = !is_inter_block(left_mbmi);
+
     if (above_intra && left_intra) {  // intra/intra
       pred_context = 2;
     } else if (above_intra || left_intra) {  // intra/inter or inter/intra
@@ -290,21 +289,10 @@
                                 edge_mbmi->ref_frame[1] == GOLDEN_FRAME);
       }
     } else {  // inter/inter
-      if (!has_second_ref(above_mbmi) && !has_second_ref(left_mbmi)) {
-        if (above_mbmi->ref_frame[0] == LAST_FRAME &&
-            left_mbmi->ref_frame[0] == LAST_FRAME) {
-          pred_context = 3;
-        } else if (above_mbmi->ref_frame[0] == LAST_FRAME ||
-                   left_mbmi->ref_frame[0] == LAST_FRAME) {
-          const MB_MODE_INFO *edge_mbmi =
-              above_mbmi->ref_frame[0] == LAST_FRAME ? left_mbmi : above_mbmi;
+      const int above_has_second = has_second_ref(above_mbmi);
+      const int left_has_second = has_second_ref(left_mbmi);
 
-          pred_context = 4 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME);
-        } else {
-          pred_context = 2 * (above_mbmi->ref_frame[0] == GOLDEN_FRAME) +
-                         2 * (left_mbmi->ref_frame[0] == GOLDEN_FRAME);
-        }
-      } else if (has_second_ref(above_mbmi) && has_second_ref(left_mbmi)) {
+      if (above_has_second && left_has_second) {
         if (above_mbmi->ref_frame[0] == left_mbmi->ref_frame[0] &&
             above_mbmi->ref_frame[1] == left_mbmi->ref_frame[1])
           pred_context = 3 * (above_mbmi->ref_frame[0] == GOLDEN_FRAME ||
@@ -313,13 +301,13 @@
                               left_mbmi->ref_frame[1] == GOLDEN_FRAME);
         else
           pred_context = 2;
-      } else {
-        const MV_REFERENCE_FRAME rfs = !has_second_ref(above_mbmi) ?
-                  above_mbmi->ref_frame[0] : left_mbmi->ref_frame[0];
-        const MV_REFERENCE_FRAME crf1 = has_second_ref(above_mbmi) ?
-                  above_mbmi->ref_frame[0] : left_mbmi->ref_frame[0];
-        const MV_REFERENCE_FRAME crf2 = has_second_ref(above_mbmi) ?
-                  above_mbmi->ref_frame[1] : left_mbmi->ref_frame[1];
+      } else if (above_has_second || left_has_second) {
+        const MV_REFERENCE_FRAME rfs = !above_has_second ?
+                     above_mbmi->ref_frame[0] : left_mbmi->ref_frame[0];
+        const MV_REFERENCE_FRAME crf1 = above_has_second ?
+                   above_mbmi->ref_frame[0] : left_mbmi->ref_frame[0];
+        const MV_REFERENCE_FRAME crf2 = above_has_second ?
+                     above_mbmi->ref_frame[1] : left_mbmi->ref_frame[1];
 
         if (rfs == GOLDEN_FRAME)
           pred_context = 3 + (crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME);
@@ -327,6 +315,19 @@
           pred_context = crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME;
         else
           pred_context = 1 + 2 * (crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME);
+      } else {
+        if (above_mbmi->ref_frame[0] == LAST_FRAME &&
+            left_mbmi->ref_frame[0] == LAST_FRAME) {
+          pred_context = 3;
+        } else if (above_mbmi->ref_frame[0] == LAST_FRAME ||
+                   left_mbmi->ref_frame[0] == LAST_FRAME) {
+          const MB_MODE_INFO *edge_mbmi =
+              above_mbmi->ref_frame[0] == LAST_FRAME ? left_mbmi : above_mbmi;
+            pred_context = 4 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME);
+        } else {
+          pred_context = 2 * (above_mbmi->ref_frame[0] == GOLDEN_FRAME) +
+                         2 * (left_mbmi->ref_frame[0] == GOLDEN_FRAME);
+        }
       }
     }
   } else if (has_above || has_left) {  // one edge available
@@ -352,8 +353,8 @@
 // The prediction flags in these dummy entries are initialized to 0.
 int vp9_get_tx_size_context(const MACROBLOCKD *xd) {
   const int max_tx_size = max_txsize_lookup[xd->mi_8x8[0]->mbmi.sb_type];
-  const MB_MODE_INFO *const above_mbmi = get_above_mbmi(get_above_mi(xd));
-  const MB_MODE_INFO *const left_mbmi = get_left_mbmi(get_left_mi(xd));
+  const MB_MODE_INFO *const above_mbmi = get_mbmi(get_above_mi(xd));
+  const MB_MODE_INFO *const left_mbmi = get_mbmi(get_left_mi(xd));
   const int has_above = above_mbmi != NULL;
   const int has_left = left_mbmi != NULL;
   int above_ctx = (has_above && !above_mbmi->skip_coeff) ? above_mbmi->tx_size
diff --git a/vp9/common/vp9_pred_common.h b/vp9/common/vp9_pred_common.h
index 66cd151..23722ba 100644
--- a/vp9/common/vp9_pred_common.h
+++ b/vp9/common/vp9_pred_common.h
@@ -104,7 +104,7 @@
     case TX_32X32:
       return tx_probs->p32x32[ctx];
     default:
-      assert(!"Invalid max_tx_size.");
+      assert(0 && "Invalid max_tx_size.");
       return NULL;
   }
 }
@@ -124,7 +124,7 @@
     case TX_32X32:
       return tx_counts->p32x32[ctx];
     default:
-      assert(!"Invalid max_tx_size.");
+      assert(0 && "Invalid max_tx_size.");
       return NULL;
   }
 }
diff --git a/vp9/common/vp9_prob.c b/vp9/common/vp9_prob.c
new file mode 100644
index 0000000..884884e
--- /dev/null
+++ b/vp9/common/vp9_prob.c
@@ -0,0 +1,30 @@
+/*
+ *  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "vp9/common/vp9_prob.h"
+
+DECLARE_ALIGNED(16, const uint8_t, vp9_norm[256]) = {
+  0, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
diff --git a/vp9/common/vp9_treecoder.h b/vp9/common/vp9_prob.h
similarity index 93%
rename from vp9/common/vp9_treecoder.h
rename to vp9/common/vp9_prob.h
index ed8c74a..6148206 100644
--- a/vp9/common/vp9_treecoder.h
+++ b/vp9/common/vp9_prob.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
  *
  *  Use of this source code is governed by a BSD-style license
  *  that can be found in the LICENSE file in the root of the source
@@ -8,15 +8,20 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef VP9_COMMON_VP9_TREECODER_H_
-#define VP9_COMMON_VP9_TREECODER_H_
+#ifndef VP9_COMMON_VP9_PROB_H_
+#define VP9_COMMON_VP9_PROB_H_
 
 #include "./vpx_config.h"
+
+#include "vpx_ports/mem.h"
 #include "vpx/vpx_integer.h"
+
 #include "vp9/common/vp9_common.h"
 
 typedef uint8_t vp9_prob;
 
+#define MAX_PROB 255
+
 #define vp9_prob_half ((vp9_prob) 128)
 
 typedef int8_t vp9_tree_index;
@@ -107,5 +112,6 @@
                         count_sat, max_update_factor, probs);
 }
 
+DECLARE_ALIGNED(16, extern const uint8_t, vp9_norm[256]);
 
-#endif  // VP9_COMMON_VP9_TREECODER_H_
+#endif  // VP9_COMMON_VP9_PROB_H_
diff --git a/vp9/common/vp9_reconinter.c b/vp9/common/vp9_reconinter.c
index a6e51d7..c84007e 100644
--- a/vp9/common/vp9_reconinter.c
+++ b/vp9/common/vp9_reconinter.c
@@ -66,11 +66,11 @@
                             uint8_t *dst, int dst_stride,
                             const int subpel_x,
                             const int subpel_y,
-                            const struct scale_factors *scale,
+                            const struct scale_factors *sf,
                             int w, int h, int ref,
                             const struct subpix_fn_table *subpix,
                             int xs, int ys) {
-  scale->sfc->predict[subpel_x != 0][subpel_y != 0][ref](
+  sf->predict[subpel_x != 0][subpel_y != 0][ref](
       src, src_stride, dst, dst_stride,
       subpix->filter_x[subpel_x], xs,
       subpix->filter_y[subpel_y], ys,
@@ -80,21 +80,22 @@
 void vp9_build_inter_predictor(const uint8_t *src, int src_stride,
                                uint8_t *dst, int dst_stride,
                                const MV *src_mv,
-                               const struct scale_factors *scale,
+                               const struct scale_factors *sf,
                                int w, int h, int ref,
                                const struct subpix_fn_table *subpix,
-                               enum mv_precision precision) {
+                               enum mv_precision precision,
+                               int x, int y) {
   const int is_q4 = precision == MV_PRECISION_Q4;
   const MV mv_q4 = { is_q4 ? src_mv->row : src_mv->row * 2,
                      is_q4 ? src_mv->col : src_mv->col * 2 };
-  const struct scale_factors_common *sfc = scale->sfc;
-  const MV32 mv = sfc->scale_mv(&mv_q4, scale);
+  MV32 mv = vp9_scale_mv(&mv_q4, x, y, sf);
   const int subpel_x = mv.col & SUBPEL_MASK;
   const int subpel_y = mv.row & SUBPEL_MASK;
+
   src += (mv.row >> SUBPEL_BITS) * src_stride + (mv.col >> SUBPEL_BITS);
 
   inter_predictor(src, src_stride, dst, dst_stride, subpel_x, subpel_y,
-                  scale, w, h, ref, subpix, sfc->x_step_q4, sfc->y_step_q4);
+                  sf, w, h, ref, subpix, sf->x_step_q4, sf->y_step_q4);
 }
 
 static INLINE int round_mv_comp_q4(int value) {
@@ -152,7 +153,7 @@
   int ref;
 
   for (ref = 0; ref < 1 + is_compound; ++ref) {
-    struct scale_factors *const scale = &xd->scale_factor[ref];
+    const struct scale_factors *const sf = xd->scale_factors[ref];
     struct buf_2d *const pre_buf = &pd->pre[ref];
     struct buf_2d *const dst_buf = &pd->dst;
     uint8_t *const dst = dst_buf->buf + dst_buf->stride * y + x;
@@ -179,12 +180,11 @@
     MV32 scaled_mv;
     int xs, ys, subpel_x, subpel_y;
 
-    if (vp9_is_scaled(scale->sfc)) {
-      pre = pre_buf->buf + scaled_buffer_offset(x, y, pre_buf->stride, scale);
-      scale->sfc->set_scaled_offsets(scale, mi_y + y, mi_x + x);
-      scaled_mv = scale->sfc->scale_mv(&mv_q4, scale);
-      xs = scale->sfc->x_step_q4;
-      ys = scale->sfc->y_step_q4;
+    if (vp9_is_scaled(sf)) {
+      pre = pre_buf->buf + scaled_buffer_offset(x, y, pre_buf->stride, sf);
+      scaled_mv = vp9_scale_mv(&mv_q4, mi_x + x, mi_y + y, sf);
+      xs = sf->x_step_q4;
+      ys = sf->y_step_q4;
     } else {
       pre = pre_buf->buf + (y * pre_buf->stride + x);
       scaled_mv.row = mv_q4.row;
@@ -197,7 +197,7 @@
            + (scaled_mv.col >> SUBPEL_BITS);
 
     inter_predictor(pre, pre_buf->stride, dst, dst_buf->stride,
-                    subpel_x, subpel_y, scale, w, h, ref, &xd->subpix, xs, ys);
+                    subpel_x, subpel_y, sf, w, h, ref, &xd->subpix, xs, ys);
   }
 }
 
@@ -256,7 +256,7 @@
   int ref;
 
   for (ref = 0; ref < 1 + is_compound; ++ref) {
-    struct scale_factors *const scale = &xd->scale_factor[ref];
+    const struct scale_factors *const sf = xd->scale_factors[ref];
     struct buf_2d *const pre_buf = &pd->pre[ref];
     struct buf_2d *const dst_buf = &pd->dst;
     uint8_t *const dst = dst_buf->buf + dst_buf->stride * y + x;
@@ -304,16 +304,15 @@
     x0_16 = x0 << SUBPEL_BITS;
     y0_16 = y0 << SUBPEL_BITS;
 
-    if (vp9_is_scaled(scale->sfc)) {
-      scale->sfc->set_scaled_offsets(scale, mi_y + y, mi_x + x);
-      scaled_mv = scale->sfc->scale_mv(&mv_q4, scale);
-      xs = scale->sfc->x_step_q4;
-      ys = scale->sfc->y_step_q4;
+    if (vp9_is_scaled(sf)) {
+      scaled_mv = vp9_scale_mv(&mv_q4, mi_x + x, mi_y + y, sf);
+      xs = sf->x_step_q4;
+      ys = sf->y_step_q4;
       // Get block position in the scaled reference frame.
-      x0 = scale->sfc->scale_value_x(x0, scale->sfc);
-      y0 = scale->sfc->scale_value_y(y0, scale->sfc);
-      x0_16 = scale->sfc->scale_value_x(x0_16, scale->sfc);
-      y0_16 = scale->sfc->scale_value_y(y0_16, scale->sfc);
+      x0 = sf->scale_value_x(x0, sf);
+      y0 = sf->scale_value_y(y0, sf);
+      x0_16 = sf->scale_value_x(x0_16, sf);
+      y0_16 = sf->scale_value_y(y0_16, sf);
     } else {
       scaled_mv.row = mv_q4.row;
       scaled_mv.col = mv_q4.col;
@@ -361,7 +360,7 @@
     }
 
     inter_predictor(buf_ptr, pre_buf->stride, dst, dst_buf->stride, subpel_x,
-                    subpel_y, scale, w, h, ref, &xd->subpix, xs, ys);
+                    subpel_y, sf, w, h, ref, &xd->subpix, xs, ys);
   }
 }
 
@@ -396,15 +395,9 @@
 void vp9_setup_scale_factors(VP9_COMMON *cm, int i) {
   const int ref = cm->active_ref_idx[i];
   struct scale_factors *const sf = &cm->active_ref_scale[i];
-  struct scale_factors_common *const sfc = &cm->active_ref_scale_comm[i];
-  if (ref >= FRAME_BUFFERS) {
-    vp9_zero(*sf);
-    vp9_zero(*sfc);
-  } else {
-    YV12_BUFFER_CONFIG *const fb = &cm->yv12_fb[ref];
-    vp9_setup_scale_factors_for_frame(sf, sfc,
-                                      fb->y_crop_width, fb->y_crop_height,
-                                      cm->width, cm->height);
-  }
+  YV12_BUFFER_CONFIG *const fb = &cm->yv12_fb[ref];
+  vp9_setup_scale_factors_for_frame(sf,
+                                    fb->y_crop_width, fb->y_crop_height,
+                                    cm->width, cm->height);
 }
 
diff --git a/vp9/common/vp9_reconinter.h b/vp9/common/vp9_reconinter.h
index 4a302f9..a4e968c 100644
--- a/vp9/common/vp9_reconinter.h
+++ b/vp9/common/vp9_reconinter.h
@@ -30,17 +30,16 @@
 void vp9_build_inter_predictor(const uint8_t *src, int src_stride,
                                uint8_t *dst, int dst_stride,
                                const MV *mv_q3,
-                               const struct scale_factors *scale,
+                               const struct scale_factors *sf,
                                int w, int h, int do_avg,
                                const struct subpix_fn_table *subpix,
-                               enum mv_precision precision);
+                               enum mv_precision precision,
+                               int x, int y);
 
 static int scaled_buffer_offset(int x_offset, int y_offset, int stride,
-                                const struct scale_factors *scale) {
-  const int x = scale ? scale->sfc->scale_value_x(x_offset, scale->sfc) :
-      x_offset;
-  const int y = scale ? scale->sfc->scale_value_y(y_offset, scale->sfc) :
-      y_offset;
+                                const struct scale_factors *sf) {
+  const int x = sf ? sf->scale_value_x(x_offset, sf) : x_offset;
+  const int y = sf ? sf->scale_value_y(y_offset, sf) : y_offset;
   return y * stride + x;
 }
 
@@ -91,10 +90,10 @@
   }
 }
 
-static void set_scale_factors(MACROBLOCKD *xd, int ref0, int ref1,
-                              struct scale_factors sf[MAX_REF_FRAMES]) {
-  xd->scale_factor[0] = sf[ref0 >= 0 ? ref0 : 0];
-  xd->scale_factor[1] = sf[ref1 >= 0 ? ref1 : 0];
+static void set_scale_factors(VP9_COMMON *cm, MACROBLOCKD *xd,
+                              int ref0, int ref1) {
+  xd->scale_factors[0] = &cm->active_ref_scale[ref0 >= 0 ? ref0 : 0];
+  xd->scale_factors[1] = &cm->active_ref_scale[ref1 >= 0 ? ref1 : 0];
 }
 
 void vp9_setup_scale_factors(VP9_COMMON *cm, int i);
diff --git a/vp9/common/vp9_reconintra.c b/vp9/common/vp9_reconintra.c
index eb643b0..96ba3e4 100644
--- a/vp9/common/vp9_reconintra.c
+++ b/vp9/common/vp9_reconintra.c
@@ -313,17 +313,21 @@
 #undef intra_pred_allsizes
 }
 
-static void build_intra_predictors(const uint8_t *ref, int ref_stride,
-                                   uint8_t *dst, int dst_stride,
+static void build_intra_predictors(const MACROBLOCKD *xd, const uint8_t *ref,
+                                   int ref_stride, uint8_t *dst, int dst_stride,
                                    MB_PREDICTION_MODE mode, TX_SIZE tx_size,
                                    int up_available, int left_available,
-                                   int right_available) {
+                                   int right_available, int x, int y,
+                                   int plane) {
   int i;
   DECLARE_ALIGNED_ARRAY(16, uint8_t, left_col, 64);
   DECLARE_ALIGNED_ARRAY(16, uint8_t, above_data, 128 + 16);
   uint8_t *above_row = above_data + 16;
   const uint8_t *const_above_row = above_row;
   const int bs = 4 << tx_size;
+  int frame_width, frame_height;
+  int x0, y0;
+  const struct macroblockd_plane *const pd = &xd->plane[plane];
 
   // 127 127 127 .. 127 127 127 127 127 127
   // 129  A   B  ..  Y   Z
@@ -334,26 +338,90 @@
 
   once(init_intra_pred_fn_ptrs);
 
+  // Get current frame pointer, width and height.
+  if (plane == 0) {
+    frame_width = xd->cur_buf->y_width;
+    frame_height = xd->cur_buf->y_height;
+  } else {
+    frame_width = xd->cur_buf->uv_width;
+    frame_height = xd->cur_buf->uv_height;
+  }
+
+  // Get block position in current frame.
+  x0 = (-xd->mb_to_left_edge >> (3 + pd->subsampling_x)) + x;
+  y0 = (-xd->mb_to_top_edge >> (3 + pd->subsampling_y)) + y;
+
   // left
   if (left_available) {
-    for (i = 0; i < bs; i++)
-      left_col[i] = ref[i * ref_stride - 1];
+    if (xd->mb_to_bottom_edge < 0) {
+      /* slower path if the block needs border extension */
+      if (y0 + bs <= frame_height) {
+        for (i = 0; i < bs; ++i)
+          left_col[i] = ref[i * ref_stride - 1];
+      } else {
+        const int extend_bottom = frame_height - y0;
+        for (i = 0; i < extend_bottom; ++i)
+          left_col[i] = ref[i * ref_stride - 1];
+        for (; i < bs; ++i)
+          left_col[i] = ref[(extend_bottom - 1) * ref_stride - 1];
+      }
+    } else {
+      /* faster path if the block does not need extension */
+      for (i = 0; i < bs; ++i)
+        left_col[i] = ref[i * ref_stride - 1];
+    }
   } else {
     vpx_memset(left_col, 129, bs);
   }
 
+  // TODO(hkuang) do not extend 2*bs pixels for all modes.
   // above
   if (up_available) {
     const uint8_t *above_ref = ref - ref_stride;
-    if (bs == 4 && right_available && left_available) {
-      const_above_row = above_ref;
+    if (xd->mb_to_right_edge < 0) {
+      /* slower path if the block needs border extension */
+      if (x0 + 2 * bs <= frame_width) {
+        if (right_available && bs == 4) {
+          vpx_memcpy(above_row - 1, above_ref - 1, 2 * bs + 1);
+        } else {
+          vpx_memcpy(above_row - 1, above_ref - 1, bs + 1);
+          vpx_memset(above_row + bs, above_row[bs - 1], bs);
+        }
+      } else if (x0 + bs <= frame_width) {
+        const int r = frame_width - x0;
+        if (right_available && bs == 4) {
+          vpx_memcpy(above_row - 1, above_ref - 1, r + 1);
+          vpx_memset(above_row + r, above_row[r - 1],
+                     x0 + 2 * bs - frame_width);
+        } else {
+          vpx_memcpy(above_row - 1, above_ref - 1, bs + 1);
+          vpx_memset(above_row + bs, above_row[bs - 1], bs);
+        }
+      } else if (x0 <= frame_width) {
+        const int r = frame_width - x0;
+        if (right_available && bs == 4) {
+          vpx_memcpy(above_row - 1, above_ref - 1, r + 1);
+          vpx_memset(above_row + r, above_row[r - 1],
+                     x0 + 2 * bs - frame_width);
+        } else {
+          vpx_memcpy(above_row - 1, above_ref - 1, r + 1);
+          vpx_memset(above_row + r, above_row[r - 1],
+                     x0 + 2 * bs - frame_width);
+        }
+        above_row[-1] = left_available ? above_ref[-1] : 129;
+      }
     } else {
-      vpx_memcpy(above_row, above_ref, bs);
-      if (bs == 4 && right_available)
-        vpx_memcpy(above_row + bs, above_ref + bs, bs);
-      else
-        vpx_memset(above_row + bs, above_row[bs - 1], bs);
-      above_row[-1] = left_available ? above_ref[-1] : 129;
+      /* faster path if the block does not need extension */
+      if (bs == 4 && right_available && left_available) {
+        const_above_row = above_ref;
+      } else {
+        vpx_memcpy(above_row, above_ref, bs);
+        if (bs == 4 && right_available)
+          vpx_memcpy(above_row + bs, above_ref + bs, bs);
+        else
+          vpx_memset(above_row + bs, above_row[bs - 1], bs);
+        above_row[-1] = left_available ? above_ref[-1] : 129;
+      }
     }
   } else {
     vpx_memset(above_row, 127, bs * 2);
@@ -370,16 +438,19 @@
 }
 
 void vp9_predict_intra_block(const MACROBLOCKD *xd, int block_idx, int bwl_in,
-                            TX_SIZE tx_size, int mode,
-                            const uint8_t *ref, int ref_stride,
-                            uint8_t *dst, int dst_stride) {
+                             TX_SIZE tx_size, int mode,
+                             const uint8_t *ref, int ref_stride,
+                             uint8_t *dst, int dst_stride,
+                             int aoff, int loff, int plane) {
   const int bwl = bwl_in - tx_size;
   const int wmask = (1 << bwl) - 1;
   const int have_top = (block_idx >> bwl) || xd->up_available;
   const int have_left = (block_idx & wmask) || xd->left_available;
   const int have_right = ((block_idx & wmask) != wmask);
+  const int x = aoff * 4;
+  const int y = loff * 4;
 
   assert(bwl >= 0);
-  build_intra_predictors(ref, ref_stride, dst, dst_stride, mode, tx_size,
-                         have_top, have_left, have_right);
+  build_intra_predictors(xd, ref, ref_stride, dst, dst_stride, mode, tx_size,
+                         have_top, have_left, have_right, x, y, plane);
 }
diff --git a/vp9/common/vp9_reconintra.h b/vp9/common/vp9_reconintra.h
index 6e3f55c..fc916fc 100644
--- a/vp9/common/vp9_reconintra.h
+++ b/vp9/common/vp9_reconintra.h
@@ -17,5 +17,6 @@
 void vp9_predict_intra_block(const MACROBLOCKD *xd, int block_idx, int bwl_in,
                              TX_SIZE tx_size, int mode,
                              const uint8_t *ref, int ref_stride,
-                             uint8_t *dst, int dst_stride);
+                             uint8_t *dst, int dst_stride,
+                             int aoff, int loff, int plane);
 #endif  // VP9_COMMON_VP9_RECONINTRA_H_
diff --git a/vp9/common/vp9_rtcd_defs.sh b/vp9/common/vp9_rtcd_defs.sh
index 19d5fc3..3025ed4 100644
--- a/vp9/common/vp9_rtcd_defs.sh
+++ b/vp9/common/vp9_rtcd_defs.sh
@@ -14,6 +14,7 @@
 struct vp9_variance_vtable;
 
 #define DEC_MVCOSTS int *mvjcost, int *mvcost[2]
+struct mv;
 union int_mv;
 struct yv12_buffer_config;
 EOF
@@ -190,38 +191,38 @@
 #
 # Loopfilter
 #
-prototype void vp9_mb_lpf_vertical_edge_w "uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh"
-specialize vp9_mb_lpf_vertical_edge_w sse2 neon dspr2
+prototype void vp9_lpf_vertical_16 "uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh"
+specialize vp9_lpf_vertical_16 sse2 neon dspr2
 
-prototype void vp9_mb_lpf_vertical_edge_w_16 "uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh"
-specialize vp9_mb_lpf_vertical_edge_w_16 sse2 neon dspr2
+prototype void vp9_lpf_vertical_16_dual "uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh"
+specialize vp9_lpf_vertical_16_dual sse2 neon dspr2
 
-prototype void vp9_mbloop_filter_vertical_edge "uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count"
-specialize vp9_mbloop_filter_vertical_edge sse2 neon dspr2
+prototype void vp9_lpf_vertical_8 "uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count"
+specialize vp9_lpf_vertical_8 sse2 neon dspr2
 
-prototype void vp9_mbloop_filter_vertical_edge_16 "uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1"
-specialize vp9_mbloop_filter_vertical_edge_16 sse2 neon dspr2
+prototype void vp9_lpf_vertical_8_dual "uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1"
+specialize vp9_lpf_vertical_8_dual sse2 neon dspr2
 
-prototype void vp9_loop_filter_vertical_edge "uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count"
-specialize vp9_loop_filter_vertical_edge mmx neon dspr2
+prototype void vp9_lpf_vertical_4 "uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count"
+specialize vp9_lpf_vertical_4 mmx neon dspr2
 
-prototype void vp9_loop_filter_vertical_edge_16 "uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1"
-specialize vp9_loop_filter_vertical_edge_16 sse2 neon dspr2
+prototype void vp9_lpf_vertical_4_dual "uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1"
+specialize vp9_lpf_vertical_4_dual sse2 neon dspr2
 
-prototype void vp9_mb_lpf_horizontal_edge_w "uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count"
-specialize vp9_mb_lpf_horizontal_edge_w sse2 avx2 neon dspr2
+prototype void vp9_lpf_horizontal_16 "uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count"
+specialize vp9_lpf_horizontal_16 sse2 avx2 neon dspr2
 
-prototype void vp9_mbloop_filter_horizontal_edge "uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count"
-specialize vp9_mbloop_filter_horizontal_edge sse2 neon dspr2
+prototype void vp9_lpf_horizontal_8 "uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count"
+specialize vp9_lpf_horizontal_8 sse2 neon dspr2
 
-prototype void vp9_mbloop_filter_horizontal_edge_16 "uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1"
-specialize vp9_mbloop_filter_horizontal_edge_16 sse2 neon dspr2
+prototype void vp9_lpf_horizontal_8_dual "uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1"
+specialize vp9_lpf_horizontal_8_dual sse2 neon dspr2
 
-prototype void vp9_loop_filter_horizontal_edge "uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count"
-specialize vp9_loop_filter_horizontal_edge mmx neon dspr2
+prototype void vp9_lpf_horizontal_4 "uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count"
+specialize vp9_lpf_horizontal_4 mmx neon dspr2
 
-prototype void vp9_loop_filter_horizontal_edge_16 "uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1"
-specialize vp9_loop_filter_horizontal_edge_16 sse2 neon dspr2
+prototype void vp9_lpf_horizontal_4_dual "uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1"
+specialize vp9_lpf_horizontal_4_dual sse2 neon dspr2
 
 #
 # post proc
@@ -736,20 +737,20 @@
 #
 # Motion search
 #
-prototype int vp9_full_search_sad "struct macroblock *x, union int_mv *ref_mv, int sad_per_bit, int distance, struct vp9_variance_vtable *fn_ptr, DEC_MVCOSTS, union int_mv *center_mv, int n"
+prototype int vp9_full_search_sad "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"
 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 "struct macroblock *x, union int_mv *ref_mv, int sad_per_bit, int distance, struct vp9_variance_vtable *fn_ptr, DEC_MVCOSTS, union int_mv *center_mv"
+prototype int vp9_refining_search_sad "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"
 specialize vp9_refining_search_sad sse3
 vp9_refining_search_sad_sse3=vp9_refining_search_sadx4
 
-prototype int vp9_diamond_search_sad "struct macroblock *x, union int_mv *ref_mv, union int_mv *best_mv, int search_param, int sad_per_bit, int *num00, struct vp9_variance_vtable *fn_ptr, DEC_MVCOSTS, union int_mv *center_mv"
+prototype int vp9_diamond_search_sad "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"
 specialize vp9_diamond_search_sad sse3
 vp9_diamond_search_sad_sse3=vp9_diamond_search_sadx4
 
-prototype int vp9_full_range_search "struct macroblock *x, union int_mv *ref_mv, union int_mv *best_mv, int search_param, int sad_per_bit, int *num00, struct vp9_variance_vtable *fn_ptr, DEC_MVCOSTS, union int_mv *center_mv"
+prototype int vp9_full_range_search "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"
 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/common/vp9_scale.c b/vp9/common/vp9_scale.c
index 3f0994f..e0f1e34 100644
--- a/vp9/common/vp9_scale.c
+++ b/vp9/common/vp9_scale.c
@@ -12,47 +12,19 @@
 #include "vp9/common/vp9_filter.h"
 #include "vp9/common/vp9_scale.h"
 
-static INLINE int scaled_x(int val, const struct scale_factors_common *sfc) {
-  return val * sfc->x_scale_fp >> REF_SCALE_SHIFT;
+static INLINE int scaled_x(int val, const struct scale_factors *sf) {
+  return val * sf->x_scale_fp >> REF_SCALE_SHIFT;
 }
 
-static INLINE int scaled_y(int val, const struct scale_factors_common *sfc) {
-  return val * sfc->y_scale_fp >> REF_SCALE_SHIFT;
+static INLINE int scaled_y(int val, const struct scale_factors *sf) {
+  return val * sf->y_scale_fp >> REF_SCALE_SHIFT;
 }
 
-static int unscaled_value(int val, const struct scale_factors_common *sfc) {
-  (void) sfc;
+static int unscaled_value(int val, const struct scale_factors *sf) {
+  (void) sf;
   return val;
 }
 
-static MV32 scaled_mv(const MV *mv, const struct scale_factors *scale) {
-  const MV32 res = {
-    scaled_y(mv->row, scale->sfc) + scale->y_offset_q4,
-    scaled_x(mv->col, scale->sfc) + scale->x_offset_q4
-  };
-  return res;
-}
-
-static MV32 unscaled_mv(const MV *mv, const struct scale_factors *scale) {
-  const MV32 res = {
-    mv->row,
-    mv->col
-  };
-  return res;
-}
-
-static void set_offsets_with_scaling(struct scale_factors *scale,
-                                     int row, int col) {
-  scale->x_offset_q4 = scaled_x(col << SUBPEL_BITS, scale->sfc) & SUBPEL_MASK;
-  scale->y_offset_q4 = scaled_y(row << SUBPEL_BITS, scale->sfc) & SUBPEL_MASK;
-}
-
-static void set_offsets_without_scaling(struct scale_factors *scale,
-                                        int row, int col) {
-  scale->x_offset_q4 = 0;
-  scale->y_offset_q4 = 0;
-}
-
 static int get_fixed_point_scale_factor(int other_size, int this_size) {
   // Calculate scaling factor once for each reference frame
   // and use fixed point scaling factors in decoding and encoding routines.
@@ -69,31 +41,36 @@
          this_h <= 16 * other_h;
 }
 
-void vp9_setup_scale_factors_for_frame(struct scale_factors *scale,
-                                       struct scale_factors_common *scale_comm,
+MV32 vp9_scale_mv(const MV *mv, int x, int y, const struct scale_factors *sf) {
+  const int x_off_q4 = scaled_x(x << SUBPEL_BITS, sf) & SUBPEL_MASK;
+  const int y_off_q4 = scaled_y(y << SUBPEL_BITS, sf) & SUBPEL_MASK;
+  const MV32 res = {
+    scaled_y(mv->row, sf) + y_off_q4,
+    scaled_x(mv->col, sf) + x_off_q4
+  };
+  return res;
+}
+
+void vp9_setup_scale_factors_for_frame(struct scale_factors *sf,
                                        int other_w, int other_h,
                                        int this_w, int this_h) {
   if (!check_scale_factors(other_w, other_h, this_w, this_h)) {
-    scale_comm->x_scale_fp = REF_INVALID_SCALE;
-    scale_comm->y_scale_fp = REF_INVALID_SCALE;
+    sf->x_scale_fp = REF_INVALID_SCALE;
+    sf->y_scale_fp = REF_INVALID_SCALE;
     return;
   }
 
-  scale_comm->x_scale_fp = get_fixed_point_scale_factor(other_w, this_w);
-  scale_comm->y_scale_fp = get_fixed_point_scale_factor(other_h, this_h);
-  scale_comm->x_step_q4 = scaled_x(16, scale_comm);
-  scale_comm->y_step_q4 = scaled_y(16, scale_comm);
+  sf->x_scale_fp = get_fixed_point_scale_factor(other_w, this_w);
+  sf->y_scale_fp = get_fixed_point_scale_factor(other_h, this_h);
+  sf->x_step_q4 = scaled_x(16, sf);
+  sf->y_step_q4 = scaled_y(16, sf);
 
-  if (vp9_is_scaled(scale_comm)) {
-    scale_comm->scale_value_x = scaled_x;
-    scale_comm->scale_value_y = scaled_y;
-    scale_comm->set_scaled_offsets = set_offsets_with_scaling;
-    scale_comm->scale_mv = scaled_mv;
+  if (vp9_is_scaled(sf)) {
+    sf->scale_value_x = scaled_x;
+    sf->scale_value_y = scaled_y;
   } else {
-    scale_comm->scale_value_x = unscaled_value;
-    scale_comm->scale_value_y = unscaled_value;
-    scale_comm->set_scaled_offsets = set_offsets_without_scaling;
-    scale_comm->scale_mv = unscaled_mv;
+    sf->scale_value_x = unscaled_value;
+    sf->scale_value_y = unscaled_value;
   }
 
   // TODO(agrange): Investigate the best choice of functions to use here
@@ -102,48 +79,44 @@
   // applied in one direction only, and not at all for 0,0, seems to give the
   // best quality, but it may be worth trying an additional mode that does
   // do the filtering on full-pel.
-  if (scale_comm->x_step_q4 == 16) {
-    if (scale_comm->y_step_q4 == 16) {
+  if (sf->x_step_q4 == 16) {
+    if (sf->y_step_q4 == 16) {
       // No scaling in either direction.
-      scale_comm->predict[0][0][0] = vp9_convolve_copy;
-      scale_comm->predict[0][0][1] = vp9_convolve_avg;
-      scale_comm->predict[0][1][0] = vp9_convolve8_vert;
-      scale_comm->predict[0][1][1] = vp9_convolve8_avg_vert;
-      scale_comm->predict[1][0][0] = vp9_convolve8_horiz;
-      scale_comm->predict[1][0][1] = vp9_convolve8_avg_horiz;
+      sf->predict[0][0][0] = vp9_convolve_copy;
+      sf->predict[0][0][1] = vp9_convolve_avg;
+      sf->predict[0][1][0] = vp9_convolve8_vert;
+      sf->predict[0][1][1] = vp9_convolve8_avg_vert;
+      sf->predict[1][0][0] = vp9_convolve8_horiz;
+      sf->predict[1][0][1] = vp9_convolve8_avg_horiz;
     } else {
       // No scaling in x direction. Must always scale in the y direction.
-      scale_comm->predict[0][0][0] = vp9_convolve8_vert;
-      scale_comm->predict[0][0][1] = vp9_convolve8_avg_vert;
-      scale_comm->predict[0][1][0] = vp9_convolve8_vert;
-      scale_comm->predict[0][1][1] = vp9_convolve8_avg_vert;
-      scale_comm->predict[1][0][0] = vp9_convolve8;
-      scale_comm->predict[1][0][1] = vp9_convolve8_avg;
+      sf->predict[0][0][0] = vp9_convolve8_vert;
+      sf->predict[0][0][1] = vp9_convolve8_avg_vert;
+      sf->predict[0][1][0] = vp9_convolve8_vert;
+      sf->predict[0][1][1] = vp9_convolve8_avg_vert;
+      sf->predict[1][0][0] = vp9_convolve8;
+      sf->predict[1][0][1] = vp9_convolve8_avg;
     }
   } else {
-    if (scale_comm->y_step_q4 == 16) {
+    if (sf->y_step_q4 == 16) {
       // No scaling in the y direction. Must always scale in the x direction.
-      scale_comm->predict[0][0][0] = vp9_convolve8_horiz;
-      scale_comm->predict[0][0][1] = vp9_convolve8_avg_horiz;
-      scale_comm->predict[0][1][0] = vp9_convolve8;
-      scale_comm->predict[0][1][1] = vp9_convolve8_avg;
-      scale_comm->predict[1][0][0] = vp9_convolve8_horiz;
-      scale_comm->predict[1][0][1] = vp9_convolve8_avg_horiz;
+      sf->predict[0][0][0] = vp9_convolve8_horiz;
+      sf->predict[0][0][1] = vp9_convolve8_avg_horiz;
+      sf->predict[0][1][0] = vp9_convolve8;
+      sf->predict[0][1][1] = vp9_convolve8_avg;
+      sf->predict[1][0][0] = vp9_convolve8_horiz;
+      sf->predict[1][0][1] = vp9_convolve8_avg_horiz;
     } else {
       // Must always scale in both directions.
-      scale_comm->predict[0][0][0] = vp9_convolve8;
-      scale_comm->predict[0][0][1] = vp9_convolve8_avg;
-      scale_comm->predict[0][1][0] = vp9_convolve8;
-      scale_comm->predict[0][1][1] = vp9_convolve8_avg;
-      scale_comm->predict[1][0][0] = vp9_convolve8;
-      scale_comm->predict[1][0][1] = vp9_convolve8_avg;
+      sf->predict[0][0][0] = vp9_convolve8;
+      sf->predict[0][0][1] = vp9_convolve8_avg;
+      sf->predict[0][1][0] = vp9_convolve8;
+      sf->predict[0][1][1] = vp9_convolve8_avg;
+      sf->predict[1][0][0] = vp9_convolve8;
+      sf->predict[1][0][1] = vp9_convolve8_avg;
     }
   }
   // 2D subpel motion always gets filtered in both directions
-  scale_comm->predict[1][1][0] = vp9_convolve8;
-  scale_comm->predict[1][1][1] = vp9_convolve8_avg;
-
-  scale->sfc = scale_comm;
-  scale->x_offset_q4 = 0;  // calculated per block
-  scale->y_offset_q4 = 0;  // calculated per block
+  sf->predict[1][1][0] = vp9_convolve8;
+  sf->predict[1][1][1] = vp9_convolve8_avg;
 }
diff --git a/vp9/common/vp9_scale.h b/vp9/common/vp9_scale.h
index 1437fcd..55b4d88 100644
--- a/vp9/common/vp9_scale.h
+++ b/vp9/common/vp9_scale.h
@@ -18,40 +18,32 @@
 #define REF_NO_SCALE (1 << REF_SCALE_SHIFT)
 #define REF_INVALID_SCALE -1
 
-struct scale_factors;
-struct scale_factors_common {
+struct scale_factors {
   int x_scale_fp;   // horizontal fixed point scale factor
   int y_scale_fp;   // vertical fixed point scale factor
   int x_step_q4;
   int y_step_q4;
 
-  int (*scale_value_x)(int val, const struct scale_factors_common *sfc);
-  int (*scale_value_y)(int val, const struct scale_factors_common *sfc);
-  void (*set_scaled_offsets)(struct scale_factors *scale, int row, int col);
-  MV32 (*scale_mv)(const MV *mv, const struct scale_factors *scale);
+  int (*scale_value_x)(int val, const struct scale_factors *sf);
+  int (*scale_value_y)(int val, const struct scale_factors *sf);
 
   convolve_fn_t predict[2][2][2];  // horiz, vert, avg
 };
 
-struct scale_factors {
-  int x_offset_q4;
-  int y_offset_q4;
-  const struct scale_factors_common *sfc;
-};
+MV32 vp9_scale_mv(const MV *mv, int x, int y, const struct scale_factors *sf);
 
-void vp9_setup_scale_factors_for_frame(struct scale_factors *scale,
-                                       struct scale_factors_common *scale_comm,
+void vp9_setup_scale_factors_for_frame(struct scale_factors *sf,
                                        int other_w, int other_h,
                                        int this_w, int this_h);
 
-static int vp9_is_valid_scale(const struct scale_factors_common *sfc) {
-  return sfc->x_scale_fp != REF_INVALID_SCALE &&
-         sfc->y_scale_fp != REF_INVALID_SCALE;
+static int vp9_is_valid_scale(const struct scale_factors *sf) {
+  return sf->x_scale_fp != REF_INVALID_SCALE &&
+         sf->y_scale_fp != REF_INVALID_SCALE;
 }
 
-static int vp9_is_scaled(const struct scale_factors_common *sfc) {
-  return sfc->x_scale_fp != REF_NO_SCALE ||
-         sfc->y_scale_fp != REF_NO_SCALE;
+static int vp9_is_scaled(const struct scale_factors *sf) {
+  return sf->x_scale_fp != REF_NO_SCALE ||
+         sf->y_scale_fp != REF_NO_SCALE;
 }
 
 #endif  // VP9_COMMON_VP9_SCALE_H_
diff --git a/vp9/common/vp9_seg_common.c b/vp9/common/vp9_seg_common.c
index ef30404..910200e 100644
--- a/vp9/common/vp9_seg_common.c
+++ b/vp9/common/vp9_seg_common.c
@@ -41,11 +41,6 @@
   seg->feature_mask[segment_id] |= 1 << feature_id;
 }
 
-void vp9_disable_segfeature(struct segmentation *seg, int segment_id,
-                            SEG_LVL_FEATURES feature_id) {
-  seg->feature_mask[segment_id] &= ~(1 << feature_id);
-}
-
 int vp9_seg_feature_data_max(SEG_LVL_FEATURES feature_id) {
   return seg_feature_data_max[feature_id];
 }
@@ -54,11 +49,6 @@
   return seg_feature_data_signed[feature_id];
 }
 
-void vp9_clear_segdata(struct segmentation *seg, int segment_id,
-                       SEG_LVL_FEATURES feature_id) {
-  seg->feature_data[segment_id][feature_id] = 0;
-}
-
 void vp9_set_segdata(struct segmentation *seg, int segment_id,
                      SEG_LVL_FEATURES feature_id, int seg_data) {
   assert(seg_data <= seg_feature_data_max[feature_id]);
diff --git a/vp9/common/vp9_seg_common.h b/vp9/common/vp9_seg_common.h
index eb38c06..8ff54fb 100644
--- a/vp9/common/vp9_seg_common.h
+++ b/vp9/common/vp9_seg_common.h
@@ -11,7 +11,7 @@
 #ifndef VP9_COMMON_VP9_SEG_COMMON_H_
 #define VP9_COMMON_VP9_SEG_COMMON_H_
 
-#include "vp9/common/vp9_treecoder.h"
+#include "vp9/common/vp9_prob.h"
 
 #define SEGMENT_DELTADATA   0
 #define SEGMENT_ABSDATA     1
@@ -55,18 +55,10 @@
                            int segment_id,
                            SEG_LVL_FEATURES feature_id);
 
-void vp9_disable_segfeature(struct segmentation *seg,
-                            int segment_id,
-                            SEG_LVL_FEATURES feature_id);
-
 int vp9_seg_feature_data_max(SEG_LVL_FEATURES feature_id);
 
 int vp9_is_segfeature_signed(SEG_LVL_FEATURES feature_id);
 
-void vp9_clear_segdata(struct segmentation *seg,
-                       int segment_id,
-                       SEG_LVL_FEATURES feature_id);
-
 void vp9_set_segdata(struct segmentation *seg,
                      int segment_id,
                      SEG_LVL_FEATURES feature_id,
diff --git a/vp9/common/x86/vp9_asm_stubs.c b/vp9/common/x86/vp9_asm_stubs.c
index 106e6d4..f954236 100644
--- a/vp9/common/x86/vp9_asm_stubs.c
+++ b/vp9/common/x86/vp9_asm_stubs.c
@@ -13,28 +13,6 @@
 #include "./vpx_config.h"
 #include "./vp9_rtcd.h"
 #include "vpx_ports/mem.h"
-///////////////////////////////////////////////////////////////////////////
-// the mmx function that does the bilinear filtering and var calculation //
-// int one pass                                                          //
-///////////////////////////////////////////////////////////////////////////
-DECLARE_ALIGNED(16, const short, vp9_bilinear_filters_mmx[16][8]) = {
-  { 128, 128, 128, 128,  0,  0,  0,  0 },
-  { 120, 120, 120, 120,  8,  8,  8,  8 },
-  { 112, 112, 112, 112, 16, 16, 16, 16 },
-  { 104, 104, 104, 104, 24, 24, 24, 24 },
-  {  96, 96, 96, 96, 32, 32, 32, 32 },
-  {  88, 88, 88, 88, 40, 40, 40, 40 },
-  {  80, 80, 80, 80, 48, 48, 48, 48 },
-  {  72, 72, 72, 72, 56, 56, 56, 56 },
-  {  64, 64, 64, 64, 64, 64, 64, 64 },
-  {  56, 56, 56, 56, 72, 72, 72, 72 },
-  {  48, 48, 48, 48, 80, 80, 80, 80 },
-  {  40, 40, 40, 40, 88, 88, 88, 88 },
-  {  32, 32, 32, 32, 96, 96, 96, 96 },
-  {  24, 24, 24, 24, 104, 104, 104, 104 },
-  {  16, 16, 16, 16, 112, 112, 112, 112 },
-  {   8,  8,  8,  8, 120, 120, 120, 120 }
-};
 
 typedef void filter8_1dfunction (
   const unsigned char *src_ptr,
diff --git a/vp9/common/x86/vp9_idct_intrin_sse2.c b/vp9/common/x86/vp9_idct_intrin_sse2.c
index 947c0ba..06df850 100644
--- a/vp9/common/x86/vp9_idct_intrin_sse2.c
+++ b/vp9/common/x86/vp9_idct_intrin_sse2.c
@@ -361,24 +361,23 @@
     out7 = _mm_unpackhi_epi64(tr1_3, tr1_7); \
   }
 
-#define TRANSPOSE_4X8(in0, in1, in2, in3, in4, in5, in6, in7, \
-                      out0, out1, out2, out3, out4, out5, out6, out7) \
-  {                                                     \
-    const __m128i tr0_0 = _mm_unpacklo_epi16(in0, in1); \
-    const __m128i tr0_1 = _mm_unpacklo_epi16(in2, in3); \
-    const __m128i tr0_4 = _mm_unpacklo_epi16(in4, in5); \
-    const __m128i tr0_5 = _mm_unpacklo_epi16(in6, in7); \
-                                                        \
+#define TRANSPOSE_4X8_10(tmp0, tmp1, tmp2, tmp3, \
+                         out0, out1, out2, out3) \
+  {                                              \
+    const __m128i tr0_0 = _mm_unpackhi_epi16(tmp0, tmp1); \
+    const __m128i tr0_1 = _mm_unpacklo_epi16(tmp1, tmp0); \
+    const __m128i tr0_4 = _mm_unpacklo_epi16(tmp2, tmp3); \
+    const __m128i tr0_5 = _mm_unpackhi_epi16(tmp3, tmp2); \
+    \
     const __m128i tr1_0 = _mm_unpacklo_epi32(tr0_0, tr0_1); \
     const __m128i tr1_2 = _mm_unpackhi_epi32(tr0_0, tr0_1); \
     const __m128i tr1_4 = _mm_unpacklo_epi32(tr0_4, tr0_5); \
     const __m128i tr1_6 = _mm_unpackhi_epi32(tr0_4, tr0_5); \
-                                                            \
+    \
     out0 = _mm_unpacklo_epi64(tr1_0, tr1_4); \
     out1 = _mm_unpackhi_epi64(tr1_0, tr1_4); \
     out2 = _mm_unpacklo_epi64(tr1_2, tr1_6); \
     out3 = _mm_unpackhi_epi64(tr1_2, tr1_6); \
-    out4 = out5 = out6 = out7 = zero; \
   }
 
 #define TRANSPOSE_8X4(in0, in1, in2, in3, out0, out1, out2, out3) \
@@ -394,6 +393,14 @@
     in3 = _mm_unpackhi_epi32(tr0_2, tr0_3);  /* i7 i6 */  \
   }
 
+#define TRANSPOSE_8X8_10(in0, in1, in2, in3, out0, out1) \
+  {                                            \
+    const __m128i tr0_0 = _mm_unpacklo_epi16(in0, in1); \
+    const __m128i tr0_1 = _mm_unpacklo_epi16(in2, in3); \
+    out0 = _mm_unpacklo_epi32(tr0_0, tr0_1); \
+    out1 = _mm_unpackhi_epi32(tr0_0, tr0_1); \
+  }
+
 // Define Macro for multiplying elements by constants and adding them together.
 #define MULTIPLICATION_AND_ADD(lo_0, hi_0, lo_1, hi_1, \
                                cst0, cst1, cst2, cst3, res0, res1, res2, res3) \
@@ -563,8 +570,8 @@
   // 2-D
   for (i = 0; i < 2; i++) {
     // 8x8 Transpose is copied from vp9_fdct8x8_sse2()
-    TRANSPOSE_8X8(in0, in1, in2, in3, in4, in5, in6, in7, in0, in1, in2, in3,
-                  in4, in5, in6, in7);
+    TRANSPOSE_8X8(in0, in1, in2, in3, in4, in5, in6, in7,
+                  in0, in1, in2, in3, in4, in5, in6, in7);
 
     // 4-stage 1D idct8x8
     IDCT8_1D
@@ -685,18 +692,9 @@
   __m128i stp2_0, stp2_1, stp2_2, stp2_3, stp2_4, stp2_5, stp2_6, stp2_7;
   __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
 
-  in0 = in[0];
-  in1 = in[1];
-  in2 = in[2];
-  in3 = in[3];
-  in4 = in[4];
-  in5 = in[5];
-  in6 = in[6];
-  in7 = in[7];
-
   // 8x8 Transpose is copied from vp9_fdct8x8_sse2()
-  TRANSPOSE_8X8(in0, in1, in2, in3, in4, in5, in6, in7, in0, in1, in2, in3,
-                in4, in5, in6, in7);
+  TRANSPOSE_8X8(in[0], in[1], in[2], in[3], in[4], in[5], in[6], in[7],
+                in0, in1, in2, in3, in4, in5, in6, in7);
 
   // 4-stage 1D idct8x8
   IDCT8_1D
@@ -1032,12 +1030,11 @@
   in3 = _mm_load_si128((const __m128i *)(input + 8 * 3));
 
   // 8x4 Transpose
-  TRANSPOSE_8X4(in0, in1, in2, in3, in0, in1, in2, in3)
-
+  TRANSPOSE_8X8_10(in0, in1, in2, in3, in0, in1);
   // Stage1
   { //NOLINT
-    const __m128i lo_17 = _mm_unpackhi_epi16(in0, in3);
-    const __m128i lo_35 = _mm_unpackhi_epi16(in1, in2);
+    const __m128i lo_17 = _mm_unpackhi_epi16(in0, zero);
+    const __m128i lo_35 = _mm_unpackhi_epi16(in1, zero);
 
     tmp0 = _mm_madd_epi16(lo_17, stg1_0);
     tmp2 = _mm_madd_epi16(lo_17, stg1_1);
@@ -1053,16 +1050,14 @@
     tmp4 = _mm_srai_epi32(tmp4, DCT_CONST_BITS);
     tmp6 = _mm_srai_epi32(tmp6, DCT_CONST_BITS);
 
-    stp1_4 = _mm_packs_epi32(tmp0, zero);
-    stp1_7 = _mm_packs_epi32(tmp2, zero);
-    stp1_5 = _mm_packs_epi32(tmp4, zero);
-    stp1_6 = _mm_packs_epi32(tmp6, zero);
+    stp1_4 = _mm_packs_epi32(tmp0, tmp2);
+    stp1_5 = _mm_packs_epi32(tmp4, tmp6);
   }
 
   // Stage2
   { //NOLINT
-    const __m128i lo_04 = _mm_unpacklo_epi16(in0, in2);
-    const __m128i lo_26 = _mm_unpacklo_epi16(in1, in3);
+    const __m128i lo_04 = _mm_unpacklo_epi16(in0, zero);
+    const __m128i lo_26 = _mm_unpacklo_epi16(in1, zero);
 
     tmp0 = _mm_madd_epi16(lo_04, stg2_0);
     tmp2 = _mm_madd_epi16(lo_04, stg2_1);
@@ -1078,24 +1073,26 @@
     tmp4 = _mm_srai_epi32(tmp4, DCT_CONST_BITS);
     tmp6 = _mm_srai_epi32(tmp6, DCT_CONST_BITS);
 
-    stp2_0 = _mm_packs_epi32(tmp0, zero);
-    stp2_1 = _mm_packs_epi32(tmp2, zero);
-    stp2_2 = _mm_packs_epi32(tmp4, zero);
-    stp2_3 = _mm_packs_epi32(tmp6, zero);
+    stp2_0 = _mm_packs_epi32(tmp0, tmp2);
+    stp2_2 = _mm_packs_epi32(tmp6, tmp4);
 
-    stp2_4 = _mm_adds_epi16(stp1_4, stp1_5);
-    stp2_5 = _mm_subs_epi16(stp1_4, stp1_5);
-    stp2_6 = _mm_subs_epi16(stp1_7, stp1_6);
-    stp2_7 = _mm_adds_epi16(stp1_7, stp1_6);
+    tmp0 = _mm_adds_epi16(stp1_4, stp1_5);
+    tmp1 = _mm_subs_epi16(stp1_4, stp1_5);
+
+    stp2_4 = tmp0;
+    stp2_5 = _mm_unpacklo_epi64(tmp1, zero);
+    stp2_6 = _mm_unpackhi_epi64(tmp1, zero);
   }
 
   // Stage3
   { //NOLINT
     const __m128i lo_56 = _mm_unpacklo_epi16(stp2_5, stp2_6);
-    stp1_0 = _mm_adds_epi16(stp2_0, stp2_3);
-    stp1_1 = _mm_adds_epi16(stp2_1, stp2_2);
-    stp1_2 = _mm_subs_epi16(stp2_1, stp2_2);
-    stp1_3 = _mm_subs_epi16(stp2_0, stp2_3);
+
+    tmp4 = _mm_adds_epi16(stp2_0, stp2_2);
+    tmp6 = _mm_subs_epi16(stp2_0, stp2_2);
+
+    stp1_2 = _mm_unpackhi_epi64(tmp6, tmp4);
+    stp1_3 = _mm_unpacklo_epi64(tmp6, tmp4);
 
     tmp0 = _mm_madd_epi16(lo_56, stg3_0);
     tmp2 = _mm_madd_epi16(lo_56, stg2_0);  // stg3_1 = stg2_0
@@ -1105,27 +1102,19 @@
     tmp0 = _mm_srai_epi32(tmp0, DCT_CONST_BITS);
     tmp2 = _mm_srai_epi32(tmp2, DCT_CONST_BITS);
 
-    stp1_5 = _mm_packs_epi32(tmp0, zero);
-    stp1_6 = _mm_packs_epi32(tmp2, zero);
+    stp1_5 = _mm_packs_epi32(tmp0, tmp2);
   }
 
   // Stage4
-  in0 = _mm_adds_epi16(stp1_0, stp2_7);
-  in1 = _mm_adds_epi16(stp1_1, stp1_6);
-  in2 = _mm_adds_epi16(stp1_2, stp1_5);
-  in3 = _mm_adds_epi16(stp1_3, stp2_4);
-  in4 = _mm_subs_epi16(stp1_3, stp2_4);
-  in5 = _mm_subs_epi16(stp1_2, stp1_5);
-  in6 = _mm_subs_epi16(stp1_1, stp1_6);
-  in7 = _mm_subs_epi16(stp1_0, stp2_7);
+  tmp0 = _mm_adds_epi16(stp1_3, stp2_4);
+  tmp1 = _mm_adds_epi16(stp1_2, stp1_5);
+  tmp2 = _mm_subs_epi16(stp1_3, stp2_4);
+  tmp3 = _mm_subs_epi16(stp1_2, stp1_5);
 
-  // Columns. 4x8 Transpose
-  TRANSPOSE_4X8(in0, in1, in2, in3, in4, in5, in6, in7, in0, in1, in2, in3,
-                in4, in5, in6, in7)
+  TRANSPOSE_4X8_10(tmp0, tmp1, tmp2, tmp3, in0, in1, in2, in3)
+  in4 = in5 = in6 = in7 = zero;
 
-  // 1D idct8x8
   IDCT8_1D
-
   // Final rounding and shift
   in0 = _mm_adds_epi16(in0, final_rounding);
   in1 = _mm_adds_epi16(in1, final_rounding);
diff --git a/vp9/common/x86/vp9_loopfilter_intrin_avx2.c b/vp9/common/x86/vp9_loopfilter_intrin_avx2.c
index 3c5cb8f..439c028 100644
--- a/vp9/common/x86/vp9_loopfilter_intrin_avx2.c
+++ b/vp9/common/x86/vp9_loopfilter_intrin_avx2.c
@@ -933,7 +933,7 @@
     }
 }
 
-void vp9_mb_lpf_horizontal_edge_w_avx2(unsigned char *s, int p,
+void vp9_lpf_horizontal_16_avx2(unsigned char *s, int p,
         const unsigned char *_blimit, const unsigned char *_limit,
         const unsigned char *_thresh, int count) {
     if (count == 1)
diff --git a/vp9/common/x86/vp9_loopfilter_intrin_sse2.c b/vp9/common/x86/vp9_loopfilter_intrin_sse2.c
index 3ca55cf..448ad5a 100644
--- a/vp9/common/x86/vp9_loopfilter_intrin_sse2.c
+++ b/vp9/common/x86/vp9_loopfilter_intrin_sse2.c
@@ -846,24 +846,20 @@
 }
 
 // TODO(yunqingwang): remove count and call these 2 functions(8 or 16) directly.
-void vp9_mb_lpf_horizontal_edge_w_sse2(unsigned char *s,
-                                       int p,
-                                       const unsigned char *_blimit,
-                                       const unsigned char *_limit,
-                                       const unsigned char *_thresh,
-                                       int count) {
+void vp9_lpf_horizontal_16_sse2(unsigned char *s, int p,
+                                const unsigned char *_blimit,
+                                const unsigned char *_limit,
+                                const unsigned char *_thresh, int count) {
   if (count == 1)
     mb_lpf_horizontal_edge_w_sse2_8(s, p, _blimit, _limit, _thresh);
   else
     mb_lpf_horizontal_edge_w_sse2_16(s, p, _blimit, _limit, _thresh);
 }
 
-void vp9_mbloop_filter_horizontal_edge_sse2(unsigned char *s,
-                                            int p,
-                                            const unsigned char *_blimit,
-                                            const unsigned char *_limit,
-                                            const unsigned char *_thresh,
-                                            int count) {
+void vp9_lpf_horizontal_8_sse2(unsigned char *s, int p,
+                               const unsigned char *_blimit,
+                               const unsigned char *_limit,
+                               const unsigned char *_thresh, int count) {
   DECLARE_ALIGNED_ARRAY(16, unsigned char, flat_op2, 16);
   DECLARE_ALIGNED_ARRAY(16, unsigned char, flat_op1, 16);
   DECLARE_ALIGNED_ARRAY(16, unsigned char, flat_op0, 16);
@@ -1083,13 +1079,13 @@
   }
 }
 
-void vp9_mbloop_filter_horizontal_edge_16_sse2(uint8_t *s, int p,
-                                               const uint8_t *_blimit0,
-                                               const uint8_t *_limit0,
-                                               const uint8_t *_thresh0,
-                                               const uint8_t *_blimit1,
-                                               const uint8_t *_limit1,
-                                               const uint8_t *_thresh1) {
+void vp9_lpf_horizontal_8_dual_sse2(uint8_t *s, int p,
+                                    const uint8_t *_blimit0,
+                                    const uint8_t *_limit0,
+                                    const uint8_t *_thresh0,
+                                    const uint8_t *_blimit1,
+                                    const uint8_t *_limit1,
+                                    const uint8_t *_thresh1) {
   DECLARE_ALIGNED_ARRAY(16, unsigned char, flat_op2, 16);
   DECLARE_ALIGNED_ARRAY(16, unsigned char, flat_op1, 16);
   DECLARE_ALIGNED_ARRAY(16, unsigned char, flat_op0, 16);
@@ -1330,14 +1326,13 @@
   }
 }
 
-void vp9_loop_filter_horizontal_edge_16_sse2(unsigned char *s,
-                                            int p,
-                                            const unsigned char *_blimit0,
-                                            const unsigned char *_limit0,
-                                            const unsigned char *_thresh0,
-                                            const unsigned char *_blimit1,
-                                            const unsigned char *_limit1,
-                                            const unsigned char *_thresh1) {
+void vp9_lpf_horizontal_4_dual_sse2(unsigned char *s, int p,
+                                    const unsigned char *_blimit0,
+                                    const unsigned char *_limit0,
+                                    const unsigned char *_thresh0,
+                                    const unsigned char *_blimit1,
+                                    const unsigned char *_limit1,
+                                    const unsigned char *_thresh1) {
   const __m128i blimit =
       _mm_unpacklo_epi64(_mm_load_si128((const __m128i *)_blimit0),
                          _mm_load_si128((const __m128i *)_blimit1));
@@ -1598,13 +1593,12 @@
   } while (++idx8x8 < num_8x8_to_transpose);
 }
 
-void vp9_loop_filter_vertical_edge_16_sse2(uint8_t *s, int p,
-                                           const uint8_t *blimit0,
-                                           const uint8_t *limit0,
-                                           const uint8_t *thresh0,
-                                           const uint8_t *blimit1,
-                                           const uint8_t *limit1,
-                                           const uint8_t *thresh1) {
+void vp9_lpf_vertical_4_dual_sse2(uint8_t *s, int p, const uint8_t *blimit0,
+                                  const uint8_t *limit0,
+                                  const uint8_t *thresh0,
+                                  const uint8_t *blimit1,
+                                  const uint8_t *limit1,
+                                  const uint8_t *thresh1) {
   DECLARE_ALIGNED_ARRAY(16, unsigned char, t_dst, 16 * 8);
   unsigned char *src[2];
   unsigned char *dst[2];
@@ -1613,8 +1607,8 @@
   transpose8x16(s - 4, s - 4 + p * 8, p, t_dst, 16);
 
   // Loop filtering
-  vp9_loop_filter_horizontal_edge_16_sse2(t_dst + 4 * 16, 16, blimit0, limit0,
-                                          thresh0, blimit1, limit1, thresh1);
+  vp9_lpf_horizontal_4_dual_sse2(t_dst + 4 * 16, 16, blimit0, limit0, thresh0,
+                                 blimit1, limit1, thresh1);
   src[0] = t_dst;
   src[1] = t_dst + 8;
   dst[0] = s - 4;
@@ -1624,11 +1618,10 @@
   transpose(src, 16, dst, p, 2);
 }
 
-void vp9_mbloop_filter_vertical_edge_sse2(unsigned char *s, int p,
-                                          const unsigned char *blimit,
-                                          const unsigned char *limit,
-                                          const unsigned char *thresh,
-                                          int count) {
+void vp9_lpf_vertical_8_sse2(unsigned char *s, int p,
+                             const unsigned char *blimit,
+                             const unsigned char *limit,
+                             const unsigned char *thresh, int count) {
   DECLARE_ALIGNED_ARRAY(8, unsigned char, t_dst, 8 * 8);
   unsigned char *src[1];
   unsigned char *dst[1];
@@ -1641,8 +1634,7 @@
   transpose(src, p, dst, 8, 1);
 
   // Loop filtering
-  vp9_mbloop_filter_horizontal_edge_sse2(t_dst + 4 * 8, 8, blimit, limit,
-                                         thresh, 1);
+  vp9_lpf_horizontal_8_sse2(t_dst + 4 * 8, 8, blimit, limit, thresh, 1);
 
   src[0] = t_dst;
   dst[0] = s - 4;
@@ -1651,13 +1643,12 @@
   transpose(src, 8, dst, p, 1);
 }
 
-void vp9_mbloop_filter_vertical_edge_16_sse2(uint8_t *s, int p,
-                                             const uint8_t *blimit0,
-                                             const uint8_t *limit0,
-                                             const uint8_t *thresh0,
-                                             const uint8_t *blimit1,
-                                             const uint8_t *limit1,
-                                             const uint8_t *thresh1) {
+void vp9_lpf_vertical_8_dual_sse2(uint8_t *s, int p, const uint8_t *blimit0,
+                                  const uint8_t *limit0,
+                                  const uint8_t *thresh0,
+                                  const uint8_t *blimit1,
+                                  const uint8_t *limit1,
+                                  const uint8_t *thresh1) {
   DECLARE_ALIGNED_ARRAY(16, unsigned char, t_dst, 16 * 8);
   unsigned char *src[2];
   unsigned char *dst[2];
@@ -1666,8 +1657,8 @@
   transpose8x16(s - 4, s - 4 + p * 8, p, t_dst, 16);
 
   // Loop filtering
-  vp9_mbloop_filter_horizontal_edge_16_sse2(t_dst + 4 * 16, 16, blimit0, limit0,
-                                            thresh0, blimit1, limit1, thresh1);
+  vp9_lpf_horizontal_8_dual_sse2(t_dst + 4 * 16, 16, blimit0, limit0, thresh0,
+                                 blimit1, limit1, thresh1);
   src[0] = t_dst;
   src[1] = t_dst + 8;
 
@@ -1678,10 +1669,10 @@
   transpose(src, 16, dst, p, 2);
 }
 
-void vp9_mb_lpf_vertical_edge_w_sse2(unsigned char *s, int p,
-                                     const unsigned char *blimit,
-                                     const unsigned char *limit,
-                                     const unsigned char *thresh) {
+void vp9_lpf_vertical_16_sse2(unsigned char *s, int p,
+                              const unsigned char *blimit,
+                              const unsigned char *limit,
+                              const unsigned char *thresh) {
   DECLARE_ALIGNED_ARRAY(8, unsigned char, t_dst, 8 * 16);
   unsigned char *src[2];
   unsigned char *dst[2];
@@ -1706,10 +1697,9 @@
   transpose(src, 8, dst, p, 2);
 }
 
-void vp9_mb_lpf_vertical_edge_w_16_sse2(unsigned char *s, int p,
-                                        const uint8_t *blimit,
-                                        const uint8_t *limit,
-                                        const uint8_t *thresh) {
+void vp9_lpf_vertical_16_dual_sse2(unsigned char *s, int p,
+                                   const uint8_t *blimit, const uint8_t *limit,
+                                   const uint8_t *thresh) {
   DECLARE_ALIGNED_ARRAY(16, unsigned char, t_dst, 256);
 
   // Transpose 16x16
diff --git a/vp9/common/x86/vp9_loopfilter_mmx.asm b/vp9/common/x86/vp9_loopfilter_mmx.asm
index 4ebb51b..a7f6930 100644
--- a/vp9/common/x86/vp9_loopfilter_mmx.asm
+++ b/vp9/common/x86/vp9_loopfilter_mmx.asm
@@ -12,7 +12,7 @@
 %include "vpx_ports/x86_abi_support.asm"
 
 
-;void vp9_loop_filter_horizontal_edge_mmx
+;void vp9_lpf_horizontal_4_mmx
 ;(
 ;    unsigned char *src_ptr,
 ;    int src_pixel_step,
@@ -21,8 +21,8 @@
 ;    const char *thresh,
 ;    int  count
 ;)
-global sym(vp9_loop_filter_horizontal_edge_mmx) PRIVATE
-sym(vp9_loop_filter_horizontal_edge_mmx):
+global sym(vp9_lpf_horizontal_4_mmx) PRIVATE
+sym(vp9_lpf_horizontal_4_mmx):
     push        rbp
     mov         rbp, rsp
     SHADOW_ARGS_TO_STACK 6
@@ -224,7 +224,7 @@
     ret
 
 
-;void vp9_loop_filter_vertical_edge_mmx
+;void vp9_lpf_vertical_4_mmx
 ;(
 ;    unsigned char *src_ptr,
 ;    int  src_pixel_step,
@@ -233,8 +233,8 @@
 ;    const char *thresh,
 ;    int count
 ;)
-global sym(vp9_loop_filter_vertical_edge_mmx) PRIVATE
-sym(vp9_loop_filter_vertical_edge_mmx):
+global sym(vp9_lpf_vertical_4_mmx) PRIVATE
+sym(vp9_lpf_vertical_4_mmx):
     push        rbp
     mov         rbp, rsp
     SHADOW_ARGS_TO_STACK 6
diff --git a/vp9/decoder/vp9_decodeframe.c b/vp9/decoder/vp9_decodeframe.c
index 56b05ce..de6dbdc 100644
--- a/vp9/decoder/vp9_decodeframe.c
+++ b/vp9/decoder/vp9_decodeframe.c
@@ -29,13 +29,13 @@
 #include "vp9/common/vp9_seg_common.h"
 #include "vp9/common/vp9_tile_common.h"
 
-#include "vp9/decoder/vp9_dboolhuff.h"
 #include "vp9/decoder/vp9_decodeframe.h"
 #include "vp9/decoder/vp9_detokenize.h"
 #include "vp9/decoder/vp9_decodemv.h"
 #include "vp9/decoder/vp9_dsubexp.h"
 #include "vp9/decoder/vp9_onyxd_int.h"
 #include "vp9/decoder/vp9_read_bit_buffer.h"
+#include "vp9/decoder/vp9_reader.h"
 #include "vp9/decoder/vp9_thread.h"
 
 typedef struct TileWorkerData {
@@ -76,9 +76,8 @@
   }
 }
 
-// len == 0 is not allowed
 static int read_is_valid(const uint8_t *start, size_t len, const uint8_t *end) {
-  return start + len > start && start + len <= end;
+  return len != 0 && len <= (size_t)(end - start);
 }
 
 static int decode_unsigned_max(struct vp9_read_bit_buffer *rb, int max) {
@@ -266,7 +265,7 @@
         vp9_idct32x32_add(dqcoeff, dst, stride, eob);
         break;
       default:
-        assert(!"Invalid transform size");
+        assert(0 && "Invalid transform size");
     }
 
     if (eob == 1) {
@@ -305,12 +304,10 @@
   txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &x, &y);
   dst = &pd->dst.buf[4 * y * pd->dst.stride + 4 * x];
 
-  if (xd->mb_to_right_edge < 0 || xd->mb_to_bottom_edge < 0)
-    extend_for_intra(xd, plane_bsize, plane, x, y);
-
   vp9_predict_intra_block(xd, block >> (tx_size << 1),
                           b_width_log2(plane_bsize), tx_size, mode,
-                          dst, pd->dst.stride, dst, pd->dst.stride);
+                          dst, pd->dst.stride, dst, pd->dst.stride,
+                          x, y, plane);
 
   if (!mi->mbmi.skip_coeff) {
     const int eob = vp9_decode_block_tokens(cm, xd, plane, block,
@@ -348,23 +345,27 @@
 static void set_offsets(VP9_COMMON *const cm, MACROBLOCKD *const xd,
                         const TileInfo *const tile,
                         BLOCK_SIZE bsize, int mi_row, int mi_col) {
-  const int bh = num_8x8_blocks_high_lookup[bsize];
   const int bw = num_8x8_blocks_wide_lookup[bsize];
+  const int bh = num_8x8_blocks_high_lookup[bsize];
+  const int x_mis = MIN(bw, cm->mi_cols - mi_col);
+  const int y_mis = MIN(bh, cm->mi_rows - mi_row);
   const int offset = mi_row * cm->mode_info_stride + mi_col;
   const int tile_offset = tile->mi_row_start * cm->mode_info_stride +
                           tile->mi_col_start;
+  int x, y;
 
   xd->mi_8x8 = cm->mi_grid_visible + offset;
   xd->prev_mi_8x8 = cm->prev_mi_grid_visible + offset;
-
-  // we are using the mode info context stream here
-  xd->mi_8x8[0] = xd->mi_stream + offset - tile_offset;
-  xd->mi_8x8[0]->mbmi.sb_type = bsize;
-
   // Special case: if prev_mi is NULL, the previous mode info context
   // cannot be used.
   xd->last_mi = cm->prev_mi ? xd->prev_mi_8x8[0] : NULL;
 
+  xd->mi_8x8[0] = xd->mi_stream + offset - tile_offset;
+  xd->mi_8x8[0]->mbmi.sb_type = bsize;
+  for (y = 0; y < y_mis; ++y)
+    for (x = !y; x < x_mis; ++x)
+      xd->mi_8x8[y * cm->mode_info_stride + x] = xd->mi_8x8[0];
+
   set_skip_context(xd, xd->above_context, xd->left_context, mi_row, mi_col);
 
   // Distance of Mb to the various image edges. These are specified to 8th pel
@@ -379,15 +380,15 @@
   MB_MODE_INFO *const mbmi = &xd->mi_8x8[0]->mbmi;
   const int ref = mbmi->ref_frame[idx] - LAST_FRAME;
   const YV12_BUFFER_CONFIG *cfg = get_frame_ref_buffer(cm, ref);
-  const struct scale_factors_common *sfc = &cm->active_ref_scale_comm[ref];
+  const struct scale_factors *sf = &cm->active_ref_scale[ref];
 
   xd->ref_buf[idx] = cfg;
-  if (!vp9_is_valid_scale(sfc))
+  if (!vp9_is_valid_scale(sf))
     vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
                        "Invalid scale factors");
 
-  xd->scale_factor[idx].sfc = sfc;
-  setup_pre_planes(xd, idx, cfg, mi_row, mi_col, &xd->scale_factor[idx]);
+  xd->scale_factors[idx] = sf;
+  setup_pre_planes(xd, idx, cfg, mi_row, mi_col, xd->scale_factors[idx]);
   xd->corrupted |= cfg->corrupted;
 }
 
@@ -507,7 +508,7 @@
         decode_modes_sb(cm, xd, tile, mi_row + hbs, mi_col + hbs, r, subsize);
         break;
       default:
-        assert(!"Invalid partition type");
+        assert(0 && "Invalid partition type");
     }
   }
 
@@ -703,9 +704,21 @@
     vp9_update_frame_size(cm);
   }
 
-  vp9_realloc_frame_buffer(get_frame_new_buffer(cm), cm->width, cm->height,
-                           cm->subsampling_x, cm->subsampling_y,
-                           VP9BORDERINPIXELS);
+  if (cm->fb_list != NULL) {
+    vpx_codec_frame_buffer_t *const ext_fb = &cm->fb_list[cm->new_fb_idx];
+    if (vp9_realloc_frame_buffer(get_frame_new_buffer(cm),
+                                 cm->width, cm->height,
+                                 cm->subsampling_x, cm->subsampling_y,
+                                 VP9BORDERINPIXELS, ext_fb,
+                                 cm->realloc_fb_cb, cm->user_priv)) {
+      vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
+                         "Failed to allocate external frame buffer");
+    }
+  } else {
+    vp9_realloc_frame_buffer(get_frame_new_buffer(cm), cm->width, cm->height,
+                             cm->subsampling_x, cm->subsampling_y,
+                             VP9BORDERINPIXELS, NULL, NULL, NULL);
+  }
 }
 
 static void setup_frame_size(VP9D_COMP *pbi,
@@ -841,10 +854,14 @@
   if (!is_last) {
     if (!read_is_valid(*data, 4, data_end))
       vpx_internal_error(error_info, VPX_CODEC_CORRUPT_FRAME,
-          "Truncated packet or corrupt tile length");
+                         "Truncated packet or corrupt tile length");
 
     size = read_be32(*data);
     *data += 4;
+
+    if (size > (size_t)(data_end - *data))
+      vpx_internal_error(error_info, VPX_CODEC_CORRUPT_FRAME,
+                         "Truncated packet or corrupt tile size");
   } else {
     size = data_end - *data;
   }
@@ -1115,7 +1132,8 @@
   cm->version = vp9_rb_read_bit(rb);
   RESERVED;
 
-  if (vp9_rb_read_bit(rb)) {
+  cm->show_existing_frame = vp9_rb_read_bit(rb);
+  if (cm->show_existing_frame) {
     // show an existing frame directly
     int frame_to_show = cm->ref_frame_map[vp9_rb_read_literal(rb, 3)];
     ref_cnt_fb(cm->fb_idx_ref_cnt, &cm->new_fb_idx, frame_to_show);
@@ -1184,7 +1202,7 @@
 
       for (i = 0; i < REFS_PER_FRAME; ++i) {
         vp9_setup_scale_factors(cm, i);
-        if (vp9_is_scaled(&cm->active_ref_scale_comm[i]))
+        if (vp9_is_scaled(&cm->active_ref_scale[i]))
           vp9_extend_frame_borders(&cm->yv12_fb[cm->active_ref_idx[i]],
                                    cm->subsampling_x, cm->subsampling_y);
       }
@@ -1333,6 +1351,7 @@
   const int tile_rows = 1 << cm->log2_tile_rows;
   const int tile_cols = 1 << cm->log2_tile_cols;
   YV12_BUFFER_CONFIG *const new_fb = get_frame_new_buffer(cm);
+  xd->cur_buf = new_fb;
 
   if (!first_partition_size) {
       // showing a frame directly
diff --git a/vp9/decoder/vp9_decodemv.c b/vp9/decoder/vp9_decodemv.c
index 164576d..c813781 100644
--- a/vp9/decoder/vp9_decodemv.c
+++ b/vp9/decoder/vp9_decodemv.c
@@ -14,16 +14,15 @@
 #include "vp9/common/vp9_entropy.h"
 #include "vp9/common/vp9_entropymode.h"
 #include "vp9/common/vp9_entropymv.h"
-#include "vp9/common/vp9_findnearmv.h"
 #include "vp9/common/vp9_mvref_common.h"
 #include "vp9/common/vp9_pred_common.h"
 #include "vp9/common/vp9_reconinter.h"
 #include "vp9/common/vp9_seg_common.h"
 
-#include "vp9/decoder/vp9_dboolhuff.h"
 #include "vp9/decoder/vp9_decodemv.h"
 #include "vp9/decoder/vp9_decodeframe.h"
 #include "vp9/decoder/vp9_onyxd_int.h"
+#include "vp9/decoder/vp9_reader.h"
 
 static MB_PREDICTION_MODE read_intra_mode(vp9_reader *r, const vp9_prob *p) {
   return (MB_PREDICTION_MODE)vp9_read_tree(r, vp9_intra_mode_tree, p);
@@ -162,12 +161,12 @@
 
 static void read_intra_frame_mode_info(VP9_COMMON *const cm,
                                        MACROBLOCKD *const xd,
-                                       MODE_INFO *const m,
                                        int mi_row, int mi_col, vp9_reader *r) {
-  MB_MODE_INFO *const mbmi = &m->mbmi;
-  const BLOCK_SIZE bsize = mbmi->sb_type;
+  MODE_INFO *const mi = xd->mi_8x8[0];
+  MB_MODE_INFO *const mbmi = &mi->mbmi;
   const MODE_INFO *above_mi = xd->mi_8x8[-cm->mode_info_stride];
   const MODE_INFO *left_mi  = xd->left_available ? xd->mi_8x8[-1] : NULL;
+  const BLOCK_SIZE bsize = mbmi->sb_type;
 
   mbmi->segment_id = read_intra_segment_id(cm, xd, mi_row, mi_col, r);
   mbmi->skip_coeff = read_skip_coeff(cm, xd, mbmi->segment_id, r);
@@ -176,8 +175,8 @@
   mbmi->ref_frame[1] = NONE;
 
   if (bsize >= BLOCK_8X8) {
-    const MB_PREDICTION_MODE A = above_block_mode(m, above_mi, 0);
-    const MB_PREDICTION_MODE L = left_block_mode(m, left_mi, 0);
+    const MB_PREDICTION_MODE A = above_block_mode(mi, above_mi, 0);
+    const MB_PREDICTION_MODE L = left_block_mode(mi, left_mi, 0);
     mbmi->mode = read_intra_mode(r, vp9_kf_y_mode_prob[A][L]);
   } else {
     // Only 4x4, 4x8, 8x4 blocks
@@ -188,19 +187,19 @@
     for (idy = 0; idy < 2; idy += num_4x4_h) {
       for (idx = 0; idx < 2; idx += num_4x4_w) {
         const int ib = idy * 2 + idx;
-        const MB_PREDICTION_MODE A = above_block_mode(m, above_mi, ib);
-        const MB_PREDICTION_MODE L = left_block_mode(m, left_mi, ib);
+        const MB_PREDICTION_MODE A = above_block_mode(mi, above_mi, ib);
+        const MB_PREDICTION_MODE L = left_block_mode(mi, left_mi, ib);
         const MB_PREDICTION_MODE b_mode = read_intra_mode(r,
                                               vp9_kf_y_mode_prob[A][L]);
-        m->bmi[ib].as_mode = b_mode;
+        mi->bmi[ib].as_mode = b_mode;
         if (num_4x4_h == 2)
-          m->bmi[ib + 2].as_mode = b_mode;
+          mi->bmi[ib + 2].as_mode = b_mode;
         if (num_4x4_w == 2)
-          m->bmi[ib + 1].as_mode = b_mode;
+          mi->bmi[ib + 1].as_mode = b_mode;
       }
     }
 
-    mbmi->mode = m->bmi[3].as_mode;
+    mbmi->mode = mi->bmi[3].as_mode;
   }
 
   mbmi->uv_mode = read_intra_mode(r, vp9_kf_uv_mode_prob[mbmi->mode]);
@@ -308,7 +307,7 @@
 
       ref_frame[1] = NONE;
     } else {
-      assert(!"Invalid prediction mode.");
+      assert(0 && "Invalid prediction mode.");
     }
   }
 }
@@ -475,8 +474,8 @@
 
         if (b_mode == NEARESTMV || b_mode == NEARMV)
           for (ref = 0; ref < 1 + is_compound; ++ref)
-            vp9_append_sub8x8_mvs_for_idx(cm, xd, tile, &nearest[ref],
-                                          &nearmv[ref], j, ref, mi_row, mi_col);
+            vp9_append_sub8x8_mvs_for_idx(cm, xd, tile, j, ref, mi_row, mi_col,
+                                          &nearest[ref], &nearmv[ref]);
 
         if (!assign_mv(cm, b_mode, block, best, nearest, nearmv,
                        is_compound, allow_hp, r)) {
@@ -509,8 +508,8 @@
 static void read_inter_frame_mode_info(VP9_COMMON *const cm,
                                        MACROBLOCKD *const xd,
                                        const TileInfo *const tile,
-                                       MODE_INFO *const mi,
                                        int mi_row, int mi_col, vp9_reader *r) {
+  MODE_INFO *const mi = xd->mi_8x8[0];
   MB_MODE_INFO *const mbmi = &mi->mbmi;
   int inter_block;
 
@@ -531,22 +530,8 @@
 void vp9_read_mode_info(VP9_COMMON *cm, MACROBLOCKD *xd,
                         const TileInfo *const tile,
                         int mi_row, int mi_col, vp9_reader *r) {
-  MODE_INFO *const mi = xd->mi_8x8[0];
-  const BLOCK_SIZE bsize = mi->mbmi.sb_type;
-  const int bw = num_8x8_blocks_wide_lookup[bsize];
-  const int bh = num_8x8_blocks_high_lookup[bsize];
-  const int y_mis = MIN(bh, cm->mi_rows - mi_row);
-  const int x_mis = MIN(bw, cm->mi_cols - mi_col);
-  int x, y, z;
-
   if (frame_is_intra_only(cm))
-    read_intra_frame_mode_info(cm, xd, mi, mi_row, mi_col, r);
+    read_intra_frame_mode_info(cm, xd, mi_row, mi_col, r);
   else
-    read_inter_frame_mode_info(cm, xd, tile, mi, mi_row, mi_col, r);
-
-  for (y = 0, z = 0; y < y_mis; y++, z += cm->mode_info_stride) {
-    for (x = !y; x < x_mis; x++) {
-      xd->mi_8x8[z + x] = mi;
-    }
-  }
+    read_inter_frame_mode_info(cm, xd, tile, mi_row, mi_col, r);
 }
diff --git a/vp9/decoder/vp9_decodemv.h b/vp9/decoder/vp9_decodemv.h
index 8e9ae4a..95272bf 100644
--- a/vp9/decoder/vp9_decodemv.h
+++ b/vp9/decoder/vp9_decodemv.h
@@ -12,7 +12,7 @@
 #define VP9_DECODER_VP9_DECODEMV_H_
 
 #include "vp9/decoder/vp9_onyxd_int.h"
-#include "vp9/decoder/vp9_dboolhuff.h"
+#include "vp9/decoder/vp9_reader.h"
 
 struct TileInfo;
 
diff --git a/vp9/decoder/vp9_detokenize.h b/vp9/decoder/vp9_detokenize.h
index 2a88073..1780a0f 100644
--- a/vp9/decoder/vp9_detokenize.h
+++ b/vp9/decoder/vp9_detokenize.h
@@ -13,7 +13,7 @@
 #define VP9_DECODER_VP9_DETOKENIZE_H_
 
 #include "vp9/decoder/vp9_onyxd_int.h"
-#include "vp9/decoder/vp9_dboolhuff.h"
+#include "vp9/decoder/vp9_reader.h"
 
 int vp9_decode_block_tokens(VP9_COMMON *cm, MACROBLOCKD *xd,
                             int plane, int block, BLOCK_SIZE plane_bsize,
diff --git a/vp9/decoder/vp9_dsubexp.h b/vp9/decoder/vp9_dsubexp.h
index aeb9399..137f546 100644
--- a/vp9/decoder/vp9_dsubexp.h
+++ b/vp9/decoder/vp9_dsubexp.h
@@ -12,7 +12,7 @@
 #ifndef VP9_DECODER_VP9_DSUBEXP_H_
 #define VP9_DECODER_VP9_DSUBEXP_H_
 
-#include "vp9/decoder/vp9_dboolhuff.h"
+#include "vp9/decoder/vp9_reader.h"
 
 void vp9_diff_update_prob(vp9_reader *r, vp9_prob* p);
 
diff --git a/vp9/decoder/vp9_onyxd_if.c b/vp9/decoder/vp9_onyxd_if.c
index e24ba42..d585b91 100644
--- a/vp9/decoder/vp9_onyxd_if.c
+++ b/vp9/decoder/vp9_onyxd_if.c
@@ -389,23 +389,25 @@
 
   cm->last_show_frame = cm->show_frame;
   if (cm->show_frame) {
-    // current mip will be the prev_mip for the next frame
-    MODE_INFO *temp = cm->prev_mip;
-    MODE_INFO **temp2 = cm->prev_mi_grid_base;
-    cm->prev_mip = cm->mip;
-    cm->mip = temp;
-    cm->prev_mi_grid_base = cm->mi_grid_base;
-    cm->mi_grid_base = temp2;
+    if (!cm->show_existing_frame) {
+      // current mip will be the prev_mip for the next frame
+      MODE_INFO *temp = cm->prev_mip;
+      MODE_INFO **temp2 = cm->prev_mi_grid_base;
+      cm->prev_mip = cm->mip;
+      cm->mip = temp;
+      cm->prev_mi_grid_base = cm->mi_grid_base;
+      cm->mi_grid_base = temp2;
 
-    // update the upper left visible macroblock ptrs
-    cm->mi = cm->mip + cm->mode_info_stride + 1;
-    cm->prev_mi = cm->prev_mip + cm->mode_info_stride + 1;
-    cm->mi_grid_visible = cm->mi_grid_base + cm->mode_info_stride + 1;
-    cm->prev_mi_grid_visible = cm->prev_mi_grid_base + cm->mode_info_stride + 1;
+      // update the upper left visible macroblock ptrs
+      cm->mi = cm->mip + cm->mode_info_stride + 1;
+      cm->prev_mi = cm->prev_mip + cm->mode_info_stride + 1;
+      cm->mi_grid_visible = cm->mi_grid_base + cm->mode_info_stride + 1;
+      cm->prev_mi_grid_visible = cm->prev_mi_grid_base +
+                                 cm->mode_info_stride + 1;
 
-    pbi->mb.mi_8x8 = cm->mi_grid_visible;
-    pbi->mb.mi_8x8[0] = cm->mi;
-
+      pbi->mb.mi_8x8 = cm->mi_grid_visible;
+      pbi->mb.mi_8x8[0] = cm->mi;
+    }
     cm->current_video_frame++;
   }
 
diff --git a/vp9/decoder/vp9_dboolhuff.c b/vp9/decoder/vp9_reader.c
similarity index 98%
rename from vp9/decoder/vp9_dboolhuff.c
rename to vp9/decoder/vp9_reader.c
index 4f16e95..fb44c88 100644
--- a/vp9/decoder/vp9_dboolhuff.c
+++ b/vp9/decoder/vp9_reader.c
@@ -11,7 +11,7 @@
 #include "vpx_ports/mem.h"
 #include "vpx_mem/vpx_mem.h"
 
-#include "vp9/decoder/vp9_dboolhuff.h"
+#include "vp9/decoder/vp9_reader.h"
 
 // This is meant to be a large, positive constant that can still be efficiently
 // loaded as an immediate (on platforms like ARM, for example).
diff --git a/vp9/decoder/vp9_dboolhuff.h b/vp9/decoder/vp9_reader.h
similarity index 90%
rename from vp9/decoder/vp9_dboolhuff.h
rename to vp9/decoder/vp9_reader.h
index 8339c27..38cf0f6 100644
--- a/vp9/decoder/vp9_dboolhuff.h
+++ b/vp9/decoder/vp9_reader.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef VP9_DECODER_VP9_DBOOLHUFF_H_
-#define VP9_DECODER_VP9_DBOOLHUFF_H_
+#ifndef VP9_DECODER_VP9_READER_H_
+#define VP9_DECODER_VP9_READER_H_
 
 #include <stddef.h>
 #include <limits.h>
@@ -18,14 +18,12 @@
 #include "vpx_ports/mem.h"
 #include "vpx/vpx_integer.h"
 
-#include "vp9/common/vp9_treecoder.h"
+#include "vp9/common/vp9_prob.h"
 
 typedef size_t BD_VALUE;
 
 #define BD_VALUE_SIZE ((int)sizeof(BD_VALUE) * CHAR_BIT)
 
-DECLARE_ALIGNED(16, extern const uint8_t, vp9_norm[256]);
-
 typedef struct {
   const uint8_t *buffer_end;
   const uint8_t *buffer;
@@ -102,4 +100,4 @@
   return -i;
 }
 
-#endif  // VP9_DECODER_VP9_DBOOLHUFF_H_
+#endif  // VP9_DECODER_VP9_READER_H_
diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c
index 1bbb12c..b4d4ef5 100644
--- a/vp9/encoder/vp9_bitstream.c
+++ b/vp9/encoder/vp9_bitstream.c
@@ -17,13 +17,11 @@
 
 #include "vp9/common/vp9_entropymode.h"
 #include "vp9/common/vp9_entropymv.h"
-#include "vp9/common/vp9_findnearmv.h"
 #include "vp9/common/vp9_tile_common.h"
 #include "vp9/common/vp9_seg_common.h"
 #include "vp9/common/vp9_pred_common.h"
 #include "vp9/common/vp9_entropy.h"
 #include "vp9/common/vp9_mvref_common.h"
-#include "vp9/common/vp9_treecoder.h"
 #include "vp9/common/vp9_systemdependent.h"
 #include "vp9/common/vp9_pragmas.h"
 
@@ -63,14 +61,14 @@
 
 static void write_intra_mode(vp9_writer *w, MB_PREDICTION_MODE mode,
                              const vp9_prob *probs) {
-  write_token(w, vp9_intra_mode_tree, probs, &intra_mode_encodings[mode]);
+  vp9_write_token(w, vp9_intra_mode_tree, probs, &intra_mode_encodings[mode]);
 }
 
 static void write_inter_mode(vp9_writer *w, MB_PREDICTION_MODE mode,
                              const vp9_prob *probs) {
   assert(is_inter_mode(mode));
-  write_token(w, vp9_inter_mode_tree, probs,
-              &inter_mode_encodings[INTER_OFFSET(mode)]);
+  vp9_write_token(w, vp9_inter_mode_tree, probs,
+                  &inter_mode_encodings[INTER_OFFSET(mode)]);
 }
 
 static INLINE void write_be32(uint8_t *p, int value) {
@@ -179,12 +177,12 @@
     if (t >= TWO_TOKEN && t < EOB_TOKEN) {
       int len = UNCONSTRAINED_NODES - p->skip_eob_node;
       int bits = v >> (n - len);
-      treed_write(w, vp9_coef_tree, p->context_tree, bits, len, i);
-      treed_write(w, vp9_coef_con_tree,
-                  vp9_pareto8_full[p->context_tree[PIVOT_NODE] - 1], v, n - len,
-                  0);
+      vp9_write_tree(w, vp9_coef_tree, p->context_tree, bits, len, i);
+      vp9_write_tree(w, vp9_coef_con_tree,
+                     vp9_pareto8_full[p->context_tree[PIVOT_NODE] - 1],
+                     v, n - len, 0);
     } else {
-      treed_write(w, vp9_coef_tree, p->context_tree, v, n, i);
+      vp9_write_tree(w, vp9_coef_tree, p->context_tree, v, n, i);
     }
 
     if (b->base_val) {
@@ -214,7 +212,7 @@
 static void write_segment_id(vp9_writer *w, const struct segmentation *seg,
                              int segment_id) {
   if (seg->enabled && seg->update_map)
-    treed_write(w, vp9_segment_tree, seg->tree_probs, segment_id, 3, 0);
+    vp9_write_tree(w, vp9_segment_tree, seg->tree_probs, segment_id, 3, 0);
 }
 
 // This function encodes the reference frame
@@ -332,16 +330,15 @@
     if (!vp9_segfeature_active(seg, segment_id, SEG_LVL_SKIP)) {
       if (bsize >= BLOCK_8X8) {
         write_inter_mode(bc, mode, mv_ref_p);
-        ++cm->counts.inter_mode[mi->mode_context[rf]]
-                               [INTER_OFFSET(mode)];
+        ++cm->counts.inter_mode[mi->mode_context[rf]][INTER_OFFSET(mode)];
       }
     }
 
     if (cm->mcomp_filter_type == SWITCHABLE) {
       const int ctx = vp9_get_pred_context_switchable_interp(xd);
-      write_token(bc, vp9_switchable_interp_tree,
-                  cm->fc.switchable_interp_prob[ctx],
-                  &switchable_interp_encodings[mi->interp_filter]);
+      vp9_write_token(bc, vp9_switchable_interp_tree,
+                      cm->fc.switchable_interp_prob[ctx],
+                      &switchable_interp_encodings[mi->interp_filter]);
     } else {
       assert(mi->interp_filter == cm->mcomp_filter_type);
     }
@@ -470,7 +467,7 @@
   const int has_cols = (mi_col + hbs) < cm->mi_cols;
 
   if (has_rows && has_cols) {
-    write_token(w, vp9_partition_tree, probs, &partition_encodings[p]);
+    vp9_write_token(w, vp9_partition_tree, probs, &partition_encodings[p]);
   } else if (!has_rows && has_cols) {
     assert(p == PARTITION_SPLIT || p == PARTITION_HORZ);
     vp9_write(w, p == PARTITION_SPLIT, probs[1]);
@@ -778,38 +775,27 @@
   vp9_wb_write_bit(wb, lf->mode_ref_delta_enabled);
 
   if (lf->mode_ref_delta_enabled) {
-    // Do the deltas need to be updated
     vp9_wb_write_bit(wb, lf->mode_ref_delta_update);
     if (lf->mode_ref_delta_update) {
-      // Send update
       for (i = 0; i < MAX_REF_LF_DELTAS; i++) {
         const int delta = lf->ref_deltas[i];
-
-        // Frame level data
-        if (delta != lf->last_ref_deltas[i]) {
+        const int changed = delta != lf->last_ref_deltas[i];
+        vp9_wb_write_bit(wb, changed);
+        if (changed) {
           lf->last_ref_deltas[i] = delta;
-          vp9_wb_write_bit(wb, 1);
-
-          assert(delta != 0);
           vp9_wb_write_literal(wb, abs(delta) & 0x3F, 6);
           vp9_wb_write_bit(wb, delta < 0);
-        } else {
-          vp9_wb_write_bit(wb, 0);
         }
       }
 
-      // Send update
       for (i = 0; i < MAX_MODE_LF_DELTAS; i++) {
         const int delta = lf->mode_deltas[i];
-        if (delta != lf->last_mode_deltas[i]) {
+        const int changed = delta != lf->last_mode_deltas[i];
+        vp9_wb_write_bit(wb, changed);
+        if (changed) {
           lf->last_mode_deltas[i] = delta;
-          vp9_wb_write_bit(wb, 1);
-
-          assert(delta != 0);
           vp9_wb_write_literal(wb, abs(delta) & 0x3F, 6);
           vp9_wb_write_bit(wb, delta < 0);
-        } else {
-          vp9_wb_write_bit(wb, 0);
         }
       }
     }
@@ -1255,7 +1241,7 @@
 
     for (i = 0; i < INTRA_INTER_CONTEXTS; i++)
       vp9_cond_prob_diff_update(&header_bc, &fc->intra_inter_prob[i],
-                                cpi->intra_inter_count[i]);
+                                cm->counts.intra_inter[i]);
 
     if (cm->allow_comp_inter_inter) {
       const int reference_mode = cpi->common.reference_mode;
@@ -1268,28 +1254,27 @@
         if (use_hybrid_pred)
           for (i = 0; i < COMP_INTER_CONTEXTS; i++)
             vp9_cond_prob_diff_update(&header_bc, &fc->comp_inter_prob[i],
-                                      cpi->comp_inter_count[i]);
+                                      cm->counts.comp_inter[i]);
       }
     }
 
     if (cm->reference_mode != COMPOUND_REFERENCE) {
       for (i = 0; i < REF_CONTEXTS; i++) {
         vp9_cond_prob_diff_update(&header_bc, &fc->single_ref_prob[i][0],
-                                  cpi->single_ref_count[i][0]);
+                                  cm->counts.single_ref[i][0]);
         vp9_cond_prob_diff_update(&header_bc, &fc->single_ref_prob[i][1],
-                                  cpi->single_ref_count[i][1]);
+                                  cm->counts.single_ref[i][1]);
       }
     }
 
     if (cm->reference_mode != SINGLE_REFERENCE)
       for (i = 0; i < REF_CONTEXTS; i++)
         vp9_cond_prob_diff_update(&header_bc, &fc->comp_ref_prob[i],
-                                  cpi->comp_ref_count[i]);
+                                  cm->counts.comp_ref[i]);
 
     for (i = 0; i < BLOCK_SIZE_GROUPS; ++i)
       prob_diff_update(vp9_intra_mode_tree, cm->fc.y_mode_prob[i],
-                       (unsigned int *)cpi->y_mode_count[i], INTRA_MODES,
-                       &header_bc);
+                       cm->counts.y_mode[i], INTRA_MODES, &header_bc);
 
     for (i = 0; i < PARTITION_CONTEXTS; ++i)
       prob_diff_update(vp9_partition_tree, fc->partition_prob[i],
@@ -1304,7 +1289,7 @@
   return header_bc.pos;
 }
 
-void vp9_pack_bitstream(VP9_COMP *cpi, uint8_t *dest, unsigned long *size) {
+void vp9_pack_bitstream(VP9_COMP *cpi, uint8_t *dest, size_t *size) {
   uint8_t *data = dest;
   size_t first_part_size;
   struct vp9_write_bit_buffer wb = {data, 0};
diff --git a/vp9/encoder/vp9_block.h b/vp9/encoder/vp9_block.h
index 0088338..374f429 100644
--- a/vp9/encoder/vp9_block.h
+++ b/vp9/encoder/vp9_block.h
@@ -41,8 +41,7 @@
   int is_coded;
   int num_4x4_blk;
   int skip;
-  int_mv best_ref_mv;
-  int_mv second_best_ref_mv;
+  int_mv best_ref_mv[2];
   int_mv ref_mvs[MAX_REF_FRAMES][MAX_MV_REF_CANDIDATES];
   int rate;
   int distortion;
@@ -59,6 +58,7 @@
   // motion vector cache for adaptive motion search control in partition
   // search loop
   int_mv pred_mv[MAX_REF_FRAMES];
+  int pred_filter_type;
 
   // Bit flag for each mode whether it has high error in comparison to others.
   unsigned int modes_with_high_error;
@@ -117,6 +117,8 @@
   int mv_best_ref_index[MAX_REF_FRAMES];
   unsigned int max_mv_context[MAX_REF_FRAMES];
   unsigned int source_variance;
+  unsigned int pred_sse[MAX_REF_FRAMES];
+  int pred_mv_sad[MAX_REF_FRAMES];
 
   int nmvjointcost[MV_JOINTS];
   int nmvcosts[2][MV_VALS];
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c
index 21cace6..800dc49 100644
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -20,7 +20,6 @@
 #include "vp9/common/vp9_common.h"
 #include "vp9/common/vp9_entropy.h"
 #include "vp9/common/vp9_entropymode.h"
-#include "vp9/common/vp9_findnearmv.h"
 #include "vp9/common/vp9_idct.h"
 #include "vp9/common/vp9_mvref_common.h"
 #include "vp9/common/vp9_pred_common.h"
@@ -368,8 +367,8 @@
   int target_rate = cpi->rc.sb64_target_rate << 8;   // convert to bits << 8
 
   const int mi_offset = mi_row * cm->mi_cols + mi_col;
-  const int bw = 1 << mi_width_log2(BLOCK_64X64);
-  const int bh = 1 << mi_height_log2(BLOCK_64X64);
+  const int bw = num_8x8_blocks_wide_lookup[BLOCK_64X64];
+  const int bh = num_8x8_blocks_high_lookup[BLOCK_64X64];
   const int xmis = MIN(cm->mi_cols - mi_col, bw);
   const int ymis = MIN(cm->mi_rows - mi_row, bh);
   int complexity_metric = 64;
@@ -514,8 +513,8 @@
       int_mv best_mv[2];
       const MV_REFERENCE_FRAME rf1 = mbmi->ref_frame[0];
       const MV_REFERENCE_FRAME rf2 = mbmi->ref_frame[1];
-      best_mv[0].as_int = ctx->best_ref_mv.as_int;
-      best_mv[1].as_int = ctx->second_best_ref_mv.as_int;
+      best_mv[0].as_int = ctx->best_ref_mv[0].as_int;
+      best_mv[1].as_int = ctx->best_ref_mv[1].as_int;
       if (mbmi->mode == NEWMV) {
         best_mv[0].as_int = mbmi->ref_mvs[rf1][0].as_int;
         if (rf2 > 0)
@@ -548,6 +547,9 @@
                           src->alpha_stride};
   int i;
 
+  // Set current frame pointer.
+  x->e_mbd.cur_buf = src;
+
   for (i = 0; i < MAX_MB_PLANE; i++)
     setup_pred_plane(&x->plane[i].src, buffers[i], strides[i], mi_row, mi_col,
                      NULL, x->e_mbd.plane[i].subsampling_x,
@@ -751,7 +753,7 @@
                                                      SEG_LVL_REF_FRAME);
 
     if (!seg_ref_active)
-      cpi->intra_inter_count[vp9_get_intra_inter_context(xd)]
+      cm->counts.intra_inter[vp9_get_intra_inter_context(xd)]
                             [is_inter_block(mbmi)]++;
 
     // If the segment reference feature is enabled we have only a single
@@ -759,17 +761,17 @@
     // the reference frame counts used to work out probabilities.
     if (is_inter_block(mbmi) && !seg_ref_active) {
       if (cm->reference_mode == REFERENCE_MODE_SELECT)
-        cpi->comp_inter_count[vp9_get_reference_mode_context(cm, xd)]
+        cm->counts.comp_inter[vp9_get_reference_mode_context(cm, xd)]
                              [has_second_ref(mbmi)]++;
 
       if (has_second_ref(mbmi)) {
-        cpi->comp_ref_count[vp9_get_pred_context_comp_ref_p(cm, xd)]
+        cm->counts.comp_ref[vp9_get_pred_context_comp_ref_p(cm, xd)]
                            [mbmi->ref_frame[0] == GOLDEN_FRAME]++;
       } else {
-        cpi->single_ref_count[vp9_get_pred_context_single_ref_p1(xd)][0]
+        cm->counts.single_ref[vp9_get_pred_context_single_ref_p1(xd)][0]
                              [mbmi->ref_frame[0] != LAST_FRAME]++;
         if (mbmi->ref_frame[0] != LAST_FRAME)
-          cpi->single_ref_count[vp9_get_pred_context_single_ref_p2(xd)][1]
+          cm->counts.single_ref[vp9_get_pred_context_single_ref_p2(xd)][1]
                                [mbmi->ref_frame[0] != GOLDEN_FRAME]++;
       }
     }
@@ -857,16 +859,9 @@
 
 static void encode_b(VP9_COMP *cpi, const TileInfo *const tile,
                      TOKENEXTRA **tp, int mi_row, int mi_col,
-                     int output_enabled, BLOCK_SIZE bsize, int sub_index) {
-  VP9_COMMON *const cm = &cpi->common;
+                     int output_enabled, BLOCK_SIZE bsize) {
   MACROBLOCK *const x = &cpi->mb;
 
-  if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols)
-    return;
-
-  if (sub_index != -1)
-    *get_sb_index(x, bsize) = sub_index;
-
   if (bsize < BLOCK_8X8) {
     // When ab_index = 0 all sub-blocks are handled, so for ab_index != 0
     // there is nothing to be done.
@@ -890,64 +885,73 @@
                       int output_enabled, BLOCK_SIZE bsize) {
   VP9_COMMON *const cm = &cpi->common;
   MACROBLOCK *const x = &cpi->mb;
-  BLOCK_SIZE c1 = BLOCK_8X8;
-  const int bsl = b_width_log2(bsize), bs = (1 << bsl) / 4;
-  int pl = 0;
+  const int bsl = b_width_log2(bsize), hbs = (1 << bsl) / 4;
+  int ctx;
   PARTITION_TYPE partition;
   BLOCK_SIZE subsize;
-  int i;
 
   if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols)
     return;
 
-  c1 = BLOCK_4X4;
   if (bsize >= BLOCK_8X8) {
-    pl = partition_plane_context(cpi->above_seg_context, cpi->left_seg_context,
+    ctx = partition_plane_context(cpi->above_seg_context, cpi->left_seg_context,
                                  mi_row, mi_col, bsize);
-    c1 = *(get_sb_partitioning(x, bsize));
+    subsize = *get_sb_partitioning(x, bsize);
+  } else {
+    ctx = 0;
+    subsize = BLOCK_4X4;
   }
-  partition = partition_lookup[bsl][c1];
+
+  partition = partition_lookup[bsl][subsize];
 
   switch (partition) {
     case PARTITION_NONE:
       if (output_enabled && bsize >= BLOCK_8X8)
-        cm->counts.partition[pl][PARTITION_NONE]++;
-      encode_b(cpi, tile, tp, mi_row, mi_col, output_enabled, c1, -1);
+        cm->counts.partition[ctx][PARTITION_NONE]++;
+      encode_b(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize);
       break;
     case PARTITION_VERT:
       if (output_enabled)
-        cm->counts.partition[pl][PARTITION_VERT]++;
-      encode_b(cpi, tile, tp, mi_row, mi_col, output_enabled, c1, 0);
-      encode_b(cpi, tile, tp, mi_row, mi_col + bs, output_enabled, c1, 1);
+        cm->counts.partition[ctx][PARTITION_VERT]++;
+      *get_sb_index(x, subsize) = 0;
+      encode_b(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize);
+      if (mi_col + hbs < cm->mi_cols) {
+        *get_sb_index(x, subsize) = 1;
+        encode_b(cpi, tile, tp, mi_row, mi_col + hbs, output_enabled, subsize);
+      }
       break;
     case PARTITION_HORZ:
       if (output_enabled)
-        cm->counts.partition[pl][PARTITION_HORZ]++;
-      encode_b(cpi, tile, tp, mi_row, mi_col, output_enabled, c1, 0);
-      encode_b(cpi, tile, tp, mi_row + bs, mi_col, output_enabled, c1, 1);
+        cm->counts.partition[ctx][PARTITION_HORZ]++;
+      *get_sb_index(x, subsize) = 0;
+      encode_b(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize);
+      if (mi_row + hbs < cm->mi_rows) {
+        *get_sb_index(x, subsize) = 1;
+        encode_b(cpi, tile, tp, mi_row + hbs, mi_col, output_enabled, subsize);
+      }
       break;
     case PARTITION_SPLIT:
       subsize = get_subsize(bsize, PARTITION_SPLIT);
-
       if (output_enabled)
-        cm->counts.partition[pl][PARTITION_SPLIT]++;
+        cm->counts.partition[ctx][PARTITION_SPLIT]++;
 
-      for (i = 0; i < 4; i++) {
-        const int x_idx = i & 1, y_idx = i >> 1;
-
-        *get_sb_index(x, subsize) = i;
-        encode_sb(cpi, tile, tp, mi_row + y_idx * bs, mi_col + x_idx * bs,
-                  output_enabled, subsize);
-      }
+      *get_sb_index(x, subsize) = 0;
+      encode_sb(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize);
+      *get_sb_index(x, subsize) = 1;
+      encode_sb(cpi, tile, tp, mi_row, mi_col + hbs, output_enabled, subsize);
+      *get_sb_index(x, subsize) = 2;
+      encode_sb(cpi, tile, tp, mi_row + hbs, mi_col, output_enabled, subsize);
+      *get_sb_index(x, subsize) = 3;
+      encode_sb(cpi, tile, tp, mi_row + hbs, mi_col + hbs, output_enabled,
+                subsize);
       break;
     default:
-      assert(0);
-      break;
+      assert("Invalid partition type.");
   }
 
   if (partition != PARTITION_SPLIT || bsize == BLOCK_8X8)
     update_partition_context(cpi->above_seg_context, cpi->left_seg_context,
-                             mi_row, mi_col, c1, bsize);
+                             mi_row, mi_col, subsize, bsize);
 }
 
 // Check to see if the given partition size is allowed for a specified number
@@ -1455,7 +1459,7 @@
   // int use_8x8 = (MIN(cpi->common.width, cpi->common.height) < 720) ? 1 : 0;
   int use_8x8 = 1;
 
-  if (cm->frame_type && !cpi->is_src_frame_alt_ref &&
+  if (cm->frame_type && !cpi->rc.is_src_frame_alt_ref &&
       ((use_8x8 && bsize == BLOCK_16X16) ||
       bsize == BLOCK_32X32 || bsize == BLOCK_64X64)) {
     int ref0 = 0, ref1 = 0, ref2 = 0, ref3 = 0;
@@ -1686,6 +1690,10 @@
       *get_sb_index(x, subsize) = i;
       if (cpi->sf.adaptive_motion_search)
         load_pred_mv(x, get_block_context(x, bsize));
+      if (cpi->sf.adaptive_pred_filter_type && bsize == BLOCK_8X8 &&
+          partition_none_allowed)
+        get_block_context(x, subsize)->pred_filter_type =
+            get_block_context(x, bsize)->mic.mbmi.interp_filter;
       rd_pick_partition(cpi, tile, tp, mi_row + y_idx, mi_col + x_idx, subsize,
                         &this_rate, &this_dist, i != 3, best_rd - sum_rd);
 
@@ -1733,6 +1741,10 @@
     *get_sb_index(x, subsize) = 0;
     if (cpi->sf.adaptive_motion_search)
       load_pred_mv(x, get_block_context(x, bsize));
+    if (cpi->sf.adaptive_pred_filter_type && bsize == BLOCK_8X8 &&
+        partition_none_allowed)
+      get_block_context(x, subsize)->pred_filter_type =
+          get_block_context(x, bsize)->mic.mbmi.interp_filter;
     pick_sb_modes(cpi, tile, mi_row, mi_col, &sum_rate, &sum_dist, subsize,
                   get_block_context(x, subsize), best_rd);
     sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist);
@@ -1744,6 +1756,10 @@
       *get_sb_index(x, subsize) = 1;
       if (cpi->sf.adaptive_motion_search)
         load_pred_mv(x, get_block_context(x, bsize));
+      if (cpi->sf.adaptive_pred_filter_type && bsize == BLOCK_8X8 &&
+          partition_none_allowed)
+        get_block_context(x, subsize)->pred_filter_type =
+            get_block_context(x, bsize)->mic.mbmi.interp_filter;
       pick_sb_modes(cpi, tile, mi_row + ms, mi_col, &this_rate,
                     &this_dist, subsize, get_block_context(x, subsize),
                     best_rd - sum_rd);
@@ -1778,6 +1794,10 @@
     *get_sb_index(x, subsize) = 0;
     if (cpi->sf.adaptive_motion_search)
       load_pred_mv(x, get_block_context(x, bsize));
+    if (cpi->sf.adaptive_pred_filter_type && bsize == BLOCK_8X8 &&
+        partition_none_allowed)
+      get_block_context(x, subsize)->pred_filter_type =
+          get_block_context(x, bsize)->mic.mbmi.interp_filter;
     pick_sb_modes(cpi, tile, mi_row, mi_col, &sum_rate, &sum_dist, subsize,
                   get_block_context(x, subsize), best_rd);
     sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist);
@@ -1788,6 +1808,10 @@
       *get_sb_index(x, subsize) = 1;
       if (cpi->sf.adaptive_motion_search)
         load_pred_mv(x, get_block_context(x, bsize));
+      if (cpi->sf.adaptive_pred_filter_type && bsize == BLOCK_8X8 &&
+          partition_none_allowed)
+        get_block_context(x, subsize)->pred_filter_type =
+            get_block_context(x, bsize)->mic.mbmi.interp_filter;
       pick_sb_modes(cpi, tile, mi_row, mi_col + ms, &this_rate,
                     &this_dist, subsize, get_block_context(x, subsize),
                     best_rd - sum_rd);
@@ -1889,6 +1913,18 @@
     int dummy_rate;
     int64_t dummy_dist;
 
+    BLOCK_SIZE i;
+    MACROBLOCK *x = &cpi->mb;
+    for (i = BLOCK_4X4; i < BLOCK_8X8; ++i) {
+      const int num_4x4_w = num_4x4_blocks_wide_lookup[i];
+      const int num_4x4_h = num_4x4_blocks_high_lookup[i];
+      const int num_4x4_blk = MAX(4, num_4x4_w * num_4x4_h);
+      for (x->sb_index = 0; x->sb_index < 4; ++x->sb_index)
+        for (x->mb_index = 0; x->mb_index < 4; ++x->mb_index)
+          for (x->b_index = 0; x->b_index < 16 / num_4x4_blk; ++x->b_index)
+            get_block_context(x, i)->pred_filter_type = SWITCHABLE;
+    }
+
     vp9_zero(cpi->mb.pred_mv);
 
     if (cpi->sf.reference_masking)
@@ -1912,7 +1948,7 @@
             || cm->prev_mi == 0
             || cpi->common.show_frame == 0
             || cpi->common.frame_type == KEY_FRAME
-            || cpi->is_src_frame_alt_ref
+            || cpi->rc.is_src_frame_alt_ref
             || ((cpi->sf.use_lastframe_partitioning ==
                  LAST_FRAME_PARTITION_LOW_MOTION) &&
                  sb_has_motion(cpi, prev_mi_8x8))) {
@@ -1969,14 +2005,14 @@
   xd->mi_8x8[0]->mbmi.mode = DC_PRED;
   xd->mi_8x8[0]->mbmi.uv_mode = DC_PRED;
 
-  vp9_zero(cpi->y_mode_count);
-  vp9_zero(cpi->y_uv_mode_count);
+  vp9_zero(cm->counts.y_mode);
+  vp9_zero(cm->counts.uv_mode);
   vp9_zero(cm->counts.inter_mode);
   vp9_zero(cm->counts.partition);
-  vp9_zero(cpi->intra_inter_count);
-  vp9_zero(cpi->comp_inter_count);
-  vp9_zero(cpi->single_ref_count);
-  vp9_zero(cpi->comp_ref_count);
+  vp9_zero(cm->counts.intra_inter);
+  vp9_zero(cm->counts.comp_inter);
+  vp9_zero(cm->counts.single_ref);
+  vp9_zero(cm->counts.comp_ref);
   vp9_zero(cm->counts.tx);
   vp9_zero(cm->counts.mbskip);
 
@@ -2040,7 +2076,7 @@
 
   xd->last_mi = cm->prev_mi;
 
-  vp9_zero(cpi->NMVcount);
+  vp9_zero(cpi->common.counts.mv);
   vp9_zero(cpi->coef_counts);
   vp9_zero(cm->counts.eob_branch);
 
@@ -2108,8 +2144,8 @@
     int j;
     unsigned int intra_count = 0, inter_count = 0;
     for (j = 0; j < INTRA_INTER_CONTEXTS; ++j) {
-      intra_count += cpi->intra_inter_count[j][0];
-      inter_count += cpi->intra_inter_count[j][1];
+      intra_count += cm->counts.intra_inter[j][0];
+      inter_count += cm->counts.intra_inter[j][1];
     }
     cpi->sf.skip_encode_frame = ((intra_count << 2) < inter_count);
     cpi->sf.skip_encode_frame &= (cm->frame_type != KEY_FRAME);
@@ -2242,7 +2278,7 @@
   int frame_type;
   if (frame_is_intra_only(&cpi->common))
     frame_type = 0;
-  else if (cpi->is_src_frame_alt_ref && cpi->refresh_golden_frame)
+  else if (cpi->rc.is_src_frame_alt_ref && cpi->refresh_golden_frame)
     frame_type = 3;
   else if (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)
     frame_type = 1;
@@ -2303,7 +2339,8 @@
   }
 
   if (cpi->sf.RD) {
-    int i, pred_type;
+    int i;
+    REFERENCE_MODE reference_mode;
     INTERPOLATION_TYPE filter_type;
     /*
      * This code does a single RD pass over the whole frame assuming
@@ -2314,55 +2351,47 @@
      * that for subsequent frames.
      * It does the same analysis for transform size selection also.
      */
-    int frame_type = get_frame_type(cpi);
+    const int frame_type = get_frame_type(cpi);
+    const int64_t *mode_thresh = cpi->rd_prediction_type_threshes[frame_type];
+    const int64_t *filter_thresh = cpi->rd_filter_threshes[frame_type];
 
     /* prediction (compound, single or hybrid) mode selection */
     if (frame_type == 3 || !cm->allow_comp_inter_inter)
-      pred_type = SINGLE_REFERENCE;
-    else if (cpi->rd_prediction_type_threshes[frame_type][1]
-             > cpi->rd_prediction_type_threshes[frame_type][0]
-             && cpi->rd_prediction_type_threshes[frame_type][1]
-             > cpi->rd_prediction_type_threshes[frame_type][2]
-             && check_dual_ref_flags(cpi) && cpi->static_mb_pct == 100)
-      pred_type = COMPOUND_REFERENCE;
-    else if (cpi->rd_prediction_type_threshes[frame_type][0]
-             > cpi->rd_prediction_type_threshes[frame_type][2])
-      pred_type = SINGLE_REFERENCE;
+      reference_mode = SINGLE_REFERENCE;
+    else if (mode_thresh[COMPOUND_REFERENCE] > mode_thresh[SINGLE_REFERENCE] &&
+             mode_thresh[COMPOUND_REFERENCE] >
+                 mode_thresh[REFERENCE_MODE_SELECT] &&
+             check_dual_ref_flags(cpi) &&
+             cpi->static_mb_pct == 100)
+      reference_mode = COMPOUND_REFERENCE;
+    else if (mode_thresh[SINGLE_REFERENCE] > mode_thresh[REFERENCE_MODE_SELECT])
+      reference_mode = SINGLE_REFERENCE;
     else
-      pred_type = REFERENCE_MODE_SELECT;
+      reference_mode = REFERENCE_MODE_SELECT;
 
     /* filter type selection */
     // FIXME(rbultje) for some odd reason, we often select smooth_filter
     // as default filter for ARF overlay frames. This is a REALLY BAD
     // IDEA so we explicitly disable it here.
     if (frame_type != 3 &&
-        cpi->rd_filter_threshes[frame_type][1] >
-            cpi->rd_filter_threshes[frame_type][0] &&
-        cpi->rd_filter_threshes[frame_type][1] >
-            cpi->rd_filter_threshes[frame_type][2] &&
-        cpi->rd_filter_threshes[frame_type][1] >
-            cpi->rd_filter_threshes[frame_type][SWITCHABLE_FILTERS]) {
+        filter_thresh[EIGHTTAP_SMOOTH] > filter_thresh[EIGHTTAP] &&
+        filter_thresh[EIGHTTAP_SMOOTH] > filter_thresh[EIGHTTAP_SHARP] &&
+        filter_thresh[EIGHTTAP_SMOOTH] > filter_thresh[SWITCHABLE - 1]) {
       filter_type = EIGHTTAP_SMOOTH;
-    } else if (cpi->rd_filter_threshes[frame_type][2] >
-            cpi->rd_filter_threshes[frame_type][0] &&
-        cpi->rd_filter_threshes[frame_type][2] >
-            cpi->rd_filter_threshes[frame_type][SWITCHABLE_FILTERS]) {
+    } else if (filter_thresh[EIGHTTAP_SHARP] > filter_thresh[EIGHTTAP] &&
+               filter_thresh[EIGHTTAP_SHARP] > filter_thresh[SWITCHABLE - 1]) {
       filter_type = EIGHTTAP_SHARP;
-    } else if (cpi->rd_filter_threshes[frame_type][0] >
-                  cpi->rd_filter_threshes[frame_type][SWITCHABLE_FILTERS]) {
+    } else if (filter_thresh[EIGHTTAP] > filter_thresh[SWITCHABLE - 1]) {
       filter_type = EIGHTTAP;
     } else {
       filter_type = SWITCHABLE;
     }
 
-    cpi->mb.e_mbd.lossless = 0;
-    if (cpi->oxcf.lossless) {
-      cpi->mb.e_mbd.lossless = 1;
-    }
+    cpi->mb.e_mbd.lossless = cpi->oxcf.lossless;
 
     /* transform size selection (4x4, 8x8, 16x16 or select-per-mb) */
     select_tx_mode(cpi);
-    cpi->common.reference_mode = pred_type;
+    cpi->common.reference_mode = reference_mode;
     cpi->common.mcomp_filter_type = filter_type;
     encode_frame_internal(cpi);
 
@@ -2394,16 +2423,16 @@
       int comp_count_zero = 0;
 
       for (i = 0; i < COMP_INTER_CONTEXTS; i++) {
-        single_count_zero += cpi->comp_inter_count[i][0];
-        comp_count_zero += cpi->comp_inter_count[i][1];
+        single_count_zero += cm->counts.comp_inter[i][0];
+        comp_count_zero += cm->counts.comp_inter[i][1];
       }
 
       if (comp_count_zero == 0) {
         cpi->common.reference_mode = SINGLE_REFERENCE;
-        vp9_zero(cpi->comp_inter_count);
+        vp9_zero(cm->counts.comp_inter);
       } else if (single_count_zero == 0) {
         cpi->common.reference_mode = COMPOUND_REFERENCE;
-        vp9_zero(cpi->comp_inter_count);
+        vp9_zero(cm->counts.comp_inter);
       }
     }
 
@@ -2447,12 +2476,12 @@
   }
 }
 
-static void sum_intra_stats(VP9_COMP *cpi, const MODE_INFO *mi) {
+static void sum_intra_stats(VP9_COMMON *cm, const MODE_INFO *mi) {
   const MB_PREDICTION_MODE y_mode = mi->mbmi.mode;
   const MB_PREDICTION_MODE uv_mode = mi->mbmi.uv_mode;
   const BLOCK_SIZE bsize = mi->mbmi.sb_type;
 
-  ++cpi->y_uv_mode_count[y_mode][uv_mode];
+  ++cm->counts.uv_mode[y_mode][uv_mode];
 
   if (bsize < BLOCK_8X8) {
     int idx, idy;
@@ -2460,9 +2489,9 @@
     const int num_4x4_blocks_high = num_4x4_blocks_high_lookup[bsize];
     for (idy = 0; idy < 2; idy += num_4x4_blocks_high)
       for (idx = 0; idx < 2; idx += num_4x4_blocks_wide)
-        ++cpi->y_mode_count[0][mi->bmi[idy * 2 + idx].as_mode];
+        ++cm->counts.y_mode[0][mi->bmi[idy * 2 + idx].as_mode];
   } else {
-    ++cpi->y_mode_count[size_group_lookup[bsize]][y_mode];
+    ++cm->counts.y_mode[size_group_lookup[bsize]][y_mode];
   }
 }
 
@@ -2486,6 +2515,25 @@
     x->act_zbin_adj = 1 - (int) (((int64_t) a + (b >> 1)) / b);
 #endif
 }
+
+static int get_zbin_mode_boost(MB_MODE_INFO *mbmi, int enabled) {
+  if (enabled) {
+    if (is_inter_block(mbmi)) {
+      if (mbmi->mode == ZEROMV) {
+        return mbmi->ref_frame[0] != LAST_FRAME ? GF_ZEROMV_ZBIN_BOOST
+                                                : LF_ZEROMV_ZBIN_BOOST;
+      } else {
+        return mbmi->sb_type < BLOCK_8X8 ? SPLIT_MV_ZBIN_BOOST
+                                         : MV_ZBIN_BOOST;
+      }
+    } else {
+      return INTRA_ZBIN_BOOST;
+    }
+  } else {
+    return 0;
+  }
+}
+
 static void encode_superblock(VP9_COMP *cpi, TOKENEXTRA **t, int output_enabled,
                               int mi_row, int mi_col, BLOCK_SIZE bsize) {
   VP9_COMMON * const cm = &cpi->common;
@@ -2524,24 +2572,8 @@
 
     // Experimental code. Special case for gf and arf zeromv modes.
     // Increase zbin size to suppress noise
-    cpi->zbin_mode_boost = 0;
-    if (cpi->zbin_mode_boost_enabled) {
-      if (is_inter_block(mbmi)) {
-        if (mbmi->mode == ZEROMV) {
-          if (mbmi->ref_frame[0] != LAST_FRAME)
-            cpi->zbin_mode_boost = GF_ZEROMV_ZBIN_BOOST;
-          else
-            cpi->zbin_mode_boost = LF_ZEROMV_ZBIN_BOOST;
-        } else if (mbmi->sb_type < BLOCK_8X8) {
-          cpi->zbin_mode_boost = SPLIT_MV_ZBIN_BOOST;
-        } else {
-          cpi->zbin_mode_boost = MV_ZBIN_BOOST;
-        }
-      } else {
-        cpi->zbin_mode_boost = INTRA_ZBIN_BOOST;
-      }
-    }
-
+    cpi->zbin_mode_boost = get_zbin_mode_boost(mbmi,
+                                               cpi->zbin_mode_boost_enabled);
     vp9_update_zbin_extra(cpi, x);
   }
 
@@ -2549,23 +2581,16 @@
     vp9_encode_intra_block_y(x, MAX(bsize, BLOCK_8X8));
     vp9_encode_intra_block_uv(x, MAX(bsize, BLOCK_8X8));
     if (output_enabled)
-      sum_intra_stats(cpi, mi);
+      sum_intra_stats(cm, mi);
   } else {
-    int idx = cm->ref_frame_map[get_ref_frame_idx(cpi, mbmi->ref_frame[0])];
-    YV12_BUFFER_CONFIG *ref_fb = &cm->yv12_fb[idx];
-    YV12_BUFFER_CONFIG *second_ref_fb = NULL;
-    if (has_second_ref(mbmi)) {
-      idx = cm->ref_frame_map[get_ref_frame_idx(cpi, mbmi->ref_frame[1])];
-      second_ref_fb = &cm->yv12_fb[idx];
+    int ref;
+    const int is_compound = has_second_ref(mbmi);
+    for (ref = 0; ref < 1 + is_compound; ++ref) {
+      YV12_BUFFER_CONFIG *cfg = &cm->yv12_fb[cm->ref_frame_map[
+          get_ref_frame_idx(cpi, mbmi->ref_frame[ref])]];
+      setup_pre_planes(xd, ref, cfg, mi_row, mi_col, xd->scale_factors[ref]);
     }
 
-    assert(cm->frame_type != KEY_FRAME);
-
-    setup_pre_planes(xd, 0, ref_fb, mi_row, mi_col,
-                     &xd->scale_factor[0]);
-    setup_pre_planes(xd, 1, second_ref_fb, mi_row, mi_col,
-                     &xd->scale_factor[1]);
-
     vp9_build_inter_predictors_sb(xd, mi_row, mi_col, MAX(bsize, BLOCK_8X8));
   }
 
@@ -2575,12 +2600,9 @@
     vp9_encode_sb(x, MAX(bsize, BLOCK_8X8));
     vp9_tokenize_sb(cpi, t, !output_enabled, MAX(bsize, BLOCK_8X8));
   } else {
-    int mb_skip_context = xd->left_available ? mi_8x8[-1]->mbmi.skip_coeff : 0;
-    mb_skip_context += mi_8x8[-mis] ? mi_8x8[-mis]->mbmi.skip_coeff : 0;
-
     mbmi->skip_coeff = 1;
     if (output_enabled)
-      cm->counts.mbskip[mb_skip_context][1]++;
+      cm->counts.mbskip[vp9_get_skip_context(xd)][1]++;
     reset_skip_context(xd, MAX(bsize, BLOCK_8X8));
   }
 
diff --git a/vp9/encoder/vp9_encodemb.c b/vp9/encoder/vp9_encodemb.c
index 0821c26..21bc588 100644
--- a/vp9/encoder/vp9_encodemb.c
+++ b/vp9/encoder/vp9_encodemb.c
@@ -31,11 +31,11 @@
   if (xd->mi_8x8 && xd->mi_8x8[0]) {
     MB_MODE_INFO *const mbmi = &xd->mi_8x8[0]->mbmi;
 
-    set_scale_factors(xd, mbmi->ref_frame[0] - LAST_FRAME,
-                          mbmi->ref_frame[1] - LAST_FRAME,
-                          cm->active_ref_scale);
+    set_scale_factors(cm, xd, mbmi->ref_frame[0] - LAST_FRAME,
+                              mbmi->ref_frame[1] - LAST_FRAME);
+
   } else {
-    set_scale_factors(xd, -1, -1, cm->active_ref_scale);
+    set_scale_factors(cm, xd, -1, -1);
   }
 
   xd->subpix.filter_x = xd->subpix.filter_y =
@@ -369,7 +369,7 @@
   int16_t *coeff = BLOCK_OFFSET(p->coeff, block);
   int16_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block);
   int16_t *dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
-  const scan_order *so;
+  const scan_order *scan_order;
   uint16_t *eob = &p->eobs[block];
   const int diff_stride = 4 * num_4x4_blocks_wide_lookup[plane_bsize];
   int i, j;
@@ -379,36 +379,39 @@
 
   switch (tx_size) {
     case TX_32X32:
-      so = &vp9_default_scan_orders[TX_32X32];
+      scan_order = &vp9_default_scan_orders[TX_32X32];
       if (x->use_lp32x32fdct)
         vp9_fdct32x32_rd(src_diff, coeff, diff_stride);
       else
         vp9_fdct32x32(src_diff, coeff, diff_stride);
       vp9_quantize_b_32x32(coeff, 1024, x->skip_block, p->zbin, p->round,
                            p->quant, p->quant_shift, qcoeff, dqcoeff,
-                           pd->dequant, p->zbin_extra, eob, so->scan,
-                           so->iscan);
+                           pd->dequant, p->zbin_extra, eob, scan_order->scan,
+                           scan_order->iscan);
       break;
     case TX_16X16:
-      so = &vp9_default_scan_orders[TX_16X16];
+      scan_order = &vp9_default_scan_orders[TX_16X16];
       vp9_fdct16x16(src_diff, coeff, diff_stride);
       vp9_quantize_b(coeff, 256, x->skip_block, p->zbin, p->round,
                      p->quant, p->quant_shift, qcoeff, dqcoeff,
-                     pd->dequant, p->zbin_extra, eob, so->scan, so->iscan);
+                     pd->dequant, p->zbin_extra, eob,
+                     scan_order->scan, scan_order->iscan);
       break;
     case TX_8X8:
-      so = &vp9_default_scan_orders[TX_8X8];
+      scan_order = &vp9_default_scan_orders[TX_8X8];
       vp9_fdct8x8(src_diff, coeff, diff_stride);
       vp9_quantize_b(coeff, 64, x->skip_block, p->zbin, p->round,
                      p->quant, p->quant_shift, qcoeff, dqcoeff,
-                     pd->dequant, p->zbin_extra, eob, so->scan, so->iscan);
+                     pd->dequant, p->zbin_extra, eob,
+                     scan_order->scan, scan_order->iscan);
       break;
     case TX_4X4:
-      so = &vp9_default_scan_orders[TX_4X4];
+      scan_order = &vp9_default_scan_orders[TX_4X4];
       x->fwd_txm4x4(src_diff, coeff, diff_stride);
       vp9_quantize_b(coeff, 16, x->skip_block, p->zbin, p->round,
                      p->quant, p->quant_shift, qcoeff, dqcoeff,
-                     pd->dequant, p->zbin_extra, eob, so->scan, so->iscan);
+                     pd->dequant, p->zbin_extra, eob,
+                     scan_order->scan, scan_order->iscan);
       break;
     default:
       assert(0);
@@ -468,7 +471,7 @@
       xd->itxm_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
       break;
     default:
-      assert(!"Invalid transform size");
+      assert(0 && "Invalid transform size");
   }
 }
 
@@ -533,7 +536,7 @@
   int16_t *coeff = BLOCK_OFFSET(p->coeff, block);
   int16_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block);
   int16_t *dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
-  const scan_order *so;
+  const scan_order *scan_order;
   TX_TYPE tx_type;
   MB_PREDICTION_MODE mode;
   const int bwl = b_width_log2(plane_bsize);
@@ -547,21 +550,17 @@
   src = &p->src.buf[4 * (j * p->src.stride + i)];
   src_diff = &p->src_diff[4 * (j * diff_stride + i)];
 
-  if (xd->mb_to_right_edge < 0 || xd->mb_to_bottom_edge < 0)
-    extend_for_intra(xd, plane_bsize, plane, i, j);
-
   // if (x->optimize)
   // vp9_optimize_b(plane, block, plane_bsize, tx_size, x, args->ctx);
 
   switch (tx_size) {
     case TX_32X32:
-      so = &vp9_default_scan_orders[TX_32X32];
+      scan_order = &vp9_default_scan_orders[TX_32X32];
       mode = plane == 0 ? mbmi->mode : mbmi->uv_mode;
-      block >>= 6;
-      vp9_predict_intra_block(xd, block, bwl, TX_32X32, mode,
+      vp9_predict_intra_block(xd, block >> 6, bwl, TX_32X32, mode,
                               x->skip_encode ? src : dst,
                               x->skip_encode ? p->src.stride : pd->dst.stride,
-                              dst, pd->dst.stride);
+                              dst, pd->dst.stride, i, j, plane);
       if (!x->skip_recode) {
         vp9_subtract_block(32, 32, src_diff, diff_stride,
                            src, p->src.stride, dst, pd->dst.stride);
@@ -571,55 +570,55 @@
           vp9_fdct32x32(src_diff, coeff, diff_stride);
         vp9_quantize_b_32x32(coeff, 1024, x->skip_block, p->zbin, p->round,
                              p->quant, p->quant_shift, qcoeff, dqcoeff,
-                             pd->dequant, p->zbin_extra, eob, so->scan,
-                             so->iscan);
+                             pd->dequant, p->zbin_extra, eob, scan_order->scan,
+                             scan_order->iscan);
       }
       if (!x->skip_encode && *eob)
         vp9_idct32x32_add(dqcoeff, dst, pd->dst.stride, *eob);
       break;
     case TX_16X16:
       tx_type = get_tx_type_16x16(pd->plane_type, xd);
-      so = &vp9_scan_orders[TX_16X16][tx_type];
+      scan_order = &vp9_scan_orders[TX_16X16][tx_type];
       mode = plane == 0 ? mbmi->mode : mbmi->uv_mode;
-      block >>= 4;
-      vp9_predict_intra_block(xd, block, bwl, TX_16X16, mode,
+      vp9_predict_intra_block(xd, block >> 4, bwl, TX_16X16, mode,
                               x->skip_encode ? src : dst,
                               x->skip_encode ? p->src.stride : pd->dst.stride,
-                              dst, pd->dst.stride);
+                              dst, pd->dst.stride, i, j, plane);
       if (!x->skip_recode) {
         vp9_subtract_block(16, 16, src_diff, diff_stride,
                            src, p->src.stride, dst, pd->dst.stride);
         vp9_fht16x16(tx_type, src_diff, coeff, diff_stride);
         vp9_quantize_b(coeff, 256, x->skip_block, p->zbin, p->round,
                        p->quant, p->quant_shift, qcoeff, dqcoeff,
-                       pd->dequant, p->zbin_extra, eob, so->scan, so->iscan);
+                       pd->dequant, p->zbin_extra, eob, scan_order->scan,
+                       scan_order->iscan);
       }
       if (!x->skip_encode && *eob)
         vp9_iht16x16_add(tx_type, dqcoeff, dst, pd->dst.stride, *eob);
       break;
     case TX_8X8:
       tx_type = get_tx_type_8x8(pd->plane_type, xd);
-      so = &vp9_scan_orders[TX_8X8][tx_type];
+      scan_order = &vp9_scan_orders[TX_8X8][tx_type];
       mode = plane == 0 ? mbmi->mode : mbmi->uv_mode;
-      block >>= 2;
-      vp9_predict_intra_block(xd, block, bwl, TX_8X8, mode,
+      vp9_predict_intra_block(xd, block >> 2, bwl, TX_8X8, mode,
                               x->skip_encode ? src : dst,
                               x->skip_encode ? p->src.stride : pd->dst.stride,
-                              dst, pd->dst.stride);
+                              dst, pd->dst.stride, i, j, plane);
       if (!x->skip_recode) {
         vp9_subtract_block(8, 8, src_diff, diff_stride,
                            src, p->src.stride, dst, pd->dst.stride);
         vp9_fht8x8(tx_type, src_diff, coeff, diff_stride);
         vp9_quantize_b(coeff, 64, x->skip_block, p->zbin, p->round, p->quant,
                        p->quant_shift, qcoeff, dqcoeff,
-                       pd->dequant, p->zbin_extra, eob, so->scan, so->iscan);
+                       pd->dequant, p->zbin_extra, eob, scan_order->scan,
+                       scan_order->iscan);
       }
       if (!x->skip_encode && *eob)
         vp9_iht8x8_add(tx_type, dqcoeff, dst, pd->dst.stride, *eob);
       break;
     case TX_4X4:
       tx_type = get_tx_type_4x4(pd->plane_type, xd, block);
-      so = &vp9_scan_orders[TX_4X4][tx_type];
+      scan_order = &vp9_scan_orders[TX_4X4][tx_type];
       if (mbmi->sb_type < BLOCK_8X8 && plane == 0)
         mode = xd->mi_8x8[0]->bmi[block].as_mode;
       else
@@ -628,7 +627,7 @@
       vp9_predict_intra_block(xd, block, bwl, TX_4X4, mode,
                               x->skip_encode ? src : dst,
                               x->skip_encode ? p->src.stride : pd->dst.stride,
-                              dst, pd->dst.stride);
+                              dst, pd->dst.stride, i, j, plane);
 
       if (!x->skip_recode) {
         vp9_subtract_block(4, 4, src_diff, diff_stride,
@@ -639,7 +638,8 @@
           x->fwd_txm4x4(src_diff, coeff, diff_stride);
         vp9_quantize_b(coeff, 16, x->skip_block, p->zbin, p->round, p->quant,
                        p->quant_shift, qcoeff, dqcoeff,
-                       pd->dequant, p->zbin_extra, eob, so->scan, so->iscan);
+                       pd->dequant, p->zbin_extra, eob, scan_order->scan,
+                       scan_order->iscan);
       }
 
       if (!x->skip_encode && *eob) {
diff --git a/vp9/encoder/vp9_encodemv.c b/vp9/encoder/vp9_encodemv.c
index 3f01c77..dae89ad 100644
--- a/vp9/encoder/vp9_encodemv.c
+++ b/vp9/encoder/vp9_encodemv.c
@@ -47,13 +47,13 @@
   vp9_write(w, sign, mvcomp->sign);
 
   // Class
-  write_token(w, vp9_mv_class_tree, mvcomp->classes,
-              &mv_class_encodings[mv_class]);
+  vp9_write_token(w, vp9_mv_class_tree, mvcomp->classes,
+                  &mv_class_encodings[mv_class]);
 
   // Integer bits
   if (mv_class == MV_CLASS_0) {
-    write_token(w, vp9_mv_class0_tree, mvcomp->class0,
-                &mv_class0_encodings[d]);
+    vp9_write_token(w, vp9_mv_class0_tree, mvcomp->class0,
+                    &mv_class0_encodings[d]);
   } else {
     int i;
     const int n = mv_class + CLASS0_BITS - 1;  // number of bits
@@ -62,9 +62,9 @@
   }
 
   // Fractional bits
-  write_token(w, vp9_mv_fp_tree,
-              mv_class == MV_CLASS_0 ?  mvcomp->class0_fp[d] : mvcomp->fp,
-              &mv_fp_encodings[fr]);
+  vp9_write_token(w, vp9_mv_fp_tree,
+                  mv_class == MV_CLASS_0 ?  mvcomp->class0_fp[d] : mvcomp->fp,
+                  &mv_fp_encodings[fr]);
 
   // High precision bit
   if (usehp)
@@ -166,7 +166,7 @@
 void vp9_write_nmv_probs(VP9_COMP* const cpi, int usehp, vp9_writer *w) {
   int i, j;
   nmv_context *mvc = &cpi->common.fc.nmvc;
-  nmv_context_counts *counts = &cpi->NMVcount;
+  nmv_context_counts *counts = &cpi->common.counts.mv;
 
   write_mv_update(vp9_mv_joint_tree, mvc->joints, counts->joints, MV_JOINTS, w);
 
@@ -209,7 +209,7 @@
   const MV_JOINT_TYPE j = vp9_get_mv_joint(&diff);
   usehp = usehp && vp9_use_mv_hp(ref);
 
-  write_token(w, vp9_mv_joint_tree, mvctx->joints, &mv_joint_encodings[j]);
+  vp9_write_token(w, vp9_mv_joint_tree, mvctx->joints, &mv_joint_encodings[j]);
   if (mv_joint_vertical(j))
     encode_mv_component(w, diff.row, &mvctx->comps[0], usehp);
 
@@ -252,6 +252,7 @@
   MODE_INFO *mi = x->e_mbd.mi_8x8[0];
   MB_MODE_INFO *const mbmi = &mi->mbmi;
   const int is_compound = has_second_ref(mbmi);
+  nmv_context_counts *counts = &cpi->common.counts.mv;
 
   if (mbmi->sb_type < BLOCK_8X8) {
     const int num_4x4_w = num_4x4_blocks_wide_lookup[mbmi->sb_type];
@@ -262,11 +263,11 @@
       for (idx = 0; idx < 2; idx += num_4x4_w) {
         const int i = idy * 2 + idx;
         if (mi->bmi[i].as_mode == NEWMV)
-          inc_mvs(mi->bmi[i].as_mv, best_ref_mv, is_compound, &cpi->NMVcount);
+          inc_mvs(mi->bmi[i].as_mv, best_ref_mv, is_compound, counts);
       }
     }
   } else if (mbmi->mode == NEWMV) {
-    inc_mvs(mbmi->mv, best_ref_mv, is_compound, &cpi->NMVcount);
+    inc_mvs(mbmi->mv, best_ref_mv, is_compound, counts);
   }
 }
 
diff --git a/vp9/encoder/vp9_extend.h b/vp9/encoder/vp9_extend.h
index 7ff79b7..9b95ee4 100644
--- a/vp9/encoder/vp9_extend.h
+++ b/vp9/encoder/vp9_extend.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef VP9_COMMON_VP9_EXTEND_H_
-#define VP9_COMMON_VP9_EXTEND_H_
+#ifndef VP9_ENCODER_VP9_EXTEND_H_
+#define VP9_ENCODER_VP9_EXTEND_H_
 
 #include "vpx_scale/yv12config.h"
 #include "vpx/vpx_integer.h"
@@ -22,4 +22,4 @@
                                          YV12_BUFFER_CONFIG *dst,
                                          int srcy, int srcx,
                                          int srch, int srcw);
-#endif  // VP9_COMMON_VP9_EXTEND_H_
+#endif  // VP9_ENCODER_VP9_EXTEND_H_
diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c
index 5f42d0e..3df9a1f 100644
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -364,54 +364,50 @@
   output_stats(cpi, cpi->output_pkt_list, &cpi->twopass.total_stats);
 }
 
-static void zz_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
-                             YV12_BUFFER_CONFIG *recon_buffer,
-                             int *best_motion_err, int recon_yoffset) {
-  MACROBLOCKD *const xd = &x->e_mbd;
-
-  // Set up pointers for this macro block recon buffer
-  xd->plane[0].pre[0].buf = recon_buffer->y_buffer + recon_yoffset;
-
-  switch (xd->mi_8x8[0]->mbmi.sb_type) {
+static vp9_variance_fn_t get_block_variance_fn(BLOCK_SIZE bsize) {
+  switch (bsize) {
     case BLOCK_8X8:
-      vp9_mse8x8(x->plane[0].src.buf, x->plane[0].src.stride,
-                 xd->plane[0].pre[0].buf, xd->plane[0].pre[0].stride,
-                 (unsigned int *)(best_motion_err));
-      break;
+      return vp9_mse8x8;
     case BLOCK_16X8:
-      vp9_mse16x8(x->plane[0].src.buf, x->plane[0].src.stride,
-                  xd->plane[0].pre[0].buf, xd->plane[0].pre[0].stride,
-                  (unsigned int *)(best_motion_err));
-      break;
+      return vp9_mse16x8;
     case BLOCK_8X16:
-      vp9_mse8x16(x->plane[0].src.buf, x->plane[0].src.stride,
-                  xd->plane[0].pre[0].buf, xd->plane[0].pre[0].stride,
-                  (unsigned int *)(best_motion_err));
-      break;
+      return vp9_mse8x16;
     default:
-      vp9_mse16x16(x->plane[0].src.buf, x->plane[0].src.stride,
-                   xd->plane[0].pre[0].buf, xd->plane[0].pre[0].stride,
-                   (unsigned int *)(best_motion_err));
-      break;
+      return vp9_mse16x16;
   }
 }
 
+static unsigned int zz_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
+                                     YV12_BUFFER_CONFIG *recon_buffer,
+                                     int recon_yoffset) {
+  MACROBLOCKD *const xd = &x->e_mbd;
+  const uint8_t *const src = x->plane[0].src.buf;
+  const int src_stride = x->plane[0].src.stride;
+  const uint8_t *const ref = xd->plane[0].pre[0].buf
+                           = recon_buffer->y_buffer + recon_yoffset;
+  const int ref_stride = xd->plane[0].pre[0].stride;
+
+  unsigned int sse;
+  vp9_variance_fn_t fn = get_block_variance_fn(xd->mi_8x8[0]->mbmi.sb_type);
+  fn(src, src_stride, ref, ref_stride, &sse);
+  return sse;
+}
+
 static void first_pass_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
-                                     int_mv *ref_mv, MV *best_mv,
+                                     MV *ref_mv, MV *best_mv,
                                      YV12_BUFFER_CONFIG *recon_buffer,
                                      int *best_motion_err, int recon_yoffset) {
   MACROBLOCKD *const xd = &x->e_mbd;
   int num00;
 
-  int_mv tmp_mv;
-  int_mv ref_mv_full;
+  MV tmp_mv = {0, 0};
+  MV ref_mv_full;
 
   int tmp_err;
   int step_param = 3;
   int further_steps = (MAX_MVSEARCH_STEPS - 1) - step_param;
   int n;
-  vp9_variance_fn_ptr_t v_fn_ptr =
-      cpi->fn_ptr[xd->mi_8x8[0]->mbmi.sb_type];
+  vp9_variance_fn_ptr_t v_fn_ptr = cpi->fn_ptr[xd->mi_8x8[0]->mbmi.sb_type];
   int new_mv_mode_penalty = 256;
 
   int sr = 0;
@@ -426,29 +422,16 @@
   further_steps -= sr;
 
   // override the default variance function to use MSE
-  switch (xd->mi_8x8[0]->mbmi.sb_type) {
-    case BLOCK_8X8:
-      v_fn_ptr.vf = vp9_mse8x8;
-      break;
-    case BLOCK_16X8:
-      v_fn_ptr.vf = vp9_mse16x8;
-      break;
-    case BLOCK_8X16:
-      v_fn_ptr.vf = vp9_mse8x16;
-      break;
-    default:
-      v_fn_ptr.vf = vp9_mse16x16;
-      break;
-  }
+  v_fn_ptr.vf = get_block_variance_fn(xd->mi_8x8[0]->mbmi.sb_type);
 
   // Set up pointers for this macro block recon buffer
   xd->plane[0].pre[0].buf = recon_buffer->y_buffer + recon_yoffset;
 
   // Initial step/diamond search centred on best mv
-  tmp_mv.as_int = 0;
-  ref_mv_full.as_mv.col = ref_mv->as_mv.col >> 3;
-  ref_mv_full.as_mv.row = ref_mv->as_mv.row >> 3;
-  tmp_err = cpi->diamond_search_sad(x, &ref_mv_full, &tmp_mv, step_param,
+  ref_mv_full.col = ref_mv->col >> 3;
+  ref_mv_full.row = ref_mv->row >> 3;
+  tmp_err = cpi->diamond_search_sad(x, &ref_mv_full, &tmp_mv,
+                                    step_param,
                                     x->sadperbit16, &num00, &v_fn_ptr,
                                     x->nmvjointcost,
                                     x->mvcost, ref_mv);
@@ -457,8 +440,8 @@
 
   if (tmp_err < *best_motion_err) {
     *best_motion_err = tmp_err;
-    best_mv->row = tmp_mv.as_mv.row;
-    best_mv->col = tmp_mv.as_mv.col;
+    best_mv->row = tmp_mv.row;
+    best_mv->col = tmp_mv.col;
   }
 
   // Further step/diamond searches as necessary
@@ -481,8 +464,8 @@
 
       if (tmp_err < *best_motion_err) {
         *best_motion_err = tmp_err;
-        best_mv->row = tmp_mv.as_mv.row;
-        best_mv->col = tmp_mv.as_mv.col;
+        best_mv->row = tmp_mv.row;
+        best_mv->col = tmp_mv.col;
       }
     }
   }
@@ -507,6 +490,7 @@
   YV12_BUFFER_CONFIG *const new_yv12 = get_frame_new_buffer(cm);
   const int recon_y_stride = lst_yv12->y_stride;
   const int recon_uv_stride = lst_yv12->uv_stride;
+  const int uv_mb_height = 16 >> (lst_yv12->y_height > lst_yv12->uv_height);
   int64_t intra_error = 0;
   int64_t coded_error = 0;
   int64_t sr_coded_error = 0;
@@ -570,7 +554,7 @@
     // reset above block coeffs
     xd->up_available = (mb_row != 0);
     recon_yoffset = (mb_row * recon_y_stride * 16);
-    recon_uvoffset = (mb_row * recon_uv_stride * 8);
+    recon_uvoffset = (mb_row * recon_uv_stride * uv_mb_height);
 
     // Set up limit values for motion vectors to prevent them extending
     // outside the UMV borders
@@ -583,10 +567,9 @@
       int this_error;
       int gf_motion_error = INT_MAX;
       int use_dc_pred = (mb_col || mb_row) && (!mb_col || !mb_row);
-      double error_weight;
+      double error_weight = 1.0;
 
       vp9_clear_system_state();  // __asm emms;
-      error_weight = 1.0;  // avoid uninitialized warnings
 
       xd->plane[0].dst.buf = new_yv12->y_buffer + recon_yoffset;
       xd->plane[1].dst.buf = new_yv12->u_buffer + recon_uvoffset;
@@ -647,18 +630,15 @@
       // Other than for the first frame do a motion search
       if (cm->current_video_frame > 0) {
         int tmp_err;
-        int motion_error = INT_MAX;
+        int motion_error = zz_motion_search(cpi, x, lst_yv12, recon_yoffset);
         int_mv mv, tmp_mv;
-
         // Simple 0,0 motion with no mv overhead
-        zz_motion_search(cpi, x, lst_yv12, &motion_error, recon_yoffset);
         mv.as_int = tmp_mv.as_int = 0;
 
         // Test last reference frame using the previous best mv as the
         // starting point (best reference) for the search
-        first_pass_motion_search(cpi, x, &best_ref_mv,
-                                 &mv.as_mv, lst_yv12,
-                                 &motion_error, recon_yoffset);
+        first_pass_motion_search(cpi, x, &best_ref_mv.as_mv, &mv.as_mv,
+                                 lst_yv12, &motion_error, recon_yoffset);
         if (cpi->oxcf.aq_mode == VARIANCE_AQ) {
           vp9_clear_system_state();  // __asm emms;
           motion_error *= error_weight;
@@ -668,7 +648,7 @@
         // based search as well.
         if (best_ref_mv.as_int) {
           tmp_err = INT_MAX;
-          first_pass_motion_search(cpi, x, &zero_ref_mv, &tmp_mv.as_mv,
+          first_pass_motion_search(cpi, x, &zero_ref_mv.as_mv, &tmp_mv.as_mv,
                                    lst_yv12, &tmp_err, recon_yoffset);
           if (cpi->oxcf.aq_mode == VARIANCE_AQ) {
             vp9_clear_system_state();  // __asm emms;
@@ -684,12 +664,10 @@
         // Experimental search in an older reference frame
         if (cm->current_video_frame > 1) {
           // Simple 0,0 motion with no mv overhead
-          zz_motion_search(cpi, x, gld_yv12,
-                           &gf_motion_error, recon_yoffset);
+          gf_motion_error = zz_motion_search(cpi, x, gld_yv12, recon_yoffset);
 
-          first_pass_motion_search(cpi, x, &zero_ref_mv,
-                                   &tmp_mv.as_mv, gld_yv12,
-                                   &gf_motion_error, recon_yoffset);
+          first_pass_motion_search(cpi, x, &zero_ref_mv.as_mv, &tmp_mv.as_mv,
+                                   gld_yv12, &gf_motion_error, recon_yoffset);
           if (cpi->oxcf.aq_mode == VARIANCE_AQ) {
             vp9_clear_system_state();  // __asm emms;
             gf_motion_error *= error_weight;
@@ -724,11 +702,9 @@
           // very close and very low. This helps with scene cut
           // detection for example in cropped clips with black bars
           // at the sides or top and bottom.
-          if ((((this_error - intrapenalty) * 9) <=
-               (motion_error * 10)) &&
-              (this_error < (2 * intrapenalty))) {
+          if (((this_error - intrapenalty) * 9 <= motion_error * 10) &&
+              this_error < 2 * intrapenalty)
             neutral_count++;
-          }
 
           mv.as_mv.row *= 8;
           mv.as_mv.col *= 8;
@@ -737,8 +713,7 @@
           xd->mi_8x8[0]->mbmi.tx_size = TX_4X4;
           xd->mi_8x8[0]->mbmi.ref_frame[0] = LAST_FRAME;
           xd->mi_8x8[0]->mbmi.ref_frame[1] = NONE;
-          vp9_build_inter_predictors_sby(xd, mb_row << 1,
-                                         mb_col << 1,
+          vp9_build_inter_predictors_sby(xd, mb_row << 1, mb_col << 1,
                                          xd->mi_8x8[0]->mbmi.sb_type);
           vp9_encode_sby(x, xd->mi_8x8[0]->mbmi.sb_type);
           sum_mvr += mv.as_mv.row;
@@ -794,17 +769,19 @@
 
       // adjust to the next column of macroblocks
       x->plane[0].src.buf += 16;
-      x->plane[1].src.buf += 8;
-      x->plane[2].src.buf += 8;
+      x->plane[1].src.buf += uv_mb_height;
+      x->plane[2].src.buf += uv_mb_height;
 
       recon_yoffset += 16;
-      recon_uvoffset += 8;
+      recon_uvoffset += uv_mb_height;
     }
 
     // adjust to the next row of mbs
     x->plane[0].src.buf += 16 * x->plane[0].src.stride - 16 * cm->mb_cols;
-    x->plane[1].src.buf += 8 * x->plane[1].src.stride - 8 * cm->mb_cols;
-    x->plane[2].src.buf += 8 * x->plane[1].src.stride - 8 * cm->mb_cols;
+    x->plane[1].src.buf += uv_mb_height * x->plane[1].src.stride -
+                           uv_mb_height * cm->mb_cols;
+    x->plane[2].src.buf += uv_mb_height * x->plane[1].src.stride -
+                           uv_mb_height * cm->mb_cols;
 
     vp9_clear_system_state();  // __asm emms;
   }
@@ -965,7 +942,7 @@
   const double error_term = err_per_mb / err_divisor;
 
   // Adjustment based on actual quantizer to power term.
-  const double power_term = MIN(vp9_convert_qindex_to_q(q) * 0.01 + pt_low,
+  const double power_term = MIN(vp9_convert_qindex_to_q(q) * 0.0125 + pt_low,
                                 pt_high);
 
   // Calculate correction factor
@@ -1025,7 +1002,7 @@
     int bits_per_mb_at_this_q;
 
     err_correction_factor = calc_correction_factor(err_per_mb,
-                                                   ERR_DIVISOR, 0.4, 0.90, q);
+                                                   ERR_DIVISOR, 0.5, 0.90, q);
 
     bits_per_mb_at_this_q = vp9_rc_bits_per_mb(INTER_FRAME, q,
                                                err_correction_factor);
@@ -1075,7 +1052,7 @@
 
     // Error per MB based correction factor
     err_correction_factor =
-      calc_correction_factor(err_per_mb, 100.0, 0.4, 0.90, q) * clip_iifactor;
+      calc_correction_factor(err_per_mb, 100.0, 0.5, 0.90, q) * clip_iifactor;
 
     bits_per_mb_at_this_q =
       vp9_rc_bits_per_mb(INTER_FRAME, q, err_correction_factor);
@@ -1168,7 +1145,6 @@
     start_pos = cpi->twopass.stats_in;  // Note starting "file" position
 
     cpi->twopass.modified_error_total = 0.0;
-    cpi->twopass.modified_error_used = 0.0;
 
     while (input_stats(cpi, &this_frame) != EOF) {
       cpi->twopass.modified_error_total +=
@@ -1187,32 +1163,15 @@
 // the prediction quality is decaying from frame to frame.
 static double get_prediction_decay_rate(VP9_COMP *cpi,
                                         FIRSTPASS_STATS *next_frame) {
-  double prediction_decay_rate;
-  double second_ref_decay;
-  double mb_sr_err_diff;
-
-  // Initial basis is the % mbs inter coded
-  prediction_decay_rate = next_frame->pcnt_inter;
-
   // Look at the observed drop in prediction quality between the last frame
   // and the GF buffer (which contains an older frame).
-  mb_sr_err_diff = (next_frame->sr_coded_error - next_frame->coded_error) /
-                   cpi->common.MBs;
-  if (mb_sr_err_diff <= 512.0) {
-    second_ref_decay = 1.0 - (mb_sr_err_diff / 512.0);
-    second_ref_decay = pow(second_ref_decay, 0.5);
-    if (second_ref_decay < 0.85)
-      second_ref_decay = 0.85;
-    else if (second_ref_decay > 1.0)
-      second_ref_decay = 1.0;
-  } else {
-    second_ref_decay = 0.85;
-  }
+  const double mb_sr_err_diff = (next_frame->sr_coded_error -
+                                     next_frame->coded_error) / cpi->common.MBs;
+  const double second_ref_decay = mb_sr_err_diff <= 512.0
+      ? fclamp(pow(1.0 - (mb_sr_err_diff / 512.0), 0.5), 0.85, 1.0)
+      : 0.85;
 
-  if (second_ref_decay < prediction_decay_rate)
-    prediction_decay_rate = second_ref_decay;
-
-  return prediction_decay_rate;
+  return MIN(second_ref_decay, next_frame->pcnt_inter);
 }
 
 // Function to test for a condition where a complex transition is followed
@@ -1528,6 +1487,8 @@
   cpi->this_frame_weight = cpi->arf_weight[cpi->sequence_number];
   assert(cpi->this_frame_weight >= 0);
 
+  cpi->twopass.gf_zeromotion_pct = 0;
+
   // Initialize frame coding order variables.
   cpi->new_frame_coding_order_period = 0;
   cpi->next_frame_in_order = 0;
@@ -1536,14 +1497,14 @@
   vp9_zero(cpi->arf_buffer_idx);
   vpx_memset(cpi->arf_weight, -1, sizeof(cpi->arf_weight));
 
-  if (cpi->twopass.frames_to_key <= (FIXED_ARF_GROUP_SIZE + 8)) {
+  if (cpi->rc.frames_to_key <= (FIXED_ARF_GROUP_SIZE + 8)) {
     // Setup a GF group close to the keyframe.
-    cpi->source_alt_ref_pending = 0;
-    cpi->rc.baseline_gf_interval = cpi->twopass.frames_to_key;
+    cpi->rc.source_alt_ref_pending = 0;
+    cpi->rc.baseline_gf_interval = cpi->rc.frames_to_key;
     schedule_frames(cpi, 0, (cpi->rc.baseline_gf_interval - 1), 2, 0, 0);
   } else {
     // Setup a fixed period ARF group.
-    cpi->source_alt_ref_pending = 1;
+    cpi->rc.source_alt_ref_pending = 1;
     cpi->rc.baseline_gf_interval = FIXED_ARF_GROUP_SIZE;
     schedule_frames(cpi, 0, -(cpi->rc.baseline_gf_interval - 1), 2, 1, 0);
   }
@@ -1641,16 +1602,16 @@
   // bits to spare and are better with a smaller interval and smaller boost.
   // At high Q when there are few bits to spare we are better with a longer
   // interval to spread the cost of the GF.
+  //
   active_max_gf_interval =
-    12 + ((int)vp9_convert_qindex_to_q(cpi->rc.active_worst_quality) >> 5);
+    11 + ((int)vp9_convert_qindex_to_q(cpi->rc.last_q[INTER_FRAME]) >> 5);
 
   if (active_max_gf_interval > cpi->rc.max_gf_interval)
     active_max_gf_interval = cpi->rc.max_gf_interval;
 
   i = 0;
-  while (((i < cpi->twopass.static_scene_max_gf_interval) ||
-          ((cpi->twopass.frames_to_key - i) < MIN_GF_INTERVAL)) &&
-         (i < cpi->twopass.frames_to_key)) {
+  while ((i < cpi->twopass.static_scene_max_gf_interval) &&
+         (i < (cpi->rc.frames_to_key - 1))) {
     i++;    // Increment the loop counter
 
     // Accumulate error score of frames in this gf group
@@ -1704,8 +1665,6 @@
       (
         // Don't break out with a very short interval
         (i > MIN_GF_INTERVAL) &&
-        // Don't break out very close to a key frame
-        ((cpi->twopass.frames_to_key - i) >= MIN_GF_INTERVAL) &&
         ((boost_score > 125.0) || (next_frame.pcnt_inter < 0.75)) &&
         (!flash_detected) &&
         ((mv_ratio_accumulator > mv_ratio_accumulator_thresh) ||
@@ -1721,17 +1680,17 @@
     old_boost_score = boost_score;
   }
 
-  cpi->gf_zeromotion_pct = (int)(zero_motion_accumulator * 1000.0);
+  cpi->twopass.gf_zeromotion_pct = (int)(zero_motion_accumulator * 1000.0);
 
   // Don't allow a gf too near the next kf
-  if ((cpi->twopass.frames_to_key - i) < MIN_GF_INTERVAL) {
-    while (i < cpi->twopass.frames_to_key) {
+  if ((cpi->rc.frames_to_key - i) < MIN_GF_INTERVAL) {
+    while (i < (cpi->rc.frames_to_key - 1)) {
       i++;
 
       if (EOF == input_stats(cpi, this_frame))
         break;
 
-      if (i < cpi->twopass.frames_to_key) {
+      if (i < cpi->rc.frames_to_key) {
         mod_frame_err = calculate_modified_err(cpi, this_frame);
         gf_group_err += mod_frame_err;
       }
@@ -1757,8 +1716,6 @@
   if (allow_alt_ref &&
       (i < cpi->oxcf.lag_in_frames) &&
       (i >= MIN_GF_INTERVAL) &&
-      // dont use ARF very near next kf
-      (i <= (cpi->twopass.frames_to_key - MIN_GF_INTERVAL)) &&
       ((next_frame.pcnt_inter > 0.75) ||
        (next_frame.pcnt_second_ref > 0.5)) &&
       ((mv_in_out_accumulator / (double)i > -0.2) ||
@@ -1767,7 +1724,7 @@
     // Alternative boost calculation for alt ref
     cpi->rc.gfu_boost = calc_arf_boost(cpi, 0, (i - 1), (i - 1), &f_boost,
                                     &b_boost);
-    cpi->source_alt_ref_pending = 1;
+    cpi->rc.source_alt_ref_pending = 1;
 
 #if CONFIG_MULTIPLE_ARF
     // Set the ARF schedule.
@@ -1777,7 +1734,7 @@
 #endif
   } else {
     cpi->rc.gfu_boost = (int)boost_score;
-    cpi->source_alt_ref_pending = 0;
+    cpi->rc.source_alt_ref_pending = 0;
 #if CONFIG_MULTIPLE_ARF
     // Set the GF schedule.
     if (cpi->multi_arf_enabled) {
@@ -1832,7 +1789,7 @@
   // where cpi->twopass.kf_group_bits is tied to cpi->twopass.bits_left.
   // This is also important for short clips where there may only be one
   // key frame.
-  if (cpi->twopass.frames_to_key >= (int)(cpi->twopass.total_stats.count -
+  if (cpi->rc.frames_to_key >= (int)(cpi->twopass.total_stats.count -
                                           cpi->common.current_video_frame)) {
     cpi->twopass.kf_group_bits =
       (cpi->twopass.bits_left > 0) ? cpi->twopass.bits_left : 0;
@@ -1863,12 +1820,10 @@
   // Reset the file position
   reset_fpf_position(cpi, start_pos);
 
-  // Update the record of error used so far (only done once per gf group)
-  cpi->twopass.modified_error_used += gf_group_err;
-
   // Assign  bits to the arf or gf.
   for (i = 0;
-      i <= (cpi->source_alt_ref_pending && cpi->common.frame_type != KEY_FRAME);
+      i <= (cpi->rc.source_alt_ref_pending &&
+            cpi->common.frame_type != KEY_FRAME);
       ++i) {
     int allocation_chunks;
     int q = cpi->rc.last_q[INTER_FRAME];
@@ -1879,7 +1834,7 @@
     // Set max and minimum boost and hence minimum allocation
     boost = clamp(boost, 125, (cpi->rc.baseline_gf_interval + 1) * 200);
 
-    if (cpi->source_alt_ref_pending && i == 0)
+    if (cpi->rc.source_alt_ref_pending && i == 0)
       allocation_chunks = ((cpi->rc.baseline_gf_interval + 1) * 100) + boost;
     else
       allocation_chunks = (cpi->rc.baseline_gf_interval * 100) + (boost - 100);
@@ -1932,7 +1887,7 @@
     if (i == 0) {
       cpi->twopass.gf_bits = gf_bits;
     }
-    if (i == 1 || (!cpi->source_alt_ref_pending
+    if (i == 1 || (!cpi->rc.source_alt_ref_pending
         && (cpi->common.frame_type != KEY_FRAME))) {
       // Per frame bit target for this frame
       cpi->rc.per_frame_bandwidth = gf_bits;
@@ -1947,15 +1902,18 @@
     if (cpi->twopass.kf_group_bits < 0)
       cpi->twopass.kf_group_bits = 0;
 
-    // Note the error score left in the remaining frames of the group.
-    // For normal GFs we want to remove the error score for the first frame
-    // of the group (except in Key frame case where this has already
-    // happened)
-    if (!cpi->source_alt_ref_pending && cpi->common.frame_type != KEY_FRAME)
+    // If this is an arf update we want to remove the score for the
+    // overlay frame at the end which will usually be very cheap to code.
+    // For normal GFs remove the score for the GF itself unless this is
+    // also a key frame in which case it has already been accounted for.
+    if (cpi->rc.source_alt_ref_pending) {
+      cpi->twopass.gf_group_error_left = (int64_t)gf_group_err - mod_frame_err;
+    } else if (cpi->common.frame_type != KEY_FRAME) {
       cpi->twopass.gf_group_error_left = (int64_t)(gf_group_err
                                                    - gf_first_frame_err);
-    else
+    } else {
       cpi->twopass.gf_group_error_left = (int64_t)gf_group_err;
+    }
 
     cpi->twopass.gf_group_bits -= cpi->twopass.gf_bits
         - cpi->rc.min_frame_bandwidth;
@@ -1967,7 +1925,7 @@
     // despite (MIN_GF_INTERVAL) and would cause a divide by 0 in the
     // calculation of alt_extra_bits.
     if (cpi->rc.baseline_gf_interval >= 3) {
-      const int boost = cpi->source_alt_ref_pending ?
+      const int boost = cpi->rc.source_alt_ref_pending ?
           b_boost : cpi->rc.gfu_boost;
 
       if (boost >= 150) {
@@ -2050,27 +2008,49 @@
   cpi->rc.per_frame_bandwidth = target_frame_size;
 }
 
-// Make a damped adjustment to the active max q.
-static int adjust_active_maxq(int old_maxqi, int new_maxqi) {
-  int i;
-  const double old_q = vp9_convert_qindex_to_q(old_maxqi);
-  const double new_q = vp9_convert_qindex_to_q(new_maxqi);
-  const double target_q = ((old_q * 7.0) + new_q) / 8.0;
-
-  if (target_q > old_q) {
-    for (i = old_maxqi; i <= new_maxqi; i++)
-      if (vp9_convert_qindex_to_q(i) >= target_q)
-        return i;
+void vp9_get_svc_params(VP9_COMP *cpi) {
+  VP9_COMMON *const cm = &cpi->common;
+  if ((cm->current_video_frame == 0) ||
+      (cm->frame_flags & FRAMEFLAGS_KEY) ||
+      (cpi->oxcf.auto_key && (cpi->rc.frames_since_key %
+                              cpi->key_frame_frequency == 0))) {
+    cm->frame_type = KEY_FRAME;
   } else {
-    for (i = old_maxqi; i >= new_maxqi; i--)
-      if (vp9_convert_qindex_to_q(i) <= target_q)
-        return i;
+    cm->frame_type = INTER_FRAME;
   }
-
-  return new_maxqi;
+  cpi->rc.frames_till_gf_update_due = INT_MAX;
+  cpi->rc.baseline_gf_interval = INT_MAX;
 }
 
-void vp9_second_pass(VP9_COMP *cpi) {
+void vp9_get_one_pass_params(VP9_COMP *cpi) {
+  VP9_COMMON *const cm = &cpi->common;
+  if (!cpi->refresh_alt_ref_frame &&
+      (cm->current_video_frame == 0 ||
+       cm->frame_flags & FRAMEFLAGS_KEY ||
+       (cpi->oxcf.auto_key && (cpi->rc.frames_since_key %
+                               cpi->key_frame_frequency == 0)))) {
+    cm->frame_type = KEY_FRAME;
+  } else {
+    cm->frame_type = INTER_FRAME;
+  }
+  if (cpi->rc.frames_till_gf_update_due == 0) {
+    cpi->rc.frames_till_gf_update_due = cpi->rc.baseline_gf_interval;
+    cpi->refresh_golden_frame = 1;
+  }
+}
+
+void vp9_get_first_pass_params(VP9_COMP *cpi) {
+  VP9_COMMON *const cm = &cpi->common;
+  if (!cpi->refresh_alt_ref_frame &&
+      (cm->current_video_frame == 0 ||
+       cm->frame_flags & FRAMEFLAGS_KEY)) {
+    cm->frame_type = KEY_FRAME;
+  } else {
+    cm->frame_type = INTER_FRAME;
+  }
+}
+
+void vp9_get_second_pass_params(VP9_COMP *cpi) {
   int tmp_q;
   int frames_left = (int)(cpi->twopass.total_stats.count -
                           cpi->common.current_video_frame);
@@ -2081,6 +2061,10 @@
   double this_frame_intra_error;
   double this_frame_coded_error;
 
+  if (cpi->refresh_alt_ref_frame) {
+    cpi->common.frame_type = INTER_FRAME;
+    return;
+  }
   if (!cpi->twopass.stats_in)
     return;
 
@@ -2109,7 +2093,7 @@
     // estimate for the clip is bad, but helps prevent excessive
     // variation in Q, especially near the end of a clip
     // where for example a small overspend may cause Q to crash
-    adjust_maxq_qrange(cpi);
+    // adjust_maxq_qrange(cpi);
   }
   vp9_zero(this_frame);
   if (EOF == input_stats(cpi, &this_frame))
@@ -2119,7 +2103,7 @@
   this_frame_coded_error = this_frame.coded_error;
 
   // keyframe and section processing !
-  if (cpi->twopass.frames_to_key == 0) {
+  if (cpi->rc.frames_to_key == 0) {
     // Define next KF group and assign bits to it
     this_frame_copy = this_frame;
     find_next_key_frame(cpi, &this_frame_copy);
@@ -2130,8 +2114,6 @@
     // Define next gf group and assign bits to it
     this_frame_copy = this_frame;
 
-    cpi->gf_zeromotion_pct = 0;
-
 #if CONFIG_MULTIPLE_ARF
     if (cpi->multi_arf_enabled) {
       define_fixed_arf_period(cpi);
@@ -2142,7 +2124,7 @@
     }
 #endif
 
-    if (cpi->gf_zeromotion_pct > 995) {
+    if (cpi->twopass.gf_zeromotion_pct > 995) {
       // As long as max_thresh for encode breakout is small enough, it is ok
       // to enable it for no-show frame, i.e. set enable_encode_breakout to 2.
       if (!cpi->common.show_frame)
@@ -2157,7 +2139,8 @@
     // from that arf boost and it should not be given extra bits
     // If the previous group was NOT coded using arf we may want to apply
     // some boost to this GF as well
-    if (cpi->source_alt_ref_pending && (cpi->common.frame_type != KEY_FRAME)) {
+    if (cpi->rc.source_alt_ref_pending &&
+        cpi->common.frame_type != KEY_FRAME) {
       // Assign a standard frames worth of bits from those allocated
       // to the GF group
       int bak = cpi->rc.per_frame_bandwidth;
@@ -2165,6 +2148,8 @@
       assign_std_frame_bits(cpi, &this_frame_copy);
       cpi->rc.per_frame_bandwidth = bak;
     }
+    cpi->rc.frames_till_gf_update_due = cpi->rc.baseline_gf_interval;
+    cpi->refresh_golden_frame = 1;
   } else {
     // Otherwise this is an ordinary frame
     // Assign bits from those allocated to the GF group
@@ -2189,7 +2174,7 @@
   if (cpi->target_bandwidth < 0)
     cpi->target_bandwidth = 0;
 
-  cpi->twopass.frames_to_key--;
+  cpi->rc.frames_to_key--;
 
   // Update the total stats remaining structure
   subtract_stats(&cpi->twopass.total_left_stats, &this_frame);
@@ -2285,6 +2270,7 @@
 
   return is_viable_kf;
 }
+
 static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
   int i, j;
   FIRSTPASS_STATS last_frame;
@@ -2311,15 +2297,15 @@
   cpi->common.frame_type = KEY_FRAME;
 
   // is this a forced key frame by interval
-  cpi->this_key_frame_forced = cpi->next_key_frame_forced;
+  cpi->rc.this_key_frame_forced = cpi->rc.next_key_frame_forced;
 
   // Clear the alt ref active flag as this can never be active on a key frame
-  cpi->source_alt_ref_active = 0;
+  cpi->rc.source_alt_ref_active = 0;
 
   // Kf is always a gf so clear frames till next gf counter
   cpi->rc.frames_till_gf_update_due = 0;
 
-  cpi->twopass.frames_to_key = 1;
+  cpi->rc.frames_to_key = 1;
 
   // Take a copy of the initial frame details
   first_frame = *this_frame;
@@ -2371,14 +2357,14 @@
         break;
 
       // Step on to the next frame
-      cpi->twopass.frames_to_key++;
+      cpi->rc.frames_to_key++;
 
       // If we don't have a real key frame within the next two
       // forcekeyframeevery intervals then break out of the loop.
-      if (cpi->twopass.frames_to_key >= 2 * (int)cpi->key_frame_frequency)
+      if (cpi->rc.frames_to_key >= 2 * (int)cpi->key_frame_frequency)
         break;
     } else {
-      cpi->twopass.frames_to_key++;
+      cpi->rc.frames_to_key++;
     }
     i++;
   }
@@ -2388,11 +2374,11 @@
   // This code centers the extra kf if the actual natural
   // interval is between 1x and 2x
   if (cpi->oxcf.auto_key
-      && cpi->twopass.frames_to_key > (int)cpi->key_frame_frequency) {
+      && cpi->rc.frames_to_key > (int)cpi->key_frame_frequency) {
     FIRSTPASS_STATS *current_pos = cpi->twopass.stats_in;
     FIRSTPASS_STATS tmp_frame;
 
-    cpi->twopass.frames_to_key /= 2;
+    cpi->rc.frames_to_key /= 2;
 
     // Copy first frame details
     tmp_frame = first_frame;
@@ -2405,7 +2391,7 @@
     kf_group_coded_err = 0;
 
     // Rescan to get the correct error data for the forced kf group
-    for (i = 0; i < cpi->twopass.frames_to_key; i++) {
+    for (i = 0; i < cpi->rc.frames_to_key; i++) {
       // Accumulate kf group errors
       kf_group_err += calculate_modified_err(cpi, &tmp_frame);
       kf_group_intra_err += tmp_frame.intra_error;
@@ -2418,9 +2404,9 @@
     // Reset to the start of the group
     reset_fpf_position(cpi, current_pos);
 
-    cpi->next_key_frame_forced = 1;
+    cpi->rc.next_key_frame_forced = 1;
   } else {
-    cpi->next_key_frame_forced = 0;
+    cpi->rc.next_key_frame_forced = 0;
   }
   // Special case for the last frame of the file
   if (cpi->twopass.stats_in >= cpi->twopass.stats_in_end) {
@@ -2450,7 +2436,7 @@
                                             cpi->twopass.modified_error_left));
 
     // Clip based on maximum per frame rate defined by the user.
-    max_grp_bits = (int64_t)max_bits * (int64_t)cpi->twopass.frames_to_key;
+    max_grp_bits = (int64_t)max_bits * (int64_t)cpi->rc.frames_to_key;
     if (cpi->twopass.kf_group_bits > max_grp_bits)
       cpi->twopass.kf_group_bits = max_grp_bits;
   } else {
@@ -2466,7 +2452,7 @@
   loop_decay_rate = 1.00;       // Starting decay rate
 
   // Scan through the kf group collating various stats.
-  for (i = 0; i < cpi->twopass.frames_to_key; i++) {
+  for (i = 0; i < cpi->rc.frames_to_key; i++) {
     double r;
 
     if (EOF == input_stats(cpi, &next_frame))
@@ -2509,7 +2495,7 @@
     zero_stats(&sectionstats);
     reset_fpf_position(cpi, start_position);
 
-    for (i = 0; i < cpi->twopass.frames_to_key; i++) {
+    for (i = 0; i < cpi->rc.frames_to_key; i++) {
       input_stats(cpi, &next_frame);
       accumulate_stats(&sectionstats, &next_frame);
     }
@@ -2530,8 +2516,8 @@
     int allocation_chunks;
     int alt_kf_bits;
 
-    if (kf_boost < (cpi->twopass.frames_to_key * 3))
-      kf_boost = (cpi->twopass.frames_to_key * 3);
+    if (kf_boost < (cpi->rc.frames_to_key * 3))
+      kf_boost = (cpi->rc.frames_to_key * 3);
 
     if (kf_boost < 300)  // Min KF boost
       kf_boost = 300;
@@ -2539,7 +2525,7 @@
     // Make a note of baseline boost and the zero motion
     // accumulator value for use elsewhere.
     cpi->rc.kf_boost = kf_boost;
-    cpi->kf_zeromotion_pct = (int)(zero_motion_accumulator * 100.0);
+    cpi->twopass.kf_zeromotion_pct = (int)(zero_motion_accumulator * 100.0);
 
     // We do three calculations for kf size.
     // The first is based on the error score for the whole kf group.
@@ -2551,14 +2537,14 @@
     // Special case if the sequence appears almost totaly static
     // In this case we want to spend almost all of the bits on the
     // key frame.
-    // cpi->twopass.frames_to_key-1 because key frame itself is taken
+    // cpi->rc.frames_to_key-1 because key frame itself is taken
     // care of by kf_boost.
     if (zero_motion_accumulator >= 0.99) {
       allocation_chunks =
-        ((cpi->twopass.frames_to_key - 1) * 10) + kf_boost;
+        ((cpi->rc.frames_to_key - 1) * 10) + kf_boost;
     } else {
       allocation_chunks =
-        ((cpi->twopass.frames_to_key - 1) * 100) + kf_boost;
+        ((cpi->rc.frames_to_key - 1) * 100) + kf_boost;
     }
 
     // Prevent overflow
@@ -2580,10 +2566,10 @@
     // kf group (which does sometimes happen... eg a blank intro frame)
     // Then use an alternate calculation based on the kf error score
     // which should give a smaller key frame.
-    if (kf_mod_err < kf_group_err / cpi->twopass.frames_to_key) {
+    if (kf_mod_err < kf_group_err / cpi->rc.frames_to_key) {
       double  alt_kf_grp_bits =
         ((double)cpi->twopass.bits_left *
-         (kf_mod_err * (double)cpi->twopass.frames_to_key) /
+         (kf_mod_err * (double)cpi->rc.frames_to_key) /
          DOUBLE_DIVIDE_CHECK(cpi->twopass.modified_error_left));
 
       alt_kf_bits = (int)((double)kf_boost *
diff --git a/vp9/encoder/vp9_firstpass.h b/vp9/encoder/vp9_firstpass.h
index c18d11e..43703c2 100644
--- a/vp9/encoder/vp9_firstpass.h
+++ b/vp9/encoder/vp9_firstpass.h
@@ -17,7 +17,11 @@
 void vp9_end_first_pass(VP9_COMP *cpi);
 
 void vp9_init_second_pass(VP9_COMP *cpi);
-void vp9_second_pass(VP9_COMP *cpi);
+void vp9_get_second_pass_params(VP9_COMP *cpi);
 void vp9_end_second_pass(VP9_COMP *cpi);
 
+void vp9_get_first_pass_params(VP9_COMP *cpi);
+void vp9_get_one_pass_params(VP9_COMP *cpi);
+void vp9_get_svc_params(VP9_COMP *cpi);
+
 #endif  // VP9_ENCODER_VP9_FIRSTPASS_H_
diff --git a/vp9/encoder/vp9_mbgraph.c b/vp9/encoder/vp9_mbgraph.c
index 544f130..32ab3fc 100644
--- a/vp9/encoder/vp9_mbgraph.c
+++ b/vp9/encoder/vp9_mbgraph.c
@@ -42,7 +42,7 @@
       (cpi->speed < 8 ? (cpi->speed > 5 ? 1 : 0) : 2);
   step_param = MIN(step_param, (cpi->sf.max_step_search_steps - 2));
 
-  vp9_clamp_mv_min_max(x, &ref_mv->as_mv);
+  vp9_set_mv_search_range(x, &ref_mv->as_mv);
 
   ref_full.as_mv.col = ref_mv->as_mv.col >> 3;
   ref_full.as_mv.row = ref_mv->as_mv.row >> 3;
@@ -152,7 +152,8 @@
     xd->mi_8x8[0]->mbmi.mode = mode;
     vp9_predict_intra_block(xd, 0, 2, TX_16X16, mode,
                             x->plane[0].src.buf, x->plane[0].src.stride,
-                            xd->plane[0].dst.buf, xd->plane[0].dst.stride);
+                            xd->plane[0].dst.buf, xd->plane[0].dst.stride,
+                            0, 0, 0);
     err = vp9_sad16x16(x->plane[0].src.buf, x->plane[0].src.stride,
                        xd->plane[0].dst.buf, xd->plane[0].dst.stride, best_err);
 
@@ -398,8 +399,7 @@
   // being a GF - so exit if we don't look ahead beyond that
   if (n_frames <= cpi->rc.frames_till_gf_update_due)
     return;
-  if (n_frames > (int)cpi->frames_till_alt_ref_frame)
-    n_frames = cpi->frames_till_alt_ref_frame;
+
   if (n_frames > MAX_LAG_BUFFERS)
     n_frames = MAX_LAG_BUFFERS;
 
diff --git a/vp9/encoder/vp9_mcomp.c b/vp9/encoder/vp9_mcomp.c
index aec8de3..5e74d1a 100644
--- a/vp9/encoder/vp9_mcomp.c
+++ b/vp9/encoder/vp9_mcomp.c
@@ -16,7 +16,6 @@
 
 #include "vpx_mem/vpx_mem.h"
 
-#include "vp9/common/vp9_findnearmv.h"
 #include "vp9/common/vp9_common.h"
 
 #include "vp9/encoder/vp9_onyx_int.h"
@@ -24,7 +23,7 @@
 
 // #define NEW_DIAMOND_SEARCH
 
-void vp9_clamp_mv_min_max(MACROBLOCK *x, MV *mv) {
+void vp9_set_mv_search_range(MACROBLOCK *x, MV *mv) {
   const int col_min = (mv->col >> 3) - MAX_FULL_PEL_VAL + (mv->col & 7 ? 1 : 0);
   const int row_min = (mv->row >> 3) - MAX_FULL_PEL_VAL + (mv->row & 7 ? 1 : 0);
   const int col_max = (mv->col >> 3) + MAX_FULL_PEL_VAL;
@@ -270,104 +269,6 @@
     }                                                   \
   }
 
-int vp9_find_best_sub_pixel_iterative(MACROBLOCK *x,
-                                      MV *bestmv, const MV *ref_mv,
-                                      int allow_hp,
-                                      int error_per_bit,
-                                      const vp9_variance_fn_ptr_t *vfp,
-                                      int forced_stop,
-                                      int iters_per_step,
-                                      int *mvjcost, int *mvcost[2],
-                                      int *distortion,
-                                      unsigned int *sse1) {
-  uint8_t *z = x->plane[0].src.buf;
-  int src_stride = x->plane[0].src.stride;
-  MACROBLOCKD *xd = &x->e_mbd;
-
-  unsigned int besterr = INT_MAX;
-  unsigned int sse;
-  unsigned int whichdir;
-  unsigned int halfiters = iters_per_step;
-  unsigned int quarteriters = iters_per_step;
-  unsigned int eighthiters = iters_per_step;
-  int thismse;
-
-  const int y_stride = xd->plane[0].pre[0].stride;
-  const int offset = bestmv->row * y_stride + bestmv->col;
-  uint8_t *y = xd->plane[0].pre[0].buf + offset;
-
-  int rr = ref_mv->row;
-  int rc = ref_mv->col;
-  int br = bestmv->row * 8;
-  int bc = bestmv->col * 8;
-  int hstep = 4;
-  const int minc = MAX(x->mv_col_min * 8, ref_mv->col - MV_MAX);
-  const int maxc = MIN(x->mv_col_max * 8, ref_mv->col + MV_MAX);
-  const int minr = MAX(x->mv_row_min * 8, ref_mv->row - MV_MAX);
-  const int maxr = MIN(x->mv_row_max * 8, ref_mv->row + MV_MAX);
-
-  int tr = br;
-  int tc = bc;
-
-  // central mv
-  bestmv->row <<= 3;
-  bestmv->col <<= 3;
-
-  // calculate central point error
-  besterr = vfp->vf(y, y_stride, z, src_stride, sse1);
-  *distortion = besterr;
-  besterr += mv_err_cost(bestmv, ref_mv, mvjcost, mvcost, error_per_bit);
-
-  // TODO(jbb): Each subsequent iteration checks at least one point in
-  // common with the last iteration could be 2 if diagonal is selected.
-  while (halfiters--) {
-    // 1/2 pel
-    FIRST_LEVEL_CHECKS;
-    // no reason to check the same one again.
-    if (tr == br && tc == bc)
-      break;
-    tr = br;
-    tc = bc;
-  }
-
-  // TODO(yaowu): Each subsequent iteration checks at least one point in common
-  // with the last iteration could be 2 if diagonal is selected.
-
-  // Note forced_stop: 0 - full, 1 - qtr only, 2 - half only
-  if (forced_stop != 2) {
-    hstep >>= 1;
-    while (quarteriters--) {
-      FIRST_LEVEL_CHECKS;
-      // no reason to check the same one again.
-      if (tr == br && tc == bc)
-        break;
-      tr = br;
-      tc = bc;
-    }
-  }
-
-  if (allow_hp && vp9_use_mv_hp(ref_mv) && forced_stop == 0) {
-    hstep >>= 1;
-    while (eighthiters--) {
-      FIRST_LEVEL_CHECKS;
-      // no reason to check the same one again.
-      if (tr == br && tc == bc)
-        break;
-      tr = br;
-      tc = bc;
-    }
-  }
-
-  bestmv->row = br;
-  bestmv->col = bc;
-
-  if ((abs(bestmv->col - ref_mv->col) > (MAX_FULL_PEL_VAL << 3)) ||
-      (abs(bestmv->row - ref_mv->row) > (MAX_FULL_PEL_VAL << 3)))
-    return INT_MAX;
-
-  return besterr;
-}
-
 int vp9_find_best_sub_pixel_tree(MACROBLOCK *x,
                                  MV *bestmv, const MV *ref_mv,
                                  int allow_hp,
@@ -460,109 +361,6 @@
     vfp->svaf(PRE(r, c), y_stride, SP(c), SP(r), \
               z, src_stride, &sse, second_pred)
 
-int vp9_find_best_sub_pixel_comp_iterative(MACROBLOCK *x,
-                                           MV *bestmv, const MV *ref_mv,
-                                           int allow_hp,
-                                           int error_per_bit,
-                                           const vp9_variance_fn_ptr_t *vfp,
-                                           int forced_stop,
-                                           int iters_per_step,
-                                           int *mvjcost, int *mvcost[2],
-                                           int *distortion,
-                                           unsigned int *sse1,
-                                           const uint8_t *second_pred,
-                                           int w, int h) {
-  uint8_t *const z = x->plane[0].src.buf;
-  const int src_stride = x->plane[0].src.stride;
-  MACROBLOCKD *const xd = &x->e_mbd;
-
-  unsigned int besterr = INT_MAX;
-  unsigned int sse;
-  unsigned int whichdir;
-  unsigned int halfiters = iters_per_step;
-  unsigned int quarteriters = iters_per_step;
-  unsigned int eighthiters = iters_per_step;
-  int thismse;
-
-  DECLARE_ALIGNED_ARRAY(16, uint8_t, comp_pred, 64 * 64);
-  const int y_stride = xd->plane[0].pre[0].stride;
-  const int offset = bestmv->row * y_stride + bestmv->col;
-  uint8_t *const y = xd->plane[0].pre[0].buf + offset;
-
-  int rr = ref_mv->row;
-  int rc = ref_mv->col;
-  int br = bestmv->row * 8;
-  int bc = bestmv->col * 8;
-  int hstep = 4;
-  const int minc = MAX(x->mv_col_min * 8, ref_mv->col - MV_MAX);
-  const int maxc = MIN(x->mv_col_max * 8, ref_mv->col + MV_MAX);
-  const int minr = MAX(x->mv_row_min * 8, ref_mv->row - MV_MAX);
-  const int maxr = MIN(x->mv_row_max * 8, ref_mv->row + MV_MAX);
-
-  int tr = br;
-  int tc = bc;
-
-  // central mv
-  bestmv->row *= 8;
-  bestmv->col *= 8;
-
-  // calculate central point error
-  // TODO(yunqingwang): central pointer error was already calculated in full-
-  // pixel search, and can be passed in this function.
-  comp_avg_pred(comp_pred, second_pred, w, h, y, y_stride);
-  besterr = vfp->vf(comp_pred, w, z, src_stride, sse1);
-  *distortion = besterr;
-  besterr += mv_err_cost(bestmv, ref_mv, mvjcost, mvcost, error_per_bit);
-
-  // Each subsequent iteration checks at least one point in
-  // common with the last iteration could be 2 ( if diag selected)
-  while (halfiters--) {
-    // 1/2 pel
-    FIRST_LEVEL_CHECKS;
-    // no reason to check the same one again.
-    if (tr == br && tc == bc)
-      break;
-    tr = br;
-    tc = bc;
-  }
-
-  // Each subsequent iteration checks at least one point in common with
-  // the last iteration could be 2 ( if diag selected) 1/4 pel
-
-  // Note forced_stop: 0 - full, 1 - qtr only, 2 - half only
-  if (forced_stop != 2) {
-    hstep >>= 1;
-    while (quarteriters--) {
-      FIRST_LEVEL_CHECKS;
-      // no reason to check the same one again.
-      if (tr == br && tc == bc)
-        break;
-      tr = br;
-      tc = bc;
-    }
-  }
-
-  if (allow_hp && vp9_use_mv_hp(ref_mv) && forced_stop == 0) {
-    hstep >>= 1;
-    while (eighthiters--) {
-      FIRST_LEVEL_CHECKS;
-      // no reason to check the same one again.
-      if (tr == br && tc == bc)
-        break;
-      tr = br;
-      tc = bc;
-    }
-  }
-  bestmv->row = br;
-  bestmv->col = bc;
-
-  if ((abs(bestmv->col - ref_mv->col) > (MAX_FULL_PEL_VAL << 3)) ||
-      (abs(bestmv->row - ref_mv->row) > (MAX_FULL_PEL_VAL << 3)))
-    return INT_MAX;
-
-  return besterr;
-}
-
 int vp9_find_best_sub_pixel_comp_tree(MACROBLOCK *x,
                                       MV *bestmv, const MV *ref_mv,
                                       int allow_hp,
@@ -686,7 +484,7 @@
     if (thissad < bestsad)\
     {\
       if (use_mvcost) \
-        thissad += mvsad_err_cost(&this_mv, &fcenter_mv.as_mv, \
+        thissad += mvsad_err_cost(&this_mv, &fcenter_mv, \
                                   mvjsadcost, mvsadcost, \
                                   sad_per_bit);\
       if (thissad < bestsad)\
@@ -738,13 +536,13 @@
   uint8_t *this_offset;
   int k = -1;
   int best_site = -1;
-  int_mv fcenter_mv;
+  MV fcenter_mv;
   int best_init_s = search_param_to_steps[search_param];
   int *mvjsadcost = x->nmvjointsadcost;
   int *mvsadcost[2] = {x->nmvsadcost[0], x->nmvsadcost[1]};
 
-  fcenter_mv.as_mv.row = center_mv->row >> 3;
-  fcenter_mv.as_mv.col = center_mv->col >> 3;
+  fcenter_mv.row = center_mv->row >> 3;
+  fcenter_mv.col = center_mv->col >> 3;
 
   // adjust ref_mv to make sure it is within MV range
   clamp_mv(ref_mv, x->mv_col_min, x->mv_col_max, x->mv_row_min, x->mv_row_max);
@@ -757,7 +555,7 @@
   this_mv.row = br;
   this_mv.col = bc;
   bestsad = vfp->sdf(what, what_stride, this_offset, in_what_stride, 0x7fffffff)
-                + mvsad_err_cost(&this_mv, &fcenter_mv.as_mv,
+                + mvsad_err_cost(&this_mv, &fcenter_mv,
                                  mvjsadcost, mvsadcost, sad_per_bit);
 
   // Search all possible scales upto the search param around the center point
@@ -1057,10 +855,10 @@
 #undef CHECK_POINT
 #undef CHECK_BETTER
 
-int vp9_full_range_search_c(MACROBLOCK *x, int_mv *ref_mv, int_mv *best_mv,
+int vp9_full_range_search_c(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], int_mv *center_mv) {
+                            int *mvcost[2], const MV *center_mv) {
   const MACROBLOCKD* const xd = &x->e_mbd;
   uint8_t *what = x->plane[0].src.buf;
   int what_stride = x->plane[0].src.stride;
@@ -1068,14 +866,14 @@
   int in_what_stride = xd->plane[0].pre[0].stride;
   uint8_t *best_address;
 
-  int_mv this_mv;
+  MV this_mv;
 
   int bestsad = INT_MAX;
   int ref_row, ref_col;
 
   uint8_t *check_here;
   int thissad;
-  int_mv fcenter_mv;
+  MV fcenter_mv;
 
   int *mvjsadcost = x->nmvjointsadcost;
   int *mvsadcost[2] = {x->nmvsadcost[0], x->nmvsadcost[1]};
@@ -1089,16 +887,15 @@
   int start_row, end_row;
   int i;
 
-  fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
-  fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;
+  fcenter_mv.row = center_mv->row >> 3;
+  fcenter_mv.col = center_mv->col >> 3;
 
-  clamp_mv(&ref_mv->as_mv,
-           x->mv_col_min, x->mv_col_max, x->mv_row_min, x->mv_row_max);
-  ref_row = ref_mv->as_mv.row;
-  ref_col = ref_mv->as_mv.col;
+  clamp_mv(ref_mv, x->mv_col_min, x->mv_col_max, x->mv_row_min, x->mv_row_max);
+  ref_row = ref_mv->row;
+  ref_col = ref_mv->col;
   *num00 = 11;
-  best_mv->as_mv.row = ref_row;
-  best_mv->as_mv.col = ref_col;
+  best_mv->row = ref_row;
+  best_mv->col = ref_col;
 
   // Work out the start point for the search
   in_what = (uint8_t *)(xd->plane[0].pre[0].buf +
@@ -1107,7 +904,7 @@
 
   // Check the starting position
   bestsad = fn_ptr->sdf(what, what_stride, in_what, in_what_stride, 0x7fffffff)
-                + mvsad_err_cost(&best_mv->as_mv, &fcenter_mv.as_mv,
+                + mvsad_err_cost(best_mv, &fcenter_mv,
                                  mvjsadcost, mvsadcost, sad_per_bit);
 
   start_row = MAX(-range, x->mv_row_min - ref_row);
@@ -1127,10 +924,10 @@
 
         for (i = 0; i < 4; ++i) {
           if (sad_array[i] < bestsad) {
-            this_mv.as_mv.row = ref_row + tr;
-            this_mv.as_mv.col = ref_col + tc + i;
+            this_mv.row = ref_row + tr;
+            this_mv.col = ref_col + tc + i;
             thissad = sad_array[i] +
-                      mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv,
+                      mvsad_err_cost(&this_mv, &fcenter_mv,
                                       mvjsadcost, mvsadcost, sad_per_bit);
             if (thissad < bestsad) {
               bestsad = thissad;
@@ -1146,9 +943,9 @@
                                 bestsad);
 
           if (thissad < bestsad) {
-            this_mv.as_mv.row = ref_row + tr;
-            this_mv.as_mv.col = ref_col + tc + i;
-            thissad += mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv,
+            this_mv.row = ref_row + tr;
+            this_mv.col = ref_col + tc + i;
+            thissad += mvsad_err_cost(&this_mv, &fcenter_mv,
                                       mvjsadcost, mvsadcost, sad_per_bit);
 
             if (thissad < bestsad) {
@@ -1162,26 +959,26 @@
     }
   }
 
-  best_mv->as_mv.row += best_tr;
-  best_mv->as_mv.col += best_tc;
+  best_mv->row += best_tr;
+  best_mv->col += best_tc;
 
-  this_mv.as_mv.row = best_mv->as_mv.row * 8;
-  this_mv.as_mv.col = best_mv->as_mv.col * 8;
+  this_mv.row = best_mv->row * 8;
+  this_mv.col = best_mv->col * 8;
 
   if (bestsad == INT_MAX)
     return INT_MAX;
 
   return fn_ptr->vf(what, what_stride, best_address, in_what_stride,
                     (unsigned int *)(&thissad)) +
-                       mv_err_cost(&this_mv.as_mv, &center_mv->as_mv,
+                       mv_err_cost(&this_mv, center_mv,
                                    mvjcost, mvcost, x->errorperbit);
 }
 
 int vp9_diamond_search_sad_c(MACROBLOCK *x,
-                             int_mv *ref_mv, int_mv *best_mv,
+                             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], int_mv *center_mv) {
+                             int *mvcost[2], const MV *center_mv) {
   int i, j, step;
 
   const MACROBLOCKD* const xd = &x->e_mbd;
@@ -1192,7 +989,7 @@
   uint8_t *best_address;
 
   int tot_steps;
-  int_mv this_mv;
+  MV this_mv;
 
   int bestsad = INT_MAX;
   int best_site = 0;
@@ -1204,21 +1001,20 @@
 
   uint8_t *check_here;
   int thissad;
-  int_mv fcenter_mv;
+  MV fcenter_mv;
 
   int *mvjsadcost = x->nmvjointsadcost;
   int *mvsadcost[2] = {x->nmvsadcost[0], x->nmvsadcost[1]};
 
-  fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
-  fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;
+  fcenter_mv.row = center_mv->row >> 3;
+  fcenter_mv.col = center_mv->col >> 3;
 
-  clamp_mv(&ref_mv->as_mv,
-           x->mv_col_min, x->mv_col_max, x->mv_row_min, x->mv_row_max);
-  ref_row = ref_mv->as_mv.row;
-  ref_col = ref_mv->as_mv.col;
+  clamp_mv(ref_mv, x->mv_col_min, x->mv_col_max, x->mv_row_min, x->mv_row_max);
+  ref_row = ref_mv->row;
+  ref_col = ref_mv->col;
   *num00 = 0;
-  best_mv->as_mv.row = ref_row;
-  best_mv->as_mv.col = ref_col;
+  best_mv->row = ref_row;
+  best_mv->col = ref_col;
 
   // Work out the start point for the search
   in_what = (uint8_t *)(xd->plane[0].pre[0].buf +
@@ -1227,7 +1023,7 @@
 
   // Check the starting position
   bestsad = fn_ptr->sdf(what, what_stride, in_what, in_what_stride, 0x7fffffff)
-                + mvsad_err_cost(&best_mv->as_mv, &fcenter_mv.as_mv,
+                + mvsad_err_cost(best_mv, &fcenter_mv,
                                  mvjsadcost, mvsadcost, sad_per_bit);
 
   // search_param determines the length of the initial step and hence the number
@@ -1242,8 +1038,8 @@
   for (step = 0; step < tot_steps; step++) {
     for (j = 0; j < x->searches_per_step; j++) {
       // Trap illegal vectors
-      this_row_offset = best_mv->as_mv.row + ss[i].mv.row;
-      this_col_offset = best_mv->as_mv.col + ss[i].mv.col;
+      this_row_offset = best_mv->row + ss[i].mv.row;
+      this_col_offset = best_mv->col + ss[i].mv.col;
 
       if ((this_col_offset > x->mv_col_min) &&
           (this_col_offset < x->mv_col_max) &&
@@ -1254,9 +1050,9 @@
                               bestsad);
 
         if (thissad < bestsad) {
-          this_mv.as_mv.row = this_row_offset;
-          this_mv.as_mv.col = this_col_offset;
-          thissad += mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv,
+          this_mv.row = this_row_offset;
+          this_mv.col = this_col_offset;
+          thissad += mvsad_err_cost(&this_mv, &fcenter_mv,
                                     mvjsadcost, mvsadcost, sad_per_bit);
 
           if (thissad < bestsad) {
@@ -1270,14 +1066,14 @@
     }
 
     if (best_site != last_site) {
-      best_mv->as_mv.row += ss[best_site].mv.row;
-      best_mv->as_mv.col += ss[best_site].mv.col;
+      best_mv->row += ss[best_site].mv.row;
+      best_mv->col += ss[best_site].mv.col;
       best_address += ss[best_site].offset;
       last_site = best_site;
 #if defined(NEW_DIAMOND_SEARCH)
       while (1) {
-        this_row_offset = best_mv->as_mv.row + ss[best_site].mv.row;
-        this_col_offset = best_mv->as_mv.col + ss[best_site].mv.col;
+        this_row_offset = best_mv->row + ss[best_site].mv.row;
+        this_col_offset = best_mv->col + ss[best_site].mv.col;
         if ((this_col_offset > x->mv_col_min) &&
             (this_col_offset < x->mv_col_max) &&
             (this_row_offset > x->mv_row_min) &&
@@ -1286,14 +1082,14 @@
           thissad = fn_ptr->sdf(what, what_stride, check_here, in_what_stride,
                                 bestsad);
           if (thissad < bestsad) {
-            this_mv.as_mv.row = this_row_offset;
-            this_mv.as_mv.col = this_col_offset;
-            thissad += mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv,
+            this_mv.row = this_row_offset;
+            this_mv.col = this_col_offset;
+            thissad += mvsad_err_cost(&this_mv, &fcenter_mv,
                                       mvjsadcost, mvsadcost, sad_per_bit);
             if (thissad < bestsad) {
               bestsad = thissad;
-              best_mv->as_mv.row += ss[best_site].mv.row;
-              best_mv->as_mv.col += ss[best_site].mv.col;
+              best_mv->row += ss[best_site].mv.row;
+              best_mv->col += ss[best_site].mv.col;
               best_address += ss[best_site].offset;
               continue;
             }
@@ -1307,23 +1103,24 @@
     }
   }
 
-  this_mv.as_mv.row = best_mv->as_mv.row * 8;
-  this_mv.as_mv.col = best_mv->as_mv.col * 8;
+  this_mv.row = best_mv->row * 8;
+  this_mv.col = best_mv->col * 8;
 
   if (bestsad == INT_MAX)
     return INT_MAX;
 
   return fn_ptr->vf(what, what_stride, best_address, in_what_stride,
                     (unsigned int *)(&thissad)) +
-                       mv_err_cost(&this_mv.as_mv, &center_mv->as_mv,
+                       mv_err_cost(&this_mv, center_mv,
                                    mvjcost, mvcost, x->errorperbit);
 }
 
 int vp9_diamond_search_sadx4(MACROBLOCK *x,
-                             int_mv *ref_mv, int_mv *best_mv, int search_param,
+                             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], int_mv *center_mv) {
+                             int *mvjcost, int *mvcost[2],
+                             const MV *center_mv) {
   int i, j, step;
 
   const MACROBLOCKD* const xd = &x->e_mbd;
@@ -1334,7 +1131,7 @@
   uint8_t *best_address;
 
   int tot_steps;
-  int_mv this_mv;
+  MV this_mv;
 
   unsigned int bestsad = INT_MAX;
   int best_site = 0;
@@ -1348,21 +1145,20 @@
 
   uint8_t *check_here;
   unsigned int thissad;
-  int_mv fcenter_mv;
+  MV fcenter_mv;
 
   int *mvjsadcost = x->nmvjointsadcost;
   int *mvsadcost[2] = {x->nmvsadcost[0], x->nmvsadcost[1]};
 
-  fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
-  fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;
+  fcenter_mv.row = center_mv->row >> 3;
+  fcenter_mv.col = center_mv->col >> 3;
 
-  clamp_mv(&ref_mv->as_mv,
-           x->mv_col_min, x->mv_col_max, x->mv_row_min, x->mv_row_max);
-  ref_row = ref_mv->as_mv.row;
-  ref_col = ref_mv->as_mv.col;
+  clamp_mv(ref_mv, x->mv_col_min, x->mv_col_max, x->mv_row_min, x->mv_row_max);
+  ref_row = ref_mv->row;
+  ref_col = ref_mv->col;
   *num00 = 0;
-  best_mv->as_mv.row = ref_row;
-  best_mv->as_mv.col = ref_col;
+  best_mv->row = ref_row;
+  best_mv->col = ref_col;
 
   // Work out the start point for the search
   in_what = (uint8_t *)(xd->plane[0].pre[0].buf +
@@ -1371,7 +1167,7 @@
 
   // Check the starting position
   bestsad = fn_ptr->sdf(what, what_stride, in_what, in_what_stride, 0x7fffffff)
-                + mvsad_err_cost(&best_mv->as_mv, &fcenter_mv.as_mv,
+                + mvsad_err_cost(best_mv, &fcenter_mv,
                                  mvjsadcost, mvsadcost, sad_per_bit);
 
   // search_param determines the length of the initial step and hence the number
@@ -1389,10 +1185,10 @@
 
     // All_in is true if every one of the points we are checking are within
     // the bounds of the image.
-    all_in &= ((best_mv->as_mv.row + ss[i].mv.row) > x->mv_row_min);
-    all_in &= ((best_mv->as_mv.row + ss[i + 1].mv.row) < x->mv_row_max);
-    all_in &= ((best_mv->as_mv.col + ss[i + 2].mv.col) > x->mv_col_min);
-    all_in &= ((best_mv->as_mv.col + ss[i + 3].mv.col) < x->mv_col_max);
+    all_in &= ((best_mv->row + ss[i].mv.row) > x->mv_row_min);
+    all_in &= ((best_mv->row + ss[i + 1].mv.row) < x->mv_row_max);
+    all_in &= ((best_mv->col + ss[i + 2].mv.col) > x->mv_col_min);
+    all_in &= ((best_mv->col + ss[i + 3].mv.col) < x->mv_col_max);
 
     // If all the pixels are within the bounds we don't check whether the
     // search point is valid in this loop,  otherwise we check each point
@@ -1411,9 +1207,9 @@
 
         for (t = 0; t < 4; t++, i++) {
           if (sad_array[t] < bestsad) {
-            this_mv.as_mv.row = best_mv->as_mv.row + ss[i].mv.row;
-            this_mv.as_mv.col = best_mv->as_mv.col + ss[i].mv.col;
-            sad_array[t] += mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv,
+            this_mv.row = best_mv->row + ss[i].mv.row;
+            this_mv.col = best_mv->col + ss[i].mv.col;
+            sad_array[t] += mvsad_err_cost(&this_mv, &fcenter_mv,
                                            mvjsadcost, mvsadcost, sad_per_bit);
 
             if (sad_array[t] < bestsad) {
@@ -1426,8 +1222,8 @@
     } else {
       for (j = 0; j < x->searches_per_step; j++) {
         // Trap illegal vectors
-        this_row_offset = best_mv->as_mv.row + ss[i].mv.row;
-        this_col_offset = best_mv->as_mv.col + ss[i].mv.col;
+        this_row_offset = best_mv->row + ss[i].mv.row;
+        this_col_offset = best_mv->col + ss[i].mv.col;
 
         if ((this_col_offset > x->mv_col_min) &&
             (this_col_offset < x->mv_col_max) &&
@@ -1438,9 +1234,9 @@
                                 bestsad);
 
           if (thissad < bestsad) {
-            this_mv.as_mv.row = this_row_offset;
-            this_mv.as_mv.col = this_col_offset;
-            thissad += mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv,
+            this_mv.row = this_row_offset;
+            this_mv.col = this_col_offset;
+            thissad += mvsad_err_cost(&this_mv, &fcenter_mv,
                                       mvjsadcost, mvsadcost, sad_per_bit);
 
             if (thissad < bestsad) {
@@ -1453,14 +1249,14 @@
       }
     }
     if (best_site != last_site) {
-      best_mv->as_mv.row += ss[best_site].mv.row;
-      best_mv->as_mv.col += ss[best_site].mv.col;
+      best_mv->row += ss[best_site].mv.row;
+      best_mv->col += ss[best_site].mv.col;
       best_address += ss[best_site].offset;
       last_site = best_site;
 #if defined(NEW_DIAMOND_SEARCH)
       while (1) {
-        this_row_offset = best_mv->as_mv.row + ss[best_site].mv.row;
-        this_col_offset = best_mv->as_mv.col + ss[best_site].mv.col;
+        this_row_offset = best_mv->row + ss[best_site].mv.row;
+        this_col_offset = best_mv->col + ss[best_site].mv.col;
         if ((this_col_offset > x->mv_col_min) &&
             (this_col_offset < x->mv_col_max) &&
             (this_row_offset > x->mv_row_min) &&
@@ -1469,14 +1265,14 @@
           thissad = fn_ptr->sdf(what, what_stride, check_here, in_what_stride,
                                 bestsad);
           if (thissad < bestsad) {
-            this_mv.as_mv.row = this_row_offset;
-            this_mv.as_mv.col = this_col_offset;
-            thissad += mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv,
+            this_mv.row = this_row_offset;
+            this_mv.col = this_col_offset;
+            thissad += mvsad_err_cost(&this_mv, &fcenter_mv,
                                       mvjsadcost, mvsadcost, sad_per_bit);
             if (thissad < bestsad) {
               bestsad = thissad;
-              best_mv->as_mv.row += ss[best_site].mv.row;
-              best_mv->as_mv.col += ss[best_site].mv.col;
+              best_mv->row += ss[best_site].mv.row;
+              best_mv->col += ss[best_site].mv.col;
               best_address += ss[best_site].offset;
               continue;
             }
@@ -1490,15 +1286,15 @@
     }
   }
 
-  this_mv.as_mv.row = best_mv->as_mv.row * 8;
-  this_mv.as_mv.col = best_mv->as_mv.col * 8;
+  this_mv.row = best_mv->row * 8;
+  this_mv.col = best_mv->col * 8;
 
   if (bestsad == INT_MAX)
     return INT_MAX;
 
   return fn_ptr->vf(what, what_stride, best_address, in_what_stride,
                     (unsigned int *)(&thissad)) +
-                    mv_err_cost(&this_mv.as_mv, &center_mv->as_mv,
+                    mv_err_cost(&this_mv, center_mv,
                                 mvjcost, mvcost, x->errorperbit);
 }
 
@@ -1513,10 +1309,10 @@
                            int_mv *ref_mv, int_mv *dst_mv) {
   int_mv temp_mv;
   int thissme, n, num00;
-  int bestsme = cpi->diamond_search_sad(x, mvp_full, &temp_mv,
+  int bestsme = cpi->diamond_search_sad(x, &mvp_full->as_mv, &temp_mv.as_mv,
                                         step_param, sadpb, &num00,
                                         fn_ptr, x->nmvjointcost,
-                                        x->mvcost, ref_mv);
+                                        x->mvcost, &ref_mv->as_mv);
   dst_mv->as_int = temp_mv.as_int;
 
   n = num00;
@@ -1533,10 +1329,10 @@
     if (num00) {
       num00--;
     } else {
-      thissme = cpi->diamond_search_sad(x, mvp_full, &temp_mv,
+      thissme = cpi->diamond_search_sad(x, &mvp_full->as_mv, &temp_mv.as_mv,
                                         step_param + n, sadpb, &num00,
                                         fn_ptr, x->nmvjointcost, x->mvcost,
-                                        ref_mv);
+                                        &ref_mv->as_mv);
 
       /* check to see if refining search is needed. */
       if (num00 > (further_steps - n))
@@ -1554,9 +1350,9 @@
     int search_range = 8;
     int_mv best_mv;
     best_mv.as_int = dst_mv->as_int;
-    thissme = cpi->refining_search_sad(x, &best_mv, sadpb, search_range,
+    thissme = cpi->refining_search_sad(x, &best_mv.as_mv, sadpb, search_range,
                                        fn_ptr, x->nmvjointcost, x->mvcost,
-                                       ref_mv);
+                                       &ref_mv->as_mv);
 
     if (thissme < bestsme) {
       bestsme = thissme;
@@ -1566,11 +1362,11 @@
   return bestsme;
 }
 
-int vp9_full_search_sad_c(MACROBLOCK *x, int_mv *ref_mv,
+int vp9_full_search_sad_c(MACROBLOCK *x, MV *ref_mv,
                           int sad_per_bit, int distance,
                           vp9_variance_fn_ptr_t *fn_ptr, int *mvjcost,
                           int *mvcost[2],
-                          int_mv *center_mv, int n) {
+                          const MV *center_mv, int n) {
   const MACROBLOCKD* const xd = &x->e_mbd;
   uint8_t *what = x->plane[0].src.buf;
   int what_stride = x->plane[0].src.stride;
@@ -1578,40 +1374,40 @@
   int in_what_stride = xd->plane[0].pre[0].stride;
   int mv_stride = xd->plane[0].pre[0].stride;
   uint8_t *bestaddress;
-  int_mv *best_mv = &x->e_mbd.mi_8x8[0]->bmi[n].as_mv[0];
-  int_mv this_mv;
+  MV *best_mv = &x->e_mbd.mi_8x8[0]->bmi[n].as_mv[0].as_mv;
+  MV this_mv;
   int bestsad = INT_MAX;
   int r, c;
 
   uint8_t *check_here;
   int thissad;
 
-  int ref_row = ref_mv->as_mv.row;
-  int ref_col = ref_mv->as_mv.col;
+  int ref_row = ref_mv->row;
+  int ref_col = ref_mv->col;
 
   int row_min = ref_row - distance;
   int row_max = ref_row + distance;
   int col_min = ref_col - distance;
   int col_max = ref_col + distance;
-  int_mv fcenter_mv;
+  MV fcenter_mv;
 
   int *mvjsadcost = x->nmvjointsadcost;
   int *mvsadcost[2] = {x->nmvsadcost[0], x->nmvsadcost[1]};
 
-  fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
-  fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;
+  fcenter_mv.row = center_mv->row >> 3;
+  fcenter_mv.col = center_mv->col >> 3;
 
   // Work out the mid point for the search
   in_what = xd->plane[0].pre[0].buf;
   bestaddress = in_what + (ref_row * xd->plane[0].pre[0].stride) + ref_col;
 
-  best_mv->as_mv.row = ref_row;
-  best_mv->as_mv.col = ref_col;
+  best_mv->row = ref_row;
+  best_mv->col = ref_col;
 
   // Baseline value at the centre
   bestsad = fn_ptr->sdf(what, what_stride, bestaddress,
                         in_what_stride, 0x7fffffff)
-                           + mvsad_err_cost(&best_mv->as_mv, &fcenter_mv.as_mv,
+                           + mvsad_err_cost(best_mv, &fcenter_mv,
                                             mvjsadcost, mvsadcost, sad_per_bit);
 
   // Apply further limits to prevent us looking using vectors that stretch
@@ -1622,21 +1418,21 @@
   row_max = MIN(row_max, x->mv_row_max);
 
   for (r = row_min; r < row_max; r++) {
-    this_mv.as_mv.row = r;
+    this_mv.row = r;
     check_here = r * mv_stride + in_what + col_min;
 
     for (c = col_min; c < col_max; c++) {
       thissad = fn_ptr->sdf(what, what_stride, check_here, in_what_stride,
                             bestsad);
 
-      this_mv.as_mv.col = c;
-      thissad += mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv,
+      this_mv.col = c;
+      thissad += mvsad_err_cost(&this_mv, &fcenter_mv,
                                 mvjsadcost, mvsadcost, sad_per_bit);
 
       if (thissad < bestsad) {
         bestsad = thissad;
-        best_mv->as_mv.row = r;
-        best_mv->as_mv.col = c;
+        best_mv->row = r;
+        best_mv->col = c;
         bestaddress = check_here;
       }
 
@@ -1644,22 +1440,22 @@
     }
   }
 
-  this_mv.as_mv.row = best_mv->as_mv.row * 8;
-  this_mv.as_mv.col = best_mv->as_mv.col * 8;
+  this_mv.row = best_mv->row * 8;
+  this_mv.col = best_mv->col * 8;
 
   if (bestsad < INT_MAX)
     return fn_ptr->vf(what, what_stride, bestaddress, in_what_stride,
                       (unsigned int *)(&thissad)) +
-                      mv_err_cost(&this_mv.as_mv, &center_mv->as_mv,
+                      mv_err_cost(&this_mv, center_mv,
                                   mvjcost, mvcost, x->errorperbit);
   else
     return INT_MAX;
 }
 
-int vp9_full_search_sadx3(MACROBLOCK *x, int_mv *ref_mv,
+int vp9_full_search_sadx3(MACROBLOCK *x, MV *ref_mv,
                           int sad_per_bit, int distance,
                           vp9_variance_fn_ptr_t *fn_ptr, int *mvjcost,
-                          int *mvcost[2], int_mv *center_mv, int n) {
+                          int *mvcost[2], const MV *center_mv, int n) {
   const MACROBLOCKD* const xd = &x->e_mbd;
   uint8_t *what = x->plane[0].src.buf;
   int what_stride = x->plane[0].src.stride;
@@ -1667,16 +1463,16 @@
   int in_what_stride = xd->plane[0].pre[0].stride;
   int mv_stride = xd->plane[0].pre[0].stride;
   uint8_t *bestaddress;
-  int_mv *best_mv = &x->e_mbd.mi_8x8[0]->bmi[n].as_mv[0];
-  int_mv this_mv;
+  MV *best_mv = &x->e_mbd.mi_8x8[0]->bmi[n].as_mv[0].as_mv;
+  MV this_mv;
   unsigned int bestsad = INT_MAX;
   int r, c;
 
   uint8_t *check_here;
   unsigned int thissad;
 
-  int ref_row = ref_mv->as_mv.row;
-  int ref_col = ref_mv->as_mv.col;
+  int ref_row = ref_mv->row;
+  int ref_col = ref_mv->col;
 
   int row_min = ref_row - distance;
   int row_max = ref_row + distance;
@@ -1684,25 +1480,25 @@
   int col_max = ref_col + distance;
 
   unsigned int sad_array[3];
-  int_mv fcenter_mv;
+  MV fcenter_mv;
 
   int *mvjsadcost = x->nmvjointsadcost;
   int *mvsadcost[2] = {x->nmvsadcost[0], x->nmvsadcost[1]};
 
-  fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
-  fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;
+  fcenter_mv.row = center_mv->row >> 3;
+  fcenter_mv.col = center_mv->col >> 3;
 
   // Work out the mid point for the search
   in_what = xd->plane[0].pre[0].buf;
   bestaddress = in_what + (ref_row * xd->plane[0].pre[0].stride) + ref_col;
 
-  best_mv->as_mv.row = ref_row;
-  best_mv->as_mv.col = ref_col;
+  best_mv->row = ref_row;
+  best_mv->col = ref_col;
 
   // Baseline value at the centre
   bestsad = fn_ptr->sdf(what, what_stride,
                         bestaddress, in_what_stride, 0x7fffffff)
-            + mvsad_err_cost(&best_mv->as_mv, &fcenter_mv.as_mv,
+            + mvsad_err_cost(best_mv, &fcenter_mv,
                              mvjsadcost, mvsadcost, sad_per_bit);
 
   // Apply further limits to prevent us looking using vectors that stretch
@@ -1713,7 +1509,7 @@
   row_max = MIN(row_max, x->mv_row_max);
 
   for (r = row_min; r < row_max; r++) {
-    this_mv.as_mv.row = r;
+    this_mv.row = r;
     check_here = r * mv_stride + in_what + col_min;
     c = col_min;
 
@@ -1726,14 +1522,14 @@
         thissad = sad_array[i];
 
         if (thissad < bestsad) {
-          this_mv.as_mv.col = c;
-          thissad += mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv,
+          this_mv.col = c;
+          thissad += mvsad_err_cost(&this_mv, &fcenter_mv,
                                     mvjsadcost, mvsadcost, sad_per_bit);
 
           if (thissad < bestsad) {
             bestsad = thissad;
-            best_mv->as_mv.row = r;
-            best_mv->as_mv.col = c;
+            best_mv->row = r;
+            best_mv->col = c;
             bestaddress = check_here;
           }
         }
@@ -1748,14 +1544,14 @@
                             bestsad);
 
       if (thissad < bestsad) {
-        this_mv.as_mv.col = c;
-        thissad  += mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv,
+        this_mv.col = c;
+        thissad  += mvsad_err_cost(&this_mv, &fcenter_mv,
                                    mvjsadcost, mvsadcost, sad_per_bit);
 
         if (thissad < bestsad) {
           bestsad = thissad;
-          best_mv->as_mv.row = r;
-          best_mv->as_mv.col = c;
+          best_mv->row = r;
+          best_mv->col = c;
           bestaddress = check_here;
         }
       }
@@ -1765,23 +1561,23 @@
     }
   }
 
-  this_mv.as_mv.row = best_mv->as_mv.row * 8;
-  this_mv.as_mv.col = best_mv->as_mv.col * 8;
+  this_mv.row = best_mv->row * 8;
+  this_mv.col = best_mv->col * 8;
 
   if (bestsad < INT_MAX)
     return fn_ptr->vf(what, what_stride, bestaddress, in_what_stride,
                       (unsigned int *)(&thissad)) +
-                      mv_err_cost(&this_mv.as_mv, &center_mv->as_mv,
+                      mv_err_cost(&this_mv, center_mv,
                                   mvjcost, mvcost, x->errorperbit);
   else
     return INT_MAX;
 }
 
-int vp9_full_search_sadx8(MACROBLOCK *x, int_mv *ref_mv,
+int vp9_full_search_sadx8(MACROBLOCK *x, MV *ref_mv,
                           int sad_per_bit, int distance,
                           vp9_variance_fn_ptr_t *fn_ptr,
                           int *mvjcost, int *mvcost[2],
-                          int_mv *center_mv, int n) {
+                          const MV *center_mv, int n) {
   const MACROBLOCKD* const xd = &x->e_mbd;
   uint8_t *what = x->plane[0].src.buf;
   int what_stride = x->plane[0].src.stride;
@@ -1789,16 +1585,16 @@
   int in_what_stride = xd->plane[0].pre[0].stride;
   int mv_stride = xd->plane[0].pre[0].stride;
   uint8_t *bestaddress;
-  int_mv *best_mv = &x->e_mbd.mi_8x8[0]->bmi[n].as_mv[0];
-  int_mv this_mv;
+  MV *best_mv = &x->e_mbd.mi_8x8[0]->bmi[n].as_mv[0].as_mv;
+  MV this_mv;
   unsigned int bestsad = INT_MAX;
   int r, c;
 
   uint8_t *check_here;
   unsigned int thissad;
 
-  int ref_row = ref_mv->as_mv.row;
-  int ref_col = ref_mv->as_mv.col;
+  int ref_row = ref_mv->row;
+  int ref_col = ref_mv->col;
 
   int row_min = ref_row - distance;
   int row_max = ref_row + distance;
@@ -1807,25 +1603,25 @@
 
   DECLARE_ALIGNED_ARRAY(16, uint32_t, sad_array8, 8);
   unsigned int sad_array[3];
-  int_mv fcenter_mv;
+  MV fcenter_mv;
 
   int *mvjsadcost = x->nmvjointsadcost;
   int *mvsadcost[2] = {x->nmvsadcost[0], x->nmvsadcost[1]};
 
-  fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
-  fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;
+  fcenter_mv.row = center_mv->row >> 3;
+  fcenter_mv.col = center_mv->col >> 3;
 
   // Work out the mid point for the search
   in_what = xd->plane[0].pre[0].buf;
   bestaddress = in_what + (ref_row * xd->plane[0].pre[0].stride) + ref_col;
 
-  best_mv->as_mv.row = ref_row;
-  best_mv->as_mv.col = ref_col;
+  best_mv->row = ref_row;
+  best_mv->col = ref_col;
 
-  // Baseline value at the centre
+  // Baseline value at the center
   bestsad = fn_ptr->sdf(what, what_stride,
                         bestaddress, in_what_stride, 0x7fffffff)
-            + mvsad_err_cost(&best_mv->as_mv, &fcenter_mv.as_mv,
+            + mvsad_err_cost(best_mv, &fcenter_mv,
                              mvjsadcost, mvsadcost, sad_per_bit);
 
   // Apply further limits to prevent us looking using vectors that stretch
@@ -1836,7 +1632,7 @@
   row_max = MIN(row_max, x->mv_row_max);
 
   for (r = row_min; r < row_max; r++) {
-    this_mv.as_mv.row = r;
+    this_mv.row = r;
     check_here = r * mv_stride + in_what + col_min;
     c = col_min;
 
@@ -1849,14 +1645,14 @@
         thissad = (unsigned int)sad_array8[i];
 
         if (thissad < bestsad) {
-          this_mv.as_mv.col = c;
-          thissad += mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv,
+          this_mv.col = c;
+          thissad += mvsad_err_cost(&this_mv, &fcenter_mv,
                                     mvjsadcost, mvsadcost, sad_per_bit);
 
           if (thissad < bestsad) {
             bestsad = thissad;
-            best_mv->as_mv.row = r;
-            best_mv->as_mv.col = c;
+            best_mv->row = r;
+            best_mv->col = c;
             bestaddress = check_here;
           }
         }
@@ -1875,14 +1671,14 @@
         thissad = sad_array[i];
 
         if (thissad < bestsad) {
-          this_mv.as_mv.col = c;
-          thissad  += mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv,
+          this_mv.col = c;
+          thissad  += mvsad_err_cost(&this_mv, &fcenter_mv,
                                      mvjsadcost, mvsadcost, sad_per_bit);
 
           if (thissad < bestsad) {
             bestsad = thissad;
-            best_mv->as_mv.row = r;
-            best_mv->as_mv.col = c;
+            best_mv->row = r;
+            best_mv->col = c;
             bestaddress = check_here;
           }
         }
@@ -1897,14 +1693,14 @@
                             bestsad);
 
       if (thissad < bestsad) {
-        this_mv.as_mv.col = c;
-        thissad += mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv,
+        this_mv.col = c;
+        thissad += mvsad_err_cost(&this_mv, &fcenter_mv,
                                   mvjsadcost, mvsadcost, sad_per_bit);
 
         if (thissad < bestsad) {
           bestsad = thissad;
-          best_mv->as_mv.row = r;
-          best_mv->as_mv.col = c;
+          best_mv->row = r;
+          best_mv->col = c;
           bestaddress = check_here;
         }
       }
@@ -1914,21 +1710,22 @@
     }
   }
 
-  this_mv.as_mv.row = best_mv->as_mv.row * 8;
-  this_mv.as_mv.col = best_mv->as_mv.col * 8;
+  this_mv.row = best_mv->row * 8;
+  this_mv.col = best_mv->col * 8;
 
   if (bestsad < INT_MAX)
     return fn_ptr->vf(what, what_stride, bestaddress, in_what_stride,
                       (unsigned int *)(&thissad)) +
-                      mv_err_cost(&this_mv.as_mv, &center_mv->as_mv,
+                      mv_err_cost(&this_mv, center_mv,
                                   mvjcost, mvcost, x->errorperbit);
   else
     return INT_MAX;
 }
 int vp9_refining_search_sad_c(MACROBLOCK *x,
-                              int_mv *ref_mv, int error_per_bit,
+                              MV *ref_mv, int error_per_bit,
                               int search_range, vp9_variance_fn_ptr_t *fn_ptr,
-                              int *mvjcost, int *mvcost[2], int_mv *center_mv) {
+                              int *mvjcost, int *mvcost[2],
+                              const MV *center_mv) {
   const MACROBLOCKD* const xd = &x->e_mbd;
   MV neighbors[4] = {{ -1, 0}, {0, -1}, {0, 1}, {1, 0}};
   int i, j;
@@ -1938,31 +1735,31 @@
   int in_what_stride = xd->plane[0].pre[0].stride;
   uint8_t *what = x->plane[0].src.buf;
   uint8_t *best_address = xd->plane[0].pre[0].buf +
-                          (ref_mv->as_mv.row * xd->plane[0].pre[0].stride) +
-                          ref_mv->as_mv.col;
+                          (ref_mv->row * xd->plane[0].pre[0].stride) +
+                          ref_mv->col;
   uint8_t *check_here;
   unsigned int thissad;
-  int_mv this_mv;
+  MV this_mv;
   unsigned int bestsad = INT_MAX;
-  int_mv fcenter_mv;
+  MV fcenter_mv;
 
   int *mvjsadcost = x->nmvjointsadcost;
   int *mvsadcost[2] = {x->nmvsadcost[0], x->nmvsadcost[1]};
 
-  fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
-  fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;
+  fcenter_mv.row = center_mv->row >> 3;
+  fcenter_mv.col = center_mv->col >> 3;
 
   bestsad = fn_ptr->sdf(what, what_stride, best_address,
                         in_what_stride, 0x7fffffff) +
-                        mvsad_err_cost(&ref_mv->as_mv, &fcenter_mv.as_mv,
+                        mvsad_err_cost(ref_mv, &fcenter_mv,
                                        mvjsadcost, mvsadcost, error_per_bit);
 
   for (i = 0; i < search_range; i++) {
     int best_site = -1;
 
     for (j = 0; j < 4; j++) {
-      this_row_offset = ref_mv->as_mv.row + neighbors[j].row;
-      this_col_offset = ref_mv->as_mv.col + neighbors[j].col;
+      this_row_offset = ref_mv->row + neighbors[j].row;
+      this_col_offset = ref_mv->col + neighbors[j].col;
 
       if ((this_col_offset > x->mv_col_min) &&
           (this_col_offset < x->mv_col_max) &&
@@ -1974,9 +1771,9 @@
                               bestsad);
 
         if (thissad < bestsad) {
-          this_mv.as_mv.row = this_row_offset;
-          this_mv.as_mv.col = this_col_offset;
-          thissad += mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv,
+          this_mv.row = this_row_offset;
+          this_mv.col = this_col_offset;
+          thissad += mvsad_err_cost(&this_mv, &fcenter_mv,
                                     mvjsadcost, mvsadcost, error_per_bit);
 
           if (thissad < bestsad) {
@@ -1990,29 +1787,30 @@
     if (best_site == -1) {
       break;
     } else {
-      ref_mv->as_mv.row += neighbors[best_site].row;
-      ref_mv->as_mv.col += neighbors[best_site].col;
+      ref_mv->row += neighbors[best_site].row;
+      ref_mv->col += neighbors[best_site].col;
       best_address += (neighbors[best_site].row) * in_what_stride +
                       neighbors[best_site].col;
     }
   }
 
-  this_mv.as_mv.row = ref_mv->as_mv.row * 8;
-  this_mv.as_mv.col = ref_mv->as_mv.col * 8;
+  this_mv.row = ref_mv->row * 8;
+  this_mv.col = ref_mv->col * 8;
 
   if (bestsad < INT_MAX)
     return fn_ptr->vf(what, what_stride, best_address, in_what_stride,
                       (unsigned int *)(&thissad)) +
-                      mv_err_cost(&this_mv.as_mv, &center_mv->as_mv,
+                      mv_err_cost(&this_mv, center_mv,
                                   mvjcost, mvcost, x->errorperbit);
   else
     return INT_MAX;
 }
 
 int vp9_refining_search_sadx4(MACROBLOCK *x,
-                              int_mv *ref_mv, int error_per_bit,
+                              MV *ref_mv, int error_per_bit,
                               int search_range, vp9_variance_fn_ptr_t *fn_ptr,
-                              int *mvjcost, int *mvcost[2], int_mv *center_mv) {
+                              int *mvjcost, int *mvcost[2],
+                              const MV *center_mv) {
   const MACROBLOCKD* const xd = &x->e_mbd;
   MV neighbors[4] = {{ -1, 0}, {0, -1}, {0, 1}, {1, 0}};
   int i, j;
@@ -2022,31 +1820,31 @@
   int in_what_stride = xd->plane[0].pre[0].stride;
   uint8_t *what = x->plane[0].src.buf;
   uint8_t *best_address = xd->plane[0].pre[0].buf +
-                          (ref_mv->as_mv.row * xd->plane[0].pre[0].stride) +
-                          ref_mv->as_mv.col;
+                          (ref_mv->row * xd->plane[0].pre[0].stride) +
+                          ref_mv->col;
   uint8_t *check_here;
   unsigned int thissad;
-  int_mv this_mv;
+  MV this_mv;
   unsigned int bestsad = INT_MAX;
-  int_mv fcenter_mv;
+  MV fcenter_mv;
 
   int *mvjsadcost = x->nmvjointsadcost;
   int *mvsadcost[2] = {x->nmvsadcost[0], x->nmvsadcost[1]};
 
-  fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
-  fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;
+  fcenter_mv.row = center_mv->row >> 3;
+  fcenter_mv.col = center_mv->col >> 3;
 
   bestsad = fn_ptr->sdf(what, what_stride, best_address,
                         in_what_stride, 0x7fffffff) +
-      mvsad_err_cost(&ref_mv->as_mv, &fcenter_mv.as_mv,
+      mvsad_err_cost(ref_mv, &fcenter_mv,
                      mvjsadcost, mvsadcost, error_per_bit);
 
   for (i = 0; i < search_range; i++) {
     int best_site = -1;
-    int all_in = ((ref_mv->as_mv.row - 1) > x->mv_row_min) &
-                 ((ref_mv->as_mv.row + 1) < x->mv_row_max) &
-                 ((ref_mv->as_mv.col - 1) > x->mv_col_min) &
-                 ((ref_mv->as_mv.col + 1) < x->mv_col_max);
+    int all_in = ((ref_mv->row - 1) > x->mv_row_min) &
+                 ((ref_mv->row + 1) < x->mv_row_max) &
+                 ((ref_mv->col - 1) > x->mv_col_min) &
+                 ((ref_mv->col + 1) < x->mv_col_max);
 
     if (all_in) {
       unsigned int sad_array[4];
@@ -2061,9 +1859,9 @@
 
       for (j = 0; j < 4; j++) {
         if (sad_array[j] < bestsad) {
-          this_mv.as_mv.row = ref_mv->as_mv.row + neighbors[j].row;
-          this_mv.as_mv.col = ref_mv->as_mv.col + neighbors[j].col;
-          sad_array[j] += mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv,
+          this_mv.row = ref_mv->row + neighbors[j].row;
+          this_mv.col = ref_mv->col + neighbors[j].col;
+          sad_array[j] += mvsad_err_cost(&this_mv, &fcenter_mv,
                                          mvjsadcost, mvsadcost, error_per_bit);
 
           if (sad_array[j] < bestsad) {
@@ -2074,8 +1872,8 @@
       }
     } else {
       for (j = 0; j < 4; j++) {
-        this_row_offset = ref_mv->as_mv.row + neighbors[j].row;
-        this_col_offset = ref_mv->as_mv.col + neighbors[j].col;
+        this_row_offset = ref_mv->row + neighbors[j].row;
+        this_col_offset = ref_mv->col + neighbors[j].col;
 
         if ((this_col_offset > x->mv_col_min) &&
             (this_col_offset < x->mv_col_max) &&
@@ -2087,9 +1885,9 @@
                                 bestsad);
 
           if (thissad < bestsad) {
-            this_mv.as_mv.row = this_row_offset;
-            this_mv.as_mv.col = this_col_offset;
-            thissad += mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv,
+            this_mv.row = this_row_offset;
+            this_mv.col = this_col_offset;
+            thissad += mvsad_err_cost(&this_mv, &fcenter_mv,
                                       mvjsadcost, mvsadcost, error_per_bit);
 
             if (thissad < bestsad) {
@@ -2104,20 +1902,20 @@
     if (best_site == -1) {
       break;
     } else {
-      ref_mv->as_mv.row += neighbors[best_site].row;
-      ref_mv->as_mv.col += neighbors[best_site].col;
+      ref_mv->row += neighbors[best_site].row;
+      ref_mv->col += neighbors[best_site].col;
       best_address += (neighbors[best_site].row) * in_what_stride +
                       neighbors[best_site].col;
     }
   }
 
-  this_mv.as_mv.row = ref_mv->as_mv.row * 8;
-  this_mv.as_mv.col = ref_mv->as_mv.col * 8;
+  this_mv.row = ref_mv->row * 8;
+  this_mv.col = ref_mv->col * 8;
 
   if (bestsad < INT_MAX)
     return fn_ptr->vf(what, what_stride, best_address, in_what_stride,
                       (unsigned int *)(&thissad)) +
-                      mv_err_cost(&this_mv.as_mv, &center_mv->as_mv,
+                      mv_err_cost(&this_mv, center_mv,
                                   mvjcost, mvcost, x->errorperbit);
   else
     return INT_MAX;
@@ -2127,9 +1925,9 @@
  * mode.
  */
 int vp9_refining_search_8p_c(MACROBLOCK *x,
-                             int_mv *ref_mv, int error_per_bit,
+                             MV *ref_mv, int error_per_bit,
                              int search_range, vp9_variance_fn_ptr_t *fn_ptr,
-                             int *mvjcost, int *mvcost[2], int_mv *center_mv,
+                             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;
   MV neighbors[8] = {{-1, 0}, {0, -1}, {0, 1}, {1, 0},
@@ -2141,32 +1939,32 @@
   int in_what_stride = xd->plane[0].pre[0].stride;
   uint8_t *what = x->plane[0].src.buf;
   uint8_t *best_address = xd->plane[0].pre[0].buf +
-                          (ref_mv->as_mv.row * xd->plane[0].pre[0].stride) +
-                          ref_mv->as_mv.col;
+                          (ref_mv->row * xd->plane[0].pre[0].stride) +
+                          ref_mv->col;
   uint8_t *check_here;
   unsigned int thissad;
-  int_mv this_mv;
+  MV this_mv;
   unsigned int bestsad = INT_MAX;
-  int_mv fcenter_mv;
+  MV fcenter_mv;
 
   int *mvjsadcost = x->nmvjointsadcost;
   int *mvsadcost[2] = {x->nmvsadcost[0], x->nmvsadcost[1]};
 
-  fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
-  fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;
+  fcenter_mv.row = center_mv->row >> 3;
+  fcenter_mv.col = center_mv->col >> 3;
 
   /* Get compound pred by averaging two pred blocks. */
   bestsad = fn_ptr->sdaf(what, what_stride, best_address, in_what_stride,
                          second_pred, 0x7fffffff) +
-      mvsad_err_cost(&ref_mv->as_mv, &fcenter_mv.as_mv,
+      mvsad_err_cost(ref_mv, &fcenter_mv,
                      mvjsadcost, mvsadcost, error_per_bit);
 
   for (i = 0; i < search_range; i++) {
     int best_site = -1;
 
     for (j = 0; j < 8; j++) {
-      this_row_offset = ref_mv->as_mv.row + neighbors[j].row;
-      this_col_offset = ref_mv->as_mv.col + neighbors[j].col;
+      this_row_offset = ref_mv->row + neighbors[j].row;
+      this_col_offset = ref_mv->col + neighbors[j].col;
 
       if ((this_col_offset > x->mv_col_min) &&
           (this_col_offset < x->mv_col_max) &&
@@ -2180,9 +1978,9 @@
                                second_pred, bestsad);
 
         if (thissad < bestsad) {
-          this_mv.as_mv.row = this_row_offset;
-          this_mv.as_mv.col = this_col_offset;
-          thissad += mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv,
+          this_mv.row = this_row_offset;
+          this_mv.col = this_col_offset;
+          thissad += mvsad_err_cost(&this_mv, &fcenter_mv,
                                     mvjsadcost, mvsadcost, error_per_bit);
           if (thissad < bestsad) {
             bestsad = thissad;
@@ -2195,22 +1993,22 @@
     if (best_site == -1) {
       break;
     } else {
-      ref_mv->as_mv.row += neighbors[best_site].row;
-      ref_mv->as_mv.col += neighbors[best_site].col;
+      ref_mv->row += neighbors[best_site].row;
+      ref_mv->col += neighbors[best_site].col;
       best_address += (neighbors[best_site].row) * in_what_stride +
           neighbors[best_site].col;
     }
   }
 
-  this_mv.as_mv.row = ref_mv->as_mv.row * 8;
-  this_mv.as_mv.col = ref_mv->as_mv.col * 8;
+  this_mv.row = ref_mv->row * 8;
+  this_mv.col = ref_mv->col * 8;
 
   if (bestsad < INT_MAX) {
     // FIXME(rbultje, yunqing): add full-pixel averaging variance functions
     // so we don't have to use the subpixel with xoff=0,yoff=0 here.
     return fn_ptr->svaf(best_address, in_what_stride, 0, 0, what, what_stride,
                         (unsigned int *)(&thissad), second_pred) +
-                        mv_err_cost(&this_mv.as_mv, &center_mv->as_mv,
+                        mv_err_cost(&this_mv, center_mv,
                                     mvjcost, mvcost, x->errorperbit);
   } else {
     return INT_MAX;
diff --git a/vp9/encoder/vp9_mcomp.h b/vp9/encoder/vp9_mcomp.h
index 10c2e4f..1cb2977 100644
--- a/vp9/encoder/vp9_mcomp.h
+++ b/vp9/encoder/vp9_mcomp.h
@@ -28,7 +28,7 @@
 #define BORDER_MV_PIXELS_B16 (16 + VP9_INTERP_EXTEND)
 
 
-void vp9_clamp_mv_min_max(MACROBLOCK *x, MV *mv);
+void vp9_set_mv_search_range(MACROBLOCK *x, MV *mv);
 int vp9_mv_bit_cost(const MV *mv, const MV *ref,
                     const int *mvjcost, int *mvcost[2], int weight);
 void vp9_init_dsmotion_compensation(MACROBLOCK *x, int stride);
@@ -84,7 +84,7 @@
     int *mvcost[2],
     int *distortion,
     unsigned int *sse);
-extern fractional_mv_step_fp vp9_find_best_sub_pixel_iterative;
+
 extern fractional_mv_step_fp vp9_find_best_sub_pixel_tree;
 
 typedef int (fractional_mv_step_comp_fp) (
@@ -99,34 +99,34 @@
     int *distortion, unsigned int *sse1,
     const uint8_t *second_pred,
     int w, int h);
-extern fractional_mv_step_comp_fp vp9_find_best_sub_pixel_comp_iterative;
+
 extern fractional_mv_step_comp_fp vp9_find_best_sub_pixel_comp_tree;
 
 typedef int (*vp9_full_search_fn_t)(MACROBLOCK *x,
-                                    int_mv *ref_mv, int sad_per_bit,
+                                    MV *ref_mv, int sad_per_bit,
                                     int distance, vp9_variance_fn_ptr_t *fn_ptr,
                                     int *mvjcost, int *mvcost[2],
-                                    int_mv *center_mv, int n);
+                                    const MV *center_mv, int n);
 
 typedef int (*vp9_refining_search_fn_t)(MACROBLOCK *x,
-                                        int_mv *ref_mv, int sad_per_bit,
+                                        MV *ref_mv, int sad_per_bit,
                                         int distance,
                                         vp9_variance_fn_ptr_t *fn_ptr,
                                         int *mvjcost, int *mvcost[2],
-                                        int_mv *center_mv);
+                                        const MV *center_mv);
 
 typedef int (*vp9_diamond_search_fn_t)(MACROBLOCK *x,
-                                       int_mv *ref_mv, int_mv *best_mv,
+                                       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],
-                                       int_mv *center_mv);
+                                       const MV *center_mv);
 
 int vp9_refining_search_8p_c(MACROBLOCK *x,
-                             int_mv *ref_mv, int error_per_bit,
+                             MV *ref_mv, int error_per_bit,
                              int search_range, vp9_variance_fn_ptr_t *fn_ptr,
                              int *mvjcost, int *mvcost[2],
-                             int_mv *center_mv, const uint8_t *second_pred,
+                             const MV *center_mv, const uint8_t *second_pred,
                              int w, int h);
 #endif  // VP9_ENCODER_VP9_MCOMP_H_
diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c
index b10d9f8..2e34b4a 100644
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -42,8 +42,6 @@
 void vp9_entropy_mode_init();
 void vp9_coef_tree_initialize();
 
-static void set_default_lf_deltas(struct loopfilter *lf);
-
 #define DEFAULT_INTERP_FILTER SWITCHABLE
 
 #define SHARP_FILTER_QTHRESH 0          /* Q threshold for 8-tap sharp filter */
@@ -172,27 +170,15 @@
   }
 }
 
-static void setup_features(VP9_COMMON *cm) {
-  struct loopfilter *const lf = &cm->lf;
+static void reset_segment_features(VP9_COMMON *cm) {
   struct segmentation *const seg = &cm->seg;
 
   // Set up default state for MB feature flags
   seg->enabled = 0;
-
   seg->update_map = 0;
   seg->update_data = 0;
   vpx_memset(seg->tree_probs, 255, sizeof(seg->tree_probs));
-
   vp9_clearall_segfeatures(seg);
-
-  lf->mode_ref_delta_enabled = 0;
-  lf->mode_ref_delta_update = 0;
-  vp9_zero(lf->ref_deltas);
-  vp9_zero(lf->mode_deltas);
-  vp9_zero(lf->last_ref_deltas);
-  vp9_zero(lf->last_mode_deltas);
-
-  set_default_lf_deltas(lf);
 }
 
 static void dealloc_compressor_data(VP9_COMP *cpi) {
@@ -302,7 +288,7 @@
 
   if (cm->frame_type == KEY_FRAME ||
       cpi->refresh_alt_ref_frame ||
-      (cpi->refresh_golden_frame && !cpi->is_src_frame_alt_ref)) {
+      (cpi->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref)) {
     // Clear down the segment map
     vpx_memset(cpi->segmentation_map, 0, cm->mi_rows * cm->mi_cols);
 
@@ -329,7 +315,6 @@
     }
   }
 }
-
 static void configure_static_seg_features(VP9_COMP *cpi) {
   VP9_COMMON *cm = &cpi->common;
   struct segmentation *seg = &cm->seg;
@@ -389,7 +374,7 @@
     // First normal frame in a valid gf or alt ref group
     if (cpi->rc.frames_since_golden == 0) {
       // Set up segment features for normal frames in an arf group
-      if (cpi->source_alt_ref_active) {
+      if (cpi->rc.source_alt_ref_active) {
         seg->update_map = 0;
         seg->update_data = 1;
         seg->abs_delta = SEGMENT_DELTADATA;
@@ -421,7 +406,7 @@
 
         vp9_clearall_segfeatures(seg);
       }
-    } else if (cpi->is_src_frame_alt_ref) {
+    } else if (cpi->rc.is_src_frame_alt_ref) {
       // Special case where we are coding over the top of a previous
       // alt ref frame.
       // Segment coding disabled for compred testing
@@ -490,23 +475,6 @@
   }
 }
 
-static void set_default_lf_deltas(struct loopfilter *lf) {
-  lf->mode_ref_delta_enabled = 1;
-  lf->mode_ref_delta_update = 1;
-
-  vp9_zero(lf->ref_deltas);
-  vp9_zero(lf->mode_deltas);
-
-  // Test of ref frame deltas
-  lf->ref_deltas[INTRA_FRAME] = 2;
-  lf->ref_deltas[LAST_FRAME] = 0;
-  lf->ref_deltas[GOLDEN_FRAME] = -2;
-  lf->ref_deltas[ALTREF_FRAME] = -2;
-
-  lf->mode_deltas[0] = 0;   // Zero
-  lf->mode_deltas[1] = 0;   // New mv
-}
-
 static void set_rd_speed_thresholds(VP9_COMP *cpi, int mode) {
   SPEED_FEATURES *sf = &cpi->sf;
   int i;
@@ -626,6 +594,7 @@
 
 void vp9_set_speed_features(VP9_COMP *cpi) {
   SPEED_FEATURES *sf = &cpi->sf;
+  VP9_COMMON *cm = &cpi->common;
   int mode = cpi->compressor_speed;
   int speed = cpi->speed;
   int i;
@@ -654,6 +623,7 @@
   sf->tx_size_search_method = USE_FULL_RD;
   sf->use_lp32x32fdct = 0;
   sf->adaptive_motion_search = 0;
+  sf->adaptive_pred_filter_type = 0;
   sf->use_avoid_tested_higherror = 0;
   sf->reference_masking = 0;
   sf->use_one_partition_size_always = 0;
@@ -704,19 +674,20 @@
       sf->recode_loop = (speed < 1);
 
       if (speed == 1) {
-        sf->use_square_partition_only = !frame_is_intra_only(&cpi->common);
+        sf->use_square_partition_only = !frame_is_intra_only(cm);
         sf->less_rectangular_check  = 1;
-        sf->tx_size_search_method = frame_is_intra_only(&cpi->common)
+        sf->tx_size_search_method = frame_is_intra_only(cm)
                                      ? USE_FULL_RD : USE_LARGESTALL;
 
-        if (MIN(cpi->common.width, cpi->common.height) >= 720)
-          sf->disable_split_mask = cpi->common.show_frame ?
+        if (MIN(cm->width, cm->height) >= 720)
+          sf->disable_split_mask = cm->show_frame ?
               DISABLE_ALL_SPLIT : DISABLE_ALL_INTER_SPLIT;
         else
           sf->disable_split_mask = DISABLE_COMPOUND_SPLIT;
 
         sf->use_rd_breakout = 1;
         sf->adaptive_motion_search = 1;
+        sf->adaptive_pred_filter_type = 1;
         sf->auto_mv_step_size = 1;
         sf->adaptive_rd_thresh = 2;
         sf->recode_loop = 2;
@@ -725,13 +696,13 @@
         sf->intra_uv_mode_mask[TX_16X16] = INTRA_DC_H_V;
       }
       if (speed == 2) {
-        sf->use_square_partition_only = !frame_is_intra_only(&cpi->common);
+        sf->use_square_partition_only = !frame_is_intra_only(cm);
         sf->less_rectangular_check  = 1;
-        sf->tx_size_search_method = frame_is_intra_only(&cpi->common)
+        sf->tx_size_search_method = frame_is_intra_only(cm)
                                      ? USE_FULL_RD : USE_LARGESTALL;
 
-        if (MIN(cpi->common.width, cpi->common.height) >= 720)
-          sf->disable_split_mask = cpi->common.show_frame ?
+        if (MIN(cm->width, cm->height) >= 720)
+          sf->disable_split_mask = cm->show_frame ?
               DISABLE_ALL_SPLIT : DISABLE_ALL_INTER_SPLIT;
         else
           sf->disable_split_mask = LAST_AND_INTRA_SPLIT_ONLY;
@@ -744,9 +715,10 @@
 
         sf->use_rd_breakout = 1;
         sf->adaptive_motion_search = 1;
+        sf->adaptive_pred_filter_type = 2;
         sf->auto_mv_step_size = 1;
 
-        sf->disable_filter_search_var_thresh = 16;
+        sf->disable_filter_search_var_thresh = 50;
         sf->comp_inter_joint_search_thresh = BLOCK_SIZES;
 
         sf->auto_min_max_partition_size = 1;
@@ -767,7 +739,7 @@
         sf->use_square_partition_only = 1;
         sf->tx_size_search_method = USE_LARGESTALL;
 
-        if (MIN(cpi->common.width, cpi->common.height) >= 720)
+        if (MIN(cm->width, cm->height) >= 720)
           sf->disable_split_mask = DISABLE_ALL_SPLIT;
         else
           sf->disable_split_mask = DISABLE_ALL_INTER_SPLIT;
@@ -779,9 +751,10 @@
 
         sf->use_rd_breakout = 1;
         sf->adaptive_motion_search = 1;
+        sf->adaptive_pred_filter_type = 2;
         sf->auto_mv_step_size = 1;
 
-        sf->disable_filter_search_var_thresh = 16;
+        sf->disable_filter_search_var_thresh = 100;
         sf->comp_inter_joint_search_thresh = BLOCK_SIZES;
 
         sf->auto_min_max_partition_size = 1;
@@ -812,9 +785,10 @@
 
         sf->use_rd_breakout = 1;
         sf->adaptive_motion_search = 1;
+        sf->adaptive_pred_filter_type = 2;
         sf->auto_mv_step_size = 1;
 
-        sf->disable_filter_search_var_thresh = 16;
+        sf->disable_filter_search_var_thresh = 200;
         sf->comp_inter_joint_search_thresh = BLOCK_SIZES;
 
         sf->auto_min_max_partition_size = 1;
@@ -841,7 +815,7 @@
         sf->comp_inter_joint_search_thresh = BLOCK_SIZES;
         sf->use_one_partition_size_always = 1;
         sf->always_this_block_size = BLOCK_16X16;
-        sf->tx_size_search_method = frame_is_intra_only(&cpi->common) ?
+        sf->tx_size_search_method = frame_is_intra_only(cm) ?
                                      USE_FULL_RD : USE_LARGESTALL;
         sf->mode_search_skip_flags = FLAG_SKIP_INTRA_DIRMISMATCH |
                                      FLAG_SKIP_INTRA_BESTINTER |
@@ -860,7 +834,7 @@
         sf->search_method = HEX;
         sf->subpel_iters_per_step = 1;
         sf->disable_split_var_thresh = 64;
-        sf->disable_filter_search_var_thresh = 96;
+        sf->disable_filter_search_var_thresh = 500;
         for (i = 0; i < TX_SIZES; i++) {
           sf->intra_y_mode_mask[i] = INTRA_DC_ONLY;
           sf->intra_uv_mode_mask[i] = INTRA_DC_ONLY;
@@ -893,10 +867,7 @@
     cpi->mb.fwd_txm4x4 = vp9_fwht4x4;
   }
 
-  if (cpi->sf.subpel_search_method == SUBPEL_ITERATIVE) {
-    cpi->find_fractional_mv_step = vp9_find_best_sub_pixel_iterative;
-    cpi->find_fractional_mv_step_comp = vp9_find_best_sub_pixel_comp_iterative;
-  } else if (cpi->sf.subpel_search_method == SUBPEL_TREE) {
+  if (cpi->sf.subpel_search_method == SUBPEL_TREE) {
     cpi->find_fractional_mv_step = vp9_find_best_sub_pixel_tree;
     cpi->find_fractional_mv_step_comp = vp9_find_best_sub_pixel_comp_tree;
   }
@@ -915,14 +886,14 @@
                                       cm->subsampling_x, cm->subsampling_y,
                                       cpi->oxcf.lag_in_frames);
   if (!cpi->lookahead)
-    vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
+    vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
                        "Failed to allocate lag buffers");
 
   if (vp9_realloc_frame_buffer(&cpi->alt_ref_buffer,
                                cpi->oxcf.width, cpi->oxcf.height,
                                cm->subsampling_x, cm->subsampling_y,
-                               VP9BORDERINPIXELS))
-    vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
+                               VP9BORDERINPIXELS, NULL, NULL, NULL))
+    vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
                        "Failed to allocate altref buffer");
 }
 
@@ -930,21 +901,21 @@
   VP9_COMMON *cm = &cpi->common;
 
   if (vp9_alloc_frame_buffers(cm, cm->width, cm->height))
-    vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
+    vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
                        "Failed to allocate frame buffers");
 
   if (vp9_alloc_frame_buffer(&cpi->last_frame_uf,
                              cm->width, cm->height,
                              cm->subsampling_x, cm->subsampling_y,
                              VP9BORDERINPIXELS))
-    vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
+    vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
                        "Failed to allocate last frame buffer");
 
   if (vp9_alloc_frame_buffer(&cpi->scaled_source,
                              cm->width, cm->height,
                              cm->subsampling_x, cm->subsampling_y,
                              VP9BORDERINPIXELS))
-    vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
+    vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
                        "Failed to allocate scaled source buffer");
 
   vpx_free(cpi->tok);
@@ -989,15 +960,15 @@
   if (vp9_realloc_frame_buffer(&cpi->last_frame_uf,
                                cm->width, cm->height,
                                cm->subsampling_x, cm->subsampling_y,
-                               VP9BORDERINPIXELS))
-    vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
+                               VP9BORDERINPIXELS, NULL, NULL, NULL))
+    vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
                        "Failed to reallocate last frame buffer");
 
   if (vp9_realloc_frame_buffer(&cpi->scaled_source,
                                cm->width, cm->height,
                                cm->subsampling_x, cm->subsampling_y,
-                               VP9BORDERINPIXELS))
-    vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
+                               VP9BORDERINPIXELS, NULL, NULL, NULL))
+    vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
                        "Failed to reallocate scaled source buffer");
 
   {
@@ -1043,6 +1014,7 @@
 
   return 63;
 };
+
 void vp9_new_framerate(VP9_COMP *cpi, double framerate) {
   if (framerate < 0.1)
     framerate = 30;
@@ -1119,7 +1091,21 @@
   // Initialize active best and worst q and average q values.
   cpi->rc.active_worst_quality      = cpi->oxcf.worst_allowed_q;
 
-  cpi->rc.avg_frame_qindex          = cpi->oxcf.worst_allowed_q;
+  if (cpi->pass == 0 && cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) {
+    cpi->rc.avg_frame_qindex[0] = cpi->oxcf.worst_allowed_q;
+    cpi->rc.avg_frame_qindex[1] = cpi->oxcf.worst_allowed_q;
+    cpi->rc.avg_frame_qindex[2] = cpi->oxcf.worst_allowed_q;
+  } else {
+    cpi->rc.avg_frame_qindex[0] = (cpi->oxcf.worst_allowed_q +
+                                   cpi->oxcf.best_allowed_q) / 2;
+    cpi->rc.avg_frame_qindex[1] = (cpi->oxcf.worst_allowed_q +
+                                   cpi->oxcf.best_allowed_q) / 2;
+    cpi->rc.avg_frame_qindex[2] = (cpi->oxcf.worst_allowed_q +
+                                   cpi->oxcf.best_allowed_q) / 2;
+  }
+  cpi->rc.last_q[0]                 = cpi->oxcf.best_allowed_q;
+  cpi->rc.last_q[1]                 = cpi->oxcf.best_allowed_q;
+  cpi->rc.last_q[2]                 = cpi->oxcf.best_allowed_q;
 
   // Initialise the starting buffer levels
   cpi->rc.buffer_level              = cpi->oxcf.starting_buffer_level;
@@ -1206,7 +1192,7 @@
   cm->refresh_frame_context = 1;
   cm->reset_frame_context = 0;
 
-  setup_features(cm);
+  reset_segment_features(cm);
   set_high_precision_mv(cpi, 0);
 
   {
@@ -1283,6 +1269,7 @@
   if (cpi->oxcf.fixed_q >= 0) {
     cpi->rc.last_q[0] = cpi->oxcf.fixed_q;
     cpi->rc.last_q[1] = cpi->oxcf.fixed_q;
+    cpi->rc.last_q[2] = cpi->oxcf.fixed_q;
     cpi->rc.last_boosted_qindex = cpi->oxcf.fixed_q;
   }
 
@@ -1302,7 +1289,7 @@
 #else
   cpi->alt_ref_source = NULL;
 #endif
-  cpi->is_src_frame_alt_ref = 0;
+  cpi->rc.is_src_frame_alt_ref = 0;
 
 #if 0
   // Experimental RD Code
@@ -1562,14 +1549,14 @@
 
   /*Initialize the feed-forward activity masking.*/
   cpi->activity_avg = 90 << 12;
-
-  cpi->frames_since_key = 8;  // Sensible default for first frame.
   cpi->key_frame_frequency = cpi->oxcf.key_freq;
-  cpi->this_key_frame_forced = 0;
-  cpi->next_key_frame_forced = 0;
 
-  cpi->source_alt_ref_pending = 0;
-  cpi->source_alt_ref_active = 0;
+  cpi->rc.frames_since_key = 8;  // Sensible default for first frame.
+  cpi->rc.this_key_frame_forced = 0;
+  cpi->rc.next_key_frame_forced = 0;
+
+  cpi->rc.source_alt_ref_pending = 0;
+  cpi->rc.source_alt_ref_active = 0;
   cpi->refresh_alt_ref_frame = 0;
 
 #if CONFIG_MULTIPLE_ARF
@@ -1622,7 +1609,6 @@
   cpi->first_time_stamp_ever = INT64_MAX;
 
   cpi->rc.frames_till_gf_update_due      = 0;
-  cpi->rc.key_frame_count              = 1;
 
   cpi->rc.ni_av_qi                     = cpi->oxcf.worst_allowed_q;
   cpi->rc.ni_tot_qi                    = 0;
@@ -1647,9 +1633,6 @@
   cpi->mb.nmvsadcost_hp[1] = &cpi->mb.nmvsadcosts_hp[1][MV_MAX];
   cal_nmvsadcosts_hp(cpi->mb.nmvsadcost_hp);
 
-  for (i = 0; i < KEY_FRAME_CONTEXT; i++)
-    cpi->rc.prior_key_frame_distance[i] = (int)cpi->output_framerate;
-
 #ifdef OUTPUT_YUV_SRC
   yuv_file = fopen("bd.yuv", "ab");
 #endif
@@ -1785,7 +1768,7 @@
   cpi->refining_search_sad = vp9_refining_search_sad;
 
   // make sure frame 1 is okay
-  cpi->error_bins[0] = cpi->common.MBs;
+  cpi->error_bins[0] = cm->MBs;
 
   /* vp9_init_quantizer() is first called here. Add check in
    * vp9_frame_init_quantizer() so that vp9_init_quantizer is only
@@ -1796,9 +1779,9 @@
 
   vp9_loop_filter_init(cm);
 
-  cpi->common.error.setjmp = 0;
+  cm->error.setjmp = 0;
 
-  vp9_zero(cpi->y_uv_mode_count);
+  vp9_zero(cpi->common.counts.uv_mode);
 
 #ifdef MODE_TEST_HIT_STATS
   vp9_zero(cpi->mode_test_hits);
@@ -2105,6 +2088,7 @@
   cpi->ref_frame_flags = ref_frame_flags;
   return 0;
 }
+
 int vp9_update_reference(VP9_PTR ptr, int ref_frame_flags) {
   VP9_COMP *cpi = (VP9_COMP *)(ptr);
 
@@ -2178,6 +2162,7 @@
 
   return 0;
 }
+
 int vp9_update_entropy(VP9_PTR comp, int update) {
   ((VP9_COMP *)comp)->common.refresh_frame_context = update;
   return 0;
@@ -2304,11 +2289,12 @@
   if (!cpi->multi_arf_enabled)
 #endif
     // Clear the alternate reference update pending flag.
-    cpi->source_alt_ref_pending = 0;
+    cpi->rc.source_alt_ref_pending = 0;
 
   // Set the alternate reference frame active flag
-  cpi->source_alt_ref_active = 1;
+  cpi->rc.source_alt_ref_active = 1;
 }
+
 static void update_golden_frame_stats(VP9_COMP *cpi) {
   // Update the Golden frame usage counts.
   if (cpi->refresh_golden_frame) {
@@ -2321,18 +2307,12 @@
     // set a flag to say so.
     if (cpi->oxcf.fixed_q >= 0 &&
         cpi->oxcf.play_alternate && !cpi->refresh_alt_ref_frame) {
-      cpi->source_alt_ref_pending = 1;
+      cpi->rc.source_alt_ref_pending = 1;
       cpi->rc.frames_till_gf_update_due = cpi->rc.baseline_gf_interval;
-
-      // TODO(ivan): For SVC encoder, GF automatic update is disabled by using
-      // a large GF_interval.
-      if (cpi->use_svc) {
-        cpi->rc.frames_till_gf_update_due = INT_MAX;
-      }
     }
 
-    if (!cpi->source_alt_ref_pending)
-      cpi->source_alt_ref_active = 0;
+    if (!cpi->rc.source_alt_ref_pending)
+      cpi->rc.source_alt_ref_active = 0;
 
     // Decrement count down till next gf
     if (cpi->rc.frames_till_gf_update_due > 0)
@@ -2343,9 +2323,6 @@
     if (cpi->rc.frames_till_gf_update_due > 0)
       cpi->rc.frames_till_gf_update_due--;
 
-    if (cpi->frames_till_alt_ref_frame)
-      cpi->frames_till_alt_ref_frame--;
-
     cpi->rc.frames_since_golden++;
   }
 }
@@ -2564,7 +2541,7 @@
       vp9_realloc_frame_buffer(&cm->yv12_fb[new_fb],
                                cm->width, cm->height,
                                cm->subsampling_x, cm->subsampling_y,
-                               VP9BORDERINPIXELS);
+                               VP9BORDERINPIXELS, NULL, NULL, NULL);
       scale_and_extend_frame(ref, &cm->yv12_fb[new_fb]);
       cpi->scaled_ref_idx[i] = new_fb;
     } else {
@@ -2637,7 +2614,7 @@
         (double)cpi->twopass.bits_left /
             (1 + cpi->twopass.total_left_stats.coded_error),
         cpi->tot_recode_hits, recon_err, cpi->rc.kf_boost,
-        cpi->kf_zeromotion_pct);
+        cpi->twopass.kf_zeromotion_pct);
 
   fclose(f);
 
@@ -2662,7 +2639,7 @@
 #endif
 
 static void encode_with_recode_loop(VP9_COMP *cpi,
-                                    unsigned long *size,
+                                    size_t *size,
                                     uint8_t *dest,
                                     int *q,
                                     int bottom_index,
@@ -2731,7 +2708,7 @@
       loop = 0;
     } else {
       // Special case handling for forced key frames
-      if ((cm->frame_type == KEY_FRAME) && cpi->this_key_frame_forced) {
+      if ((cm->frame_type == KEY_FRAME) && cpi->rc.this_key_frame_forced) {
         int last_q = *q;
         int kf_err = vp9_calc_ss_err(cpi->Source, get_frame_new_buffer(cm));
 
@@ -2845,7 +2822,7 @@
       }
     }
 
-    if (cpi->is_src_frame_alt_ref)
+    if (cpi->rc.is_src_frame_alt_ref)
       loop = 0;
 
     if (loop) {
@@ -2858,8 +2835,36 @@
   } while (loop);
 }
 
+static void get_ref_frame_flags(VP9_COMP *cpi) {
+  if (cpi->refresh_last_frame & cpi->refresh_golden_frame)
+    cpi->gold_is_last = 1;
+  else if (cpi->refresh_last_frame ^ cpi->refresh_golden_frame)
+    cpi->gold_is_last = 0;
+
+  if (cpi->refresh_last_frame & cpi->refresh_alt_ref_frame)
+    cpi->alt_is_last = 1;
+  else if (cpi->refresh_last_frame ^ cpi->refresh_alt_ref_frame)
+    cpi->alt_is_last = 0;
+
+  if (cpi->refresh_alt_ref_frame & cpi->refresh_golden_frame)
+    cpi->gold_is_alt = 1;
+  else if (cpi->refresh_alt_ref_frame ^ cpi->refresh_golden_frame)
+    cpi->gold_is_alt = 0;
+
+  cpi->ref_frame_flags = VP9_ALT_FLAG | VP9_GOLD_FLAG | VP9_LAST_FLAG;
+
+  if (cpi->gold_is_last)
+    cpi->ref_frame_flags &= ~VP9_GOLD_FLAG;
+
+  if (cpi->alt_is_last)
+    cpi->ref_frame_flags &= ~VP9_ALT_FLAG;
+
+  if (cpi->gold_is_alt)
+    cpi->ref_frame_flags &= ~VP9_ALT_FLAG;
+}
+
 static void encode_frame_to_data_rate(VP9_COMP *cpi,
-                                      unsigned long *size,
+                                      size_t *size,
                                       uint8_t *dest,
                                       unsigned int *frame_flags) {
   VP9_COMMON *const cm = &cpi->common;
@@ -2868,7 +2873,6 @@
   int frame_over_shoot_limit;
   int frame_under_shoot_limit;
   int top_index;
-  int top_index_prop;
   int bottom_index;
 
   SPEED_FEATURES *const sf = &cpi->sf;
@@ -2907,14 +2911,14 @@
   cpi->zbin_mode_boost_enabled = 0;
 
   // Current default encoder behavior for the altref sign bias.
-  cpi->common.ref_frame_sign_bias[ALTREF_FRAME] = cpi->source_alt_ref_active;
+  cpi->common.ref_frame_sign_bias[ALTREF_FRAME] = cpi->rc.source_alt_ref_active;
 
   // Check to see if a key frame is signaled.
   // For two pass with auto key frame enabled cm->frame_type may already be
   // set, but not for one pass.
   if ((cm->current_video_frame == 0) ||
       (cm->frame_flags & FRAMEFLAGS_KEY) ||
-      (cpi->oxcf.auto_key && (cpi->frames_since_key %
+      (cpi->oxcf.auto_key && (cpi->rc.frames_since_key %
                               cpi->key_frame_frequency == 0))) {
     // Set frame type to key frame for the force key frame, if we exceed the
     // maximum distance in an automatic keyframe selection or for the first
@@ -2948,7 +2952,7 @@
   if (frame_is_intra_only(cm)) {
     vp9_setup_key_frame(cpi);
     // Reset the loop filter deltas and segmentation map.
-    setup_features(cm);
+    reset_segment_features(cm);
 
     // If segmentation is enabled force a map update for key frames.
     if (seg->enabled) {
@@ -2957,7 +2961,7 @@
     }
 
     // The alternate reference frame cannot be active for a key frame.
-    cpi->source_alt_ref_active = 0;
+    cpi->rc.source_alt_ref_active = 0;
 
     cm->error_resilient_mode = (cpi->oxcf.error_resilient_mode != 0);
     cm->frame_parallel_decoding_mode =
@@ -2980,6 +2984,20 @@
     configure_static_seg_features(cpi);
   }
 
+  // For 1 pass CBR, check if we are dropping this frame.
+  // Never drop on key frame.
+  if (cpi->pass == 0 &&
+      cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER &&
+      cm->frame_type != KEY_FRAME) {
+    if (vp9_drop_frame(cpi)) {
+      // Update buffer level with zero size, update frame counters, and return.
+      vp9_update_buffer_level(cpi, 0);
+      cm->current_video_frame++;
+      cpi->rc.frames_since_key++;
+      return;
+    }
+  }
+
   vp9_clear_system_state();
 
   vp9_zero(cpi->rd_tx_select_threshes);
@@ -3024,8 +3042,7 @@
   // Decide q and q bounds
   q = vp9_rc_pick_q_and_adjust_q_bounds(cpi,
                                         &bottom_index,
-                                        &top_index,
-                                        &top_index_prop);
+                                        &top_index);
 
   if (!frame_is_intra_only(cm)) {
     cm->mcomp_filter_type = DEFAULT_INTERP_FILTER;
@@ -3045,7 +3062,7 @@
   // Special case code to reduce pulsing when key frames are forced at a
   // fixed interval. Note the reconstruction error if it is the frame before
   // the force key frame
-  if (cpi->next_key_frame_forced && (cpi->twopass.frames_to_key == 0)) {
+  if (cpi->rc.next_key_frame_forced && (cpi->rc.frames_to_key == 0)) {
     cpi->ambient_err = vp9_calc_ss_err(cpi->Source, get_frame_new_buffer(cm));
   }
 
@@ -3094,15 +3111,6 @@
   }
 
   if (!frame_is_intra_only(&cpi->common)) {
-    FRAME_COUNTS *counts = &cpi->common.counts;
-
-    vp9_copy(counts->y_mode, cpi->y_mode_count);
-    vp9_copy(counts->uv_mode, cpi->y_uv_mode_count);
-    vp9_copy(counts->intra_inter, cpi->intra_inter_count);
-    vp9_copy(counts->comp_inter, cpi->comp_inter_count);
-    vp9_copy(counts->single_ref, cpi->single_ref_count);
-    vp9_copy(counts->comp_ref, cpi->comp_ref_count);
-    counts->mv = cpi->NMVcount;
     if (!cpi->common.error_resilient_mode &&
         !cpi->common.frame_parallel_decoding_mode) {
       vp9_adapt_mode_probs(&cpi->common);
@@ -3118,7 +3126,7 @@
    * needed in motion search besides loopfilter */
   cm->last_frame_type = cm->frame_type;
 
-  vp9_rc_postencode_update(cpi, *size, top_index_prop);
+  vp9_rc_postencode_update(cpi, *size);
 
 #if 0
   output_frame_level_debug_stats(cpi);
@@ -3133,32 +3141,7 @@
   else
     cm->frame_flags = cm->frame_flags&~FRAMEFLAGS_ALTREF;
 
-
-  if (cpi->refresh_last_frame & cpi->refresh_golden_frame)
-    cpi->gold_is_last = 1;
-  else if (cpi->refresh_last_frame ^ cpi->refresh_golden_frame)
-    cpi->gold_is_last = 0;
-
-  if (cpi->refresh_last_frame & cpi->refresh_alt_ref_frame)
-    cpi->alt_is_last = 1;
-  else if (cpi->refresh_last_frame ^ cpi->refresh_alt_ref_frame)
-    cpi->alt_is_last = 0;
-
-  if (cpi->refresh_alt_ref_frame & cpi->refresh_golden_frame)
-    cpi->gold_is_alt = 1;
-  else if (cpi->refresh_alt_ref_frame ^ cpi->refresh_golden_frame)
-    cpi->gold_is_alt = 0;
-
-  cpi->ref_frame_flags = VP9_ALT_FLAG | VP9_GOLD_FLAG | VP9_LAST_FLAG;
-
-  if (cpi->gold_is_last)
-    cpi->ref_frame_flags &= ~VP9_GOLD_FLAG;
-
-  if (cpi->alt_is_last)
-    cpi->ref_frame_flags &= ~VP9_ALT_FLAG;
-
-  if (cpi->gold_is_alt)
-    cpi->ref_frame_flags &= ~VP9_ALT_FLAG;
+  get_ref_frame_flags(cpi);
 
   if (cpi->oxcf.play_alternate && cpi->refresh_alt_ref_frame
       && (cm->frame_type != KEY_FRAME))
@@ -3183,6 +3166,8 @@
 
     // As this frame is a key frame the next defaults to an inter frame.
     cm->frame_type = INTER_FRAME;
+    vp9_clear_system_state();
+    cpi->rc.frames_since_key = 0;
   } else {
     *frame_flags = cm->frame_flags&~FRAMEFLAGS_KEY;
 
@@ -3232,35 +3217,41 @@
     // Don't increment frame counters if this was an altref buffer
     // update not a real frame
     ++cm->current_video_frame;
-    ++cpi->frames_since_key;
+    ++cpi->rc.frames_since_key;
   }
   // restore prev_mi
   cm->prev_mi = cm->prev_mip + cm->mode_info_stride + 1;
   cm->prev_mi_grid_visible = cm->prev_mi_grid_base + cm->mode_info_stride + 1;
 }
 
-static void Pass0Encode(VP9_COMP *cpi, unsigned long *size, unsigned char *dest,
-                        unsigned int *frame_flags) {
+static void SvcEncode(VP9_COMP *cpi, size_t *size, uint8_t *dest,
+                      unsigned int *frame_flags) {
+  vp9_get_svc_params(cpi);
   encode_frame_to_data_rate(cpi, size, dest, frame_flags);
 }
 
-static void Pass1Encode(VP9_COMP *cpi, unsigned long *size, unsigned char *dest,
+static void Pass0Encode(VP9_COMP *cpi, size_t *size, uint8_t *dest,
+                        unsigned int *frame_flags) {
+  vp9_get_one_pass_params(cpi);
+  encode_frame_to_data_rate(cpi, size, dest, frame_flags);
+}
+
+static void Pass1Encode(VP9_COMP *cpi, size_t *size, uint8_t *dest,
                         unsigned int *frame_flags) {
   (void) size;
   (void) dest;
   (void) frame_flags;
 
+  vp9_get_first_pass_params(cpi);
   vp9_set_quantizer(cpi, find_fp_qindex());
   vp9_first_pass(cpi);
 }
 
-static void Pass2Encode(VP9_COMP *cpi, unsigned long *size,
-                        unsigned char *dest, unsigned int *frame_flags) {
+static void Pass2Encode(VP9_COMP *cpi, size_t *size,
+                        uint8_t *dest, unsigned int *frame_flags) {
   cpi->enable_encode_breakout = 1;
 
-  if (!cpi->refresh_alt_ref_frame)
-    vp9_second_pass(cpi);
-
+  vp9_get_second_pass_params(cpi);
   encode_frame_to_data_rate(cpi, size, dest, frame_flags);
   // vp9_print_modes_and_motion_vectors(&cpi->common, "encode.stt");
 
@@ -3320,7 +3311,7 @@
 #endif
 
 int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags,
-                            unsigned long *size, unsigned char *dest,
+                            size_t *size, uint8_t *dest,
                             int64_t *time_stamp, int64_t *time_end, int flush) {
   VP9_COMP *cpi = (VP9_COMP *) ptr;
   VP9_COMMON *cm = &cpi->common;
@@ -3339,7 +3330,7 @@
   set_high_precision_mv(cpi, ALTREF_HIGH_PRECISION_MV);
 
   // Should we code an alternate reference frame.
-  if (cpi->oxcf.play_alternate && cpi->source_alt_ref_pending) {
+  if (cpi->oxcf.play_alternate && cpi->rc.source_alt_ref_pending) {
     int frames_to_arf;
 
 #if CONFIG_MULTIPLE_ARF
@@ -3353,7 +3344,7 @@
 #endif
       frames_to_arf = cpi->rc.frames_till_gf_update_due;
 
-    assert(frames_to_arf < cpi->twopass.frames_to_key);
+    assert(frames_to_arf < cpi->rc.frames_to_key);
 
     if ((cpi->source = vp9_lookahead_peek(cpi->lookahead, frames_to_arf))) {
 #if CONFIG_MULTIPLE_ARF
@@ -3377,15 +3368,12 @@
       cpi->refresh_alt_ref_frame = 1;
       cpi->refresh_golden_frame = 0;
       cpi->refresh_last_frame = 0;
-      cpi->is_src_frame_alt_ref = 0;
-
-      // TODO(agrange) This needs to vary depending on where the next ARF is.
-      cpi->frames_till_alt_ref_frame = frames_to_arf;
+      cpi->rc.is_src_frame_alt_ref = 0;
 
 #if CONFIG_MULTIPLE_ARF
       if (!cpi->multi_arf_enabled)
 #endif
-        cpi->source_alt_ref_pending = 0;   // Clear Pending altf Ref flag.
+        cpi->rc.source_alt_ref_pending = 0;   // Clear Pending altf Ref flag.
     }
   }
 
@@ -3399,19 +3387,19 @@
 
 #if CONFIG_MULTIPLE_ARF
       // Is this frame the ARF overlay.
-      cpi->is_src_frame_alt_ref = 0;
+      cpi->rc.is_src_frame_alt_ref = 0;
       for (i = 0; i < cpi->arf_buffered; ++i) {
         if (cpi->source == cpi->alt_ref_source[i]) {
-          cpi->is_src_frame_alt_ref = 1;
+          cpi->rc.is_src_frame_alt_ref = 1;
           cpi->refresh_golden_frame = 1;
           break;
         }
       }
 #else
-      cpi->is_src_frame_alt_ref = cpi->alt_ref_source
-                                  && (cpi->source == cpi->alt_ref_source);
+      cpi->rc.is_src_frame_alt_ref = cpi->alt_ref_source
+          && (cpi->source == cpi->alt_ref_source);
 #endif
-      if (cpi->is_src_frame_alt_ref) {
+      if (cpi->rc.is_src_frame_alt_ref) {
         // Current frame is an ARF overlay frame.
 #if CONFIG_MULTIPLE_ARF
         cpi->alt_ref_source[i] = NULL;
@@ -3449,7 +3437,7 @@
 
 #if CONFIG_MULTIPLE_ARF
     if ((cm->frame_type != KEY_FRAME) && (cpi->pass == 2))
-      cpi->source_alt_ref_pending = is_next_frame_arf(cpi);
+      cpi->rc.source_alt_ref_pending = is_next_frame_arf(cpi);
 #endif
   } else {
     *size = 0;
@@ -3542,25 +3530,24 @@
         cm->active_ref_idx[0], cm->active_ref_idx[1], cm->active_ref_idx[2]);
     if (cpi->refresh_alt_ref_frame)
       fprintf(fp_out, "  type:ARF");
-    if (cpi->is_src_frame_alt_ref)
+    if (cpi->rc.is_src_frame_alt_ref)
       fprintf(fp_out, "  type:OVERLAY[%d]", cpi->alt_fb_idx);
     fprintf(fp_out, "\n");
   }
 #endif
 
-  cm->frame_type = INTER_FRAME;
   cm->frame_flags = *frame_flags;
 
   // Reset the frame pointers to the current frame size
   vp9_realloc_frame_buffer(get_frame_new_buffer(cm),
                            cm->width, cm->height,
                            cm->subsampling_x, cm->subsampling_y,
-                           VP9BORDERINPIXELS);
+                           VP9BORDERINPIXELS, NULL, NULL, NULL);
 
   // Calculate scaling factors for each of the 3 available references
   for (i = 0; i < REFS_PER_FRAME; ++i) {
     vp9_setup_scale_factors(cm, i);
-    if (vp9_is_scaled(&cm->active_ref_scale_comm[i]))
+    if (vp9_is_scaled(&cm->active_ref_scale[i]))
       vp9_extend_frame_borders(&cm->yv12_fb[cm->active_ref_idx[i]],
                                cm->subsampling_x, cm->subsampling_y);
   }
@@ -3571,7 +3558,9 @@
       vp9_vaq_init();
   }
 
-  if (cpi->pass == 1) {
+  if (cpi->use_svc) {
+    SvcEncode(cpi, size, dest, frame_flags);
+  } else if (cpi->pass == 1) {
     Pass1Encode(cpi, size, dest, frame_flags);
   } else if (cpi->pass == 2) {
     Pass2Encode(cpi, size, dest, frame_flags);
@@ -3583,6 +3572,11 @@
   if (cm->refresh_frame_context)
     cm->frame_contexts[cm->frame_context_idx] = cm->fc;
 
+  // Frame was dropped, release scaled references.
+  if (*size == 0) {
+    release_scaled_references(cpi);
+  }
+
   if (*size > 0) {
     // if its a dropped frame honor the requests on subsequent frames
     cpi->droppable = !frame_is_reference(cpi);
@@ -3593,7 +3587,6 @@
     cpi->refresh_alt_ref_frame = 0;
     cpi->refresh_golden_frame = 0;
     cpi->refresh_last_frame = 1;
-    cm->frame_type = INTER_FRAME;
   }
 
   vpx_usec_timer_mark(&cmptimer);
diff --git a/vp9/encoder/vp9_onyx_int.h b/vp9/encoder/vp9_onyx_int.h
index 72e9196..f5b6562 100644
--- a/vp9/encoder/vp9_onyx_int.h
+++ b/vp9/encoder/vp9_onyx_int.h
@@ -26,7 +26,6 @@
 #include "vpx_ports/mem.h"
 #include "vpx/internal/vpx_codec_internal.h"
 #include "vp9/encoder/vp9_mcomp.h"
-#include "vp9/common/vp9_findnearmv.h"
 #include "vp9/encoder/vp9_lookahead.h"
 
 #define DISABLE_RC_LONG_TERM_MEM 0
@@ -216,8 +215,7 @@
 } MODE_SEARCH_SKIP_LOGIC;
 
 typedef enum {
-  SUBPEL_ITERATIVE = 0,
-  SUBPEL_TREE = 1,
+  SUBPEL_TREE = 0,
   // Other methods to come
 } SUBPEL_SEARCH_METHODS;
 
@@ -270,6 +268,7 @@
   int using_small_partition_info;
   // TODO(jingning): combine the related motion search speed features
   int adaptive_motion_search;
+  int adaptive_pred_filter_type;
 
   // Implements various heuristics to skip searching modes
   // The heuristics selected are based on  flags
@@ -293,7 +292,7 @@
   int this_frame_target;
   int projected_frame_size;
   int sb64_target_rate;
-  int last_q[2];                   // Separate values for Intra/Inter
+  int last_q[3];                   // Separate values for Intra/Inter/ARF-GF
   int last_boosted_qindex;         // Last boosted GF/KF/ARF q
 
   int gfu_boost;
@@ -305,13 +304,17 @@
   double gf_rate_correction_factor;
 
   unsigned int frames_since_golden;
-  int frames_till_gf_update_due;  // Count down till next GF
+  unsigned int frames_till_gf_update_due;  // Count down till next GF
+  unsigned int max_gf_interval;
+  unsigned int baseline_gf_interval;
+  unsigned int frames_to_key;
+  unsigned int frames_since_key;
+  unsigned int this_key_frame_forced;
+  unsigned int next_key_frame_forced;
+  unsigned int source_alt_ref_pending;
+  unsigned int source_alt_ref_active;
+  unsigned int is_src_frame_alt_ref;
 
-  int max_gf_interval;
-  int baseline_gf_interval;
-
-  int64_t key_frame_count;
-  int prior_key_frame_distance[KEY_FRAME_CONTEXT];
   int per_frame_bandwidth;  // Current section per frame bandwidth target
   int av_per_frame_bandwidth;  // Average frame size target for clip
   int min_frame_bandwidth;  // Minimum allocation used for any frame
@@ -319,13 +322,16 @@
   int ni_av_qi;
   int ni_tot_qi;
   int ni_frames;
-  int avg_frame_qindex;
+  int avg_frame_qindex[3];  // 0 - KEY, 1 - INTER, 2 - ARF/GF
   double tot_q;
   double avg_q;
 
   int buffer_level;
   int bits_off_target;
 
+  int decimation_factor;
+  int decimation_count;
+
   int rolling_target_bits;
   int rolling_actual_bits;
 
@@ -375,11 +381,7 @@
   YV12_BUFFER_CONFIG *un_scaled_source;
   YV12_BUFFER_CONFIG scaled_source;
 
-  unsigned int frames_till_alt_ref_frame;
-  int source_alt_ref_pending;
-  int source_alt_ref_active;
-
-  int is_src_frame_alt_ref;
+  unsigned int key_frame_frequency;
 
   int gold_is_last;  // gold same as last frame ( short circuit gold searches)
   int alt_is_last;  // Alt same as last ( short circuit altref search)
@@ -404,11 +406,6 @@
   TOKENEXTRA *tok;
   unsigned int tok_count[4][1 << 6];
 
-
-  unsigned int frames_since_key;
-  unsigned int key_frame_frequency;
-  unsigned int this_key_frame_forced;
-  unsigned int next_key_frame_forced;
 #if CONFIG_MULTIPLE_ARF
   // Position within a frame coding order (including any additional ARF frames).
   unsigned int sequence_number;
@@ -432,11 +429,6 @@
 
   int64_t rd_comp_pred_diff[REFERENCE_MODES];
   int64_t rd_prediction_type_threshes[4][REFERENCE_MODES];
-  unsigned int intra_inter_count[INTRA_INTER_CONTEXTS][2];
-  unsigned int comp_inter_count[COMP_INTER_CONTEXTS][2];
-  unsigned int single_ref_count[REF_CONTEXTS][2][2];
-  unsigned int comp_ref_count[REF_CONTEXTS][2];
-
   int64_t rd_tx_select_diff[TX_MODES];
   // FIXME(rbultje) can this overflow?
   int rd_tx_select_threshes[4][TX_MODES];
@@ -444,6 +436,7 @@
   int64_t rd_filter_diff[SWITCHABLE_FILTER_CONTEXTS];
   int64_t rd_filter_threshes[4][SWITCHABLE_FILTER_CONTEXTS];
   int64_t rd_filter_cache[SWITCHABLE_FILTER_CONTEXTS];
+  int64_t mask_filter_rd;
 
   int RDMULT;
   int RDDIV;
@@ -464,18 +457,10 @@
 
   int cq_target_quality;
 
-  int y_mode_count[4][INTRA_MODES];
-  int y_uv_mode_count[INTRA_MODES][INTRA_MODES];
-
-  nmv_context_counts NMVcount;
-
   vp9_coeff_count coef_counts[TX_SIZES][PLANE_TYPES];
   vp9_coeff_probs_model frame_coef_probs[TX_SIZES][PLANE_TYPES];
   vp9_coeff_stats frame_branch_ct[TX_SIZES][PLANE_TYPES];
 
-  int kf_zeromotion_pct;
-  int gf_zeromotion_pct;
-
   int64_t target_bandwidth;
   struct vpx_codec_pkt_list  *output_pkt_list;
 
@@ -489,9 +474,6 @@
   int static_mb_pct;                // % forced skip mbs by segmentation
   int seg0_progress, seg0_idx, seg0_cnt;
 
-  int decimation_factor;
-  int decimation_count;
-
   // for real time encoding
   int speed;
   int compressor_speed;
@@ -544,11 +526,9 @@
     int64_t clip_bits_total;
     double avg_iiratio;
     double modified_error_total;
-    double modified_error_used;
     double modified_error_left;
     double kf_intra_err_min;
     double gf_intra_err_min;
-    int frames_to_key;
     int maxq_max_limit;
     int maxq_min_limit;
     int static_scene_max_gf_interval;
@@ -569,6 +549,9 @@
     int alt_extra_bits;
 
     int sr_update_lag;
+
+    int kf_zeromotion_pct;
+    int gf_zeromotion_pct;
   } twopass;
 
   YV12_BUFFER_CONFIG alt_ref_buffer;
@@ -683,8 +666,7 @@
 
 void vp9_encode_frame(VP9_COMP *cpi);
 
-void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest,
-                        unsigned long *size);
+void vp9_pack_bitstream(VP9_COMP *cpi, uint8_t *dest, size_t *size);
 
 void vp9_activity_masking(VP9_COMP *cpi, MACROBLOCK *x);
 
diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c
index 3fa8cea..8a0dd4c 100644
--- a/vp9/encoder/vp9_ratectrl.c
+++ b/vp9/encoder/vp9_ratectrl.c
@@ -34,9 +34,6 @@
 // Bits Per MB at different Q (Multiplied by 512)
 #define BPER_MB_NORMBITS    9
 
-static const unsigned int prior_key_frame_weight[KEY_FRAME_CONTEXT] =
-    { 1, 2, 3, 4, 5 };
-
 // Tables relating active max Q to active min Q
 static int kf_low_motion_minq[QINDEX_RANGE];
 static int kf_high_motion_minq[QINDEX_RANGE];
@@ -225,6 +222,31 @@
   // New Two pass RC
   target = cpi->rc.per_frame_bandwidth;
 
+  // For 1-pass.
+  if (cpi->pass == 0) {
+    if (cpi->common.current_video_frame == 0) {
+      target = cpi->oxcf.starting_buffer_level / 2;
+    } else {
+      // TODO(marpan): Add in adjustment based on Q.
+      // If this keyframe was forced, use a more recent Q estimate.
+      // int Q = (cpi->common.frame_flags & FRAMEFLAGS_KEY) ?
+      //    cpi->rc.avg_frame_qindex : cpi->rc.ni_av_qi;
+      int initial_boost = 32;
+      // Boost depends somewhat on frame rate.
+      int kf_boost = MAX(initial_boost, (int)(2 * cpi->output_framerate - 16));
+      // Adjustment up based on q: need to fix.
+      // kf_boost = kf_boost * kfboost_qadjust(Q) / 100;
+      // Frame separation adjustment (down).
+      if (cpi->rc.frames_since_key  < cpi->output_framerate / 2) {
+        kf_boost = (int)(kf_boost * cpi->rc.frames_since_key /
+            (cpi->output_framerate / 2));
+      }
+      kf_boost = (kf_boost < 16) ? 16 : kf_boost;
+      target = ((16 + kf_boost) * cpi->rc.per_frame_bandwidth) >> 4;
+    }
+    cpi->rc.active_worst_quality = cpi->rc.worst_quality;
+  }
+
   if (cpi->oxcf.rc_max_intra_bitrate_pct) {
     int max_rate = cpi->rc.per_frame_bandwidth
                  * cpi->oxcf.rc_max_intra_bitrate_pct / 100;
@@ -245,18 +267,154 @@
   cpi->rc.frames_till_gf_update_due = cpi->rc.baseline_gf_interval;
 }
 
+// Update the buffer level: leaky bucket model.
+void vp9_update_buffer_level(VP9_COMP *const cpi, int encoded_frame_size) {
+  VP9_COMMON *const cm = &cpi->common;
+  // Non-viewable frames are a special case and are treated as pure overhead.
+  if (!cm->show_frame) {
+    cpi->rc.bits_off_target -= encoded_frame_size;
+  } else {
+    cpi->rc.bits_off_target += cpi->rc.av_per_frame_bandwidth -
+        encoded_frame_size;
+  }
+  // Clip the buffer level to the maximum specified buffer size.
+  if (cpi->rc.bits_off_target > cpi->oxcf.maximum_buffer_size) {
+    cpi->rc.bits_off_target = cpi->oxcf.maximum_buffer_size;
+  }
+  cpi->rc.buffer_level = cpi->rc.bits_off_target;
+}
 
-static void calc_pframe_target_size(VP9_COMP *cpi) {
-  const int min_frame_target = MAX(cpi->rc.min_frame_bandwidth,
-                                   cpi->rc.av_per_frame_bandwidth >> 5);
+int vp9_drop_frame(VP9_COMP *const cpi) {
+  if (!cpi->oxcf.drop_frames_water_mark) {
+    return 0;
+  } else {
+    if (cpi->rc.buffer_level < 0) {
+      // Always drop if buffer is below 0.
+      return 1;
+    } else {
+      // If buffer is below drop_mark, for now just drop every other frame
+      // (starting with the next frame) until it increases back over drop_mark.
+      int drop_mark = (int)(cpi->oxcf.drop_frames_water_mark *
+          cpi->oxcf.optimal_buffer_level / 100);
+      if ((cpi->rc.buffer_level > drop_mark) &&
+          (cpi->rc.decimation_factor > 0)) {
+        --cpi->rc.decimation_factor;
+      } else if (cpi->rc.buffer_level <= drop_mark &&
+          cpi->rc.decimation_factor == 0) {
+        cpi->rc.decimation_factor = 1;
+      }
+      if (cpi->rc.decimation_factor > 0) {
+        if (cpi->rc.decimation_count > 0) {
+          --cpi->rc.decimation_count;
+          return 1;
+        } else {
+          cpi->rc.decimation_count = cpi->rc.decimation_factor;
+          return 0;
+        }
+      } else {
+        cpi->rc.decimation_count = 0;
+        return 0;
+      }
+    }
+  }
+}
+
+// Adjust active_worst_quality level based on buffer level.
+static int adjust_active_worst_quality_from_buffer_level(const VP9_COMP *cpi) {
+  // Adjust active_worst_quality: If buffer is above the optimal/target level,
+  // bring active_worst_quality down depending on fullness over buffer.
+  // If buffer is below the optimal level, let the active_worst_quality go from
+  // ambient Q (at buffer = optimal level) to worst_quality level
+  // (at buffer = critical level).
+  int active_worst_quality = cpi->rc.active_worst_quality;
+  // Maximum limit for down adjustment, ~20%.
+  int max_adjustment_down = active_worst_quality / 5;
+  // Buffer level below which we push active_worst to worst_quality.
+  int critical_level = cpi->oxcf.optimal_buffer_level >> 2;
+  int adjustment = 0;
+  int buff_lvl_step = 0;
+  if (cpi->rc.buffer_level > cpi->oxcf.optimal_buffer_level) {
+    // Adjust down.
+    if (max_adjustment_down) {
+      buff_lvl_step = (int)((cpi->oxcf.maximum_buffer_size -
+          cpi->oxcf.optimal_buffer_level) / max_adjustment_down);
+      if (buff_lvl_step) {
+        adjustment = (int)((cpi->rc.buffer_level -
+            cpi->oxcf.optimal_buffer_level) / buff_lvl_step);
+      }
+      active_worst_quality -= adjustment;
+    }
+  } else if (cpi->rc.buffer_level > critical_level) {
+    // Adjust up from ambient Q.
+    if (critical_level) {
+      buff_lvl_step = (cpi->oxcf.optimal_buffer_level - critical_level);
+      if (buff_lvl_step) {
+        adjustment =
+            (cpi->rc.worst_quality - cpi->rc.avg_frame_qindex[INTER_FRAME]) *
+            (cpi->oxcf.optimal_buffer_level - cpi->rc.buffer_level) /
+            buff_lvl_step;
+      }
+      active_worst_quality = cpi->rc.avg_frame_qindex[INTER_FRAME] + adjustment;
+    }
+  } else {
+    // Set to worst_quality if buffer is below critical level.
+    active_worst_quality = cpi->rc.worst_quality;
+  }
+  return active_worst_quality;
+}
+
+// Adjust target frame size with respect to the buffering constraints:
+static int target_size_from_buffer_level(const VP9_COMP *cpi) {
+  int this_frame_target = cpi->rc.this_frame_target;
+  int percent_low = 0;
+  int percent_high = 0;
+  int one_percent_bits = (int)(1 + cpi->oxcf.optimal_buffer_level / 100);
+  if (cpi->rc.buffer_level < cpi->oxcf.optimal_buffer_level) {
+    percent_low = (int)((cpi->oxcf.optimal_buffer_level - cpi->rc.buffer_level)
+        / one_percent_bits);
+    if (percent_low > cpi->oxcf.under_shoot_pct) {
+      percent_low = cpi->oxcf.under_shoot_pct;
+    } else if (percent_low < 0) {
+      percent_low = 0;
+    }
+    // Lower the target bandwidth for this frame.
+    this_frame_target -= (this_frame_target * percent_low) / 200;
+  } else  if (cpi->rc.buffer_level > cpi->oxcf.optimal_buffer_level) {
+    percent_high = (int)((cpi->rc.buffer_level - cpi->oxcf.optimal_buffer_level)
+        / one_percent_bits);
+    if (percent_high > cpi->oxcf.over_shoot_pct) {
+      percent_high = cpi->oxcf.over_shoot_pct;
+    } else if (percent_high < 0) {
+      percent_high = 0;
+    }
+    // Increase the target bandwidth for this frame.
+    this_frame_target += (this_frame_target * percent_high) / 200;
+  }
+  return this_frame_target;
+}
+
+static void calc_pframe_target_size(VP9_COMP *const cpi) {
+  int min_frame_target = MAX(cpi->rc.min_frame_bandwidth,
+                             cpi->rc.av_per_frame_bandwidth >> 5);
   if (cpi->refresh_alt_ref_frame) {
     // Special alt reference frame case
     // Per frame bit target for the alt ref frame
     cpi->rc.per_frame_bandwidth = cpi->twopass.gf_bits;
     cpi->rc.this_frame_target = cpi->rc.per_frame_bandwidth;
   } else {
-    // Normal frames (gf,and inter)
+    // Normal frames (gf and inter).
     cpi->rc.this_frame_target = cpi->rc.per_frame_bandwidth;
+    // Set target frame size based on buffer level, for 1 pass CBR.
+    if (cpi->pass == 0 && cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) {
+      // Need to decide how low min_frame_target should be for 1-pass CBR.
+      // For now, use: cpi->rc.av_per_frame_bandwidth / 16:
+      min_frame_target = MAX(cpi->rc.av_per_frame_bandwidth >> 4,
+                             FRAME_OVERHEAD_BITS);
+      cpi->rc.this_frame_target = target_size_from_buffer_level(cpi);
+      // Adjust qp-max based on buffer level.
+      cpi->rc.active_worst_quality =
+          adjust_active_worst_quality_from_buffer_level(cpi);
+    }
   }
 
   // Check that the total sum of adjustments is not above the maximum allowed.
@@ -265,17 +423,16 @@
   // not capable of recovering all the extra bits we have spent in the KF or GF,
   // then the remainder will have to be recovered over a longer time span via
   // other buffer / rate control mechanisms.
-  if (cpi->rc.this_frame_target < min_frame_target)
+  if (cpi->rc.this_frame_target < min_frame_target) {
     cpi->rc.this_frame_target = min_frame_target;
+  }
 
   // Adjust target frame size for Golden Frames:
-  if (cpi->rc.frames_till_gf_update_due == 0) {
-    cpi->refresh_golden_frame = 1;
-    calc_gf_params(cpi);
+  if (cpi->refresh_golden_frame) {
     // If we are using alternate ref instead of gf then do not apply the boost
     // It will instead be applied to the altref update
     // Jims modified boost
-    if (!cpi->source_alt_ref_active) {
+    if (!cpi->rc.source_alt_ref_active) {
       // The spend on the GF is defined in the two pass code
       // for two pass encodes
       cpi->rc.this_frame_target = cpi->rc.per_frame_bandwidth;
@@ -443,8 +600,7 @@
 
 int vp9_rc_pick_q_and_adjust_q_bounds(const VP9_COMP *cpi,
                                       int *bottom_index,
-                                      int *top_index,
-                                      int *top_index_prop) {
+                                      int *top_index) {
   const VP9_COMMON *const cm = &cpi->common;
   int active_best_quality;
   int active_worst_quality = cpi->rc.active_worst_quality;
@@ -456,7 +612,7 @@
     // Handle the special case for key frames forced when we have75 reached
     // the maximum key frame interval. Here force the Q to a range
     // based on the ambient Q to reduce the risk of popping.
-    if (cpi->this_key_frame_forced) {
+    if (cpi->rc.this_key_frame_forced) {
       int delta_qindex;
       int qindex = cpi->rc.last_boosted_qindex;
       double last_boosted_q = vp9_convert_qindex_to_q(qindex);
@@ -483,7 +639,7 @@
       }
 
       // Make a further adjustment based on the kf zero motion measure.
-      q_adj_factor += 0.05 - (0.001 * (double)cpi->kf_zeromotion_pct);
+      q_adj_factor += 0.05 - (0.001 * (double)cpi->twopass.kf_zeromotion_pct);
 
       // Convert the adjustment factor to a qindex delta
       // on active_best_quality.
@@ -498,15 +654,15 @@
     active_best_quality = active_worst_quality
         + vp9_compute_qdelta(cpi, current_q, current_q * 0.3);
 #endif
-  } else if (!cpi->is_src_frame_alt_ref &&
+  } else if (!cpi->rc.is_src_frame_alt_ref &&
              (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
 
     // Use the lower of active_worst_quality and recent
     // average Q as basis for GF/ARF best Q limit unless last frame was
     // a key frame.
-    if (cpi->frames_since_key > 1 &&
-        cpi->rc.avg_frame_qindex < active_worst_quality) {
-      q = cpi->rc.avg_frame_qindex;
+    if (cpi->rc.frames_since_key > 1 &&
+        cpi->rc.avg_frame_qindex[INTER_FRAME] < active_worst_quality) {
+      q = cpi->rc.avg_frame_qindex[INTER_FRAME];
     } else {
       q = active_worst_quality;
     }
@@ -514,7 +670,7 @@
     if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) {
       if (q < cpi->cq_target_quality)
         q = cpi->cq_target_quality;
-      if (cpi->frames_since_key > 1) {
+      if (cpi->rc.frames_since_key > 1) {
         active_best_quality = get_active_quality(q, cpi->rc.gfu_boost,
                                                  gf_low, gf_high,
                                                  afq_low_motion_minq,
@@ -532,7 +688,7 @@
       if (!cpi->refresh_alt_ref_frame) {
         active_best_quality = cpi->cq_target_quality;
       } else {
-        if (cpi->frames_since_key > 1) {
+        if (cpi->rc.frames_since_key > 1) {
           active_best_quality = get_active_quality(
               q, cpi->rc.gfu_boost, gf_low, gf_high,
               afq_low_motion_minq, afq_high_motion_minq);
@@ -552,10 +708,10 @@
       active_best_quality = cpi->cq_target_quality;
     } else {
       if (cpi->pass == 0 &&
-          cpi->rc.avg_frame_qindex < active_worst_quality)
+          cpi->rc.avg_frame_qindex[INTER_FRAME] < active_worst_quality)
         // 1-pass: for now, use the average Q for the active_best, if its lower
         // than active_worst.
-        active_best_quality = inter_minq[cpi->rc.avg_frame_qindex];
+        active_best_quality = inter_minq[cpi->rc.avg_frame_qindex[INTER_FRAME]];
       else
         active_best_quality = inter_minq[active_worst_quality];
 
@@ -587,19 +743,18 @@
   if (active_worst_quality < active_best_quality)
     active_worst_quality = active_best_quality;
 
-  *top_index_prop = active_worst_quality;
   *top_index = active_worst_quality;
   *bottom_index = active_best_quality;
 
 #if LIMIT_QRANGE_FOR_ALTREF_AND_KEY
   // Limit Q range for the adaptive loop.
-  if (cm->frame_type == KEY_FRAME && !cpi->this_key_frame_forced) {
+  if (cm->frame_type == KEY_FRAME && !cpi->rc.this_key_frame_forced) {
     if (!(cpi->pass == 0 && cpi->common.current_video_frame == 0)) {
       *top_index = active_worst_quality;
       *top_index =
           (active_worst_quality + active_best_quality * 3) / 4;
     }
-  } else if (!cpi->is_src_frame_alt_ref &&
+  } else if (!cpi->rc.is_src_frame_alt_ref &&
              (cpi->oxcf.end_usage != USAGE_STREAM_FROM_SERVER) &&
              (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
     *top_index =
@@ -610,20 +765,11 @@
   if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) {
     q = active_best_quality;
   // Special case code to try and match quality with forced key frames
-  } else if ((cm->frame_type == KEY_FRAME) && cpi->this_key_frame_forced) {
+  } else if ((cm->frame_type == KEY_FRAME) && cpi->rc.this_key_frame_forced) {
     q = cpi->rc.last_boosted_qindex;
   } else {
-    // Determine initial Q to try.
-    if (cpi->pass == 0) {
-      // 1-pass: for now, use per-frame-bw for target size of frame, scaled
-      // by |x| for key frame.
-      int scale = (cm->frame_type == KEY_FRAME) ? 5 : 1;
-      q = vp9_rc_regulate_q(cpi, scale * cpi->rc.av_per_frame_bandwidth,
-                            active_best_quality, active_worst_quality);
-    } else {
-      q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target,
-                            active_best_quality, active_worst_quality);
-    }
+    q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target,
+                          active_best_quality, active_worst_quality);
     if (q > *top_index)
       q = *top_index;
   }
@@ -647,61 +793,6 @@
   return q;
 }
 
-static int estimate_keyframe_frequency(VP9_COMP *cpi) {
-  int i;
-
-  // Average key frame frequency
-  int av_key_frame_frequency = 0;
-
-  /* First key frame at start of sequence is a special case. We have no
-   * frequency data.
-   */
-  if (cpi->rc.key_frame_count == 1) {
-    /* Assume a default of 1 kf every 2 seconds, or the max kf interval,
-     * whichever is smaller.
-     */
-    int key_freq = cpi->oxcf.key_freq > 0 ? cpi->oxcf.key_freq : 1;
-    av_key_frame_frequency = (int)cpi->output_framerate * 2;
-
-    if (cpi->oxcf.auto_key && av_key_frame_frequency > key_freq)
-      av_key_frame_frequency = cpi->oxcf.key_freq;
-
-    cpi->rc.prior_key_frame_distance[KEY_FRAME_CONTEXT - 1]
-      = av_key_frame_frequency;
-  } else {
-    unsigned int total_weight = 0;
-    int last_kf_interval =
-      (cpi->frames_since_key > 0) ? cpi->frames_since_key : 1;
-
-    /* reset keyframe context and calculate weighted average of last
-     * KEY_FRAME_CONTEXT keyframes
-     */
-    for (i = 0; i < KEY_FRAME_CONTEXT; i++) {
-      if (i < KEY_FRAME_CONTEXT - 1)
-        cpi->rc.prior_key_frame_distance[i]
-          = cpi->rc.prior_key_frame_distance[i + 1];
-      else
-        cpi->rc.prior_key_frame_distance[i] = last_kf_interval;
-
-      av_key_frame_frequency += prior_key_frame_weight[i]
-                                * cpi->rc.prior_key_frame_distance[i];
-      total_weight += prior_key_frame_weight[i];
-    }
-
-    av_key_frame_frequency /= total_weight;
-  }
-  return av_key_frame_frequency;
-}
-
-
-static void adjust_key_frame_context(VP9_COMP *cpi) {
-  // Clear down mmx registers to allow floating point in what follows
-  vp9_clear_system_state();
-
-  cpi->frames_since_key = 0;
-  cpi->rc.key_frame_count++;
-}
-
 void vp9_rc_compute_frame_size_bounds(const VP9_COMP *cpi,
                                       int this_frame_target,
                                       int *frame_under_shoot_limit,
@@ -755,8 +846,7 @@
   return 1;
 }
 
-void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used,
-                              int worst_q) {
+void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used) {
   VP9_COMMON *const cm = &cpi->common;
   // Update rate control heuristics
   cpi->rc.projected_frame_size = (bytes_used << 3);
@@ -766,34 +856,21 @@
       cpi, (cpi->sf.recode_loop ||
             cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) ? 2 : 0);
 
-  cpi->rc.last_q[cm->frame_type] = cm->base_qindex;
-  cpi->rc.active_worst_quality = worst_q;
-
-  // Keep record of last boosted (KF/KF/ARF) Q value.
-  // If the current frame is coded at a lower Q then we also update it.
-  // If all mbs in this group are skipped only update if the Q value is
-  // better than that already stored.
-  // This is used to help set quality in forced key frames to reduce popping
-  if ((cm->base_qindex < cpi->rc.last_boosted_qindex) ||
-      ((cpi->static_mb_pct < 100) &&
-       ((cm->frame_type == KEY_FRAME) || cpi->refresh_alt_ref_frame ||
-        (cpi->refresh_golden_frame && !cpi->is_src_frame_alt_ref)))) {
-    cpi->rc.last_boosted_qindex = cm->base_qindex;
-  }
-
+  // Keep a record of last Q and ambient average Q.
   if (cm->frame_type == KEY_FRAME) {
-    adjust_key_frame_context(cpi);
-  }
-
-  // Keep a record of ambient average Q.
-  if (cm->frame_type != KEY_FRAME)
-    cpi->rc.avg_frame_qindex = (2 + 3 * cpi->rc.avg_frame_qindex +
-                            cm->base_qindex) >> 2;
-
-  // Keep a record from which we can calculate the average Q excluding GF
-  // updates and key frames.
-  if (cm->frame_type != KEY_FRAME &&
-      !cpi->refresh_golden_frame && !cpi->refresh_alt_ref_frame) {
+    cpi->rc.last_q[KEY_FRAME] = cm->base_qindex;
+    cpi->rc.avg_frame_qindex[KEY_FRAME] =
+        (2 + 3 * cpi->rc.avg_frame_qindex[KEY_FRAME] + cm->base_qindex) >> 2;
+  } else if (!cpi->rc.is_src_frame_alt_ref &&
+             (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
+    cpi->rc.last_q[2] = cm->base_qindex;
+    cpi->rc.avg_frame_qindex[2] =
+        (2 + 3 * cpi->rc.avg_frame_qindex[2] + cm->base_qindex) >> 2;
+  } else {
+    cpi->rc.last_q[INTER_FRAME] = cm->base_qindex;
+    cpi->rc.avg_frame_qindex[INTER_FRAME] =
+        (2 + 3 * cpi->rc.avg_frame_qindex[INTER_FRAME] +
+         cm->base_qindex) >> 2;
     cpi->rc.ni_frames++;
     cpi->rc.tot_q += vp9_convert_qindex_to_q(cm->base_qindex);
     cpi->rc.avg_q = cpi->rc.tot_q / (double)cpi->rc.ni_frames;
@@ -803,17 +880,19 @@
     cpi->rc.ni_av_qi = cpi->rc.ni_tot_qi / cpi->rc.ni_frames;
   }
 
-  // Update the buffer level variable.
-  // Non-viewable frames are a special case and are treated as pure overhead.
-  if (!cm->show_frame)
-    cpi->rc.bits_off_target -= cpi->rc.projected_frame_size;
-  else
-    cpi->rc.bits_off_target += cpi->rc.av_per_frame_bandwidth -
-                               cpi->rc.projected_frame_size;
+  // Keep record of last boosted (KF/KF/ARF) Q value.
+  // If the current frame is coded at a lower Q then we also update it.
+  // If all mbs in this group are skipped only update if the Q value is
+  // better than that already stored.
+  // This is used to help set quality in forced key frames to reduce popping
+  if ((cm->base_qindex < cpi->rc.last_boosted_qindex) ||
+      ((cpi->static_mb_pct < 100) &&
+       ((cm->frame_type == KEY_FRAME) || cpi->refresh_alt_ref_frame ||
+        (cpi->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref)))) {
+    cpi->rc.last_boosted_qindex = cm->base_qindex;
+  }
 
-  // Clip the buffer level at the maximum buffer size
-  if (cpi->rc.bits_off_target > cpi->oxcf.maximum_buffer_size)
-    cpi->rc.bits_off_target = cpi->oxcf.maximum_buffer_size;
+  vp9_update_buffer_level(cpi, cpi->rc.projected_frame_size);
 
   // Rolling monitors of whether we are over or underspending used to help
   // regulate min and Max Q in two pass.
@@ -839,8 +918,6 @@
   cpi->rc.total_target_vs_actual += (cpi->rc.this_frame_target -
                                      cpi->rc.projected_frame_size);
 
-  cpi->rc.buffer_level = cpi->rc.bits_off_target;
-
 #ifndef DISABLE_RC_LONG_TERM_MEM
   // Update bits left to the kf and gf groups to account for overshoot or
   // undershoot on these frames
diff --git a/vp9/encoder/vp9_ratectrl.h b/vp9/encoder/vp9_ratectrl.h
index 063ac8f..8293557 100644
--- a/vp9/encoder/vp9_ratectrl.h
+++ b/vp9/encoder/vp9_ratectrl.h
@@ -42,18 +42,16 @@
 // Picks q and q bounds given the target for bits
 int vp9_rc_pick_q_and_adjust_q_bounds(const VP9_COMP *cpi,
                                       int *bottom_index,
-                                      int *top_index,
-                                      int *top_index_prop);
+                                      int *top_index);
 
 // Estimates q to achieve a target bits per frame
 int vp9_rc_regulate_q(const VP9_COMP *cpi, int target_bits_per_frame,
                       int active_best_quality, int active_worst_quality);
 
 // Post encode update of the rate control parameters based
-// on bytes used and q used for the frame
+// on bytes used
 void vp9_rc_postencode_update(VP9_COMP *cpi,
-                              uint64_t bytes_used,
-                              int worst_q);
+                              uint64_t bytes_used);
 
 // estimates bits per mb for a given qindex and correction factor
 int vp9_rc_bits_per_mb(FRAME_TYPE frame_type, int qindex,
@@ -63,4 +61,10 @@
 void vp9_twopass_postencode_update(VP9_COMP *cpi,
                                    uint64_t bytes_used);
 
+// Decide if we should drop this frame: For 1-pass CBR.
+int vp9_drop_frame(VP9_COMP *cpi);
+
+// Update the buffer level.
+void vp9_update_buffer_level(VP9_COMP *cpi, int encoded_frame_size);
+
 #endif  // VP9_ENCODER_VP9_RATECTRL_H_
diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c
index 3e18327..22e480b 100644
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -20,7 +20,6 @@
 #include "vp9/common/vp9_entropymode.h"
 #include "vp9/common/vp9_reconinter.h"
 #include "vp9/common/vp9_reconintra.h"
-#include "vp9/common/vp9_findnearmv.h"
 #include "vp9/common/vp9_quant_common.h"
 #include "vp9/encoder/vp9_encodemb.h"
 #include "vp9/encoder/vp9_quantize.h"
@@ -417,16 +416,19 @@
   // Hence quantizer step is also 8 times. To get effective quantizer
   // we need to divide by 8 before sending to modeling function.
   int i, rate_sum = 0, dist_sum = 0;
+  int ref = xd->mi_8x8[0]->mbmi.ref_frame[0];
+  unsigned int sse;
 
   for (i = 0; i < MAX_MB_PLANE; ++i) {
     struct macroblock_plane *const p = &x->plane[i];
     struct macroblockd_plane *const pd = &xd->plane[i];
     const BLOCK_SIZE bs = get_plane_block_size(bsize, pd);
-    unsigned int sse;
     int rate;
     int64_t dist;
     (void) cpi->fn_ptr[bs].vf(p->src.buf, p->src.stride,
                               pd->dst.buf, pd->dst.stride, &sse);
+    if (i == 0)
+      x->pred_sse[ref] = sse;
     // sse works better than var, since there is no dc prediction used
     model_rd_from_var_lapndz(sse, 1 << num_pels_log2_lookup[bs],
                              pd->dequant[1] >> 3, &rate, &dist);
@@ -686,7 +688,7 @@
         t_left[i] = !!*(const uint64_t *)&left[i];
       break;
     default:
-      assert(!"Invalid transform size.");
+      assert(0 && "Invalid transform size.");
   }
 }
 
@@ -1042,7 +1044,7 @@
                                 TX_4X4, mode,
                                 x->skip_encode ? src : dst,
                                 x->skip_encode ? src_stride : dst_stride,
-                                dst, dst_stride);
+                                dst, dst_stride, idx, idy, 0);
         vp9_subtract_block(4, 4, src_diff, 8,
                            src, src_stride,
                            dst, dst_stride);
@@ -1496,7 +1498,8 @@
                                        int *labelyrate,
                                        int64_t *distortion, int64_t *sse,
                                        ENTROPY_CONTEXT *ta,
-                                       ENTROPY_CONTEXT *tl) {
+                                       ENTROPY_CONTEXT *tl,
+                                       int mi_row, int mi_col) {
   int k;
   MACROBLOCKD *xd = &x->e_mbd;
   struct macroblockd_plane *const pd = &xd->plane[0];
@@ -1521,8 +1524,10 @@
     vp9_build_inter_predictor(pre, pd->pre[ref].stride,
                               dst, pd->dst.stride,
                               &mi->bmi[i].as_mv[ref].as_mv,
-                              &xd->scale_factor[ref],
-                              width, height, ref, &xd->subpix, MV_PRECISION_Q3);
+                              xd->scale_factors[ref],
+                              width, height, ref, &xd->subpix, MV_PRECISION_Q3,
+                              mi_col * MI_SIZE + 4 * (i % 2),
+                              mi_row * MI_SIZE + 4 * (i / 2));
   }
 
   vp9_subtract_block(height, width,
@@ -1669,15 +1674,15 @@
 
       frame_mv[ZEROMV][mbmi->ref_frame[0]].as_int = 0;
       vp9_append_sub8x8_mvs_for_idx(&cpi->common, &x->e_mbd, tile,
+                                    i, 0, mi_row, mi_col,
                                     &frame_mv[NEARESTMV][mbmi->ref_frame[0]],
-                                    &frame_mv[NEARMV][mbmi->ref_frame[0]],
-                                    i, 0, mi_row, mi_col);
+                                    &frame_mv[NEARMV][mbmi->ref_frame[0]]);
       if (has_second_rf) {
         frame_mv[ZEROMV][mbmi->ref_frame[1]].as_int = 0;
         vp9_append_sub8x8_mvs_for_idx(&cpi->common, &x->e_mbd, tile,
+                                      i, 1, mi_row, mi_col,
                                       &frame_mv[NEARESTMV][mbmi->ref_frame[1]],
-                                      &frame_mv[NEARMV][mbmi->ref_frame[1]],
-                                      i, 1, mi_row, mi_col);
+                                      &frame_mv[NEARMV][mbmi->ref_frame[1]]);
       }
       // search for the best motion vector on this segment
       for (this_mode = NEARESTMV; this_mode <= NEWMV; ++this_mode) {
@@ -1781,7 +1786,7 @@
           // adjust src pointer for this block
           mi_buf_shift(x, i);
 
-          vp9_clamp_mv_min_max(x, &bsi->ref_mv->as_mv);
+          vp9_set_mv_search_range(x, &bsi->ref_mv->as_mv);
 
           if (cpi->sf.search_method == HEX) {
             bestsme = vp9_hex_search(x, &mvp_full.as_mv,
@@ -1813,10 +1818,10 @@
             clamp_mv(&mvp_full.as_mv, x->mv_col_min, x->mv_col_max,
                      x->mv_row_min, x->mv_row_max);
 
-            thissme = cpi->full_search_sad(x, &mvp_full,
+            thissme = cpi->full_search_sad(x, &mvp_full.as_mv,
                                            sadpb, 16, v_fn_ptr,
                                            x->nmvjointcost, x->mvcost,
-                                           bsi->ref_mv, i);
+                                           &bsi->ref_mv->as_mv, i);
 
             if (thissme < bestsme) {
               bestsme = thissme;
@@ -1830,7 +1835,6 @@
 
           if (bestsme < INT_MAX) {
             int distortion;
-            unsigned int sse;
             cpi->find_fractional_mv_step(x,
                                          &mode_mv[NEWMV].as_mv,
                                          &bsi->ref_mv->as_mv,
@@ -1838,7 +1842,8 @@
                                          x->errorperbit, v_fn_ptr,
                                          0, cpi->sf.subpel_iters_per_step,
                                          x->nmvjointcost, x->mvcost,
-                                         &distortion, &sse);
+                                         &distortion,
+                                         &x->pred_sse[mbmi->ref_frame[0]]);
 
             // save motion search result for use in compound prediction
             seg_mvs[i][mbmi->ref_frame[0]].as_int = mode_mv[NEWMV].as_int;
@@ -1956,7 +1961,8 @@
                                     &bsi->rdstat[i][mode_idx].bdist,
                                     &bsi->rdstat[i][mode_idx].bsse,
                                     bsi->rdstat[i][mode_idx].ta,
-                                    bsi->rdstat[i][mode_idx].tl);
+                                    bsi->rdstat[i][mode_idx].tl,
+                                    mi_row, mi_col);
         if (bsi->rdstat[i][mode_idx].brdcost < INT64_MAX) {
           bsi->rdstat[i][mode_idx].brdcost += RDCOST(x->rdmult, x->rddiv,
                                             bsi->rdstat[i][mode_idx].brate, 0);
@@ -2132,6 +2138,7 @@
   // Note the index of the mv that worked best in the reference list.
   x->mv_best_ref_index[ref_frame] = best_index;
   x->max_mv_context[ref_frame] = max_mv;
+  x->pred_mv_sad[ref_frame] = best_sad;
 }
 
 static void estimate_ref_frame_costs(VP9_COMP *cpi, int segment_id,
@@ -2210,8 +2217,8 @@
   ctx->best_mode_index = mode_index;
   ctx->mic = *xd->mi_8x8[0];
 
-  ctx->best_ref_mv.as_int = ref_mv->as_int;
-  ctx->second_best_ref_mv.as_int = second_ref_mv->as_int;
+  ctx->best_ref_mv[0].as_int = ref_mv->as_int;
+  ctx->best_ref_mv[1].as_int = second_ref_mv->as_int;
 
   ctx->single_pred_diff = (int)comp_pred_diff[SINGLE_REFERENCE];
   ctx->comp_pred_diff   = (int)comp_pred_diff[COMPOUND_REFERENCE];
@@ -2255,23 +2262,18 @@
                                int mi_row, int mi_col,
                                int_mv frame_nearest_mv[MAX_REF_FRAMES],
                                int_mv frame_near_mv[MAX_REF_FRAMES],
-                               struct buf_2d yv12_mb[4][MAX_MB_PLANE],
-                               struct scale_factors scale[MAX_REF_FRAMES]) {
+                               struct buf_2d yv12_mb[4][MAX_MB_PLANE]) {
   VP9_COMMON *cm = &cpi->common;
   YV12_BUFFER_CONFIG *yv12 = &cm->yv12_fb[cpi->common.ref_frame_map[idx]];
   MACROBLOCKD *const xd = &x->e_mbd;
   MB_MODE_INFO *const mbmi = &xd->mi_8x8[0]->mbmi;
+  const struct scale_factors *const sf =
+      &cpi->common.active_ref_scale[frame_type - 1];
 
-  // set up scaling factors
-  scale[frame_type] = cpi->common.active_ref_scale[frame_type - 1];
-
-  scale[frame_type].sfc->set_scaled_offsets(&scale[frame_type],
-                                            mi_row * MI_SIZE, mi_col * MI_SIZE);
 
   // TODO(jkoleszar): Is the UV buffer ever used here? If so, need to make this
   // use the UV scaling factors.
-  setup_pred_block(xd, yv12_mb[frame_type], yv12, mi_row, mi_col,
-                   &scale[frame_type], &scale[frame_type]);
+  setup_pred_block(xd, yv12_mb[frame_type], yv12, mi_row, mi_col, sf, sf);
 
   // Gets an initial list of candidate vectors from neighbours and orders them
   vp9_find_mv_refs(cm, xd, tile, xd->mi_8x8[0],
@@ -2288,7 +2290,7 @@
   // Further refinement that is encode side only to test the top few candidates
   // in full and choose the best as the centre point for subsequent searches.
   // The current implementation doesn't support scaling.
-  if (!vp9_is_scaled(scale[frame_type].sfc) && block_size >= BLOCK_8X8)
+  if (!vp9_is_scaled(sf) && block_size >= BLOCK_8X8)
     mv_pred(cpi, x, yv12_mb[frame_type][0].buf, yv12->y_stride,
             frame_type, block_size);
 }
@@ -2344,7 +2346,7 @@
     setup_pre_planes(xd, 0, scaled_ref_frame, mi_row, mi_col, NULL);
   }
 
-  vp9_clamp_mv_min_max(x, &ref_mv.as_mv);
+  vp9_set_mv_search_range(x, &ref_mv.as_mv);
 
   // Adjust search parameters based on small partitions' result.
   if (x->fast_ms) {
@@ -2384,6 +2386,30 @@
     step_param = MAX(step_param, boffset);
   }
 
+  if (cpi->sf.adaptive_motion_search) {
+    int bwl = b_width_log2_lookup[bsize];
+    int bhl = b_height_log2_lookup[bsize];
+    int i;
+    int tlevel = x->pred_mv_sad[ref] >> (bwl + bhl + 4);
+
+    if (tlevel < 5)
+      step_param += 2;
+
+    for (i = LAST_FRAME; i <= ALTREF_FRAME && cpi->common.show_frame; ++i) {
+      if ((x->pred_mv_sad[ref] >> 3) > x->pred_mv_sad[i]) {
+        x->pred_mv[ref].as_int = 0;
+        tmp_mv->as_int = INVALID_MV;
+
+        if (scaled_ref_frame) {
+          int i;
+          for (i = 0; i < MAX_MB_PLANE; i++)
+            xd->plane[i].pre[0] = backup_yv12[i];
+        }
+        return;
+      }
+    }
+  }
+
   mvp_full.as_int = x->mv_best_ref_index[ref] < MAX_MV_REF_CANDIDATES ?
       mbmi->ref_mvs[ref][x->mv_best_ref_index[ref]].as_int :
       x->pred_mv[ref].as_int;
@@ -2426,14 +2452,13 @@
 
   if (bestsme < INT_MAX) {
     int dis;  /* TODO: use dis in distortion calculation later. */
-    unsigned int sse;
     cpi->find_fractional_mv_step(x, &tmp_mv->as_mv, &ref_mv.as_mv,
                                  cm->allow_high_precision_mv,
                                  x->errorperbit,
                                  &cpi->fn_ptr[bsize],
                                  0, cpi->sf.subpel_iters_per_step,
                                  x->nmvjointcost, x->mvcost,
-                                 &dis, &sse);
+                                 &dis, &x->pred_sse[ref]);
   }
   *rate_mv = vp9_mv_bit_cost(&tmp_mv->as_mv, &ref_mv.as_mv,
                              x->nmvjointcost, x->mvcost, MV_COST_WEIGHT);
@@ -2487,8 +2512,6 @@
       setup_pre_planes(xd, ref, scaled_ref_frame[ref], mi_row, mi_col, NULL);
     }
 
-    xd->scale_factor[ref].sfc->set_scaled_offsets(&xd->scale_factor[ref],
-                                                  mi_row, mi_col);
     frame_mv[refs[ref]].as_int = single_newmv[refs[ref]].as_int;
   }
 
@@ -2516,14 +2539,15 @@
                               ref_yv12[!id].stride,
                               second_pred, pw,
                               &frame_mv[refs[!id]].as_mv,
-                              &xd->scale_factor[!id],
+                              xd->scale_factors[!id],
                               pw, ph, 0,
-                              &xd->subpix, MV_PRECISION_Q3);
+                              &xd->subpix, MV_PRECISION_Q3,
+                              mi_col * MI_SIZE, mi_row * MI_SIZE);
 
     // Compound motion search on first ref frame.
     if (id)
       xd->plane[0].pre[0] = ref_yv12[id];
-    vp9_clamp_mv_min_max(x, &ref_mv[id].as_mv);
+    vp9_set_mv_search_range(x, &ref_mv[id].as_mv);
 
     // Use mv result from single mode as mvp.
     tmp_mv.as_int = frame_mv[refs[id]].as_int;
@@ -2532,11 +2556,11 @@
     tmp_mv.as_mv.row >>= 3;
 
     // Small-range full-pixel motion search
-    bestsme = vp9_refining_search_8p_c(x, &tmp_mv, sadpb,
+    bestsme = vp9_refining_search_8p_c(x, &tmp_mv.as_mv, sadpb,
                                        search_range,
                                        &cpi->fn_ptr[bsize],
                                        x->nmvjointcost, x->mvcost,
-                                       &ref_mv[id], second_pred,
+                                       &ref_mv[id].as_mv, second_pred,
                                        pw, ph);
 
     x->mv_col_min = tmp_col_min;
@@ -2547,7 +2571,6 @@
     if (bestsme < INT_MAX) {
       int dis; /* TODO: use dis in distortion calculation later. */
       unsigned int sse;
-
       bestsme = cpi->find_fractional_mv_step_comp(
           x, &tmp_mv.as_mv,
           &ref_mv[id].as_mv,
@@ -2748,20 +2771,23 @@
     intpel_mv &= (mbmi->mv[1].as_mv.row & 15) == 0 &&
         (mbmi->mv[1].as_mv.col & 15) == 0;
 
+
   // Search for best switchable filter by checking the variance of
   // pred error irrespective of whether the filter will be used
+  cpi->mask_filter_rd = 0;
+  for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; ++i)
+    cpi->rd_filter_cache[i] = INT64_MAX;
+
   if (cm->mcomp_filter_type != BILINEAR) {
     *best_filter = EIGHTTAP;
     if (x->source_variance <
         cpi->sf.disable_filter_search_var_thresh) {
       *best_filter = EIGHTTAP;
-      vp9_zero(cpi->rd_filter_cache);
     } else {
-      int i, newbest;
+      int newbest;
       int tmp_rate_sum = 0;
       int64_t tmp_dist_sum = 0;
 
-      cpi->rd_filter_cache[SWITCHABLE_FILTERS] = INT64_MAX;
       for (i = 0; i < SWITCHABLE_FILTERS; ++i) {
         int j;
         int64_t rs_rd;
@@ -2771,14 +2797,13 @@
         rs_rd = RDCOST(x->rdmult, x->rddiv, rs, 0);
 
         if (i > 0 && intpel_mv) {
-          cpi->rd_filter_cache[i] = RDCOST(x->rdmult, x->rddiv,
-                                           tmp_rate_sum, tmp_dist_sum);
+          rd = RDCOST(x->rdmult, x->rddiv, tmp_rate_sum, tmp_dist_sum);
+          cpi->rd_filter_cache[i] = rd;
           cpi->rd_filter_cache[SWITCHABLE_FILTERS] =
-              MIN(cpi->rd_filter_cache[SWITCHABLE_FILTERS],
-                  cpi->rd_filter_cache[i] + rs_rd);
-          rd = cpi->rd_filter_cache[i];
+              MIN(cpi->rd_filter_cache[SWITCHABLE_FILTERS], rd + rs_rd);
           if (cm->mcomp_filter_type == SWITCHABLE)
             rd += rs_rd;
+          cpi->mask_filter_rd = MAX(cpi->mask_filter_rd, rd);
         } else {
           int rate_sum = 0;
           int64_t dist_sum = 0;
@@ -2796,19 +2821,21 @@
           }
           vp9_build_inter_predictors_sb(xd, mi_row, mi_col, bsize);
           model_rd_for_sb(cpi, bsize, x, xd, &rate_sum, &dist_sum);
-          cpi->rd_filter_cache[i] = RDCOST(x->rdmult, x->rddiv,
-                                           rate_sum, dist_sum);
+
+          rd = RDCOST(x->rdmult, x->rddiv, rate_sum, dist_sum);
+          cpi->rd_filter_cache[i] = rd;
           cpi->rd_filter_cache[SWITCHABLE_FILTERS] =
-              MIN(cpi->rd_filter_cache[SWITCHABLE_FILTERS],
-                  cpi->rd_filter_cache[i] + rs_rd);
-          rd = cpi->rd_filter_cache[i];
+              MIN(cpi->rd_filter_cache[SWITCHABLE_FILTERS], rd + rs_rd);
           if (cm->mcomp_filter_type == SWITCHABLE)
             rd += rs_rd;
+          cpi->mask_filter_rd = MAX(cpi->mask_filter_rd, rd);
+
           if (i == 0 && intpel_mv) {
             tmp_rate_sum = rate_sum;
             tmp_dist_sum = dist_sum;
           }
         }
+
         if (i == 0 && cpi->sf.use_rd_breakout && ref_best_rd < INT64_MAX) {
           if (rd / 2 > ref_best_rd) {
             restore_dst_buf(xd, orig_dst, orig_dst_stride);
@@ -2853,7 +2880,6 @@
     vp9_build_inter_predictors_sb(xd, mi_row, mi_col, bsize);
   }
 
-
   if (cpi->sf.use_rd_breakout && ref_best_rd < INT64_MAX) {
     int tmp_rate;
     int64_t tmp_dist;
@@ -3122,7 +3148,6 @@
   int64_t dist_uv[TX_SIZES];
   int skip_uv[TX_SIZES];
   MB_PREDICTION_MODE mode_uv[TX_SIZES];
-  struct scale_factors scale_factor[4];
   unsigned int ref_frame_mask = 0;
   unsigned int mode_mask = 0;
   int64_t mode_distortions[MB_MODE_COUNT] = {-1};
@@ -3149,6 +3174,8 @@
     best_filter_rd[i] = INT64_MAX;
   for (i = 0; i < TX_SIZES; i++)
     rate_uv_intra[i] = INT_MAX;
+  for (i = 0; i < MAX_REF_FRAMES; ++i)
+    x->pred_sse[i] = INT_MAX;
 
   *returnrate = INT_MAX;
 
@@ -3186,11 +3213,11 @@
   }
 
   for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ref_frame++) {
+    x->pred_mv_sad[ref_frame] = INT_MAX;
     if (cpi->ref_frame_flags & flag_list[ref_frame]) {
       setup_buffer_inter(cpi, x, tile, idx_list[ref_frame], ref_frame,
                          block_size, mi_row, mi_col,
-                         frame_mv[NEARESTMV], frame_mv[NEARMV],
-                         yv12_mb, scale_factor);
+                         frame_mv[NEARESTMV], frame_mv[NEARMV], yv12_mb);
     }
     frame_mv[NEWMV][ref_frame].as_int = INVALID_MV;
     frame_mv[ZEROMV][ref_frame].as_int = 0;
@@ -3237,7 +3264,7 @@
             break;
           case NONE:
           case MAX_REF_FRAMES:
-            assert(!"Invalid Reference frame");
+            assert(0 && "Invalid Reference frame");
         }
       }
       if (cpi->mode_skip_mask & ((int64_t)1 << mode_index))
@@ -3303,7 +3330,7 @@
           continue;
     }
 
-    set_scale_factors(xd, ref_frame, second_ref_frame, scale_factor);
+    set_scale_factors(cm, xd, ref_frame - 1, second_ref_frame - 1);
     mbmi->uv_mode = DC_PRED;
 
     // Evaluate all sub-pel filters irrespective of whether we can use
@@ -3315,7 +3342,6 @@
       if (!(cpi->ref_frame_flags & flag_list[second_ref_frame]))
         continue;
 
-      set_scale_factors(xd, ref_frame, second_ref_frame, scale_factor);
       mode_excluded = mode_excluded ? mode_excluded
                                     : cm->reference_mode == SINGLE_REFERENCE;
     } else {
@@ -3351,7 +3377,7 @@
       // unless ARNR filtering is enabled in which case we want
       // an unfiltered alternative. We allow near/nearest as well
       // because they may result in zero-zero MVs but be cheaper.
-      if (cpi->is_src_frame_alt_ref && (cpi->oxcf.arnr_max_frames == 0)) {
+      if (cpi->rc.is_src_frame_alt_ref && (cpi->oxcf.arnr_max_frames == 0)) {
         if ((this_mode != ZEROMV &&
              !(this_mode == NEARMV &&
                frame_mv[NEARMV][ALTREF_FRAME].as_int == 0) &&
@@ -3607,23 +3633,21 @@
         cm->mcomp_filter_type != BILINEAR) {
       int64_t ref = cpi->rd_filter_cache[cm->mcomp_filter_type == SWITCHABLE ?
                               SWITCHABLE_FILTERS : cm->mcomp_filter_type];
+
       for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; i++) {
         int64_t adj_rd;
-        // In cases of poor prediction, filter_cache[] can contain really big
-        // values, which actually are bigger than this_rd itself. This can
-        // cause negative best_filter_rd[] values, which is obviously silly.
-        // Therefore, if filter_cache < ref, we do an adjusted calculation.
-        if (cpi->rd_filter_cache[i] >= ref) {
-          adj_rd = this_rd + cpi->rd_filter_cache[i] - ref;
-        } else {
-          // FIXME(rbultje) do this for comppsred also
-          //
-          // To prevent out-of-range computation in
-          //    adj_rd = cpi->rd_filter_cache[i] * this_rd / ref
-          // cpi->rd_filter_cache[i] / ref is converted to a 256 based ratio.
-          int tmp = cpi->rd_filter_cache[i] * 256 / ref;
-          adj_rd = (this_rd * tmp) >> 8;
-        }
+        if (ref == INT64_MAX)
+          adj_rd = 0;
+        else if (cpi->rd_filter_cache[i] == INT64_MAX)
+          // when early termination is triggered, the encoder does not have
+          // access to the rate-distortion cost. it only knows that the cost
+          // should be above the maximum valid value. hence it takes the known
+          // maximum plus an arbitrary constant as the rate-distortion cost.
+          adj_rd = cpi->mask_filter_rd - ref + 10;
+        else
+          adj_rd = cpi->rd_filter_cache[i] - ref;
+
+        adj_rd += this_rd;
         best_filter_rd[i] = MIN(best_filter_rd[i], adj_rd);
       }
     }
@@ -3755,8 +3779,7 @@
     vp9_zero(best_tx_diff);
   }
 
-  set_scale_factors(xd, mbmi->ref_frame[0], mbmi->ref_frame[1],
-                    scale_factor);
+  set_scale_factors(cm, xd, mbmi->ref_frame[0] - 1, mbmi->ref_frame[1] - 1);
   store_coding_context(x, ctx, best_mode_index,
                        &mbmi->ref_mvs[mbmi->ref_frame[0]][0],
                        &mbmi->ref_mvs[mbmi->ref_frame[1] < 0 ? 0 :
@@ -3810,9 +3833,6 @@
   int64_t dist_uv[TX_SIZES];
   int skip_uv[TX_SIZES];
   MB_PREDICTION_MODE mode_uv[TX_SIZES] = { 0 };
-  struct scale_factors scale_factor[4];
-  unsigned int ref_frame_mask = 0;
-  unsigned int mode_mask = 0;
   int intra_cost_penalty = 20 * vp9_dc_quant(cpi->common.base_qindex,
                                              cpi->common.y_dc_delta_q);
   int_mv seg_mvs[4][MAX_REF_FRAMES];
@@ -3842,21 +3862,12 @@
 
   *returnrate = INT_MAX;
 
-  // Create a mask set to 1 for each reference frame used by a smaller
-  // resolution.
-  if (cpi->sf.use_avoid_tested_higherror) {
-    ref_frame_mask = 0;
-    mode_mask = 0;
-    ref_frame_mask = ~ref_frame_mask;
-    mode_mask = ~mode_mask;
-  }
-
   for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ref_frame++) {
     if (cpi->ref_frame_flags & flag_list[ref_frame]) {
       setup_buffer_inter(cpi, x, tile, idx_list[ref_frame], ref_frame,
                          block_size, mi_row, mi_col,
                          frame_mv[NEARESTMV], frame_mv[NEARMV],
-                         yv12_mb, scale_factor);
+                         yv12_mb);
     }
     frame_mv[NEWMV][ref_frame].as_int = INVALID_MV;
     frame_mv[ZEROMV][ref_frame].as_int = 0;
@@ -3902,7 +3913,7 @@
             break;
           case NONE:
           case MAX_REF_FRAMES:
-            assert(!"Invalid Reference frame");
+            assert(0 && "Invalid Reference frame");
         }
       }
       if (cpi->mode_skip_mask & ((int64_t)1 << mode_index))
@@ -3953,14 +3964,14 @@
     // TODO(jingning, jkoleszar): scaling reference frame not supported for
     // sub8x8 blocks.
     if (ref_frame > 0 &&
-        vp9_is_scaled(scale_factor[ref_frame].sfc))
+        vp9_is_scaled(&cpi->common.active_ref_scale[ref_frame - 1]))
       continue;
 
     if (second_ref_frame > 0 &&
-        vp9_is_scaled(scale_factor[second_ref_frame].sfc))
+        vp9_is_scaled(&cpi->common.active_ref_scale[second_ref_frame - 1]))
       continue;
 
-    set_scale_factors(xd, ref_frame, second_ref_frame, scale_factor);
+    set_scale_factors(cm, xd, ref_frame - 1, second_ref_frame - 1);
     mbmi->uv_mode = DC_PRED;
 
     // Evaluate all sub-pel filters irrespective of whether we can use
@@ -3971,7 +3982,6 @@
     if (comp_pred) {
       if (!(cpi->ref_frame_flags & flag_list[second_ref_frame]))
         continue;
-      set_scale_factors(xd, ref_frame, second_ref_frame, scale_factor);
 
       mode_excluded = mode_excluded ? mode_excluded
                                     : cm->reference_mode == SINGLE_REFERENCE;
@@ -4009,7 +4019,7 @@
       // unless ARNR filtering is enabled in which case we want
       // an unfiltered alternative. We allow near/nearest as well
       // because they may result in zero-zero MVs but be cheaper.
-      if (cpi->is_src_frame_alt_ref && (cpi->oxcf.arnr_max_frames == 0))
+      if (cpi->rc.is_src_frame_alt_ref && (cpi->oxcf.arnr_max_frames == 0))
         continue;
     }
 
@@ -4068,13 +4078,21 @@
           cpi->rd_thresh_sub8x8[segment_id][bsize][THR_GOLD] : this_rd_thresh;
       xd->mi_8x8[0]->mbmi.tx_size = TX_4X4;
 
-      cpi->rd_filter_cache[SWITCHABLE_FILTERS] = INT64_MAX;
+      cpi->mask_filter_rd = 0;
+      for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; ++i)
+        cpi->rd_filter_cache[i] = INT64_MAX;
+
       if (cm->mcomp_filter_type != BILINEAR) {
         tmp_best_filter = EIGHTTAP;
         if (x->source_variance <
             cpi->sf.disable_filter_search_var_thresh) {
           tmp_best_filter = EIGHTTAP;
-          vp9_zero(cpi->rd_filter_cache);
+        } else if (cpi->sf.adaptive_pred_filter_type == 1 &&
+                   ctx->pred_filter_type < SWITCHABLE) {
+          tmp_best_filter = ctx->pred_filter_type;
+        } else if (cpi->sf.adaptive_pred_filter_type == 2) {
+          tmp_best_filter = ctx->pred_filter_type < SWITCHABLE ?
+                              ctx->pred_filter_type : 0;
         } else {
           for (switchable_filter_index = 0;
                switchable_filter_index < SWITCHABLE_FILTERS;
@@ -4096,15 +4114,17 @@
 
             if (tmp_rd == INT64_MAX)
               continue;
-            cpi->rd_filter_cache[switchable_filter_index] = tmp_rd;
             rs = get_switchable_rate(x);
             rs_rd = RDCOST(x->rdmult, x->rddiv, rs, 0);
+            cpi->rd_filter_cache[switchable_filter_index] = tmp_rd;
             cpi->rd_filter_cache[SWITCHABLE_FILTERS] =
                 MIN(cpi->rd_filter_cache[SWITCHABLE_FILTERS],
                     tmp_rd + rs_rd);
             if (cm->mcomp_filter_type == SWITCHABLE)
               tmp_rd += rs_rd;
 
+            cpi->mask_filter_rd = MAX(cpi->mask_filter_rd, tmp_rd);
+
             newbest = (tmp_rd < tmp_best_rd);
             if (newbest) {
               tmp_best_filter = mbmi->interp_filter;
@@ -4141,7 +4161,7 @@
         }
       }
 
-      if (tmp_best_rdu == INT64_MAX)
+      if (tmp_best_rdu == INT64_MAX && pred_exists)
         continue;
 
       mbmi->interp_filter = (cm->mcomp_filter_type == SWITCHABLE ?
@@ -4352,16 +4372,20 @@
         cm->mcomp_filter_type != BILINEAR) {
       int64_t ref = cpi->rd_filter_cache[cm->mcomp_filter_type == SWITCHABLE ?
                               SWITCHABLE_FILTERS : cm->mcomp_filter_type];
+      int64_t adj_rd;
       for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; i++) {
-        int64_t adj_rd;
-        // In cases of poor prediction, filter_cache[] can contain really big
-        // values, which actually are bigger than this_rd itself. This can
-        // cause negative best_filter_rd[] values, which is obviously silly.
-        // Therefore, if filter_cache < ref, we do an adjusted calculation.
-        if (cpi->rd_filter_cache[i] >= ref)
-          adj_rd = this_rd + cpi->rd_filter_cache[i] - ref;
-        else  // FIXME(rbultje) do this for comppred also
-          adj_rd = this_rd - (ref - cpi->rd_filter_cache[i]) * this_rd / ref;
+        if (ref == INT64_MAX)
+          adj_rd = 0;
+        else if (cpi->rd_filter_cache[i] == INT64_MAX)
+          // when early termination is triggered, the encoder does not have
+          // access to the rate-distortion cost. it only knows that the cost
+          // should be above the maximum valid value. hence it takes the known
+          // maximum plus an arbitrary constant as the rate-distortion cost.
+          adj_rd = cpi->mask_filter_rd - ref + 10;
+        else
+          adj_rd = cpi->rd_filter_cache[i] - ref;
+
+        adj_rd += this_rd;
         best_filter_rd[i] = MIN(best_filter_rd[i], adj_rd);
       }
     }
@@ -4493,8 +4517,7 @@
     vp9_zero(best_tx_diff);
   }
 
-  set_scale_factors(xd, mbmi->ref_frame[0], mbmi->ref_frame[1],
-                    scale_factor);
+  set_scale_factors(cm, xd, mbmi->ref_frame[0] - 1, mbmi->ref_frame[1] - 1);
   store_coding_context(x, ctx, best_mode_index,
                        &mbmi->ref_mvs[mbmi->ref_frame[0]][0],
                        &mbmi->ref_mvs[mbmi->ref_frame[1] < 0 ? 0 :
diff --git a/vp9/encoder/vp9_sadmxn.h b/vp9/encoder/vp9_sadmxn.h
index b2dfd63..1bae4dd 100644
--- a/vp9/encoder/vp9_sadmxn.h
+++ b/vp9/encoder/vp9_sadmxn.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef VP9_COMMON_VP9_SADMXN_H_
-#define VP9_COMMON_VP9_SADMXN_H_
+#ifndef VP9_ENCODER_VP9_SADMXN_H_
+#define VP9_ENCODER_VP9_SADMXN_H_
 
 #include "./vpx_config.h"
 #include "vpx/vpx_integer.h"
@@ -35,4 +35,4 @@
   return sad;
 }
 
-#endif  // VP9_COMMON_VP9_SADMXN_H_
+#endif  // VP9_ENCODER_VP9_SADMXN_H_
diff --git a/vp9/encoder/vp9_segmentation.c b/vp9/encoder/vp9_segmentation.c
index a9cdc9a..4568e7a 100644
--- a/vp9/encoder/vp9_segmentation.c
+++ b/vp9/encoder/vp9_segmentation.c
@@ -58,6 +58,15 @@
   // vpx_memcpy(cpi->mb.e_mbd.segment_feature_mask, 0,
   //            sizeof(cpi->mb.e_mbd.segment_feature_mask));
 }
+void vp9_disable_segfeature(struct segmentation *seg, int segment_id,
+                            SEG_LVL_FEATURES feature_id) {
+  seg->feature_mask[segment_id] &= ~(1 << feature_id);
+}
+
+void vp9_clear_segdata(struct segmentation *seg, int segment_id,
+                       SEG_LVL_FEATURES feature_id) {
+  seg->feature_data[segment_id][feature_id] = 0;
+}
 
 // Based on set of segment counts calculate a probability tree
 static void calc_segtree_probs(int *segcounts, vp9_prob *segment_tree_probs) {
diff --git a/vp9/encoder/vp9_segmentation.h b/vp9/encoder/vp9_segmentation.h
index 2183771..03f14ea 100644
--- a/vp9/encoder/vp9_segmentation.h
+++ b/vp9/encoder/vp9_segmentation.h
@@ -18,6 +18,12 @@
 void vp9_enable_segmentation(VP9_PTR ptr);
 void vp9_disable_segmentation(VP9_PTR ptr);
 
+void vp9_disable_segfeature(struct segmentation *seg,
+                            int segment_id,
+                            SEG_LVL_FEATURES feature_id);
+void vp9_clear_segdata(struct segmentation *seg,
+                       int segment_id,
+                       SEG_LVL_FEATURES feature_id);
 // Valid values for a segment are 0 to 3
 // Segmentation map is arrange as [Rows][Columns]
 void vp9_set_segmentation_map(VP9_PTR ptr, unsigned char *segmentation_map);
diff --git a/vp9/encoder/vp9_subexp.c b/vp9/encoder/vp9_subexp.c
index f31e568..def99d1 100644
--- a/vp9/encoder/vp9_subexp.c
+++ b/vp9/encoder/vp9_subexp.c
@@ -11,8 +11,8 @@
 #include "vp9/common/vp9_common.h"
 #include "vp9/common/vp9_entropy.h"
 
-#include "vp9/encoder/vp9_boolhuff.h"
 #include "vp9/encoder/vp9_treewriter.h"
+#include "vp9/encoder/vp9_writer.h"
 
 #define vp9_cost_upd256  ((int)(vp9_cost_one(upd) - vp9_cost_zero(upd)))
 
diff --git a/vp9/encoder/vp9_subexp.h b/vp9/encoder/vp9_subexp.h
index 521c777..1cafd87 100644
--- a/vp9/encoder/vp9_subexp.h
+++ b/vp9/encoder/vp9_subexp.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef VP9_DECODER_VP9_SUBEXP_H_
-#define VP9_DECODER_VP9_SUBEXP_H_
+#ifndef VP9_ENCODER_VP9_SUBEXP_H_
+#define VP9_ENCODER_VP9_SUBEXP_H_
 
 void vp9_compute_update_table();
 
@@ -32,4 +32,4 @@
                                               vp9_prob upd,
                                               int b, int r);
 
-#endif  // VP9_DECODER_VP9_SUBEXP_H_
+#endif  // VP9_ENCODER_VP9_SUBEXP_H_
diff --git a/vp9/encoder/vp9_temporal_filter.c b/vp9/encoder/vp9_temporal_filter.c
index 6d4075e..8762192 100644
--- a/vp9/encoder/vp9_temporal_filter.c
+++ b/vp9/encoder/vp9_temporal_filter.c
@@ -36,12 +36,23 @@
                                             uint8_t *u_mb_ptr,
                                             uint8_t *v_mb_ptr,
                                             int stride,
+                                            int uv_block_size,
                                             int mv_row,
                                             int mv_col,
                                             uint8_t *pred,
-                                            struct scale_factors *scale) {
+                                            struct scale_factors *scale,
+                                            int x, int y) {
   const int which_mv = 0;
   MV mv = { mv_row, mv_col };
+  enum mv_precision mv_precision_uv;
+  int uv_stride;
+  if (uv_block_size == 8) {
+    uv_stride = (stride + 1) >> 1;
+    mv_precision_uv = MV_PRECISION_Q4;
+  } else {
+    uv_stride = stride;
+    mv_precision_uv = MV_PRECISION_Q3;
+  }
 
   vp9_build_inter_predictor(y_mb_ptr, stride,
                             &pred[0], 16,
@@ -49,25 +60,23 @@
                             scale,
                             16, 16,
                             which_mv,
-                            &xd->subpix, MV_PRECISION_Q3);
+                            &xd->subpix, MV_PRECISION_Q3, x, y);
 
-  stride = (stride + 1) >> 1;
-
-  vp9_build_inter_predictor(u_mb_ptr, stride,
-                            &pred[256], 8,
+  vp9_build_inter_predictor(u_mb_ptr, uv_stride,
+                            &pred[256], uv_block_size,
                             &mv,
                             scale,
-                            8, 8,
+                            uv_block_size, uv_block_size,
                             which_mv,
-                            &xd->subpix, MV_PRECISION_Q4);
+                            &xd->subpix, mv_precision_uv, x, y);
 
-  vp9_build_inter_predictor(v_mb_ptr, stride,
-                            &pred[320], 8,
+  vp9_build_inter_predictor(v_mb_ptr, uv_stride,
+                            &pred[512], uv_block_size,
                             &mv,
                             scale,
-                            8, 8,
+                            uv_block_size, uv_block_size,
                             which_mv,
-                            &xd->subpix, MV_PRECISION_Q4);
+                            &xd->subpix, mv_precision_uv, x, y);
 }
 
 void vp9_temporal_filter_apply_c(uint8_t *frame1,
@@ -197,17 +206,21 @@
   int mb_rows = cpi->common.mb_rows;
   int mb_y_offset = 0;
   int mb_uv_offset = 0;
-  DECLARE_ALIGNED_ARRAY(16, unsigned int, accumulator, 16 * 16 + 8 * 8 + 8 * 8);
-  DECLARE_ALIGNED_ARRAY(16, uint16_t, count, 16 * 16 + 8 * 8 + 8 * 8);
+  DECLARE_ALIGNED_ARRAY(16, unsigned int, accumulator, 16 * 16 * 3);
+  DECLARE_ALIGNED_ARRAY(16, uint16_t, count, 16 * 16 * 3);
   MACROBLOCKD *mbd = &cpi->mb.e_mbd;
   YV12_BUFFER_CONFIG *f = cpi->frames[alt_ref_index];
   uint8_t *dst1, *dst2;
-  DECLARE_ALIGNED_ARRAY(16, uint8_t,  predictor, 16 * 16 + 8 * 8 + 8 * 8);
+  DECLARE_ALIGNED_ARRAY(16, uint8_t,  predictor, 16 * 16 * 3);
+  const int mb_uv_height = 16 >> mbd->plane[1].subsampling_y;
 
   // Save input state
   uint8_t* input_buffer[MAX_MB_PLANE];
   int i;
 
+  // TODO(aconverse): Add 4:2:2 support
+  assert(mbd->plane[1].subsampling_x == mbd->plane[1].subsampling_y);
+
   for (i = 0; i < MAX_MB_PLANE; i++)
     input_buffer[i] = mbd->plane[i].pre[0].buf;
 
@@ -233,8 +246,8 @@
       int i, j, k;
       int stride;
 
-      vpx_memset(accumulator, 0, 384 * sizeof(unsigned int));
-      vpx_memset(count, 0, 384 * sizeof(uint16_t));
+      vpx_memset(accumulator, 0, 16 * 16 * 3 * sizeof(accumulator[0]));
+      vpx_memset(count, 0, 16 * 16 * 3 * sizeof(count[0]));
 
 #if ALT_REF_MC_ENABLED
       cpi->mb.mv_col_min = -((mb_col * 16) + (17 - 2 * VP9_INTERP_EXTEND));
@@ -280,9 +293,11 @@
            cpi->frames[frame]->u_buffer + mb_uv_offset,
            cpi->frames[frame]->v_buffer + mb_uv_offset,
            cpi->frames[frame]->y_stride,
+           mb_uv_height,
            mbd->mi_8x8[0]->bmi[0].as_mv[0].as_mv.row,
            mbd->mi_8x8[0]->bmi[0].as_mv[0].as_mv.col,
-           predictor, scale);
+           predictor, scale,
+           mb_col * 16, mb_row * 16);
 
           // Apply the filter (YUV)
           vp9_temporal_filter_apply(f->y_buffer + mb_y_offset, f->y_stride,
@@ -290,12 +305,14 @@
                                     accumulator, count);
 
           vp9_temporal_filter_apply(f->u_buffer + mb_uv_offset, f->uv_stride,
-                                    predictor + 256, 8, strength, filter_weight,
-                                    accumulator + 256, count + 256);
+                                    predictor + 256, mb_uv_height, strength,
+                                    filter_weight, accumulator + 256,
+                                    count + 256);
 
           vp9_temporal_filter_apply(f->v_buffer + mb_uv_offset, f->uv_stride,
-                                    predictor + 320, 8, strength, filter_weight,
-                                    accumulator + 320, count + 320);
+                                    predictor + 512, mb_uv_height, strength,
+                                    filter_weight, accumulator + 512,
+                                    count + 512);
         }
       }
 
@@ -322,9 +339,9 @@
       dst2 = cpi->alt_ref_buffer.v_buffer;
       stride = cpi->alt_ref_buffer.uv_stride;
       byte = mb_uv_offset;
-      for (i = 0, k = 256; i < 8; i++) {
-        for (j = 0; j < 8; j++, k++) {
-          int m = k + 64;
+      for (i = 0, k = 256; i < mb_uv_height; i++) {
+        for (j = 0; j < mb_uv_height; j++, k++) {
+          int m = k + 256;
 
           // U
           unsigned int pval = accumulator[k] + (count[k] >> 1);
@@ -342,15 +359,15 @@
           byte++;
         }
 
-        byte += stride - 8;
+        byte += stride - mb_uv_height;
       }
 
       mb_y_offset += 16;
-      mb_uv_offset += 8;
+      mb_uv_offset += mb_uv_height;
     }
 
     mb_y_offset += 16 * (f->y_stride - mb_cols);
-    mb_uv_offset += 8 * (f->uv_stride - mb_cols);
+    mb_uv_offset += mb_uv_height * (f->uv_stride - mb_cols);
   }
 
   // Restore input state
@@ -376,8 +393,7 @@
   const int num_frames_forward = vp9_lookahead_depth(cpi->lookahead)
                                - (num_frames_backward + 1);
 
-  struct scale_factors scale;
-  struct scale_factors_common scale_comm;
+  struct scale_factors sf;
 
   switch (blur_type) {
     case 1:
@@ -437,7 +453,7 @@
 #endif
 
   // Setup scaling factors. Scaling on each of the arnr frames is not supported
-  vp9_setup_scale_factors_for_frame(&scale, &scale_comm,
+  vp9_setup_scale_factors_for_frame(&sf,
       get_frame_new_buffer(cm)->y_crop_width,
       get_frame_new_buffer(cm)->y_crop_height,
       cm->width, cm->height);
@@ -452,7 +468,7 @@
   }
 
   temporal_filter_iterate_c(cpi, frames_to_blur, frames_to_blur_backward,
-                            strength, &scale);
+                            strength, &sf);
 }
 
 void configure_arnr_filter(VP9_COMP *cpi, const unsigned int this_frame,
diff --git a/vp9/encoder/vp9_treewriter.h b/vp9/encoder/vp9_treewriter.h
index a2f9df1..09f80b0 100644
--- a/vp9/encoder/vp9_treewriter.h
+++ b/vp9/encoder/vp9_treewriter.h
@@ -8,18 +8,10 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-
 #ifndef VP9_ENCODER_VP9_TREEWRITER_H_
 #define VP9_ENCODER_VP9_TREEWRITER_H_
 
-/* Trees map alphabets into huffman-like codes suitable for an arithmetic
-   bit coder.  Timothy S Murphy  11 October 2004 */
-
-#include "vp9/common/vp9_treecoder.h"
-
-#include "vp9/encoder/vp9_boolhuff.h"       /* for now */
-
-#define vp9_write_prob(w, v) vp9_write_literal((w), (v), 8)
+#include "vp9/encoder/vp9_writer.h"
 
 #define vp9_cost_zero(prob) (vp9_prob_cost[prob])
 
@@ -33,31 +25,6 @@
   return ct[0] * vp9_cost_zero(p) + ct[1] * vp9_cost_one(p);
 }
 
-static INLINE void treed_write(vp9_writer *w,
-                               vp9_tree tree, const vp9_prob *probs,
-                               int bits, int len,
-                               vp9_tree_index i) {
-  do {
-    const int bit = (bits >> --len) & 1;
-    vp9_write(w, bit, probs[i >> 1]);
-    i = tree[i + bit];
-  } while (len);
-}
-
-struct vp9_token {
-  int value;
-  int len;
-};
-
-
-void vp9_tokens_from_tree(struct vp9_token*, const vp9_tree_index *);
-
-static INLINE void write_token(vp9_writer *w, vp9_tree tree,
-                               const vp9_prob *probs,
-                               const struct vp9_token *token) {
-  treed_write(w, tree, probs, token->value, token->len, 0);
-}
-
 static INLINE int treed_cost(vp9_tree tree, const vp9_prob *probs,
                              int bits, int len) {
   int cost = 0;
@@ -79,4 +46,27 @@
                                       unsigned int branch_ct[ /* n - 1 */ ][2],
                                       const unsigned int num_events[ /* n */ ]);
 
+struct vp9_token {
+  int value;
+  int len;
+};
+
+void vp9_tokens_from_tree(struct vp9_token*, const vp9_tree_index *);
+
+static INLINE void vp9_write_tree(vp9_writer *w, const vp9_tree_index *tree,
+                                  const vp9_prob *probs, int bits, int len,
+                                  vp9_tree_index i) {
+  do {
+    const int bit = (bits >> --len) & 1;
+    vp9_write(w, bit, probs[i >> 1]);
+    i = tree[i + bit];
+  } while (len);
+}
+
+static INLINE void vp9_write_token(vp9_writer *w, const vp9_tree_index *tree,
+                                   const vp9_prob *probs,
+                                   const struct vp9_token *token) {
+  vp9_write_tree(w, tree, probs, token->value, token->len, 0);
+}
+
 #endif  // VP9_ENCODER_VP9_TREEWRITER_H_
diff --git a/vp9/encoder/vp9_vaq.h b/vp9/encoder/vp9_vaq.h
index dc18b22..c45c479 100644
--- a/vp9/encoder/vp9_vaq.h
+++ b/vp9/encoder/vp9_vaq.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef VP9_ENCODER_VP9_CONFIG_VAQ_H_
-#define VP9_ENCODER_VP9_CONFIG_VAQ_H_
+#ifndef VP9_ENCODER_VP9_VAQ_H_
+#define VP9_ENCODER_VP9_VAQ_H_
 
 #include "vp9/encoder/vp9_onyx_int.h"
 
@@ -23,4 +23,4 @@
 
 int vp9_block_energy(VP9_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bs);
 
-#endif  // VP9_ENCODER_VP9_CONFIG_VAQ_H_
+#endif  // VP9_ENCODER_VP9_VAQ_H_
diff --git a/vp9/encoder/vp9_write_bit_buffer.h b/vp9/encoder/vp9_write_bit_buffer.h
index 6f91cfc..dfed903 100644
--- a/vp9/encoder/vp9_write_bit_buffer.h
+++ b/vp9/encoder/vp9_write_bit_buffer.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef VP9_BIT_WRITE_BUFFER_H_
-#define VP9_BIT_WRITE_BUFFER_H_
+#ifndef VP9_ENCODER_VP9_WRITE_BIT_BUFFER_H_
+#define VP9_ENCODER_VP9_WRITE_BIT_BUFFER_H_
 
 #include <limits.h>
 
@@ -45,4 +45,4 @@
 }
 
 
-#endif  // VP9_BIT_WRITE_BUFFER_H_
+#endif  // VP9_ENCODER_VP9_WRITE_BIT_BUFFER_H_
diff --git a/vp9/encoder/vp9_boolhuff.c b/vp9/encoder/vp9_writer.c
similarity index 98%
rename from vp9/encoder/vp9_boolhuff.c
rename to vp9/encoder/vp9_writer.c
index 32c136e..3d13d07 100644
--- a/vp9/encoder/vp9_boolhuff.c
+++ b/vp9/encoder/vp9_writer.c
@@ -9,7 +9,7 @@
  */
 
 #include <assert.h>
-#include "vp9/encoder/vp9_boolhuff.h"
+#include "vp9/encoder/vp9_writer.h"
 #include "vp9/common/vp9_entropy.h"
 
 #if defined(SECTIONBITS_OUTPUT)
diff --git a/vp9/encoder/vp9_boolhuff.h b/vp9/encoder/vp9_writer.h
similarity index 83%
rename from vp9/encoder/vp9_boolhuff.h
rename to vp9/encoder/vp9_writer.h
index c3f340d..9cac7a8 100644
--- a/vp9/encoder/vp9_boolhuff.h
+++ b/vp9/encoder/vp9_writer.h
@@ -8,19 +8,13 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-
-/****************************************************************************
-*
-*   Module Title :     vp9_boolhuff.h
-*
-*   Description  :     Bool Coder header file.
-*
-****************************************************************************/
-#ifndef VP9_ENCODER_VP9_BOOLHUFF_H_
-#define VP9_ENCODER_VP9_BOOLHUFF_H_
+#ifndef VP9_ENCODER_VP9_WRITER_H_
+#define VP9_ENCODER_VP9_WRITER_H_
 
 #include "vpx_ports/mem.h"
 
+#include "vp9/common/vp9_prob.h"
+
 typedef struct {
   unsigned int lowvalue;
   unsigned int range;
@@ -31,7 +25,7 @@
 
   // Variables used to track bit costs without outputing to the bitstream
   unsigned int  measure_cost;
-  unsigned long bit_counter;
+  uint64_t bit_counter;
 } vp9_writer;
 
 extern const unsigned int vp9_prob_cost[256];
@@ -39,8 +33,6 @@
 void vp9_start_encode(vp9_writer *bc, uint8_t *buffer);
 void vp9_stop_encode(vp9_writer *bc);
 
-DECLARE_ALIGNED(16, extern const unsigned char, vp9_norm[256]);
-
 static void vp9_write(vp9_writer *br, int bit, int probability) {
   unsigned int split;
   int count = br->count;
@@ -111,5 +103,6 @@
     vp9_write_bit(w, 1 & (data >> bit));
 }
 
+#define vp9_write_prob(w, v) vp9_write_literal((w), (v), 8)
 
-#endif  // VP9_ENCODER_VP9_BOOLHUFF_H_
+#endif  // VP9_ENCODER_VP9_WRITER_H_
diff --git a/vp9/encoder/x86/vp9_mcomp_x86.h b/vp9/encoder/x86/vp9_mcomp_x86.h
index ca80b8b..e1fcf40 100644
--- a/vp9/encoder/x86/vp9_mcomp_x86.h
+++ b/vp9/encoder/x86/vp9_mcomp_x86.h
@@ -36,5 +36,5 @@
 #endif
 #endif
 
-#endif
+#endif  // VP9_ENCODER_X86_VP9_MCOMP_X86_H_
 
diff --git a/vp9/exports_enc b/vp9/exports_enc
index 25156e8..2a0fef3 100644
--- a/vp9/exports_enc
+++ b/vp9/exports_enc
@@ -1,4 +1,2 @@
 data vpx_codec_vp9_cx_algo
 text vpx_codec_vp9_cx
-data vpx_codec_vp9x_cx_algo
-text vpx_codec_vp9x_cx
diff --git a/vp9/vp9_common.mk b/vp9/vp9_common.mk
index 01c55a4..7818756 100644
--- a/vp9/vp9_common.mk
+++ b/vp9/vp9_common.mk
@@ -22,7 +22,6 @@
 VP9_COMMON_SRCS-yes += common/vp9_entropymv.c
 VP9_COMMON_SRCS-yes += common/vp9_filter.c
 VP9_COMMON_SRCS-yes += common/vp9_filter.h
-VP9_COMMON_SRCS-yes += common/vp9_findnearmv.c
 VP9_COMMON_SRCS-yes += common/generic/vp9_systemdependent.c
 VP9_COMMON_SRCS-yes += common/vp9_idct.c
 VP9_COMMON_SRCS-yes += common/vp9_alloccommon.h
@@ -32,13 +31,14 @@
 VP9_COMMON_SRCS-yes += common/vp9_entropymode.h
 VP9_COMMON_SRCS-yes += common/vp9_entropymv.h
 VP9_COMMON_SRCS-yes += common/vp9_enums.h
-VP9_COMMON_SRCS-yes += common/vp9_findnearmv.h
 VP9_COMMON_SRCS-yes += common/vp9_idct.h
 VP9_COMMON_SRCS-yes += common/vp9_loopfilter.h
 VP9_COMMON_SRCS-yes += common/vp9_mv.h
 VP9_COMMON_SRCS-yes += common/vp9_onyxc_int.h
 VP9_COMMON_SRCS-yes += common/vp9_pred_common.h
 VP9_COMMON_SRCS-yes += common/vp9_pred_common.c
+VP9_COMMON_SRCS-yes += common/vp9_prob.h
+VP9_COMMON_SRCS-yes += common/vp9_prob.c
 VP9_COMMON_SRCS-yes += common/vp9_quant_common.h
 VP9_COMMON_SRCS-yes += common/vp9_reconinter.h
 VP9_COMMON_SRCS-yes += common/vp9_reconintra.h
@@ -52,7 +52,6 @@
 VP9_COMMON_SRCS-yes += common/vp9_textblit.h
 VP9_COMMON_SRCS-yes += common/vp9_tile_common.h
 VP9_COMMON_SRCS-yes += common/vp9_tile_common.c
-VP9_COMMON_SRCS-yes += common/vp9_treecoder.h
 VP9_COMMON_SRCS-yes += common/vp9_loopfilter.c
 VP9_COMMON_SRCS-yes += common/vp9_loopfilter_filters.c
 VP9_COMMON_SRCS-yes += common/vp9_mvref_common.c
diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c
index 5d53a41..5bd9bf1 100644
--- a/vp9/vp9_cx_iface.c
+++ b/vp9/vp9_cx_iface.c
@@ -32,7 +32,6 @@
   unsigned int                arnr_max_frames;
   unsigned int                arnr_strength;
   unsigned int                arnr_type;
-  unsigned int                experimental;
   vp8e_tuning                 tuning;
   unsigned int                cq_level;         /* constrained quality level */
   unsigned int                rc_max_intra_bitrate_pct;
@@ -61,7 +60,6 @@
       7,                          /* arnr_max_frames */
       5,                          /* arnr_strength */
       3,                          /* arnr_type*/
-      0,                          /* experimental mode */
       0,                          /* tuning*/
       10,                         /* cq_level */
       0,                          /* rc_max_intra_bitrate_pct */
@@ -77,14 +75,14 @@
   vpx_codec_enc_cfg_t     cfg;
   struct vp9_extracfg     vp8_cfg;
   VP9_CONFIG              oxcf;
-  VP9_PTR             cpi;
+  VP9_PTR                 cpi;
   unsigned char          *cx_data;
-  unsigned int            cx_data_sz;
+  size_t                  cx_data_sz;
   unsigned char          *pending_cx_data;
-  unsigned int            pending_cx_data_sz;
+  size_t                  pending_cx_data_sz;
   int                     pending_frame_count;
-  uint32_t                pending_frame_sizes[8];
-  uint32_t                pending_frame_magnitude;
+  size_t                  pending_frame_sizes[8];
+  size_t                  pending_frame_magnitude;
   vpx_image_t             preview_img;
   vp8_postproc_cfg_t      preview_ppcfg;
   vpx_codec_pkt_list_decl(64) pkt_list;
@@ -100,7 +98,7 @@
     case VP8_ALTR_FRAME:
       return VP9_ALT_FLAG;
   }
-  assert(!"Invalid Reference Frame");
+  assert(0 && "Invalid Reference Frame");
   return VP9_LAST_FLAG;
 }
 
@@ -250,7 +248,7 @@
 static vpx_codec_err_t set_vp9e_config(VP9_CONFIG *oxcf,
                                        vpx_codec_enc_cfg_t cfg,
                                        struct vp9_extracfg vp8_cfg) {
-  oxcf->version = cfg.g_profile | (vp8_cfg.experimental ? 0x4 : 0);
+  oxcf->version = cfg.g_profile;
   oxcf->width   = cfg.g_w;
   oxcf->height  = cfg.g_h;
   /* guess a frame rate if out of whack, use 30 */
@@ -307,6 +305,8 @@
   oxcf->starting_buffer_level   = cfg.rc_buf_initial_sz;
   oxcf->optimal_buffer_level    = cfg.rc_buf_optimal_sz;
 
+  oxcf->drop_frames_water_mark   = cfg.rc_dropframe_thresh;
+
   oxcf->two_pass_vbrbias         = cfg.rc_2pass_vbr_bias_pct;
   oxcf->two_pass_vbrmin_section  = cfg.rc_2pass_vbr_minsection_pct;
   oxcf->two_pass_vbrmax_section  = cfg.rc_2pass_vbr_maxsection_pct;
@@ -470,8 +470,7 @@
 }
 
 
-static vpx_codec_err_t vp9e_common_init(vpx_codec_ctx_t *ctx,
-                                        int              experimental) {
+static vpx_codec_err_t vp9e_common_init(vpx_codec_ctx_t *ctx) {
   vpx_codec_err_t            res = VPX_CODEC_OK;
   struct vpx_codec_alg_priv *priv;
   vpx_codec_enc_cfg_t       *cfg;
@@ -513,7 +512,6 @@
 
     priv->vp8_cfg = extracfg_map[i].cfg;
     priv->vp8_cfg.pkt_list = &priv->pkt_list.head;
-    priv->vp8_cfg.experimental = experimental;
 
     // TODO(agrange) Check the limits set on this buffer, or the check that is
     // applied in vp9e_encode.
@@ -551,18 +549,9 @@
 
 static vpx_codec_err_t vp9e_init(vpx_codec_ctx_t *ctx,
                                  vpx_codec_priv_enc_mr_cfg_t *data) {
-  return vp9e_common_init(ctx, 0);
+  return vp9e_common_init(ctx);
 }
 
-
-#if CONFIG_EXPERIMENTAL
-static vpx_codec_err_t vp9e_exp_init(vpx_codec_ctx_t *ctx,
-                                     vpx_codec_priv_enc_mr_cfg_t *data) {
-  return vp9e_common_init(ctx, 1);
-}
-#endif
-
-
 static vpx_codec_err_t vp9e_destroy(vpx_codec_alg_priv_t *ctx) {
   free(ctx->cx_data);
   vp9_remove_compressor(&ctx->cpi);
@@ -708,7 +697,7 @@
     unsigned int lib_flags;
     YV12_BUFFER_CONFIG sd;
     int64_t dst_time_stamp, dst_end_time_stamp;
-    unsigned long size, cx_data_sz;
+    size_t size, cx_data_sz;
     unsigned char *cx_data;
 
     /* Set up internal flags */
@@ -1175,33 +1164,3 @@
     vp9e_get_preview,
   } /* encoder functions */
 };
-
-
-#if CONFIG_EXPERIMENTAL
-
-CODEC_INTERFACE(vpx_codec_vp9x_cx) = {
-  "VP8 Experimental Encoder" VERSION_STRING,
-  VPX_CODEC_INTERNAL_ABI_VERSION,
-  VPX_CODEC_CAP_ENCODER | VPX_CODEC_CAP_PSNR,
-  /* vpx_codec_caps_t          caps; */
-  vp9e_exp_init,      /* vpx_codec_init_fn_t       init; */
-  vp9e_destroy,       /* vpx_codec_destroy_fn_t    destroy; */
-  vp9e_ctf_maps,      /* vpx_codec_ctrl_fn_map_t  *ctrl_maps; */
-  NOT_IMPLEMENTED,    /* vpx_codec_get_mmap_fn_t   get_mmap; */
-  NOT_IMPLEMENTED,    /* vpx_codec_set_mmap_fn_t   set_mmap; */
-  {  // NOLINT
-    NOT_IMPLEMENTED,    /* vpx_codec_peek_si_fn_t    peek_si; */
-    NOT_IMPLEMENTED,    /* vpx_codec_get_si_fn_t     get_si; */
-    NOT_IMPLEMENTED,    /* vpx_codec_decode_fn_t     decode; */
-    NOT_IMPLEMENTED,    /* vpx_codec_frame_get_fn_t  frame_get; */
-  },
-  {  // NOLINT
-    vp9e_usage_cfg_map, /* vpx_codec_enc_cfg_map_t    peek_si; */
-    vp9e_encode,        /* vpx_codec_encode_fn_t      encode; */
-    vp9e_get_cxdata,    /* vpx_codec_get_cx_data_fn_t   frame_get; */
-    vp9e_set_config,
-    NOT_IMPLEMENTED,
-    vp9e_get_preview,
-  } /* encoder functions */
-};
-#endif
diff --git a/vp9/vp9_dx_iface.c b/vp9/vp9_dx_iface.c
index fde73e4..a7d2e1d 100644
--- a/vp9/vp9_dx_iface.c
+++ b/vp9/vp9_dx_iface.c
@@ -59,6 +59,13 @@
   int                     img_setup;
   int                     img_avail;
   int                     invert_tile_order;
+  int                     fb_lru;
+
+  /* External buffer info to save for VP9 common. */
+  vpx_codec_frame_buffer_t *fb_list;  // External frame buffers
+  int fb_count;  // Total number of frame buffers
+  vpx_realloc_frame_buffer_cb_fn_t realloc_fb_cb;
+  void *user_priv;  // Private data associated with the external frame buffers.
 };
 
 static unsigned long priv_sz(const vpx_codec_dec_cfg_t *si,
@@ -153,7 +160,8 @@
     struct vp9_read_bit_buffer rb = { data, data + data_sz, 0, NULL, NULL };
     const int frame_marker = vp9_rb_read_literal(&rb, 2);
     const int version = vp9_rb_read_bit(&rb) | (vp9_rb_read_bit(&rb) << 1);
-    if (frame_marker != 0x2) return VPX_CODEC_UNSUP_BITSTREAM;
+    if (frame_marker != VP9_FRAME_MARKER)
+      return VPX_CODEC_UNSUP_BITSTREAM;
 #if CONFIG_NON420
     if (version > 1) return VPX_CODEC_UNSUP_BITSTREAM;
 #else
@@ -307,10 +315,32 @@
         ctx->postproc_cfg.noise_level = 0;
       }
 
-      if (!optr)
+      if (!optr) {
         res = VPX_CODEC_ERROR;
-      else
+      } else {
+        VP9D_COMP *const pbi = (VP9D_COMP*)optr;
+        VP9_COMMON *const cm = &pbi->common;
+        if (ctx->fb_list != NULL && ctx->realloc_fb_cb != NULL &&
+            ctx->fb_count > 0) {
+          cm->fb_list = ctx->fb_list;
+          cm->fb_count = ctx->fb_count;
+          cm->realloc_fb_cb = ctx->realloc_fb_cb;
+          cm->user_priv = ctx->user_priv;
+        } else {
+          cm->fb_count = FRAME_BUFFERS;
+        }
+        cm->fb_lru = ctx->fb_lru;
+        CHECK_MEM_ERROR(cm, cm->yv12_fb,
+                        vpx_calloc(cm->fb_count, sizeof(*cm->yv12_fb)));
+        CHECK_MEM_ERROR(cm, cm->fb_idx_ref_cnt,
+                        vpx_calloc(cm->fb_count, sizeof(*cm->fb_idx_ref_cnt)));
+        if (cm->fb_lru) {
+          CHECK_MEM_ERROR(cm, cm->fb_idx_ref_lru,
+                          vpx_calloc(cm->fb_count,
+                                     sizeof(*cm->fb_idx_ref_lru)));
+        }
         ctx->pbi = optr;
+      }
     }
 
     ctx->decoder_init = 1;
@@ -347,7 +377,7 @@
     }
 
     if (vp9_receive_compressed_data(ctx->pbi, data_sz, data, deadline)) {
-      VP9D_COMP *pbi = (VP9D_COMP *)ctx->pbi;
+      VP9D_COMP *pbi = (VP9D_COMP*)ctx->pbi;
       res = update_error_state(ctx, &pbi->common.error);
     }
 
@@ -475,6 +505,28 @@
   return img;
 }
 
+static vpx_codec_err_t vp9_set_frame_buffers(
+    vpx_codec_alg_priv_t *ctx,
+    vpx_codec_frame_buffer_t *fb_list, int fb_count,
+    vpx_realloc_frame_buffer_cb_fn_t cb, void *user_priv) {
+  if (fb_count < (VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS)) {
+    /* The application must pass in at least VP9_MAXIMUM_REF_BUFFERS +
+     * VPX_MAXIMUM_WORK_BUFFERS frame buffers. */
+    return VPX_CODEC_INVALID_PARAM;
+  } else if (!ctx->pbi) {
+    /* If the decoder has already been initialized, do not accept external
+     * frame buffers.
+     */
+    ctx->fb_list = fb_list;
+    ctx->fb_count = fb_count;
+    ctx->realloc_fb_cb = cb;
+    ctx->user_priv = user_priv;
+    return VPX_CODEC_OK;
+  }
+
+  return VPX_CODEC_ERROR;
+}
+
 static vpx_codec_err_t vp9_xma_get_mmap(const vpx_codec_ctx_t      *ctx,
                                         vpx_codec_mmap_t           *mmap,
                                         vpx_codec_iter_t           *iter) {
@@ -639,7 +691,7 @@
                                             int ctrl_id,
                                             va_list args) {
   int *update_info = va_arg(args, int *);
-  VP9D_COMP *pbi = (VP9D_COMP *)ctx->pbi;
+  VP9D_COMP *pbi = (VP9D_COMP*)ctx->pbi;
 
   if (update_info) {
     *update_info = pbi->refresh_frame_flags;
@@ -657,7 +709,7 @@
   int *corrupted = va_arg(args, int *);
 
   if (corrupted) {
-    VP9D_COMP *pbi = (VP9D_COMP *)ctx->pbi;
+    VP9D_COMP *pbi = (VP9D_COMP*)ctx->pbi;
     if (pbi)
       *corrupted = pbi->common.frame_to_show->corrupted;
     else
@@ -674,7 +726,7 @@
   int *const display_size = va_arg(args, int *);
 
   if (display_size) {
-    const VP9D_COMP *const pbi = (VP9D_COMP *)ctx->pbi;
+    const VP9D_COMP *const pbi = (VP9D_COMP*)ctx->pbi;
     if (pbi) {
       display_size[0] = pbi->common.display_width;
       display_size[1] = pbi->common.display_height;
@@ -694,6 +746,21 @@
   return VPX_CODEC_OK;
 }
 
+static vpx_codec_err_t set_frame_buffer_lru_cache(vpx_codec_alg_priv_t *ctx,
+                                                  int ctr_id,
+                                                  va_list args) {
+  VP9D_COMP *const pbi = (VP9D_COMP*)ctx->pbi;
+
+  // Save for later to pass into vp9 common.
+  ctx->fb_lru = va_arg(args, int);
+
+  if (pbi) {
+    VP9_COMMON *const cm = &pbi->common;
+    cm->fb_lru = ctx->fb_lru;
+  }
+  return VPX_CODEC_OK;
+}
+
 static vpx_codec_ctrl_fn_map_t ctf_maps[] = {
   {VP8_SET_REFERENCE,             set_reference},
   {VP8_COPY_REFERENCE,            copy_reference},
@@ -707,6 +774,7 @@
   {VP9_GET_REFERENCE,             get_reference},
   {VP9D_GET_DISPLAY_SIZE,         get_display_size},
   {VP9_INVERT_TILE_DECODE_ORDER,  set_invert_tile_order},
+  {VP9D_SET_FRAME_BUFFER_LRU_CACHE, set_frame_buffer_lru_cache},
   { -1, NULL},
 };
 
@@ -717,7 +785,8 @@
 CODEC_INTERFACE(vpx_codec_vp9_dx) = {
   "WebM Project VP9 Decoder" VERSION_STRING,
   VPX_CODEC_INTERNAL_ABI_VERSION,
-  VPX_CODEC_CAP_DECODER | VP9_CAP_POSTPROC,
+  VPX_CODEC_CAP_DECODER | VP9_CAP_POSTPROC |
+      VPX_CODEC_CAP_EXTERNAL_FRAME_BUFFER,
   /* vpx_codec_caps_t          caps; */
   vp9_init,         /* vpx_codec_init_fn_t       init; */
   vp9_destroy,      /* vpx_codec_destroy_fn_t    destroy; */
@@ -729,6 +798,7 @@
     vp9_get_si,       /* vpx_codec_get_si_fn_t     get_si; */
     vp9_decode,       /* vpx_codec_decode_fn_t     decode; */
     vp9_get_frame,    /* vpx_codec_frame_get_fn_t  frame_get; */
+    vp9_set_frame_buffers,    /* vpx_codec_set_frame_buffers_fn_t  set_fb; */
   },
   { // NOLINT
     /* encoder functions */
diff --git a/vp9/vp9cx.mk b/vp9/vp9cx.mk
index ce83a67..9114a30 100644
--- a/vp9/vp9cx.mk
+++ b/vp9/vp9cx.mk
@@ -18,7 +18,6 @@
 VP9_CX_SRCS-yes += vp9_cx_iface.c
 
 VP9_CX_SRCS-yes += encoder/vp9_bitstream.c
-VP9_CX_SRCS-yes += encoder/vp9_boolhuff.c
 VP9_CX_SRCS-yes += encoder/vp9_dct.c
 VP9_CX_SRCS-yes += encoder/vp9_dct.h
 VP9_CX_SRCS-yes += encoder/vp9_encodeframe.c
@@ -28,7 +27,8 @@
 VP9_CX_SRCS-yes += encoder/vp9_extend.c
 VP9_CX_SRCS-yes += encoder/vp9_firstpass.c
 VP9_CX_SRCS-yes += encoder/vp9_block.h
-VP9_CX_SRCS-yes += encoder/vp9_boolhuff.h
+VP9_CX_SRCS-yes += encoder/vp9_writer.h
+VP9_CX_SRCS-yes += encoder/vp9_writer.c
 VP9_CX_SRCS-yes += encoder/vp9_write_bit_buffer.h
 VP9_CX_SRCS-yes += encoder/vp9_bitstream.h
 VP9_CX_SRCS-yes += encoder/vp9_encodemb.h
diff --git a/vp9/vp9dx.mk b/vp9/vp9dx.mk
index f431721..b722200 100644
--- a/vp9/vp9dx.mk
+++ b/vp9/vp9dx.mk
@@ -17,12 +17,12 @@
 
 VP9_DX_SRCS-yes += vp9_dx_iface.c
 
-VP9_DX_SRCS-yes += decoder/vp9_dboolhuff.c
 VP9_DX_SRCS-yes += decoder/vp9_decodemv.c
 VP9_DX_SRCS-yes += decoder/vp9_decodeframe.c
 VP9_DX_SRCS-yes += decoder/vp9_decodeframe.h
 VP9_DX_SRCS-yes += decoder/vp9_detokenize.c
-VP9_DX_SRCS-yes += decoder/vp9_dboolhuff.h
+VP9_DX_SRCS-yes += decoder/vp9_reader.h
+VP9_DX_SRCS-yes += decoder/vp9_reader.c
 VP9_DX_SRCS-yes += decoder/vp9_read_bit_buffer.h
 VP9_DX_SRCS-yes += decoder/vp9_decodemv.h
 VP9_DX_SRCS-yes += decoder/vp9_detokenize.h
diff --git a/vpx/exports_dec b/vpx/exports_dec
index ed121f7..d058c9b 100644
--- a/vpx/exports_dec
+++ b/vpx/exports_dec
@@ -7,3 +7,4 @@
 text vpx_codec_register_put_frame_cb
 text vpx_codec_register_put_slice_cb
 text vpx_codec_set_mem_map
+text vpx_codec_set_frame_buffers
diff --git a/vpx/internal/vpx_codec_internal.h b/vpx/internal/vpx_codec_internal.h
index 05fed97..6c644f0 100644
--- a/vpx/internal/vpx_codec_internal.h
+++ b/vpx/internal/vpx_codec_internal.h
@@ -41,8 +41,8 @@
  * Once initialized, the instance is manged using other functions from
  * the vpx_codec_* family.
  */
-#ifndef VPX_CODEC_INTERNAL_H
-#define VPX_CODEC_INTERNAL_H
+#ifndef VPX_INTERNAL_VPX_CODEC_INTERNAL_H_
+#define VPX_INTERNAL_VPX_CODEC_INTERNAL_H_
 #include "../vpx_decoder.h"
 #include "../vpx_encoder.h"
 #include <stdarg.h>
@@ -56,7 +56,7 @@
  * types, removing or reassigning enums, adding/removing/rearranging
  * fields to structures
  */
-#define VPX_CODEC_INTERNAL_ABI_VERSION (4) /**<\hideinitializer*/
+#define VPX_CODEC_INTERNAL_ABI_VERSION (5) /**<\hideinitializer*/
 
 typedef struct vpx_codec_alg_priv  vpx_codec_alg_priv_t;
 typedef struct vpx_codec_priv_enc_mr_cfg vpx_codec_priv_enc_mr_cfg_t;
@@ -215,6 +215,37 @@
 typedef vpx_image_t *(*vpx_codec_get_frame_fn_t)(vpx_codec_alg_priv_t *ctx,
                                                  vpx_codec_iter_t     *iter);
 
+/*!\brief Pass in external frame buffers for the decoder to use.
+ *
+ * Registers a given function to be called when the current frame to
+ * decode will be bigger than the external frame buffer size. This
+ * function must be called before the first call to decode or libvpx
+ * will assume the default behavior of allocating frame buffers internally.
+ * Frame buffers with a size of 0 are valid.
+ *
+ * \param[in] ctx          Pointer to this instance's context
+ * \param[in] fb_list      Pointer to array of frame buffers
+ * \param[in] fb_count     Number of elements in frame buffer array
+ * \param[in] cb           Pointer to the callback function
+ * \param[in] user_priv    User's private data
+ *
+ * \retval #VPX_CODEC_OK
+ *     External frame buffers will be used by libvpx.
+ * \retval #VPX_CODEC_INVALID_PARAM
+ *     fb_count was less than the value needed by the codec.
+ * \retval #VPX_CODEC_ERROR
+ *     Decoder context not initialized, or algorithm not capable of
+ *     using external frame buffers.
+ *
+ * \note
+ * When decoding VP9, the application must pass in at least
+ * #VP9_MAXIMUM_REF_BUFFERS + #VPX_MAXIMUM_WORK_BUFFERS external frame
+ * buffers.
+ */
+typedef vpx_codec_err_t (*vpx_codec_set_frame_buffers_fn_t)(
+    vpx_codec_alg_priv_t *ctx,
+    vpx_codec_frame_buffer_t *fb_list, int fb_count,
+    vpx_realloc_frame_buffer_cb_fn_t cb, void *user_priv);
 
 /*\brief eXternal Memory Allocation memory map get iterator
  *
@@ -305,6 +336,7 @@
     vpx_codec_get_si_fn_t     get_si;      /**< \copydoc ::vpx_codec_get_si_fn_t */
     vpx_codec_decode_fn_t     decode;      /**< \copydoc ::vpx_codec_decode_fn_t */
     vpx_codec_get_frame_fn_t  get_frame;   /**< \copydoc ::vpx_codec_get_frame_fn_t */
+    vpx_codec_set_frame_buffers_fn_t set_fb; /**< \copydoc ::vpx_codec_set_frame_buffers_fn_t */
   } dec;
   struct vpx_codec_enc_iface {
     vpx_codec_enc_cfg_map_t           *cfg_maps;      /**< \copydoc ::vpx_codec_enc_cfg_map_t */
@@ -500,4 +532,4 @@
                                    const vpx_codec_mmap_t *mmaps,
                                    const mem_req_t *mem_reqs, int nreqs,
                                    vpx_codec_flags_t init_flags);
-#endif
+#endif  // VPX_INTERNAL_VPX_CODEC_INTERNAL_H_
diff --git a/vpx/src/vpx_decoder.c b/vpx/src/vpx_decoder.c
index a99e48f..39fd217 100644
--- a/vpx/src/vpx_decoder.c
+++ b/vpx/src/vpx_decoder.c
@@ -226,3 +226,22 @@
 
   return SAVE_STATUS(ctx, res);
 }
+
+vpx_codec_err_t vpx_codec_set_frame_buffers(
+    vpx_codec_ctx_t *ctx,
+    vpx_codec_frame_buffer_t *fb_list, int fb_count,
+    vpx_realloc_frame_buffer_cb_fn_t cb, void *user_priv) {
+  vpx_codec_err_t res;
+
+  if (!ctx || !fb_list || fb_count <= 0 || !cb) {
+    res = VPX_CODEC_INVALID_PARAM;
+  } else if (!ctx->iface || !ctx->priv ||
+             !(ctx->iface->caps & VPX_CODEC_CAP_EXTERNAL_FRAME_BUFFER)) {
+    res = VPX_CODEC_ERROR;
+  } else {
+    res = ctx->iface->dec.set_fb(ctx->priv->alg_priv, fb_list, fb_count,
+                                 cb, user_priv);
+  }
+
+  return SAVE_STATUS(ctx, res);
+}
diff --git a/vpx/src/vpx_encoder.c b/vpx/src/vpx_encoder.c
index e0a29cb..778ed2f 100644
--- a/vpx/src/vpx_encoder.c
+++ b/vpx/src/vpx_encoder.c
@@ -149,6 +149,7 @@
         cfg++;
         dsf++;
       }
+      ctx--;
     }
   }
 
diff --git a/vpx/svc_context.h b/vpx/svc_context.h
index 8204f9c..f675fb6 100644
--- a/vpx/svc_context.h
+++ b/vpx/svc_context.h
@@ -16,8 +16,8 @@
 #ifndef VPX_SVC_CONTEXT_H_
 #define VPX_SVC_CONTEXT_H_
 
-#include "vpx/vp8cx.h"
-#include "vpx/vpx_encoder.h"
+#include "./vp8cx.h"
+#include "./vpx_encoder.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -138,4 +138,4 @@
 }  // extern "C"
 #endif
 
-#endif  /* VPX_SVC_CONTEXT_H_ */
+#endif  // VPX_SVC_CONTEXT_H_
diff --git a/vpx/vp8.h b/vpx/vp8.h
index 056fa7a..2a31af6 100644
--- a/vpx/vp8.h
+++ b/vpx/vp8.h
@@ -27,8 +27,8 @@
 /*!\file
  * \brief Provides controls common to both the VP8 encoder and decoder.
  */
-#ifndef VP8_H
-#define VP8_H
+#ifndef VPX_VP8_H_
+#define VPX_VP8_H_
 
 #include "./vpx_codec.h"
 #include "./vpx_image.h"
@@ -135,4 +135,4 @@
 }  // extern "C"
 #endif
 
-#endif
+#endif  // VPX_VP8_H_
diff --git a/vpx/vp8cx.h b/vpx/vp8cx.h
index c0424f1..829490f 100644
--- a/vpx/vp8cx.h
+++ b/vpx/vp8cx.h
@@ -7,15 +7,15 @@
  *  in the file PATENTS.  All contributing project authors may
  *  be found in the AUTHORS file in the root of the source tree.
  */
-#ifndef VP8CX_H
-#define VP8CX_H
+#ifndef VPX_VP8CX_H_
+#define VPX_VP8CX_H_
 
 /*!\defgroup vp8_encoder WebM VP8 Encoder
  * \ingroup vp8
  *
  * @{
  */
-#include "vp8.h"
+#include "./vp8.h"
 
 /*!\file
  * \brief Provides definitions for using the VP8 encoder algorithm within the
@@ -38,8 +38,6 @@
 /* TODO(jkoleszar): These move to VP9 in a later patch set. */
 extern vpx_codec_iface_t  vpx_codec_vp9_cx_algo;
 extern vpx_codec_iface_t *vpx_codec_vp9_cx(void);
-extern vpx_codec_iface_t  vpx_codec_vp9x_cx_algo;
-extern vpx_codec_iface_t *vpx_codec_vp9x_cx(void);
 
 /*!@} - end algorithm interface member group*/
 
@@ -257,7 +255,7 @@
 /*!\brief VP8 token partition mode
  *
  * This defines VP8 partitioning mode for compressed data, i.e., the number of
- * sub-streams in the bitstream. Used for parallelized decoding.
+ * sub-streams in the bitstream. Used for parallelized decoding.
  *
  */
 
@@ -351,4 +349,4 @@
 }  // extern "C"
 #endif
 
-#endif
+#endif  // VPX_VP8CX_H_
diff --git a/vpx/vp8dx.h b/vpx/vp8dx.h
index b457b93..e89c0bc 100644
--- a/vpx/vp8dx.h
+++ b/vpx/vp8dx.h
@@ -9,8 +9,6 @@
  */
 
 
-#include "vp8.h"
-
 /*!\defgroup vp8_decoder WebM VP8 Decoder
  * \ingroup vp8
  *
@@ -20,13 +18,16 @@
  * \brief Provides definitions for using the VP8 algorithm within the vpx Decoder
  *        interface.
  */
-#ifndef VP8DX_H
-#define VP8DX_H
+#ifndef VPX_VP8DX_H_
+#define VPX_VP8DX_H_
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+/* Include controls common to both the encoder and decoder */
+#include "./vp8.h"
+
 /*!\name Algorithm interface for VP8
  *
  * This interface provides the capability to decode raw VP8 streams, as would
@@ -41,9 +42,6 @@
 extern vpx_codec_iface_t *vpx_codec_vp9_dx(void);
 /*!@} - end algorithm interface member group*/
 
-/* Include controls common to both the encoder and decoder */
-#include "vp8.h"
-
 
 /*!\enum vp8_dec_control_id
  * \brief VP8 decoder control functions
@@ -79,6 +77,13 @@
   /** For testing. */
   VP9_INVERT_TILE_DECODE_ORDER,
 
+  /** control function to set the vp9 decoder into using the least recently
+   * used frame buffer when a new buffer is requested. Takes an int and if
+   * the value is zero will turn off using lru cache. The value of zero is
+   * the default. If the value is anything besides zero, then that will turn
+   * on lru cache.*/
+  VP9D_SET_FRAME_BUFFER_LRU_CACHE,
+
   VP8_DECODER_CTRL_ID_MAX
 };
 
@@ -110,6 +115,7 @@
 VPX_CTRL_USE_TYPE(VP8D_SET_DECRYPTOR,          vp8_decrypt_init *)
 VPX_CTRL_USE_TYPE(VP9D_GET_DISPLAY_SIZE,       int *)
 VPX_CTRL_USE_TYPE(VP9_INVERT_TILE_DECODE_ORDER, int)
+VPX_CTRL_USE_TYPE(VP9D_SET_FRAME_BUFFER_LRU_CACHE, int)
 
 /*! @} - end defgroup vp8_decoder */
 
@@ -117,4 +123,4 @@
 }  // extern "C"
 #endif
 
-#endif
+#endif  // VPX_VP8DX_H_
diff --git a/vpx/vpx_codec.h b/vpx/vpx_codec.h
index 3ea36d6..03d2dec 100644
--- a/vpx/vpx_codec.h
+++ b/vpx/vpx_codec.h
@@ -36,15 +36,15 @@
  * Once initialized, the instance is manged using other functions from
  * the vpx_codec_* family.
  */
-#ifndef VPX_CODEC_H
-#define VPX_CODEC_H
+#ifndef VPX_VPX_CODEC_H_
+#define VPX_VPX_CODEC_H_
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-#include "vpx_integer.h"
-#include "vpx_image.h"
+#include "./vpx_integer.h"
+#include "./vpx_image.h"
 
   /*!\brief Decorator indicating a function is deprecated */
 #ifndef DEPRECATED
@@ -554,5 +554,5 @@
 #ifdef __cplusplus
 }
 #endif
-#endif
+#endif  // VPX_VPX_CODEC_H_
 
diff --git a/vpx/vpx_codec.mk b/vpx/vpx_codec.mk
index 549c249..df3ff6e 100644
--- a/vpx/vpx_codec.mk
+++ b/vpx/vpx_codec.mk
@@ -27,6 +27,7 @@
 API_DOC_SRCS-yes += vpx_decoder.h
 API_DOC_SRCS-yes += vpx_encoder.h
 API_DOC_SRCS-yes += vpx_image.h
+API_DOC_SRCS-yes += vpx_external_frame_buffer.h
 
 API_SRCS-yes                += src/vpx_decoder.c
 API_SRCS-yes                += vpx_decoder.h
@@ -38,4 +39,5 @@
 API_SRCS-yes                += vpx_codec.h
 API_SRCS-yes                += vpx_codec.mk
 API_SRCS-yes                += vpx_image.h
+API_SRCS-yes                += vpx_external_frame_buffer.h
 API_SRCS-$(BUILD_LIBVPX)    += vpx_integer.h
diff --git a/vpx/vpx_decoder.h b/vpx/vpx_decoder.h
index 2dcd024..24be82d 100644
--- a/vpx/vpx_decoder.h
+++ b/vpx/vpx_decoder.h
@@ -7,8 +7,8 @@
  *  in the file PATENTS.  All contributing project authors may
  *  be found in the AUTHORS file in the root of the source tree.
  */
-#ifndef VPX_DECODER_H
-#define VPX_DECODER_H
+#ifndef VPX_VPX_DECODER_H_
+#define VPX_VPX_DECODER_H_
 
 /*!\defgroup decoder Decoder Algorithm Interface
  * \ingroup codec
@@ -29,7 +29,8 @@
 extern "C" {
 #endif
 
-#include "vpx_codec.h"
+#include "./vpx_codec.h"
+#include "./vpx_external_frame_buffer.h"
 
   /*!\brief Current ABI version number
    *
@@ -39,7 +40,7 @@
    * types, removing or reassigning enums, adding/removing/rearranging
    * fields to structures
    */
-#define VPX_DECODER_ABI_VERSION (2 + VPX_CODEC_ABI_VERSION) /**<\hideinitializer*/
+#define VPX_DECODER_ABI_VERSION (3 + VPX_CODEC_ABI_VERSION) /**<\hideinitializer*/
 
   /*! \brief Decoder capabilities bitfield
    *
@@ -66,6 +67,8 @@
    */
 #define VPX_CODEC_CAP_FRAME_THREADING   0x200000 /**< Can support frame-based
                                                       multi-threading */
+#define VPX_CODEC_CAP_EXTERNAL_FRAME_BUFFER 0x400000 /**< Can support external
+                                                      frame buffers */
 
 #define VPX_CODEC_USE_POSTPROC   0x10000 /**< Postprocess decoded frame */
 #define VPX_CODEC_USE_ERROR_CONCEALMENT 0x20000 /**< Conceal errors in decoded
@@ -326,9 +329,53 @@
 
   /*!@} - end defgroup cap_put_slice*/
 
+  /*!\defgroup cap_external_frame_buffer External Frame Buffer Functions
+   *
+   * The following section is required to be implemented for all decoders
+   * that advertise the VPX_CODEC_CAP_EXTERNAL_FRAME_BUFFER capability.
+   * Calling this function for codecs that don't advertise this capability
+   * will result in an error code being returned, usually VPX_CODEC_ERROR.
+   *
+   * \note
+   * Currently this only works with VP9.
+   * @{
+   */
+
+  /*!\brief Pass in external frame buffers for the decoder to use.
+   *
+   * Registers a given function to be called when the current frame to
+   * decode will be bigger than the external frame buffer size. This
+   * function must be called before the first call to decode or libvpx
+   * will assume the default behavior of allocating frame buffers internally.
+   * Frame buffers with a size of 0 are valid.
+   *
+   * \param[in] ctx          Pointer to this instance's context
+   * \param[in] fb_list      Pointer to array of frame buffers
+   * \param[in] fb_count     Number of elements in frame buffer array
+   * \param[in] cb           Pointer to the callback function
+   * \param[in] user_priv    User's private data
+   *
+   * \retval #VPX_CODEC_OK
+   *     External frame buffers passed into the decoder.
+   * \retval #VPX_CODEC_ERROR
+   *     Decoder context not initialized, or algorithm not capable of
+   *     using external frame buffers.
+   *
+   * \note
+   * When decoding VP9, the application must pass in at least
+   * #VP9_MAXIMUM_REF_BUFFERS + #VPX_MAXIMUM_WORK_BUFFERS external frame
+   * buffers.
+   */
+  vpx_codec_err_t vpx_codec_set_frame_buffers(
+      vpx_codec_ctx_t *ctx,
+      vpx_codec_frame_buffer_t *fb_list, int fb_count,
+      vpx_realloc_frame_buffer_cb_fn_t cb, void *user_priv);
+
+  /*!@} - end defgroup cap_external_frame_buffer */
+
   /*!@} - end defgroup decoder*/
 #ifdef __cplusplus
 }
 #endif
-#endif
+#endif  // VPX_VPX_DECODER_H_
 
diff --git a/vpx/vpx_encoder.h b/vpx/vpx_encoder.h
index 56752cf..3473885 100644
--- a/vpx/vpx_encoder.h
+++ b/vpx/vpx_encoder.h
@@ -7,8 +7,8 @@
  *  in the file PATENTS.  All contributing project authors may
  *  be found in the AUTHORS file in the root of the source tree.
  */
-#ifndef VPX_ENCODER_H
-#define VPX_ENCODER_H
+#ifndef VPX_VPX_ENCODER_H_
+#define VPX_VPX_ENCODER_H_
 
 /*!\defgroup encoder Encoder Algorithm Interface
  * \ingroup codec
@@ -29,7 +29,7 @@
 extern "C" {
 #endif
 
-#include "vpx_codec.h"
+#include "./vpx_codec.h"
 
   /*! Temporal Scalability: Maximum length of the sequence defining frame
    * layer membership
@@ -932,5 +932,5 @@
 #ifdef __cplusplus
 }
 #endif
-#endif
+#endif  // VPX_VPX_ENCODER_H_
 
diff --git a/vpx/vpx_external_frame_buffer.h b/vpx/vpx_external_frame_buffer.h
new file mode 100644
index 0000000..98ce5fd
--- /dev/null
+++ b/vpx/vpx_external_frame_buffer.h
@@ -0,0 +1,61 @@
+/*
+ *  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef VPX_VPX_EXTERNAL_FRAME_BUFFER_H_
+#define VPX_VPX_EXTERNAL_FRAME_BUFFER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "./vpx_integer.h"
+
+/*!\brief The maximum number of work buffers used by libvpx.
+ */
+#define VPX_MAXIMUM_WORK_BUFFERS 1
+
+/*!\brief The maximum number of reference buffers that a VP9 encoder may use.
+ */
+#define VP9_MAXIMUM_REF_BUFFERS 8
+
+/*!\brief External frame buffer
+ *
+ * This structure is used to hold external frame buffers passed into the
+ * decoder by the application.
+ */
+typedef struct vpx_codec_frame_buffer {
+  uint8_t *data;    /**< Pointer to the data buffer */
+  size_t size;      /**< Size of data in bytes */
+  void *frame_priv;  /**< Frame's private data */
+} vpx_codec_frame_buffer_t;
+
+/*!\brief realloc frame buffer callback prototype
+ *
+ * This callback is invoked by the decoder to notify the application one
+ * of the external frame buffers must increase in size, in order for the
+ * decode call to complete. The callback must allocate at least new_size in
+ * bytes and assign it to fb->data. Then the callback must set fb->size to
+ * the allocated size. The application does not need to align the allocated
+ * data. The callback is usually triggered by a frame size change. On success
+ * the callback must return 0. Any failure the callback must return a value
+ * less than 0.
+ *
+ * \param[in] user_priv    User's private data
+ * \param[in] new_size     Size in bytes needed by the buffer.
+ * \param[in/out] fb       Pointer to frame buffer to increase size.
+ */
+typedef int (*vpx_realloc_frame_buffer_cb_fn_t)(
+    void *user_priv, size_t new_size, vpx_codec_frame_buffer_t *fb);
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // VPX_VPX_EXTERNAL_FRAME_BUFFER_H_
diff --git a/vpx/vpx_image.h b/vpx/vpx_image.h
index c304bac..79e11aa 100644
--- a/vpx/vpx_image.h
+++ b/vpx/vpx_image.h
@@ -17,8 +17,8 @@
 extern "C" {
 #endif
 
-#ifndef VPX_IMAGE_H
-#define VPX_IMAGE_H
+#ifndef VPX_VPX_IMAGE_H_
+#define VPX_VPX_IMAGE_H_
 
   /*!\brief Current ABI version number
    *
@@ -240,4 +240,4 @@
 #endif
 #ifdef __cplusplus
 }
-#endif
+#endif  // VPX_VPX_IMAGE_H_
diff --git a/vpx/vpx_integer.h b/vpx/vpx_integer.h
index 0ccc96c..dfa361b 100644
--- a/vpx/vpx_integer.h
+++ b/vpx/vpx_integer.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef VPX_INTEGER_H
-#define VPX_INTEGER_H
+#ifndef VPX_VPX_INTEGER_H_
+#define VPX_VPX_INTEGER_H_
 
 /* get ptrdiff_t, size_t, wchar_t, NULL */
 #include <stddef.h>
@@ -54,4 +54,4 @@
 #include <inttypes.h>
 #endif
 
-#endif
+#endif  // VPX_VPX_INTEGER_H_
diff --git a/vpx_mem/include/vpx_mem_intrnl.h b/vpx_mem/include/vpx_mem_intrnl.h
index 2248ad5..225a3ba 100644
--- a/vpx_mem/include/vpx_mem_intrnl.h
+++ b/vpx_mem/include/vpx_mem_intrnl.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef __VPX_MEM_INTRNL_H__
-#define __VPX_MEM_INTRNL_H__
+#ifndef VPX_MEM_INCLUDE_VPX_MEM_INTRNL_H_
+#define VPX_MEM_INCLUDE_VPX_MEM_INTRNL_H_
 #include "./vpx_config.h"
 
 #ifndef CONFIG_MEM_MANAGER
@@ -92,4 +92,4 @@
 /*returns an addr aligned to the byte boundary specified by align*/
 #define align_addr(addr,align) (void*)(((size_t)(addr) + ((align) - 1)) & (size_t)-(align))
 
-#endif /*__VPX_MEM_INTRNL_H__*/
+#endif  // VPX_MEM_INCLUDE_VPX_MEM_INTRNL_H_
diff --git a/vpx_mem/include/vpx_mem_tracker.h b/vpx_mem/include/vpx_mem_tracker.h
index 3be0d2d..1335e00 100644
--- a/vpx_mem/include/vpx_mem_tracker.h
+++ b/vpx_mem/include/vpx_mem_tracker.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef __VPX_MEM_TRACKER_H__
-#define __VPX_MEM_TRACKER_H__
+#ifndef VPX_MEM_INCLUDE_VPX_MEM_TRACKER_H_
+#define VPX_MEM_INCLUDE_VPX_MEM_TRACKER_H_
 
 /* vpx_mem_tracker version info */
 #define vpx_mem_tracker_version "2.5.1.1"
@@ -176,4 +176,4 @@
 }
 #endif
 
-#endif // __VPX_MEM_TRACKER_H__
+#endif  // VPX_MEM_INCLUDE_VPX_MEM_TRACKER_H_
diff --git a/vpx_mem/memory_manager/include/cavl_if.h b/vpx_mem/memory_manager/include/cavl_if.h
index ec6e525..a5ced8b 100644
--- a/vpx_mem/memory_manager/include/cavl_if.h
+++ b/vpx_mem/memory_manager/include/cavl_if.h
@@ -8,6 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#ifndef VPX_MEM_MEMORY_MANAGER_INCLUDE_CAVL_IF_H_
+#define VPX_MEM_MEMORY_MANAGER_INCLUDE_CAVL_IF_H_
 
 /* Abstract AVL Tree Generic C Package.
 ** Interface generation header file.
@@ -222,3 +224,5 @@
 #undef L_SC
 #undef L_LONG_BIT
 #undef L_BIT_ARR_DEFN
+
+#endif  // VPX_MEM_MEMORY_MANAGER_INCLUDE_CAVL_IF_H_
diff --git a/vpx_mem/memory_manager/include/cavl_impl.h b/vpx_mem/memory_manager/include/cavl_impl.h
index cf7deb7..8b9ae27 100644
--- a/vpx_mem/memory_manager/include/cavl_impl.h
+++ b/vpx_mem/memory_manager/include/cavl_impl.h
@@ -8,6 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#ifndef VPX_MEM_MEMORY_MANAGER_INCLUDE_CAVL_IMPL_H_
+#define VPX_MEM_MEMORY_MANAGER_INCLUDE_CAVL_IMPL_H_
 
 /* Abstract AVL Tree Generic C Package.
 ** Implementation generation header file.
@@ -1146,3 +1148,5 @@
 #undef L_SC
 #undef L_BALANCE_PARAM_CALL_PREFIX
 #undef L_BALANCE_PARAM_DECL_PREFIX
+
+#endif  // VPX_MEM_MEMORY_MANAGER_INCLUDE_CAVL_IMPL_H_
diff --git a/vpx_mem/memory_manager/include/heapmm.h b/vpx_mem/memory_manager/include/heapmm.h
index 4934c2d..d584b19 100644
--- a/vpx_mem/memory_manager/include/heapmm.h
+++ b/vpx_mem/memory_manager/include/heapmm.h
@@ -8,6 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#ifndef VPX_MEM_MEMORY_MANAGER_INCLUDE_HEAPMM_H_
+#define VPX_MEM_MEMORY_MANAGER_INCLUDE_HEAPMM_H_
 
 /* This code is in the public domain.
 ** Version: 1.1  Author: Walt Karas
@@ -150,3 +152,4 @@
   HMM_UNIQUE(size_bau) num_block_align_units);
 
 #endif /* defined HMM_PROCESS */
+#endif  // VPX_MEM_MEMORY_MANAGER_INCLUDE_HEAPMM_H_
diff --git a/vpx_mem/memory_manager/include/hmm_cnfg.h b/vpx_mem/memory_manager/include/hmm_cnfg.h
index 2c3391d..caa8713 100644
--- a/vpx_mem/memory_manager/include/hmm_cnfg.h
+++ b/vpx_mem/memory_manager/include/hmm_cnfg.h
@@ -8,6 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#ifndef VPX_MEM_MEMORY_MANAGER_INCLUDE_HMM_CNFG_H_
+#define VPX_MEM_MEMORY_MANAGER_INCLUDE_HMM_CNFG_H_
 
 /* This code is in the public domain.
 ** Version: 1.1  Author: Walt Karas
@@ -114,3 +116,5 @@
 /* Put configuration 5 definitions here. */
 
 #endif
+
+#endif  // VPX_MEM_MEMORY_MANAGER_INCLUDE_HMM_CNFG_H_
diff --git a/vpx_mem/memory_manager/include/hmm_intrnl.h b/vpx_mem/memory_manager/include/hmm_intrnl.h
index 27cefe4..7302aa2 100644
--- a/vpx_mem/memory_manager/include/hmm_intrnl.h
+++ b/vpx_mem/memory_manager/include/hmm_intrnl.h
@@ -13,8 +13,8 @@
 ** Version: 1.1  Author: Walt Karas
 */
 
-#ifndef HMM_INTRNL_H_
-#define HMM_INTRNL_H_
+#ifndef VPX_MEM_MEMORY_MANAGER_INCLUDE_HMM_INTRNL_H_
+#define VPX_MEM_MEMORY_MANAGER_INCLUDE_HMM_INTRNL_H_
 
 #ifdef __uClinux__
 # include <lddk.h>
@@ -156,4 +156,4 @@
 
 #include "cavl_if.h"
 
-#endif /* Include once. */
+#endif  // VPX_MEM_MEMORY_MANAGER_INCLUDE_HMM_INTRNL_H_
diff --git a/vpx_mem/vpx_mem.h b/vpx_mem/vpx_mem.h
index c7321a9..33686b2 100644
--- a/vpx_mem/vpx_mem.h
+++ b/vpx_mem/vpx_mem.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef __VPX_MEM_H__
-#define __VPX_MEM_H__
+#ifndef VPX_MEM_VPX_MEM_H_
+#define VPX_MEM_VPX_MEM_H_
 
 #include "vpx_config.h"
 #if defined(__uClinux__)
@@ -170,4 +170,4 @@
 }
 #endif
 
-#endif /* __VPX_MEM_H__ */
+#endif  // VPX_MEM_VPX_MEM_H_
diff --git a/vpx_ports/arm.h b/vpx_ports/arm.h
index 525a764..2562d9c 100644
--- a/vpx_ports/arm.h
+++ b/vpx_ports/arm.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef VPX_PORTS_ARM_H
-#define VPX_PORTS_ARM_H
+#ifndef VPX_PORTS_ARM_H_
+#define VPX_PORTS_ARM_H_
 #include <stdlib.h>
 #include "vpx_config.h"
 
@@ -23,5 +23,5 @@
 
 int arm_cpu_caps(void);
 
-#endif
+#endif  // VPX_PORTS_ARM_H_
 
diff --git a/vpx_ports/asm_offsets.h b/vpx_ports/asm_offsets.h
index d3a3e5a..317bbed 100644
--- a/vpx_ports/asm_offsets.h
+++ b/vpx_ports/asm_offsets.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef VPX_PORTS_ASM_OFFSETS_H
-#define VPX_PORTS_ASM_OFFSETS_H
+#ifndef VPX_PORTS_ASM_OFFSETS_H_
+#define VPX_PORTS_ASM_OFFSETS_H_
 
 #include <stddef.h>
 
@@ -28,4 +28,4 @@
 #define END
 #endif
 
-#endif /* VPX_PORTS_ASM_OFFSETS_H */
+#endif  // VPX_PORTS_ASM_OFFSETS_H_
diff --git a/vpx_ports/config.h b/vpx_ports/config.h
index 1abe70d..3c1ab99 100644
--- a/vpx_ports/config.h
+++ b/vpx_ports/config.h
@@ -7,4 +7,10 @@
  *  in the file PATENTS.  All contributing project authors may
  *  be found in the AUTHORS file in the root of the source tree.
  */
+
+#ifndef VPX_PORTS_CONFIG_H_
+#define VPX_PORTS_CONFIG_H_
+
 #include "vpx_config.h"
+
+#endif  // VPX_PORTS_CONFIG_H_
diff --git a/vpx_ports/emmintrin_compat.h b/vpx_ports/emmintrin_compat.h
index 782d603..1617638 100644
--- a/vpx_ports/emmintrin_compat.h
+++ b/vpx_ports/emmintrin_compat.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef VPX_PORTS_EMMINTRIN_COMPAT_H
-#define VPX_PORTS_EMMINTRIN_COMPAT_H
+#ifndef VPX_PORTS_EMMINTRIN_COMPAT_H_
+#define VPX_PORTS_EMMINTRIN_COMPAT_H_
 
 #if defined(__GNUC__) && __GNUC__ < 4
 /* From emmintrin.h (gcc 4.5.3) */
@@ -52,4 +52,4 @@
 }
 #endif
 
-#endif
+#endif  // VPX_PORTS_EMMINTRIN_COMPAT_H_
diff --git a/vpx_ports/mem.h b/vpx_ports/mem.h
index 62b86bb..e91d776 100644
--- a/vpx_ports/mem.h
+++ b/vpx_ports/mem.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef VPX_PORTS_MEM_H
-#define VPX_PORTS_MEM_H
+#ifndef VPX_PORTS_MEM_H_
+#define VPX_PORTS_MEM_H_
 
 #include "vpx_config.h"
 #include "vpx/vpx_integer.h"
@@ -44,4 +44,4 @@
 #define UNINITIALIZED_IS_SAFE(x) x=x
 #else
 #define UNINITIALIZED_IS_SAFE(x) x
-#endif
+#endif  // VPX_PORTS_MEM_H_
diff --git a/vpx_ports/mem_ops.h b/vpx_ports/mem_ops.h
index 2d44a3a..8c8b526 100644
--- a/vpx_ports/mem_ops.h
+++ b/vpx_ports/mem_ops.h
@@ -8,6 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#ifndef VPX_PORTS_MEM_OPS_H_
+#define VPX_PORTS_MEM_OPS_H_
 
 /* \file
  * \brief Provides portable memory access primitives
@@ -220,3 +222,5 @@
   mem[2] = (val >> 16) & 0xff;
   mem[3] = (val >> 24) & 0xff;
 }
+
+#endif  // VPX_PORTS_MEM_OPS_H_
diff --git a/vpx_ports/mem_ops_aligned.h b/vpx_ports/mem_ops_aligned.h
index 0100300..da7c65d 100644
--- a/vpx_ports/mem_ops_aligned.h
+++ b/vpx_ports/mem_ops_aligned.h
@@ -8,6 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#ifndef VPX_PORTS_MEM_OPS_ALIGNED_H_
+#define VPX_PORTS_MEM_OPS_ALIGNED_H_
 
 /* \file
  * \brief Provides portable memory access primitives for operating on aligned
@@ -155,3 +157,5 @@
 #undef swap_endian_32
 #undef swap_endian_16_se
 #undef swap_endian_32_se
+
+#endif  // VPX_PORTS_MEM_OPS_ALIGNED_H_
diff --git a/vpx_ports/vpx_once.h b/vpx_ports/vpx_once.h
index 6052c4d..182892a 100644
--- a/vpx_ports/vpx_once.h
+++ b/vpx_ports/vpx_once.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef VPX_ONCE_H
-#define VPX_ONCE_H
+#ifndef VPX_PORTS_VPX_ONCE_H_
+#define VPX_PORTS_VPX_ONCE_H_
 
 #include "vpx_config.h"
 
@@ -100,4 +100,4 @@
 }
 #endif
 
-#endif
+#endif  // VPX_PORTS_VPX_ONCE_H_
diff --git a/vpx_ports/vpx_timer.h b/vpx_ports/vpx_timer.h
index cdad9ef..9e2015e 100644
--- a/vpx_ports/vpx_timer.h
+++ b/vpx_ports/vpx_timer.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef VPX_TIMER_H
-#define VPX_TIMER_H
+#ifndef VPX_PORTS_VPX_TIMER_H_
+#define VPX_PORTS_VPX_TIMER_H_
 #include "vpx/vpx_integer.h"
 
 #if CONFIG_OS_SUPPORT
@@ -114,4 +114,4 @@
 
 #endif /* CONFIG_OS_SUPPORT */
 
-#endif
+#endif  // VPX_PORTS_VPX_TIMER_H_
diff --git a/vpx_ports/x86.h b/vpx_ports/x86.h
index fdbed25..a9d51a3 100644
--- a/vpx_ports/x86.h
+++ b/vpx_ports/x86.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef VPX_PORTS_X86_H
-#define VPX_PORTS_X86_H
+#ifndef VPX_PORTS_X86_H_
+#define VPX_PORTS_X86_H_
 #include <stdlib.h>
 #include "vpx_config.h"
 
@@ -256,5 +256,5 @@
 
 
 extern void vpx_reset_mmx_state(void);
-#endif
+#endif  // VPX_PORTS_X86_H_
 
diff --git a/vpx_scale/generic/yv12config.c b/vpx_scale/generic/yv12config.c
index 7c3f7ec..fc05d8c 100644
--- a/vpx_scale/generic/yv12config.c
+++ b/vpx_scale/generic/yv12config.c
@@ -19,10 +19,18 @@
 /****************************************************************************
  *
  ****************************************************************************/
+
+#define yv12_align_addr(addr, align) \
+  (void*)(((size_t)(addr) + ((align) - 1)) & (size_t)-(align))
+
 int
 vp8_yv12_de_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf) {
   if (ybf) {
-    vpx_free(ybf->buffer_alloc);
+    // If libvpx is using external frame buffers then buffer_alloc_sz must
+    // not be set.
+    if (ybf->buffer_alloc_sz > 0) {
+      vpx_free(ybf->buffer_alloc);
+    }
 
     /* buffer_alloc isn't accessed by most functions.  Rather y_buffer,
       u_buffer and v_buffer point to buffer_alloc and are used.  Clear out
@@ -108,7 +116,9 @@
 
 int vp9_free_frame_buffer(YV12_BUFFER_CONFIG *ybf) {
   if (ybf) {
-    vpx_free(ybf->buffer_alloc);
+    if (ybf->buffer_alloc_sz > 0) {
+      vpx_free(ybf->buffer_alloc);
+    }
 
     /* buffer_alloc isn't accessed by most functions.  Rather y_buffer,
       u_buffer and v_buffer point to buffer_alloc and are used.  Clear out
@@ -123,7 +133,10 @@
 
 int vp9_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
                              int width, int height,
-                             int ss_x, int ss_y, int border) {
+                             int ss_x, int ss_y, int border,
+                             vpx_codec_frame_buffer_t *ext_fb,
+                             vpx_realloc_frame_buffer_cb_fn_t cb,
+                             void *user_priv) {
   if (ybf) {
     const int aligned_width = (width + 7) & ~7;
     const int aligned_height = (height + 7) & ~7;
@@ -148,15 +161,36 @@
 #else
     const int frame_size = yplane_size + 2 * uvplane_size;
 #endif
-    if (frame_size > ybf->buffer_alloc_sz) {
-      // Allocation to hold larger frame, or first allocation.
-      if (ybf->buffer_alloc)
-        vpx_free(ybf->buffer_alloc);
-      ybf->buffer_alloc = vpx_memalign(32, frame_size);
-      ybf->buffer_alloc_sz = frame_size;
+
+    if (ext_fb != NULL) {
+      const int align_addr_extra_size = 31;
+      const size_t external_frame_size = frame_size + align_addr_extra_size;
+      if (external_frame_size > ext_fb->size) {
+        // Allocation to hold larger frame, or first allocation.
+        if (cb(user_priv, external_frame_size, ext_fb) < 0) {
+          return -1;
+        }
+
+        if (ext_fb->data == NULL || ext_fb->size < external_frame_size) {
+          return -1;
+        }
+
+        ybf->buffer_alloc = yv12_align_addr(ext_fb->data, 32);
+      }
+    } else {
+      if (frame_size > ybf->buffer_alloc_sz) {
+        // Allocation to hold larger frame, or first allocation.
+        if (ybf->buffer_alloc)
+          vpx_free(ybf->buffer_alloc);
+        ybf->buffer_alloc = vpx_memalign(32, frame_size);
+        ybf->buffer_alloc_sz = frame_size;
+      }
+
+      if (ybf->buffer_alloc_sz < frame_size)
+        return -1;
     }
 
-    if (!ybf->buffer_alloc || ybf->buffer_alloc_sz < frame_size)
+    if (!ybf->buffer_alloc)
       return -1;
 
     /* Only support allocating buffers that have a border that's a multiple
@@ -206,7 +240,8 @@
                            int ss_x, int ss_y, int border) {
   if (ybf) {
     vp9_free_frame_buffer(ybf);
-    return vp9_realloc_frame_buffer(ybf, width, height, ss_x, ss_y, border);
+    return vp9_realloc_frame_buffer(ybf, width, height, ss_x, ss_y, border,
+                                    NULL, NULL, NULL);
   }
   return -2;
 }
diff --git a/vpx_scale/vpx_scale.h b/vpx_scale/vpx_scale.h
index 9ddf62e..43fcf9d 100644
--- a/vpx_scale/vpx_scale.h
+++ b/vpx_scale/vpx_scale.h
@@ -9,8 +9,8 @@
  */
 
 
-#ifndef VPXSCALE_H
-#define VPXSCALE_H
+#ifndef VPX_SCALE_VPX_SCALE_H_
+#define VPX_SCALE_VPX_SCALE_H_
 
 #include "vpx_scale/yv12config.h"
 
@@ -24,4 +24,4 @@
                             unsigned int vratio,
                             unsigned int interlaced);
 
-#endif
+#endif  // VPX_SCALE_VPX_SCALE_H_
diff --git a/vpx_scale/yv12config.h b/vpx_scale/yv12config.h
index 0e950fb..bf5fc07 100644
--- a/vpx_scale/yv12config.h
+++ b/vpx_scale/yv12config.h
@@ -8,13 +8,14 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef YV12_CONFIG_H
-#define YV12_CONFIG_H
+#ifndef VPX_SCALE_YV12CONFIG_H_
+#define VPX_SCALE_YV12CONFIG_H_
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#include "vpx/vpx_external_frame_buffer.h"
 #include "vpx/vpx_integer.h"
 
 #define VP8BORDERINPIXELS       32
@@ -64,13 +65,24 @@
   int vp9_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
                              int width, int height, int ss_x, int ss_y,
                              int border);
+
+  // Updates the yv12 buffer config with the frame buffer. If ext_fb is not
+  // NULL then libvpx is using external frame buffers. The function will
+  // check if the frame buffer is big enough to fit the decoded frame and
+  // try to reallocate the frame buffer. If ext_fb is not NULL and the frame
+  // buffer is not big enough libvpx will call cb with minimum size in bytes.
+  //
+  // Returns 0 on success. Returns < 0 on failure.
   int vp9_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
                                int width, int height, int ss_x, int ss_y,
-                               int border);
+                               int border,
+                               vpx_codec_frame_buffer_t *ext_fb,
+                               vpx_realloc_frame_buffer_cb_fn_t cb,
+                               void *user_priv);
   int vp9_free_frame_buffer(YV12_BUFFER_CONFIG *ybf);
 
 #ifdef __cplusplus
 }
 #endif
 
-#endif  // YV12_CONFIG_H
+#endif  // VPX_SCALE_YV12CONFIG_H_
diff --git a/vpxdec.c b/vpxdec.c
index 1b9bfd3..655b756 100644
--- a/vpxdec.c
+++ b/vpxdec.c
@@ -29,9 +29,7 @@
 #include "vpx/vp8dx.h"
 #endif
 
-#if CONFIG_MD5
 #include "./md5_utils.h"
-#endif
 
 #include "./tools_common.h"
 #include "./webmdec.h"
@@ -89,19 +87,20 @@
                                                    "Enable decoder error-concealment");
 static const arg_def_t scalearg = ARG_DEF("S", "scale", 0,
                                             "Scale output frames uniformly");
+static const arg_def_t fb_arg =
+    ARG_DEF(NULL, "frame-buffers", 1, "Number of frame buffers to use");
+static const arg_def_t fb_lru_arg =
+    ARG_DEF(NULL, "frame-buffers-lru", 1, "Turn on/off frame buffer lru");
 
 
-#if CONFIG_MD5
 static const arg_def_t md5arg = ARG_DEF(NULL, "md5", 0,
                                         "Compute the MD5 sum of the decoded frame");
-#endif
+
 static const arg_def_t *all_args[] = {
   &codecarg, &use_yv12, &use_i420, &flipuvarg, &noblitarg,
   &progressarg, &limitarg, &skiparg, &postprocarg, &summaryarg, &outputfile,
-  &threadsarg, &verbosearg, &scalearg,
-#if CONFIG_MD5
+  &threadsarg, &verbosearg, &scalearg, &fb_arg, &fb_lru_arg,
   &md5arg,
-#endif
   &error_concealment,
   NULL
 };
@@ -232,11 +231,9 @@
   void *out = NULL;
 
   if (do_md5) {
-#if CONFIG_MD5
     MD5Context *md5_ctx = out = malloc(sizeof(MD5Context));
     (void)out_fn;
     MD5Init(md5_ctx);
-#endif
   } else {
     FILE *outfile = out = strcmp("-", out_fn) ? fopen(out_fn, "wb")
                           : set_binary_mode(stdout);
@@ -251,9 +248,7 @@
 
 void out_put(void *out, const uint8_t *buf, unsigned int len, int do_md5) {
   if (do_md5) {
-#if CONFIG_MD5
     MD5Update(out, buf, len);
-#endif
   } else {
     (void) fwrite(buf, 1, len, out);
   }
@@ -261,7 +256,6 @@
 
 void out_close(void *out, const char *out_fn, int do_md5) {
   if (do_md5) {
-#if CONFIG_MD5
     uint8_t md5[16];
     int i;
 
@@ -272,7 +266,6 @@
       printf("%02x", md5[i]);
 
     printf("  %s\n", out_fn);
-#endif
   } else {
     fclose(out);
   }
@@ -314,6 +307,31 @@
           (float)frame_out * 1000000.0 / (float)dx_time);
 }
 
+// Called by libvpx if the frame buffer size needs to increase.
+//
+// Parameters:
+// user_priv    Data passed into libvpx.
+// new_size     Minimum size needed by libvpx to decompress the next frame.
+// fb           Pointer to the frame buffer to update.
+//
+// Returns 0 on success. Returns < 0 on failure.
+int realloc_vp9_frame_buffer(void *user_priv, size_t new_size,
+                             vpx_codec_frame_buffer_t *fb) {
+  (void)user_priv;
+  if (!fb)
+    return -1;
+
+  free(fb->data);
+  fb->data = (uint8_t*)malloc(new_size);
+  if (!fb->data) {
+    fb->size = 0;
+    return -1;
+  }
+
+  fb->size = new_size;
+  return 0;
+}
+
 void generate_filename(const char *pattern, char *out, size_t q_len,
                        unsigned int d_w, unsigned int d_h,
                        unsigned int frame_in) {
@@ -428,6 +446,9 @@
   int                     do_scale = 0;
   vpx_image_t             *scaled_img = NULL;
   int                     frame_avail, got_data;
+  int                     num_external_frame_buffers = 0;
+  int                     fb_lru_cache = 0;
+  vpx_codec_frame_buffer_t *frame_buffers = NULL;
 
   struct VpxDecInputContext input = {0};
   struct VpxInputContext vpx_input_ctx = {0};
@@ -487,6 +508,10 @@
       quiet = 0;
     else if (arg_match(&arg, &scalearg, argi))
       do_scale = 1;
+    else if (arg_match(&arg, &fb_arg, argi))
+      num_external_frame_buffers = arg_parse_uint(&arg);
+    else if (arg_match(&arg, &fb_lru_arg, argi))
+      fb_lru_cache = arg_parse_uint(&arg);
 
 #if CONFIG_VP8_DECODER
     else if (arg_match(&arg, &addnoise_level, argi)) {
@@ -704,6 +729,30 @@
     arg_skip--;
   }
 
+  if (num_external_frame_buffers > 0) {
+    // Allocate the frame buffer list, setting all of the values to 0.
+    // Including the size of frame buffers. Libvpx will request the
+    // application to realloc the frame buffer data if the size is too small.
+    frame_buffers = (vpx_codec_frame_buffer_t*)calloc(
+        num_external_frame_buffers, sizeof(*frame_buffers));
+    if (vpx_codec_set_frame_buffers(&decoder, frame_buffers,
+                                    num_external_frame_buffers,
+                                    realloc_vp9_frame_buffer,
+                                    NULL)) {
+      fprintf(stderr, "Failed to configure external frame buffers: %s\n",
+              vpx_codec_error(&decoder));
+      return EXIT_FAILURE;
+    }
+  }
+
+  if (fb_lru_cache > 0 &&
+      vpx_codec_control(&decoder, VP9D_SET_FRAME_BUFFER_LRU_CACHE,
+                        fb_lru_cache)) {
+    fprintf(stderr, "Failed to set frame buffer lru cache: %s\n",
+            vpx_codec_error(&decoder));
+    return EXIT_FAILURE;
+  }
+
   frame_avail = 1;
   got_data = 0;
 
@@ -878,6 +927,10 @@
     free(buf);
 
   if (scaled_img) vpx_img_free(scaled_img);
+  for (i = 0; i < num_external_frame_buffers; ++i) {
+    free(frame_buffers[i].data);
+  }
+  free(frame_buffers);
 
   fclose(infile);
   free(argv);
diff --git a/webmdec.c b/webmdec.c
index 4bf7c7e..0c75d7a 100644
--- a/webmdec.c
+++ b/webmdec.c
@@ -117,8 +117,10 @@
 
     do {
       /* End of this packet, get another. */
-      if (webm_ctx->pkt)
+      if (webm_ctx->pkt) {
         nestegg_free_packet(webm_ctx->pkt);
+        webm_ctx->pkt = NULL;
+      }
 
       if (nestegg_read_packet(webm_ctx->nestegg_ctx, &webm_ctx->pkt) <= 0 ||
           nestegg_packet_track(webm_ctx->pkt, &track)) {
@@ -188,6 +190,9 @@
 }
 
 void webm_free(struct WebmInputContext *webm_ctx) {
-  if (webm_ctx && webm_ctx->nestegg_ctx)
+  if (webm_ctx && webm_ctx->nestegg_ctx) {
+    if (webm_ctx->pkt)
+      nestegg_free_packet(webm_ctx->pkt);
     nestegg_destroy(webm_ctx->nestegg_ctx);
+  }
 }
diff --git a/y4minput.h b/y4minput.h
index b2a390c..615debe 100644
--- a/y4minput.h
+++ b/y4minput.h
@@ -10,8 +10,10 @@
  *  Based on code from the OggTheora software codec source code,
  *  Copyright (C) 2002-2010 The Xiph.Org Foundation and contributors.
  */
-#if !defined(_y4minput_H)
-# define _y4minput_H (1)
+
+#ifndef Y4MINPUT_H_
+#define Y4MINPUT_H_
+
 # include <stdio.h>
 # include "vpx/vpx_image.h"
 
@@ -60,4 +62,4 @@
 void y4m_input_close(y4m_input *_y4m);
 int y4m_input_fetch_frame(y4m_input *_y4m, FILE *_fin, vpx_image_t *img);
 
-#endif
+#endif  // Y4MINPUT_H_