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);
- }
-}
-