dct16x16_test.cc 17.6 KB
Newer Older
Daniel Kang's avatar
Daniel Kang committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

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

#include "third_party/googletest/src/include/gtest/gtest.h"
16 17 18 19
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "test/util.h"
Daniel Kang's avatar
Daniel Kang committed
20

Yaowu Xu's avatar
Yaowu Xu committed
21
#include "./vp9_rtcd.h"
22 23 24 25
#include "vp9/common/vp9_entropy.h"
#include "vpx/vpx_integer.h"

extern "C" {
26
void vp9_idct16x16_256_add_c(const int16_t *input, uint8_t *output, int pitch);
Daniel Kang's avatar
Daniel Kang committed
27 28 29 30 31
}

using libvpx_test::ACMRandom;

namespace {
32 33 34 35

#ifdef _MSC_VER
static int round(double x) {
  if (x < 0)
Yaowu Xu's avatar
Yaowu Xu committed
36
    return static_cast<int>(ceil(x - 0.5));
37
  else
Yaowu Xu's avatar
Yaowu Xu committed
38
    return static_cast<int>(floor(x + 0.5));
39 40
}
#endif
Daniel Kang's avatar
Daniel Kang committed
41

42
const int kNumCoeffs = 256;
Daniel Kang's avatar
Daniel Kang committed
43 44 45 46 47 48 49 50
const double PI = 3.1415926535898;
void reference2_16x16_idct_2d(double *input, double *output) {
  double x;
  for (int l = 0; l < 16; ++l) {
    for (int k = 0; k < 16; ++k) {
      double s = 0;
      for (int i = 0; i < 16; ++i) {
        for (int j = 0; j < 16; ++j) {
Yaowu Xu's avatar
Yaowu Xu committed
51 52 53
          x = cos(PI * j * (l + 0.5) / 16.0) *
              cos(PI * i * (k + 0.5) / 16.0) *
              input[i * 16 + j] / 256;
Daniel Kang's avatar
Daniel Kang committed
54 55 56 57 58 59 60 61 62 63 64 65
          if (i != 0)
            x *= sqrt(2.0);
          if (j != 0)
            x *= sqrt(2.0);
          s += x;
        }
      }
      output[k*16+l] = s;
    }
  }
}

66

67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
const double C1 = 0.995184726672197;
const double C2 = 0.98078528040323;
const double C3 = 0.956940335732209;
const double C4 = 0.923879532511287;
const double C5 = 0.881921264348355;
const double C6 = 0.831469612302545;
const double C7 = 0.773010453362737;
const double C8 = 0.707106781186548;
const double C9 = 0.634393284163646;
const double C10 = 0.555570233019602;
const double C11 = 0.471396736825998;
const double C12 = 0.38268343236509;
const double C13 = 0.290284677254462;
const double C14 = 0.195090322016128;
const double C15 = 0.098017140329561;
82

Jingning Han's avatar
Jingning Han committed
83
void butterfly_16x16_dct_1d(double input[16], double output[16]) {
Daniel Kang's avatar
Daniel Kang committed
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
  double step[16];
  double intermediate[16];
  double temp1, temp2;

  // step 1
  step[ 0] = input[0] + input[15];
  step[ 1] = input[1] + input[14];
  step[ 2] = input[2] + input[13];
  step[ 3] = input[3] + input[12];
  step[ 4] = input[4] + input[11];
  step[ 5] = input[5] + input[10];
  step[ 6] = input[6] + input[ 9];
  step[ 7] = input[7] + input[ 8];
  step[ 8] = input[7] - input[ 8];
  step[ 9] = input[6] - input[ 9];
  step[10] = input[5] - input[10];
  step[11] = input[4] - input[11];
  step[12] = input[3] - input[12];
  step[13] = input[2] - input[13];
  step[14] = input[1] - input[14];
  step[15] = input[0] - input[15];

  // step 2
  output[0] = step[0] + step[7];
  output[1] = step[1] + step[6];
  output[2] = step[2] + step[5];
  output[3] = step[3] + step[4];
  output[4] = step[3] - step[4];
  output[5] = step[2] - step[5];
  output[6] = step[1] - step[6];
  output[7] = step[0] - step[7];

116 117
  temp1 = step[ 8] * C7;
  temp2 = step[15] * C9;
Daniel Kang's avatar
Daniel Kang committed
118 119
  output[ 8] = temp1 + temp2;

120 121
  temp1 = step[ 9] * C11;
  temp2 = step[14] * C5;
Daniel Kang's avatar
Daniel Kang committed
122 123
  output[ 9] = temp1 - temp2;

124 125
  temp1 = step[10] * C3;
  temp2 = step[13] * C13;
Daniel Kang's avatar
Daniel Kang committed
126 127
  output[10] = temp1 + temp2;

128 129
  temp1 = step[11] * C15;
  temp2 = step[12] * C1;
Daniel Kang's avatar
Daniel Kang committed
130 131
  output[11] = temp1 - temp2;

132 133
  temp1 = step[11] * C1;
  temp2 = step[12] * C15;
Daniel Kang's avatar
Daniel Kang committed
134 135
  output[12] = temp2 + temp1;

136 137
  temp1 = step[10] * C13;
  temp2 = step[13] * C3;
Daniel Kang's avatar
Daniel Kang committed
138 139
  output[13] = temp2 - temp1;

140 141
  temp1 = step[ 9] * C5;
  temp2 = step[14] * C11;
Daniel Kang's avatar
Daniel Kang committed
142 143
  output[14] = temp2 + temp1;

144 145
  temp1 = step[ 8] * C9;
  temp2 = step[15] * C7;
Daniel Kang's avatar
Daniel Kang committed
146 147 148 149 150 151 152 153
  output[15] = temp2 - temp1;

  // step 3
  step[ 0] = output[0] + output[3];
  step[ 1] = output[1] + output[2];
  step[ 2] = output[1] - output[2];
  step[ 3] = output[0] - output[3];

154 155
  temp1 = output[4] * C14;
  temp2 = output[7] * C2;
Daniel Kang's avatar
Daniel Kang committed
156 157
  step[ 4] = temp1 + temp2;

158 159
  temp1 = output[5] * C10;
  temp2 = output[6] * C6;
Daniel Kang's avatar
Daniel Kang committed
160 161
  step[ 5] = temp1 + temp2;

162 163
  temp1 = output[5] * C6;
  temp2 = output[6] * C10;
Daniel Kang's avatar
Daniel Kang committed
164 165
  step[ 6] = temp2 - temp1;

166 167
  temp1 = output[4] * C2;
  temp2 = output[7] * C14;
Daniel Kang's avatar
Daniel Kang committed
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
  step[ 7] = temp2 - temp1;

  step[ 8] = output[ 8] + output[11];
  step[ 9] = output[ 9] + output[10];
  step[10] = output[ 9] - output[10];
  step[11] = output[ 8] - output[11];

  step[12] = output[12] + output[15];
  step[13] = output[13] + output[14];
  step[14] = output[13] - output[14];
  step[15] = output[12] - output[15];

  // step 4
  output[ 0] = (step[ 0] + step[ 1]);
  output[ 8] = (step[ 0] - step[ 1]);

184 185
  temp1 = step[2] * C12;
  temp2 = step[3] * C4;
Daniel Kang's avatar
Daniel Kang committed
186
  temp1 = temp1 + temp2;
187
  output[ 4] = 2*(temp1 * C8);
Daniel Kang's avatar
Daniel Kang committed
188

189 190
  temp1 = step[2] * C4;
  temp2 = step[3] * C12;
Daniel Kang's avatar
Daniel Kang committed
191
  temp1 = temp2 - temp1;
192
  output[12] = 2 * (temp1 * C8);
Daniel Kang's avatar
Daniel Kang committed
193

194 195
  output[ 2] = 2 * ((step[4] + step[ 5]) * C8);
  output[14] = 2 * ((step[7] - step[ 6]) * C8);
Daniel Kang's avatar
Daniel Kang committed
196 197 198 199 200 201 202 203 204

  temp1 = step[4] - step[5];
  temp2 = step[6] + step[7];
  output[ 6] = (temp1 + temp2);
  output[10] = (temp1 - temp2);

  intermediate[8] = step[8] + step[14];
  intermediate[9] = step[9] + step[15];

205 206
  temp1 = intermediate[8] * C12;
  temp2 = intermediate[9] * C4;
Daniel Kang's avatar
Daniel Kang committed
207
  temp1 = temp1 - temp2;
208
  output[3] = 2 * (temp1 * C8);
Daniel Kang's avatar
Daniel Kang committed
209

210 211
  temp1 = intermediate[8] * C4;
  temp2 = intermediate[9] * C12;
Daniel Kang's avatar
Daniel Kang committed
212
  temp1 = temp2 + temp1;
213
  output[13] = 2 * (temp1 * C8);
Daniel Kang's avatar
Daniel Kang committed
214

215
  output[ 9] = 2 * ((step[10] + step[11]) * C8);
Daniel Kang's avatar
Daniel Kang committed
216 217 218 219 220 221 222 223 224 225

  intermediate[11] = step[10] - step[11];
  intermediate[12] = step[12] + step[13];
  intermediate[13] = step[12] - step[13];
  intermediate[14] = step[ 8] - step[14];
  intermediate[15] = step[ 9] - step[15];

  output[15] = (intermediate[11] + intermediate[12]);
  output[ 1] = -(intermediate[11] - intermediate[12]);

226
  output[ 7] = 2 * (intermediate[13] * C8);
Daniel Kang's avatar
Daniel Kang committed
227

228 229
  temp1 = intermediate[14] * C12;
  temp2 = intermediate[15] * C4;
Daniel Kang's avatar
Daniel Kang committed
230
  temp1 = temp1 - temp2;
231
  output[11] = -2 * (temp1 * C8);
Daniel Kang's avatar
Daniel Kang committed
232

233 234
  temp1 = intermediate[14] * C4;
  temp2 = intermediate[15] * C12;
Daniel Kang's avatar
Daniel Kang committed
235
  temp1 = temp2 + temp1;
236
  output[ 5] = 2 * (temp1 * C8);
Daniel Kang's avatar
Daniel Kang committed
237 238
}

239
void reference_16x16_dct_2d(int16_t input[256], double output[256]) {
Daniel Kang's avatar
Daniel Kang committed
240 241 242 243
  // First transform columns
  for (int i = 0; i < 16; ++i) {
    double temp_in[16], temp_out[16];
    for (int j = 0; j < 16; ++j)
244
      temp_in[j] = input[j * 16 + i];
Daniel Kang's avatar
Daniel Kang committed
245 246
    butterfly_16x16_dct_1d(temp_in, temp_out);
    for (int j = 0; j < 16; ++j)
247
      output[j * 16 + i] = temp_out[j];
Daniel Kang's avatar
Daniel Kang committed
248 249 250 251 252
  }
  // Then transform rows
  for (int i = 0; i < 16; ++i) {
    double temp_in[16], temp_out[16];
    for (int j = 0; j < 16; ++j)
253
      temp_in[j] = output[j + i * 16];
Daniel Kang's avatar
Daniel Kang committed
254 255 256
    butterfly_16x16_dct_1d(temp_in, temp_out);
    // Scale by some magic number
    for (int j = 0; j < 16; ++j)
257
      output[j + i * 16] = temp_out[j]/2;
Daniel Kang's avatar
Daniel Kang committed
258 259 260
  }
}

261 262 263 264 265
typedef void (*fdct_t)(const int16_t *in, int16_t *out, int stride);
typedef void (*idct_t)(const int16_t *in, uint8_t *out, int stride);
typedef void (*fht_t) (const int16_t *in, int16_t *out, int stride,
                       int tx_type);
typedef void (*iht_t) (const int16_t *in, uint8_t *out, int stride,
266
                       int tx_type);
Daniel Kang's avatar
Daniel Kang committed
267

268 269 270
typedef std::tr1::tuple<fdct_t, idct_t, int> dct_16x16_param_t;
typedef std::tr1::tuple<fht_t, iht_t, int> ht_16x16_param_t;

271
void fdct16x16_ref(const int16_t *in, int16_t *out, int stride, int tx_type) {
272
  vp9_fdct16x16_c(in, out, stride);
273 274
}

275 276 277 278
void idct16x16_ref(const int16_t *in, uint8_t *dest, int stride, int tx_type) {
  vp9_idct16x16_256_add_c(in, dest, stride);
}

279
void fht16x16_ref(const int16_t *in, int16_t *out, int stride, int tx_type) {
280
  vp9_fht16x16_c(in, out, stride, tx_type);
281 282
}

283 284 285 286
void iht16x16_ref(const int16_t *in, uint8_t *dest, int stride, int tx_type) {
  vp9_iht16x16_256_add_c(in, dest, stride, tx_type);
}

287
class Trans16x16TestBase {
288
 public:
289
  virtual ~Trans16x16TestBase() {}
290

291
 protected:
292
  virtual void RunFwdTxfm(int16_t *in, int16_t *out, int stride) = 0;
293

294
  virtual void RunInvTxfm(int16_t *out, uint8_t *dst, int stride) = 0;
295 296 297

