Merge "Further supertx costing fixes." into nextgenv2
diff --git a/test/sum_squares_test.cc b/test/sum_squares_test.cc
new file mode 100644
index 0000000..7de7a81
--- /dev/null
+++ b/test/sum_squares_test.cc
@@ -0,0 +1,133 @@
+/*
+ *  Copyright (c) 2014 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <cmath>
+#include <cstdlib>
+#include <string>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_config.h"
+#include "./vpx_dsp_rtcd.h"
+#include "vpx_ports/mem.h"
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+
+
+using libvpx_test::ACMRandom;
+
+namespace {
+const int kNumIterations = 10000;
+
+typedef uint64_t (*SSI16Func)(const int16_t *src,
+                             int stride ,
+                             int size);
+
+typedef std::tr1::tuple<SSI16Func, SSI16Func> SumSquaresParam;
+
+class SumSquaresTest : public ::testing::TestWithParam<SumSquaresParam> {
+ public:
+  virtual ~SumSquaresTest() {}
+  virtual void SetUp() {
+    ref_func_ = GET_PARAM(0);
+    tst_func_ = GET_PARAM(1);
+  }
+
+  virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+  SSI16Func ref_func_;
+  SSI16Func tst_func_;
+};
+
+TEST_P(SumSquaresTest, OperationCheck) {
+  ACMRandom rnd(ACMRandom::DeterministicSeed());
+  DECLARE_ALIGNED(16, int16_t, src[256*256]);
+
+  int failed = 0;
+
+  const int msb = 11;   // Up to 12 bit input
+  const int limit = 1 << (msb+1);
+
+  for (int k = 0; k < kNumIterations; k++) {
+    int size = 4 << rnd(6);     // Up to 128x128
+    int stride = 4 << rnd(7);   // Up to 256 stride
+    while (stride < size) {     // Make sure it's valid
+      stride = 4 << rnd(7);
+    }
+
+    for (int ii = 0 ; ii < size; ii++) {
+      for (int jj = 0; jj < size; jj++) {
+        src[ii*stride+jj] = rnd(2) ? rnd(limit) : -rnd(limit);
+      }
+    }
+
+    uint64_t res_ref = ref_func_(src, stride, size);
+    uint64_t res_tst;
+    ASM_REGISTER_STATE_CHECK(res_tst = tst_func_(src, stride, size));
+
+    if (!failed) {
+      failed = res_ref != res_tst;
+      EXPECT_EQ(res_ref, res_tst)
+        << "Error: Sum Squares Test"
+        << " C output does not match optimized output.";
+    }
+  }
+}
+
+TEST_P(SumSquaresTest, ExtremeValues) {
+  ACMRandom rnd(ACMRandom::DeterministicSeed());
+  DECLARE_ALIGNED(16, int16_t, src[256*256]);
+
+  int failed = 0;
+
+  const int msb = 11;   // Up to 12 bit input
+  const int limit = 1 << (msb+1);
+
+  for (int k = 0; k < kNumIterations; k++) {
+    int size = 4 << rnd(6);     // Up to 128x128
+    int stride = 4 << rnd(7);   // Up to 256 stride
+    while (stride < size) {     // Make sure it's valid
+      stride = 4 << rnd(7);
+    }
+
+    int val = rnd(2) ? limit-1 : -(limit-1);
+    for (int ii = 0 ; ii < size; ii++) {
+      for (int jj = 0; jj < size; jj++) {
+        src[ii*stride+jj] = val;
+      }
+    }
+
+    uint64_t res_ref = ref_func_(src, stride, size);
+    uint64_t res_tst;
+    ASM_REGISTER_STATE_CHECK(res_tst = tst_func_(src, stride, size));
+
+    if (!failed) {
+      failed = res_ref != res_tst;
+      EXPECT_EQ(res_ref, res_tst)
+        << "Error: Sum Squares Test"
+        << " C output does not match optimized output.";
+    }
+  }
+}
+using std::tr1::make_tuple;
+
+#if HAVE_SSE2
+
+INSTANTIATE_TEST_CASE_P(
+    SSE2, SumSquaresTest,
+    ::testing::Values(
+        make_tuple(&vpx_sum_squares_2d_i16_c, &vpx_sum_squares_2d_i16_sse2)
+    )
+);
+#endif  // HAVE_SSE2
+}  // namespace
diff --git a/test/test.mk b/test/test.mk
index 7926cae..a73ebd9 100644
--- a/test/test.mk
+++ b/test/test.mk
@@ -163,11 +163,11 @@
 
 ## VP10
 ifeq ($(CONFIG_VP10),yes)
-
 LIBVPX_TEST_SRCS-yes                    += vp10_inv_txfm_test.cc
 LIBVPX_TEST_SRCS-$(CONFIG_VP10_ENCODER) += vp10_dct_test.cc
 LIBVPX_TEST_SRCS-$(CONFIG_ANS)          += vp10_ans_test.cc
 
+LIBVPX_TEST_SRCS-$(CONFIG_VP10_ENCODER) += sum_squares_test.cc
 endif # VP10
 
 ## Multi-codec / unconditional whitebox tests.
diff --git a/vp10/common/blockd.h b/vp10/common/blockd.h
index 4a3e67c..6a69231 100644
--- a/vp10/common/blockd.h
+++ b/vp10/common/blockd.h
@@ -167,6 +167,10 @@
   INTRA_FILTER intra_filter;
 #endif  // CONFIG_EXT_INTRA
 
+#if CONFIG_OBMC
+  int8_t obmc;
+#endif  // CONFIG_OBMC
+
   int_mv mv[2];
   int_mv pred_mv[2];
 #if CONFIG_REF_MV
@@ -192,6 +196,12 @@
   return mbmi->ref_frame[1] > INTRA_FRAME;
 }
 
+#if CONFIG_OBMC
+static INLINE int is_obmc_allowed(const MB_MODE_INFO *mbmi) {
+  return (mbmi->sb_type >= BLOCK_8X8);
+}
+#endif  // CONFIG_OBMC
+
 PREDICTION_MODE vp10_left_block_mode(const MODE_INFO *cur_mi,
                                     const MODE_INFO *left_mi, int b);
 
diff --git a/vp10/common/entropymode.c b/vp10/common/entropymode.c
index 77f537e..735e10e 100644
--- a/vp10/common/entropymode.c
+++ b/vp10/common/entropymode.c
@@ -228,6 +228,12 @@
 };
 #endif  // CONFIG_EXT_INTER
 
+#if CONFIG_OBMC
+static const vpx_prob default_obmc_prob[BLOCK_SIZES] = {
+    255, 255, 255, 151, 153, 144, 178, 165, 160, 207, 195, 168, 244,
+};
+#endif  // CONFIG_OBMC
+
 /* Array indices are identical to previously-existing INTRAMODECONTEXTNODES. */
 const vpx_tree_index vp10_intra_mode_tree[TREE_SIZE(INTRA_MODES)] = {
   -DC_PRED, 2,                      /* 0 = DC_NODE */
@@ -1303,6 +1309,9 @@
 #endif  // CONFIG_EXT_INTER
 #endif  // CONFIG_REF_MV
   vp10_copy(fc->inter_mode_probs, default_inter_mode_probs);
+#if CONFIG_OBMC
+  vp10_copy(fc->obmc_prob, default_obmc_prob);
+#endif  // CONFIG_OBMC
 #if CONFIG_EXT_INTER
   vp10_copy(fc->inter_compound_mode_probs, default_inter_compound_mode_probs);
 #endif  // CONFIG_EXT_INTER
@@ -1383,6 +1392,12 @@
                 counts->inter_mode[i], fc->inter_mode_probs[i]);
 #endif
 
+#if CONFIG_OBMC
+  for (i = BLOCK_8X8; i < BLOCK_SIZES; ++i)
+    fc->obmc_prob[i] = mode_mv_merge_probs(pre_fc->obmc_prob[i],
+                                           counts->obmc[i]);
+#endif  // CONFIG_OBMC
+
 #if CONFIG_SUPERTX
   for (i = 0; i < PARTITION_SUPERTX_CONTEXTS; ++i) {
     int j;
diff --git a/vp10/common/entropymode.h b/vp10/common/entropymode.h
index 4b4bdf1..d581a08 100644
--- a/vp10/common/entropymode.h
+++ b/vp10/common/entropymode.h
@@ -81,6 +81,9 @@
   vpx_prob inter_compound_mode_probs[INTER_MODE_CONTEXTS]
                                     [INTER_COMPOUND_MODES - 1];
 #endif  // CONFIG_EXT_INTER
+#if CONFIG_OBMC
+  vpx_prob obmc_prob[BLOCK_SIZES];
+#endif  // CONFIG_OBMC
   vpx_prob intra_inter_prob[INTRA_INTER_CONTEXTS];
   vpx_prob comp_inter_prob[COMP_INTER_CONTEXTS];
   vpx_prob single_ref_prob[REF_CONTEXTS][SINGLE_REFS-1];
@@ -135,6 +138,9 @@
 #if CONFIG_EXT_INTER
   unsigned int inter_compound_mode[INTER_MODE_CONTEXTS][INTER_COMPOUND_MODES];
 #endif  // CONFIG_EXT_INTER
+#if CONFIG_OBMC
+  unsigned int obmc[BLOCK_SIZES][2];
+#endif  // CONFIG_OBMC
   unsigned int intra_inter[INTRA_INTER_CONTEXTS][2];
   unsigned int comp_inter[COMP_INTER_CONTEXTS][2];
   unsigned int single_ref[REF_CONTEXTS][SINGLE_REFS-1][2];
diff --git a/vp10/common/mvref_common.h b/vp10/common/mvref_common.h
index 224c5ed..b02c0dd 100644
--- a/vp10/common/mvref_common.h
+++ b/vp10/common/mvref_common.h
@@ -260,16 +260,16 @@
 
 static INLINE uint8_t vp10_drl_ctx(const CANDIDATE_MV *ref_mv_stack,
                                    int ref_idx) {
-  if (ref_mv_stack[ref_idx + 1].weight > REF_CAT_LEVEL &&
-      ref_mv_stack[ref_idx + 2].weight > REF_CAT_LEVEL)
+  if (ref_mv_stack[ref_idx].weight > REF_CAT_LEVEL &&
+      ref_mv_stack[ref_idx + 1].weight > REF_CAT_LEVEL)
     return 0;
 
-  if (ref_mv_stack[ref_idx + 1].weight > REF_CAT_LEVEL &&
-      ref_mv_stack[ref_idx + 2].weight < REF_CAT_LEVEL)
+  if (ref_mv_stack[ref_idx].weight > REF_CAT_LEVEL &&
+      ref_mv_stack[ref_idx + 1].weight < REF_CAT_LEVEL)
     return 1;
 
-  if (ref_mv_stack[ref_idx + 1].weight < REF_CAT_LEVEL &&
-      ref_mv_stack[ref_idx + 2].weight < REF_CAT_LEVEL)
+  if (ref_mv_stack[ref_idx].weight < REF_CAT_LEVEL &&
+      ref_mv_stack[ref_idx + 1].weight < REF_CAT_LEVEL)
     return 2;
 
   assert(0);
diff --git a/vp10/common/reconinter.c b/vp10/common/reconinter.c
index 60592fd..efc1ee1 100644
--- a/vp10/common/reconinter.c
+++ b/vp10/common/reconinter.c
@@ -18,6 +18,9 @@
 #include "vp10/common/blockd.h"
 #include "vp10/common/reconinter.h"
 #include "vp10/common/reconintra.h"
+#if CONFIG_OBMC
+#include "vp10/common/onyxc_int.h"
+#endif  // CONFIG_OBMC
 
 #if CONFIG_VP9_HIGHBITDEPTH
 void vp10_highbd_build_inter_predictor(const uint8_t *src, int src_stride,
@@ -64,12 +67,20 @@
                   sf, w, h, ref, interp_filter, sf->x_step_q4, sf->y_step_q4);
 }
 
-void build_inter_predictors(MACROBLOCKD *xd, int plane, int block,
+void build_inter_predictors(MACROBLOCKD *xd, int plane,
+#if CONFIG_OBMC
+                            int mi_col_offset, int mi_row_offset,
+#endif  // CONFIG_OBMC
+                            int block,
                             int bw, int bh,
                             int x, int y, int w, int h,
                             int mi_x, int mi_y) {
   struct macroblockd_plane *const pd = &xd->plane[plane];
+#if CONFIG_OBMC
+  const MODE_INFO *mi = xd->mi[mi_col_offset + xd->mi_stride * mi_row_offset];
+#else
   const MODE_INFO *mi = xd->mi[0];
+#endif  // CONFIG_OBMC
   const int is_compound = has_second_ref(&mi->mbmi);
   const INTERP_FILTER interp_filter = mi->mbmi.interp_filter;
   int ref;
@@ -201,10 +212,18 @@
       assert(pw * num_4x4_w == bw && ph * num_4x4_h == bh);
       for (y = 0; y < num_4x4_h; ++y)
         for (x = 0; x < num_4x4_w; ++x)
-           build_inter_predictors(xd, plane, y * 2 + x, bw, bh,
+           build_inter_predictors(xd, plane,
+#if CONFIG_OBMC
+                                  0, 0,
+#endif  // CONFIG_OBMC
+                                  y * 2 + x, bw, bh,
                                   4 * x, 4 * y, pw, ph, mi_x, mi_y);
     } else {
-      build_inter_predictors(xd, plane, 0, bw, bh,
+      build_inter_predictors(xd, plane,
+#if CONFIG_OBMC
+                             0, 0,
+#endif  // CONFIG_OBMC
+                             0, bw, bh,
                              0, 0, bw, bh, mi_x, mi_y);
     }
   }
@@ -309,7 +328,6 @@
   }
 }
 
-
 void vp10_build_masked_inter_predictor_complex(
     MACROBLOCKD *xd,
     uint8_t *dst, int dst_stride, uint8_t *dst2, int dst2_stride,
@@ -483,9 +501,271 @@
     const int bw = 4 * num_4x4_w;
     const int bh = 4 * num_4x4_h;
 
-    build_inter_predictors(xd, plane, block, bw, bh,
+    build_inter_predictors(xd, plane,
+#if CONFIG_OBMC
+                           0, 0,
+#endif  // CONFIG_OBMC
+                           block, bw, bh,
                            0, 0, bw, bh,
                            mi_x, mi_y);
   }
 }
 #endif  // CONFIG_SUPERTX
+
+#if CONFIG_OBMC
+// obmc_mask_N[is_neighbor_predictor][overlap_position]
+static const uint8_t obmc_mask_1[2][1] = {
+    { 55},
+    {  9}
+};
+
+static const uint8_t obmc_mask_2[2][2] = {
+    { 45, 62},
+    { 19,  2}
+};
+
+static const uint8_t obmc_mask_4[2][4] = {
+    { 39, 50, 59, 64},
+    { 25, 14,  5,  0}
+};
+
+static const uint8_t obmc_mask_8[2][8] = {
+    { 36, 42, 48, 53, 57, 61, 63, 64},
+    { 28, 22, 16, 11,  7,  3,  1,  0}
+};
+
+static const uint8_t obmc_mask_16[2][16] = {
+    { 34, 37, 40, 43, 46, 49, 52, 54, 56, 58, 60, 61, 63, 64, 64, 64},
+    { 30, 27, 24, 21, 18, 15, 12, 10,  8,  6,  4,  3,  1,  0,  0,  0}
+};
+
+static const uint8_t obmc_mask_32[2][32] = {
+    { 33, 35, 36, 38, 40, 41, 43, 44, 45, 47, 48, 50, 51, 52, 53, 55,
+      56, 57, 58, 59, 60, 60, 61, 62, 62, 63, 63, 64, 64, 64, 64, 64},
+    { 31, 29, 28, 26, 24, 23, 21, 20, 19, 17, 16, 14, 13, 12, 11,  9,
+       8,  7,  6,  5,  4,  4,  3,  2,  2,  1,  1,  0,  0,  0,  0,  0}
+};
+
+void setup_obmc_mask(int length, const uint8_t *mask[2]) {
+  switch (length) {
+    case 1:
+      mask[0] = obmc_mask_1[0];
+      mask[1] = obmc_mask_1[1];
+      break;
+    case 2:
+      mask[0] = obmc_mask_2[0];
+      mask[1] = obmc_mask_2[1];
+      break;
+    case 4:
+      mask[0] = obmc_mask_4[0];
+      mask[1] = obmc_mask_4[1];
+      break;
+    case 8:
+      mask[0] = obmc_mask_8[0];
+      mask[1] = obmc_mask_8[1];
+      break;
+    case 16:
+      mask[0] = obmc_mask_16[0];
+      mask[1] = obmc_mask_16[1];
+      break;
+    case 32:
+      mask[0] = obmc_mask_32[0];
+      mask[1] = obmc_mask_32[1];
+      break;
+    default:
+      mask[0] = obmc_mask_32[0];
+      mask[1] = obmc_mask_32[1];
+      assert(0);
+      break;
+  }
+}
+
+// This function combines motion compensated predictions that is generated by
+// top/left neighboring blocks' inter predictors with the regular inter
+// prediction. We assume the original prediction (bmc) is stored in
+// xd->plane[].dst.buf
+void vp10_build_obmc_inter_prediction(VP10_COMMON *cm,
+                                      MACROBLOCKD *xd, int mi_row, int mi_col,
+                                      int use_tmp_dst_buf,
+                                      uint8_t *final_buf[MAX_MB_PLANE],
+                                      int final_stride[MAX_MB_PLANE],
+                                      uint8_t *tmp_buf1[MAX_MB_PLANE],
+                                      int tmp_stride1[MAX_MB_PLANE],
+                                      uint8_t *tmp_buf2[MAX_MB_PLANE],
+                                      int tmp_stride2[MAX_MB_PLANE]) {
+  const TileInfo *const tile = &xd->tile;
+  BLOCK_SIZE bsize = xd->mi[0]->mbmi.sb_type;
+  int plane, i, mi_step;
+#if CONFIG_VP9_HIGHBITDEPTH
+  int is_hbd = (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) ? 1 : 0;
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+
+  if (use_tmp_dst_buf) {
+    for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
+      const struct macroblockd_plane *pd = &xd->plane[plane];
+      int bw = (xd->n8_w * 8) >> pd->subsampling_x;
+      int bh = (xd->n8_h * 8) >> pd->subsampling_y;
+      int row;
+#if CONFIG_VP9_HIGHBITDEPTH
+      if (is_hbd) {
+        uint16_t *final_buf16 = CONVERT_TO_SHORTPTR(final_buf[plane]);
+        uint16_t *bmc_buf16 = CONVERT_TO_SHORTPTR(pd->dst.buf);
+        for (row = 0; row < bh; ++row)
+          memcpy(final_buf16 + row * final_stride[plane],
+                 bmc_buf16 + row * pd->dst.stride, bw * sizeof(uint16_t));
+      } else {
+#endif
+      for (row = 0; row < bh; ++row)
+        memcpy(final_buf[plane] + row * final_stride[plane],
+               pd->dst.buf + row * pd->dst.stride, bw);
+#if CONFIG_VP9_HIGHBITDEPTH
+      }
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+    }
+  }
+
+  // handle above row
+  for (i = 0; mi_row > 0 && i < VPXMIN(xd->n8_w, cm->mi_cols - mi_col);
+       i += mi_step) {
+    int mi_row_offset = -1;
+    int mi_col_offset = i;
+    int overlap;
+    MODE_INFO *above_mi = xd->mi[mi_col_offset +
+                                 mi_row_offset * xd->mi_stride];
+    MB_MODE_INFO *above_mbmi = &above_mi->mbmi;
+
+    mi_step = VPXMIN(xd->n8_w,
+                     num_8x8_blocks_wide_lookup[above_mbmi->sb_type]);
+
+    if (!is_inter_block(above_mbmi))
+      continue;
+
+    overlap = (above_mbmi->skip) ?
+              num_4x4_blocks_high_lookup[bsize] << 1 :
+              VPXMIN(num_4x4_blocks_high_lookup[bsize],
+                     num_4x4_blocks_high_lookup[above_mbmi->sb_type]) << 1;
+
+    for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
+      const struct macroblockd_plane *pd = &xd->plane[plane];
+      int bw = (mi_step * 8) >> pd->subsampling_x;
+      int bh = overlap >> pd->subsampling_y;
+      int row, col;
+      int dst_stride = use_tmp_dst_buf ? final_stride[plane] : pd->dst.stride;
+      uint8_t *dst = use_tmp_dst_buf ?
+          &final_buf[plane][(i * 8) >> pd->subsampling_x] :
+          &pd->dst.buf[(i * 8) >> pd->subsampling_x];
+      int bmc_stride = pd->dst.stride;
+      uint8_t *bmc = &pd->dst.buf[(i * 8) >> pd->subsampling_x];
+      int tmp_stride = tmp_stride1[plane];
+      uint8_t *tmp = &tmp_buf1[plane][(i * 8) >> pd->subsampling_x];
+      const uint8_t *mask[2];
+
+      setup_obmc_mask(bh, mask);
+
+#if CONFIG_VP9_HIGHBITDEPTH
+      if (is_hbd) {
+        uint16_t *dst16 = CONVERT_TO_SHORTPTR(dst);
+        uint16_t *bmc16 = CONVERT_TO_SHORTPTR(bmc);
+        uint16_t *tmp16 = CONVERT_TO_SHORTPTR(tmp);
+
+        for (row = 0; row < bh; ++row) {
+          for (col = 0; col < bw; ++col) {
+            dst16[col] = (mask[0][row] * bmc16[col] + mask[1][row] * tmp16[col]
+                          + 32) >> 6;
+          }
+          dst16 += dst_stride;
+          bmc16 += bmc_stride;
+          tmp16 += tmp_stride;
+        }
+      } else {
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+      for (row = 0; row < bh; ++row) {
+        for (col = 0; col < bw; ++col) {
+          dst[col] = (mask[0][row] * bmc[col] + mask[1][row] * tmp[col] + 32)
+                     >> 6;
+        }
+        dst += dst_stride;
+        bmc += bmc_stride;
+        tmp += tmp_stride;
+      }
+#if CONFIG_VP9_HIGHBITDEPTH
+      }
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+    }
+  }  // each mi in the above row
+
+  if (mi_col == 0 || (mi_col - 1 < tile->mi_col_start) ||
+      (mi_col - 1) >= tile->mi_col_end)
+    return;
+  // handle left column
+  for (i = 0; i < VPXMIN(xd->n8_h, cm->mi_rows - mi_row);
+       i += mi_step) {
+    int mi_row_offset = i;
+    int mi_col_offset = -1;
+    int overlap;
+    MODE_INFO *left_mi = xd->mi[mi_col_offset +
+                                mi_row_offset * xd->mi_stride];
+    MB_MODE_INFO *left_mbmi = &left_mi->mbmi;
+
+    mi_step = VPXMIN(xd->n8_h,
+                     num_8x8_blocks_high_lookup[left_mbmi->sb_type]);
+
+    if (!is_inter_block(left_mbmi))
+      continue;
+
+    overlap = (left_mbmi->skip) ?
+              num_4x4_blocks_wide_lookup[bsize] << 1 :
+              VPXMIN(num_4x4_blocks_wide_lookup[bsize],
+                     num_4x4_blocks_wide_lookup[left_mbmi->sb_type]) << 1;
+
+    for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
+      const struct macroblockd_plane *pd = &xd->plane[plane];
+      int bw = overlap >> pd->subsampling_x;
+      int bh = (mi_step * 8) >> pd->subsampling_y;
+      int row, col;
+      int dst_stride = use_tmp_dst_buf ? final_stride[plane] : pd->dst.stride;
+      uint8_t *dst = use_tmp_dst_buf ?
+          &final_buf[plane][(i * 8 * dst_stride) >> pd->subsampling_y] :
+          &pd->dst.buf[(i * 8 * dst_stride) >> pd->subsampling_y];
+      int bmc_stride = pd->dst.stride;
+      uint8_t *bmc = &pd->dst.buf[(i * 8 * bmc_stride) >> pd->subsampling_y];
+      int tmp_stride = tmp_stride2[plane];
+      uint8_t *tmp = &tmp_buf2[plane]
+                              [(i * 8 * tmp_stride) >> pd->subsampling_y];
+      const uint8_t *mask[2];
+
+      setup_obmc_mask(bw, mask);
+
+#if CONFIG_VP9_HIGHBITDEPTH
+      if (is_hbd) {
+        uint16_t *dst16 = CONVERT_TO_SHORTPTR(dst);
+        uint16_t *bmc16 = CONVERT_TO_SHORTPTR(bmc);
+        uint16_t *tmp16 = CONVERT_TO_SHORTPTR(tmp);
+
+        for (row = 0; row < bh; ++row) {
+          for (col = 0; col < bw; ++col) {
+            dst16[col] = (mask[0][row] * bmc16[col] + mask[1][row] * tmp16[col]
+                          + 32) >> 6;
+          }
+          dst16 += dst_stride;
+          bmc16 += bmc_stride;
+          tmp16 += tmp_stride;
+        }
+      } else {
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+      for (row = 0; row < bh; ++row) {
+        for (col = 0; col < bw; ++col) {
+          dst[col] = (mask[0][col] * bmc[col] + mask[1][col] * tmp[col] + 32)
+                     >> 6;
+        }
+        dst += dst_stride;
+        bmc += bmc_stride;
+        tmp += tmp_stride;
+      }
+#if CONFIG_VP9_HIGHBITDEPTH
+      }
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+    }
+  }  // each mi in the left column
+}
+#endif  // CONFIG_OBMC
diff --git a/vp10/common/reconinter.h b/vp10/common/reconinter.h
index 3fcdb97..2b36d61 100644
--- a/vp10/common/reconinter.h
+++ b/vp10/common/reconinter.h
@@ -177,7 +177,11 @@
   return res;
 }
 
