From 3e0138edb72b2ef1a77d4b636d7c60f74a7abab9 Mon Sep 17 00:00:00 2001 From: James Zern Date: Wed, 18 Nov 2015 23:17:27 -0800 Subject: [PATCH] vp9_satd: return an int the final sum may use up to 26 bits + add a unit test + disable the sse2 as the result will rollover; this will be fixed in a future commit Change-Id: I2a49811dfaa06abfd9fa1e1e65ed7cd68e4c97ce --- test/vp9_avg_test.cc | 80 +++++++++++++++++++++++++++ vp9/common/vp9_rtcd_defs.pl | 4 +- vp9/encoder/vp9_avg.c | 4 +- vp9/encoder/vp9_pickmode.c | 2 +- vp9/encoder/x86/vp9_avg_intrin_sse2.c | 5 +- 5 files changed, 89 insertions(+), 6 deletions(-) diff --git a/test/vp9_avg_test.cc b/test/vp9_avg_test.cc index d38313116..045f4781b 100644 --- a/test/vp9_avg_test.cc +++ b/test/vp9_avg_test.cc @@ -194,6 +194,48 @@ class IntProColTest int16_t sum_c_; }; +typedef int (*SatdFunc)(const int16_t *coeffs, int length); +typedef std::tr1::tuple SatdTestParam; + +class SatdTest + : public ::testing::Test, + public ::testing::WithParamInterface { + protected: + virtual void SetUp() { + satd_size_ = GET_PARAM(0); + satd_func_ = GET_PARAM(1); + rnd_.Reset(ACMRandom::DeterministicSeed()); + src_ = reinterpret_cast( + vpx_memalign(16, sizeof(*src_) * satd_size_)); + ASSERT_TRUE(src_ != NULL); + } + + virtual void TearDown() { + libvpx_test::ClearSystemState(); + vpx_free(src_); + } + + void FillConstant(const int16_t val) { + for (int i = 0; i < satd_size_; ++i) src_[i] = val; + } + + void FillRandom() { + for (int i = 0; i < satd_size_; ++i) src_[i] = rnd_.Rand16(); + } + + void Check(const int expected) { + int total; + ASM_REGISTER_STATE_CHECK(total = satd_func_(src_, satd_size_)); + EXPECT_EQ(expected, total); + } + + int satd_size_; + + private: + int16_t *src_; + SatdFunc satd_func_; + ACMRandom rnd_; +}; uint8_t* AverageTestBase::source_data_ = NULL; @@ -246,6 +288,36 @@ TEST_P(IntProColTest, Random) { RunComparison(); } + +TEST_P(SatdTest, MinValue) { + const int kMin = -32640; + const int expected = -kMin * satd_size_; + FillConstant(kMin); + Check(expected); +} + +TEST_P(SatdTest, MaxValue) { + const int kMax = 32640; + const int expected = kMax * satd_size_; + FillConstant(kMax); + Check(expected); +} + +TEST_P(SatdTest, Random) { + int expected; + switch (satd_size_) { + case 16: expected = 205298; break; + case 64: expected = 1113950; break; + case 256: expected = 4268415; break; + case 1024: expected = 16954082; break; + default: + FAIL() << "Invalid satd size (" << satd_size_ + << ") valid: 16/64/256/1024"; + } + FillRandom(); + Check(expected); +} + using std::tr1::make_tuple; INSTANTIATE_TEST_CASE_P( @@ -254,6 +326,14 @@ INSTANTIATE_TEST_CASE_P( make_tuple(16, 16, 1, 8, &vp9_avg_8x8_c), make_tuple(16, 16, 1, 4, &vp9_avg_4x4_c))); +INSTANTIATE_TEST_CASE_P( + C, SatdTest, + ::testing::Values( + make_tuple(16, &vp9_satd_c), + make_tuple(64, &vp9_satd_c), + make_tuple(256, &vp9_satd_c), + make_tuple(1024, &vp9_satd_c))); + #if HAVE_SSE2 INSTANTIATE_TEST_CASE_P( SSE2, AverageTest, diff --git a/vp9/common/vp9_rtcd_defs.pl b/vp9/common/vp9_rtcd_defs.pl index 890b63821..7439ff088 100644 --- a/vp9/common/vp9_rtcd_defs.pl +++ b/vp9/common/vp9_rtcd_defs.pl @@ -209,8 +209,8 @@ specialize qw/vp9_hadamard_8x8 sse2/, "$ssse3_x86_64_x86inc"; add_proto qw/void vp9_hadamard_16x16/, "int16_t const *src_diff, int src_stride, int16_t *coeff"; specialize qw/vp9_hadamard_16x16 sse2/; -add_proto qw/int16_t vp9_satd/, "const int16_t *coeff, int length"; -specialize qw/vp9_satd sse2/; +add_proto qw/int vp9_satd/, "const int16_t *coeff, int length"; +specialize qw/vp9_satd/; add_proto qw/void vp9_int_pro_row/, "int16_t *hbuf, uint8_t const *ref, const int ref_stride, const int height"; specialize qw/vp9_int_pro_row sse2 neon/; diff --git a/vp9/encoder/vp9_avg.c b/vp9/encoder/vp9_avg.c index a9a4c3050..7baa09ae5 100644 --- a/vp9/encoder/vp9_avg.c +++ b/vp9/encoder/vp9_avg.c @@ -117,14 +117,14 @@ void vp9_hadamard_16x16_c(int16_t const *src_diff, int src_stride, // coeff: 16 bits, dynamic range [-32640, 32640]. // length: value range {16, 64, 256, 1024}. -int16_t vp9_satd_c(const int16_t *coeff, int length) { +int vp9_satd_c(const int16_t *coeff, int length) { int i; int satd = 0; for (i = 0; i < length; ++i) satd += abs(coeff[i]); // satd: 26 bits, dynamic range [-32640 * 1024, 32640 * 1024] - return (int16_t)satd; + return satd; } // Integer projection onto row vectors. diff --git a/vp9/encoder/vp9_pickmode.c b/vp9/encoder/vp9_pickmode.c index 9db044f6b..266c15f4e 100644 --- a/vp9/encoder/vp9_pickmode.c +++ b/vp9/encoder/vp9_pickmode.c @@ -673,7 +673,7 @@ static void block_yrd(VP9_COMP *cpi, MACROBLOCK *x, int *rate, int64_t *dist, if (*eob == 1) *rate += (int)abs(qcoeff[0]); else if (*eob > 1) - *rate += (int)vp9_satd((const int16_t *)qcoeff, step << 4); + *rate += vp9_satd((const int16_t *)qcoeff, step << 4); *dist += vp9_block_error_fp(coeff, dqcoeff, step << 4) >> shift; } diff --git a/vp9/encoder/x86/vp9_avg_intrin_sse2.c b/vp9/encoder/x86/vp9_avg_intrin_sse2.c index 4531d794a..489bdfe55 100644 --- a/vp9/encoder/x86/vp9_avg_intrin_sse2.c +++ b/vp9/encoder/x86/vp9_avg_intrin_sse2.c @@ -283,7 +283,9 @@ void vp9_hadamard_16x16_sse2(int16_t const *src_diff, int src_stride, } } -int16_t vp9_satd_sse2(const int16_t *coeff, int length) { +// TODO(jingning): the sum needs to be accumulated in 32-bits to avoid rollover. +#if 0 +int vp9_satd_sse2(const int16_t *coeff, int length) { int i; __m128i sum = _mm_load_si128((const __m128i *)coeff); __m128i sign = _mm_srai_epi16(sum, 15); @@ -309,6 +311,7 @@ int16_t vp9_satd_sse2(const int16_t *coeff, int length) { return _mm_extract_epi16(sum, 0); } +#endif void vp9_int_pro_row_sse2(int16_t *hbuf, uint8_t const*ref, const int ref_stride, const int height) {