OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebM project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebM project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
265 typedef void (*iht_t) (const int16_t *in, uint8_t *out, int stride, | 265 typedef void (*iht_t) (const int16_t *in, uint8_t *out, int stride, |
266 int tx_type); | 266 int tx_type); |
267 | 267 |
268 typedef std::tr1::tuple<fdct_t, idct_t, int> dct_16x16_param_t; | 268 typedef std::tr1::tuple<fdct_t, idct_t, int> dct_16x16_param_t; |
269 typedef std::tr1::tuple<fht_t, iht_t, int> ht_16x16_param_t; | 269 typedef std::tr1::tuple<fht_t, iht_t, int> ht_16x16_param_t; |
270 | 270 |
271 void fdct16x16_ref(const int16_t *in, int16_t *out, int stride, int tx_type) { | 271 void fdct16x16_ref(const int16_t *in, int16_t *out, int stride, int tx_type) { |
272 vp9_fdct16x16_c(in, out, stride); | 272 vp9_fdct16x16_c(in, out, stride); |
273 } | 273 } |
274 | 274 |
| 275 void idct16x16_ref(const int16_t *in, uint8_t *dest, int stride, int tx_type) { |
| 276 vp9_idct16x16_256_add_c(in, dest, stride); |
| 277 } |
| 278 |
275 void fht16x16_ref(const int16_t *in, int16_t *out, int stride, int tx_type) { | 279 void fht16x16_ref(const int16_t *in, int16_t *out, int stride, int tx_type) { |
276 vp9_fht16x16_c(in, out, stride, tx_type); | 280 vp9_fht16x16_c(in, out, stride, tx_type); |
277 } | 281 } |
278 | 282 |
| 283 void iht16x16_ref(const int16_t *in, uint8_t *dest, int stride, int tx_type) { |
| 284 vp9_iht16x16_256_add_c(in, dest, stride, tx_type); |
| 285 } |
| 286 |
279 class Trans16x16TestBase { | 287 class Trans16x16TestBase { |
280 public: | 288 public: |
281 virtual ~Trans16x16TestBase() {} | 289 virtual ~Trans16x16TestBase() {} |
282 | 290 |
283 protected: | 291 protected: |
284 virtual void RunFwdTxfm(int16_t *in, int16_t *out, int stride) = 0; | 292 virtual void RunFwdTxfm(int16_t *in, int16_t *out, int stride) = 0; |
285 | 293 |
286 virtual void RunInvTxfm(int16_t *out, uint8_t *dst, int stride) = 0; | 294 virtual void RunInvTxfm(int16_t *out, uint8_t *dst, int stride) = 0; |
287 | 295 |
288 void RunAccuracyCheck() { | 296 void RunAccuracyCheck() { |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
351 DECLARE_ALIGNED_ARRAY(16, int16_t, input_extreme_block, kNumCoeffs); | 359 DECLARE_ALIGNED_ARRAY(16, int16_t, input_extreme_block, kNumCoeffs); |
352 DECLARE_ALIGNED_ARRAY(16, int16_t, output_ref_block, kNumCoeffs); | 360 DECLARE_ALIGNED_ARRAY(16, int16_t, output_ref_block, kNumCoeffs); |
353 DECLARE_ALIGNED_ARRAY(16, int16_t, output_block, kNumCoeffs); | 361 DECLARE_ALIGNED_ARRAY(16, int16_t, output_block, kNumCoeffs); |
354 | 362 |
355 for (int i = 0; i < count_test_block; ++i) { | 363 for (int i = 0; i < count_test_block; ++i) { |
356 // Initialize a test block with input range [-255, 255]. | 364 // Initialize a test block with input range [-255, 255]. |
357 for (int j = 0; j < kNumCoeffs; ++j) { | 365 for (int j = 0; j < kNumCoeffs; ++j) { |
358 input_block[j] = rnd.Rand8() - rnd.Rand8(); | 366 input_block[j] = rnd.Rand8() - rnd.Rand8(); |
359 input_extreme_block[j] = rnd.Rand8() % 2 ? 255 : -255; | 367 input_extreme_block[j] = rnd.Rand8() % 2 ? 255 : -255; |
360 } | 368 } |
361 if (i == 0) | 369 if (i == 0) { |
362 for (int j = 0; j < kNumCoeffs; ++j) | 370 for (int j = 0; j < kNumCoeffs; ++j) |
363 input_extreme_block[j] = 255; | 371 input_extreme_block[j] = 255; |
364 if (i == 1) | 372 } else if (i == 1) { |
365 for (int j = 0; j < kNumCoeffs; ++j) | 373 for (int j = 0; j < kNumCoeffs; ++j) |
366 input_extreme_block[j] = -255; | 374 input_extreme_block[j] = -255; |
| 375 } |
367 | 376 |
368 fwd_txfm_ref(input_extreme_block, output_ref_block, pitch_, tx_type_); | 377 fwd_txfm_ref(input_extreme_block, output_ref_block, pitch_, tx_type_); |
369 REGISTER_STATE_CHECK(RunFwdTxfm(input_extreme_block, | 378 REGISTER_STATE_CHECK(RunFwdTxfm(input_extreme_block, |
370 output_block, pitch_)); | 379 output_block, pitch_)); |
371 | 380 |
372 // The minimum quant value is 4. | 381 // The minimum quant value is 4. |
373 for (int j = 0; j < kNumCoeffs; ++j) { | 382 for (int j = 0; j < kNumCoeffs; ++j) { |
374 EXPECT_EQ(output_block[j], output_ref_block[j]); | 383 EXPECT_EQ(output_block[j], output_ref_block[j]); |
375 EXPECT_GE(4 * DCT_MAX_VALUE, abs(output_block[j])) | 384 EXPECT_GE(4 * DCT_MAX_VALUE, abs(output_block[j])) |
376 << "Error: 16x16 FDCT has coefficient larger than 4*DCT_MAX_VALUE"; | 385 << "Error: 16x16 FDCT has coefficient larger than 4*DCT_MAX_VALUE"; |
377 } | 386 } |
378 } | 387 } |
379 } | 388 } |
380 | 389 |
| 390 void RunQuantCheck(int dc_thred, int ac_thred) { |
| 391 ACMRandom rnd(ACMRandom::DeterministicSeed()); |
| 392 const int count_test_block = 1000; |
| 393 DECLARE_ALIGNED_ARRAY(16, int16_t, input_block, kNumCoeffs); |
| 394 DECLARE_ALIGNED_ARRAY(16, int16_t, input_extreme_block, kNumCoeffs); |
| 395 DECLARE_ALIGNED_ARRAY(16, int16_t, output_ref_block, kNumCoeffs); |
| 396 |
| 397 DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, kNumCoeffs); |
| 398 DECLARE_ALIGNED_ARRAY(16, uint8_t, ref, kNumCoeffs); |
| 399 |
| 400 for (int i = 0; i < count_test_block; ++i) { |
| 401 // Initialize a test block with input range [-255, 255]. |
| 402 for (int j = 0; j < kNumCoeffs; ++j) { |
| 403 input_block[j] = rnd.Rand8() - rnd.Rand8(); |
| 404 input_extreme_block[j] = rnd.Rand8() % 2 ? 255 : -255; |
| 405 } |
| 406 if (i == 0) |
| 407 for (int j = 0; j < kNumCoeffs; ++j) |
| 408 input_extreme_block[j] = 255; |
| 409 if (i == 1) |
| 410 for (int j = 0; j < kNumCoeffs; ++j) |
| 411 input_extreme_block[j] = -255; |
| 412 |
| 413 fwd_txfm_ref(input_extreme_block, output_ref_block, pitch_, tx_type_); |
| 414 |
| 415 // clear reconstructed pixel buffers |
| 416 vpx_memset(dst, 0, kNumCoeffs * sizeof(uint8_t)); |
| 417 vpx_memset(ref, 0, kNumCoeffs * sizeof(uint8_t)); |
| 418 |
| 419 // quantization with maximum allowed step sizes |
| 420 output_ref_block[0] = (output_ref_block[0] / dc_thred) * dc_thred; |
| 421 for (int j = 1; j < kNumCoeffs; ++j) |
| 422 output_ref_block[j] = (output_ref_block[j] / ac_thred) * ac_thred; |
| 423 inv_txfm_ref(output_ref_block, ref, pitch_, tx_type_); |
| 424 REGISTER_STATE_CHECK(RunInvTxfm(output_ref_block, dst, pitch_)); |
| 425 |
| 426 for (int j = 0; j < kNumCoeffs; ++j) |
| 427 EXPECT_EQ(ref[j], dst[j]); |
| 428 } |
| 429 } |
| 430 |
381 void RunInvAccuracyCheck() { | 431 void RunInvAccuracyCheck() { |
382 ACMRandom rnd(ACMRandom::DeterministicSeed()); | 432 ACMRandom rnd(ACMRandom::DeterministicSeed()); |
383 const int count_test_block = 1000; | 433 const int count_test_block = 1000; |
384 DECLARE_ALIGNED_ARRAY(16, int16_t, in, kNumCoeffs); | 434 DECLARE_ALIGNED_ARRAY(16, int16_t, in, kNumCoeffs); |
385 DECLARE_ALIGNED_ARRAY(16, int16_t, coeff, kNumCoeffs); | 435 DECLARE_ALIGNED_ARRAY(16, int16_t, coeff, kNumCoeffs); |
386 DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, kNumCoeffs); | 436 DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, kNumCoeffs); |
387 DECLARE_ALIGNED_ARRAY(16, uint8_t, src, kNumCoeffs); | 437 DECLARE_ALIGNED_ARRAY(16, uint8_t, src, kNumCoeffs); |
388 | 438 |
389 for (int i = 0; i < count_test_block; ++i) { | 439 for (int i = 0; i < count_test_block; ++i) { |
390 double out_r[kNumCoeffs]; | 440 double out_r[kNumCoeffs]; |
(...skipping 16 matching lines...) Expand all Loading... |
407 const uint32_t error = diff * diff; | 457 const uint32_t error = diff * diff; |
408 EXPECT_GE(1u, error) | 458 EXPECT_GE(1u, error) |
409 << "Error: 16x16 IDCT has error " << error | 459 << "Error: 16x16 IDCT has error " << error |
410 << " at index " << j; | 460 << " at index " << j; |
411 } | 461 } |
412 } | 462 } |
413 } | 463 } |
414 int pitch_; | 464 int pitch_; |
415 int tx_type_; | 465 int tx_type_; |
416 fht_t fwd_txfm_ref; | 466 fht_t fwd_txfm_ref; |
| 467 iht_t inv_txfm_ref; |
417 }; | 468 }; |
418 | 469 |
419 class Trans16x16DCT | 470 class Trans16x16DCT |
420 : public Trans16x16TestBase, | 471 : public Trans16x16TestBase, |
421 public ::testing::TestWithParam<dct_16x16_param_t> { | 472 public ::testing::TestWithParam<dct_16x16_param_t> { |
422 public: | 473 public: |
423 virtual ~Trans16x16DCT() {} | 474 virtual ~Trans16x16DCT() {} |
424 | 475 |
425 virtual void SetUp() { | 476 virtual void SetUp() { |
426 fwd_txfm_ = GET_PARAM(0); | 477 fwd_txfm_ = GET_PARAM(0); |
427 inv_txfm_ = GET_PARAM(1); | 478 inv_txfm_ = GET_PARAM(1); |
428 tx_type_ = GET_PARAM(2); | 479 tx_type_ = GET_PARAM(2); |
429 pitch_ = 16; | 480 pitch_ = 16; |
430 fwd_txfm_ref = fdct16x16_ref; | 481 fwd_txfm_ref = fdct16x16_ref; |
| 482 inv_txfm_ref = idct16x16_ref; |
431 } | 483 } |
432 virtual void TearDown() { libvpx_test::ClearSystemState(); } | 484 virtual void TearDown() { libvpx_test::ClearSystemState(); } |
433 | 485 |
434 protected: | 486 protected: |
435 void RunFwdTxfm(int16_t *in, int16_t *out, int stride) { | 487 void RunFwdTxfm(int16_t *in, int16_t *out, int stride) { |
436 fwd_txfm_(in, out, stride); | 488 fwd_txfm_(in, out, stride); |
437 } | 489 } |
438 void RunInvTxfm(int16_t *out, uint8_t *dst, int stride) { | 490 void RunInvTxfm(int16_t *out, uint8_t *dst, int stride) { |
439 inv_txfm_(out, dst, stride); | 491 inv_txfm_(out, dst, stride); |
440 } | 492 } |
441 | 493 |
442 fdct_t fwd_txfm_; | 494 fdct_t fwd_txfm_; |
443 idct_t inv_txfm_; | 495 idct_t inv_txfm_; |
444 }; | 496 }; |
445 | 497 |
446 TEST_P(Trans16x16DCT, AccuracyCheck) { | 498 TEST_P(Trans16x16DCT, AccuracyCheck) { |
447 RunAccuracyCheck(); | 499 RunAccuracyCheck(); |
448 } | 500 } |
449 | 501 |
450 TEST_P(Trans16x16DCT, CoeffCheck) { | 502 TEST_P(Trans16x16DCT, CoeffCheck) { |
451 RunCoeffCheck(); | 503 RunCoeffCheck(); |
452 } | 504 } |
453 | 505 |
454 TEST_P(Trans16x16DCT, MemCheck) { | 506 TEST_P(Trans16x16DCT, MemCheck) { |
455 RunMemCheck(); | 507 RunMemCheck(); |
456 } | 508 } |
457 | 509 |
| 510 TEST_P(Trans16x16DCT, QuantCheck) { |
| 511 // Use maximally allowed quantization step sizes for DC and AC |
| 512 // coefficients respectively. |
| 513 RunQuantCheck(1336, 1828); |
| 514 } |
| 515 |
458 TEST_P(Trans16x16DCT, InvAccuracyCheck) { | 516 TEST_P(Trans16x16DCT, InvAccuracyCheck) { |
459 RunInvAccuracyCheck(); | 517 RunInvAccuracyCheck(); |
460 } | 518 } |
461 | 519 |
462 class Trans16x16HT | 520 class Trans16x16HT |
463 : public Trans16x16TestBase, | 521 : public Trans16x16TestBase, |
464 public ::testing::TestWithParam<ht_16x16_param_t> { | 522 public ::testing::TestWithParam<ht_16x16_param_t> { |
465 public: | 523 public: |
466 virtual ~Trans16x16HT() {} | 524 virtual ~Trans16x16HT() {} |
467 | 525 |
468 virtual void SetUp() { | 526 virtual void SetUp() { |
469 fwd_txfm_ = GET_PARAM(0); | 527 fwd_txfm_ = GET_PARAM(0); |
470 inv_txfm_ = GET_PARAM(1); | 528 inv_txfm_ = GET_PARAM(1); |
471 tx_type_ = GET_PARAM(2); | 529 tx_type_ = GET_PARAM(2); |
472 pitch_ = 16; | 530 pitch_ = 16; |
473 fwd_txfm_ref = fht16x16_ref; | 531 fwd_txfm_ref = fht16x16_ref; |
| 532 inv_txfm_ref = iht16x16_ref; |
474 } | 533 } |
475 virtual void TearDown() { libvpx_test::ClearSystemState(); } | 534 virtual void TearDown() { libvpx_test::ClearSystemState(); } |
476 | 535 |
477 protected: | 536 protected: |
478 void RunFwdTxfm(int16_t *in, int16_t *out, int stride) { | 537 void RunFwdTxfm(int16_t *in, int16_t *out, int stride) { |
479 fwd_txfm_(in, out, stride, tx_type_); | 538 fwd_txfm_(in, out, stride, tx_type_); |
480 } | 539 } |
481 void RunInvTxfm(int16_t *out, uint8_t *dst, int stride) { | 540 void RunInvTxfm(int16_t *out, uint8_t *dst, int stride) { |
482 inv_txfm_(out, dst, stride, tx_type_); | 541 inv_txfm_(out, dst, stride, tx_type_); |
483 } | 542 } |
484 | 543 |
485 fht_t fwd_txfm_; | 544 fht_t fwd_txfm_; |
486 iht_t inv_txfm_; | 545 iht_t inv_txfm_; |
487 }; | 546 }; |
488 | 547 |
489 TEST_P(Trans16x16HT, AccuracyCheck) { | 548 TEST_P(Trans16x16HT, AccuracyCheck) { |
490 RunAccuracyCheck(); | 549 RunAccuracyCheck(); |
491 } | 550 } |
492 | 551 |
493 TEST_P(Trans16x16HT, CoeffCheck) { | 552 TEST_P(Trans16x16HT, CoeffCheck) { |
494 RunCoeffCheck(); | 553 RunCoeffCheck(); |
495 } | 554 } |
496 | 555 |
497 TEST_P(Trans16x16HT, MemCheck) { | 556 TEST_P(Trans16x16HT, MemCheck) { |
498 RunMemCheck(); | 557 RunMemCheck(); |
499 } | 558 } |
500 | 559 |
| 560 TEST_P(Trans16x16HT, QuantCheck) { |
| 561 // The encoder skips any non-DC intra prediction modes, |
| 562 // when the quantization step size goes beyond 988. |
| 563 RunQuantCheck(549, 988); |
| 564 } |
| 565 |
501 using std::tr1::make_tuple; | 566 using std::tr1::make_tuple; |
502 | 567 |
503 INSTANTIATE_TEST_CASE_P( | 568 INSTANTIATE_TEST_CASE_P( |
504 C, Trans16x16DCT, | 569 C, Trans16x16DCT, |
505 ::testing::Values( | 570 ::testing::Values( |
506 make_tuple(&vp9_fdct16x16_c, &vp9_idct16x16_256_add_c, 0))); | 571 make_tuple(&vp9_fdct16x16_c, &vp9_idct16x16_256_add_c, 0))); |
507 INSTANTIATE_TEST_CASE_P( | 572 INSTANTIATE_TEST_CASE_P( |
508 C, Trans16x16HT, | 573 C, Trans16x16HT, |
509 ::testing::Values( | 574 ::testing::Values( |
510 make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 0), | 575 make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 0), |
(...skipping 16 matching lines...) Expand all Loading... |
527 make_tuple(&vp9_fdct16x16_sse2, | 592 make_tuple(&vp9_fdct16x16_sse2, |
528 &vp9_idct16x16_256_add_sse2, 0))); | 593 &vp9_idct16x16_256_add_sse2, 0))); |
529 INSTANTIATE_TEST_CASE_P( | 594 INSTANTIATE_TEST_CASE_P( |
530 SSE2, Trans16x16HT, | 595 SSE2, Trans16x16HT, |
531 ::testing::Values( | 596 ::testing::Values( |
532 make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 0), | 597 make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 0), |
533 make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 1), | 598 make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 1), |
534 make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 2), | 599 make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 2), |
535 make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 3))); | 600 make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 3))); |
536 #endif | 601 #endif |
| 602 |
| 603 #if HAVE_SSSE3 |
| 604 INSTANTIATE_TEST_CASE_P( |
| 605 SSSE3, Trans16x16DCT, |
| 606 ::testing::Values( |
| 607 make_tuple(&vp9_fdct16x16_c, &vp9_idct16x16_256_add_ssse3, 0))); |
| 608 #endif |
| 609 |
| 610 #if HAVE_AVX2 |
| 611 // TODO(jzern): these prototypes can be removed after the avx2 versions are |
| 612 // reenabled in vp9_rtcd_defs.pl. |
| 613 extern "C" { |
| 614 void vp9_fdct16x16_avx2(const int16_t *input, int16_t *output, int stride); |
| 615 void vp9_fht16x16_avx2(const int16_t *input, int16_t *output, int stride, |
| 616 int tx_type); |
| 617 } |
| 618 INSTANTIATE_TEST_CASE_P( |
| 619 DISABLED_AVX2, Trans16x16DCT, |
| 620 ::testing::Values( |
| 621 make_tuple(&vp9_fdct16x16_avx2, |
| 622 &vp9_idct16x16_256_add_c, 0))); |
| 623 INSTANTIATE_TEST_CASE_P( |
| 624 AVX2, Trans16x16HT, |
| 625 ::testing::Values( |
| 626 make_tuple(&vp9_fht16x16_avx2, &vp9_iht16x16_256_add_c, 3))); |
| 627 INSTANTIATE_TEST_CASE_P( |
| 628 DISABLED_AVX2, Trans16x16HT, |
| 629 ::testing::Values( |
| 630 make_tuple(&vp9_fht16x16_avx2, &vp9_iht16x16_256_add_c, 0), |
| 631 make_tuple(&vp9_fht16x16_avx2, &vp9_iht16x16_256_add_c, 1), |
| 632 make_tuple(&vp9_fht16x16_avx2, &vp9_iht16x16_256_add_c, 2))); |
| 633 #endif |
537 } // namespace | 634 } // namespace |
OLD | NEW |