-void build_inter_predictors(MACROBLOCKD *xd, int plane, int block,
+void build_inter_predictors(MACROBLOCKD *xd, int plane,
+#if CONFIG_OBMC
+                            int mi_col_offset, int mi_row_offset,
+#endif  // CONFIG_OBMC
+                            int block,
                             int bw, int bh,
                             int x, int y, int w, int h,
                             int mi_x, int mi_y);
@@ -352,6 +356,19 @@
   return !intpel_mv;
 }
 #endif  // CONFIG_EXT_INTERP
+
+#if CONFIG_OBMC
+void vp10_build_obmc_inter_prediction(VP10_COMMON *cm,
+                                      MACROBLOCKD *xd, int mi_row, int mi_col,
+                                      int use_tmp_dst_buf,
+                                      uint8_t *final_buf[MAX_MB_PLANE],
+                                      int final_stride[MAX_MB_PLANE],
+                                      uint8_t *tmp_buf1[MAX_MB_PLANE],
+                                      int tmp_stride1[MAX_MB_PLANE],
+                                      uint8_t *tmp_buf2[MAX_MB_PLANE],
+                                      int tmp_stride2[MAX_MB_PLANE]);
+#endif  // CONFIG_OBMC
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif
diff --git a/vp10/decoder/decodeframe.c b/vp10/decoder/decodeframe.c
index 8ed9d2c..a003d7a 100644
--- a/vp10/decoder/decodeframe.c
+++ b/vp10/decoder/decodeframe.c
@@ -657,7 +657,7 @@
       buf_stride, subpel_x, subpel_y;
   uint8_t *ref_frame, *buf_ptr;
 #if CONFIG_EXT_INTERP
-  const int i_filter = IsInterpolatingFilter(xd->mi[0]->mbmi.interp_filter);
+  const int i_filter = IsInterpolatingFilter(interp_filter);
 #endif  // CONFIG_EXT_INTERP
 
   // Get reference frame pointer, width and height.
@@ -699,6 +699,11 @@
     xs = sf->x_step_q4;
     ys = sf->y_step_q4;
   } else {
+#if CONFIG_OBMC
+    const MV mv_q4 = clamp_mv_to_umv_border_sb(xd, mv, bw, bh,
+                                               pd->subsampling_x,
+                                               pd->subsampling_y);
+#endif  // CONFIG_OBMC
     // Co-ordinate of containing block to pixel precision.
     x0 = (-xd->mb_to_left_edge >> (3 + pd->subsampling_x)) + x;
     y0 = (-xd->mb_to_top_edge >> (3 + pd->subsampling_y)) + y;
@@ -707,8 +712,13 @@
     x0_16 = x0 << SUBPEL_BITS;
     y0_16 = y0 << SUBPEL_BITS;
 
+#if CONFIG_OBMC
+    scaled_mv.row = mv_q4.row;
+    scaled_mv.col = mv_q4.col;
+#else
     scaled_mv.row = mv->row * (1 << (1 - pd->subsampling_y));
     scaled_mv.col = mv->col * (1 << (1 - pd->subsampling_x));
+#endif  // CONFIG_OBMC
     xs = ys = 16;
   }
   subpel_x = scaled_mv.col & SUBPEL_MASK;
@@ -871,6 +881,7 @@
     }
   }
 }
+
 #if CONFIG_SUPERTX
 static void dec_build_inter_predictors_sb_sub8x8(VP10Decoder *const pbi,
                                                  MACROBLOCKD *xd,
@@ -914,7 +925,211 @@
     }
   }
 }
-#endif
+#endif  // CONFIG_SUPERTX
+
+#if CONFIG_OBMC
+static void dec_build_prediction_by_above_preds(VP10Decoder *const pbi,
+                                                MACROBLOCKD *xd,
+                                                int mi_row, int mi_col,
+                                                uint8_t *tmp_buf[MAX_MB_PLANE],
+                                                int tmp_stride[MAX_MB_PLANE]) {
+  VP10_COMMON *const cm = &pbi->common;
+  BLOCK_SIZE bsize = xd->mi[0]->mbmi.sb_type;
+  int i, j, mi_step, ref;
+
+  if (mi_row == 0)
+    return;
+
+  for (i = 0; i < VPXMIN(xd->n8_w, cm->mi_cols - mi_col); i += mi_step) {
+    int mi_row_offset = -1;
+    int mi_col_offset = i;
+    int mi_x, mi_y, bw, bh;
+    const MODE_INFO *mi = xd->mi[mi_col_offset + mi_row_offset * cm->mi_stride];
+    const MB_MODE_INFO *mbmi = &mi->mbmi;
+    const BLOCK_SIZE sb_type = mbmi->sb_type;
+    const int is_compound = has_second_ref(mbmi);
+    const INTERP_FILTER interp_filter = mbmi->interp_filter;
+
+    mi_step = VPXMIN(xd->n8_w, num_8x8_blocks_wide_lookup[sb_type]);
+
+    if (!is_inter_block(mbmi))
+      continue;
+
+    for (j = 0; j < MAX_MB_PLANE; ++j) {
+      struct macroblockd_plane *const pd = &xd->plane[j];
+      setup_pred_plane(&pd->dst,
+                       tmp_buf[j], tmp_stride[j],
+                       0, i, NULL,
+                       pd->subsampling_x, pd->subsampling_y);
+    }
+    for (ref = 0; ref < 1 + is_compound; ++ref) {
+      MV_REFERENCE_FRAME frame = mbmi->ref_frame[ref];
+      RefBuffer *ref_buf = &cm->frame_refs[frame - LAST_FRAME];
+
+      xd->block_refs[ref] = ref_buf;
+      if ((!vp10_is_valid_scale(&ref_buf->sf)))
+        vpx_internal_error(xd->error_info, VPX_CODEC_UNSUP_BITSTREAM,
+                           "Reference frame has invalid dimensions");
+      vp10_setup_pre_planes(xd, ref, ref_buf->buf, mi_row, mi_col + i,
+                            &ref_buf->sf);
+    }
+
+    xd->mb_to_left_edge = -(((mi_col + i) * MI_SIZE) * 8);
+    mi_x = (mi_col + i) << MI_SIZE_LOG2;
+    mi_y = mi_row << MI_SIZE_LOG2;
+
+    for (j = 0; j < MAX_MB_PLANE; ++j) {
+      struct macroblockd_plane *pd = &xd->plane[j];
+      struct buf_2d *const dst_buf = &pd->dst;
+      bw = (mi_step * 8) >> pd->subsampling_x;
+      bh = VPXMAX((num_4x4_blocks_high_lookup[bsize] * 2) >> pd->subsampling_y,
+                  4);
+
+      for (ref = 0; ref < 1 + is_compound; ++ref) {
+        const struct scale_factors *const sf = &xd->block_refs[ref]->sf;
+        struct buf_2d *const pre_buf = &pd->pre[ref];
+        const int idx = xd->block_refs[ref]->idx;
+        BufferPool *const pool = pbi->common.buffer_pool;
+        RefCntBuffer *const ref_frame_buf = &pool->frame_bufs[idx];
+        const int is_scaled = vp10_is_scaled(sf);
+
+        if (sb_type < BLOCK_8X8) {
+          const PARTITION_TYPE bp = BLOCK_8X8 - sb_type;
+          const int have_vsplit = bp != PARTITION_HORZ;
+          const int have_hsplit = bp != PARTITION_VERT;
+          const int num_4x4_w = 2 >> ((!have_vsplit) | pd->subsampling_x);
+          const int num_4x4_h = 2 >> ((!have_hsplit) | pd->subsampling_y);
+          const int pw = 8 >> (have_vsplit | pd->subsampling_x);
+          int x, y;
+
+          for (y = 0; y < num_4x4_h; ++y)
+            for (x = 0; x < num_4x4_w; ++x) {
+              const MV mv = average_split_mvs(pd, mi, ref, y * 2 + x);
+              if ((bp == PARTITION_HORZ || bp == PARTITION_SPLIT)
+                  && y == 0 && !pd->subsampling_y)
+                continue;
+
+              dec_build_inter_predictors(pbi, xd, j, bw, bh,
+                                         4 * x, 0, pw, bh, mi_x, mi_y,
+                                         interp_filter, sf, pre_buf, dst_buf,
+                                         &mv, ref_frame_buf, is_scaled, ref);
+            }
+        } else {
+          const MV mv = mi->mbmi.mv[ref].as_mv;
+          dec_build_inter_predictors(pbi, xd, j, bw, bh,
+                                     0, 0, bw, bh, mi_x, mi_y, interp_filter,
+                                     sf, pre_buf, dst_buf, &mv, ref_frame_buf,
+                                     is_scaled, ref);
+        }
+      }
+    }
+  }
+  xd->mb_to_left_edge   = -((mi_col * MI_SIZE) * 8);
+}
+
+static void dec_build_prediction_by_left_preds(VP10Decoder *const pbi,
+                                               MACROBLOCKD *xd,
+                                               int mi_row, int mi_col,
+                                               uint8_t *tmp_buf[MAX_MB_PLANE],
+                                               int tmp_stride[MAX_MB_PLANE]) {
+  VP10_COMMON *const cm = &pbi->common;
+  const TileInfo *const tile = &xd->tile;
+  BLOCK_SIZE bsize = xd->mi[0]->mbmi.sb_type;
+  int i, j, mi_step, ref;
+
+  if (mi_col == 0 || (mi_col - 1 < tile->mi_col_start) ||
+      (mi_col - 1) >= tile->mi_col_end)
+    return;
+
+  for (i = 0; i < VPXMIN(xd->n8_h, cm->mi_rows - mi_row); i += mi_step) {
+    int mi_row_offset = i;
+    int mi_col_offset = -1;
+    int mi_x, mi_y, bw, bh;
+    const MODE_INFO *mi = xd->mi[mi_col_offset + mi_row_offset * cm->mi_stride];
+    const MB_MODE_INFO *mbmi = &mi->mbmi;
+    const BLOCK_SIZE sb_type = mbmi->sb_type;
+    const int is_compound = has_second_ref(mbmi);
+    const INTERP_FILTER interp_filter = mbmi->interp_filter;
+
+    mi_step = VPXMIN(xd->n8_h, num_8x8_blocks_high_lookup[sb_type]);
+
+    if (!is_inter_block(mbmi))
+      continue;
+
+    for (j = 0; j < MAX_MB_PLANE; ++j) {
+      struct macroblockd_plane *const pd = &xd->plane[j];
+      setup_pred_plane(&pd->dst,
+                       tmp_buf[j], tmp_stride[j],
+                       i, 0, NULL,
+                       pd->subsampling_x, pd->subsampling_y);
+    }
+
+    for (ref = 0; ref < 1 + is_compound; ++ref) {
+      MV_REFERENCE_FRAME frame = mbmi->ref_frame[ref];
+      RefBuffer *ref_buf = &cm->frame_refs[frame - LAST_FRAME];
+
+      xd->block_refs[ref] = ref_buf;
+      if ((!vp10_is_valid_scale(&ref_buf->sf)))
+        vpx_internal_error(xd->error_info, VPX_CODEC_UNSUP_BITSTREAM,
+                           "Reference frame has invalid dimensions");
+      vp10_setup_pre_planes(xd, ref, ref_buf->buf, mi_row + i, mi_col,
+                            &ref_buf->sf);
+    }
+
+    xd->mb_to_top_edge    = -(((mi_row + i) * MI_SIZE) * 8);
+    mi_x = mi_col << MI_SIZE_LOG2;
+    mi_y = (mi_row + i) << MI_SIZE_LOG2;
+
+    for (j = 0; j < MAX_MB_PLANE; ++j) {
+      struct macroblockd_plane *pd = &xd->plane[j];
+      struct buf_2d *const dst_buf = &pd->dst;
+      bw = VPXMAX((num_4x4_blocks_wide_lookup[bsize] * 2) >> pd->subsampling_x,
+                  4);
+      bh = (mi_step << MI_SIZE_LOG2) >> pd->subsampling_y;
+
+      for (ref = 0; ref < 1 + is_compound; ++ref) {
+        const struct scale_factors *const sf = &xd->block_refs[ref]->sf;
+        struct buf_2d *const pre_buf = &pd->pre[ref];
+        const int idx = xd->block_refs[ref]->idx;
+        BufferPool *const pool = pbi->common.buffer_pool;
+        RefCntBuffer *const ref_frame_buf = &pool->frame_bufs[idx];
+        const int is_scaled = vp10_is_scaled(sf);
+
+        if (sb_type < BLOCK_8X8) {
+          const PARTITION_TYPE bp = BLOCK_8X8 - sb_type;
+          const int have_vsplit = bp != PARTITION_HORZ;
+          const int have_hsplit = bp != PARTITION_VERT;
+          const int num_4x4_w = 2 >> ((!have_vsplit) | pd->subsampling_x);
+          const int num_4x4_h = 2 >> ((!have_hsplit) | pd->subsampling_y);
+          const int ph = 8 >> (have_hsplit | pd->subsampling_y);
+          int x, y;
+
+          for (y = 0; y < num_4x4_h; ++y)
+            for (x = 0; x < num_4x4_w; ++x) {
+              const MV mv = average_split_mvs(pd, mi, ref, y * 2 + x);
+              if ((bp == PARTITION_VERT || bp == PARTITION_SPLIT)
+                  && x == 0 && !pd->subsampling_x)
+                continue;
+
+              dec_build_inter_predictors(pbi, xd, j, bw, bh,
+                                         0, 4 * y, bw, ph, mi_x, mi_y,
+                                         interp_filter, sf, pre_buf, dst_buf,
+                                         &mv, ref_frame_buf, is_scaled, ref);
+            }
+        } else {
+          const MV mv = mi->mbmi.mv[ref].as_mv;
+          dec_build_inter_predictors(pbi, xd, j, bw, bh,
+                                     0, 0, bw, bh, mi_x, mi_y, interp_filter,
+                                     sf, pre_buf, dst_buf, &mv, ref_frame_buf,
+                                     is_scaled, ref);
+        }
+      }
+    }
+  }
+  xd->mb_to_top_edge    = -((mi_row * MI_SIZE) * 8);
+}
+#endif  // CONFIG_OBMC
+
 static INLINE TX_SIZE dec_get_uv_tx_size(const MB_MODE_INFO *mbmi,
                                          int n4_wl, int n4_hl) {
   // get minimum log2 num4x4s dimension
@@ -1638,6 +1853,52 @@
     } else {
       // Prediction
       dec_build_inter_predictors_sb(pbi, xd, mi_row, mi_col);
+#if CONFIG_OBMC
+      if (mbmi->obmc) {
+#if CONFIG_VP9_HIGHBITDEPTH
+        DECLARE_ALIGNED(16, uint8_t, tmp_buf1[2 * MAX_MB_PLANE * 64 * 64]);
+        DECLARE_ALIGNED(16, uint8_t, tmp_buf2[2 * MAX_MB_PLANE * 64 * 64]);
+#else
+        DECLARE_ALIGNED(16, uint8_t, tmp_buf1[MAX_MB_PLANE * 64 * 64]);
+        DECLARE_ALIGNED(16, uint8_t, tmp_buf2[MAX_MB_PLANE * 64 * 64]);
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+        uint8_t *dst_buf1[MAX_MB_PLANE], *dst_buf2[MAX_MB_PLANE];
+        int dst_stride1[MAX_MB_PLANE] = {64, 64, 64};
+        int dst_stride2[MAX_MB_PLANE] = {64, 64, 64};
+
+        assert(mbmi->sb_type >= BLOCK_8X8);
+#if CONFIG_VP9_HIGHBITDEPTH
+        if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
+          int len = sizeof(uint16_t);
+          dst_buf1[0] = CONVERT_TO_BYTEPTR(tmp_buf1);
+          dst_buf1[1] = CONVERT_TO_BYTEPTR(tmp_buf1 + 4096 * len);
+          dst_buf1[2] = CONVERT_TO_BYTEPTR(tmp_buf1 + 8192 * len);
+          dst_buf2[0] = CONVERT_TO_BYTEPTR(tmp_buf2);
+          dst_buf2[1] = CONVERT_TO_BYTEPTR(tmp_buf2 + 4096 * len);
+          dst_buf2[2] = CONVERT_TO_BYTEPTR(tmp_buf2 + 8192 * len);
+        } else {
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+        dst_buf1[0] = tmp_buf1;
+        dst_buf1[1] = tmp_buf1 + 4096;
+        dst_buf1[2] = tmp_buf1 + 8192;
+        dst_buf2[0] = tmp_buf2;
+        dst_buf2[1] = tmp_buf2 + 4096;
+        dst_buf2[2] = tmp_buf2 + 8192;
+#if CONFIG_VP9_HIGHBITDEPTH
+        }
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+
+        dec_build_prediction_by_above_preds(pbi, xd, mi_row, mi_col,
+                                            dst_buf1, dst_stride1);
+        dec_build_prediction_by_left_preds(pbi, xd, mi_row, mi_col,
+                                           dst_buf2, dst_stride2);
+        vp10_setup_dst_planes(xd->plane, get_frame_new_buffer(cm),
+                              mi_row, mi_col);
+        vp10_build_obmc_inter_prediction(cm, xd, mi_row, mi_col, 0, NULL, NULL,
+                                         dst_buf1, dst_stride1,
+                                         dst_buf2, dst_stride2);
+      }
+#endif  // CONFIG_OBMC
 
       // Reconstruction
       if (!mbmi->skip) {
@@ -3313,6 +3574,11 @@
     read_inter_compound_mode_probs(fc, &r);
 #endif  // CONFIG_EXT_INTER
 
+#if CONFIG_OBMC
+    for (i = BLOCK_8X8; i < BLOCK_SIZES; ++i)
+      vp10_diff_update_prob(&r, &fc->obmc_prob[i]);
+#endif  // CONFIG_OBMC
+
     if (cm->interp_filter == SWITCHABLE)
       read_switchable_interp_probs(fc, &r);
 
@@ -3367,6 +3633,10 @@
                  zero_counts.inter_compound_mode,
                  sizeof(cm->counts.inter_compound_mode)));
 #endif  // CONFIG_EXT_INTER