  void RunAccuracyCheck() {
    ACMRandom rnd(ACMRandom::DeterministicSeed());
298 299
    uint32_t max_error = 0;
    int64_t total_error = 0;
300 301 302 303 304 305 306
    const int count_test_block = 10000;
    for (int i = 0; i < count_test_block; ++i) {
      DECLARE_ALIGNED_ARRAY(16, int16_t, test_input_block, kNumCoeffs);
      DECLARE_ALIGNED_ARRAY(16, int16_t, test_temp_block, kNumCoeffs);
      DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, kNumCoeffs);
      DECLARE_ALIGNED_ARRAY(16, uint8_t, src, kNumCoeffs);

307
      // Initialize a test block with input range [-255, 255].
308 309 310 311 312 313
      for (int j = 0; j < kNumCoeffs; ++j) {
        src[j] = rnd.Rand8();
        dst[j] = rnd.Rand8();
        test_input_block[j] = src[j] - dst[j];
      }

314 315 316
      REGISTER_STATE_CHECK(RunFwdTxfm(test_input_block,
                                      test_temp_block, pitch_));
      REGISTER_STATE_CHECK(RunInvTxfm(test_temp_block, dst, pitch_));
317 318

      for (int j = 0; j < kNumCoeffs; ++j) {
319 320
        const uint32_t diff = dst[j] - src[j];
        const uint32_t error = diff * diff;
321 322 323 324
        if (max_error < error)
          max_error = error;
        total_error += error;
      }
Scott LaVarnway's avatar
Scott LaVarnway committed
325
    }
Daniel Kang's avatar
Daniel Kang committed
326

327
    EXPECT_GE(1u, max_error)
328 329 330 331
        << "Error: 16x16 FHT/IHT has an individual round trip error > 1";

