1/* 2 * Copyright (c) 2014 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 <math.h> 12#include <stdlib.h> 13#include <string.h> 14 15#include "third_party/googletest/src/include/gtest/gtest.h" 16 17#include "./vpx_config.h" 18#include "./vpx_dsp_rtcd.h" 19#include "test/acm_random.h" 20#include "test/clear_system_state.h" 21#include "test/register_state_check.h" 22#include "test/util.h" 23#include "vp9/common/vp9_entropy.h" 24#include "vp9/common/vp9_scan.h" 25#include "vpx/vpx_codec.h" 26#include "vpx/vpx_integer.h" 27 28using libvpx_test::ACMRandom; 29 30namespace { 31#if CONFIG_VP9_HIGHBITDEPTH 32const int number_of_iterations = 100; 33 34typedef void (*QuantizeFunc)(const tran_low_t *coeff, intptr_t count, 35 int skip_block, const int16_t *zbin, 36 const int16_t *round, const int16_t *quant, 37 const int16_t *quant_shift, tran_low_t *qcoeff, 38 tran_low_t *dqcoeff, const int16_t *dequant, 39 uint16_t *eob, const int16_t *scan, 40 const int16_t *iscan); 41typedef std::tr1::tuple<QuantizeFunc, QuantizeFunc, vpx_bit_depth_t> 42 QuantizeParam; 43 44class VP9QuantizeTest : public ::testing::TestWithParam<QuantizeParam> { 45 public: 46 virtual ~VP9QuantizeTest() {} 47 virtual void SetUp() { 48 quantize_op_ = GET_PARAM(0); 49 ref_quantize_op_ = GET_PARAM(1); 50 bit_depth_ = GET_PARAM(2); 51 mask_ = (1 << bit_depth_) - 1; 52 } 53 54 virtual void TearDown() { libvpx_test::ClearSystemState(); } 55 56 protected: 57 vpx_bit_depth_t bit_depth_; 58 int mask_; 59 QuantizeFunc quantize_op_; 60 QuantizeFunc ref_quantize_op_; 61}; 62 63class VP9Quantize32Test : public ::testing::TestWithParam<QuantizeParam> { 64 public: 65 virtual ~VP9Quantize32Test() {} 66 virtual void SetUp() { 67 quantize_op_ = GET_PARAM(0); 68 ref_quantize_op_ = GET_PARAM(1); 69 bit_depth_ = GET_PARAM(2); 70 mask_ = (1 << bit_depth_) - 1; 71 } 72 73 virtual void TearDown() { libvpx_test::ClearSystemState(); } 74 75 protected: 76 vpx_bit_depth_t bit_depth_; 77 int mask_; 78 QuantizeFunc quantize_op_; 79 QuantizeFunc ref_quantize_op_; 80}; 81 82TEST_P(VP9QuantizeTest, OperationCheck) { 83 ACMRandom rnd(ACMRandom::DeterministicSeed()); 84 DECLARE_ALIGNED(16, tran_low_t, coeff_ptr[256]); 85 DECLARE_ALIGNED(16, int16_t, zbin_ptr[2]); 86 DECLARE_ALIGNED(16, int16_t, round_ptr[2]); 87 DECLARE_ALIGNED(16, int16_t, quant_ptr[2]); 88 DECLARE_ALIGNED(16, int16_t, quant_shift_ptr[2]); 89 DECLARE_ALIGNED(16, tran_low_t, qcoeff_ptr[256]); 90 DECLARE_ALIGNED(16, tran_low_t, dqcoeff_ptr[256]); 91 DECLARE_ALIGNED(16, tran_low_t, ref_qcoeff_ptr[256]); 92 DECLARE_ALIGNED(16, tran_low_t, ref_dqcoeff_ptr[256]); 93 DECLARE_ALIGNED(16, int16_t, dequant_ptr[2]); 94 DECLARE_ALIGNED(16, uint16_t, eob_ptr[1]); 95 DECLARE_ALIGNED(16, uint16_t, ref_eob_ptr[1]); 96 int err_count_total = 0; 97 int first_failure = -1; 98 for (int i = 0; i < number_of_iterations; ++i) { 99 const int skip_block = i == 0; 100 const TX_SIZE sz = (TX_SIZE)(i % 3); // TX_4X4, TX_8X8 TX_16X16 101 const TX_TYPE tx_type = (TX_TYPE)((i >> 2) % 3); 102 const scan_order *scan_order = &vp9_scan_orders[sz][tx_type]; 103 const int count = (4 << sz) * (4 << sz); // 16, 64, 256 104 int err_count = 0; 105 *eob_ptr = rnd.Rand16(); 106 *ref_eob_ptr = *eob_ptr; 107 for (int j = 0; j < count; j++) { 108 coeff_ptr[j] = rnd.Rand16() & mask_; 109 } 110 for (int j = 0; j < 2; j++) { 111 zbin_ptr[j] = rnd.Rand16() & mask_; 112 round_ptr[j] = rnd.Rand16(); 113 quant_ptr[j] = rnd.Rand16(); 114 quant_shift_ptr[j] = rnd.Rand16(); 115 dequant_ptr[j] = rnd.Rand16(); 116 } 117 ref_quantize_op_(coeff_ptr, count, skip_block, zbin_ptr, round_ptr, 118 quant_ptr, quant_shift_ptr, ref_qcoeff_ptr, 119 ref_dqcoeff_ptr, dequant_ptr, ref_eob_ptr, 120 scan_order->scan, scan_order->iscan); 121 ASM_REGISTER_STATE_CHECK(quantize_op_( 122 coeff_ptr, count, skip_block, zbin_ptr, round_ptr, quant_ptr, 123 quant_shift_ptr, qcoeff_ptr, dqcoeff_ptr, dequant_ptr, eob_ptr, 124 scan_order->scan, scan_order->iscan)); 125 for (int j = 0; j < sz; ++j) { 126 err_count += (ref_qcoeff_ptr[j] != qcoeff_ptr[j]) | 127 (ref_dqcoeff_ptr[j] != dqcoeff_ptr[j]); 128 } 129 err_count += (*ref_eob_ptr != *eob_ptr); 130 if (err_count && !err_count_total) { 131 first_failure = i; 132 } 133 err_count_total += err_count; 134 } 135 EXPECT_EQ(0, err_count_total) 136 << "Error: Quantization Test, C output doesn't match SSE2 output. " 137 << "First failed at test case " << first_failure; 138} 139 140TEST_P(VP9Quantize32Test, OperationCheck) { 141 ACMRandom rnd(ACMRandom::DeterministicSeed()); 142 DECLARE_ALIGNED(16, tran_low_t, coeff_ptr[1024]); 143 DECLARE_ALIGNED(16, int16_t, zbin_ptr[2]); 144 DECLARE_ALIGNED(16, int16_t, round_ptr[2]); 145 DECLARE_ALIGNED(16, int16_t, quant_ptr[2]); 146 DECLARE_ALIGNED(16, int16_t, quant_shift_ptr[2]); 147 DECLARE_ALIGNED(16, tran_low_t, qcoeff_ptr[1024]); 148 DECLARE_ALIGNED(16, tran_low_t, dqcoeff_ptr[1024]); 149 DECLARE_ALIGNED(16, tran_low_t, ref_qcoeff_ptr[1024]); 150 DECLARE_ALIGNED(16, tran_low_t, ref_dqcoeff_ptr[1024]); 151 DECLARE_ALIGNED(16, int16_t, dequant_ptr[2]); 152 DECLARE_ALIGNED(16, uint16_t, eob_ptr[1]); 153 DECLARE_ALIGNED(16, uint16_t, ref_eob_ptr[1]); 154 int err_count_total = 0; 155 int first_failure = -1; 156 for (int i = 0; i < number_of_iterations; ++i) { 157 const int skip_block = i == 0; 158 const TX_SIZE sz = TX_32X32; 159 const TX_TYPE tx_type = (TX_TYPE)(i % 4); 160 const scan_order *scan_order = &vp9_scan_orders[sz][tx_type]; 161 const int count = (4 << sz) * (4 << sz); // 1024 162 int err_count = 0; 163 *eob_ptr = rnd.Rand16(); 164 *ref_eob_ptr = *eob_ptr; 165 for (int j = 0; j < count; j++) { 166 coeff_ptr[j] = rnd.Rand16() & mask_; 167 } 168 for (int j = 0; j < 2; j++) { 169 zbin_ptr[j] = rnd.Rand16() & mask_; 170 round_ptr[j] = rnd.Rand16(); 171 quant_ptr[j] = rnd.Rand16(); 172 quant_shift_ptr[j] = rnd.Rand16(); 173 dequant_ptr[j] = rnd.Rand16(); 174 } 175 ref_quantize_op_(coeff_ptr, count, skip_block, zbin_ptr, round_ptr, 176 quant_ptr, quant_shift_ptr, ref_qcoeff_ptr, 177 ref_dqcoeff_ptr, dequant_ptr, ref_eob_ptr, 178 scan_order->scan, scan_order->iscan); 179 ASM_REGISTER_STATE_CHECK(quantize_op_( 180 coeff_ptr, count, skip_block, zbin_ptr, round_ptr, quant_ptr, 181 quant_shift_ptr, qcoeff_ptr, dqcoeff_ptr, dequant_ptr, eob_ptr, 182 scan_order->scan, scan_order->iscan)); 183 for (int j = 0; j < sz; ++j) { 184 err_count += (ref_qcoeff_ptr[j] != qcoeff_ptr[j]) | 185 (ref_dqcoeff_ptr[j] != dqcoeff_ptr[j]); 186 } 187 err_count += (*ref_eob_ptr != *eob_ptr); 188 if (err_count && !err_count_total) { 189 first_failure = i; 190 } 191 err_count_total += err_count; 192 } 193 EXPECT_EQ(0, err_count_total) 194 << "Error: Quantization Test, C output doesn't match SSE2 output. " 195 << "First failed at test case " << first_failure; 196} 197 198TEST_P(VP9QuantizeTest, EOBCheck) { 199 ACMRandom rnd(ACMRandom::DeterministicSeed()); 200 DECLARE_ALIGNED(16, tran_low_t, coeff_ptr[256]); 201 DECLARE_ALIGNED(16, int16_t, zbin_ptr[2]); 202 DECLARE_ALIGNED(16, int16_t, round_ptr[2]); 203 DECLARE_ALIGNED(16, int16_t, quant_ptr[2]); 204 DECLARE_ALIGNED(16, int16_t, quant_shift_ptr[2]); 205 DECLARE_ALIGNED(16, tran_low_t, qcoeff_ptr[256]); 206 DECLARE_ALIGNED(16, tran_low_t, dqcoeff_ptr[256]); 207 DECLARE_ALIGNED(16, tran_low_t, ref_qcoeff_ptr[256]); 208 DECLARE_ALIGNED(16, tran_low_t, ref_dqcoeff_ptr[256]); 209 DECLARE_ALIGNED(16, int16_t, dequant_ptr[2]); 210 DECLARE_ALIGNED(16, uint16_t, eob_ptr[1]); 211 DECLARE_ALIGNED(16, uint16_t, ref_eob_ptr[1]); 212 int err_count_total = 0; 213 int first_failure = -1; 214 for (int i = 0; i < number_of_iterations; ++i) { 215 int skip_block = i == 0; 216 TX_SIZE sz = (TX_SIZE)(i % 3); // TX_4X4, TX_8X8 TX_16X16 217 TX_TYPE tx_type = (TX_TYPE)((i >> 2) % 3); 218 const scan_order *scan_order = &vp9_scan_orders[sz][tx_type]; 219 int count = (4 << sz) * (4 << sz); // 16, 64, 256 220 int err_count = 0; 221 *eob_ptr = rnd.Rand16(); 222 *ref_eob_ptr = *eob_ptr; 223 // Two random entries 224 for (int j = 0; j < count; j++) { 225 coeff_ptr[j] = 0; 226 } 227 coeff_ptr[rnd(count)] = rnd.Rand16() & mask_; 228 coeff_ptr[rnd(count)] = rnd.Rand16() & mask_; 229 for (int j = 0; j < 2; j++) { 230 zbin_ptr[j] = rnd.Rand16() & mask_; 231 round_ptr[j] = rnd.Rand16(); 232 quant_ptr[j] = rnd.Rand16(); 233 quant_shift_ptr[j] = rnd.Rand16(); 234 dequant_ptr[j] = rnd.Rand16(); 235 } 236 237 ref_quantize_op_(coeff_ptr, count, skip_block, zbin_ptr, round_ptr, 238 quant_ptr, quant_shift_ptr, ref_qcoeff_ptr, 239 ref_dqcoeff_ptr, dequant_ptr, ref_eob_ptr, 240 scan_order->scan, scan_order->iscan); 241 ASM_REGISTER_STATE_CHECK(quantize_op_( 242 coeff_ptr, count, skip_block, zbin_ptr, round_ptr, quant_ptr, 243 quant_shift_ptr, qcoeff_ptr, dqcoeff_ptr, dequant_ptr, eob_ptr, 244 scan_order->scan, scan_order->iscan)); 245 246 for (int j = 0; j < sz; ++j) { 247 err_count += (ref_qcoeff_ptr[j] != qcoeff_ptr[j]) | 248 (ref_dqcoeff_ptr[j] != dqcoeff_ptr[j]); 249 } 250 err_count += (*ref_eob_ptr != *eob_ptr); 251 if (err_count && !err_count_total) { 252 first_failure = i; 253 } 254 err_count_total += err_count; 255 } 256 EXPECT_EQ(0, err_count_total) 257 << "Error: Quantization Test, C output doesn't match SSE2 output. " 258 << "First failed at test case " << first_failure; 259} 260 261TEST_P(VP9Quantize32Test, EOBCheck) { 262 ACMRandom rnd(ACMRandom::DeterministicSeed()); 263 DECLARE_ALIGNED(16, tran_low_t, coeff_ptr[1024]); 264 DECLARE_ALIGNED(16, int16_t, zbin_ptr[2]); 265 DECLARE_ALIGNED(16, int16_t, round_ptr[2]); 266 DECLARE_ALIGNED(16, int16_t, quant_ptr[2]); 267 DECLARE_ALIGNED(16, int16_t, quant_shift_ptr[2]); 268 DECLARE_ALIGNED(16, tran_low_t, qcoeff_ptr[1024]); 269 DECLARE_ALIGNED(16, tran_low_t, dqcoeff_ptr[1024]); 270 DECLARE_ALIGNED(16, tran_low_t, ref_qcoeff_ptr[1024]); 271 DECLARE_ALIGNED(16, tran_low_t, ref_dqcoeff_ptr[1024]); 272 DECLARE_ALIGNED(16, int16_t, dequant_ptr[2]); 273 DECLARE_ALIGNED(16, uint16_t, eob_ptr[1]); 274 DECLARE_ALIGNED(16, uint16_t, ref_eob_ptr[1]); 275 int err_count_total = 0; 276 int first_failure = -1; 277 for (int i = 0; i < number_of_iterations; ++i) { 278 int skip_block = i == 0; 279 TX_SIZE sz = TX_32X32; 280 TX_TYPE tx_type = (TX_TYPE)(i % 4); 281 const scan_order *scan_order = &vp9_scan_orders[sz][tx_type]; 282 int count = (4 << sz) * (4 << sz); // 1024 283 int err_count = 0; 284 *eob_ptr = rnd.Rand16(); 285 *ref_eob_ptr = *eob_ptr; 286 for (int j = 0; j < count; j++) { 287 coeff_ptr[j] = 0; 288 } 289 // Two random entries 290 coeff_ptr[rnd(count)] = rnd.Rand16() & mask_; 291 coeff_ptr[rnd(count)] = rnd.Rand16() & mask_; 292 for (int j = 0; j < 2; j++) { 293 zbin_ptr[j] = rnd.Rand16() & mask_; 294 round_ptr[j] = rnd.Rand16(); 295 quant_ptr[j] = rnd.Rand16(); 296 quant_shift_ptr[j] = rnd.Rand16(); 297 dequant_ptr[j] = rnd.Rand16(); 298 } 299 300 ref_quantize_op_(coeff_ptr, count, skip_block, zbin_ptr, round_ptr, 301 quant_ptr, quant_shift_ptr, ref_qcoeff_ptr, 302 ref_dqcoeff_ptr, dequant_ptr, ref_eob_ptr, 303 scan_order->scan, scan_order->iscan); 304 ASM_REGISTER_STATE_CHECK(quantize_op_( 305 coeff_ptr, count, skip_block, zbin_ptr, round_ptr, quant_ptr, 306 quant_shift_ptr, qcoeff_ptr, dqcoeff_ptr, dequant_ptr, eob_ptr, 307 scan_order->scan, scan_order->iscan)); 308 309 for (int j = 0; j < sz; ++j) { 310 err_count += (ref_qcoeff_ptr[j] != qcoeff_ptr[j]) | 311 (ref_dqcoeff_ptr[j] != dqcoeff_ptr[j]); 312 } 313 err_count += (*ref_eob_ptr != *eob_ptr); 314 if (err_count && !err_count_total) { 315 first_failure = i; 316 } 317 err_count_total += err_count; 318 } 319 EXPECT_EQ(0, err_count_total) 320 << "Error: Quantization Test, C output doesn't match SSE2 output. " 321 << "First failed at test case " << first_failure; 322} 323using std::tr1::make_tuple; 324 325#if HAVE_SSE2 326INSTANTIATE_TEST_CASE_P( 327 SSE2, VP9QuantizeTest, 328 ::testing::Values(make_tuple(&vpx_highbd_quantize_b_sse2, 329 &vpx_highbd_quantize_b_c, VPX_BITS_8), 330 make_tuple(&vpx_highbd_quantize_b_sse2, 331 &vpx_highbd_quantize_b_c, VPX_BITS_10), 332 make_tuple(&vpx_highbd_quantize_b_sse2, 333 &vpx_highbd_quantize_b_c, VPX_BITS_12))); 334INSTANTIATE_TEST_CASE_P( 335 SSE2, VP9Quantize32Test, 336 ::testing::Values(make_tuple(&vpx_highbd_quantize_b_32x32_sse2, 337 &vpx_highbd_quantize_b_32x32_c, VPX_BITS_8), 338 make_tuple(&vpx_highbd_quantize_b_32x32_sse2, 339 &vpx_highbd_quantize_b_32x32_c, VPX_BITS_10), 340 make_tuple(&vpx_highbd_quantize_b_32x32_sse2, 341 &vpx_highbd_quantize_b_32x32_c, VPX_BITS_12))); 342#endif // HAVE_SSE2 343#endif // CONFIG_VP9_HIGHBITDEPTH 344} // namespace 345