+#if CONFIG_OBMC
+  assert(!memcmp(cm->counts.obmc, zero_counts.obmc,
+                 sizeof(cm->counts.obmc)));
+#endif  // CONFIG_OBMC
   assert(!memcmp(cm->counts.intra_inter, zero_counts.intra_inter,
                  sizeof(cm->counts.intra_inter)));
   assert(!memcmp(cm->counts.comp_inter, zero_counts.comp_inter,
diff --git a/vp10/decoder/decodemv.c b/vp10/decoder/decodemv.c
index 78ddf1a..f9ed5a5 100644
--- a/vp10/decoder/decodemv.c
+++ b/vp10/decoder/decodemv.c
@@ -156,7 +156,7 @@
   mbmi->ref_mv_idx = 0;
 
   if (xd->ref_mv_count[ref_frame_type] > 2) {
-    uint8_t drl0_ctx = vp10_drl_ctx(xd->ref_mv_stack[ref_frame_type], 0);
+    uint8_t drl0_ctx = vp10_drl_ctx(xd->ref_mv_stack[ref_frame_type], 1);
     vpx_prob drl0_prob = cm->fc->drl_prob0[drl0_ctx];
     if (vpx_read(r, drl0_prob)) {
       mbmi->ref_mv_idx = 1;
@@ -164,7 +164,7 @@
         ++xd->counts->drl_mode0[drl0_ctx][1];
       if (xd->ref_mv_count[ref_frame_type] > 3) {
         uint8_t drl1_ctx =
-            vp10_drl_ctx(xd->ref_mv_stack[ref_frame_type], 1);
+            vp10_drl_ctx(xd->ref_mv_stack[ref_frame_type], 2);
         vpx_prob drl1_prob = cm->fc->drl_prob1[drl1_ctx];
         if (vpx_read(r, drl1_prob)) {
           mbmi->ref_mv_idx = 2;
@@ -778,6 +778,24 @@
 }
 
 
+#if CONFIG_OBMC
+static int read_is_obmc_block(VP10_COMMON *const cm, MACROBLOCKD *const xd,
+                              vpx_reader *r) {
+  BLOCK_SIZE bsize = xd->mi[0]->mbmi.sb_type;
+  FRAME_COUNTS *counts = xd->counts;
+  int is_obmc;
+
+  if (is_obmc_allowed(&xd->mi[0]->mbmi)) {
+    is_obmc = vpx_read(r, cm->fc->obmc_prob[bsize]);
+    if (counts)
+      ++counts->obmc[bsize][is_obmc];
+    return is_obmc;
+  } else {
+    return 0;
+  }
+}
+#endif  // CONFIG_OBMC
+
 static INLINE INTERP_FILTER read_switchable_interp_filter(
     VP10_COMMON *const cm, MACROBLOCKD *const xd,
     vpx_reader *r) {
@@ -1016,7 +1034,12 @@
 static void read_inter_block_mode_info(VP10Decoder *const pbi,
                                        MACROBLOCKD *const xd,
                                        MODE_INFO *const mi,
+#if CONFIG_OBMC && CONFIG_SUPERTX
+                                       int mi_row, int mi_col, vpx_reader *r,
+                                       int supertx_enabled) {
+#else
                                        int mi_row, int mi_col, vpx_reader *r) {
+#endif  // CONFIG_OBMC && CONFIG_SUPERTX
   VP10_COMMON *const cm = &pbi->common;
   MB_MODE_INFO *const mbmi = &mi->mbmi;
   const BLOCK_SIZE bsize = mbmi->sb_type;
@@ -1062,6 +1085,13 @@
                       mi_row, mi_col, fpm_sync, (void *)pbi, inter_mode_ctx);
   }
 
+#if CONFIG_OBMC
+#if CONFIG_SUPERTX
+  if (!supertx_enabled)
+#endif  // CONFIG_SUPERTX
+  mbmi->obmc = read_is_obmc_block(cm, xd, r);
+#endif  // CONFIG_OBMC
+
 #if CONFIG_REF_MV
 #if CONFIG_EXT_INTER
   if (is_compound)
@@ -1365,14 +1395,19 @@
     xd->mi[0]->mbmi.tx_size = xd->supertx_size;
     for (idy = 0; idy < height; ++idy)
       for (idx = 0; idx < width; ++idx)
-        xd->mi[0]->mbmi.inter_tx_size[(idy >> 1) * 8 + (idx >> 1)] = xd->supertx_size;
+        xd->mi[0]->mbmi.inter_tx_size[(idy >> 1) * 8 + (idx >> 1)] =
+            xd->supertx_size;
   }
 #endif  // CONFIG_VAR_TX
 #endif  // CONFIG_SUPERTX
 
   if (inter_block)
     read_inter_block_mode_info(pbi, xd,
+#if CONFIG_OBMC && CONFIG_SUPERTX
+                               mi, mi_row, mi_col, r, supertx_enabled);
+#else
                                mi, mi_row, mi_col, r);
+#endif  // CONFIG_OBMC && CONFIG_SUPERTX
   else
     read_intra_block_mode_info(cm, xd, mi, r);
 
diff --git a/vp10/encoder/bitstream.c b/vp10/encoder/bitstream.c
index 1c59b35..b786b5c 100644
--- a/vp10/encoder/bitstream.c
+++ b/vp10/encoder/bitstream.c
@@ -185,13 +185,13 @@
   uint8_t ref_frame_type = vp10_ref_frame_type(mbmi->ref_frame);
   if (mbmi_ext->ref_mv_count[ref_frame_type] > 2) {
     uint8_t drl0_ctx =
-        vp10_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], 0);
+        vp10_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], 1);
     vpx_prob drl0_prob = cm->fc->drl_prob0[drl0_ctx];
     vpx_write(w, mbmi->ref_mv_idx != 0, drl0_prob);
     if (mbmi_ext->ref_mv_count[ref_frame_type] > 3 &&
         mbmi->ref_mv_idx > 0) {
       uint8_t drl1_ctx =
-          vp10_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], 1);
+          vp10_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], 2);
       vpx_prob drl1_prob = cm->fc->drl_prob1[drl1_ctx];
       vpx_write(w, mbmi->ref_mv_idx != 1, drl1_prob);
     }
@@ -995,6 +995,13 @@
   } else {
     int16_t mode_ctx = mbmi_ext->mode_context[mbmi->ref_frame[0]];
     write_ref_frames(cm, xd, w);
+#if CONFIG_OBMC
+#if CONFIG_SUPERTX
+    if (!supertx_enabled)
+#endif  // CONFIG_SUPERTX
+    if (is_obmc_allowed(mbmi))
+      vpx_write(w, mbmi->obmc, cm->fc->obmc_prob[bsize]);
+#endif  // CONFIG_OBMC
 
 #if CONFIG_REF_MV
 #if CONFIG_EXT_INTER
@@ -2395,6 +2402,12 @@
     update_inter_compound_mode_probs(cm, &header_bc);
 #endif  // CONFIG_EXT_INTER
 
+#if CONFIG_OBMC
+    for (i = BLOCK_8X8; i < BLOCK_SIZES; ++i)
+      vp10_cond_prob_diff_update(&header_bc, &fc->obmc_prob[i],
+                                 counts->obmc[i]);
+#endif  // CONFIG_OBMC
+
     if (cm->interp_filter == SWITCHABLE)
       update_switchable_interp_probs(cm, &header_bc, counts);
 
diff --git a/vp10/encoder/block.h b/vp10/encoder/block.h
index 3e322de..3c49d14 100644
--- a/vp10/encoder/block.h
+++ b/vp10/encoder/block.h
@@ -81,8 +81,14 @@
   int skip_optimize;
   int q_index;
 
+  // The equivalent error at the current rdmult of one whole bit (not one
+  // bitcost unit).
   int errorperbit;
+  // The equivalend SAD error of one (whole) bit at the current quantizer
+  // for large blocks.
   int sadperbit16;
+  // The equivalend SAD error of one (whole) bit at the current quantizer
+  // for sub-8x8 blocks.
   int sadperbit4;
   int rddiv;
   int rdmult;
diff --git a/vp10/encoder/cost.c b/vp10/encoder/cost.c
index ded51d3..7e33edf 100644
--- a/vp10/encoder/cost.c
+++ b/vp10/encoder/cost.c
@@ -12,29 +12,32 @@
 #include "vp10/encoder/cost.h"
 #include "vp10/common/entropy.h"
 
-const unsigned int vp10_prob_cost[256] = {
-  2047, 2047, 1791, 1641, 1535, 1452, 1385, 1328, 1279, 1235, 1196, 1161,
-  1129, 1099, 1072, 1046, 1023, 1000, 979,  959,  940,  922,  905,  889,
-  873,  858,  843,  829,  816,  803,  790,  778,  767,  755,  744,  733,
-  723,  713,  703,  693,  684,  675,  666,  657,  649,  641,  633,  625,
-  617,  609,  602,  594,  587,  580,  573,  567,  560,  553,  547,  541,
-  534,  528,  522,  516,  511,  505,  499,  494,  488,  483,  477,  472,
-  467,  462,  457,  452,  447,  442,  437,  433,  428,  424,  419,  415,
-  410,  406,  401,  397,  393,  389,  385,  381,  377,  373,  369,  365,
-  361,  357,  353,  349,  346,  342,  338,  335,  331,  328,  324,  321,
-  317,  314,  311,  307,  304,  301,  297,  294,  291,  288,  285,  281,
-  278,  275,  272,  269,  266,  263,  260,  257,  255,  252,  249,  246,
-  243,  240,  238,  235,  232,  229,  227,  224,  221,  219,  216,  214,
-  211,  208,  206,  203,  201,  198,  196,  194,  191,  189,  186,  184,
-  181,  179,  177,  174,  172,  170,  168,  165,  163,  161,  159,  156,
-  154,  152,  150,  148,  145,  143,  141,  139,  137,  135,  133,  131,
-  129,  127,  125,  123,  121,  119,  117,  115,  113,  111,  109,  107,
-  105,  103,  101,  99,   97,   95,   93,   92,   90,   88,   86,   84,
-  82,   81,   79,   77,   75,   73,   72,   70,   68,   66,   65,   63,
-  61,   60,   58,   56,   55,   53,   51,   50,   48,   46,   45,   43,
-  41,   40,   38,   37,   35,   33,   32,   30,   29,   27,   25,   24,
-  22,   21,   19,   18,   16,   15,   13,   12,   10,   9,    7,    6,
-  4,    3,    1,    1};
+/* round(-log2(i/256.) * (1 << VP9_PROB_COST_SHIFT))
+   Begins and ends with a bogus entry to satisfy use of prob=0 in the firstpass.
+   https://code.google.com/p/webm/issues/detail?id=1089 */
+const uint16_t vp10_prob_cost[257] = {
+    4096, 4096, 3584, 3284, 3072, 2907, 2772, 2659, 2560, 2473, 2395, 2325,
+    2260, 2201, 2147, 2096, 2048, 2003, 1961, 1921, 1883, 1847, 1813, 1780,
+    1748, 1718, 1689, 1661, 1635, 1609, 1584, 1559, 1536, 1513, 1491, 1470,
+    1449, 1429, 1409, 1390, 1371, 1353, 1335, 1318, 1301, 1284, 1268, 1252,
+    1236, 1221, 1206, 1192, 1177, 1163, 1149, 1136, 1123, 1110, 1097, 1084,
+    1072, 1059, 1047, 1036, 1024, 1013, 1001, 990,  979,  968,  958,  947,
+    937,  927,  917,  907,  897,  887,  878,  868,  859,  850,  841,  832,
+    823,  814,  806,  797,  789,  780,  772,  764,  756,  748,  740,  732,
+    724,  717,  709,  702,  694,  687,  680,  673,  665,  658,  651,  644,
+    637,  631,  624,  617,  611,  604,  598,  591,  585,  578,  572,  566,
+    560,  554,  547,  541,  535,  530,  524,  518,  512,  506,  501,  495,
+    489,  484,  478,  473,  467,  462,  456,  451,  446,  441,  435,  430,
+    425,  420,  415,  410,  405,  400,  395,  390,  385,  380,  375,  371,
+    366,  361,  356,  352,  347,  343,  338,  333,  329,  324,  320,  316,
+    311,  307,  302,  298,  294,  289,  285,  281,  277,  273,  268,  264,
+    260,  256,  252,  248,  244,  240,  236,  232,  228,  224,  220,  216,
+    212,  209,  205,  201,  197,  194,  190,  186,  182,  179,  175,  171,
+    168,  164,  161,  157,  153,  150,  146,  143,  139,  136,  132,  129,
+    125,  122,  119,  115,  112,  109,  105,  102,  99,   95,   92,   89,
+    86,   82,   79,   76,   73,   70,   66,   63,   60,   57,   54,   51,
+    48,   45,   42,   38,   35,   32,   29,   26,   23,   20,   18,   15,
+    12,   9,    6,    3,     3};
 
 static void cost(int *costs, vpx_tree tree, const vpx_prob *probs,
                  int i, int c) {
diff --git a/vp10/encoder/cost.h b/vp10/encoder/cost.h
index 551e4e5..d4a9efb 100644
--- a/vp10/encoder/cost.h
+++ b/vp10/encoder/cost.h
@@ -12,18 +12,22 @@
 #define VP10_ENCODER_COST_H_
 
 #include "vpx_dsp/prob.h"
+#include "vpx/vpx_integer.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-extern const unsigned int vp10_prob_cost[256];
+extern const uint16_t vp10_prob_cost[257];
+
+// The factor to scale from cost in bits to cost in vp10_prob_cost units.
+#define VP9_PROB_COST_SHIFT 9
 
 #define vp10_cost_zero(prob) (vp10_prob_cost[prob])
 
-#define vp10_cost_one(prob) vp10_cost_zero(vpx_complement(prob))
+#define vp10_cost_one(prob) vp10_cost_zero(256 - (prob))
 
-#define vp10_cost_bit(prob, bit) vp10_cost_zero((bit) ? vpx_complement(prob) \
+#define vp10_cost_bit(prob, bit) vp10_cost_zero((bit) ? 256 - (prob) \
                                                     : (prob))
 
 static INLINE unsigned int cost_branch256(const unsigned int ct[2],
diff --git a/vp10/encoder/encodeframe.c b/vp10/encoder/encodeframe.c
index 185dcbb..755c33b 100644
--- a/vp10/encoder/encodeframe.c
+++ b/vp10/encoder/encodeframe.c
@@ -1801,6 +1801,13 @@
                               [ref0 != GOLDEN_FRAME]++;
 #endif  // CONFIG_EXT_REFS
         }
+#if CONFIG_OBMC
+#if CONFIG_SUPERTX
+        if (!supertx_enabled)
+#endif  // CONFIG_SUPERTX
+        if (is_obmc_allowed(mbmi))
+          counts->obmc[mbmi->sb_type][mbmi->obmc]++;
+#endif  // CONFIG_OBMC
       }
     }
     if (inter_block &&
@@ -1827,7 +1834,7 @@
           uint8_t ref_frame_type = vp10_ref_frame_type(mbmi->ref_frame);
           if (mbmi_ext->ref_mv_count[ref_frame_type] > 2) {
             uint8_t drl0_ctx =
-                vp10_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], 0);
+                vp10_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], 1);
             if (mbmi->ref_mv_idx == 0)
               ++counts->drl_mode0[drl0_ctx][0];
             else
@@ -1836,7 +1843,7 @@
             if (mbmi_ext->ref_mv_count[ref_frame_type] > 3 &&
                 mbmi->ref_mv_idx > 0) {
               uint8_t drl1_ctx =
-                  vp10_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], 1);
+                  vp10_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], 2);
               if (mbmi->ref_mv_idx == 1)
                 ++counts->drl_mode1[drl1_ctx][0];
               else
@@ -4421,6 +4428,55 @@
     vp10_build_inter_predictors_sbuv(xd, mi_row, mi_col,
                                      VPXMAX(bsize, BLOCK_8X8));
 
+#if CONFIG_OBMC
+    if (mbmi->obmc) {
+#if CONFIG_VP9_HIGHBITDEPTH
+      DECLARE_ALIGNED(16, uint8_t, tmp_buf1[2 * MAX_MB_PLANE * 64 * 64]);
+      DECLARE_ALIGNED(16, uint8_t, tmp_buf2[2 * MAX_MB_PLANE * 64 * 64]);
+#else
+      DECLARE_ALIGNED(16, uint8_t, tmp_buf1[MAX_MB_PLANE * 64 * 64]);
+      DECLARE_ALIGNED(16, uint8_t, tmp_buf2[MAX_MB_PLANE * 64 * 64]);
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+      uint8_t *dst_buf1[MAX_MB_PLANE], *dst_buf2[MAX_MB_PLANE];
+      int dst_stride1[MAX_MB_PLANE] = {64, 64, 64};
+      int dst_stride2[MAX_MB_PLANE] = {64, 64, 64};
+
+      assert(mbmi->sb_type >= BLOCK_8X8);
+
+#if CONFIG_VP9_HIGHBITDEPTH
+      if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
+        int len = sizeof(uint16_t);
+        dst_buf1[0] = CONVERT_TO_BYTEPTR(tmp_buf1);
+        dst_buf1[1] = CONVERT_TO_BYTEPTR(tmp_buf1 + 4096 * len);
+        dst_buf1[2] = CONVERT_TO_BYTEPTR(tmp_buf1 + 8192 * len);
+        dst_buf2[0] = CONVERT_TO_BYTEPTR(tmp_buf2);
+        dst_buf2[1] = CONVERT_TO_BYTEPTR(tmp_buf2 + 4096 * len);
+        dst_buf2[2] = CONVERT_TO_BYTEPTR(tmp_buf2 + 8192 * len);
+      } else {
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+      dst_buf1[0] = tmp_buf1;
+      dst_buf1[1] = tmp_buf1 + 4096;
+      dst_buf1[2] = tmp_buf1 + 8192;
+      dst_buf2[0] = tmp_buf2;
+      dst_buf2[1] = tmp_buf2 + 4096;
+      dst_buf2[2] = tmp_buf2 + 8192;
+#if CONFIG_VP9_HIGHBITDEPTH
+      }
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+
+      vp10_build_prediction_by_above_preds(cpi, xd, mi_row, mi_col, dst_buf1,
+                                           dst_stride1);
+      vp10_build_prediction_by_left_preds(cpi, xd, mi_row, mi_col, dst_buf2,
+                                          dst_stride2);
+      vp10_setup_dst_planes(xd->plane, get_frame_new_buffer(cm),
+                            mi_row, mi_col);
+      vp10_build_obmc_inter_prediction(cm, xd, mi_row, mi_col, 0, NULL, NULL,
+                                       dst_buf1, dst_stride1,
+                                       dst_buf2, dst_stride2);
+    }
+
+#endif  // CONFIG_OBMC
+
     vp10_encode_sb(x, VPXMAX(bsize, BLOCK_8X8));
 #if CONFIG_VAR_TX
     vp10_tokenize_sb_inter(cpi, td, t, !output_enabled,
diff --git a/vp10/encoder/encodemb.c b/vp10/encoder/encodemb.c
index e359b93..700088c 100644
--- a/vp10/encoder/encodemb.c
+++ b/vp10/encoder/encodemb.c
@@ -52,7 +52,9 @@
                      pd->dst.buf, pd->dst.stride);
 }
 
-#define RDTRUNC(RM, DM, R, D) ((128 + (R) * (RM)) & 0xFF)
+#define RDTRUNC(RM, DM, R, D)                        \
+  (((1 << (VP9_PROB_COST_SHIFT - 1)) + (R) * (RM)) & \
+   ((1 << VP9_PROB_COST_SHIFT) - 1))
 
 typedef struct vp10_token_state {
   int           rate;
@@ -119,9 +121,9 @@
   EXTRABIT e0;
   int best, band, pt, i, final_eob;
 #if CONFIG_VP9_HIGHBITDEPTH
-  const int16_t *cat6_high_cost = vp10_get_high_cost_table(xd->bd);
+  const int *cat6_high_cost = vp10_get_high_cost_table(xd->bd);
 #else
-  const int16_t *cat6_high_cost = vp10_get_high_cost_table(8);
+  const int *cat6_high_cost = vp10_get_high_cost_table(8);
 #endif
 
   assert((!type && !plane) || (type && plane));
diff --git a/vp10/encoder/encoder.h b/vp10/encoder/encoder.h
index 8faf4ed..cc20765 100644
--- a/vp10/encoder/encoder.h
+++ b/vp10/encoder/encoder.h
@@ -479,6 +479,9 @@
   unsigned int inter_compound_mode_cost[INTER_MODE_CONTEXTS]
                                        [INTER_COMPOUND_MODES];
 #endif  // CONFIG_EXT_INTER
+#if CONFIG_OBMC
+  int obmc_cost[BLOCK_SIZES][2];
+#endif  // CONFIG_OBMC
   int intra_uv_mode_cost[INTRA_MODES][INTRA_MODES];
   int y_mode_costs[INTRA_MODES][INTRA_MODES][INTRA_MODES];
   int switchable_interp_costs[SWITCHABLE_FILTER_CONTEXTS][SWITCHABLE_FILTERS];
diff --git a/vp10/encoder/mcomp.c b/vp10/encoder/mcomp.c
index 2c1c591..dd19e02 100644
--- a/vp10/encoder/mcomp.c
+++ b/vp10/encoder/mcomp.c
@@ -80,24 +80,29 @@
   return ROUND_POWER_OF_TWO(mv_cost(&diff, mvjcost, mvcost) * weight, 7);
 }
 
