Merge "Rework transform quantization pipeline" into nextgenv2
diff --git a/test/array_utils.h b/test/array_utils.h
deleted file mode 100644
index 8d4310e..0000000
--- a/test/array_utils.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- *  Copyright (c) 2016 The WebM project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-
-#ifndef TEST_ARRAY_UTILS_H_
-#define TEST_ARRAY_UTILS_H_
-
-#include "third_party/googletest/src/include/gtest/gtest.h"
-
-namespace libvpx_test {
-namespace array_utils {
-
-template<typename T, size_t n, typename V>
-void arraySet(T (&arr)[n], const V &v) {
-  for (size_t i = 0; i < n ; i++) {
-    arr[i] = v;
-  }
-}
-
-template<typename T, size_t n, size_t m, typename V>
-void arraySet(T (&arr)[n][m], const V &v) {
-  for (size_t i = 0; i < n ; i++) {
-    for (size_t j = 0; j < m ; j++) {
-      arr[i][j] = v;
-    }
-  }
-}
-
-}   // namespace array_utils
-}   // namespace libvpx_test
-
-#endif  // TEST_ARRAY_UTILS_H_
diff --git a/test/sum_squares_test.cc b/test/sum_squares_test.cc
index cf550ea..7de7a81 100644
--- a/test/sum_squares_test.cc
+++ b/test/sum_squares_test.cc
@@ -8,145 +8,126 @@
  *  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/array_utils.h"
-#include "test/assertion_helpers.h"
-#include "test/function_equivalence_test.h"
-#include "test/randomise.h"
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
 #include "test/register_state_check.h"
-#include "test/snapshot.h"
+#include "test/util.h"
 
