Переглянути джерело

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.
Zaggy1024 2 роки тому
батько
коміт
33ff3427eb

+ 43 - 72
Userland/Libraries/LibVideo/VP9/Decoder.cpp

@@ -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();

+ 7 - 10
Userland/Libraries/LibVideo/VP9/Decoder.h

@@ -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&);