1 // Copyright 2021 The libgav1 Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "src/dsp/inverse_transform.h"
16
17 #include <algorithm>
18 #include <cstdint>
19 #include <cstdio>
20 #include <cstring>
21 #include <ostream>
22
23 #include "absl/strings/match.h"
24 #include "absl/time/clock.h"
25 #include "absl/time/time.h"
26 #include "gtest/gtest.h"
27 #include "src/dsp/constants.h"
28 #include "src/dsp/dsp.h"
29 #include "src/utils/array_2d.h"
30 #include "src/utils/bit_mask_set.h"
31 #include "src/utils/common.h"
32 #include "src/utils/constants.h"
33 #include "src/utils/cpu.h"
34 #include "src/utils/memory.h"
35 #include "tests/block_utils.h"
36 #include "tests/third_party/libvpx/acm_random.h"
37 #include "tests/utils.h"
38
39 namespace libgav1 {
40 namespace dsp {
41 namespace {
42
43 constexpr int kMaxBlockSize = 64;
44 constexpr int kTotalPixels = kMaxBlockSize * kMaxBlockSize;
45
46 const char* const kTransform1dSizeNames[kNumTransform1dSizes] = {
47 "kTransform1dSize4", "kTransform1dSize8", "kTransform1dSize16",
48 "kTransform1dSize32", "kTransform1dSize64"};
49
50 constexpr Transform1dSize kRowTransform1dSizes[] = {
51 kTransform1dSize4, kTransform1dSize4, kTransform1dSize4,
52 kTransform1dSize8, kTransform1dSize8, kTransform1dSize8,
53 kTransform1dSize8, kTransform1dSize16, kTransform1dSize16,
54 kTransform1dSize16, kTransform1dSize16, kTransform1dSize16,
55 kTransform1dSize32, kTransform1dSize32, kTransform1dSize32,
56 kTransform1dSize32, kTransform1dSize64, kTransform1dSize64,
57 kTransform1dSize64};
58
59 constexpr Transform1dSize kColTransform1dSizes[] = {
60 kTransform1dSize4, kTransform1dSize8, kTransform1dSize16,
61 kTransform1dSize4, kTransform1dSize8, kTransform1dSize16,
62 kTransform1dSize32, kTransform1dSize4, kTransform1dSize8,
63 kTransform1dSize16, kTransform1dSize32, kTransform1dSize64,
64 kTransform1dSize8, kTransform1dSize16, kTransform1dSize32,
65 kTransform1dSize64, kTransform1dSize16, kTransform1dSize32,
66 kTransform1dSize64};
67
68 template <int bitdepth, typename SrcPixel, typename DstPixel>
69 class InverseTransformTestBase : public testing::TestWithParam<TransformSize>,
70 public test_utils::MaxAlignedAllocable {
71 public:
72 static_assert(bitdepth >= kBitdepth8 && bitdepth <= LIBGAV1_MAX_BITDEPTH, "");
InverseTransformTestBase()73 InverseTransformTestBase() {
74 switch (tx_size_) {
75 case kNumTransformSizes:
76 EXPECT_NE(tx_size_, kNumTransformSizes);
77 break;
78 default:
79 block_width_ = kTransformWidth[tx_size_];
80 block_height_ = kTransformHeight[tx_size_];
81 break;
82 }
83 }
84
85 InverseTransformTestBase(const InverseTransformTestBase&) = delete;
86 InverseTransformTestBase& operator=(const InverseTransformTestBase&) = delete;
87 ~InverseTransformTestBase() override = default;
88
89 protected:
90 struct InverseTransformMem {
Resetlibgav1::dsp::__anon6944daf30111::InverseTransformTestBase::InverseTransformMem91 void Reset(libvpx_test::ACMRandom* rnd, int width, int height) {
92 ASSERT_NE(rnd, nullptr);
93 // Limit the size of the residual values to bitdepth + sign in order
94 // to prevent outranging in the transforms.
95 const int num_bits = bitdepth + 1;
96 const int sign_shift = (bitdepth == 8 ? 16 : 32) - num_bits;
97 const int mask = (1 << num_bits) - 1;
98 // Fill residual with random data. For widths == 64, only fill the upper
99 // left 32 x min(block_height_, 32).
100 memset(ref_src, 0, sizeof(ref_src));
101 SrcPixel* r = ref_src;
102 const int stride = width;
103 for (int y = 0; y < std::min(height, 32); ++y) {
104 for (int x = 0; x < std::min(width, 32); ++x) {
105 r[x] = rnd->Rand16() & mask;
106 // The msb of num_bits is the sign bit, so force each 16 bit value to
107 // the correct sign.
108 r[x] = (r[x] << sign_shift) >> sign_shift;
109 }
110 r += stride;
111 }
112
113 // Set frame data to random values.
114 for (int y = 0; y < kMaxBlockSize; ++y) {
115 for (int x = 0; x < kMaxBlockSize; ++x) {
116 const int mask = (1 << bitdepth) - 1;
117 cur_frame[y * kMaxBlockSize + x] = base_frame[y * kMaxBlockSize + x] =
118 rnd->Rand16() & mask;
119 }
120 }
121 }
122
123 // Set ref_src to |pixel|.
Setlibgav1::dsp::__anon6944daf30111::InverseTransformTestBase::InverseTransformMem124 void Set(const SrcPixel pixel) {
125 for (auto& r : ref_src) r = pixel;
126 }
127
128 alignas(kMaxAlignment) DstPixel base_frame[kTotalPixels];
129 alignas(kMaxAlignment) DstPixel cur_frame[kTotalPixels];
130
131 alignas(kMaxAlignment) SrcPixel base_residual[kTotalPixels];
132 alignas(kMaxAlignment) SrcPixel cur_residual[kTotalPixels];
133
134 alignas(kMaxAlignment) SrcPixel ref_src[kTotalPixels];
135 };
136
SetUp()137 void SetUp() override { test_utils::ResetDspTable(bitdepth); }
138
139 const TransformSize tx_size_ = GetParam();
140 int block_width_;
141 int block_height_;
142 InverseTransformMem inverse_transform_mem_;
143 };
144
145 //------------------------------------------------------------------------------
146 // InverseTransformTest
147
148 template <int bitdepth, typename Pixel, typename DstPixel>
149 class InverseTransformTest
150 : public InverseTransformTestBase<bitdepth, Pixel, DstPixel> {
151 public:
152 static_assert(bitdepth >= kBitdepth8 && bitdepth <= LIBGAV1_MAX_BITDEPTH, "");
153 InverseTransformTest() = default;
154 InverseTransformTest(const InverseTransformTest&) = delete;
155 InverseTransformTest& operator=(const InverseTransformTest&) = delete;
156 ~InverseTransformTest() override = default;
157
158 protected:
159 using InverseTransformTestBase<bitdepth, Pixel, DstPixel>::tx_size_;
160 using InverseTransformTestBase<bitdepth, Pixel, DstPixel>::block_width_;
161 using InverseTransformTestBase<bitdepth, Pixel, DstPixel>::block_height_;
162 using InverseTransformTestBase<bitdepth, Pixel,
163 DstPixel>::inverse_transform_mem_;
164
SetUp()165 void SetUp() override {
166 InverseTransformTestBase<bitdepth, Pixel, DstPixel>::SetUp();
167 InverseTransformInit_C();
168
169 const Dsp* const dsp = GetDspTable(bitdepth);
170 ASSERT_NE(dsp, nullptr);
171
172 tx_size_1d_row_ = kRowTransform1dSizes[tx_size_];
173 tx_size_1d_column_ = kColTransform1dSizes[tx_size_];
174
175 memcpy(base_inverse_transforms_, dsp->inverse_transforms,
176 sizeof(base_inverse_transforms_));
177
178 const testing::TestInfo* const test_info =
179 testing::UnitTest::GetInstance()->current_test_info();
180 const char* const test_case = test_info->test_suite_name();
181 if (absl::StartsWith(test_case, "C/")) {
182 memset(base_inverse_transforms_, 0, sizeof(base_inverse_transforms_));
183 } else if (absl::StartsWith(test_case, "SSE41/")) {
184 if ((GetCpuInfo() & kSSE4_1) == 0) GTEST_SKIP() << "No SSE4.1 support!";
185 InverseTransformInit_SSE4_1();
186 } else if (absl::StartsWith(test_case, "NEON/")) {
187 InverseTransformInit_NEON();
188 InverseTransformInit10bpp_NEON();
189 } else {
190 FAIL() << "Unrecognized architecture prefix in test case name: "
191 << test_case;
192 }
193
194 memcpy(cur_inverse_transforms_, dsp->inverse_transforms,
195 sizeof(cur_inverse_transforms_));
196
197 for (int i = 0; i < kNumTransform1ds; ++i) {
198 // skip functions that haven't been specialized for this particular
199 // architecture.
200 if (cur_inverse_transforms_[i][tx_size_1d_row_][kRow] ==
201 base_inverse_transforms_[i][tx_size_1d_row_][kRow]) {
202 cur_inverse_transforms_[i][tx_size_1d_row_][kRow] = nullptr;
203 }
204 if (cur_inverse_transforms_[i][tx_size_1d_column_][kColumn] ==
205 base_inverse_transforms_[i][tx_size_1d_column_][kColumn]) {
206 cur_inverse_transforms_[i][tx_size_1d_column_][kColumn] = nullptr;
207 }
208 }
209
210 base_frame_buffer_.Reset(kMaxBlockSize, kMaxBlockSize,
211 inverse_transform_mem_.base_frame);
212
213 cur_frame_buffer_.Reset(kMaxBlockSize, kMaxBlockSize,
214 inverse_transform_mem_.cur_frame);
215 }
216
217 // These tests modify inverse_transform_mem_.
218 void TestRandomValues(int num_tests);
219 void TestDcOnlyRandomValue(int num_tests);
220
221 Array2DView<DstPixel> base_frame_buffer_;
222 Array2DView<DstPixel> cur_frame_buffer_;
223
224 Transform1dSize tx_size_1d_row_ = kTransform1dSize4;
225 Transform1dSize tx_size_1d_column_ = kTransform1dSize4;
226
227 InverseTransformAddFuncs base_inverse_transforms_;
228 InverseTransformAddFuncs cur_inverse_transforms_;
229 };
230
231 constexpr TransformType kLibgav1TxType[kNumTransformTypes] = {
232 kTransformTypeDctDct, kTransformTypeAdstDct,
233 kTransformTypeDctAdst, kTransformTypeAdstAdst,
234 kTransformTypeFlipadstDct, kTransformTypeDctFlipadst,
235 kTransformTypeFlipadstFlipadst, kTransformTypeAdstFlipadst,
236 kTransformTypeFlipadstAdst, kTransformTypeIdentityIdentity,
237 kTransformTypeIdentityDct, kTransformTypeDctIdentity,
238 kTransformTypeIdentityAdst, kTransformTypeAdstIdentity,
239 kTransformTypeIdentityFlipadst, kTransformTypeFlipadstIdentity};
240
241 // Maps TransformType to dsp::Transform1d for the row transforms.
242 constexpr Transform1d kRowTransform[kNumTransformTypes] = {
243 kTransform1dDct, kTransform1dAdst, kTransform1dDct,
244 kTransform1dAdst, kTransform1dAdst, kTransform1dDct,
245 kTransform1dAdst, kTransform1dAdst, kTransform1dAdst,
246 kTransform1dIdentity, kTransform1dIdentity, kTransform1dDct,
247 kTransform1dIdentity, kTransform1dAdst, kTransform1dIdentity,
248 kTransform1dAdst};
249
250 // Maps TransformType to dsp::Transform1d for the column transforms.
251 constexpr Transform1d kColumnTransform[kNumTransformTypes] = {
252 kTransform1dDct, kTransform1dDct, kTransform1dAdst,
253 kTransform1dAdst, kTransform1dDct, kTransform1dAdst,
254 kTransform1dAdst, kTransform1dAdst, kTransform1dAdst,
255 kTransform1dIdentity, kTransform1dDct, kTransform1dIdentity,
256 kTransform1dAdst, kTransform1dIdentity, kTransform1dAdst,
257 kTransform1dIdentity};
258
259 // Mask indicating whether the transform sets contain a particular transform
260 // type. If |tx_type| is present in |tx_set|, then the |tx_type|th LSB is set.
261 constexpr BitMaskSet kTransformTypeInSetMask[kNumTransformSets] = {
262 BitMaskSet(0x1), BitMaskSet(0xE0F), BitMaskSet(0x20F),
263 BitMaskSet(0xFFFF), BitMaskSet(0xFFF), BitMaskSet(0x201)};
264
IsTxSizeTypeValid(TransformSize tx_size,TransformType tx_type)265 bool IsTxSizeTypeValid(TransformSize tx_size, TransformType tx_type) {
266 const TransformSize tx_size_square_max = kTransformSizeSquareMax[tx_size];
267 TransformSet tx_set;
268 if (tx_size_square_max > kTransformSize32x32) {
269 tx_set = kTransformSetDctOnly;
270 } else if (tx_size_square_max == kTransformSize32x32) {
271 tx_set = kTransformSetInter3;
272 } else if (tx_size_square_max == kTransformSize16x16) {
273 tx_set = kTransformSetInter2;
274 } else {
275 tx_set = kTransformSetInter1;
276 }
277 return kTransformTypeInSetMask[tx_set].Contains(tx_type);
278 }
279
280 template <int bitdepth, typename Pixel, typename DstPixel>
TestRandomValues(int num_tests)281 void InverseTransformTest<bitdepth, Pixel, DstPixel>::TestRandomValues(
282 int num_tests) {
283 libvpx_test::ACMRandom rnd(libvpx_test::ACMRandom::DeterministicSeed());
284
285 for (int tx_type_idx = -1; tx_type_idx < kNumTransformTypes; ++tx_type_idx) {
286 const TransformType tx_type = (tx_type_idx == -1)
287 ? kTransformTypeDctDct
288 : kLibgav1TxType[tx_type_idx];
289 const Transform1d row_transform =
290 (tx_type_idx == -1) ? kTransform1dWht : kRowTransform[tx_type];
291 const Transform1d column_transform =
292 (tx_type_idx == -1) ? kTransform1dWht : kColumnTransform[tx_type];
293
294 // Skip the 'C' test case as this is used as the reference.
295 if (base_inverse_transforms_[row_transform][tx_size_1d_row_][kRow] ==
296 nullptr ||
297 cur_inverse_transforms_[row_transform][tx_size_1d_row_][kRow] ==
298 nullptr ||
299 base_inverse_transforms_[column_transform][tx_size_1d_column_]
300 [kColumn] == nullptr ||
301 cur_inverse_transforms_[column_transform][tx_size_1d_column_]
302 [kColumn] == nullptr) {
303 continue;
304 }
305
306 // Only test valid tx_size for given tx_type. See 5.11.40.
307 if (!IsTxSizeTypeValid(tx_size_, tx_type)) continue;
308
309 absl::Duration base_elapsed_time[2];
310 absl::Duration cur_elapsed_time[2];
311
312 for (int n = 0; n < num_tests; ++n) {
313 const int tx_height = std::min(block_height_, 32);
314 const int start_x = 0;
315 const int start_y = 0;
316
317 inverse_transform_mem_.Reset(&rnd, block_width_, block_height_);
318 memcpy(inverse_transform_mem_.base_residual,
319 inverse_transform_mem_.ref_src,
320 sizeof(inverse_transform_mem_.ref_src));
321 memcpy(inverse_transform_mem_.cur_residual,
322 inverse_transform_mem_.ref_src,
323 sizeof(inverse_transform_mem_.ref_src));
324
325 const absl::Time base_row_start = absl::Now();
326 base_inverse_transforms_[row_transform][tx_size_1d_row_][kRow](
327 tx_type, tx_size_, tx_height, inverse_transform_mem_.base_residual,
328 start_x, start_y, &base_frame_buffer_);
329 base_elapsed_time[kRow] += absl::Now() - base_row_start;
330
331 const absl::Time cur_row_start = absl::Now();
332 cur_inverse_transforms_[row_transform][tx_size_1d_row_][kRow](
333 tx_type, tx_size_, tx_height, inverse_transform_mem_.cur_residual,
334 start_x, start_y, &cur_frame_buffer_);
335 cur_elapsed_time[kRow] += absl::Now() - cur_row_start;
336
337 const absl::Time base_column_start = absl::Now();
338 base_inverse_transforms_[column_transform][tx_size_1d_column_][kColumn](
339 tx_type, tx_size_, tx_height, inverse_transform_mem_.base_residual,
340 start_x, start_y, &base_frame_buffer_);
341 base_elapsed_time[kColumn] += absl::Now() - base_column_start;
342
343 const absl::Time cur_column_start = absl::Now();
344 cur_inverse_transforms_[column_transform][tx_size_1d_column_][kColumn](
345 tx_type, tx_size_, tx_height, inverse_transform_mem_.cur_residual,
346 start_x, start_y, &cur_frame_buffer_);
347 cur_elapsed_time[kColumn] += absl::Now() - cur_column_start;
348
349 if (!test_utils::CompareBlocks(inverse_transform_mem_.base_frame,
350 inverse_transform_mem_.cur_frame,
351 block_width_, block_height_, kMaxBlockSize,
352 kMaxBlockSize, false)) {
353 ADD_FAILURE() << "Result from optimized version of "
354 << ToString(
355 static_cast<Transform1dSize>(tx_size_1d_column_))
356 << " differs from reference in iteration #" << n
357 << " tx_type_idx:" << tx_type_idx;
358 break;
359 }
360 }
361
362 if (num_tests > 1) {
363 const auto base_row_elapsed_time_us =
364 static_cast<int>(absl::ToInt64Microseconds(base_elapsed_time[kRow]));
365 const auto cur_row_elapsed_time_us =
366 static_cast<int>(absl::ToInt64Microseconds(cur_elapsed_time[kRow]));
367 printf("TxType %30s[%19s]:: base_row: %5d us cur_row: %5d us %2.2fx \n",
368 (tx_type_idx == -1) ? ToString(row_transform) : ToString(tx_type),
369 kTransform1dSizeNames[tx_size_1d_row_], base_row_elapsed_time_us,
370 cur_row_elapsed_time_us,
371 static_cast<float>(base_row_elapsed_time_us) /
372 static_cast<float>(cur_row_elapsed_time_us));
373 const auto base_column_elapsed_time_us = static_cast<int>(
374 absl::ToInt64Microseconds(base_elapsed_time[kColumn]));
375 const auto cur_column_elapsed_time_us = static_cast<int>(
376 absl::ToInt64Microseconds(cur_elapsed_time[kColumn]));
377 printf(
378 "TxType %30s[%19s]:: base_col: %5d us cur_col: %5d us %2.2fx \n",
379 (tx_type_idx == -1) ? ToString(column_transform) : ToString(tx_type),
380 kTransform1dSizeNames[tx_size_1d_column_],
381 base_column_elapsed_time_us, cur_column_elapsed_time_us,
382 static_cast<float>(base_column_elapsed_time_us) /
383 static_cast<float>(cur_column_elapsed_time_us));
384 }
385 }
386 }
387
388 template <int bitdepth, typename Pixel, typename DstPixel>
TestDcOnlyRandomValue(int num_tests)389 void InverseTransformTest<bitdepth, Pixel, DstPixel>::TestDcOnlyRandomValue(
390 int num_tests) {
391 libvpx_test::ACMRandom rnd(libvpx_test::ACMRandom::DeterministicSeed());
392
393 for (int tx_type_idx = 0; tx_type_idx < kNumTransformTypes; ++tx_type_idx) {
394 const TransformType tx_type = kLibgav1TxType[tx_type_idx];
395 const Transform1d row_transform = kRowTransform[tx_type];
396 const Transform1d column_transform = kColumnTransform[tx_type];
397
398 if (cur_inverse_transforms_[row_transform][tx_size_1d_row_][kRow] ==
399 nullptr ||
400 cur_inverse_transforms_[column_transform][tx_size_1d_column_]
401 [kColumn] == nullptr) {
402 continue;
403 }
404
405 // Only test valid tx_size for given tx_type. See 5.11.40.
406 if (IsTxSizeTypeValid(tx_size_, tx_type) == 0) continue;
407
408 absl::Duration base_elapsed_time[2];
409 absl::Duration cur_elapsed_time[2];
410
411 for (int n = 0; n < num_tests; ++n) {
412 const int tx_height = std::min(block_height_, 32);
413 const int start_x = 0;
414 const int start_y = 0;
415
416 // Using width == 1 and height == 1 will reset only the dc value.
417 inverse_transform_mem_.Reset(&rnd, 1, 1);
418 memcpy(inverse_transform_mem_.base_residual,
419 inverse_transform_mem_.ref_src,
420 sizeof(inverse_transform_mem_.ref_src));
421 memcpy(inverse_transform_mem_.cur_residual,
422 inverse_transform_mem_.ref_src,
423 sizeof(inverse_transform_mem_.ref_src));
424
425 // For this test, the "base" contains the output when the
426 // tx_height is set to the max for the given block size. The
427 // "cur" contains the output when the passed in tx_height is 1.
428 // Compare the outputs for match.
429 const absl::Time base_row_start = absl::Now();
430 cur_inverse_transforms_[row_transform][tx_size_1d_row_][kRow](
431 tx_type, tx_size_, tx_height, inverse_transform_mem_.base_residual,
432 start_x, start_y, &base_frame_buffer_);
433 base_elapsed_time[kRow] += absl::Now() - base_row_start;
434
435 const absl::Time cur_row_start = absl::Now();
436 cur_inverse_transforms_[row_transform][tx_size_1d_row_][kRow](
437 tx_type, tx_size_, /*adjusted_tx_height=*/1,
438 inverse_transform_mem_.cur_residual, start_x, start_y,
439 &cur_frame_buffer_);
440 cur_elapsed_time[kRow] += absl::Now() - cur_row_start;
441
442 const absl::Time base_column_start = absl::Now();
443 cur_inverse_transforms_[column_transform][tx_size_1d_column_][kColumn](
444 tx_type, tx_size_, tx_height, inverse_transform_mem_.base_residual,
445 start_x, start_y, &base_frame_buffer_);
446 base_elapsed_time[kColumn] += absl::Now() - base_column_start;
447
448 const absl::Time cur_column_start = absl::Now();
449 cur_inverse_transforms_[column_transform][tx_size_1d_column_][kColumn](
450 tx_type, tx_size_, /*adjusted_tx_height=*/1,
451 inverse_transform_mem_.cur_residual, start_x, start_y,
452 &cur_frame_buffer_);
453 cur_elapsed_time[kColumn] += absl::Now() - cur_column_start;
454
455 if (!test_utils::CompareBlocks(inverse_transform_mem_.base_frame,
456 inverse_transform_mem_.cur_frame,
457 block_width_, block_height_, kMaxBlockSize,
458 kMaxBlockSize, false)) {
459 ADD_FAILURE() << "Result from dc only version of "
460 << ToString(
461 static_cast<Transform1dSize>(tx_size_1d_column_))
462 << " differs from reference in iteration #" << n
463 << "tx_type_idx:" << tx_type_idx;
464 break;
465 }
466 }
467
468 if (num_tests > 1) {
469 const auto base_row_elapsed_time_us =
470 static_cast<int>(absl::ToInt64Microseconds(base_elapsed_time[kRow]));
471 const auto cur_row_elapsed_time_us =
472 static_cast<int>(absl::ToInt64Microseconds(cur_elapsed_time[kRow]));
473 printf("TxType %30s[%19s]:: base_row: %5d us cur_row: %5d us %2.2fx \n",
474 ToString(tx_type), kTransform1dSizeNames[tx_size_1d_row_],
475 base_row_elapsed_time_us, cur_row_elapsed_time_us,
476 static_cast<float>(base_row_elapsed_time_us) /
477 static_cast<float>(cur_row_elapsed_time_us));
478 const auto base_column_elapsed_time_us = static_cast<int>(
479 absl::ToInt64Microseconds(base_elapsed_time[kColumn]));
480 const auto cur_column_elapsed_time_us = static_cast<int>(
481 absl::ToInt64Microseconds(cur_elapsed_time[kColumn]));
482 printf("TxType %30s[%19s]:: base_col: %5d us cur_col: %5d us %2.2fx \n",
483 ToString(tx_type), kTransform1dSizeNames[tx_size_1d_column_],
484 base_column_elapsed_time_us, cur_column_elapsed_time_us,
485 static_cast<float>(base_column_elapsed_time_us) /
486 static_cast<float>(cur_column_elapsed_time_us));
487 }
488 }
489 }
490
491 using InverseTransformTest8bpp = InverseTransformTest<8, int16_t, uint8_t>;
492
TEST_P(InverseTransformTest8bpp,Random)493 TEST_P(InverseTransformTest8bpp, Random) { TestRandomValues(1); }
494
TEST_P(InverseTransformTest8bpp,DISABLED_Speed)495 TEST_P(InverseTransformTest8bpp, DISABLED_Speed) { TestRandomValues(10000); }
496
TEST_P(InverseTransformTest8bpp,DcRandom)497 TEST_P(InverseTransformTest8bpp, DcRandom) { TestDcOnlyRandomValue(1); }
498
499 constexpr TransformSize kTransformSizesAll[] = {
500 kTransformSize4x4, kTransformSize4x8, kTransformSize4x16,
501 kTransformSize8x4, kTransformSize8x8, kTransformSize8x16,
502 kTransformSize8x32, kTransformSize16x4, kTransformSize16x8,
503 kTransformSize16x16, kTransformSize16x32, kTransformSize16x64,
504 kTransformSize32x8, kTransformSize32x16, kTransformSize32x32,
505 kTransformSize32x64, kTransformSize64x16, kTransformSize64x32,
506 kTransformSize64x64};
507
508 INSTANTIATE_TEST_SUITE_P(C, InverseTransformTest8bpp,
509 testing::ValuesIn(kTransformSizesAll));
510 #if LIBGAV1_ENABLE_NEON
511 INSTANTIATE_TEST_SUITE_P(NEON, InverseTransformTest8bpp,
512 testing::ValuesIn(kTransformSizesAll));
513 #endif
514 #if LIBGAV1_ENABLE_SSE4_1
515 INSTANTIATE_TEST_SUITE_P(SSE41, InverseTransformTest8bpp,
516 testing::ValuesIn(kTransformSizesAll));
517 #endif
518
519 #if LIBGAV1_MAX_BITDEPTH >= 10
520 using InverseTransformTest10bpp = InverseTransformTest<10, int32_t, uint16_t>;
521
TEST_P(InverseTransformTest10bpp,Random)522 TEST_P(InverseTransformTest10bpp, Random) { TestRandomValues(1); }
523
TEST_P(InverseTransformTest10bpp,DISABLED_Speed)524 TEST_P(InverseTransformTest10bpp, DISABLED_Speed) { TestRandomValues(10000); }
525
TEST_P(InverseTransformTest10bpp,DcRandom)526 TEST_P(InverseTransformTest10bpp, DcRandom) { TestDcOnlyRandomValue(1); }
527
528 INSTANTIATE_TEST_SUITE_P(C, InverseTransformTest10bpp,
529 testing::ValuesIn(kTransformSizesAll));
530
531 #if LIBGAV1_ENABLE_NEON
532 INSTANTIATE_TEST_SUITE_P(NEON, InverseTransformTest10bpp,
533 testing::ValuesIn(kTransformSizesAll));
534 #endif
535 #endif // LIBGAV1_MAX_BITDEPTH >= 10
536
537 #if LIBGAV1_MAX_BITDEPTH == 12
538 using InverseTransformTest12bpp = InverseTransformTest<12, int32_t, uint16_t>;
539
TEST_P(InverseTransformTest12bpp,Random)540 TEST_P(InverseTransformTest12bpp, Random) { TestRandomValues(1); }
541
TEST_P(InverseTransformTest12bpp,DISABLED_Speed)542 TEST_P(InverseTransformTest12bpp, DISABLED_Speed) { TestRandomValues(12000); }
543
TEST_P(InverseTransformTest12bpp,DcRandom)544 TEST_P(InverseTransformTest12bpp, DcRandom) { TestDcOnlyRandomValue(1); }
545
546 INSTANTIATE_TEST_SUITE_P(C, InverseTransformTest12bpp,
547 testing::ValuesIn(kTransformSizesAll));
548 #endif // LIBGAV1_MAX_BITDEPTH == 12
549
550 } // namespace
551 } // namespace dsp
552
operator <<(std::ostream & os,const TransformSize param)553 static std::ostream& operator<<(std::ostream& os, const TransformSize param) {
554 return os << ToString(param);
555 }
556
557 } // namespace libgav1
558