    EXPECT_GE(count_test_block , total_error)
        << "Error: 16x16 FHT/IHT has average round trip error > 1 per block";
332 333
  }

334
  void RunCoeffCheck() {
335 336
    ACMRandom rnd(ACMRandom::DeterministicSeed());
    const int count_test_block = 1000;
337 338 339 340
    DECLARE_ALIGNED_ARRAY(16, int16_t, input_block, kNumCoeffs);
    DECLARE_ALIGNED_ARRAY(16, int16_t, output_ref_block, kNumCoeffs);
    DECLARE_ALIGNED_ARRAY(16, int16_t, output_block, kNumCoeffs);

341
    for (int i = 0; i < count_test_block; ++i) {
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
      // Initialize a test block with input range [-255, 255].
      for (int j = 0; j < kNumCoeffs; ++j)
        input_block[j] = rnd.Rand8() - rnd.Rand8();

      fwd_txfm_ref(input_block, output_ref_block, pitch_, tx_type_);
      REGISTER_STATE_CHECK(RunFwdTxfm(input_block, output_block, pitch_));

      // The minimum quant value is 4.
      for (int j = 0; j < kNumCoeffs; ++j)
        EXPECT_EQ(output_block[j], output_ref_block[j]);
    }
  }

  void RunMemCheck() {
    ACMRandom rnd(ACMRandom::DeterministicSeed());
    const int count_test_block = 1000;
    DECLARE_ALIGNED_ARRAY(16, int16_t, input_block, kNumCoeffs);
    DECLARE_ALIGNED_ARRAY(16, int16_t, input_extreme_block, kNumCoeffs);
    DECLARE_ALIGNED_ARRAY(16, int16_t, output_ref_block, kNumCoeffs);
    DECLARE_ALIGNED_ARRAY(16, int16_t, output_block, kNumCoeffs);
Scott LaVarnway's avatar
Scott LaVarnway committed
362

363
    for (int i = 0; i < count_test_block; ++i) {
364
      // Initialize a test block with input range [-255, 255].
365 366 367 368 369 370 371
      for (int j = 0; j < kNumCoeffs; ++j) {
        input_block[j] = rnd.Rand8() - rnd.Rand8();
        input_extreme_block[j] = rnd.Rand8() % 2 ? 255 : -255;
      }
      if (i == 0)
        for (int j = 0; j < kNumCoeffs; ++j)
          input_extreme_block[j] = 255;
372 373 374
      if (i == 1)
        for (int j = 0; j < kNumCoeffs; ++j)
          input_extreme_block[j] = -255;
375

376
      fwd_txfm_ref(input_extreme_block, output_ref_block, pitch_, tx_type_);
377
      REGISTER_STATE_CHECK(RunFwdTxfm(input_extreme_block,
378
                                      output_block, pitch_));
379 380 381

      // The minimum quant value is 4.
      for (int j = 0; j < kNumCoeffs; ++j) {
382
        EXPECT_EQ(output_block[j], output_ref_block[j]);
383 384 385
        EXPECT_GE(4 * DCT_MAX_VALUE, abs(output_block[j]))
            << "Error: 16x16 FDCT has coefficient larger than 4*DCT_MAX_VALUE";
      }
386
    }
387 388
  }

389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429
  void RunQuantCheck(int dc_thred, int ac_thred) {
    ACMRandom rnd(ACMRandom::DeterministicSeed());
    const int count_test_block = 1000;
    DECLARE_ALIGNED_ARRAY(16, int16_t, input_block, kNumCoeffs);
    DECLARE_ALIGNED_ARRAY(16, int16_t, input_extreme_block, kNumCoeffs);
    DECLARE_ALIGNED_ARRAY(16, int16_t, output_ref_block, kNumCoeffs);

    DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, kNumCoeffs);
    DECLARE_ALIGNED_ARRAY(16, uint8_t, ref, kNumCoeffs);

