fdct8x8_test.cc 25 KB
Newer Older
Daniel Kang's avatar
Daniel Kang committed
1
/*
Yaowu Xu's avatar
Yaowu Xu committed
2
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Daniel Kang's avatar
Daniel Kang committed
3
 *
Yaowu Xu's avatar
Yaowu Xu committed
4 5 6 7 8 9
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
 * Media Patent License 1.0 was not distributed with this source code in the
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10
 */
Daniel Kang's avatar
Daniel Kang committed
11 12 13 14 15

#include <math.h>
#include <stdlib.h>
#include <string.h>

16
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
17

Yaowu Xu's avatar
Yaowu Xu committed
18 19
#include "./av1_rtcd.h"
#include "./aom_dsp_rtcd.h"
20
#include "test/acm_random.h"
21 22
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
23
#include "test/util.h"
24 25
#include "av1/common/entropy.h"
#include "av1/common/scan.h"
Yaowu Xu's avatar
Yaowu Xu committed
26 27
#include "aom/aom_codec.h"
#include "aom/aom_integer.h"
28
#include "aom_ports/mem.h"
29

30
using libaom_test::ACMRandom;
31 32 33

namespace {

34 35
const int kNumCoeffs = 64;
const double kPi = 3.141592653589793238462643383279502884;
36 37 38 39 40 41 42

const int kSignBiasMaxDiff255 = 1500;
const int kSignBiasMaxDiff15 = 10000;

typedef void (*FdctFunc)(const int16_t *in, tran_low_t *out, int stride);
typedef void (*IdctFunc)(const tran_low_t *in, uint8_t *out, int stride);
typedef void (*FhtFunc)(const int16_t *in, tran_low_t *out, int stride,
43
                        FWD_TXFM_PARAM *fwd_txfm_param);
44
typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride,
45
                        const INV_TXFM_PARAM *inv_txfm_param);
46

Yaowu Xu's avatar
Yaowu Xu committed
47 48 49
typedef std::tr1::tuple<FdctFunc, IdctFunc, int, aom_bit_depth_t> Dct8x8Param;
typedef std::tr1::tuple<FhtFunc, IhtFunc, int, aom_bit_depth_t> Ht8x8Param;
typedef std::tr1::tuple<IdctFunc, IdctFunc, int, aom_bit_depth_t> Idct8x8Param;
50

51
void reference_8x8_dct_1d(const double in[8], double out[8]) {
52 53 54 55 56
  const double kInvSqrt2 = 0.707106781186547524400844362104;
  for (int k = 0; k < 8; k++) {
    out[k] = 0.0;
    for (int n = 0; n < 8; n++)
      out[k] += in[n] * cos(kPi * (2 * n + 1) * k / 16.0);
clang-format's avatar
clang-format committed
57
    if (k == 0) out[k] = out[k] * kInvSqrt2;
58 59 60 61 62 63 64 65
  }
}

void reference_8x8_dct_2d(const int16_t input[kNumCoeffs],
                          double output[kNumCoeffs]) {
  // First transform columns
  for (int i = 0; i < 8; ++i) {
    double temp_in[8], temp_out[8];
clang-format's avatar
clang-format committed
66
    for (int j = 0; j < 8; ++j) temp_in[j] = input[j * 8 + i];
67
    reference_8x8_dct_1d(temp_in, temp_out);
clang-format's avatar
clang-format committed
68
    for (int j = 0; j < 8; ++j) output[j * 8 + i] = temp_out[j];
69 70 71 72
  }
  // Then transform rows
  for (int i = 0; i < 8; ++i) {
    double temp_in[8], temp_out[8];
clang-format's avatar
clang-format committed
73
    for (int j = 0; j < 8; ++j) temp_in[j] = output[j + i * 8];
74
    reference_8x8_dct_1d(temp_in, temp_out);
75
    // Scale by some magic number
clang-format's avatar
clang-format committed
76
    for (int j = 0; j < 8; ++j) output[j + i * 8] = temp_out[j] * 2;
77
  }
Daniel Kang's avatar
Daniel Kang committed
78 79
}

80
void fdct8x8_ref(const int16_t *in, tran_low_t *out, int stride,
81
                 FWD_TXFM_PARAM * /*fwd_txfm_param*/) {
Yaowu Xu's avatar
Yaowu Xu committed
82
  aom_fdct8x8_c(in, out, stride);
Jingning Han's avatar
Jingning Han committed
83
}
84

85 86 87
void fht8x8_ref(const int16_t *in, tran_low_t *out, int stride,
                FWD_TXFM_PARAM *fwd_txfm_param) {
  av1_fht8x8_c(in, out, stride, fwd_txfm_param);
Jingning Han's avatar
Jingning Han committed
88 89
}

90
#if CONFIG_HIGHBITDEPTH
91 92 93
void fht8x8_10(const int16_t *in, tran_low_t *out, int stride,
               FWD_TXFM_PARAM *fwd_txfm_param) {
  av1_fwd_txfm2d_8x8_c(in, out, stride, fwd_txfm_param->tx_type, 10);
94 95
}

96 97 98
void fht8x8_12(const int16_t *in, tran_low_t *out, int stride,
               FWD_TXFM_PARAM *fwd_txfm_param) {
  av1_fwd_txfm2d_8x8_c(in, out, stride, fwd_txfm_param->tx_type, 12);
99 100
}