-static int mv_err_cost(const MV *mv, const MV *ref,
-                       const int *mvjcost, int *mvcost[2],
-                       int error_per_bit) {
+#define PIXEL_TRANSFORM_ERROR_SCALE 4
+static int mv_err_cost(const MV *mv, const MV *ref, const int *mvjcost,
+                       int *mvcost[2], int error_per_bit) {
   if (mvcost) {
-    const MV diff = { mv->row - ref->row,
-                      mv->col - ref->col };
-    return ROUND_POWER_OF_TWO(mv_cost(&diff, mvjcost, mvcost) *
-                                  error_per_bit, 13);
+    const MV diff = {mv->row - ref->row, mv->col - ref->col};
+    // This product sits at a 32-bit ceiling right now and any additional
+    // accuracy in either bit cost or error cost will cause it to overflow.
+    return ROUND_POWER_OF_TWO(
+        (unsigned)mv_cost(&diff, mvjcost, mvcost) * error_per_bit,
+        RDDIV_BITS + VP9_PROB_COST_SHIFT - RD_EPB_SHIFT +
+            PIXEL_TRANSFORM_ERROR_SCALE);
   }
   return 0;
 }
 
 static int mvsad_err_cost(const MACROBLOCK *x, const MV *mv, const MV *ref,
-                          int error_per_bit) {
+                          int sad_per_bit) {
   const MV diff = { mv->row - ref->row,
                     mv->col - ref->col };
-  return ROUND_POWER_OF_TWO(mv_cost(&diff, x->nmvjointsadcost,
-                                    x->nmvsadcost) * error_per_bit, 8);
+  return ROUND_POWER_OF_TWO(
+      (unsigned)mv_cost(&diff, x->nmvjointsadcost, x->nmvsadcost) *
+          sad_per_bit,
+      VP9_PROB_COST_SHIFT);
 }
 
 void vp10_init_dsmotion_compensation(search_site_config *cfg, int stride) {
@@ -155,12 +160,13 @@
  * could reduce the area.
  */
 
-/* estimated cost of a motion vector (r,c) */
-#define MVC(r, c)                                       \
-    (mvcost ?                                           \
-     ((mvjcost[((r) != rr) * 2 + ((c) != rc)] +         \
-       mvcost[0][((r) - rr)] + mvcost[1][((c) - rc)]) * \
-      error_per_bit + 4096) >> 13 : 0)
+/* Estimated (square) error cost of a motion vector (r,c). The 14 scale comes
+ * from the same math as in mv_err_cost(). */
+#define MVC(r, c)                                              \
+    (mvcost ?                                                  \
+     ((unsigned)(mvjcost[((r) != rr) * 2 + ((c) != rc)] +      \
+       mvcost[0][((r) - rr)] + mvcost[1][((c) - rc)]) *        \
+      error_per_bit + 8192) >> 14 : 0)
 
 
 // convert motion vector component to offset for sv[a]f calc
@@ -852,9 +858,9 @@
       cost_list[i + 1] = fn_ptr->vf(what->buf, what->stride,
                                     get_buf_from_mv(in_what, &this_mv),
                                     in_what->stride, &sse) +
-          // mvsad_err_cost(x, &this_mv, &fcenter_mv, sadpb);
-          mv_err_cost(&this_mv, &fcenter_mv, x->nmvjointcost, x->mvcost,
-                      x->errorperbit);
+                                    mv_err_cost(&this_mv, &fcenter_mv,
+                                                x->nmvjointcost, x->mvcost,
+                                                x->errorperbit);
     }
   } else {
     for (i = 0; i < 4; i++) {
@@ -866,9 +872,9 @@
         cost_list[i + 1] = fn_ptr->vf(what->buf, what->stride,
                                       get_buf_from_mv(in_what, &this_mv),
                                       in_what->stride, &sse) +
-            // mvsad_err_cost(x, &this_mv, &fcenter_mv, sadpb);
-            mv_err_cost(&this_mv, &fcenter_mv, x->nmvjointcost, x->mvcost,
-                        x->errorperbit);
+                                      mv_err_cost(&this_mv, &fcenter_mv,
+                                                  x->nmvjointcost, x->mvcost,
+                                                  x->errorperbit);
     }
   }
 }
diff --git a/vp10/encoder/quantize.c b/vp10/encoder/quantize.c
index 66db396..f8a59ec 100644
--- a/vp10/encoder/quantize.c
+++ b/vp10/encoder/quantize.c
@@ -519,8 +519,7 @@
   x->skip_block = segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP);
   x->q_index = qindex;
 
-  x->errorperbit = rdmult >> 6;
-  x->errorperbit += (x->errorperbit == 0);
+  set_error_per_bit(x, rdmult);
 
   vp10_initialize_me_consts(cpi, x, x->q_index);
 }
diff --git a/vp10/encoder/rd.c b/vp10/encoder/rd.c
index 8498ce9..bf73064 100644
--- a/vp10/encoder/rd.c
+++ b/vp10/encoder/rd.c
@@ -41,7 +41,6 @@
 #include "vp10/encoder/tokenize.h"
 
 #define RD_THRESH_POW      1.25
-#define RD_MULT_EPB_RATIO  64
 
 // Factor to weigh the rate for switchable interp filters.
 #define SWITCHABLE_INTERP_RATE_FACTOR 1
@@ -343,8 +342,7 @@
   rd->RDDIV = RDDIV_BITS;  // In bits (to multiply D by 128).
   rd->RDMULT = vp10_compute_rd_mult(cpi, cm->base_qindex + cm->y_dc_delta_q);
 
-  x->errorperbit = rd->RDMULT / RD_MULT_EPB_RATIO;
-  x->errorperbit += (x->errorperbit == 0);
+  set_error_per_bit(x, rd->RDMULT);
 
   x->select_tx_size = (cpi->sf.tx_size_search_method == USE_LARGESTALL &&
                        cm->frame_type != KEY_FRAME) ? 0 : 1;
@@ -407,6 +405,12 @@
                        cm->fc->inter_compound_mode_probs[i],
                        vp10_inter_compound_mode_tree);
 #endif  // CONFIG_EXT_INTER
+#if CONFIG_OBMC
+    for (i = BLOCK_8X8; i < BLOCK_SIZES; i++) {
+      cpi->obmc_cost[i][0] = vp10_cost_bit(cm->fc->obmc_prob[i], 0);
+      cpi->obmc_cost[i][1] = vp10_cost_bit(cm->fc->obmc_prob[i], 1);
+    }
+#endif  // CONFIG_OBMC
   }
 }
 
@@ -504,7 +508,7 @@
         (((uint64_t)qstep * qstep << (n_log2 + 10)) + (var >> 1)) / var;
     const int xsq_q10 = (int)VPXMIN(xsq_q10_64, MAX_XSQ_Q10);
     model_rd_norm(xsq_q10, &r_q10, &d_q10);
-    *rate = ((r_q10 << n_log2) + 2) >> 2;
+    *rate = ROUND_POWER_OF_TWO(r_q10 << n_log2, 10 - VP9_PROB_COST_SHIFT);
     *dist = (var * (int64_t)d_q10 + 512) >> 10;
   }
 }
diff --git a/vp10/encoder/rd.h b/vp10/encoder/rd.h
index 2303c20..5d6f8e6 100644
--- a/vp10/encoder/rd.h
+++ b/vp10/encoder/rd.h
@@ -17,18 +17,21 @@
 
 #include "vp10/encoder/block.h"
 #include "vp10/encoder/context_tree.h"
+#include "vp10/encoder/cost.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 #define RDDIV_BITS          7
+#define RD_EPB_SHIFT        6
 
 #define RDCOST(RM, DM, R, D) \
-  (((128 + ((int64_t)R) * (RM)) >> 8) + (D << DM))
+  (ROUND_POWER_OF_TWO(((int64_t)R) * (RM), VP9_PROB_COST_SHIFT) + (D << DM))
 
-#define RDCOST_DBL(RM, DM, R, D) \
-  (((((double)(R)) * (RM)) / 256.0) + ((double)(D)  * (1 << (DM))))
+#define RDCOST_DBL(RM, DM, R, D)                                   \
+  (((((double)(R)) * (RM)) / (double)(1 << VP9_PROB_COST_SHIFT)) + \
+   ((double)(D) * (1 << (DM))))
 
 #define QIDX_SKIP_THRESH     115
 
@@ -310,6 +313,11 @@
                  uint8_t *ref_y_buffer, int ref_y_stride,
                  int ref_frame, BLOCK_SIZE block_size);
 
+static INLINE void set_error_per_bit(MACROBLOCK *x, int rdmult) {
+  x->errorperbit = rdmult >> RD_EPB_SHIFT;
+  x->errorperbit += (x->errorperbit == 0);
+}
+
 void vp10_setup_pred_block(const MACROBLOCKD *xd,
                           struct buf_2d dst[MAX_MB_PLANE],
                           const YV12_BUFFER_CONFIG *src,
diff --git a/vp10/encoder/rdopt.c b/vp10/encoder/rdopt.c
index 78aa590..a025be8 100644
--- a/vp10/encoder/rdopt.c
+++ b/vp10/encoder/rdopt.c
@@ -411,7 +411,7 @@
       int quantizer = (pd->dequant[1] >> dequant_shift);
 
       if (quantizer < 120)
-        rate = (square_error * (280 - quantizer)) >> 8;
+        rate = (square_error * (280 - quantizer)) >> (16 - VP9_PROB_COST_SHIFT);
       else
         rate = 0;
       dist = (square_error * quantizer) >> 8;
@@ -523,9 +523,9 @@
 #endif
   int c, cost;
 #if CONFIG_VP9_HIGHBITDEPTH
-  const int16_t *cat6_high_cost = vp10_get_high_cost_table(xd->bd);
+  const int *cat6_high_cost = vp10_get_high_cost_table(xd->bd);
 #else
-  const int16_t *cat6_high_cost = vp10_get_high_cost_table(8);
+  const int *cat6_high_cost = vp10_get_high_cost_table(8);
 #endif
 
 #if !CONFIG_VAR_TX && !CONFIG_SUPERTX
@@ -654,27 +654,31 @@
   if (!is_inter_block(mbmi)) {
     struct encode_b_args arg = {x, NULL, &mbmi->skip};
 #if CONFIG_VAR_TX
-    uint8_t *dst, *src;
-    int src_stride = x->plane[plane].src.stride;
-    int dst_stride = xd->plane[plane].dst.stride;
-    unsigned int tmp_sse;
-    PREDICTION_MODE mode = (plane == 0) ?
-        get_y_mode(xd->mi[0], block) : mbmi->uv_mode;
-
-    src = &x->plane[plane].src.buf[4 * (blk_row * src_stride + blk_col)];
-    dst = &xd->plane[plane].dst.buf[4 * (blk_row * dst_stride + blk_col)];
-    vp10_predict_intra_block(xd, b_width_log2_lookup[plane_bsize],
-                             b_height_log2_lookup[plane_bsize],
-                             tx_size, mode, dst, dst_stride,
-                             dst, dst_stride, blk_col, blk_row, plane);
-    args->cpi->fn_ptr[txsize_to_bsize[tx_size]].vf(src, src_stride,
-                                                   dst, dst_stride, &tmp_sse);
-    sse = (int64_t)tmp_sse * 16;
     vp10_encode_block_intra(plane, block, blk_row, blk_col,
                             plane_bsize, tx_size, &arg);
-    args->cpi->fn_ptr[txsize_to_bsize[tx_size]].vf(src, src_stride,
-                                                   dst, dst_stride, &tmp_sse);
-    dist = (int64_t)tmp_sse * 16;
+
+    {
+      const int bs = 4 << tx_size;
+      const BLOCK_SIZE tx_bsize = txsize_to_bsize[tx_size];
+      const vpx_variance_fn_t variance = args->cpi->fn_ptr[tx_bsize].vf;
+
+      const struct macroblock_plane *const p = &x->plane[plane];
+      const struct macroblockd_plane *const pd = &xd->plane[plane];
+
+      const int src_stride = p->src.stride;
+      const int dst_stride = pd->dst.stride;
+      const int diff_stride = 4 * num_4x4_blocks_wide_lookup[plane_bsize];
+
+      const uint8_t *src = &p->src.buf[4 * (blk_row * src_stride + blk_col)];
+      const uint8_t *dst = &pd->dst.buf[4 * (blk_row * dst_stride + blk_col)];
+      const int16_t *diff = &p->src_diff[4 * (blk_row * diff_stride + blk_col)];
+
+      unsigned int tmp;
+
+      sse = (int64_t)vpx_sum_squares_2d_i16(diff, diff_stride, bs) * 16;
+      variance(src, src_stride, dst, dst_stride, &tmp);
+      dist = (int64_t)tmp * 16;
+    }
 #else
     vp10_encode_block_intra(plane, block, blk_row, blk_col,
                             plane_bsize, tx_size, &arg);
@@ -2330,6 +2334,8 @@
 #else
   DECLARE_ALIGNED(16, uint8_t, rec_buffer[32 * 32]);
 #endif
+  const int diff_stride = 4 * num_4x4_blocks_wide_lookup[plane_bsize];
+  const int16_t *diff = &p->src_diff[4 * (blk_row * diff_stride + blk_col)];
 
   int max_blocks_high = num_4x4_blocks_high_lookup[plane_bsize];
   int max_blocks_wide = num_4x4_blocks_wide_lookup[plane_bsize];
@@ -2360,20 +2366,16 @@
   if (blk_row + (bh >> 2) > max_blocks_high ||
       blk_col + (bh >> 2) > max_blocks_wide) {
     int idx, idy;
-    unsigned int this_sse;
     int blocks_height = VPXMIN(bh >> 2, max_blocks_high - blk_row);
     int blocks_width  = VPXMIN(bh >> 2, max_blocks_wide - blk_col);
     for (idy = 0; idy < blocks_height; idy += 2) {
       for (idx = 0; idx < blocks_width; idx += 2) {
-        cpi->fn_ptr[BLOCK_8X8].vf(src + 4 * idy * src_stride + 4 * idx,
-                                  src_stride,
-                                  rec_buffer + 4 * idy * 32 + 4 * idx,
-                                  32, &this_sse);
-        tmp_sse += this_sse;
+        const int16_t *d = diff + 4 * idy * diff_stride + 4 * idx;
+        tmp_sse += vpx_sum_squares_2d_i16(d, diff_stride, 8);
       }
     }
   } else {
-    cpi->fn_ptr[txm_bsize].vf(src, src_stride, rec_buffer, 32, &tmp_sse);
+    tmp_sse = vpx_sum_squares_2d_i16(diff, diff_stride, bh);
   }
 
   *bsse += (int64_t)tmp_sse * 16;
@@ -4584,9 +4586,6 @@
 #endif  // CONFIG_EXT_REFS
       unsigned int base_cost = vp10_cost_bit(intra_inter_p, 1);
 
-      if (cm->reference_mode == REFERENCE_MODE_SELECT)
-        base_cost += vp10_cost_bit(comp_inter_p, 0);
-
       ref_costs_single[LAST_FRAME] =
 #if CONFIG_EXT_REFS
           ref_costs_single[LAST2_FRAME] =
@@ -4642,9 +4641,6 @@
 #endif  // CONFIG_EXT_REFS
       unsigned int base_cost = vp10_cost_bit(intra_inter_p, 1);
 
-      if (cm->reference_mode == REFERENCE_MODE_SELECT)
-        base_cost += vp10_cost_bit(comp_inter_p, 1);
-
       ref_costs_comp[LAST_FRAME] =
 #if CONFIG_EXT_REFS
           ref_costs_comp[LAST2_FRAME] =
@@ -4932,7 +4928,6 @@
                xd->mb_to_top_edge - LEFT_TOP_MARGIN,
                xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN);
 }
-
 static INTERP_FILTER predict_interp_filter(const VP10_COMP *cpi,
                                            const MACROBLOCK *x,
                                            const BLOCK_SIZE bsize,
@@ -4942,19 +4937,17 @@
                                            (*single_filter)[MAX_REF_FRAMES]
                                            ) {
   INTERP_FILTER best_filter = SWITCHABLE;
-
   const VP10_COMMON *cm = &cpi->common;
   const MACROBLOCKD *xd = &x->e_mbd;
   int bsl = mi_width_log2_lookup[bsize];
   int pred_filter_search = cpi->sf.cb_pred_filter_search ?
       (((mi_row + mi_col) >> bsl) +
-       get_chessboard_index(cm->current_video_frame)) & 0x1 : 0;
+          get_chessboard_index(cm->current_video_frame)) & 0x1 : 0;
   MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
   const int is_comp_pred = has_second_ref(mbmi);
   const int this_mode = mbmi->mode;
   int refs[2] = { mbmi->ref_frame[0],
-    (mbmi->ref_frame[1] < 0 ? 0 : mbmi->ref_frame[1]) };
-
+      (mbmi->ref_frame[1] < 0 ? 0 : mbmi->ref_frame[1]) };
   if (pred_filter_search) {
     INTERP_FILTER af = SWITCHABLE, lf = SWITCHABLE;
     if (xd->up_available)
@@ -5053,6 +5046,12 @@
                                  int *disable_skip,
                                  int_mv (*mode_mv)[MAX_REF_FRAMES],
                                  int mi_row, int mi_col,
+#if CONFIG_OBMC
+                                 uint8_t *dst_buf1[3],
+                                 int dst_stride1[3],
+                                 uint8_t *dst_buf2[3],
+                                 int dst_stride2[3],
+#endif  // CONFIG_OBMC
 #if CONFIG_EXT_INTER
                                  int_mv single_newmvs[2][MAX_REF_FRAMES],
 #else
@@ -5088,6 +5087,24 @@
 #else
   DECLARE_ALIGNED(16, uint8_t, tmp_buf[MAX_MB_PLANE * 64 * 64]);
 #endif  // CONFIG_VP9_HIGHBITDEPTH
+#if CONFIG_OBMC
+#if CONFIG_VP9_HIGHBITDEPTH
+  DECLARE_ALIGNED(16, uint16_t, tmp_buf1_16[MAX_MB_PLANE * 64 * 64]);
+  uint8_t *tmp_buf1;
+  uint8_t *obmc_tmp_buf[3];
+#else
+  DECLARE_ALIGNED(16, uint8_t, tmp_buf1[MAX_MB_PLANE * 64 * 64]);
+  uint8_t *obmc_tmp_buf[3] = {tmp_buf1, tmp_buf1 + 4096, tmp_buf1 + 8192};
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+  int obmc_tmp_stride[3] = {64, 64, 64};
+  int best_obmc_flag = 0;
+  uint8_t tmp_skip_txfm[MAX_MB_PLANE << 2] = {0};
+  int64_t tmp_bsse[MAX_MB_PLANE << 2] = {0};
+  int64_t rdobmc;
+  int skip_txfm_sb_obmc = 0;
+  int64_t skip_sse_sb_obmc = INT64_MAX;
+  int allow_obmc = is_obmc_allowed(mbmi);
+#endif  // CONFIG_OBMC
   int pred_exists = 0;
   int intpel_mv;
   int64_t rd, tmp_rd, best_rd = INT64_MAX;
@@ -5104,6 +5121,9 @@
   int64_t distortion_y = 0, distortion_uv = 0;
   int16_t mode_ctx = mbmi_ext->mode_context[refs[0]];
 
+#if CONFIG_OBMC
+  tmp_rd = 0;
+#endif  // CONFIG_OBMC
 #if CONFIG_REF_MV
 #if CONFIG_EXT_INTER
   if (is_comp_pred)
@@ -5117,9 +5137,20 @@
 #if CONFIG_VP9_HIGHBITDEPTH
   if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
     tmp_buf = CONVERT_TO_BYTEPTR(tmp_buf16);
+#if CONFIG_OBMC
+    tmp_buf1 = CONVERT_TO_BYTEPTR(tmp_buf1_16);
+#endif  // CONFIG_OBMC
   } else {
     tmp_buf = (uint8_t *)tmp_buf16;
+#if CONFIG_OBMC
+    tmp_buf1 = (uint8_t *)tmp_buf1_16;
+#endif  // CONFIG_OBMC
   }