    for (int i = 0; i < count_test_block; ++i) {
      // Initialize a test block with input range [-255, 255].
      for (int j = 0; j < kNumCoeffs; ++j) {
        input_block[j] = rnd.Rand8() - rnd.Rand8();
        input_extreme_block[j] = rnd.Rand8() % 2 ? 255 : -255;
      }
      if (i == 0)
        for (int j = 0; j < kNumCoeffs; ++j)
          input_extreme_block[j] = 255;
      if (i == 1)
        for (int j = 0; j < kNumCoeffs; ++j)
          input_extreme_block[j] = -255;

      fwd_txfm_ref(input_extreme_block, output_ref_block, pitch_, tx_type_);

      // clear reconstructed pixel buffers
      vpx_memset(dst, 0, kNumCoeffs * sizeof(uint8_t));
      vpx_memset(ref, 0, kNumCoeffs * sizeof(uint8_t));

      // quantization with maximum allowed step sizes
      output_ref_block[0] = (output_ref_block[0] / dc_thred) * dc_thred;
      for (int j = 1; j < kNumCoeffs; ++j)
        output_ref_block[j] = (output_ref_block[j] / ac_thred) * ac_thred;
      inv_txfm_ref(output_ref_block, ref, pitch_, tx_type_);
      REGISTER_STATE_CHECK(RunInvTxfm(output_ref_block, dst, pitch_));

      for (int j = 0; j < kNumCoeffs; ++j)
        EXPECT_EQ(ref[j], dst[j]);
    }
  }