101 102 103 104
void iht8x8_10(const tran_low_t *in, uint8_t *out, int stride,
               const INV_TXFM_PARAM *inv_txfm_param) {
  av1_inv_txfm2d_add_8x8_c(in, CONVERT_TO_SHORTPTR(out), stride,
                           inv_txfm_param->tx_type, 10);
105 106
}

107 108 109 110
void iht8x8_12(const tran_low_t *in, uint8_t *out, int stride,
               const INV_TXFM_PARAM *inv_txfm_param) {
  av1_inv_txfm2d_add_8x8_c(in, CONVERT_TO_SHORTPTR(out), stride,
                           inv_txfm_param->tx_type, 12);
111
}
112

113
#endif  // CONFIG_HIGHBITDEPTH
114

115
class FwdTrans8x8TestBase {
Jingning Han's avatar
Jingning Han committed
116
 public:
117
  virtual ~FwdTrans8x8TestBase() {}
Jingning Han's avatar
Jingning Han committed
118 119

 protected:
120 121
  virtual void RunFwdTxfm(int16_t *in, tran_low_t *out, int stride) = 0;
  virtual void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) = 0;
Jingning Han's avatar
Jingning Han committed
122

123 124
  void RunSignBiasCheck() {
    ACMRandom rnd(ACMRandom::DeterministicSeed());
125 126
    DECLARE_ALIGNED(16, int16_t, test_input_block[64]);
    DECLARE_ALIGNED(16, tran_low_t, test_output_block[64]);
127 128
    int count_sign_block[64][2];
    const int count_test_block = 100000;
Daniel Kang's avatar
Daniel Kang committed
129

130
    memset(count_sign_block, 0, sizeof(count_sign_block));
Daniel Kang's avatar
Daniel Kang committed
131

132 133 134
    for (int i = 0; i < count_test_block; ++i) {
      // Initialize a test block with input range [-255, 255].
      for (int j = 0; j < 64; ++j)
135 136
        test_input_block[j] = ((rnd.Rand16() >> (16 - bit_depth_)) & mask_) -
                              ((rnd.Rand16() >> (16 - bit_depth_)) & mask_);
137
      ASM_REGISTER_STATE_CHECK(
138
          RunFwdTxfm(test_input_block, test_output_block, pitch_));
Daniel Kang's avatar
Daniel Kang committed
139

140 141 142 143 144 145 146
      for (int j = 0; j < 64; ++j) {
        if (test_output_block[j] < 0)
          ++count_sign_block[j][0];
        else if (test_output_block[j] > 0)
          ++count_sign_block[j][1];
      }
    }
Daniel Kang's avatar
Daniel Kang committed
147 148

    for (int j = 0; j < 64; ++j) {
149
      const int diff = abs(count_sign_block[j][0] - count_sign_block[j][1]);
150
      const int max_diff = kSignBiasMaxDiff255;
151
      EXPECT_LT(diff, max_diff << (bit_depth_ - 8))
152 153 154 155
          << "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]
clang-format's avatar
clang-format committed
156
          << " count1: " << count_sign_block[j][1] << " diff: " << diff;
Daniel Kang's avatar
Daniel Kang committed
157 158
    }

159
    memset(count_sign_block, 0, sizeof(count_sign_block));
Daniel Kang's avatar
Daniel Kang committed
160

161
    for (int i = 0; i < count_test_block; ++i) {
162
      // Initialize a test block with input range [-mask_ / 16, mask_ / 16].
163
      for (int j = 0; j < 64; ++j)
clang-format's avatar
clang-format committed
164 165
        test_input_block[j] =
            ((rnd.Rand16() & mask_) >> 4) - ((rnd.Rand16() & mask_) >> 4);
166
      ASM_REGISTER_STATE_CHECK(
167
          RunFwdTxfm(test_input_block, test_output_block, pitch_));
Daniel Kang's avatar
Daniel Kang committed
168

169 170 171 172 173 174 175
      for (int j = 0; j < 64; ++j) {
        if (test_output_block[j] < 0)
          ++count_sign_block[j][0];
        else if (test_output_block[j] > 0)
          ++count_sign_block[j][1];
      }
    }
Daniel Kang's avatar
Daniel Kang committed
176 177

    for (int j = 0; j < 64; ++j) {
178
      const int diff = abs(count_sign_block[j][0] - count_sign_block[j][1]);
179
      const int max_diff = kSignBiasMaxDiff15;
180
      EXPECT_LT(diff, max_diff << (bit_depth_ - 8))
181
          << "Error: 8x8 FDCT/FHT has a sign bias > "
182 183 184
          << 1. * max_diff / count_test_block * 100 << "%"
          << " for input range [-15, 15] at index " << j
          << " count0: " << count_sign_block[j][0]
clang-format's avatar
clang-format committed
185
          << " count1: " << count_sign_block[j][1] << " diff: " << diff;
Daniel Kang's avatar
Daniel Kang committed
186 187 188
    }
  }

