Merge "configure: default configure log to config.log"
diff --git a/build/make/configure.sh b/build/make/configure.sh
index 64ef2e6..30a6106 100755
--- a/build/make/configure.sh
+++ b/build/make/configure.sh
@@ -653,6 +653,10 @@
                 tgt_isa=x86_64
                 tgt_os=darwin12
                 ;;
+            *darwin13*)
+                tgt_isa=x86_64
+                tgt_os=darwin13
+                ;;
             x86_64*mingw32*)
                 tgt_os=win64
                 ;;
@@ -751,6 +755,10 @@
             add_cflags  "-mmacosx-version-min=10.8"
             add_ldflags "-mmacosx-version-min=10.8"
             ;;
+        *-darwin13-*)
+            add_cflags  "-mmacosx-version-min=10.9"
+            add_ldflags "-mmacosx-version-min=10.9"
+            ;;
     esac
 
     # Handle Solaris variants. Solaris 10 needs -lposix4
diff --git a/build/make/obj_int_extract.c b/build/make/obj_int_extract.c
index 1604b5e..feed9d9 100644
--- a/build/make/obj_int_extract.c
+++ b/build/make/obj_int_extract.c
@@ -38,7 +38,21 @@
 #include <mach-o/loader.h>
 #include <mach-o/nlist.h>
 
-int parse_macho(uint8_t *base_buf, size_t sz) {
+int print_macho_equ(output_fmt_t mode, uint8_t* name, int val) {
+  switch (mode) {
+    case OUTPUT_FMT_RVDS:
+      printf("%-40s EQU %5d\n", name, val);
+      return 0;
+    case  OUTPUT_FMT_GAS:
+      printf(".set %-40s, %5d\n", name, val);
+      return 0;
+    default:
+      log_msg("Unsupported mode: %d", mode);
+      return 1;
+  }
+}
+
+int parse_macho(uint8_t *base_buf, size_t sz, output_fmt_t mode) {
   int i, j;
   struct mach_header header;
   uint8_t *buf = base_buf;
@@ -156,8 +170,7 @@
 
             memcpy(&val, base_buf + base_data_section + nl.n_value,
                    sizeof(val));
-            printf("%-40s EQU %5d\n",
-                   str_buf + nl.n_un.n_strx + 1, val);
+            print_macho_equ(mode, str_buf + nl.n_un.n_strx + 1, val);
           } else { /* if (bits == 64) */
             struct nlist_64 nl;
             int val;
@@ -167,8 +180,7 @@
 
             memcpy(&val, base_buf + base_data_section + nl.n_value,
                    sizeof(val));
-            printf("%-40s EQU %5d\n",
-                   str_buf + nl.n_un.n_strx + 1, val);
+            print_macho_equ(mode, str_buf + nl.n_un.n_strx + 1, val);
           }
         }
       }
@@ -796,7 +808,7 @@
 
 #if defined(__GNUC__) && __GNUC__
 #if defined(__MACH__)
-  res = parse_macho(file_buf, file_size);
+  res = parse_macho(file_buf, file_size, mode);
 #elif defined(__ELF__)
   res = parse_elf(file_buf, file_size, mode);
 #endif
diff --git a/configure b/configure
index 36fc08f..bc6439d 100755
--- a/configure
+++ b/configure
@@ -115,6 +115,7 @@
 all_platforms="${all_platforms} x86-darwin10-gcc"
 all_platforms="${all_platforms} x86-darwin11-gcc"
 all_platforms="${all_platforms} x86-darwin12-gcc"
+all_platforms="${all_platforms} x86-darwin13-gcc"
 all_platforms="${all_platforms} x86-linux-gcc"
 all_platforms="${all_platforms} x86-linux-icc"
 all_platforms="${all_platforms} x86-os2-gcc"
@@ -129,6 +130,7 @@
 all_platforms="${all_platforms} x86_64-darwin10-gcc"
 all_platforms="${all_platforms} x86_64-darwin11-gcc"
 all_platforms="${all_platforms} x86_64-darwin12-gcc"
+all_platforms="${all_platforms} x86_64-darwin13-gcc"
 all_platforms="${all_platforms} x86_64-linux-gcc"
 all_platforms="${all_platforms} x86_64-linux-icc"
 all_platforms="${all_platforms} x86_64-solaris-gcc"
@@ -142,6 +144,7 @@
 all_platforms="${all_platforms} universal-darwin10-gcc"
 all_platforms="${all_platforms} universal-darwin11-gcc"
 all_platforms="${all_platforms} universal-darwin12-gcc"
+all_platforms="${all_platforms} universal-darwin13-gcc"
 all_platforms="${all_platforms} generic-gnu"
 
 # all_targets is a list of all targets that can be configured