430 431 432
  void RunInvAccuracyCheck() {
    ACMRandom rnd(ACMRandom::DeterministicSeed());
    const int count_test_block = 1000;
433 434 435 436
    DECLARE_ALIGNED_ARRAY(16, int16_t, in, kNumCoeffs);
    DECLARE_ALIGNED_ARRAY(16, int16_t, coeff, kNumCoeffs);
    DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, kNumCoeffs);
    DECLARE_ALIGNED_ARRAY(16, uint8_t, src, kNumCoeffs);
Daniel Kang's avatar
Daniel Kang committed
437

438 439
    for (int i = 0; i < count_test_block; ++i) {
      double out_r[kNumCoeffs];
Daniel Kang's avatar
Daniel Kang committed
440

441 442 443 444 445 446 447 448 449 450 451
      // Initialize a test block with input range [-255, 255].
      for (int j = 0; j < kNumCoeffs; ++j) {
        src[j] = rnd.Rand8();
        dst[j] = rnd.Rand8();
        in[j] = src[j] - dst[j];
      }

      reference_16x16_dct_2d(in, out_r);
      for (int j = 0; j < kNumCoeffs; ++j)
        coeff[j] = round(out_r[j]);

452
      REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, 16));
453 454

      for (int j = 0; j < kNumCoeffs; ++j) {
455 456 457
        const uint32_t diff = dst[j] - src[j];
        const uint32_t error = diff * diff;
        EXPECT_GE(1u, error)
458 459 460
            << "Error: 16x16 IDCT has error " << error
            << " at index " << j;
      }