189 190 191 192 193
  void RunRoundTripErrorCheck() {
    ACMRandom rnd(ACMRandom::DeterministicSeed());
    int max_error = 0;
    int total_error = 0;
    const int count_test_block = 100000;
194 195 196 197
    DECLARE_ALIGNED(16, int16_t, test_input_block[64]);
    DECLARE_ALIGNED(16, tran_low_t, test_temp_block[64]);
    DECLARE_ALIGNED(16, uint8_t, dst[64]);
    DECLARE_ALIGNED(16, uint8_t, src[64]);
198
#if CONFIG_HIGHBITDEPTH
199 200
    DECLARE_ALIGNED(16, uint16_t, dst16[64]);
    DECLARE_ALIGNED(16, uint16_t, src16[64]);
201
#endif
Daniel Kang's avatar
Daniel Kang committed
202

203
    for (int i = 0; i < count_test_block; ++i) {
204
      // Initialize a test block with input range [-mask_, mask_].
205
      for (int j = 0; j < 64; ++j) {
Yaowu Xu's avatar
Yaowu Xu committed
206
        if (bit_depth_ == AOM_BITS_8) {
207 208 209
          src[j] = rnd.Rand8();
          dst[j] = rnd.Rand8();
          test_input_block[j] = src[j] - dst[j];
210
#if CONFIG_HIGHBITDEPTH
211 212 213 214 215 216
        } else {
          src16[j] = rnd.Rand16() & mask_;
          dst16[j] = rnd.Rand16() & mask_;
          test_input_block[j] = src16[j] - dst16[j];
#endif
        }
217
      }
Daniel Kang's avatar
Daniel Kang committed
218

219
      ASM_REGISTER_STATE_CHECK(
220 221
          RunFwdTxfm(test_input_block, test_temp_block, pitch_));
      for (int j = 0; j < 64; ++j) {
clang-format's avatar
clang-format committed
222 223 224 225 226 227 228 229 230
        if (test_temp_block[j] > 0) {
          test_temp_block[j] += 2;
          test_temp_block[j] /= 4;
          test_temp_block[j] *= 4;
        } else {
          test_temp_block[j] -= 2;
          test_temp_block[j] /= 4;
          test_temp_block[j] *= 4;
        }
231
      }
Yaowu Xu's avatar
Yaowu Xu committed
232
      if (bit_depth_ == AOM_BITS_8) {
clang-format's avatar
clang-format committed
233
        ASM_REGISTER_STATE_CHECK(RunInvTxfm(test_temp_block, dst, pitch_));
234
#if CONFIG_HIGHBITDEPTH
235 236 237 238 239
      } else {
        ASM_REGISTER_STATE_CHECK(
            RunInvTxfm(test_temp_block, CONVERT_TO_BYTEPTR(dst16), pitch_));
#endif
      }
240 241

      for (int j = 0; j < 64; ++j) {
242
#if CONFIG_HIGHBITDEPTH
243
        const int diff =
Yaowu Xu's avatar
Yaowu Xu committed
244
            bit_depth_ == AOM_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j];
245
#else
246
        const int diff = dst[j] - src[j];
247
#endif
248
        const int error = diff * diff;
clang-format's avatar
clang-format committed
249
        if (max_error < error) max_error = error;
250 251
        total_error += error;
      }
Daniel Kang's avatar
Daniel Kang committed
252 253
    }

254
    EXPECT_GE(1 << 2 * (bit_depth_ - 8), max_error)
clang-format's avatar
clang-format committed
255 256
        << "Error: 8x8 FDCT/IDCT or FHT/IHT has an individual"
        << " roundtrip error > 1";
Daniel Kang's avatar
Daniel Kang committed
257

clang-format's avatar
clang-format committed
258 259 260
    EXPECT_GE((count_test_block << 2 * (bit_depth_ - 8)) / 5, total_error)
        << "Error: 8x8 FDCT/IDCT or FHT/IHT has average roundtrip "
        << "error > 1/5 per block";
261
  }
Daniel Kang's avatar
Daniel Kang committed
262

