Merge "Converting mode_lf_lut struct member into static lookup table."
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/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/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..2d46522 100644
--- a/test/datarate_test.cc
+++ b/test/datarate_test.cc
@@ -248,9 +248,11 @@
     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!";
   }
 }
diff --git a/test/decode_test_driver.h b/test/decode_test_driver.h
index ddaed9f..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;
 
diff --git a/test/external_frame_buffer_test.cc b/test/external_frame_buffer_test.cc
new file mode 100644
index 0000000..874d199
--- /dev/null
+++ b/test/external_frame_buffer_test.cc
@@ -0,0 +1,309 @@
+/*
+ *  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);
+
+  // Tell compiler we are not using kVP8TestVectors.
+  (void)libvpx_test::kVP8TestVectors;
+
+  // 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, EightFrameBuffers) {
+  // Minimum number of reference buffers for VP9 is 8.
+  const int num_buffers = 8;
+  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 number of possible reference buffers(8), plus
+  // one working buffer, plus eight jitter buffers.
+  const int num_buffers = 17;
+  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 reference buffers for VP9 is 8.
+  const int num_buffers = 7;
+  ASSERT_EQ(VPX_CODEC_INVALID_PARAM,
+            SetExternalFrameBuffers(num_buffers, realloc_vp9_frame_buffer));
+}
+
+TEST_F(ExternalFrameBufferTest, NullFrameBufferList) {
+  // Number of buffers equals number of possible reference buffers(8), plus
+  // one working buffer, plus four jitter buffers.
+  const int num_buffers = 13;
+  ASSERT_EQ(VPX_CODEC_INVALID_PARAM,
+            SetNullFrameBuffers(num_buffers, realloc_vp9_frame_buffer));
+}
+
+TEST_F(ExternalFrameBufferTest, NullRealloc) {
+  // Number of buffers equals number of possible reference buffers(8), plus
+  // one working buffer, plus four jitter buffers.
+  const int num_buffers = 13;
+  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 number of possible reference buffers(8), plus
+  // one working buffer, plus four jitter buffers.
+  const int num_buffers = 13;
+  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/test-data.sha1 b/test/test-data.sha1
index 442bfd2..03881c7 100644
--- a/test/test-data.sha1
+++ b/test/test-data.sha1
@@ -569,3 +569,5 @@
 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
diff --git a/test/test.mk b/test/test.mk
index 743d0a4..2905a1a 100644
--- a/test/test.mk
+++ b/test/test.mk
@@ -34,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
@@ -666,6 +668,8 @@
 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) += vp91-2-04-yv444.webm
 LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp91-2-04-yv444.webm.md5
 
diff --git a/test/test_vectors.cc b/test/test_vectors.cc
index 7ffecf0..5b58c4a 100644
--- a/test/test_vectors.cc
+++ b/test/test_vectors.cc
@@ -158,6 +158,7 @@
   "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",
 #if CONFIG_NON420
   "vp91-2-04-yv444.webm"
 #endif
diff --git a/test/test_vectors.h b/test/test_vectors.h
index 942175a..491de33 100644
--- a/test/test_vectors.h
+++ b/test/test_vectors.h
@@ -22,9 +22,9 @@
 
 #if CONFIG_VP9_DECODER
 #if CONFIG_NON420
-const int kNumVp9TestVectors = 214;
+const int kNumVp9TestVectors = 215;
 #else
-const int kNumVp9TestVectors = 213;
+const int kNumVp9TestVectors = 214;
 #endif
 
 extern const char *kVP9TestVectors[kNumVp9TestVectors];
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/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/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/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/vp9_alloccommon.c b/vp9/common/vp9_alloccommon.c
index f567840..80c48d1 100644
--- a/vp9/common/vp9_alloccommon.c
+++ b/vp9/common/vp9_alloccommon.c
@@ -34,7 +34,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 +86,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 +138,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 +215,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..ead4661 100644
--- a/vp9/common/vp9_blockd.h
+++ b/vp9/common/vp9_blockd.h
@@ -238,6 +238,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 +412,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_loopfilter.c b/vp9/common/vp9_loopfilter.c
index c535723..1cf60af 100644
--- a/vp9/common/vp9_loopfilter.c
+++ b/vp9/common/vp9_loopfilter.c
@@ -968,15 +968,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_mvref_common.c b/vp9/common/vp9_mvref_common.c
index 8df8aec..df4961c 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
diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h
index a6e5b27..bfb94e4 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
@@ -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..449b945 100644
--- a/vp9/common/vp9_pred_common.c
+++ b/vp9/common/vp9_pred_common.c
@@ -16,12 +16,8 @@
 #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 +26,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)
@@ -50,8 +44,8 @@
 }
 // Returns a context number for the given MB prediction signal
 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;
@@ -76,8 +70,8 @@
 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,12 +113,10 @@
 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 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;
   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;
   // Note:
@@ -148,10 +140,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 +156,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,8 +192,8 @@
 
 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;
@@ -264,8 +256,8 @@
 
 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;
@@ -352,8 +344,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_reconinter.c b/vp9/common/vp9_reconinter.c
index a6e51d7..b177252 100644
--- a/vp9/common/vp9_reconinter.c
+++ b/vp9/common/vp9_reconinter.c
@@ -397,7 +397,7 @@
   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) {
+  if (ref >= cm->fb_count) {
     vp9_zero(*sf);
     vp9_zero(*sfc);
   } else {
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_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..0b0879e 100644
--- a/vp9/common/vp9_seg_common.h
+++ b/vp9/common/vp9_seg_common.h
@@ -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/decoder/vp9_decodeframe.c b/vp9/decoder/vp9_decodeframe.c
index daf89b4..c167004 100644
--- a/vp9/decoder/vp9_decodeframe.c
+++ b/vp9/decoder/vp9_decodeframe.c
@@ -305,12 +305,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,
@@ -707,9 +705,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,
@@ -1337,6 +1347,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 4e2bc35..305ed0d 100644
--- a/vp9/decoder/vp9_decodemv.c
+++ b/vp9/decoder/vp9_decodemv.c
@@ -528,7 +528,8 @@
     read_intra_block_mode_info(cm, mi, r);
 }
 
-void vp9_read_mode_info(VP9_COMMON *cm, MACROBLOCKD *xd, const TileInfo *tile,
+void vp9_read_mode_info(VP9_COMMON *cm, MACROBLOCKD *xd,
+                        const TileInfo *const tile,
                         int mi_row, int mi_col, vp9_reader *r) {
   if (frame_is_intra_only(cm))
     read_intra_frame_mode_info(cm, xd, mi_row, mi_col, r);
diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c
index 1356ca5..88e25eb 100644
--- a/vp9/encoder/vp9_bitstream.c
+++ b/vp9/encoder/vp9_bitstream.c
@@ -777,38 +777,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);
         }
       }
     }
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c
index 5f9d0c9..7af9a1f 100644
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -548,6 +548,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,
@@ -857,16 +860,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 +886,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 +1460,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;
@@ -1944,7 +1949,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))) {
@@ -2072,7 +2077,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);
 
@@ -2274,7 +2279,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;
diff --git a/vp9/encoder/vp9_encodemb.c b/vp9/encoder/vp9_encodemb.c
index e05ba1b..6bc1a4b 100644
--- a/vp9/encoder/vp9_encodemb.c
+++ b/vp9/encoder/vp9_encodemb.c
@@ -550,9 +550,6 @@
   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);
 
@@ -563,7 +560,7 @@
       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);
@@ -586,7 +583,7 @@
       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);
@@ -606,7 +603,7 @@
       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);
@@ -630,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,
diff --git a/vp9/encoder/vp9_encodemv.c b/vp9/encoder/vp9_encodemv.c
index 9af28f9..dae89ad 100644
--- a/vp9/encoder/vp9_encodemv.c
+++ b/vp9/encoder/vp9_encodemv.c
@@ -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);
 
@@ -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 cd6831a..b54f78a 100644
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -393,14 +393,14 @@
 }
 
 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;
@@ -440,21 +440,20 @@
   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.as_mv, &tmp_mv.as_mv,
+  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->as_mv);
+                                    x->mvcost, ref_mv);
   if (tmp_err < INT_MAX - new_mv_mode_penalty)
     tmp_err += new_mv_mode_penalty;
 
   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
@@ -467,18 +466,18 @@
     if (num00) {
       num00--;
     } else {
-      tmp_err = cpi->diamond_search_sad(x, &ref_mv_full.as_mv, &tmp_mv.as_mv,
+      tmp_err = cpi->diamond_search_sad(x, &ref_mv_full, &tmp_mv,
                                         step_param + n, x->sadperbit16,
                                         &num00, &v_fn_ptr,
                                         x->nmvjointcost,
-                                        x->mvcost, &ref_mv->as_mv);
+                                        x->mvcost, ref_mv);
       if (tmp_err < INT_MAX - new_mv_mode_penalty)
         tmp_err += new_mv_mode_penalty;
 
       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;
       }
     }
   }
@@ -649,9 +648,8 @@
 
         // 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;
@@ -661,7 +659,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;
@@ -679,9 +677,8 @@
           // Simple 0,0 motion with no mv overhead
           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;
@@ -1517,6 +1514,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;
@@ -1525,14 +1524,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);
   }
@@ -1630,16 +1629,17 @@
   // 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)) {
+          ((cpi->rc.frames_to_key - i) < MIN_GF_INTERVAL)) &&
+         (i < cpi->rc.frames_to_key)) {
     i++;    // Increment the loop counter
 
     // Accumulate error score of frames in this gf group
@@ -1694,7 +1694,7 @@
         // 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) &&
+        ((cpi->rc.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) ||
@@ -1710,17 +1710,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) {
       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;
       }
@@ -1747,7 +1747,7 @@
       (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)) &&
+      (i <= (cpi->rc.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) ||
@@ -1756,7 +1756,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.
@@ -1766,7 +1766,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) {
@@ -1821,7 +1821,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;
@@ -1857,7 +1857,8 @@
 
   // 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];
@@ -1868,7 +1869,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);
@@ -1921,7 +1922,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;
@@ -1940,7 +1941,7 @@
     // 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 (!cpi->rc.source_alt_ref_pending && cpi->common.frame_type != KEY_FRAME)
       cpi->twopass.gf_group_error_left = (int64_t)(gf_group_err
                                                    - gf_first_frame_err);
     else
@@ -1956,7 +1957,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) {
@@ -2098,7 +2099,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))
@@ -2108,7 +2109,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);
@@ -2119,8 +2120,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);
@@ -2131,7 +2130,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)
@@ -2146,7 +2145,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;
@@ -2178,7 +2178,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);
@@ -2274,6 +2274,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;
@@ -2300,15 +2301,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;
@@ -2360,14 +2361,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++;
   }
@@ -2377,11 +2378,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;
@@ -2394,7 +2395,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;
@@ -2407,9 +2408,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) {
@@ -2439,7 +2440,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 {
@@ -2455,7 +2456,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))
@@ -2498,7 +2499,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);
     }
@@ -2519,8 +2520,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;
@@ -2528,7 +2529,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.
@@ -2540,14 +2541,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
@@ -2569,10 +2570,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_mbgraph.c b/vp9/encoder/vp9_mbgraph.c
index e2ef256..32ab3fc 100644
--- a/vp9/encoder/vp9_mbgraph.c
+++ b/vp9/encoder/vp9_mbgraph.c
@@ -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 87b5988..382ccb0 100644
--- a/vp9/encoder/vp9_mcomp.c
+++ b/vp9/encoder/vp9_mcomp.c
@@ -688,7 +688,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)\
@@ -741,13 +741,13 @@
   int k = -1;
   int all_in;
   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);
@@ -760,7 +760,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
@@ -1212,13 +1212,13 @@
 
   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->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;
 
   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;
@@ -1234,7 +1234,7 @@
 
   // Check the starting position
   bestsad = fn_ptr->sdf(what, what_stride, in_what, in_what_stride, 0x7fffffff)
-                + mvsad_err_cost(best_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
@@ -1263,7 +1263,7 @@
         if (thissad < bestsad) {
           this_mv.row = this_row_offset;
           this_mv.col = this_col_offset;
-          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) {
@@ -1295,7 +1295,7 @@
           if (thissad < bestsad) {
             this_mv.row = this_row_offset;
             this_mv.col = this_col_offset;
-            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) {
               bestsad = thissad;
@@ -1356,13 +1356,13 @@
 
   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->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;
 
   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;
@@ -1378,7 +1378,7 @@
 
   // Check the starting position
   bestsad = fn_ptr->sdf(what, what_stride, in_what, in_what_stride, 0x7fffffff)
-                + mvsad_err_cost(best_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
@@ -1420,7 +1420,7 @@
           if (sad_array[t] < bestsad) {
             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.as_mv,
+            sad_array[t] += mvsad_err_cost(&this_mv, &fcenter_mv,
                                            mvjsadcost, mvsadcost, sad_per_bit);
 
             if (sad_array[t] < bestsad) {
@@ -1447,7 +1447,7 @@
           if (thissad < bestsad) {
             this_mv.row = this_row_offset;
             this_mv.col = this_col_offset;
-            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) {
@@ -1478,7 +1478,7 @@
           if (thissad < bestsad) {
             this_mv.row = this_row_offset;
             this_mv.col = this_col_offset;
-            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) {
               bestsad = thissad;
@@ -1585,7 +1585,7 @@
   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];
+  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;
@@ -1612,13 +1612,13 @@
   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,
+                           + mvsad_err_cost(best_mv, &fcenter_mv,
                                             mvjsadcost, mvsadcost, sad_per_bit);
 
   // Apply further limits to prevent us looking using vectors that stretch
@@ -1642,8 +1642,8 @@
 
       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;
       }
 
@@ -1651,8 +1651,8 @@
     }
   }
 
-  this_mv.row = best_mv->as_mv.row * 8;
-  this_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,
@@ -1674,7 +1674,7 @@
   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];
+  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;
@@ -1703,13 +1703,13 @@
   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,
+            + mvsad_err_cost(best_mv, &fcenter_mv,
                              mvjsadcost, mvsadcost, sad_per_bit);
 
   // Apply further limits to prevent us looking using vectors that stretch
@@ -1739,8 +1739,8 @@
 
           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;
           }
         }
@@ -1761,8 +1761,8 @@
 
         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;
         }
       }
@@ -1772,8 +1772,8 @@
     }
   }
 
-  this_mv.row = best_mv->as_mv.row * 8;
-  this_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,
@@ -1796,7 +1796,7 @@
   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];
+  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;
@@ -1826,13 +1826,13 @@
   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,
+            + mvsad_err_cost(best_mv, &fcenter_mv,
                              mvjsadcost, mvsadcost, sad_per_bit);
 
   // Apply further limits to prevent us looking using vectors that stretch
@@ -1862,8 +1862,8 @@
 
           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;
           }
         }
@@ -1888,8 +1888,8 @@
 
           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;
           }
         }
@@ -1910,8 +1910,8 @@
 
         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;
         }
       }
@@ -1921,8 +1921,8 @@
     }
   }
 
-  this_mv.row = best_mv->as_mv.row * 8;
-  this_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,
@@ -2136,9 +2136,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},
@@ -2150,32 +2150,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) &&
@@ -2189,9 +2189,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;
@@ -2204,22 +2204,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 c574e61..f9d1f90 100644
--- a/vp9/encoder/vp9_mcomp.h
+++ b/vp9/encoder/vp9_mcomp.h
@@ -124,9 +124,9 @@
                                        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 d7bfc1d..5bbd42b 100644
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -302,7 +302,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 +329,6 @@
     }
   }
 }
-
 static void configure_static_seg_features(VP9_COMP *cpi) {
   VP9_COMMON *cm = &cpi->common;
   struct segmentation *seg = &cm->seg;
@@ -389,7 +388,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 +420,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
@@ -926,7 +925,7 @@
   if (vp9_realloc_frame_buffer(&cpi->alt_ref_buffer,
                                cpi->oxcf.width, cpi->oxcf.height,
                                cm->subsampling_x, cm->subsampling_y,
-                               VP9BORDERINPIXELS))
+                               VP9BORDERINPIXELS, NULL, NULL, NULL))
     vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
                        "Failed to allocate altref buffer");
 }
@@ -994,14 +993,14 @@
   if (vp9_realloc_frame_buffer(&cpi->last_frame_uf,
                                cm->width, cm->height,
                                cm->subsampling_x, cm->subsampling_y,
-                               VP9BORDERINPIXELS))
+                               VP9BORDERINPIXELS, NULL, NULL, NULL))
     vpx_internal_error(&cpi->common.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))
+                               VP9BORDERINPIXELS, NULL, NULL, NULL))
     vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
                        "Failed to reallocate scaled source buffer");
 
@@ -1048,6 +1047,7 @@
 
   return 63;
 };
+
 void vp9_new_framerate(VP9_COMP *cpi, double framerate) {
   if (framerate < 0.1)
     framerate = 30;
@@ -1124,7 +1124,15 @@
   // 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;
+  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;
@@ -1288,6 +1296,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;
   }
 
@@ -1307,7 +1316,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
@@ -1567,14 +1576,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
@@ -1627,7 +1636,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;
@@ -1652,9 +1660,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
@@ -2309,11 +2314,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) {
@@ -2326,7 +2332,7 @@
     // 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
@@ -2336,8 +2342,8 @@
       }
     }
 
-    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)
@@ -2348,9 +2354,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++;
   }
 }
@@ -2569,7 +2572,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 {
@@ -2642,7 +2645,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);
 
@@ -2736,7 +2739,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));
 
@@ -2850,7 +2853,7 @@
       }
     }
 
-    if (cpi->is_src_frame_alt_ref)
+    if (cpi->rc.is_src_frame_alt_ref)
       loop = 0;
 
     if (loop) {
@@ -2873,7 +2876,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;
@@ -2912,14 +2914,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
@@ -2962,7 +2964,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 =
@@ -3029,8 +3031,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;
@@ -3050,7 +3051,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));
   }
 
@@ -3107,7 +3108,6 @@
     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);
@@ -3123,7 +3123,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);
@@ -3188,6 +3188,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;
 
@@ -3237,7 +3239,7 @@
     // 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;
@@ -3344,7 +3346,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
@@ -3358,7 +3360,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
@@ -3382,15 +3384,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.
     }
   }
 
@@ -3404,19 +3403,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;
@@ -3454,7 +3453,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;
@@ -3547,7 +3546,7 @@
         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");
   }
@@ -3560,7 +3559,7 @@
   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) {
diff --git a/vp9/encoder/vp9_onyx_int.h b/vp9/encoder/vp9_onyx_int.h
index 8f2ffc9..2d7cd01 100644
--- a/vp9/encoder/vp9_onyx_int.h
+++ b/vp9/encoder/vp9_onyx_int.h
@@ -294,7 +294,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;
@@ -306,13 +306,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
@@ -320,7 +324,7 @@
   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;
 
@@ -376,11 +380,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)
@@ -405,11 +405,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;
@@ -468,15 +463,10 @@
   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;
 
@@ -549,7 +539,6 @@
     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;
@@ -570,6 +559,9 @@
     int alt_extra_bits;
 
     int sr_update_lag;
+
+    int kf_zeromotion_pct;
+    int gf_zeromotion_pct;
   } twopass;
 
   YV12_BUFFER_CONFIG alt_ref_buffer;
diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c
index 3fa8cea..9ea0c3d 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];
@@ -275,7 +272,7 @@
     // 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 +440,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 +452,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 +479,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 +494,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 +510,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 +528,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 +548,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 +583,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,7 +605,7 @@
   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.
@@ -647,61 +642,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 +695,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,8 +705,29 @@
       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 a record of last Q and ambient average Q.
+  if (cm->frame_type == KEY_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;
+
+    // Calculate the average Q for normal inter frames (not key or GFU frames).
+    cpi->rc.ni_tot_qi += cm->base_qindex;
+    cpi->rc.ni_av_qi = cpi->rc.ni_tot_qi / cpi->rc.ni_frames;
+  }
 
   // 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.
@@ -777,32 +737,10 @@
   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->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref)))) {
     cpi->rc.last_boosted_qindex = cm->base_qindex;
   }
 
-  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.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;
-
-    // Calculate the average Q for normal inter frames (not key or GFU frames).
-    cpi->rc.ni_tot_qi += cm->base_qindex;
-    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)
diff --git a/vp9/encoder/vp9_ratectrl.h b/vp9/encoder/vp9_ratectrl.h
index 063ac8f..8113a05 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,
diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c
index 5702e5a..d464d15 100644
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -1042,7 +1042,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);
@@ -2532,11 +2532,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;
@@ -2748,6 +2748,7 @@
     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
   if (cm->mcomp_filter_type != BILINEAR) {
@@ -2757,7 +2758,7 @@
       *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;
 
@@ -3351,7 +3352,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) &&
@@ -3864,6 +3865,7 @@
     int this_skip2 = 0;
     int64_t total_sse = INT_MAX;
     int early_term = 0;
+    int64_t mask_rd = 0;
 
     for (i = 0; i < TX_MODES; ++i)
       tx_cache[i] = INT64_MAX;
@@ -3998,7 +4000,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;
     }
 
@@ -4057,21 +4059,20 @@
           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;
+      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;
-          vp9_zero(cpi->rd_filter_cache);
         } else if (cpi->sf.adaptive_pred_filter_type == 2) {
           tmp_best_filter = ctx->pred_filter_type < SWITCHABLE ?
                               ctx->pred_filter_type : 0;
-          vp9_zero(cpi->rd_filter_cache);
         } else {
           for (switchable_filter_index = 0;
                switchable_filter_index < SWITCHABLE_FILTERS;
@@ -4093,7 +4094,6 @@
 
             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_FILTERS] =
@@ -4102,6 +4102,9 @@
             if (cm->mcomp_filter_type == SWITCHABLE)
               tmp_rd += rs_rd;
 
+            cpi->rd_filter_cache[switchable_filter_index] = tmp_rd;
+            mask_rd = MAX(tmp_rd, mask_rd);
+
             newbest = (tmp_rd < tmp_best_rd);
             if (newbest) {
               tmp_best_filter = mbmi->interp_filter;
@@ -4349,16 +4352,17 @@
         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)
+          adj_rd = mask_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);
       }
     }
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.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_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/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/vp9_dx_iface.c b/vp9/vp9_dx_iface.c
index fde73e4..c123c46 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,
@@ -307,10 +314,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 +376,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 +504,27 @@
   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 < REF_FRAMES) {
+    /* The application must pass in at least REF_FRAMES 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 +689,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 +707,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 +724,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 +744,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 +772,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 +783,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 +796,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/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..5ab3256 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,36 @@
 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 8 external
+ * frame buffers, as VP9 can have up to 8 reference frames.
+ */
+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 +335,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 +531,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/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..1243ac1 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
@@ -351,4 +351,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..30a74ea 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,52 @@
 
   /*!@} - 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 8 external
+   * frame buffers, as VP9 can have up to 8 reference frames.
+   */
+  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..0b787b8
--- /dev/null
+++ b/vpx/vpx_external_frame_buffer.h
@@ -0,0 +1,53 @@
+/*
+ *  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 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..91d8faf 100644
--- a/vpxdec.c
+++ b/vpxdec.c
@@ -89,6 +89,10 @@
                                                    "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
@@ -98,7 +102,7 @@
 static const arg_def_t *all_args[] = {
   &codecarg, &use_yv12, &use_i420, &flipuvarg, &noblitarg,
   &progressarg, &limitarg, &skiparg, &postprocarg, &summaryarg, &outputfile,
-  &threadsarg, &verbosearg, &scalearg,
+  &threadsarg, &verbosearg, &scalearg, &fb_arg, &fb_lru_arg,
 #if CONFIG_MD5
   &md5arg,
 #endif
@@ -314,6 +318,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 +457,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 +519,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 +740,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 +938,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/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_