xref: /aosp_15_r20/external/libgav1/src/dsp/distance_weighted_blend_test.cc (revision 095378508e87ed692bf8dfeb34008b65b3735891)
1 // Copyright 2020 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/distance_weighted_blend.h"
16 
17 #include <cassert>
18 #include <cstdint>
19 #include <ostream>
20 #include <string>
21 #include <type_traits>
22 
23 #include "absl/strings/match.h"
24 #include "absl/strings/string_view.h"
25 #include "absl/time/clock.h"
26 #include "absl/time/time.h"
27 #include "gtest/gtest.h"
28 #include "src/dsp/constants.h"
29 #include "src/dsp/dsp.h"
30 #include "src/utils/common.h"
31 #include "src/utils/constants.h"
32 #include "src/utils/cpu.h"
33 #include "src/utils/memory.h"
34 #include "tests/third_party/libvpx/acm_random.h"
35 #include "tests/utils.h"
36 
37 namespace libgav1 {
38 namespace dsp {
39 namespace {
40 
41 constexpr int kNumSpeedTests = 500000;
42 
43 constexpr int kQuantizedDistanceLookup[4][2] = {
44     {9, 7}, {11, 5}, {12, 4}, {13, 3}};
45 
46 template <int bitdepth, typename Pixel>
47 class DistanceWeightedBlendTest : public testing::TestWithParam<BlockSize>,
48                                   public test_utils::MaxAlignedAllocable {
49  public:
50   static_assert(bitdepth >= kBitdepth8 && bitdepth <= LIBGAV1_MAX_BITDEPTH, "");
51   DistanceWeightedBlendTest() = default;
52   ~DistanceWeightedBlendTest() override = default;
53 
SetUp()54   void SetUp() override {
55     test_utils::ResetDspTable(bitdepth);
56     DistanceWeightedBlendInit_C();
57     const dsp::Dsp* const dsp = dsp::GetDspTable(bitdepth);
58     ASSERT_NE(dsp, nullptr);
59     base_func_ = dsp->distance_weighted_blend;
60     const testing::TestInfo* const test_info =
61         testing::UnitTest::GetInstance()->current_test_info();
62     const absl::string_view test_case = test_info->test_suite_name();
63     if (absl::StartsWith(test_case, "C/")) {
64       base_func_ = nullptr;
65     } else if (absl::StartsWith(test_case, "SSE41/")) {
66       if ((GetCpuInfo() & kSSE4_1) == 0) GTEST_SKIP() << "No SSE4.1 support!";
67       DistanceWeightedBlendInit_SSE4_1();
68     } else if (absl::StartsWith(test_case, "NEON/")) {
69       DistanceWeightedBlendInit_NEON();
70     } else {
71       FAIL() << "Unrecognized architecture prefix in test case name: "
72              << test_case;
73     }
74     func_ = dsp->distance_weighted_blend;
75   }
76 
77  protected:
78   void Test(const char* digest, int num_tests);
79 
80  private:
81   using PredType =
82       typename std::conditional<bitdepth == 8, int16_t, uint16_t>::type;
83   static constexpr int kDestStride = kMaxSuperBlockSizeInPixels;
84   const int width_ = kBlockWidthPixels[GetParam()];
85   const int height_ = kBlockHeightPixels[GetParam()];
86   alignas(kMaxAlignment) PredType
87       source1_[kMaxSuperBlockSizeInPixels * kMaxSuperBlockSizeInPixels];
88   alignas(kMaxAlignment) PredType
89       source2_[kMaxSuperBlockSizeInPixels * kMaxSuperBlockSizeInPixels];
90   Pixel dest_[kMaxSuperBlockSizeInPixels * kMaxSuperBlockSizeInPixels] = {};
91   Pixel reference_[kMaxSuperBlockSizeInPixels * kMaxSuperBlockSizeInPixels] =
92       {};
93   dsp::DistanceWeightedBlendFunc base_func_;
94   dsp::DistanceWeightedBlendFunc func_;
95 };
96 
97 template <int bitdepth, typename Pixel>
Test(const char * digest,int num_tests)98 void DistanceWeightedBlendTest<bitdepth, Pixel>::Test(const char* digest,
99                                                       int num_tests) {
100   if (func_ == nullptr) return;
101   libvpx_test::ACMRandom rnd(libvpx_test::ACMRandom::DeterministicSeed());
102   PredType* src_1 = source1_;
103   PredType* src_2 = source2_;
104 
105   const int index = rnd.Rand8() & 3;
106   const uint8_t weight_0 = kQuantizedDistanceLookup[index][0];
107   const uint8_t weight_1 = kQuantizedDistanceLookup[index][1];
108   // In libgav1, predictors have an offset which are later subtracted and
109   // clipped in distance weighted blending. Therefore we add the offset
110   // here to match libaom's implementation.
111   for (int y = 0; y < height_; ++y) {
112     for (int x = 0; x < width_; ++x) {
113       // distance_weighted_blend is applied to compound prediction values. This
114       // implies a range far exceeding that of pixel values.
115       // The ranges include kCompoundOffset in 10bpp and 12bpp.
116       // see: src/dsp/convolve.cc & src/dsp/warp.cc.
117       static constexpr int kCompoundPredictionRange[3][2] = {
118           // 8bpp
119           {-5132, 9212},
120           // 10bpp
121           {3988, 61532},
122           // 12bpp
123           {3974, 61559},
124       };
125       constexpr int bitdepth_index = (bitdepth - 8) >> 1;
126       const int min_val = kCompoundPredictionRange[bitdepth_index][0];
127       const int max_val = kCompoundPredictionRange[bitdepth_index][1];
128       src_1[x] = static_cast<PredType>(rnd(max_val - min_val) + min_val);
129       src_2[x] = static_cast<PredType>(rnd(max_val - min_val) + min_val);
130     }
131     src_1 += width_;
132     src_2 += width_;
133   }
134   absl::Duration elapsed_time;
135   for (int i = 0; i < num_tests; ++i) {
136     const absl::Time start = absl::Now();
137     func_(source1_, source2_, weight_0, weight_1, width_, height_, dest_,
138           sizeof(Pixel) * kDestStride);
139     elapsed_time += absl::Now() - start;
140   }
141 
142   test_utils::CheckMd5Digest("DistanceWeightedBlend", ToString(GetParam()),
143                              digest, dest_, sizeof(dest_), elapsed_time);
144 }
145 
146 const BlockSize kTestParam[] = {
147     kBlock4x4,    kBlock4x8,     kBlock4x16,  kBlock8x4,   kBlock8x8,
148     kBlock8x16,   kBlock8x32,    kBlock16x4,  kBlock16x8,  kBlock16x16,
149     kBlock16x32,  kBlock16x64,   kBlock32x8,  kBlock32x16, kBlock32x32,
150     kBlock32x64,  kBlock64x16,   kBlock64x32, kBlock64x64, kBlock64x128,
151     kBlock128x64, kBlock128x128,
152 };
153 
GetDistanceWeightedBlendDigest8bpp(const BlockSize block_size)154 const char* GetDistanceWeightedBlendDigest8bpp(const BlockSize block_size) {
155   static const char* const kDigests[kMaxBlockSizes] = {
156       // 4xN
157       "ebf389f724f8ab46a2cac895e4e073ca",
158       "09acd567b6b12c8cf8eb51d8b86eb4bf",
159       "57bb4d65695d8ec6752f2bd8686b64fd",
160       // 8xN
161       "270905ac76f9a2cba8a552eb0bf7c8c1",
162       "f0801c8574d2c271ef2bbea77a1d7352",
163       "e761b580e3312be33a227492a233ce72",
164       "ff214dab1a7e98e2285961d6421720c6",
165       // 16xN
166       "4f712609a36e817f9752326d58562ff8",
167       "14243f5c5f7c7104160c1f2cef0a0fbc",
168       "3ac3f3161b7c8dd8436b02abfdde104a",
169       "81a00b704e0e41a5dbe6436ac70c098d",
170       "af8fd02017c7acdff788be742d700baa",
171       // 32xN
172       "ee34332c66a6d6ed8ce64031aafe776c",
173       "b5e3d22bd2dbdb624c8b86a1afb5ce6d",
174       "607ffc22098d81b7e37a7bf62f4af5d3",
175       "3823dbf043b4682f56d5ca698e755ea5",
176       // 64xN
177       "4acf556b921956c2bc24659cd5128401",
178       "a298c544c9c3b27924b4c23cc687ea5a",
179       "539e2df267782ce61c70103b23b7d922",
180       "3b0cb2a0b5d384efee4d81401025bec1",
181       // 128xN
182       "8b56b636dd712c2f8d138badb7219991",
183       "8cfc8836908902b8f915639b7bff45b3",
184   };
185   assert(block_size < kMaxBlockSizes);
186   return kDigests[block_size];
187 }
188 
189 using DistanceWeightedBlendTest8bpp = DistanceWeightedBlendTest<8, uint8_t>;
190 
TEST_P(DistanceWeightedBlendTest8bpp,Blending)191 TEST_P(DistanceWeightedBlendTest8bpp, Blending) {
192   Test(GetDistanceWeightedBlendDigest8bpp(GetParam()), 1);
193 }
194 
TEST_P(DistanceWeightedBlendTest8bpp,DISABLED_Speed)195 TEST_P(DistanceWeightedBlendTest8bpp, DISABLED_Speed) {
196   Test(GetDistanceWeightedBlendDigest8bpp(GetParam()), kNumSpeedTests);
197 }
198 
199 INSTANTIATE_TEST_SUITE_P(C, DistanceWeightedBlendTest8bpp,
200                          testing::ValuesIn(kTestParam));
201 
202 #if LIBGAV1_ENABLE_NEON
203 INSTANTIATE_TEST_SUITE_P(NEON, DistanceWeightedBlendTest8bpp,
204                          testing::ValuesIn(kTestParam));
205 #endif
206 
207 #if LIBGAV1_ENABLE_SSE4_1
208 INSTANTIATE_TEST_SUITE_P(SSE41, DistanceWeightedBlendTest8bpp,
209                          testing::ValuesIn(kTestParam));
210 #endif
211 
212 #if LIBGAV1_MAX_BITDEPTH >= 10
GetDistanceWeightedBlendDigest10bpp(const BlockSize block_size)213 const char* GetDistanceWeightedBlendDigest10bpp(const BlockSize block_size) {
214   static const char* const kDigests[] = {
215       // 4xN
216       "55f594b56e16d5c401274affebbcc3d3",
217       "69df14da4bb33a8f7d7087921008e919",
218       "1b61f33604c54015794198a13bfebf46",
219       // 8xN
220       "825a938185b152f7cf09bf1c0723ce2b",
221       "85ea315c51d979bc9b45834d6b40ec6f",
222       "92ebde208e8c39f7ec6de2de82182dbb",
223       "520f84716db5b43684dbb703806383fe",
224       // 16xN
225       "12ca23e3e2930005a0511646e8c83da4",
226       "6208694a6744f4a3906f58c1add670e3",
227       "a33d63889df989a3bbf84ff236614267",
228       "34830846ecb0572a98bbd192fed02b16",
229       "34bb2f79c0bd7f9a80691b8af597f2a8",
230       // 32xN
231       "fa97f2d0e3143f1f44d3ac018b0d696d",
232       "3df4a22456c9ab6ed346ab1b9750ae7d",
233       "6276a058b35c6131bc0c94a4b4a37ebc",
234       "9ca42da5d2d5eb339df03ae2c7a26914",
235       // 64xN
236       "800e692c520f99223bc24c1ac95a0166",
237       "818b6d20426585ef7fe844015a03aaf5",
238       "fb48691ccfff083e01d74826e88e613f",
239       "0bd350bc5bc604a224d77a5f5a422698",
240       // 128xN
241       "a130840813cd6bd69d09bcf5f8d0180f",
242       "6ece1846bea55e8f8f2ed7fbf73718de",
243   };
244   assert(block_size < kMaxBlockSizes);
245   return kDigests[block_size];
246 }
247 
248 using DistanceWeightedBlendTest10bpp = DistanceWeightedBlendTest<10, uint16_t>;
249 
TEST_P(DistanceWeightedBlendTest10bpp,Blending)250 TEST_P(DistanceWeightedBlendTest10bpp, Blending) {
251   Test(GetDistanceWeightedBlendDigest10bpp(GetParam()), 1);
252 }
253 
TEST_P(DistanceWeightedBlendTest10bpp,DISABLED_Speed)254 TEST_P(DistanceWeightedBlendTest10bpp, DISABLED_Speed) {
255   Test(GetDistanceWeightedBlendDigest10bpp(GetParam()), kNumSpeedTests);
256 }
257 
258 INSTANTIATE_TEST_SUITE_P(C, DistanceWeightedBlendTest10bpp,
259                          testing::ValuesIn(kTestParam));
260 
261 #if LIBGAV1_ENABLE_SSE4_1
262 INSTANTIATE_TEST_SUITE_P(SSE41, DistanceWeightedBlendTest10bpp,
263                          testing::ValuesIn(kTestParam));
264 #endif
265 #if LIBGAV1_ENABLE_NEON
266 INSTANTIATE_TEST_SUITE_P(NEON, DistanceWeightedBlendTest10bpp,
267                          testing::ValuesIn(kTestParam));
268 #endif
269 #endif  // LIBGAV1_MAX_BITDEPTH >= 10
270 
271 #if LIBGAV1_MAX_BITDEPTH == 12
GetDistanceWeightedBlendDigest12bpp(const BlockSize block_size)272 const char* GetDistanceWeightedBlendDigest12bpp(const BlockSize block_size) {
273   static const char* const kDigests[] = {
274       // 4xN
275       "e30bf8f5f294206ad1dd79bd10a20827",
276       "f0cfb60134562d9c5f2ec6ad106e01ef",
277       "ad0876244e1b769203266a9c75b74afc",
278       // 8xN
279       "5265b954479c15a80f427561c5f36ff4",
280       "7f157457d1671e4ecce7a0884e9e3f76",
281       "d2cef5cf217f2d1f787c8951b7fe7cb2",
282       "6d23059008adbbb84ac941c8b4968f5b",
283       // 16xN
284       "ae521a5656ed3440d1fa950c20d90a79",
285       "935bec0e12b5dd3e0c34b3de8ba51476",
286       "0334bafcdcd7ddddb673ded492bca25a",
287       "c5360f08d0be77c79dc19fb55a0c5fe0",
288       "c2d1e7a4244a8aaaac041aed0cefc148",
289       // 32xN
290       "ce7f3cf78ae4f836cf69763137f7f6a6",
291       "800e52ebb14d5831c047d391cd760f95",
292       "74aa2b412b42165f1967daf3042b4f17",
293       "140d4cc600944b629b1991e88a9fe97c",
294       // 64xN
295       "3d206f93229ee2cea5c5da4e0ac6445a",
296       "3d13028f8fffe79fd35752c0177291ca",
297       "e7a7669acb5979dc7b15a19eed09cd4c",
298       "599368f4971c203fc5fa32989fe8cb44",
299       // 128xN
300       "54b46af2e2c8d2081e26fa0315b4ffd7",
301       "602e769bb2104e78223e68e50e7e86a0",
302   };
303   assert(block_size < kMaxBlockSizes);
304   return kDigests[block_size];
305 }
306 
307 using DistanceWeightedBlendTest12bpp = DistanceWeightedBlendTest<12, uint16_t>;
308 
TEST_P(DistanceWeightedBlendTest12bpp,Blending)309 TEST_P(DistanceWeightedBlendTest12bpp, Blending) {
310   Test(GetDistanceWeightedBlendDigest12bpp(GetParam()), 1);
311 }
312 
TEST_P(DistanceWeightedBlendTest12bpp,DISABLED_Speed)313 TEST_P(DistanceWeightedBlendTest12bpp, DISABLED_Speed) {
314   Test(GetDistanceWeightedBlendDigest12bpp(GetParam()), kNumSpeedTests);
315 }
316 
317 INSTANTIATE_TEST_SUITE_P(C, DistanceWeightedBlendTest12bpp,
318                          testing::ValuesIn(kTestParam));
319 #endif  // LIBGAV1_MAX_BITDEPTH == 12
320 
321 }  // namespace
322 }  // namespace dsp
323 
operator <<(std::ostream & os,const BlockSize param)324 static std::ostream& operator<<(std::ostream& os, const BlockSize param) {
325   return os << ToString(param);
326 }
327 
328 }  // namespace libgav1
329