263 264 265 266
  void RunExtremalCheck() {
    ACMRandom rnd(ACMRandom::DeterministicSeed());
    int max_error = 0;
    int total_error = 0;
267
    int total_coeff_error = 0;
268
    const int count_test_block = 100000;
269 270 271 272 273
    DECLARE_ALIGNED(16, int16_t, test_input_block[64]);
    DECLARE_ALIGNED(16, tran_low_t, test_temp_block[64]);
    DECLARE_ALIGNED(16, tran_low_t, ref_temp_block[64]);
    DECLARE_ALIGNED(16, uint8_t, dst[64]);
    DECLARE_ALIGNED(16, uint8_t, src[64]);
274
#if CONFIG_HIGHBITDEPTH
275 276
    DECLARE_ALIGNED(16, uint16_t, dst16[64]);
    DECLARE_ALIGNED(16, uint16_t, src16[64]);
277
#endif
Daniel Kang's avatar
Daniel Kang committed
278

279
    for (int i = 0; i < count_test_block; ++i) {
280
      // Initialize a test block with input range [-mask_, mask_].
281
      for (int j = 0; j < 64; ++j) {
Yaowu Xu's avatar
Yaowu Xu committed
282
        if (bit_depth_ == AOM_BITS_8) {
283 284 285 286 287 288 289 290 291 292 293
          if (i == 0) {
            src[j] = 255;
            dst[j] = 0;
          } else if (i == 1) {
            src[j] = 0;
            dst[j] = 255;
          } else {
            src[j] = rnd.Rand8() % 2 ? 255 : 0;
            dst[j] = rnd.Rand8() % 2 ? 255 : 0;
          }
          test_input_block[j] = src[j] - dst[j];
294
#if CONFIG_HIGHBITDEPTH
295
        } else {
296 297 298 299 300 301 302 303 304 305 306 307
          if (i == 0) {
            src16[j] = mask_;
            dst16[j] = 0;
          } else if (i == 1) {
            src16[j] = 0;
            dst16[j] = mask_;
          } else {
            src16[j] = rnd.Rand8() % 2 ? mask_ : 0;
            dst16[j] = rnd.Rand8() % 2 ? mask_ : 0;
          }
          test_input_block[j] = src16[j] - dst16[j];
#endif
308
        }
309
      }
Daniel Kang's avatar
Daniel Kang committed
310

311
      ASM_REGISTER_STATE_CHECK(
312
          RunFwdTxfm(test_input_block, test_temp_block, pitch_));
313 314
      ASM_REGISTER_STATE_CHECK(fwd_txfm_ref(test_input_block, ref_temp_block,
                                            pitch_, &fwd_txfm_param_));
Yaowu Xu's avatar
Yaowu Xu committed
315
      if (bit_depth_ == AOM_BITS_8) {
clang-format's avatar
clang-format committed
316
        ASM_REGISTER_STATE_CHECK(RunInvTxfm(test_temp_block, dst, pitch_));
317
#if CONFIG_HIGHBITDEPTH
318 319 320 321 322
      } else {
        ASM_REGISTER_STATE_CHECK(
            RunInvTxfm(test_temp_block, CONVERT_TO_BYTEPTR(dst16), pitch_));
#endif
      }
323 324

      for (int j = 0; j < 64; ++j) {
325
#if CONFIG_HIGHBITDEPTH
326
        const int diff =
Yaowu Xu's avatar
Yaowu Xu committed
327
            bit_depth_ == AOM_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j];
328
#else
329
        const int diff = dst[j] - src[j];
330
#endif
331
        const int error = diff * diff;
clang-format's avatar
clang-format committed
332
        if (max_error < error) max_error = error;
333
        total_error += error;
334 335 336

        const int coeff_diff = test_temp_block[j] - ref_temp_block[j];
        total_coeff_error += abs(coeff_diff);
337 338
      }

339
      EXPECT_GE(1 << 2 * (bit_depth_ - 8), max_error)
340 341 342
          << "Error: Extremal 8x8 FDCT/IDCT or FHT/IHT has"
          << "an individual roundtrip error > 1";

clang-format's avatar
clang-format committed
343
      EXPECT_GE((count_test_block << 2 * (bit_depth_ - 8)) / 5, total_error)
344 345
          << "Error: Extremal 8x8 FDCT/IDCT or FHT/IHT has average"
          << " roundtrip error > 1/5 per block";
346 347 348 349

      EXPECT_EQ(0, total_coeff_error)
          << "Error: Extremal 8x8 FDCT/FHT has"
          << "overflow issues in the intermediate steps > 1";
Daniel Kang's avatar
Daniel Kang committed
350
    }
351
  }
Daniel Kang's avatar
Daniel Kang committed
352

353 354 355
  void RunInvAccuracyCheck() {
    ACMRandom rnd(ACMRandom::DeterministicSeed());
    const int count_test_block = 1000;
356 357 358 359
    DECLARE_ALIGNED(16, int16_t, in[kNumCoeffs]);
    DECLARE_ALIGNED(16, tran_low_t, coeff[kNumCoeffs]);
    DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]);
    DECLARE_ALIGNED(16, uint8_t, src[kNumCoeffs]);
360
#if CONFIG_HIGHBITDEPTH
361 362
    DECLARE_ALIGNED(16, uint16_t, src16[kNumCoeffs]);
    DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]);
363 364 365 366 367 368 369
#endif

    for (int i = 0; i < count_test_block; ++i) {
      double out_r[kNumCoeffs];

      // Initialize a test block with input range [-255, 255].
      for (int j = 0; j < kNumCoeffs; ++j) {
Yaowu Xu's avatar
Yaowu Xu committed
370
        if (bit_depth_ == AOM_BITS_8) {
371 372 373
          src[j] = rnd.Rand8() % 2 ? 255 : 0;
          dst[j] = src[j] > 0 ? 0 : 255;
          in[j] = src[j] - dst[j];
374
#if CONFIG_HIGHBITDEPTH
375 376 377 378 379 380 381 382 383 384
        } else {
          src16[j] = rnd.Rand8() % 2 ? mask_ : 0;
          dst16[j] = src16[j] > 0 ? 0 : mask_;
          in[j] = src16[j] - dst16[j];
#endif
        }
      }

      reference_8x8_dct_2d(in, out_r);
      for (int j = 0; j < kNumCoeffs; ++j)
385
        coeff[j] = static_cast<tran_low_t>(round(out_r[j]));
386

Yaowu Xu's avatar
Yaowu Xu committed
387
      if (bit_depth_ == AOM_BITS_8) {
388
        ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, pitch_));