diff --git a/test/idct_test.cc b/test/idct_test.cc
index 659cce0..aa786cb 100644
--- a/test/idct_test.cc
+++ b/test/idct_test.cc
@@ -8,7 +8,6 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-
 extern "C" {
 #include "./vpx_config.h"
 #include "./vp8_rtcd.h"
@@ -22,100 +21,94 @@
                           int dst_stride);
 namespace {
 class IDCTTest : public ::testing::TestWithParam<idct_fn_t> {
-  protected:
-    virtual void SetUp() {
-        int i;
+ protected:
+  virtual void SetUp() {
+    int i;
 
-        UUT = GetParam();
-        memset(input, 0, sizeof(input));
-        /* Set up guard blocks */
-        for (i = 0; i < 256; i++)
-            output[i] = ((i & 0xF) < 4 && (i < 64)) ? 0 : -1;
-    }
+    UUT = GetParam();
+    memset(input, 0, sizeof(input));
+    /* Set up guard blocks */
+    for (i = 0; i < 256; i++) output[i] = ((i & 0xF) < 4 && (i < 64)) ? 0 : -1;
+  }
 
-    virtual void TearDown() {
-      libvpx_test::ClearSystemState();
-    }
+  virtual void TearDown() { libvpx_test::ClearSystemState(); }
 
-    idct_fn_t UUT;
-    short input[16];
-    unsigned char output[256];
-    unsigned char predict[256];
+  idct_fn_t UUT;
+  short input[16];
+  unsigned char output[256];
+  unsigned char predict[256];
 };
 
 TEST_P(IDCTTest, TestGuardBlocks) {
-    int i;
+  int i;
 
-    for (i = 0; i < 256; i++)
-        if ((i & 0xF) < 4 && i < 64)
-            EXPECT_EQ(0, output[i]) << i;
-        else
-            EXPECT_EQ(255, output[i]);
+  for (i = 0; i < 256; i++)
+    if ((i & 0xF) < 4 && i < 64)
+      EXPECT_EQ(0, output[i]) << i;
+    else
+      EXPECT_EQ(255, output[i]);
 }
 
 TEST_P(IDCTTest, TestAllZeros) {
-    int i;
+  int i;
 
-    REGISTER_STATE_CHECK(UUT(input, output, 16, output, 16));
+  REGISTER_STATE_CHECK(UUT(input, output, 16, output, 16));
 
-    for (i = 0; i < 256; i++)
-        if ((i & 0xF) < 4 && i < 64)
-            EXPECT_EQ(0, output[i]) << "i==" << i;
-        else
-            EXPECT_EQ(255, output[i]) << "i==" << i;
+  for (i = 0; i < 256; i++)
+    if ((i & 0xF) < 4 && i < 64)
+      EXPECT_EQ(0, output[i]) << "i==" << i;
+    else
+      EXPECT_EQ(255, output[i]) << "i==" << i;
 }
 
 TEST_P(IDCTTest, TestAllOnes) {
-    int i;
+  int i;
 
-    input[0] = 4;
-    REGISTER_STATE_CHECK(UUT(input, output, 16, output, 16));
+  input[0] = 4;
+  REGISTER_STATE_CHECK(UUT(input, output, 16, output, 16));
 
-    for (i = 0; i < 256; i++)
-        if ((i & 0xF) < 4 && i < 64)
-            EXPECT_EQ(1, output[i]) << "i==" << i;
-        else
-            EXPECT_EQ(255, output[i]) << "i==" << i;
+  for (i = 0; i < 256; i++)
+    if ((i & 0xF) < 4 && i < 64)
+      EXPECT_EQ(1, output[i]) << "i==" << i;
+    else
+      EXPECT_EQ(255, output[i]) << "i==" << i;
 }
 
 TEST_P(IDCTTest, TestAddOne) {
-    int i;
+  int i;
 
-    for (i = 0; i < 256; i++)
-        predict[i] = i;
-    input[0] = 4;
-    REGISTER_STATE_CHECK(UUT(input, predict, 16, output, 16));
+  for (i = 0; i < 256; i++) predict[i] = i;
+  input[0] = 4;
+  REGISTER_STATE_CHECK(UUT(input, predict, 16, output, 16));
 
-    for (i = 0; i < 256; i++)
-        if ((i & 0xF) < 4 && i < 64)
-            EXPECT_EQ(i+1, output[i]) << "i==" << i;
-        else
-            EXPECT_EQ(255, output[i]) << "i==" << i;
+  for (i = 0; i < 256; i++)
+    if ((i & 0xF) < 4 && i < 64)
+      EXPECT_EQ(i + 1, output[i]) << "i==" << i;
+    else
+      EXPECT_EQ(255, output[i]) << "i==" << i;
 }
 
 TEST_P(IDCTTest, TestWithData) {
-    int i;
+  int i;
 
-    for (i = 0; i < 16; i++)
-        input[i] = i;
+  for (i = 0; i < 16; i++) input[i] = i;
 
-    REGISTER_STATE_CHECK(UUT(input, output, 16, output, 16));
+  REGISTER_STATE_CHECK(UUT(input, output, 16, output, 16));
 
-    for (i = 0; i < 256; i++)
-        if ((i & 0xF) > 3 || i > 63)
-            EXPECT_EQ(255, output[i]) << "i==" << i;
-        else if (i == 0)
-            EXPECT_EQ(11, output[i]) << "i==" << i;
-        else if (i == 34)
-            EXPECT_EQ(1, output[i]) << "i==" << i;
-        else if (i == 2 || i == 17 || i == 32)
-            EXPECT_EQ(3, output[i]) << "i==" << i;
-        else
-            EXPECT_EQ(0, output[i]) << "i==" << i;
+  for (i = 0; i < 256; i++)
+    if ((i & 0xF) > 3 || i > 63)
+      EXPECT_EQ(255, output[i]) << "i==" << i;
+    else if (i == 0)
+      EXPECT_EQ(11, output[i]) << "i==" << i;
+    else if (i == 34)
+      EXPECT_EQ(1, output[i]) << "i==" << i;
+    else if (i == 2 || i == 17 || i == 32)
+      EXPECT_EQ(3, output[i]) << "i==" << i;
+    else
+      EXPECT_EQ(0, output[i]) << "i==" << i;
 }
 
-INSTANTIATE_TEST_CASE_P(C, IDCTTest,
-                        ::testing::Values(vp8_short_idct4x4llm_c));
+INSTANTIATE_TEST_CASE_P(C, IDCTTest, ::testing::Values(vp8_short_idct4x4llm_c));
 #if HAVE_MMX
 INSTANTIATE_TEST_CASE_P(MMX, IDCTTest,
                         ::testing::Values(vp8_short_idct4x4llm_mmx));
diff --git a/test/ivf_video_source.h b/test/ivf_video_source.h
index 88bc597..926f801 100644
--- a/test/ivf_video_source.h
+++ b/test/ivf_video_source.h
@@ -47,7 +47,8 @@
   virtual void Init() {
     // Allocate a buffer for read in the compressed video frame.
     compressed_frame_buf_ = new uint8_t[libvpx_test::kCodeBufferSize];
-    ASSERT_TRUE(compressed_frame_buf_) << "Allocate frame buffer failed";
+    ASSERT_TRUE(compressed_frame_buf_ != NULL)
+        << "Allocate frame buffer failed";
   }
 
   virtual void Begin() {
diff --git a/test/subtract_test.cc b/test/subtract_test.cc
index 81bfb66..574bfbf 100644
--- a/test/subtract_test.cc
+++ b/test/subtract_test.cc
@@ -61,7 +61,7 @@
     int16_t *src_diff = be.src_diff;
     for (int r = 0; r < kBlockHeight; ++r) {
       for (int c = 0; c < kBlockWidth; ++c) {
-        src_diff[c] = 0xa5a5;
+        src_diff[c] = static_cast<int16_t>(0xa5a5);
       }
       src_diff += kDiffPredStride;
     }
diff --git a/test/tile_independence_test.cc b/test/tile_independence_test.cc
index 9633ed7..403dbb6 100644
--- a/test/tile_independence_test.cc
+++ b/test/tile_independence_test.cc
@@ -23,10 +23,13 @@
 
 namespace {
 class TileIndependenceTest : public ::libvpx_test::EncoderTest,
-    public ::libvpx_test::CodecTestWithParam<int> {
+                             public ::libvpx_test::CodecTestWithParam<int> {
  protected:
-  TileIndependenceTest() : EncoderTest(GET_PARAM(0)), n_tiles_(GET_PARAM(1)),
-      md5_fw_order_(), md5_inv_order_() {
+  TileIndependenceTest()
+      : EncoderTest(GET_PARAM(0)),
+        md5_fw_order_(),
+        md5_inv_order_(),
+        n_tiles_(GET_PARAM(1)) {
     init_flags_ = VPX_CODEC_USE_PSNR;
     vpx_codec_dec_cfg_t cfg;
     cfg.w = 704;
@@ -56,9 +59,8 @@
 
   void UpdateMD5(::libvpx_test::Decoder *dec, const vpx_codec_cx_pkt_t *pkt,
                  ::libvpx_test::MD5 *md5) {
-    const vpx_codec_err_t res =
-        dec->DecodeFrame(reinterpret_cast<uint8_t*>(pkt->data.frame.buf),
-                         pkt->data.frame.sz);
+    const vpx_codec_err_t res = dec->DecodeFrame(
+        reinterpret_cast<uint8_t*>(pkt->data.frame.buf), pkt->data.frame.sz);
     if (res != VPX_CODEC_OK) {
       abort_ = true;
       ASSERT_EQ(VPX_CODEC_OK, res);
@@ -72,11 +74,11 @@
     UpdateMD5(inv_dec_, pkt, &md5_inv_order_);
   }
 
- private:
-  int n_tiles_;
- protected:
   ::libvpx_test::MD5 md5_fw_order_, md5_inv_order_;
   ::libvpx_test::Decoder *fw_dec_, *inv_dec_;
+
+ private:
+  int n_tiles_;
 };
 
 // run an encode with 2 or 4 tiles, and do the decode both in normal and
@@ -93,7 +95,7 @@
                                      timebase.den, timebase.num, 0, 30);
   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
 
-  const char *md5_fw_str  = md5_fw_order_.Get();
+  const char *md5_fw_str = md5_fw_order_.Get();
   const char *md5_inv_str = md5_inv_order_.Get();
 
   // could use ASSERT_EQ(!memcmp(.., .., 16) here, but this gives nicer
@@ -102,7 +104,6 @@
   ASSERT_STREQ(md5_fw_str, md5_inv_str);
 }
 
-VP9_INSTANTIATE_TEST_CASE(TileIndependenceTest,
-                          ::testing::Range(0, 2, 1));
+VP9_INSTANTIATE_TEST_CASE(TileIndependenceTest, ::testing::Range(0, 2, 1));
 
 }  // namespace
diff --git a/test/util.h b/test/util.h
index 533a1db..4d7f3d4 100644
--- a/test/util.h
+++ b/test/util.h
@@ -37,7 +37,7 @@
                   img2->planes[VPX_PLANE_Y][i * img2->stride[VPX_PLANE_Y] + j];
       sqrerr += d * d;
     }
-  double mse = sqrerr / (width_y * height_y);
+  double mse = static_cast<double>(sqrerr) / (width_y * height_y);
   double psnr = 100.0;
   if (mse > 0.0) {
     psnr = 10 * log10(255.0 * 255.0 / mse);
diff --git a/vp8/common/onyxc_int.h b/vp8/common/onyxc_int.h
index a0c97a1..e9bb7af 100644
--- a/vp8/common/onyxc_int.h
+++ b/vp8/common/onyxc_int.h
@@ -114,9 +114,6 @@
     int uvdc_delta_q;
     int uvac_delta_q;
 
-    unsigned int frames_since_golden;
-    unsigned int frames_till_alt_ref_frame;
-
     /* We allocate a MODE_INFO struct for each macroblock, together with
        an extra row on top and column on the left to simplify prediction. */
 
diff --git a/vp8/encoder/firstpass.c b/vp8/encoder/firstpass.c
index 4eac3b6..ded0c43 100644
--- a/vp8/encoder/firstpass.c
+++ b/vp8/encoder/firstpass.c
@@ -2398,7 +2398,7 @@
     target_frame_size += cpi->min_frame_bandwidth;
 
     /* Every other frame gets a few extra bits */
-    if ( (cpi->common.frames_since_golden & 0x01) &&
+    if ( (cpi->frames_since_golden & 0x01) &&
          (cpi->frames_till_gf_update_due > 0) )
     {
         target_frame_size += cpi->twopass.alt_extra_bits;
diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c
index c73060f..7c07975 100644
--- a/vp8/encoder/onyx_if.c
+++ b/vp8/encoder/onyx_if.c
@@ -2750,7 +2750,7 @@
     cpi->gf_active_count = cm->mb_rows * cm->mb_cols;
 
     /* this frame refreshes means next frames don't unless specified by user */
-    cpi->common.frames_since_golden = 0;
+    cpi->frames_since_golden = 0;
 
     /* Clear the alternate reference update pending flag. */
     cpi->source_alt_ref_pending = 0;
@@ -2802,7 +2802,7 @@
          * user
          */
         cm->refresh_golden_frame = 0;
-        cpi->common.frames_since_golden = 0;
+        cpi->frames_since_golden = 0;
 
         cpi->recent_ref_frame_usage[INTRA_FRAME] = 1;
         cpi->recent_ref_frame_usage[LAST_FRAME] = 1;
@@ -2834,12 +2834,12 @@
         if (cpi->frames_till_gf_update_due > 0)
             cpi->frames_till_gf_update_due--;
 
-        if (cpi->common.frames_till_alt_ref_frame)
-            cpi->common.frames_till_alt_ref_frame --;
+        if (cpi->frames_till_alt_ref_frame)
+            cpi->frames_till_alt_ref_frame --;
 
-        cpi->common.frames_since_golden ++;
+        cpi->frames_since_golden ++;
 
-        if (cpi->common.frames_since_golden > 1)
+        if (cpi->frames_since_golden > 1)
         {
             cpi->recent_ref_frame_usage[INTRA_FRAME] +=
                 cpi->mb.count_mb_ref_frame_usage[INTRA_FRAME];
@@ -2890,11 +2890,11 @@
             cpi->prob_last_coded = 200;
             cpi->prob_gf_coded = 1;
         }
-        else if (cpi->common.frames_since_golden == 0)
+        else if (cpi->frames_since_golden == 0)
         {
             cpi->prob_last_coded = 214;
         }
-        else if (cpi->common.frames_since_golden == 1)
+        else if (cpi->frames_since_golden == 1)
         {
             cpi->prob_last_coded = 192;
             cpi->prob_gf_coded = 220;
@@ -4934,7 +4934,7 @@
                                               cpi->frames_till_gf_update_due);
                 force_src_buffer = &cpi->alt_ref_buffer;
             }
-            cm->frames_till_alt_ref_frame = cpi->frames_till_gf_update_due;
+            cpi->frames_till_alt_ref_frame = cpi->frames_till_gf_update_due;
             cm->refresh_alt_ref_frame = 1;
             cm->refresh_golden_frame = 0;
             cm->refresh_last_frame = 0;
diff --git a/vp8/encoder/onyx_int.h b/vp8/encoder/onyx_int.h
index f49cfe3..3ab0fe8 100644
--- a/vp8/encoder/onyx_int.h
+++ b/vp8/encoder/onyx_int.h
@@ -320,6 +320,7 @@
     YV12_BUFFER_CONFIG scaled_source;
     YV12_BUFFER_CONFIG *last_frame_unscaled_source;
 
+    unsigned int frames_till_alt_ref_frame;
     /* frame in src_buffers has been identified to be encoded as an alt ref */
     int source_alt_ref_pending;
     /* an alt ref frame has been encoded and is usable */
@@ -369,6 +370,7 @@
     double key_frame_rate_correction_factor;
     double gf_rate_correction_factor;
 
+    unsigned int frames_since_golden;
     /* Count down till next GF */
     int frames_till_gf_update_due;
 
diff --git a/vp8/encoder/ratectrl.c b/vp8/encoder/ratectrl.c
index fd71b9a..1e8259c 100644
--- a/vp8/encoder/ratectrl.c
+++ b/vp8/encoder/ratectrl.c
@@ -234,7 +234,7 @@
     cc->frames_since_key          = cpi->frames_since_key;
     cc->filter_level             = cpi->common.filter_level;
     cc->frames_till_gf_update_due   = cpi->frames_till_gf_update_due;
-    cc->frames_since_golden       = cpi->common.frames_since_golden;
+    cc->frames_since_golden       = cpi->frames_since_golden;
 
     vp8_copy(cc->mvc,      cpi->common.fc.mvc);
     vp8_copy(cc->mvcosts,  cpi->rd_costs.mvcosts);
@@ -271,7 +271,7 @@
     cpi->frames_since_key         =   cc->frames_since_key;
     cpi->common.filter_level     =   cc->filter_level;
     cpi->frames_till_gf_update_due  =   cc->frames_till_gf_update_due;
-    cpi->common.frames_since_golden       =   cc->frames_since_golden;
+    cpi->frames_since_golden       =   cc->frames_since_golden;
 
     vp8_copy(cpi->common.fc.mvc, cc->mvc);
 
@@ -715,7 +715,7 @@
                 if (Adjustment > (cpi->this_frame_target - min_frame_target))
                     Adjustment = (cpi->this_frame_target - min_frame_target);
 
-                if (cpi->common.frames_since_golden == (cpi->current_gf_interval >> 1))
+                if (cpi->frames_since_golden == (cpi->current_gf_interval >> 1))
                     cpi->this_frame_target += ((cpi->current_gf_interval - 1) * Adjustment);
                 else
                     cpi->this_frame_target -= Adjustment;
diff --git a/vp9/common/arm/neon/vp9_loopfilter_neon.asm b/vp9/common/arm/neon/vp9_loopfilter_neon.asm
index d6f1f0b..4fe1a6a 100644
--- a/vp9/common/arm/neon/vp9_loopfilter_neon.asm
+++ b/vp9/common/arm/neon/vp9_loopfilter_neon.asm
@@ -38,6 +38,7 @@
     push        {lr}
 
     ldr         r12, [sp,#8]               ; load count
+    add         r1, r1, r1                 ; double pitch
     cmp         r12, #0
     beq         end_vp9_lf_h_edge
 
@@ -47,9 +48,8 @@
     vld1.8      {d2[]}, [r2]               ; duplicate *thresh
 
 count_lf_h_loop
-    sub         r2, r0, r1, lsl #2         ; move src pointer down by 4 lines
-    add         r3, r2, r1
-    add         r1, r1, r1
+    sub         r2, r0, r1, lsl #1         ; move src pointer down by 4 lines
+    add         r3, r2, r1, lsr #1         ; set to 3 lines down
 
     vld1.u8     {d3}, [r2@64], r1          ; p3
     vld1.u8     {d4}, [r3@64], r1          ; p2
@@ -278,6 +278,7 @@
     push        {r4-r5, lr}
 
     ldr         r12, [sp,#16]              ; load count
+    add         r1, r1, r1                 ; double pitch
     cmp         r12, #0
     beq         end_vp9_mblf_h_edge
 
@@ -287,9 +288,8 @@
     vld1.8      {d2[]}, [r2]               ; duplicate *thresh
 
 count_mblf_h_loop
-    sub         r3, r0, r1, lsl #2         ; move src pointer down by 4 lines
-    add         r2, r3, r1
-    add         r1, r1, r1
+    sub         r3, r0, r1, lsl #1         ; move src pointer down by 4 lines
+    add         r2, r3, r1, lsr #1         ; set to 3 lines down
 
     vld1.u8     {d3}, [r3@64], r1          ; p3
     vld1.u8     {d4}, [r2@64], r1          ; p2
diff --git a/vp9/common/arm/neon/vp9_short_idct8x8_add_neon.asm b/vp9/common/arm/neon/vp9_short_idct8x8_add_neon.asm
new file mode 100644
index 0000000..8e4aada
--- /dev/null
+++ b/vp9/common/arm/neon/vp9_short_idct8x8_add_neon.asm
@@ -0,0 +1,356 @@
+;
+;  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.
+;
+
+    EXPORT  |vp9_short_idct8x8_add_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+    ; Parallel 1D IDCT on all the columns of a 8x8 16bit data matrix which are
+    ; loaded in q8-q15. The output will be stored back into q8-q15 registers.
+    ; This macro will touch q0-q7 registers and use them as buffer during
+    ; calculation.
+    MACRO
+    IDCT8x8_1D
+    ; stage 1
+    vdup.16         d0, r3;                   ; duplicate cospi_28_64
+    vdup.16         d1, r4;                   ; duplicate cospi_4_64
+
+    ; input[1] * cospi_28_64
+    vmull.s16       q2, d18, d0
+    vmull.s16       q3, d19, d0
+
+    ; input[7] * cospi_4_64
+    vmull.s16       q4, d30, d1
+    vmull.s16       q5, d31, d1
+
+    ; input[1]*cospi_28_64-input[7]*cospi_4_64
+    vsub.s32        q6, q2, q4
+    vsub.s32        q7, q3, q5
+
+    ; dct_const_round_shift(input_dc * cospi_16_64)
+    vqrshrn.s32     d8, q6, #14               ; >> 14
+    vqrshrn.s32     d9, q7, #14               ; >> 14
+
+    ; input[1] * cospi_4_64
+    vmull.s16       q2, d18, d1
+    vmull.s16       q3, d19, d1
+
+    ; input[7] * cospi_28_64
+    vmull.s16       q1, d30, d0
+    vmull.s16       q5, d31, d0
+
+    ; input[1]*cospi_4_64+input[7]*cospi_28_64
+    vadd.s32        q2, q2, q1
+    vadd.s32        q3, q3, q5
+
+    ; dct_const_round_shift(input_dc * cospi_16_64)
+    vqrshrn.s32     d14, q2, #14              ; >> 14
+    vqrshrn.s32     d15, q3, #14              ; >> 14
+
+    vdup.16         d0, r5;                   ; duplicate cospi_12_64
+    vdup.16         d1, r6;                   ; duplicate cospi_20_64
+
+    ; input[5] * cospi_12_64
+    vmull.s16       q2, d26, d0
+    vmull.s16       q3, d27, d0
+
+    ; input[3] * cospi_20_64
+    vmull.s16       q5, d22, d1
+    vmull.s16       q6, d23, d1
+
+    ; input[5] * cospi_12_64 - input[3] * cospi_20_64
+    vsub.s32        q2, q2, q5
+    vsub.s32        q3, q3, q6
+
+    ; dct_const_round_shift(input_dc * cospi_16_64)
+    vqrshrn.s32     d10, q2, #14              ; >> 14
+    vqrshrn.s32     d11, q3, #14              ; >> 14
+
+    ; input[5] * cospi_20_64
+    vmull.s16       q2, d26, d1
+    vmull.s16       q3, d27, d1
+
+    ; input[3] * cospi_12_64
+    vmull.s16       q9, d22, d0
+    vmull.s16       q15, d23, d0
+
+    ; input[5] * cospi_20_64 + input[3] * cospi_12_64
+    vadd.s32        q0, q2, q9
+    vadd.s32        q1, q3, q15
+
+    ; dct_const_round_shift(input_dc * cospi_16_64)
+    vqrshrn.s32     d12, q0, #14              ; >> 14
+    vqrshrn.s32     d13, q1, #14              ; >> 14
+
+    ; stage 2 & stage 3 - even half
+    vdup.16         d0, r7;                   ; duplicate cospi_16_64
+
+    ; input[0] * cospi_16_64
+    vmull.s16       q2, d16, d0
+    vmull.s16       q3, d17, d0
+
+    ; input[2] * cospi_16_64
+    vmull.s16       q9,  d24, d0
+    vmull.s16       q11, d25, d0
+
+    ; (input[0] + input[2]) * cospi_16_64
+    vadd.s32        q9, q2, q9
+    vadd.s32        q11, q3, q11
+
+    ; dct_const_round_shift(input_dc * cospi_16_64)
+    vqrshrn.s32     d18, q9, #14              ; >> 14
+    vqrshrn.s32     d19, q11, #14             ; >> 14
+
+    ; input[0] * cospi_16_64
+    vmull.s16       q2, d16, d0
+    vmull.s16       q3, d17, d0
+
+    ; input[2] * cospi_16_64
+    vmull.s16       q13,  d24, d0
+    vmull.s16       q15, d25, d0
+
+    ; (input[0] - input[2]) * cospi_16_64
+    vsub.s32        q2, q2, q13
+    vsub.s32        q3, q3, q15
+
+    ; dct_const_round_shift(input_dc * cospi_16_64)
+    vqrshrn.s32     d22, q2, #14              ; >> 14
+    vqrshrn.s32     d23, q3, #14              ; >> 14
+
+    ; input[1] * cospi_24_64 - input[3] * cospi_8_64
+    vdup.16         d0, r8;                   ; duplicate cospi_24_64
+    vdup.16         d1, r9;                   ; duplicate cospi_8_64
+
+    ; input[1] * cospi_24_64
+    vmull.s16       q2, d20, d0
+    vmull.s16       q3, d21, d0
+
+    ; input[3] * cospi_8_64
+    vmull.s16       q13, d28, d1
+    vmull.s16       q15, d29, d1
+
+    ; input[1] * cospi_24_64 - input[3] * cospi_8_64
+    vsub.s32        q2, q2, q13
+    vsub.s32        q3, q3, q15
+
+    ; dct_const_round_shift(input_dc * cospi_16_64)
+    vqrshrn.s32     d26, q2, #14              ; >> 14
+    vqrshrn.s32     d27, q3, #14              ; >> 14
+
+    ; input[1] * cospi_8_64
+    vmull.s16       q2, d20, d1
+    vmull.s16       q3, d21, d1
+
+    ; input[3] * cospi_24_64
+    vmull.s16       q8, d28, d0
+    vmull.s16       q10, d29, d0
+
+    ; input[1] * cospi_8_64 + input[3] * cospi_24_64
+    vadd.s32        q0, q2, q8
+    vadd.s32        q1, q3, q10
+
+    ; dct_const_round_shift(input_dc * cospi_16_64)
+    vqrshrn.s32     d30, q0, #14              ; >> 14
+    vqrshrn.s32     d31, q1, #14              ; >> 14
+
+
+    vadd.s16        q0, q9, q15               ; output[0] = step[0] + step[3]
+    vadd.s16        q1, q11, q13              ; output[1] = step[1] + step[2]
+    vsub.s16        q2, q11, q13              ; output[2] = step[1] - step[2]
+    vsub.s16        q3, q9, q15               ; output[3] = step[0] - step[3]
+
+    ; stage 2 - odd half
+    vsub.s16        q13, q4, q5               ; step2[5] = step1[4] - step1[5]
+    vadd.s16        q4, q4, q5                ; step2[4] = step1[4] + step1[5]
+    vsub.s16        q14, q7, q6               ; step2[6] = -step1[6] + step1[7]
+    vadd.s16        q7, q7, q6                ; step2[7] = step1[6] + step1[7]
+
+    ; stage 3 -odd half
+    vdup.16         d16, r7;                   ; duplicate cospi_16_64
+
+    ; step2[6] * cospi_16_64
+    vmull.s16       q9, d28, d16
+    vmull.s16       q10, d29, d16
+
+    ; step2[5] * cospi_16_64
+    vmull.s16       q11, d26, d16
+    vmull.s16       q12, d27, d16
+
+    ; (step2[6] - step2[5]) * cospi_16_64
+    vsub.s32        q9, q9, q11
+    vsub.s32        q10, q10, q12
+
+    ; dct_const_round_shift(input_dc * cospi_16_64)
+    vqrshrn.s32     d10, q9, #14              ; >> 14
+    vqrshrn.s32     d11, q10, #14             ; >> 14
+
+    ; step2[6] * cospi_16_64
+    vmull.s16       q9, d28, d16
+    vmull.s16       q10, d29, d16
+
+    ; step2[5] * cospi_16_64
+    vmull.s16       q11, d26, d16
+    vmull.s16       q12, d27, d16
+
+    ; (step2[5] + step2[6]) * cospi_16_64
+    vadd.s32        q9, q9, q11
+    vadd.s32        q10, q10, q12
+
+    ; dct_const_round_shift(input_dc * cospi_16_64)
+    vqrshrn.s32     d12, q9, #14              ; >> 14
+    vqrshrn.s32     d13, q10, #14             ; >> 14
+
+    ; stage 4
+    vadd.s16        q8, q0, q7;               ; output[0] = step1[0] + step1[7];
+    vadd.s16        q9, q1, q6;               ; output[1] = step1[1] + step1[6];
+    vadd.s16        q10, q2, q5;              ; output[2] = step1[2] + step1[5];
+    vadd.s16        q11, q3, q4;              ; output[3] = step1[3] + step1[4];
+    vsub.s16        q12, q3, q4;              ; output[4] = step1[3] - step1[4];
+    vsub.s16        q13, q2, q5;              ; output[5] = step1[2] - step1[5];
+    vsub.s16        q14, q1, q6;              ; output[6] = step1[1] - step1[6];
+    vsub.s16        q15, q0, q7;              ; output[7] = step1[0] - step1[7];
+    MEND
+
+    ; Transpose a 8x8 16bit data matrix. Datas are loaded in q8-q15.
+    MACRO
+    TRANSPOSE8X8
+    vswp            d17, d24
+    vswp            d23, d30
+    vswp            d21, d28
+    vswp            d19, d26
+    vtrn.32         q8, q10
+    vtrn.32         q9, q11
+    vtrn.32         q12, q14
+    vtrn.32         q13, q15
+    vtrn.16         q8, q9
+    vtrn.16         q10, q11
+    vtrn.16         q12, q13
+    vtrn.16         q14, q15
+    MEND
+
+    AREA    Block, CODE, READONLY ; name this block of code
+;void vp9_short_idct8x8_add_neon(int16_t *input, uint8_t *dest, int dest_stride)
+;
+; r0  int16_t input
+; r1  uint8_t *dest
+; r2  int dest_stride)
+
+|vp9_short_idct8x8_add_neon| PROC
+    push            {r4-r9}
+    vld1.s16        {q8}, [r0]!
+    vld1.s16        {q9}, [r0]!
+    vld1.s16        {q10}, [r0]!
+    vld1.s16        {q11}, [r0]!
+    vld1.s16        {q12}, [r0]!
+    vld1.s16        {q13}, [r0]!
+    vld1.s16        {q14}, [r0]!
+    vld1.s16        {q15}, [r0]!
+
+    ; transpose the input data
+    TRANSPOSE8X8
+
+    ; generate  cospi_28_64 = 3196
+    mov             r3, #0x0c00
+    add             r3, #0x7c
+
+    ; generate cospi_4_64  = 16069
+    mov             r4, #0x3e00
+    add             r4, #0xc5
+
+    ; generate cospi_12_64 = 13623
+    mov             r5, #0x3500
+    add             r5, #0x37
+
+    ; generate cospi_20_64 = 9102
+    mov             r6, #0x2300
+    add             r6, #0x8e
+
+    ; generate cospi_16_64 = 11585
+    mov             r7, #0x2d00
+    add             r7, #0x41
+
+    ; generate cospi_24_64 = 6270
+    mov             r8, #0x1800
+    add             r8, #0x7e
+
+    ; generate cospi_8_64 = 15137
+    mov             r9, #0x3b00
+    add             r9, #0x21
+
+    ; First transform rows
+    IDCT8x8_1D
+
+    ; Transpose the matrix
+    TRANSPOSE8X8
+
+    ; Then transform columns
+    IDCT8x8_1D
+
+    ; ROUND_POWER_OF_TWO(temp_out[j], 5)
+    vrshr.s16       q8, q8, #5
+    vrshr.s16       q9, q9, #5
+    vrshr.s16       q10, q10, #5
+    vrshr.s16       q11, q11, #5
+    vrshr.s16       q12, q12, #5
+    vrshr.s16       q13, q13, #5
+    vrshr.s16       q14, q14, #5
+    vrshr.s16       q15, q15, #5
+
+    ; save dest pointer
+    mov             r0, r1
+
+    ; load destination data
+    vld1.u8         {d0}, [r1], r2
+    vld1.u8         {d1}, [r1], r2
+    vld1.s16        {d2}, [r1], r2
+    vld1.s16        {d3}, [r1], r2
+    vld1.s16        {d4}, [r1], r2
+    vld1.s16        {d5}, [r1], r2
+    vld1.s16        {d6}, [r1], r2
+    vld1.s16        {d7}, [r1]
+
+    ; ROUND_POWER_OF_TWO(temp_out[j], 5) + dest[j * dest_stride + i]
+    vaddw.u8        q8, q8, d0
+    vaddw.u8        q9, q9, d1
+    vaddw.u8        q10, q10, d2
+    vaddw.u8        q11, q11, d3
+    vaddw.u8        q12, q12, d4
+    vaddw.u8        q13, q13, d5
+    vaddw.u8        q14, q14, d6
+    vaddw.u8        q15, q15, d7
+
+    ; clip_pixel
+    vqmovun.s16     d0, q8
+    vqmovun.s16     d1, q9
+    vqmovun.s16     d2, q10
+    vqmovun.s16     d3, q11
+    vqmovun.s16     d4, q12
+    vqmovun.s16     d5, q13
+    vqmovun.s16     d6, q14
+    vqmovun.s16     d7, q15
+
+    ; store the data
+    vst1.64         {d0}, [r0], r2
+    vst1.64         {d1}, [r0], r2
+    vst1.64         {d2}, [r0], r2
+    vst1.64         {d3}, [r0], r2
+    vst1.64         {d4}, [r0], r2
+    vst1.64         {d5}, [r0], r2
+    vst1.64         {d6}, [r0], r2
+    vst1.64         {d7}, [r0], r2
+
+    pop             {r4-r9}
+    bx              lr
+    ENDP  ; |vp9_short_idct8x8_add_neon|
+
+    END
diff --git a/vp9/common/vp9_alloccommon.c b/vp9/common/vp9_alloccommon.c
index 749efe2..0a4f921 100644
--- a/vp9/common/vp9_alloccommon.c
+++ b/vp9/common/vp9_alloccommon.c
@@ -174,7 +174,7 @@
 
   vp9_init_mbmode_probs(oci);
 
-  oci->txfm_mode = ONLY_4X4;
+  oci->tx_mode = ONLY_4X4;
   oci->comp_pred_mode = HYBRID_PREDICTION;
 
   // Initialize reference frame sign bias structure to defaults
diff --git a/vp9/common/vp9_blockd.h b/vp9/common/vp9_blockd.h
index 0795975..dc20f2a 100644
--- a/vp9/common/vp9_blockd.h
+++ b/vp9/common/vp9_blockd.h
@@ -31,9 +31,6 @@
 
 #define MBSKIP_CONTEXTS 3
 
-#define MAX_REF_LF_DELTAS       4
-#define MAX_MODE_LF_DELTAS      2
-
 /* Segment Feature Masks */
 #define MAX_MV_REF_CANDIDATES 2
 
@@ -99,6 +96,10 @@
 
 #define VP9_INTER_MODES (1 + NEWMV - NEARESTMV)
 
+static INLINE int inter_mode_offset(MB_PREDICTION_MODE mode) {
+  return (mode - NEARESTMV);
+}
+
 /* For keyframes, intra block modes are predicted by the (already decoded)
    modes for the Y blocks to the left and above us; for interframes, there
    is a single probability table. */
@@ -169,7 +170,7 @@
 };
 
 #define VP9_REF_SCALE_SHIFT 14
-#define VP9_REF_NO_SCALE 16384
+#define VP9_REF_NO_SCALE (1 << VP9_REF_SCALE_SHIFT)
 
 struct scale_factors {
   int x_scale_fp;   // horizontal fixed point scale factor
@@ -215,43 +216,47 @@
 
 #define BLOCK_OFFSET(x, i, n) ((x) + (i) * (n))
 
+#define MAX_REF_LF_DELTAS       4
+#define MAX_MODE_LF_DELTAS      2
+
+struct loopfilter {
+  int filter_level;
+
+  int sharpness_level;
+  int last_sharpness_level;
+
+  uint8_t mode_ref_delta_enabled;
+  uint8_t mode_ref_delta_update;
+
+  // 0 = Intra, Last, GF, ARF
+  signed char ref_deltas[MAX_REF_LF_DELTAS];
+  signed char last_ref_deltas[MAX_REF_LF_DELTAS];
+
+  // 0 = ZERO_MV, MV
+  signed char mode_deltas[MAX_MODE_LF_DELTAS];
+  signed char last_mode_deltas[MAX_MODE_LF_DELTAS];
+};
+
 typedef struct macroblockd {
   struct macroblockd_plane plane[MAX_MB_PLANE];
 
   struct scale_factors scale_factor[2];
-  struct scale_factors scale_factor_uv[2];
 
   MODE_INFO *prev_mode_info_context;
   MODE_INFO *mode_info_context;
   int mode_info_stride;
 
-  FRAME_TYPE frame_type;
-
   int up_available;
   int left_available;
   int right_available;
 
   struct segmentation seg;
+  struct loopfilter lf;
 
   // partition contexts
   PARTITION_CONTEXT *above_seg_context;
   PARTITION_CONTEXT *left_seg_context;
 
-  /* mode_based Loop filter adjustment */
-  unsigned char mode_ref_lf_delta_enabled;
-  unsigned char mode_ref_lf_delta_update;
-
-  /* Delta values have the range +/- MAX_LOOP_FILTER */
-  /* 0 = Intra, Last, GF, ARF */
-  signed char last_ref_lf_deltas[MAX_REF_LF_DELTAS];
-  /* 0 = Intra, Last, GF, ARF */
-  signed char ref_lf_deltas[MAX_REF_LF_DELTAS];
-
-  /* 0 = ZERO_MV, MV */
-  signed char last_mode_lf_deltas[MAX_MODE_LF_DELTAS];
-  /* 0 = ZERO_MV, MV */
-  signed char mode_lf_deltas[MAX_MODE_LF_DELTAS];
-
   /* Distance of MB away from frame edges */
   int mb_to_left_edge;
   int mb_to_right_edge;
@@ -270,15 +275,16 @@
 
   int corrupted;
 
-  int sb_index;   // index of 32x32 block inside the 64x64 block
-  int mb_index;   // index of 16x16 block inside the 32x32 block
-  int b_index;    // index of 8x8 block inside the 16x16 block
-  int ab_index;   // index of 4x4 block inside the 8x8 block
+  unsigned char sb_index;   // index of 32x32 block inside the 64x64 block
+  unsigned char mb_index;   // index of 16x16 block inside the 32x32 block
+  unsigned char b_index;    // index of 8x8 block inside the 16x16 block
+  unsigned char ab_index;   // index of 4x4 block inside the 8x8 block
+
   int q_index;
 
 } MACROBLOCKD;
 
-static INLINE int *get_sb_index(MACROBLOCKD *xd, BLOCK_SIZE_TYPE subsize) {
+static INLINE unsigned char *get_sb_index(MACROBLOCKD *xd, BLOCK_SIZE_TYPE subsize) {
   switch (subsize) {
     case BLOCK_SIZE_SB64X64:
     case BLOCK_SIZE_SB64X32:
diff --git a/vp9/common/vp9_entropy.c b/vp9/common/vp9_entropy.c
index 5e8af6c..0692918 100644
--- a/vp9/common/vp9_entropy.c
+++ b/vp9/common/vp9_entropy.c
@@ -625,8 +625,10 @@
 
 static void adapt_coef_probs(VP9_COMMON *cm, TX_SIZE txfm_size,
                              int count_sat, int update_factor) {
+  FRAME_CONTEXT *pre_fc = &cm->frame_contexts[cm->frame_context_idx];
+
   vp9_coeff_probs_model *dst_coef_probs = cm->fc.coef_probs[txfm_size];
-  vp9_coeff_probs_model *pre_coef_probs = cm->fc.pre_coef_probs[txfm_size];
+  vp9_coeff_probs_model *pre_coef_probs = pre_fc->coef_probs[txfm_size];
   vp9_coeff_count_model *coef_counts = cm->fc.coef_counts[txfm_size];
   unsigned int (*eob_branch_count)[REF_TYPES][COEF_BANDS][PREV_COEF_CONTEXTS] =
       cm->fc.eob_branch_counts[txfm_size];
diff --git a/vp9/common/vp9_entropymode.c b/vp9/common/vp9_entropymode.c
index 80e4e49..4cfde35 100644
--- a/vp9/common/vp9_entropymode.c
+++ b/vp9/common/vp9_entropymode.c
@@ -14,8 +14,8 @@
 #include "vp9/common/vp9_onyxc_int.h"
 #include "vp9/common/vp9_seg_common.h"
 
-static const vp9_prob default_kf_uv_probs[VP9_INTRA_MODES]
-                                         [VP9_INTRA_MODES - 1] = {
+const vp9_prob vp9_kf_uv_mode_prob[VP9_INTRA_MODES]
+                                  [VP9_INTRA_MODES - 1] = {
   { 144,  11,  54, 157, 195, 130,  46,  58, 108 } /* y = dc */,
   { 118,  15, 123, 148, 131, 101,  44,  93, 131 } /* y = v */,
   { 113,  12,  23, 188, 226, 142,  26,  32, 125 } /* y = h */,
@@ -98,9 +98,9 @@
   }
 };
 
-static const vp9_prob default_kf_bmode_probs[VP9_INTRA_MODES]
-                                            [VP9_INTRA_MODES]
-                                            [VP9_INTRA_MODES - 1] = {
+const vp9_prob vp9_kf_y_mode_prob[VP9_INTRA_MODES]
+                                 [VP9_INTRA_MODES]
+                                 [VP9_INTRA_MODES - 1] = {
   { /* above = dc */
     { 137,  30,  42, 148, 151, 207,  70,  52,  91 } /* left = dc */,
     {  92,  45, 102, 136, 116, 180,  74,  90, 100 } /* left = v */,
@@ -238,7 +238,7 @@
   -D153_PRED, -D27_PRED             /* 8 = D153_NODE */
 };
 
-const vp9_tree_index vp9_sb_mv_ref_tree[6] = {
+const vp9_tree_index vp9_inter_mode_tree[6] = {
   -ZEROMV, 2,
   -NEARESTMV, 4,
   -NEARMV, -NEWMV
@@ -251,8 +251,7 @@
 };
 
 struct vp9_token vp9_intra_mode_encodings[VP9_INTRA_MODES];
-
-struct vp9_token vp9_sb_mv_ref_encoding_array[VP9_INTER_MODES];
+struct vp9_token vp9_inter_mode_encodings[VP9_INTER_MODES];
 
 struct vp9_token vp9_partition_encodings[PARTITION_TYPES];
 
@@ -328,7 +327,6 @@
 
 void vp9_init_mbmode_probs(VP9_COMMON *cm) {
   vp9_copy(cm->fc.uv_mode_prob, default_if_uv_probs);
-  vp9_copy(cm->kf_uv_mode_prob, default_kf_uv_probs);
   vp9_copy(cm->fc.y_mode_prob, default_if_y_probs);
   vp9_copy(cm->fc.switchable_interp_prob, default_switchable_interp_prob);
   vp9_copy(cm->fc.partition_prob, default_partition_probs);
@@ -357,8 +355,8 @@
   vp9_tokens_from_tree(vp9_switchable_interp_encodings,
                        vp9_switchable_interp_tree);
   vp9_tokens_from_tree(vp9_partition_encodings, vp9_partition_tree);
-  vp9_tokens_from_tree_offset(vp9_sb_mv_ref_encoding_array,
-                              vp9_sb_mv_ref_tree, NEARESTMV);
+  vp9_tokens_from_tree_offset(vp9_inter_mode_encodings,
+                              vp9_inter_mode_tree, NEARESTMV);
 }
 
 void vp9_init_mode_contexts(VP9_COMMON *pc) {
@@ -393,6 +391,8 @@
 #define MVREF_MAX_UPDATE_FACTOR 128
 void vp9_adapt_mode_context(VP9_COMMON *pc) {
   int i, j;
+  FRAME_CONTEXT *pre_fc = &pc->frame_contexts[pc->frame_context_idx];
+
   unsigned int (*inter_mode_counts)[VP9_INTER_MODES - 1][2] =
       pc->fc.inter_mode_counts;
   vp9_prob (*mode_context)[VP9_INTER_MODES - 1] = pc->fc.inter_mode_probs;
@@ -404,7 +404,7 @@
       count = count > MVREF_COUNT_SAT ? MVREF_COUNT_SAT : count;
       factor = (MVREF_MAX_UPDATE_FACTOR * count / MVREF_COUNT_SAT);
       mode_context[j][i] = weighted_prob(
-          pc->fc.pre_inter_mode_probs[j][i],
+          pre_fc->inter_mode_probs[j][i],
           get_binary_prob(inter_mode_counts[j][i][0],
                           inter_mode_counts[j][i][1]),
           factor);
@@ -451,6 +451,8 @@
 void vp9_adapt_mode_probs(VP9_COMMON *cm) {
   int i, j;
   FRAME_CONTEXT *fc = &cm->fc;
+  FRAME_CONTEXT *pre_fc = &cm->frame_contexts[cm->frame_context_idx];
+
 #ifdef MODE_COUNT_TESTING
   int t;
 
@@ -486,43 +488,44 @@
 #endif
 
   for (i = 0; i < INTRA_INTER_CONTEXTS; i++)
-    fc->intra_inter_prob[i] = update_mode_ct2(fc->pre_intra_inter_prob[i],
+    fc->intra_inter_prob[i] = update_mode_ct2(pre_fc->intra_inter_prob[i],
                                               fc->intra_inter_count[i]);
   for (i = 0; i < COMP_INTER_CONTEXTS; i++)
-    fc->comp_inter_prob[i] = update_mode_ct2(fc->pre_comp_inter_prob[i],
+    fc->comp_inter_prob[i] = update_mode_ct2(pre_fc->comp_inter_prob[i],
                                              fc->comp_inter_count[i]);
   for (i = 0; i < REF_CONTEXTS; i++)
-    fc->comp_ref_prob[i] = update_mode_ct2(fc->pre_comp_ref_prob[i],
+    fc->comp_ref_prob[i] = update_mode_ct2(pre_fc->comp_ref_prob[i],
                                            fc->comp_ref_count[i]);
   for (i = 0; i < REF_CONTEXTS; i++)
     for (j = 0; j < 2; j++)
-      fc->single_ref_prob[i][j] = update_mode_ct2(fc->pre_single_ref_prob[i][j],
+      fc->single_ref_prob[i][j] = update_mode_ct2(pre_fc->single_ref_prob[i][j],
                                                   fc->single_ref_count[i][j]);
 
   for (i = 0; i < BLOCK_SIZE_GROUPS; i++)
     update_mode_probs(VP9_INTRA_MODES, vp9_intra_mode_tree,
-                      fc->y_mode_counts[i], fc->pre_y_mode_prob[i],
+                      fc->y_mode_counts[i], pre_fc->y_mode_prob[i],
                       fc->y_mode_prob[i], 0);
 
   for (i = 0; i < VP9_INTRA_MODES; ++i)
     update_mode_probs(VP9_INTRA_MODES, vp9_intra_mode_tree,
-                      fc->uv_mode_counts[i], fc->pre_uv_mode_prob[i],
+                      fc->uv_mode_counts[i], pre_fc->uv_mode_prob[i],
                       fc->uv_mode_prob[i], 0);
 
   for (i = 0; i < NUM_PARTITION_CONTEXTS; i++)
     update_mode_probs(PARTITION_TYPES, vp9_partition_tree,
-                      fc->partition_counts[i], fc->pre_partition_prob[i],
+                      fc->partition_counts[i],
+                      pre_fc->partition_prob[INTER_FRAME][i],
                       fc->partition_prob[INTER_FRAME][i], 0);
 
   if (cm->mcomp_filter_type == SWITCHABLE) {
     for (i = 0; i <= VP9_SWITCHABLE_FILTERS; i++)
       update_mode_probs(VP9_SWITCHABLE_FILTERS, vp9_switchable_interp_tree,
                         fc->switchable_interp_count[i],
-                        fc->pre_switchable_interp_prob[i],
+                        pre_fc->switchable_interp_prob[i],
                         fc->switchable_interp_prob[i], 0);
   }
 
-  if (cm->txfm_mode == TX_MODE_SELECT) {
+  if (cm->tx_mode == TX_MODE_SELECT) {
     int j;
     unsigned int branch_ct_8x8p[TX_SIZE_MAX_SB - 3][2];
     unsigned int branch_ct_16x16p[TX_SIZE_MAX_SB - 2][2];
@@ -531,39 +534,39 @@
     for (i = 0; i < TX_SIZE_CONTEXTS; ++i) {
       tx_counts_to_branch_counts_8x8(fc->tx_counts.p8x8[i], branch_ct_8x8p);
       for (j = 0; j < TX_SIZE_MAX_SB - 3; ++j)
-        fc->tx_probs.p8x8[i][j] = update_tx_ct(fc->pre_tx_probs.p8x8[i][j],
+        fc->tx_probs.p8x8[i][j] = update_tx_ct(pre_fc->tx_probs.p8x8[i][j],
                                                branch_ct_8x8p[j]);
 
       tx_counts_to_branch_counts_16x16(fc->tx_counts.p16x16[i],
                                        branch_ct_16x16p);
       for (j = 0; j < TX_SIZE_MAX_SB - 2; ++j)
-        fc->tx_probs.p16x16[i][j] = update_tx_ct(fc->tx_probs.p16x16[i][j],
+        fc->tx_probs.p16x16[i][j] = update_tx_ct(pre_fc->tx_probs.p16x16[i][j],
                                                  branch_ct_16x16p[j]);
 
       tx_counts_to_branch_counts_32x32(fc->tx_counts.p32x32[i],
                                        branch_ct_32x32p);
       for (j = 0; j < TX_SIZE_MAX_SB - 1; ++j)
-        fc->tx_probs.p32x32[i][j] = update_tx_ct(fc->pre_tx_probs.p32x32[i][j],
+        fc->tx_probs.p32x32[i][j] = update_tx_ct(pre_fc->tx_probs.p32x32[i][j],
                                                  branch_ct_32x32p[j]);
     }
   }
 
   for (i = 0; i < MBSKIP_CONTEXTS; ++i)
-    fc->mbskip_probs[i] = update_mode_ct2(fc->pre_mbskip_probs[i],
+    fc->mbskip_probs[i] = update_mode_ct2(pre_fc->mbskip_probs[i],
                                           fc->mbskip_count[i]);
 }
 
 static void set_default_lf_deltas(MACROBLOCKD *xd) {
-  xd->mode_ref_lf_delta_enabled = 1;
-  xd->mode_ref_lf_delta_update = 1;
+  xd->lf.mode_ref_delta_enabled = 1;
+  xd->lf.mode_ref_delta_update = 1;
 
-  xd->ref_lf_deltas[INTRA_FRAME] = 1;
-  xd->ref_lf_deltas[LAST_FRAME] = 0;
-  xd->ref_lf_deltas[GOLDEN_FRAME] = -1;
-  xd->ref_lf_deltas[ALTREF_FRAME] = -1;
+  xd->lf.ref_deltas[INTRA_FRAME] = 1;
+  xd->lf.ref_deltas[LAST_FRAME] = 0;
+  xd->lf.ref_deltas[GOLDEN_FRAME] = -1;
+  xd->lf.ref_deltas[ALTREF_FRAME] = -1;
 
-  xd->mode_lf_deltas[0] = 0;
-  xd->mode_lf_deltas[1] = 0;
+  xd->lf.mode_deltas[0] = 0;
+  xd->lf.mode_deltas[1] = 0;
 }
 
 void vp9_setup_past_independence(VP9_COMMON *cm, MACROBLOCKD *xd) {
@@ -576,19 +579,17 @@
     vpx_memset(cm->last_frame_seg_map, 0, (cm->mi_rows * cm->mi_cols));
 
   // Reset the mode ref deltas for loop filter
-  vp9_zero(xd->last_ref_lf_deltas);
-  vp9_zero(xd->last_mode_lf_deltas);
+  vp9_zero(xd->lf.last_ref_deltas);
+  vp9_zero(xd->lf.last_mode_deltas);
   set_default_lf_deltas(xd);
 
   vp9_default_coef_probs(cm);
   vp9_init_mbmode_probs(cm);
 
-  vp9_copy(cm->kf_y_mode_prob, default_kf_bmode_probs);
-
   vp9_init_mv_probs(cm);
 
   // To force update of the sharpness
-  cm->last_sharpness_level = -1;
+  xd->lf.last_sharpness_level = -1;
 
   vp9_init_mode_contexts(cm);
 
diff --git a/vp9/common/vp9_entropymode.h b/vp9/common/vp9_entropymode.h
index cfdc274..613657b 100644
--- a/vp9/common/vp9_entropymode.h
+++ b/vp9/common/vp9_entropymode.h
@@ -16,15 +16,17 @@
 
 #define SUBMVREF_COUNT 5
 #define TX_SIZE_CONTEXTS 2
-
 #define VP9_MODE_UPDATE_PROB  252
+#define VP9_SWITCHABLE_FILTERS 3   // number of switchable filters
 
 // #define MODE_STATS
 
+struct VP9Common;
+
 struct tx_probs {
   vp9_prob p32x32[TX_SIZE_CONTEXTS][TX_SIZE_MAX_SB - 1];
   vp9_prob p16x16[TX_SIZE_CONTEXTS][TX_SIZE_MAX_SB - 2];
-  vp9_prob p8x8[TX_SIZE_CONTEXTS][TX_SIZE_MAX_SB - 2];
+  vp9_prob p8x8[TX_SIZE_CONTEXTS][TX_SIZE_MAX_SB - 3];
 };
 
 struct tx_counts {
@@ -33,58 +35,52 @@
   unsigned int p8x8[TX_SIZE_CONTEXTS][TX_SIZE_MAX_SB - 2];
 };
 
-int vp9_mv_cont(const int_mv *l, const int_mv *a);
+extern const vp9_prob vp9_kf_uv_mode_prob[VP9_INTRA_MODES][VP9_INTRA_MODES - 1];
+extern const vp9_prob vp9_kf_y_mode_prob[VP9_INTRA_MODES][VP9_INTRA_MODES]
+                                        [VP9_INTRA_MODES - 1];
 
 extern const vp9_tree_index vp9_intra_mode_tree[];
-extern const vp9_tree_index  vp9_sb_mv_ref_tree[];
+extern const vp9_tree_index vp9_inter_mode_tree[];
 
 extern struct vp9_token vp9_intra_mode_encodings[VP9_INTRA_MODES];
-
-/* Inter mode values do not start at zero */
-
-extern struct vp9_token vp9_sb_mv_ref_encoding_array[VP9_INTER_MODES];
+extern struct vp9_token vp9_inter_mode_encodings[VP9_INTER_MODES];
 
 // probability models for partition information
-extern const vp9_tree_index  vp9_partition_tree[];
+extern const vp9_tree_index vp9_partition_tree[];
 extern struct vp9_token vp9_partition_encodings[PARTITION_TYPES];
 
-void vp9_entropy_mode_init(void);
+extern const INTERPOLATIONFILTERTYPE vp9_switchable_interp
+                 [VP9_SWITCHABLE_FILTERS];
 
-struct VP9Common;
+extern const int vp9_switchable_interp_map[SWITCHABLE + 1];
+extern const int vp9_is_interpolating_filter[SWITCHABLE + 1];
 
-/* sets up common features to forget past dependence */
+extern const vp9_tree_index vp9_switchable_interp_tree
+                 [2 * (VP9_SWITCHABLE_FILTERS - 1)];
+
+extern struct vp9_token vp9_switchable_interp_encodings[VP9_SWITCHABLE_FILTERS];
+
+void vp9_entropy_mode_init();
+
+int vp9_mv_cont(const int_mv *l, const int_mv *a);
+
 void vp9_setup_past_independence(struct VP9Common *cm, MACROBLOCKD *xd);
 
 void vp9_init_mbmode_probs(struct VP9Common *x);
 
-extern void vp9_init_mode_contexts(struct VP9Common *pc);
+void vp9_init_mode_contexts(struct VP9Common *pc);
 
-extern void vp9_adapt_mode_context(struct VP9Common *pc);
-
-extern void vp9_accum_mv_refs(struct VP9Common *pc,
-                              MB_PREDICTION_MODE m,
-                              const int context);
+void vp9_adapt_mode_context(struct VP9Common *pc);
 
 void vp9_adapt_mode_probs(struct VP9Common *);
 
-#define VP9_SWITCHABLE_FILTERS 3 /* number of switchable filters */
+void vp9_accum_mv_refs(struct VP9Common *pc, MB_PREDICTION_MODE m, int context);
 
-extern const  INTERPOLATIONFILTERTYPE vp9_switchable_interp
-                  [VP9_SWITCHABLE_FILTERS];
+void tx_counts_to_branch_counts_32x32(unsigned int *tx_count_32x32p,
+                                      unsigned int (*ct_32x32p)[2]);
+void tx_counts_to_branch_counts_16x16(unsigned int *tx_count_16x16p,
+                                      unsigned int (*ct_16x16p)[2]);
+void tx_counts_to_branch_counts_8x8(unsigned int *tx_count_8x8p,
+                                    unsigned int (*ct_8x8p)[2]);
 
-extern const  int vp9_switchable_interp_map[SWITCHABLE + 1];
-
-extern const  int vp9_is_interpolating_filter[SWITCHABLE + 1];
-
-extern const  vp9_tree_index vp9_switchable_interp_tree
-                  [2 * (VP9_SWITCHABLE_FILTERS - 1)];
-
-extern struct vp9_token vp9_switchable_interp_encodings[VP9_SWITCHABLE_FILTERS];
-
-extern void tx_counts_to_branch_counts_32x32(unsigned int *tx_count_32x32p,
-                                             unsigned int (*ct_32x32p)[2]);
-extern void tx_counts_to_branch_counts_16x16(unsigned int *tx_count_16x16p,
-                                             unsigned int (*ct_16x16p)[2]);
-extern void tx_counts_to_branch_counts_8x8(unsigned int *tx_count_8x8p,
-                                           unsigned int (*ct_8x8p)[2]);
 #endif  // VP9_COMMON_VP9_ENTROPYMODE_H_
diff --git a/vp9/common/vp9_entropymv.c b/vp9/common/vp9_entropymv.c
index c1b87e2..a03862b 100644
--- a/vp9/common/vp9_entropymv.c
+++ b/vp9/common/vp9_entropymv.c
@@ -164,11 +164,9 @@
   }
 }
 
-void vp9_inc_mv(const MV *mv, const MV *ref, nmv_context_counts *mvctx,
-                       int usehp) {
+void vp9_inc_mv(const MV *mv,  nmv_context_counts *mvctx) {
   const MV_JOINT_TYPE j = vp9_get_mv_joint(mv);
   mvctx->joints[j]++;
-  usehp = usehp && vp9_use_mv_hp(ref);
   if (mv_joint_vertical(j))
     inc_mv_component_count(mv->row, &mvctx->comps[0], 1);
 
@@ -224,8 +222,10 @@
 void vp9_adapt_mv_probs(VP9_COMMON *cm, int usehp) {
   int i, j;
 
+  FRAME_CONTEXT *pre_fc = &cm->frame_contexts[cm->frame_context_idx];
+
   nmv_context *ctx = &cm->fc.nmvc;
-  nmv_context *pre_ctx = &cm->fc.pre_nmvc;
+  nmv_context *pre_ctx = &pre_fc->nmvc;
   nmv_context_counts *cts = &cm->fc.NMVcount;
 
   vp9_counts_process(cts, usehp);
diff --git a/vp9/common/vp9_entropymv.h b/vp9/common/vp9_entropymv.h
index 895df30..d7d6576 100644
--- a/vp9/common/vp9_entropymv.h
+++ b/vp9/common/vp9_entropymv.h
@@ -125,8 +125,7 @@
   nmv_component_counts comps[2];
 } nmv_context_counts;
 
-void vp9_inc_mv(const MV *mv, const MV *ref, nmv_context_counts *mvctx,
-                int usehp);
+void vp9_inc_mv(const MV *mv, nmv_context_counts *mvctx);
 
 void vp9_counts_process(nmv_context_counts *NMVcount, int usehp);
 
diff --git a/vp9/common/vp9_enums.h b/vp9/common/vp9_enums.h
index bc739ff..855c5e3 100644
--- a/vp9/common/vp9_enums.h
+++ b/vp9/common/vp9_enums.h
@@ -58,6 +58,15 @@
 } TX_SIZE;
 
 typedef enum {
+  ONLY_4X4            = 0,
+  ALLOW_8X8           = 1,
+  ALLOW_16X16         = 2,
+  ALLOW_32X32         = 3,
+  TX_MODE_SELECT      = 4,
+  NB_TXFM_MODES       = 5,
+} TX_MODE;
+
+typedef enum {
   DCT_DCT   = 0,                      // DCT  in both horizontal and vertical
   ADST_DCT  = 1,                      // ADST in vertical, DCT in horizontal
   DCT_ADST  = 2,                      // DCT  in vertical, ADST in horizontal
diff --git a/vp9/common/vp9_findnearmv.h b/vp9/common/vp9_findnearmv.h
index d68572b..b0fa505 100644
--- a/vp9/common/vp9_findnearmv.h
+++ b/vp9/common/vp9_findnearmv.h
@@ -28,18 +28,6 @@
                            int_mv *nearest,
                            int_mv *near);
 
-static void mv_bias(int refmb_ref_frame_sign_bias, int refframe,
-                    int_mv *mvp, const int *ref_frame_sign_bias) {
-  MV xmv = mvp->as_mv;
-
-  if (refmb_ref_frame_sign_bias != ref_frame_sign_bias[refframe]) {
-    xmv.row *= -1;
-    xmv.col *= -1;
-  }
-
-  mvp->as_mv = xmv;
-}
-
 // TODO(jingning): this mv clamping function should be block size dependent.
 static void clamp_mv(int_mv *mv,
                      int mb_to_left_edge,
@@ -61,15 +49,6 @@
   return tmp_mv.as_int != mv->as_int;
 }
 
-static int check_mv_bounds(int_mv *mv,
-                           int mb_to_left_edge, int mb_to_right_edge,
-                           int mb_to_top_edge, int mb_to_bottom_edge) {
-  return mv->as_mv.col < mb_to_left_edge ||
-         mv->as_mv.col > mb_to_right_edge ||
-         mv->as_mv.row < mb_to_top_edge ||
-         mv->as_mv.row > mb_to_bottom_edge;
-}
-
 void vp9_append_sub8x8_mvs_for_idx(VP9_COMMON *pc,
                                    MACROBLOCKD *xd,
                                    int_mv *dst_nearest,
diff --git a/vp9/common/vp9_idct.c b/vp9/common/vp9_idct.c
index abde63d..3103be2 100644
--- a/vp9/common/vp9_idct.c
+++ b/vp9/common/vp9_idct.c
@@ -124,9 +124,7 @@
 
   // Rows
   for (i = 0; i < 4; ++i) {
-    for (j = 0; j < 4; ++j)
-      temp_in[j] = input[j];
-    vp9_idct4_1d(temp_in, outptr);
+    vp9_idct4_1d(input, outptr);
     input += 4;
     outptr += 4;
   }
diff --git a/vp9/common/vp9_loopfilter.c b/vp9/common/vp9_loopfilter.c
index eea2eea..f0c0e39 100644
--- a/vp9/common/vp9_loopfilter.c
+++ b/vp9/common/vp9_loopfilter.c
@@ -55,13 +55,13 @@
   }
 }
 
-void vp9_loop_filter_init(VP9_COMMON *cm) {
+void vp9_loop_filter_init(VP9_COMMON *cm, struct loopfilter *lf) {
   loop_filter_info_n *lfi = &cm->lf_info;
   int i;
 
   // init limits for given sharpness
-  update_sharpness(lfi, cm->sharpness_level);
-  cm->last_sharpness_level = cm->sharpness_level;
+  update_sharpness(lfi, lf->sharpness_level);
+  lf->last_sharpness_level = lf->sharpness_level;
 
   // init LUT for lvl  and hev thr picking
   lf_init_lut(lfi);
@@ -79,11 +79,12 @@
   // 2 when filter_lvl is between 32 and 63
   const int n_shift = default_filt_lvl >> 5;
   loop_filter_info_n *const lfi = &cm->lf_info;
+  struct loopfilter *lf = &xd->lf;
 
   // update limits if sharpness has changed
-  if (cm->last_sharpness_level != cm->sharpness_level) {
-    update_sharpness(lfi, cm->sharpness_level);
-    cm->last_sharpness_level = cm->sharpness_level;
+  if (lf->last_sharpness_level != lf->sharpness_level) {
+    update_sharpness(lfi, lf->sharpness_level);
+    lf->last_sharpness_level = lf->sharpness_level;
   }
 
   for (seg = 0; seg < MAX_MB_SEGMENTS; seg++) {
@@ -97,20 +98,20 @@
                   : clamp(default_filt_lvl + data, 0, MAX_LOOP_FILTER);
     }
 
-    if (!xd->mode_ref_lf_delta_enabled) {
+    if (!lf->mode_ref_delta_enabled) {
       // we could get rid of this if we assume that deltas are set to
       // zero when not in use; encoder always uses deltas
       vpx_memset(lfi->lvl[seg][0], lvl_seg, 4 * 4);
       continue;
     }
 
-    intra_lvl = lvl_seg + (xd->ref_lf_deltas[INTRA_FRAME] << n_shift);
+    intra_lvl = lvl_seg + (lf->ref_deltas[INTRA_FRAME] << n_shift);
     lfi->lvl[seg][INTRA_FRAME][0] = clamp(intra_lvl, 0, MAX_LOOP_FILTER);
 
     for (ref = LAST_FRAME; ref < MAX_REF_FRAMES; ++ref)
       for (mode = 0; mode < MAX_MODE_LF_DELTAS; ++mode) {
-        const int inter_lvl = lvl_seg + (xd->ref_lf_deltas[ref] << n_shift)
-                                      + (xd->mode_lf_deltas[mode] << n_shift);
+        const int inter_lvl = lvl_seg + (lf->ref_deltas[ref] << n_shift)
+                                      + (lf->mode_deltas[mode] << n_shift);
         lfi->lvl[seg][ref][mode] = clamp(inter_lvl, 0, MAX_LOOP_FILTER);
       }
   }
diff --git a/vp9/common/vp9_loopfilter.h b/vp9/common/vp9_loopfilter.h
index 9620a52..cbe52c2 100644
--- a/vp9/common/vp9_loopfilter.h
+++ b/vp9/common/vp9_loopfilter.h
@@ -46,7 +46,7 @@
 struct VP9Common;
 struct macroblockd;
 
-void vp9_loop_filter_init(struct VP9Common *cm);
+void vp9_loop_filter_init(struct VP9Common *cm, struct loopfilter *lf);
 
 void vp9_loop_filter_frame(struct VP9Common *cm,
                            struct macroblockd *mbd,
diff --git a/vp9/common/vp9_mv.h b/vp9/common/vp9_mv.h
index b4dc355..a095258 100644
--- a/vp9/common/vp9_mv.h
+++ b/vp9/common/vp9_mv.h
@@ -28,9 +28,4 @@
   int32_t col;
 } MV32;
 
-typedef union int_mv32 {
-  uint64_t as_int;
-  MV32 as_mv;
-} int_mv32; /* facilitates faster equality tests and copies */
-
 #endif  // VP9_COMMON_VP9_MV_H_
diff --git a/vp9/common/vp9_onyx.h b/vp9/common/vp9_onyx.h
index d266c15..fe8122b 100644
--- a/vp9/common/vp9_onyx.h
+++ b/vp9/common/vp9_onyx.h
@@ -64,34 +64,6 @@
     FRAMEFLAGS_ALTREF = 4,
   } FRAMETYPE_FLAGS;
 
-
-#include <assert.h>
-  static INLINE void Scale2Ratio(int mode, int *hr, int *hs) {
-    switch (mode) {
-      case    NORMAL:
-        *hr = 1;
-        *hs = 1;
-        break;
-      case    FOURFIVE:
-        *hr = 4;
-        *hs = 5;
-        break;
-      case    THREEFIVE:
-        *hr = 3;
-        *hs = 5;
-        break;
-      case    ONETWO:
-        *hr = 1;
-        *hs = 2;
-        break;
-      default:
-        *hr = 1;
-        *hs = 1;
-        assert(0);
-        break;
-    }
-  }
-
   typedef struct {
     int version;  // 4 versions of bitstream defined:
                   //   0 - best quality/slowest decode,
diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h
index 8d5743b..fb33276 100644
--- a/vp9/common/vp9_onyxc_int.h
+++ b/vp9/common/vp9_onyxc_int.h
@@ -43,16 +43,13 @@
   vp9_prob uv_mode_prob[VP9_INTRA_MODES][VP9_INTRA_MODES - 1];
   vp9_prob partition_prob[NUM_FRAME_TYPES][NUM_PARTITION_CONTEXTS]
                          [PARTITION_TYPES - 1];
-  vp9_prob pre_y_mode_prob[BLOCK_SIZE_GROUPS][VP9_INTRA_MODES - 1];
-  vp9_prob pre_uv_mode_prob[VP9_INTRA_MODES][VP9_INTRA_MODES - 1];
-  vp9_prob pre_partition_prob[NUM_PARTITION_CONTEXTS][PARTITION_TYPES - 1];
+
   unsigned int y_mode_counts[BLOCK_SIZE_GROUPS][VP9_INTRA_MODES];
   unsigned int uv_mode_counts[VP9_INTRA_MODES][VP9_INTRA_MODES];
   unsigned int partition_counts[NUM_PARTITION_CONTEXTS][PARTITION_TYPES];
 
   // coeff
   vp9_coeff_probs_model coef_probs[TX_SIZE_MAX_SB][BLOCK_TYPES];
-  vp9_coeff_probs_model pre_coef_probs[TX_SIZE_MAX_SB][BLOCK_TYPES];
   vp9_coeff_count_model coef_counts[TX_SIZE_MAX_SB][BLOCK_TYPES];
   unsigned int eob_branch_counts[TX_SIZE_MAX_SB][BLOCK_TYPES][REF_TYPES]
                                 [COEF_BANDS][PREV_COEF_CONTEXTS];
@@ -60,13 +57,10 @@
   // switchable_interp
   vp9_prob switchable_interp_prob[VP9_SWITCHABLE_FILTERS + 1]
                                  [VP9_SWITCHABLE_FILTERS - 1];
-  vp9_prob pre_switchable_interp_prob[VP9_SWITCHABLE_FILTERS + 1]
-                                     [VP9_SWITCHABLE_FILTERS - 1];
   unsigned int switchable_interp_count[VP9_SWITCHABLE_FILTERS + 1]
                                       [VP9_SWITCHABLE_FILTERS];
   // inter_mode
   vp9_prob inter_mode_probs[INTER_MODE_CONTEXTS][VP9_INTER_MODES - 1];
-  vp9_prob pre_inter_mode_probs[INTER_MODE_CONTEXTS][VP9_INTER_MODES - 1];
   unsigned int inter_mode_counts[INTER_MODE_CONTEXTS][VP9_INTER_MODES - 1][2];
 
   // intra_inter, comp_inter, single_ref, comp_ref
@@ -74,10 +68,7 @@
   vp9_prob comp_inter_prob[COMP_INTER_CONTEXTS];
   vp9_prob single_ref_prob[REF_CONTEXTS][2];
   vp9_prob comp_ref_prob[REF_CONTEXTS];
-  vp9_prob pre_intra_inter_prob[INTRA_INTER_CONTEXTS];
-  vp9_prob pre_comp_inter_prob[COMP_INTER_CONTEXTS];
-  vp9_prob pre_single_ref_prob[REF_CONTEXTS][2];
-  vp9_prob pre_comp_ref_prob[REF_CONTEXTS];
+
   unsigned int intra_inter_count[INTRA_INTER_CONTEXTS][2];
   unsigned int comp_inter_count[COMP_INTER_CONTEXTS][2];
   unsigned int single_ref_count[REF_CONTEXTS][2][2];
@@ -85,17 +76,14 @@
 
   // tx_probs
   struct tx_probs tx_probs;
-  struct tx_probs pre_tx_probs;
   struct tx_counts tx_counts;
 
   // mbskip
   vp9_prob mbskip_probs[MBSKIP_CONTEXTS];
-  vp9_prob pre_mbskip_probs[MBSKIP_CONTEXTS];
   unsigned int mbskip_count[MBSKIP_CONTEXTS][2];
 
   // mv
   nmv_context nmvc;
-  nmv_context pre_nmvc;
   nmv_context_counts NMVcount;
 } FRAME_CONTEXT;
 
@@ -106,15 +94,6 @@
   NB_PREDICTION_TYPES    = 3,
 } COMPPREDMODE_TYPE;
 
-typedef enum {
-  ONLY_4X4            = 0,
-  ALLOW_8X8           = 1,
-  ALLOW_16X16         = 2,
-  ALLOW_32X32         = 3,
-  TX_MODE_SELECT      = 4,
-  NB_TXFM_MODES       = 5,
-} TXFM_MODE;
-
 typedef struct VP9Common {
   struct vpx_internal_error_info  error;
 
@@ -179,7 +158,7 @@
   int mode_info_stride;
 
   /* profile settings */
-  TXFM_MODE txfm_mode;
+  TX_MODE tx_mode;
 
   int base_qindex;
   int last_kf_gf_q;  /* Q used on the last GF or KF */
@@ -192,9 +171,6 @@
   int a_ac_delta_q;
 #endif
 
-  unsigned int frames_since_golden;
-  unsigned int frames_till_alt_ref_frame;
-
   /* We allocate a MODE_INFO struct for each macroblock, together with
      an extra row on top and column on the left to simplify prediction. */
 
@@ -211,10 +187,6 @@
 
   loop_filter_info_n lf_info;
 
-  int filter_level;
-  int last_sharpness_level;
-  int sharpness_level;
-
   int refresh_frame_context;    /* Two state 0 = NO, 1 = YES */
 
   int ref_frame_sign_bias[MAX_REF_FRAMES];    /* Two state 0, 1 */
@@ -227,13 +199,6 @@
   PARTITION_CONTEXT *above_seg_context;
   PARTITION_CONTEXT left_seg_context[8];
 
-  /* keyframe block modes are predicted by their above, left neighbors */
-
-  vp9_prob kf_y_mode_prob[VP9_INTRA_MODES]
-                         [VP9_INTRA_MODES]
-                         [VP9_INTRA_MODES - 1];
-  vp9_prob kf_uv_mode_prob[VP9_INTRA_MODES] [VP9_INTRA_MODES - 1];
-
   // Context probabilities for reference frame prediction
   int allow_comp_inter_inter;
   MV_REFERENCE_FRAME comp_fixed_ref;
diff --git a/vp9/common/vp9_postproc.c b/vp9/common/vp9_postproc.c
index 840d922..1157fbb 100644
--- a/vp9/common/vp9_postproc.c
+++ b/vp9/common/vp9_postproc.c
@@ -630,9 +630,11 @@
   }
 }
 
-int vp9_post_proc_frame(VP9_COMMON *oci, YV12_BUFFER_CONFIG *dest,
+int vp9_post_proc_frame(struct VP9Common *oci,
+                        struct loopfilter *lf,
+                        YV12_BUFFER_CONFIG *dest,
                         vp9_ppflags_t *ppflags) {
-  int q = oci->filter_level * 10 / 6;
+  int q = lf->filter_level * 10 / 6;
   int flags = ppflags->post_proc_flag;
   int deblock_level = ppflags->deblocking_level;
   int noise_level = ppflags->noise_level;
diff --git a/vp9/common/vp9_postproc.h b/vp9/common/vp9_postproc.h
index 2c0d333..a814e39 100644
--- a/vp9/common/vp9_postproc.h
+++ b/vp9/common/vp9_postproc.h
@@ -26,8 +26,8 @@
 #include "vp9/common/vp9_onyxc_int.h"
 #include "vp9/common/vp9_ppflags.h"
 
-int vp9_post_proc_frame(struct VP9Common *oci, YV12_BUFFER_CONFIG *dest,
-                        vp9_ppflags_t *flags);
+int vp9_post_proc_frame(struct VP9Common *oci, struct loopfilter *lf,
+                        YV12_BUFFER_CONFIG *dest, vp9_ppflags_t *flags);
 
 void vp9_denoise(const YV12_BUFFER_CONFIG *src, YV12_BUFFER_CONFIG *dst, int q);
 
diff --git a/vp9/common/vp9_pred_common.c b/vp9/common/vp9_pred_common.c
index 5c8e346..ea2b0f4 100644
--- a/vp9/common/vp9_pred_common.c
+++ b/vp9/common/vp9_pred_common.c
@@ -17,10 +17,9 @@
 #include "vp9/common/vp9_treecoder.h"
 
 // Returns a context number for the given MB prediction signal
-unsigned char vp9_get_pred_context_switchable_interp(const VP9_COMMON *cm,
-                                                     const MACROBLOCKD *xd) {
+unsigned char vp9_get_pred_context_switchable_interp(const MACROBLOCKD *xd) {
   const MODE_INFO *const mi = xd->mode_info_context;
-  const MB_MODE_INFO *const above_mbmi = &mi[-cm->mode_info_stride].mbmi;
+  const MB_MODE_INFO *const above_mbmi = &mi[-xd->mode_info_stride].mbmi;
   const MB_MODE_INFO *const left_mbmi = &mi[-1].mbmi;
   const int left_in_image = xd->left_available && left_mbmi->mb_in_image;
   const int above_in_image = xd->up_available && above_mbmi->mb_in_image;
@@ -55,11 +54,10 @@
     return VP9_SWITCHABLE_FILTERS;
 }
 // Returns a context number for the given MB prediction signal
-unsigned char vp9_get_pred_context_intra_inter(const VP9_COMMON *cm,
-                                               const MACROBLOCKD *xd) {
+unsigned char vp9_get_pred_context_intra_inter(const MACROBLOCKD *xd) {
   int pred_context;
   const MODE_INFO *const mi = xd->mode_info_context;
-  const MB_MODE_INFO *const above_mbmi = &mi[-cm->mode_info_stride].mbmi;
+  const MB_MODE_INFO *const above_mbmi = &mi[-xd->mode_info_stride].mbmi;
   const MB_MODE_INFO *const left_mbmi = &mi[-1].mbmi;
   const int left_in_image = xd->left_available && left_mbmi->mb_in_image;
   const int above_in_image = xd->up_available && above_mbmi->mb_in_image;
@@ -211,11 +209,10 @@
 
   return pred_context;
 }
-unsigned char vp9_get_pred_context_single_ref_p1(const VP9_COMMON *cm,
-                                                 const MACROBLOCKD *xd) {
+unsigned char vp9_get_pred_context_single_ref_p1(const MACROBLOCKD *xd) {
   int pred_context;
   const MODE_INFO *const mi = xd->mode_info_context;
-  const MB_MODE_INFO *const above_mbmi = &mi[-cm->mode_info_stride].mbmi;
+  const MB_MODE_INFO *const above_mbmi = &mi[-xd->mode_info_stride].mbmi;
   const MB_MODE_INFO *const left_mbmi = &mi[-1].mbmi;
   const int left_in_image = xd->left_available && left_mbmi->mb_in_image;
   const int above_in_image = xd->up_available && above_mbmi->mb_in_image;
@@ -277,11 +274,10 @@
   return pred_context;
 }
 
-unsigned char vp9_get_pred_context_single_ref_p2(const VP9_COMMON *cm,
-                                                 const MACROBLOCKD *xd) {
+unsigned char vp9_get_pred_context_single_ref_p2(const MACROBLOCKD *xd) {
   int pred_context;
   const MODE_INFO *const mi = xd->mode_info_context;
-  const MB_MODE_INFO *const above_mbmi = &mi[-cm->mode_info_stride].mbmi;
+  const MB_MODE_INFO *const above_mbmi = &mi[-xd->mode_info_stride].mbmi;
   const MB_MODE_INFO *const left_mbmi = &mi[-1].mbmi;
   const int left_in_image = xd->left_available && left_mbmi->mb_in_image;
   const int above_in_image = xd->up_available && above_mbmi->mb_in_image;
@@ -367,10 +363,9 @@
   return pred_context;
 }
 // Returns a context number for the given MB prediction signal
-unsigned char vp9_get_pred_context_tx_size(const VP9_COMMON *cm,
-                                           const MACROBLOCKD *xd) {
+unsigned char vp9_get_pred_context_tx_size(const MACROBLOCKD *xd) {
   const MODE_INFO *const mi = xd->mode_info_context;
-  const MODE_INFO *const above_mi = mi - cm->mode_info_stride;
+  const MODE_INFO *const above_mi = mi - xd->mode_info_stride;
   const MODE_INFO *const left_mi = mi - 1;
   const int left_in_image = xd->left_available && left_mi->mbmi.mb_in_image;
   const int above_in_image = xd->up_available && above_mi->mbmi.mb_in_image;
diff --git a/vp9/common/vp9_pred_common.h b/vp9/common/vp9_pred_common.h
index 7fc9a1c..9c83a63 100644
--- a/vp9/common/vp9_pred_common.h
+++ b/vp9/common/vp9_pred_common.h
@@ -55,21 +55,19 @@
 void vp9_set_pred_flag_mbskip(VP9_COMMON *cm, BLOCK_SIZE_TYPE bsize,
                               int mi_row, int mi_col, uint8_t pred_flag);
 
-unsigned char vp9_get_pred_context_switchable_interp(const VP9_COMMON *cm,
-                                                     const MACROBLOCKD *xd);
+unsigned char vp9_get_pred_context_switchable_interp(const MACROBLOCKD *xd);
 
 static INLINE const vp9_prob *vp9_get_pred_probs_switchable_interp(
     const VP9_COMMON *cm, const MACROBLOCKD *xd) {
-  const int pred_context = vp9_get_pred_context_switchable_interp(cm, xd);
+  const int pred_context = vp9_get_pred_context_switchable_interp(xd);
   return &cm->fc.switchable_interp_prob[pred_context][0];
 }
 
-unsigned char vp9_get_pred_context_intra_inter(const VP9_COMMON *cm,
-                                               const MACROBLOCKD *xd);
+unsigned char vp9_get_pred_context_intra_inter(const MACROBLOCKD *xd);
 
 static INLINE vp9_prob vp9_get_pred_prob_intra_inter(const VP9_COMMON *cm,
                                                      const MACROBLOCKD *xd) {
-  const int pred_context = vp9_get_pred_context_intra_inter(cm, xd);
+  const int pred_context = vp9_get_pred_context_intra_inter(xd);
   return cm->fc.intra_inter_prob[pred_context];
 }
 
@@ -92,37 +90,34 @@
   return cm->fc.comp_ref_prob[pred_context];
 }
 
-unsigned char vp9_get_pred_context_single_ref_p1(const VP9_COMMON *cm,
-                                                 const MACROBLOCKD *xd);
+unsigned char vp9_get_pred_context_single_ref_p1(const MACROBLOCKD *xd);
 
 static INLINE vp9_prob vp9_get_pred_prob_single_ref_p1(const VP9_COMMON *cm,
                                                        const MACROBLOCKD *xd) {
-  const int pred_context = vp9_get_pred_context_single_ref_p1(cm, xd);
+  const int pred_context = vp9_get_pred_context_single_ref_p1(xd);
   return cm->fc.single_ref_prob[pred_context][0];
 }
 
-unsigned char vp9_get_pred_context_single_ref_p2(const VP9_COMMON *cm,
-                                                 const MACROBLOCKD *xd);
+unsigned char vp9_get_pred_context_single_ref_p2(const MACROBLOCKD *xd);
 
 static INLINE vp9_prob vp9_get_pred_prob_single_ref_p2(const VP9_COMMON *cm,
                                                        const MACROBLOCKD *xd) {
-  const int pred_context = vp9_get_pred_context_single_ref_p2(cm, xd);
+  const int pred_context = vp9_get_pred_context_single_ref_p2(xd);
   return cm->fc.single_ref_prob[pred_context][1];
 }
 
-unsigned char vp9_get_pred_context_tx_size(const VP9_COMMON *cm,
-                                           const MACROBLOCKD *xd);
+unsigned char vp9_get_pred_context_tx_size(const MACROBLOCKD *xd);
 
-static INLINE const vp9_prob *vp9_get_pred_probs_tx_size(const VP9_COMMON *cm,
-                                                         const MACROBLOCKD * xd) {
+static const vp9_prob *vp9_get_pred_probs_tx_size(const MACROBLOCKD *xd,
+                           const struct tx_probs *tx_probs) {
   const MODE_INFO *const mi = xd->mode_info_context;
-  const int pred_context = vp9_get_pred_context_tx_size(cm, xd);
+  const int pred_context = vp9_get_pred_context_tx_size(xd);
   if (mi->mbmi.sb_type < BLOCK_SIZE_MB16X16)
-    return cm->fc.tx_probs.p8x8[pred_context];
+    return tx_probs->p8x8[pred_context];
   else if (mi->mbmi.sb_type < BLOCK_SIZE_SB32X32)
-    return cm->fc.tx_probs.p16x16[pred_context];
+    return tx_probs->p16x16[pred_context];
   else
-    return cm->fc.tx_probs.p32x32[pred_context];
+    return tx_probs->p32x32[pred_context];
 }
 
 #endif  // VP9_COMMON_VP9_PRED_COMMON_H_
diff --git a/vp9/common/vp9_reconinter.c b/vp9/common/vp9_reconinter.c
index c1b64d8..63e5646 100644
--- a/vp9/common/vp9_reconinter.c
+++ b/vp9/common/vp9_reconinter.c
@@ -296,8 +296,7 @@
     const int pre_stride = arg->pre_stride[which_mv][plane];
     const uint8_t *const pre = base_pre +
         scaled_buffer_offset(x, y, pre_stride, &xd->scale_factor[which_mv]);
-    struct scale_factors * const scale =
-      plane == 0 ? &xd->scale_factor[which_mv] : &xd->scale_factor_uv[which_mv];
+    struct scale_factors * const scale = &xd->scale_factor[which_mv];
 
     // dest
     uint8_t *const dst = arg->dst[plane] + arg->dst_stride[plane] * y + x;
diff --git a/vp9/common/vp9_reconinter.h b/vp9/common/vp9_reconinter.h
index 5b939ed..e37750d 100644
--- a/vp9/common/vp9_reconinter.h
+++ b/vp9/common/vp9_reconinter.h
@@ -83,8 +83,7 @@
 static void setup_pre_planes(MACROBLOCKD *xd, int i,
                              const YV12_BUFFER_CONFIG *src,
                              int mi_row, int mi_col,
-                             const struct scale_factors *scale,
-                             const struct scale_factors *scale_uv) {
+                             const struct scale_factors *sf) {
   if (src) {
     int j;
     uint8_t* buffers[4] = {src->y_buffer, src->u_buffer, src->v_buffer,
@@ -94,7 +93,6 @@
 
     for (j = 0; j < MAX_MB_PLANE; ++j) {
       struct macroblockd_plane *pd = &xd->plane[j];
-      const struct scale_factors *sf = j ? scale_uv : scale;
       setup_pred_plane(&pd->pre[i], buffers[j], strides[j],
                      mi_row, mi_col, sf, pd->subsampling_x, pd->subsampling_y);
     }
@@ -103,8 +101,8 @@
 
 static void set_scale_factors(MACROBLOCKD *xd, int ref0, int ref1,
                               struct scale_factors sf[MAX_REF_FRAMES]) {
-  xd->scale_factor[0] = xd->scale_factor_uv[0] = sf[ref0 >= 0 ? ref0 : 0];
-  xd->scale_factor[1] = xd->scale_factor_uv[1] = sf[ref1 >= 0 ? ref1 : 0];
+  xd->scale_factor[0] = sf[ref0 >= 0 ? ref0 : 0];
+  xd->scale_factor[1] = sf[ref1 >= 0 ? ref1 : 0];
 }
 
 void vp9_setup_scale_factors(VP9_COMMON *cm, int i);
diff --git a/vp9/common/vp9_rtcd_defs.sh b/vp9/common/vp9_rtcd_defs.sh
index c36efbd..2a9e62d 100644
--- a/vp9/common/vp9_rtcd_defs.sh
+++ b/vp9/common/vp9_rtcd_defs.sh
@@ -298,7 +298,7 @@
 specialize vp9_short_idct4x4_add sse2
 
 prototype void vp9_short_idct8x8_add "int16_t *input, uint8_t *dest, int dest_stride"
-specialize vp9_short_idct8x8_add sse2
+specialize vp9_short_idct8x8_add sse2 neon
 
 prototype void vp9_short_idct10_8x8_add "int16_t *input, uint8_t *dest, int dest_stride"
 specialize vp9_short_idct10_8x8_add sse2
diff --git a/vp9/decoder/vp9_decodemv.c b/vp9/decoder/vp9_decodemv.c
index a193c9f..6660f5b 100644
--- a/vp9/decoder/vp9_decodemv.c
+++ b/vp9/decoder/vp9_decodemv.c
@@ -31,7 +31,7 @@
 }
 
 static MB_PREDICTION_MODE read_inter_mode(vp9_reader *r, const vp9_prob *p) {
-  return (MB_PREDICTION_MODE)treed_read(r, vp9_sb_mv_ref_tree, p);
+  return (MB_PREDICTION_MODE)treed_read(r, vp9_inter_mode_tree, p);
 }
 
 static int read_segment_id(vp9_reader *r, const struct segmentation *seg) {
@@ -40,8 +40,8 @@
 
 static TX_SIZE read_selected_txfm_size(VP9_COMMON *cm, MACROBLOCKD *xd,
                                        BLOCK_SIZE_TYPE bsize, vp9_reader *r) {
-  const int context = vp9_get_pred_context_tx_size(cm, xd);
-  const vp9_prob *tx_probs = vp9_get_pred_probs_tx_size(cm, xd);
+  const int context = vp9_get_pred_context_tx_size(xd);
+  const vp9_prob *tx_probs = vp9_get_pred_probs_tx_size(xd, &cm->fc.tx_probs);
   TX_SIZE txfm_size = vp9_read(r, tx_probs[0]);
   if (txfm_size != TX_4X4 && bsize >= BLOCK_SIZE_MB16X16) {
     txfm_size += vp9_read(r, tx_probs[1]);
@@ -59,19 +59,19 @@
   return txfm_size;
 }
 
-static TX_SIZE read_txfm_size(VP9D_COMP *pbi, TXFM_MODE txfm_mode,
+static TX_SIZE read_txfm_size(VP9D_COMP *pbi, TX_MODE tx_mode,
                               BLOCK_SIZE_TYPE bsize, int select_cond,
                               vp9_reader *r) {
   VP9_COMMON *const cm = &pbi->common;
   MACROBLOCKD *const xd = &pbi->mb;
 
-  if (txfm_mode == TX_MODE_SELECT && bsize >= BLOCK_SIZE_SB8X8 && select_cond)
+  if (tx_mode == TX_MODE_SELECT && bsize >= BLOCK_SIZE_SB8X8 && select_cond)
     return read_selected_txfm_size(cm, xd, bsize, r);
-  else if (txfm_mode >= ALLOW_32X32 && bsize >= BLOCK_SIZE_SB32X32)
+  else if (tx_mode >= ALLOW_32X32 && bsize >= BLOCK_SIZE_SB32X32)
     return TX_32X32;
-  else if (txfm_mode >= ALLOW_16X16 && bsize >= BLOCK_SIZE_MB16X16)
+  else if (tx_mode >= ALLOW_16X16 && bsize >= BLOCK_SIZE_MB16X16)
     return TX_16X16;
-  else if (txfm_mode >= ALLOW_8X8 && bsize >= BLOCK_SIZE_SB8X8)
+  else if (tx_mode >= ALLOW_8X8 && bsize >= BLOCK_SIZE_SB8X8)
     return TX_8X8;
   else
     return TX_4X4;
@@ -162,14 +162,14 @@
 
   mbmi->segment_id = read_intra_segment_id(pbi, mi_row, mi_col, r);
   mbmi->mb_skip_coeff = read_skip_coeff(pbi, mbmi->segment_id, r);
-  mbmi->txfm_size = read_txfm_size(pbi, cm->txfm_mode, bsize, 1, r);
+  mbmi->txfm_size = read_txfm_size(pbi, cm->tx_mode, bsize, 1, r);
   mbmi->ref_frame[0] = INTRA_FRAME;
 
   if (bsize >= BLOCK_SIZE_SB8X8) {
     const MB_PREDICTION_MODE A = above_block_mode(m, 0, mis);
     const MB_PREDICTION_MODE L = xd->left_available ?
                                   left_block_mode(m, 0) : DC_PRED;
-    mbmi->mode = read_intra_mode(r, cm->kf_y_mode_prob[A][L]);
+    mbmi->mode = read_intra_mode(r, vp9_kf_y_mode_prob[A][L]);
   } else {
     // Only 4x4, 4x8, 8x4 blocks
     const int bw = 1 << b_width_log2(bsize);
@@ -183,7 +183,7 @@
         const MB_PREDICTION_MODE L = (xd->left_available || idx) ?
                                       left_block_mode(m, ib) : DC_PRED;
         const MB_PREDICTION_MODE b_mode = read_intra_mode(r,
-                                              cm->kf_y_mode_prob[A][L]);
+                                              vp9_kf_y_mode_prob[A][L]);
         m->bmi[ib].as_mode = b_mode;
         if (bh == 2)
           m->bmi[ib + 2].as_mode = b_mode;
@@ -195,7 +195,7 @@
     mbmi->mode = m->bmi[3].as_mode;
   }
 
-  mbmi->uv_mode = read_intra_mode(r, cm->kf_uv_mode_prob[mbmi->mode]);
+  mbmi->uv_mode = read_intra_mode(r, vp9_kf_uv_mode_prob[mbmi->mode]);
 }
 
 static int read_mv_component(vp9_reader *r,
@@ -245,7 +245,7 @@
   if (mv_joint_horizontal(j))
     diff.col = read_mv_component(r, &ctx->comps[1], usehp);
 
-  vp9_inc_mv(&diff, ref, counts, usehp);
+  vp9_inc_mv(&diff, counts);
 
   mv->row = ref->row + diff.row;
   mv->col = ref->col + diff.col;
@@ -330,10 +330,10 @@
       ref_frame[fix_ref_idx] = cm->comp_fixed_ref;
       ref_frame[!fix_ref_idx] = cm->comp_var_ref[b];
     } else {
-      const int ref1_ctx = vp9_get_pred_context_single_ref_p1(cm, xd);
+      const int ref1_ctx = vp9_get_pred_context_single_ref_p1(xd);
       ref_frame[1] = NONE;
       if (vp9_read(r, fc->single_ref_prob[ref1_ctx][0])) {
-        const int ref2_ctx = vp9_get_pred_context_single_ref_p2(cm, xd);
+        const int ref2_ctx = vp9_get_pred_context_single_ref_p2(xd);
         const int b = vp9_read(r, fc->single_ref_prob[ref2_ctx][1]);
         ref_frame[0] = b ? ALTREF_FRAME : GOLDEN_FRAME;
         fc->single_ref_count[ref1_ctx][0][1]++;
@@ -385,7 +385,7 @@
   MACROBLOCKD *const xd = &pbi->mb;
   const vp9_prob *probs = vp9_get_pred_probs_switchable_interp(cm, xd);
   const int index = treed_read(r, vp9_switchable_interp_tree, probs);
-  const int ctx = vp9_get_pred_context_switchable_interp(cm, xd);
+  const int ctx = vp9_get_pred_context_switchable_interp(xd);
   ++cm->fc.switchable_interp_count[ctx][index];
   return vp9_switchable_interp[index];
 }
@@ -433,7 +433,7 @@
 
   MV_REFERENCE_FRAME ref;
   if (!vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_REF_FRAME)) {
-    const int ctx = vp9_get_pred_context_intra_inter(cm, xd);
+    const int ctx = vp9_get_pred_context_intra_inter(xd);
     ref = (MV_REFERENCE_FRAME)
               vp9_read(r, vp9_get_pred_prob_intra_inter(cm, xd));
     cm->fc.intra_inter_count[ctx][ref != INTRA_FRAME]++;
@@ -463,7 +463,7 @@
   mbmi->mb_skip_coeff = read_skip_coeff(pbi, mbmi->segment_id, r);
   mbmi->ref_frame[0] = read_reference_frame(pbi, mbmi->segment_id, r);
   mbmi->ref_frame[1] = NONE;
-  mbmi->txfm_size = read_txfm_size(pbi, cm->txfm_mode, bsize,
+  mbmi->txfm_size = read_txfm_size(pbi, cm->tx_mode, bsize,
      (!mbmi->mb_skip_coeff || mbmi->ref_frame[0] == INTRA_FRAME), r);
 
   if (mbmi->ref_frame[0] != INTRA_FRAME) {
diff --git a/vp9/decoder/vp9_decodframe.c b/vp9/decoder/vp9_decodframe.c
index 118843a..3d11a22 100644
--- a/vp9/decoder/vp9_decodframe.c
+++ b/vp9/decoder/vp9_decodframe.c
@@ -48,11 +48,11 @@
   return data > max ? max : data;
 }
 
-static TXFM_MODE read_tx_mode(vp9_reader *r) {
-  TXFM_MODE txfm_mode = vp9_read_literal(r, 2);
-  if (txfm_mode == ALLOW_32X32)
-    txfm_mode += vp9_read_bit(r);
-  return txfm_mode;
+static TX_MODE read_tx_mode(vp9_reader *r) {
+  TX_MODE tx_mode = vp9_read_literal(r, 2);
+  if (tx_mode == ALLOW_32X32)
+    tx_mode += vp9_read_bit(r);
+  return tx_mode;
 }
 
 static void read_tx_probs(struct tx_probs *tx_probs, vp9_reader *r) {
@@ -215,9 +215,7 @@
 
   const YV12_BUFFER_CONFIG *cfg = &cm->yv12_fb[cm->active_ref_idx[ref]];
   xd->scale_factor[i] = cm->active_ref_scale[ref];
-  xd->scale_factor_uv[i] = cm->active_ref_scale[ref];
-  setup_pre_planes(xd, i, cfg, mi_row, mi_col,
-                   &xd->scale_factor[i], &xd->scale_factor_uv[i]);
+  setup_pre_planes(xd, i, cfg, mi_row, mi_col, &xd->scale_factor[i]);
   xd->corrupted |= cfg->corrupted;
 }
 
@@ -374,17 +372,17 @@
                   vp9_diff_update_prob(r, &coef_probs[i][j][k][l][m]);
 }
 
-static void read_coef_probs(FRAME_CONTEXT *fc, TXFM_MODE txfm_mode,
+static void read_coef_probs(FRAME_CONTEXT *fc, TX_MODE tx_mode,
                             vp9_reader *r) {
   read_coef_probs_common(fc->coef_probs[TX_4X4], r);
 
-  if (txfm_mode > ONLY_4X4)
+  if (tx_mode > ONLY_4X4)
     read_coef_probs_common(fc->coef_probs[TX_8X8], r);
 
-  if (txfm_mode > ALLOW_8X8)
+  if (tx_mode > ALLOW_8X8)
     read_coef_probs_common(fc->coef_probs[TX_16X16], r);
 
-  if (txfm_mode > ALLOW_16X16)
+  if (tx_mode > ALLOW_16X16)
     read_coef_probs_common(fc->coef_probs[TX_32X32], r);
 }
 
@@ -440,30 +438,29 @@
   }
 }
 
-static void setup_loopfilter(VP9D_COMP *pbi, struct vp9_read_bit_buffer *rb) {
-  VP9_COMMON *const cm = &pbi->common;
-  MACROBLOCKD *const xd = &pbi->mb;
+static void setup_loopfilter(struct loopfilter *lf,
+                             struct vp9_read_bit_buffer *rb) {
 
-  cm->filter_level = vp9_rb_read_literal(rb, 6);
-  cm->sharpness_level = vp9_rb_read_literal(rb, 3);
+  lf->filter_level = vp9_rb_read_literal(rb, 6);
+  lf->sharpness_level = vp9_rb_read_literal(rb, 3);
 
   // Read in loop filter deltas applied at the MB level based on mode or ref
   // frame.
-  xd->mode_ref_lf_delta_update = 0;
+  lf->mode_ref_delta_update = 0;
 
-  xd->mode_ref_lf_delta_enabled = vp9_rb_read_bit(rb);
-  if (xd->mode_ref_lf_delta_enabled) {
-    xd->mode_ref_lf_delta_update = vp9_rb_read_bit(rb);
-    if (xd->mode_ref_lf_delta_update) {
+  lf->mode_ref_delta_enabled = vp9_rb_read_bit(rb);
+  if (lf->mode_ref_delta_enabled) {
+    lf->mode_ref_delta_update = vp9_rb_read_bit(rb);
+    if (lf->mode_ref_delta_update) {
       int i;
 
       for (i = 0; i < MAX_REF_LF_DELTAS; i++)
         if (vp9_rb_read_bit(rb))
-          xd->ref_lf_deltas[i] = vp9_rb_read_signed_literal(rb, 6);
+          lf->ref_deltas[i] = vp9_rb_read_signed_literal(rb, 6);
 
       for (i = 0; i < MAX_MODE_LF_DELTAS; i++)
         if (vp9_rb_read_bit(rb))
-          xd->mode_lf_deltas[i] = vp9_rb_read_signed_literal(rb, 6);
+          lf->mode_deltas[i] = vp9_rb_read_signed_literal(rb, 6);
     }
   }
 }
@@ -585,21 +582,7 @@
   apply_frame_size(pbi, width, height);
 }
 
-static void update_frame_context(FRAME_CONTEXT *fc) {
-  vp9_copy(fc->pre_coef_probs, fc->coef_probs);
-  vp9_copy(fc->pre_y_mode_prob, fc->y_mode_prob);
-  vp9_copy(fc->pre_uv_mode_prob, fc->uv_mode_prob);
-  vp9_copy(fc->pre_partition_prob, fc->partition_prob[1]);
-  vp9_copy(fc->pre_intra_inter_prob, fc->intra_inter_prob);
-  vp9_copy(fc->pre_comp_inter_prob, fc->comp_inter_prob);
-  vp9_copy(fc->pre_single_ref_prob, fc->single_ref_prob);
-  vp9_copy(fc->pre_comp_ref_prob, fc->comp_ref_prob);
-  fc->pre_nmvc = fc->nmvc;
-  vp9_copy(fc->pre_switchable_interp_prob, fc->switchable_interp_prob);
-  vp9_copy(fc->pre_inter_mode_probs, fc->inter_mode_probs);
-  fc->pre_tx_probs = fc->tx_probs;
-  vp9_copy(fc->pre_mbskip_probs, fc->mbskip_probs);
-
+static void zero_counts(FRAME_CONTEXT *fc) {
   vp9_zero(fc->coef_counts);
   vp9_zero(fc->eob_branch_counts);
   vp9_zero(fc->y_mode_counts);
@@ -647,12 +630,11 @@
     cm->log2_tile_rows += vp9_rb_read_bit(rb);
 }
 
-static void decode_tiles(VP9D_COMP *pbi,
-                         const uint8_t *data, size_t first_partition_size,
-                         vp9_reader *residual_bc) {
+static const uint8_t *decode_tiles(VP9D_COMP *pbi, const uint8_t *data) {
+  vp9_reader residual_bc;
+
   VP9_COMMON *const pc = &pbi->common;
 
-  const uint8_t *data_ptr = data + first_partition_size;
   const uint8_t *const data_end = pbi->source + pbi->source_sz;
   const int aligned_mi_cols = mi_cols_aligned_to_sb(pc->mi_cols);
   const int tile_cols = 1 << pc->log2_tile_cols;
@@ -672,7 +654,7 @@
     vp9_reader bc_bak = {0};
 
     // pre-initialize the offsets, we're going to read in inverse order
-    data_ptr2[0][0] = data_ptr;
+    data_ptr2[0][0] = data;
     for (tile_row = 0; tile_row < tile_rows; tile_row++) {
       if (tile_row) {
         const int size = read_be32(data_ptr2[tile_row - 1][tile_cols - 1]);
@@ -694,13 +676,13 @@
         vp9_get_tile_col_offsets(pc, tile_col);
         setup_token_decoder(pbi, data_ptr2[tile_row][tile_col],
                             data_end - data_ptr2[tile_row][tile_col],
-                            residual_bc);
-        decode_tile(pbi, residual_bc);
+                            &residual_bc);
+        decode_tile(pbi, &residual_bc);
         if (tile_row == tile_rows - 1 && tile_col == tile_cols - 1)
-          bc_bak = *residual_bc;
+          bc_bak = residual_bc;
       }
     }
-    *residual_bc = bc_bak;
+    residual_bc = bc_bak;
   } else {
     int has_more;
 
@@ -713,22 +695,24 @@
 
         has_more = tile_col < tile_cols - 1 || tile_row < tile_rows - 1;
         if (has_more) {
-          if (!read_is_valid(data_ptr, 4, data_end))
+          if (!read_is_valid(data, 4, data_end))
             vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
                          "Truncated packet or corrupt tile length");
 
-          size = read_be32(data_ptr);
-          data_ptr += 4;
+          size = read_be32(data);
+          data += 4;
         } else {
-          size = data_end - data_ptr;
+          size = data_end - data;
         }
 
-        setup_token_decoder(pbi, data_ptr, size, residual_bc);
-        decode_tile(pbi, residual_bc);
-        data_ptr += size;
+        setup_token_decoder(pbi, data, size, &residual_bc);
+        decode_tile(pbi, &residual_bc);
+        data += size;
       }
     }
   }
+
+  return vp9_reader_find_end(&residual_bc);
 }
 
 static void check_sync_code(VP9_COMMON *cm, struct vp9_read_bit_buffer *rb) {
@@ -798,7 +782,7 @@
     int frame_to_show = cm->ref_frame_map[vp9_rb_read_literal(rb, 3)];
     ref_cnt_fb(cm->fb_idx_ref_cnt, &cm->new_fb_idx, frame_to_show);
     pbi->refresh_frame_flags = 0;
-    cm->filter_level = 0;
+    xd->lf.filter_level = 0;
     return 0;
   }
 
@@ -882,9 +866,9 @@
   if (cm->frame_type == KEY_FRAME || cm->error_resilient_mode || cm->intra_only)
     vp9_setup_past_independence(cm, xd);
 
-  setup_loopfilter(pbi, rb);
+  setup_loopfilter(&xd->lf, rb);
   setup_quantization(pbi, rb);
-  setup_segmentation(&pbi->mb.seg, rb);
+  setup_segmentation(&xd->seg, rb);
 
   setup_tile_info(cm, rb);
 
@@ -901,10 +885,10 @@
     vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
                        "Failed to allocate bool decoder 0");
 
-  cm->txfm_mode = xd->lossless ? ONLY_4X4 : read_tx_mode(&r);
-  if (cm->txfm_mode == TX_MODE_SELECT)
+  cm->tx_mode = xd->lossless ? ONLY_4X4 : read_tx_mode(&r);
+  if (cm->tx_mode == TX_MODE_SELECT)
     read_tx_probs(&cm->fc.tx_probs, &r);
-  read_coef_probs(&cm->fc, cm->txfm_mode, &r);
+  read_coef_probs(&cm->fc, cm->tx_mode, &r);
 
   vp9_prepare_read_mode_info(pbi, &r);
 
@@ -925,7 +909,6 @@
 
 int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) {
   int i;
-  vp9_reader residual_bc;
   VP9_COMMON *const pc = &pbi->common;
   MACROBLOCKD *const xd = &pbi->mb;
 
@@ -956,7 +939,6 @@
 
   xd->mode_info_context = pc->mi;
   xd->prev_mode_info_context = pc->prev_mi;
-  xd->frame_type = pc->frame_type;
   xd->mode_info_stride = pc->mode_info_stride;
 
   init_dequantizer(pc, &pbi->mb);
@@ -966,11 +948,10 @@
 
   pc->fc = pc->frame_contexts[pc->frame_context_idx];
 
-  update_frame_context(&pc->fc);
+  zero_counts(&pc->fc);
 
   // Initialize xd pointers. Any reference should do for xd->pre, so use 0.
-  setup_pre_planes(xd, 0, &pc->yv12_fb[pc->active_ref_idx[0]], 0, 0,
-                   NULL, NULL);
+  setup_pre_planes(xd, 0, &pc->yv12_fb[pc->active_ref_idx[0]], 0, 0, NULL);
   setup_dst_planes(xd, new_fb, 0, 0);
 
   new_fb->corrupted |= read_compressed_header(pbi, data, first_partition_size);
@@ -988,7 +969,7 @@
 
   set_prev_mi(pc);
 
-  decode_tiles(pbi, data, first_partition_size, &residual_bc);
+  *p_data_end = decode_tiles(pbi, data + first_partition_size);
 
   pc->last_width = pc->width;
   pc->last_height = pc->height;
@@ -1016,6 +997,5 @@
   if (pc->refresh_frame_context)
     pc->frame_contexts[pc->frame_context_idx] = pc->fc;
 
-  *p_data_end = vp9_reader_find_end(&residual_bc);
   return 0;
 }
diff --git a/vp9/decoder/vp9_onyxd_if.c b/vp9/decoder/vp9_onyxd_if.c
index f734eae..095485c 100644
--- a/vp9/decoder/vp9_onyxd_if.c
+++ b/vp9/decoder/vp9_onyxd_if.c
@@ -136,7 +136,7 @@
   // vp9_init_dequantizer() for every frame.
   vp9_init_dequantizer(&pbi->common);
 
-  vp9_loop_filter_init(&pbi->common);
+  vp9_loop_filter_init(&pbi->common, &pbi->mb.lf);
 
   pbi->common.error.setjmp = 0;
   pbi->decoded_key_frame = 0;
@@ -154,7 +154,6 @@
     vpx_free(pbi->common.last_frame_seg_map);
 
   vp9_remove_common(&pbi->common);
-  vpx_free(pbi->mbc);
   vpx_free(pbi);
 }
 
@@ -347,9 +346,9 @@
                              cm->current_video_frame + 1000);
 #endif
 
-    if (cm->filter_level) {
+    if (pbi->mb.lf.filter_level) {
       /* Apply the loop filter if appropriate. */
-      vp9_loop_filter_frame(cm, &pbi->mb, cm->filter_level, 0);
+      vp9_loop_filter_frame(cm, &pbi->mb, pbi->mb.lf.filter_level, 0);
     }
 
 #if WRITE_RECON_BUFFER == 2
@@ -414,7 +413,7 @@
   *time_end_stamp = 0;
 
 #if CONFIG_POSTPROC
-  ret = vp9_post_proc_frame(&pbi->common, sd, flags);
+  ret = vp9_post_proc_frame(&pbi->common, &pbi->mb.lf, sd, flags);
 #else
 
   if (pbi->common.frame_to_show) {
diff --git a/vp9/decoder/vp9_onyxd_int.h b/vp9/decoder/vp9_onyxd_int.h
index e78cbb5..0d85d44 100644
--- a/vp9/decoder/vp9_onyxd_int.h
+++ b/vp9/decoder/vp9_onyxd_int.h
@@ -10,13 +10,14 @@
 
 #ifndef VP9_DECODER_VP9_ONYXD_INT_H_
 #define VP9_DECODER_VP9_ONYXD_INT_H_
+
 #include "./vpx_config.h"
+
+#include "vp9/common/vp9_onyxc_int.h"
+
+#include "vp9/decoder/vp9_idct_blk.h"
 #include "vp9/decoder/vp9_onyxd.h"
 #include "vp9/decoder/vp9_treereader.h"
-#include "vp9/common/vp9_onyxc_int.h"
-#include "vp9/decoder/vp9_idct_blk.h"
-
-// #define DEC_DEBUG
 
 typedef struct VP9Decompressor {
   DECLARE_ALIGNED(16, MACROBLOCKD, mb);
@@ -28,12 +29,10 @@
   const uint8_t *source;
   uint32_t source_sz;
 
-  vp9_reader *mbc;
   int64_t last_time_stamp;
   int ready_for_new_data;
 
   int refresh_frame_flags;
-  vp9_prob prob_skip_false;
 
   int decoded_key_frame;
 
diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c
index 928fb70..07cb2b8 100644
--- a/vp9/encoder/vp9_bitstream.c
+++ b/vp9/encoder/vp9_bitstream.c
@@ -202,9 +202,9 @@
 
 static void write_selected_txfm_size(const VP9_COMP *cpi, TX_SIZE tx_size,
                                      BLOCK_SIZE_TYPE bsize, vp9_writer *w) {
-  const VP9_COMMON *const c = &cpi->common;
+  const VP9_COMMON *const cm = &cpi->common;
   const MACROBLOCKD *const xd = &cpi->mb.e_mbd;
-  const vp9_prob *tx_probs = vp9_get_pred_probs_tx_size(c, xd);
+  const vp9_prob *tx_probs = vp9_get_pred_probs_tx_size(xd, &cm->fc.tx_probs);
   vp9_write(w, tx_size != TX_4X4, tx_probs[0]);
   if (bsize >= BLOCK_SIZE_MB16X16 && tx_size != TX_4X4) {
     vp9_write(w, tx_size != TX_8X8, tx_probs[1]);
@@ -350,8 +350,8 @@
 static void write_sb_mv_ref(vp9_writer *w, MB_PREDICTION_MODE mode,
                             const vp9_prob *p) {
   assert(is_inter_mode(mode));
-  write_token(w, vp9_sb_mv_ref_tree, p,
-              &vp9_sb_mv_ref_encoding_array[mode - NEARESTMV]);
+  write_token(w, vp9_inter_mode_tree, p,
+              &vp9_inter_mode_encodings[mode - NEARESTMV]);
 }
 
 
@@ -441,7 +441,7 @@
     vp9_write(bc, rf != INTRA_FRAME,
               vp9_get_pred_prob_intra_inter(pc, xd));
 
-  if (mi->sb_type >= BLOCK_SIZE_SB8X8 && pc->txfm_mode == TX_MODE_SELECT &&
+  if (mi->sb_type >= BLOCK_SIZE_SB8X8 && pc->tx_mode == TX_MODE_SELECT &&
       !(rf != INTRA_FRAME &&
         (skip_coeff || vp9_segfeature_active(seg, segment_id, SEG_LVL_SKIP)))) {
     write_selected_txfm_size(cpi, mi->txfm_size, mi->sb_type, bc);
@@ -505,7 +505,7 @@
         for (idx = 0; idx < 2; idx += bw) {
           j = idy * 2 + idx;
           blockmode = cpi->mb.partition_info->bmi[j].mode;
-          blockmv = cpi->mb.partition_info->bmi[j].mv;
+          blockmv = m->bmi[j].as_mv[0];
           write_sb_mv_ref(bc, blockmode, mv_ref_p);
           vp9_accum_mv_refs(&cpi->common, blockmode, mi->mb_mode_context[rf]);
           if (blockmode == NEWMV) {
@@ -517,7 +517,7 @@
 
             if (mi->ref_frame[1] > INTRA_FRAME)
               vp9_encode_mv(cpi, bc,
-                            &cpi->mb.partition_info->bmi[j].second_mv.as_mv,
+                            &m->bmi[j].as_mv[1].as_mv,
                             &mi->best_second_mv.as_mv,
                             nmvc, xd->allow_high_precision_mv);
           }
@@ -553,14 +553,14 @@
 
   write_skip_coeff(cpi, segment_id, m, bc);
 
-  if (m->mbmi.sb_type >= BLOCK_SIZE_SB8X8 && c->txfm_mode == TX_MODE_SELECT)
+  if (m->mbmi.sb_type >= BLOCK_SIZE_SB8X8 && c->tx_mode == TX_MODE_SELECT)
     write_selected_txfm_size(cpi, m->mbmi.txfm_size, m->mbmi.sb_type, bc);
 
   if (m->mbmi.sb_type >= BLOCK_SIZE_SB8X8) {
     const MB_PREDICTION_MODE A = above_block_mode(m, 0, mis);
     const MB_PREDICTION_MODE L = xd->left_available ?
                                  left_block_mode(m, 0) : DC_PRED;
-    write_intra_mode(bc, ym, c->kf_y_mode_prob[A][L]);
+    write_intra_mode(bc, ym, vp9_kf_y_mode_prob[A][L]);
   } else {
     int idx, idy;
     int bw = 1 << b_width_log2(m->mbmi.sb_type);
@@ -575,12 +575,12 @@
 #ifdef ENTROPY_STATS
         ++intra_mode_stats[A][L][bm];
 #endif
-        write_intra_mode(bc, bm, c->kf_y_mode_prob[A][L]);
+        write_intra_mode(bc, bm, vp9_kf_y_mode_prob[A][L]);
       }
     }
   }
 
-  write_intra_mode(bc, m->mbmi.uv_mode, c->kf_uv_mode_prob[ym]);
+  write_intra_mode(bc, m->mbmi.uv_mode, vp9_kf_uv_mode_prob[ym]);
 }
 
 static void write_modes_b(VP9_COMP *cpi, MODE_INFO *m, vp9_writer *bc,
@@ -905,7 +905,7 @@
 }
 
 static void update_coef_probs(VP9_COMP* const cpi, vp9_writer* const bc) {
-  const TXFM_MODE txfm_mode = cpi->common.txfm_mode;
+  const TX_MODE tx_mode = cpi->common.tx_mode;
 
   vp9_clear_system_state();
 
@@ -915,39 +915,39 @@
   update_coef_probs_common(bc, cpi, TX_4X4);
 
   // do not do this if not even allowed
-  if (txfm_mode > ONLY_4X4)
+  if (tx_mode > ONLY_4X4)
     update_coef_probs_common(bc, cpi, TX_8X8);
 
-  if (txfm_mode > ALLOW_8X8)
+  if (tx_mode > ALLOW_8X8)
     update_coef_probs_common(bc, cpi, TX_16X16);
 
-  if (txfm_mode > ALLOW_16X16)
+  if (tx_mode > ALLOW_16X16)
     update_coef_probs_common(bc, cpi, TX_32X32);
 }
 
-static void encode_loopfilter(VP9_COMMON *pc, MACROBLOCKD *xd,
+static void encode_loopfilter(struct loopfilter *lf,
                               struct vp9_write_bit_buffer *wb) {
   int i;
 
   // Encode the loop filter level and type
-  vp9_wb_write_literal(wb, pc->filter_level, 6);
-  vp9_wb_write_literal(wb, pc->sharpness_level, 3);
+  vp9_wb_write_literal(wb, lf->filter_level, 6);
+  vp9_wb_write_literal(wb, lf->sharpness_level, 3);
 
   // Write out loop filter deltas applied at the MB level based on mode or
   // ref frame (if they are enabled).
-  vp9_wb_write_bit(wb, xd->mode_ref_lf_delta_enabled);
+  vp9_wb_write_bit(wb, lf->mode_ref_delta_enabled);
 
-  if (xd->mode_ref_lf_delta_enabled) {
+  if (lf->mode_ref_delta_enabled) {
     // Do the deltas need to be updated
-    vp9_wb_write_bit(wb, xd->mode_ref_lf_delta_update);
-    if (xd->mode_ref_lf_delta_update) {
+    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 = xd->ref_lf_deltas[i];
+        const int delta = lf->ref_deltas[i];
 
         // Frame level data
-        if (delta != xd->last_ref_lf_deltas[i]) {
-          xd->last_ref_lf_deltas[i] = delta;
+        if (delta != lf->last_ref_deltas[i]) {
+          lf->last_ref_deltas[i] = delta;
           vp9_wb_write_bit(wb, 1);
 
           assert(delta != 0);
@@ -960,9 +960,9 @@
 
       // Send update
       for (i = 0; i < MAX_MODE_LF_DELTAS; i++) {
-        const int delta = xd->mode_lf_deltas[i];
-        if (delta != xd->last_mode_lf_deltas[i]) {
-          xd->last_mode_lf_deltas[i] = delta;
+        const int delta = lf->mode_deltas[i];
+        if (delta != lf->last_mode_deltas[i]) {
+          lf->last_mode_deltas[i] = delta;
           vp9_wb_write_bit(wb, 1);
 
           assert(delta != 0);
@@ -1062,12 +1062,12 @@
   VP9_COMMON *const cm = &cpi->common;
 
   // Mode
-  vp9_write_literal(w, MIN(cm->txfm_mode, ALLOW_32X32), 2);
-  if (cm->txfm_mode >= ALLOW_32X32)
-    vp9_write_bit(w, cm->txfm_mode == TX_MODE_SELECT);
+  vp9_write_literal(w, MIN(cm->tx_mode, ALLOW_32X32), 2);
+  if (cm->tx_mode >= ALLOW_32X32)
+    vp9_write_bit(w, cm->tx_mode == TX_MODE_SELECT);
 
   // Probabilities
-  if (cm->txfm_mode == TX_MODE_SELECT) {
+  if (cm->tx_mode == TX_MODE_SELECT) {
     int i, j;
     unsigned int ct_8x8p[TX_SIZE_MAX_SB - 3][2];
     unsigned int ct_16x16p[TX_SIZE_MAX_SB - 2][2];
@@ -1372,7 +1372,7 @@
 
   vp9_wb_write_literal(wb, cm->frame_context_idx, NUM_FRAME_CONTEXTS_LOG2);
 
-  encode_loopfilter(cm, xd, wb);
+  encode_loopfilter(&xd->lf, wb);
   encode_quantization(cm, wb);
   encode_segmentation(cpi, wb);
 
@@ -1388,7 +1388,7 @@
   vp9_start_encode(&header_bc, data);
 
   if (xd->lossless)
-    cm->txfm_mode = ONLY_4X4;
+    cm->tx_mode = ONLY_4X4;
   else
     encode_txfm_probs(cpi, &header_bc);
 
@@ -1471,7 +1471,6 @@
 }
 
 void vp9_pack_bitstream(VP9_COMP *cpi, uint8_t *dest, unsigned long *size) {
-  FRAME_CONTEXT *const fc = &cpi->common.fc;
   uint8_t *data = dest;
   size_t first_part_size;
   struct vp9_write_bit_buffer wb = {data, 0};
@@ -1494,20 +1493,6 @@
 
   vp9_clear_system_state();  // __asm emms;
 
-  vp9_copy(fc->pre_coef_probs, fc->coef_probs);
-  vp9_copy(fc->pre_y_mode_prob, fc->y_mode_prob);
-  vp9_copy(fc->pre_uv_mode_prob, fc->uv_mode_prob);
-  vp9_copy(fc->pre_partition_prob, fc->partition_prob[INTER_FRAME]);
-  fc->pre_nmvc = fc->nmvc;
-  vp9_copy(fc->pre_switchable_interp_prob, fc->switchable_interp_prob);
-  vp9_copy(fc->pre_inter_mode_probs, fc->inter_mode_probs);
-  vp9_copy(fc->pre_intra_inter_prob, fc->intra_inter_prob);
-  vp9_copy(fc->pre_comp_inter_prob, fc->comp_inter_prob);
-  vp9_copy(fc->pre_comp_ref_prob, fc->comp_ref_prob);
-  vp9_copy(fc->pre_single_ref_prob, fc->single_ref_prob);
-  fc->pre_tx_probs = fc->tx_probs;
-  vp9_copy(fc->pre_mbskip_probs, fc->mbskip_probs);
-
   first_part_size = write_compressed_header(cpi, data);
   data += first_part_size;
   vp9_wb_write_literal(&saved_wb, first_part_size, 16);
diff --git a/vp9/encoder/vp9_block.h b/vp9/encoder/vp9_block.h
index b4c06f5..d6882d5 100644
--- a/vp9/encoder/vp9_block.h
+++ b/vp9/encoder/vp9_block.h
@@ -24,11 +24,8 @@
 } search_site;
 
 typedef struct {
-  int count;
   struct {
     MB_PREDICTION_MODE mode;
-    int_mv mv;
-    int_mv second_mv;
   } bmi[4];
 } PARTITION_INFO;
 
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c
index 3dd235a..2e7cb29 100644
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -352,8 +352,8 @@
 
   if (mbmi->ref_frame[0] != INTRA_FRAME && mbmi->sb_type < BLOCK_SIZE_SB8X8) {
     *x->partition_info = ctx->partition_info;
-    mbmi->mv[0].as_int = x->partition_info->bmi[3].mv.as_int;
-    mbmi->mv[1].as_int = x->partition_info->bmi[3].second_mv.as_int;
+    mbmi->mv[0].as_int = mi->bmi[3].as_mv[0].as_int;
+    mbmi->mv[1].as_int = mi->bmi[3].as_mv[1].as_int;
   }
 
   x->skip = ctx->skip;
@@ -422,7 +422,7 @@
     if (cpi->common.mcomp_filter_type == SWITCHABLE
         && is_inter_mode(mbmi->mode)) {
       ++cpi->common.fc.switchable_interp_count[
-          vp9_get_pred_context_switchable_interp(&cpi->common, xd)]
+          vp9_get_pred_context_switchable_interp(xd)]
             [vp9_switchable_interp_map[mbmi->interp_filter]];
     }
 
@@ -542,7 +542,8 @@
 
 static void pick_sb_modes(VP9_COMP *cpi, int mi_row, int mi_col,
                           int *totalrate, int64_t *totaldist,
-                          BLOCK_SIZE_TYPE bsize, PICK_MODE_CONTEXT *ctx) {
+                          BLOCK_SIZE_TYPE bsize, PICK_MODE_CONTEXT *ctx,
+                          int64_t best_rd) {
   VP9_COMMON *const cm = &cpi->common;
   MACROBLOCK *const x = &cpi->mb;
   MACROBLOCKD *const xd = &x->e_mbd;
@@ -561,10 +562,11 @@
   // Find best coding mode & reconstruct the MB so it is available
   // as a predictor for MBs that follow in the SB
   if (cm->frame_type == KEY_FRAME)
-    vp9_rd_pick_intra_mode_sb(cpi, x, totalrate, totaldist, bsize, ctx);
+    vp9_rd_pick_intra_mode_sb(cpi, x, totalrate, totaldist, bsize, ctx,
+                              best_rd);
   else
     vp9_rd_pick_inter_mode_sb(cpi, x, mi_row, mi_col, totalrate, totaldist,
-                              bsize, ctx);
+                              bsize, ctx, best_rd);
 }
 
 static void update_stats(VP9_COMP *cpi, int mi_row, int mi_col) {
@@ -579,7 +581,7 @@
                                                      SEG_LVL_REF_FRAME);
 
     if (!seg_ref_active)
-      cpi->intra_inter_count[vp9_get_pred_context_intra_inter(cm, xd)][mbmi
+      cpi->intra_inter_count[vp9_get_pred_context_intra_inter(xd)][mbmi
           ->ref_frame[0] > INTRA_FRAME]++;
 
     // If the segment reference feature is enabled we have only a single
@@ -594,10 +596,10 @@
         cpi->comp_ref_count[vp9_get_pred_context_comp_ref_p(cm, xd)][mbmi
             ->ref_frame[0] == GOLDEN_FRAME]++;
       } else {
-        cpi->single_ref_count[vp9_get_pred_context_single_ref_p1(cm, xd)]
+        cpi->single_ref_count[vp9_get_pred_context_single_ref_p1(xd)]
                               [0][mbmi->ref_frame[0] != LAST_FRAME]++;
         if (mbmi->ref_frame[0] != LAST_FRAME)
-          cpi->single_ref_count[vp9_get_pred_context_single_ref_p2(cm, xd)][1]
+          cpi->single_ref_count[vp9_get_pred_context_single_ref_p2(xd)][1]
               [mbmi->ref_frame[0] != GOLDEN_FRAME]++;
       }
     }
@@ -1076,9 +1078,9 @@
     YV12_BUFFER_CONFIG *second_ref_fb = NULL;
 
     setup_pre_planes(xd, 0, ref_fb, mi_row, mi_col,
-                     &xd->scale_factor[0], &xd->scale_factor_uv[0]);
+                     &xd->scale_factor[0]);
     setup_pre_planes(xd, 1, second_ref_fb, mi_row, mi_col,
-                     &xd->scale_factor[1], &xd->scale_factor_uv[1]);
+                     &xd->scale_factor[1]);
     xd->mode_info_context->mbmi.ref_frame[0] = LAST_FRAME;
     xd->mode_info_context->mbmi.sb_type = BLOCK_SIZE_SB64X64;
     vp9_find_best_ref_mvs(xd, m->mbmi.ref_mvs[m->mbmi.ref_frame[0]],
@@ -1230,7 +1232,7 @@
         mi_col + (ms >> 1) < cm->mi_cols) {
       *(get_sb_partitioning(x, bsize)) = bsize;
       pick_sb_modes(cpi, mi_row, mi_col, &none_rate, &none_dist, bsize,
-                    get_block_context(x, bsize));
+                    get_block_context(x, bsize), INT64_MAX);
 
       set_partition_seg_context(cm, xd, mi_row, mi_col);
       pl = partition_plane_context(xd, bsize);
@@ -1245,48 +1247,52 @@
   switch (partition) {
     case PARTITION_NONE:
       pick_sb_modes(cpi, mi_row, mi_col, &last_part_rate, &last_part_dist,
-                    bsize, get_block_context(x, bsize));
-      set_partition_seg_context(cm, xd, mi_row, mi_col);
-      pl = partition_plane_context(xd, bsize);
-      last_part_rate += x->partition_cost[pl][PARTITION_NONE];
+                    bsize, get_block_context(x, bsize), INT64_MAX);
       break;
     case PARTITION_HORZ:
       *(get_sb_index(xd, subsize)) = 0;
       pick_sb_modes(cpi, mi_row, mi_col, &last_part_rate, &last_part_dist,
-                    subsize, get_block_context(x, subsize));
-      if (bsize >= BLOCK_SIZE_SB8X8 && mi_row + (mh >> 1) < cm->mi_rows) {
+                    subsize, get_block_context(x, subsize), INT64_MAX);
+      if (last_part_rate != INT_MAX &&
+          bsize >= BLOCK_SIZE_SB8X8 && mi_row + (mh >> 1) < cm->mi_rows) {
         int rt = 0;
         int64_t dt = 0;
         update_state(cpi, get_block_context(x, subsize), subsize, 0);
         encode_superblock(cpi, tp, 0, mi_row, mi_col, subsize);
         *(get_sb_index(xd, subsize)) = 1;
         pick_sb_modes(cpi, mi_row + (ms >> 1), mi_col, &rt, &dt, subsize,
-                      get_block_context(x, subsize));
+                      get_block_context(x, subsize), INT64_MAX);
+        if (rt == INT_MAX || dt == INT_MAX) {
+          last_part_rate = INT_MAX;
+          last_part_dist = INT_MAX;
+          break;
+        }
+
         last_part_rate += rt;
         last_part_dist += dt;
       }
-      set_partition_seg_context(cm, xd, mi_row, mi_col);
-      pl = partition_plane_context(xd, bsize);
-      last_part_rate += x->partition_cost[pl][PARTITION_HORZ];
       break;
     case PARTITION_VERT:
       *(get_sb_index(xd, subsize)) = 0;
       pick_sb_modes(cpi, mi_row, mi_col, &last_part_rate, &last_part_dist,
-                    subsize, get_block_context(x, subsize));
-      if (bsize >= BLOCK_SIZE_SB8X8 && mi_col + (ms >> 1) < cm->mi_cols) {
+                    subsize, get_block_context(x, subsize), INT64_MAX);
+      if (last_part_rate != INT_MAX &&
+          bsize >= BLOCK_SIZE_SB8X8 && mi_col + (ms >> 1) < cm->mi_cols) {
         int rt = 0;
         int64_t dt = 0;
         update_state(cpi, get_block_context(x, subsize), subsize, 0);
         encode_superblock(cpi, tp, 0, mi_row, mi_col, subsize);
         *(get_sb_index(xd, subsize)) = 1;
         pick_sb_modes(cpi, mi_row, mi_col + (ms >> 1), &rt, &dt, subsize,
-                      get_block_context(x, subsize));
+                      get_block_context(x, subsize), INT64_MAX);
+        if (rt == INT_MAX || dt == INT_MAX) {
+          last_part_rate = INT_MAX;
+          last_part_dist = INT_MAX;
+          break;
+        }
         last_part_rate += rt;
         last_part_dist += dt;
       }
-      set_partition_seg_context(cm, xd, mi_row, mi_col);
-      pl = partition_plane_context(xd, bsize);
-      last_part_rate += x->partition_cost[pl][PARTITION_VERT];
       break;
     case PARTITION_SPLIT:
       // Split partition.
@@ -1306,16 +1312,23 @@
 
         rd_use_partition(cpi, m + jj * bss * mis + ii * bss, tp, mi_row + y_idx,
                          mi_col + x_idx, subsize, &rt, &dt, i != 3);
+        if (rt == INT_MAX || dt == INT_MAX) {
+          last_part_rate = INT_MAX;
+          last_part_dist = INT_MAX;
+          break;
+        }
         last_part_rate += rt;
         last_part_dist += dt;
       }
-      set_partition_seg_context(cm, xd, mi_row, mi_col);
-      pl = partition_plane_context(xd, bsize);
-      last_part_rate += x->partition_cost[pl][PARTITION_SPLIT];
       break;
     default:
       assert(0);
   }
+  set_partition_seg_context(cm, xd, mi_row, mi_col);
+  pl = partition_plane_context(xd, bsize);
+  if (last_part_rate < INT_MAX)
+    last_part_rate += x->partition_cost[pl][partition];
+
   if (cpi->sf.adjust_partitioning_from_last_frame
       && partition != PARTITION_SPLIT && bsize > BLOCK_SIZE_SB8X8
       && (mi_row + ms < cm->mi_rows || mi_row + (ms >> 1) == cm->mi_rows)
@@ -1345,11 +1358,18 @@
       save_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
 
       pick_sb_modes(cpi, mi_row + y_idx, mi_col + x_idx, &rt, &dt,
-                    split_subsize, get_block_context(x, split_subsize));
+                    split_subsize, get_block_context(x, split_subsize),
+                    INT64_MAX);
 
       restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
 
-      if (rt < INT_MAX && dt < INT_MAX && i != 3)
+      if (rt == INT_MAX || dt == INT_MAX) {
+        split_rate = INT_MAX;
+        split_dist = INT_MAX;
+        break;
+      }
+
+      if (i != 3)
         encode_sb(cpi, tp,  mi_row + y_idx, mi_col + x_idx, 0,
                   split_subsize);
 
@@ -1361,10 +1381,12 @@
     }
     set_partition_seg_context(cm, xd, mi_row, mi_col);
     pl = partition_plane_context(xd, bsize);
-    split_rate += x->partition_cost[pl][PARTITION_SPLIT];
+    if (split_rate < INT_MAX) {
+      split_rate += x->partition_cost[pl][PARTITION_SPLIT];
 
-    chosen_rate = split_rate;
-    chosen_dist = split_dist;
+      chosen_rate = split_rate;
+      chosen_dist = split_dist;
+    }
   }
 
   // If last_part is better set the partitioning to that...
@@ -1389,10 +1411,12 @@
 
   // We must have chosen a partitioning and encoding or we'll fail later on.
   // No other opportunities for success.
-  assert(chosen_rate < INT_MAX && chosen_dist < INT_MAX);
+  if ( bsize == BLOCK_SIZE_SB64X64)
+    assert(chosen_rate < INT_MAX && chosen_dist < INT_MAX);
 
   if (do_recon)
     encode_sb(cpi, tp, mi_row, mi_col, bsize == BLOCK_SIZE_SB64X64, bsize);
+
   *rate = chosen_rate;
   *dist = chosen_dist;
 }
@@ -1403,7 +1427,7 @@
 // results, for encoding speed-up.
 static void rd_pick_partition(VP9_COMP *cpi, TOKENEXTRA **tp, int mi_row,
                               int mi_col, BLOCK_SIZE_TYPE bsize, int *rate,
-                              int64_t *dist, int do_recon) {
+                              int64_t *dist, int do_recon, int64_t best_rd) {
   VP9_COMMON * const cm = &cpi->common;
   MACROBLOCK * const x = &cpi->mb;
   MACROBLOCKD * const xd = &x->e_mbd;
@@ -1433,13 +1457,12 @@
   if (!cpi->sf.use_partitions_greater_than
       || (cpi->sf.use_partitions_greater_than
           && bsize > cpi->sf.greater_than_block_size)) {
-    if (bsize >= BLOCK_SIZE_SB8X8) {
+    if (bsize > BLOCK_SIZE_SB8X8) {
       int r4 = 0;
-      int64_t d4 = 0;
+      int64_t d4 = 0, sum_rd = 0;
       subsize = get_subsize(bsize, PARTITION_SPLIT);
-      *(get_sb_partitioning(x, bsize)) = subsize;
 
-      for (i = 0; i < 4; ++i) {
+      for (i = 0; i < 4 && sum_rd < best_rd; ++i) {
         int x_idx = (i & 1) * (ms >> 1);
         int y_idx = (i >> 1) * (ms >> 1);
         int r = 0;
@@ -1450,19 +1473,28 @@
 
         *(get_sb_index(xd, subsize)) = i;
         rd_pick_partition(cpi, tp, mi_row + y_idx, mi_col + x_idx, subsize, &r,
-                          &d, i != 3);
+                          &d, i != 3, best_rd - sum_rd);
 
-        r4 += r;
-        d4 += d;
+        if (r == INT_MAX) {
+          r4 = INT_MAX;
+          sum_rd = INT64_MAX;
+        } else {
+          r4 += r;
+          d4 += d;
+          sum_rd = RDCOST(x->rdmult, x->rddiv, r4, d4);
+        }
       }
       set_partition_seg_context(cm, xd, mi_row, mi_col);
       pl = partition_plane_context(xd, bsize);
-      if (r4 < INT_MAX)
+      if (r4 != INT_MAX && i == 4) {
         r4 += x->partition_cost[pl][PARTITION_SPLIT];
-      assert(r4 >= 0);
-      assert(d4 >= 0);
-      srate = r4;
-      sdist = d4;
+        *(get_sb_partitioning(x, bsize)) = subsize;
+        assert(r4 >= 0);
+        assert(d4 >= 0);
+        srate = r4;
+        sdist = d4;
+        best_rd = MIN(best_rd, RDCOST(x->rdmult, x->rddiv, r4, d4));
+      }
       restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
     }
   }
@@ -1608,15 +1640,18 @@
       int r;
       int64_t d;
       pick_sb_modes(cpi, mi_row, mi_col, &r, &d, bsize,
-                    get_block_context(x, bsize));
-      if (bsize >= BLOCK_SIZE_SB8X8) {
+                    get_block_context(x, bsize), best_rd);
+      if (r != INT_MAX && bsize >= BLOCK_SIZE_SB8X8) {
         set_partition_seg_context(cm, xd, mi_row, mi_col);
         pl = partition_plane_context(xd, bsize);
         r += x->partition_cost[pl][PARTITION_NONE];
       }
 
-      if (RDCOST(x->rdmult, x->rddiv, r, d)
-          < RDCOST(x->rdmult, x->rddiv, srate, sdist)) {
+      if (r != INT_MAX &&
+          (bsize == BLOCK_SIZE_SB8X8 ||
+           RDCOST(x->rdmult, x->rddiv, r, d) <
+               RDCOST(x->rdmult, x->rddiv, srate, sdist))) {
+        best_rd = MIN(best_rd, RDCOST(x->rdmult, x->rddiv, r, d));
         srate = r;
         sdist = d;
         larger_is_better = 1;
@@ -1624,33 +1659,84 @@
           *(get_sb_partitioning(x, bsize)) = bsize;
       }
     }
+
+    if (bsize == BLOCK_SIZE_SB8X8) {
+      int r4 = 0;
+      int64_t d4 = 0, sum_rd = 0;
+      subsize = get_subsize(bsize, PARTITION_SPLIT);
+
+      for (i = 0; i < 4 && sum_rd < best_rd; ++i) {
+        int x_idx = (i & 1) * (ms >> 1);
+        int y_idx = (i >> 1) * (ms >> 1);
+        int r = 0;
+        int64_t d = 0;
+
+        if ((mi_row + y_idx >= cm->mi_rows) || (mi_col + x_idx >= cm->mi_cols))
+          continue;
+
+        *(get_sb_index(xd, subsize)) = i;
+        rd_pick_partition(cpi, tp, mi_row + y_idx, mi_col + x_idx, subsize, &r,
+                          &d, i != 3, best_rd - sum_rd);
+
+        if (r == INT_MAX) {
+          r4 = INT_MAX;
+          sum_rd = INT64_MAX;
+        } else {
+          r4 += r;
+          d4 += d;
+          sum_rd = RDCOST(x->rdmult, x->rddiv, r4, d4);
+        }
+      }
+      set_partition_seg_context(cm, xd, mi_row, mi_col);
+      pl = partition_plane_context(xd, bsize);
+      if (r4 != INT_MAX && i == 4) {
+        r4 += x->partition_cost[pl][PARTITION_SPLIT];
+        if (RDCOST(x->rdmult, x->rddiv, r4, d4) <
+            RDCOST(x->rdmult, x->rddiv, srate, sdist)) {
+          srate = r4;
+          sdist = d4;
+          larger_is_better = 0;
+          *(get_sb_partitioning(x, bsize)) = subsize;
+          best_rd = MIN(best_rd, RDCOST(x->rdmult, x->rddiv, r4, d4));
+        }
+      }
+      restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
+    }
+
     if (!cpi->sf.use_square_partition_only &&
         (!cpi->sf.less_rectangular_check ||!larger_is_better)) {
       // PARTITION_HORZ
       if (bsize >= BLOCK_SIZE_SB8X8 && mi_col + (ms >> 1) < cm->mi_cols) {
         int r2, r = 0;
-        int64_t d2, d = 0;
+        int64_t d2, d = 0, h_rd;
         subsize = get_subsize(bsize, PARTITION_HORZ);
         *(get_sb_index(xd, subsize)) = 0;
         pick_sb_modes(cpi, mi_row, mi_col, &r2, &d2, subsize,
-                      get_block_context(x, subsize));
+                      get_block_context(x, subsize), best_rd);
+        h_rd = RDCOST(x->rdmult, x->rddiv, r2, d2);
 
-        if (mi_row + (ms >> 1) < cm->mi_rows) {
+        if (r2 != INT_MAX && h_rd < best_rd &&
+            mi_row + (ms >> 1) < cm->mi_rows) {
           update_state(cpi, get_block_context(x, subsize), subsize, 0);
           encode_superblock(cpi, tp, 0, mi_row, mi_col, subsize);
 
           *(get_sb_index(xd, subsize)) = 1;
           pick_sb_modes(cpi, mi_row + (ms >> 1), mi_col, &r, &d, subsize,
-                        get_block_context(x, subsize));
-          r2 += r;
-          d2 += d;
+                        get_block_context(x, subsize), best_rd - h_rd);
+          if (r == INT_MAX) {
+            r2 = INT_MAX;
+          } else {
+            r2 += r;
+            d2 += d;
+          }
         }
         set_partition_seg_context(cm, xd, mi_row, mi_col);
         pl = partition_plane_context(xd, bsize);
         if (r2 < INT_MAX)
           r2 += x->partition_cost[pl][PARTITION_HORZ];
-        if (RDCOST(x->rdmult, x->rddiv, r2, d2)
+        if (r2 != INT_MAX && RDCOST(x->rdmult, x->rddiv, r2, d2)
             < RDCOST(x->rdmult, x->rddiv, srate, sdist)) {
+          best_rd = MIN(best_rd, RDCOST(x->rdmult, x->rddiv, r2, d2));
           srate = r2;
           sdist = d2;
           *(get_sb_partitioning(x, bsize)) = subsize;
@@ -1661,12 +1747,14 @@
       // PARTITION_VERT
       if (bsize >= BLOCK_SIZE_SB8X8 && mi_row + (ms >> 1) < cm->mi_rows) {
         int r2;
-        int64_t d2;
+        int64_t d2, v_rd;
         subsize = get_subsize(bsize, PARTITION_VERT);
         *(get_sb_index(xd, subsize)) = 0;
         pick_sb_modes(cpi, mi_row, mi_col, &r2, &d2, subsize,
-                      get_block_context(x, subsize));
-        if (mi_col + (ms >> 1) < cm->mi_cols) {
+                      get_block_context(x, subsize), best_rd);
+        v_rd = RDCOST(x->rdmult, x->rddiv, r2, d2);
+        if (r2 != INT_MAX && v_rd < best_rd &&
+            mi_col + (ms >> 1) < cm->mi_cols) {
           int r = 0;
           int64_t d = 0;
           update_state(cpi, get_block_context(x, subsize), subsize, 0);
@@ -1674,15 +1762,20 @@
 
           *(get_sb_index(xd, subsize)) = 1;
           pick_sb_modes(cpi, mi_row, mi_col + (ms >> 1), &r, &d, subsize,
-                        get_block_context(x, subsize));
-          r2 += r;
-          d2 += d;
+                        get_block_context(x, subsize), best_rd - v_rd);
+          if (r == INT_MAX) {
+            r2 = INT_MAX;
+          } else {
+            r2 += r;
+            d2 += d;
+          }
         }
         set_partition_seg_context(cm, xd, mi_row, mi_col);
         pl = partition_plane_context(xd, bsize);
         if (r2 < INT_MAX)
           r2 += x->partition_cost[pl][PARTITION_VERT];
-        if (RDCOST(x->rdmult, x->rddiv, r2, d2)
+        if (r2 != INT_MAX &&
+            RDCOST(x->rdmult, x->rddiv, r2, d2)
             < RDCOST(x->rdmult, x->rddiv, srate, sdist)) {
           srate = r2;
           sdist = d2;
@@ -1733,7 +1826,7 @@
       (mi_col + (ms >> 1) < cm->mi_cols)) {
     cpi->set_ref_frame_mask = 1;
     pick_sb_modes(cpi, mi_row, mi_col, &r, &d, BLOCK_SIZE_SB64X64,
-                  get_block_context(x, BLOCK_SIZE_SB64X64));
+                  get_block_context(x, BLOCK_SIZE_SB64X64), INT64_MAX);
     set_partition_seg_context(cm, xd, mi_row, mi_col);
     pl = partition_plane_context(xd, BLOCK_SIZE_SB64X64);
     r += x->partition_cost[pl][PARTITION_NONE];
@@ -1811,7 +1904,7 @@
             || cpi->common.frame_type == KEY_FRAME
             || cpi->is_src_frame_alt_ref) {
           rd_pick_partition(cpi, tp, mi_row, mi_col, BLOCK_SIZE_SB64X64,
-                            &dummy_rate, &dummy_dist, 1);
+                            &dummy_rate, &dummy_dist, 1, INT64_MAX);
         } else {
           copy_partitioning(cpi, m, p);
           rd_use_partition(cpi, m, tp, mi_row, mi_col, BLOCK_SIZE_SB64X64,
@@ -1820,7 +1913,7 @@
       }
     } else {
       rd_pick_partition(cpi, tp, mi_row, mi_col, BLOCK_SIZE_SB64X64,
-                        &dummy_rate, &dummy_dist, 1);
+                        &dummy_rate, &dummy_dist, 1, INT64_MAX);
     }
   }
 }
@@ -1835,7 +1928,6 @@
   cpi->seg0_idx = 0;
 
   xd->mode_info_stride = cm->mode_info_stride;
-  xd->frame_type = cm->frame_type;
 
   // reset intra mode contexts
   if (cm->frame_type == KEY_FRAME)
@@ -1846,7 +1938,7 @@
 
   // TODO(jkoleszar): are these initializations required?
   setup_pre_planes(xd, 0, &cm->yv12_fb[cm->ref_frame_map[cpi->lst_fb_idx]],
-                   0, 0, NULL, NULL);
+                   0, 0, NULL);
   setup_dst_planes(xd, &cm->yv12_fb[cm->new_fb_idx], 0, 0);
 
   setup_block_dptrs(&x->e_mbd, cm->subsampling_x, cm->subsampling_y);
@@ -1881,9 +1973,9 @@
     cpi->mb.e_mbd.inv_txm4x4_1_add = vp9_short_iwalsh4x4_1_add;
     cpi->mb.e_mbd.inv_txm4x4_add = vp9_short_iwalsh4x4_add;
     cpi->mb.optimize = 0;
-    cpi->common.filter_level = 0;
+    cpi->mb.e_mbd.lf.filter_level = 0;
     cpi->zbin_mode_boost_enabled = 0;
-    cpi->common.txfm_mode = ONLY_4X4;
+    cpi->common.tx_mode = ONLY_4X4;
   } else {
     // printf("Not lossless\n");
     cpi->mb.fwd_txm8x4 = vp9_short_fdct8x4;
@@ -1893,10 +1985,10 @@
   }
 }
 
-static void switch_txfm_mode(VP9_COMP *cpi) {
+static void switch_tx_mode(VP9_COMP *cpi) {
   if (cpi->sf.tx_size_search_method == USE_LARGESTALL &&
-      cpi->common.txfm_mode >= ALLOW_32X32)
-    cpi->common.txfm_mode = ALLOW_32X32;
+      cpi->common.tx_mode >= ALLOW_32X32)
+    cpi->common.tx_mode = ALLOW_32X32;
 }
 
 static void encode_frame_internal(VP9_COMP *cpi) {
@@ -1943,7 +2035,7 @@
 
   vp9_initialize_rd_consts(cpi, cm->base_qindex + cm->y_dc_delta_q);
   vp9_initialize_me_consts(cpi, cm->base_qindex);
-  switch_txfm_mode(cpi);
+  switch_tx_mode(cpi);
 
   if (cpi->oxcf.tuning == VP8_TUNE_SSIM) {
     // Initialize encode frame context.
@@ -2157,17 +2249,17 @@
   return frame_type;
 }
 
-static void select_txfm_mode(VP9_COMP *cpi) {
+static void select_tx_mode(VP9_COMP *cpi) {
   if (cpi->oxcf.lossless) {
-    cpi->common.txfm_mode = ONLY_4X4;
+    cpi->common.tx_mode = ONLY_4X4;
   } else if (cpi->common.current_video_frame == 0) {
-    cpi->common.txfm_mode = TX_MODE_SELECT;
+    cpi->common.tx_mode = TX_MODE_SELECT;
   } else {
     if (cpi->sf.tx_size_search_method == USE_LARGESTALL) {
-      cpi->common.txfm_mode = ALLOW_32X32;
+      cpi->common.tx_mode = ALLOW_32X32;
     } else if (cpi->sf.tx_size_search_method == USE_FULL_RD) {
       int frame_type = get_frame_type(cpi);
-      cpi->common.txfm_mode =
+      cpi->common.tx_mode =
           cpi->rd_tx_select_threshes[frame_type][ALLOW_32X32]
           > cpi->rd_tx_select_threshes[frame_type][TX_MODE_SELECT] ?
           ALLOW_32X32 : TX_MODE_SELECT;
@@ -2178,7 +2270,7 @@
         total += cpi->txfm_stepdown_count[i];
       if (total) {
         double fraction = (double)cpi->txfm_stepdown_count[0] / total;
-        cpi->common.txfm_mode = fraction > 0.90 ? ALLOW_32X32 : TX_MODE_SELECT;
+        cpi->common.tx_mode = fraction > 0.90 ? ALLOW_32X32 : TX_MODE_SELECT;
         // printf("fraction = %f\n", fraction);
       }  // else keep unchanged
     }
@@ -2266,7 +2358,7 @@
       cpi->mb.e_mbd.lossless = 1;
     }
 
-    select_txfm_mode(cpi);
+    select_tx_mode(cpi);
     cpi->common.comp_pred_mode = pred_type;
     cpi->common.mcomp_filter_type = filter_type;
     encode_frame_internal(cpi);
@@ -2312,7 +2404,7 @@
       }
     }
 
-    if (cpi->common.txfm_mode == TX_MODE_SELECT) {
+    if (cpi->common.tx_mode == TX_MODE_SELECT) {
       int count4x4 = 0;
       int count8x8_lp = 0, count8x8_8x8p = 0;
       int count16x16_16x16p = 0, count16x16_lp = 0;
@@ -2344,16 +2436,16 @@
 
       if (count4x4 == 0 && count16x16_lp == 0 && count16x16_16x16p == 0
           && count32x32 == 0) {
-        cpi->common.txfm_mode = ALLOW_8X8;
+        cpi->common.tx_mode = ALLOW_8X8;
         reset_skip_txfm_size(cpi, TX_8X8);
       } else if (count8x8_8x8p == 0 && count16x16_16x16p == 0
                  && count8x8_lp == 0 && count16x16_lp == 0 && count32x32 == 0) {
-        cpi->common.txfm_mode = ONLY_4X4;
+        cpi->common.tx_mode = ONLY_4X4;
         reset_skip_txfm_size(cpi, TX_4X4);
       } else if (count8x8_lp == 0 && count16x16_lp == 0 && count4x4 == 0) {
-        cpi->common.txfm_mode = ALLOW_32X32;
+        cpi->common.tx_mode = ALLOW_32X32;
       } else if (count32x32 == 0 && count8x8_lp == 0 && count4x4 == 0) {
-        cpi->common.txfm_mode = ALLOW_16X16;
+        cpi->common.tx_mode = ALLOW_16X16;
         reset_skip_txfm_size(cpi, TX_16X16);
       }
     }
@@ -2480,9 +2572,9 @@
     assert(cm->frame_type != KEY_FRAME);
 
     setup_pre_planes(xd, 0, ref_fb, mi_row, mi_col,
-                     &xd->scale_factor[0], &xd->scale_factor_uv[0]);
+                     &xd->scale_factor[0]);
     setup_pre_planes(xd, 1, second_ref_fb, mi_row, mi_col,
-                     &xd->scale_factor[1], &xd->scale_factor_uv[1]);
+                     &xd->scale_factor[1]);
 
 
     vp9_build_inter_predictors_sb(
@@ -2513,12 +2605,12 @@
   vp9_set_pred_flag_mbskip(cm, bsize, mi_row, mi_col, mi->mbmi.mb_skip_coeff);
 
   if (output_enabled) {
-    if (cm->txfm_mode == TX_MODE_SELECT &&
+    if (cm->tx_mode == TX_MODE_SELECT &&
         mbmi->sb_type >= BLOCK_SIZE_SB8X8  &&
         !(mbmi->ref_frame[0] != INTRA_FRAME &&
             (mbmi->mb_skip_coeff ||
              vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_SKIP)))) {
-      const int context = vp9_get_pred_context_tx_size(cm, xd);
+      const int context = vp9_get_pred_context_tx_size(xd);
       if (bsize >= BLOCK_SIZE_SB32X32) {
         cm->fc.tx_counts.p32x32[context][mbmi->txfm_size]++;
       } else if (bsize >= BLOCK_SIZE_MB16X16) {
@@ -2528,7 +2620,7 @@
       }
     } else {
       int x, y;
-      TX_SIZE sz = (cm->txfm_mode == TX_MODE_SELECT) ? TX_32X32 : cm->txfm_mode;
+      TX_SIZE sz = (cm->tx_mode == TX_MODE_SELECT) ? TX_32X32 : cm->tx_mode;
       // The new intra coding scheme requires no change of transform size
       if (mi->mbmi.ref_frame[0] != INTRA_FRAME) {
         if (sz == TX_32X32 && bsize < BLOCK_SIZE_SB32X32)
diff --git a/vp9/encoder/vp9_encodemv.c b/vp9/encoder/vp9_encodemv.c
index 8adad9d..500f574 100644
--- a/vp9/encoder/vp9_encodemv.c
+++ b/vp9/encoder/vp9_encodemv.c
@@ -510,44 +510,42 @@
 
 void vp9_update_nmv_count(VP9_COMP *cpi, MACROBLOCK *x,
                          int_mv *best_ref_mv, int_mv *second_best_ref_mv) {
-  MB_MODE_INFO * mbmi = &x->e_mbd.mode_info_context->mbmi;
-  MV mv;
-  int bwl = b_width_log2(mbmi->sb_type), bw = 1 << bwl;
-  int bhl = b_height_log2(mbmi->sb_type), bh = 1 << bhl;
+  MODE_INFO *mi = x->e_mbd.mode_info_context;
+  MB_MODE_INFO *const mbmi = &mi->mbmi;
+  MV diff;
+  const int bw = 1 << b_width_log2(mbmi->sb_type);
+  const int bh = 1 << b_height_log2(mbmi->sb_type);
   int idx, idy;
 
   if (mbmi->sb_type < BLOCK_SIZE_SB8X8) {
-    int i;
     PARTITION_INFO *pi = x->partition_info;
     for (idy = 0; idy < 2; idy += bh) {
       for (idx = 0; idx < 2; idx += bw) {
-        i = idy * 2 + idx;
+        const int i = idy * 2 + idx;
         if (pi->bmi[i].mode == NEWMV) {
-          mv.row = (pi->bmi[i].mv.as_mv.row - best_ref_mv->as_mv.row);
-          mv.col = (pi->bmi[i].mv.as_mv.col - best_ref_mv->as_mv.col);
-          vp9_inc_mv(&mv, &best_ref_mv->as_mv, &cpi->NMVcount,
-                     x->e_mbd.allow_high_precision_mv);
+          diff.row = mi->bmi[i].as_mv[0].as_mv.row - best_ref_mv->as_mv.row;
+          diff.col = mi->bmi[i].as_mv[0].as_mv.col - best_ref_mv->as_mv.col;
+          vp9_inc_mv(&diff, &cpi->NMVcount);
+
           if (x->e_mbd.mode_info_context->mbmi.ref_frame[1] > INTRA_FRAME) {
-            mv.row = pi->bmi[i].second_mv.as_mv.row -
+            diff.row = mi->bmi[i].as_mv[1].as_mv.row -
                          second_best_ref_mv->as_mv.row;
-            mv.col = pi->bmi[i].second_mv.as_mv.col -
+            diff.col = mi->bmi[i].as_mv[1].as_mv.col -
                          second_best_ref_mv->as_mv.col;
-            vp9_inc_mv(&mv, &second_best_ref_mv->as_mv, &cpi->NMVcount,
-                       x->e_mbd.allow_high_precision_mv);
+            vp9_inc_mv(&diff, &cpi->NMVcount);
           }
         }
       }
     }
   } else if (mbmi->mode == NEWMV) {
-    mv.row = mbmi->mv[0].as_mv.row - best_ref_mv->as_mv.row;
-    mv.col = mbmi->mv[0].as_mv.col - best_ref_mv->as_mv.col;
-    vp9_inc_mv(&mv, &best_ref_mv->as_mv, &cpi->NMVcount,
-                      x->e_mbd.allow_high_precision_mv);
+    diff.row = mbmi->mv[0].as_mv.row - best_ref_mv->as_mv.row;
+    diff.col = mbmi->mv[0].as_mv.col - best_ref_mv->as_mv.col;
+    vp9_inc_mv(&diff, &cpi->NMVcount);
+
     if (mbmi->ref_frame[1] > INTRA_FRAME) {
-      mv.row = mbmi->mv[1].as_mv.row - second_best_ref_mv->as_mv.row;
-      mv.col = mbmi->mv[1].as_mv.col - second_best_ref_mv->as_mv.col;
-      vp9_inc_mv(&mv, &second_best_ref_mv->as_mv, &cpi->NMVcount,
-                 x->e_mbd.allow_high_precision_mv);
+      diff.row = mbmi->mv[1].as_mv.row - second_best_ref_mv->as_mv.row;
+      diff.col = mbmi->mv[1].as_mv.col - second_best_ref_mv->as_mv.col;
+      vp9_inc_mv(&diff, &cpi->NMVcount);
     }
   }
 }
diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c
index b5932eb..ec2e361 100644
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -501,7 +501,7 @@
   vp9_clear_system_state();  // __asm emms;
 
   vp9_setup_src_planes(x, cpi->Source, 0, 0);
-  setup_pre_planes(xd, 0, lst_yv12, 0, 0, NULL, NULL);
+  setup_pre_planes(xd, 0, lst_yv12, 0, 0, NULL);
   setup_dst_planes(xd, new_yv12, 0, 0);
 
   x->partition_info = x->pi;
diff --git a/vp9/encoder/vp9_mbgraph.c b/vp9/encoder/vp9_mbgraph.c
index 9637393..7d6db07 100644
--- a/vp9/encoder/vp9_mbgraph.c
+++ b/vp9/encoder/vp9_mbgraph.c
@@ -406,8 +406,8 @@
   // being a GF - so exit if we don't look ahead beyond that
   if (n_frames <= cpi->frames_till_gf_update_due)
     return;
-  if (n_frames > (int)cpi->common.frames_till_alt_ref_frame)
-    n_frames = cpi->common.frames_till_alt_ref_frame;
+  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_modecosts.c b/vp9/encoder/vp9_modecosts.c
index f2e4ce4..993aba7 100644
--- a/vp9/encoder/vp9_modecosts.c
+++ b/vp9/encoder/vp9_modecosts.c
@@ -22,8 +22,8 @@
 
   for (i = 0; i < VP9_INTRA_MODES; i++) {
     for (j = 0; j < VP9_INTRA_MODES; j++) {
-      vp9_cost_tokens((int *)c->mb.y_mode_costs[i][j],
-                      x->kf_y_mode_prob[i][j], KT);
+      vp9_cost_tokens((int *)c->mb.y_mode_costs[i][j], vp9_kf_y_mode_prob[i][j],
+                      KT);
     }
   }
 
@@ -33,7 +33,8 @@
   vp9_cost_tokens(c->mb.intra_uv_mode_cost[1],
                   x->fc.uv_mode_prob[VP9_INTRA_MODES - 1], vp9_intra_mode_tree);
   vp9_cost_tokens(c->mb.intra_uv_mode_cost[0],
-                  x->kf_uv_mode_prob[VP9_INTRA_MODES - 1], vp9_intra_mode_tree);
+                  vp9_kf_uv_mode_prob[VP9_INTRA_MODES - 1],
+                  vp9_intra_mode_tree);
 
   for (i = 0; i <= VP9_SWITCHABLE_FILTERS; ++i)
     vp9_cost_tokens((int *)c->mb.switchable_interp_costs[i],
diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c
index 500bdfe..fe276fa 100644
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -131,6 +131,32 @@
 static int gf_high_motion_minq[QINDEX_RANGE];
 static int inter_minq[QINDEX_RANGE];
 
+static INLINE void Scale2Ratio(int mode, int *hr, int *hs) {
+  switch (mode) {
+    case NORMAL:
+      *hr = 1;
+      *hs = 1;
+      break;
+    case FOURFIVE:
+      *hr = 4;
+      *hs = 5;
+      break;
+    case THREEFIVE:
+      *hr = 3;
+      *hs = 5;
+    break;
+    case ONETWO:
+      *hr = 1;
+      *hs = 2;
+    break;
+    default:
+      *hr = 1;
+      *hs = 1;
+       assert(0);
+      break;
+  }
+}
+
 // Functions to compute the active minq lookup table entries based on a
 // formulaic approach to facilitate easier adjustment of the Q tables.
 // The formulae were derived from computing a 3rd order polynomial best
@@ -217,6 +243,7 @@
 
 static void setup_features(VP9_COMP *cpi) {
   MACROBLOCKD *xd = &cpi->mb.e_mbd;
+  struct loopfilter *lf = &xd->lf;
 
   // Set up default state for MB feature flags
   xd->seg.enabled = 0;
@@ -227,12 +254,12 @@
 
   vp9_clearall_segfeatures(&xd->seg);
 
-  xd->mode_ref_lf_delta_enabled = 0;
-  xd->mode_ref_lf_delta_update = 0;
-  vpx_memset(xd->ref_lf_deltas, 0, sizeof(xd->ref_lf_deltas));
-  vpx_memset(xd->mode_lf_deltas, 0, sizeof(xd->mode_lf_deltas));
-  vpx_memset(xd->last_ref_lf_deltas, 0, sizeof(xd->ref_lf_deltas));
-  vpx_memset(xd->last_mode_lf_deltas, 0, sizeof(xd->mode_lf_deltas));
+  lf->mode_ref_delta_enabled = 0;
+  lf->mode_ref_delta_update = 0;
+  vp9_zero(lf->ref_deltas);
+  vp9_zero(lf->mode_deltas);
+  vp9_zero(lf->last_ref_deltas);
+  vp9_zero(lf->last_mode_deltas);
 
   set_default_lf_deltas(cpi);
 }
@@ -351,7 +378,7 @@
     // All other frames if segmentation has been enabled
 
     // First normal frame in a valid gf or alt ref group
-    if (cpi->common.frames_since_golden == 0) {
+    if (cpi->frames_since_golden == 0) {
       // Set up segment features for normal frames in an arf group
       if (cpi->source_alt_ref_active) {
         xd->seg.update_map = 0;
@@ -518,20 +545,22 @@
 }
 
 static void set_default_lf_deltas(VP9_COMP *cpi) {
-  cpi->mb.e_mbd.mode_ref_lf_delta_enabled = 1;
-  cpi->mb.e_mbd.mode_ref_lf_delta_update = 1;
+  struct loopfilter *lf = &cpi->mb.e_mbd.lf;
 
-  vpx_memset(cpi->mb.e_mbd.ref_lf_deltas, 0, sizeof(cpi->mb.e_mbd.ref_lf_deltas));
-  vpx_memset(cpi->mb.e_mbd.mode_lf_deltas, 0, sizeof(cpi->mb.e_mbd.mode_lf_deltas));
+  lf->mode_ref_delta_enabled = 1;
+  lf->mode_ref_delta_update = 1;
+
+  vp9_zero(lf->ref_deltas);
+  vp9_zero(lf->mode_deltas);
 
   // Test of ref frame deltas
-  cpi->mb.e_mbd.ref_lf_deltas[INTRA_FRAME] = 2;
-  cpi->mb.e_mbd.ref_lf_deltas[LAST_FRAME] = 0;
-  cpi->mb.e_mbd.ref_lf_deltas[GOLDEN_FRAME] = -2;
-  cpi->mb.e_mbd.ref_lf_deltas[ALTREF_FRAME] = -2;
+  lf->ref_deltas[INTRA_FRAME] = 2;
+  lf->ref_deltas[LAST_FRAME] = 0;
+  lf->ref_deltas[GOLDEN_FRAME] = -2;
+  lf->ref_deltas[ALTREF_FRAME] = -2;
 
-  cpi->mb.e_mbd.mode_lf_deltas[0] = 0;              // Zero
-  cpi->mb.e_mbd.mode_lf_deltas[1] = 0;               // New mv
+  lf->mode_deltas[0] = 0;   // Zero
+  lf->mode_deltas[1] = 0;   // New mv
 }
 
 static void set_rd_speed_thresholds(VP9_COMP *cpi, int mode, int speed) {
@@ -543,60 +572,57 @@
   for (i = 0; i < MAX_MODES; ++i)
     sf->thresh_mult[i] = mode == 0 ? -500 : 0;
 
-  sf->thresh_mult[THR_ZEROMV] = 0;
-  sf->thresh_mult[THR_ZEROG] = 0;
-  sf->thresh_mult[THR_ZEROA] = 0;
-
   sf->thresh_mult[THR_NEARESTMV] = 0;
   sf->thresh_mult[THR_NEARESTG] = 0;
   sf->thresh_mult[THR_NEARESTA] = 0;
 
+  sf->thresh_mult[THR_NEWMV] += speed_multiplier * 1000;
+  sf->thresh_mult[THR_COMP_NEARESTLA] += speed_multiplier * 1000;
   sf->thresh_mult[THR_NEARMV] += speed_multiplier * 1000;
-  sf->thresh_mult[THR_NEARG] += speed_multiplier * 1000;
+  sf->thresh_mult[THR_COMP_NEARESTGA] += speed_multiplier * 1000;
+
+  sf->thresh_mult[THR_DC] += speed_multiplier * 1000;
+
+  sf->thresh_mult[THR_NEWG] += speed_multiplier * 1000;
+  sf->thresh_mult[THR_NEWA] += speed_multiplier * 1000;
   sf->thresh_mult[THR_NEARA] += speed_multiplier * 1000;
 
-  sf->thresh_mult[THR_DC       ] = 0;
   sf->thresh_mult[THR_TM] += speed_multiplier * 1000;
-  sf->thresh_mult[THR_V_PRED   ] += speed_multiplier * 1000;
-  sf->thresh_mult[THR_H_PRED   ] += speed_multiplier * 1000;
-  sf->thresh_mult[THR_D45_PRED ] += speed_multiplier * 1500;
-  sf->thresh_mult[THR_D135_PRED] += speed_multiplier * 1500;
-  sf->thresh_mult[THR_D117_PRED] += speed_multiplier * 1500;
-  sf->thresh_mult[THR_D153_PRED] += speed_multiplier * 1500;
-  sf->thresh_mult[THR_D27_PRED ] += speed_multiplier * 1500;
-  sf->thresh_mult[THR_D63_PRED ] += speed_multiplier * 1500;
-
-  sf->thresh_mult[THR_B_PRED   ] += speed_multiplier * 2500;
-
-  sf->thresh_mult[THR_NEWMV    ] += speed_multiplier * 1000;
-  sf->thresh_mult[THR_NEWG     ] += speed_multiplier * 1000;
-  sf->thresh_mult[THR_NEWA     ] += speed_multiplier * 1000;
-
-  sf->thresh_mult[THR_SPLITMV  ] += speed_multiplier * 2500;
-  sf->thresh_mult[THR_SPLITG   ] += speed_multiplier * 2500;
-  sf->thresh_mult[THR_SPLITA   ] += speed_multiplier * 2500;
-
-  sf->thresh_mult[THR_COMP_ZEROLA] += speed_multiplier * 1500;
-  sf->thresh_mult[THR_COMP_ZEROGA] += speed_multiplier * 1500;
-
-  sf->thresh_mult[THR_COMP_NEARESTLA] += speed_multiplier * 1500;
-  sf->thresh_mult[THR_COMP_NEARESTGA] += speed_multiplier * 1500;
 
   sf->thresh_mult[THR_COMP_NEARLA] += speed_multiplier * 1500;
+  sf->thresh_mult[THR_COMP_NEWLA] += speed_multiplier * 2000;
+  sf->thresh_mult[THR_NEARG] += speed_multiplier * 1000;
   sf->thresh_mult[THR_COMP_NEARGA] += speed_multiplier * 1500;
+  sf->thresh_mult[THR_COMP_NEWGA] += speed_multiplier * 2000;
 
-  sf->thresh_mult[THR_COMP_NEWLA    ] += speed_multiplier * 2000;
-  sf->thresh_mult[THR_COMP_NEWGA    ] += speed_multiplier * 2000;
+  sf->thresh_mult[THR_SPLITMV] += speed_multiplier * 2500;
+  sf->thresh_mult[THR_SPLITG] += speed_multiplier * 2500;
+  sf->thresh_mult[THR_SPLITA] += speed_multiplier * 2500;
+  sf->thresh_mult[THR_COMP_SPLITLA] += speed_multiplier * 4500;
+  sf->thresh_mult[THR_COMP_SPLITGA] += speed_multiplier * 4500;
 
-  sf->thresh_mult[THR_COMP_SPLITLA  ] += speed_multiplier * 4500;
-  sf->thresh_mult[THR_COMP_SPLITGA  ] += speed_multiplier * 4500;
+  sf->thresh_mult[THR_ZEROMV] += speed_multiplier * 2000;
+  sf->thresh_mult[THR_ZEROG] += speed_multiplier * 2000;
+  sf->thresh_mult[THR_ZEROA] += speed_multiplier * 2000;
+  sf->thresh_mult[THR_COMP_ZEROLA] += speed_multiplier * 2500;
+  sf->thresh_mult[THR_COMP_ZEROGA] += speed_multiplier * 2500;
+
+  sf->thresh_mult[THR_B_PRED] += speed_multiplier * 2500;
+  sf->thresh_mult[THR_H_PRED] += speed_multiplier * 2000;
+  sf->thresh_mult[THR_V_PRED] += speed_multiplier * 2000;
+  sf->thresh_mult[THR_D45_PRED ] += speed_multiplier * 2500;
+  sf->thresh_mult[THR_D135_PRED] += speed_multiplier * 2500;
+  sf->thresh_mult[THR_D117_PRED] += speed_multiplier * 2500;
+  sf->thresh_mult[THR_D153_PRED] += speed_multiplier * 2500;
+  sf->thresh_mult[THR_D27_PRED] += speed_multiplier * 2500;
+  sf->thresh_mult[THR_D63_PRED] += speed_multiplier * 2500;
 
   if (cpi->sf.skip_lots_of_modes) {
     for (i = 0; i < MAX_MODES; ++i)
       sf->thresh_mult[i] = INT_MAX;
 
-    sf->thresh_mult[THR_DC] = 0;
-    sf->thresh_mult[THR_TM] = 0;
+    sf->thresh_mult[THR_DC] = 2000;
+    sf->thresh_mult[THR_TM] = 2000;
     sf->thresh_mult[THR_NEWMV] = 4000;
     sf->thresh_mult[THR_NEWG] = 4000;
     sf->thresh_mult[THR_NEWA] = 4000;
@@ -877,8 +903,6 @@
 
   cpi->mb.quantize_b_4x4      = vp9_regular_quantize_b_4x4;
 
-  vp9_init_quantizer(cpi);
-
   if (cpi->sf.iterative_sub_pixel == 1) {
     cpi->find_fractional_mv_step = vp9_find_best_sub_pixel_step_iteratively;
   } else if (cpi->sf.quarter_pixel_search) {
@@ -1261,7 +1285,7 @@
   // VP8 sharpness level mapping 0-7 (vs 0-10 in general VPx dialogs)
   cpi->oxcf.Sharpness = MIN(7, cpi->oxcf.Sharpness);
 
-  cm->sharpness_level = cpi->oxcf.Sharpness;
+  cpi->mb.e_mbd.lf.sharpness_level = cpi->oxcf.Sharpness;
 
   if (cpi->initial_width) {
     // Increasing the size of the frame beyond the first seen frame, or some
@@ -1664,7 +1688,7 @@
    */
   vp9_init_quantizer(cpi);
 
-  vp9_loop_filter_init(cm);
+  vp9_loop_filter_init(cm, &cpi->mb.e_mbd.lf);
 
   cpi->common.error.setjmp = 0;
 
@@ -2151,7 +2175,7 @@
 
 static void update_alt_ref_frame_stats(VP9_COMP *cpi) {
   // this frame refreshes means next frames don't unless specified by user
-  cpi->common.frames_since_golden = 0;
+  cpi->frames_since_golden = 0;
 
 #if CONFIG_MULTIPLE_ARF
   if (!cpi->multi_arf_enabled)
@@ -2167,7 +2191,7 @@
   if (cpi->refresh_golden_frame) {
     // this frame refreshes means next frames don't unless specified by user
     cpi->refresh_golden_frame = 0;
-    cpi->common.frames_since_golden = 0;
+    cpi->frames_since_golden = 0;
 
     // ******** Fixed Q test code only ************
     // If we are going to use the ALT reference for the next group of frames set a flag to say so.
@@ -2189,10 +2213,10 @@
     if (cpi->frames_till_gf_update_due > 0)
       cpi->frames_till_gf_update_due--;
 
-    if (cpi->common.frames_till_alt_ref_frame)
-      cpi->common.frames_till_alt_ref_frame--;
+    if (cpi->frames_till_alt_ref_frame)
+      cpi->frames_till_alt_ref_frame--;
 
-    cpi->common.frames_since_golden++;
+    cpi->frames_since_golden++;
   }
 }
 
@@ -2384,8 +2408,9 @@
 }
 
 static void loopfilter_frame(VP9_COMP *cpi, VP9_COMMON *cm) {
-  if (cpi->mb.e_mbd.lossless) {
-    cm->filter_level = 0;
+  MACROBLOCKD *xd = &cpi->mb.e_mbd;
+  if (xd->lossless) {
+      xd->lf.filter_level = 0;
   } else {
     struct vpx_usec_timer timer;
 
@@ -2399,14 +2424,13 @@
     cpi->time_pick_lpf += vpx_usec_timer_elapsed(&timer);
   }
 
-  if (cm->filter_level > 0) {
-    vp9_set_alt_lf_level(cpi, cm->filter_level);
-    vp9_loop_filter_frame(cm, &cpi->mb.e_mbd, cm->filter_level, 0);
+  if (xd->lf.filter_level > 0) {
+    vp9_set_alt_lf_level(cpi, xd->lf.filter_level);
+    vp9_loop_filter_frame(cm, xd, xd->lf.filter_level, 0);
   }
 
   vp9_extend_frame_inner_borders(cm->frame_to_show,
-                           cm->subsampling_x, cm->subsampling_y);
-
+                                 cm->subsampling_x, cm->subsampling_y);
 }
 
 static void scale_references(VP9_COMP *cpi) {
@@ -2561,7 +2585,7 @@
   }
 
   // Set default state for segment based loop filter update flags
-  xd->mode_ref_lf_delta_update = 0;
+  xd->lf.mode_ref_delta_update = 0;
 
 
   // Set various flags etc to special state if it is a key frame
@@ -3414,7 +3438,7 @@
   // Clear the one shot update flags for segmentation map and mode/ref loop filter deltas.
   xd->seg.update_map = 0;
   xd->seg.update_data = 0;
-  xd->mode_ref_lf_delta_update = 0;
+  xd->lf.mode_ref_delta_update = 0;
 
   // keep track of the last coded dimensions
   cm->last_width = cm->width;
@@ -3523,7 +3547,7 @@
          cpi->refresh_golden_frame ||
          cpi->refresh_alt_ref_frame ||
          cm->refresh_frame_context ||
-         mb->mode_ref_lf_delta_update ||
+         mb->lf.mode_ref_delta_update ||
          mb->seg.update_map ||
          mb->seg.update_data;
 }
@@ -3596,7 +3620,7 @@
       cpi->is_src_frame_alt_ref = 0;
 
       // TODO(agrange) This needs to vary depending on where the next ARF is.
-      cm->frames_till_alt_ref_frame = frames_to_arf;
+      cpi->frames_till_alt_ref_frame = frames_to_arf;
 
 #if CONFIG_MULTIPLE_ARF
       if (!cpi->multi_arf_enabled)
@@ -3854,7 +3878,7 @@
           double weight = 0;
 #if CONFIG_POSTPROC
           vp9_deblock(cm->frame_to_show, &cm->post_proc_buffer,
-                      cm->filter_level * 10 / 6);
+                      cpi->mb.e_mbd.lf.filter_level * 10 / 6);
 #endif
           vp9_clear_system_state();
 
@@ -3929,7 +3953,7 @@
   else {
     int ret;
 #if CONFIG_POSTPROC
-    ret = vp9_post_proc_frame(&cpi->common, dest, flags);
+    ret = vp9_post_proc_frame(&cpi->common, &cpi->mb.e_mbd.lf, dest, flags);
 #else
 
     if (cpi->common.frame_to_show) {
diff --git a/vp9/encoder/vp9_onyx_int.h b/vp9/encoder/vp9_onyx_int.h
index 19b1e3a..2c65fec 100644
--- a/vp9/encoder/vp9_onyx_int.h
+++ b/vp9/encoder/vp9_onyx_int.h
@@ -141,55 +141,52 @@
   MBGRAPH_MB_STATS *mb_stats;
 } MBGRAPH_FRAME_STATS;
 
+// This enumerator type needs to be kept aligned with the mode order in
+// const MODE_DEFINITION vp9_mode_order[MAX_MODES] used in the rd code.
 typedef enum {
-  THR_ZEROMV,
+  THR_NEARESTMV,
+  THR_NEARESTA,
+  THR_NEARESTG,
+  THR_NEWMV,
+  THR_COMP_NEARESTLA,
+  THR_NEARMV,
+  THR_COMP_NEARESTGA,
+
   THR_DC,
 
-  THR_NEARESTMV,
-  THR_NEARMV,
-
-  THR_ZEROG,
-  THR_NEARESTG,
-
-  THR_ZEROA,
-  THR_NEARESTA,
-
-  THR_NEARG,
-  THR_NEARA,
-
-  THR_V_PRED,
-  THR_H_PRED,
-  THR_D45_PRED,
-  THR_D135_PRED,
-  THR_D117_PRED,
-  THR_D153_PRED,
-  THR_D27_PRED,
-  THR_D63_PRED,
-  THR_TM,
-
-  THR_NEWMV,
   THR_NEWG,
   THR_NEWA,
+  THR_NEARA,
+
+  THR_TM,
+
+  THR_COMP_NEARLA,
+  THR_COMP_NEWLA,
+  THR_NEARG,
+  THR_COMP_NEARGA,
+  THR_COMP_NEWGA,
 
   THR_SPLITMV,
   THR_SPLITG,
   THR_SPLITA,
-
-  THR_B_PRED,
-
-  THR_COMP_ZEROLA,
-  THR_COMP_NEARESTLA,
-  THR_COMP_NEARLA,
-
-  THR_COMP_ZEROGA,
-  THR_COMP_NEARESTGA,
-  THR_COMP_NEARGA,
-
-  THR_COMP_NEWLA,
-  THR_COMP_NEWGA,
-
   THR_COMP_SPLITLA,
   THR_COMP_SPLITGA,
+
+  THR_ZEROMV,
+  THR_ZEROG,
+  THR_ZEROA,
+  THR_COMP_ZEROLA,
+  THR_COMP_ZEROGA,
+
+  THR_B_PRED,
+  THR_H_PRED,
+  THR_V_PRED,
+  THR_D135_PRED,
+  THR_D27_PRED,
+  THR_D153_PRED,
+  THR_D63_PRED,
+  THR_D117_PRED,
+  THR_D45_PRED,
 } THR_MODES;
 
 typedef enum {
@@ -313,6 +310,7 @@
   YV12_BUFFER_CONFIG *un_scaled_source;
   YV12_BUFFER_CONFIG scaled_source;
 
+  unsigned int frames_till_alt_ref_frame;
   int source_alt_ref_pending; // frame in src_buffers has been identified to be encoded as an alt ref
   int source_alt_ref_active;  // an alt ref frame has been encoded and is usable
 
@@ -395,6 +393,7 @@
   double key_frame_rate_correction_factor;
   double gf_rate_correction_factor;
 
+  unsigned int frames_since_golden;
   int frames_till_gf_update_due;      // Count down till next GF
 
   int gf_overspend_bits;            // Total bits overspent becasue of GF boost (cumulative)
diff --git a/vp9/encoder/vp9_picklpf.c b/vp9/encoder/vp9_picklpf.c
index a87d058..2b8f2cd 100644
--- a/vp9/encoder/vp9_picklpf.c
+++ b/vp9/encoder/vp9_picklpf.c
@@ -127,6 +127,7 @@
 
 void vp9_pick_filter_level(YV12_BUFFER_CONFIG *sd, VP9_COMP *cpi) {
   VP9_COMMON *cm = &cpi->common;
+  struct loopfilter *lf = &cpi->mb.e_mbd.lf;
 
   int best_err = 0;
   int filt_err = 0;
@@ -135,7 +136,8 @@
 
   int filter_step;
   int filt_high = 0;
-  int filt_mid = cm->filter_level;      // Start search at previous frame filter level
+  // Start search at previous frame filter level
+  int filt_mid = lf->filter_level;
   int filt_low = 0;
   int filt_best;
   int filt_direction = 0;
@@ -146,12 +148,12 @@
   vp8_yv12_copy_y(cm->frame_to_show, &cpi->last_frame_uf);
 
   if (cm->frame_type == KEY_FRAME)
-    cm->sharpness_level = 0;
+    lf->sharpness_level = 0;
   else
-    cm->sharpness_level = cpi->oxcf.Sharpness;
+    lf->sharpness_level = cpi->oxcf.Sharpness;
 
   // Start the search at the previous frame filter level unless it is now out of range.
-  filt_mid = cm->filter_level;
+  filt_mid = lf->filter_level;
 
   if (filt_mid < min_filter_level)
     filt_mid = min_filter_level;
@@ -179,7 +181,7 @@
       Bias = Bias * cpi->twopass.section_intra_rating / 20;
 
     // yx, bias less for large block size
-    if (cpi->common.txfm_mode != ONLY_4X4)
+    if (cpi->common.tx_mode != ONLY_4X4)
       Bias >>= 1;
 
     filt_high = ((filt_mid + filter_step) > max_filter_level) ? max_filter_level : (filt_mid + filter_step);
@@ -232,5 +234,5 @@
     }
   }
 
-  cm->filter_level = filt_best;
+  lf->filter_level = filt_best;
 }
diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c
index da5a805..d3a9529 100644
--- a/vp9/encoder/vp9_ratectrl.c
+++ b/vp9/encoder/vp9_ratectrl.c
@@ -32,46 +32,8 @@
 // Bits Per MB at different Q (Multiplied by 512)
 #define BPER_MB_NORMBITS    9
 
-// % adjustment to target kf size based on seperation from previous frame
-static const int kf_boost_seperation_adjustment[16] = {
-  30,   40,   50,   55,   60,   65,   70,   75,
-  80,   85,   90,   95,  100,  100,  100,  100,
-};
-
-static const int gf_adjust_table[101] = {
-  100,
-  115, 130, 145, 160, 175, 190, 200, 210, 220, 230,
-  240, 260, 270, 280, 290, 300, 310, 320, 330, 340,
-  350, 360, 370, 380, 390, 400, 400, 400, 400, 400,
-  400, 400, 400, 400, 400, 400, 400, 400, 400, 400,
-  400, 400, 400, 400, 400, 400, 400, 400, 400, 400,
-  400, 400, 400, 400, 400, 400, 400, 400, 400, 400,
-  400, 400, 400, 400, 400, 400, 400, 400, 400, 400,
-  400, 400, 400, 400, 400, 400, 400, 400, 400, 400,
-  400, 400, 400, 400, 400, 400, 400, 400, 400, 400,
-  400, 400, 400, 400, 400, 400, 400, 400, 400, 400,
-};
-
-static const int gf_intra_usage_adjustment[20] = {
-  125, 120, 115, 110, 105, 100,  95,  85,  80,  75,
-  70,  65,  60,  55,  50,  50,  50,  50,  50,  50,
-};
-
-static const int gf_interval_table[101] = {
-  7,
-  7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-  7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-  7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-  8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-  8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-  9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
-  9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
-  10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
-  10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
-  11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
-};
-
-static const unsigned int prior_key_frame_weight[KEY_FRAME_CONTEXT] = { 1, 2, 3, 4, 5 };
+static const unsigned int prior_key_frame_weight[KEY_FRAME_CONTEXT] =
+    { 1, 2, 3, 4, 5 };
 
 // These functions use formulaic calculations to make playing with the
 // quantizer tables easier. If necessary they can be replaced by lookup
@@ -137,8 +99,8 @@
   vpx_memcpy(cpi->coding_context.last_frame_seg_map_copy,
              cm->last_frame_seg_map, (cm->mi_rows * cm->mi_cols));
 
-  vp9_copy(cc->last_ref_lf_deltas, xd->last_ref_lf_deltas);
-  vp9_copy(cc->last_mode_lf_deltas, xd->last_mode_lf_deltas);
+  vp9_copy(cc->last_ref_lf_deltas, xd->lf.last_ref_deltas);
+  vp9_copy(cc->last_mode_lf_deltas, xd->lf.last_mode_deltas);
 
   vp9_copy(cc->coef_probs, cm->fc.coef_probs);
   vp9_copy(cc->switchable_interp_prob, cm->fc.switchable_interp_prob);
@@ -176,8 +138,8 @@
              cpi->coding_context.last_frame_seg_map_copy,
              (cm->mi_rows * cm->mi_cols));
 
-  vp9_copy(xd->last_ref_lf_deltas, cc->last_ref_lf_deltas);
-  vp9_copy(xd->last_mode_lf_deltas, cc->last_mode_lf_deltas);
+  vp9_copy(xd->lf.last_ref_deltas, cc->last_ref_lf_deltas);
+  vp9_copy(xd->lf.last_mode_deltas, cc->last_mode_lf_deltas);
 
   vp9_copy(cm->fc.coef_probs, cc->coef_probs);
   vp9_copy(cm->fc.switchable_interp_prob, cc->switchable_interp_prob);
diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c
index 6df1701..775e107 100644
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -53,56 +53,49 @@
 #define SPLITMV 0x10000
 
 const MODE_DEFINITION vp9_mode_order[MAX_MODES] = {
-  {ZEROMV,    LAST_FRAME,   NONE},
+  {NEARESTMV, LAST_FRAME,   NONE},
+  {NEARESTMV, ALTREF_FRAME, NONE},
+  {NEARESTMV, GOLDEN_FRAME, NONE},
+  {NEWMV,     LAST_FRAME,   NONE},
+  {NEARESTMV, LAST_FRAME,   ALTREF_FRAME},
+  {NEARMV,    LAST_FRAME,   NONE},
+  {NEARESTMV, GOLDEN_FRAME, ALTREF_FRAME},
+
   {DC_PRED,   INTRA_FRAME,  NONE},
 
-  {NEARESTMV, LAST_FRAME,   NONE},
-  {NEARMV,    LAST_FRAME,   NONE},
-
-  {ZEROMV,    GOLDEN_FRAME, NONE},
-  {NEARESTMV, GOLDEN_FRAME, NONE},
-
-  {ZEROMV,    ALTREF_FRAME, NONE},
-  {NEARESTMV, ALTREF_FRAME, NONE},
-
-  {NEARMV,    GOLDEN_FRAME, NONE},
+  {NEWMV,     GOLDEN_FRAME, NONE},
+  {NEWMV,     ALTREF_FRAME, NONE},
   {NEARMV,    ALTREF_FRAME, NONE},
 
-  {V_PRED,    INTRA_FRAME,  NONE},
-  {H_PRED,    INTRA_FRAME,  NONE},
-  {D45_PRED,  INTRA_FRAME,  NONE},
-  {D135_PRED, INTRA_FRAME,  NONE},
-  {D117_PRED, INTRA_FRAME,  NONE},
-  {D153_PRED, INTRA_FRAME,  NONE},
-  {D27_PRED,  INTRA_FRAME,  NONE},
-  {D63_PRED,  INTRA_FRAME,  NONE},
-
   {TM_PRED,   INTRA_FRAME,  NONE},
 
-  {NEWMV,     LAST_FRAME,   NONE},
-  {NEWMV,     GOLDEN_FRAME, NONE},
-  {NEWMV,     ALTREF_FRAME, NONE},
+  {NEARMV,    LAST_FRAME,   ALTREF_FRAME},
+  {NEWMV,     LAST_FRAME,   ALTREF_FRAME},
+  {NEARMV,    GOLDEN_FRAME, NONE},
+  {NEARMV,    GOLDEN_FRAME, ALTREF_FRAME},
+  {NEWMV,     GOLDEN_FRAME, ALTREF_FRAME},
 
   {SPLITMV,   LAST_FRAME,   NONE},
   {SPLITMV,   GOLDEN_FRAME, NONE},
   {SPLITMV,   ALTREF_FRAME, NONE},
-
-  {I4X4_PRED, INTRA_FRAME,  NONE},
-
-  /* compound prediction modes */
-  {ZEROMV,    LAST_FRAME,   ALTREF_FRAME},
-  {NEARESTMV, LAST_FRAME,   ALTREF_FRAME},
-  {NEARMV,    LAST_FRAME,   ALTREF_FRAME},
-
-  {ZEROMV,    GOLDEN_FRAME, ALTREF_FRAME},
-  {NEARESTMV, GOLDEN_FRAME, ALTREF_FRAME},
-  {NEARMV,    GOLDEN_FRAME, ALTREF_FRAME},
-
-  {NEWMV,     LAST_FRAME,   ALTREF_FRAME},
-  {NEWMV,     GOLDEN_FRAME, ALTREF_FRAME},
-
   {SPLITMV,   LAST_FRAME,   ALTREF_FRAME},
   {SPLITMV,   GOLDEN_FRAME, ALTREF_FRAME},
+
+  {ZEROMV,    LAST_FRAME,   NONE},
+  {ZEROMV,    GOLDEN_FRAME, NONE},
+  {ZEROMV,    ALTREF_FRAME, NONE},
+  {ZEROMV,    LAST_FRAME,   ALTREF_FRAME},
+  {ZEROMV,    GOLDEN_FRAME, ALTREF_FRAME},
+
+  {I4X4_PRED, INTRA_FRAME,  NONE},
+  {H_PRED,    INTRA_FRAME,  NONE},
+  {V_PRED,    INTRA_FRAME,  NONE},
+  {D135_PRED, INTRA_FRAME,  NONE},
+  {D27_PRED,  INTRA_FRAME,  NONE},
+  {D153_PRED, INTRA_FRAME,  NONE},
+  {D63_PRED,  INTRA_FRAME,  NONE},
+  {D117_PRED, INTRA_FRAME,  NONE},
+  {D45_PRED,  INTRA_FRAME,  NONE},
 };
 
 // The baseline rd thresholds for breaking out of the rd loop for
@@ -282,9 +275,9 @@
 
       for (m = NEARESTMV; m < MB_MODE_COUNT; m++)
         cpi->mb.inter_mode_cost[i][m - NEARESTMV] =
-            cost_token(vp9_sb_mv_ref_tree,
+            cost_token(vp9_inter_mode_tree,
                        cpi->common.fc.inter_mode_probs[i],
-                       vp9_sb_mv_ref_encoding_array - NEARESTMV + m);
+                       vp9_inter_mode_encodings - NEARESTMV + m);
     }
   }
 }
@@ -776,10 +769,14 @@
   MACROBLOCK *const x = args->x;
   MACROBLOCKD *const xd = &x->e_mbd;
   struct encode_b_args encode_args = {args->cm, x, NULL};
+  int64_t rd1, rd2, rd;
 
   if (args->skip)
     return;
-  if (RDCOST(x->rdmult, x->rddiv, args->rate, args->dist) > args->best_rd) {
+  rd1 = RDCOST(x->rdmult, x->rddiv, args->rate, args->dist);
+  rd2 = RDCOST(x->rdmult, x->rddiv, 0, args->sse);
+  rd = MIN(rd1, rd2);
+  if (rd > args->best_rd) {
     args->skip = 1;
     args->rate = INT_MAX;
     args->dist = INT64_MAX;
@@ -830,15 +827,15 @@
   MACROBLOCKD *const xd = &x->e_mbd;
   MB_MODE_INFO *const mbmi = &xd->mode_info_context->mbmi;
   if (max_txfm_size == TX_32X32 &&
-      (cm->txfm_mode == ALLOW_32X32 ||
-       cm->txfm_mode == TX_MODE_SELECT)) {
+      (cm->tx_mode == ALLOW_32X32 ||
+       cm->tx_mode == TX_MODE_SELECT)) {
     mbmi->txfm_size = TX_32X32;
   } else if (max_txfm_size >= TX_16X16 &&
-             (cm->txfm_mode == ALLOW_16X16 ||
-              cm->txfm_mode == ALLOW_32X32 ||
-              cm->txfm_mode == TX_MODE_SELECT)) {
+             (cm->tx_mode == ALLOW_16X16 ||
+              cm->tx_mode == ALLOW_32X32 ||
+              cm->tx_mode == TX_MODE_SELECT)) {
     mbmi->txfm_size = TX_16X16;
-  } else if (cm->txfm_mode != ONLY_4X4) {
+  } else if (cm->tx_mode != ONLY_4X4) {
     mbmi->txfm_size = TX_8X8;
   } else {
     mbmi->txfm_size = TX_4X4;
@@ -865,7 +862,7 @@
   int n, m;
   int s0, s1;
 
-  const vp9_prob *tx_probs = vp9_get_pred_probs_tx_size(cm, xd);
+  const vp9_prob *tx_probs = vp9_get_pred_probs_tx_size(xd, &cm->fc.tx_probs);
 
   for (n = TX_4X4; n <= max_txfm_size; n++) {
     r[n][1] = r[n][0];
@@ -897,29 +894,29 @@
   }
 
   if (max_txfm_size == TX_32X32 &&
-      (cm->txfm_mode == ALLOW_32X32 ||
-       (cm->txfm_mode == TX_MODE_SELECT &&
+      (cm->tx_mode == ALLOW_32X32 ||
+       (cm->tx_mode == TX_MODE_SELECT &&
         rd[TX_32X32][1] < rd[TX_16X16][1] && rd[TX_32X32][1] < rd[TX_8X8][1] &&
         rd[TX_32X32][1] < rd[TX_4X4][1]))) {
     mbmi->txfm_size = TX_32X32;
   } else if (max_txfm_size >= TX_16X16 &&
-             (cm->txfm_mode == ALLOW_16X16 ||
-              cm->txfm_mode == ALLOW_32X32 ||
-              (cm->txfm_mode == TX_MODE_SELECT &&
+             (cm->tx_mode == ALLOW_16X16 ||
+              cm->tx_mode == ALLOW_32X32 ||
+              (cm->tx_mode == TX_MODE_SELECT &&
                rd[TX_16X16][1] < rd[TX_8X8][1] &&
                rd[TX_16X16][1] < rd[TX_4X4][1]))) {
     mbmi->txfm_size = TX_16X16;
-  } else if (cm->txfm_mode == ALLOW_8X8 ||
-             cm->txfm_mode == ALLOW_16X16 ||
-             cm->txfm_mode == ALLOW_32X32 ||
-           (cm->txfm_mode == TX_MODE_SELECT && rd[TX_8X8][1] < rd[TX_4X4][1])) {
+  } else if (cm->tx_mode == ALLOW_8X8 ||
+             cm->tx_mode == ALLOW_16X16 ||
+             cm->tx_mode == ALLOW_32X32 ||
+           (cm->tx_mode == TX_MODE_SELECT && rd[TX_8X8][1] < rd[TX_4X4][1])) {
     mbmi->txfm_size = TX_8X8;
   } else {
     mbmi->txfm_size = TX_4X4;
   }
 
   *distortion = d[mbmi->txfm_size];
-  *rate       = r[mbmi->txfm_size][cm->txfm_mode == TX_MODE_SELECT];
+  *rate       = r[mbmi->txfm_size][cm->tx_mode == TX_MODE_SELECT];
   *skip       = s[mbmi->txfm_size];
 
   txfm_cache[ONLY_4X4] = rd[TX_4X4][0];
@@ -972,7 +969,7 @@
   double scale_rd[TX_SIZE_MAX_SB] = {1.73, 1.44, 1.20, 1.00};
   // double scale_r[TX_SIZE_MAX_SB] = {2.82, 2.00, 1.41, 1.00};
 
-  const vp9_prob *tx_probs = vp9_get_pred_probs_tx_size(cm, xd);
+  const vp9_prob *tx_probs = vp9_get_pred_probs_tx_size(xd, &cm->fc.tx_probs);
 
   // for (n = TX_4X4; n <= max_txfm_size; n++)
   //   r[n][0] = (r[n][0] * scale_r[n]);
@@ -1005,23 +1002,23 @@
   }
 
   if (max_txfm_size == TX_32X32 &&
-      (cm->txfm_mode == ALLOW_32X32 ||
-       (cm->txfm_mode == TX_MODE_SELECT &&
+      (cm->tx_mode == ALLOW_32X32 ||
+       (cm->tx_mode == TX_MODE_SELECT &&
         rd[TX_32X32][1] <= rd[TX_16X16][1] &&
         rd[TX_32X32][1] <= rd[TX_8X8][1] &&
         rd[TX_32X32][1] <= rd[TX_4X4][1]))) {
     mbmi->txfm_size = TX_32X32;
   } else if (max_txfm_size >= TX_16X16 &&
-             (cm->txfm_mode == ALLOW_16X16 ||
-              cm->txfm_mode == ALLOW_32X32 ||
-              (cm->txfm_mode == TX_MODE_SELECT &&
+             (cm->tx_mode == ALLOW_16X16 ||
+              cm->tx_mode == ALLOW_32X32 ||
+              (cm->tx_mode == TX_MODE_SELECT &&
                rd[TX_16X16][1] <= rd[TX_8X8][1] &&
                rd[TX_16X16][1] <= rd[TX_4X4][1]))) {
     mbmi->txfm_size = TX_16X16;
-  } else if (cm->txfm_mode == ALLOW_8X8 ||
-             cm->txfm_mode == ALLOW_16X16 ||
-             cm->txfm_mode == ALLOW_32X32 ||
-           (cm->txfm_mode == TX_MODE_SELECT &&
+  } else if (cm->tx_mode == ALLOW_8X8 ||
+             cm->tx_mode == ALLOW_16X16 ||
+             cm->tx_mode == ALLOW_32X32 ||
+           (cm->tx_mode == TX_MODE_SELECT &&
             rd[TX_8X8][1] <= rd[TX_4X4][1])) {
     mbmi->txfm_size = TX_8X8;
   } else {
@@ -1036,7 +1033,7 @@
                              bs, mbmi->txfm_size);
   } else {
     *distortion = d[mbmi->txfm_size];
-    *rate       = r[mbmi->txfm_size][cm->txfm_mode == TX_MODE_SELECT];
+    *rate       = r[mbmi->txfm_size][cm->tx_mode == TX_MODE_SELECT];
     *skip       = s[mbmi->txfm_size];
   }
 
@@ -1342,7 +1339,7 @@
       int64_t UNINITIALIZED_IS_SAFE(d);
       i = idy * 2 + idx;
 
-      if (xd->frame_type == KEY_FRAME) {
+      if (cpi->common.frame_type == KEY_FRAME) {
         const MB_PREDICTION_MODE A = above_block_mode(mic, i, mis);
         const MB_PREDICTION_MODE L = (xd->left_available || idx) ?
                                      left_block_mode(mic, i) : DC_PRED;
@@ -1364,13 +1361,10 @@
         mic->bmi[i + j].as_mode = best_mode;
 
       if (total_rd >= best_rd)
-        break;
+        return INT64_MAX;
     }
   }
 
-  if (total_rd >= best_rd)
-    return INT64_MAX;
-
   *Rate = cost;
   *rate_y = tot_rate_y;
   *Distortion = distortion;
@@ -1383,22 +1377,17 @@
                                       int *rate, int *rate_tokenonly,
                                       int64_t *distortion, int *skippable,
                                       BLOCK_SIZE_TYPE bsize,
-                                      int64_t txfm_cache[NB_TXFM_MODES]) {
+                                      int64_t txfm_cache[NB_TXFM_MODES],
+                                      int64_t best_rd) {
   MB_PREDICTION_MODE mode;
   MB_PREDICTION_MODE UNINITIALIZED_IS_SAFE(mode_selected);
   MACROBLOCKD *const xd = &x->e_mbd;
   int this_rate, this_rate_tokenonly, s;
-  int64_t this_distortion;
-  int64_t best_rd = INT64_MAX, this_rd;
+  int64_t this_distortion, this_rd;
   TX_SIZE UNINITIALIZED_IS_SAFE(best_tx);
   int i;
   int *bmode_costs = x->mbmode_cost;
 
-  if (bsize < BLOCK_SIZE_SB8X8) {
-    x->e_mbd.mode_info_context->mbmi.txfm_size = TX_4X4;
-    return best_rd;
-  }
-
   if (cpi->sf.tx_size_search_method == USE_FULL_RD) {
     for (i = 0; i < NB_TXFM_MODES; i++)
       txfm_cache[i] = INT64_MAX;
@@ -1441,7 +1430,7 @@
     if (cpi->sf.tx_size_search_method == USE_FULL_RD && this_rd < INT64_MAX) {
       for (i = 0; i < NB_TXFM_MODES; i++) {
         int64_t adj_rd = this_rd + local_txfm_cache[i] -
-            local_txfm_cache[cpi->common.txfm_mode];
+            local_txfm_cache[cpi->common.tx_mode];
         if (adj_rd < txfm_cache[i]) {
           txfm_cache[i] = adj_rd;
         }
@@ -1492,13 +1481,12 @@
                                        int64_t *distortion, int *skippable,
                                        BLOCK_SIZE_TYPE bsize) {
   MB_PREDICTION_MODE mode;
-  MB_PREDICTION_MODE last_mode;
   MB_PREDICTION_MODE UNINITIALIZED_IS_SAFE(mode_selected);
   int64_t best_rd = INT64_MAX, this_rd;
   int this_rate_tokenonly, this_rate, s;
   int64_t this_distortion;
 
-  last_mode = bsize <= BLOCK_SIZE_SB8X8 ?
+  MB_PREDICTION_MODE last_mode = bsize <= BLOCK_SIZE_SB8X8 ?
               TM_PRED : cpi->sf.last_chroma_intra_mode;
 
   for (mode = DC_PRED; mode <= last_mode; mode++) {
@@ -1506,7 +1494,7 @@
     super_block_uvrd(&cpi->common, x, &this_rate_tokenonly,
                      &this_distortion, &s, NULL, bsize);
     this_rate = this_rate_tokenonly +
-                x->intra_uv_mode_cost[x->e_mbd.frame_type][mode];
+                x->intra_uv_mode_cost[cpi->common.frame_type][mode];
     this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
 
     if (this_rd < best_rd) {
@@ -1534,7 +1522,7 @@
   super_block_uvrd(&cpi->common, x, rate_tokenonly,
                    distortion, skippable, NULL, bsize);
   *rate = *rate_tokenonly +
-          x->intra_uv_mode_cost[x->e_mbd.frame_type][DC_PRED];
+          x->intra_uv_mode_cost[cpi->common.frame_type][DC_PRED];
   this_rd = RDCOST(x->rdmult, x->rddiv, *rate, *distortion);
 
   x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED;
@@ -1542,6 +1530,29 @@
   return this_rd;
 }
 
+static void choose_intra_uv_mode(VP9_COMP *cpi, BLOCK_SIZE_TYPE bsize,
+                                 int *rate_uv, int *rate_uv_tokenonly,
+                                 int64_t *dist_uv, int *skip_uv,
+                                 MB_PREDICTION_MODE *mode_uv) {
+  MACROBLOCK *const x = &cpi->mb;
+
+  // Use an estimated rd for uv_intra based on DC_PRED if the
+  // appropriate speed flag is set.
+  if (cpi->sf.use_uv_intra_rd_estimate) {
+    rd_sbuv_dcpred(cpi, x, rate_uv, rate_uv_tokenonly, dist_uv, skip_uv,
+                   (bsize < BLOCK_SIZE_SB8X8) ? BLOCK_SIZE_SB8X8 :
+                   bsize);
+  // Else do a proper rd search for each possible transform size that may
+  // be considered in the main rd loop.
+  } else {
+    rd_pick_intra_sbuv_mode(cpi, x,
+                            rate_uv, rate_uv_tokenonly, dist_uv, skip_uv,
+                            (bsize < BLOCK_SIZE_SB8X8) ? BLOCK_SIZE_SB8X8
+                            : bsize);
+  }
+  *mode_uv = x->e_mbd.mode_info_context->mbmi.uv_mode;
+}
+
 static int cost_mv_ref(VP9_COMP *cpi, MB_PREDICTION_MODE mode,
                        int mode_context) {
   MACROBLOCK *const x = &cpi->mb;
@@ -1637,18 +1648,10 @@
     mic->bmi[i].as_mv[1].as_int = this_second_mv->as_int;
 
   x->partition_info->bmi[i].mode = m;
-  x->partition_info->bmi[i].mv.as_int = this_mv->as_int;
-  if (mbmi->ref_frame[1] > 0)
-    x->partition_info->bmi[i].second_mv.as_int = this_second_mv->as_int;
-  for (idy = 0; idy < bh; ++idy) {
-    for (idx = 0; idx < bw; ++idx) {
+  for (idy = 0; idy < bh; ++idy)
+    for (idx = 0; idx < bw; ++idx)
       vpx_memcpy(&mic->bmi[i + idy * 2 + idx],
                  &mic->bmi[i], sizeof(mic->bmi[i]));
-      vpx_memcpy(&x->partition_info->bmi[i + idy * 2 + idx],
-                 &x->partition_info->bmi[i],
-                 sizeof(x->partition_info->bmi[i]));
-    }
-  }
 
   cost += thismvcost;
   return cost;
@@ -1712,12 +1715,10 @@
                      src, src_stride,
                      dst, xd->plane[0].dst.stride);
 
-  *labelyrate = 0;
-  *distortion = 0;
   k = i;
   for (idy = 0; idy < bh / 4; ++idy) {
     for (idx = 0; idx < bw / 4; ++idx) {
-      int64_t ssz;
+      int64_t ssz, rd, rd1, rd2;
 
       k += (idy * 2 + idx);
       src_diff = raster_block_offset_int16(xd, BLOCK_SIZE_SB8X8, 0, k,
@@ -1732,17 +1733,33 @@
       thisrate += cost_coeffs(cm, x, 0, k, PLANE_TYPE_Y_WITH_DC,
                               ta + (k & 1),
                               tl + (k >> 1), TX_4X4, 16);
+      rd1 = RDCOST(x->rdmult, x->rddiv, thisrate, thisdistortion >> 2);
+      rd2 = RDCOST(x->rdmult, x->rddiv, 0, thissse >> 2);
+      rd = MIN(rd1, rd2);
+      if (rd >= best_yrd)
+        return INT64_MAX;
     }
   }
-  *distortion += thisdistortion;
-  *labelyrate += thisrate;
+  *distortion = thisdistortion >> 2;
+  *labelyrate = thisrate;
   *sse = thissse >> 2;
 
-  *distortion >>= 2;
   return RDCOST(x->rdmult, x->rddiv, *labelyrate, *distortion);
 }
 
 typedef struct {
+  int eobs;
+  int brate;
+  int byrate;
+  int64_t bdist;
+  int64_t bsse;
+  int64_t brdcost;
+  int_mv mvs[2];
+  ENTROPY_CONTEXT ta[2];
+  ENTROPY_CONTEXT tl[2];
+} SEG_RDSTAT;
+
+typedef struct {
   int_mv *ref_mv, *second_ref_mv;
   int_mv mvp;
 
@@ -1752,8 +1769,7 @@
   int64_t sse;
   int segment_yrate;
   MB_PREDICTION_MODE modes[4];
-  int_mv mvs[4], second_mvs[4];
-  int eobs[4];
+  SEG_RDSTAT rdstat[4][VP9_INTER_MODES];
   int mvthresh;
 } BEST_SEG_INFO;
 
@@ -1794,24 +1810,26 @@
 }
 
 static void rd_check_segment_txsize(VP9_COMP *cpi, MACROBLOCK *x,
-                                    BEST_SEG_INFO *bsi,
+                                    BEST_SEG_INFO *bsi_buf, int filter_idx,
                                     int_mv seg_mvs[4][MAX_REF_FRAMES],
                                     int mi_row, int mi_col) {
-  int i, j, br = 0, rate = 0, sbr = 0, idx, idy;
-  int64_t bd = 0, sbd = 0, subblock_sse = 0, block_sse = 0;
+  int i, j, br = 0, idx, idy;
+  int64_t bd = 0, block_sse = 0;
   MB_PREDICTION_MODE this_mode;
-  MB_MODE_INFO * mbmi = &x->e_mbd.mode_info_context->mbmi;
+  MODE_INFO *mi = x->e_mbd.mode_info_context;
+  MB_MODE_INFO *const mbmi = &mi->mbmi;
   const int label_count = 4;
   int64_t this_segment_rd = 0;
   int label_mv_thresh;
   int segmentyrate = 0;
-  int best_eobs[4] = { 0 };
   BLOCK_SIZE_TYPE bsize = mbmi->sb_type;
   int bwl = b_width_log2(bsize), bw = 1 << bwl;
   int bhl = b_height_log2(bsize), bh = 1 << bhl;
   vp9_variance_fn_ptr_t *v_fn_ptr;
-  ENTROPY_CONTEXT t_above[4], t_left[4];
-  ENTROPY_CONTEXT t_above_b[4], t_left_b[4];
+  ENTROPY_CONTEXT t_above[2], t_left[2];
+  BEST_SEG_INFO *bsi = bsi_buf + filter_idx;
+  int mode_idx;
+  int subpelmv = 1, have_ref = 0;
 
   vpx_memcpy(t_above, x->e_mbd.plane[0].above_context, sizeof(t_above));
   vpx_memcpy(t_left, x->e_mbd.plane[0].left_context, sizeof(t_left));
@@ -1831,9 +1849,8 @@
       // loop for 4x4/4x8/8x4 block coding. to be replaced with new rd loop
       int_mv mode_mv[MB_MODE_COUNT], second_mode_mv[MB_MODE_COUNT];
       int_mv frame_mv[MB_MODE_COUNT][MAX_REF_FRAMES];
-      int64_t best_label_rd = INT64_MAX;
       MB_PREDICTION_MODE mode_selected = ZEROMV;
-      int bestlabelyrate = 0;
+      int64_t best_rd = INT64_MAX;
       i = idy * 2 + idx;
 
       frame_mv[ZEROMV][mbmi->ref_frame[0]].as_int = 0;
@@ -1850,17 +1867,54 @@
 
       // search for the best motion vector on this segment
       for (this_mode = NEARESTMV; this_mode <= NEWMV; ++this_mode) {
-        int64_t this_rd;
-        int64_t distortion, sse;
-        int labelyrate;
-        ENTROPY_CONTEXT t_above_s[4], t_left_s[4];
         const struct buf_2d orig_src = x->plane[0].src;
         struct buf_2d orig_pre[2];
 
-        vpx_memcpy(orig_pre, x->e_mbd.plane[0].pre, sizeof(orig_pre));
+        mode_idx = inter_mode_offset(this_mode);
+        bsi->rdstat[i][mode_idx].brdcost = INT64_MAX;
 
-        vpx_memcpy(t_above_s, t_above, sizeof(t_above_s));
-        vpx_memcpy(t_left_s, t_left, sizeof(t_left_s));
+        // if we're near/nearest and mv == 0,0, compare to zeromv
+        if ((this_mode == NEARMV || this_mode == NEARESTMV ||
+             this_mode == ZEROMV) &&
+            frame_mv[this_mode][mbmi->ref_frame[0]].as_int == 0 &&
+            (mbmi->ref_frame[1] <= 0 ||
+             frame_mv[this_mode][mbmi->ref_frame[1]].as_int == 0)) {
+          int rfc = mbmi->mb_mode_context[mbmi->ref_frame[0]];
+          int c1 = cost_mv_ref(cpi, NEARMV, rfc);
+          int c2 = cost_mv_ref(cpi, NEARESTMV, rfc);
+          int c3 = cost_mv_ref(cpi, ZEROMV, rfc);
+
+          if (this_mode == NEARMV) {
+            if (c1 > c3)
+              continue;
+          } else if (this_mode == NEARESTMV) {
+            if (c2 > c3)
+              continue;
+          } else {
+            assert(this_mode == ZEROMV);
+            if (mbmi->ref_frame[1] <= 0) {
+              if ((c3 >= c2 &&
+                   frame_mv[NEARESTMV][mbmi->ref_frame[0]].as_int == 0) ||
+                  (c3 >= c1 &&
+                   frame_mv[NEARMV][mbmi->ref_frame[0]].as_int == 0))
+                continue;
+            } else {
+              if ((c3 >= c2 &&
+                   frame_mv[NEARESTMV][mbmi->ref_frame[0]].as_int == 0 &&
+                   frame_mv[NEARESTMV][mbmi->ref_frame[1]].as_int == 0) ||
+                  (c3 >= c1 &&
+                   frame_mv[NEARMV][mbmi->ref_frame[0]].as_int == 0 &&
+                   frame_mv[NEARMV][mbmi->ref_frame[1]].as_int == 0))
+                continue;
+            }
+          }
+        }
+
+        vpx_memcpy(orig_pre, x->e_mbd.plane[0].pre, sizeof(orig_pre));
+        vpx_memcpy(bsi->rdstat[i][mode_idx].ta, t_above,
+                   sizeof(bsi->rdstat[i][mode_idx].ta));
+        vpx_memcpy(bsi->rdstat[i][mode_idx].tl, t_left,
+                   sizeof(bsi->rdstat[i][mode_idx].tl));
 
         // motion search for newmv (single predictor case only)
         if (mbmi->ref_frame[1] <= 0 && this_mode == NEWMV &&
@@ -1873,7 +1927,7 @@
 
           /* Is the best so far sufficiently good that we cant justify doing
            * and new motion search. */
-          if (best_label_rd < label_mv_thresh)
+          if (best_rd < label_mv_thresh)
             break;
 
           if (cpi->compressor_speed) {
@@ -1960,57 +2014,122 @@
           mi_buf_restore(x, orig_src, orig_pre);
         }
 
-        rate = labels2mode(x, i, this_mode, &mode_mv[this_mode],
-                           &second_mode_mv[this_mode], frame_mv, seg_mvs[i],
-                           bsi->ref_mv, bsi->second_ref_mv, x->nmvjointcost,
-                           x->mvcost, cpi);
+        bsi->rdstat[i][mode_idx].brate =
+            labels2mode(x, i, this_mode, &mode_mv[this_mode],
+                        &second_mode_mv[this_mode], frame_mv, seg_mvs[i],
+                        bsi->ref_mv, bsi->second_ref_mv, x->nmvjointcost,
+                        x->mvcost, cpi);
+
+        bsi->rdstat[i][mode_idx].mvs[0].as_int = mode_mv[this_mode].as_int;
+        if (bw > 1)
+          bsi->rdstat[i + 1][mode_idx].mvs[0].as_int =
+              mode_mv[this_mode].as_int;
+        if (bh > 1)
+          bsi->rdstat[i + 2][mode_idx].mvs[0].as_int =
+              mode_mv[this_mode].as_int;
+        if (mbmi->ref_frame[1] > 0) {
+          bsi->rdstat[i][mode_idx].mvs[1].as_int =
+              second_mode_mv[this_mode].as_int;
+          if (bw > 1)
+            bsi->rdstat[i + 1][mode_idx].mvs[1].as_int =
+                second_mode_mv[this_mode].as_int;
+          if (bh > 1)
+            bsi->rdstat[i + 2][mode_idx].mvs[1].as_int =
+                second_mode_mv[this_mode].as_int;
+        }
 
         // Trap vectors that reach beyond the UMV borders
-        if (((mode_mv[this_mode].as_mv.row >> 3) < x->mv_row_min) ||
-            ((mode_mv[this_mode].as_mv.row >> 3) > x->mv_row_max) ||
-            ((mode_mv[this_mode].as_mv.col >> 3) < x->mv_col_min) ||
-            ((mode_mv[this_mode].as_mv.col >> 3) > x->mv_col_max)) {
+        if (mv_check_bounds(x, &mode_mv[this_mode]))
           continue;
-        }
         if (mbmi->ref_frame[1] > 0 &&
             mv_check_bounds(x, &second_mode_mv[this_mode]))
           continue;
 
-        this_rd = encode_inter_mb_segment(cpi, x,
-                                          bsi->segment_rd - this_segment_rd,
-                                          i, &labelyrate, &distortion, &sse,
-                                          t_above_s, t_left_s);
-        this_rd += RDCOST(x->rdmult, x->rddiv, rate, 0);
-        rate += labelyrate;
+        if (filter_idx > 0) {
+          BEST_SEG_INFO *ref_bsi = bsi_buf;
+          subpelmv = (mode_mv[this_mode].as_mv.row & 0x0f) ||
+                     (mode_mv[this_mode].as_mv.col & 0x0f);
+          have_ref = mode_mv[this_mode].as_int ==
+                     ref_bsi->rdstat[i][mode_idx].mvs[0].as_int;
+          if (mbmi->ref_frame[1] > 0) {
+            subpelmv |= (second_mode_mv[this_mode].as_mv.row & 0x0f) ||
+                        (second_mode_mv[this_mode].as_mv.col & 0x0f);
+            have_ref  &= second_mode_mv[this_mode].as_int ==
+                         ref_bsi->rdstat[i][mode_idx].mvs[1].as_int;
+          }
 
-        if (this_rd < best_label_rd) {
-          sbr = rate;
-          sbd = distortion;
-          subblock_sse = sse;
-          bestlabelyrate = labelyrate;
+          if (filter_idx > 1 && !subpelmv && !have_ref) {
+            ref_bsi = bsi_buf + 1;
+            have_ref = mode_mv[this_mode].as_int ==
+                       ref_bsi->rdstat[i][mode_idx].mvs[0].as_int;
+            if (mbmi->ref_frame[1] > 0) {
+              have_ref  &= second_mode_mv[this_mode].as_int ==
+                           ref_bsi->rdstat[i][mode_idx].mvs[1].as_int;
+            }
+          }
+
+          if (!subpelmv && have_ref &&
+              ref_bsi->rdstat[i][mode_idx].brdcost < INT64_MAX) {
+            vpx_memcpy(&bsi->rdstat[i][mode_idx], &ref_bsi->rdstat[i][mode_idx],
+                       sizeof(SEG_RDSTAT));
+            if (bsi->rdstat[i][mode_idx].brdcost < best_rd) {
+              mode_selected = this_mode;
+              best_rd = bsi->rdstat[i][mode_idx].brdcost;
+            }
+            continue;
+          }
+        }
+
+        bsi->rdstat[i][mode_idx].brdcost =
+            encode_inter_mb_segment(cpi, x,
+                                    bsi->segment_rd - this_segment_rd, i,
+                                    &bsi->rdstat[i][mode_idx].byrate,
+                                    &bsi->rdstat[i][mode_idx].bdist,
+                                    &bsi->rdstat[i][mode_idx].bsse,
+                                    bsi->rdstat[i][mode_idx].ta,
+                                    bsi->rdstat[i][mode_idx].tl);
+        if (bsi->rdstat[i][mode_idx].brdcost < INT64_MAX) {
+          bsi->rdstat[i][mode_idx].brdcost += RDCOST(x->rdmult, x->rddiv,
+                                            bsi->rdstat[i][mode_idx].brate, 0);
+          bsi->rdstat[i][mode_idx].brate += bsi->rdstat[i][mode_idx].byrate;
+          bsi->rdstat[i][mode_idx].eobs = x->e_mbd.plane[0].eobs[i];
+        }
+
+        if (bsi->rdstat[i][mode_idx].brdcost < best_rd) {
           mode_selected = this_mode;
-          best_label_rd = this_rd;
-          best_eobs[i] = x->e_mbd.plane[0].eobs[i];
-          vpx_memcpy(t_above_b, t_above_s, sizeof(t_above_s));
-          vpx_memcpy(t_left_b, t_left_s, sizeof(t_left_s));
+          best_rd = bsi->rdstat[i][mode_idx].brdcost;
         }
       } /*for each 4x4 mode*/
 
-      vpx_memcpy(t_above, t_above_b, sizeof(t_above));
-      vpx_memcpy(t_left, t_left_b, sizeof(t_left));
+      if (best_rd == INT64_MAX) {
+        int iy, midx;
+        for (iy = i + 1; iy < 4; ++iy)
+          for (midx = 0; midx < VP9_INTER_MODES; ++midx)
+            bsi->rdstat[iy][midx].brdcost = INT64_MAX;
+        bsi->segment_rd = INT64_MAX;
+        return;
+      }
+
+      mode_idx = inter_mode_offset(mode_selected);
+      vpx_memcpy(t_above, bsi->rdstat[i][mode_idx].ta, sizeof(t_above));
+      vpx_memcpy(t_left, bsi->rdstat[i][mode_idx].tl, sizeof(t_left));
 
       labels2mode(x, i, mode_selected, &mode_mv[mode_selected],
                   &second_mode_mv[mode_selected], frame_mv, seg_mvs[i],
                   bsi->ref_mv, bsi->second_ref_mv, x->nmvjointcost,
                   x->mvcost, cpi);
 
-      br += sbr;
-      bd += sbd;
-      block_sse += subblock_sse;
-      segmentyrate += bestlabelyrate;
-      this_segment_rd += best_label_rd;
+      br += bsi->rdstat[i][mode_idx].brate;
+      bd += bsi->rdstat[i][mode_idx].bdist;
+      block_sse += bsi->rdstat[i][mode_idx].bsse;
+      segmentyrate += bsi->rdstat[i][mode_idx].byrate;
+      this_segment_rd += bsi->rdstat[i][mode_idx].brdcost;
 
       if (this_segment_rd > bsi->segment_rd) {
+        int iy, midx;
+        for (iy = i + 1; iy < 4; ++iy)
+          for (midx = 0; midx < VP9_INTER_MODES; ++midx)
+            bsi->rdstat[iy][midx].brdcost = INT64_MAX;
         bsi->segment_rd = INT64_MAX;
         return;
       }
@@ -2032,14 +2151,9 @@
   bsi->segment_rd = this_segment_rd;
   bsi->sse = block_sse;
 
-  // store everything needed to come back to this!!
-  for (i = 0; i < 4; i++) {
-    bsi->mvs[i].as_mv = x->partition_info->bmi[i].mv.as_mv;
-    if (mbmi->ref_frame[1] > 0)
-      bsi->second_mvs[i].as_mv = x->partition_info->bmi[i].second_mv.as_mv;
+  // update the coding decisions
+  for (i = 0; i < 4; ++i)
     bsi->modes[i] = x->partition_info->bmi[i].mode;
-    bsi->eobs[i] = best_eobs[i];
-  }
 }
 
 static int64_t rd_pick_best_mbsegmentation(VP9_COMP *cpi, MACROBLOCK *x,
@@ -2052,57 +2166,52 @@
                                            int *skippable, int64_t *psse,
                                            int mvthresh,
                                            int_mv seg_mvs[4][MAX_REF_FRAMES],
+                                           BEST_SEG_INFO *bsi_buf,
+                                           int filter_idx,
                                            int mi_row, int mi_col) {
   int i;
-  BEST_SEG_INFO bsi;
-  MB_MODE_INFO * mbmi = &x->e_mbd.mode_info_context->mbmi;
+  BEST_SEG_INFO *bsi = bsi_buf + filter_idx;
+  MACROBLOCKD *xd = &x->e_mbd;
+  MODE_INFO *mi = xd->mode_info_context;
+  MB_MODE_INFO *mbmi = &mi->mbmi;
+  int mode_idx;
 
-  vpx_memset(&bsi, 0, sizeof(bsi));
+  vpx_memset(bsi, 0, sizeof(*bsi));
 
-  bsi.segment_rd = best_rd;
-  bsi.ref_mv = best_ref_mv;
-  bsi.second_ref_mv = second_best_ref_mv;
-  bsi.mvp.as_int = best_ref_mv->as_int;
-  bsi.mvthresh = mvthresh;
+  bsi->segment_rd = best_rd;
+  bsi->ref_mv = best_ref_mv;
+  bsi->second_ref_mv = second_best_ref_mv;
+  bsi->mvp.as_int = best_ref_mv->as_int;
+  bsi->mvthresh = mvthresh;
 
   for (i = 0; i < 4; i++)
-    bsi.modes[i] = ZEROMV;
+    bsi->modes[i] = ZEROMV;
 
-  rd_check_segment_txsize(cpi, x, &bsi, seg_mvs, mi_row, mi_col);
+  rd_check_segment_txsize(cpi, x, bsi_buf, filter_idx, seg_mvs, mi_row, mi_col);
 
+  if (bsi.segment_rd > best_rd)
+    return INT64_MAX;
   /* set it to the best */
   for (i = 0; i < 4; i++) {
-    x->e_mbd.mode_info_context->bmi[i].as_mv[0].as_int = bsi.mvs[i].as_int;
+    mode_idx = inter_mode_offset(bsi->modes[i]);
+    mi->bmi[i].as_mv[0].as_int = bsi->rdstat[i][mode_idx].mvs[0].as_int;
     if (mbmi->ref_frame[1] > 0)
-      x->e_mbd.mode_info_context->bmi[i].as_mv[1].as_int =
-      bsi.second_mvs[i].as_int;
-    x->e_mbd.plane[0].eobs[i] = bsi.eobs[i];
+      mi->bmi[i].as_mv[1].as_int = bsi->rdstat[i][mode_idx].mvs[1].as_int;
+    xd->plane[0].eobs[i] = bsi->rdstat[i][mode_idx].eobs;
+    x->partition_info->bmi[i].mode = bsi->modes[i];
   }
 
-  /* save partitions */
-  x->partition_info->count = 4;
-
-  for (i = 0; i < x->partition_info->count; i++) {
-    x->partition_info->bmi[i].mode = bsi.modes[i];
-    x->partition_info->bmi[i].mv.as_mv = bsi.mvs[i].as_mv;
-    if (mbmi->ref_frame[1] > 0)
-      x->partition_info->bmi[i].second_mv.as_mv = bsi.second_mvs[i].as_mv;
-  }
   /*
    * used to set mbmi->mv.as_int
    */
-  x->partition_info->bmi[3].mv.as_int = bsi.mvs[3].as_int;
-  if (mbmi->ref_frame[1] > 0)
-    x->partition_info->bmi[3].second_mv.as_int = bsi.second_mvs[3].as_int;
-
-  *returntotrate = bsi.r;
-  *returndistortion = bsi.d;
-  *returnyrate = bsi.segment_yrate;
+  *returntotrate = bsi->r;
+  *returndistortion = bsi->d;
+  *returnyrate = bsi->segment_yrate;
   *skippable = vp9_sby_is_skippable(&x->e_mbd, BLOCK_SIZE_SB8X8);
-  *psse = bsi.sse;
-  mbmi->mode = bsi.modes[3];
+  *psse = bsi->sse;
+  mbmi->mode = bsi->modes[3];
 
-  return bsi.segment_rd;
+  return bsi->segment_rd;
 }
 
 static void mv_pred(VP9_COMP *cpi, MACROBLOCK *x,
@@ -2314,8 +2423,8 @@
   // Further refinement that is encode side only to test the top few candidates
   // in full and choose the best as the centre point for subsequent searches.
   // The current implementation doesn't support scaling.
-  if (scale[frame_type].x_scale_fp == (1 << VP9_REF_SCALE_SHIFT) &&
-      scale[frame_type].y_scale_fp == (1 << VP9_REF_SCALE_SHIFT))
+  if (scale[frame_type].x_scale_fp == VP9_REF_NO_SCALE &&
+      scale[frame_type].y_scale_fp == VP9_REF_NO_SCALE)
     mv_pred(cpi, x, yv12_mb[frame_type][0].buf, yv12->y_stride,
             frame_type, block_size);
 }
@@ -2332,7 +2441,7 @@
   MACROBLOCKD *xd = &x->e_mbd;
   MB_MODE_INFO *const mbmi = &xd->mode_info_context->mbmi;
 
-  const int c = vp9_get_pred_context_switchable_interp(cm, xd);
+  const int c = vp9_get_pred_context_switchable_interp(xd);
   const int m = vp9_switchable_interp_map[mbmi->interp_filter];
   return SWITCHABLE_INTERP_RATE_FACTOR * x->switchable_interp_costs[c][m];
 }
@@ -2368,7 +2477,7 @@
     for (i = 0; i < MAX_MB_PLANE; i++)
       backup_yv12[i] = xd->plane[i].pre[0];
 
-    setup_pre_planes(xd, 0, scaled_ref_frame, mi_row, mi_col, NULL, NULL);
+    setup_pre_planes(xd, 0, scaled_ref_frame, mi_row, mi_col, NULL);
   }
 
   vp9_clamp_mv_min_max(x, &ref_mv);
@@ -2476,7 +2585,7 @@
     // motion search code to be used without additional modifications.
     for (i = 0; i < MAX_MB_PLANE; i++)
       backup_yv12[i] = xd->plane[i].pre[0];
-    setup_pre_planes(xd, 0, scaled_ref_frame[0], mi_row, mi_col, NULL, NULL);
+    setup_pre_planes(xd, 0, scaled_ref_frame[0], mi_row, mi_col, NULL);
   }
 
   if (scaled_ref_frame[1]) {
@@ -2484,7 +2593,7 @@
     for (i = 0; i < MAX_MB_PLANE; i++)
       backup_second_yv12[i] = xd->plane[i].pre[1];
 
-    setup_pre_planes(xd, 0, scaled_ref_frame[1], mi_row, mi_col, NULL, NULL);
+    setup_pre_planes(xd, 0, scaled_ref_frame[1], mi_row, mi_col, NULL);
   }
 
   xd->scale_factor[0].set_scaled_offsets(&xd->scale_factor[0],
@@ -2606,7 +2715,7 @@
                                  int *rate_uv, int64_t *distortion_uv,
                                  int *mode_excluded, int *disable_skip,
                                  INTERPOLATIONFILTERTYPE *best_filter,
-                                 int_mv *frame_mv,
+                                 int_mv (*mode_mv)[MAX_REF_FRAMES],
                                  int mi_row, int mi_col,
                                  int_mv single_newmv[MAX_REF_FRAMES],
                                  int64_t *psse, int64_t ref_best_rd) {
@@ -2616,6 +2725,7 @@
   const int is_comp_pred = (mbmi->ref_frame[1] > 0);
   const int num_refs = is_comp_pred ? 2 : 1;
   const int this_mode = mbmi->mode;
+  int_mv *frame_mv = mode_mv[this_mode];
   int i;
   int refs[2] = { mbmi->ref_frame[0],
     (mbmi->ref_frame[1] < 0 ? 0 : mbmi->ref_frame[1]) };
@@ -2656,7 +2766,6 @@
             frame_mv[refs[1]].as_int == INVALID_MV)
           return INT64_MAX;
         *rate2 += rate_mv;
-
       } else {
         int_mv tmp_mv;
         single_motion_search(cpi, x, bsize, mi_row, mi_col,
@@ -2673,6 +2782,43 @@
     default:
       break;
   }
+
+  // if we're near/nearest and mv == 0,0, compare to zeromv
+  if ((this_mode == NEARMV || this_mode == NEARESTMV || this_mode == ZEROMV) &&
+      frame_mv[refs[0]].as_int == 0 &&
+      !vp9_segfeature_active(&xd->seg, mbmi->segment_id, SEG_LVL_SKIP) &&
+      (num_refs == 1 || frame_mv[refs[1]].as_int == 0)) {
+    int rfc = mbmi->mb_mode_context[mbmi->ref_frame[0]];
+    int c1 = cost_mv_ref(cpi, NEARMV, rfc);
+    int c2 = cost_mv_ref(cpi, NEARESTMV, rfc);
+    int c3 = cost_mv_ref(cpi, ZEROMV, rfc);
+
+    if (this_mode == NEARMV) {
+      if (c1 > c3)
+        return INT64_MAX;
+    } else if (this_mode == NEARESTMV) {
+      if (c2 > c3)
+        return INT64_MAX;
+    } else {
+      assert(this_mode == ZEROMV);
+      if (num_refs == 1) {
+        if ((c3 >= c2 &&
+             mode_mv[NEARESTMV][mbmi->ref_frame[0]].as_int == 0) ||
+            (c3 >= c1 &&
+             mode_mv[NEARMV][mbmi->ref_frame[0]].as_int == 0))
+          return INT64_MAX;
+      } else {
+        if ((c3 >= c2 &&
+             mode_mv[NEARESTMV][mbmi->ref_frame[0]].as_int == 0 &&
+             mode_mv[NEARESTMV][mbmi->ref_frame[1]].as_int == 0) ||
+            (c3 >= c1 &&
+             mode_mv[NEARMV][mbmi->ref_frame[0]].as_int == 0 &&
+             mode_mv[NEARMV][mbmi->ref_frame[1]].as_int == 0))
+          return INT64_MAX;
+      }
+    }
+  }
+
   for (i = 0; i < num_refs; ++i) {
     cur_mv[i] = frame_mv[refs[i]];
     // Clip "next_nearest" so that it does not extend to far out of image
@@ -2949,51 +3095,42 @@
 void vp9_rd_pick_intra_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
                                int *returnrate, int64_t *returndist,
                                BLOCK_SIZE_TYPE bsize,
-                               PICK_MODE_CONTEXT *ctx) {
-  VP9_COMMON *cm = &cpi->common;
-  MACROBLOCKD *xd = &x->e_mbd;
-  int rate_y = 0, rate_uv = 0;
-  int rate_y_tokenonly = 0, rate_uv_tokenonly = 0;
-  int64_t dist_y = 0, dist_uv = 0;
-  int y_skip = 0, uv_skip = 0;
-  int64_t txfm_cache[NB_TXFM_MODES], err;
-  MB_PREDICTION_MODE mode;
-  TX_SIZE txfm_size;
-  int rate4x4_y, rate4x4_y_tokenonly;
-  int64_t dist4x4_y;
-  int64_t err4x4 = INT64_MAX;
+                               PICK_MODE_CONTEXT *ctx, int64_t best_rd) {
+  VP9_COMMON *const cm = &cpi->common;
+  MACROBLOCKD *const xd = &x->e_mbd;
+  int rate_y = 0, rate_uv = 0, rate_y_tokenonly = 0, rate_uv_tokenonly = 0;
+  int y_skip = 0, uv_skip;
+  int64_t dist_y = 0, dist_uv = 0, txfm_cache[NB_TXFM_MODES];
 
   x->skip_encode = 0;
-  vpx_memset(&txfm_cache,0,sizeof(txfm_cache));
+  vpx_memset(&txfm_cache, 0, sizeof(txfm_cache));
   ctx->skip = 0;
-  xd->mode_info_context->mbmi.mode = DC_PRED;
   xd->mode_info_context->mbmi.ref_frame[0] = INTRA_FRAME;
-  err = rd_pick_intra_sby_mode(cpi, x, &rate_y, &rate_y_tokenonly,
-                               &dist_y, &y_skip, bsize, txfm_cache);
-  mode = xd->mode_info_context->mbmi.mode;
-  txfm_size = xd->mode_info_context->mbmi.txfm_size;
-  rd_pick_intra_sbuv_mode(cpi, x, &rate_uv, &rate_uv_tokenonly,
-                          &dist_uv, &uv_skip,
-                          (bsize < BLOCK_SIZE_SB8X8) ? BLOCK_SIZE_SB8X8 :
-                                                       bsize);
-  if (bsize < BLOCK_SIZE_SB8X8)
-    err4x4 = rd_pick_intra4x4mby_modes(cpi, x, &rate4x4_y,
-                                       &rate4x4_y_tokenonly,
-                                       &dist4x4_y, err);
+  if (bsize >= BLOCK_SIZE_SB8X8) {
+    if (rd_pick_intra_sby_mode(cpi, x, &rate_y, &rate_y_tokenonly,
+                               &dist_y, &y_skip, bsize, txfm_cache,
+                               best_rd) >= best_rd) {
+      *returnrate = INT_MAX;
+      return;
+    }
+    rd_pick_intra_sbuv_mode(cpi, x, &rate_uv, &rate_uv_tokenonly,
+                            &dist_uv, &uv_skip, bsize);
+  } else {
+    y_skip = 0;
+    if (rd_pick_intra4x4mby_modes(cpi, x, &rate_y, &rate_y_tokenonly,
+                                  &dist_y, best_rd) >= best_rd) {
+      *returnrate = INT_MAX;
+      return;
+    }
+    rd_pick_intra_sbuv_mode(cpi, x, &rate_uv, &rate_uv_tokenonly,
+                            &dist_uv, &uv_skip, BLOCK_SIZE_SB8X8);
+  }
 
   if (y_skip && uv_skip) {
     *returnrate = rate_y + rate_uv - rate_y_tokenonly - rate_uv_tokenonly +
                   vp9_cost_bit(vp9_get_pred_prob_mbskip(cm, xd), 1);
     *returndist = dist_y + (dist_uv >> 2);
     memset(ctx->txfm_rd_diff, 0, sizeof(ctx->txfm_rd_diff));
-    xd->mode_info_context->mbmi.mode = mode;
-    xd->mode_info_context->mbmi.txfm_size = txfm_size;
-  } else if (bsize < BLOCK_SIZE_SB8X8 && err4x4 < err) {
-    *returnrate = rate4x4_y + rate_uv +
-        vp9_cost_bit(vp9_get_pred_prob_mbskip(cm, xd), 0);
-    *returndist = dist4x4_y + (dist_uv >> 2);
-    vpx_memset(ctx->txfm_rd_diff, 0, sizeof(ctx->txfm_rd_diff));
-    xd->mode_info_context->mbmi.txfm_size = TX_4X4;
   } else {
     int i;
     *returnrate = rate_y + rate_uv +
@@ -3001,11 +3138,9 @@
     *returndist = dist_y + (dist_uv >> 2);
     if (cpi->sf.tx_size_search_method == USE_FULL_RD) {
       for (i = 0; i < NB_TXFM_MODES; i++) {
-        ctx->txfm_rd_diff[i] = txfm_cache[i] - txfm_cache[cm->txfm_mode];
+        ctx->txfm_rd_diff[i] = txfm_cache[i] - txfm_cache[cm->tx_mode];
       }
     }
-    xd->mode_info_context->mbmi.txfm_size = txfm_size;
-    xd->mode_info_context->mbmi.mode = mode;
   }
 
   ctx->mic = *xd->mode_info_context;
@@ -3016,7 +3151,8 @@
                                   int *returnrate,
                                   int64_t *returndistortion,
                                   BLOCK_SIZE_TYPE bsize,
-                                  PICK_MODE_CONTEXT *ctx) {
+                                  PICK_MODE_CONTEXT *ctx,
+                                  int64_t best_rd_so_far) {
   VP9_COMMON *cm = &cpi->common;
   MACROBLOCKD *xd = &x->e_mbd;
   MB_MODE_INFO *mbmi = &xd->mode_info_context->mbmi;
@@ -3034,8 +3170,8 @@
                      cpi->lst_fb_idx,
                      cpi->gld_fb_idx,
                      cpi->alt_fb_idx};
-  int64_t best_rd = INT64_MAX;
-  int64_t best_yrd = INT64_MAX;
+  int64_t best_rd = best_rd_so_far;
+  int64_t best_yrd = best_rd_so_far;  // FIXME(rbultje) more precise
   int64_t best_txfm_rd[NB_TXFM_MODES];
   int64_t best_txfm_diff[NB_TXFM_MODES];
   int64_t best_pred_diff[NB_PREDICTION_TYPES];
@@ -3097,6 +3233,10 @@
     best_txfm_rd[i] = INT64_MAX;
   for (i = 0; i <= VP9_SWITCHABLE_FILTERS; i++)
     best_filter_rd[i] = INT64_MAX;
+  for (i = 0; i < TX_SIZE_MAX_SB; i++)
+    rate_uv_intra[i] = INT_MAX;
+
+  *returnrate = INT_MAX;
 
   // Create a mask set to 1 for each frame used by a smaller resolution.
   if (cpi->sf.use_avoid_tested_higherror) {
@@ -3140,44 +3280,6 @@
     frame_mv[ZEROMV][ref_frame].as_int = 0;
   }
 
-  // If intra is not masked off then get uv intra mode rd.
-  if (x->fast_ms < 2 && (!cpi->sf.use_avoid_tested_higherror
-      || (cpi->sf.use_avoid_tested_higherror
-          && (ref_frame_mask & (1 << INTRA_FRAME))))) {
-    // Note that the enumerator TXFM_MODE "matches" TX_SIZE.
-    // Eg. ONLY_4X4 = TX_4X4, ALLOW_8X8 = TX_8X8 etc such that the MIN
-    // operation below correctly constrains max_uvtxfm_size.
-    TX_SIZE max_uvtxfm_size =
-      MIN(max_uv_txsize_lookup[bsize], (TX_SIZE)cm->txfm_mode);
-    TX_SIZE min_uvtxfm_size = (cpi->sf.tx_size_search_method == USE_LARGESTALL)
-                              ? max_uvtxfm_size : TX_4X4;
-
-    mbmi->mode = DC_PRED;
-    mbmi->ref_frame[0] = INTRA_FRAME;
-
-    // Test all possible UV transform sizes that may be used in the main loop
-    for (i = min_uvtxfm_size; i <= max_uvtxfm_size; ++i) {
-      mbmi->txfm_size = i;
-
-      // Use an estimated rd for uv_intra based on DC_PRED if the
-      // appropriate speed flag is set.
-      if (cpi->sf.use_uv_intra_rd_estimate) {
-        rd_sbuv_dcpred(cpi, x, &rate_uv_intra[i],
-                       &rate_uv_tokenonly[i], &dist_uv[i], &skip_uv[i],
-                       (bsize < BLOCK_SIZE_SB8X8) ? BLOCK_SIZE_SB8X8 :
-                                                    bsize);
-      // Else do a proper rd search for each possible transform size that may
-      // be considered in the main rd loop.
-      } else {
-        rd_pick_intra_sbuv_mode(cpi, x, &rate_uv_intra[i],
-                                &rate_uv_tokenonly[i], &dist_uv[i], &skip_uv[i],
-                                (bsize < BLOCK_SIZE_SB8X8) ? BLOCK_SIZE_SB8X8
-                                                           : bsize);
-      }
-      mode_uv[i] = mbmi->uv_mode;
-    }
-  }
-
   for (mode_index = 0; mode_index < MAX_MODES; ++mode_index) {
     int mode_excluded = 0;
     int64_t this_rd = INT64_MAX;
@@ -3267,18 +3369,14 @@
     // TODO(jingning, jkoleszar): scaling reference frame not supported for
     // SPLITMV.
     if (mbmi->ref_frame[0] > 0 &&
-          (scale_factor[mbmi->ref_frame[0]].x_scale_fp !=
-           (1 << VP9_REF_SCALE_SHIFT) ||
-           scale_factor[mbmi->ref_frame[0]].y_scale_fp !=
-           (1 << VP9_REF_SCALE_SHIFT)) &&
+        (scale_factor[mbmi->ref_frame[0]].x_scale_fp != VP9_REF_NO_SCALE ||
+         scale_factor[mbmi->ref_frame[0]].y_scale_fp != VP9_REF_NO_SCALE) &&
         this_mode == SPLITMV)
       continue;
 
     if (mbmi->ref_frame[1] > 0 &&
-          (scale_factor[mbmi->ref_frame[1]].x_scale_fp !=
-           (1 << VP9_REF_SCALE_SHIFT) ||
-           scale_factor[mbmi->ref_frame[1]].y_scale_fp !=
-           (1 << VP9_REF_SCALE_SHIFT)) &&
+        (scale_factor[mbmi->ref_frame[1]].x_scale_fp != VP9_REF_NO_SCALE ||
+         scale_factor[mbmi->ref_frame[1]].y_scale_fp != VP9_REF_NO_SCALE) &&
         this_mode == SPLITMV)
       continue;
 
@@ -3343,9 +3441,15 @@
                                       SEG_LVL_REF_FRAME)) {
       // Only consider ZEROMV/ALTREF_FRAME for alt ref frame,
       // unless ARNR filtering is enabled in which case we want
-      // an unfiltered alternative
+      // 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 (this_mode != ZEROMV || ref_frame != ALTREF_FRAME) {
+        if ((this_mode != ZEROMV &&
+             !(this_mode == NEARMV &&
+               frame_mv[NEARMV][ALTREF_FRAME].as_int == 0) &&
+             !(this_mode == NEARESTMV &&
+               frame_mv[NEARESTMV][ALTREF_FRAME].as_int == 0)) ||
+            ref_frame != ALTREF_FRAME) {
           continue;
         }
       }
@@ -3376,8 +3480,14 @@
       rate2 += intra_cost_penalty;
       distortion2 += distortion_y;
 
+      if (rate_uv_intra[TX_4X4] == INT_MAX) {
+        choose_intra_uv_mode(cpi, bsize, &rate_uv_intra[TX_4X4],
+                             &rate_uv_tokenonly[TX_4X4],
+                             &dist_uv[TX_4X4], &skip_uv[TX_4X4],
+                             &mode_uv[TX_4X4]);
+      }
       rate2 += rate_uv_intra[TX_4X4];
-      rate_uv = rate_uv_intra[TX_4X4];
+      rate_uv = rate_uv_tokenonly[TX_4X4];
       distortion2 += dist_uv[TX_4X4];
       distortion_uv = dist_uv[TX_4X4];
       mbmi->uv_mode = mode_uv[TX_4X4];
@@ -3404,13 +3514,19 @@
         continue;
 
       uv_tx = MIN(mbmi->txfm_size, max_uv_txsize_lookup[bsize]);
+      if (rate_uv_intra[uv_tx] == INT_MAX) {
+        choose_intra_uv_mode(cpi, bsize, &rate_uv_intra[uv_tx],
+                             &rate_uv_tokenonly[uv_tx],
+                             &dist_uv[uv_tx], &skip_uv[uv_tx],
+                             &mode_uv[uv_tx]);
+      }
 
-      rate_uv = rate_uv_intra[uv_tx];
+      rate_uv = rate_uv_tokenonly[uv_tx];
       distortion_uv = dist_uv[uv_tx];
       skippable = skippable && skip_uv[uv_tx];
       mbmi->uv_mode = mode_uv[uv_tx];
 
-      rate2 = rate_y + x->mbmode_cost[mbmi->mode] + rate_uv;
+      rate2 = rate_y + x->mbmode_cost[mbmi->mode] + rate_uv_intra[uv_tx];
       if (mbmi->mode != DC_PRED && mbmi->mode != TM_PRED)
         rate2 += intra_cost_penalty;
       distortion2 = distortion_y + distortion_uv;
@@ -3429,6 +3545,7 @@
       union b_mode_info tmp_best_bmodes[16];
       MB_MODE_INFO tmp_best_mbmode;
       PARTITION_INFO tmp_best_partition;
+      BEST_SEG_INFO bsi[VP9_SWITCHABLE_FILTERS];
       int pred_exists = 0;
       int uv_skippable;
       if (is_comp_pred) {
@@ -3466,10 +3583,11 @@
                      &rate, &rate_y, &distortion,
                      &skippable, &total_sse,
                      (int)this_rd_thresh, seg_mvs,
+                     bsi, switchable_filter_index,
                      mi_row, mi_col);
-        if (tmp_rd == INT64_MAX) {
+
+        if (tmp_rd == INT64_MAX)
           continue;
-        }
         cpi->rd_filter_cache[switchable_filter_index] = tmp_rd;
         rs = get_switchable_rate(cm, x);
         rs_rd = RDCOST(x->rdmult, x->rddiv, rs, 0);
@@ -3510,6 +3628,7 @@
           }
         }
       }  // switchable_filter_index loop
+
       if (tmp_best_rdu == INT64_MAX)
         continue;
 
@@ -3526,6 +3645,7 @@
                      &rate, &rate_y, &distortion,
                      &skippable, &total_sse,
                      (int)this_rd_thresh, seg_mvs,
+                     bsi, 0,
                      mi_row, mi_col);
         if (tmp_rd == INT64_MAX)
           continue;
@@ -3588,7 +3708,7 @@
                                   &rate_y, &distortion_y,
                                   &rate_uv, &distortion_uv,
                                   &mode_excluded, &disable_skip,
-                                  &tmp_best_filter, frame_mv[this_mode],
+                                  &tmp_best_filter, frame_mv,
                                   mi_row, mi_col,
                                   single_newmv, &total_sse, best_rd);
       if (this_rd == INT64_MAX)
@@ -3817,7 +3937,7 @@
       for (i = 0; i < NB_TXFM_MODES; i++) {
         int64_t adj_rd = INT64_MAX;
         if (this_mode != I4X4_PRED) {
-          adj_rd = this_rd + txfm_cache[i] - txfm_cache[cm->txfm_mode];
+          adj_rd = this_rd + txfm_cache[i] - txfm_cache[cm->tx_mode];
         } else {
           adj_rd = this_rd;
         }
@@ -3833,6 +3953,8 @@
     if (x->skip && !mode_excluded)
       break;
   }
+  if (best_rd >= best_rd_so_far)
+    return INT64_MAX;
 
   // If we used an estimate for the uv intra rd in the loop above...
   if (cpi->sf.use_uv_intra_rd_estimate) {
@@ -3924,35 +4046,6 @@
   }
 #endif
 
-  // This code forces Altref,0,0 and skip for the frame that overlays a
-  // an alrtef unless Altref is filtered. However, this is unsafe if
-  // segment level coding of ref frame is enabled for this segment.
-  if (!vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_REF_FRAME) &&
-      cpi->is_src_frame_alt_ref &&
-      (cpi->oxcf.arnr_max_frames == 0) &&
-      (best_mbmode.mode != ZEROMV || best_mbmode.ref_frame[0] != ALTREF_FRAME)
-      && bsize >= BLOCK_SIZE_SB8X8) {
-    mbmi->mode = ZEROMV;
-    mbmi->ref_frame[0] = ALTREF_FRAME;
-    mbmi->ref_frame[1] = NONE;
-    mbmi->mv[0].as_int = 0;
-    mbmi->uv_mode = DC_PRED;
-    mbmi->mb_skip_coeff = 1;
-    if (cm->txfm_mode == TX_MODE_SELECT) {
-      if (bsize >= BLOCK_SIZE_SB32X32)
-        mbmi->txfm_size = TX_32X32;
-      else if (bsize >= BLOCK_SIZE_MB16X16)
-        mbmi->txfm_size = TX_16X16;
-      else
-        mbmi->txfm_size = TX_8X8;
-    }
-
-    vpx_memset(best_txfm_diff, 0, sizeof(best_txfm_diff));
-    vpx_memset(best_pred_diff, 0, sizeof(best_pred_diff));
-    vpx_memset(best_filter_diff, 0, sizeof(best_filter_diff));
-    goto end;
-  }
-
   // macroblock modes
   *mbmi = best_mbmode;
   x->skip |= best_skip2;
@@ -3975,8 +4068,8 @@
 
     *x->partition_info = best_partition;
 
-    mbmi->mv[0].as_int = x->partition_info->bmi[3].mv.as_int;
-    mbmi->mv[1].as_int = x->partition_info->bmi[3].second_mv.as_int;
+    mbmi->mv[0].as_int = xd->mode_info_context->bmi[3].as_mv[0].as_int;
+    mbmi->mv[1].as_int = xd->mode_info_context->bmi[3].as_mv[1].as_int;
   }
 
   for (i = 0; i < NB_PREDICTION_TYPES; ++i) {
@@ -4010,7 +4103,6 @@
     vpx_memset(best_txfm_diff, 0, sizeof(best_txfm_diff));
   }
 
- end:
   set_scale_factors(xd, mbmi->ref_frame[0], mbmi->ref_frame[1],
                     scale_factor);
   store_coding_context(x, ctx, best_mode_index,
diff --git a/vp9/encoder/vp9_rdopt.h b/vp9/encoder/vp9_rdopt.h
index 22d0a95..7c84b48 100644
--- a/vp9/encoder/vp9_rdopt.h
+++ b/vp9/encoder/vp9_rdopt.h
@@ -23,12 +23,12 @@
 
 void vp9_rd_pick_intra_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
                                int *r, int64_t *d, BLOCK_SIZE_TYPE bsize,
-                               PICK_MODE_CONTEXT *ctx);
+                               PICK_MODE_CONTEXT *ctx, int64_t best_rd);
 
 int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
                                   int mi_row, int mi_col,
                                   int *r, int64_t *d, BLOCK_SIZE_TYPE bsize,
-                                  PICK_MODE_CONTEXT *ctx);
+                                  PICK_MODE_CONTEXT *ctx, int64_t best_rd);
 
 void vp9_init_me_luts();
 
diff --git a/vp9/encoder/vp9_temporal_filter.c b/vp9/encoder/vp9_temporal_filter.c
index c1bd93b..821b7c6 100644
--- a/vp9/encoder/vp9_temporal_filter.c
+++ b/vp9/encoder/vp9_temporal_filter.c
@@ -58,7 +58,7 @@
   vp9_build_inter_predictor(u_mb_ptr, stride,
                             &pred[256], 8,
                             &mv,
-                            &xd->scale_factor_uv[which_mv],
+                            &xd->scale_factor[which_mv],
                             8, 8,
                             which_mv,
                             &xd->subpix, MV_PRECISION_Q4);
@@ -66,7 +66,7 @@
   vp9_build_inter_predictor(v_mb_ptr, stride,
                             &pred[320], 8,
                             &mv,
-                            &xd->scale_factor_uv[which_mv],
+                            &xd->scale_factor[which_mv],
                             8, 8,
                             which_mv,
                             &xd->subpix, MV_PRECISION_Q4);
@@ -443,7 +443,6 @@
       cm->yv12_fb[cm->new_fb_idx].y_crop_width,
       cm->yv12_fb[cm->new_fb_idx].y_crop_height,
       cm->width, cm->height);
-  cpi->mb.e_mbd.scale_factor_uv[0] = cpi->mb.e_mbd.scale_factor[0];
 
   // Setup frame pointers, NULL indicates frame not included in filter
   vpx_memset(cpi->frames, 0, max_frames * sizeof(YV12_BUFFER_CONFIG *));
diff --git a/vp9/vp9_common.mk b/vp9/vp9_common.mk
index 196846e..5a0c1c9 100644
--- a/vp9/vp9_common.mk
+++ b/vp9/vp9_common.mk
@@ -90,5 +90,6 @@
 VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_convolve8_avg_neon$(ASM)
 VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_loopfilter_neon$(ASM)
 VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_dc_only_idct_add_neon$(ASM)
+VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_short_idct8x8_add_neon$(ASM)
 
 $(eval $(call rtcd_h_template,vp9_rtcd,vp9/common/vp9_rtcd_defs.sh))