1 /*
2 * Copyright 2019 The libgav1 Authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef LIBGAV1_SRC_UTILS_COMMON_H_
18 #define LIBGAV1_SRC_UTILS_COMMON_H_
19
20 #if defined(_MSC_VER)
21 #include <intrin.h>
22 #pragma intrinsic(_BitScanForward)
23 #pragma intrinsic(_BitScanReverse)
24 #if defined(_M_X64) || defined(_M_ARM) || defined(_M_ARM64)
25 #pragma intrinsic(_BitScanReverse64)
26 #define HAVE_BITSCANREVERSE64
27 #endif // defined(_M_X64) || defined(_M_ARM) || defined(_M_ARM64)
28 #endif // defined(_MSC_VER)
29
30 #include <cassert>
31 #include <cstddef>
32 #include <cstdint>
33 #include <cstdlib>
34 #include <cstring>
35 #include <type_traits>
36
37 #include "src/utils/bit_mask_set.h"
38 #include "src/utils/constants.h"
39 #include "src/utils/types.h"
40
41 namespace libgav1 {
42
43 // Aligns |value| to the desired |alignment|. |alignment| must be a power of 2.
44 template <typename T>
Align(T value,T alignment)45 inline T Align(T value, T alignment) {
46 assert(alignment != 0);
47 const T alignment_mask = alignment - 1;
48 return (value + alignment_mask) & ~alignment_mask;
49 }
50
51 // Aligns |addr| to the desired |alignment|. |alignment| must be a power of 2.
AlignAddr(uint8_t * const addr,const uintptr_t alignment)52 inline uint8_t* AlignAddr(uint8_t* const addr, const uintptr_t alignment) {
53 const auto value = reinterpret_cast<uintptr_t>(addr);
54 return reinterpret_cast<uint8_t*>(Align(value, alignment));
55 }
56
Clip3(int32_t value,int32_t low,int32_t high)57 inline int32_t Clip3(int32_t value, int32_t low, int32_t high) {
58 return value < low ? low : (value > high ? high : value);
59 }
60
61 // The following 2 templates set a block of data with uncontiguous memory to
62 // |value|. The compilers usually generate several branches to handle different
63 // cases of |columns| when inlining memset() and std::fill(), and these branches
64 // are unfortunately within the loop of |rows|. So calling these templates
65 // directly could be inefficient. It is recommended to specialize common cases
66 // of |columns|, such as 1, 2, 4, 8, 16 and 32, etc. in advance before
67 // processing the generic case of |columns|. The code size may be larger, but
68 // there would be big speed gains.
69 // Call template MemSetBlock<> when sizeof(|T|) is 1.
70 // Call template SetBlock<> when sizeof(|T|) is larger than 1.
71 template <typename T>
MemSetBlock(int rows,int columns,T value,T * dst,ptrdiff_t stride)72 void MemSetBlock(int rows, int columns, T value, T* dst, ptrdiff_t stride) {
73 static_assert(sizeof(T) == 1, "");
74 do {
75 memset(dst, value, columns);
76 dst += stride;
77 } while (--rows != 0);
78 }
79
80 template <typename T>
SetBlock(int rows,int columns,T value,T * dst,ptrdiff_t stride)81 void SetBlock(int rows, int columns, T value, T* dst, ptrdiff_t stride) {
82 do {
83 std::fill(dst, dst + columns, value);
84 dst += stride;
85 } while (--rows != 0);
86 }
87
88 #if defined(__GNUC__)
89
CountLeadingZeros(uint32_t n)90 inline int CountLeadingZeros(uint32_t n) {
91 assert(n != 0);
92 return __builtin_clz(n);
93 }
94
CountLeadingZeros(uint64_t n)95 inline int CountLeadingZeros(uint64_t n) {
96 assert(n != 0);
97 return __builtin_clzll(n);
98 }
99
CountTrailingZeros(uint32_t n)100 inline int CountTrailingZeros(uint32_t n) {
101 assert(n != 0);
102 return __builtin_ctz(n);
103 }
104
105 #elif defined(_MSC_VER)
106
CountLeadingZeros(uint32_t n)107 inline int CountLeadingZeros(uint32_t n) {
108 assert(n != 0);
109 unsigned long first_set_bit; // NOLINT(runtime/int)
110 const unsigned char bit_set = _BitScanReverse(&first_set_bit, n);
111 assert(bit_set != 0);
112 static_cast<void>(bit_set);
113 return 31 - static_cast<int>(first_set_bit);
114 }
115
CountLeadingZeros(uint64_t n)116 inline int CountLeadingZeros(uint64_t n) {
117 assert(n != 0);
118 unsigned long first_set_bit; // NOLINT(runtime/int)
119 #if defined(HAVE_BITSCANREVERSE64)
120 const unsigned char bit_set =
121 _BitScanReverse64(&first_set_bit, static_cast<unsigned __int64>(n));
122 #else // !defined(HAVE_BITSCANREVERSE64)
123 const auto n_hi = static_cast<unsigned long>(n >> 32); // NOLINT(runtime/int)
124 if (n_hi != 0) {
125 const unsigned char bit_set = _BitScanReverse(&first_set_bit, n_hi);
126 assert(bit_set != 0);
127 static_cast<void>(bit_set);
128 return 31 - static_cast<int>(first_set_bit);
129 }
130 const unsigned char bit_set = _BitScanReverse(
131 &first_set_bit, static_cast<unsigned long>(n)); // NOLINT(runtime/int)
132 #endif // defined(HAVE_BITSCANREVERSE64)
133 assert(bit_set != 0);
134 static_cast<void>(bit_set);
135 return 63 - static_cast<int>(first_set_bit);
136 }
137
138 #undef HAVE_BITSCANREVERSE64
139
CountTrailingZeros(uint32_t n)140 inline int CountTrailingZeros(uint32_t n) {
141 assert(n != 0);
142 unsigned long first_set_bit; // NOLINT(runtime/int)
143 const unsigned char bit_set = _BitScanForward(&first_set_bit, n);
144 assert(bit_set != 0);
145 static_cast<void>(bit_set);
146 return static_cast<int>(first_set_bit);
147 }
148
149 #else // !defined(__GNUC__) && !defined(_MSC_VER)
150
151 template <const int kMSB, typename T>
CountLeadingZeros(T n)152 inline int CountLeadingZeros(T n) {
153 assert(n != 0);
154 const T msb = T{1} << kMSB;
155 int count = 0;
156 while ((n & msb) == 0) {
157 ++count;
158 n <<= 1;
159 }
160 return count;
161 }
162
CountLeadingZeros(uint32_t n)163 inline int CountLeadingZeros(uint32_t n) { return CountLeadingZeros<31>(n); }
164
CountLeadingZeros(uint64_t n)165 inline int CountLeadingZeros(uint64_t n) { return CountLeadingZeros<63>(n); }
166
167 // This is the algorithm on the left in Figure 5-23, Hacker's Delight, Second
168 // Edition, page 109. The book says:
169 // If the number of trailing 0's is expected to be small or large, then the
170 // simple loops shown in Figure 5-23 are quite fast.
CountTrailingZeros(uint32_t n)171 inline int CountTrailingZeros(uint32_t n) {
172 assert(n != 0);
173 // Create a word with 1's at the positions of the trailing 0's in |n|, and
174 // 0's elsewhere (e.g., 01011000 => 00000111).
175 n = ~n & (n - 1);
176 int count = 0;
177 while (n != 0) {
178 ++count;
179 n >>= 1;
180 }
181 return count;
182 }
183
184 #endif // defined(__GNUC__)
185
FloorLog2(int32_t n)186 inline int FloorLog2(int32_t n) {
187 assert(n > 0);
188 return 31 - CountLeadingZeros(static_cast<uint32_t>(n));
189 }
190
FloorLog2(uint32_t n)191 inline int FloorLog2(uint32_t n) {
192 assert(n > 0);
193 return 31 - CountLeadingZeros(n);
194 }
195
FloorLog2(int64_t n)196 inline int FloorLog2(int64_t n) {
197 assert(n > 0);
198 return 63 - CountLeadingZeros(static_cast<uint64_t>(n));
199 }
200
FloorLog2(uint64_t n)201 inline int FloorLog2(uint64_t n) {
202 assert(n > 0);
203 return 63 - CountLeadingZeros(n);
204 }
205
CeilLog2(unsigned int n)206 inline int CeilLog2(unsigned int n) {
207 // The expression FloorLog2(n - 1) + 1 is undefined not only for n == 0 but
208 // also for n == 1, so this expression must be guarded by the n < 2 test. An
209 // alternative implementation is:
210 // return (n == 0) ? 0 : FloorLog2(n) + static_cast<int>((n & (n - 1)) != 0);
211 return (n < 2) ? 0 : FloorLog2(n - 1) + 1;
212 }
213
Ceil(int dividend,int divisor)214 constexpr int Ceil(int dividend, int divisor) {
215 return dividend / divisor + static_cast<int>(dividend % divisor != 0);
216 }
217
RightShiftWithRounding(int32_t value,int bits)218 inline int32_t RightShiftWithRounding(int32_t value, int bits) {
219 assert(bits >= 0);
220 return (value + ((1 << bits) >> 1)) >> bits;
221 }
222
RightShiftWithRounding(uint32_t value,int bits)223 inline uint32_t RightShiftWithRounding(uint32_t value, int bits) {
224 assert(bits >= 0);
225 return (value + ((1 << bits) >> 1)) >> bits;
226 }
227
228 // This variant is used when |value| can exceed 32 bits. Although the final
229 // result must always fit into int32_t.
RightShiftWithRounding(int64_t value,int bits)230 inline int32_t RightShiftWithRounding(int64_t value, int bits) {
231 assert(bits >= 0);
232 return static_cast<int32_t>((value + ((int64_t{1} << bits) >> 1)) >> bits);
233 }
234
RightShiftWithRoundingSigned(int32_t value,int bits)235 inline int32_t RightShiftWithRoundingSigned(int32_t value, int bits) {
236 assert(bits > 0);
237 // The next line is equivalent to:
238 // return (value >= 0) ? RightShiftWithRounding(value, bits)
239 // : -RightShiftWithRounding(-value, bits);
240 return RightShiftWithRounding(value + (value >> 31), bits);
241 }
242
243 // This variant is used when |value| can exceed 32 bits. Although the final
244 // result must always fit into int32_t.
RightShiftWithRoundingSigned(int64_t value,int bits)245 inline int32_t RightShiftWithRoundingSigned(int64_t value, int bits) {
246 assert(bits > 0);
247 // The next line is equivalent to:
248 // return (value >= 0) ? RightShiftWithRounding(value, bits)
249 // : -RightShiftWithRounding(-value, bits);
250 return RightShiftWithRounding(value + (value >> 63), bits);
251 }
252
DivideBy2(int n)253 constexpr int DivideBy2(int n) { return n >> 1; }
DivideBy4(int n)254 constexpr int DivideBy4(int n) { return n >> 2; }
DivideBy8(int n)255 constexpr int DivideBy8(int n) { return n >> 3; }
DivideBy16(int n)256 constexpr int DivideBy16(int n) { return n >> 4; }
DivideBy32(int n)257 constexpr int DivideBy32(int n) { return n >> 5; }
DivideBy64(int n)258 constexpr int DivideBy64(int n) { return n >> 6; }
DivideBy128(int n)259 constexpr int DivideBy128(int n) { return n >> 7; }
260
261 // Convert |value| to unsigned before shifting to avoid undefined behavior with
262 // negative values.
LeftShift(int value,int bits)263 inline int LeftShift(int value, int bits) {
264 assert(bits >= 0);
265 assert(value >= -(int64_t{1} << (31 - bits)));
266 assert(value <= (int64_t{1} << (31 - bits)) - ((bits == 0) ? 1 : 0));
267 return static_cast<int>(static_cast<uint32_t>(value) << bits);
268 }
MultiplyBy2(int n)269 inline int MultiplyBy2(int n) { return LeftShift(n, 1); }
MultiplyBy4(int n)270 inline int MultiplyBy4(int n) { return LeftShift(n, 2); }
MultiplyBy8(int n)271 inline int MultiplyBy8(int n) { return LeftShift(n, 3); }
MultiplyBy16(int n)272 inline int MultiplyBy16(int n) { return LeftShift(n, 4); }
MultiplyBy32(int n)273 inline int MultiplyBy32(int n) { return LeftShift(n, 5); }
MultiplyBy64(int n)274 inline int MultiplyBy64(int n) { return LeftShift(n, 6); }
275
Mod32(int n)276 constexpr int Mod32(int n) { return n & 0x1f; }
Mod64(int n)277 constexpr int Mod64(int n) { return n & 0x3f; }
278
279 //------------------------------------------------------------------------------
280 // Bitstream functions
281
IsIntraFrame(FrameType type)282 constexpr bool IsIntraFrame(FrameType type) {
283 return type == kFrameKey || type == kFrameIntraOnly;
284 }
285
GetTransformClass(TransformType tx_type)286 inline TransformClass GetTransformClass(TransformType tx_type) {
287 constexpr BitMaskSet kTransformClassVerticalMask(
288 kTransformTypeIdentityDct, kTransformTypeIdentityAdst,
289 kTransformTypeIdentityFlipadst);
290 if (kTransformClassVerticalMask.Contains(tx_type)) {
291 return kTransformClassVertical;
292 }
293 constexpr BitMaskSet kTransformClassHorizontalMask(
294 kTransformTypeDctIdentity, kTransformTypeAdstIdentity,
295 kTransformTypeFlipadstIdentity);
296 if (kTransformClassHorizontalMask.Contains(tx_type)) {
297 return kTransformClassHorizontal;
298 }
299 return kTransformClass2D;
300 }
301
RowOrColumn4x4ToPixel(int row_or_column4x4,Plane plane,int8_t subsampling)302 inline int RowOrColumn4x4ToPixel(int row_or_column4x4, Plane plane,
303 int8_t subsampling) {
304 return MultiplyBy4(row_or_column4x4) >> (plane == kPlaneY ? 0 : subsampling);
305 }
306
GetPlaneType(Plane plane)307 constexpr PlaneType GetPlaneType(Plane plane) {
308 return static_cast<PlaneType>(plane != kPlaneY);
309 }
310
311 // 5.11.44.
IsDirectionalMode(PredictionMode mode)312 constexpr bool IsDirectionalMode(PredictionMode mode) {
313 return mode >= kPredictionModeVertical && mode <= kPredictionModeD67;
314 }
315
316 // 5.9.3.
317 //
318 // |a| and |b| are order hints, treated as unsigned order_hint_bits-bit
319 // integers. |order_hint_shift_bits| equals (32 - order_hint_bits) % 32.
320 // order_hint_bits is at most 8, so |order_hint_shift_bits| is zero or a
321 // value between 24 and 31 (inclusive).
322 //
323 // If |order_hint_shift_bits| is zero, |a| and |b| are both zeros, and the
324 // result is zero. If |order_hint_shift_bits| is not zero, returns the
325 // signed difference |a| - |b| using "modular arithmetic". More precisely, the
326 // signed difference |a| - |b| is treated as a signed order_hint_bits-bit
327 // integer and cast to an int. The returned difference is between
328 // -(1 << (order_hint_bits - 1)) and (1 << (order_hint_bits - 1)) - 1
329 // (inclusive).
330 //
331 // NOTE: |a| and |b| are the order_hint_bits least significant bits of the
332 // actual values. This function returns the signed difference between the
333 // actual values. The returned difference is correct as long as the actual
334 // values are not more than 1 << (order_hint_bits - 1) - 1 apart.
335 //
336 // Example: Suppose order_hint_bits is 4 and |order_hint_shift_bits|
337 // is 28. Then |a| and |b| are in the range [0, 15], and the actual values for
338 // |a| and |b| must not be more than 7 apart. (If the actual values for |a| and
339 // |b| are exactly 8 apart, this function cannot tell whether the actual value
340 // for |a| is before or after the actual value for |b|.)
341 //
342 // First, consider the order hints 2 and 6. For this simple case, we have
343 // GetRelativeDistance(2, 6, 28) = 2 - 6 = -4, and
344 // GetRelativeDistance(6, 2, 28) = 6 - 2 = 4.
345 //
346 // On the other hand, consider the order hints 2 and 14. The order hints are
347 // 12 (> 7) apart, so we need to use the actual values instead. The actual
348 // values may be 34 (= 2 mod 16) and 30 (= 14 mod 16), respectively. Therefore
349 // we have
350 // GetRelativeDistance(2, 14, 28) = 34 - 30 = 4, and
351 // GetRelativeDistance(14, 2, 28) = 30 - 34 = -4.
352 //
353 // The following comments apply only to specific CPUs' SIMD implementations,
354 // such as intrinsics code.
355 // For the 2 shift operations in this function, if the SIMD packed data is
356 // 16-bit wide, try to use |order_hint_shift_bits| - 16 as the number of bits to
357 // shift; If the SIMD packed data is 8-bit wide, try to use
358 // |order_hint_shift_bits| - 24 as as the number of bits to shift.
359 // |order_hint_shift_bits| - 16 and |order_hint_shift_bits| - 24 could be -16 or
360 // -24. In these cases diff is 0, and the behavior of left or right shifting -16
361 // or -24 bits is defined for x86 SIMD instructions and ARM NEON instructions,
362 // and the result of shifting 0 is still 0. There is no guarantee that this
363 // behavior and result apply to other CPUs' SIMD instructions.
GetRelativeDistance(const unsigned int a,const unsigned int b,const unsigned int order_hint_shift_bits)364 inline int GetRelativeDistance(const unsigned int a, const unsigned int b,
365 const unsigned int order_hint_shift_bits) {
366 const int diff = a - b;
367 assert(order_hint_shift_bits <= 31);
368 if (order_hint_shift_bits == 0) {
369 assert(a == 0);
370 assert(b == 0);
371 } else {
372 assert(order_hint_shift_bits >= 24); // i.e., order_hint_bits <= 8
373 assert(a < (1u << (32 - order_hint_shift_bits)));
374 assert(b < (1u << (32 - order_hint_shift_bits)));
375 assert(diff < (1 << (32 - order_hint_shift_bits)));
376 assert(diff >= -(1 << (32 - order_hint_shift_bits)));
377 }
378 // Sign extend the result of subtracting the values.
379 // Cast to unsigned int and then left shift to avoid undefined behavior with
380 // negative values. Cast to int to do the sign extension through right shift.
381 // This requires the right shift of a signed integer be an arithmetic shift,
382 // which is true for clang, gcc, and Visual C++.
383 // These two casts do not generate extra instructions.
384 // Don't use LeftShift(diff) since a valid diff may fail its assertions.
385 // For example, GetRelativeDistance(2, 14, 28), diff equals -12 and is less
386 // than the minimum allowed value of LeftShift() which is -8.
387 // The next 3 lines are equivalent to:
388 // const int order_hint_bits = Mod32(32 - order_hint_shift_bits);
389 // const int m = (1 << order_hint_bits) >> 1;
390 // return (diff & (m - 1)) - (diff & m);
391 return static_cast<int>(static_cast<unsigned int>(diff)
392 << order_hint_shift_bits) >>
393 order_hint_shift_bits;
394 }
395
396 // Applies |sign| (must be 0 or -1) to |value|, i.e.,
397 // return (sign == 0) ? value : -value;
398 // and does so without a branch.
ApplySign(int value,int sign)399 constexpr int ApplySign(int value, int sign) { return (value ^ sign) - sign; }
400
401 // 7.9.3. (without the clamp for numerator and denominator).
GetMvProjection(const MotionVector & mv,int numerator,int division_multiplier,MotionVector * projection_mv)402 inline void GetMvProjection(const MotionVector& mv, int numerator,
403 int division_multiplier,
404 MotionVector* projection_mv) {
405 // Allow numerator and to be 0 so that this function can be called
406 // unconditionally. When numerator is 0, |projection_mv| will be 0, and this
407 // is what we want.
408 assert(std::abs(numerator) <= kMaxFrameDistance);
409 for (int i = 0; i < 2; ++i) {
410 projection_mv->mv[i] =
411 Clip3(RightShiftWithRoundingSigned(
412 mv.mv[i] * numerator * division_multiplier, 14),
413 -kProjectionMvClamp, kProjectionMvClamp);
414 }
415 }
416
417 // 7.9.4.
Project(int value,int delta,int dst_sign)418 constexpr int Project(int value, int delta, int dst_sign) {
419 return value + ApplySign(delta / 64, dst_sign);
420 }
421
IsBlockSmallerThan8x8(BlockSize size)422 inline bool IsBlockSmallerThan8x8(BlockSize size) {
423 return size < kBlock8x8 && size != kBlock4x16;
424 }
425
426 // Returns true if the either the width or the height of the block is equal to
427 // four.
IsBlockDimension4(BlockSize size)428 inline bool IsBlockDimension4(BlockSize size) {
429 return size < kBlock8x8 || size == kBlock16x4;
430 }
431
432 // Converts bitdepth 8, 10, and 12 to array index 0, 1, and 2, respectively.
BitdepthToArrayIndex(int bitdepth)433 constexpr int BitdepthToArrayIndex(int bitdepth) { return (bitdepth - 8) >> 1; }
434
435 // Maps a square transform to an index between [0, 4]. kTransformSize4x4 maps
436 // to 0, kTransformSize8x8 maps to 1 and so on.
TransformSizeToSquareTransformIndex(TransformSize tx_size)437 inline int TransformSizeToSquareTransformIndex(TransformSize tx_size) {
438 assert(kTransformWidth[tx_size] == kTransformHeight[tx_size]);
439
440 // The values of the square transform sizes happen to be in the right
441 // ranges, so we can just divide them by 4 to get the indexes.
442 static_assert(
443 std::is_unsigned<std::underlying_type<TransformSize>::type>::value, "");
444 static_assert(kTransformSize4x4 < 4, "");
445 static_assert(4 <= kTransformSize8x8 && kTransformSize8x8 < 8, "");
446 static_assert(8 <= kTransformSize16x16 && kTransformSize16x16 < 12, "");
447 static_assert(12 <= kTransformSize32x32 && kTransformSize32x32 < 16, "");
448 static_assert(16 <= kTransformSize64x64 && kTransformSize64x64 < 20, "");
449 return DivideBy4(tx_size);
450 }
451
452 // Gets the corresponding Y/U/V position, to set and get filter masks
453 // in deblock filtering.
454 // Returns luma_position if it's Y plane, whose subsampling must be 0.
455 // Returns the odd position for U/V plane, if there is subsampling.
GetDeblockPosition(const int luma_position,const int subsampling)456 constexpr int GetDeblockPosition(const int luma_position,
457 const int subsampling) {
458 return luma_position | subsampling;
459 }
460
461 // Returns the size of the residual buffer required to hold the residual values
462 // for a block or frame of size |rows| by |columns| (taking into account
463 // |subsampling_x|, |subsampling_y| and |residual_size|). |residual_size| is the
464 // number of bytes required to represent one residual value.
GetResidualBufferSize(const int rows,const int columns,const int subsampling_x,const int subsampling_y,const size_t residual_size)465 inline size_t GetResidualBufferSize(const int rows, const int columns,
466 const int subsampling_x,
467 const int subsampling_y,
468 const size_t residual_size) {
469 // The subsampling multipliers are:
470 // Both x and y are subsampled: 3 / 2.
471 // Only x or y is subsampled: 2 / 1 (which is equivalent to 4 / 2).
472 // Both x and y are not subsampled: 3 / 1 (which is equivalent to 6 / 2).
473 // So we compute the final subsampling multiplier as follows:
474 // multiplier = (2 + (4 >> subsampling_x >> subsampling_y)) / 2.
475 // Add 32 * |kResidualPaddingVertical| padding to avoid bottom boundary checks
476 // when parsing quantized coefficients.
477 const int subsampling_multiplier_num =
478 2 + (4 >> subsampling_x >> subsampling_y);
479 const int number_elements =
480 (rows * columns * subsampling_multiplier_num) >> 1;
481 const int tx_padding = 32 * kResidualPaddingVertical;
482 return residual_size * (number_elements + tx_padding);
483 }
484
485 // This function is equivalent to:
486 // std::min({kTransformWidthLog2[tx_size] - 2,
487 // kTransformWidthLog2[left_tx_size] - 2,
488 // 2});
GetTransformSizeIdWidth(TransformSize tx_size,TransformSize left_tx_size)489 constexpr LoopFilterTransformSizeId GetTransformSizeIdWidth(
490 TransformSize tx_size, TransformSize left_tx_size) {
491 return static_cast<LoopFilterTransformSizeId>(
492 static_cast<int>(tx_size > kTransformSize4x16 &&
493 left_tx_size > kTransformSize4x16) +
494 static_cast<int>(tx_size > kTransformSize8x32 &&
495 left_tx_size > kTransformSize8x32));
496 }
497
498 // This is used for 7.11.3.4 Block Inter Prediction Process, to select convolve
499 // filters.
GetFilterIndex(const int filter_index,const int length)500 inline int GetFilterIndex(const int filter_index, const int length) {
501 if (length <= 4) {
502 if (filter_index == kInterpolationFilterEightTap ||
503 filter_index == kInterpolationFilterEightTapSharp) {
504 return 4;
505 }
506 if (filter_index == kInterpolationFilterEightTapSmooth) {
507 return 5;
508 }
509 }
510 return filter_index;
511 }
512
SubsampledValue(int value,int subsampling)513 constexpr int SubsampledValue(int value, int subsampling) {
514 return (value + subsampling) >> subsampling;
515 }
516
517 } // namespace libgav1
518
519 #endif // LIBGAV1_SRC_UTILS_COMMON_H_
520