389
#if CONFIG_HIGHBITDEPTH
390
      } else {
clang-format's avatar
clang-format committed
391 392
        ASM_REGISTER_STATE_CHECK(
            RunInvTxfm(coeff, CONVERT_TO_BYTEPTR(dst16), pitch_));
393 394 395 396
#endif
      }

      for (int j = 0; j < kNumCoeffs; ++j) {
397
#if CONFIG_HIGHBITDEPTH
398
        const int diff =
Yaowu Xu's avatar
Yaowu Xu committed
399
            bit_depth_ == AOM_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j];
400
#else
401
        const int diff = dst[j] - src[j];
402 403 404
#endif
        const uint32_t error = diff * diff;
        EXPECT_GE(1u << 2 * (bit_depth_ - 8), error)
clang-format's avatar
clang-format committed
405
            << "Error: 8x8 IDCT has error " << error << " at index " << j;
406 407 408 409 410 411 412
      }
    }
  }

  void RunFwdAccuracyCheck() {
    ACMRandom rnd(ACMRandom::DeterministicSeed());
    const int count_test_block = 1000;
413 414 415
    DECLARE_ALIGNED(16, int16_t, in[kNumCoeffs]);
    DECLARE_ALIGNED(16, tran_low_t, coeff_r[kNumCoeffs]);
    DECLARE_ALIGNED(16, tran_low_t, coeff[kNumCoeffs]);
416 417 418 419 420 421 422 423 424 425 426

    for (int i = 0; i < count_test_block; ++i) {
      double out_r[kNumCoeffs];

      // Initialize a test block with input range [-mask_, mask_].
      for (int j = 0; j < kNumCoeffs; ++j)
        in[j] = rnd.Rand8() % 2 == 0 ? mask_ : -mask_;

      RunFwdTxfm(in, coeff, pitch_);
      reference_8x8_dct_2d(in, out_r);
      for (int j = 0; j < kNumCoeffs; ++j)
427
        coeff_r[j] = static_cast<tran_low_t>(round(out_r[j]));
428 429

      for (int j = 0; j < kNumCoeffs; ++j) {
Yaowu Xu's avatar
Yaowu Xu committed
430
        const int32_t diff = coeff[j] - coeff_r[j];
431 432
        const uint32_t error = diff * diff;
        EXPECT_GE(9u << 2 * (bit_depth_ - 8), error)
clang-format's avatar
clang-format committed
433
            << "Error: 8x8 DCT has error " << error << " at index " << j;
434 435 436
      }
    }
  }
437

clang-format's avatar
clang-format committed
438
  void CompareInvReference(IdctFunc ref_txfm, int thresh) {
439 440 441
    ACMRandom rnd(ACMRandom::DeterministicSeed());
    const int count_test_block = 10000;
    const int eob = 12;
442 443 444
    DECLARE_ALIGNED(16, tran_low_t, coeff[kNumCoeffs]);
    DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]);
    DECLARE_ALIGNED(16, uint8_t, ref[kNumCoeffs]);
445
#if CONFIG_HIGHBITDEPTH
446 447
    DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]);
    DECLARE_ALIGNED(16, uint16_t, ref16[kNumCoeffs]);
448
#endif
Yaowu Xu's avatar
Yaowu Xu committed
449
    const int16_t *scan = av1_default_scan_orders[TX_8X8].scan;
450 451 452 453 454

    for (int i = 0; i < count_test_block; ++i) {
      for (int j = 0; j < kNumCoeffs; ++j) {
        if (j < eob) {
          // Random values less than the threshold, either positive or negative
clang-format's avatar
clang-format committed
455
          coeff[scan[j]] = rnd(thresh) * (1 - 2 * (i % 2));
456 457 458
        } else {
          coeff[scan[j]] = 0;
        }
Yaowu Xu's avatar
Yaowu Xu committed
459
        if (bit_depth_ == AOM_BITS_8) {
460 461
          dst[j] = 0;
          ref[j] = 0;
462
#if CONFIG_HIGHBITDEPTH
463 464 465 466 467 468
        } else {
          dst16[j] = 0;
          ref16[j] = 0;
#endif
        }
      }
Yaowu Xu's avatar
Yaowu Xu committed
469
      if (bit_depth_ == AOM_BITS_8) {
470 471
        ref_txfm(coeff, ref, pitch_);
        ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, pitch_));
472
#if CONFIG_HIGHBITDEPTH
473 474
      } else {
        ref_txfm(coeff, CONVERT_TO_BYTEPTR(ref16), pitch_);
clang-format's avatar
clang-format committed
475 476
        ASM_REGISTER_STATE_CHECK(
            RunInvTxfm(coeff, CONVERT_TO_BYTEPTR(dst16), pitch_));
477 478 479 480
#endif
      }

      for (int j = 0; j < kNumCoeffs; ++j) {
481
#if CONFIG_HIGHBITDEPTH
482
        const int diff =
Yaowu Xu's avatar
Yaowu Xu committed
483
            bit_depth_ == AOM_BITS_8 ? dst[j] - ref[j] : dst16[j] - ref16[j];
484
#else
485
        const int diff = dst[j] - ref[j];
486 487
#endif
        const uint32_t error = diff * diff;
clang-format's avatar
clang-format committed
488 489
        EXPECT_EQ(0u, error) << "Error: 8x8 IDCT has error " << error
                             << " at index " << j;
490 491 492
      }
    }
  }
