xref: /aosp_15_r20/external/libaom/test/intra_edge_test.cc (revision 77c1e3ccc04c968bd2bc212e87364f250e820521)
1 /*
2  * Copyright (c) 2017, Alliance for Open Media. All rights reserved.
3  *
4  * This source code is subject to the terms of the BSD 2 Clause License and
5  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6  * was not distributed with this source code in the LICENSE file, you can
7  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8  * Media Patent License 1.0 was not distributed with this source code in the
9  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10  */
11 
12 #include <math.h>
13 #include <stdlib.h>
14 #include <string.h>
15 
16 #include "gtest/gtest.h"
17 #include "test/register_state_check.h"
18 #include "test/function_equivalence_test.h"
19 
20 #include "config/aom_config.h"
21 #include "config/aom_dsp_rtcd.h"
22 #include "config/av1_rtcd.h"
23 
24 #include "aom/aom_integer.h"
25 #include "av1/common/enums.h"
26 
27 using libaom_test::FunctionEquivalenceTest;
28 
29 namespace {
30 
31 template <typename F, typename T>
32 class UpsampleTest : public FunctionEquivalenceTest<F> {
33  protected:
34   static const int kIterations = 1000000;
35   static const int kMinEdge = 4;
36   static const int kMaxEdge = 24;
37   static const int kBufSize = 2 * 64 + 32;
38   static const int kOffset = 16;
39 
40   ~UpsampleTest() override = default;
41 
42   virtual void Execute(T *edge_tst) = 0;
43 
Common()44   void Common() {
45     edge_ref_ = &edge_ref_data_[kOffset];
46     edge_tst_ = &edge_tst_data_[kOffset];
47 
48     Execute(edge_tst_);
49 
50     const int max_idx = (size_ - 1) * 2;
51     for (int r = -2; r <= max_idx; ++r) {
52       ASSERT_EQ(edge_ref_[r], edge_tst_[r]);
53     }
54   }
55 
56   T edge_ref_data_[kBufSize];
57   T edge_tst_data_[kBufSize];
58 
59   T *edge_ref_;
60   T *edge_tst_;
61 
62   int size_;
63 };
64 
65 typedef void (*UP8B)(uint8_t *p, int size);
66 typedef libaom_test::FuncParam<UP8B> TestFuncs;
67 
68 class UpsampleTest8B : public UpsampleTest<UP8B, uint8_t> {
69  protected:
Execute(uint8_t * edge_tst)70   void Execute(uint8_t *edge_tst) override {
71     params_.ref_func(edge_ref_, size_);
72     API_REGISTER_STATE_CHECK(params_.tst_func(edge_tst, size_));
73   }
74 };
75 
TEST_P(UpsampleTest8B,RandomValues)76 TEST_P(UpsampleTest8B, RandomValues) {
77   for (int iter = 0; iter < kIterations && !HasFatalFailure(); ++iter) {
78     size_ = 4 * (this->rng_(4) + 1);
79 
80     int i, pix = 0;
81     for (i = 0; i < kOffset + size_; ++i) {
82       pix = rng_.Rand8();
83       edge_ref_data_[i] = pix;
84       edge_tst_data_[i] = edge_ref_data_[i];
85     }
86 
87     // Extend final sample
88     while (i < kBufSize) {
89       edge_ref_data_[i] = pix;
90       edge_tst_data_[i] = pix;
91       i++;
92     }
93 
94     Common();
95   }
96 }
97 
TEST_P(UpsampleTest8B,DISABLED_Speed)98 TEST_P(UpsampleTest8B, DISABLED_Speed) {
99   const int test_count = 10000000;
100   size_ = kMaxEdge;
101   for (int i = 0; i < kOffset + size_; ++i) {
102     edge_tst_data_[i] = rng_.Rand8();
103   }
104   edge_tst_ = &edge_tst_data_[kOffset];
105   for (int iter = 0; iter < test_count; ++iter) {
106     API_REGISTER_STATE_CHECK(params_.tst_func(edge_tst_, size_));
107   }
108 }
109 
110 #if HAVE_SSE4_1
111 INSTANTIATE_TEST_SUITE_P(
112     SSE4_1, UpsampleTest8B,
113     ::testing::Values(TestFuncs(av1_upsample_intra_edge_c,
114                                 av1_upsample_intra_edge_sse4_1)));
115 #endif  // HAVE_SSE4_1
116 
117 #if HAVE_NEON
118 INSTANTIATE_TEST_SUITE_P(
119     NEON, UpsampleTest8B,
120     ::testing::Values(TestFuncs(av1_upsample_intra_edge_c,
121                                 av1_upsample_intra_edge_neon)));
122 #endif  // HAVE_NEON
123 
124 template <typename F, typename T>
125 class FilterEdgeTest : public FunctionEquivalenceTest<F> {
126  protected:
127   static const int kIterations = 1000000;
128   static const int kMaxEdge = 2 * 64;
129   static const int kBufSize = kMaxEdge + 32;
130   static const int kOffset = 15;
131 
132   ~FilterEdgeTest() override = default;
133 
134   virtual void Execute(T *edge_tst) = 0;
135 
Common()136   void Common() {
137     edge_ref_ = &edge_ref_data_[kOffset];
138     edge_tst_ = &edge_tst_data_[kOffset];
139 
140     Execute(edge_tst_);
141 
142     for (int r = 0; r < size_; ++r) {
143       ASSERT_EQ(edge_ref_[r], edge_tst_[r]);
144     }
145   }
146 
147   T edge_ref_data_[kBufSize];
148   T edge_tst_data_[kBufSize];
149 
150   T *edge_ref_;
151   T *edge_tst_;
152 
153   int size_;
154   int strength_;
155 };
156 
157 typedef void (*FE8B)(uint8_t *p, int size, int strength);
158 typedef libaom_test::FuncParam<FE8B> FilterEdgeTestFuncs;
159 
160 class FilterEdgeTest8B : public FilterEdgeTest<FE8B, uint8_t> {
161  protected:
Execute(uint8_t * edge_tst)162   void Execute(uint8_t *edge_tst) override {
163     params_.ref_func(edge_ref_, size_, strength_);
164     API_REGISTER_STATE_CHECK(params_.tst_func(edge_tst, size_, strength_));
165   }
166 };
167 
TEST_P(FilterEdgeTest8B,RandomValues)168 TEST_P(FilterEdgeTest8B, RandomValues) {
169   for (int iter = 0; iter < kIterations && !HasFatalFailure(); ++iter) {
170     strength_ = this->rng_(4);
171     size_ = 4 * (this->rng_(128 / 4) + 1) + 1;
172 
173     int i, pix = 0;
174     for (i = 0; i < kOffset + size_; ++i) {
175       pix = rng_.Rand8();
176       edge_ref_data_[i] = pix;
177       edge_tst_data_[i] = pix;
178     }
179 
180     Common();
181   }
182 }
183 
TEST_P(FilterEdgeTest8B,DISABLED_Speed)184 TEST_P(FilterEdgeTest8B, DISABLED_Speed) {
185   const int test_count = 10000000;
186   size_ = kMaxEdge;
187   strength_ = 1;
188   for (int i = 0; i < kOffset + size_; ++i) {
189     edge_tst_data_[i] = rng_.Rand8();
190   }
191   edge_tst_ = &edge_tst_data_[kOffset];
192   for (int iter = 0; iter < test_count; ++iter) {
193     API_REGISTER_STATE_CHECK(params_.tst_func(edge_tst_, size_, strength_));
194     // iterate over filter strengths (1,2,3)
195     strength_ = strength_ == 3 ? 1 : strength_ + 1;
196   }
197 }
198 
199 #if HAVE_SSE4_1
200 INSTANTIATE_TEST_SUITE_P(
201     SSE4_1, FilterEdgeTest8B,
202     ::testing::Values(FilterEdgeTestFuncs(av1_filter_intra_edge_c,
203                                           av1_filter_intra_edge_sse4_1)));
204 #endif  // HAVE_SSE4_1
205 
206 #if HAVE_NEON
207 INSTANTIATE_TEST_SUITE_P(
208     NEON, FilterEdgeTest8B,
209     ::testing::Values(FilterEdgeTestFuncs(av1_filter_intra_edge_c,
210                                           av1_filter_intra_edge_neon)));
211 #endif  // HAVE_NEON
212 
213 #if CONFIG_AV1_HIGHBITDEPTH
214 
215 typedef void (*UPHB)(uint16_t *p, int size, int bd);
216 typedef libaom_test::FuncParam<UPHB> TestFuncsHBD;
217 
218 class UpsampleTestHB : public UpsampleTest<UPHB, uint16_t> {
219  protected:
Execute(uint16_t * edge_tst)220   void Execute(uint16_t *edge_tst) override {
221     params_.ref_func(edge_ref_, size_, bit_depth_);
222     API_REGISTER_STATE_CHECK(params_.tst_func(edge_tst, size_, bit_depth_));
223   }
224   int bit_depth_;
225 };
226 
TEST_P(UpsampleTestHB,RandomValues)227 TEST_P(UpsampleTestHB, RandomValues) {
228   for (int iter = 0; iter < kIterations && !HasFatalFailure(); ++iter) {
229     switch (rng_(3)) {
230       case 0: bit_depth_ = 8; break;
231       case 1: bit_depth_ = 10; break;
232       default: bit_depth_ = 12; break;
233     }
234     const int hi = 1 << bit_depth_;
235 
236     size_ = 4 * (this->rng_(4) + 1);
237 
238     int i, pix = 0;
239     for (i = 0; i < kOffset + size_; ++i) {
240       pix = rng_(hi);
241       edge_ref_data_[i] = pix;
242       edge_tst_data_[i] = pix;
243     }
244 
245     // Extend final sample
246     while (i < kBufSize) {
247       edge_ref_data_[i] = pix;
248       edge_tst_data_[i] = pix;
249       i++;
250     }
251 
252     Common();
253   }
254 }
255 
TEST_P(UpsampleTestHB,DISABLED_Speed)256 TEST_P(UpsampleTestHB, DISABLED_Speed) {
257   const int test_count = 10000000;
258   size_ = kMaxEdge;
259   bit_depth_ = 12;
260   const int hi = 1 << bit_depth_;
261   for (int i = 0; i < kOffset + size_; ++i) {
262     edge_tst_data_[i] = rng_(hi);
263   }
264   edge_tst_ = &edge_tst_data_[kOffset];
265   for (int iter = 0; iter < test_count; ++iter) {
266     API_REGISTER_STATE_CHECK(params_.tst_func(edge_tst_, size_, bit_depth_));
267   }
268 }
269 
270 #if HAVE_SSE4_1
271 INSTANTIATE_TEST_SUITE_P(
272     SSE4_1, UpsampleTestHB,
273     ::testing::Values(TestFuncsHBD(av1_highbd_upsample_intra_edge_c,
274                                    av1_highbd_upsample_intra_edge_sse4_1)));
275 #endif  // HAVE_SSE4_1
276 
277 #if HAVE_NEON
278 INSTANTIATE_TEST_SUITE_P(
279     NEON, UpsampleTestHB,
280     ::testing::Values(TestFuncsHBD(av1_highbd_upsample_intra_edge_c,
281                                    av1_highbd_upsample_intra_edge_neon)));
282 #endif  // HAVE_NEON
283 
284 typedef void (*FEHB)(uint16_t *p, int size, int strength);
285 typedef libaom_test::FuncParam<FEHB> FilterEdgeTestFuncsHBD;
286 
287 class FilterEdgeTestHB : public FilterEdgeTest<FEHB, uint16_t> {
288  protected:
Execute(uint16_t * edge_tst)289   void Execute(uint16_t *edge_tst) override {
290     params_.ref_func(edge_ref_, size_, strength_);
291     API_REGISTER_STATE_CHECK(params_.tst_func(edge_tst, size_, strength_));
292   }
293   int bit_depth_;
294 };
295 
TEST_P(FilterEdgeTestHB,RandomValues)296 TEST_P(FilterEdgeTestHB, RandomValues) {
297   for (int iter = 0; iter < kIterations && !HasFatalFailure(); ++iter) {
298     switch (rng_(3)) {
299       case 0: bit_depth_ = 8; break;
300       case 1: bit_depth_ = 10; break;
301       default: bit_depth_ = 12; break;
302     }
303     const int hi = 1 << bit_depth_;
304     strength_ = this->rng_(4);
305     size_ = 4 * (this->rng_(128 / 4) + 1) + 1;
306 
307     int i, pix = 0;
308     for (i = 0; i < kOffset + size_; ++i) {
309       pix = rng_(hi);
310       edge_ref_data_[i] = pix;
311       edge_tst_data_[i] = pix;
312     }
313 
314     Common();
315   }
316 }
317 
TEST_P(FilterEdgeTestHB,DISABLED_Speed)318 TEST_P(FilterEdgeTestHB, DISABLED_Speed) {
319   const int test_count = 10000000;
320   size_ = kMaxEdge;
321   strength_ = 1;
322   bit_depth_ = 12;
323   const int hi = 1 << bit_depth_;
324   for (int i = 0; i < kOffset + size_; ++i) {
325     edge_tst_data_[i] = rng_(hi);
326   }
327   edge_tst_ = &edge_tst_data_[kOffset];
328   for (int iter = 0; iter < test_count; ++iter) {
329     API_REGISTER_STATE_CHECK(params_.tst_func(edge_tst_, size_, strength_));
330     // iterate over filter strengths (1,2,3)
331     strength_ = strength_ == 3 ? 1 : strength_ + 1;
332   }
333 }
334 
335 #if HAVE_SSE4_1
336 INSTANTIATE_TEST_SUITE_P(SSE4_1, FilterEdgeTestHB,
337                          ::testing::Values(FilterEdgeTestFuncsHBD(
338                              av1_highbd_filter_intra_edge_c,
339                              av1_highbd_filter_intra_edge_sse4_1)));
340 #endif  // HAVE_SSE4_1
341 
342 #if HAVE_NEON
343 INSTANTIATE_TEST_SUITE_P(NEON, FilterEdgeTestHB,
344                          ::testing::Values(FilterEdgeTestFuncsHBD(
345                              av1_highbd_filter_intra_edge_c,
346                              av1_highbd_filter_intra_edge_neon)));
347 #endif  // HAVE_NEON
348 
349 #endif  // CONFIG_AV1_HIGHBITDEPTH
350 
351 }  // namespace
352