xref: /aosp_15_r20/external/libgav1/src/dsp/mask_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/mask_blend.h"
16 
17 #include <cassert>
18 #include <cstddef>
19 #include <cstdint>
20 #include <cstring>
21 #include <ostream>
22 #include <string>
23 #include <type_traits>
24 
25 #include "absl/strings/match.h"
26 #include "absl/strings/string_view.h"
27 #include "absl/time/clock.h"
28 #include "absl/time/time.h"
29 #include "gtest/gtest.h"
30 #include "src/dsp/constants.h"
31 #include "src/dsp/dsp.h"
32 #include "src/utils/common.h"
33 #include "src/utils/constants.h"
34 #include "src/utils/cpu.h"
35 #include "src/utils/memory.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 kNumSpeedTests = 50000;
44 // mask_blend is applied to compound prediction values when is_inter_intra is
45 // false. This implies a range far exceeding that of pixel values. The ranges
46 // include kCompoundOffset in 10bpp and 12bpp.
47 // see: src/dsp/convolve.cc & src/dsp/warp.cc.
48 constexpr int kCompoundPredictionRange[3][2] = {
49     // 8bpp
50     {-5132, 9212},
51     // 10bpp
52     {3988, 61532},
53     // 12bpp
54     {3974, 61559},
55 };
56 
GetDigest8bpp(int id)57 const char* GetDigest8bpp(int id) {
58   static const char* const kDigest[] = {
59       "4b70d5ef5ac7554b4b2660a4abe14a41", "64adb36f07e4a2c4ea4f05cfd715ff58",
60       "2cd162cebf99724a3fc22d501bd8c8e4", "c490478208374a43765900ef7115c264",
61       "b98f222eb70ef8589da2d6c839ca22b8", "54752ca05f67b5af571bc311aa4e3de3",
62       "5ae48814dd285bfca4f5ee8e339dca99", "383f3f4f47563f065d1b6068e5931a24",
63       "344b2dab7accd8bd0a255bee16207336", "0b2f6f755d1547eea7e0172f8133ea01",
64       "310dc6364fdacba186c01f0e8ac4fcb7", "c2ee4673078d34971319c77ca77b23d1",
65       "b0c9f08b73d9e5c16eaf5abdbca1fdc0", "eaad805999d949fa1e1bbbb63b4b7827",
66       "6eb2a80d212df89403efb50db7a81b08", "c30730aa799dba78a2ebd3f729af82c7",
67       "4346c2860b23f0072b6b288f14c1df36", "1cdace53543063e129a125c4084ca5d7",
68       "1ae5328e0c0f4f2bec640d1af03b2978", "3860e040fbee0c5f68f0b4af769209b3",
69       "e9480ded15d9c38ee19bf5fa816dd296", "4e17c222b64f428df29938a8120ca256",
70       "2a943bc6de9b29c8bcae189ad3bec276", "b5a6bc02c76fa61040678fb2c6c112d2",
71       "2c11bb9bd29c5577194edb77cfd1c614", "31ed1832810ae385f4ad8f57795dde1e",
72       "eb87d647839c33984dfb25bac0e7cdb3", "f652ec2b1478e35acb19cf28042ee849",
73       "0cfb18ac0cb94af1447bcac32ac20c36", "e152bbbf5ee4b40b7b41ec1f2e901aaa",
74       "f17f78fd485f7beafa8126c1cda801d7", "9f9fbee0cc9d99435efd3dff644be273",
75       "9b498843d66440c1e68dc7ab04f57d42", "2f2b0beceb31b79ccb9179991629e4b8",
76       "e06a6ebb6791529bb23fe5b0a9914220", "2b3d1ff19812a17c17b1be1f1727815e",
77       "d0bbdecec414950ed63a8a35c2bae397", "8e53906c6513058d7f17013fe0d32bf1",
78       "be0690efd31f0bf3c2adcd27ca011ed5", "c2b26243c5f147fdeadf52735aa68fb5",
79       "94bb83e774d9189c5ee04fb361855e19", "dad6441e723791a91f31a56b2136fd33",
80       "10ccac76a2debb842a0685a527b6a659", "346fb0a4914b64dda3ca0f521412b999",
81       "d7e400b855502bbb4f2b8294e207bb96", "3487503f2d73ec52f25b5e8d06c81da4",
82       "3f49c096acfcf46d44ce18b48debca7c", "8ed6a745a2b5457ac7f3ac145ce57e72",
83       "21f9dda5ef934a5ee6274b22cc22f93b", "507b60611afeb373384d9b7606f7ea46",
84       "ac766fadcdb85a47ad14a6846b9e5c36", "fde149bc2162e02bbc5fa85cc41641a5",
85       "f5f094b5742d0a920ba734b017452d24", "c90d06b0c76a0983bd1428df2a1b64b3",
86       "3649e6a6ed9f69e3f78e0b75160fb82a", "1d44b7649497e651216db50d325e3073",
87       "948fa112e90e3ca4d15f3d2f2acfab9a", "9bb54c0f7d07c0b44c44ba09379a04ff",
88       "228261ab6f098f489a8968cff1e1f7ae", "5e128db7462164f7327d1d8feeb2e4c7",
89       "9e8b97f6d9d482d5770b138bd1077747", "81563d505a4e8dd779a089abf2a28b77",
90       "b7157451de7cfa161dff1afd7f9b8622", "6a25cc0a4aaf8a315d1158dbb0ec2966",
91       "303867ee010ba51da485ee10149c6f9b", "63b64b7527d2476e9ae5139b8166e8c9",
92       "cfa93c2aeeb27a1190a445a6fee61e15", "804bcff8709665eed6830e24346101be",
93       "829947ed3e90776cda4ae82918461497", "1df10a1cb80c1a81f521e7e0f80b4f99",
94       "3c9593e42ac574f3555bb8511d438a54", "eecef71492c0626685815e646f728f79",
95       "0c43d59f456ddca2449e016ae4e34be7", "207d4ac2579f1271fc9eca8d743917b3",
96       "3c472bb0b1c891ffda19077ebb659e48", "a4ae7a0d25113bc0238fa27409f9c0dd",
97       "e8ad037ca81f46774bb01d20f46671ce", "b22741e4fe0e4062e40a2decec102ffd",
98       "c72f9e7bc0170163cb94da0faa0d3ffb", "accaf5d475d155cbd3a8c113f90718bc",
99       "2fd31e72444ea258380c16881580de81", "8a6a2a253f6f5b0ff75ba39488e6b082",
100       "c5e8159c0f3ebb7536e84ab3dadac1b3", "ef7ec20b46c7dcf16591835642bd68ef",
101       "0c3425399dc64870d726c2837666a55e", "0365029ffbfc4cedf3bf2d757ea5b9df",
102       "836aa403254af2e04d4b7a7c4db8bfc5", "7f2f3f9c91677b233795169f9a88b2b2",
103       "9fc8bbe787244dac638c367b9c611d13", "f66ef45fae8e163ab0f0f393531dad26",
104       "beb984e88b6f9b96ae6efe5da23ad16b", "1083b829ea766b1d4eb0bb96e9fb3bff",
105       "be8abad1da69e4d238a45fc02a0061cf",
106   };
107   assert(id >= 0);
108   assert(id < sizeof(kDigest) / sizeof(kDigest[0]));
109   return kDigest[id];
110 }
111 
112 #if LIBGAV1_MAX_BITDEPTH >= 10
GetDigest10bpp(int id)113 const char* GetDigest10bpp(int id) {
114   static const char* const kDigest[] = {
115       "1af3cbd1616941b59e6a3f6a417b6312", "1d8b3f4b9d5d2f4ff5be8e81b7243121",
116       "e767350f150a84ac5a06dc348e815d62", "53a3a76bf2bcd5761cd15fc739a4f4e1",
117       "7597f69dc19a584280be0d67911db6a6", "e1221c172843dc6c1b345bcd370771cc",
118       "1a640c71ff9bb45505d89761f19efa8f", "e192f64322e0edb250b52f63aaa4de97",
119       "2ccbe012ca167114b14c3ba70befa960", "0f68632d7e5faddb4554ca430d1df822",
120       "8caa0061a26e142b783951d5abd7bf5d", "b01eeed3ec549e4a593100d9c5ba587a",
121       "1cce6acdbd8ca8d2546ba937584730bf", "022913e87a3c1a86aaefe2c2d4f89882",
122       "48f8ab636ba15a06731d869b603cbe58", "ba1616c990d224c20de123c3ccf19952",
123       "346a797b7cb4de10759e329f8b49e077", "d4929154275255f2d786d6fc42c7c5d3",
124       "18a6af6f36ca1ea4ab6f5a76505de040", "0c43e68414bfc02f9b20e796506f643b",
125       "9f483f543f6b1d58e23abf9337ed6fe6", "e114860c2538b63f1be4a23560420cdc",
126       "da8680798f96572c46155c7838b452c3", "20b47a27617297231843c0f2ed7b559b",
127       "16fa4a4f33a32e28c79da83dca63fd41", "76e2c1d3c323777a3c478e11e1ba6bf2",
128       "dccdfd52a71855cc4da18af52bda4c03", "121befbd6c246e85a34225241b8bcaf1",
129       "5780757555fd87ca1ff3f1b498a1d6e9", "6b0be2256285694b1edc0201608e1326",
130       "b7ef338c58d17f69426b5a99170c7295", "b92b84b5b3d01afac02fb9c092e84b06",
131       "e6ef7fea8b183f871c4306c4f49370c5", "c1bf95c05774d8471504e57a3efa66e4",
132       "bbacdbdafc625a139361ec22fe2cf003", "5fbbb2d6ca8fc6d07ca8d4105fda4a01",
133       "c1cbb295d9f00aa865d91a95e96f99b2", "1490e4f2c874a76ecc2bbf35dce446c3",
134       "c3bd73daaeec39895a8b64812773c93c", "6d385068ef3afbd821183d36851f709b",
135       "a34c52ef7f2fd04d1cd420238641ef48", "45d10029358c6835cf968a30605659ea",
136       "a72c1bb18cf9312c5713ce0de370743d", "df7368db2a7515a1c06a4c9dd9e32ebf",
137       "52782632271caccfa9a35ed7533e2052", "6f0ef9b62d2b9956a6464694b7a86b79",
138       "814dbc176f7201725a1cfd1cf668b4b9", "065ffbee984f4b9343c8acb0eb04fcbe",
139       "0915d76ce458d5164e3c90c1ce150795", "bf2b431d9bfa7a9925ea6f6509267ae9",
140       "d3df8c0c940a01b7bf3c3afb80b6dcd4", "15ab86216c9856a8427a51fe599258a3",
141       "2cb078484472c88e26b7401c9f11cf51", "7c5f68cc098c8adabc9e26f9cd549151",
142       "a8e47da1fcc91c2bc74d030892621576", "71af422ba2d86a401f8278591c0ef540",
143       "964c902bb4698ce82f4aa0a1edc80cd6", "78271c37d62af86576dab72ed59746b3",
144       "7247c3a7534a41137027e7d3f255f5ef", "8e529ab964f5f9d0f7c3ced98239cfc8",
145       "2481ed50bff6b36a3cac6dca2aca5ae5", "78a1ff18bf217d45f5170675dee26948",
146       "00fc534119c13aa7af4b818cad9218a2", "67501a83c93f2f9debfa86955bdffde5",
147       "2a512ef738e33a4d8476f72654deffb4", "f4eef28078bbc12de9cfb5bc2fef6238",
148       "b7ac3a35205a978bed587356155bae0e", "51ea101f09c4de2f754b61ab5aff1526",
149       "2bd689d7ec964ee8c8f6f0682f93f5ca", "eecac8dbdaa73b8b3c2234892c444147",
150       "cb7086f44ef70ef919086a3d200d8c13", "0abe35e3c796c2de1e550426b2b19441",
151       "0eb140561e1ea3843464a5247d8ecb18", "d908f7317f00daacbe3dd43495db64ad",
152       "d4d677c4b347de0a13ccab7bc16b8e6e", "26523c2c2df7f31896a3ae5aa24d5ada",
153       "0ebb9f816684769816b2ae0b1f94e3a4", "fd938d0577e3687b0a810e199f69f0bb",
154       "eb8fb832e72030e2aa214936ae0effe4", "56631887763f7daf6e1e73783e5ff656",
155       "590a25cc722c2aa4d885eede5ef09f20", "80944a218ed9b9b0374cde72914449eb",
156       "d9cbc2f1e0e56cdd6722310932db1981", "a88eb213b7a6767bbe639cda120a4ab6",
157       "9972ecbadfdf3ed0b3fedf435c5a804f", "01fdf7e22405a1b17a8d275b7451094f",
158       "6a7824e10406fade0d032e886bbc76b6", "76fefadd793ec3928e915d92782bc7e1",
159       "0fbd6b076752c9f5c926ca5c1df892ac", "aac9457239f07ad633fcd45c1465af2a",
160       "56823ef9a8e21c9c7441cc9ed870d648", "52f4c7a0b7177175302652cbc482f442",
161       "f4a4f4d7c8b93c0486cf3cbaa26fbc19",
162   };
163   assert(id >= 0);
164   assert(id < sizeof(kDigest) / sizeof(kDigest[0]));
165   return kDigest[id];
166 }
167 #endif  // LIBGAV1_MAX_BITDEPTH >= 10
168 
169 #if LIBGAV1_MAX_BITDEPTH == 12
GetDigest12bpp(int id)170 const char* GetDigest12bpp(int id) {
171   static const char* const kDigest[] = {
172       "79a505b3877177197c94f0faeb0c9ec6", "cd22657d242f30c88bb83eae9efbbcce",
173       "c4c60a60976d119df3832ff6956e0181", "796bd78bf2346e8dfd61cecbf508ea0e",
174       "79e06cc6f880daf6cdb59b9b3a8efe1c", "f0643108e6b57bd566bc0d47b2dc64a1",
175       "8272a471e538ca469eaf5c997309589c", "3094741b63a29925da83dc1dc187654a",
176       "d0141df80f2335ed6051397cb2a5bc61", "33d9fd317b74f4572afbe004f991ca83",
177       "ea2413cd11bf1da93de9285381b471df", "c4f78ae2b994a3a999cb3f5dac2bb498",
178       "44804ec226453bc5f688506b56ad2a8a", "9de9c12a5f3bb8d4af13da8807dfe53f",
179       "c190dac15c08f2e591b222e1d75b60c2", "c46889b58b44d242e24b91ef531e9176",
180       "b6697e1256b60b3426a8980c7c6f9a80", "1e0eb156152fbb74b0cff41bdbdf98b5",
181       "98ab6c0abc45fd44565f84e66dc71133", "f2f2126fac1b7c0c7b7ff511c6f3c91e",
182       "0cc720e878cfa35f9b72762d08adb1bf", "6efee9ce87e098122dd05525f4c74a2f",
183       "187270514a93bd7065d2cfdb02146959", "947be7f2921b5a192d4296b2060a215c",
184       "42f02b046eda2a94133032184fdaa26d", "487e94b20867e7021dd1f10d477c3acf",
185       "9f9eac4394d8821f5c14857a28c5549b", "75d781b60c1f4aa44ceb6bc65f597a52",
186       "779f9ac3c01a86812964ccc38da2711a", "16dc8824efbd7a47808ccdbf8e37df56",
187       "e72899a8ddf6cc816e1917c25739a512", "96a4bcaedae79b55399d931fecd64312",
188       "5c5e8f4a4f0153315133e4e86a02c3a6", "d1c339b6f6cc0eabdd6674028e1f4260",
189       "4ef5868adaf6712d033dce9e51837c0b", "ed90a4ddfc463dddfe71314bc3415b4e",
190       "2312299492a47246269d6d37e67c8c0c", "56baf1c4453c5cf5ce3d6857cff4aa8f",
191       "d534ce3430377b355c3f59695cfb188b", "f40248f1a6fac4299c9645350138f598",
192       "f2e3cbbd066d9d28304667d82312d950", "e8a7784eb367b72b96486bec856b873c",
193       "02941ae2cf8272b353268a30cf9c2ee0", "8f6273a5fa62b9a4225ebdbf2ce44e27",
194       "85bb0aaba73fe8c89dcee6b5c55d5cfc", "c28c63a4e46ee2a98dd2b58379971c8c",
195       "4af35738c29d27ca9930a488bacdffe6", "34a419cc3e6ab21cf099d244169d253e",
196       "7c5b8d19ac8a81b37011fabac10143d0", "e582811e05def83270d8f65060fe8966",
197       "24662536326615a3c325409e780f65bf", "717a7f7e99d329a74391477ef3c6d738",
198       "e0f38a3dba4c6e060b6ca12a18d75fc2", "fbd0cba6a27eb06e74c5ed376187e05c",
199       "14dfb487c4a7e989629a195810b814ee", "3cf6d595317ec46e08f6eaa0f0e99b43",
200       "b3cb98c418ea854e433b612fc532bac5", "262206cee670c082361497e51cbd0f43",
201       "84c11b103a9b0a61f07493dcd269e6fd", "bd9bd9994057371252398bf52c7586f0",
202       "72e5537ba5f04fe17b7a371bd12ca0e2", "5986a20b406ceed273f9e41bc0c4c775",
203       "d5eb9ea00ce19079b49562ba4a8cb574", "3205e6f3c532a63f8d5d939fa46bc444",
204       "cfb21ac467f21954903948d4e6c9a2a1", "bd9fd6aab18bbba8096746f9ed35a640",
205       "d42ec4f13f042014c5b4af5f03d19034", "8a7fdee2b57ac641e03365625850f5d6",
206       "d18638521275b3aa9dd463d067d6a390", "a7a71c433d85576198b52608c99cab47",
207       "96e2a2443bf8cfe32d7590c5011c7523", "6fbe7cd83208937229c11a8e3be5e1e9",
208       "ecf66dac310e332a108be639171b5cf3", "327b1656c61d795c30a914f52e3d7629",
209       "157d26190bde1a6f34680708bff5d02e", "d927bba0073263a7914a4076a5edfe29",
210       "b88930ec68e5e49da8204ef21635cea2", "58e174ed0036b1ac1f5a9bdd44860222",
211       "415055dfa80c6fe7c12e4d16cac22168", "9058939bfb5998d6ecd71d87a52be893",
212       "847894efa35f1528732ec3584f62f86f", "8aa9b33c0d9695690cb4088c32f31214",
213       "11e28ab9a3192a2bc9ffd3fd0a466a13", "f246009c5efafd9310fa8e365d23cab4",
214       "2381fcd9ee0ffceba5509879d9f5709d", "1cf1dc7c7c6ecf1f3381455c99e2239e",
215       "e74601883b53791045f50bbcbbbcc803", "22926eecefa94f9f39b9bb9dbb183e5b",
216       "128c24f5a5342aebb21bdaa87907daf7", "11c39f844a2e51cc4c80ffe1afa58e70",
217       "2c0548cff2145031e304d8f97abfd751", "66e1a3daf84029341b999b18bf86e5b3",
218       "0f790f210d5366bbad7eb352b4909dd9",
219   };
220   assert(id >= 0);
221   assert(id < sizeof(kDigest) / sizeof(kDigest[0]));
222   return kDigest[id];
223 }
224 #endif  // LIBGAV1_MAX_BITDEPTH == 12
225 
226 struct MaskBlendTestParam {
MaskBlendTestParamlibgav1::dsp::__anon71e0b92c0111::MaskBlendTestParam227   MaskBlendTestParam(BlockSize block_size, int subsampling_x, int subsampling_y,
228                      bool is_inter_intra, bool is_wedge_inter_intra)
229       : block_size(block_size),
230         width(kBlockWidthPixels[block_size]),
231         height(kBlockHeightPixels[block_size]),
232         subsampling_x(subsampling_x),
233         subsampling_y(subsampling_y),
234         is_inter_intra(is_inter_intra),
235         is_wedge_inter_intra(is_wedge_inter_intra) {}
236   BlockSize block_size;
237   int width;
238   int height;
239   int subsampling_x;
240   int subsampling_y;
241   bool is_inter_intra;
242   bool is_wedge_inter_intra;
243 };
244 
operator <<(std::ostream & os,const MaskBlendTestParam & param)245 std::ostream& operator<<(std::ostream& os, const MaskBlendTestParam& param) {
246   return os << ToString(param.block_size)
247             << ", subsampling(x/y): " << param.subsampling_x << "/"
248             << param.subsampling_y
249             << ", is_inter_intra: " << param.is_inter_intra
250             << ", is_wedge_inter_intra: " << param.is_wedge_inter_intra;
251 }
252 
253 template <int bitdepth, typename Pixel>
254 class MaskBlendTest : public testing::TestWithParam<MaskBlendTestParam>,
255                       public test_utils::MaxAlignedAllocable {
256  public:
257   static_assert(bitdepth >= kBitdepth8 && bitdepth <= LIBGAV1_MAX_BITDEPTH, "");
258   MaskBlendTest() = default;
259   ~MaskBlendTest() override = default;
260 
SetUp()261   void SetUp() override {
262     test_utils::ResetDspTable(bitdepth);
263     MaskBlendInit_C();
264     const dsp::Dsp* const dsp = dsp::GetDspTable(bitdepth);
265     ASSERT_NE(dsp, nullptr);
266     const testing::TestInfo* const test_info =
267         testing::UnitTest::GetInstance()->current_test_info();
268     const absl::string_view test_case = test_info->test_suite_name();
269     if (absl::StartsWith(test_case, "C/")) {
270     } else if (absl::StartsWith(test_case, "NEON/")) {
271       MaskBlendInit_NEON();
272     } else if (absl::StartsWith(test_case, "SSE41/")) {
273       if ((GetCpuInfo() & kSSE4_1) == 0) GTEST_SKIP() << "No SSE4.1 support!";
274       MaskBlendInit_SSE4_1();
275     } else {
276       FAIL() << "Unrecognized architecture prefix in test case name: "
277              << test_case;
278     }
279     func_ = (param_.is_inter_intra && !param_.is_wedge_inter_intra)
280                 ? dsp->mask_blend[0][param_.is_inter_intra]
281                 : dsp->mask_blend[param_.subsampling_x + param_.subsampling_y]
282                                  [param_.is_inter_intra];
283     func_8bpp_ = dsp->inter_intra_mask_blend_8bpp[param_.is_wedge_inter_intra
284                                                       ? param_.subsampling_x +
285                                                             param_.subsampling_y
286                                                       : 0];
287   }
288 
289  protected:
GetDigestIdOffset() const290   int GetDigestIdOffset() const {
291     // id is for retrieving the corresponding digest from the lookup table given
292     // the set of input parameters. id can be figured out by the block size and
293     // an offset (id_offset).
294     // For example, in kMaskBlendTestParam, this set of parameters
295     // (8, 8, 0, 0, false, false) corresponds to the first entry in the
296     // digest lookup table, where id == 0.
297     // (8, 8, 1, 0, false, false) corresponds to id == 17.
298     // (8, 8, 1, 1, false, false) corresponds to id == 34.
299     // (8, 8, 0, 0, true, false) corresponds to id == 51.
300     // Id_offset denotes offset for different modes (is_inter_intra,
301     // is_wedge_inter_intra).
302     // ...
303     if (!param_.is_inter_intra && !param_.is_wedge_inter_intra) {
304       return param_.subsampling_x * 17 + param_.subsampling_y * 17;
305     }
306     if (param_.is_inter_intra && !param_.is_wedge_inter_intra) {
307       return 51 + param_.subsampling_x * 7 + param_.subsampling_y * 7;
308     }
309     if (param_.is_inter_intra && param_.is_wedge_inter_intra) {
310       return 72 + param_.subsampling_x * 7 + param_.subsampling_y * 7;
311     }
312     return 0;
313   }
314 
GetDigestId() const315   int GetDigestId() const {
316     // Only 8x8 and larger blocks are tested.
317     int block_size_adjustment =
318         static_cast<int>(param_.block_size > kBlock16x4);
319     if (param_.is_inter_intra || param_.is_wedge_inter_intra) {
320       // 4:1/1:4 blocks are invalid for these modes.
321       block_size_adjustment += static_cast<int>(param_.block_size > kBlock8x32);
322       block_size_adjustment +=
323           static_cast<int>(param_.block_size > kBlock16x64);
324       block_size_adjustment += static_cast<int>(param_.block_size > kBlock32x8);
325       block_size_adjustment +=
326           static_cast<int>(param_.block_size > kBlock64x16);
327     }
328     return GetDigestIdOffset() + param_.block_size - kBlock8x8 -
329            block_size_adjustment;
330   }
331 
332   void Test(const char* digest, int num_runs);
333 
334  private:
335   using PredType =
336       typename std::conditional<bitdepth == 8, int16_t, uint16_t>::type;
337   static constexpr int kStride = kMaxSuperBlockSizeInPixels;
338   static constexpr int kDestStride = kMaxSuperBlockSizeInPixels * sizeof(Pixel);
339   const MaskBlendTestParam param_ = GetParam();
340   alignas(kMaxAlignment) PredType
341       source1_[kMaxSuperBlockSizeInPixels * kMaxSuperBlockSizeInPixels] = {};
342   uint8_t source1_8bpp_[kMaxSuperBlockSizeInPixels *
343                         kMaxSuperBlockSizeInPixels] = {};
344   alignas(kMaxAlignment) PredType
345       source2_[kMaxSuperBlockSizeInPixels * kMaxSuperBlockSizeInPixels] = {};
346   uint8_t source2_8bpp_[kMaxSuperBlockSizeInPixels *
347                         kMaxSuperBlockSizeInPixels] = {};
348   uint8_t source2_8bpp_cache_[kMaxSuperBlockSizeInPixels *
349                               kMaxSuperBlockSizeInPixels] = {};
350   uint8_t mask_[kMaxSuperBlockSizeInPixels * kMaxSuperBlockSizeInPixels];
351   uint8_t dest_[sizeof(Pixel) * kMaxSuperBlockSizeInPixels *
352                 kMaxSuperBlockSizeInPixels] = {};
353   dsp::MaskBlendFunc func_;
354   dsp::InterIntraMaskBlendFunc8bpp func_8bpp_;
355 };
356 
357 template <int bitdepth, typename Pixel>
Test(const char * const digest,const int num_runs)358 void MaskBlendTest<bitdepth, Pixel>::Test(const char* const digest,
359                                           const int num_runs) {
360   if (func_ == nullptr && func_8bpp_ == nullptr) return;
361   const int width = param_.width >> param_.subsampling_x;
362   const int height = param_.height >> param_.subsampling_y;
363 
364   // Add id offset to seed just to add more randomness to input blocks.
365   // If we use the same seed for different block sizes, the generated input
366   // blocks are repeated. For example, if input size is 8x8, the generated
367   // block is exactly the upper left half of the generated 16x16 block.
368   libvpx_test::ACMRandom rnd(libvpx_test::ACMRandom::DeterministicSeed() +
369                              GetDigestIdOffset());
370   PredType* src_1 = source1_;
371   uint8_t* src_1_8bpp = source1_8bpp_;
372   PredType* src_2 = source2_;
373   uint8_t* src_2_8bpp = source2_8bpp_;
374   const ptrdiff_t src_2_stride = param_.is_inter_intra ? kStride : width;
375   const ptrdiff_t mask_stride = param_.width;
376   uint8_t* mask_row = mask_;
377   const int range_mask = (1 << (bitdepth)) - 1;
378   for (int y = 0; y < height; ++y) {
379     for (int x = 0; x < width; ++x) {
380       src_1[x] = static_cast<PredType>(rnd.Rand16() & range_mask);
381       src_2[x] = static_cast<PredType>(rnd.Rand16() & range_mask);
382       if (param_.is_inter_intra && bitdepth == 8) {
383         src_1_8bpp[x] = src_1[x];
384         src_2_8bpp[x] = src_2[x];
385       }
386       if (!param_.is_inter_intra) {
387         // Implies isCompound == true.
388         constexpr int bitdepth_index = (bitdepth - 8) >> 1;
389         const int min_val = kCompoundPredictionRange[bitdepth_index][0];
390         const int max_val = kCompoundPredictionRange[bitdepth_index][1];
391         src_1[x] = static_cast<PredType>(rnd(max_val - min_val) + min_val);
392         src_2[x] = static_cast<PredType>(rnd(max_val - min_val) + min_val);
393       }
394     }
395     src_1 += width;
396     src_1_8bpp += width;
397     src_2 += src_2_stride;
398     src_2_8bpp += src_2_stride;
399   }
400   // Mask should be setup regardless of subsampling.
401   for (int y = 0; y < param_.height; ++y) {
402     for (int x = 0; x < param_.width; ++x) {
403       mask_row[x] = rnd.Rand8() & 63;
404       mask_row[x] += rnd.Rand8() & 1;  // Range of mask is [0, 64].
405     }
406     mask_row += mask_stride;
407   }
408 
409   absl::Duration elapsed_time;
410   for (int i = 0; i < num_runs; ++i) {
411     const absl::Time start = absl::Now();
412     if (param_.is_inter_intra && bitdepth == 8) {
413       ASSERT_EQ(func_, nullptr);
414       static_assert(sizeof(source2_8bpp_cache_) == sizeof(source2_8bpp_), "");
415       // source2_8bpp_ is modified in the call.
416       memcpy(source2_8bpp_cache_, source2_8bpp_, sizeof(source2_8bpp_));
417       func_8bpp_(source1_8bpp_, source2_8bpp_, src_2_stride, mask_, mask_stride,
418                  width, height);
419       for (int y = 0; y < height; ++y) {
420         for (int x = 0; x < width; ++x) {
421           dest_[y * kDestStride + x] = source2_8bpp_[y * src_2_stride + x];
422         }
423       }
424       memcpy(source2_8bpp_, source2_8bpp_cache_, sizeof(source2_8bpp_));
425     } else {
426       if (bitdepth != 8) {
427         ASSERT_EQ(func_8bpp_, nullptr);
428       }
429       ASSERT_NE(func_, nullptr);
430       func_(source1_, source2_, src_2_stride, mask_, mask_stride, width, height,
431             dest_, kDestStride);
432     }
433     elapsed_time += absl::Now() - start;
434   }
435 
436   test_utils::CheckMd5Digest("MaskBlend", ToString(param_.block_size), digest,
437                              dest_, sizeof(dest_), elapsed_time);
438 }
439 
440 const MaskBlendTestParam kMaskBlendTestParam[] = {
441     // is_inter_intra = false, is_wedge_inter_intra = false.
442     // block size range is from 8x8 to 128x128.
443     MaskBlendTestParam(kBlock8x8, 0, 0, false, false),
444     MaskBlendTestParam(kBlock8x16, 0, 0, false, false),
445     MaskBlendTestParam(kBlock8x32, 0, 0, false, false),
446     MaskBlendTestParam(kBlock16x8, 0, 0, false, false),
447     MaskBlendTestParam(kBlock16x16, 0, 0, false, false),
448     MaskBlendTestParam(kBlock16x32, 0, 0, false, false),
449     MaskBlendTestParam(kBlock16x64, 0, 0, false, false),
450     MaskBlendTestParam(kBlock32x8, 0, 0, false, false),
451     MaskBlendTestParam(kBlock32x16, 0, 0, false, false),
452     MaskBlendTestParam(kBlock32x32, 0, 0, false, false),
453     MaskBlendTestParam(kBlock32x64, 0, 0, false, false),
454     MaskBlendTestParam(kBlock64x16, 0, 0, false, false),
455     MaskBlendTestParam(kBlock64x32, 0, 0, false, false),
456     MaskBlendTestParam(kBlock64x64, 0, 0, false, false),
457     MaskBlendTestParam(kBlock64x128, 0, 0, false, false),
458     MaskBlendTestParam(kBlock128x64, 0, 0, false, false),
459     MaskBlendTestParam(kBlock128x128, 0, 0, false, false),
460     MaskBlendTestParam(kBlock8x8, 1, 0, false, false),
461     MaskBlendTestParam(kBlock8x16, 1, 0, false, false),
462     MaskBlendTestParam(kBlock8x32, 1, 0, false, false),
463     MaskBlendTestParam(kBlock16x8, 1, 0, false, false),
464     MaskBlendTestParam(kBlock16x16, 1, 0, false, false),
465     MaskBlendTestParam(kBlock16x32, 1, 0, false, false),
466     MaskBlendTestParam(kBlock16x64, 1, 0, false, false),
467     MaskBlendTestParam(kBlock32x8, 1, 0, false, false),
468     MaskBlendTestParam(kBlock32x16, 1, 0, false, false),
469     MaskBlendTestParam(kBlock32x32, 1, 0, false, false),
470     MaskBlendTestParam(kBlock32x64, 1, 0, false, false),
471     MaskBlendTestParam(kBlock64x16, 1, 0, false, false),
472     MaskBlendTestParam(kBlock64x32, 1, 0, false, false),
473     MaskBlendTestParam(kBlock64x64, 1, 0, false, false),
474     MaskBlendTestParam(kBlock64x128, 1, 0, false, false),
475     MaskBlendTestParam(kBlock128x64, 1, 0, false, false),
476     MaskBlendTestParam(kBlock128x128, 1, 0, false, false),
477     MaskBlendTestParam(kBlock8x8, 1, 1, false, false),
478     MaskBlendTestParam(kBlock8x16, 1, 1, false, false),
479     MaskBlendTestParam(kBlock8x32, 1, 1, false, false),
480     MaskBlendTestParam(kBlock16x8, 1, 1, false, false),
481     MaskBlendTestParam(kBlock16x16, 1, 1, false, false),
482     MaskBlendTestParam(kBlock16x32, 1, 1, false, false),
483     MaskBlendTestParam(kBlock16x64, 1, 1, false, false),
484     MaskBlendTestParam(kBlock32x8, 1, 1, false, false),
485     MaskBlendTestParam(kBlock32x16, 1, 1, false, false),
486     MaskBlendTestParam(kBlock32x32, 1, 1, false, false),
487     MaskBlendTestParam(kBlock32x64, 1, 1, false, false),
488     MaskBlendTestParam(kBlock64x16, 1, 1, false, false),
489     MaskBlendTestParam(kBlock64x32, 1, 1, false, false),
490     MaskBlendTestParam(kBlock64x64, 1, 1, false, false),
491     MaskBlendTestParam(kBlock64x128, 1, 1, false, false),
492     MaskBlendTestParam(kBlock128x64, 1, 1, false, false),
493     MaskBlendTestParam(kBlock128x128, 1, 1, false, false),
494     // is_inter_intra = true, is_wedge_inter_intra = false.
495     // block size range is from 8x8 to 32x32 (no 4:1/1:4 blocks, Section 5.11.28
496     // Read inter intra syntax).
497     MaskBlendTestParam(kBlock8x8, 0, 0, true, false),
498     MaskBlendTestParam(kBlock8x16, 0, 0, true, false),
499     MaskBlendTestParam(kBlock16x8, 0, 0, true, false),
500     MaskBlendTestParam(kBlock16x16, 0, 0, true, false),
501     MaskBlendTestParam(kBlock16x32, 0, 0, true, false),
502     MaskBlendTestParam(kBlock32x16, 0, 0, true, false),
503     MaskBlendTestParam(kBlock32x32, 0, 0, true, false),
504     MaskBlendTestParam(kBlock8x8, 1, 0, true, false),
505     MaskBlendTestParam(kBlock8x16, 1, 0, true, false),
506     MaskBlendTestParam(kBlock16x8, 1, 0, true, false),
507     MaskBlendTestParam(kBlock16x16, 1, 0, true, false),
508     MaskBlendTestParam(kBlock16x32, 1, 0, true, false),
509     MaskBlendTestParam(kBlock32x16, 1, 0, true, false),
510     MaskBlendTestParam(kBlock32x32, 1, 0, true, false),
511     MaskBlendTestParam(kBlock8x8, 1, 1, true, false),
512     MaskBlendTestParam(kBlock8x16, 1, 1, true, false),
513     MaskBlendTestParam(kBlock16x8, 1, 1, true, false),
514     MaskBlendTestParam(kBlock16x16, 1, 1, true, false),
515     MaskBlendTestParam(kBlock16x32, 1, 1, true, false),
516     MaskBlendTestParam(kBlock32x16, 1, 1, true, false),
517     MaskBlendTestParam(kBlock32x32, 1, 1, true, false),
518     // is_inter_intra = true, is_wedge_inter_intra = true.
519     // block size range is from 8x8 to 32x32 (no 4:1/1:4 blocks, Section 5.11.28
520     // Read inter intra syntax).
521     MaskBlendTestParam(kBlock8x8, 0, 0, true, true),
522     MaskBlendTestParam(kBlock8x16, 0, 0, true, true),
523     MaskBlendTestParam(kBlock16x8, 0, 0, true, true),
524     MaskBlendTestParam(kBlock16x16, 0, 0, true, true),
525     MaskBlendTestParam(kBlock16x32, 0, 0, true, true),
526     MaskBlendTestParam(kBlock32x16, 0, 0, true, true),
527     MaskBlendTestParam(kBlock32x32, 0, 0, true, true),
528     MaskBlendTestParam(kBlock8x8, 1, 0, true, true),
529     MaskBlendTestParam(kBlock8x16, 1, 0, true, true),
530     MaskBlendTestParam(kBlock16x8, 1, 0, true, true),
531     MaskBlendTestParam(kBlock16x16, 1, 0, true, true),
532     MaskBlendTestParam(kBlock16x32, 1, 0, true, true),
533     MaskBlendTestParam(kBlock32x16, 1, 0, true, true),
534     MaskBlendTestParam(kBlock32x32, 1, 0, true, true),
535     MaskBlendTestParam(kBlock8x8, 1, 1, true, true),
536     MaskBlendTestParam(kBlock8x16, 1, 1, true, true),
537     MaskBlendTestParam(kBlock16x8, 1, 1, true, true),
538     MaskBlendTestParam(kBlock16x16, 1, 1, true, true),
539     MaskBlendTestParam(kBlock16x32, 1, 1, true, true),
540     MaskBlendTestParam(kBlock32x16, 1, 1, true, true),
541     MaskBlendTestParam(kBlock32x32, 1, 1, true, true),
542 };
543 
544 using MaskBlendTest8bpp = MaskBlendTest<8, uint8_t>;
545 
TEST_P(MaskBlendTest8bpp,Blending)546 TEST_P(MaskBlendTest8bpp, Blending) { Test(GetDigest8bpp(GetDigestId()), 1); }
547 
TEST_P(MaskBlendTest8bpp,DISABLED_Speed)548 TEST_P(MaskBlendTest8bpp, DISABLED_Speed) {
549   Test(GetDigest8bpp(GetDigestId()), kNumSpeedTests);
550 }
551 
552 INSTANTIATE_TEST_SUITE_P(C, MaskBlendTest8bpp,
553                          testing::ValuesIn(kMaskBlendTestParam));
554 
555 #if LIBGAV1_ENABLE_NEON
556 INSTANTIATE_TEST_SUITE_P(NEON, MaskBlendTest8bpp,
557                          testing::ValuesIn(kMaskBlendTestParam));
558 #endif
559 
560 #if LIBGAV1_ENABLE_SSE4_1
561 INSTANTIATE_TEST_SUITE_P(SSE41, MaskBlendTest8bpp,
562                          testing::ValuesIn(kMaskBlendTestParam));
563 #endif
564 
565 #if LIBGAV1_MAX_BITDEPTH >= 10
566 using MaskBlendTest10bpp = MaskBlendTest<10, uint16_t>;
567 
TEST_P(MaskBlendTest10bpp,Blending)568 TEST_P(MaskBlendTest10bpp, Blending) { Test(GetDigest10bpp(GetDigestId()), 1); }
569 
TEST_P(MaskBlendTest10bpp,DISABLED_Speed)570 TEST_P(MaskBlendTest10bpp, DISABLED_Speed) {
571   Test(GetDigest10bpp(GetDigestId()), kNumSpeedTests);
572 }
573 
574 INSTANTIATE_TEST_SUITE_P(C, MaskBlendTest10bpp,
575                          testing::ValuesIn(kMaskBlendTestParam));
576 
577 #if LIBGAV1_ENABLE_SSE4_1
578 INSTANTIATE_TEST_SUITE_P(SSE41, MaskBlendTest10bpp,
579                          testing::ValuesIn(kMaskBlendTestParam));
580 #endif
581 #if LIBGAV1_ENABLE_NEON
582 INSTANTIATE_TEST_SUITE_P(NEON, MaskBlendTest10bpp,
583                          testing::ValuesIn(kMaskBlendTestParam));
584 #endif
585 #endif  // LIBGAV1_MAX_BITDEPTH >= 10
586 
587 #if LIBGAV1_MAX_BITDEPTH == 12
588 using MaskBlendTest12bpp = MaskBlendTest<12, uint16_t>;
589 
TEST_P(MaskBlendTest12bpp,Blending)590 TEST_P(MaskBlendTest12bpp, Blending) { Test(GetDigest12bpp(GetDigestId()), 1); }
591 
TEST_P(MaskBlendTest12bpp,DISABLED_Speed)592 TEST_P(MaskBlendTest12bpp, DISABLED_Speed) {
593   Test(GetDigest12bpp(GetDigestId()), kNumSpeedTests);
594 }
595 
596 INSTANTIATE_TEST_SUITE_P(C, MaskBlendTest12bpp,
597                          testing::ValuesIn(kMaskBlendTestParam));
598 #endif  // LIBGAV1_MAX_BITDEPTH == 12
599 
600 }  // namespace
601 }  // namespace dsp
602 }  // namespace libgav1
603