493
  int pitch_;
494
  FhtFunc fwd_txfm_ref;
Yaowu Xu's avatar
Yaowu Xu committed
495
  aom_bit_depth_t bit_depth_;
496
  int mask_;
497 498
  FWD_TXFM_PARAM fwd_txfm_param_;
  INV_TXFM_PARAM inv_txfm_param_;
499
};
Daniel Kang's avatar
Daniel Kang committed
500

clang-format's avatar
clang-format committed
501 502
class FwdTrans8x8DCT : public FwdTrans8x8TestBase,
                       public ::testing::TestWithParam<Dct8x8Param> {
503 504 505 506 507 508
 public:
  virtual ~FwdTrans8x8DCT() {}

  virtual void SetUp() {
    fwd_txfm_ = GET_PARAM(0);
    inv_txfm_ = GET_PARAM(1);
clang-format's avatar
clang-format committed
509
    pitch_ = 8;
510
    fwd_txfm_ref = fdct8x8_ref;
511 512
    bit_depth_ = GET_PARAM(3);
    mask_ = (1 << bit_depth_) - 1;
513 514
    fwd_txfm_param_.tx_type = (TX_TYPE)GET_PARAM(2);
    inv_txfm_param_.tx_type = (TX_TYPE)GET_PARAM(2);
515 516
  }

517
  virtual void TearDown() { libaom_test::ClearSystemState(); }
518 519

 protected:
520
  void RunFwdTxfm(int16_t *in, tran_low_t *out, int stride) {
521 522
    fwd_txfm_(in, out, stride);
  }
523
  void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) {
524
    inv_txfm_(out, dst, stride);
Daniel Kang's avatar
Daniel Kang committed
525
  }
526

527 528
  FdctFunc fwd_txfm_;
  IdctFunc inv_txfm_;
529 530
};

clang-format's avatar
clang-format committed
531
TEST_P(FwdTrans8x8DCT, SignBiasCheck) { RunSignBiasCheck(); }
Daniel Kang's avatar
Daniel Kang committed
532

clang-format's avatar
clang-format committed
533
TEST_P(FwdTrans8x8DCT, RoundTripErrorCheck) { RunRoundTripErrorCheck(); }
534

clang-format's avatar
clang-format committed
535
TEST_P(FwdTrans8x8DCT, ExtremalCheck) { RunExtremalCheck(); }
536

clang-format's avatar
clang-format committed
537
TEST_P(FwdTrans8x8DCT, FwdAccuracyCheck) { RunFwdAccuracyCheck(); }
538

clang-format's avatar
clang-format committed
539
TEST_P(FwdTrans8x8DCT, InvAccuracyCheck) { RunInvAccuracyCheck(); }
540

clang-format's avatar
clang-format committed
541 542
class FwdTrans8x8HT : public FwdTrans8x8TestBase,
                      public ::testing::TestWithParam<Ht8x8Param> {
543 544 545 546 547 548
 public:
  virtual ~FwdTrans8x8HT() {}

  virtual void SetUp() {
    fwd_txfm_ = GET_PARAM(0);
    inv_txfm_ = GET_PARAM(1);
clang-format's avatar
clang-format committed
549
    pitch_ = 8;
550
    fwd_txfm_ref = fht8x8_ref;
551 552
    bit_depth_ = GET_PARAM(3);
    mask_ = (1 << bit_depth_) - 1;
553 554
    fwd_txfm_param_.tx_type = (TX_TYPE)GET_PARAM(2);
    inv_txfm_param_.tx_type = (TX_TYPE)GET_PARAM(2);
555 556 557 558 559 560 561
#if CONFIG_HIGHBITDEPTH
    switch (bit_depth_) {
      case AOM_BITS_10: fwd_txfm_ref = fht8x8_10; break;
      case AOM_BITS_12: fwd_txfm_ref = fht8x8_12; break;
      default: fwd_txfm_ref = fht8x8_ref; break;
    }
#endif
562 563
  }

564
  virtual void TearDown() { libaom_test::ClearSystemState(); }
565 566

 protected:
567
  void RunFwdTxfm(int16_t *in, tran_low_t *out, int stride) {
568
    fwd_txfm_(in, out, stride, &fwd_txfm_param_);
569
  }
570
  void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) {
571
    inv_txfm_(out, dst, stride, &inv_txfm_param_);
572 573
  }

574 575
  FhtFunc fwd_txfm_;
  IhtFunc inv_txfm_;
576 577
};

clang-format's avatar
clang-format committed
578
TEST_P(FwdTrans8x8HT, SignBiasCheck) { RunSignBiasCheck(); }
579

clang-format's avatar
clang-format committed
580
TEST_P(FwdTrans8x8HT, RoundTripErrorCheck) { RunRoundTripErrorCheck(); }
581

clang-format's avatar
clang-format committed
582
TEST_P(FwdTrans8x8HT, ExtremalCheck) { RunExtremalCheck(); }
583

