From cf768b2d80891fe478abb41dd8687fcb86bfda81 Mon Sep 17 00:00:00 2001 From: Jingning Han Date: Tue, 9 Jul 2013 16:16:49 -0700 Subject: [PATCH] Add unit test for 16x16 forward ADST/DCT Unit tests on the functional accuracy of forward ADST/DCT. Change-Id: I81afff866bdeacbd457b0af96993a035741657f6 --- test/dct16x16_test.cc | 141 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 100 insertions(+), 41 deletions(-) diff --git a/test/dct16x16_test.cc b/test/dct16x16_test.cc index 9fb45d6..13b1dc8 100644 --- a/test/dct16x16_test.cc +++ b/test/dct16x16_test.cc @@ -13,6 +13,7 @@ #include #include "third_party/googletest/src/include/gtest/gtest.h" +#include "vpx_ports/mem.h" extern "C" { #include "vp9/common/vp9_entropy.h" @@ -264,47 +265,69 @@ void reference_16x16_dct_2d(int16_t input[16*16], double output[16*16]) { } } +void fdct16x16(int16_t *in, int16_t *out, uint8_t* /*dst*/, + int stride, int /*tx_type*/) { + vp9_short_fdct16x16_c(in, out, stride); +} +void idct16x16_add(int16_t* /*in*/, int16_t *out, uint8_t *dst, + int stride, int /*tx_type*/) { + vp9_short_idct16x16_add_c(out, dst, stride >> 1); +} +void fht16x16(int16_t *in, int16_t *out, uint8_t* /*dst*/, + int stride, int tx_type) { + // FIXME(jingning): patch dependency on SSE2 16x16 hybrid transform coding +#if HAVE_SSE2 && 0 + vp9_short_fht16x16_sse2(in, out, stride >> 1, tx_type); +#else + vp9_short_fht16x16_c(in, out, stride >> 1, tx_type); +#endif +} +void iht16x16_add(int16_t* /*in*/, int16_t *out, uint8_t *dst, + int stride, int tx_type) { + vp9_short_iht16x16_add_c(out, dst, stride >> 1, tx_type); +} -TEST(VP9Idct16x16Test, AccuracyCheck) { - ACMRandom rnd(ACMRandom::DeterministicSeed()); - const int count_test_block = 1000; - for (int i = 0; i < count_test_block; ++i) { - int16_t in[256], coeff[256]; - uint8_t dst[256], src[256]; - double out_r[256]; - - for (int j = 0; j < 256; ++j) { - src[j] = rnd.Rand8(); - dst[j] = rnd.Rand8(); +class FwdTrans16x16Test : public ::testing::TestWithParam { + public: + FwdTrans16x16Test() { SetUpTestTxfm(); } + ~FwdTrans16x16Test() {} + + void SetUpTestTxfm() { + tx_type_ = GetParam(); + if (tx_type_ == 0) { + fwd_txfm = fdct16x16; + inv_txfm = idct16x16_add; + } else { + fwd_txfm = fht16x16; + inv_txfm = iht16x16_add; } - // Initialize a test block with input range [-255, 255]. - for (int j = 0; j < 256; ++j) - in[j] = src[j] - dst[j]; + } - reference_16x16_dct_2d(in, out_r); - for (int j = 0; j < 256; j++) - coeff[j] = round(out_r[j]); - vp9_short_idct16x16_add_c(coeff, dst, 16); - for (int j = 0; j < 256; ++j) { - const int diff = dst[j] - src[j]; - const int error = diff * diff; - EXPECT_GE(1, error) - << "Error: 16x16 IDCT has error " << error - << " at index " << j; - } + protected: + void RunFwdTxfm(int16_t *in, int16_t *out, uint8_t *dst, + int stride, int tx_type) { + (*fwd_txfm)(in, out, dst, stride, tx_type); } -} + void RunInvTxfm(int16_t *in, int16_t *out, uint8_t *dst, + int stride, int tx_type) { + (*inv_txfm)(in, out, dst, stride, tx_type); + } + + int tx_type_; + void (*fwd_txfm)(int16_t*, int16_t*, uint8_t*, int, int); + void (*inv_txfm)(int16_t*, int16_t*, uint8_t*, int, int); +}; -// we need enable fdct test once we re-do the 16 point fdct. -TEST(VP9Fdct16x16Test, AccuracyCheck) { +TEST_P(FwdTrans16x16Test, AccuracyCheck) { ACMRandom rnd(ACMRandom::DeterministicSeed()); int max_error = 0; double total_error = 0; - const int count_test_block = 1000; + const int count_test_block = 10000; for (int i = 0; i < count_test_block; ++i) { - int16_t test_input_block[256]; - int16_t test_temp_block[256]; - uint8_t dst[256], src[256]; + DECLARE_ALIGNED_ARRAY(16, int16_t, test_input_block, 256); + DECLARE_ALIGNED_ARRAY(16, int16_t, test_temp_block, 256); + DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, 256); + DECLARE_ALIGNED_ARRAY(16, uint8_t, src, 256); for (int j = 0; j < 256; ++j) { src[j] = rnd.Rand8(); @@ -315,8 +338,8 @@ TEST(VP9Fdct16x16Test, AccuracyCheck) { test_input_block[j] = src[j] - dst[j]; const int pitch = 32; - vp9_short_fdct16x16_c(test_input_block, test_temp_block, pitch); - vp9_short_idct16x16_add_c(test_temp_block, dst, 16); + RunFwdTxfm(test_input_block, test_temp_block, dst, pitch, tx_type_); + RunInvTxfm(test_input_block, test_temp_block, dst, pitch, tx_type_); for (int j = 0; j < 256; ++j) { const int diff = dst[j] - src[j]; @@ -328,18 +351,21 @@ TEST(VP9Fdct16x16Test, AccuracyCheck) { } EXPECT_GE(1, max_error) - << "Error: 16x16 FDCT/IDCT has an individual round trip error > 1"; + << "Error: 16x16 FHT/IHT has an individual round trip error > 1"; EXPECT_GE(count_test_block , total_error) - << "Error: 16x16 FDCT/IDCT has average round trip error > 1 per block"; + << "Error: 16x16 FHT/IHT has average round trip error > 1 per block"; } -TEST(VP9Fdct16x16Test, CoeffSizeCheck) { +TEST_P(FwdTrans16x16Test, CoeffSizeCheck) { ACMRandom rnd(ACMRandom::DeterministicSeed()); const int count_test_block = 1000; for (int i = 0; i < count_test_block; ++i) { - int16_t input_block[256], input_extreme_block[256]; - int16_t output_block[256], output_extreme_block[256]; + DECLARE_ALIGNED_ARRAY(16, int16_t, input_block, 256); + DECLARE_ALIGNED_ARRAY(16, int16_t, input_extreme_block, 256); + DECLARE_ALIGNED_ARRAY(16, int16_t, output_block, 256); + DECLARE_ALIGNED_ARRAY(16, int16_t, output_extreme_block, 256); + DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, 256); // Initialize a test block with input range [-255, 255]. for (int j = 0; j < 256; ++j) { @@ -351,8 +377,8 @@ TEST(VP9Fdct16x16Test, CoeffSizeCheck) { input_extreme_block[j] = 255; const int pitch = 32; - vp9_short_fdct16x16_c(input_block, output_block, pitch); - vp9_short_fdct16x16_c(input_extreme_block, output_extreme_block, pitch); + RunFwdTxfm(input_block, output_block, dst, pitch, tx_type_); + RunFwdTxfm(input_extreme_block, output_extreme_block, dst, pitch, tx_type_); // The minimum quant value is 4. for (int j = 0; j < 256; ++j) { @@ -363,4 +389,37 @@ TEST(VP9Fdct16x16Test, CoeffSizeCheck) { } } } + +INSTANTIATE_TEST_CASE_P(VP9, FwdTrans16x16Test, ::testing::Range(0, 4)); + +TEST(VP9Idct16x16Test, AccuracyCheck) { + ACMRandom rnd(ACMRandom::DeterministicSeed()); + const int count_test_block = 1000; + for (int i = 0; i < count_test_block; ++i) { + int16_t in[256], coeff[256]; + uint8_t dst[256], src[256]; + double out_r[256]; + + for (int j = 0; j < 256; ++j) { + src[j] = rnd.Rand8(); + dst[j] = rnd.Rand8(); + } + // Initialize a test block with input range [-255, 255]. + for (int j = 0; j < 256; ++j) + in[j] = src[j] - dst[j]; + + reference_16x16_dct_2d(in, out_r); + for (int j = 0; j < 256; j++) + coeff[j] = round(out_r[j]); + vp9_short_idct16x16_add_c(coeff, dst, 16); + for (int j = 0; j < 256; ++j) { + const int diff = dst[j] - src[j]; + const int error = diff * diff; + EXPECT_GE(1, error) + << "Error: 16x16 IDCT has error " << error + << " at index " << j; + } + } +} + } // namespace -- 2.7.4