+#if CONFIG_OBMC
+  obmc_tmp_buf[0] = tmp_buf1;
+  obmc_tmp_buf[1] = tmp_buf1 + 4096;
+  obmc_tmp_buf[2] = tmp_buf1 + 8192;
+#endif  // CONFIG_OBMC
 #endif  // CONFIG_VP9_HIGHBITDEPTH
 
   if (is_comp_pred) {
@@ -5302,9 +5333,8 @@
   if (this_mode == NEARMV && is_comp_pred) {
     uint8_t ref_frame_type = vp10_ref_frame_type(mbmi->ref_frame);
     if (mbmi_ext->ref_mv_count[ref_frame_type] > 1) {
-      int ref_mv_idx = mbmi->ref_mv_idx + 1;
-      cur_mv[0] = mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_idx].this_mv;
-      cur_mv[1] = mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_idx].comp_mv;
+      cur_mv[0] = mbmi_ext->ref_mv_stack[ref_frame_type][1].this_mv;
+      cur_mv[1] = mbmi_ext->ref_mv_stack[ref_frame_type][1].comp_mv;
 
       for (i = 0; i < 2; ++i) {
         lower_mv_precision(&cur_mv[i].as_mv, cm->allow_high_precision_mv);
@@ -5383,6 +5413,11 @@
       int64_t rs_rd;
       int tmp_skip_sb = 0;
       int64_t tmp_skip_sse = INT64_MAX;
+#if CONFIG_OBMC
+      int obmc_flag = 0;
+      int tmp_skip_sb_obmc = 0;
+      int64_t tmp_skip_sse_obmc = INT64_MAX;
+#endif  // CONFIG_OBMC
 
       mbmi->interp_filter = i;
       rs = vp10_get_switchable_rate(cpi, xd);
@@ -5395,10 +5430,21 @@
             VPXMIN(filter_cache[SWITCHABLE_FILTERS], rd + rs_rd);
         if (cm->interp_filter == SWITCHABLE)
           rd += rs_rd;
+#if CONFIG_OBMC
+        if (allow_obmc) {
+          obmc_flag = best_obmc_flag;
+          rd += RDCOST(x->rdmult, x->rddiv,
+                       cpi->obmc_cost[bsize][obmc_flag], 0);
+        }
+#endif  // CONFIG_OBMC
         *mask_filter = VPXMAX(*mask_filter, rd);
       } else {
         int rate_sum = 0;
         int64_t dist_sum = 0;
+#if CONFIG_OBMC
+        int rate_sum_obmc = 0;
+        int64_t dist_sum_obmc = 0;
+#endif  // CONFIG_OBMC
         if (i > 0 && cpi->sf.adaptive_interp_filter_search &&
             (cpi->sf.interp_filter_search_mask & (1 << i))) {
           rate_sum = INT_MAX;
@@ -5423,6 +5469,40 @@
                         &tmp_skip_sb, &tmp_skip_sse);
 
         rd = RDCOST(x->rdmult, x->rddiv, rate_sum, dist_sum);
+#if CONFIG_OBMC
+        if (allow_obmc) {
+          rd += RDCOST(x->rdmult, x->rddiv, cpi->obmc_cost[bsize][0], 0);
+          memcpy(tmp_skip_txfm, x->skip_txfm, sizeof(tmp_skip_txfm));
+          memcpy(tmp_bsse, x->bsse, sizeof(tmp_bsse));
+
+          vp10_build_obmc_inter_prediction(cm, xd, mi_row, mi_col, 1,
+                                           obmc_tmp_buf, obmc_tmp_stride,
+                                           dst_buf1, dst_stride1,
+                                           dst_buf2, dst_stride2);
+          for (j = 0; j < MAX_MB_PLANE; ++j) {
+            xd->plane[j].dst.buf = obmc_tmp_buf[j];
+            xd->plane[j].dst.stride = obmc_tmp_stride[j];
+          }
+          model_rd_for_sb(cpi, bsize, x, xd, &rate_sum_obmc, &dist_sum_obmc,
+                          &tmp_skip_sb_obmc, &tmp_skip_sse_obmc);
+          rdobmc = RDCOST(x->rdmult, x->rddiv,
+                          rate_sum_obmc + cpi->obmc_cost[bsize][1],
+                          dist_sum_obmc);
+
+          if ((double)rdobmc <= 0.99 * (double)rd) {
+            obmc_flag = 1;
+            rd = rdobmc;
+            rate_sum = rate_sum_obmc;
+            dist_sum = dist_sum_obmc;
+            tmp_skip_sb = tmp_skip_sb_obmc;
+            tmp_skip_sse = tmp_skip_sse_obmc;
+          } else {
+            obmc_flag = 0;
+            memcpy(x->skip_txfm, tmp_skip_txfm, sizeof(tmp_skip_txfm));
+            memcpy(x->bsse, tmp_bsse, sizeof(tmp_bsse));
+          }
+        }
+#endif  // CONFIG_OBMC
         filter_cache[i] = rd;
         filter_cache[SWITCHABLE_FILTERS] =
             VPXMIN(filter_cache[SWITCHABLE_FILTERS], rd + rs_rd);
@@ -5447,6 +5527,10 @@
       if (newbest) {
         best_rd = rd;
         best_filter = mbmi->interp_filter;
+#if CONFIG_OBMC
+          if (allow_obmc)
+            best_obmc_flag = obmc_flag;
+#endif  // CONFIG_OBMC
         if (cm->interp_filter == SWITCHABLE && i &&
             !(intpel_mv && IsInterpolatingFilter(i)))
           best_needs_copy = !best_needs_copy;
@@ -5471,8 +5555,18 @@
   mbmi->interp_filter = cm->interp_filter != SWITCHABLE ?
       cm->interp_filter : best_filter;
   rs = cm->interp_filter == SWITCHABLE ? vp10_get_switchable_rate(cpi, xd) : 0;
+#if CONFIG_OBMC
+  if (allow_obmc)
+    mbmi->obmc = best_obmc_flag;
+  else
+    mbmi->obmc = 0;
+#endif  // CONFIG_OBMC
 
+#if CONFIG_OBMC
+  if (pred_exists && !mbmi->obmc) {
+#else
   if (pred_exists) {
+#endif  // CONFIG_OBMC
     if (best_needs_copy) {
       // again temporarily set the buffers to local memory to prevent a memcpy
       for (i = 0; i < MAX_MB_PLANE; i++) {
@@ -5481,16 +5575,77 @@
       }
     }
     rd = tmp_rd + RDCOST(x->rdmult, x->rddiv, rs, 0);
+#if CONFIG_OBMC
+    if (allow_obmc)
+      rd += RDCOST(x->rdmult, x->rddiv,
+                   cpi->obmc_cost[bsize][mbmi->obmc], 0);
+#endif  // CONFIG_OBMC
   } else {
     int tmp_rate;
     int64_t tmp_dist;
+#if CONFIG_OBMC
+    int tmp_rate_obmc;
+    int64_t tmp_dist_obmc;
+#endif  // CONFIG_OBMC
     // Handles the special case when a filter that is not in the
     // switchable list (ex. bilinear) is indicated at the frame level, or
     // skip condition holds.
     vp10_build_inter_predictors_sb(xd, mi_row, mi_col, bsize);
+#if CONFIG_OBMC
+    if (mbmi->obmc) {
+      vp10_build_obmc_inter_prediction(cm, xd, mi_row, mi_col, 1,
+                                       obmc_tmp_buf, obmc_tmp_stride,
+                                       dst_buf1, dst_stride1,
+                                       dst_buf2, dst_stride2);
+      for (i = 0; i < MAX_MB_PLANE; ++i) {
+        xd->plane[i].dst.buf = obmc_tmp_buf[i];
+        xd->plane[i].dst.stride = obmc_tmp_stride[i];
+      }
+      model_rd_for_sb(cpi, bsize, x, xd, &tmp_rate, &tmp_dist,
+                      &skip_txfm_sb, &skip_sse_sb);
+      rd = RDCOST(x->rdmult, x->rddiv,
+                  rs + tmp_rate + cpi->obmc_cost[bsize][1],
+                  tmp_dist);
+    } else {
+#endif  // CONFIG_OBMC
     model_rd_for_sb(cpi, bsize, x, xd, &tmp_rate, &tmp_dist,
                     &skip_txfm_sb, &skip_sse_sb);
     rd = RDCOST(x->rdmult, x->rddiv, rs + tmp_rate, tmp_dist);
+#if CONFIG_OBMC
+      if (allow_obmc) {
+        rd += RDCOST(x->rdmult, x->rddiv, cpi->obmc_cost[bsize][0], 0);
+        memcpy(tmp_skip_txfm, x->skip_txfm, sizeof(tmp_skip_txfm));
+        memcpy(tmp_bsse, x->bsse, sizeof(tmp_bsse));
+
+        vp10_build_obmc_inter_prediction(cm, xd, mi_row, mi_col, 1,
+                                         obmc_tmp_buf, obmc_tmp_stride,
+                                         dst_buf1, dst_stride1,
+                                         dst_buf2, dst_stride2);
+        for (i = 0; i < MAX_MB_PLANE; ++i) {
+          xd->plane[i].dst.buf = obmc_tmp_buf[i];
+          xd->plane[i].dst.stride = obmc_tmp_stride[i];
+        }
+        model_rd_for_sb(cpi, bsize, x, xd, &tmp_rate_obmc, &tmp_dist_obmc,
+                        &skip_txfm_sb_obmc, &skip_sse_sb_obmc);
+        rdobmc = RDCOST(x->rdmult, x->rddiv,
+                        rs + tmp_rate_obmc + cpi->obmc_cost[bsize][1],
+                        tmp_dist_obmc);
+        if ((double)rdobmc <= 0.99 * (double)rd) {
+          mbmi->obmc = 1;
+          rd = rdobmc;
+          skip_txfm_sb = skip_txfm_sb_obmc;
+          skip_sse_sb = skip_sse_sb_obmc;
+        } else {
+          mbmi->obmc = 0;
+          memcpy(x->skip_txfm, tmp_skip_txfm, sizeof(tmp_skip_txfm));
+          memcpy(x->bsse, tmp_bsse, sizeof(tmp_bsse));
+          restore_dst_buf(xd, orig_dst, orig_dst_stride);
+        }
+      } else {
+        mbmi->obmc = 0;
+      }
+    }
+#endif  // CONFIG_OBMC
     memcpy(skip_txfm, x->skip_txfm, sizeof(skip_txfm));
     memcpy(bsse, x->bsse, sizeof(bsse));
   }
@@ -5570,6 +5725,10 @@
 
   if (cm->interp_filter == SWITCHABLE)
     *rate2 += rs;
+#if CONFIG_OBMC
+  if (allow_obmc)
+    *rate2 += cpi->obmc_cost[bsize][mbmi->obmc];
+#endif  // CONFIG_OBMC
 
   memcpy(x->skip_txfm, skip_txfm, sizeof(skip_txfm));
   memcpy(x->bsse, bsse, sizeof(bsse));
@@ -5916,6 +6075,39 @@
   int64_t filter_cache[SWITCHABLE_FILTER_CONTEXTS];
   const TX_SIZE max_tx_size = max_txsize_lookup[bsize];
   const vpx_prob *tx_probs = get_tx_probs2(max_tx_size, xd, &cm->fc->tx_probs);
+#if CONFIG_OBMC
+#if CONFIG_VP9_HIGHBITDEPTH
+  DECLARE_ALIGNED(16, uint8_t, tmp_buf1[2 * MAX_MB_PLANE * 64 * 64]);
+  DECLARE_ALIGNED(16, uint8_t, tmp_buf2[2 * MAX_MB_PLANE * 64 * 64]);
+#else
+  DECLARE_ALIGNED(16, uint8_t, tmp_buf1[MAX_MB_PLANE * 64 * 64]);
+  DECLARE_ALIGNED(16, uint8_t, tmp_buf2[MAX_MB_PLANE * 64 * 64]);
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+  uint8_t *dst_buf1[3], *dst_buf2[3];
+  int dst_stride1[3] = {64, 64, 64};
+  int dst_stride2[3] = {64, 64, 64};
+
+#if CONFIG_VP9_HIGHBITDEPTH
+  if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
+    int len = sizeof(uint16_t);
+    dst_buf1[0] = CONVERT_TO_BYTEPTR(tmp_buf1);
+    dst_buf1[1] = CONVERT_TO_BYTEPTR(tmp_buf1 + 4096 * len);
+    dst_buf1[2] = CONVERT_TO_BYTEPTR(tmp_buf1 + 8192 * len);
+    dst_buf2[0] = CONVERT_TO_BYTEPTR(tmp_buf2);
+    dst_buf2[1] = CONVERT_TO_BYTEPTR(tmp_buf2 + 4096 * len);
+    dst_buf2[2] = CONVERT_TO_BYTEPTR(tmp_buf2 + 8192 * len);
+  } else {
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+  dst_buf1[0] = tmp_buf1;
+  dst_buf1[1] = tmp_buf1 + 4096;
+  dst_buf1[2] = tmp_buf1 + 8192;
+  dst_buf2[0] = tmp_buf2;
+  dst_buf2[1] = tmp_buf2 + 4096;
+  dst_buf2[2] = tmp_buf2 + 8192;
+#if CONFIG_VP9_HIGHBITDEPTH
+  }
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+#endif  // CONFIG_OBMC
 
   vp10_zero(best_mbmode);
 
@@ -5988,6 +6180,14 @@
   }
 #endif
 
+#if CONFIG_OBMC
+  vp10_build_prediction_by_above_preds(cpi, xd, mi_row, mi_col, dst_buf1,
+                                       dst_stride1);
+  vp10_build_prediction_by_left_preds(cpi, xd, mi_row, mi_col, dst_buf2,
+                                      dst_stride2);
+  vp10_setup_dst_planes(xd->plane, get_frame_new_buffer(cm), mi_row, mi_col);
+#endif  // CONFIG_OBMC
+
   for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
     if (!(cpi->ref_frame_flags & flag_list[ref_frame])) {
       // Skip checking missing references in both single and compound reference
@@ -6286,6 +6486,9 @@
     mbmi->interp_filter = cm->interp_filter == SWITCHABLE ? EIGHTTAP
                                                           : cm->interp_filter;
     mbmi->mv[0].as_int = mbmi->mv[1].as_int = 0;
+#if CONFIG_OBMC
+    mbmi->obmc = 0;
+#endif  // CONFIG_OBMC
 
     x->skip = 0;
     set_ref_ptrs(cm, xd, ref_frame, second_ref_frame);
@@ -6450,6 +6653,10 @@
                                   &rate_y, &rate_uv,
                                   &disable_skip, frame_mv,
                                   mi_row, mi_col,
+#if CONFIG_OBMC
+                                  dst_buf1, dst_stride1,
+                                  dst_buf2, dst_stride2,
+#endif  // CONFIG_OBMC
 #if CONFIG_EXT_INTER
                                   single_newmvs,
 #else
@@ -6473,7 +6680,7 @@
         int ref_set = VPXMIN(2, mbmi_ext->ref_mv_count[ref_frame_type] - 2);
 
         uint8_t drl0_ctx =
-            vp10_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], 0);
+            vp10_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], 1);
         rate2 += cpi->drl_mode_cost0[drl0_ctx][0];
 
         if (this_rd < INT64_MAX) {
@@ -6522,6 +6729,10 @@
                                            &tmp_rate_y, &tmp_rate_uv,
                                            &dummy_disable_skip, frame_mv,
                                            mi_row, mi_col,
+#if CONFIG_OBMC
+                                           dst_buf1, dst_stride1,
+                                           dst_buf2, dst_stride2,
+#endif  // CONFIG_OBMC
 #if CONFIG_EXT_INTER
                                            dummy_single_newmvs,
 #else
@@ -6538,7 +6749,7 @@
 
           if (mbmi_ext->ref_mv_count[ref_frame_type] > 3) {
             uint8_t drl1_ctx =
-                vp10_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], 1);
+                vp10_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], 2);
             tmp_rate += cpi->drl_mode_cost1[drl1_ctx][ref_idx];
           }
 
@@ -6671,6 +6882,10 @@
         }
         *returnrate_nocoef -= vp10_cost_bit(vp10_get_intra_inter_prob(cm, xd),
                                             mbmi->ref_frame[0] != INTRA_FRAME);
+#if CONFIG_OBMC
+        if (is_inter_block(mbmi) && is_obmc_allowed(mbmi))
+          *returnrate_nocoef -= cpi->obmc_cost[bsize][mbmi->obmc];
+#endif  // CONFIG_OBMC
 #endif  // CONFIG_SUPERTX
         rd_cost->dist = distortion2;
         rd_cost->rdcost = this_rd;
@@ -7178,6 +7393,9 @@
   mbmi->ext_intra_mode_info.use_ext_intra_mode[0] = 0;
   mbmi->ext_intra_mode_info.use_ext_intra_mode[1] = 0;
 #endif  // CONFIG_EXT_INTRA
+#if CONFIG_OBMC
+  mbmi->obmc = 0;
+#endif  // CONFIG_OBMC
 
   for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; ++i)
     filter_cache[i] = INT64_MAX;
@@ -7896,3 +8114,167 @@
   store_coding_context(x, ctx, best_ref_index,
                        best_pred_diff, best_filter_diff, 0);
 }
+
+#if CONFIG_OBMC
+void vp10_build_prediction_by_above_preds(VP10_COMP *cpi,
+                                          MACROBLOCKD *xd,
+                                          int mi_row, int mi_col,
+                                          uint8_t *tmp_buf[MAX_MB_PLANE],
+                                          int tmp_stride[MAX_MB_PLANE]) {
+  VP10_COMMON *const cm = &cpi->common;
+  BLOCK_SIZE bsize = xd->mi[0]->mbmi.sb_type;
+  int i, j, mi_step, ref;
+
+  if (mi_row == 0)
+    return;
+
+  for (i = 0; i < VPXMIN(xd->n8_w, cm->mi_cols - mi_col); i += mi_step) {
+    int mi_row_offset = -1;
+    int mi_col_offset = i;
+    int mi_x, mi_y, bw, bh;
+    MODE_INFO *above_mi = xd->mi[mi_col_offset +
+                                 mi_row_offset * xd->mi_stride];
+    MB_MODE_INFO *above_mbmi = &above_mi->mbmi;
+
+    mi_step = VPXMIN(xd->n8_w,
+                     num_8x8_blocks_wide_lookup[above_mbmi->sb_type]);
+
+    if (!is_inter_block(above_mbmi))
+      continue;
+
+    for (j = 0; j < MAX_MB_PLANE; ++j) {
+      struct macroblockd_plane *const pd = &xd->plane[j];
+      setup_pred_plane(&pd->dst,
+                       tmp_buf[j], tmp_stride[j],
+                       0, i, NULL,
+                       pd->subsampling_x, pd->subsampling_y);
+    }
+    set_ref_ptrs(cm, xd, above_mbmi->ref_frame[0], above_mbmi->ref_frame[1]);
+    for (ref = 0; ref < 1 + has_second_ref(above_mbmi); ++ref) {
+      YV12_BUFFER_CONFIG *cfg = get_ref_frame_buffer(cpi,
+                                                  above_mbmi->ref_frame[ref]);
+      assert(cfg != NULL);
+      vp10_setup_pre_planes(xd, ref, cfg, mi_row, mi_col + i,
+                            &xd->block_refs[ref]->sf);
+    }
+
+    xd->mb_to_left_edge   = -(((mi_col + i) * MI_SIZE) * 8);
+    mi_x = (mi_col + i) << MI_SIZE_LOG2;
+    mi_y = mi_row << MI_SIZE_LOG2;
+
+    for (j = 0; j < MAX_MB_PLANE; ++j) {
+      const struct macroblockd_plane *pd = &xd->plane[j];
+      bw = (mi_step * 8) >> pd->subsampling_x;
+      bh = VPXMAX((num_4x4_blocks_high_lookup[bsize] * 2) >> pd->subsampling_y,
+                  4);
+
+      if (above_mbmi->sb_type < BLOCK_8X8) {
+        const PARTITION_TYPE bp = BLOCK_8X8 - above_mbmi->sb_type;
+        const int have_vsplit = bp != PARTITION_HORZ;
+        const int have_hsplit = bp != PARTITION_VERT;
+        const int num_4x4_w = 2 >> ((!have_vsplit) | pd->subsampling_x);
+        const int num_4x4_h = 2 >> ((!have_hsplit) | pd->subsampling_y);
+        const int pw = 8 >> (have_vsplit | pd->subsampling_x);
+        int x, y;
+
+        for (y = 0; y < num_4x4_h; ++y)
+          for (x = 0; x < num_4x4_w; ++x) {
+            if ((bp == PARTITION_HORZ || bp == PARTITION_SPLIT)
+                && y == 0 && !pd->subsampling_y)
+              continue;
+
+            build_inter_predictors(xd, j, mi_col_offset, mi_row_offset,
+                                   y * 2 + x, bw, bh,
+                                   4 * x, 0, pw, bh, mi_x, mi_y);
+          }
+      } else {
+        build_inter_predictors(xd, j, mi_col_offset, mi_row_offset, 0,
+                               bw, bh, 0, 0, bw, bh, mi_x, mi_y);
+      }
+    }
+  }
+  xd->mb_to_left_edge   = -((mi_col * MI_SIZE) * 8);
+}
+
+void vp10_build_prediction_by_left_preds(VP10_COMP *cpi,
+                                         MACROBLOCKD *xd,
+                                         int mi_row, int mi_col,
+                                         uint8_t *tmp_buf[MAX_MB_PLANE],
+                                         int tmp_stride[MAX_MB_PLANE]) {
+  VP10_COMMON *const cm = &cpi->common;
+  const TileInfo *const tile = &xd->tile;
+  BLOCK_SIZE bsize = xd->mi[0]->mbmi.sb_type;
+  int i, j, mi_step, ref;
+
+  if (mi_col == 0 || (mi_col - 1 < tile->mi_col_start) ||
+      (mi_col - 1) >= tile->mi_col_end)
+    return;
+
+  for (i = 0; i < VPXMIN(xd->n8_h, cm->mi_rows - mi_row); i += mi_step) {
+    int mi_row_offset = i;
+    int mi_col_offset = -1;
+    int mi_x, mi_y, bw, bh;
+    MODE_INFO *left_mi = xd->mi[mi_col_offset +
+                                mi_row_offset * xd->mi_stride];
+    MB_MODE_INFO *left_mbmi = &left_mi->mbmi;
+
+    mi_step = VPXMIN(xd->n8_h,
+                     num_8x8_blocks_high_lookup[left_mbmi->sb_type]);
+
+    if (!is_inter_block(left_mbmi))
+      continue;
+
+    for (j = 0; j < MAX_MB_PLANE; ++j) {
+      struct macroblockd_plane *const pd = &xd->plane[j];
+      setup_pred_plane(&pd->dst,
+                       tmp_buf[j], tmp_stride[j],
+                       i, 0, NULL,
+                       pd->subsampling_x, pd->subsampling_y);
+    }
+    set_ref_ptrs(cm, xd, left_mbmi->ref_frame[0], left_mbmi->ref_frame[1]);
+    for (ref = 0; ref < 1 + has_second_ref(left_mbmi); ++ref) {
+      YV12_BUFFER_CONFIG *cfg = get_ref_frame_buffer(cpi,
+                                                     left_mbmi->ref_frame[ref]);
+      assert(cfg != NULL);
+      vp10_setup_pre_planes(xd, ref, cfg, mi_row + i, mi_col,
+                            &xd->block_refs[ref]->sf);
+    }
+
+    xd->mb_to_top_edge    = -(((mi_row + i) * MI_SIZE) * 8);
+    mi_x = mi_col << MI_SIZE_LOG2;
+    mi_y = (mi_row + i) << MI_SIZE_LOG2;
+
+    for (j = 0; j < MAX_MB_PLANE; ++j) {
+      const struct macroblockd_plane *pd = &xd->plane[j];
+      bw = VPXMAX((num_4x4_blocks_wide_lookup[bsize] * 2) >> pd->subsampling_x,
+                  4);
+      bh = (mi_step << MI_SIZE_LOG2) >> pd->subsampling_y;
+
+      if (left_mbmi->sb_type < BLOCK_8X8) {
+        const PARTITION_TYPE bp = BLOCK_8X8 - left_mbmi->sb_type;
+        const int have_vsplit = bp != PARTITION_HORZ;
+        const int have_hsplit = bp != PARTITION_VERT;
+        const int num_4x4_w = 2 >> ((!have_vsplit) | pd->subsampling_x);
+        const int num_4x4_h = 2 >> ((!have_hsplit) | pd->subsampling_y);
+        const int ph = 8 >> (have_hsplit | pd->subsampling_y);
+        int x, y;
+
+        for (y = 0; y < num_4x4_h; ++y)
+          for (x = 0; x < num_4x4_w; ++x) {
+            if ((bp == PARTITION_VERT || bp == PARTITION_SPLIT)
+                && x == 0 && !pd->subsampling_x)
+              continue;
+
+            build_inter_predictors(xd, j, mi_col_offset, mi_row_offset,
+                                   y * 2 + x, bw, bh,
+                                   0, 4 * y, bw, ph, mi_x, mi_y);
+          }
+      } else {
+        build_inter_predictors(xd, j, mi_col_offset, mi_row_offset, 0,
+                               bw, bh, 0, 0, bw, bh, mi_x, mi_y);
+      }
+    }
+  }
+  xd->mb_to_top_edge    = -((mi_row * MI_SIZE) * 8);
+}
+#endif  // CONFIG_OBMC
diff --git a/vp10/encoder/rdopt.h b/vp10/encoder/rdopt.h
index 7c7e9eb..888ca4b 100644
--- a/vp10/encoder/rdopt.h
+++ b/vp10/encoder/rdopt.h
@@ -89,6 +89,18 @@
                                    int use_fast_coef_casting);
 #endif  // CONFIG_SUPERTX
 