clang-format's avatar
clang-format committed
584 585
class InvTrans8x8DCT : public FwdTrans8x8TestBase,
                       public ::testing::TestWithParam<Idct8x8Param> {
586 587 588 589 590 591 592 593 594 595 596 597
 public:
  virtual ~InvTrans8x8DCT() {}

  virtual void SetUp() {
    ref_txfm_ = GET_PARAM(0);
    inv_txfm_ = GET_PARAM(1);
    thresh_ = GET_PARAM(2);
    pitch_ = 8;
    bit_depth_ = GET_PARAM(3);
    mask_ = (1 << bit_depth_) - 1;
  }

598
  virtual void TearDown() { libaom_test::ClearSystemState(); }
599 600 601 602 603

 protected:
  void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) {
    inv_txfm_(out, dst, stride);
  }
604
  void RunFwdTxfm(int16_t * /*out*/, tran_low_t * /*dst*/, int /*stride*/) {}
605 606 607 608 609 610 611 612 613 614

  IdctFunc ref_txfm_;
  IdctFunc inv_txfm_;
  int thresh_;
};

TEST_P(InvTrans8x8DCT, CompareReference) {
  CompareInvReference(ref_txfm_, thresh_);
}

615 616
using std::tr1::make_tuple;

617
#if CONFIG_HIGHBITDEPTH
618 619 620 621
INSTANTIATE_TEST_CASE_P(C, FwdTrans8x8DCT,
                        ::testing::Values(make_tuple(&aom_fdct8x8_c,
                                                     &aom_idct8x8_64_add_c, 0,
                                                     AOM_BITS_8)));
622
#else
clang-format's avatar
clang-format committed
623
INSTANTIATE_TEST_CASE_P(C, FwdTrans8x8DCT,
Yaowu Xu's avatar
Yaowu Xu committed
624 625 626
                        ::testing::Values(make_tuple(&aom_fdct8x8_c,
                                                     &aom_idct8x8_64_add_c, 0,
                                                     AOM_BITS_8)));
627
#endif  // CONFIG_HIGHBITDEPTH
628

629
#if CONFIG_HIGHBITDEPTH
630 631 632
INSTANTIATE_TEST_CASE_P(
    C, FwdTrans8x8HT,
    ::testing::Values(
Yaowu Xu's avatar
Yaowu Xu committed
633
        make_tuple(&av1_fht8x8_c, &av1_iht8x8_64_add_c, 0, AOM_BITS_8),
634 635 636 637 638 639 640 641
        make_tuple(&fht8x8_10, &iht8x8_10, 0, AOM_BITS_10),
        make_tuple(&fht8x8_10, &iht8x8_10, 1, AOM_BITS_10),
        make_tuple(&fht8x8_10, &iht8x8_10, 2, AOM_BITS_10),
        make_tuple(&fht8x8_10, &iht8x8_10, 3, AOM_BITS_10),
        make_tuple(&fht8x8_12, &iht8x8_12, 0, AOM_BITS_12),
        make_tuple(&fht8x8_12, &iht8x8_12, 1, AOM_BITS_12),
        make_tuple(&fht8x8_12, &iht8x8_12, 2, AOM_BITS_12),
        make_tuple(&fht8x8_12, &iht8x8_12, 3, AOM_BITS_12),
Yaowu Xu's avatar
Yaowu Xu committed
642 643 644
        make_tuple(&av1_fht8x8_c, &av1_iht8x8_64_add_c, 1, AOM_BITS_8),
        make_tuple(&av1_fht8x8_c, &av1_iht8x8_64_add_c, 2, AOM_BITS_8),
        make_tuple(&av1_fht8x8_c, &av1_iht8x8_64_add_c, 3, AOM_BITS_8)));
645 646 647 648
#else
INSTANTIATE_TEST_CASE_P(
    C, FwdTrans8x8HT,
    ::testing::Values(
Yaowu Xu's avatar
Yaowu Xu committed
649 650 651 652
        make_tuple(&av1_fht8x8_c, &av1_iht8x8_64_add_c, 0, AOM_BITS_8),
        make_tuple(&av1_fht8x8_c, &av1_iht8x8_64_add_c, 1, AOM_BITS_8),
        make_tuple(&av1_fht8x8_c, &av1_iht8x8_64_add_c, 2, AOM_BITS_8),
        make_tuple(&av1_fht8x8_c, &av1_iht8x8_64_add_c, 3, AOM_BITS_8)));
653
#endif  // CONFIG_HIGHBITDEPTH
654

655
#if HAVE_NEON_ASM && !CONFIG_HIGHBITDEPTH
clang-format's avatar
clang-format committed
656
INSTANTIATE_TEST_CASE_P(NEON, FwdTrans8x8DCT,
Yaowu Xu's avatar
Yaowu Xu committed
657 658 659
                        ::testing::Values(make_tuple(&aom_fdct8x8_neon,
                                                     &aom_idct8x8_64_add_neon,
                                                     0, AOM_BITS_8)));
660
#endif  // HAVE_NEON_ASM && !CONFIG_HIGHBITDEPTH
661

