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 <math.h> 12#include <stdlib.h> 13#include <string.h> 14 15#include "third_party/googletest/src/include/gtest/gtest.h" 16#include "test/acm_random.h" 17#include "test/clear_system_state.h" 18#include "test/register_state_check.h" 19#include "test/util.h" 20 21#include "./vp9_rtcd.h" 22#include "vp9/common/vp9_entropy.h" 23#include "vpx/vpx_codec.h" 24#include "vpx/vpx_integer.h" 25 26using libvpx_test::ACMRandom; 27 28namespace { 29 30#ifdef _MSC_VER 31static int round(double x) { 32 if (x < 0) 33 return static_cast<int>(ceil(x - 0.5)); 34 else 35 return static_cast<int>(floor(x + 0.5)); 36} 37#endif 38 39const int kNumCoeffs = 256; 40const double PI = 3.1415926535898; 41void reference2_16x16_idct_2d(double *input, double *output) { 42 double x; 43 for (int l = 0; l < 16; ++l) { 44 for (int k = 0; k < 16; ++k) { 45 double s = 0; 46 for (int i = 0; i < 16; ++i) { 47 for (int j = 0; j < 16; ++j) { 48 x = cos(PI * j * (l + 0.5) / 16.0) * 49 cos(PI * i * (k + 0.5) / 16.0) * 50 input[i * 16 + j] / 256; 51 if (i != 0) 52 x *= sqrt(2.0); 53 if (j != 0) 54 x *= sqrt(2.0); 55 s += x; 56 } 57 } 58 output[k*16+l] = s; 59 } 60 } 61} 62 63 64const double C1 = 0.995184726672197; 65const double C2 = 0.98078528040323; 66const double C3 = 0.956940335732209; 67const double C4 = 0.923879532511287; 68const double C5 = 0.881921264348355; 69const double C6 = 0.831469612302545; 70const double C7 = 0.773010453362737; 71const double C8 = 0.707106781186548; 72const double C9 = 0.634393284163646; 73const double C10 = 0.555570233019602; 74const double C11 = 0.471396736825998; 75const double C12 = 0.38268343236509; 76const double C13 = 0.290284677254462; 77const double C14 = 0.195090322016128; 78const double C15 = 0.098017140329561; 79 80void butterfly_16x16_dct_1d(double input[16], double output[16]) { 81 double step[16]; 82 double intermediate[16]; 83 double temp1, temp2; 84 85 // step 1 86 step[ 0] = input[0] + input[15]; 87 step[ 1] = input[1] + input[14]; 88 step[ 2] = input[2] + input[13]; 89 step[ 3] = input[3] + input[12]; 90 step[ 4] = input[4] + input[11]; 91 step[ 5] = input[5] + input[10]; 92 step[ 6] = input[6] + input[ 9]; 93 step[ 7] = input[7] + input[ 8]; 94 step[ 8] = input[7] - input[ 8]; 95 step[ 9] = input[6] - input[ 9]; 96 step[10] = input[5] - input[10]; 97 step[11] = input[4] - input[11]; 98 step[12] = input[3] - input[12]; 99 step[13] = input[2] - input[13]; 100 step[14] = input[1] - input[14]; 101 step[15] = input[0] - input[15]; 102 103 // step 2 104 output[0] = step[0] + step[7]; 105 output[1] = step[1] + step[6]; 106 output[2] = step[2] + step[5]; 107 output[3] = step[3] + step[4]; 108 output[4] = step[3] - step[4]; 109 output[5] = step[2] - step[5]; 110 output[6] = step[1] - step[6]; 111 output[7] = step[0] - step[7]; 112 113 temp1 = step[ 8] * C7; 114 temp2 = step[15] * C9; 115 output[ 8] = temp1 + temp2; 116 117 temp1 = step[ 9] * C11; 118 temp2 = step[14] * C5; 119 output[ 9] = temp1 - temp2; 120 121 temp1 = step[10] * C3; 122 temp2 = step[13] * C13; 123 output[10] = temp1 + temp2; 124 125 temp1 = step[11] * C15; 126 temp2 = step[12] * C1; 127 output[11] = temp1 - temp2; 128 129 temp1 = step[11] * C1; 130 temp2 = step[12] * C15; 131 output[12] = temp2 + temp1; 132 133 temp1 = step[10] * C13; 134 temp2 = step[13] * C3; 135 output[13] = temp2 - temp1; 136 137 temp1 = step[ 9] * C5; 138 temp2 = step[14] * C11; 139 output[14] = temp2 + temp1; 140 141 temp1 = step[ 8] * C9; 142 temp2 = step[15] * C7; 143 output[15] = temp2 - temp1; 144 145 // step 3 146 step[ 0] = output[0] + output[3]; 147 step[ 1] = output[1] + output[2]; 148 step[ 2] = output[1] - output[2]; 149 step[ 3] = output[0] - output[3]; 150 151 temp1 = output[4] * C14; 152 temp2 = output[7] * C2; 153 step[ 4] = temp1 + temp2; 154 155 temp1 = output[5] * C10; 156 temp2 = output[6] * C6; 157 step[ 5] = temp1 + temp2; 158 159 temp1 = output[5] * C6; 160 temp2 = output[6] * C10; 161 step[ 6] = temp2 - temp1; 162 163 temp1 = output[4] * C2; 164 temp2 = output[7] * C14; 165 step[ 7] = temp2 - temp1; 166 167 step[ 8] = output[ 8] + output[11]; 168 step[ 9] = output[ 9] + output[10]; 169 step[10] = output[ 9] - output[10]; 170 step[11] = output[ 8] - output[11]; 171 172 step[12] = output[12] + output[15]; 173 step[13] = output[13] + output[14]; 174 step[14] = output[13] - output[14]; 175 step[15] = output[12] - output[15]; 176 177 // step 4 178 output[ 0] = (step[ 0] + step[ 1]); 179 output[ 8] = (step[ 0] - step[ 1]); 180 181 temp1 = step[2] * C12; 182 temp2 = step[3] * C4; 183 temp1 = temp1 + temp2; 184 output[ 4] = 2*(temp1 * C8); 185 186 temp1 = step[2] * C4; 187 temp2 = step[3] * C12; 188 temp1 = temp2 - temp1; 189 output[12] = 2 * (temp1 * C8); 190 191 output[ 2] = 2 * ((step[4] + step[ 5]) * C8); 192 output[14] = 2 * ((step[7] - step[ 6]) * C8); 193 194 temp1 = step[4] - step[5]; 195 temp2 = step[6] + step[7]; 196 output[ 6] = (temp1 + temp2); 197 output[10] = (temp1 - temp2); 198 199 intermediate[8] = step[8] + step[14]; 200 intermediate[9] = step[9] + step[15]; 201 202 temp1 = intermediate[8] * C12; 203 temp2 = intermediate[9] * C4; 204 temp1 = temp1 - temp2; 205 output[3] = 2 * (temp1 * C8); 206 207 temp1 = intermediate[8] * C4; 208 temp2 = intermediate[9] * C12; 209 temp1 = temp2 + temp1; 210 output[13] = 2 * (temp1 * C8); 211 212 output[ 9] = 2 * ((step[10] + step[11]) * C8); 213 214 intermediate[11] = step[10] - step[11]; 215 intermediate[12] = step[12] + step[13]; 216 intermediate[13] = step[12] - step[13]; 217 intermediate[14] = step[ 8] - step[14]; 218 intermediate[15] = step[ 9] - step[15]; 219 220 output[15] = (intermediate[11] + intermediate[12]); 221 output[ 1] = -(intermediate[11] - intermediate[12]); 222 223 output[ 7] = 2 * (intermediate[13] * C8); 224 225 temp1 = intermediate[14] * C12; 226 temp2 = intermediate[15] * C4; 227 temp1 = temp1 - temp2; 228 output[11] = -2 * (temp1 * C8); 229 230 temp1 = intermediate[14] * C4; 231 temp2 = intermediate[15] * C12; 232 temp1 = temp2 + temp1; 233 output[ 5] = 2 * (temp1 * C8); 234} 235 236void reference_16x16_dct_2d(int16_t input[256], double output[256]) { 237 // First transform columns 238 for (int i = 0; i < 16; ++i) { 239 double temp_in[16], temp_out[16]; 240 for (int j = 0; j < 16; ++j) 241 temp_in[j] = input[j * 16 + i]; 242 butterfly_16x16_dct_1d(temp_in, temp_out); 243 for (int j = 0; j < 16; ++j) 244 output[j * 16 + i] = temp_out[j]; 245 } 246 // Then transform rows 247 for (int i = 0; i < 16; ++i) { 248 double temp_in[16], temp_out[16]; 249 for (int j = 0; j < 16; ++j) 250 temp_in[j] = output[j + i * 16]; 251 butterfly_16x16_dct_1d(temp_in, temp_out); 252 // Scale by some magic number 253 for (int j = 0; j < 16; ++j) 254 output[j + i * 16] = temp_out[j]/2; 255 } 256} 257 258typedef void (*FdctFunc)(const int16_t *in, tran_low_t *out, int stride); 259typedef void (*IdctFunc)(const tran_low_t *in, uint8_t *out, int stride); 260typedef void (*FhtFunc)(const int16_t *in, tran_low_t *out, int stride, 261 int tx_type); 262typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride, 263 int tx_type); 264 265typedef std::tr1::tuple<FdctFunc, IdctFunc, int, vpx_bit_depth_t> Dct16x16Param; 266typedef std::tr1::tuple<FhtFunc, IhtFunc, int, vpx_bit_depth_t> Ht16x16Param; 267 268void fdct16x16_ref(const int16_t *in, tran_low_t *out, int stride, 269 int /*tx_type*/) { 270 vp9_fdct16x16_c(in, out, stride); 271} 272 273void idct16x16_ref(const tran_low_t *in, uint8_t *dest, int stride, 274 int /*tx_type*/) { 275 vp9_idct16x16_256_add_c(in, dest, stride); 276} 277 278void fht16x16_ref(const int16_t *in, tran_low_t *out, int stride, 279 int tx_type) { 280 vp9_fht16x16_c(in, out, stride, tx_type); 281} 282 283void iht16x16_ref(const tran_low_t *in, uint8_t *dest, int stride, 284 int tx_type) { 285 vp9_iht16x16_256_add_c(in, dest, stride, tx_type); 286} 287 288#if CONFIG_VP9_HIGHBITDEPTH 289void idct16x16_10(const tran_low_t *in, uint8_t *out, int stride) { 290 vp9_high_idct16x16_256_add_c(in, out, stride, 10); 291} 292 293void idct16x16_12(const tran_low_t *in, uint8_t *out, int stride) { 294 vp9_high_idct16x16_256_add_c(in, out, stride, 12); 295} 296 297void idct16x16_10_ref(const tran_low_t *in, uint8_t *out, int stride, 298 int tx_type) { 299 idct16x16_10(in, out, stride); 300} 301 302void idct16x16_12_ref(const tran_low_t *in, uint8_t *out, int stride, 303 int tx_type) { 304 idct16x16_12(in, out, stride); 305} 306 307void iht16x16_10(const tran_low_t *in, uint8_t *out, int stride, int tx_type) { 308 vp9_high_iht16x16_256_add_c(in, out, stride, tx_type, 10); 309} 310 311void iht16x16_12(const tran_low_t *in, uint8_t *out, int stride, int tx_type) { 312 vp9_high_iht16x16_256_add_c(in, out, stride, tx_type, 12); 313} 314#endif 315 316class Trans16x16TestBase { 317 public: 318 virtual ~Trans16x16TestBase() {} 319 320 protected: 321 virtual void RunFwdTxfm(int16_t *in, tran_low_t *out, int stride) = 0; 322 323 virtual void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) = 0; 324 325 void RunAccuracyCheck() { 326 ACMRandom rnd(ACMRandom::DeterministicSeed()); 327 uint32_t max_error = 0; 328 int64_t total_error = 0; 329 const int count_test_block = 10000; 330 for (int i = 0; i < count_test_block; ++i) { 331 DECLARE_ALIGNED_ARRAY(16, int16_t, test_input_block, kNumCoeffs); 332 DECLARE_ALIGNED_ARRAY(16, tran_low_t, test_temp_block, kNumCoeffs); 333 DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, kNumCoeffs); 334 DECLARE_ALIGNED_ARRAY(16, uint8_t, src, kNumCoeffs); 335#if CONFIG_VP9_HIGHBITDEPTH 336 DECLARE_ALIGNED_ARRAY(16, uint16_t, dst16, kNumCoeffs); 337 DECLARE_ALIGNED_ARRAY(16, uint16_t, src16, kNumCoeffs); 338#endif 339 340 // Initialize a test block with input range [-mask_, mask_]. 341 for (int j = 0; j < kNumCoeffs; ++j) { 342 if (bit_depth_ == VPX_BITS_8) { 343 src[j] = rnd.Rand8(); 344 dst[j] = rnd.Rand8(); 345 test_input_block[j] = src[j] - dst[j]; 346#if CONFIG_VP9_HIGHBITDEPTH 347 } else { 348 src16[j] = rnd.Rand16() & mask_; 349 dst16[j] = rnd.Rand16() & mask_; 350 test_input_block[j] = src16[j] - dst16[j]; 351#endif 352 } 353 } 354 355 ASM_REGISTER_STATE_CHECK(RunFwdTxfm(test_input_block, 356 test_temp_block, pitch_)); 357 if (bit_depth_ == VPX_BITS_8) { 358 ASM_REGISTER_STATE_CHECK( 359 RunInvTxfm(test_temp_block, dst, pitch_)); 360#if CONFIG_VP9_HIGHBITDEPTH 361 } else { 362 ASM_REGISTER_STATE_CHECK( 363 RunInvTxfm(test_temp_block, CONVERT_TO_BYTEPTR(dst16), pitch_)); 364#endif 365 } 366 367 for (int j = 0; j < kNumCoeffs; ++j) { 368#if CONFIG_VP9_HIGHBITDEPTH 369 const uint32_t diff = 370 bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j]; 371#else 372 const uint32_t diff = dst[j] - src[j]; 373#endif 374 const uint32_t error = diff * diff; 375 if (max_error < error) 376 max_error = error; 377 total_error += error; 378 } 379 } 380 381 EXPECT_GE(1u << 2 * (bit_depth_ - 8), max_error) 382 << "Error: 16x16 FHT/IHT has an individual round trip error > 1"; 383 384 EXPECT_GE(count_test_block << 2 * (bit_depth_ - 8), total_error) 385 << "Error: 16x16 FHT/IHT has average round trip error > 1 per block"; 386 } 387 388 void RunCoeffCheck() { 389 ACMRandom rnd(ACMRandom::DeterministicSeed()); 390 const int count_test_block = 1000; 391 DECLARE_ALIGNED_ARRAY(16, int16_t, input_block, kNumCoeffs); 392 DECLARE_ALIGNED_ARRAY(16, tran_low_t, output_ref_block, kNumCoeffs); 393 DECLARE_ALIGNED_ARRAY(16, tran_low_t, output_block, kNumCoeffs); 394 395 for (int i = 0; i < count_test_block; ++i) { 396 // Initialize a test block with input range [-mask_, mask_]. 397 for (int j = 0; j < kNumCoeffs; ++j) 398 input_block[j] = (rnd.Rand16() & mask_) - (rnd.Rand16() & mask_); 399 400 fwd_txfm_ref(input_block, output_ref_block, pitch_, tx_type_); 401 ASM_REGISTER_STATE_CHECK(RunFwdTxfm(input_block, output_block, pitch_)); 402 403 // The minimum quant value is 4. 404 for (int j = 0; j < kNumCoeffs; ++j) 405 EXPECT_EQ(output_block[j], output_ref_block[j]); 406 } 407 } 408 409 void RunMemCheck() { 410 ACMRandom rnd(ACMRandom::DeterministicSeed()); 411 const int count_test_block = 1000; 412 DECLARE_ALIGNED_ARRAY(16, int16_t, input_block, kNumCoeffs); 413 DECLARE_ALIGNED_ARRAY(16, int16_t, input_extreme_block, kNumCoeffs); 414 DECLARE_ALIGNED_ARRAY(16, tran_low_t, output_ref_block, kNumCoeffs); 415 DECLARE_ALIGNED_ARRAY(16, tran_low_t, output_block, kNumCoeffs); 416 417 for (int i = 0; i < count_test_block; ++i) { 418 // Initialize a test block with input range [-mask_, mask_]. 419 for (int j = 0; j < kNumCoeffs; ++j) { 420 input_block[j] = (rnd.Rand16() & mask_) - (rnd.Rand16() & mask_); 421 input_extreme_block[j] = rnd.Rand8() % 2 ? mask_ : -mask_; 422 } 423 if (i == 0) { 424 for (int j = 0; j < kNumCoeffs; ++j) 425 input_extreme_block[j] = mask_; 426 } else if (i == 1) { 427 for (int j = 0; j < kNumCoeffs; ++j) 428 input_extreme_block[j] = -mask_; 429 } 430 431 fwd_txfm_ref(input_extreme_block, output_ref_block, pitch_, tx_type_); 432 ASM_REGISTER_STATE_CHECK(RunFwdTxfm(input_extreme_block, 433 output_block, pitch_)); 434 435 // The minimum quant value is 4. 436 for (int j = 0; j < kNumCoeffs; ++j) { 437 EXPECT_EQ(output_block[j], output_ref_block[j]); 438 EXPECT_GE(4 * DCT_MAX_VALUE << (bit_depth_ - 8), abs(output_block[j])) 439 << "Error: 16x16 FDCT has coefficient larger than 4*DCT_MAX_VALUE"; 440 } 441 } 442 } 443 444 void RunQuantCheck(int dc_thred, int ac_thred) { 445 ACMRandom rnd(ACMRandom::DeterministicSeed()); 446 const int count_test_block = 1000; 447 DECLARE_ALIGNED_ARRAY(16, int16_t, input_block, kNumCoeffs); 448 DECLARE_ALIGNED_ARRAY(16, int16_t, input_extreme_block, kNumCoeffs); 449 DECLARE_ALIGNED_ARRAY(16, tran_low_t, output_ref_block, kNumCoeffs); 450 451 DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, kNumCoeffs); 452 DECLARE_ALIGNED_ARRAY(16, uint8_t, ref, kNumCoeffs); 453#if CONFIG_VP9_HIGHBITDEPTH 454 DECLARE_ALIGNED_ARRAY(16, uint16_t, dst16, kNumCoeffs); 455 DECLARE_ALIGNED_ARRAY(16, uint16_t, ref16, kNumCoeffs); 456#endif 457 458 for (int i = 0; i < count_test_block; ++i) { 459 // Initialize a test block with input range [-mask_, mask_]. 460 for (int j = 0; j < kNumCoeffs; ++j) { 461 if (bit_depth_ == VPX_BITS_8) 462 input_block[j] = rnd.Rand8() - rnd.Rand8(); 463 else 464 input_block[j] = (rnd.Rand16() & mask_) - (rnd.Rand16() & mask_); 465 input_extreme_block[j] = rnd.Rand8() % 2 ? mask_ : -mask_; 466 } 467 if (i == 0) 468 for (int j = 0; j < kNumCoeffs; ++j) 469 input_extreme_block[j] = mask_; 470 if (i == 1) 471 for (int j = 0; j < kNumCoeffs; ++j) 472 input_extreme_block[j] = -mask_; 473 474 fwd_txfm_ref(input_extreme_block, output_ref_block, pitch_, tx_type_); 475 476 // clear reconstructed pixel buffers 477 vpx_memset(dst, 0, kNumCoeffs * sizeof(uint8_t)); 478 vpx_memset(ref, 0, kNumCoeffs * sizeof(uint8_t)); 479#if CONFIG_VP9_HIGHBITDEPTH 480 vpx_memset(dst16, 0, kNumCoeffs * sizeof(uint16_t)); 481 vpx_memset(ref16, 0, kNumCoeffs * sizeof(uint16_t)); 482#endif 483 484 // quantization with maximum allowed step sizes 485 output_ref_block[0] = (output_ref_block[0] / dc_thred) * dc_thred; 486 for (int j = 1; j < kNumCoeffs; ++j) 487 output_ref_block[j] = (output_ref_block[j] / ac_thred) * ac_thred; 488 if (bit_depth_ == VPX_BITS_8) { 489 inv_txfm_ref(output_ref_block, ref, pitch_, tx_type_); 490 ASM_REGISTER_STATE_CHECK(RunInvTxfm(output_ref_block, dst, pitch_)); 491#if CONFIG_VP9_HIGHBITDEPTH 492 } else { 493 inv_txfm_ref(output_ref_block, CONVERT_TO_BYTEPTR(ref16), pitch_, 494 tx_type_); 495 ASM_REGISTER_STATE_CHECK(RunInvTxfm(output_ref_block, 496 CONVERT_TO_BYTEPTR(dst16), pitch_)); 497#endif 498 } 499 if (bit_depth_ == VPX_BITS_8) { 500 for (int j = 0; j < kNumCoeffs; ++j) 501 EXPECT_EQ(ref[j], dst[j]); 502#if CONFIG_VP9_HIGHBITDEPTH 503 } else { 504 for (int j = 0; j < kNumCoeffs; ++j) 505 EXPECT_EQ(ref16[j], dst16[j]); 506#endif 507 } 508 } 509 } 510 511 void RunInvAccuracyCheck() { 512 ACMRandom rnd(ACMRandom::DeterministicSeed()); 513 const int count_test_block = 1000; 514 DECLARE_ALIGNED_ARRAY(16, int16_t, in, kNumCoeffs); 515 DECLARE_ALIGNED_ARRAY(16, tran_low_t, coeff, kNumCoeffs); 516 DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, kNumCoeffs); 517 DECLARE_ALIGNED_ARRAY(16, uint8_t, src, kNumCoeffs); 518#if CONFIG_VP9_HIGHBITDEPTH 519 DECLARE_ALIGNED_ARRAY(16, uint16_t, dst16, kNumCoeffs); 520 DECLARE_ALIGNED_ARRAY(16, uint16_t, src16, kNumCoeffs); 521#endif 522 523 for (int i = 0; i < count_test_block; ++i) { 524 double out_r[kNumCoeffs]; 525 526 // Initialize a test block with input range [-255, 255]. 527 for (int j = 0; j < kNumCoeffs; ++j) { 528 if (bit_depth_ == VPX_BITS_8) { 529 src[j] = rnd.Rand8(); 530 dst[j] = rnd.Rand8(); 531 in[j] = src[j] - dst[j]; 532#if CONFIG_VP9_HIGHBITDEPTH 533 } else { 534 src16[j] = rnd.Rand16() & mask_; 535 dst16[j] = rnd.Rand16() & mask_; 536 in[j] = src16[j] - dst16[j]; 537#endif 538 } 539 } 540 541 reference_16x16_dct_2d(in, out_r); 542 for (int j = 0; j < kNumCoeffs; ++j) 543 coeff[j] = round(out_r[j]); 544 545 if (bit_depth_ == VPX_BITS_8) { 546 ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, 16)); 547#if CONFIG_VP9_HIGHBITDEPTH 548 } else { 549 ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, CONVERT_TO_BYTEPTR(dst16), 550 16)); 551#endif 552 } 553 554 for (int j = 0; j < kNumCoeffs; ++j) { 555#if CONFIG_VP9_HIGHBITDEPTH 556 const uint32_t diff = 557 bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j]; 558#else 559 const uint32_t diff = dst[j] - src[j]; 560#endif 561 const uint32_t error = diff * diff; 562 EXPECT_GE(1u, error) 563 << "Error: 16x16 IDCT has error " << error 564 << " at index " << j; 565 } 566 } 567 } 568 int pitch_; 569 int tx_type_; 570 vpx_bit_depth_t bit_depth_; 571 int mask_; 572 FhtFunc fwd_txfm_ref; 573 IhtFunc inv_txfm_ref; 574}; 575 576class Trans16x16DCT 577 : public Trans16x16TestBase, 578 public ::testing::TestWithParam<Dct16x16Param> { 579 public: 580 virtual ~Trans16x16DCT() {} 581 582 virtual void SetUp() { 583 fwd_txfm_ = GET_PARAM(0); 584 inv_txfm_ = GET_PARAM(1); 585 tx_type_ = GET_PARAM(2); 586 bit_depth_ = GET_PARAM(3); 587 pitch_ = 16; 588 fwd_txfm_ref = fdct16x16_ref; 589 inv_txfm_ref = idct16x16_ref; 590 mask_ = (1 << bit_depth_) - 1; 591#if CONFIG_VP9_HIGHBITDEPTH 592 switch (bit_depth_) { 593 case 10: 594 inv_txfm_ref = idct16x16_10_ref; 595 break; 596 case 12: 597 inv_txfm_ref = idct16x16_12_ref; 598 break; 599 default: 600 inv_txfm_ref = idct16x16_ref; 601 break; 602 } 603#else 604 inv_txfm_ref = idct16x16_ref; 605#endif 606 } 607 virtual void TearDown() { libvpx_test::ClearSystemState(); } 608 609 protected: 610 void RunFwdTxfm(int16_t *in, tran_low_t *out, int stride) { 611 fwd_txfm_(in, out, stride); 612 } 613 void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) { 614 inv_txfm_(out, dst, stride); 615 } 616 617 FdctFunc fwd_txfm_; 618 IdctFunc inv_txfm_; 619}; 620 621TEST_P(Trans16x16DCT, AccuracyCheck) { 622 RunAccuracyCheck(); 623} 624 625TEST_P(Trans16x16DCT, CoeffCheck) { 626 RunCoeffCheck(); 627} 628 629TEST_P(Trans16x16DCT, MemCheck) { 630 RunMemCheck(); 631} 632 633TEST_P(Trans16x16DCT, QuantCheck) { 634 // Use maximally allowed quantization step sizes for DC and AC 635 // coefficients respectively. 636 RunQuantCheck(1336, 1828); 637} 638 639TEST_P(Trans16x16DCT, InvAccuracyCheck) { 640 RunInvAccuracyCheck(); 641} 642 643class Trans16x16HT 644 : public Trans16x16TestBase, 645 public ::testing::TestWithParam<Ht16x16Param> { 646 public: 647 virtual ~Trans16x16HT() {} 648 649 virtual void SetUp() { 650 fwd_txfm_ = GET_PARAM(0); 651 inv_txfm_ = GET_PARAM(1); 652 tx_type_ = GET_PARAM(2); 653 bit_depth_ = GET_PARAM(3); 654 pitch_ = 16; 655 fwd_txfm_ref = fht16x16_ref; 656 inv_txfm_ref = iht16x16_ref; 657 mask_ = (1 << bit_depth_) - 1; 658#if CONFIG_VP9_HIGHBITDEPTH 659 switch (bit_depth_) { 660 case VPX_BITS_10: 661 inv_txfm_ref = iht16x16_10; 662 break; 663 case VPX_BITS_12: 664 inv_txfm_ref = iht16x16_12; 665 break; 666 default: 667 inv_txfm_ref = iht16x16_ref; 668 break; 669 } 670#else 671 inv_txfm_ref = iht16x16_ref; 672#endif 673 } 674 virtual void TearDown() { libvpx_test::ClearSystemState(); } 675 676 protected: 677 void RunFwdTxfm(int16_t *in, tran_low_t *out, int stride) { 678 fwd_txfm_(in, out, stride, tx_type_); 679 } 680 void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) { 681 inv_txfm_(out, dst, stride, tx_type_); 682 } 683 684 FhtFunc fwd_txfm_; 685 IhtFunc inv_txfm_; 686}; 687 688TEST_P(Trans16x16HT, AccuracyCheck) { 689 RunAccuracyCheck(); 690} 691 692TEST_P(Trans16x16HT, CoeffCheck) { 693 RunCoeffCheck(); 694} 695 696TEST_P(Trans16x16HT, MemCheck) { 697 RunMemCheck(); 698} 699 700TEST_P(Trans16x16HT, QuantCheck) { 701 // The encoder skips any non-DC intra prediction modes, 702 // when the quantization step size goes beyond 988. 703 RunQuantCheck(549, 988); 704} 705 706using std::tr1::make_tuple; 707 708#if CONFIG_VP9_HIGHBITDEPTH 709INSTANTIATE_TEST_CASE_P( 710 C, Trans16x16DCT, 711 ::testing::Values( 712 make_tuple(&vp9_high_fdct16x16_c, &idct16x16_10, 0, VPX_BITS_10), 713 make_tuple(&vp9_high_fdct16x16_c, &idct16x16_12, 0, VPX_BITS_12), 714 make_tuple(&vp9_fdct16x16_c, &vp9_idct16x16_256_add_c, 0, VPX_BITS_8))); 715#else 716INSTANTIATE_TEST_CASE_P( 717 C, Trans16x16DCT, 718 ::testing::Values( 719 make_tuple(&vp9_fdct16x16_c, &vp9_idct16x16_256_add_c, 0, VPX_BITS_8))); 720#endif 721 722#if CONFIG_VP9_HIGHBITDEPTH 723INSTANTIATE_TEST_CASE_P( 724 C, Trans16x16HT, 725 ::testing::Values( 726 make_tuple(&vp9_high_fht16x16_c, &iht16x16_10, 0, VPX_BITS_10), 727 make_tuple(&vp9_high_fht16x16_c, &iht16x16_10, 1, VPX_BITS_10), 728 make_tuple(&vp9_high_fht16x16_c, &iht16x16_10, 2, VPX_BITS_10), 729 make_tuple(&vp9_high_fht16x16_c, &iht16x16_10, 3, VPX_BITS_10), 730 make_tuple(&vp9_high_fht16x16_c, &iht16x16_12, 0, VPX_BITS_12), 731 make_tuple(&vp9_high_fht16x16_c, &iht16x16_12, 1, VPX_BITS_12), 732 make_tuple(&vp9_high_fht16x16_c, &iht16x16_12, 2, VPX_BITS_12), 733 make_tuple(&vp9_high_fht16x16_c, &iht16x16_12, 3, VPX_BITS_12), 734 make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 0, VPX_BITS_8), 735 make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 1, VPX_BITS_8), 736 make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 2, VPX_BITS_8), 737 make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 3, VPX_BITS_8))); 738#else 739INSTANTIATE_TEST_CASE_P( 740 C, Trans16x16HT, 741 ::testing::Values( 742 make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 0, VPX_BITS_8), 743 make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 1, VPX_BITS_8), 744 make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 2, VPX_BITS_8), 745 make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 3, VPX_BITS_8))); 746#endif 747 748#if HAVE_NEON_ASM && !CONFIG_VP9_HIGHBITDEPTH 749INSTANTIATE_TEST_CASE_P( 750 NEON, Trans16x16DCT, 751 ::testing::Values( 752 make_tuple(&vp9_fdct16x16_c, 753 &vp9_idct16x16_256_add_neon, 0, VPX_BITS_8))); 754#endif 755 756#if HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH 757INSTANTIATE_TEST_CASE_P( 758 SSE2, Trans16x16DCT, 759 ::testing::Values( 760 make_tuple(&vp9_fdct16x16_sse2, 761 &vp9_idct16x16_256_add_sse2, 0, VPX_BITS_8))); 762INSTANTIATE_TEST_CASE_P( 763 SSE2, Trans16x16HT, 764 ::testing::Values( 765 make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 0, 766 VPX_BITS_8), 767 make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 1, 768 VPX_BITS_8), 769 make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 2, 770 VPX_BITS_8), 771 make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 3, 772 VPX_BITS_8))); 773#endif 774 775#if HAVE_SSSE3 && !CONFIG_VP9_HIGHBITDEPTH 776INSTANTIATE_TEST_CASE_P( 777 SSSE3, Trans16x16DCT, 778 ::testing::Values( 779 make_tuple(&vp9_fdct16x16_c, &vp9_idct16x16_256_add_ssse3, 0, 780 VPX_BITS_8))); 781#endif 782} // namespace 783