+#if CONFIG_OBMC
+void vp10_build_prediction_by_above_preds(VP10_COMP *cpi,
+                                          MACROBLOCKD *xd,
+                                          int mi_row, int mi_col,
+                                          uint8_t *tmp_buf[MAX_MB_PLANE],
+                                          int tmp_stride[MAX_MB_PLANE]);
+void vp10_build_prediction_by_left_preds(VP10_COMP *cpi,
+                                         MACROBLOCKD *xd,
+                                         int mi_row, int mi_col,
+                                         uint8_t *tmp_buf[MAX_MB_PLANE],
+                                         int tmp_stride[MAX_MB_PLANE]);
+#endif  // CONFIG_OBMC
 #ifdef __cplusplus
 }  // extern "C"
 #endif
diff --git a/vp10/encoder/subexp.c b/vp10/encoder/subexp.c
index 8e60f40..9ddec2d 100644
--- a/vp10/encoder/subexp.c
+++ b/vp10/encoder/subexp.c
@@ -80,7 +80,7 @@
 
 static int prob_diff_update_cost(vpx_prob newp, vpx_prob oldp) {
   int delp = remap_prob(newp, oldp);
-  return update_bits[delp] * 256;
+  return update_bits[delp] << VP9_PROB_COST_SHIFT;
 }
 
 static void encode_uniform(vpx_writer *w, int v) {
diff --git a/vp10/encoder/tokenize.c b/vp10/encoder/tokenize.c
index 66bb990..0aaeb2a 100644
--- a/vp10/encoder/tokenize.c
+++ b/vp10/encoder/tokenize.c
@@ -75,292 +75,170 @@
     14, 14, 16, 16, 18, 18, 20, 20, 22, 22, 24, 24, 26, 26, 0, 0};
 
 static const int16_t zero_cost[] = {0};
-static const int16_t sign_cost[] = {255, 257};
-static const int16_t cat1_cost[] = {429, 431, 616, 618};
-static const int16_t cat2_cost[] = {624, 626, 727, 729, 848, 850, 951, 953};
-static const int16_t cat3_cost[] = {
-  820, 822, 893, 895, 940, 942, 1013, 1015, 1096, 1098, 1169, 1171, 1216, 1218,
-  1289, 1291
-};
-static const int16_t cat4_cost[] = {
-  1032, 1034, 1075, 1077, 1105, 1107, 1148, 1150, 1194, 1196, 1237, 1239,
-  1267, 1269, 1310, 1312, 1328, 1330, 1371, 1373, 1401, 1403, 1444, 1446,
-  1490, 1492, 1533, 1535, 1563, 1565, 1606, 1608
-};
-static const int16_t cat5_cost[] = {
-  1269, 1271, 1283, 1285, 1306, 1308, 1320,
-  1322, 1347, 1349, 1361, 1363, 1384, 1386, 1398, 1400, 1443, 1445, 1457,
-  1459, 1480, 1482, 1494, 1496, 1521, 1523, 1535, 1537, 1558, 1560, 1572,
-  1574, 1592, 1594, 1606, 1608, 1629, 1631, 1643, 1645, 1670, 1672, 1684,
-  1686, 1707, 1709, 1721, 1723, 1766, 1768, 1780, 1782, 1803, 1805, 1817,
-  1819, 1844, 1846, 1858, 1860, 1881, 1883, 1895, 1897
-};
+static const int16_t sign_cost[1] = {512};
+static const int16_t cat1_cost[1 << 1] = {864, 1229};
+static const int16_t cat2_cost[1 << 2] = {1256, 1453, 1696, 1893};
+static const int16_t cat3_cost[1 << 3] = {1652, 1791, 1884, 2023,
+                                          2195, 2334, 2427, 2566};
+static const int16_t cat4_cost[1 << 4] = {2079, 2160, 2218, 2299, 2395, 2476,
+                                          2534, 2615, 2661, 2742, 2800, 2881,
+                                          2977, 3058, 3116, 3197};
+static const int16_t cat5_cost[1 << 5] = {
+    2553, 2576, 2622, 2645, 2703, 2726, 2772, 2795, 2894, 2917, 2963,
+    2986, 3044, 3067, 3113, 3136, 3190, 3213, 3259, 3282, 3340, 3363,
+    3409, 3432, 3531, 3554, 3600, 3623, 3681, 3704, 3750, 3773};
 const int16_t vp10_cat6_low_cost[256] = {
-  1638, 1640, 1646, 1648, 1652, 1654, 1660, 1662,
-  1670, 1672, 1678, 1680, 1684, 1686, 1692, 1694, 1711, 1713, 1719, 1721,
-  1725, 1727, 1733, 1735, 1743, 1745, 1751, 1753, 1757, 1759, 1765, 1767,
-  1787, 1789, 1795, 1797, 1801, 1803, 1809, 1811, 1819, 1821, 1827, 1829,
-  1833, 1835, 1841, 1843, 1860, 1862, 1868, 1870, 1874, 1876, 1882, 1884,
-  1892, 1894, 1900, 1902, 1906, 1908, 1914, 1916, 1940, 1942, 1948, 1950,
-  1954, 1956, 1962, 1964, 1972, 1974, 1980, 1982, 1986, 1988, 1994, 1996,
-  2013, 2015, 2021, 2023, 2027, 2029, 2035, 2037, 2045, 2047, 2053, 2055,
-  2059, 2061, 2067, 2069, 2089, 2091, 2097, 2099, 2103, 2105, 2111, 2113,
-  2121, 2123, 2129, 2131, 2135, 2137, 2143, 2145, 2162, 2164, 2170, 2172,
-  2176, 2178, 2184, 2186, 2194, 2196, 2202, 2204, 2208, 2210, 2216, 2218,
-  2082, 2084, 2090, 2092, 2096, 2098, 2104, 2106, 2114, 2116, 2122, 2124,
-  2128, 2130, 2136, 2138, 2155, 2157, 2163, 2165, 2169, 2171, 2177, 2179,
-  2187, 2189, 2195, 2197, 2201, 2203, 2209, 2211, 2231, 2233, 2239, 2241,
-  2245, 2247, 2253, 2255, 2263, 2265, 2271, 2273, 2277, 2279, 2285, 2287,
-  2304, 2306, 2312, 2314, 2318, 2320, 2326, 2328, 2336, 2338, 2344, 2346,
-  2350, 2352, 2358, 2360, 2384, 2386, 2392, 2394, 2398, 2400, 2406, 2408,
-  2416, 2418, 2424, 2426, 2430, 2432, 2438, 2440, 2457, 2459, 2465, 2467,
-  2471, 2473, 2479, 2481, 2489, 2491, 2497, 2499, 2503, 2505, 2511, 2513,
-  2533, 2535, 2541, 2543, 2547, 2549, 2555, 2557, 2565, 2567, 2573, 2575,
-  2579, 2581, 2587, 2589, 2606, 2608, 2614, 2616, 2620, 2622, 2628, 2630,
-  2638, 2640, 2646, 2648, 2652, 2654, 2660, 2662
-};
-const int16_t vp10_cat6_high_cost[128] = {
-  72, 892, 1183, 2003, 1448, 2268, 2559, 3379,
-  1709, 2529, 2820, 3640, 3085, 3905, 4196, 5016, 2118, 2938, 3229, 4049,
-  3494, 4314, 4605, 5425, 3755, 4575, 4866, 5686, 5131, 5951, 6242, 7062,
-  2118, 2938, 3229, 4049, 3494, 4314, 4605, 5425, 3755, 4575, 4866, 5686,
-  5131, 5951, 6242, 7062, 4164, 4984, 5275, 6095, 5540, 6360, 6651, 7471,
-  5801, 6621, 6912, 7732, 7177, 7997, 8288, 9108, 2118, 2938, 3229, 4049,
-  3494, 4314, 4605, 5425, 3755, 4575, 4866, 5686, 5131, 5951, 6242, 7062,
-  4164, 4984, 5275, 6095, 5540, 6360, 6651, 7471, 5801, 6621, 6912, 7732,
-  7177, 7997, 8288, 9108, 4164, 4984, 5275, 6095, 5540, 6360, 6651, 7471,
-  5801, 6621, 6912, 7732, 7177, 7997, 8288, 9108, 6210, 7030, 7321, 8141,
-  7586, 8406, 8697, 9517, 7847, 8667, 8958, 9778, 9223, 10043, 10334, 11154
-};
+    3378, 3390, 3401, 3413, 3435, 3447, 3458, 3470, 3517, 3529, 3540, 3552,
+    3574, 3586, 3597, 3609, 3671, 3683, 3694, 3706, 3728, 3740, 3751, 3763,
+    3810, 3822, 3833, 3845, 3867, 3879, 3890, 3902, 3973, 3985, 3996, 4008,
+    4030, 4042, 4053, 4065, 4112, 4124, 4135, 4147, 4169, 4181, 4192, 4204,
+    4266, 4278, 4289, 4301, 4323, 4335, 4346, 4358, 4405, 4417, 4428, 4440,
+    4462, 4474, 4485, 4497, 4253, 4265, 4276, 4288, 4310, 4322, 4333, 4345,
+    4392, 4404, 4415, 4427, 4449, 4461, 4472, 4484, 4546, 4558, 4569, 4581,
+    4603, 4615, 4626, 4638, 4685, 4697, 4708, 4720, 4742, 4754, 4765, 4777,
+    4848, 4860, 4871, 4883, 4905, 4917, 4928, 4940, 4987, 4999, 5010, 5022,
+    5044, 5056, 5067, 5079, 5141, 5153, 5164, 5176, 5198, 5210, 5221, 5233,
+    5280, 5292, 5303, 5315, 5337, 5349, 5360, 5372, 4988, 5000, 5011, 5023,
+    5045, 5057, 5068, 5080, 5127, 5139, 5150, 5162, 5184, 5196, 5207, 5219,
+    5281, 5293, 5304, 5316, 5338, 5350, 5361, 5373, 5420, 5432, 5443, 5455,
+    5477, 5489, 5500, 5512, 5583, 5595, 5606, 5618, 5640, 5652, 5663, 5675,
+    5722, 5734, 5745, 5757, 5779, 5791, 5802, 5814, 5876, 5888, 5899, 5911,
+    5933, 5945, 5956, 5968, 6015, 6027, 6038, 6050, 6072, 6084, 6095, 6107,
+    5863, 5875, 5886, 5898, 5920, 5932, 5943, 5955, 6002, 6014, 6025, 6037,
+    6059, 6071, 6082, 6094, 6156, 6168, 6179, 6191, 6213, 6225, 6236, 6248,
+    6295, 6307, 6318, 6330, 6352, 6364, 6375, 6387, 6458, 6470, 6481, 6493,
+    6515, 6527, 6538, 6550, 6597, 6609, 6620, 6632, 6654, 6666, 6677, 6689,
+    6751, 6763, 6774, 6786, 6808, 6820, 6831, 6843, 6890, 6902, 6913, 6925,
+    6947, 6959, 6970, 6982};
+const int vp10_cat6_high_cost[64] = {
+    88,    2251,  2727,  4890,  3148,  5311,  5787,  7950,  3666,  5829,  6305,
+    8468,  6726,  8889,  9365,  11528, 3666,  5829,  6305,  8468,  6726,  8889,
+    9365,  11528, 7244,  9407,  9883,  12046, 10304, 12467, 12943, 15106, 3666,
+    5829,  6305,  8468,  6726,  8889,  9365,  11528, 7244,  9407,  9883,  12046,
+    10304, 12467, 12943, 15106, 7244,  9407,  9883,  12046, 10304, 12467, 12943,
+    15106, 10822, 12985, 13461, 15624, 13882, 16045, 16521, 18684};
 
 #if CONFIG_VP9_HIGHBITDEPTH