-using libvpx_test::FunctionEquivalenceTest;
-using libvpx_test::Snapshot;
-using libvpx_test::Randomise;
-using libvpx_test::array_utils::arraySet;
-using libvpx_test::assertion_helpers::ArraysEq;
+
+using libvpx_test::ACMRandom;
 
 namespace {
+const int kNumIterations = 10000;
 
-static const int16_t int13_max = (1<<12) - 1;
+typedef uint64_t (*SSI16Func)(const int16_t *src,
+                             int stride ,
+                             int size);
 
-//////////////////////////////////////////////////////////////////////////////
-// 2D version
-//////////////////////////////////////////////////////////////////////////////
+typedef std::tr1::tuple<SSI16Func, SSI16Func> SumSquaresParam;
 
-typedef uint64_t (*F2D)(const int16_t *src, int stride, uint32_t size);
-
-class SumSquares2DTest : public FunctionEquivalenceTest<F2D> {
- protected:
-  void Common() {
-    const int sizelog2 = randomise.uniform<int>(2, 8);
-
-    const uint32_t size = 1 << sizelog2;
-    const int stride = 1 << randomise.uniform<int>(sizelog2, 9);
-
-    snapshot(src);
-
-    uint64_t ref_res, tst_res;
-
-    ref_res = ref_func_(src, stride, size);
-    ASM_REGISTER_STATE_CHECK(tst_res = tst_func_(src, stride, size));
-
-    ASSERT_EQ(ref_res, tst_res);
-
-    ASSERT_TRUE(ArraysEq(snapshot.get(src), src));
+class SumSquaresTest : public ::testing::TestWithParam<SumSquaresParam> {
+ public:
+  virtual ~SumSquaresTest() {}
+  virtual void SetUp() {
+    ref_func_ = GET_PARAM(0);
+    tst_func_ = GET_PARAM(1);
   }
 
-  Snapshot snapshot;
-  Randomise randomise;
+  virtual void TearDown() { libvpx_test::ClearSystemState(); }
 
-  DECLARE_ALIGNED(16, int16_t, src[256*256]);
+ protected:
+  SSI16Func ref_func_;
+  SSI16Func tst_func_;
 };
 
-TEST_P(SumSquares2DTest, RandomValues) {
-  for (int i = 0 ; i < 10000 && !HasFatalFailure(); i++) {
-    randomise(src, -int13_max, int13_max + 1);
+TEST_P(SumSquaresTest, OperationCheck) {
+  ACMRandom rnd(ACMRandom::DeterministicSeed());
+  DECLARE_ALIGNED(16, int16_t, src[256*256]);
 
-    Common();
+  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(SumSquares2DTest, ExtremeValues) {
-  for (int i = 0 ; i < 10000 && !HasFatalFailure(); i++) {
-    if (randomise.uniform<bool>())
-      arraySet(src, int13_max);
-    else
-      arraySet(src, -int13_max);
+TEST_P(SumSquaresTest, ExtremeValues) {
+  ACMRandom rnd(ACMRandom::DeterministicSeed());
+  DECLARE_ALIGNED(16, int16_t, src[256*256]);
 
-    Common();
+  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, SumSquares2DTest,
+    SSE2, SumSquaresTest,
     ::testing::Values(
         make_tuple(&vpx_sum_squares_2d_i16_c, &vpx_sum_squares_2d_i16_sse2)
     )
 );
 #endif  // HAVE_SSE2
-
-//////////////////////////////////////////////////////////////////////////////
-// 1D version
-//////////////////////////////////////////////////////////////////////////////
-
-typedef uint64_t (*F1D)(const int16_t *src, uint32_t N);
-
-class SumSquares1DTest : public FunctionEquivalenceTest<F1D> {
- protected:
-  void Common() {
-    const int N = randomise.uniform<int>(1, 256*256-1);
-
-    snapshot(src);
-
-    uint64_t ref_res, tst_res;
-
-    ref_res = ref_func_(src, N);
-    ASM_REGISTER_STATE_CHECK(tst_res = tst_func_(src, N));
-
-    ASSERT_EQ(ref_res, tst_res);
-
-    ASSERT_TRUE(ArraysEq(snapshot.get(src), src));
-  }
-
-  Snapshot snapshot;
-  Randomise randomise;
-
-  DECLARE_ALIGNED(16, int16_t, src[256*256]);
-};
-
-TEST_P(SumSquares1DTest, RandomValues) {
-  for (int i = 0 ; i < 10000 && !HasFatalFailure(); i++) {
-    randomise(src, -int13_max, int13_max+1);
-
-    Common();
-  }
-}
-
-TEST_P(SumSquares1DTest, ExtremeValues) {
-  for (int i = 0 ; i < 10000 && !HasFatalFailure(); i++) {
-    if (randomise.uniform<bool>())
-      arraySet(src, int13_max);
-    else
-      arraySet(src, -int13_max);
-
-    Common();
-  }
-}
-using std::tr1::make_tuple;
-
-#if HAVE_SSE2
-INSTANTIATE_TEST_CASE_P(
-    SSE2, SumSquares1DTest,
-    ::testing::Values(
-        make_tuple(&vpx_sum_squares_i16_c, &vpx_sum_squares_i16_sse2)
-    )
-);
-#endif  // HAVE_SSE2
 }  // namespace
diff --git a/vp10/common/reconinter.c b/vp10/common/reconinter.c
index d7b63a3..866bda8 100644
--- a/vp10/common/reconinter.c
+++ b/vp10/common/reconinter.c
@@ -333,22 +333,15 @@
   return master;
 }
 
-static const uint8_t *get_wedge_mask(int wedge_index,
-                                     int neg,
-                                     BLOCK_SIZE bsize) {
-  return wedge_params_lookup[bsize].masks[neg][wedge_index];
-}
-
 const uint8_t *vp10_get_soft_mask(int wedge_index,
                                   int wedge_sign,
                                   BLOCK_SIZE sb_type,
                                   int offset_x,
                                   int offset_y) {
-  const int bw = 4 * num_4x4_blocks_wide_lookup[sb_type];
   const uint8_t *mask =
-      get_wedge_mask(wedge_index, wedge_sign, sb_type);
+      get_wedge_mask_inplace(wedge_index, wedge_sign, sb_type);
   if (mask)
-    mask -= (offset_x + offset_y * bw);
+    mask -= (offset_x + offset_y * MASK_MASTER_STRIDE);
   return mask;
 }
 
@@ -469,7 +462,7 @@
   vpx_blend_mask6(dst, dst_stride,
                   src0, src0_stride,
                   src1, src1_stride,
-                  mask, 4 * num_4x4_blocks_wide_lookup[sb_type],
+                  mask, MASK_MASTER_STRIDE,
                   h, w, subh, subw);
 }
 
@@ -489,7 +482,7 @@
   vpx_highbd_blend_mask6(dst_8, dst_stride,
                          src0_8, src0_stride,
                          src1_8, src1_stride,
-                         mask, 4 * num_4x4_blocks_wide_lookup[sb_type],
+                         mask, MASK_MASTER_STRIDE,
                          h, w, subh, subw, bd);
 }
 #endif  // CONFIG_VP9_HIGHBITDEPTH
@@ -506,8 +499,8 @@
   // pass in subsampling factors directly.
   const int subh = (2 << b_height_log2_lookup[sb_type]) == h;
   const int subw = (2 << b_width_log2_lookup[sb_type]) == w;
-  const uint8_t *mask = vp10_get_soft_mask(wedge_index, wedge_sign,
-                                           sb_type, 0, 0);
+  const uint8_t *mask = vp10_get_contiguous_soft_mask(wedge_index, wedge_sign,
+                                                      sb_type);
   vpx_blend_mask6(dst, dst_stride,
                   src0, src0_stride,
                   src1, src1_stride,
@@ -526,8 +519,8 @@
   // pass in subsampling factors directly.
   const int subh = (2 << b_height_log2_lookup[sb_type]) == h;
   const int subw = (2 << b_width_log2_lookup[sb_type]) == w;
-  const uint8_t *mask = vp10_get_soft_mask(wedge_index, wedge_sign,
-                                           sb_type, 0, 0);
+  const uint8_t *mask = vp10_get_contiguous_soft_mask(wedge_index, wedge_sign,
+                                                      sb_type);
   vpx_highbd_blend_mask6(dst_8, dst_stride,
                          src0_8, src0_stride,
                          src1_8, src1_stride,
@@ -713,66 +706,79 @@
 
 #if CONFIG_DUAL_FILTER
   if (mi->mbmi.sb_type < BLOCK_8X8 && plane > 0) {
-    int blk_num = 1 << (pd->subsampling_x + pd->subsampling_y);
-    int chr_idx;
-    int x_base = x;
-    int y_base = y;
-    int x_step = w >> pd->subsampling_x;
-    int y_step = h >> pd->subsampling_y;
+    // block size in log2
+    const int b4_wl = b_width_log2_lookup[mi->mbmi.sb_type];
+    const int b4_hl = b_height_log2_lookup[mi->mbmi.sb_type];
+    const int b8_sl = b_width_log2_lookup[BLOCK_8X8];
 
-    for (chr_idx = 0; chr_idx < blk_num; ++chr_idx) {
-      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];
-        struct buf_2d *const dst_buf = &pd->dst;
-        uint8_t *dst = dst_buf->buf;
-        const MV mv = mi->bmi[chr_idx].as_mv[ref].as_mv;
-        const MV mv_q4 = clamp_mv_to_umv_border_sb(xd, &mv, bw, bh,
-                                                   pd->subsampling_x,
-                                                   pd->subsampling_y);
-        uint8_t *pre;
-        MV32 scaled_mv;
-        int xs, ys, subpel_x, subpel_y;
-        const int is_scaled = vp10_is_scaled(sf);
+    // block size
+    const int b4_w = 1 << b4_wl;
+    const int b4_h = 1 << b4_hl;
+    const int b8_s = 1 << b8_sl;
+    int idx, idy;
 
-        x = x_base + (chr_idx & 0x01) * x_step;
-        y = y_base + (chr_idx >> 1) * y_step;
+    const int x_base = x;
+    const int y_base = y;
 
-        dst += dst_buf->stride * y + x;
+    // processing unit size
+    const int x_step = w >> (b8_sl - b4_wl);
+    const int y_step = h >> (b8_sl - b4_hl);
 
-        if (is_scaled) {
-          pre = pre_buf->buf + scaled_buffer_offset(x, y, pre_buf->stride, sf);
-          scaled_mv = vp10_scale_mv(&mv_q4, mi_x + x, mi_y + y, sf);
-          xs = sf->x_step_q4;
-          ys = sf->y_step_q4;
-        } else {
-          pre = pre_buf->buf + y * pre_buf->stride + x;
-          scaled_mv.row = mv_q4.row;
-          scaled_mv.col = mv_q4.col;
-          xs = ys = 16;
+    for (idy = 0; idy < b8_s; idy += b4_h) {
+      for (idx = 0; idx < b8_s; idx += b4_w) {
+        const int chr_idx = (idy * 2) + idx;
+        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];
+          struct buf_2d *const dst_buf = &pd->dst;
+          uint8_t *dst = dst_buf->buf;
+          const MV mv = mi->bmi[chr_idx].as_mv[ref].as_mv;
+          const MV mv_q4 = clamp_mv_to_umv_border_sb(
+              xd, &mv, bw, bh, pd->subsampling_x, pd->subsampling_y);
+          uint8_t *pre;
+          MV32 scaled_mv;
+          int xs, ys, subpel_x, subpel_y;
+          const int is_scaled = vp10_is_scaled(sf);
+
+          x = x_base + idx * x_step;
+          y = y_base + idy * y_step;
+
+          dst += dst_buf->stride * y + x;
+
+          if (is_scaled) {
+            pre =
+                pre_buf->buf + scaled_buffer_offset(x, y, pre_buf->stride, sf);
+            scaled_mv = vp10_scale_mv(&mv_q4, mi_x + x, mi_y + y, sf);
+            xs = sf->x_step_q4;
+            ys = sf->y_step_q4;
+          } else {
+            pre = pre_buf->buf + y * pre_buf->stride + x;
+            scaled_mv.row = mv_q4.row;
+            scaled_mv.col = mv_q4.col;
+            xs = ys = 16;
+          }
+
+          subpel_x = scaled_mv.col & SUBPEL_MASK;
+          subpel_y = scaled_mv.row & SUBPEL_MASK;
+          pre += (scaled_mv.row >> SUBPEL_BITS) * pre_buf->stride +
+                 (scaled_mv.col >> SUBPEL_BITS);
+
+#if CONFIG_EXT_INTER
+          if (ref && is_interinter_wedge_used(mi->mbmi.sb_type) &&
+              mi->mbmi.use_wedge_interinter)
+            vp10_make_masked_inter_predictor(
+                pre, pre_buf->stride, dst, dst_buf->stride, subpel_x, subpel_y,
+                sf, w, h, mi->mbmi.interp_filter, xs, ys,
+#if CONFIG_SUPERTX
+                wedge_offset_x, wedge_offset_y,
+#endif  // CONFIG_SUPERTX
+                xd);
+          else
+#endif  // CONFIG_EXT_INTER
+            vp10_make_inter_predictor(
+                pre, pre_buf->stride, dst, dst_buf->stride, subpel_x, subpel_y,
+                sf, x_step, y_step, ref, mi->mbmi.interp_filter, xs, ys, xd);
         }
-
-        subpel_x = scaled_mv.col & SUBPEL_MASK;
-        subpel_y = scaled_mv.row & SUBPEL_MASK;
-        pre += (scaled_mv.row >> SUBPEL_BITS) * pre_buf->stride
-               + (scaled_mv.col >> SUBPEL_BITS);
-
-    #if CONFIG_EXT_INTER
-        if (ref && is_interinter_wedge_used(mi->mbmi.sb_type) &&
-            mi->mbmi.use_wedge_interinter)
-          vp10_make_masked_inter_predictor(
-              pre, pre_buf->stride, dst, dst_buf->stride,
-              subpel_x, subpel_y, sf, w, h,
-              mi->mbmi.interp_filter, xs, ys,
-    #if CONFIG_SUPERTX
-              wedge_offset_x, wedge_offset_y,
-    #endif  // CONFIG_SUPERTX
-              xd);
-        else
-    #endif  // CONFIG_EXT_INTER
-          vp10_make_inter_predictor(pre, pre_buf->stride, dst, dst_buf->stride,
-                                    subpel_x, subpel_y, sf, x_step, y_step, ref,
-                                    mi->mbmi.interp_filter, xs, ys, xd);
       }
     }
     return;
@@ -1887,8 +1893,9 @@
 
   if (use_wedge_interintra) {
     if (is_interintra_wedge_used(bsize)) {
-      const uint8_t *mask = vp10_get_soft_mask(wedge_index, wedge_sign,
-                                               bsize, 0, 0);
+      const uint8_t *mask = vp10_get_contiguous_soft_mask(wedge_index,
+                                                          wedge_sign,
+                                                          bsize);
       const int subw = 2 * num_4x4_blocks_wide_lookup[bsize] == bw;
       const int subh = 2 * num_4x4_blocks_high_lookup[bsize] == bh;
       vpx_blend_mask6(comppred, compstride,
@@ -2026,8 +2033,9 @@
 
   if (use_wedge_interintra) {
     if (is_interintra_wedge_used(bsize)) {
-      const uint8_t *mask = vp10_get_soft_mask(wedge_index, wedge_sign,
-                                               bsize, 0, 0);
+      const uint8_t *mask = vp10_get_contiguous_soft_mask(wedge_index,
+                                                          wedge_sign,
+                                                          bsize);
       const int subh = 2 * num_4x4_blocks_high_lookup[bsize] == bh;
       const int subw = 2 * num_4x4_blocks_wide_lookup[bsize] == bw;
       vpx_highbd_blend_mask6(comppred8, compstride,
diff --git a/vp10/common/reconinter.h b/vp10/common/reconinter.h
index e84e20e..537d767 100644
--- a/vp10/common/reconinter.h
+++ b/vp10/common/reconinter.h
@@ -589,6 +589,12 @@
 
 void vp10_init_wedge_masks();
 
+static INLINE const uint8_t *vp10_get_contiguous_soft_mask(int wedge_index,
+                                                           int wedge_sign,
+                                                           BLOCK_SIZE sb_type) {
+  return wedge_params_lookup[sb_type].masks[wedge_sign][wedge_index];
+}
+
 const uint8_t *vp10_get_soft_mask(int wedge_index,
                                   int wedge_sign,
                                   BLOCK_SIZE sb_type,
diff --git a/vp10/encoder/rdopt.c b/vp10/encoder/rdopt.c
index 7079b2b..51ee898 100644
--- a/vp10/encoder/rdopt.c
+++ b/vp10/encoder/rdopt.c
@@ -6513,7 +6513,7 @@
   BLOCK_SIZE sb_type = mbmi->sb_type;
   const uint8_t *mask;
   const int mask_stride = 4 * num_4x4_blocks_wide_lookup[bsize];
-  mask = vp10_get_soft_mask(wedge_index, wedge_sign, sb_type, 0, 0);
+  mask = vp10_get_contiguous_soft_mask(wedge_index, wedge_sign, sb_type);
 
   if (which == 0 || which == 2)
     do_masked_motion_search(cpi, x, mask, mask_stride, bsize,
@@ -6522,7 +6522,7 @@
 
   if (which == 1 || which == 2) {
     // get the negative mask
-    mask = vp10_get_soft_mask(wedge_index, !wedge_sign, sb_type, 0, 0);
+    mask = vp10_get_contiguous_soft_mask(wedge_index, !wedge_sign, sb_type);
     do_masked_motion_search(cpi, x, mask, mask_stride, bsize,
                             mi_row, mi_col, &tmp_mv[1], &rate_mv[1],
                             1, mv_idx[1]);
@@ -7578,8 +7578,8 @@
         // Refine motion vector.
         if (have_newmv_in_inter_mode(this_mode) && best_wedge_index > -1) {
           // get negative of mask
-          const uint8_t* mask = vp10_get_soft_mask(
-              best_wedge_index, 1, bsize, 0, 0);
+          const uint8_t* mask = vp10_get_contiguous_soft_mask(
+              best_wedge_index, 1, bsize);
           mbmi->interintra_wedge_index = best_wedge_index;
           mbmi->interintra_wedge_sign = 0;
           do_masked_motion_search(cpi, x, mask, bw, bsize,
@@ -8308,6 +8308,189 @@
       color_map[r * cols + c] = indices[r * cols + c];
 }
 
+#if CONFIG_EXT_INTRA
+static void pick_ext_intra_iframe(VP10_COMP *cpi, MACROBLOCK *x,
+                                  PICK_MODE_CONTEXT *ctx, BLOCK_SIZE bsize,
+                                  int *rate_uv_intra, int *rate_uv_tokenonly,
+                                  int64_t *dist_uv, int *skip_uv,
+                                  PREDICTION_MODE *mode_uv,
+                                  EXT_INTRA_MODE_INFO *ext_intra_mode_info_uv,
+                                  PALETTE_MODE_INFO *pmi_uv,
+                                  int8_t *uv_angle_delta,
+                                  int palette_ctx, int skip_mask,
+                                  unsigned int *ref_costs_single,
+                                  int64_t *best_rd, int64_t *best_intra_rd,
+                                  PREDICTION_MODE *best_intra_mode,
+                                  int *best_mode_index, int *best_skip2,
+                                  int *best_mode_skippable,
+#if CONFIG_SUPERTX
+                                  int *returnrate_nocoef,
+#endif  // CONFIG_SUPERTX
+                                  int64_t *best_pred_rd,
+                                  MB_MODE_INFO *best_mbmode, RD_COST *rd_cost) {
+  VP10_COMMON *const cm = &cpi->common;
+  MACROBLOCKD *const xd = &x->e_mbd;
+  MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
+  PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
+  const TX_SIZE max_tx_size = max_txsize_lookup[bsize];
+  int rate2 = 0, rate_y = INT_MAX, skippable = 0, rate_uv, rate_dummy, i;
+  int dc_mode_index;
+  const int * const intra_mode_cost =
+      cpi->mbmode_cost[size_group_lookup[bsize]];
+  int64_t distortion2 = 0, distortion_y = 0, this_rd = *best_rd, distortion_uv;
+  TX_SIZE uv_tx;
+
+  for (i = 0; i < MAX_MODES; ++i)
+    if (vp10_mode_order[i].mode == DC_PRED &&
+        vp10_mode_order[i].ref_frame[0] == INTRA_FRAME)
+      break;
+  dc_mode_index = i;
+  assert(i < MAX_MODES);
+
+  // TODO(huisu): use skip_mask for further speedup.
+  (void)skip_mask;
+  mbmi->mode = DC_PRED;
+  mbmi->uv_mode = DC_PRED;
+  mbmi->ref_frame[0] = INTRA_FRAME;
+  mbmi->ref_frame[1] = NONE;
+  memset(x->skip_txfm, SKIP_TXFM_NONE, sizeof(x->skip_txfm));
+  if (!rd_pick_ext_intra_sby(cpi, x, &rate_dummy, &rate_y, &distortion_y,
+                             &skippable, bsize,
+                             intra_mode_cost[mbmi->mode], &this_rd, 0))
+    return;
+  if (rate_y == INT_MAX)
+    return;
+
+  uv_tx = get_uv_tx_size_impl(mbmi->tx_size, bsize,
+                              xd->plane[1].subsampling_x,
+                              xd->plane[1].subsampling_y);
+  if (rate_uv_intra[uv_tx] == INT_MAX) {
+    choose_intra_uv_mode(cpi, x, ctx, bsize, uv_tx,
+                         &rate_uv_intra[uv_tx], &rate_uv_tokenonly[uv_tx],
+                         &dist_uv[uv_tx], &skip_uv[uv_tx], &mode_uv[uv_tx]);
+    if (cm->allow_screen_content_tools)
+      pmi_uv[uv_tx] = *pmi;
+    ext_intra_mode_info_uv[uv_tx] = mbmi->ext_intra_mode_info;
+    uv_angle_delta[uv_tx] = mbmi->angle_delta[1];
+  }
+
+  rate_uv = rate_uv_tokenonly[uv_tx];
+  distortion_uv = dist_uv[uv_tx];
+  skippable = skippable && skip_uv[uv_tx];
+  mbmi->uv_mode = mode_uv[uv_tx];
+  if (cm->allow_screen_content_tools) {
+    pmi->palette_size[1] = pmi_uv[uv_tx].palette_size[1];
+    memcpy(pmi->palette_colors + PALETTE_MAX_SIZE,
+           pmi_uv[uv_tx].palette_colors + PALETTE_MAX_SIZE,
+           2 * PALETTE_MAX_SIZE * sizeof(pmi->palette_colors[0]));
+  }
+  mbmi->angle_delta[1] = uv_angle_delta[uv_tx];
+  mbmi->ext_intra_mode_info.use_ext_intra_mode[1] =
+      ext_intra_mode_info_uv[uv_tx].use_ext_intra_mode[1];
+  if (ext_intra_mode_info_uv[uv_tx].use_ext_intra_mode[1]) {
+    mbmi->ext_intra_mode_info.ext_intra_mode[1] =
+        ext_intra_mode_info_uv[uv_tx].ext_intra_mode[1];
+  }
+
+  rate2 = rate_y + intra_mode_cost[mbmi->mode] + rate_uv +
+      cpi->intra_uv_mode_cost[mbmi->mode][mbmi->uv_mode];
+  if (cpi->common.allow_screen_content_tools && mbmi->mode == DC_PRED)
+    rate2 +=
+        vp10_cost_bit(vp10_default_palette_y_mode_prob[bsize - BLOCK_8X8]
+                                                       [palette_ctx], 0);
+
+  if (!xd->lossless[mbmi->segment_id]) {
+    // super_block_yrd above includes the cost of the tx_size in the
+    // tokenonly rate, but for intra blocks, tx_size is always coded
+    // (prediction granularity), so we account for it in the full rate,
+    // not the tokenonly rate.
+    rate_y -=
+        cpi->tx_size_cost[max_tx_size - TX_8X8][get_tx_size_context(xd)]
+                                                [mbmi->tx_size];
+  }
+
+  rate2 += vp10_cost_bit(cm->fc->ext_intra_probs[0],
+                         mbmi->ext_intra_mode_info.use_ext_intra_mode[0]);
+  rate2 += write_uniform_cost(FILTER_INTRA_MODES,
+                              mbmi->ext_intra_mode_info.ext_intra_mode[0]);
+  if (mbmi->uv_mode != DC_PRED && mbmi->uv_mode != TM_PRED) {
+    rate2 += write_uniform_cost(2 * MAX_ANGLE_DELTAS + 1,
+                                MAX_ANGLE_DELTAS +
+                                mbmi->angle_delta[1]);
+  }
+  if (ALLOW_FILTER_INTRA_MODES && mbmi->mode == DC_PRED) {
+    rate2 += vp10_cost_bit(cpi->common.fc->ext_intra_probs[1],
+                           mbmi->ext_intra_mode_info.use_ext_intra_mode[1]);
+    if (mbmi->ext_intra_mode_info.use_ext_intra_mode[1])
+      rate2 +=
+          write_uniform_cost(FILTER_INTRA_MODES,
+                             mbmi->ext_intra_mode_info.ext_intra_mode[1]);
+  }
+  distortion2 = distortion_y + distortion_uv;
+  vp10_encode_intra_block_plane(x, bsize, 0, 0);
+#if CONFIG_VP9_HIGHBITDEPTH
+  if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
+    x->recon_variance =
+        vp10_high_get_sby_perpixel_variance(cpi, &xd->plane[0].dst,
+                                            bsize, xd->bd);
+  } else {
+    x->recon_variance =
+        vp10_get_sby_perpixel_variance(cpi, &xd->plane[0].dst, bsize);
+  }
+#else
+  x->recon_variance =
+      vp10_get_sby_perpixel_variance(cpi, &xd->plane[0].dst, bsize);
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+
+  rate2 += ref_costs_single[INTRA_FRAME];
+
+  if (skippable) {
+    rate2 -= (rate_y + rate_uv);
+    rate_y = 0;
+    rate_uv = 0;
+    rate2 += vp10_cost_bit(vp10_get_skip_prob(cm, xd), 1);
+  } else {
+    rate2 += vp10_cost_bit(vp10_get_skip_prob(cm, xd), 0);
+  }
+  this_rd = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
+  rd_variance_adjustment(x, &this_rd, INTRA_FRAME,
+#if CONFIG_OBMC
+                         is_inter_block(mbmi),
+#endif  // CONFIG_OBMC
+                         x->source_variance);
+
+  if (this_rd < *best_intra_rd) {
+    *best_intra_rd = this_rd;
+    *best_intra_mode = mbmi->mode;
+  }
+  for (i = 0; i < REFERENCE_MODES; ++i)
+    best_pred_rd[i] = VPXMIN(best_pred_rd[i], this_rd);
+
+  if (this_rd < *best_rd) {
+    *best_mode_index = dc_mode_index;
+    mbmi->mv[0].as_int = 0;
+    rd_cost->rate = rate2;
+#if CONFIG_SUPERTX
+    if (x->skip)
+      *returnrate_nocoef = rate2;
+    else
+      *returnrate_nocoef = rate2 - rate_y - rate_uv;
+    *returnrate_nocoef -= vp10_cost_bit(vp10_get_skip_prob(cm, xd), skippable);
+    *returnrate_nocoef -= vp10_cost_bit(vp10_get_intra_inter_prob(cm, xd),
+                                        mbmi->ref_frame[0] != INTRA_FRAME);
+#endif  // CONFIG_SUPERTX
+    rd_cost->dist = distortion2;
+    rd_cost->rdcost = this_rd;
+    *best_rd = this_rd;
+    *best_mbmode = *mbmi;
+    *best_skip2 = 0;
+    *best_mode_skippable = skippable;
+    memcpy(ctx->zcoeff_blk, x->zcoeff_blk[mbmi->tx_size],
+           sizeof(ctx->zcoeff_blk[0]) * ctx->num_4x4_blk);
+  }
+}
+#endif  // CONFIG_EXT_INTRA
+
 void vp10_rd_pick_inter_mode_sb(VP10_COMP *cpi,
                                 TileDataEnc *tile_data,
                                 MACROBLOCK *x,
@@ -8374,7 +8557,7 @@
   PALETTE_MODE_INFO pmi_uv[TX_SIZES];
 #if CONFIG_EXT_INTRA
   EXT_INTRA_MODE_INFO ext_intra_mode_info_uv[TX_SIZES];
-  int8_t uv_angle_delta[TX_SIZES];
+  int8_t uv_angle_delta[TX_SIZES], dc_skipped = 1;
   int is_directional_mode, angle_stats_ready = 0;
   int rate_overhead, rate_dummy;
   uint8_t directional_mode_skip_mask[INTRA_MODES];
@@ -8937,28 +9120,6 @@
         mbmi->angle_delta[0] = 0;
         super_block_yrd(cpi, x, &rate_y, &distortion_y, &skippable,
                         NULL, bsize, best_rd);
-        if (rate_y == INT_MAX)
-          continue;
-      }
-
-      // TODO(huisu): ext-intra is turned off in lossless mode for now to
-      // avoid a unit test failure
-      if (mbmi->mode == DC_PRED && !xd->lossless[mbmi->segment_id] &&
-          ALLOW_FILTER_INTRA_MODES) {
-        MB_MODE_INFO mbmi_copy = *mbmi;
-
-        if (rate_y != INT_MAX) {
-          int this_rate = rate_y + intra_mode_cost[mbmi->mode] +
-              vp10_cost_bit(cm->fc->ext_intra_probs[0], 0);
-          this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, distortion_y);
-        } else {
-          this_rd = best_rd;
-        }
-
-        if (!rd_pick_ext_intra_sby(cpi, x, &rate_dummy, &rate_y, &distortion_y,
-                                   &skippable, bsize,
-                                   intra_mode_cost[mbmi->mode], &this_rd, 0))
-          *mbmi = mbmi_copy;
       }
 #else
       super_block_yrd(cpi, x, &rate_y, &distortion_y, &skippable,
@@ -8967,6 +9128,12 @@
 
       if (rate_y == INT_MAX)
         continue;
+
+#if CONFIG_EXT_INTRA
+      if (mbmi->mode == DC_PRED)
+        dc_skipped = 0;
+#endif  // CONFIG_EXT_INTRA
+
       uv_tx = get_uv_tx_size_impl(mbmi->tx_size, bsize, pd->subsampling_x,
                                   pd->subsampling_y);
       if (rate_uv_intra[uv_tx] == INT_MAX) {
@@ -9034,11 +9201,26 @@
         rate2 += vp10_cost_bit(cm->fc->ext_intra_probs[0],
                                mbmi->ext_intra_mode_info.use_ext_intra_mode[0]);
         if (mbmi->ext_intra_mode_info.use_ext_intra_mode[0]) {
-          EXT_INTRA_MODE ext_intra_mode =
-              mbmi->ext_intra_mode_info.ext_intra_mode[0];
-          rate2 += write_uniform_cost(FILTER_INTRA_MODES, ext_intra_mode);
+          rate2 +=
+              write_uniform_cost(FILTER_INTRA_MODES,
+                                 mbmi->ext_intra_mode_info.ext_intra_mode[0]);
         }
       }
+
+      if (mbmi->uv_mode != DC_PRED && mbmi->uv_mode != TM_PRED) {
+        rate2 += write_uniform_cost(2 * MAX_ANGLE_DELTAS + 1,
+                                    MAX_ANGLE_DELTAS +
+                                    mbmi->angle_delta[1]);
+      }
+
+      if (ALLOW_FILTER_INTRA_MODES && mbmi->mode == DC_PRED) {
+        rate2 += vp10_cost_bit(cpi->common.fc->ext_intra_probs[1],
+                               mbmi->ext_intra_mode_info.use_ext_intra_mode[1]);
+        if (mbmi->ext_intra_mode_info.use_ext_intra_mode[1])
+          rate2 +=
+              write_uniform_cost(FILTER_INTRA_MODES,
+                                 mbmi->ext_intra_mode_info.ext_intra_mode[1]);
+      }
 #endif  // CONFIG_EXT_INTRA
       if (this_mode != DC_PRED && this_mode != TM_PRED)
         rate2 += intra_cost_penalty;
@@ -9506,9 +9688,11 @@
       break;
   }
 
-  if (sf->tx_type_search.fast_inter_tx_type_search == 1 &&
-      xd->lossless[mbmi->segment_id] == 0 &&
-      best_mode_index >= 0) {
+  if (xd->lossless[mbmi->segment_id] == 0 && best_mode_index >= 0 &&
+      ((sf->tx_type_search.fast_inter_tx_type_search == 1 &&
+        is_inter_mode(best_mbmode.mode)) ||
+       (sf->tx_type_search.fast_intra_tx_type_search == 1 &&
+        !is_inter_mode(best_mbmode.mode)))) {
     int rate_y = 0, rate_uv = 0;
     int64_t dist_y = 0, dist_uv = 0;
     int skip_y = 0, skip_uv = 0, skip_blk = 0;
@@ -9707,6 +9891,26 @@
   }
   PALETTE_EXIT:
 
+#if CONFIG_EXT_INTRA
+  // TODO(huisu): ext-intra is turned off in lossless mode for now to
+  // avoid a unit test failure
+  if (!xd->lossless[mbmi->segment_id] &&
+      mbmi->palette_mode_info.palette_size[0] == 0 && !dc_skipped &&
+      best_mode_index >= 0 && (best_intra_rd >> 1)  < best_rd) {
+    pick_ext_intra_iframe(cpi, x, ctx, bsize, rate_uv_intra,
+                          rate_uv_tokenonly, dist_uv, skip_uv,
+                          mode_uv, ext_intra_mode_info_uv,
+                          pmi_uv, uv_angle_delta, palette_ctx, 0,
+                          ref_costs_single, &best_rd, &best_intra_rd,
+                          &best_intra_mode, &best_mode_index,
+                          &best_skip2, &best_mode_skippable,
+#if CONFIG_SUPERTX
+                          returnrate_nocoef,
+#endif  // CONFIG_SUPERTX
+                          best_pred_rd, &best_mbmode, rd_cost);
+  }
+#endif  // CONFIG_EXT_INTRA
+
   // The inter modes' rate costs are not calculated precisely in some cases.
   // Therefore, sometimes, NEWMV is chosen instead of NEARESTMV, NEARMV, and
   // ZEROMV. Here, checks are added for those cases, and the mode decisions
diff --git a/vpx_dsp/sum_squares.c b/vpx_dsp/sum_squares.c
index b827205..8a5a3d9 100644
--- a/vpx_dsp/sum_squares.c
+++ b/vpx_dsp/sum_squares.c
@@ -13,7 +13,7 @@
 #include "./vpx_dsp_rtcd.h"
 
 uint64_t vpx_sum_squares_2d_i16_c(const int16_t *src, int src_stride,
-                                  uint32_t size) {
+                                  int size) {
   int r, c;
   uint64_t ss = 0;
 
@@ -27,13 +27,3 @@
 
   return ss;
 }
-
-uint64_t vpx_sum_squares_i16_c(const int16_t *src, uint32_t n) {
-  uint64_t ss = 0;
-  do {
-    const int16_t v = *src++;
-    ss += v*v;
-  } while (--n);
-
-  return ss;
-}
diff --git a/vpx_dsp/vpx_dsp_rtcd_defs.pl b/vpx_dsp/vpx_dsp_rtcd_defs.pl
index 1253c7e..7bae037 100644
--- a/vpx_dsp/vpx_dsp_rtcd_defs.pl
+++ b/vpx_dsp/vpx_dsp_rtcd_defs.pl
@@ -970,11 +970,8 @@
   #
   # Sum of Squares
   #
-  add_proto qw/uint64_t vpx_sum_squares_2d_i16/, "const int16_t *src, int stride, uint32_t size";
+  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/;
-
-  add_proto qw/uint64_t vpx_sum_squares_i16/, "const int16_t *src, uint32_t N";
-  specialize qw/vpx_sum_squares_i16 sse2/;
 }
 
 if ((vpx_config("CONFIG_VP9_ENCODER") eq "yes") || (vpx_config("CONFIG_VP10_ENCODER") eq "yes")) {
diff --git a/vpx_dsp/x86/sum_squares_sse2.c b/vpx_dsp/x86/sum_squares_sse2.c
index 5947672..ed1dc0c 100644
--- a/vpx_dsp/x86/sum_squares_sse2.c
+++ b/vpx_dsp/x86/sum_squares_sse2.c
@@ -12,14 +12,8 @@
 #include <emmintrin.h>
 #include <stdio.h>
 
-#include "vpx_dsp/x86/synonyms.h"
-
 #include "./vpx_dsp_rtcd.h"
 
-//////////////////////////////////////////////////////////////////////////////
-// 2D version
-//////////////////////////////////////////////////////////////////////////////
-
 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));
@@ -50,7 +44,7 @@
 #endif
 static uint64_t vpx_sum_squares_2d_i16_nxn_sse2(const int16_t *src,
                                                 int stride,
-                                                uint32_t size) {
+                                                int size) {
   int r, c;
 
   const __m128i v_zext_mask_q = _mm_set_epi32(0, 0xffffffff, 0, 0xffffffff);
@@ -112,7 +106,7 @@
 }
 
 uint64_t vpx_sum_squares_2d_i16_sse2(const int16_t *src, int stride,
-                                     uint32_t size) {
+                                     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.
@@ -123,78 +117,3 @@
     return vpx_sum_squares_2d_i16_nxn_sse2(src, stride, size);
   }
 }
-
-//////////////////////////////////////////////////////////////////////////////
-// 1D version
-//////////////////////////////////////////////////////////////////////////////
-
-static uint64_t vpx_sum_squares_i16_64n_sse2(const int16_t *src, uint32_t n) {
-  const __m128i v_zext_mask_q = _mm_set_epi32(0, 0xffffffff, 0, 0xffffffff);
-  __m128i v_acc0_q = _mm_setzero_si128();
-  __m128i v_acc1_q = _mm_setzero_si128();
-
-  const int16_t *const end = src + n;
-
-  assert(n % 64 == 0);
-
-  while (src < end) {
-    const __m128i v_val_0_w = xx_load_128(src);
-    const __m128i v_val_1_w = xx_load_128(src + 8);
-    const __m128i v_val_2_w = xx_load_128(src + 16);
-    const __m128i v_val_3_w = xx_load_128(src + 24);
-    const __m128i v_val_4_w = xx_load_128(src + 32);
-    const __m128i v_val_5_w = xx_load_128(src + 40);
-    const __m128i v_val_6_w = xx_load_128(src + 48);
-    const __m128i v_val_7_w = xx_load_128(src + 56);
-
-    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);
-
-    const __m128i v_sum_d = _mm_add_epi32(v_sum_0123_d, v_sum_4567_d);
-
-    v_acc0_q = _mm_add_epi64(v_acc0_q, _mm_and_si128(v_sum_d, v_zext_mask_q));
-    v_acc1_q = _mm_add_epi64(v_acc1_q, _mm_srli_epi64(v_sum_d, 32));
-
-    src += 64;
-  }
-
-  v_acc0_q = _mm_add_epi64(v_acc0_q, v_acc1_q);
-  v_acc0_q = _mm_add_epi64(v_acc0_q, _mm_srli_si128(v_acc0_q, 8));
-
-#if ARCH_X86_64
-  return (uint64_t)_mm_cvtsi128_si64(v_acc0_q);
-#else
-  {
-    uint64_t tmp;
-    _mm_storel_epi64((__m128i*)&tmp, v_acc0_q);
-    return tmp;
-  }
-#endif
-}
-
-uint64_t vpx_sum_squares_i16_sse2(const int16_t *src, uint32_t n) {
-  if (n % 64 == 0) {
-    return vpx_sum_squares_i16_64n_sse2(src, n);
-  } else if (n > 64) {
-    int k = n & ~(64-1);
-    return vpx_sum_squares_i16_64n_sse2(src, k) +
-           vpx_sum_squares_i16_c(src + k, n - k);
-  } else {
-    return vpx_sum_squares_i16_c(src, n);
-  }
-}
-