From ab362621fe4331486155e1ac7dbbb17a85108324 Mon Sep 17 00:00:00 2001 From: Jingning Han Date: Fri, 21 Jun 2013 11:45:47 -0700 Subject: [PATCH] Add 8x8 dct/adst unit tests This commit enables 8x8 DCT and hybrid transform unit tests. It also tunes the forward hybrid transform rounding opertions for more precise round-trip performance. Change-Id: If05c1ce59d75d641b9c6c91527d02d3a6ef498c3 --- test/fdct4x4_test.cc | 18 +++++------ test/fdct8x8_test.cc | 83 ++++++++++++++++++++++++++++++++++++++++----------- vp9/encoder/vp9_dct.c | 2 +- 3 files changed, 75 insertions(+), 28 deletions(-) diff --git a/test/fdct4x4_test.cc b/test/fdct4x4_test.cc index e246491..261fc1c 100644 --- a/test/fdct4x4_test.cc +++ b/test/fdct4x4_test.cc @@ -41,12 +41,12 @@ void iht4x4_add(int16_t *in, int16_t *out, uint8_t *dst, class FwdTrans4x4Test : public ::testing::TestWithParam { public: - FwdTrans4x4Test() {SetUpTestTxfm();} + FwdTrans4x4Test() { SetUpTestTxfm(); } ~FwdTrans4x4Test() {} void SetUpTestTxfm() { - tx_type = GetParam(); - if (tx_type == 0) { + tx_type_ = GetParam(); + if (tx_type_ == 0) { fwd_txfm = fdct4x4; inv_txfm = idct4x4_add; } else { @@ -66,7 +66,7 @@ class FwdTrans4x4Test : public ::testing::TestWithParam { (*inv_txfm)(in, out, dst, stride, tx_type); } - int tx_type; + int tx_type_; void (*fwd_txfm)(int16_t *in, int16_t *out, uint8_t *dst, int stride, int tx_type); void (*inv_txfm)(int16_t *in, int16_t *out, uint8_t *dst, @@ -87,7 +87,7 @@ TEST_P(FwdTrans4x4Test, SignBiasCheck) { for (int j = 0; j < 16; ++j) test_input_block[j] = rnd.Rand8() - rnd.Rand8(); - RunFwdTxfm(test_input_block, test_output_block, NULL, pitch, tx_type); + RunFwdTxfm(test_input_block, test_output_block, NULL, pitch, tx_type_); for (int j = 0; j < 16; ++j) { if (test_output_block[j] < 0) @@ -103,7 +103,7 @@ TEST_P(FwdTrans4x4Test, SignBiasCheck) { EXPECT_TRUE(bias_acceptable) << "Error: 4x4 FDCT/FHT has a sign bias > 1%" << " for input range [-255, 255] at index " << j - << " tx_type " << tx_type; + << " tx_type " << tx_type_; } memset(count_sign_block, 0, sizeof(count_sign_block)); @@ -112,7 +112,7 @@ TEST_P(FwdTrans4x4Test, SignBiasCheck) { for (int j = 0; j < 16; ++j) test_input_block[j] = (rnd.Rand8() >> 4) - (rnd.Rand8() >> 4); - RunFwdTxfm(test_input_block, test_output_block, NULL, pitch, tx_type); + RunFwdTxfm(test_input_block, test_output_block, NULL, pitch, tx_type_); for (int j = 0; j < 16; ++j) { if (test_output_block[j] < 0) @@ -151,7 +151,7 @@ TEST_P(FwdTrans4x4Test, RoundTripErrorCheck) { test_input_block[j] = src[j] - dst[j]; const int pitch = 8; - RunFwdTxfm(test_input_block, test_temp_block, dst, pitch, tx_type); + RunFwdTxfm(test_input_block, test_temp_block, dst, pitch, tx_type_); for (int j = 0; j < 16; ++j) { if(test_temp_block[j] > 0) { @@ -166,7 +166,7 @@ TEST_P(FwdTrans4x4Test, RoundTripErrorCheck) { } // inverse transform and reconstruct the pixel block - RunInvTxfm(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 < 16; ++j) { const int diff = dst[j] - src[j]; diff --git a/test/fdct8x8_test.cc b/test/fdct8x8_test.cc index 90b4ecd..8b9cff5 100644 --- a/test/fdct8x8_test.cc +++ b/test/fdct8x8_test.cc @@ -25,8 +25,53 @@ void vp9_short_idct8x8_add_c(short *input, uint8_t *output, int pitch); using libvpx_test::ACMRandom; namespace { +void fdct8x8(int16_t *in, int16_t *out, uint8_t *dst, int stride, int tx_type) { + vp9_short_fdct8x8_c(in, out, stride); +} +void idct8x8_add(int16_t *in, int16_t *out, uint8_t *dst, + int stride, int tx_type) { + vp9_short_idct8x8_add_c(out, dst, stride >> 1); +} +void fht8x8(int16_t *in, int16_t *out, uint8_t *dst, int stride, int tx_type) { + vp9_short_fht8x8_c(in, out, stride >> 1, tx_type); +} +void iht8x8_add(int16_t *in, int16_t *out, uint8_t *dst, + int stride, int tx_type) { + vp9_short_iht8x8_add_c(out, dst, stride >> 1, tx_type); +} + +class FwdTrans8x8Test : public ::testing::TestWithParam { + public: + FwdTrans8x8Test() { SetUpTestTxfm(); } + ~FwdTrans8x8Test() {} + + void SetUpTestTxfm() { + tx_type_ = GetParam(); + if (tx_type_ == 0) { + fwd_txfm = fdct8x8; + inv_txfm = idct8x8_add; + } else { + fwd_txfm = fht8x8; + inv_txfm = iht8x8_add; + } + } + + 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); +}; -TEST(VP9Fdct8x8Test, SignBiasCheck) { +TEST_P(FwdTrans8x8Test, SignBiasCheck) { ACMRandom rnd(ACMRandom::DeterministicSeed()); int16_t test_input_block[64]; int16_t test_output_block[64]; @@ -41,7 +86,7 @@ TEST(VP9Fdct8x8Test, SignBiasCheck) { for (int j = 0; j < 64; ++j) test_input_block[j] = rnd.Rand8() - rnd.Rand8(); - vp9_short_fdct8x8_c(test_input_block, test_output_block, pitch); + RunFwdTxfm(test_input_block, test_output_block, NULL, pitch, tx_type_); for (int j = 0; j < 64; ++j) { if (test_output_block[j] < 0) @@ -55,7 +100,7 @@ TEST(VP9Fdct8x8Test, SignBiasCheck) { const int diff = abs(count_sign_block[j][0] - count_sign_block[j][1]); const int max_diff = 1125; EXPECT_LT(diff, max_diff) - << "Error: 8x8 FDCT has a sign bias > " + << "Error: 8x8 FDCT/FHT has a sign bias > " << 1. * max_diff / count_test_block * 100 << "%" << " for input range [-255, 255] at index " << j << " count0: " << count_sign_block[j][0] @@ -70,7 +115,7 @@ TEST(VP9Fdct8x8Test, SignBiasCheck) { for (int j = 0; j < 64; ++j) test_input_block[j] = (rnd.Rand8() >> 4) - (rnd.Rand8() >> 4); - vp9_short_fdct8x8_c(test_input_block, test_output_block, pitch); + RunFwdTxfm(test_input_block, test_output_block, NULL, pitch, tx_type_); for (int j = 0; j < 64; ++j) { if (test_output_block[j] < 0) @@ -84,16 +129,16 @@ TEST(VP9Fdct8x8Test, SignBiasCheck) { const int diff = abs(count_sign_block[j][0] - count_sign_block[j][1]); const int max_diff = 10000; EXPECT_LT(diff, max_diff) - << "Error: 4x4 FDCT has a sign bias > " + << "Error: 4x4 FDCT/FHT has a sign bias > " << 1. * max_diff / count_test_block * 100 << "%" << " for input range [-15, 15] at index " << j << " count0: " << count_sign_block[j][0] << " count1: " << count_sign_block[j][1] << " diff: " << diff; } -}; +} -TEST(VP9Fdct8x8Test, RoundTripErrorCheck) { +TEST_P(FwdTrans8x8Test, RoundTripErrorCheck) { ACMRandom rnd(ACMRandom::DeterministicSeed()); int max_error = 0; double total_error = 0; @@ -112,7 +157,7 @@ TEST(VP9Fdct8x8Test, RoundTripErrorCheck) { test_input_block[j] = src[j] - dst[j]; const int pitch = 16; - vp9_short_fdct8x8_c(test_input_block, test_temp_block, pitch); + RunFwdTxfm(test_input_block, test_temp_block, dst, pitch, tx_type_); for (int j = 0; j < 64; ++j){ if(test_temp_block[j] > 0) { test_temp_block[j] += 2; @@ -124,7 +169,7 @@ TEST(VP9Fdct8x8Test, RoundTripErrorCheck) { test_temp_block[j] *= 4; } } - vp9_short_idct8x8_add_c(test_temp_block, dst, 8); + RunInvTxfm(test_input_block, test_temp_block, dst, pitch, tx_type_); for (int j = 0; j < 64; ++j) { const int diff = dst[j] - src[j]; @@ -136,13 +181,14 @@ TEST(VP9Fdct8x8Test, RoundTripErrorCheck) { } EXPECT_GE(1, max_error) - << "Error: 8x8 FDCT/IDCT has an individual roundtrip error > 1"; + << "Error: 8x8 FDCT/IDCT or FHT/IHT has an individual roundtrip error > 1"; EXPECT_GE(count_test_block/5, total_error) - << "Error: 8x8 FDCT/IDCT has average roundtrip error > 1/5 per block"; -}; + << "Error: 8x8 FDCT/IDCT or FHT/IHT has average roundtrip " + "error > 1/5 per block"; +} -TEST(VP9Fdct8x8Test, ExtremalCheck) { +TEST_P(FwdTrans8x8Test, ExtremalCheck) { ACMRandom rnd(ACMRandom::DeterministicSeed()); int max_error = 0; double total_error = 0; @@ -161,8 +207,8 @@ TEST(VP9Fdct8x8Test, ExtremalCheck) { test_input_block[j] = src[j] - dst[j]; const int pitch = 16; - vp9_short_fdct8x8_c(test_input_block, test_temp_block, pitch); - vp9_short_idct8x8_add_c(test_temp_block, dst, 8); + 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 < 64; ++j) { const int diff = dst[j] - src[j]; @@ -173,13 +219,14 @@ TEST(VP9Fdct8x8Test, ExtremalCheck) { } EXPECT_GE(1, max_error) - << "Error: Extremal 8x8 FDCT/IDCT has an" + << "Error: Extremal 8x8 FDCT/IDCT or FHT/IHT has an" << " individual roundtrip error > 1"; EXPECT_GE(count_test_block/5, total_error) - << "Error: Extremal 8x8 FDCT/IDCT has average" + << "Error: Extremal 8x8 FDCT/IDCT or FHT/IHT has average" << " roundtrip error > 1/5 per block"; } -}; +} +INSTANTIATE_TEST_CASE_P(VP9, FwdTrans8x8Test, ::testing::Range(0, 4)); } // namespace diff --git a/vp9/encoder/vp9_dct.c b/vp9/encoder/vp9_dct.c index a90bcf5..8be893e 100644 --- a/vp9/encoder/vp9_dct.c +++ b/vp9/encoder/vp9_dct.c @@ -587,7 +587,7 @@ void vp9_short_fht8x8_c(int16_t *input, int16_t *output, temp_in[j] = out[j + i * 8]; ht.rows(temp_in, temp_out); for (j = 0; j < 8; ++j) - output[j + i * 8] = temp_out[j] >> 1; + output[j + i * 8] = (temp_out[j] + (temp_out[j] < 0)) >> 1; } } -- 2.7.4