-const int16_t vp10_cat6_high10_high_cost[512] = {
-  74, 894, 1185, 2005, 1450, 2270, 2561,
-  3381, 1711, 2531, 2822, 3642, 3087, 3907, 4198, 5018, 2120, 2940, 3231,
-  4051, 3496, 4316, 4607, 5427, 3757, 4577, 4868, 5688, 5133, 5953, 6244,
-  7064, 2120, 2940, 3231, 4051, 3496, 4316, 4607, 5427, 3757, 4577, 4868,
-  5688, 5133, 5953, 6244, 7064, 4166, 4986, 5277, 6097, 5542, 6362, 6653,
-  7473, 5803, 6623, 6914, 7734, 7179, 7999, 8290, 9110, 2120, 2940, 3231,
-  4051, 3496, 4316, 4607, 5427, 3757, 4577, 4868, 5688, 5133, 5953, 6244,
-  7064, 4166, 4986, 5277, 6097, 5542, 6362, 6653, 7473, 5803, 6623, 6914,
-  7734, 7179, 7999, 8290, 9110, 4166, 4986, 5277, 6097, 5542, 6362, 6653,
-  7473, 5803, 6623, 6914, 7734, 7179, 7999, 8290, 9110, 6212, 7032, 7323,
-  8143, 7588, 8408, 8699, 9519, 7849, 8669, 8960, 9780, 9225, 10045, 10336,
-  11156, 2120, 2940, 3231, 4051, 3496, 4316, 4607, 5427, 3757, 4577, 4868,
-  5688, 5133, 5953, 6244, 7064, 4166, 4986, 5277, 6097, 5542, 6362, 6653,
-  7473, 5803, 6623, 6914, 7734, 7179, 7999, 8290, 9110, 4166, 4986, 5277,
-  6097, 5542, 6362, 6653, 7473, 5803, 6623, 6914, 7734, 7179, 7999, 8290,
-  9110, 6212, 7032, 7323, 8143, 7588, 8408, 8699, 9519, 7849, 8669, 8960,
-  9780, 9225, 10045, 10336, 11156, 4166, 4986, 5277, 6097, 5542, 6362, 6653,
-  7473, 5803, 6623, 6914, 7734, 7179, 7999, 8290, 9110, 6212, 7032, 7323,
-  8143, 7588, 8408, 8699, 9519, 7849, 8669, 8960, 9780, 9225, 10045, 10336,
-  11156, 6212, 7032, 7323, 8143, 7588, 8408, 8699, 9519, 7849, 8669, 8960,
-  9780, 9225, 10045, 10336, 11156, 8258, 9078, 9369, 10189, 9634, 10454,
-  10745, 11565, 9895, 10715, 11006, 11826, 11271, 12091, 12382, 13202, 2120,
-  2940, 3231, 4051, 3496, 4316, 4607, 5427, 3757, 4577, 4868, 5688, 5133,
-  5953, 6244, 7064, 4166, 4986, 5277, 6097, 5542, 6362, 6653, 7473, 5803,
-  6623, 6914, 7734, 7179, 7999, 8290, 9110, 4166, 4986, 5277, 6097, 5542,
-  6362, 6653, 7473, 5803, 6623, 6914, 7734, 7179, 7999, 8290, 9110, 6212,
-  7032, 7323, 8143, 7588, 8408, 8699, 9519, 7849, 8669, 8960, 9780, 9225,
-  10045, 10336, 11156, 4166, 4986, 5277, 6097, 5542, 6362, 6653, 7473, 5803,
-  6623, 6914, 7734, 7179, 7999, 8290, 9110, 6212, 7032, 7323, 8143, 7588,
-  8408, 8699, 9519, 7849, 8669, 8960, 9780, 9225, 10045, 10336, 11156, 6212,
-  7032, 7323, 8143, 7588, 8408, 8699, 9519, 7849, 8669, 8960, 9780, 9225,
-  10045, 10336, 11156, 8258, 9078, 9369, 10189, 9634, 10454, 10745, 11565,
-  9895, 10715, 11006, 11826, 11271, 12091, 12382, 13202, 4166, 4986, 5277,
-  6097, 5542, 6362, 6653, 7473, 5803, 6623, 6914, 7734, 7179, 7999, 8290,
-  9110, 6212, 7032, 7323, 8143, 7588, 8408, 8699, 9519, 7849, 8669, 8960,
-  9780, 9225, 10045, 10336, 11156, 6212, 7032, 7323, 8143, 7588, 8408, 8699,
-  9519, 7849, 8669, 8960, 9780, 9225, 10045, 10336, 11156, 8258, 9078, 9369,
-  10189, 9634, 10454, 10745, 11565, 9895, 10715, 11006, 11826, 11271, 12091,
-  12382, 13202, 6212, 7032, 7323, 8143, 7588, 8408, 8699, 9519, 7849, 8669,
-  8960, 9780, 9225, 10045, 10336, 11156, 8258, 9078, 9369, 10189, 9634, 10454,
-  10745, 11565, 9895, 10715, 11006, 11826, 11271, 12091, 12382, 13202, 8258,
-  9078, 9369, 10189, 9634, 10454, 10745, 11565, 9895, 10715, 11006, 11826,
-  11271, 12091, 12382, 13202, 10304, 11124, 11415, 12235, 11680, 12500, 12791,
-  13611, 11941, 12761, 13052, 13872, 13317, 14137, 14428, 15248,
-};
-const int16_t vp10_cat6_high12_high_cost[2048] = {
-  76, 896, 1187, 2007, 1452, 2272, 2563,
-  3383, 1713, 2533, 2824, 3644, 3089, 3909, 4200, 5020, 2122, 2942, 3233,
-  4053, 3498, 4318, 4609, 5429, 3759, 4579, 4870, 5690, 5135, 5955, 6246,
-  7066, 2122, 2942, 3233, 4053, 3498, 4318, 4609, 5429, 3759, 4579, 4870,
-  5690, 5135, 5955, 6246, 7066, 4168, 4988, 5279, 6099, 5544, 6364, 6655,
-  7475, 5805, 6625, 6916, 7736, 7181, 8001, 8292, 9112, 2122, 2942, 3233,
-  4053, 3498, 4318, 4609, 5429, 3759, 4579, 4870, 5690, 5135, 5955, 6246,
-  7066, 4168, 4988, 5279, 6099, 5544, 6364, 6655, 7475, 5805, 6625, 6916,
-  7736, 7181, 8001, 8292, 9112, 4168, 4988, 5279, 6099, 5544, 6364, 6655,
-  7475, 5805, 6625, 6916, 7736, 7181, 8001, 8292, 9112, 6214, 7034, 7325,
-  8145, 7590, 8410, 8701, 9521, 7851, 8671, 8962, 9782, 9227, 10047, 10338,
-  11158, 2122, 2942, 3233, 4053, 3498, 4318, 4609, 5429, 3759, 4579, 4870,
-  5690, 5135, 5955, 6246, 7066, 4168, 4988, 5279, 6099, 5544, 6364, 6655,
-  7475, 5805, 6625, 6916, 7736, 7181, 8001, 8292, 9112, 4168, 4988, 5279,
-  6099, 5544, 6364, 6655, 7475, 5805, 6625, 6916, 7736, 7181, 8001, 8292,
-  9112, 6214, 7034, 7325, 8145, 7590, 8410, 8701, 9521, 7851, 8671, 8962,
-  9782, 9227, 10047, 10338, 11158, 4168, 4988, 5279, 6099, 5544, 6364, 6655,
-  7475, 5805, 6625, 6916, 7736, 7181, 8001, 8292, 9112, 6214, 7034, 7325,
-  8145, 7590, 8410, 8701, 9521, 7851, 8671, 8962, 9782, 9227, 10047, 10338,
-  11158, 6214, 7034, 7325, 8145, 7590, 8410, 8701, 9521, 7851, 8671, 8962,
-  9782, 9227, 10047, 10338, 11158, 8260, 9080, 9371, 10191, 9636, 10456,
-  10747, 11567, 9897, 10717, 11008, 11828, 11273, 12093, 12384, 13204, 2122,
-  2942, 3233, 4053, 3498, 4318, 4609, 5429, 3759, 4579, 4870, 5690, 5135,
-  5955, 6246, 7066, 4168, 4988, 5279, 6099, 5544, 6364, 6655, 7475, 5805,
-  6625, 6916, 7736, 7181, 8001, 8292, 9112, 4168, 4988, 5279, 6099, 5544,
-  6364, 6655, 7475, 5805, 6625, 6916, 7736, 7181, 8001, 8292, 9112, 6214,
-  7034, 7325, 8145, 7590, 8410, 8701, 9521, 7851, 8671, 8962, 9782, 9227,
-  10047, 10338, 11158, 4168, 4988, 5279, 6099, 5544, 6364, 6655, 7475, 5805,
-  6625, 6916, 7736, 7181, 8001, 8292, 9112, 6214, 7034, 7325, 8145, 7590,
-  8410, 8701, 9521, 7851, 8671, 8962, 9782, 9227, 10047, 10338, 11158, 6214,
-  7034, 7325, 8145, 7590, 8410, 8701, 9521, 7851, 8671, 8962, 9782, 9227,
-  10047, 10338, 11158, 8260, 9080, 9371, 10191, 9636, 10456, 10747, 11567,
-  9897, 10717, 11008, 11828, 11273, 12093, 12384, 13204, 4168, 4988, 5279,
-  6099, 5544, 6364, 6655, 7475, 5805, 6625, 6916, 7736, 7181, 8001, 8292,
-  9112, 6214, 7034, 7325, 8145, 7590, 8410, 8701, 9521, 7851, 8671, 8962,
-  9782, 9227, 10047, 10338, 11158, 6214, 7034, 7325, 8145, 7590, 8410, 8701,
-  9521, 7851, 8671, 8962, 9782, 9227, 10047, 10338, 11158, 8260, 9080, 9371,
-  10191, 9636, 10456, 10747, 11567, 9897, 10717, 11008, 11828, 11273, 12093,
-  12384, 13204, 6214, 7034, 7325, 8145, 7590, 8410, 8701, 9521, 7851, 8671,
-  8962, 9782, 9227, 10047, 10338, 11158, 8260, 9080, 9371, 10191, 9636, 10456,
-  10747, 11567, 9897, 10717, 11008, 11828, 11273, 12093, 12384, 13204, 8260,
-  9080, 9371, 10191, 9636, 10456, 10747, 11567, 9897, 10717, 11008, 11828,
-  11273, 12093, 12384, 13204, 10306, 11126, 11417, 12237, 11682, 12502, 12793,
-  13613, 11943, 12763, 13054, 13874, 13319, 14139, 14430, 15250, 2122, 2942,
-  3233, 4053, 3498, 4318, 4609, 5429, 3759, 4579, 4870, 5690, 5135, 5955,
-  6246, 7066, 4168, 4988, 5279, 6099, 5544, 6364, 6655, 7475, 5805, 6625,
-  6916, 7736, 7181, 8001, 8292, 9112, 4168, 4988, 5279, 6099, 5544, 6364,
-  6655, 7475, 5805, 6625, 6916, 7736, 7181, 8001, 8292, 9112, 6214, 7034,
-  7325, 8145, 7590, 8410, 8701, 9521, 7851, 8671, 8962, 9782, 9227, 10047,
-  10338, 11158, 4168, 4988, 5279, 6099, 5544, 6364, 6655, 7475, 5805, 6625,
-  6916, 7736, 7181, 8001, 8292, 9112, 6214, 7034, 7325, 8145, 7590, 8410,
-  8701, 9521, 7851, 8671, 8962, 9782, 9227, 10047, 10338, 11158, 6214, 7034,
-  7325, 8145, 7590, 8410, 8701, 9521, 7851, 8671, 8962, 9782, 9227, 10047,
-  10338, 11158, 8260, 9080, 9371, 10191, 9636, 10456, 10747, 11567, 9897,
-  10717, 11008, 11828, 11273, 12093, 12384, 13204, 4168, 4988, 5279, 6099,
-  5544, 6364, 6655, 7475, 5805, 6625, 6916, 7736, 7181, 8001, 8292, 9112,
-  6214, 7034, 7325, 8145, 7590, 8410, 8701, 9521, 7851, 8671, 8962, 9782,
-  9227, 10047, 10338, 11158, 6214, 7034, 7325, 8145, 7590, 8410, 8701, 9521,
-  7851, 8671, 8962, 9782, 9227, 10047, 10338, 11158, 8260, 9080, 9371, 10191,
-  9636, 10456, 10747, 11567, 9897, 10717, 11008, 11828, 11273, 12093, 12384,
-  13204, 6214, 7034, 7325, 8145, 7590, 8410, 8701, 9521, 7851, 8671, 8962,
-  9782, 9227, 10047, 10338, 11158, 8260, 9080, 9371, 10191, 9636, 10456,
-  10747, 11567, 9897, 10717, 11008, 11828, 11273, 12093, 12384, 13204, 8260,
-  9080, 9371, 10191, 9636, 10456, 10747, 11567, 9897, 10717, 11008, 11828,
-  11273, 12093, 12384, 13204, 10306, 11126, 11417, 12237, 11682, 12502, 12793,
-  13613, 11943, 12763, 13054, 13874, 13319, 14139, 14430, 15250, 4168, 4988,
-  5279, 6099, 5544, 6364, 6655, 7475, 5805, 6625, 6916, 7736, 7181, 8001,
-  8292, 9112, 6214, 7034, 7325, 8145, 7590, 8410, 8701, 9521, 7851, 8671,
-  8962, 9782, 9227, 10047, 10338, 11158, 6214, 7034, 7325, 8145, 7590, 8410,
-  8701, 9521, 7851, 8671, 8962, 9782, 9227, 10047, 10338, 11158, 8260, 9080,
-  9371, 10191, 9636, 10456, 10747, 11567, 9897, 10717, 11008, 11828, 11273,
-  12093, 12384, 13204, 6214, 7034, 7325, 8145, 7590, 8410, 8701, 9521, 7851,
-  8671, 8962, 9782, 9227, 10047, 10338, 11158, 8260, 9080, 9371, 10191, 9636,
-  10456, 10747, 11567, 9897, 10717, 11008, 11828, 11273, 12093, 12384, 13204,
-  8260, 9080, 9371, 10191, 9636, 10456, 10747, 11567, 9897, 10717, 11008,
-  11828, 11273, 12093, 12384, 13204, 10306, 11126, 11417, 12237, 11682, 12502,
-  12793, 13613, 11943, 12763, 13054, 13874, 13319, 14139, 14430, 15250, 6214,
-  7034, 7325, 8145, 7590, 8410, 8701, 9521, 7851, 8671, 8962, 9782, 9227,
-  10047, 10338, 11158, 8260, 9080, 9371, 10191, 9636, 10456, 10747, 11567,
-  9897, 10717, 11008, 11828, 11273, 12093, 12384, 13204, 8260, 9080, 9371,
-  10191, 9636, 10456, 10747, 11567, 9897, 10717, 11008, 11828, 11273, 12093,
-  12384, 13204, 10306, 11126, 11417, 12237, 11682, 12502, 12793, 13613, 11943,
-  12763, 13054, 13874, 13319, 14139, 14430, 15250, 8260, 9080, 9371, 10191,
-  9636, 10456, 10747, 11567, 9897, 10717, 11008, 11828, 11273, 12093, 12384,
-  13204, 10306, 11126, 11417, 12237, 11682, 12502, 12793, 13613, 11943, 12763,
-  13054, 13874, 13319, 14139, 14430, 15250, 10306, 11126, 11417, 12237, 11682,
-  12502, 12793, 13613, 11943, 12763, 13054, 13874, 13319, 14139, 14430, 15250,
-  12352, 13172, 13463, 14283, 13728, 14548, 14839, 15659, 13989, 14809, 15100,
-  15920, 15365, 16185, 16476, 17296, 2122, 2942, 3233, 4053, 3498, 4318, 4609,
-  5429, 3759, 4579, 4870, 5690, 5135, 5955, 6246, 7066, 4168, 4988, 5279,
-  6099, 5544, 6364, 6655, 7475, 5805, 6625, 6916, 7736, 7181, 8001, 8292,
-  9112, 4168, 4988, 5279, 6099, 5544, 6364, 6655, 7475, 5805, 6625, 6916,
-  7736, 7181, 8001, 8292, 9112, 6214, 7034, 7325, 8145, 7590, 8410, 8701,
-  9521, 7851, 8671, 8962, 9782, 9227, 10047, 10338, 11158, 4168, 4988, 5279,
-  6099, 5544, 6364, 6655, 7475, 5805, 6625, 6916, 7736, 7181, 8001, 8292,
-  9112, 6214, 7034, 7325, 8145, 7590, 8410, 8701, 9521, 7851, 8671, 8962,
-  9782, 9227, 10047, 10338, 11158, 6214, 7034, 7325, 8145, 7590, 8410, 8701,
-  9521, 7851, 8671, 8962, 9782, 9227, 10047, 10338, 11158, 8260, 9080, 9371,
-  10191, 9636, 10456, 10747, 11567, 9897, 10717, 11008, 11828, 11273, 12093,
-  12384, 13204, 4168, 4988, 5279, 6099, 5544, 6364, 6655, 7475, 5805, 6625,
-  6916, 7736, 7181, 8001, 8292, 9112, 6214, 7034, 7325, 8145, 7590, 8410,
-  8701, 9521, 7851, 8671, 8962, 9782, 9227, 10047, 10338, 11158, 6214, 7034,
-  7325, 8145, 7590, 8410, 8701, 9521, 7851, 8671, 8962, 9782, 9227, 10047,
-  10338, 11158, 8260, 9080, 9371, 10191, 9636, 10456, 10747, 11567, 9897,
-  10717, 11008, 11828, 11273, 12093, 12384, 13204, 6214, 7034, 7325, 8145,
-  7590, 8410, 8701, 9521, 7851, 8671, 8962, 9782, 9227, 10047, 10338, 11158,
-  8260, 9080, 9371, 10191, 9636, 10456, 10747, 11567, 9897, 10717, 11008,
-  11828, 11273, 12093, 12384, 13204, 8260, 9080, 9371, 10191, 9636, 10456,
-  10747, 11567, 9897, 10717, 11008, 11828, 11273, 12093, 12384, 13204, 10306,
-  11126, 11417, 12237, 11682, 12502, 12793, 13613, 11943, 12763, 13054, 13874,
-  13319, 14139, 14430, 15250, 4168, 4988, 5279, 6099, 5544, 6364, 6655, 7475,
-  5805, 6625, 6916, 7736, 7181, 8001, 8292, 9112, 6214, 7034, 7325, 8145,
-  7590, 8410, 8701, 9521, 7851, 8671, 8962, 9782, 9227, 10047, 10338, 11158,
-  6214, 7034, 7325, 8145, 7590, 8410, 8701, 9521, 7851, 8671, 8962, 9782,
-  9227, 10047, 10338, 11158, 8260, 9080, 9371, 10191, 9636, 10456, 10747,
-  11567, 9897, 10717, 11008, 11828, 11273, 12093, 12384, 13204, 6214, 7034,
-  7325, 8145, 7590, 8410, 8701, 9521, 7851, 8671, 8962, 9782, 9227, 10047,
-  10338, 11158, 8260, 9080, 9371, 10191, 9636, 10456, 10747, 11567, 9897,
-  10717, 11008, 11828, 11273, 12093, 12384, 13204, 8260, 9080, 9371, 10191,
-  9636, 10456, 10747, 11567, 9897, 10717, 11008, 11828, 11273, 12093, 12384,
-  13204, 10306, 11126, 11417, 12237, 11682, 12502, 12793, 13613, 11943, 12763,
-  13054, 13874, 13319, 14139, 14430, 15250, 6214, 7034, 7325, 8145, 7590,
-  8410, 8701, 9521, 7851, 8671, 8962, 9782, 9227, 10047, 10338, 11158, 8260,
-  9080, 9371, 10191, 9636, 10456, 10747, 11567, 9897, 10717, 11008, 11828,
-  11273, 12093, 12384, 13204, 8260, 9080, 9371, 10191, 9636, 10456, 10747,
-  11567, 9897, 10717, 11008, 11828, 11273, 12093, 12384, 13204, 10306, 11126,
-  11417, 12237, 11682, 12502, 12793, 13613, 11943, 12763, 13054, 13874, 13319,
-  14139, 14430, 15250, 8260, 9080, 9371, 10191, 9636, 10456, 10747, 11567,
-  9897, 10717, 11008, 11828, 11273, 12093, 12384, 13204, 10306, 11126, 11417,
-  12237, 11682, 12502, 12793, 13613, 11943, 12763, 13054, 13874, 13319, 14139,
-  14430, 15250, 10306, 11126, 11417, 12237, 11682, 12502, 12793, 13613, 11943,
-  12763, 13054, 13874, 13319, 14139, 14430, 15250, 12352, 13172, 13463, 14283,
-  13728, 14548, 14839, 15659, 13989, 14809, 15100, 15920, 15365, 16185, 16476,
-  17296, 4168, 4988, 5279, 6099, 5544, 6364, 6655, 7475, 5805, 6625, 6916,
-  7736, 7181, 8001, 8292, 9112, 6214, 7034, 7325, 8145, 7590, 8410, 8701,
-  9521, 7851, 8671, 8962, 9782, 9227, 10047, 10338, 11158, 6214, 7034, 7325,
-  8145, 7590, 8410, 8701, 9521, 7851, 8671, 8962, 9782, 9227, 10047, 10338,
-  11158, 8260, 9080, 9371, 10191, 9636, 10456, 10747, 11567, 9897, 10717,
-  11008, 11828, 11273, 12093, 12384, 13204, 6214, 7034, 7325, 8145, 7590,
-  8410, 8701, 9521, 7851, 8671, 8962, 9782, 9227, 10047, 10338, 11158, 8260,
-  9080, 9371, 10191, 9636, 10456, 10747, 11567, 9897, 10717, 11008, 11828,
-  11273, 12093, 12384, 13204, 8260, 9080, 9371, 10191, 9636, 10456, 10747,
-  11567, 9897, 10717, 11008, 11828, 11273, 12093, 12384, 13204, 10306, 11126,
-  11417, 12237, 11682, 12502, 12793, 13613, 11943, 12763, 13054, 13874, 13319,
-  14139, 14430, 15250, 6214, 7034, 7325, 8145, 7590, 8410, 8701, 9521, 7851,
-  8671, 8962, 9782, 9227, 10047, 10338, 11158, 8260, 9080, 9371, 10191, 9636,
-  10456, 10747, 11567, 9897, 10717, 11008, 11828, 11273, 12093, 12384, 13204,
-  8260, 9080, 9371, 10191, 9636, 10456, 10747, 11567, 9897, 10717, 11008,
-  11828, 11273, 12093, 12384, 13204, 10306, 11126, 11417, 12237, 11682, 12502,
-  12793, 13613, 11943, 12763, 13054, 13874, 13319, 14139, 14430, 15250, 8260,
-  9080, 9371, 10191, 9636, 10456, 10747, 11567, 9897, 10717, 11008, 11828,
-  11273, 12093, 12384, 13204, 10306, 11126, 11417, 12237, 11682, 12502, 12793,
-  13613, 11943, 12763, 13054, 13874, 13319, 14139, 14430, 15250, 10306, 11126,
-  11417, 12237, 11682, 12502, 12793, 13613, 11943, 12763, 13054, 13874, 13319,
-  14139, 14430, 15250, 12352, 13172, 13463, 14283, 13728, 14548, 14839, 15659,
-  13989, 14809, 15100, 15920, 15365, 16185, 16476, 17296, 6214, 7034, 7325,
-  8145, 7590, 8410, 8701, 9521, 7851, 8671, 8962, 9782, 9227, 10047, 10338,
-  11158, 8260, 9080, 9371, 10191, 9636, 10456, 10747, 11567, 9897, 10717,
-  11008, 11828, 11273, 12093, 12384, 13204, 8260, 9080, 9371, 10191, 9636,
-  10456, 10747, 11567, 9897, 10717, 11008, 11828, 11273, 12093, 12384, 13204,
-  10306, 11126, 11417, 12237, 11682, 12502, 12793, 13613, 11943, 12763, 13054,
-  13874, 13319, 14139, 14430, 15250, 8260, 9080, 9371, 10191, 9636, 10456,
-  10747, 11567, 9897, 10717, 11008, 11828, 11273, 12093, 12384, 13204, 10306,
-  11126, 11417, 12237, 11682, 12502, 12793, 13613, 11943, 12763, 13054, 13874,
-  13319, 14139, 14430, 15250, 10306, 11126, 11417, 12237, 11682, 12502, 12793,
-  13613, 11943, 12763, 13054, 13874, 13319, 14139, 14430, 15250, 12352, 13172,
-  13463, 14283, 13728, 14548, 14839, 15659, 13989, 14809, 15100, 15920, 15365,
-  16185, 16476, 17296, 8260, 9080, 9371, 10191, 9636, 10456, 10747, 11567,
-  9897, 10717, 11008, 11828, 11273, 12093, 12384, 13204, 10306, 11126, 11417,
-  12237, 11682, 12502, 12793, 13613, 11943, 12763, 13054, 13874, 13319, 14139,
-  14430, 15250, 10306, 11126, 11417, 12237, 11682, 12502, 12793, 13613, 11943,
-  12763, 13054, 13874, 13319, 14139, 14430, 15250, 12352, 13172, 13463, 14283,
-  13728, 14548, 14839, 15659, 13989, 14809, 15100, 15920, 15365, 16185, 16476,
-  17296, 10306, 11126, 11417, 12237, 11682, 12502, 12793, 13613, 11943, 12763,
-  13054, 13874, 13319, 14139, 14430, 15250, 12352, 13172, 13463, 14283, 13728,
-  14548, 14839, 15659, 13989, 14809, 15100, 15920, 15365, 16185, 16476, 17296,
-  12352, 13172, 13463, 14283, 13728, 14548, 14839, 15659, 13989, 14809, 15100,
-  15920, 15365, 16185, 16476, 17296, 14398, 15218, 15509, 16329, 15774, 16594,
-  16885, 17705, 16035, 16855, 17146, 17966, 17411, 18231, 18522, 19342
-};
+const int vp10_cat6_high10_high_cost[256] = {
+    94,    2257,  2733,  4896,  3154,  5317,  5793,  7956,  3672,  5835,  6311,
+    8474,  6732,  8895,  9371,  11534, 3672,  5835,  6311,  8474,  6732,  8895,
+    9371,  11534, 7250,  9413,  9889,  12052, 10310, 12473, 12949, 15112, 3672,
+    5835,  6311,  8474,  6732,  8895,  9371,  11534, 7250,  9413,  9889,  12052,
+    10310, 12473, 12949, 15112, 7250,  9413,  9889,  12052, 10310, 12473, 12949,
+    15112, 10828, 12991, 13467, 15630, 13888, 16051, 16527, 18690, 4187,  6350,
+    6826,  8989,  7247,  9410,  9886,  12049, 7765,  9928,  10404, 12567, 10825,
+    12988, 13464, 15627, 7765,  9928,  10404, 12567, 10825, 12988, 13464, 15627,
+    11343, 13506, 13982, 16145, 14403, 16566, 17042, 19205, 7765,  9928,  10404,
+    12567, 10825, 12988, 13464, 15627, 11343, 13506, 13982, 16145, 14403, 16566,
+    17042, 19205, 11343, 13506, 13982, 16145, 14403, 16566, 17042, 19205, 14921,
+    17084, 17560, 19723, 17981, 20144, 20620, 22783, 4187,  6350,  6826,  8989,
+    7247,  9410,  9886,  12049, 7765,  9928,  10404, 12567, 10825, 12988, 13464,
+    15627, 7765,  9928,  10404, 12567, 10825, 12988, 13464, 15627, 11343, 13506,
+    13982, 16145, 14403, 16566, 17042, 19205, 7765,  9928,  10404, 12567, 10825,
+    12988, 13464, 15627, 11343, 13506, 13982, 16145, 14403, 16566, 17042, 19205,
+    11343, 13506, 13982, 16145, 14403, 16566, 17042, 19205, 14921, 17084, 17560,
+    19723, 17981, 20144, 20620, 22783, 8280,  10443, 10919, 13082, 11340, 13503,
+    13979, 16142, 11858, 14021, 14497, 16660, 14918, 17081, 17557, 19720, 11858,
+    14021, 14497, 16660, 14918, 17081, 17557, 19720, 15436, 17599, 18075, 20238,
+    18496, 20659, 21135, 23298, 11858, 14021, 14497, 16660, 14918, 17081, 17557,
+    19720, 15436, 17599, 18075, 20238, 18496, 20659, 21135, 23298, 15436, 17599,
+    18075, 20238, 18496, 20659, 21135, 23298, 19014, 21177, 21653, 23816, 22074,
+    24237, 24713, 26876};
+const int vp10_cat6_high12_high_cost[1024] = {
+    100,   2263,  2739,  4902,  3160,  5323,  5799,  7962,  3678,  5841,  6317,
+    8480,  6738,  8901,  9377,  11540, 3678,  5841,  6317,  8480,  6738,  8901,
+    9377,  11540, 7256,  9419,  9895,  12058, 10316, 12479, 12955, 15118, 3678,
+    5841,  6317,  8480,  6738,  8901,  9377,  11540, 7256,  9419,  9895,  12058,
+    10316, 12479, 12955, 15118, 7256,  9419,  9895,  12058, 10316, 12479, 12955,
+    15118, 10834, 12997, 13473, 15636, 13894, 16057, 16533, 18696, 4193,  6356,
+    6832,  8995,  7253,  9416,  9892,  12055, 7771,  9934,  10410, 12573, 10831,
+    12994, 13470, 15633, 7771,  9934,  10410, 12573, 10831, 12994, 13470, 15633,
+    11349, 13512, 13988, 16151, 14409, 16572, 17048, 19211, 7771,  9934,  10410,
+    12573, 10831, 12994, 13470, 15633, 11349, 13512, 13988, 16151, 14409, 16572,
+    17048, 19211, 11349, 13512, 13988, 16151, 14409, 16572, 17048, 19211, 14927,
+    17090, 17566, 19729, 17987, 20150, 20626, 22789, 4193,  6356,  6832,  8995,
+    7253,  9416,  9892,  12055, 7771,  9934,  10410, 12573, 10831, 12994, 13470,
+    15633, 7771,  9934,  10410, 12573, 10831, 12994, 13470, 15633, 11349, 13512,
+    13988, 16151, 14409, 16572, 17048, 19211, 7771,  9934,  10410, 12573, 10831,
+    12994, 13470, 15633, 11349, 13512, 13988, 16151, 14409, 16572, 17048, 19211,
+    11349, 13512, 13988, 16151, 14409, 16572, 17048, 19211, 14927, 17090, 17566,
+    19729, 17987, 20150, 20626, 22789, 8286,  10449, 10925, 13088, 11346, 13509,
+    13985, 16148, 11864, 14027, 14503, 16666, 14924, 17087, 17563, 19726, 11864,
+    14027, 14503, 16666, 14924, 17087, 17563, 19726, 15442, 17605, 18081, 20244,
+    18502, 20665, 21141, 23304, 11864, 14027, 14503, 16666, 14924, 17087, 17563,
+    19726, 15442, 17605, 18081, 20244, 18502, 20665, 21141, 23304, 15442, 17605,
+    18081, 20244, 18502, 20665, 21141, 23304, 19020, 21183, 21659, 23822, 22080,
+    24243, 24719, 26882, 4193,  6356,  6832,  8995,  7253,  9416,  9892,  12055,
+    7771,  9934,  10410, 12573, 10831, 12994, 13470, 15633, 7771,  9934,  10410,
+    12573, 10831, 12994, 13470, 15633, 11349, 13512, 13988, 16151, 14409, 16572,
+    17048, 19211, 7771,  9934,  10410, 12573, 10831, 12994, 13470, 15633, 11349,
+    13512, 13988, 16151, 14409, 16572, 17048, 19211, 11349, 13512, 13988, 16151,
+    14409, 16572, 17048, 19211, 14927, 17090, 17566, 19729, 17987, 20150, 20626,
+    22789, 8286,  10449, 10925, 13088, 11346, 13509, 13985, 16148, 11864, 14027,
+    14503, 16666, 14924, 17087, 17563, 19726, 11864, 14027, 14503, 16666, 14924,
+    17087, 17563, 19726, 15442, 17605, 18081, 20244, 18502, 20665, 21141, 23304,
+    11864, 14027, 14503, 16666, 14924, 17087, 17563, 19726, 15442, 17605, 18081,
+    20244, 18502, 20665, 21141, 23304, 15442, 17605, 18081, 20244, 18502, 20665,
+    21141, 23304, 19020, 21183, 21659, 23822, 22080, 24243, 24719, 26882, 8286,
+    10449, 10925, 13088, 11346, 13509, 13985, 16148, 11864, 14027, 14503, 16666,
+    14924, 17087, 17563, 19726, 11864, 14027, 14503, 16666, 14924, 17087, 17563,
+    19726, 15442, 17605, 18081, 20244, 18502, 20665, 21141, 23304, 11864, 14027,
+    14503, 16666, 14924, 17087, 17563, 19726, 15442, 17605, 18081, 20244, 18502,
+    20665, 21141, 23304, 15442, 17605, 18081, 20244, 18502, 20665, 21141, 23304,
+    19020, 21183, 21659, 23822, 22080, 24243, 24719, 26882, 12379, 14542, 15018,
+    17181, 15439, 17602, 18078, 20241, 15957, 18120, 18596, 20759, 19017, 21180,
+    21656, 23819, 15957, 18120, 18596, 20759, 19017, 21180, 21656, 23819, 19535,
+    21698, 22174, 24337, 22595, 24758, 25234, 27397, 15957, 18120, 18596, 20759,
+    19017, 21180, 21656, 23819, 19535, 21698, 22174, 24337, 22595, 24758, 25234,
+    27397, 19535, 21698, 22174, 24337, 22595, 24758, 25234, 27397, 23113, 25276,
+    25752, 27915, 26173, 28336, 28812, 30975, 4193,  6356,  6832,  8995,  7253,
+    9416,  9892,  12055, 7771,  9934,  10410, 12573, 10831, 12994, 13470, 15633,
+    7771,  9934,  10410, 12573, 10831, 12994, 13470, 15633, 11349, 13512, 13988,
+    16151, 14409, 16572, 17048, 19211, 7771,  9934,  10410, 12573, 10831, 12994,
+    13470, 15633, 11349, 13512, 13988, 16151, 14409, 16572, 17048, 19211, 11349,
+    13512, 13988, 16151, 14409, 16572, 17048, 19211, 14927, 17090, 17566, 19729,
+    17987, 20150, 20626, 22789, 8286,  10449, 10925, 13088, 11346, 13509, 13985,
+    16148, 11864, 14027, 14503, 16666, 14924, 17087, 17563, 19726, 11864, 14027,
+    14503, 16666, 14924, 17087, 17563, 19726, 15442, 17605, 18081, 20244, 18502,
+    20665, 21141, 23304, 11864, 14027, 14503, 16666, 14924, 17087, 17563, 19726,
+    15442, 17605, 18081, 20244, 18502, 20665, 21141, 23304, 15442, 17605, 18081,
+    20244, 18502, 20665, 21141, 23304, 19020, 21183, 21659, 23822, 22080, 24243,
+    24719, 26882, 8286,  10449, 10925, 13088, 11346, 13509, 13985, 16148, 11864,
+    14027, 14503, 16666, 14924, 17087, 17563, 19726, 11864, 14027, 14503, 16666,
+    14924, 17087, 17563, 19726, 15442, 17605, 18081, 20244, 18502, 20665, 21141,
+    23304, 11864, 14027, 14503, 16666, 14924, 17087, 17563, 19726, 15442, 17605,
+    18081, 20244, 18502, 20665, 21141, 23304, 15442, 17605, 18081, 20244, 18502,
+    20665, 21141, 23304, 19020, 21183, 21659, 23822, 22080, 24243, 24719, 26882,
+    12379, 14542, 15018, 17181, 15439, 17602, 18078, 20241, 15957, 18120, 18596,
+    20759, 19017, 21180, 21656, 23819, 15957, 18120, 18596, 20759, 19017, 21180,
+    21656, 23819, 19535, 21698, 22174, 24337, 22595, 24758, 25234, 27397, 15957,
+    18120, 18596, 20759, 19017, 21180, 21656, 23819, 19535, 21698, 22174, 24337,
+    22595, 24758, 25234, 27397, 19535, 21698, 22174, 24337, 22595, 24758, 25234,
+    27397, 23113, 25276, 25752, 27915, 26173, 28336, 28812, 30975, 8286,  10449,
+    10925, 13088, 11346, 13509, 13985, 16148, 11864, 14027, 14503, 16666, 14924,
+    17087, 17563, 19726, 11864, 14027, 14503, 16666, 14924, 17087, 17563, 19726,
+    15442, 17605, 18081, 20244, 18502, 20665, 21141, 23304, 11864, 14027, 14503,
+    16666, 14924, 17087, 17563, 19726, 15442, 17605, 18081, 20244, 18502, 20665,
+    21141, 23304, 15442, 17605, 18081, 20244, 18502, 20665, 21141, 23304, 19020,
+    21183, 21659, 23822, 22080, 24243, 24719, 26882, 12379, 14542, 15018, 17181,
+    15439, 17602, 18078, 20241, 15957, 18120, 18596, 20759, 19017, 21180, 21656,
+    23819, 15957, 18120, 18596, 20759, 19017, 21180, 21656, 23819, 19535, 21698,
+    22174, 24337, 22595, 24758, 25234, 27397, 15957, 18120, 18596, 20759, 19017,
+    21180, 21656, 23819, 19535, 21698, 22174, 24337, 22595, 24758, 25234, 27397,
+    19535, 21698, 22174, 24337, 22595, 24758, 25234, 27397, 23113, 25276, 25752,
+    27915, 26173, 28336, 28812, 30975, 12379, 14542, 15018, 17181, 15439, 17602,
+    18078, 20241, 15957, 18120, 18596, 20759, 19017, 21180, 21656, 23819, 15957,
+    18120, 18596, 20759, 19017, 21180, 21656, 23819, 19535, 21698, 22174, 24337,
+    22595, 24758, 25234, 27397, 15957, 18120, 18596, 20759, 19017, 21180, 21656,
+    23819, 19535, 21698, 22174, 24337, 22595, 24758, 25234, 27397, 19535, 21698,
+    22174, 24337, 22595, 24758, 25234, 27397, 23113, 25276, 25752, 27915, 26173,
+    28336, 28812, 30975, 16472, 18635, 19111, 21274, 19532, 21695, 22171, 24334,
+    20050, 22213, 22689, 24852, 23110, 25273, 25749, 27912, 20050, 22213, 22689,
+    24852, 23110, 25273, 25749, 27912, 23628, 25791, 26267, 28430, 26688, 28851,
+    29327, 31490, 20050, 22213, 22689, 24852, 23110, 25273, 25749, 27912, 23628,
+    25791, 26267, 28430, 26688, 28851, 29327, 31490, 23628, 25791, 26267, 28430,
+    26688, 28851, 29327, 31490, 27206, 29369, 29845, 32008, 30266, 32429, 32905,
+    35068};
 #endif
 
 #if CONFIG_VP9_HIGHBITDEPTH
