1/* 2 * Copyright (c) 2012 The WebM project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11#include <limits.h> 12#include <stdio.h> 13#include <string.h> 14 15#include "third_party/googletest/src/include/gtest/gtest.h" 16 17#include "./vpx_config.h" 18#if CONFIG_VP9_ENCODER 19#include "./vp9_rtcd.h" 20#endif 21 22#include "test/acm_random.h" 23#include "test/clear_system_state.h" 24#include "test/register_state_check.h" 25#include "test/util.h" 26#include "vpx_mem/vpx_mem.h" 27 28using libvpx_test::ACMRandom; 29 30namespace { 31class AverageTestBase : public ::testing::Test { 32 public: 33 AverageTestBase(int width, int height) : width_(width), height_(height) {} 34 35 static void SetUpTestCase() { 36 source_data_ = reinterpret_cast<uint8_t*>( 37 vpx_memalign(kDataAlignment, kDataBlockSize)); 38 } 39 40 static void TearDownTestCase() { 41 vpx_free(source_data_); 42 source_data_ = NULL; 43 } 44 45 virtual void TearDown() { 46 libvpx_test::ClearSystemState(); 47 } 48 49 protected: 50 // Handle blocks up to 4 blocks 64x64 with stride up to 128 51 static const int kDataAlignment = 16; 52 static const int kDataBlockSize = 64 * 128; 53 54 virtual void SetUp() { 55 source_stride_ = (width_ + 31) & ~31; 56 rnd_.Reset(ACMRandom::DeterministicSeed()); 57 } 58 59 // Sum Pixels 60 unsigned int ReferenceAverage8x8(const uint8_t* source, int pitch ) { 61 unsigned int average = 0; 62 for (int h = 0; h < 8; ++h) 63 for (int w = 0; w < 8; ++w) 64 average += source[h * source_stride_ + w]; 65 return ((average + 32) >> 6); 66 } 67 68 unsigned int ReferenceAverage4x4(const uint8_t* source, int pitch ) { 69 unsigned int average = 0; 70 for (int h = 0; h < 4; ++h) 71 for (int w = 0; w < 4; ++w) 72 average += source[h * source_stride_ + w]; 73 return ((average + 8) >> 4); 74 } 75 76 void FillConstant(uint8_t fill_constant) { 77 for (int i = 0; i < width_ * height_; ++i) { 78 source_data_[i] = fill_constant; 79 } 80 } 81 82 void FillRandom() { 83 for (int i = 0; i < width_ * height_; ++i) { 84 source_data_[i] = rnd_.Rand8(); 85 } 86 } 87 88 int width_, height_; 89 static uint8_t* source_data_; 90 int source_stride_; 91 92 ACMRandom rnd_; 93}; 94typedef unsigned int (*AverageFunction)(const uint8_t* s, int pitch); 95 96typedef std::tr1::tuple<int, int, int, int, AverageFunction> AvgFunc; 97 98class AverageTest 99 : public AverageTestBase, 100 public ::testing::WithParamInterface<AvgFunc>{ 101 public: 102 AverageTest() : AverageTestBase(GET_PARAM(0), GET_PARAM(1)) {} 103 104 protected: 105 void CheckAverages() { 106 unsigned int expected = 0; 107 if (GET_PARAM(3) == 8) { 108 expected = ReferenceAverage8x8(source_data_+ GET_PARAM(2), 109 source_stride_); 110 } else if (GET_PARAM(3) == 4) { 111 expected = ReferenceAverage4x4(source_data_+ GET_PARAM(2), 112 source_stride_); 113 } 114 115 ASM_REGISTER_STATE_CHECK(GET_PARAM(4)(source_data_+ GET_PARAM(2), 116 source_stride_)); 117 unsigned int actual = GET_PARAM(4)(source_data_+ GET_PARAM(2), 118 source_stride_); 119 120 EXPECT_EQ(expected, actual); 121 } 122}; 123 124typedef void (*IntProRowFunc)(int16_t hbuf[16], uint8_t const *ref, 125 const int ref_stride, const int height); 126 127typedef std::tr1::tuple<int, IntProRowFunc, IntProRowFunc> IntProRowParam; 128 129class IntProRowTest 130 : public AverageTestBase, 131 public ::testing::WithParamInterface<IntProRowParam> { 132 public: 133 IntProRowTest() 134 : AverageTestBase(16, GET_PARAM(0)), 135 hbuf_asm_(NULL), 136 hbuf_c_(NULL) { 137 asm_func_ = GET_PARAM(1); 138 c_func_ = GET_PARAM(2); 139 } 140 141 protected: 142 virtual void SetUp() { 143 hbuf_asm_ = reinterpret_cast<int16_t*>( 144 vpx_memalign(kDataAlignment, sizeof(*hbuf_asm_) * 16)); 145 hbuf_c_ = reinterpret_cast<int16_t*>( 146 vpx_memalign(kDataAlignment, sizeof(*hbuf_c_) * 16)); 147 } 148 149 virtual void TearDown() { 150 vpx_free(hbuf_c_); 151 hbuf_c_ = NULL; 152 vpx_free(hbuf_asm_); 153 hbuf_asm_ = NULL; 154 } 155 156 void RunComparison() { 157 ASM_REGISTER_STATE_CHECK(c_func_(hbuf_c_, source_data_, 0, height_)); 158 ASM_REGISTER_STATE_CHECK(asm_func_(hbuf_asm_, source_data_, 0, height_)); 159 EXPECT_EQ(0, memcmp(hbuf_c_, hbuf_asm_, sizeof(*hbuf_c_) * 16)) 160 << "Output mismatch"; 161 } 162 163 private: 164 IntProRowFunc asm_func_; 165 IntProRowFunc c_func_; 166 int16_t *hbuf_asm_; 167 int16_t *hbuf_c_; 168}; 169 170typedef int16_t (*IntProColFunc)(uint8_t const *ref, const int width); 171 172typedef std::tr1::tuple<int, IntProColFunc, IntProColFunc> IntProColParam; 173 174class IntProColTest 175 : public AverageTestBase, 176 public ::testing::WithParamInterface<IntProColParam> { 177 public: 178 IntProColTest() : AverageTestBase(GET_PARAM(0), 1), sum_asm_(0), sum_c_(0) { 179 asm_func_ = GET_PARAM(1); 180 c_func_ = GET_PARAM(2); 181 } 182 183 protected: 184 void RunComparison() { 185 ASM_REGISTER_STATE_CHECK(sum_c_ = c_func_(source_data_, width_)); 186 ASM_REGISTER_STATE_CHECK(sum_asm_ = asm_func_(source_data_, width_)); 187 EXPECT_EQ(sum_c_, sum_asm_) << "Output mismatch"; 188 } 189 190 private: 191 IntProColFunc asm_func_; 192 IntProColFunc c_func_; 193 int16_t sum_asm_; 194 int16_t sum_c_; 195}; 196 197 198uint8_t* AverageTestBase::source_data_ = NULL; 199 200TEST_P(AverageTest, MinValue) { 201 FillConstant(0); 202 CheckAverages(); 203} 204 205TEST_P(AverageTest, MaxValue) { 206 FillConstant(255); 207 CheckAverages(); 208} 209 210TEST_P(AverageTest, Random) { 211 // The reference frame, but not the source frame, may be unaligned for 212 // certain types of searches. 213 for (int i = 0; i < 1000; i++) { 214 FillRandom(); 215 CheckAverages(); 216 } 217} 218 219TEST_P(IntProRowTest, MinValue) { 220 FillConstant(0); 221 RunComparison(); 222} 223 224TEST_P(IntProRowTest, MaxValue) { 225 FillConstant(255); 226 RunComparison(); 227} 228 229TEST_P(IntProRowTest, Random) { 230 FillRandom(); 231 RunComparison(); 232} 233 234TEST_P(IntProColTest, MinValue) { 235 FillConstant(0); 236 RunComparison(); 237} 238 239TEST_P(IntProColTest, MaxValue) { 240 FillConstant(255); 241 RunComparison(); 242} 243 244TEST_P(IntProColTest, Random) { 245 FillRandom(); 246 RunComparison(); 247} 248 249using std::tr1::make_tuple; 250 251INSTANTIATE_TEST_CASE_P( 252 C, AverageTest, 253 ::testing::Values( 254 make_tuple(16, 16, 1, 8, &vp9_avg_8x8_c), 255 make_tuple(16, 16, 1, 4, &vp9_avg_4x4_c))); 256 257#if HAVE_SSE2 258INSTANTIATE_TEST_CASE_P( 259 SSE2, AverageTest, 260 ::testing::Values( 261 make_tuple(16, 16, 0, 8, &vp9_avg_8x8_sse2), 262 make_tuple(16, 16, 5, 8, &vp9_avg_8x8_sse2), 263 make_tuple(32, 32, 15, 8, &vp9_avg_8x8_sse2), 264 make_tuple(16, 16, 0, 4, &vp9_avg_4x4_sse2), 265 make_tuple(16, 16, 5, 4, &vp9_avg_4x4_sse2), 266 make_tuple(32, 32, 15, 4, &vp9_avg_4x4_sse2))); 267 268INSTANTIATE_TEST_CASE_P( 269 SSE2, IntProRowTest, ::testing::Values( 270 make_tuple(16, &vp9_int_pro_row_sse2, &vp9_int_pro_row_c), 271 make_tuple(32, &vp9_int_pro_row_sse2, &vp9_int_pro_row_c), 272 make_tuple(64, &vp9_int_pro_row_sse2, &vp9_int_pro_row_c))); 273 274INSTANTIATE_TEST_CASE_P( 275 SSE2, IntProColTest, ::testing::Values( 276 make_tuple(16, &vp9_int_pro_col_sse2, &vp9_int_pro_col_c), 277 make_tuple(32, &vp9_int_pro_col_sse2, &vp9_int_pro_col_c), 278 make_tuple(64, &vp9_int_pro_col_sse2, &vp9_int_pro_col_c))); 279#endif 280 281#if HAVE_NEON 282INSTANTIATE_TEST_CASE_P( 283 NEON, AverageTest, 284 ::testing::Values( 285 make_tuple(16, 16, 0, 8, &vp9_avg_8x8_neon), 286 make_tuple(16, 16, 5, 8, &vp9_avg_8x8_neon), 287 make_tuple(32, 32, 15, 8, &vp9_avg_8x8_neon))); 288 289INSTANTIATE_TEST_CASE_P( 290 NEON, IntProRowTest, ::testing::Values( 291 make_tuple(16, &vp9_int_pro_row_neon, &vp9_int_pro_row_c), 292 make_tuple(32, &vp9_int_pro_row_neon, &vp9_int_pro_row_c), 293 make_tuple(64, &vp9_int_pro_row_neon, &vp9_int_pro_row_c))); 294 295INSTANTIATE_TEST_CASE_P( 296 NEON, IntProColTest, ::testing::Values( 297 make_tuple(16, &vp9_int_pro_col_neon, &vp9_int_pro_col_c), 298 make_tuple(32, &vp9_int_pro_col_neon, &vp9_int_pro_col_c), 299 make_tuple(64, &vp9_int_pro_col_neon, &vp9_int_pro_col_c))); 300#endif 301 302#if HAVE_MSA 303INSTANTIATE_TEST_CASE_P( 304 MSA, AverageTest, 305 ::testing::Values( 306 make_tuple(16, 16, 0, 8, &vp9_avg_8x8_msa), 307 make_tuple(16, 16, 5, 8, &vp9_avg_8x8_msa), 308 make_tuple(32, 32, 15, 8, &vp9_avg_8x8_msa), 309 make_tuple(16, 16, 0, 4, &vp9_avg_4x4_msa), 310 make_tuple(16, 16, 5, 4, &vp9_avg_4x4_msa), 311 make_tuple(32, 32, 15, 4, &vp9_avg_4x4_msa))); 312#endif 313 314} // namespace 315