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