1*77c1e3ccSAndroid Build Coastguard Worker /* 2*77c1e3ccSAndroid Build Coastguard Worker * Copyright (c) 2016, Alliance for Open Media. All rights reserved. 3*77c1e3ccSAndroid Build Coastguard Worker * 4*77c1e3ccSAndroid Build Coastguard Worker * This source code is subject to the terms of the BSD 2 Clause License and 5*77c1e3ccSAndroid Build Coastguard Worker * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License 6*77c1e3ccSAndroid Build Coastguard Worker * was not distributed with this source code in the LICENSE file, you can 7*77c1e3ccSAndroid Build Coastguard Worker * obtain it at www.aomedia.org/license/software. If the Alliance for Open 8*77c1e3ccSAndroid Build Coastguard Worker * Media Patent License 1.0 was not distributed with this source code in the 9*77c1e3ccSAndroid Build Coastguard Worker * PATENTS file, you can obtain it at www.aomedia.org/license/patent. 10*77c1e3ccSAndroid Build Coastguard Worker */ 11*77c1e3ccSAndroid Build Coastguard Worker 12*77c1e3ccSAndroid Build Coastguard Worker #ifndef AOM_TEST_TRANSFORM_TEST_BASE_H_ 13*77c1e3ccSAndroid Build Coastguard Worker #define AOM_TEST_TRANSFORM_TEST_BASE_H_ 14*77c1e3ccSAndroid Build Coastguard Worker 15*77c1e3ccSAndroid Build Coastguard Worker #include "gtest/gtest.h" 16*77c1e3ccSAndroid Build Coastguard Worker 17*77c1e3ccSAndroid Build Coastguard Worker #include "aom/aom_codec.h" 18*77c1e3ccSAndroid Build Coastguard Worker #include "aom_dsp/txfm_common.h" 19*77c1e3ccSAndroid Build Coastguard Worker #include "aom_mem/aom_mem.h" 20*77c1e3ccSAndroid Build Coastguard Worker #include "test/acm_random.h" 21*77c1e3ccSAndroid Build Coastguard Worker 22*77c1e3ccSAndroid Build Coastguard Worker namespace libaom_test { 23*77c1e3ccSAndroid Build Coastguard Worker 24*77c1e3ccSAndroid Build Coastguard Worker // Note: 25*77c1e3ccSAndroid Build Coastguard Worker // Same constant are defined in av1/common/av1_entropy.h and 26*77c1e3ccSAndroid Build Coastguard Worker // av1/common/entropy.h. Goal is to make this base class 27*77c1e3ccSAndroid Build Coastguard Worker // to use for future codec transform testing. But including 28*77c1e3ccSAndroid Build Coastguard Worker // either of them would lead to compiling error when we do 29*77c1e3ccSAndroid Build Coastguard Worker // unit test for another codec. Suggest to move the definition 30*77c1e3ccSAndroid Build Coastguard Worker // to a aom header file. 31*77c1e3ccSAndroid Build Coastguard Worker const int kDctMaxValue = 16384; 32*77c1e3ccSAndroid Build Coastguard Worker 33*77c1e3ccSAndroid Build Coastguard Worker template <typename OutputType> 34*77c1e3ccSAndroid Build Coastguard Worker using FhtFunc = void (*)(const int16_t *in, OutputType *out, int stride, 35*77c1e3ccSAndroid Build Coastguard Worker TxfmParam *txfm_param); 36*77c1e3ccSAndroid Build Coastguard Worker 37*77c1e3ccSAndroid Build Coastguard Worker template <typename OutputType> 38*77c1e3ccSAndroid Build Coastguard Worker using IhtFunc = void (*)(const tran_low_t *in, uint8_t *out, int stride, 39*77c1e3ccSAndroid Build Coastguard Worker const TxfmParam *txfm_param); 40*77c1e3ccSAndroid Build Coastguard Worker 41*77c1e3ccSAndroid Build Coastguard Worker template <typename OutType> 42*77c1e3ccSAndroid Build Coastguard Worker class TransformTestBase { 43*77c1e3ccSAndroid Build Coastguard Worker public: 44*77c1e3ccSAndroid Build Coastguard Worker virtual ~TransformTestBase() = default; 45*77c1e3ccSAndroid Build Coastguard Worker 46*77c1e3ccSAndroid Build Coastguard Worker protected: 47*77c1e3ccSAndroid Build Coastguard Worker virtual void RunFwdTxfm(const int16_t *in, OutType *out, int stride) = 0; 48*77c1e3ccSAndroid Build Coastguard Worker 49*77c1e3ccSAndroid Build Coastguard Worker virtual void RunInvTxfm(const OutType *out, uint8_t *dst, int stride) = 0; 50*77c1e3ccSAndroid Build Coastguard Worker RunAccuracyCheck(uint32_t ref_max_error,double ref_avg_error)51*77c1e3ccSAndroid Build Coastguard Worker void RunAccuracyCheck(uint32_t ref_max_error, double ref_avg_error) { 52*77c1e3ccSAndroid Build Coastguard Worker ACMRandom rnd(ACMRandom::DeterministicSeed()); 53*77c1e3ccSAndroid Build Coastguard Worker uint32_t max_error = 0; 54*77c1e3ccSAndroid Build Coastguard Worker int64_t total_error = 0; 55*77c1e3ccSAndroid Build Coastguard Worker const int count_test_block = 10000; 56*77c1e3ccSAndroid Build Coastguard Worker 57*77c1e3ccSAndroid Build Coastguard Worker int16_t *test_input_block = reinterpret_cast<int16_t *>( 58*77c1e3ccSAndroid Build Coastguard Worker aom_memalign(16, sizeof(int16_t) * num_coeffs_)); 59*77c1e3ccSAndroid Build Coastguard Worker ASSERT_NE(test_input_block, nullptr); 60*77c1e3ccSAndroid Build Coastguard Worker OutType *test_temp_block = reinterpret_cast<OutType *>( 61*77c1e3ccSAndroid Build Coastguard Worker aom_memalign(16, sizeof(test_temp_block[0]) * num_coeffs_)); 62*77c1e3ccSAndroid Build Coastguard Worker ASSERT_NE(test_temp_block, nullptr); 63*77c1e3ccSAndroid Build Coastguard Worker uint8_t *dst = reinterpret_cast<uint8_t *>( 64*77c1e3ccSAndroid Build Coastguard Worker aom_memalign(16, sizeof(uint8_t) * num_coeffs_)); 65*77c1e3ccSAndroid Build Coastguard Worker ASSERT_NE(dst, nullptr); 66*77c1e3ccSAndroid Build Coastguard Worker uint8_t *src = reinterpret_cast<uint8_t *>( 67*77c1e3ccSAndroid Build Coastguard Worker aom_memalign(16, sizeof(uint8_t) * num_coeffs_)); 68*77c1e3ccSAndroid Build Coastguard Worker ASSERT_NE(src, nullptr); 69*77c1e3ccSAndroid Build Coastguard Worker uint16_t *dst16 = reinterpret_cast<uint16_t *>( 70*77c1e3ccSAndroid Build Coastguard Worker aom_memalign(16, sizeof(uint16_t) * num_coeffs_)); 71*77c1e3ccSAndroid Build Coastguard Worker ASSERT_NE(dst16, nullptr); 72*77c1e3ccSAndroid Build Coastguard Worker uint16_t *src16 = reinterpret_cast<uint16_t *>( 73*77c1e3ccSAndroid Build Coastguard Worker aom_memalign(16, sizeof(uint16_t) * num_coeffs_)); 74*77c1e3ccSAndroid Build Coastguard Worker ASSERT_NE(src16, nullptr); 75*77c1e3ccSAndroid Build Coastguard Worker 76*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < count_test_block; ++i) { 77*77c1e3ccSAndroid Build Coastguard Worker // Initialize a test block with input range [-255, 255]. 78*77c1e3ccSAndroid Build Coastguard Worker for (int j = 0; j < num_coeffs_; ++j) { 79*77c1e3ccSAndroid Build Coastguard Worker if (bit_depth_ == AOM_BITS_8) { 80*77c1e3ccSAndroid Build Coastguard Worker src[j] = rnd.Rand8(); 81*77c1e3ccSAndroid Build Coastguard Worker dst[j] = rnd.Rand8(); 82*77c1e3ccSAndroid Build Coastguard Worker test_input_block[j] = src[j] - dst[j]; 83*77c1e3ccSAndroid Build Coastguard Worker } else { 84*77c1e3ccSAndroid Build Coastguard Worker src16[j] = rnd.Rand16() & mask_; 85*77c1e3ccSAndroid Build Coastguard Worker dst16[j] = rnd.Rand16() & mask_; 86*77c1e3ccSAndroid Build Coastguard Worker test_input_block[j] = src16[j] - dst16[j]; 87*77c1e3ccSAndroid Build Coastguard Worker } 88*77c1e3ccSAndroid Build Coastguard Worker } 89*77c1e3ccSAndroid Build Coastguard Worker 90*77c1e3ccSAndroid Build Coastguard Worker API_REGISTER_STATE_CHECK( 91*77c1e3ccSAndroid Build Coastguard Worker RunFwdTxfm(test_input_block, test_temp_block, pitch_)); 92*77c1e3ccSAndroid Build Coastguard Worker if (bit_depth_ == AOM_BITS_8) { 93*77c1e3ccSAndroid Build Coastguard Worker API_REGISTER_STATE_CHECK(RunInvTxfm(test_temp_block, dst, pitch_)); 94*77c1e3ccSAndroid Build Coastguard Worker } else { 95*77c1e3ccSAndroid Build Coastguard Worker API_REGISTER_STATE_CHECK( 96*77c1e3ccSAndroid Build Coastguard Worker RunInvTxfm(test_temp_block, CONVERT_TO_BYTEPTR(dst16), pitch_)); 97*77c1e3ccSAndroid Build Coastguard Worker } 98*77c1e3ccSAndroid Build Coastguard Worker 99*77c1e3ccSAndroid Build Coastguard Worker for (int j = 0; j < num_coeffs_; ++j) { 100*77c1e3ccSAndroid Build Coastguard Worker const int diff = 101*77c1e3ccSAndroid Build Coastguard Worker bit_depth_ == AOM_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j]; 102*77c1e3ccSAndroid Build Coastguard Worker const uint32_t error = diff * diff; 103*77c1e3ccSAndroid Build Coastguard Worker if (max_error < error) max_error = error; 104*77c1e3ccSAndroid Build Coastguard Worker total_error += error; 105*77c1e3ccSAndroid Build Coastguard Worker } 106*77c1e3ccSAndroid Build Coastguard Worker } 107*77c1e3ccSAndroid Build Coastguard Worker 108*77c1e3ccSAndroid Build Coastguard Worker double avg_error = total_error * 1. / count_test_block / num_coeffs_; 109*77c1e3ccSAndroid Build Coastguard Worker 110*77c1e3ccSAndroid Build Coastguard Worker EXPECT_GE(ref_max_error, max_error) 111*77c1e3ccSAndroid Build Coastguard Worker << "Error: FHT/IHT has an individual round trip error > " 112*77c1e3ccSAndroid Build Coastguard Worker << ref_max_error; 113*77c1e3ccSAndroid Build Coastguard Worker 114*77c1e3ccSAndroid Build Coastguard Worker EXPECT_GE(ref_avg_error, avg_error) 115*77c1e3ccSAndroid Build Coastguard Worker << "Error: FHT/IHT has average round trip error > " << ref_avg_error 116*77c1e3ccSAndroid Build Coastguard Worker << " per block"; 117*77c1e3ccSAndroid Build Coastguard Worker 118*77c1e3ccSAndroid Build Coastguard Worker aom_free(test_input_block); 119*77c1e3ccSAndroid Build Coastguard Worker aom_free(test_temp_block); 120*77c1e3ccSAndroid Build Coastguard Worker aom_free(dst); 121*77c1e3ccSAndroid Build Coastguard Worker aom_free(src); 122*77c1e3ccSAndroid Build Coastguard Worker aom_free(dst16); 123*77c1e3ccSAndroid Build Coastguard Worker aom_free(src16); 124*77c1e3ccSAndroid Build Coastguard Worker } 125*77c1e3ccSAndroid Build Coastguard Worker RunCoeffCheck()126*77c1e3ccSAndroid Build Coastguard Worker void RunCoeffCheck() { 127*77c1e3ccSAndroid Build Coastguard Worker ACMRandom rnd(ACMRandom::DeterministicSeed()); 128*77c1e3ccSAndroid Build Coastguard Worker const int count_test_block = 5000; 129*77c1e3ccSAndroid Build Coastguard Worker 130*77c1e3ccSAndroid Build Coastguard Worker // Use a stride value which is not the width of any transform, to catch 131*77c1e3ccSAndroid Build Coastguard Worker // cases where the transforms use the stride incorrectly. 132*77c1e3ccSAndroid Build Coastguard Worker int stride = 96; 133*77c1e3ccSAndroid Build Coastguard Worker 134*77c1e3ccSAndroid Build Coastguard Worker int16_t *input_block = reinterpret_cast<int16_t *>( 135*77c1e3ccSAndroid Build Coastguard Worker aom_memalign(16, sizeof(int16_t) * stride * height_)); 136*77c1e3ccSAndroid Build Coastguard Worker ASSERT_NE(input_block, nullptr); 137*77c1e3ccSAndroid Build Coastguard Worker OutType *output_ref_block = reinterpret_cast<OutType *>( 138*77c1e3ccSAndroid Build Coastguard Worker aom_memalign(16, sizeof(output_ref_block[0]) * num_coeffs_)); 139*77c1e3ccSAndroid Build Coastguard Worker ASSERT_NE(output_ref_block, nullptr); 140*77c1e3ccSAndroid Build Coastguard Worker OutType *output_block = reinterpret_cast<OutType *>( 141*77c1e3ccSAndroid Build Coastguard Worker aom_memalign(16, sizeof(output_block[0]) * num_coeffs_)); 142*77c1e3ccSAndroid Build Coastguard Worker ASSERT_NE(output_block, nullptr); 143*77c1e3ccSAndroid Build Coastguard Worker 144*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < count_test_block; ++i) { 145*77c1e3ccSAndroid Build Coastguard Worker int j, k; 146*77c1e3ccSAndroid Build Coastguard Worker for (j = 0; j < height_; ++j) { 147*77c1e3ccSAndroid Build Coastguard Worker for (k = 0; k < pitch_; ++k) { 148*77c1e3ccSAndroid Build Coastguard Worker int in_idx = j * stride + k; 149*77c1e3ccSAndroid Build Coastguard Worker int out_idx = j * pitch_ + k; 150*77c1e3ccSAndroid Build Coastguard Worker input_block[in_idx] = (rnd.Rand16() & mask_) - (rnd.Rand16() & mask_); 151*77c1e3ccSAndroid Build Coastguard Worker if (bit_depth_ == AOM_BITS_8) { 152*77c1e3ccSAndroid Build Coastguard Worker output_block[out_idx] = output_ref_block[out_idx] = rnd.Rand8(); 153*77c1e3ccSAndroid Build Coastguard Worker } else { 154*77c1e3ccSAndroid Build Coastguard Worker output_block[out_idx] = output_ref_block[out_idx] = 155*77c1e3ccSAndroid Build Coastguard Worker rnd.Rand16() & mask_; 156*77c1e3ccSAndroid Build Coastguard Worker } 157*77c1e3ccSAndroid Build Coastguard Worker } 158*77c1e3ccSAndroid Build Coastguard Worker } 159*77c1e3ccSAndroid Build Coastguard Worker 160*77c1e3ccSAndroid Build Coastguard Worker fwd_txfm_ref(input_block, output_ref_block, stride, &txfm_param_); 161*77c1e3ccSAndroid Build Coastguard Worker API_REGISTER_STATE_CHECK(RunFwdTxfm(input_block, output_block, stride)); 162*77c1e3ccSAndroid Build Coastguard Worker 163*77c1e3ccSAndroid Build Coastguard Worker // The minimum quant value is 4. 164*77c1e3ccSAndroid Build Coastguard Worker for (j = 0; j < height_; ++j) { 165*77c1e3ccSAndroid Build Coastguard Worker for (k = 0; k < pitch_; ++k) { 166*77c1e3ccSAndroid Build Coastguard Worker int out_idx = j * pitch_ + k; 167*77c1e3ccSAndroid Build Coastguard Worker ASSERT_EQ(output_block[out_idx], output_ref_block[out_idx]) 168*77c1e3ccSAndroid Build Coastguard Worker << "Error: not bit-exact result at index: " << out_idx 169*77c1e3ccSAndroid Build Coastguard Worker << " at test block: " << i; 170*77c1e3ccSAndroid Build Coastguard Worker } 171*77c1e3ccSAndroid Build Coastguard Worker } 172*77c1e3ccSAndroid Build Coastguard Worker } 173*77c1e3ccSAndroid Build Coastguard Worker aom_free(input_block); 174*77c1e3ccSAndroid Build Coastguard Worker aom_free(output_ref_block); 175*77c1e3ccSAndroid Build Coastguard Worker aom_free(output_block); 176*77c1e3ccSAndroid Build Coastguard Worker } 177*77c1e3ccSAndroid Build Coastguard Worker RunInvCoeffCheck()178*77c1e3ccSAndroid Build Coastguard Worker void RunInvCoeffCheck() { 179*77c1e3ccSAndroid Build Coastguard Worker ACMRandom rnd(ACMRandom::DeterministicSeed()); 180*77c1e3ccSAndroid Build Coastguard Worker const int count_test_block = 5000; 181*77c1e3ccSAndroid Build Coastguard Worker 182*77c1e3ccSAndroid Build Coastguard Worker // Use a stride value which is not the width of any transform, to catch 183*77c1e3ccSAndroid Build Coastguard Worker // cases where the transforms use the stride incorrectly. 184*77c1e3ccSAndroid Build Coastguard Worker int stride = 96; 185*77c1e3ccSAndroid Build Coastguard Worker 186*77c1e3ccSAndroid Build Coastguard Worker int16_t *input_block = reinterpret_cast<int16_t *>( 187*77c1e3ccSAndroid Build Coastguard Worker aom_memalign(16, sizeof(int16_t) * num_coeffs_)); 188*77c1e3ccSAndroid Build Coastguard Worker ASSERT_NE(input_block, nullptr); 189*77c1e3ccSAndroid Build Coastguard Worker OutType *trans_block = reinterpret_cast<OutType *>( 190*77c1e3ccSAndroid Build Coastguard Worker aom_memalign(16, sizeof(trans_block[0]) * num_coeffs_)); 191*77c1e3ccSAndroid Build Coastguard Worker ASSERT_NE(trans_block, nullptr); 192*77c1e3ccSAndroid Build Coastguard Worker uint8_t *output_block = reinterpret_cast<uint8_t *>( 193*77c1e3ccSAndroid Build Coastguard Worker aom_memalign(16, sizeof(uint8_t) * stride * height_)); 194*77c1e3ccSAndroid Build Coastguard Worker ASSERT_NE(output_block, nullptr); 195*77c1e3ccSAndroid Build Coastguard Worker uint8_t *output_ref_block = reinterpret_cast<uint8_t *>( 196*77c1e3ccSAndroid Build Coastguard Worker aom_memalign(16, sizeof(uint8_t) * stride * height_)); 197*77c1e3ccSAndroid Build Coastguard Worker ASSERT_NE(output_ref_block, nullptr); 198*77c1e3ccSAndroid Build Coastguard Worker 199*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < count_test_block; ++i) { 200*77c1e3ccSAndroid Build Coastguard Worker // Initialize a test block with input range [-mask_, mask_]. 201*77c1e3ccSAndroid Build Coastguard Worker int j, k; 202*77c1e3ccSAndroid Build Coastguard Worker for (j = 0; j < height_; ++j) { 203*77c1e3ccSAndroid Build Coastguard Worker for (k = 0; k < pitch_; ++k) { 204*77c1e3ccSAndroid Build Coastguard Worker int in_idx = j * pitch_ + k; 205*77c1e3ccSAndroid Build Coastguard Worker int out_idx = j * stride + k; 206*77c1e3ccSAndroid Build Coastguard Worker input_block[in_idx] = (rnd.Rand16() & mask_) - (rnd.Rand16() & mask_); 207*77c1e3ccSAndroid Build Coastguard Worker output_ref_block[out_idx] = rnd.Rand16() & mask_; 208*77c1e3ccSAndroid Build Coastguard Worker output_block[out_idx] = output_ref_block[out_idx]; 209*77c1e3ccSAndroid Build Coastguard Worker } 210*77c1e3ccSAndroid Build Coastguard Worker } 211*77c1e3ccSAndroid Build Coastguard Worker 212*77c1e3ccSAndroid Build Coastguard Worker fwd_txfm_ref(input_block, trans_block, pitch_, &txfm_param_); 213*77c1e3ccSAndroid Build Coastguard Worker 214*77c1e3ccSAndroid Build Coastguard Worker inv_txfm_ref(trans_block, output_ref_block, stride, &txfm_param_); 215*77c1e3ccSAndroid Build Coastguard Worker API_REGISTER_STATE_CHECK(RunInvTxfm(trans_block, output_block, stride)); 216*77c1e3ccSAndroid Build Coastguard Worker 217*77c1e3ccSAndroid Build Coastguard Worker for (j = 0; j < height_; ++j) { 218*77c1e3ccSAndroid Build Coastguard Worker for (k = 0; k < pitch_; ++k) { 219*77c1e3ccSAndroid Build Coastguard Worker int out_idx = j * stride + k; 220*77c1e3ccSAndroid Build Coastguard Worker ASSERT_EQ(output_block[out_idx], output_ref_block[out_idx]) 221*77c1e3ccSAndroid Build Coastguard Worker << "Error: not bit-exact result at index: " << out_idx 222*77c1e3ccSAndroid Build Coastguard Worker << " j = " << j << " k = " << k << " at test block: " << i; 223*77c1e3ccSAndroid Build Coastguard Worker } 224*77c1e3ccSAndroid Build Coastguard Worker } 225*77c1e3ccSAndroid Build Coastguard Worker } 226*77c1e3ccSAndroid Build Coastguard Worker aom_free(input_block); 227*77c1e3ccSAndroid Build Coastguard Worker aom_free(trans_block); 228*77c1e3ccSAndroid Build Coastguard Worker aom_free(output_ref_block); 229*77c1e3ccSAndroid Build Coastguard Worker aom_free(output_block); 230*77c1e3ccSAndroid Build Coastguard Worker } 231*77c1e3ccSAndroid Build Coastguard Worker RunMemCheck()232*77c1e3ccSAndroid Build Coastguard Worker void RunMemCheck() { 233*77c1e3ccSAndroid Build Coastguard Worker ACMRandom rnd(ACMRandom::DeterministicSeed()); 234*77c1e3ccSAndroid Build Coastguard Worker const int count_test_block = 5000; 235*77c1e3ccSAndroid Build Coastguard Worker 236*77c1e3ccSAndroid Build Coastguard Worker int16_t *input_extreme_block = reinterpret_cast<int16_t *>( 237*77c1e3ccSAndroid Build Coastguard Worker aom_memalign(16, sizeof(int16_t) * num_coeffs_)); 238*77c1e3ccSAndroid Build Coastguard Worker ASSERT_NE(input_extreme_block, nullptr); 239*77c1e3ccSAndroid Build Coastguard Worker OutType *output_ref_block = reinterpret_cast<OutType *>( 240*77c1e3ccSAndroid Build Coastguard Worker aom_memalign(16, sizeof(output_ref_block[0]) * num_coeffs_)); 241*77c1e3ccSAndroid Build Coastguard Worker ASSERT_NE(output_ref_block, nullptr); 242*77c1e3ccSAndroid Build Coastguard Worker OutType *output_block = reinterpret_cast<OutType *>( 243*77c1e3ccSAndroid Build Coastguard Worker aom_memalign(16, sizeof(output_block[0]) * num_coeffs_)); 244*77c1e3ccSAndroid Build Coastguard Worker ASSERT_NE(output_block, nullptr); 245*77c1e3ccSAndroid Build Coastguard Worker 246*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < count_test_block; ++i) { 247*77c1e3ccSAndroid Build Coastguard Worker // Initialize a test block with input range [-mask_, mask_]. 248*77c1e3ccSAndroid Build Coastguard Worker for (int j = 0; j < num_coeffs_; ++j) { 249*77c1e3ccSAndroid Build Coastguard Worker input_extreme_block[j] = rnd.Rand8() % 2 ? mask_ : -mask_; 250*77c1e3ccSAndroid Build Coastguard Worker } 251*77c1e3ccSAndroid Build Coastguard Worker if (i == 0) { 252*77c1e3ccSAndroid Build Coastguard Worker for (int j = 0; j < num_coeffs_; ++j) input_extreme_block[j] = mask_; 253*77c1e3ccSAndroid Build Coastguard Worker } else if (i == 1) { 254*77c1e3ccSAndroid Build Coastguard Worker for (int j = 0; j < num_coeffs_; ++j) input_extreme_block[j] = -mask_; 255*77c1e3ccSAndroid Build Coastguard Worker } 256*77c1e3ccSAndroid Build Coastguard Worker 257*77c1e3ccSAndroid Build Coastguard Worker fwd_txfm_ref(input_extreme_block, output_ref_block, pitch_, &txfm_param_); 258*77c1e3ccSAndroid Build Coastguard Worker API_REGISTER_STATE_CHECK( 259*77c1e3ccSAndroid Build Coastguard Worker RunFwdTxfm(input_extreme_block, output_block, pitch_)); 260*77c1e3ccSAndroid Build Coastguard Worker 261*77c1e3ccSAndroid Build Coastguard Worker int row_length = FindRowLength(); 262*77c1e3ccSAndroid Build Coastguard Worker // The minimum quant value is 4. 263*77c1e3ccSAndroid Build Coastguard Worker for (int j = 0; j < num_coeffs_; ++j) { 264*77c1e3ccSAndroid Build Coastguard Worker ASSERT_EQ(output_block[j], output_ref_block[j]) 265*77c1e3ccSAndroid Build Coastguard Worker << "Not bit-exact at test index: " << i << ", " 266*77c1e3ccSAndroid Build Coastguard Worker << "j = " << j << std::endl; 267*77c1e3ccSAndroid Build Coastguard Worker EXPECT_GE(row_length * kDctMaxValue << (bit_depth_ - 8), 268*77c1e3ccSAndroid Build Coastguard Worker abs(output_block[j])) 269*77c1e3ccSAndroid Build Coastguard Worker << "Error: NxN FDCT has coefficient larger than N*DCT_MAX_VALUE"; 270*77c1e3ccSAndroid Build Coastguard Worker } 271*77c1e3ccSAndroid Build Coastguard Worker } 272*77c1e3ccSAndroid Build Coastguard Worker aom_free(input_extreme_block); 273*77c1e3ccSAndroid Build Coastguard Worker aom_free(output_ref_block); 274*77c1e3ccSAndroid Build Coastguard Worker aom_free(output_block); 275*77c1e3ccSAndroid Build Coastguard Worker } 276*77c1e3ccSAndroid Build Coastguard Worker RunInvAccuracyCheck(int limit)277*77c1e3ccSAndroid Build Coastguard Worker void RunInvAccuracyCheck(int limit) { 278*77c1e3ccSAndroid Build Coastguard Worker ACMRandom rnd(ACMRandom::DeterministicSeed()); 279*77c1e3ccSAndroid Build Coastguard Worker const int count_test_block = 1000; 280*77c1e3ccSAndroid Build Coastguard Worker 281*77c1e3ccSAndroid Build Coastguard Worker int16_t *in = reinterpret_cast<int16_t *>( 282*77c1e3ccSAndroid Build Coastguard Worker aom_memalign(16, sizeof(int16_t) * num_coeffs_)); 283*77c1e3ccSAndroid Build Coastguard Worker ASSERT_NE(in, nullptr); 284*77c1e3ccSAndroid Build Coastguard Worker OutType *coeff = reinterpret_cast<OutType *>( 285*77c1e3ccSAndroid Build Coastguard Worker aom_memalign(16, sizeof(coeff[0]) * num_coeffs_)); 286*77c1e3ccSAndroid Build Coastguard Worker ASSERT_NE(coeff, nullptr); 287*77c1e3ccSAndroid Build Coastguard Worker uint8_t *dst = reinterpret_cast<uint8_t *>( 288*77c1e3ccSAndroid Build Coastguard Worker aom_memalign(16, sizeof(uint8_t) * num_coeffs_)); 289*77c1e3ccSAndroid Build Coastguard Worker ASSERT_NE(dst, nullptr); 290*77c1e3ccSAndroid Build Coastguard Worker uint8_t *src = reinterpret_cast<uint8_t *>( 291*77c1e3ccSAndroid Build Coastguard Worker aom_memalign(16, sizeof(uint8_t) * num_coeffs_)); 292*77c1e3ccSAndroid Build Coastguard Worker ASSERT_NE(src, nullptr); 293*77c1e3ccSAndroid Build Coastguard Worker 294*77c1e3ccSAndroid Build Coastguard Worker uint16_t *dst16 = reinterpret_cast<uint16_t *>( 295*77c1e3ccSAndroid Build Coastguard Worker aom_memalign(16, sizeof(uint16_t) * num_coeffs_)); 296*77c1e3ccSAndroid Build Coastguard Worker ASSERT_NE(dst16, nullptr); 297*77c1e3ccSAndroid Build Coastguard Worker uint16_t *src16 = reinterpret_cast<uint16_t *>( 298*77c1e3ccSAndroid Build Coastguard Worker aom_memalign(16, sizeof(uint16_t) * num_coeffs_)); 299*77c1e3ccSAndroid Build Coastguard Worker ASSERT_NE(src16, nullptr); 300*77c1e3ccSAndroid Build Coastguard Worker 301*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < count_test_block; ++i) { 302*77c1e3ccSAndroid Build Coastguard Worker // Initialize a test block with input range [-mask_, mask_]. 303*77c1e3ccSAndroid Build Coastguard Worker for (int j = 0; j < num_coeffs_; ++j) { 304*77c1e3ccSAndroid Build Coastguard Worker if (bit_depth_ == AOM_BITS_8) { 305*77c1e3ccSAndroid Build Coastguard Worker src[j] = rnd.Rand8(); 306*77c1e3ccSAndroid Build Coastguard Worker dst[j] = rnd.Rand8(); 307*77c1e3ccSAndroid Build Coastguard Worker in[j] = src[j] - dst[j]; 308*77c1e3ccSAndroid Build Coastguard Worker } else { 309*77c1e3ccSAndroid Build Coastguard Worker src16[j] = rnd.Rand16() & mask_; 310*77c1e3ccSAndroid Build Coastguard Worker dst16[j] = rnd.Rand16() & mask_; 311*77c1e3ccSAndroid Build Coastguard Worker in[j] = src16[j] - dst16[j]; 312*77c1e3ccSAndroid Build Coastguard Worker } 313*77c1e3ccSAndroid Build Coastguard Worker } 314*77c1e3ccSAndroid Build Coastguard Worker 315*77c1e3ccSAndroid Build Coastguard Worker fwd_txfm_ref(in, coeff, pitch_, &txfm_param_); 316*77c1e3ccSAndroid Build Coastguard Worker 317*77c1e3ccSAndroid Build Coastguard Worker if (bit_depth_ == AOM_BITS_8) { 318*77c1e3ccSAndroid Build Coastguard Worker API_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, pitch_)); 319*77c1e3ccSAndroid Build Coastguard Worker } else { 320*77c1e3ccSAndroid Build Coastguard Worker API_REGISTER_STATE_CHECK( 321*77c1e3ccSAndroid Build Coastguard Worker RunInvTxfm(coeff, CONVERT_TO_BYTEPTR(dst16), pitch_)); 322*77c1e3ccSAndroid Build Coastguard Worker } 323*77c1e3ccSAndroid Build Coastguard Worker 324*77c1e3ccSAndroid Build Coastguard Worker for (int j = 0; j < num_coeffs_; ++j) { 325*77c1e3ccSAndroid Build Coastguard Worker const int diff = 326*77c1e3ccSAndroid Build Coastguard Worker bit_depth_ == AOM_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j]; 327*77c1e3ccSAndroid Build Coastguard Worker const uint32_t error = diff * diff; 328*77c1e3ccSAndroid Build Coastguard Worker ASSERT_GE(static_cast<uint32_t>(limit), error) 329*77c1e3ccSAndroid Build Coastguard Worker << "Error: 4x4 IDCT has error " << error << " at index " << j; 330*77c1e3ccSAndroid Build Coastguard Worker } 331*77c1e3ccSAndroid Build Coastguard Worker } 332*77c1e3ccSAndroid Build Coastguard Worker aom_free(in); 333*77c1e3ccSAndroid Build Coastguard Worker aom_free(coeff); 334*77c1e3ccSAndroid Build Coastguard Worker aom_free(dst); 335*77c1e3ccSAndroid Build Coastguard Worker aom_free(src); 336*77c1e3ccSAndroid Build Coastguard Worker aom_free(src16); 337*77c1e3ccSAndroid Build Coastguard Worker aom_free(dst16); 338*77c1e3ccSAndroid Build Coastguard Worker } 339*77c1e3ccSAndroid Build Coastguard Worker 340*77c1e3ccSAndroid Build Coastguard Worker int pitch_; 341*77c1e3ccSAndroid Build Coastguard Worker int height_; 342*77c1e3ccSAndroid Build Coastguard Worker FhtFunc<OutType> fwd_txfm_ref; 343*77c1e3ccSAndroid Build Coastguard Worker IhtFunc<OutType> inv_txfm_ref; 344*77c1e3ccSAndroid Build Coastguard Worker aom_bit_depth_t bit_depth_; 345*77c1e3ccSAndroid Build Coastguard Worker int mask_; 346*77c1e3ccSAndroid Build Coastguard Worker int num_coeffs_; 347*77c1e3ccSAndroid Build Coastguard Worker TxfmParam txfm_param_; 348*77c1e3ccSAndroid Build Coastguard Worker 349*77c1e3ccSAndroid Build Coastguard Worker private: 350*77c1e3ccSAndroid Build Coastguard Worker // Assume transform size is 4x4, 8x8, 16x16,... FindRowLength()351*77c1e3ccSAndroid Build Coastguard Worker int FindRowLength() const { 352*77c1e3ccSAndroid Build Coastguard Worker int row = 4; 353*77c1e3ccSAndroid Build Coastguard Worker if (16 == num_coeffs_) { 354*77c1e3ccSAndroid Build Coastguard Worker row = 4; 355*77c1e3ccSAndroid Build Coastguard Worker } else if (64 == num_coeffs_) { 356*77c1e3ccSAndroid Build Coastguard Worker row = 8; 357*77c1e3ccSAndroid Build Coastguard Worker } else if (256 == num_coeffs_) { 358*77c1e3ccSAndroid Build Coastguard Worker row = 16; 359*77c1e3ccSAndroid Build Coastguard Worker } else if (1024 == num_coeffs_) { 360*77c1e3ccSAndroid Build Coastguard Worker row = 32; 361*77c1e3ccSAndroid Build Coastguard Worker } 362*77c1e3ccSAndroid Build Coastguard Worker return row; 363*77c1e3ccSAndroid Build Coastguard Worker } 364*77c1e3ccSAndroid Build Coastguard Worker }; 365*77c1e3ccSAndroid Build Coastguard Worker 366*77c1e3ccSAndroid Build Coastguard Worker } // namespace libaom_test 367*77c1e3ccSAndroid Build Coastguard Worker 368*77c1e3ccSAndroid Build Coastguard Worker #endif // AOM_TEST_TRANSFORM_TEST_BASE_H_ 369