Daniel Kang's avatar
Daniel Kang committed
461 462
    }
  }
463 464 465
  int pitch_;
  int tx_type_;
  fht_t fwd_txfm_ref;
466
  iht_t inv_txfm_ref;
467
};
Daniel Kang's avatar
Daniel Kang committed
468

469 470 471
class Trans16x16DCT
    : public Trans16x16TestBase,
      public ::testing::TestWithParam<dct_16x16_param_t> {
472 473
 public:
  virtual ~Trans16x16DCT() {}
Daniel Kang's avatar
Daniel Kang committed
474

475 476 477 478
  virtual void SetUp() {
    fwd_txfm_ = GET_PARAM(0);
    inv_txfm_ = GET_PARAM(1);
    tx_type_  = GET_PARAM(2);
479
    pitch_    = 16;
480
    fwd_txfm_ref = fdct16x16_ref;
481
    inv_txfm_ref = idct16x16_ref;
482 483
  }
  virtual void TearDown() { libvpx_test::ClearSystemState(); }
Daniel Kang's avatar
Daniel Kang committed
484

485
 protected:
486
  void RunFwdTxfm(int16_t *in, int16_t *out, int stride) {
487 488
    fwd_txfm_(in, out, stride);
  }
489
  void RunInvTxfm(int16_t *out, uint8_t *dst, int stride) {
490
    inv_txfm_(out, dst, stride);
Daniel Kang's avatar
Daniel Kang committed
491
  }
492 493 494 495 496 497 498

  fdct_t fwd_txfm_;
  idct_t inv_txfm_;
};

TEST_P(Trans16x16DCT, AccuracyCheck) {
  RunAccuracyCheck();
Daniel Kang's avatar
Daniel Kang committed
499
}
500

501 502 503 504 505 506
TEST_P(Trans16x16DCT, CoeffCheck) {
  RunCoeffCheck();
}

