1 // Copyright 2021 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/utils/common.h"
16
17 #include <cstddef>
18 #include <cstdint>
19 #include <memory>
20 #include <string>
21
22 #include "absl/base/macros.h"
23 #include "gtest/gtest.h"
24 #include "src/utils/constants.h"
25 #include "src/utils/memory.h"
26 #include "src/utils/types.h"
27
28 namespace libgav1 {
29 namespace {
30
BitLength(int64_t n)31 int BitLength(int64_t n) {
32 int count = 0;
33 while (n != 0) {
34 ++count;
35 n >>= 1;
36 }
37 return count;
38 }
39
TEST(CommonUtilsTest,Align)40 TEST(CommonUtilsTest, Align) {
41 for (int i = 0; i <= 8; ++i) {
42 const int alignment = 1 << i;
43 SCOPED_TRACE("alignment: " + std::to_string(alignment));
44 EXPECT_EQ(Align(0, alignment), 0);
45 EXPECT_EQ(Align(1, alignment), alignment);
46 EXPECT_EQ(Align(alignment + 1, alignment), 2 * alignment);
47 if (i > 1) {
48 EXPECT_EQ(Align(alignment - 1, alignment), alignment);
49 EXPECT_EQ(Align(2 * alignment - 1, alignment), 2 * alignment);
50 }
51 }
52 }
53
TEST(CommonUtilsTest,AlignAddr)54 TEST(CommonUtilsTest, AlignAddr) {
55 auto buf = MakeAlignedUniquePtr<uint8_t>(/*alignment=*/1024, 512);
56 ASSERT_NE(buf, nullptr);
57 auto* const bufptr = buf.get();
58 ASSERT_EQ(reinterpret_cast<uintptr_t>(bufptr) % 1024, 0);
59
60 for (int i = 0; i <= 8; ++i) {
61 const int alignment = 1 << i;
62 ASSERT_LE(alignment, 1024);
63 SCOPED_TRACE("alignment: " + std::to_string(alignment));
64 EXPECT_EQ(AlignAddr(nullptr, alignment), nullptr);
65 EXPECT_EQ(AlignAddr(bufptr, alignment), bufptr);
66 EXPECT_EQ(AlignAddr(bufptr + 1, alignment), bufptr + alignment);
67 EXPECT_EQ(AlignAddr(bufptr + alignment + 1, alignment),
68 bufptr + 2 * alignment);
69 if (i > 1) {
70 EXPECT_EQ(AlignAddr(bufptr + alignment - 1, alignment),
71 bufptr + alignment);
72 EXPECT_EQ(AlignAddr(bufptr + 2 * alignment - 1, alignment),
73 bufptr + 2 * alignment);
74 }
75 }
76 }
77
TEST(CommonUtilsTest,Clip3)78 TEST(CommonUtilsTest, Clip3) {
79 // Value <= lower boundary.
80 EXPECT_EQ(Clip3(10, 20, 30), 20);
81 EXPECT_EQ(Clip3(20, 20, 30), 20);
82 // Value >= higher boundary.
83 EXPECT_EQ(Clip3(40, 20, 30), 30);
84 EXPECT_EQ(Clip3(30, 20, 30), 30);
85 // Value within boundary.
86 EXPECT_EQ(Clip3(25, 20, 30), 25);
87 // Clipping based on bitdepth (clamp between 0 and 2^bitdepth - 1). Make sure
88 // that the resulting values are always in the pixel range for the
89 // corresponding bitdepth.
90 static constexpr int bitdepths[] = {8, 10, 12};
91 static constexpr int pixels[] = {100, 500, 5000, -100, -500, -5000};
92 for (const auto& bitdepth : bitdepths) {
93 for (const auto& pixel : pixels) {
94 const int clipped_pixel = Clip3(pixel, 0, (1 << bitdepth) - 1);
95 EXPECT_GE(clipped_pixel, 0)
96 << "Clip3 mismatch for bitdepth: " << bitdepth << " pixel: " << pixel;
97 EXPECT_LE(clipped_pixel, (1 << bitdepth) - 1)
98 << "Clip3 mismatch for bitdepth: " << bitdepth << " pixel: " << pixel;
99 }
100 }
101 }
102
103 template <typename Pixel>
TestExtendLine(int width,const int left,int right,Pixel left_value,Pixel right_value)104 void TestExtendLine(int width, const int left, int right, Pixel left_value,
105 Pixel right_value) {
106 constexpr int size = 1000;
107 ASSERT_LE(width + left + right, size);
108 Pixel line[size];
109 Pixel* line_start = line + left;
110 line_start[0] = left_value;
111 line_start[width - 1] = right_value;
112 ExtendLine<Pixel>(line_start, width, left, right);
113 for (int x = 0; x < left; x++) {
114 EXPECT_EQ(left_value, line[x]) << "Left side mismatch at x: " << x;
115 }
116 for (int x = 0; x < right; x++) {
117 EXPECT_EQ(right_value, line[left + width + x])
118 << "Right side mismatch at x: " << x;
119 }
120 }
121
TEST(CommonUtilsTest,ExtendLine)122 TEST(CommonUtilsTest, ExtendLine) {
123 TestExtendLine<uint8_t>(300, 0, 0, 31, 13);
124 TestExtendLine<uint8_t>(100, 10, 20, 31, 13);
125 TestExtendLine<uint8_t>(257, 31, 77, 59, 255);
126 TestExtendLine<uint16_t>(600, 0, 0, 1234, 4321);
127 TestExtendLine<uint16_t>(200, 55, 88, 12345, 54321);
128 TestExtendLine<uint16_t>(2, 99, 333, 257, 513);
129 }
130
131 template <typename T>
TestMemSetBlock(int rows,int columns,ptrdiff_t stride,T value)132 void TestMemSetBlock(int rows, int columns, ptrdiff_t stride, T value) {
133 constexpr int size = 1000;
134 T block[size];
135 static_assert(sizeof(T) == 1, "");
136 ASSERT_LE(rows * stride, size);
137 ASSERT_LE(columns, stride);
138 MemSetBlock<T>(rows, columns, value, block, stride);
139 for (int y = 0; y < rows; y++) {
140 for (int x = 0; x < columns; x++) {
141 EXPECT_EQ(value, block[y * stride + x])
142 << "Mismatch at y: " << y << " x: " << x;
143 }
144 }
145 }
146
TEST(CommonUtilsTest,MemSetBlock)147 TEST(CommonUtilsTest, MemSetBlock) {
148 TestMemSetBlock<bool>(15, 28, 29, true);
149 TestMemSetBlock<bool>(17, 1, 24, false);
150 TestMemSetBlock<bool>(7, 2, 13, true);
151 TestMemSetBlock<int8_t>(35, 17, 19, 123);
152 TestMemSetBlock<uint8_t>(19, 16, 16, 234);
153 }
154
155 template <typename T>
TestSetBlock(int rows,int columns,ptrdiff_t stride,T value)156 void TestSetBlock(int rows, int columns, ptrdiff_t stride, T value) {
157 constexpr int size = 1000;
158 T block[size];
159 ASSERT_LE(rows * stride, size);
160 ASSERT_LE(columns, stride);
161 SetBlock<T>(rows, columns, value, block, stride);
162 for (int y = 0; y < rows; y++) {
163 for (int x = 0; x < columns; x++) {
164 EXPECT_EQ(value, block[y * stride + x])
165 << "Mismatch at y: " << y << " x: " << x;
166 }
167 }
168 }
169
TEST(CommonUtilsTest,SetBlock)170 TEST(CommonUtilsTest, SetBlock) {
171 // Test 1-byte block set.
172 TestSetBlock<bool>(15, 28, 29, true);
173 TestSetBlock<bool>(17, 1, 24, false);
174 TestSetBlock<bool>(7, 2, 13, true);
175 TestSetBlock<int8_t>(35, 17, 19, 123);
176 TestSetBlock<uint8_t>(19, 16, 16, 234);
177 // Test 2-byte block set.
178 TestSetBlock<int16_t>(23, 27, 28, 1234);
179 TestSetBlock<uint16_t>(13, 39, 44, 4321);
180 // Test 4-byte block set.
181 TestSetBlock<int>(14, 7, 7, 12345);
182 TestSetBlock<int>(33, 4, 15, 54321);
183 // Test pointer block set.
184 int data;
185 TestSetBlock<int*>(23, 8, 25, &data);
186 }
187
TEST(CommonUtilsTest,CountTrailingZeros)188 TEST(CommonUtilsTest, CountTrailingZeros) {
189 EXPECT_EQ(CountTrailingZeros(0x1), 0);
190 EXPECT_EQ(CountTrailingZeros(0x3), 0);
191 EXPECT_EQ(CountTrailingZeros(0x7), 0);
192 EXPECT_EQ(CountTrailingZeros(0xF), 0);
193 EXPECT_EQ(CountTrailingZeros(0x2), 1);
194 EXPECT_EQ(CountTrailingZeros(0x6), 1);
195 EXPECT_EQ(CountTrailingZeros(0xE), 1);
196 EXPECT_EQ(CountTrailingZeros(0x4), 2);
197 EXPECT_EQ(CountTrailingZeros(0xC), 2);
198 EXPECT_EQ(CountTrailingZeros(0x8), 3);
199 EXPECT_EQ(CountTrailingZeros(0x10), 4);
200 EXPECT_EQ(CountTrailingZeros(0x30), 4);
201 EXPECT_EQ(CountTrailingZeros(0x70), 4);
202 EXPECT_EQ(CountTrailingZeros(0xF0), 4);
203 EXPECT_EQ(CountTrailingZeros(0x20), 5);
204 EXPECT_EQ(CountTrailingZeros(0x60), 5);
205 EXPECT_EQ(CountTrailingZeros(0xE0), 5);
206 EXPECT_EQ(CountTrailingZeros(0x40), 6);
207 EXPECT_EQ(CountTrailingZeros(0xC0), 6);
208 EXPECT_EQ(CountTrailingZeros(0x80), 7);
209 EXPECT_EQ(CountTrailingZeros(0x31), 0);
210 EXPECT_EQ(CountTrailingZeros(0x32), 1);
211 EXPECT_EQ(CountTrailingZeros(0x34), 2);
212 EXPECT_EQ(CountTrailingZeros(0x38), 3);
213 EXPECT_EQ(CountTrailingZeros(0x310), 4);
214 EXPECT_EQ(CountTrailingZeros(0x320), 5);
215 EXPECT_EQ(CountTrailingZeros(0x340), 6);
216 EXPECT_EQ(CountTrailingZeros(0x380), 7);
217 }
218
TEST(CommonUtilsTest,FloorLog2)219 TEST(CommonUtilsTest, FloorLog2) {
220 // Powers of 2.
221 EXPECT_EQ(FloorLog2(1), 0);
222 EXPECT_EQ(FloorLog2(2), 1);
223 EXPECT_EQ(FloorLog2(8), 3);
224 EXPECT_EQ(FloorLog2(64), 6);
225 // Powers of 2 +/- 1.
226 EXPECT_EQ(FloorLog2(9), 3);
227 EXPECT_EQ(FloorLog2(15), 3);
228 EXPECT_EQ(FloorLog2(63), 5);
229 // Large value, smaller than 32 bit.
230 EXPECT_EQ(FloorLog2(0x7fffffff), 30);
231 EXPECT_EQ(FloorLog2(0x80000000), 31);
232 // Larger than 32 bit.
233 EXPECT_EQ(FloorLog2(uint64_t{0x7fffffffffffffff}), 62);
234 EXPECT_EQ(FloorLog2(uint64_t{0x8000000000000000}), 63);
235 EXPECT_EQ(FloorLog2(uint64_t{0xffffffffffffffff}), 63);
236 }
237
TEST(CommonUtilsTest,CeilLog2)238 TEST(CommonUtilsTest, CeilLog2) {
239 // Even though log2(0) is -inf, here we explicitly define it to be 0.
240 EXPECT_EQ(CeilLog2(0), 0);
241 // Powers of 2.
242 EXPECT_EQ(CeilLog2(1), 0);
243 EXPECT_EQ(CeilLog2(2), 1);
244 EXPECT_EQ(CeilLog2(8), 3);
245 EXPECT_EQ(CeilLog2(64), 6);
246 // Powers of 2 +/- 1.
247 EXPECT_EQ(CeilLog2(9), 4);
248 EXPECT_EQ(CeilLog2(15), 4);
249 EXPECT_EQ(CeilLog2(63), 6);
250 // Large value.
251 EXPECT_EQ(CeilLog2(0x7fffffff), 31);
252 }
253
TEST(CommonUtilsTest,RightShiftWithCeiling)254 TEST(CommonUtilsTest, RightShiftWithCeiling) {
255 // Shift 1 bit.
256 EXPECT_EQ(RightShiftWithCeiling(1, 1), 1);
257 EXPECT_EQ(RightShiftWithCeiling(2, 1), 1);
258 EXPECT_EQ(RightShiftWithCeiling(3, 1), 2);
259 EXPECT_EQ(RightShiftWithCeiling(4, 1), 2);
260 EXPECT_EQ(RightShiftWithCeiling(5, 1), 3);
261 // Shift 2 bits.
262 EXPECT_EQ(RightShiftWithCeiling(1, 2), 1);
263 EXPECT_EQ(RightShiftWithCeiling(2, 2), 1);
264 EXPECT_EQ(RightShiftWithCeiling(3, 2), 1);
265 EXPECT_EQ(RightShiftWithCeiling(4, 2), 1);
266 EXPECT_EQ(RightShiftWithCeiling(5, 2), 2);
267 // Shift 20 bits.
268 EXPECT_EQ(RightShiftWithCeiling(1, 20), 1);
269 EXPECT_EQ(RightShiftWithCeiling((1 << 20) - 1, 20), 1);
270 EXPECT_EQ(RightShiftWithCeiling(1 << 20, 20), 1);
271 EXPECT_EQ(RightShiftWithCeiling((1 << 20) + 1, 20), 2);
272 EXPECT_EQ(RightShiftWithCeiling((1 << 21) - 1, 20), 2);
273 }
274
275 template <typename Input, typename Output>
VerifyRightShiftWithRounding(const Input * const values,const int * const bits,const Output * const rounded_values,size_t count)276 void VerifyRightShiftWithRounding(const Input* const values,
277 const int* const bits,
278 const Output* const rounded_values,
279 size_t count) {
280 for (size_t i = 0; i < count; ++i) {
281 const Output rounded_value = RightShiftWithRounding(values[i], bits[i]);
282 EXPECT_EQ(rounded_value, rounded_values[i]) << "Mismatch at index " << i;
283 // Rounding reduces the bit length by |bits[i]| - 1.
284 EXPECT_LE(BitLength(rounded_value), BitLength(values[i]) - (bits[i] - 1))
285 << "Mismatch at index " << i;
286 }
287 }
288
TEST(CommonUtilTest,RightShiftWithRoundingInt32)289 TEST(CommonUtilTest, RightShiftWithRoundingInt32) {
290 static constexpr int32_t values[] = {5, 203, 204, 255, 40000, 50000};
291 static constexpr int bits[] = {0, 3, 3, 3, 12, 12};
292 static constexpr int32_t rounded_values[] = {5, 25, 26, 32, 10, 12};
293 static_assert(ABSL_ARRAYSIZE(values) == ABSL_ARRAYSIZE(bits), "");
294 static_assert(ABSL_ARRAYSIZE(values) == ABSL_ARRAYSIZE(rounded_values), "");
295 VerifyRightShiftWithRounding<int32_t, int32_t>(values, bits, rounded_values,
296 ABSL_ARRAYSIZE(values));
297 }
298
TEST(CommonUtilTest,RightShiftWithRoundingUint32)299 TEST(CommonUtilTest, RightShiftWithRoundingUint32) {
300 static constexpr uint32_t values[] = {5, 203, 204, 255,
301 40000, 50000, 0x7fffffff};
302 static constexpr int bits[] = {0, 3, 3, 3, 12, 12, 20};
303 static constexpr uint32_t rounded_values[] = {5, 25, 26, 32, 10, 12, 2048};
304 static_assert(ABSL_ARRAYSIZE(values) == ABSL_ARRAYSIZE(bits), "");
305 static_assert(ABSL_ARRAYSIZE(values) == ABSL_ARRAYSIZE(rounded_values), "");
306 VerifyRightShiftWithRounding<uint32_t, uint32_t>(values, bits, rounded_values,
307 ABSL_ARRAYSIZE(values));
308 }
309
TEST(CommonUtilTest,RightShiftWithRoundingInt64)310 TEST(CommonUtilTest, RightShiftWithRoundingInt64) {
311 static constexpr int64_t values[] = {5, 203, 204, 255,
312 40000, 50000, 0x7fffffff, 0x8fffffff};
313 static constexpr int bits[] = {0, 3, 3, 3, 12, 12, 20, 20};
314 static constexpr int32_t rounded_values[] = {5, 25, 26, 32,
315 10, 12, 2048, 2304};
316 static_assert(ABSL_ARRAYSIZE(values) == ABSL_ARRAYSIZE(bits), "");
317 static_assert(ABSL_ARRAYSIZE(values) == ABSL_ARRAYSIZE(rounded_values), "");
318 VerifyRightShiftWithRounding<int64_t, int32_t>(values, bits, rounded_values,
319 ABSL_ARRAYSIZE(values));
320 }
321
322 template <typename Input>
VerifyRightShiftWithRoundingSigned(const Input * const values,const int * const bits,const int32_t * const rounded_values,int count)323 void VerifyRightShiftWithRoundingSigned(const Input* const values,
324 const int* const bits,
325 const int32_t* const rounded_values,
326 int count) {
327 for (int i = 0; i < count; ++i) {
328 int32_t rounded_value = RightShiftWithRoundingSigned(values[i], bits[i]);
329 EXPECT_EQ(rounded_value, rounded_values[i]) << "Mismatch at index " << i;
330 rounded_value = RightShiftWithRoundingSigned(-values[i], bits[i]);
331 EXPECT_EQ(rounded_value, -rounded_values[i]) << "Mismatch at index " << i;
332 }
333 }
334
TEST(CommonUtilTest,RightShiftWithRoundingSignedInt32)335 TEST(CommonUtilTest, RightShiftWithRoundingSignedInt32) {
336 static constexpr int32_t values[] = {203, 204, 255, 40000, 50000};
337 static constexpr int bits[] = {3, 3, 3, 12, 12};
338 static constexpr int32_t rounded_values[] = {25, 26, 32, 10, 12};
339 static_assert(ABSL_ARRAYSIZE(values) == ABSL_ARRAYSIZE(bits), "");
340 static_assert(ABSL_ARRAYSIZE(values) == ABSL_ARRAYSIZE(rounded_values), "");
341 VerifyRightShiftWithRoundingSigned<int32_t>(values, bits, rounded_values,
342 ABSL_ARRAYSIZE(values));
343 }
344
TEST(CommonUtilTest,RightShiftWithRoundingSignedInt64)345 TEST(CommonUtilTest, RightShiftWithRoundingSignedInt64) {
346 static constexpr int64_t values[] = {203, 204, 255, 40000,
347 50000, 0x7fffffff, 0x8fffffff};
348 static constexpr int bits[] = {3, 3, 3, 12, 12, 20, 20};
349 static constexpr int32_t rounded_values[] = {25, 26, 32, 10, 12, 2048, 2304};
350 static_assert(ABSL_ARRAYSIZE(values) == ABSL_ARRAYSIZE(bits), "");
351 static_assert(ABSL_ARRAYSIZE(values) == ABSL_ARRAYSIZE(rounded_values), "");
352 VerifyRightShiftWithRoundingSigned<int64_t>(values, bits, rounded_values,
353 ABSL_ARRAYSIZE(values));
354 }
355
TEST(CommonUtilTest,GetResidualBufferSize)356 TEST(CommonUtilTest, GetResidualBufferSize) {
357 // No subsampling.
358 EXPECT_EQ(GetResidualBufferSize(64, 64, 0, 0, 2),
359 /* 2*(64*64*3/1 + 32*4) = */ 24832);
360 // Only X is subsampled.
361 EXPECT_EQ(GetResidualBufferSize(64, 64, 1, 0, 2),
362 /* 2*(64*64*2/1 + 32*4) = */ 16640);
363 // Only Y is subsampled.
364 EXPECT_EQ(GetResidualBufferSize(64, 64, 0, 1, 2),
365 /* 2*(64*64*2/1 + 32*4) = */ 16640);
366 // Both X and Y are subsampled.
367 EXPECT_EQ(GetResidualBufferSize(64, 64, 1, 1, 2),
368 /* 2*(64*64*3/2 + 32*4) = */ 12544);
369 }
370
371 //------------------------------------------------------------------------------
372 // Tests for bitstream util functions
373
TEST(BitstreamUtilTest,IsIntraFrame)374 TEST(BitstreamUtilTest, IsIntraFrame) {
375 EXPECT_TRUE(IsIntraFrame(kFrameKey));
376 EXPECT_TRUE(IsIntraFrame(kFrameIntraOnly));
377 EXPECT_FALSE(IsIntraFrame(kFrameInter));
378 EXPECT_FALSE(IsIntraFrame(kFrameSwitch));
379 }
380
TEST(BitstreamUtilTest,GetTransformClass)381 TEST(BitstreamUtilTest, GetTransformClass) {
382 static constexpr TransformClass expected_classes[kNumTransformTypes] = {
383 kTransformClass2D, kTransformClass2D,
384 kTransformClass2D, kTransformClass2D,
385 kTransformClass2D, kTransformClass2D,
386 kTransformClass2D, kTransformClass2D,
387 kTransformClass2D, kTransformClass2D,
388 kTransformClassVertical, kTransformClassHorizontal,
389 kTransformClassVertical, kTransformClassHorizontal,
390 kTransformClassVertical, kTransformClassHorizontal,
391 };
392 for (int i = 0; i < kNumTransformTypes; ++i) {
393 EXPECT_EQ(GetTransformClass(static_cast<TransformType>(i)),
394 expected_classes[i])
395 << "Mismatch at index " << i;
396 }
397 }
398
TEST(BitstreamUtilTest,RowOrColumn4x4ToPixel)399 TEST(BitstreamUtilTest, RowOrColumn4x4ToPixel) {
400 EXPECT_EQ(RowOrColumn4x4ToPixel(10, kPlaneY, 0), 40);
401 EXPECT_EQ(RowOrColumn4x4ToPixel(10, kPlaneY, 1),
402 40); // Subsampling should have no effect on Y plane.
403 EXPECT_EQ(RowOrColumn4x4ToPixel(10, kPlaneU, 0), 40);
404 EXPECT_EQ(RowOrColumn4x4ToPixel(10, kPlaneU, 1), 20);
405 EXPECT_EQ(RowOrColumn4x4ToPixel(10, kPlaneV, 0), 40);
406 EXPECT_EQ(RowOrColumn4x4ToPixel(10, kPlaneV, 1), 20);
407 }
408
TEST(BitstreamUtilTest,GetPlaneType)409 TEST(BitstreamUtilTest, GetPlaneType) {
410 EXPECT_EQ(GetPlaneType(kPlaneY), kPlaneTypeY);
411 EXPECT_EQ(GetPlaneType(kPlaneU), kPlaneTypeUV);
412 EXPECT_EQ(GetPlaneType(kPlaneV), kPlaneTypeUV);
413 }
414
TEST(BitstreamUtils,IsDirectionalMode)415 TEST(BitstreamUtils, IsDirectionalMode) {
416 static constexpr bool is_directional_modes[kNumPredictionModes] = {
417 false, true, true, true, true, true, true, true, true,
418 false, false, false, false, false, false, false, false, false,
419 false, false, false, false, false, false, false, false,
420 };
421 for (int i = 0; i < kNumPredictionModes; ++i) {
422 EXPECT_EQ(IsDirectionalMode(static_cast<PredictionMode>(i)),
423 is_directional_modes[i])
424 << "Mismatch at index " << i;
425 }
426 }
427
TEST(BitstreamUtils,GetRelativeDistance)428 TEST(BitstreamUtils, GetRelativeDistance) {
429 // Both order_hint_bits and order_hint_shift_bits are zero. (a and b must be
430 // zero.)
431 EXPECT_EQ(GetRelativeDistance(0, 0, 0), 0);
432 EXPECT_EQ(GetRelativeDistance(10, 20, 27), -10);
433
434 EXPECT_EQ(GetRelativeDistance(2, 1, 30), 1);
435 EXPECT_EQ(GetRelativeDistance(2, 1, 29), 1);
436
437 EXPECT_EQ(GetRelativeDistance(1, 2, 30), -1);
438 EXPECT_EQ(GetRelativeDistance(1, 2, 29), -1);
439
440 // With an order_hint_bits of 4 and an order_hint_shift_bits of 28, 16 is the
441 // same as 0, 17 is the same as 1, etc. The most positive distance is 7, and
442 // the most negative distance is -8.
443
444 EXPECT_EQ(GetRelativeDistance(2, 6, 28), -4);
445 EXPECT_EQ(GetRelativeDistance(6, 2, 28), 4);
446 // 18 - 14 = 4.
447 EXPECT_EQ(GetRelativeDistance(2, 14, 28), 4);
448 // 14 - 18 = -4.
449 EXPECT_EQ(GetRelativeDistance(14, 2, 28), -4);
450 // If a and b are exactly 8 apart, GetRelativeDistance() cannot tell whether
451 // a is before or after b. GetRelativeDistance(a, b) and
452 // GetRelativeDistance(b, a) are both -8.
453 // 1 - 9 = -8.
454 EXPECT_EQ(GetRelativeDistance(1, 9, 28), -8);
455 // 9 - 17 = -8.
456 EXPECT_EQ(GetRelativeDistance(9, 1, 28), -8);
457
458 // With an order_hint_bits of 5 and an order_hint_shift_bits of 27, 32 is the
459 // same as 0, 33 is the same as 1, etc. The most positive distance is 15, and
460 // the most negative distance is -16.
461
462 // 31 - 32 = -1.
463 EXPECT_EQ(GetRelativeDistance(31, 0, 27), -1);
464 // 32 - 31 = 1.
465 EXPECT_EQ(GetRelativeDistance(0, 31, 27), 1);
466 // 30 - 33 = -3.
467 EXPECT_EQ(GetRelativeDistance(30, 1, 27), -3);
468 // 33 - 30 = 3.
469 EXPECT_EQ(GetRelativeDistance(1, 30, 27), 3);
470 // 25 - 36 = -11.
471 EXPECT_EQ(GetRelativeDistance(25, 4, 27), -11);
472 // 36 - 25 = 11.
473 EXPECT_EQ(GetRelativeDistance(4, 25, 27), 11);
474 // 15 - 0 = 15.
475 EXPECT_EQ(GetRelativeDistance(15, 0, 27), 15);
476 // If a and b are exactly 16 apart, GetRelativeDistance() cannot tell whether
477 // a is before or after b. GetRelativeDistance(a, b) and
478 // GetRelativeDistance(b, a) are both -16.
479 // 16 - 32 = -16.
480 EXPECT_EQ(GetRelativeDistance(16, 0, 27), -16);
481 // 0 - 16 = -16.
482 EXPECT_EQ(GetRelativeDistance(0, 16, 27), -16);
483 }
484
TEST(BitstreamUtils,ApplySign)485 TEST(BitstreamUtils, ApplySign) {
486 // ApplyPositive(0) = 0
487 EXPECT_EQ(ApplySign(0, 0), 0);
488 // ApplyNegative(0) = 0
489 EXPECT_EQ(ApplySign(0, -1), 0);
490
491 // ApplyPositive(1) = 1
492 EXPECT_EQ(ApplySign(1, 0), 1);
493 // ApplyNegative(1) = -1
494 EXPECT_EQ(ApplySign(1, -1), -1);
495
496 // ApplyPositive(-1) = -1
497 EXPECT_EQ(ApplySign(-1, 0), -1);
498 // ApplyNegative(-1) = 1
499 EXPECT_EQ(ApplySign(-1, -1), 1);
500
501 // ApplyPositive(1234) = 1234
502 EXPECT_EQ(ApplySign(1234, 0), 1234);
503 // ApplyNegative(1234) = -1234
504 EXPECT_EQ(ApplySign(1234, -1), -1234);
505
506 // ApplyPositive(-1234) = -1234
507 EXPECT_EQ(ApplySign(-1234, 0), -1234);
508 // ApplyNegative(-1234) = 1234
509 EXPECT_EQ(ApplySign(-1234, -1), 1234);
510 }
511
512 // 7.9.3. (without the clamp for numerator and denominator).
SpecGetMvProjectionKernel(int mv,int numerator,int denominator)513 int SpecGetMvProjectionKernel(int mv, int numerator, int denominator) {
514 int value = mv * numerator * kProjectionMvDivisionLookup[denominator];
515 if (value >= 0) {
516 value += 1 << 13;
517 value >>= 14;
518 } else {
519 value = -value;
520 value += 1 << 13;
521 value >>= 14;
522 value = -value;
523 }
524 if (value < (-(1 << 14) + 1)) value = -(1 << 14) + 1;
525 if (value > (1 << 14) - 1) value = (1 << 14) - 1;
526 return value;
527 }
528
SpecGetMvProjectionNoClamp(const MotionVector & mv,int numerator,int denominator,MotionVector * projection_mv)529 void SpecGetMvProjectionNoClamp(const MotionVector& mv, int numerator,
530 int denominator, MotionVector* projection_mv) {
531 for (int i = 0; i < 2; ++i) {
532 projection_mv->mv[i] =
533 SpecGetMvProjectionKernel(mv.mv[i], numerator, denominator);
534 }
535 }
536
TEST(BitstreamUtils,GetMvProjection)537 TEST(BitstreamUtils, GetMvProjection) {
538 const int16_t mvs[5][2] = {
539 {0, 0}, {11, 73}, {-84, 272}, {733, -827}, {-472, -697}};
540 for (auto& mv_value : mvs) {
541 for (int numerator = -kMaxFrameDistance; numerator <= kMaxFrameDistance;
542 ++numerator) {
543 for (int denominator = 0; denominator <= kMaxFrameDistance;
544 ++denominator) {
545 MotionVector mv, projection_mv, spec_projection_mv;
546 mv.mv[0] = mv_value[0];
547 mv.mv[1] = mv_value[1];
548 GetMvProjection(mv, numerator, kProjectionMvDivisionLookup[denominator],
549 &projection_mv);
550 SpecGetMvProjectionNoClamp(mv, numerator, denominator,
551 &spec_projection_mv);
552 EXPECT_EQ(projection_mv.mv32, spec_projection_mv.mv32);
553 }
554 }
555 }
556 }
557
558 // 7.9.4.
SpecProject(int value,int delta,int dst_sign)559 int SpecProject(int value, int delta, int dst_sign) {
560 constexpr int kMiSizeLog2 = 2;
561 const int sign = (dst_sign == 0) ? 1 : dst_sign;
562 int offset;
563 if (delta >= 0) {
564 offset = delta >> (3 + 1 + kMiSizeLog2);
565 } else {
566 offset = -((-delta) >> (3 + 1 + kMiSizeLog2));
567 }
568 return value + sign * offset;
569 }
570
TEST(BitstreamUtils,Project)571 TEST(BitstreamUtils, Project) {
572 for (int value = -10; value <= 10; ++value) {
573 for (int delta = -256; delta <= 256; ++delta) {
574 for (int dst_sign = -1; dst_sign <= 0; ++dst_sign) {
575 EXPECT_EQ(Project(value, delta, dst_sign),
576 SpecProject(value, delta, dst_sign));
577 }
578 }
579 }
580 }
581
TEST(BitstreamUtils,IsBlockSmallerThan8x8)582 TEST(BitstreamUtils, IsBlockSmallerThan8x8) {
583 static constexpr bool is_block_smaller_than8x8[kMaxBlockSizes] = {
584 true, true, false, true, false, false, false, false,
585 false, false, false, false, false, false, false, false,
586 false, false, false, false, false, false,
587 };
588 for (int i = 0; i < kMaxBlockSizes; ++i) {
589 EXPECT_EQ(IsBlockSmallerThan8x8(static_cast<BlockSize>(i)),
590 is_block_smaller_than8x8[i])
591 << "Mismatch at index " << i;
592 }
593 }
594
TEST(BitstreamUtils,TransformSizeToSquareTransformIndex)595 TEST(BitstreamUtils, TransformSizeToSquareTransformIndex) {
596 EXPECT_EQ(TransformSizeToSquareTransformIndex(kTransformSize4x4), 0);
597 EXPECT_EQ(TransformSizeToSquareTransformIndex(kTransformSize8x8), 1);
598 EXPECT_EQ(TransformSizeToSquareTransformIndex(kTransformSize16x16), 2);
599 EXPECT_EQ(TransformSizeToSquareTransformIndex(kTransformSize32x32), 3);
600 EXPECT_EQ(TransformSizeToSquareTransformIndex(kTransformSize64x64), 4);
601 }
602
603 } // namespace
604 } // namespace libgav1
605