• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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