dct16x16_test.cc 17.7 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 266
typedef void (*FdctFunc)(const int16_t *in, int16_t *out, int stride);
typedef void (*IdctFunc)(const int16_t *in, uint8_t *out, int stride);
typedef void (*FhtFunc)(const int16_t *in, int16_t *out, int stride,
                        int tx_type);
typedef void (*IhtFunc)(const int16_t *in, uint8_t *out, int stride,
                        int tx_type);
Daniel Kang's avatar
Daniel Kang committed
267

268 269
typedef std::tr1::tuple<FdctFunc, IdctFunc, int> Dct16x16Param;
typedef std::tr1::tuple<FhtFunc, IhtFunc, int> Ht16x16Param;
270

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

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

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

285 286 287 288
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);
}

289
class Trans16x16TestBase {
290
 public:
291
  virtual ~Trans16x16TestBase() {}
292

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

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

  void RunAccuracyCheck() {
    ACMRandom rnd(ACMRandom::DeterministicSeed());
300 301
    uint32_t max_error = 0;
    int64_t total_error = 0;
302 303 304 305 306 307 308
    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);

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

316 317 318
      ASM_REGISTER_STATE_CHECK(RunFwdTxfm(test_input_block,
                                          test_temp_block, pitch_));
      ASM_REGISTER_STATE_CHECK(RunInvTxfm(test_temp_block, dst, pitch_));
319 320

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

329
    EXPECT_GE(1u, max_error)
330 331 332 333
        << "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";
334 335
  }

336
  void RunCoeffCheck() {
337 338
    ACMRandom rnd(ACMRandom::DeterministicSeed());
    const int count_test_block = 1000;
339 340 341 342
    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);

343
    for (int i = 0; i < count_test_block; ++i) {
344 345 346 347 348
      // 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_);
349
      ASM_REGISTER_STATE_CHECK(RunFwdTxfm(input_block, output_block, pitch_));
350 351 352 353 354 355 356 357 358 359 360 361 362 363

      // 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
364

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

379
      fwd_txfm_ref(input_extreme_block, output_ref_block, pitch_, tx_type_);
380 381
      ASM_REGISTER_STATE_CHECK(RunFwdTxfm(input_extreme_block,
                                          output_block, pitch_));
382 383 384

      // The minimum quant value is 4.
      for (int j = 0; j < kNumCoeffs; ++j) {
385
        EXPECT_EQ(output_block[j], output_ref_block[j]);
386 387 388
        EXPECT_GE(4 * DCT_MAX_VALUE, abs(output_block[j]))
            << "Error: 16x16 FDCT has coefficient larger than 4*DCT_MAX_VALUE";
      }
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
  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_);
426
      ASM_REGISTER_STATE_CHECK(RunInvTxfm(output_ref_block, dst, pitch_));
427 428 429 430 431 432

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

433 434 435
  void RunInvAccuracyCheck() {
    ACMRandom rnd(ACMRandom::DeterministicSeed());
    const int count_test_block = 1000;
436 437 438 439
    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
440

441 442
    for (int i = 0; i < count_test_block; ++i) {
      double out_r[kNumCoeffs];
Daniel Kang's avatar
Daniel Kang committed
443

444 445 446 447 448 449 450 451 452 453 454
      // 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]);

455
      ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, 16));
456 457

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

472 473
class Trans16x16DCT
    : public Trans16x16TestBase,
474
      public ::testing::TestWithParam<Dct16x16Param> {
475 476
 public:
  virtual ~Trans16x16DCT() {}
Daniel Kang's avatar
Daniel Kang committed
477

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

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

496 497
  FdctFunc fwd_txfm_;
  IdctFunc inv_txfm_;
498 499 500 501
};

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

504 505 506 507 508 509
TEST_P(Trans16x16DCT, CoeffCheck) {
  RunCoeffCheck();
}

TEST_P(Trans16x16DCT, MemCheck) {
  RunMemCheck();
510 511
}

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

518 519 520 521
TEST_P(Trans16x16DCT, InvAccuracyCheck) {
  RunInvAccuracyCheck();
}

522 523
class Trans16x16HT
    : public Trans16x16TestBase,
524
      public ::testing::TestWithParam<Ht16x16Param> {
525 526 527 528 529 530 531
 public:
  virtual ~Trans16x16HT() {}

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

 protected:
539 540
  void RunFwdTxfm(int16_t *in, int16_t *out, int stride) {
    fwd_txfm_(in, out, stride, tx_type_);
541
  }
542 543
  void RunInvTxfm(int16_t *out, uint8_t *dst, int stride) {
    inv_txfm_(out, dst, stride, tx_type_);
544 545
  }

546 547
  FhtFunc fwd_txfm_;
  IhtFunc inv_txfm_;
548 549 550 551 552 553
};

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

554 555 556 557 558 559
TEST_P(Trans16x16HT, CoeffCheck) {
  RunCoeffCheck();
}

TEST_P(Trans16x16HT, MemCheck) {
  RunMemCheck();
560 561
}

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

568 569 570 571 572
using std::tr1::make_tuple;

INSTANTIATE_TEST_CASE_P(
    C, Trans16x16DCT,
    ::testing::Values(
573
        make_tuple(&vp9_fdct16x16_c, &vp9_idct16x16_256_add_c, 0)));
574 575 576
INSTANTIATE_TEST_CASE_P(
    C, Trans16x16HT,
    ::testing::Values(
577 578 579 580
        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)));
581

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

590 591 592 593
#if HAVE_SSE2
INSTANTIATE_TEST_CASE_P(
    SSE2, Trans16x16DCT,
    ::testing::Values(
594
        make_tuple(&vp9_fdct16x16_sse2,
595
                   &vp9_idct16x16_256_add_sse2, 0)));
596 597 598
INSTANTIATE_TEST_CASE_P(
    SSE2, Trans16x16HT,
    ::testing::Values(
599 600 601 602
        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)));
603
#endif
604 605 606 607 608 609 610

#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
611
}  // namespace