• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2017 The WebM project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include <math.h>
12 #include <stdlib.h>
13 #include <string.h>
14 
15 #include "third_party/googletest/src/include/gtest/gtest.h"
16 
17 #include "./vp9_rtcd.h"
18 #include "./vpx_dsp_rtcd.h"
19 #include "test/acm_random.h"
20 #include "test/buffer.h"
21 #include "test/clear_system_state.h"
22 #include "test/register_state_check.h"
23 #include "test/util.h"
24 #include "vp9/common/vp9_entropy.h"
25 #include "vpx/vpx_codec.h"
26 #include "vpx/vpx_integer.h"
27 #include "vpx_ports/mem.h"
28 
29 using libvpx_test::ACMRandom;
30 using libvpx_test::Buffer;
31 using std::tr1::tuple;
32 using std::tr1::make_tuple;
33 
34 namespace {
35 typedef void (*FdctFunc)(const int16_t *in, tran_low_t *out, int stride);
36 typedef void (*IdctFunc)(const tran_low_t *in, uint8_t *out, int stride);
37 typedef void (*FhtFunc)(const int16_t *in, tran_low_t *out, int stride,
38                         int tx_type);
39 typedef void (*FhtFuncRef)(const Buffer<int16_t> &in, Buffer<tran_low_t> *out,
40                            int size, int tx_type);
41 typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride,
42                         int tx_type);
43 
44 /* forward transform, inverse transform, size, transform type, bit depth */
45 typedef tuple<FdctFunc, IdctFunc, int, int, vpx_bit_depth_t> DctParam;
46 typedef tuple<FhtFunc, IhtFunc, int, int, vpx_bit_depth_t> HtParam;
47 
fdct_ref(const Buffer<int16_t> & in,Buffer<tran_low_t> * out,int size,int)48 void fdct_ref(const Buffer<int16_t> &in, Buffer<tran_low_t> *out, int size,
49               int /*tx_type*/) {
50   const int16_t *i = in.TopLeftPixel();
51   const int i_stride = in.stride();
52   tran_low_t *o = out->TopLeftPixel();
53   if (size == 4) {
54     vpx_fdct4x4_c(i, o, i_stride);
55   } else if (size == 8) {
56     vpx_fdct8x8_c(i, o, i_stride);
57   } else if (size == 16) {
58     vpx_fdct16x16_c(i, o, i_stride);
59   } else if (size == 32) {
60     vpx_fdct32x32_c(i, o, i_stride);
61   }
62 }
63 
fht_ref(const Buffer<int16_t> & in,Buffer<tran_low_t> * out,int size,int tx_type)64 void fht_ref(const Buffer<int16_t> &in, Buffer<tran_low_t> *out, int size,
65              int tx_type) {
66   const int16_t *i = in.TopLeftPixel();
67   const int i_stride = in.stride();
68   tran_low_t *o = out->TopLeftPixel();
69   if (size == 4) {
70     vp9_fht4x4_c(i, o, i_stride, tx_type);
71   } else if (size == 8) {
72     vp9_fht8x8_c(i, o, i_stride, tx_type);
73   } else if (size == 16) {
74     vp9_fht16x16_c(i, o, i_stride, tx_type);
75   }
76 }
77 
fwht_ref(const Buffer<int16_t> & in,Buffer<tran_low_t> * out,int size,int)78 void fwht_ref(const Buffer<int16_t> &in, Buffer<tran_low_t> *out, int size,
79               int /*tx_type*/) {
80   ASSERT_EQ(size, 4);
81   vp9_fwht4x4_c(in.TopLeftPixel(), out->TopLeftPixel(), in.stride());
82 }
83 
84 #if CONFIG_VP9_HIGHBITDEPTH
85 #define idctNxN(n, coeffs, bitdepth)                                       \
86   void idct##n##x##n##_##bitdepth(const tran_low_t *in, uint8_t *out,      \
87                                   int stride) {                            \
88     vpx_highbd_idct##n##x##n##_##coeffs##_add_c(in, CAST_TO_SHORTPTR(out), \
89                                                 stride, bitdepth);         \
90   }
91 
92 idctNxN(4, 16, 10);
93 idctNxN(4, 16, 12);
94 idctNxN(8, 64, 10);
95 idctNxN(8, 64, 12);
96 idctNxN(16, 256, 10);
97 idctNxN(16, 256, 12);
98 idctNxN(32, 1024, 10);
99 idctNxN(32, 1024, 12);
100 
101 #define ihtNxN(n, coeffs, bitdepth)                                        \
102   void iht##n##x##n##_##bitdepth(const tran_low_t *in, uint8_t *out,       \
103                                  int stride, int tx_type) {                \
104     vp9_highbd_iht##n##x##n##_##coeffs##_add_c(in, CAST_TO_SHORTPTR(out),  \
105                                                stride, tx_type, bitdepth); \
106   }
107 
108 ihtNxN(4, 16, 10);
109 ihtNxN(4, 16, 12);
110 ihtNxN(8, 64, 10);
111 ihtNxN(8, 64, 12);
112 ihtNxN(16, 256, 10);
113 // ihtNxN(16, 256, 12);
114 
iwht4x4_10(const tran_low_t * in,uint8_t * out,int stride)115 void iwht4x4_10(const tran_low_t *in, uint8_t *out, int stride) {
116   vpx_highbd_iwht4x4_16_add_c(in, CAST_TO_SHORTPTR(out), stride, 10);
117 }
118 
iwht4x4_12(const tran_low_t * in,uint8_t * out,int stride)119 void iwht4x4_12(const tran_low_t *in, uint8_t *out, int stride) {
120   vpx_highbd_iwht4x4_16_add_c(in, CAST_TO_SHORTPTR(out), stride, 12);
121 }
122 #endif  // CONFIG_VP9_HIGHBITDEPTH
123 
124 class TransTestBase {
125  public:
TearDown()126   virtual void TearDown() { libvpx_test::ClearSystemState(); }
127 
128  protected:
129   virtual void RunFwdTxfm(const Buffer<int16_t> &in,
130                           Buffer<tran_low_t> *out) = 0;
131 
132   virtual void RunInvTxfm(const Buffer<tran_low_t> &in, uint8_t *out) = 0;
133 
RunAccuracyCheck(int limit)134   void RunAccuracyCheck(int limit) {
135     ACMRandom rnd(ACMRandom::DeterministicSeed());
136     Buffer<int16_t> test_input_block =
137         Buffer<int16_t>(size_, size_, 8, size_ == 4 ? 0 : 16);
138     ASSERT_TRUE(test_input_block.Init());
139     Buffer<tran_low_t> test_temp_block =
140         Buffer<tran_low_t>(size_, size_, 0, 16);
141     ASSERT_TRUE(test_temp_block.Init());
142     Buffer<uint8_t> dst = Buffer<uint8_t>(size_, size_, 0, 16);
143     ASSERT_TRUE(dst.Init());
144     Buffer<uint8_t> src = Buffer<uint8_t>(size_, size_, 0, 16);
145     ASSERT_TRUE(src.Init());
146 #if CONFIG_VP9_HIGHBITDEPTH
147     Buffer<uint16_t> dst16 = Buffer<uint16_t>(size_, size_, 0, 16);
148     ASSERT_TRUE(dst16.Init());
149     Buffer<uint16_t> src16 = Buffer<uint16_t>(size_, size_, 0, 16);
150     ASSERT_TRUE(src16.Init());
151 #endif  // CONFIG_VP9_HIGHBITDEPTH
152     uint32_t max_error = 0;
153     int64_t total_error = 0;
154     const int count_test_block = 10000;
155     for (int i = 0; i < count_test_block; ++i) {
156       if (bit_depth_ == 8) {
157         src.Set(&rnd, &ACMRandom::Rand8);
158         dst.Set(&rnd, &ACMRandom::Rand8);
159         // Initialize a test block with input range [-255, 255].
160         for (int h = 0; h < size_; ++h) {
161           for (int w = 0; w < size_; ++w) {
162             test_input_block.TopLeftPixel()[h * test_input_block.stride() + w] =
163                 src.TopLeftPixel()[h * src.stride() + w] -
164                 dst.TopLeftPixel()[h * dst.stride() + w];
165           }
166         }
167 #if CONFIG_VP9_HIGHBITDEPTH
168       } else {
169         src16.Set(&rnd, 0, max_pixel_value_);
170         dst16.Set(&rnd, 0, max_pixel_value_);
171         for (int h = 0; h < size_; ++h) {
172           for (int w = 0; w < size_; ++w) {
173             test_input_block.TopLeftPixel()[h * test_input_block.stride() + w] =
174                 src16.TopLeftPixel()[h * src16.stride() + w] -
175                 dst16.TopLeftPixel()[h * dst16.stride() + w];
176           }
177         }
178 #endif  // CONFIG_VP9_HIGHBITDEPTH
179       }
180 
181       ASM_REGISTER_STATE_CHECK(RunFwdTxfm(test_input_block, &test_temp_block));
182       if (bit_depth_ == VPX_BITS_8) {
183         ASM_REGISTER_STATE_CHECK(
184             RunInvTxfm(test_temp_block, dst.TopLeftPixel()));
185 #if CONFIG_VP9_HIGHBITDEPTH
186       } else {
187         ASM_REGISTER_STATE_CHECK(
188             RunInvTxfm(test_temp_block, CAST_TO_BYTEPTR(dst16.TopLeftPixel())));
189 #endif  // CONFIG_VP9_HIGHBITDEPTH
190       }
191 
192       for (int h = 0; h < size_; ++h) {
193         for (int w = 0; w < size_; ++w) {
194           int diff;
195 #if CONFIG_VP9_HIGHBITDEPTH
196           if (bit_depth_ != 8) {
197             diff = dst16.TopLeftPixel()[h * dst16.stride() + w] -
198                    src16.TopLeftPixel()[h * src16.stride() + w];
199           } else {
200 #endif  // CONFIG_VP9_HIGHBITDEPTH
201             diff = dst.TopLeftPixel()[h * dst.stride() + w] -
202                    src.TopLeftPixel()[h * src.stride() + w];
203 #if CONFIG_VP9_HIGHBITDEPTH
204           }
205 #endif  // CONFIG_VP9_HIGHBITDEPTH
206           const uint32_t error = diff * diff;
207           if (max_error < error) max_error = error;
208           total_error += error;
209         }
210       }
211     }
212 
213     EXPECT_GE(static_cast<uint32_t>(limit), max_error)
214         << "Error: 4x4 FHT/IHT has an individual round trip error > " << limit;
215 
216     EXPECT_GE(count_test_block * limit, total_error)
217         << "Error: 4x4 FHT/IHT has average round trip error > " << limit
218         << " per block";
219   }
220 
RunCoeffCheck()221   void RunCoeffCheck() {
222     ACMRandom rnd(ACMRandom::DeterministicSeed());
223     const int count_test_block = 5000;
224     Buffer<int16_t> input_block =
225         Buffer<int16_t>(size_, size_, 8, size_ == 4 ? 0 : 16);
226     ASSERT_TRUE(input_block.Init());
227     Buffer<tran_low_t> output_ref_block = Buffer<tran_low_t>(size_, size_, 0);
228     ASSERT_TRUE(output_ref_block.Init());
229     Buffer<tran_low_t> output_block = Buffer<tran_low_t>(size_, size_, 0, 16);
230     ASSERT_TRUE(output_block.Init());
231 
232     for (int i = 0; i < count_test_block; ++i) {
233       // Initialize a test block with input range [-max_pixel_value_,
234       // max_pixel_value_].
235       input_block.Set(&rnd, -max_pixel_value_, max_pixel_value_);
236 
237       fwd_txfm_ref(input_block, &output_ref_block, size_, tx_type_);
238       ASM_REGISTER_STATE_CHECK(RunFwdTxfm(input_block, &output_block));
239 
240       // The minimum quant value is 4.
241       EXPECT_TRUE(output_block.CheckValues(output_ref_block));
242       if (::testing::Test::HasFailure()) {
243         printf("Size: %d Transform type: %d\n", size_, tx_type_);
244         output_block.PrintDifference(output_ref_block);
245         return;
246       }
247     }
248   }
249 
RunMemCheck()250   void RunMemCheck() {
251     ACMRandom rnd(ACMRandom::DeterministicSeed());
252     const int count_test_block = 5000;
253     Buffer<int16_t> input_extreme_block =
254         Buffer<int16_t>(size_, size_, 8, size_ == 4 ? 0 : 16);
255     ASSERT_TRUE(input_extreme_block.Init());
256     Buffer<tran_low_t> output_ref_block = Buffer<tran_low_t>(size_, size_, 0);
257     ASSERT_TRUE(output_ref_block.Init());
258     Buffer<tran_low_t> output_block = Buffer<tran_low_t>(size_, size_, 0, 16);
259     ASSERT_TRUE(output_block.Init());
260 
261     for (int i = 0; i < count_test_block; ++i) {
262       // Initialize a test block with -max_pixel_value_ or max_pixel_value_.
263       if (i == 0) {
264         input_extreme_block.Set(max_pixel_value_);
265       } else if (i == 1) {
266         input_extreme_block.Set(-max_pixel_value_);
267       } else {
268         for (int h = 0; h < size_; ++h) {
269           for (int w = 0; w < size_; ++w) {
270             input_extreme_block
271                 .TopLeftPixel()[h * input_extreme_block.stride() + w] =
272                 rnd.Rand8() % 2 ? max_pixel_value_ : -max_pixel_value_;
273           }
274         }
275       }
276 
277       fwd_txfm_ref(input_extreme_block, &output_ref_block, size_, tx_type_);
278       ASM_REGISTER_STATE_CHECK(RunFwdTxfm(input_extreme_block, &output_block));
279 
280       // The minimum quant value is 4.
281       EXPECT_TRUE(output_block.CheckValues(output_ref_block));
282       for (int h = 0; h < size_; ++h) {
283         for (int w = 0; w < size_; ++w) {
284           EXPECT_GE(
285               4 * DCT_MAX_VALUE << (bit_depth_ - 8),
286               abs(output_block.TopLeftPixel()[h * output_block.stride() + w]))
287               << "Error: 4x4 FDCT has coefficient larger than "
288                  "4*DCT_MAX_VALUE"
289               << " at " << w << "," << h;
290           if (::testing::Test::HasFailure()) {
291             printf("Size: %d Transform type: %d\n", size_, tx_type_);
292             output_block.DumpBuffer();
293             return;
294           }
295         }
296       }
297     }
298   }
299 
RunInvAccuracyCheck(int limit)300   void RunInvAccuracyCheck(int limit) {
301     ACMRandom rnd(ACMRandom::DeterministicSeed());
302     const int count_test_block = 1000;
303     Buffer<int16_t> in = Buffer<int16_t>(size_, size_, 4);
304     ASSERT_TRUE(in.Init());
305     Buffer<tran_low_t> coeff = Buffer<tran_low_t>(size_, size_, 0, 16);
306     ASSERT_TRUE(coeff.Init());
307     Buffer<uint8_t> dst = Buffer<uint8_t>(size_, size_, 0, 16);
308     ASSERT_TRUE(dst.Init());
309     Buffer<uint8_t> src = Buffer<uint8_t>(size_, size_, 0);
310     ASSERT_TRUE(src.Init());
311     Buffer<uint16_t> dst16 = Buffer<uint16_t>(size_, size_, 0, 16);
312     ASSERT_TRUE(dst16.Init());
313     Buffer<uint16_t> src16 = Buffer<uint16_t>(size_, size_, 0);
314     ASSERT_TRUE(src16.Init());
315 
316     for (int i = 0; i < count_test_block; ++i) {
317       // Initialize a test block with input range [-max_pixel_value_,
318       // max_pixel_value_].
319       if (bit_depth_ == VPX_BITS_8) {
320         src.Set(&rnd, &ACMRandom::Rand8);
321         dst.Set(&rnd, &ACMRandom::Rand8);
322         for (int h = 0; h < size_; ++h) {
323           for (int w = 0; w < size_; ++w) {
324             in.TopLeftPixel()[h * in.stride() + w] =
325                 src.TopLeftPixel()[h * src.stride() + w] -
326                 dst.TopLeftPixel()[h * dst.stride() + w];
327           }
328         }
329 #if CONFIG_VP9_HIGHBITDEPTH
330       } else {
331         src16.Set(&rnd, 0, max_pixel_value_);
332         dst16.Set(&rnd, 0, max_pixel_value_);
333         for (int h = 0; h < size_; ++h) {
334           for (int w = 0; w < size_; ++w) {
335             in.TopLeftPixel()[h * in.stride() + w] =
336                 src16.TopLeftPixel()[h * src16.stride() + w] -
337                 dst16.TopLeftPixel()[h * dst16.stride() + w];
338           }
339         }
340 #endif  // CONFIG_VP9_HIGHBITDEPTH
341       }
342 
343       fwd_txfm_ref(in, &coeff, size_, tx_type_);
344 
345       if (bit_depth_ == VPX_BITS_8) {
346         ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst.TopLeftPixel()));
347 #if CONFIG_VP9_HIGHBITDEPTH
348       } else {
349         ASM_REGISTER_STATE_CHECK(
350             RunInvTxfm(coeff, CAST_TO_BYTEPTR(dst16.TopLeftPixel())));
351 #endif  // CONFIG_VP9_HIGHBITDEPTH
352       }
353 
354       for (int h = 0; h < size_; ++h) {
355         for (int w = 0; w < size_; ++w) {
356           int diff;
357 #if CONFIG_VP9_HIGHBITDEPTH
358           if (bit_depth_ != 8) {
359             diff = dst16.TopLeftPixel()[h * dst16.stride() + w] -
360                    src16.TopLeftPixel()[h * src16.stride() + w];
361           } else {
362 #endif  // CONFIG_VP9_HIGHBITDEPTH
363             diff = dst.TopLeftPixel()[h * dst.stride() + w] -
364                    src.TopLeftPixel()[h * src.stride() + w];
365 #if CONFIG_VP9_HIGHBITDEPTH
366           }
367 #endif  // CONFIG_VP9_HIGHBITDEPTH
368           const uint32_t error = diff * diff;
369           EXPECT_GE(static_cast<uint32_t>(limit), error)
370               << "Error: " << size_ << "x" << size_ << " IDCT has error "
371               << error << " at " << w << "," << h;
372         }
373       }
374     }
375   }
376 
377   FhtFuncRef fwd_txfm_ref;
378   vpx_bit_depth_t bit_depth_;
379   int tx_type_;
380   int max_pixel_value_;
381   int size_;
382 };
383 
384 class TransDCT : public TransTestBase,
385                  public ::testing::TestWithParam<DctParam> {
386  public:
TransDCT()387   TransDCT() {
388     fwd_txfm_ref = fdct_ref;
389     fwd_txfm_ = GET_PARAM(0);
390     inv_txfm_ = GET_PARAM(1);
391     size_ = GET_PARAM(2);
392     tx_type_ = GET_PARAM(3);
393     bit_depth_ = GET_PARAM(4);
394     max_pixel_value_ = (1 << bit_depth_) - 1;
395   }
396 
397  protected:
RunFwdTxfm(const Buffer<int16_t> & in,Buffer<tran_low_t> * out)398   void RunFwdTxfm(const Buffer<int16_t> &in, Buffer<tran_low_t> *out) {
399     fwd_txfm_(in.TopLeftPixel(), out->TopLeftPixel(), in.stride());
400   }
401 
RunInvTxfm(const Buffer<tran_low_t> & in,uint8_t * out)402   void RunInvTxfm(const Buffer<tran_low_t> &in, uint8_t *out) {
403     inv_txfm_(in.TopLeftPixel(), out, in.stride());
404   }
405 
406   FdctFunc fwd_txfm_;
407   IdctFunc inv_txfm_;
408 };
409 
TEST_P(TransDCT,AccuracyCheck)410 TEST_P(TransDCT, AccuracyCheck) { RunAccuracyCheck(1); }
411 
TEST_P(TransDCT,CoeffCheck)412 TEST_P(TransDCT, CoeffCheck) { RunCoeffCheck(); }
413 
TEST_P(TransDCT,MemCheck)414 TEST_P(TransDCT, MemCheck) { RunMemCheck(); }
415 
TEST_P(TransDCT,InvAccuracyCheck)416 TEST_P(TransDCT, InvAccuracyCheck) { RunInvAccuracyCheck(1); }
417 
418 #if CONFIG_VP9_HIGHBITDEPTH
419 INSTANTIATE_TEST_CASE_P(
420     C, TransDCT,
421     ::testing::Values(
422         make_tuple(&vpx_highbd_fdct32x32_c, &idct32x32_10, 32, 0, VPX_BITS_10),
423         make_tuple(&vpx_highbd_fdct32x32_c, &idct32x32_12, 32, 0, VPX_BITS_10),
424         make_tuple(&vpx_fdct32x32_c, &vpx_idct32x32_1024_add_c, 32, 0,
425                    VPX_BITS_8),
426         make_tuple(&vpx_highbd_fdct16x16_c, &idct16x16_10, 16, 0, VPX_BITS_10),
427         make_tuple(&vpx_highbd_fdct16x16_c, &idct16x16_12, 16, 0, VPX_BITS_10),
428         make_tuple(&vpx_fdct16x16_c, &vpx_idct16x16_256_add_c, 16, 0,
429                    VPX_BITS_8),
430         make_tuple(&vpx_highbd_fdct8x8_c, &idct8x8_10, 8, 0, VPX_BITS_10),
431         make_tuple(&vpx_highbd_fdct8x8_c, &idct8x8_12, 8, 0, VPX_BITS_10),
432         make_tuple(&vpx_fdct8x8_c, &vpx_idct8x8_64_add_c, 8, 0, VPX_BITS_8),
433         make_tuple(&vpx_highbd_fdct4x4_c, &idct4x4_10, 4, 0, VPX_BITS_10),
434         make_tuple(&vpx_highbd_fdct4x4_c, &idct4x4_12, 4, 0, VPX_BITS_12),
435         make_tuple(&vpx_fdct4x4_c, &vpx_idct4x4_16_add_c, 4, 0, VPX_BITS_8)));
436 #else
437 INSTANTIATE_TEST_CASE_P(
438     C, TransDCT,
439     ::testing::Values(
440         make_tuple(&vpx_fdct32x32_c, &vpx_idct32x32_1024_add_c, 32, 0,
441                    VPX_BITS_8),
442         make_tuple(&vpx_fdct16x16_c, &vpx_idct16x16_256_add_c, 16, 0,
443                    VPX_BITS_8),
444         make_tuple(&vpx_fdct8x8_c, &vpx_idct8x8_64_add_c, 8, 0, VPX_BITS_8),
445         make_tuple(&vpx_fdct4x4_c, &vpx_idct4x4_16_add_c, 4, 0, VPX_BITS_8)));
446 #endif  // CONFIG_VP9_HIGHBITDEPTH
447 
448 #if HAVE_SSE2
449 #if !CONFIG_EMULATE_HARDWARE
450 #if CONFIG_VP9_HIGHBITDEPTH
451 /* TODO:(johannkoenig) Determine why these fail AccuracyCheck
452    make_tuple(&vpx_highbd_fdct32x32_sse2, &idct32x32_12, 32, 0, VPX_BITS_12),
453    make_tuple(&vpx_highbd_fdct16x16_sse2, &idct16x16_12, 16, 0, VPX_BITS_12),
454 */
455 INSTANTIATE_TEST_CASE_P(
456     SSE2, TransDCT,
457     ::testing::Values(
458         make_tuple(&vpx_highbd_fdct32x32_sse2, &idct32x32_10, 32, 0,
459                    VPX_BITS_10),
460         make_tuple(&vpx_fdct32x32_sse2, &vpx_idct32x32_1024_add_sse2, 32, 0,
461                    VPX_BITS_8),
462         make_tuple(&vpx_highbd_fdct16x16_sse2, &idct16x16_10, 16, 0,
463                    VPX_BITS_10),
464         make_tuple(&vpx_fdct16x16_sse2, &vpx_idct16x16_256_add_sse2, 16, 0,
465                    VPX_BITS_8),
466         make_tuple(&vpx_highbd_fdct8x8_sse2, &idct8x8_10, 8, 0, VPX_BITS_10),
467         make_tuple(&vpx_highbd_fdct8x8_sse2, &idct8x8_12, 8, 0, VPX_BITS_12),
468         make_tuple(&vpx_fdct8x8_sse2, &vpx_idct8x8_64_add_sse2, 8, 0,
469                    VPX_BITS_8),
470         make_tuple(&vpx_highbd_fdct4x4_sse2, &idct4x4_10, 4, 0, VPX_BITS_10),
471         make_tuple(&vpx_highbd_fdct4x4_sse2, &idct4x4_12, 4, 0, VPX_BITS_12),
472         make_tuple(&vpx_fdct4x4_sse2, &vpx_idct4x4_16_add_sse2, 4, 0,
473                    VPX_BITS_8)));
474 #else
475 INSTANTIATE_TEST_CASE_P(
476     SSE2, TransDCT,
477     ::testing::Values(make_tuple(&vpx_fdct32x32_sse2,
478                                  &vpx_idct32x32_1024_add_sse2, 32, 0,
479                                  VPX_BITS_8),
480                       make_tuple(&vpx_fdct16x16_sse2,
481                                  &vpx_idct16x16_256_add_sse2, 16, 0,
482                                  VPX_BITS_8),
483                       make_tuple(&vpx_fdct8x8_sse2, &vpx_idct8x8_64_add_sse2, 8,
484                                  0, VPX_BITS_8),
485                       make_tuple(&vpx_fdct4x4_sse2, &vpx_idct4x4_16_add_sse2, 4,
486                                  0, VPX_BITS_8)));
487 #endif  // CONFIG_VP9_HIGHBITDEPTH
488 #endif  // !CONFIG_EMULATE_HARDWARE
489 #endif  // HAVE_SSE2
490 
491 #if !CONFIG_VP9_HIGHBITDEPTH
492 #if HAVE_SSSE3 && !CONFIG_EMULATE_HARDWARE
493 #if !ARCH_X86_64
494 // TODO(johannkoenig): high bit depth fdct8x8.
495 INSTANTIATE_TEST_CASE_P(
496     SSSE3, TransDCT,
497     ::testing::Values(make_tuple(&vpx_fdct32x32_c, &vpx_idct32x32_1024_add_sse2,
498                                  32, 0, VPX_BITS_8),
499                       make_tuple(&vpx_fdct8x8_c, &vpx_idct8x8_64_add_sse2, 8, 0,
500                                  VPX_BITS_8)));
501 #else
502 // vpx_fdct8x8_ssse3 is only available in 64 bit builds.
503 INSTANTIATE_TEST_CASE_P(
504     SSSE3, TransDCT,
505     ::testing::Values(make_tuple(&vpx_fdct32x32_c, &vpx_idct32x32_1024_add_sse2,
506                                  32, 0, VPX_BITS_8),
507                       make_tuple(&vpx_fdct8x8_ssse3, &vpx_idct8x8_64_add_sse2,
508                                  8, 0, VPX_BITS_8)));
509 #endif  // !ARCH_X86_64
510 #endif  // HAVE_SSSE3 && !CONFIG_EMULATE_HARDWARE
511 #endif  // !CONFIG_VP9_HIGHBITDEPTH
512 
513 #if !CONFIG_VP9_HIGHBITDEPTH && HAVE_AVX2 && !CONFIG_EMULATE_HARDWARE
514 // TODO(johannkoenig): high bit depth fdct32x32.
515 INSTANTIATE_TEST_CASE_P(
516     AVX2, TransDCT, ::testing::Values(make_tuple(&vpx_fdct32x32_avx2,
517                                                  &vpx_idct32x32_1024_add_sse2,
518                                                  32, 0, VPX_BITS_8)));
519 
520 #endif  // !CONFIG_VP9_HIGHBITDEPTH && HAVE_AVX2 && !CONFIG_EMULATE_HARDWARE
521 
522 #if HAVE_NEON
523 #if !CONFIG_EMULATE_HARDWARE
524 INSTANTIATE_TEST_CASE_P(
525     NEON, TransDCT,
526     ::testing::Values(make_tuple(&vpx_fdct32x32_neon,
527                                  &vpx_idct32x32_1024_add_neon, 32, 0,
528                                  VPX_BITS_8),
529                       make_tuple(&vpx_fdct16x16_neon,
530                                  &vpx_idct16x16_256_add_neon, 16, 0,
531                                  VPX_BITS_8),
532                       make_tuple(&vpx_fdct8x8_neon, &vpx_idct8x8_64_add_neon, 8,
533                                  0, VPX_BITS_8),
534                       make_tuple(&vpx_fdct4x4_neon, &vpx_idct4x4_16_add_neon, 4,
535                                  0, VPX_BITS_8)));
536 #endif  // !CONFIG_EMULATE_HARDWARE
537 #endif  // HAVE_NEON
538 
539 #if HAVE_MSA
540 #if !CONFIG_VP9_HIGHBITDEPTH
541 #if !CONFIG_EMULATE_HARDWARE
542 INSTANTIATE_TEST_CASE_P(
543     MSA, TransDCT,
544     ::testing::Values(
545         make_tuple(&vpx_fdct32x32_msa, &vpx_idct32x32_1024_add_msa, 32, 0,
546                    VPX_BITS_8),
547         make_tuple(&vpx_fdct16x16_msa, &vpx_idct16x16_256_add_msa, 16, 0,
548                    VPX_BITS_8),
549         make_tuple(&vpx_fdct8x8_msa, &vpx_idct8x8_64_add_msa, 8, 0, VPX_BITS_8),
550         make_tuple(&vpx_fdct4x4_msa, &vpx_idct4x4_16_add_msa, 4, 0,
551                    VPX_BITS_8)));
552 #endif  // !CONFIG_EMULATE_HARDWARE
553 #endif  // !CONFIG_VP9_HIGHBITDEPTH
554 #endif  // HAVE_MSA
555 
556 #if HAVE_VSX && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
557 INSTANTIATE_TEST_CASE_P(VSX, TransDCT,
558                         ::testing::Values(make_tuple(&vpx_fdct4x4_c,
559                                                      &vpx_idct4x4_16_add_vsx, 4,
560                                                      0, VPX_BITS_8)));
561 #endif  // HAVE_VSX && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
562 
563 class TransHT : public TransTestBase, public ::testing::TestWithParam<HtParam> {
564  public:
TransHT()565   TransHT() {
566     fwd_txfm_ref = fht_ref;
567     fwd_txfm_ = GET_PARAM(0);
568     inv_txfm_ = GET_PARAM(1);
569     size_ = GET_PARAM(2);
570     tx_type_ = GET_PARAM(3);
571     bit_depth_ = GET_PARAM(4);
572     max_pixel_value_ = (1 << bit_depth_) - 1;
573   }
574 
575  protected:
RunFwdTxfm(const Buffer<int16_t> & in,Buffer<tran_low_t> * out)576   void RunFwdTxfm(const Buffer<int16_t> &in, Buffer<tran_low_t> *out) {
577     fwd_txfm_(in.TopLeftPixel(), out->TopLeftPixel(), in.stride(), tx_type_);
578   }
579 
RunInvTxfm(const Buffer<tran_low_t> & in,uint8_t * out)580   void RunInvTxfm(const Buffer<tran_low_t> &in, uint8_t *out) {
581     inv_txfm_(in.TopLeftPixel(), out, in.stride(), tx_type_);
582   }
583 
584   FhtFunc fwd_txfm_;
585   IhtFunc inv_txfm_;
586 };
587 
TEST_P(TransHT,AccuracyCheck)588 TEST_P(TransHT, AccuracyCheck) { RunAccuracyCheck(1); }
589 
TEST_P(TransHT,CoeffCheck)590 TEST_P(TransHT, CoeffCheck) { RunCoeffCheck(); }
591 
TEST_P(TransHT,MemCheck)592 TEST_P(TransHT, MemCheck) { RunMemCheck(); }
593 
TEST_P(TransHT,InvAccuracyCheck)594 TEST_P(TransHT, InvAccuracyCheck) { RunInvAccuracyCheck(1); }
595 
596 /* TODO:(johannkoenig) Determine why these fail AccuracyCheck
597    make_tuple(&vp9_highbd_fht16x16_c, &iht16x16_12, 16, 0, VPX_BITS_12),
598    make_tuple(&vp9_highbd_fht16x16_c, &iht16x16_12, 16, 1, VPX_BITS_12),
599    make_tuple(&vp9_highbd_fht16x16_c, &iht16x16_12, 16, 2, VPX_BITS_12),
600    make_tuple(&vp9_highbd_fht16x16_c, &iht16x16_12, 16, 3, VPX_BITS_12),
601   */
602 #if CONFIG_VP9_HIGHBITDEPTH
603 INSTANTIATE_TEST_CASE_P(
604     C, TransHT,
605     ::testing::Values(
606         make_tuple(&vp9_highbd_fht16x16_c, &iht16x16_10, 16, 0, VPX_BITS_10),
607         make_tuple(&vp9_highbd_fht16x16_c, &iht16x16_10, 16, 1, VPX_BITS_10),
608         make_tuple(&vp9_highbd_fht16x16_c, &iht16x16_10, 16, 2, VPX_BITS_10),
609         make_tuple(&vp9_highbd_fht16x16_c, &iht16x16_10, 16, 3, VPX_BITS_10),
610         make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 16, 0, VPX_BITS_8),
611         make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 16, 1, VPX_BITS_8),
612         make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 16, 2, VPX_BITS_8),
613         make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 16, 3, VPX_BITS_8),
614         make_tuple(&vp9_highbd_fht8x8_c, &iht8x8_10, 8, 0, VPX_BITS_10),
615         make_tuple(&vp9_highbd_fht8x8_c, &iht8x8_10, 8, 1, VPX_BITS_10),
616         make_tuple(&vp9_highbd_fht8x8_c, &iht8x8_10, 8, 2, VPX_BITS_10),
617         make_tuple(&vp9_highbd_fht8x8_c, &iht8x8_10, 8, 3, VPX_BITS_10),
618         make_tuple(&vp9_highbd_fht8x8_c, &iht8x8_12, 8, 0, VPX_BITS_12),
619         make_tuple(&vp9_highbd_fht8x8_c, &iht8x8_12, 8, 1, VPX_BITS_12),
620         make_tuple(&vp9_highbd_fht8x8_c, &iht8x8_12, 8, 2, VPX_BITS_12),
621         make_tuple(&vp9_highbd_fht8x8_c, &iht8x8_12, 8, 3, VPX_BITS_12),
622         make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 8, 0, VPX_BITS_8),
623         make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 8, 1, VPX_BITS_8),
624         make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 8, 2, VPX_BITS_8),
625         make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 8, 3, VPX_BITS_8),
626         make_tuple(&vp9_highbd_fht4x4_c, &iht4x4_10, 4, 0, VPX_BITS_10),
627         make_tuple(&vp9_highbd_fht4x4_c, &iht4x4_10, 4, 1, VPX_BITS_10),
628         make_tuple(&vp9_highbd_fht4x4_c, &iht4x4_10, 4, 2, VPX_BITS_10),
629         make_tuple(&vp9_highbd_fht4x4_c, &iht4x4_10, 4, 3, VPX_BITS_10),
630         make_tuple(&vp9_highbd_fht4x4_c, &iht4x4_12, 4, 0, VPX_BITS_12),
631         make_tuple(&vp9_highbd_fht4x4_c, &iht4x4_12, 4, 1, VPX_BITS_12),
632         make_tuple(&vp9_highbd_fht4x4_c, &iht4x4_12, 4, 2, VPX_BITS_12),
633         make_tuple(&vp9_highbd_fht4x4_c, &iht4x4_12, 4, 3, VPX_BITS_12),
634         make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_c, 4, 0, VPX_BITS_8),
635         make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_c, 4, 1, VPX_BITS_8),
636         make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_c, 4, 2, VPX_BITS_8),
637         make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_c, 4, 3, VPX_BITS_8)));
638 #else
639 INSTANTIATE_TEST_CASE_P(
640     C, TransHT,
641     ::testing::Values(
642         make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 16, 0, VPX_BITS_8),
643         make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 16, 1, VPX_BITS_8),
644         make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 16, 2, VPX_BITS_8),
645         make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 16, 3, VPX_BITS_8),
646 
647         make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 8, 0, VPX_BITS_8),
648         make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 8, 1, VPX_BITS_8),
649         make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 8, 2, VPX_BITS_8),
650         make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 8, 3, VPX_BITS_8),
651 
652         make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_c, 4, 0, VPX_BITS_8),
653         make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_c, 4, 1, VPX_BITS_8),
654         make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_c, 4, 2, VPX_BITS_8),
655         make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_c, 4, 3, VPX_BITS_8)));
656 #endif  // CONFIG_VP9_HIGHBITDEPTH
657 
658 #if HAVE_SSE2
659 INSTANTIATE_TEST_CASE_P(
660     SSE2, TransHT,
661     ::testing::Values(
662         make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 16, 0,
663                    VPX_BITS_8),
664         make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 16, 1,
665                    VPX_BITS_8),
666         make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 16, 2,
667                    VPX_BITS_8),
668         make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 16, 3,
669                    VPX_BITS_8),
670 
671         make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_sse2, 8, 0, VPX_BITS_8),
672         make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_sse2, 8, 1, VPX_BITS_8),
673         make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_sse2, 8, 2, VPX_BITS_8),
674         make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_sse2, 8, 3, VPX_BITS_8),
675 
676         make_tuple(&vp9_fht4x4_sse2, &vp9_iht4x4_16_add_sse2, 4, 0, VPX_BITS_8),
677         make_tuple(&vp9_fht4x4_sse2, &vp9_iht4x4_16_add_sse2, 4, 1, VPX_BITS_8),
678         make_tuple(&vp9_fht4x4_sse2, &vp9_iht4x4_16_add_sse2, 4, 2, VPX_BITS_8),
679         make_tuple(&vp9_fht4x4_sse2, &vp9_iht4x4_16_add_sse2, 4, 3,
680                    VPX_BITS_8)));
681 #endif  // HAVE_SSE2
682 
683 class TransWHT : public TransTestBase,
684                  public ::testing::TestWithParam<DctParam> {
685  public:
TransWHT()686   TransWHT() {
687     fwd_txfm_ref = fwht_ref;
688     fwd_txfm_ = GET_PARAM(0);
689     inv_txfm_ = GET_PARAM(1);
690     size_ = GET_PARAM(2);
691     tx_type_ = GET_PARAM(3);
692     bit_depth_ = GET_PARAM(4);
693     max_pixel_value_ = (1 << bit_depth_) - 1;
694   }
695 
696  protected:
RunFwdTxfm(const Buffer<int16_t> & in,Buffer<tran_low_t> * out)697   void RunFwdTxfm(const Buffer<int16_t> &in, Buffer<tran_low_t> *out) {
698     fwd_txfm_(in.TopLeftPixel(), out->TopLeftPixel(), in.stride());
699   }
700 
RunInvTxfm(const Buffer<tran_low_t> & in,uint8_t * out)701   void RunInvTxfm(const Buffer<tran_low_t> &in, uint8_t *out) {
702     inv_txfm_(in.TopLeftPixel(), out, in.stride());
703   }
704 
705   FdctFunc fwd_txfm_;
706   IdctFunc inv_txfm_;
707 };
708 
TEST_P(TransWHT,AccuracyCheck)709 TEST_P(TransWHT, AccuracyCheck) { RunAccuracyCheck(0); }
710 
TEST_P(TransWHT,CoeffCheck)711 TEST_P(TransWHT, CoeffCheck) { RunCoeffCheck(); }
712 
TEST_P(TransWHT,MemCheck)713 TEST_P(TransWHT, MemCheck) { RunMemCheck(); }
714 
TEST_P(TransWHT,InvAccuracyCheck)715 TEST_P(TransWHT, InvAccuracyCheck) { RunInvAccuracyCheck(0); }
716 
717 #if CONFIG_VP9_HIGHBITDEPTH
718 INSTANTIATE_TEST_CASE_P(
719     C, TransWHT,
720     ::testing::Values(
721         make_tuple(&vp9_highbd_fwht4x4_c, &iwht4x4_10, 4, 0, VPX_BITS_10),
722         make_tuple(&vp9_highbd_fwht4x4_c, &iwht4x4_12, 4, 0, VPX_BITS_12),
723         make_tuple(&vp9_fwht4x4_c, &vpx_iwht4x4_16_add_c, 4, 0, VPX_BITS_8)));
724 #else
725 INSTANTIATE_TEST_CASE_P(C, TransWHT,
726                         ::testing::Values(make_tuple(&vp9_fwht4x4_c,
727                                                      &vpx_iwht4x4_16_add_c, 4,
728                                                      0, VPX_BITS_8)));
729 #endif  // CONFIG_VP9_HIGHBITDEPTH
730 
731 #if HAVE_SSE2
732 INSTANTIATE_TEST_CASE_P(SSE2, TransWHT,
733                         ::testing::Values(make_tuple(&vp9_fwht4x4_sse2,
734                                                      &vpx_iwht4x4_16_add_sse2,
735                                                      4, 0, VPX_BITS_8)));
736 #endif  // HAVE_SSE2
737 }  // namespace
738