TEST_P(Trans16x16DCT, MemCheck) {
  RunMemCheck();
507 508
}

509 510 511 512 513 514
TEST_P(Trans16x16DCT, QuantCheck) {
  // Use maximally allowed quantization step sizes for DC and AC
  // coefficients respectively.
  RunQuantCheck(1336, 1828);
}

515 516 517 518
TEST_P(Trans16x16DCT, InvAccuracyCheck) {
  RunInvAccuracyCheck();
}

519 520 521
class Trans16x16HT
    : public Trans16x16TestBase,
      public ::testing::TestWithParam<ht_16x16_param_t> {
522 523 524 525 526 527 528
 public:
  virtual ~Trans16x16HT() {}

  virtual void SetUp() {
    fwd_txfm_ = GET_PARAM(0);
    inv_txfm_ = GET_PARAM(1);
    tx_type_  = GET_PARAM(2);
529 530
    pitch_    = 16;
    fwd_txfm_ref = fht16x16_ref;
531
    inv_txfm_ref = iht16x16_ref;
532
  }
533 534 535
  virtual void TearDown() { libvpx_test::ClearSystemState(); }

 protected:
536 537
  void RunFwdTxfm(int16_t *in, int16_t *out, int stride) {
    fwd_txfm_(in, out, stride, tx_type_);
538
  }
539 540
  void RunInvTxfm(int16_t *out, uint8_t *dst, int stride) {
    inv_txfm_(out, dst, stride, tx_type_);
541 542 543 544 545 546 547 548 549 550
  }

  fht_t fwd_txfm_;
  iht_t inv_txfm_;
};

TEST_P(Trans16x16HT, AccuracyCheck) {
  RunAccuracyCheck();
}

551 552 553 554 555 556
TEST_P(Trans16x16HT, CoeffCheck) {
  RunCoeffCheck();
}

TEST_P(Trans16x16HT, MemCheck) {
  RunMemCheck();
557 558
}

559 560 561 562 563 564
TEST_P(Trans16x16HT, QuantCheck) {
  // The encoder skips any non-DC intra prediction modes,
  // when the quantization step size goes beyond 988.
  RunQuantCheck(549, 988);
}

565 566 567 568 569
using std::tr1::make_tuple;

INSTANTIATE_TEST_CASE_P(
    C, Trans16x16DCT,
    ::testing::Values(
570
        make_tuple(&vp9_fdct16x16_c, &vp9_idct16x16_256_add_c, 0)));
571 572 573
INSTANTIATE_TEST_CASE_P(
    C, Trans16x16HT,
    ::testing::Values(
574 575 576 577
        make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 0),
        make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 1),
        make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 2),
        make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 3)));
578

579
#if HAVE_NEON_ASM
James Zern's avatar
James Zern committed
580 581 582 583 584 585 586
INSTANTIATE_TEST_CASE_P(
    NEON, Trans16x16DCT,
    ::testing::Values(
        make_tuple(&vp9_fdct16x16_c,
                   &vp9_idct16x16_256_add_neon, 0)));
#endif

587 588 589 590
#if HAVE_SSE2
INSTANTIATE_TEST_CASE_P(
    SSE2, Trans16x16DCT,
    ::testing::Values(
591
        make_tuple(&vp9_fdct16x16_sse2,
592
                   &vp9_idct16x16_256_add_sse2, 0)));
593 594 595
INSTANTIATE_TEST_CASE_P(
    SSE2, Trans16x16HT,
    ::testing::Values(
596 597 598 599
        make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 0),
        make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 1),
        make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 2),
        make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 3)));
600
#endif
601 602 603 604 605 606 607

#if HAVE_SSSE3
INSTANTIATE_TEST_CASE_P(
    SSSE3, Trans16x16DCT,
    ::testing::Values(
        make_tuple(&vp9_fdct16x16_c, &vp9_idct16x16_256_add_ssse3, 0)));
#endif
Daniel Kang's avatar
Daniel Kang committed
608
}  // namespace