662
#if HAVE_NEON && !CONFIG_HIGHBITDEPTH
James Zern's avatar
James Zern committed
663
INSTANTIATE_TEST_CASE_P(
664
    NEON, FwdTrans8x8HT,
James Zern's avatar
James Zern committed
665
    ::testing::Values(
Yaowu Xu's avatar
Yaowu Xu committed
666 667 668 669
        make_tuple(&av1_fht8x8_c, &av1_iht8x8_64_add_neon, 0, AOM_BITS_8),
        make_tuple(&av1_fht8x8_c, &av1_iht8x8_64_add_neon, 1, AOM_BITS_8),
        make_tuple(&av1_fht8x8_c, &av1_iht8x8_64_add_neon, 2, AOM_BITS_8),
        make_tuple(&av1_fht8x8_c, &av1_iht8x8_64_add_neon, 3, AOM_BITS_8)));
670
#endif  // HAVE_NEON && !CONFIG_HIGHBITDEPTH
James Zern's avatar
James Zern committed
671

672
#if HAVE_SSE2 && !CONFIG_HIGHBITDEPTH
clang-format's avatar
clang-format committed
673
INSTANTIATE_TEST_CASE_P(SSE2, FwdTrans8x8DCT,
Yaowu Xu's avatar
Yaowu Xu committed
674 675 676
                        ::testing::Values(make_tuple(&aom_fdct8x8_sse2,
                                                     &aom_idct8x8_64_add_sse2,
                                                     0, AOM_BITS_8)));
677 678 679
INSTANTIATE_TEST_CASE_P(
    SSE2, FwdTrans8x8HT,
    ::testing::Values(
Yaowu Xu's avatar
Yaowu Xu committed
680 681 682 683
        make_tuple(&av1_fht8x8_sse2, &av1_iht8x8_64_add_sse2, 0, AOM_BITS_8),
        make_tuple(&av1_fht8x8_sse2, &av1_iht8x8_64_add_sse2, 1, AOM_BITS_8),
        make_tuple(&av1_fht8x8_sse2, &av1_iht8x8_64_add_sse2, 2, AOM_BITS_8),
        make_tuple(&av1_fht8x8_sse2, &av1_iht8x8_64_add_sse2, 3, AOM_BITS_8)));
684
#endif  // HAVE_SSE2 && !CONFIG_HIGHBITDEPTH
Yaowu Xu's avatar
Yaowu Xu committed
685

686
#if HAVE_SSE2 && CONFIG_HIGHBITDEPTH
687 688 689 690
INSTANTIATE_TEST_CASE_P(SSE2, FwdTrans8x8DCT,
                        ::testing::Values(make_tuple(&aom_fdct8x8_sse2,
                                                     &aom_idct8x8_64_add_c, 0,
                                                     AOM_BITS_8)));
691 692 693 694

INSTANTIATE_TEST_CASE_P(
    SSE2, FwdTrans8x8HT,
    ::testing::Values(
Yaowu Xu's avatar
Yaowu Xu committed
695 696 697 698
        make_tuple(&av1_fht8x8_sse2, &av1_iht8x8_64_add_c, 0, AOM_BITS_8),
        make_tuple(&av1_fht8x8_sse2, &av1_iht8x8_64_add_c, 1, AOM_BITS_8),
        make_tuple(&av1_fht8x8_sse2, &av1_iht8x8_64_add_c, 2, AOM_BITS_8),
        make_tuple(&av1_fht8x8_sse2, &av1_iht8x8_64_add_c, 3, AOM_BITS_8)));
699

700
#endif  // HAVE_SSE2 && CONFIG_HIGHBITDEPTH
701

702
#if HAVE_SSSE3 && ARCH_X86_64
clang-format's avatar
clang-format committed
703
INSTANTIATE_TEST_CASE_P(SSSE3, FwdTrans8x8DCT,
Yaowu Xu's avatar
Yaowu Xu committed
704 705 706
                        ::testing::Values(make_tuple(&aom_fdct8x8_ssse3,
                                                     &aom_idct8x8_64_add_ssse3,
                                                     0, AOM_BITS_8)));
707
#endif
708

709
#if HAVE_MSA && !CONFIG_HIGHBITDEPTH
clang-format's avatar
clang-format committed
710
INSTANTIATE_TEST_CASE_P(MSA, FwdTrans8x8DCT,
Yaowu Xu's avatar
Yaowu Xu committed
711 712 713
                        ::testing::Values(make_tuple(&aom_fdct8x8_msa,
                                                     &aom_idct8x8_64_add_msa, 0,
                                                     AOM_BITS_8)));
714
#if !CONFIG_EXT_TX
715 716 717
INSTANTIATE_TEST_CASE_P(
    MSA, FwdTrans8x8HT,
    ::testing::Values(
Yaowu Xu's avatar
Yaowu Xu committed
718 719 720 721
        make_tuple(&av1_fht8x8_msa, &av1_iht8x8_64_add_msa, 0, AOM_BITS_8),
        make_tuple(&av1_fht8x8_msa, &av1_iht8x8_64_add_msa, 1, AOM_BITS_8),
        make_tuple(&av1_fht8x8_msa, &av1_iht8x8_64_add_msa, 2, AOM_BITS_8),
        make_tuple(&av1_fht8x8_msa, &av1_iht8x8_64_add_msa, 3, AOM_BITS_8)));
722
#endif  // !CONFIG_EXT_TX
723
#endif  // HAVE_MSA && !CONFIG_HIGHBITDEPTH
Daniel Kang's avatar
Daniel Kang committed
724
}  // namespace