LibVideo/VP9: Drop the decoder intermediate bounds checks
Checking the bounds of the intermediate values was only implemented to help debug the decoder. However, it is non-fatal to have the values exceed the spec-defined bounds, and causes a measurable performance reduction. Additionally, the checks were implemented as an assertion, which is easily broken by bad input files. I see about a 4-5% decrease in decoding times in the `webm_in_vp9` test in TestVP9Decode.
This commit is contained in:
parent
7c607462a4
commit
33ff3427eb
Notes:
sideshowbarker
2024-07-17 22:09:47 +09:00
Author: https://github.com/Zaggy1024 Commit: https://github.com/SerenityOS/serenity/commit/33ff3427eb Pull-request: https://github.com/SerenityOS/serenity/pull/17416
2 changed files with 50 additions and 82 deletions
|
@ -1099,8 +1099,8 @@ DecoderErrorOr<void> Decoder::reconstruct(u8 plane, BlockContext const& block_co
|
|||
|
||||
// It is a requirement of bitstream conformance that the values written into the Dequant array in steps 1 and 2
|
||||
// are representable by a signed integer with 8 + BitDepth bits.
|
||||
for (auto i = 0u; i < block_size * block_size; i++)
|
||||
VERIFY(check_intermediate_bounds(block_context.frame_context.color_config.bit_depth, dequantized[i]));
|
||||
// Note: Since bounds checks just ensure that we will not have resulting values that will overflow, it's non-fatal
|
||||
// to allow these bounds to be violated. Therefore, we can avoid the performance cost here.
|
||||
|
||||
// 3. Invoke the 2D inverse transform block process defined in section 8.7.2 with the variable n as input.
|
||||
// The inverse transform outputs are stored back to the Dequant buffer.
|
||||
|
@ -1172,20 +1172,8 @@ inline i32 Decoder::round_2(T value, u8 bits)
|
|||
return static_cast<i32>(value);
|
||||
}
|
||||
|
||||
inline bool check_bounds(i64 value, u8 bits)
|
||||
{
|
||||
i64 const maximum = (1ll << (bits - 1ll)) - 1ll;
|
||||
return value >= ~maximum && value <= maximum;
|
||||
}
|
||||
|
||||
inline bool Decoder::check_intermediate_bounds(u8 bit_depth, Intermediate value)
|
||||
{
|
||||
i32 maximum = (1 << (8 + bit_depth - 1)) - 1;
|
||||
return value >= ~maximum && value <= maximum;
|
||||
}
|
||||
|
||||
// (8.7.1.1) The function B( a, b, angle, 0 ) performs a butterfly rotation.
|
||||
inline void Decoder::butterfly_rotation_in_place(u8 bit_depth, Span<Intermediate> data, size_t index_a, size_t index_b, u8 angle, bool flip)
|
||||
inline void Decoder::butterfly_rotation_in_place(Span<Intermediate> data, size_t index_a, size_t index_b, u8 angle, bool flip)
|
||||
{
|
||||
auto cos = cos64(angle);
|
||||
auto sin = sin64(angle);
|
||||
|
@ -1206,12 +1194,12 @@ inline void Decoder::butterfly_rotation_in_place(u8 bit_depth, Span<Intermediate
|
|||
|
||||
// It is a requirement of bitstream conformance that the values saved into the array T by this function are
|
||||
// representable by a signed integer using 8 + BitDepth bits of precision.
|
||||
VERIFY(check_intermediate_bounds(bit_depth, data[index_a]));
|
||||
VERIFY(check_intermediate_bounds(bit_depth, data[index_b]));
|
||||
// Note: Since bounds checks just ensure that we will not have resulting values that will overflow, it's non-fatal
|
||||
// to allow these bounds to be violated. Therefore, we can avoid the performance cost here.
|
||||
}
|
||||
|
||||
// (8.7.1.1) The function H( a, b, 0 ) performs a Hadamard rotation.
|
||||
inline void Decoder::hadamard_rotation_in_place(u8 bit_depth, Span<Intermediate> data, size_t index_a, size_t index_b, bool flip)
|
||||
inline void Decoder::hadamard_rotation_in_place(Span<Intermediate> data, size_t index_a, size_t index_b, bool flip)
|
||||
{
|
||||
// The function H( a, b, 1 ) performs a Hadamard rotation with flipped indices and is specified as follows:
|
||||
// 1. The function H( b, a, 0 ) is invoked.
|
||||
|
@ -1231,8 +1219,8 @@ inline void Decoder::hadamard_rotation_in_place(u8 bit_depth, Span<Intermediate>
|
|||
|
||||
// It is a requirement of bitstream conformance that the values saved into the array T by this function are
|
||||
// representable by a signed integer using 8 + BitDepth bits of precision.
|
||||
VERIFY(check_intermediate_bounds(bit_depth, data[index_a]));
|
||||
VERIFY(check_intermediate_bounds(bit_depth, data[index_b]));
|
||||
// Note: Since bounds checks just ensure that we will not have resulting values that will overflow, it's non-fatal
|
||||
// to allow these bounds to be violated. Therefore, we can avoid the performance cost here.
|
||||
}
|
||||
|
||||
inline DecoderErrorOr<void> Decoder::inverse_discrete_cosine_transform_array_permutation(Span<Intermediate> data, u8 log2_of_block_size)
|
||||
|
@ -1255,7 +1243,7 @@ inline DecoderErrorOr<void> Decoder::inverse_discrete_cosine_transform_array_per
|
|||
return {};
|
||||
}
|
||||
|
||||
inline DecoderErrorOr<void> Decoder::inverse_discrete_cosine_transform(u8 bit_depth, Span<Intermediate> data, u8 log2_of_block_size)
|
||||
inline DecoderErrorOr<void> Decoder::inverse_discrete_cosine_transform(Span<Intermediate> data, u8 log2_of_block_size)
|
||||
{
|
||||
// 2.1. The variable n0 is set equal to 1<<n.
|
||||
u8 block_size = 1 << log2_of_block_size;
|
||||
|
@ -1272,14 +1260,14 @@ inline DecoderErrorOr<void> Decoder::inverse_discrete_cosine_transform(u8 bit_de
|
|||
// 2.5 If n is equal to 2, invoke B( 0, 1, 16, 1 ), otherwise recursively invoke the inverse DCT defined in this
|
||||
// section with the variable n set equal to n - 1.
|
||||
if (log2_of_block_size == 2)
|
||||
butterfly_rotation_in_place(bit_depth, data, 0, 1, 16, true);
|
||||
butterfly_rotation_in_place(data, 0, 1, 16, true);
|
||||
else
|
||||
TRY(inverse_discrete_cosine_transform(bit_depth, data, log2_of_block_size - 1));
|
||||
TRY(inverse_discrete_cosine_transform(data, log2_of_block_size - 1));
|
||||
|
||||
// 2.6 Invoke B( n1+i, n0-1-i, 32-brev( 5, n1+i), 0 ) for i = 0..(n2-1).
|
||||
for (auto i = 0u; i < quarter_block_size; i++) {
|
||||
auto index = half_block_size + i;
|
||||
butterfly_rotation_in_place(bit_depth, data, index, block_size - 1 - i, 32 - brev(5, index), false);
|
||||
butterfly_rotation_in_place(data, index, block_size - 1 - i, 32 - brev(5, index), false);
|
||||
}
|
||||
|
||||
// 2.7 If n is greater than or equal to 3:
|
||||
|
@ -1288,7 +1276,7 @@ inline DecoderErrorOr<void> Decoder::inverse_discrete_cosine_transform(u8 bit_de
|
|||
for (auto i = 0u; i < eighth_block_size; i++) {
|
||||
for (auto j = 0u; j < 2; j++) {
|
||||
auto index = half_block_size + (4 * i) + (2 * j);
|
||||
hadamard_rotation_in_place(bit_depth, data, index, index + 1, j);
|
||||
hadamard_rotation_in_place(data, index, index + 1, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1301,7 +1289,7 @@ inline DecoderErrorOr<void> Decoder::inverse_discrete_cosine_transform(u8 bit_de
|
|||
auto index_a = block_size - log2_of_block_size + 3 - (quarter_block_size * j) - (4 * i);
|
||||
auto index_b = half_block_size + log2_of_block_size - 4 + (quarter_block_size * j) + (4 * i);
|
||||
auto angle = 28 - (16 * i) + (56 * j);
|
||||
butterfly_rotation_in_place(bit_depth, data, index_a, index_b, angle, true);
|
||||
butterfly_rotation_in_place(data, index_a, index_b, angle, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1310,7 +1298,7 @@ inline DecoderErrorOr<void> Decoder::inverse_discrete_cosine_transform(u8 bit_de
|
|||
for (auto j = 0u; j < 4; j++) {
|
||||
auto index_a = half_block_size + (eighth_block_size * j) + i;
|
||||
auto index_b = half_block_size + quarter_block_size - 5 + (eighth_block_size * j) - i;
|
||||
hadamard_rotation_in_place(bit_depth, data, index_a, index_b, (j & 1) != 0);
|
||||
hadamard_rotation_in_place(data, index_a, index_b, (j & 1) != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1322,7 +1310,7 @@ inline DecoderErrorOr<void> Decoder::inverse_discrete_cosine_transform(u8 bit_de
|
|||
for (auto j = 0u; j < 2; j++) {
|
||||
auto index_a = block_size - log2_of_block_size + 2 - i - (quarter_block_size * j);
|
||||
auto index_b = half_block_size + log2_of_block_size - 3 + i + (quarter_block_size * j);
|
||||
butterfly_rotation_in_place(bit_depth, data, index_a, index_b, 24 + (48 * j), true);
|
||||
butterfly_rotation_in_place(data, index_a, index_b, 24 + (48 * j), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1331,7 +1319,7 @@ inline DecoderErrorOr<void> Decoder::inverse_discrete_cosine_transform(u8 bit_de
|
|||
for (auto j = 0u; j < 2; j++) {
|
||||
auto index_a = half_block_size + (quarter_block_size * j) + i;
|
||||
auto index_b = half_block_size + quarter_block_size - 1 + (quarter_block_size * j) - i;
|
||||
hadamard_rotation_in_place(bit_depth, data, index_a, index_b, (j & 1) != 0);
|
||||
hadamard_rotation_in_place(data, index_a, index_b, (j & 1) != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1342,13 +1330,13 @@ inline DecoderErrorOr<void> Decoder::inverse_discrete_cosine_transform(u8 bit_de
|
|||
for (auto i = 0u; i < eighth_block_size; i++) {
|
||||
auto index_a = block_size - eighth_block_size - 1 - i;
|
||||
auto index_b = half_block_size + eighth_block_size + i;
|
||||
butterfly_rotation_in_place(bit_depth, data, index_a, index_b, 16, true);
|
||||
butterfly_rotation_in_place(data, index_a, index_b, 16, true);
|
||||
}
|
||||
}
|
||||
|
||||
// 7. Invoke H( i, n0-1-i, 0 ) for i = 0..(n1-1).
|
||||
for (auto i = 0u; i < half_block_size; i++)
|
||||
hadamard_rotation_in_place(bit_depth, data, i, block_size - 1 - i, false);
|
||||
hadamard_rotation_in_place(data, i, block_size - 1 - i, false);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
@ -1402,7 +1390,7 @@ inline void Decoder::inverse_asymmetric_discrete_sine_transform_output_array_per
|
|||
}
|
||||
}
|
||||
|
||||
inline void Decoder::inverse_asymmetric_discrete_sine_transform_4(u8 bit_depth, Span<Intermediate> data)
|
||||
inline void Decoder::inverse_asymmetric_discrete_sine_transform_4(Span<Intermediate> data)
|
||||
{
|
||||
VERIFY(data.size() == 4);
|
||||
const i64 sinpi_1_9 = 5283;
|
||||
|
@ -1459,11 +1447,8 @@ inline void Decoder::inverse_asymmetric_discrete_sine_transform_4(u8 bit_depth,
|
|||
// (8.7.1.1) The inverse asymmetric discrete sine transforms also make use of an intermediate array named S.
|
||||
// The values in this array require higher precision to avoid overflow. Using signed integers with 24 +
|
||||
// BitDepth bits of precision is enough to avoid overflow.
|
||||
const u8 bits = 24 + bit_depth;
|
||||
VERIFY(check_bounds(data[0], bits));
|
||||
VERIFY(check_bounds(data[1], bits));
|
||||
VERIFY(check_bounds(data[2], bits));
|
||||
VERIFY(check_bounds(data[3], bits));
|
||||
// Note: Since bounds checks just ensure that we will not have resulting values that will overflow, it's non-fatal
|
||||
// to allow these bounds to be violated. Therefore, we can avoid the performance cost here.
|
||||
}
|
||||
|
||||
// The function SB( a, b, angle, 0 ) performs a butterfly rotation.
|
||||
|
@ -1503,12 +1488,14 @@ inline void Decoder::hadamard_rotation(Span<S> source, Span<D> destination, size
|
|||
destination[index_b] = round_2(a - b, 14);
|
||||
}
|
||||
|
||||
inline DecoderErrorOr<void> Decoder::inverse_asymmetric_discrete_sine_transform_8(u8 bit_depth, Span<Intermediate> data)
|
||||
inline DecoderErrorOr<void> Decoder::inverse_asymmetric_discrete_sine_transform_8(Span<Intermediate> data)
|
||||
{
|
||||
VERIFY(data.size() == 8);
|
||||
// This process does an in-place transform of the array T using:
|
||||
|
||||
// A higher precision array S for intermediate results.
|
||||
// (8.7.1.1) NOTE - The values in array S require higher precision to avoid overflow. Using signed integers with
|
||||
// 24 + BitDepth bits of precision is enough to avoid overflow.
|
||||
Array<i64, 8> high_precision_temp;
|
||||
|
||||
// The following ordered steps apply:
|
||||
|
@ -1520,11 +1507,7 @@ inline DecoderErrorOr<void> Decoder::inverse_asymmetric_discrete_sine_transform_
|
|||
// 2. Invoke SB( 2*i, 1+2*i, 30-8*i, 1 ) for i = 0..3.
|
||||
for (auto i = 0u; i < 4; i++)
|
||||
butterfly_rotation(data, high_precision_temp.span(), 2 * i, 1 + (2 * i), 30 - (8 * i), true);
|
||||
// (8.7.1.1) NOTE - The values in array S require higher precision to avoid overflow. Using signed integers with
|
||||
// 24 + BitDepth bits of precision is enough to avoid overflow.
|
||||
const u8 bits = 24 + bit_depth;
|
||||
for (auto i = 0u; i < 8; i++)
|
||||
VERIFY(check_bounds(high_precision_temp[i], bits));
|
||||
|
||||
// 3. Invoke SH( i, 4+i ) for i = 0..3.
|
||||
for (auto i = 0u; i < 4; i++)
|
||||
hadamard_rotation(high_precision_temp.span(), data, i, 4 + i);
|
||||
|
@ -1532,20 +1515,17 @@ inline DecoderErrorOr<void> Decoder::inverse_asymmetric_discrete_sine_transform_
|
|||
// 4. Invoke SB( 4+3*i, 5+i, 24-16*i, 1 ) for i = 0..1.
|
||||
for (auto i = 0u; i < 2; i++)
|
||||
butterfly_rotation(data, high_precision_temp.span(), 4 + (3 * i), 5 + i, 24 - (16 * i), true);
|
||||
// Check again that we haven't exceeded the integer bounds.
|
||||
for (auto i = 0u; i < 8; i++)
|
||||
VERIFY(check_bounds(high_precision_temp[i], bits));
|
||||
// 5. Invoke SH( 4+i, 6+i ) for i = 0..1.
|
||||
for (auto i = 0u; i < 2; i++)
|
||||
hadamard_rotation(high_precision_temp.span(), data, 4 + i, 6 + i);
|
||||
|
||||
// 6. Invoke H( i, 2+i, 0 ) for i = 0..1.
|
||||
for (auto i = 0u; i < 2; i++)
|
||||
hadamard_rotation_in_place(bit_depth, data, i, 2 + i, false);
|
||||
hadamard_rotation_in_place(data, i, 2 + i, false);
|
||||
|
||||
// 7. Invoke B( 2+4*i, 3+4*i, 16, 1 ) for i = 0..1.
|
||||
for (auto i = 0u; i < 2; i++)
|
||||
butterfly_rotation_in_place(bit_depth, data, 2 + (4 * i), 3 + (4 * i), 16, true);
|
||||
butterfly_rotation_in_place(data, 2 + (4 * i), 3 + (4 * i), 16, true);
|
||||
|
||||
// 8. Invoke the ADST output array permutation process specified in section 8.7.1.5 with the input variable n
|
||||
// set equal to 3.
|
||||
|
@ -1559,12 +1539,15 @@ inline DecoderErrorOr<void> Decoder::inverse_asymmetric_discrete_sine_transform_
|
|||
return {};
|
||||
}
|
||||
|
||||
inline DecoderErrorOr<void> Decoder::inverse_asymmetric_discrete_sine_transform_16(u8 bit_depth, Span<Intermediate> data)
|
||||
inline DecoderErrorOr<void> Decoder::inverse_asymmetric_discrete_sine_transform_16(Span<Intermediate> data)
|
||||
{
|
||||
VERIFY(data.size() == 16);
|
||||
// This process does an in-place transform of the array T using:
|
||||
|
||||
// A higher precision array S for intermediate results.
|
||||
// (8.7.1.1) The inverse asymmetric discrete sine transforms also make use of an intermediate array named S.
|
||||
// The values in this array require higher precision to avoid overflow. Using signed integers with 24 +
|
||||
// BitDepth bits of precision is enough to avoid overflow.
|
||||
Array<i64, 16> high_precision_temp;
|
||||
|
||||
// The following ordered steps apply:
|
||||
|
@ -1576,12 +1559,6 @@ inline DecoderErrorOr<void> Decoder::inverse_asymmetric_discrete_sine_transform_
|
|||
// 2. Invoke SB( 2*i, 1+2*i, 31-4*i, 1 ) for i = 0..7.
|
||||
for (auto i = 0u; i < 8; i++)
|
||||
butterfly_rotation(data, high_precision_temp.span(), 2 * i, 1 + (2 * i), 31 - (4 * i), true);
|
||||
// (8.7.1.1) The inverse asymmetric discrete sine transforms also make use of an intermediate array named S.
|
||||
// The values in this array require higher precision to avoid overflow. Using signed integers with 24 +
|
||||
// BitDepth bits of precision is enough to avoid overflow.
|
||||
const u8 bits = 24 + bit_depth;
|
||||
for (auto i = 0u; i < 16; i++)
|
||||
VERIFY(check_bounds(data[i], bits));
|
||||
// 3. Invoke SH( i, 8+i ) for i = 0..7.
|
||||
for (auto i = 0u; i < 8; i++)
|
||||
hadamard_rotation(high_precision_temp.span(), data, i, 8 + i);
|
||||
|
@ -1589,24 +1566,18 @@ inline DecoderErrorOr<void> Decoder::inverse_asymmetric_discrete_sine_transform_
|
|||
// 4. Invoke SB( 8+2*i, 9+2*i, 28-16*i, 1 ) for i = 0..3.
|
||||
for (auto i = 0u; i < 4; i++)
|
||||
butterfly_rotation(data, high_precision_temp.span(), 8 + (2 * i), 9 + (2 * i), 128 + 28 - (16 * i), true);
|
||||
// Check again that we haven't exceeded the integer bounds.
|
||||
for (auto i = 0u; i < 16; i++)
|
||||
VERIFY(check_bounds(data[i], bits));
|
||||
// 5. Invoke SH( 8+i, 12+i ) for i = 0..3.
|
||||
for (auto i = 0u; i < 4; i++)
|
||||
hadamard_rotation(high_precision_temp.span(), data, 8 + i, 12 + i);
|
||||
|
||||
// 6. Invoke H( i, 4+i, 0 ) for i = 0..3.
|
||||
for (auto i = 0u; i < 4; i++)
|
||||
hadamard_rotation_in_place(bit_depth, data, i, 4 + i, false);
|
||||
hadamard_rotation_in_place(data, i, 4 + i, false);
|
||||
|
||||
// 7. Invoke SB( 4+8*i+3*j, 5+8*i+j, 24-16*j, 1 ) for i = 0..1, for j = 0..1.
|
||||
for (auto i = 0u; i < 2; i++)
|
||||
for (auto j = 0u; j < 2; j++)
|
||||
butterfly_rotation(data, high_precision_temp.span(), 4 + (8 * i) + (3 * j), 5 + (8 * i) + j, 24 - (16 * j), true);
|
||||
// Check again that we haven't exceeded the integer bounds.
|
||||
for (auto i = 0u; i < 16; i++)
|
||||
VERIFY(check_bounds(data[i], bits));
|
||||
// 8. Invoke SH( 4+8*j+i, 6+8*j+i ) for i = 0..1, j = 0..1.
|
||||
for (auto i = 0u; i < 2; i++)
|
||||
for (auto j = 0u; j < 2; j++)
|
||||
|
@ -1615,11 +1586,11 @@ inline DecoderErrorOr<void> Decoder::inverse_asymmetric_discrete_sine_transform_
|
|||
// 9. Invoke H( 8*j+i, 2+8*j+i, 0 ) for i = 0..1, for j = 0..1.
|
||||
for (auto i = 0u; i < 2; i++)
|
||||
for (auto j = 0u; j < 2; j++)
|
||||
hadamard_rotation_in_place(bit_depth, data, (8 * j) + i, 2 + (8 * j) + i, false);
|
||||
hadamard_rotation_in_place(data, (8 * j) + i, 2 + (8 * j) + i, false);
|
||||
// 10. Invoke B( 2+4*j+8*i, 3+4*j+8*i, 48+64*(i^j), 0 ) for i = 0..1, for j = 0..1.
|
||||
for (auto i = 0u; i < 2; i++)
|
||||
for (auto j = 0u; j < 2; j++)
|
||||
butterfly_rotation_in_place(bit_depth, data, 2 + (4 * j) + (8 * i), 3 + (4 * j) + (8 * i), 48 + (64 * (i ^ j)), false);
|
||||
butterfly_rotation_in_place(data, 2 + (4 * j) + (8 * i), 3 + (4 * j) + (8 * i), 48 + (64 * (i ^ j)), false);
|
||||
|
||||
// 11. Invoke the ADST output array permutation process specified in section 8.7.1.5 with the input variable n
|
||||
// set equal to 4.
|
||||
|
@ -1635,7 +1606,7 @@ inline DecoderErrorOr<void> Decoder::inverse_asymmetric_discrete_sine_transform_
|
|||
return {};
|
||||
}
|
||||
|
||||
inline DecoderErrorOr<void> Decoder::inverse_asymmetric_discrete_sine_transform(u8 bit_depth, Span<Intermediate> data, u8 log2_of_block_size)
|
||||
inline DecoderErrorOr<void> Decoder::inverse_asymmetric_discrete_sine_transform(Span<Intermediate> data, u8 log2_of_block_size)
|
||||
{
|
||||
// 8.7.1.9 Inverse ADST Process
|
||||
|
||||
|
@ -1646,15 +1617,15 @@ inline DecoderErrorOr<void> Decoder::inverse_asymmetric_discrete_sine_transform(
|
|||
// The process to invoke depends on n as follows:
|
||||
if (log2_of_block_size == 2) {
|
||||
// − If n is equal to 2, invoke the Inverse ADST4 process specified in section 8.7.1.6.
|
||||
inverse_asymmetric_discrete_sine_transform_4(bit_depth, data);
|
||||
inverse_asymmetric_discrete_sine_transform_4(data);
|
||||
return {};
|
||||
}
|
||||
if (log2_of_block_size == 3) {
|
||||
// − Otherwise if n is equal to 3, invoke the Inverse ADST8 process specified in section 8.7.1.7.
|
||||
return inverse_asymmetric_discrete_sine_transform_8(bit_depth, data);
|
||||
return inverse_asymmetric_discrete_sine_transform_8(data);
|
||||
}
|
||||
// − Otherwise (n is equal to 4), invoke the Inverse ADST16 process specified in section 8.7.1.8.
|
||||
return inverse_asymmetric_discrete_sine_transform_16(bit_depth, data);
|
||||
return inverse_asymmetric_discrete_sine_transform_16(data);
|
||||
}
|
||||
|
||||
DecoderErrorOr<void> Decoder::inverse_transform_2d(BlockContext const& block_context, Span<Intermediate> dequantized, u8 log2_of_block_size, TransformSet transform_set)
|
||||
|
@ -1687,12 +1658,12 @@ DecoderErrorOr<void> Decoder::inverse_transform_2d(BlockContext const& block_con
|
|||
// 1. Invoke the inverse DCT permutation process as specified in section 8.7.1.2 with the input variable n.
|
||||
TRY(inverse_discrete_cosine_transform_array_permutation(row, log2_of_block_size));
|
||||
// 2. Invoke the inverse DCT process as specified in section 8.7.1.3 with the input variable n.
|
||||
TRY(inverse_discrete_cosine_transform(block_context.frame_context.color_config.bit_depth, row, log2_of_block_size));
|
||||
TRY(inverse_discrete_cosine_transform(row, log2_of_block_size));
|
||||
break;
|
||||
case TransformType::ADST:
|
||||
// 4. Otherwise (TxType is equal to DCT_ADST or TxType is equal to ADST_ADST), invoke the inverse ADST
|
||||
// process as specified in section 8.7.1.9 with input variable n.
|
||||
TRY(inverse_asymmetric_discrete_sine_transform(block_context.frame_context.color_config.bit_depth, row, log2_of_block_size));
|
||||
TRY(inverse_asymmetric_discrete_sine_transform(row, log2_of_block_size));
|
||||
break;
|
||||
default:
|
||||
return DecoderError::corrupted("Unknown tx_type"sv);
|
||||
|
@ -1725,12 +1696,12 @@ DecoderErrorOr<void> Decoder::inverse_transform_2d(BlockContext const& block_con
|
|||
// 1. Invoke the inverse DCT permutation process as specified in section 8.7.1.2 with the input variable n.
|
||||
TRY(inverse_discrete_cosine_transform_array_permutation(column, log2_of_block_size));
|
||||
// 2. Invoke the inverse DCT process as specified in section 8.7.1.3 with the input variable n.
|
||||
TRY(inverse_discrete_cosine_transform(block_context.frame_context.color_config.bit_depth, column, log2_of_block_size));
|
||||
TRY(inverse_discrete_cosine_transform(column, log2_of_block_size));
|
||||
break;
|
||||
case TransformType::ADST:
|
||||
// 4. Otherwise (TxType is equal to ADST_DCT or TxType is equal to ADST_ADST), invoke the inverse ADST
|
||||
// process as specified in section 8.7.1.9 with input variable n.
|
||||
TRY(inverse_asymmetric_discrete_sine_transform(block_context.frame_context.color_config.bit_depth, column, log2_of_block_size));
|
||||
TRY(inverse_asymmetric_discrete_sine_transform(column, log2_of_block_size));
|
||||
break;
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
|
|
|
@ -89,9 +89,9 @@ private:
|
|||
inline i32 cos64(u8 angle);
|
||||
inline i32 sin64(u8 angle);
|
||||
// The function B( a, b, angle, 0 ) performs a butterfly rotation.
|
||||
inline void butterfly_rotation_in_place(u8 bit_depth, Span<Intermediate> data, size_t index_a, size_t index_b, u8 angle, bool flip);
|
||||
inline void butterfly_rotation_in_place(Span<Intermediate> data, size_t index_a, size_t index_b, u8 angle, bool flip);
|
||||
// The function H( a, b, 0 ) performs a Hadamard rotation.
|
||||
inline void hadamard_rotation_in_place(u8 bit_depth, Span<Intermediate> data, size_t index_a, size_t index_b, bool flip);
|
||||
inline void hadamard_rotation_in_place(Span<Intermediate> data, size_t index_a, size_t index_b, bool flip);
|
||||
// The function SB( a, b, angle, 0 ) performs a butterfly rotation.
|
||||
// Spec defines the source as array T, and the destination array as S.
|
||||
template<typename S, typename D>
|
||||
|
@ -104,16 +104,13 @@ private:
|
|||
template<typename T>
|
||||
inline i32 round_2(T value, u8 bits);
|
||||
|
||||
// Checks whether the value is representable by a signed integer with (8 + bit_depth) bits.
|
||||
inline bool check_intermediate_bounds(u8 bit_depth, Intermediate value);
|
||||
|
||||
// (8.7.1.10) This process does an in-place Walsh-Hadamard transform of the array T (of length 4).
|
||||
inline DecoderErrorOr<void> inverse_walsh_hadamard_transform(Span<Intermediate> data, u8 log2_of_block_size, u8 shift);
|
||||
|
||||
// (8.7.1.2) Inverse DCT array permutation process
|
||||
inline DecoderErrorOr<void> inverse_discrete_cosine_transform_array_permutation(Span<Intermediate> data, u8 log2_of_block_size);
|
||||
// (8.7.1.3) Inverse DCT process
|
||||
inline DecoderErrorOr<void> inverse_discrete_cosine_transform(u8 bit_depth, Span<Intermediate> data, u8 log2_of_block_size);
|
||||
inline DecoderErrorOr<void> inverse_discrete_cosine_transform(Span<Intermediate> data, u8 log2_of_block_size);
|
||||
|
||||
// (8.7.1.4) This process performs the in-place permutation of the array T of length 2 n which is required as the first step of
|
||||
// the inverse ADST.
|
||||
|
@ -123,15 +120,15 @@ private:
|
|||
inline void inverse_asymmetric_discrete_sine_transform_output_array_permutation(Span<Intermediate> data, u8 log2_of_block_size);
|
||||
|
||||
// (8.7.1.6) This process does an in-place transform of the array T to perform an inverse ADST.
|
||||
inline void inverse_asymmetric_discrete_sine_transform_4(u8 bit_depth, Span<Intermediate> data);
|
||||
inline void inverse_asymmetric_discrete_sine_transform_4(Span<Intermediate> data);
|
||||
// (8.7.1.7) This process does an in-place transform of the array T using a higher precision array S for intermediate
|
||||
// results.
|
||||
inline DecoderErrorOr<void> inverse_asymmetric_discrete_sine_transform_8(u8 bit_depth, Span<Intermediate> data);
|
||||
inline DecoderErrorOr<void> inverse_asymmetric_discrete_sine_transform_8(Span<Intermediate> data);
|
||||
// (8.7.1.8) This process does an in-place transform of the array T using a higher precision array S for intermediate
|
||||
// results.
|
||||
inline DecoderErrorOr<void> inverse_asymmetric_discrete_sine_transform_16(u8 bit_depth, Span<Intermediate> data);
|
||||
inline DecoderErrorOr<void> inverse_asymmetric_discrete_sine_transform_16(Span<Intermediate> data);
|
||||
// (8.7.1.9) This process performs an in-place inverse ADST process on the array T of size 2 n for 2 ≤ n ≤ 4.
|
||||
inline DecoderErrorOr<void> inverse_asymmetric_discrete_sine_transform(u8 bit_depth, Span<Intermediate> data, u8 log2_of_block_size);
|
||||
inline DecoderErrorOr<void> inverse_asymmetric_discrete_sine_transform(Span<Intermediate> data, u8 log2_of_block_size);
|
||||
|
||||
/* (8.10) Reference Frame Update Process */
|
||||
DecoderErrorOr<void> update_reference_frames(FrameContext const&);
|
||||
|
|
Loading…
Add table
Reference in a new issue