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/dsp.h"
16
17 #include <algorithm>
18 #include <cstddef>
19 #include <cstdint>
20
21 #include "absl/strings/str_cat.h"
22 #include "gtest/gtest.h"
23 #include "src/dsp/constants.h"
24 #include "src/utils/constants.h"
25 #include "src/utils/cpu.h"
26
27 #if LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
28 #include "tests/utils.h"
29 #endif
30
31 namespace libgav1 {
32 namespace dsp {
33 namespace {
34
35 // Maps 1D transform to the maximum valid size for the corresponding transform.
36 constexpr int kMaxTransform1dSize[kNumTransform1ds] = {
37 kTransform1dSize64, // Dct.
38 kTransform1dSize16, // Adst.
39 kTransform1dSize32, // Identity.
40 kTransform1dSize4, // Wht.
41 };
42
CheckTables(bool c_only)43 void CheckTables(bool c_only) {
44 #if LIBGAV1_MAX_BITDEPTH == 12
45 static constexpr int kBitdepths[] = {kBitdepth8, kBitdepth10, kBitdepth12};
46 #elif LIBGAV1_MAX_BITDEPTH >= 10
47 static constexpr int kBitdepths[] = {kBitdepth8, kBitdepth10};
48 #else
49 static constexpr int kBitdepths[] = {kBitdepth8};
50 #endif
51
52 for (const auto& bitdepth : kBitdepths) {
53 const Dsp* const dsp = GetDspTable(bitdepth);
54 ASSERT_NE(dsp, nullptr);
55 SCOPED_TRACE(absl::StrCat("bitdepth: ", bitdepth));
56 for (int i = 0; i < kNumTransformSizes; ++i) {
57 for (int j = 0; j < kNumIntraPredictors; ++j) {
58 EXPECT_NE(dsp->intra_predictors[i][j], nullptr)
59 << "index [" << i << "][" << j << "]";
60 }
61 }
62 EXPECT_NE(dsp->directional_intra_predictor_zone1, nullptr);
63 EXPECT_NE(dsp->directional_intra_predictor_zone2, nullptr);
64 EXPECT_NE(dsp->directional_intra_predictor_zone3, nullptr);
65 EXPECT_NE(dsp->filter_intra_predictor, nullptr);
66 for (int i = 0; i < kNumTransformSizes; ++i) {
67 if (std::max(kTransformWidth[i], kTransformHeight[i]) == 64) {
68 EXPECT_EQ(dsp->cfl_intra_predictors[i], nullptr)
69 << "index [" << i << "]";
70 for (int j = 0; j < kNumSubsamplingTypes; ++j) {
71 EXPECT_EQ(dsp->cfl_subsamplers[i][j], nullptr)
72 << "index [" << i << "][" << j << "]";
73 }
74 } else {
75 EXPECT_NE(dsp->cfl_intra_predictors[i], nullptr)
76 << "index [" << i << "]";
77 for (int j = 0; j < kNumSubsamplingTypes; ++j) {
78 EXPECT_NE(dsp->cfl_subsamplers[i][j], nullptr)
79 << "index [" << i << "][" << j << "]";
80 }
81 }
82 }
83 EXPECT_NE(dsp->intra_edge_filter, nullptr);
84 EXPECT_NE(dsp->intra_edge_upsampler, nullptr);
85 for (int i = 0; i < kNumTransform1ds; ++i) {
86 for (int j = 0; j < kNumTransform1dSizes; ++j) {
87 for (int k = 0; k < 2; ++k) {
88 if (j <= kMaxTransform1dSize[i]) {
89 EXPECT_NE(dsp->inverse_transforms[i][j][k], nullptr)
90 << "index [" << i << "][" << j << "][" << k << "]";
91 } else {
92 EXPECT_EQ(dsp->inverse_transforms[i][j][k], nullptr)
93 << "index [" << i << "][" << j << "][" << k << "]";
94 }
95 }
96 }
97 }
98 for (int i = 0; i < kNumLoopFilterSizes; ++i) {
99 for (int j = 0; j < kNumLoopFilterTypes; ++j) {
100 EXPECT_NE(dsp->loop_filters[i][j], nullptr)
101 << "index [" << i << "][" << j << "]";
102 }
103 }
104 for (int i = 0; i < 2; ++i) {
105 EXPECT_NE(dsp->loop_restorations[i], nullptr) << "index [" << i << "]";
106 }
107
108 bool super_res_coefficients_is_nonnull = LIBGAV1_ENABLE_NEON;
109 #if LIBGAV1_ENABLE_SSE4_1
110 const uint32_t cpu_features = GetCpuInfo();
111 super_res_coefficients_is_nonnull = (cpu_features & kSSE4_1) != 0;
112 #endif
113 if (c_only || bitdepth == kBitdepth12) {
114 super_res_coefficients_is_nonnull = false;
115 }
116 if (super_res_coefficients_is_nonnull) {
117 EXPECT_NE(dsp->super_res_coefficients, nullptr);
118 } else {
119 EXPECT_EQ(dsp->super_res_coefficients, nullptr);
120 }
121
122 EXPECT_NE(dsp->super_res, nullptr);
123 EXPECT_NE(dsp->cdef_direction, nullptr);
124 for (int i = 0; i < 2; ++i) {
125 for (int j = 0; j < 3; ++j) {
126 EXPECT_NE(dsp->cdef_filters[i][j], nullptr)
127 << "index [" << i << "][" << j << "]";
128 }
129 }
130 for (auto convolve_func : dsp->convolve_scale) {
131 EXPECT_NE(convolve_func, nullptr);
132 }
133 for (int j = 0; j < 2; ++j) {
134 for (int k = 0; k < 2; ++k) {
135 for (int l = 0; l < 2; ++l) {
136 for (int m = 0; m < 2; ++m) {
137 if (j == 1 && k == 1) {
138 EXPECT_EQ(dsp->convolve[j][k][l][m], nullptr);
139 } else {
140 EXPECT_NE(dsp->convolve[j][k][l][m], nullptr);
141 }
142 }
143 }
144 }
145 }
146 for (const auto& m : dsp->mask_blend) {
147 for (int i = 0; i < 2; ++i) {
148 if (i == 0 || bitdepth >= 10) {
149 EXPECT_NE(m[i], nullptr);
150 } else {
151 EXPECT_EQ(m[i], nullptr);
152 }
153 }
154 }
155 for (const auto& m : dsp->inter_intra_mask_blend_8bpp) {
156 if (bitdepth == 8) {
157 EXPECT_NE(m, nullptr);
158 } else {
159 EXPECT_EQ(m, nullptr);
160 }
161 }
162 for (int i = kBlock4x4; i < kMaxBlockSizes; ++i) {
163 const int width_index = k4x4WidthLog2[i] - 1;
164 const int height_index = k4x4HeightLog2[i] - 1;
165 // Only block sizes >= 8x8 are handled with this function.
166 if (width_index < 0 || height_index < 0) continue;
167
168 for (size_t j = 0; j < 2; ++j) {
169 EXPECT_NE(dsp->weight_mask[width_index][height_index][j], nullptr)
170 << ToString(static_cast<BlockSize>(i)) << " index [" << width_index
171 << "]"
172 << "[" << height_index << "][" << j << "]";
173 }
174 }
175
176 EXPECT_NE(dsp->average_blend, nullptr);
177 EXPECT_NE(dsp->distance_weighted_blend, nullptr);
178 for (int i = 0; i < kNumObmcDirections; ++i) {
179 EXPECT_NE(dsp->obmc_blend[i], nullptr)
180 << "index [" << ToString(static_cast<ObmcDirection>(i)) << "]";
181 }
182 EXPECT_NE(dsp->warp, nullptr);
183 EXPECT_NE(dsp->warp_compound, nullptr);
184
185 for (int i = 0; i < kNumAutoRegressionLags - 1; ++i) {
186 EXPECT_NE(dsp->film_grain.luma_auto_regression[i], nullptr)
187 << "index [" << i << "]";
188 }
189 for (int i = 0; i < 2; ++i) {
190 for (int j = 0; j < kNumAutoRegressionLags; ++j) {
191 if (i == 0 && j == 0) {
192 EXPECT_EQ(dsp->film_grain.chroma_auto_regression[i][j], nullptr)
193 << " index [" << i << "]"
194 << "[" << j << "]";
195 } else {
196 EXPECT_NE(dsp->film_grain.chroma_auto_regression[i][j], nullptr)
197 << " index [" << i << "]"
198 << "[" << j << "]";
199 }
200 }
201 EXPECT_NE(dsp->film_grain.construct_noise_stripes[i], nullptr)
202 << "index [" << i << "]";
203 EXPECT_NE(dsp->film_grain.blend_noise_chroma[i], nullptr)
204 << "index [" << i << "]";
205 }
206 EXPECT_NE(dsp->film_grain.construct_noise_image_overlap, nullptr);
207 EXPECT_NE(dsp->film_grain.initialize_scaling_lut, nullptr);
208 EXPECT_NE(dsp->film_grain.blend_noise_luma, nullptr);
209
210 if (bitdepth == 8) {
211 EXPECT_NE(dsp->motion_field_projection_kernel, nullptr);
212 EXPECT_NE(dsp->mv_projection_compound[0], nullptr);
213 EXPECT_NE(dsp->mv_projection_compound[1], nullptr);
214 EXPECT_NE(dsp->mv_projection_compound[2], nullptr);
215 EXPECT_NE(dsp->mv_projection_single[0], nullptr);
216 EXPECT_NE(dsp->mv_projection_single[1], nullptr);
217 EXPECT_NE(dsp->mv_projection_single[2], nullptr);
218 } else {
219 EXPECT_EQ(dsp->motion_field_projection_kernel, nullptr);
220 EXPECT_EQ(dsp->mv_projection_compound[0], nullptr);
221 EXPECT_EQ(dsp->mv_projection_compound[1], nullptr);
222 EXPECT_EQ(dsp->mv_projection_compound[2], nullptr);
223 EXPECT_EQ(dsp->mv_projection_single[0], nullptr);
224 EXPECT_EQ(dsp->mv_projection_single[1], nullptr);
225 EXPECT_EQ(dsp->mv_projection_single[2], nullptr);
226 }
227 }
228 }
229
TEST(Dsp,TablesArePopulated)230 TEST(Dsp, TablesArePopulated) {
231 DspInit();
232 CheckTables(/*c_only=*/false);
233 }
234
235 #if LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
TEST(Dsp,TablesArePopulatedCOnly)236 TEST(Dsp, TablesArePopulatedCOnly) {
237 test_utils::ResetDspTable(kBitdepth8);
238 #if LIBGAV1_MAX_BITDEPTH >= 10
239 test_utils::ResetDspTable(kBitdepth10);
240 #endif
241 #if LIBGAV1_MAX_BITDEPTH == 12
242 test_utils::ResetDspTable(kBitdepth12);
243 #endif
244 dsp_internal::DspInit_C();
245 CheckTables(/*c_only=*/true);
246 }
247 #endif // LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
248
TEST(Dsp,GetDspTable)249 TEST(Dsp, GetDspTable) {
250 EXPECT_EQ(GetDspTable(1), nullptr);
251 EXPECT_NE(GetDspTable(kBitdepth8), nullptr);
252 EXPECT_EQ(dsp_internal::GetWritableDspTable(1), nullptr);
253 EXPECT_NE(dsp_internal::GetWritableDspTable(kBitdepth8), nullptr);
254 #if LIBGAV1_MAX_BITDEPTH >= 10
255 EXPECT_NE(GetDspTable(kBitdepth10), nullptr);
256 EXPECT_NE(dsp_internal::GetWritableDspTable(kBitdepth10), nullptr);
257 #else
258 EXPECT_EQ(GetDspTable(kBitdepth10), nullptr);
259 EXPECT_EQ(dsp_internal::GetWritableDspTable(kBitdepth10), nullptr);
260 #endif
261 #if LIBGAV1_MAX_BITDEPTH == 12
262 EXPECT_NE(GetDspTable(kBitdepth12), nullptr);
263 EXPECT_NE(dsp_internal::GetWritableDspTable(kBitdepth12), nullptr);
264 #else
265 EXPECT_EQ(GetDspTable(kBitdepth12), nullptr);
266 EXPECT_EQ(dsp_internal::GetWritableDspTable(kBitdepth12), nullptr);
267 #endif
268 }
269
270 } // namespace
271 } // namespace dsp
272 } // namespace libgav1
273