diff --git a/vp10/encoder/tokenize.h b/vp10/encoder/tokenize.h
index c03ec02..12f5f1f 100644
--- a/vp10/encoder/tokenize.h
+++ b/vp10/encoder/tokenize.h
@@ -77,25 +77,25 @@
 extern const TOKENVALUE *vp10_dct_value_tokens_ptr;
 extern const TOKENVALUE *vp10_dct_cat_lt_10_value_tokens;
 extern const int16_t vp10_cat6_low_cost[256];
-extern const int16_t vp10_cat6_high_cost[128];
-extern const int16_t vp10_cat6_high10_high_cost[512];
-extern const int16_t vp10_cat6_high12_high_cost[2048];
-static INLINE int16_t vp10_get_cost(int16_t token, EXTRABIT extrabits,
-                                   const int16_t *cat6_high_table) {
+extern const int vp10_cat6_high_cost[64];
+extern const int vp10_cat6_high10_high_cost[256];
+extern const int vp10_cat6_high12_high_cost[1024];
+static INLINE int vp10_get_cost(int16_t token, EXTRABIT extrabits,
+                               const int *cat6_high_table) {
   if (token != CATEGORY6_TOKEN)
-    return vp10_extra_bits[token].cost[extrabits];
-  return vp10_cat6_low_cost[extrabits & 0xff]
-      + cat6_high_table[extrabits >> 8];
+    return vp10_extra_bits[token].cost[extrabits >> 1];
+  return vp10_cat6_low_cost[(extrabits >> 1) & 0xff]
+      + cat6_high_table[extrabits >> 9];
 }
 
 #if CONFIG_VP9_HIGHBITDEPTH
-static INLINE const int16_t* vp10_get_high_cost_table(int bit_depth) {
+static INLINE const int* vp10_get_high_cost_table(int bit_depth) {
   return bit_depth == 8 ? vp10_cat6_high_cost
       : (bit_depth == 10 ? vp10_cat6_high10_high_cost :
          vp10_cat6_high12_high_cost);
 }
 #else
-static INLINE const int16_t* vp10_get_high_cost_table(int bit_depth) {
+static INLINE const int* vp10_get_high_cost_table(int bit_depth) {
   (void) bit_depth;
   return vp10_cat6_high_cost;
 }
diff --git a/vpx_dsp/sum_squares.c b/vpx_dsp/sum_squares.c
new file mode 100644
index 0000000..8a5a3d9
--- /dev/null
+++ b/vpx_dsp/sum_squares.c
@@ -0,0 +1,29 @@
+/*
+ *  Copyright (c) 2015 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <assert.h>
+
+#include "./vpx_dsp_rtcd.h"
+
+uint64_t vpx_sum_squares_2d_i16_c(const int16_t *src, int src_stride,
+                                  int size) {
+  int r, c;
+  uint64_t ss = 0;
+
+  for (r = 0; r < size; r++) {
+    for (c = 0; c < size; c++) {
+      const int16_t v = src[c];
+      ss += v*v;
+    }
+    src  += src_stride;
+  }
+
+  return ss;
+}
diff --git a/vpx_dsp/vpx_dsp.mk b/vpx_dsp/vpx_dsp.mk
index e394688..a44f948 100644
--- a/vpx_dsp/vpx_dsp.mk
+++ b/vpx_dsp/vpx_dsp.mk
@@ -266,6 +266,12 @@
 
 endif  # CONFIG_VP9_ENCODER || CONFIG_VP10_ENCODER
 
+ifeq ($(CONFIG_VP10_ENCODER),yes)
+DSP_SRCS-yes            += sum_squares.c
+
+DSP_SRCS-$(HAVE_SSE2)   += x86/sum_squares_sse2.c
+endif # CONFIG_VP10_ENCODER
+
 ifeq ($(CONFIG_ENCODERS),yes)
 DSP_SRCS-yes            += sad.c
 DSP_SRCS-yes            += subtract.c
@@ -297,7 +303,6 @@
 DSP_SRCS-$(HAVE_SSE2) += x86/highbd_sad_sse2.asm
 endif  # CONFIG_VP9_HIGHBITDEPTH
 endif  # CONFIG_USE_X86INC
-
 endif  # CONFIG_ENCODERS
 
 ifneq ($(filter yes,$(CONFIG_ENCODERS) $(CONFIG_POSTPROC) $(CONFIG_VP9_POSTPROC)),)
diff --git a/vpx_dsp/vpx_dsp_common.h b/vpx_dsp/vpx_dsp_common.h
index a9e180e..b4e6f4c 100644
--- a/vpx_dsp/vpx_dsp_common.h
+++ b/vpx_dsp/vpx_dsp_common.h
@@ -23,6 +23,18 @@
 #define VPXMIN(x, y) (((x) < (y)) ? (x) : (y))
 #define VPXMAX(x, y) (((x) > (y)) ? (x) : (y))
 
+// These can be used to give a hint about branch outcomes.
+// This can have an effect, even if your target processor has a
+// good branch predictor, as these hints can affect basic block
+// ordering by the compiler.
+#ifdef __GNUC__
+# define LIKELY(v)    __builtin_expect(v, 1)
+# define UNLIKELY(v)  __builtin_expect(v, 0)
+#else
+# define LIKELY(v)    (v)
+# define UNLIKELY(v)  (v)
+#endif
+
 #if CONFIG_VP9_HIGHBITDEPTH
 // Note:
 // tran_low_t  is the datatype used for final transform coefficients.
diff --git a/vpx_dsp/vpx_dsp_rtcd_defs.pl b/vpx_dsp/vpx_dsp_rtcd_defs.pl
index 73726d2..8168b48 100644
--- a/vpx_dsp/vpx_dsp_rtcd_defs.pl
+++ b/vpx_dsp/vpx_dsp_rtcd_defs.pl
@@ -954,6 +954,14 @@
 add_proto qw/void vpx_subtract_block/, "int rows, int cols, int16_t *diff_ptr, ptrdiff_t diff_stride, const uint8_t *src_ptr, ptrdiff_t src_stride, const uint8_t *pred_ptr, ptrdiff_t pred_stride";
 specialize qw/vpx_subtract_block neon msa/, "$sse2_x86inc";
 
+if (vpx_config("CONFIG_VP10_ENCODER") eq "yes") {
+#
+# Sum of Squares
+#
+  add_proto qw/uint64_t vpx_sum_squares_2d_i16/, "const int16_t *src, int stride, int size";
+  specialize qw/vpx_sum_squares_2d_i16 sse2/;
+}
+
 #
 # Single block SAD
 #
diff --git a/vpx_dsp/x86/sum_squares_sse2.c b/vpx_dsp/x86/sum_squares_sse2.c
new file mode 100644
index 0000000..ed1dc0c
--- /dev/null
+++ b/vpx_dsp/x86/sum_squares_sse2.c
@@ -0,0 +1,119 @@
+/*
+ *  Copyright (c) 2015 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <assert.h>
+#include <emmintrin.h>
+#include <stdio.h>
+
+#include "./vpx_dsp_rtcd.h"
+
+static uint64_t vpx_sum_squares_2d_i16_4x4_sse2(const int16_t *src,
+                                                int stride) {
+  const __m128i v_val_0_w = _mm_loadl_epi64((const __m128i*)(src+0*stride));
+  const __m128i v_val_1_w = _mm_loadl_epi64((const __m128i*)(src+1*stride));
+  const __m128i v_val_2_w = _mm_loadl_epi64((const __m128i*)(src+2*stride));
+  const __m128i v_val_3_w = _mm_loadl_epi64((const __m128i*)(src+3*stride));
+
+  const __m128i v_sq_0_d = _mm_madd_epi16(v_val_0_w, v_val_0_w);
+  const __m128i v_sq_1_d = _mm_madd_epi16(v_val_1_w, v_val_1_w);
+  const __m128i v_sq_2_d = _mm_madd_epi16(v_val_2_w, v_val_2_w);
+  const __m128i v_sq_3_d = _mm_madd_epi16(v_val_3_w, v_val_3_w);
+
+  const __m128i v_sum_01_d = _mm_add_epi32(v_sq_0_d, v_sq_1_d);
+  const __m128i v_sum_23_d = _mm_add_epi32(v_sq_2_d, v_sq_3_d);
+  const __m128i v_sum_0123_d = _mm_add_epi32(v_sum_01_d, v_sum_23_d);
+
+  const __m128i v_sum_d = _mm_add_epi32(v_sum_0123_d,
+                                        _mm_srli_epi64(v_sum_0123_d, 32));
+
+  return (uint64_t)_mm_cvtsi128_si32(v_sum_d);
+}
+
+#ifdef __GNUC__
+// This prevents GCC/Clang from inlining this function into
+// vpx_sum_squares_2d_i16_sse2, which in turn saves some stack
+// maintenance instructions in the common case of 4x4.
+__attribute__((noinline))
+#endif
+static uint64_t vpx_sum_squares_2d_i16_nxn_sse2(const int16_t *src,
+                                                int stride,
+                                                int size) {
+  int r, c;
+
+  const __m128i v_zext_mask_q = _mm_set_epi32(0, 0xffffffff, 0, 0xffffffff);
+  __m128i v_acc_q = _mm_setzero_si128();
+
+  for (r = 0; r < size; r += 8) {
+    __m128i v_acc_d = _mm_setzero_si128();
+
+    for (c = 0; c < size; c += 8) {
+      const int16_t *b = src+c;
+
+      const __m128i v_val_0_w = _mm_load_si128((const __m128i*)(b+0*stride));
+      const __m128i v_val_1_w = _mm_load_si128((const __m128i*)(b+1*stride));
+      const __m128i v_val_2_w = _mm_load_si128((const __m128i*)(b+2*stride));
+      const __m128i v_val_3_w = _mm_load_si128((const __m128i*)(b+3*stride));
+      const __m128i v_val_4_w = _mm_load_si128((const __m128i*)(b+4*stride));
+      const __m128i v_val_5_w = _mm_load_si128((const __m128i*)(b+5*stride));
+      const __m128i v_val_6_w = _mm_load_si128((const __m128i*)(b+6*stride));
+      const __m128i v_val_7_w = _mm_load_si128((const __m128i*)(b+7*stride));
+
+      const __m128i v_sq_0_d = _mm_madd_epi16(v_val_0_w, v_val_0_w);
+      const __m128i v_sq_1_d = _mm_madd_epi16(v_val_1_w, v_val_1_w);
+      const __m128i v_sq_2_d = _mm_madd_epi16(v_val_2_w, v_val_2_w);
+      const __m128i v_sq_3_d = _mm_madd_epi16(v_val_3_w, v_val_3_w);
+      const __m128i v_sq_4_d = _mm_madd_epi16(v_val_4_w, v_val_4_w);
+      const __m128i v_sq_5_d = _mm_madd_epi16(v_val_5_w, v_val_5_w);
+      const __m128i v_sq_6_d = _mm_madd_epi16(v_val_6_w, v_val_6_w);
+      const __m128i v_sq_7_d = _mm_madd_epi16(v_val_7_w, v_val_7_w);
+
+      const __m128i v_sum_01_d = _mm_add_epi32(v_sq_0_d, v_sq_1_d);
+      const __m128i v_sum_23_d = _mm_add_epi32(v_sq_2_d, v_sq_3_d);
+      const __m128i v_sum_45_d = _mm_add_epi32(v_sq_4_d, v_sq_5_d);
+      const __m128i v_sum_67_d = _mm_add_epi32(v_sq_6_d, v_sq_7_d);
+
+      const __m128i v_sum_0123_d = _mm_add_epi32(v_sum_01_d, v_sum_23_d);
+      const __m128i v_sum_4567_d = _mm_add_epi32(v_sum_45_d, v_sum_67_d);
+
+      v_acc_d = _mm_add_epi32(v_acc_d, v_sum_0123_d);
+      v_acc_d = _mm_add_epi32(v_acc_d, v_sum_4567_d);
+    }
+
+    v_acc_q = _mm_add_epi64(v_acc_q, _mm_and_si128(v_acc_d, v_zext_mask_q));
+    v_acc_q = _mm_add_epi64(v_acc_q, _mm_srli_epi64(v_acc_d, 32));
+
+    src += 8*stride;
+  }
+
+  v_acc_q = _mm_add_epi64(v_acc_q, _mm_srli_si128(v_acc_q, 8));
+
+#if ARCH_X86_64
+  return (uint64_t)_mm_cvtsi128_si64(v_acc_q);
+#else
+  {
+    uint64_t tmp;
+    _mm_storel_epi64((__m128i*)&tmp, v_acc_q);
+    return tmp;
+  }
+#endif
+}
+
+uint64_t vpx_sum_squares_2d_i16_sse2(const int16_t *src, int stride,
+                                     int size) {
+  // 4 elements per row only requires half an XMM register, so this
+  // must be a special case, but also note that over 75% of all calls
+  // are with size == 4, so it is also the common case.
+  if (LIKELY(size == 4)) {
+    return vpx_sum_squares_2d_i16_4x4_sse2(src, stride);
+  } else {
+  // Generic case
+    return vpx_sum_squares_2d_i16_nxn_sse2(src, stride, size);
+  }
+}