1*09537850SAkhilesh Sanikop // Copyright 2021 The libgav1 Authors
2*09537850SAkhilesh Sanikop //
3*09537850SAkhilesh Sanikop // Licensed under the Apache License, Version 2.0 (the "License");
4*09537850SAkhilesh Sanikop // you may not use this file except in compliance with the License.
5*09537850SAkhilesh Sanikop // You may obtain a copy of the License at
6*09537850SAkhilesh Sanikop //
7*09537850SAkhilesh Sanikop // http://www.apache.org/licenses/LICENSE-2.0
8*09537850SAkhilesh Sanikop //
9*09537850SAkhilesh Sanikop // Unless required by applicable law or agreed to in writing, software
10*09537850SAkhilesh Sanikop // distributed under the License is distributed on an "AS IS" BASIS,
11*09537850SAkhilesh Sanikop // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*09537850SAkhilesh Sanikop // See the License for the specific language governing permissions and
13*09537850SAkhilesh Sanikop // limitations under the License.
14*09537850SAkhilesh Sanikop
15*09537850SAkhilesh Sanikop #include "src/dsp/cdef.h"
16*09537850SAkhilesh Sanikop
17*09537850SAkhilesh Sanikop #include <cstdint>
18*09537850SAkhilesh Sanikop #include <cstring>
19*09537850SAkhilesh Sanikop #include <ostream>
20*09537850SAkhilesh Sanikop
21*09537850SAkhilesh Sanikop #include "absl/strings/match.h"
22*09537850SAkhilesh Sanikop #include "absl/time/clock.h"
23*09537850SAkhilesh Sanikop #include "absl/time/time.h"
24*09537850SAkhilesh Sanikop #include "gtest/gtest.h"
25*09537850SAkhilesh Sanikop #include "src/dsp/dsp.h"
26*09537850SAkhilesh Sanikop #include "src/utils/common.h"
27*09537850SAkhilesh Sanikop #include "src/utils/constants.h"
28*09537850SAkhilesh Sanikop #include "src/utils/cpu.h"
29*09537850SAkhilesh Sanikop #include "src/utils/memory.h"
30*09537850SAkhilesh Sanikop #include "tests/third_party/libvpx/acm_random.h"
31*09537850SAkhilesh Sanikop #include "tests/third_party/libvpx/md5_helper.h"
32*09537850SAkhilesh Sanikop #include "tests/utils.h"
33*09537850SAkhilesh Sanikop
34*09537850SAkhilesh Sanikop namespace libgav1 {
35*09537850SAkhilesh Sanikop namespace dsp {
36*09537850SAkhilesh Sanikop namespace {
37*09537850SAkhilesh Sanikop
38*09537850SAkhilesh Sanikop constexpr char kCdef[] = "Cdef";
39*09537850SAkhilesh Sanikop constexpr char kCdefDirectionName[] = "Cdef Direction";
40*09537850SAkhilesh Sanikop constexpr char kCdefFilterName[] = "Cdef Filtering";
41*09537850SAkhilesh Sanikop constexpr int kTestBufferStride = 8;
42*09537850SAkhilesh Sanikop constexpr int kTestBufferSize = 64;
43*09537850SAkhilesh Sanikop constexpr int kSourceStride = kMaxSuperBlockSizeInPixels + 2 * 8;
44*09537850SAkhilesh Sanikop constexpr int kSourceBufferSize =
45*09537850SAkhilesh Sanikop (kMaxSuperBlockSizeInPixels + 2 * 3) * kSourceStride;
46*09537850SAkhilesh Sanikop constexpr int kNumSpeedTests = 5000;
47*09537850SAkhilesh Sanikop
GetDirectionDigest(const int bitdepth,const int num_runs)48*09537850SAkhilesh Sanikop const char* GetDirectionDigest(const int bitdepth, const int num_runs) {
49*09537850SAkhilesh Sanikop static const char* const kDigest[3][2] = {
50*09537850SAkhilesh Sanikop {"de78c820a1fec7e81385aa0a615dbf8c", "7bfc543244f932a542691480dc4541b2"},
51*09537850SAkhilesh Sanikop {"b54236de5d25e16c0f8678d9784cb85e", "559144cf183f3c69cb0e5d98cbf532ff"},
52*09537850SAkhilesh Sanikop {"5532919a157c4f937da9e822bdb105f7", "dd9dfca6dfca83777d942e693c17627a"}};
53*09537850SAkhilesh Sanikop const int bitdepth_index = (bitdepth - 8) / 2;
54*09537850SAkhilesh Sanikop const int run_index = (num_runs == 1) ? 0 : 1;
55*09537850SAkhilesh Sanikop return kDigest[bitdepth_index][run_index];
56*09537850SAkhilesh Sanikop }
57*09537850SAkhilesh Sanikop
58*09537850SAkhilesh Sanikop // The 'int' parameter is unused but required to allow for instantiations of C,
59*09537850SAkhilesh Sanikop // NEON, etc.
60*09537850SAkhilesh Sanikop template <int bitdepth, typename Pixel>
61*09537850SAkhilesh Sanikop class CdefDirectionTest : public testing::TestWithParam<int> {
62*09537850SAkhilesh Sanikop public:
63*09537850SAkhilesh Sanikop static_assert(bitdepth >= kBitdepth8 && bitdepth <= LIBGAV1_MAX_BITDEPTH, "");
64*09537850SAkhilesh Sanikop CdefDirectionTest() = default;
65*09537850SAkhilesh Sanikop CdefDirectionTest(const CdefDirectionTest&) = delete;
66*09537850SAkhilesh Sanikop CdefDirectionTest& operator=(const CdefDirectionTest&) = delete;
67*09537850SAkhilesh Sanikop ~CdefDirectionTest() override = default;
68*09537850SAkhilesh Sanikop
69*09537850SAkhilesh Sanikop protected:
SetUp()70*09537850SAkhilesh Sanikop void SetUp() override {
71*09537850SAkhilesh Sanikop test_utils::ResetDspTable(bitdepth);
72*09537850SAkhilesh Sanikop CdefInit_C();
73*09537850SAkhilesh Sanikop
74*09537850SAkhilesh Sanikop const Dsp* const dsp = GetDspTable(bitdepth);
75*09537850SAkhilesh Sanikop ASSERT_NE(dsp, nullptr);
76*09537850SAkhilesh Sanikop base_cdef_direction_ = nullptr;
77*09537850SAkhilesh Sanikop const testing::TestInfo* const test_info =
78*09537850SAkhilesh Sanikop testing::UnitTest::GetInstance()->current_test_info();
79*09537850SAkhilesh Sanikop const char* const test_case = test_info->test_suite_name();
80*09537850SAkhilesh Sanikop if (absl::StartsWith(test_case, "C/")) {
81*09537850SAkhilesh Sanikop } else if (absl::StartsWith(test_case, "SSE41/")) {
82*09537850SAkhilesh Sanikop if ((GetCpuInfo() & kSSE4_1) == 0) GTEST_SKIP() << "No SSE4.1 support!";
83*09537850SAkhilesh Sanikop CdefInit_SSE4_1();
84*09537850SAkhilesh Sanikop } else if (absl::StartsWith(test_case, "AVX2/")) {
85*09537850SAkhilesh Sanikop if ((GetCpuInfo() & kAVX2) == 0) GTEST_SKIP() << "No AVX2 support!";
86*09537850SAkhilesh Sanikop CdefInit_AVX2();
87*09537850SAkhilesh Sanikop } else if (absl::StartsWith(test_case, "NEON/")) {
88*09537850SAkhilesh Sanikop CdefInit_NEON();
89*09537850SAkhilesh Sanikop } else {
90*09537850SAkhilesh Sanikop FAIL() << "Unrecognized architecture prefix in test case name: "
91*09537850SAkhilesh Sanikop << test_case;
92*09537850SAkhilesh Sanikop }
93*09537850SAkhilesh Sanikop cur_cdef_direction_ = dsp->cdef_direction;
94*09537850SAkhilesh Sanikop }
95*09537850SAkhilesh Sanikop
96*09537850SAkhilesh Sanikop void TestRandomValues(int num_runs);
97*09537850SAkhilesh Sanikop
98*09537850SAkhilesh Sanikop Pixel buffer_[kTestBufferSize];
99*09537850SAkhilesh Sanikop int strength_;
100*09537850SAkhilesh Sanikop int size_;
101*09537850SAkhilesh Sanikop
102*09537850SAkhilesh Sanikop CdefDirectionFunc base_cdef_direction_;
103*09537850SAkhilesh Sanikop CdefDirectionFunc cur_cdef_direction_;
104*09537850SAkhilesh Sanikop };
105*09537850SAkhilesh Sanikop
106*09537850SAkhilesh Sanikop template <int bitdepth, typename Pixel>
TestRandomValues(int num_runs)107*09537850SAkhilesh Sanikop void CdefDirectionTest<bitdepth, Pixel>::TestRandomValues(int num_runs) {
108*09537850SAkhilesh Sanikop if (cur_cdef_direction_ == nullptr) return;
109*09537850SAkhilesh Sanikop libvpx_test::ACMRandom rnd(libvpx_test::ACMRandom::DeterministicSeed());
110*09537850SAkhilesh Sanikop absl::Duration elapsed_time;
111*09537850SAkhilesh Sanikop libvpx_test::MD5 actual_digest;
112*09537850SAkhilesh Sanikop for (int num_tests = 0; num_tests < num_runs; ++num_tests) {
113*09537850SAkhilesh Sanikop for (int level = 0; level < (1 << bitdepth); level += 1 + (bitdepth - 8)) {
114*09537850SAkhilesh Sanikop for (int bits = 0; bits <= bitdepth; ++bits) {
115*09537850SAkhilesh Sanikop for (auto& pixel : buffer_) {
116*09537850SAkhilesh Sanikop pixel = Clip3((rnd.Rand16() & ((1 << bits) - 1)) + level, 0,
117*09537850SAkhilesh Sanikop (1 << bitdepth) - 1);
118*09537850SAkhilesh Sanikop }
119*09537850SAkhilesh Sanikop int output[2] = {};
120*09537850SAkhilesh Sanikop const absl::Time start = absl::Now();
121*09537850SAkhilesh Sanikop cur_cdef_direction_(buffer_, kTestBufferStride * sizeof(Pixel),
122*09537850SAkhilesh Sanikop reinterpret_cast<uint8_t*>(&output[0]), &output[1]);
123*09537850SAkhilesh Sanikop elapsed_time += absl::Now() - start;
124*09537850SAkhilesh Sanikop actual_digest.Add(reinterpret_cast<const uint8_t*>(output),
125*09537850SAkhilesh Sanikop sizeof(output));
126*09537850SAkhilesh Sanikop }
127*09537850SAkhilesh Sanikop }
128*09537850SAkhilesh Sanikop }
129*09537850SAkhilesh Sanikop test_utils::CheckMd5Digest(kCdef, kCdefDirectionName,
130*09537850SAkhilesh Sanikop GetDirectionDigest(bitdepth, num_runs),
131*09537850SAkhilesh Sanikop actual_digest.Get(), elapsed_time);
132*09537850SAkhilesh Sanikop }
133*09537850SAkhilesh Sanikop
134*09537850SAkhilesh Sanikop using CdefDirectionTest8bpp = CdefDirectionTest<8, uint8_t>;
135*09537850SAkhilesh Sanikop
TEST_P(CdefDirectionTest8bpp,Correctness)136*09537850SAkhilesh Sanikop TEST_P(CdefDirectionTest8bpp, Correctness) { TestRandomValues(1); }
137*09537850SAkhilesh Sanikop
TEST_P(CdefDirectionTest8bpp,DISABLED_Speed)138*09537850SAkhilesh Sanikop TEST_P(CdefDirectionTest8bpp, DISABLED_Speed) {
139*09537850SAkhilesh Sanikop TestRandomValues(kNumSpeedTests / 100);
140*09537850SAkhilesh Sanikop }
141*09537850SAkhilesh Sanikop
142*09537850SAkhilesh Sanikop INSTANTIATE_TEST_SUITE_P(C, CdefDirectionTest8bpp, testing::Values(0));
143*09537850SAkhilesh Sanikop
144*09537850SAkhilesh Sanikop #if LIBGAV1_ENABLE_NEON
145*09537850SAkhilesh Sanikop INSTANTIATE_TEST_SUITE_P(NEON, CdefDirectionTest8bpp, testing::Values(0));
146*09537850SAkhilesh Sanikop #endif
147*09537850SAkhilesh Sanikop
148*09537850SAkhilesh Sanikop #if LIBGAV1_ENABLE_SSE4_1
149*09537850SAkhilesh Sanikop INSTANTIATE_TEST_SUITE_P(SSE41, CdefDirectionTest8bpp, testing::Values(0));
150*09537850SAkhilesh Sanikop #endif
151*09537850SAkhilesh Sanikop
152*09537850SAkhilesh Sanikop #if LIBGAV1_ENABLE_AVX2
153*09537850SAkhilesh Sanikop INSTANTIATE_TEST_SUITE_P(AVX2, CdefDirectionTest8bpp, testing::Values(0));
154*09537850SAkhilesh Sanikop #endif // LIBGAV1_ENABLE_AVX2
155*09537850SAkhilesh Sanikop
156*09537850SAkhilesh Sanikop #if LIBGAV1_MAX_BITDEPTH >= 10
157*09537850SAkhilesh Sanikop using CdefDirectionTest10bpp = CdefDirectionTest<10, uint16_t>;
158*09537850SAkhilesh Sanikop
TEST_P(CdefDirectionTest10bpp,Correctness)159*09537850SAkhilesh Sanikop TEST_P(CdefDirectionTest10bpp, Correctness) { TestRandomValues(1); }
160*09537850SAkhilesh Sanikop
TEST_P(CdefDirectionTest10bpp,DISABLED_Speed)161*09537850SAkhilesh Sanikop TEST_P(CdefDirectionTest10bpp, DISABLED_Speed) {
162*09537850SAkhilesh Sanikop TestRandomValues(kNumSpeedTests / 100);
163*09537850SAkhilesh Sanikop }
164*09537850SAkhilesh Sanikop
165*09537850SAkhilesh Sanikop INSTANTIATE_TEST_SUITE_P(C, CdefDirectionTest10bpp, testing::Values(0));
166*09537850SAkhilesh Sanikop
167*09537850SAkhilesh Sanikop #if LIBGAV1_ENABLE_NEON
168*09537850SAkhilesh Sanikop INSTANTIATE_TEST_SUITE_P(NEON, CdefDirectionTest10bpp, testing::Values(0));
169*09537850SAkhilesh Sanikop #endif
170*09537850SAkhilesh Sanikop #endif // LIBGAV1_MAX_BITDEPTH >= 10
171*09537850SAkhilesh Sanikop
172*09537850SAkhilesh Sanikop #if LIBGAV1_MAX_BITDEPTH == 12
173*09537850SAkhilesh Sanikop using CdefDirectionTest12bpp = CdefDirectionTest<12, uint16_t>;
174*09537850SAkhilesh Sanikop
TEST_P(CdefDirectionTest12bpp,Correctness)175*09537850SAkhilesh Sanikop TEST_P(CdefDirectionTest12bpp, Correctness) { TestRandomValues(1); }
176*09537850SAkhilesh Sanikop
TEST_P(CdefDirectionTest12bpp,DISABLED_Speed)177*09537850SAkhilesh Sanikop TEST_P(CdefDirectionTest12bpp, DISABLED_Speed) {
178*09537850SAkhilesh Sanikop TestRandomValues(kNumSpeedTests / 100);
179*09537850SAkhilesh Sanikop }
180*09537850SAkhilesh Sanikop
181*09537850SAkhilesh Sanikop INSTANTIATE_TEST_SUITE_P(C, CdefDirectionTest12bpp, testing::Values(0));
182*09537850SAkhilesh Sanikop #endif // LIBGAV1_MAX_BITDEPTH == 12
183*09537850SAkhilesh Sanikop
GetDigest8bpp(int id)184*09537850SAkhilesh Sanikop const char* GetDigest8bpp(int id) {
185*09537850SAkhilesh Sanikop static const char* const kDigest[] = {
186*09537850SAkhilesh Sanikop "b6fe1a1f5bbb23e35197160ce57d90bd", "8aed39871b19184f1d381b145779bc33",
187*09537850SAkhilesh Sanikop "82653dd66072e8ebd967083a0413ab03", "421c048396bc66ffaa6aafa016c7bc54",
188*09537850SAkhilesh Sanikop "1f70ba51091e8c6034c3f0974af241c3", "8f700997452a24091136ca58890a5be4",
189*09537850SAkhilesh Sanikop "9e3dea21ee4246172121f0420eccd899", "0848bdeffa74145758ef47992e1035c4",
190*09537850SAkhilesh Sanikop "0bb55818de986e9d988b0c1cc6883887", "9b558a7eefc934f90cd09ca26b998bfd",
191*09537850SAkhilesh Sanikop "3a38670f8c5f0c61cc47c9c79da728d2", "ed18fe91180e78008ccb98e9019bed69",
192*09537850SAkhilesh Sanikop "2aa4bbcb6fb088ad42bde76be014dff0", "88f746f0d6c079ab8e9ecc7ff67524c7",
193*09537850SAkhilesh Sanikop "7cffa948f5ddbccc7c6b07d15ca9eb69", "5e22c1c89735965dda935d1249129548",
194*09537850SAkhilesh Sanikop "e765133d133b94e1578c8c5616248a96", "da95d47cad74eb4a075893ca98e658ab",
195*09537850SAkhilesh Sanikop };
196*09537850SAkhilesh Sanikop return kDigest[id];
197*09537850SAkhilesh Sanikop }
198*09537850SAkhilesh Sanikop
199*09537850SAkhilesh Sanikop #if LIBGAV1_MAX_BITDEPTH >= 10
GetDigest10bpp(int id)200*09537850SAkhilesh Sanikop const char* GetDigest10bpp(int id) {
201*09537850SAkhilesh Sanikop static const char* const kDigest[] = {
202*09537850SAkhilesh Sanikop "0a9630b39974850998db653b07e09ab4", "97a924661d931b23ee57893da617ae70",
203*09537850SAkhilesh Sanikop "0d79516b9a491ce5112eb00bbae5eb80", "d5801fd96029a7509cf66dde61e8e2d8",
204*09537850SAkhilesh Sanikop "5bf5c0ea5a85e9b6c1e6991619c34ebc", "e2f1c08a8b3cd93b3a85511493a0ee31",
205*09537850SAkhilesh Sanikop "45c047d2be5e2dcf6094937780a3f88a", "346caf437c1ad85862de72a622e29845",
206*09537850SAkhilesh Sanikop "0e9cb69d24d9badbe956da779d912b05", "81803dcb00971237b3fe6372564a842f",
207*09537850SAkhilesh Sanikop "17681ad2ed4a2456d70760852af6c6fd", "5312f8049a08a5f9b1708fda936f7a55",
208*09537850SAkhilesh Sanikop "3f0f522f3a33e4ff2a97bdc1e614c5c4", "3818a50be7fe16aa0c636a7392d1eceb",
209*09537850SAkhilesh Sanikop "c6849b8cd77a076dc7e3c26e8cd55b9e", "223c0dd685bbc74aec1d088356708433",
210*09537850SAkhilesh Sanikop "90992957cb8103222aa2fb43c6cd2fc4", "a4ba6edcefe4130851c4c2607b147f95",
211*09537850SAkhilesh Sanikop };
212*09537850SAkhilesh Sanikop return kDigest[id];
213*09537850SAkhilesh Sanikop }
214*09537850SAkhilesh Sanikop #endif // LIBGAV1_MAX_BITDEPTH >= 10
215*09537850SAkhilesh Sanikop
216*09537850SAkhilesh Sanikop #if LIBGAV1_MAX_BITDEPTH == 12
GetDigest12bpp(int id)217*09537850SAkhilesh Sanikop const char* GetDigest12bpp(int id) {
218*09537850SAkhilesh Sanikop static const char* const kDigest[] = {
219*09537850SAkhilesh Sanikop "a32569989c42fd4254979f70c1c65f5a", "dc389048217633e2dd64126376be7d25",
220*09537850SAkhilesh Sanikop "3b0e8dae294895330f349863b1773c39", "9741fe8d27d109cb99b7a9cdc030f52a",
221*09537850SAkhilesh Sanikop "ab70f3729b52287c6432ba7624280a68", "c1e5cf39cbc8030b82e09633c6c67d42",
222*09537850SAkhilesh Sanikop "d5120a196164ff5a0ad7aa8c02e9b064", "1133759f3aee3a362a0ab668f6faf843",
223*09537850SAkhilesh Sanikop "feb0ab7f515665f79fce213e8cd2fb10", "e86ea55c2d6d5cc69716535bd455c99f",
224*09537850SAkhilesh Sanikop "e463da1b9d089b6ee82c041794257fd7", "27800e4af0cceeaf0a95c96275a7befe",
225*09537850SAkhilesh Sanikop "f42e426481db00582b327eb2971bca96", "6127ff289833dde0270000d8240f36b7",
226*09537850SAkhilesh Sanikop "cc5dbaf70e2fef7729a8e2ea9937fbcf", "51850b4e3e2a3919e110376fcb6318d3",
227*09537850SAkhilesh Sanikop "d5ac7ac25eb1b5aee293b2a2ec9de775", "64ecc00b2e24a2f07df833fb50ce09c3",
228*09537850SAkhilesh Sanikop };
229*09537850SAkhilesh Sanikop return kDigest[id];
230*09537850SAkhilesh Sanikop }
231*09537850SAkhilesh Sanikop #endif // LIBGAV1_MAX_BITDEPTH == 12
232*09537850SAkhilesh Sanikop
233*09537850SAkhilesh Sanikop struct CdefTestParam {
CdefTestParamlibgav1::dsp::__anon31afbc4e0111::CdefTestParam234*09537850SAkhilesh Sanikop CdefTestParam(int subsampling_x, int subsampling_y, int rows4x4,
235*09537850SAkhilesh Sanikop int columns4x4)
236*09537850SAkhilesh Sanikop : subsampling_x(subsampling_x),
237*09537850SAkhilesh Sanikop subsampling_y(subsampling_y),
238*09537850SAkhilesh Sanikop rows4x4(rows4x4),
239*09537850SAkhilesh Sanikop columns4x4(columns4x4) {}
240*09537850SAkhilesh Sanikop int subsampling_x;
241*09537850SAkhilesh Sanikop int subsampling_y;
242*09537850SAkhilesh Sanikop int rows4x4;
243*09537850SAkhilesh Sanikop int columns4x4;
244*09537850SAkhilesh Sanikop };
245*09537850SAkhilesh Sanikop
operator <<(std::ostream & os,const CdefTestParam & param)246*09537850SAkhilesh Sanikop std::ostream& operator<<(std::ostream& os, const CdefTestParam& param) {
247*09537850SAkhilesh Sanikop return os << "subsampling(x/y): " << param.subsampling_x << "/"
248*09537850SAkhilesh Sanikop << param.subsampling_y << ", (rows,columns)4x4: " << param.rows4x4
249*09537850SAkhilesh Sanikop << ", " << param.columns4x4;
250*09537850SAkhilesh Sanikop }
251*09537850SAkhilesh Sanikop
252*09537850SAkhilesh Sanikop // TODO(b/154245961): rework the parameters for this test to match
253*09537850SAkhilesh Sanikop // CdefFilteringFuncs. It should cover 4x4, 8x4, 8x8 blocks and
254*09537850SAkhilesh Sanikop // primary/secondary strength combinations for both Y and UV.
255*09537850SAkhilesh Sanikop template <int bitdepth, typename Pixel>
256*09537850SAkhilesh Sanikop class CdefFilteringTest : public testing::TestWithParam<CdefTestParam> {
257*09537850SAkhilesh Sanikop public:
258*09537850SAkhilesh Sanikop static_assert(bitdepth >= kBitdepth8 && bitdepth <= LIBGAV1_MAX_BITDEPTH, "");
259*09537850SAkhilesh Sanikop CdefFilteringTest() = default;
260*09537850SAkhilesh Sanikop CdefFilteringTest(const CdefFilteringTest&) = delete;
261*09537850SAkhilesh Sanikop CdefFilteringTest& operator=(const CdefFilteringTest&) = delete;
262*09537850SAkhilesh Sanikop ~CdefFilteringTest() override = default;
263*09537850SAkhilesh Sanikop
264*09537850SAkhilesh Sanikop protected:
SetUp()265*09537850SAkhilesh Sanikop void SetUp() override {
266*09537850SAkhilesh Sanikop test_utils::ResetDspTable(bitdepth);
267*09537850SAkhilesh Sanikop CdefInit_C();
268*09537850SAkhilesh Sanikop
269*09537850SAkhilesh Sanikop const Dsp* const dsp = GetDspTable(bitdepth);
270*09537850SAkhilesh Sanikop ASSERT_NE(dsp, nullptr);
271*09537850SAkhilesh Sanikop const testing::TestInfo* const test_info =
272*09537850SAkhilesh Sanikop testing::UnitTest::GetInstance()->current_test_info();
273*09537850SAkhilesh Sanikop const char* const test_case = test_info->test_suite_name();
274*09537850SAkhilesh Sanikop if (absl::StartsWith(test_case, "C/")) {
275*09537850SAkhilesh Sanikop } else if (absl::StartsWith(test_case, "NEON/")) {
276*09537850SAkhilesh Sanikop CdefInit_NEON();
277*09537850SAkhilesh Sanikop } else if (absl::StartsWith(test_case, "SSE41/")) {
278*09537850SAkhilesh Sanikop if ((GetCpuInfo() & kSSE4_1) == 0) GTEST_SKIP() << "No SSE4.1 support!";
279*09537850SAkhilesh Sanikop CdefInit_SSE4_1();
280*09537850SAkhilesh Sanikop } else if (absl::StartsWith(test_case, "AVX2/")) {
281*09537850SAkhilesh Sanikop if ((GetCpuInfo() & kAVX2) == 0) GTEST_SKIP() << "No AVX2 support!";
282*09537850SAkhilesh Sanikop CdefInit_AVX2();
283*09537850SAkhilesh Sanikop } else {
284*09537850SAkhilesh Sanikop FAIL() << "Unrecognized architecture prefix in test case name: "
285*09537850SAkhilesh Sanikop << test_case;
286*09537850SAkhilesh Sanikop }
287*09537850SAkhilesh Sanikop memcpy(cur_cdef_filter_, dsp->cdef_filters, sizeof(cur_cdef_filter_));
288*09537850SAkhilesh Sanikop }
289*09537850SAkhilesh Sanikop
290*09537850SAkhilesh Sanikop void TestRandomValues(int num_runs);
291*09537850SAkhilesh Sanikop
292*09537850SAkhilesh Sanikop uint16_t source_[kSourceBufferSize];
293*09537850SAkhilesh Sanikop Pixel dest_[kMaxPlanes][kTestBufferSize];
294*09537850SAkhilesh Sanikop int primary_strength_;
295*09537850SAkhilesh Sanikop int secondary_strength_;
296*09537850SAkhilesh Sanikop int damping_;
297*09537850SAkhilesh Sanikop int direction_;
298*09537850SAkhilesh Sanikop CdefTestParam param_ = GetParam();
299*09537850SAkhilesh Sanikop
300*09537850SAkhilesh Sanikop CdefFilteringFuncs cur_cdef_filter_;
301*09537850SAkhilesh Sanikop };
302*09537850SAkhilesh Sanikop
303*09537850SAkhilesh Sanikop template <int bitdepth, typename Pixel>
TestRandomValues(int num_runs)304*09537850SAkhilesh Sanikop void CdefFilteringTest<bitdepth, Pixel>::TestRandomValues(int num_runs) {
305*09537850SAkhilesh Sanikop const int id = static_cast<int>(param_.rows4x4 < 4) * 3 +
306*09537850SAkhilesh Sanikop (param_.subsampling_x + param_.subsampling_y) * 6;
307*09537850SAkhilesh Sanikop absl::Duration elapsed_time[kMaxPlanes];
308*09537850SAkhilesh Sanikop for (int num_tests = 0; num_tests < num_runs; ++num_tests) {
309*09537850SAkhilesh Sanikop for (int plane = kPlaneY; plane < kMaxPlanes; ++plane) {
310*09537850SAkhilesh Sanikop const int subsampling_x = (plane == kPlaneY) ? 0 : param_.subsampling_x;
311*09537850SAkhilesh Sanikop const int subsampling_y = (plane == kPlaneY) ? 0 : param_.subsampling_y;
312*09537850SAkhilesh Sanikop const int block_width = 8 >> subsampling_x;
313*09537850SAkhilesh Sanikop const int block_height = 8 >> subsampling_y;
314*09537850SAkhilesh Sanikop libvpx_test::ACMRandom rnd(libvpx_test::ACMRandom::DeterministicSeed() +
315*09537850SAkhilesh Sanikop id + plane);
316*09537850SAkhilesh Sanikop const int offset = 2 * kSourceStride + 2;
317*09537850SAkhilesh Sanikop // Fill boundaries with a large value such that cdef does not take them
318*09537850SAkhilesh Sanikop // into calculation.
319*09537850SAkhilesh Sanikop const int plane_width = MultiplyBy4(param_.columns4x4) >> subsampling_x;
320*09537850SAkhilesh Sanikop const int plane_height = MultiplyBy4(param_.rows4x4) >> subsampling_y;
321*09537850SAkhilesh Sanikop for (int y = 0; y < plane_height; ++y) {
322*09537850SAkhilesh Sanikop for (int x = 0; x < plane_width; ++x) {
323*09537850SAkhilesh Sanikop source_[y * kSourceStride + x + offset] =
324*09537850SAkhilesh Sanikop rnd.Rand16() & ((1 << bitdepth) - 1);
325*09537850SAkhilesh Sanikop }
326*09537850SAkhilesh Sanikop }
327*09537850SAkhilesh Sanikop for (int y = 0; y < 2; ++y) {
328*09537850SAkhilesh Sanikop Memset(&source_[y * kSourceStride], kCdefLargeValue, kSourceStride);
329*09537850SAkhilesh Sanikop Memset(&source_[(y + plane_height + 2) * kSourceStride],
330*09537850SAkhilesh Sanikop kCdefLargeValue, kSourceStride);
331*09537850SAkhilesh Sanikop }
332*09537850SAkhilesh Sanikop for (int y = 0; y < plane_height; ++y) {
333*09537850SAkhilesh Sanikop Memset(&source_[y * kSourceStride + offset - 2], kCdefLargeValue, 2);
334*09537850SAkhilesh Sanikop Memset(&source_[y * kSourceStride + offset + plane_width],
335*09537850SAkhilesh Sanikop kCdefLargeValue, 2);
336*09537850SAkhilesh Sanikop }
337*09537850SAkhilesh Sanikop do {
338*09537850SAkhilesh Sanikop int strength = rnd.Rand16() & 15;
339*09537850SAkhilesh Sanikop if (strength == 3) ++strength;
340*09537850SAkhilesh Sanikop primary_strength_ = strength << (bitdepth - 8);
341*09537850SAkhilesh Sanikop } while (primary_strength_ == 0);
342*09537850SAkhilesh Sanikop do {
343*09537850SAkhilesh Sanikop int strength = rnd.Rand16() & 3;
344*09537850SAkhilesh Sanikop if (strength == 3) ++strength;
345*09537850SAkhilesh Sanikop secondary_strength_ = strength << (bitdepth - 8);
346*09537850SAkhilesh Sanikop } while (secondary_strength_ == 0);
347*09537850SAkhilesh Sanikop damping_ = (rnd.Rand16() & 3) + 3;
348*09537850SAkhilesh Sanikop direction_ = (rnd.Rand16() & 7);
349*09537850SAkhilesh Sanikop
350*09537850SAkhilesh Sanikop memset(dest_[plane], 0, sizeof(dest_[plane]));
351*09537850SAkhilesh Sanikop const absl::Time start = absl::Now();
352*09537850SAkhilesh Sanikop const int width_index = block_width >> 3;
353*09537850SAkhilesh Sanikop if (cur_cdef_filter_[width_index][0] == nullptr) return;
354*09537850SAkhilesh Sanikop cur_cdef_filter_[width_index][0](
355*09537850SAkhilesh Sanikop source_ + offset, kSourceStride, block_height, primary_strength_,
356*09537850SAkhilesh Sanikop secondary_strength_, damping_, direction_, dest_[plane],
357*09537850SAkhilesh Sanikop kTestBufferStride * sizeof(dest_[0][0]));
358*09537850SAkhilesh Sanikop elapsed_time[plane] += absl::Now() - start;
359*09537850SAkhilesh Sanikop }
360*09537850SAkhilesh Sanikop }
361*09537850SAkhilesh Sanikop
362*09537850SAkhilesh Sanikop for (int plane = kPlaneY; plane < kMaxPlanes; ++plane) {
363*09537850SAkhilesh Sanikop const char* expected_digest = nullptr;
364*09537850SAkhilesh Sanikop switch (bitdepth) {
365*09537850SAkhilesh Sanikop case 8:
366*09537850SAkhilesh Sanikop expected_digest = GetDigest8bpp(id + plane);
367*09537850SAkhilesh Sanikop break;
368*09537850SAkhilesh Sanikop #if LIBGAV1_MAX_BITDEPTH >= 10
369*09537850SAkhilesh Sanikop case 10:
370*09537850SAkhilesh Sanikop expected_digest = GetDigest10bpp(id + plane);
371*09537850SAkhilesh Sanikop break;
372*09537850SAkhilesh Sanikop #endif
373*09537850SAkhilesh Sanikop #if LIBGAV1_MAX_BITDEPTH == 12
374*09537850SAkhilesh Sanikop case 12:
375*09537850SAkhilesh Sanikop expected_digest = GetDigest12bpp(id + plane);
376*09537850SAkhilesh Sanikop break;
377*09537850SAkhilesh Sanikop #endif
378*09537850SAkhilesh Sanikop }
379*09537850SAkhilesh Sanikop ASSERT_NE(expected_digest, nullptr);
380*09537850SAkhilesh Sanikop test_utils::CheckMd5Digest(kCdef, kCdefFilterName, expected_digest,
381*09537850SAkhilesh Sanikop reinterpret_cast<uint8_t*>(dest_[plane]),
382*09537850SAkhilesh Sanikop sizeof(dest_[plane]), elapsed_time[plane]);
383*09537850SAkhilesh Sanikop }
384*09537850SAkhilesh Sanikop }
385*09537850SAkhilesh Sanikop
386*09537850SAkhilesh Sanikop // Do not test single blocks with any subsampling. 2xH and Wx2 blocks are not
387*09537850SAkhilesh Sanikop // supported.
388*09537850SAkhilesh Sanikop const CdefTestParam cdef_test_param[] = {
389*09537850SAkhilesh Sanikop CdefTestParam(0, 0, 4, 4), CdefTestParam(0, 0, 2, 2),
390*09537850SAkhilesh Sanikop CdefTestParam(1, 0, 4, 4), CdefTestParam(1, 0, 2, 2),
391*09537850SAkhilesh Sanikop CdefTestParam(1, 1, 4, 4), CdefTestParam(1, 1, 2, 2),
392*09537850SAkhilesh Sanikop };
393*09537850SAkhilesh Sanikop
394*09537850SAkhilesh Sanikop using CdefFilteringTest8bpp = CdefFilteringTest<8, uint8_t>;
395*09537850SAkhilesh Sanikop
TEST_P(CdefFilteringTest8bpp,Correctness)396*09537850SAkhilesh Sanikop TEST_P(CdefFilteringTest8bpp, Correctness) { TestRandomValues(1); }
397*09537850SAkhilesh Sanikop
TEST_P(CdefFilteringTest8bpp,DISABLED_Speed)398*09537850SAkhilesh Sanikop TEST_P(CdefFilteringTest8bpp, DISABLED_Speed) {
399*09537850SAkhilesh Sanikop TestRandomValues(kNumSpeedTests);
400*09537850SAkhilesh Sanikop }
401*09537850SAkhilesh Sanikop
402*09537850SAkhilesh Sanikop INSTANTIATE_TEST_SUITE_P(C, CdefFilteringTest8bpp,
403*09537850SAkhilesh Sanikop testing::ValuesIn(cdef_test_param));
404*09537850SAkhilesh Sanikop
405*09537850SAkhilesh Sanikop #if LIBGAV1_ENABLE_NEON
406*09537850SAkhilesh Sanikop INSTANTIATE_TEST_SUITE_P(NEON, CdefFilteringTest8bpp,
407*09537850SAkhilesh Sanikop testing::ValuesIn(cdef_test_param));
408*09537850SAkhilesh Sanikop #endif
409*09537850SAkhilesh Sanikop
410*09537850SAkhilesh Sanikop #if LIBGAV1_ENABLE_SSE4_1
411*09537850SAkhilesh Sanikop INSTANTIATE_TEST_SUITE_P(SSE41, CdefFilteringTest8bpp,
412*09537850SAkhilesh Sanikop testing::ValuesIn(cdef_test_param));
413*09537850SAkhilesh Sanikop #endif
414*09537850SAkhilesh Sanikop
415*09537850SAkhilesh Sanikop #if LIBGAV1_ENABLE_AVX2
416*09537850SAkhilesh Sanikop INSTANTIATE_TEST_SUITE_P(AVX2, CdefFilteringTest8bpp,
417*09537850SAkhilesh Sanikop testing::ValuesIn(cdef_test_param));
418*09537850SAkhilesh Sanikop #endif // LIBGAV1_ENABLE_AVX2
419*09537850SAkhilesh Sanikop
420*09537850SAkhilesh Sanikop #if LIBGAV1_MAX_BITDEPTH >= 10
421*09537850SAkhilesh Sanikop using CdefFilteringTest10bpp = CdefFilteringTest<10, uint16_t>;
422*09537850SAkhilesh Sanikop
TEST_P(CdefFilteringTest10bpp,Correctness)423*09537850SAkhilesh Sanikop TEST_P(CdefFilteringTest10bpp, Correctness) { TestRandomValues(1); }
424*09537850SAkhilesh Sanikop
TEST_P(CdefFilteringTest10bpp,DISABLED_Speed)425*09537850SAkhilesh Sanikop TEST_P(CdefFilteringTest10bpp, DISABLED_Speed) {
426*09537850SAkhilesh Sanikop TestRandomValues(kNumSpeedTests);
427*09537850SAkhilesh Sanikop }
428*09537850SAkhilesh Sanikop
429*09537850SAkhilesh Sanikop INSTANTIATE_TEST_SUITE_P(C, CdefFilteringTest10bpp,
430*09537850SAkhilesh Sanikop testing::ValuesIn(cdef_test_param));
431*09537850SAkhilesh Sanikop
432*09537850SAkhilesh Sanikop #if LIBGAV1_ENABLE_NEON
433*09537850SAkhilesh Sanikop INSTANTIATE_TEST_SUITE_P(NEON, CdefFilteringTest10bpp,
434*09537850SAkhilesh Sanikop testing::ValuesIn(cdef_test_param));
435*09537850SAkhilesh Sanikop #endif
436*09537850SAkhilesh Sanikop #endif // LIBGAV1_MAX_BITDEPTH >= 10
437*09537850SAkhilesh Sanikop
438*09537850SAkhilesh Sanikop #if LIBGAV1_MAX_BITDEPTH == 12
439*09537850SAkhilesh Sanikop using CdefFilteringTest12bpp = CdefFilteringTest<12, uint16_t>;
440*09537850SAkhilesh Sanikop
TEST_P(CdefFilteringTest12bpp,Correctness)441*09537850SAkhilesh Sanikop TEST_P(CdefFilteringTest12bpp, Correctness) { TestRandomValues(1); }
442*09537850SAkhilesh Sanikop
TEST_P(CdefFilteringTest12bpp,DISABLED_Speed)443*09537850SAkhilesh Sanikop TEST_P(CdefFilteringTest12bpp, DISABLED_Speed) {
444*09537850SAkhilesh Sanikop TestRandomValues(kNumSpeedTests);
445*09537850SAkhilesh Sanikop }
446*09537850SAkhilesh Sanikop
447*09537850SAkhilesh Sanikop INSTANTIATE_TEST_SUITE_P(C, CdefFilteringTest12bpp,
448*09537850SAkhilesh Sanikop testing::ValuesIn(cdef_test_param));
449*09537850SAkhilesh Sanikop #endif // LIBGAV1_MAX_BITDEPTH == 12
450*09537850SAkhilesh Sanikop
451*09537850SAkhilesh Sanikop } // namespace
452*09537850SAkhilesh Sanikop } // namespace dsp
453*09537850SAkhilesh Sanikop } // namespace libgav1
454