Parcourir la source

LibVideo/VP9: Convert the Parser to use AK/BitStream.h

This doesn't appear to have had a measurable impact on performance,
and behavior is the same.

With the tiles using independent BooleanDecoders with their own
backing BitStreams, we're even one step closer to threaded tiles!
Zaggy1024 il y a 2 ans
Parent
commit
fb0c226da3

+ 1 - 1
Userland/Libraries/LibVideo/CMakeLists.txt

@@ -6,7 +6,7 @@ set(SOURCES
     Containers/Matroska/Reader.cpp
     PlaybackManager.cpp
     VideoFrame.cpp
-    VP9/BitStream.cpp
+    VP9/BooleanDecoder.cpp
     VP9/Decoder.cpp
     VP9/Parser.cpp
     VP9/ProbabilityTables.cpp

+ 0 - 168
Userland/Libraries/LibVideo/VP9/BitStream.cpp

@@ -1,168 +0,0 @@
-/*
- * Copyright (c) 2021, Hunter Salyer <thefalsehonesty@gmail.com>
- * Copyright (c) 2022, Gregory Bertilson <zaggy1024@gmail.com>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
-
-#include <AK/BuiltinWrappers.h>
-
-#include "BitStream.h"
-
-namespace Video::VP9 {
-
-ErrorOr<void> BitStream::fill_reservoir()
-{
-    VERIFY(m_reservoir_bits_remaining == 0);
-    if (m_data_ptr == m_end_ptr)
-        return Error::from_string_literal("Stream is out of data");
-    VERIFY(m_data_ptr < m_end_ptr);
-    m_reservoir = 0;
-
-    size_t byte_index;
-    for (byte_index = 0; m_data_ptr < m_end_ptr && byte_index < sizeof(m_reservoir); byte_index++) {
-        m_reservoir = (m_reservoir << 8) | *m_data_ptr;
-        m_data_ptr++;
-    }
-
-    m_reservoir_bits_remaining = byte_index * 8;
-    m_reservoir <<= (sizeof(m_reservoir) - byte_index) * 8;
-    return {};
-}
-
-ErrorOr<u64> BitStream::read_bits(u8 bit_count)
-{
-    if (bit_count > sizeof(u64) * 8)
-        return Error::from_string_literal("Requested read is too large");
-    u64 result = 0;
-
-    while (bit_count > 0) {
-        if (m_reservoir_bits_remaining == 0)
-            TRY(fill_reservoir());
-
-        u64 batch_bits = min(bit_count, m_reservoir_bits_remaining);
-        u64 bit_shift = (sizeof(m_reservoir) * 8u) - batch_bits;
-
-        result = (result << batch_bits) | m_reservoir >> bit_shift;
-        m_reservoir <<= batch_bits;
-        bit_count -= batch_bits;
-        m_reservoir_bits_remaining -= batch_bits;
-        m_bits_read += batch_bits;
-    }
-
-    return result;
-}
-
-ErrorOr<bool> BitStream::read_bit()
-{
-    auto value = TRY(read_bits(1));
-    VERIFY(value <= 2);
-    return value != 0;
-}
-
-ErrorOr<u8> BitStream::read_f8()
-{
-    return TRY(read_bits(8));
-}
-
-ErrorOr<u16> BitStream::read_f16()
-{
-    return TRY(read_bits(16));
-}
-
-/* 9.2.1 */
-ErrorOr<void> BitStream::init_bool(size_t bytes)
-{
-    if (bytes > bytes_remaining())
-        return Error::from_string_literal("Available data is too small for range decoder");
-    m_bool_value = TRY(read_f8());
-    m_bool_range = 255;
-    m_bool_max_bits = (8 * bytes) - 8;
-    if (TRY(read_bool(128)))
-        return Error::from_string_literal("Range decoder marker was non-zero");
-    return {};
-}
-
-/* 9.2.2 */
-ErrorOr<bool> BitStream::read_bool(u8 probability)
-{
-    auto split = 1u + (((m_bool_range - 1u) * probability) >> 8u);
-    bool return_bool;
-
-    if (m_bool_value < split) {
-        m_bool_range = split;
-        return_bool = false;
-    } else {
-        m_bool_range -= split;
-        m_bool_value -= split;
-        return_bool = true;
-    }
-
-    if (m_bool_range < 128) {
-        u8 bits_to_shift_into_range = count_leading_zeroes(m_bool_range);
-
-        if (bits_to_shift_into_range > m_bool_max_bits)
-            return Error::from_string_literal("Range decoder is out of data");
-
-        m_bool_range <<= bits_to_shift_into_range;
-        m_bool_value = (m_bool_value << bits_to_shift_into_range) | TRY(read_bits(bits_to_shift_into_range));
-        m_bool_max_bits -= bits_to_shift_into_range;
-    }
-
-    return return_bool;
-}
-
-/* 9.2.3 */
-ErrorOr<void> BitStream::exit_bool()
-{
-    while (m_bool_max_bits > 0) {
-        auto padding_read_size = min(m_bool_max_bits, sizeof(m_reservoir) * 8);
-        auto padding_bits = TRY(read_bits(padding_read_size));
-        m_bool_max_bits -= padding_read_size;
-
-        if (padding_bits != 0)
-            return Error::from_string_literal("Range decoder has non-zero padding element");
-    }
-
-    // FIXME: It is a requirement of bitstream conformance that enough padding bits are inserted to ensure that the final coded byte of a frame is not equal to a superframe marker.
-    //  A byte b is equal to a superframe marker if and only if (b & 0xe0)is equal to 0xc0, i.e. if the most significant 3 bits are equal to 0b110.
-    return {};
-}
-
-size_t BitStream::range_coding_bits_remaining()
-{
-    return m_bool_max_bits;
-}
-
-ErrorOr<u8> BitStream::read_literal(u8 n)
-{
-    u8 return_value = 0;
-    for (size_t i = 0; i < n; i++) {
-        return_value = (2 * return_value) + TRY(read_bool(128));
-    }
-    return return_value;
-}
-
-ErrorOr<i8> BitStream::read_s(size_t n)
-{
-    i8 value = TRY(read_bits(n));
-    bool sign = TRY(read_bit());
-    return sign ? -value : value;
-}
-
-u64 BitStream::get_position()
-{
-    return m_bits_read;
-}
-
-size_t BitStream::bytes_remaining()
-{
-    return (m_end_ptr - m_data_ptr) + (m_reservoir_bits_remaining / 8);
-}
-
-size_t BitStream::bits_remaining()
-{
-    return ((m_end_ptr - m_data_ptr) * sizeof(m_data_ptr) * 8) + m_reservoir_bits_remaining;
-}
-
-}

+ 0 - 59
Userland/Libraries/LibVideo/VP9/BitStream.h

@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2021, Hunter Salyer <thefalsehonesty@gmail.com>
- * Copyright (c) 2022, Gregory Bertilson <zaggy1024@gmail.com>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
-
-#pragma once
-
-#include <AK/Error.h>
-#include <AK/Optional.h>
-#include <AK/Types.h>
-
-namespace Video::VP9 {
-
-class BitStream {
-public:
-    BitStream(u8 const* data, size_t size)
-        : m_data_ptr(data)
-        , m_end_ptr(data + size)
-    {
-    }
-
-    ErrorOr<bool> read_bit();
-
-    ErrorOr<u64> read_bits(u8 bit_count);
-    /* (9.1) */
-    ErrorOr<u8> read_f8();
-    ErrorOr<u16> read_f16();
-
-    /* (9.2) */
-    ErrorOr<void> init_bool(size_t bytes);
-    ErrorOr<bool> read_bool(u8 probability);
-    ErrorOr<void> exit_bool();
-    ErrorOr<u8> read_literal(u8 bit_count);
-    size_t range_coding_bits_remaining();
-
-    /* (4.9.2) */
-    ErrorOr<i8> read_s(size_t n);
-
-    u64 get_position();
-    size_t bytes_remaining();
-    size_t bits_remaining();
-
-private:
-    ErrorOr<void> fill_reservoir();
-
-    u8 const* m_data_ptr { nullptr };
-    u8 const* m_end_ptr { nullptr };
-    u64 m_reservoir { 0 };
-    u8 m_reservoir_bits_remaining { 0 };
-    size_t m_bits_read { 0 };
-
-    u8 m_bool_value { 0 };
-    u8 m_bool_range { 0 };
-    u64 m_bool_max_bits { 0 };
-};
-
-}

+ 87 - 0
Userland/Libraries/LibVideo/VP9/BooleanDecoder.cpp

@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2021, Hunter Salyer <thefalsehonesty@gmail.com>
+ * Copyright (c) 2022, Gregory Bertilson <zaggy1024@gmail.com>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <AK/BuiltinWrappers.h>
+
+#include "BooleanDecoder.h"
+
+namespace Video::VP9 {
+
+/* 9.2.1 */
+ErrorOr<BooleanDecoder> BooleanDecoder::initialize(MaybeOwned<BigEndianInputBitStream> bit_stream, size_t bytes)
+{
+    VERIFY(bit_stream->is_aligned_to_byte_boundary());
+    auto value = TRY(bit_stream->read_value<u8>());
+    u8 range = 255;
+    u64 max_bits = (8 * bytes) - 8;
+    BooleanDecoder decoder { move(bit_stream), value, range, max_bits };
+    if (TRY(decoder.read_bool(128)))
+        return Error::from_string_literal("Range decoder marker was non-zero");
+    return decoder;
+}
+
+/* 9.2.2 */
+ErrorOr<bool> BooleanDecoder::read_bool(u8 probability)
+{
+    auto split = 1u + (((m_range - 1u) * probability) >> 8u);
+    bool return_bool;
+
+    if (m_value < split) {
+        m_range = split;
+        return_bool = false;
+    } else {
+        m_range -= split;
+        m_value -= split;
+        return_bool = true;
+    }
+
+    if (m_range < 128) {
+        u8 bits_to_shift_into_range = count_leading_zeroes(m_range);
+
+        if (bits_to_shift_into_range > m_bits_left)
+            return Error::from_string_literal("Range decoder is out of data");
+
+        m_range <<= bits_to_shift_into_range;
+        m_value = (m_value << bits_to_shift_into_range) | TRY(m_bit_stream->read_bits<u8>(bits_to_shift_into_range));
+        m_bits_left -= bits_to_shift_into_range;
+    }
+
+    return return_bool;
+}
+
+ErrorOr<u8> BooleanDecoder::read_literal(u8 bits)
+{
+    u8 return_value = 0;
+    for (size_t i = 0; i < bits; i++) {
+        return_value = (2 * return_value) + TRY(read_bool(128));
+    }
+    return return_value;
+}
+
+size_t BooleanDecoder::bits_remaining() const
+{
+    return m_bits_left;
+}
+
+/* 9.2.3 */
+ErrorOr<void> BooleanDecoder::finish_decode()
+{
+    while (m_bits_left > 0) {
+        auto padding_read_size = min(m_bits_left, 64);
+        auto padding_bits = TRY(m_bit_stream->read_bits(padding_read_size));
+        m_bits_left -= padding_read_size;
+
+        if (padding_bits != 0)
+            return Error::from_string_literal("Range decoder has non-zero padding element");
+    }
+
+    // FIXME: It is a requirement of bitstream conformance that enough padding bits are inserted to ensure that the final coded byte of a frame is not equal to a superframe marker.
+    //  A byte b is equal to a superframe marker if and only if (b & 0xe0)is equal to 0xc0, i.e. if the most significant 3 bits are equal to 0b110.
+    return {};
+}
+
+}

+ 41 - 0
Userland/Libraries/LibVideo/VP9/BooleanDecoder.h

@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2021, Hunter Salyer <thefalsehonesty@gmail.com>
+ * Copyright (c) 2022, Gregory Bertilson <zaggy1024@gmail.com>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/BitStream.h>
+#include <AK/Error.h>
+#include <AK/Optional.h>
+#include <AK/Types.h>
+
+namespace Video::VP9 {
+
+class BooleanDecoder {
+public:
+    /* (9.2) */
+    static ErrorOr<BooleanDecoder> initialize(MaybeOwned<BigEndianInputBitStream> bit_stream, size_t bytes);
+    ErrorOr<bool> read_bool(u8 probability);
+    ErrorOr<u8> read_literal(u8 bits);
+    size_t bits_remaining() const;
+    ErrorOr<void> finish_decode();
+
+private:
+    BooleanDecoder(MaybeOwned<BigEndianInputBitStream>&& bit_stream, u8 value, u8 range, u64 bits_left)
+        : m_bit_stream(move(bit_stream))
+        , m_value(value)
+        , m_range(range)
+        , m_bits_left(bits_left)
+    {
+    }
+
+    MaybeOwned<BigEndianInputBitStream> m_bit_stream;
+    u8 m_value { 0 };
+    u8 m_range { 0 };
+    u64 m_bits_left { 0 };
+};
+
+}

+ 22 - 3
Userland/Libraries/LibVideo/VP9/Context.h

@@ -8,11 +8,14 @@
 #pragma once
 
 #include <AK/Array.h>
+#include <AK/BitStream.h>
 #include <AK/Error.h>
 #include <AK/FixedArray.h>
+#include <AK/MemoryStream.h>
 #include <LibGfx/Size.h>
 #include <LibVideo/Color/CodingIndependentCodePoints.h>
 
+#include "BooleanDecoder.h"
 #include "ContextStorage.h"
 #include "Enums.h"
 #include "LookupTables.h"
@@ -29,11 +32,20 @@ enum class FrameShowMode {
 
 struct FrameContext {
 public:
-    FrameContext(Vector2D<FrameBlockContext>& contexts)
-        : m_block_contexts(contexts)
+    FrameContext(ReadonlyBytes data,
+        Vector2D<FrameBlockContext>& contexts)
+        : stream(data)
+        , bit_stream(MaybeOwned<Stream>(stream))
+        , m_block_contexts(contexts)
     {
     }
 
+    FrameContext(FrameContext const&) = delete;
+    FrameContext(FrameContext&&) = default;
+
+    FixedMemoryStream stream;
+    BigEndianInputBitStream bit_stream;
+
     u8 profile { 0 };
 
     FrameType type { FrameType::KeyFrame };
@@ -175,14 +187,18 @@ static NonZeroTokensView create_non_zero_tokens_view(NonZeroTokens& non_zero_tok
 
 struct TileContext {
 public:
-    static ErrorOr<TileContext> try_create(FrameContext& frame_context, u32 rows_start, u32 rows_end, u32 columns_start, u32 columns_end, PartitionContextView above_partition_context, NonZeroTokensView above_non_zero_tokens, SegmentationPredictionContextView above_segmentation_ids)
+    static ErrorOr<TileContext> try_create(FrameContext& frame_context, u32 tile_size, u32 rows_start, u32 rows_end, u32 columns_start, u32 columns_end, PartitionContextView above_partition_context, NonZeroTokensView above_non_zero_tokens, SegmentationPredictionContextView above_segmentation_ids)
     {
         auto width = columns_end - columns_start;
         auto height = rows_end - rows_start;
         auto context_view = frame_context.m_block_contexts.view(rows_start, columns_start, height, width);
 
+        auto bit_stream = TRY(try_make<BigEndianInputBitStream>(TRY(try_make<FixedMemoryStream>(frame_context.stream))));
+        auto decoder = TRY(BooleanDecoder::initialize(move(bit_stream), tile_size));
+
         return TileContext {
             frame_context,
+            move(decoder),
             rows_start,
             rows_end,
             columns_start,
@@ -200,6 +216,7 @@ public:
     Vector2D<FrameBlockContext> const& frame_block_contexts() const { return frame_context.block_contexts(); }
 
     FrameContext const& frame_context;
+    BooleanDecoder decoder;
     u32 rows_start { 0 };
     u32 rows_end { 0 };
     u32 columns_start { 0 };
@@ -231,6 +248,7 @@ struct BlockContext {
         return BlockContext {
             .frame_context = tile_context.frame_context,
             .tile_context = tile_context,
+            .decoder = tile_context.decoder,
             .row = row,
             .column = column,
             .size = size,
@@ -246,6 +264,7 @@ struct BlockContext {
 
     FrameContext const& frame_context;
     TileContext const& tile_context;
+    BooleanDecoder& decoder;
     u32 row { 0 };
     u32 column { 0 };
     BlockSubsize size;

Fichier diff supprimé car celui-ci est trop grand
+ 222 - 222
Userland/Libraries/LibVideo/VP9/Parser.cpp


+ 27 - 29
Userland/Libraries/LibVideo/VP9/Parser.h

@@ -14,7 +14,6 @@
 #include <LibVideo/Color/CodingIndependentCodePoints.h>
 #include <LibVideo/DecoderError.h>
 
-#include "BitStream.h"
 #include "ContextStorage.h"
 #include "LookupTables.h"
 #include "MotionVector.h"
@@ -45,48 +44,48 @@ private:
      * See also section 5.26. */
     Vector<size_t> parse_superframe_sizes(ReadonlyBytes);
 
-    DecoderErrorOr<VideoFullRangeFlag> read_video_full_range_flag();
+    DecoderErrorOr<VideoFullRangeFlag> read_video_full_range_flag(BigEndianInputBitStream&);
 
     /* (6.1) Frame Syntax */
     bool trailing_bits();
     DecoderErrorOr<void> refresh_probs(FrameContext const&);
 
     /* (6.2) Uncompressed Header Syntax */
-    DecoderErrorOr<FrameContext> uncompressed_header();
-    DecoderErrorOr<void> frame_sync_code();
-    DecoderErrorOr<ColorConfig> parse_color_config(FrameContext const&);
-    DecoderErrorOr<Gfx::Size<u32>> parse_frame_size();
-    DecoderErrorOr<Gfx::Size<u32>> parse_frame_size_with_refs(Array<u8, 3> const& reference_indices);
-    DecoderErrorOr<Gfx::Size<u32>> parse_render_size(Gfx::Size<u32> frame_size);
+    DecoderErrorOr<void> uncompressed_header(FrameContext& frame_context);
+    DecoderErrorOr<void> frame_sync_code(BigEndianInputBitStream&);
+    DecoderErrorOr<ColorConfig> parse_color_config(BigEndianInputBitStream&, u8 profile);
+    DecoderErrorOr<Gfx::Size<u32>> parse_frame_size(BigEndianInputBitStream&);
+    DecoderErrorOr<Gfx::Size<u32>> parse_frame_size_with_refs(BigEndianInputBitStream&, Array<u8, 3> const& reference_indices);
+    DecoderErrorOr<Gfx::Size<u32>> parse_render_size(BigEndianInputBitStream&, Gfx::Size<u32> frame_size);
     DecoderErrorOr<void> compute_image_size(FrameContext&);
-    DecoderErrorOr<InterpolationFilter> read_interpolation_filter();
+    DecoderErrorOr<InterpolationFilter> read_interpolation_filter(BigEndianInputBitStream&);
     DecoderErrorOr<void> loop_filter_params(FrameContext&);
     DecoderErrorOr<void> quantization_params(FrameContext&);
-    DecoderErrorOr<i8> read_delta_q();
+    DecoderErrorOr<i8> read_delta_q(BigEndianInputBitStream&);
     DecoderErrorOr<void> segmentation_params(FrameContext&);
-    DecoderErrorOr<u8> read_prob();
+    DecoderErrorOr<u8> read_prob(BigEndianInputBitStream&);
     DecoderErrorOr<void> parse_tile_counts(FrameContext&);
     void setup_past_independence();
 
     /* (6.3) Compressed Header Syntax */
     DecoderErrorOr<void> compressed_header(FrameContext&);
-    DecoderErrorOr<TransformMode> read_tx_mode(FrameContext const&);
-    DecoderErrorOr<void> tx_mode_probs();
-    DecoderErrorOr<u8> diff_update_prob(u8 prob);
-    DecoderErrorOr<u8> decode_term_subexp();
+    DecoderErrorOr<TransformMode> read_tx_mode(BooleanDecoder&, FrameContext const&);
+    DecoderErrorOr<void> tx_mode_probs(BooleanDecoder&);
+    DecoderErrorOr<u8> diff_update_prob(BooleanDecoder&, u8 prob);
+    DecoderErrorOr<u8> decode_term_subexp(BooleanDecoder&);
     u8 inv_remap_prob(u8 delta_prob, u8 prob);
     u8 inv_recenter_nonneg(u8 v, u8 m);
-    DecoderErrorOr<void> read_coef_probs(TransformMode);
-    DecoderErrorOr<void> read_skip_prob();
-    DecoderErrorOr<void> read_inter_mode_probs();
-    DecoderErrorOr<void> read_interp_filter_probs();
-    DecoderErrorOr<void> read_is_inter_probs();
-    DecoderErrorOr<void> frame_reference_mode(FrameContext&);
-    DecoderErrorOr<void> frame_reference_mode_probs(FrameContext const&);
-    DecoderErrorOr<void> read_y_mode_probs();
-    DecoderErrorOr<void> read_partition_probs();
-    DecoderErrorOr<void> mv_probs(FrameContext const&);
-    DecoderErrorOr<u8> update_mv_prob(u8 prob);
+    DecoderErrorOr<void> read_coef_probs(BooleanDecoder&, TransformMode);
+    DecoderErrorOr<void> read_skip_prob(BooleanDecoder&);
+    DecoderErrorOr<void> read_inter_mode_probs(BooleanDecoder&);
+    DecoderErrorOr<void> read_interp_filter_probs(BooleanDecoder&);
+    DecoderErrorOr<void> read_is_inter_probs(BooleanDecoder&);
+    DecoderErrorOr<void> frame_reference_mode(FrameContext&, BooleanDecoder&);
+    DecoderErrorOr<void> frame_reference_mode_probs(BooleanDecoder&, FrameContext const&);
+    DecoderErrorOr<void> read_y_mode_probs(BooleanDecoder&);
+    DecoderErrorOr<void> read_partition_probs(BooleanDecoder&);
+    DecoderErrorOr<void> mv_probs(BooleanDecoder&, FrameContext const&);
+    DecoderErrorOr<u8> update_mv_prob(BooleanDecoder&, u8 prob);
 
     /* (6.4) Decode Tiles Syntax */
     DecoderErrorOr<void> decode_tiles(FrameContext&);
@@ -109,10 +108,10 @@ private:
     DecoderErrorOr<void> read_ref_frames(BlockContext&, FrameBlockContext above_context, FrameBlockContext left_context);
     DecoderErrorOr<MotionVectorPair> get_motion_vector(BlockContext const&, BlockMotionVectorCandidates const&);
     DecoderErrorOr<MotionVector> read_motion_vector(BlockContext const&, BlockMotionVectorCandidates const&, ReferenceIndex);
-    DecoderErrorOr<i32> read_single_motion_vector_component(u8 component, bool use_high_precision);
+    DecoderErrorOr<i32> read_single_motion_vector_component(BooleanDecoder&, u8 component, bool use_high_precision);
     DecoderErrorOr<bool> residual(BlockContext&, bool has_block_above, bool has_block_left);
     DecoderErrorOr<bool> tokens(BlockContext&, size_t plane, u32 x, u32 y, TransformSize, TransformSet, Array<u8, 1024> token_cache);
-    DecoderErrorOr<i32> read_coef(u8 bit_depth, Token token);
+    DecoderErrorOr<i32> read_coef(BooleanDecoder&, u8 bit_depth, Token token);
 
     /* (6.5) Motion Vector Prediction */
     MotionVectorPair find_reference_motion_vectors(BlockContext&, ReferenceFrameType, i32 block);
@@ -140,7 +139,6 @@ private:
     Vector2D<FrameBlockContext> m_reusable_frame_block_contexts;
     Vector2D<PersistentBlockContext> m_previous_block_contexts;
 
-    OwnPtr<BitStream> m_bit_stream;
     OwnPtr<ProbabilityTables> m_probability_tables;
     OwnPtr<SyntaxElementCounter> m_syntax_element_counter;
     Decoder& m_decoder;

+ 58 - 58
Userland/Libraries/LibVideo/VP9/TreeParser.cpp

@@ -51,7 +51,7 @@ private:
 };
 
 template<typename OutputType>
-inline ErrorOr<OutputType> parse_tree(BitStream& bit_stream, TreeSelection tree_selection, Function<u8(u8)> const& probability_getter)
+inline ErrorOr<OutputType> parse_tree(BooleanDecoder& decoder, TreeSelection tree_selection, Function<u8(u8)> const& probability_getter)
 {
     // 9.3.3: The tree decoding function.
     if (tree_selection.is_single_value())
@@ -61,13 +61,13 @@ inline ErrorOr<OutputType> parse_tree(BitStream& bit_stream, TreeSelection tree_
     int n = 0;
     do {
         u8 node = n >> 1;
-        n = tree[n + TRY(bit_stream.read_bool(probability_getter(node)))];
+        n = tree[n + TRY(decoder.read_bool(probability_getter(node)))];
     } while (n > 0);
 
     return static_cast<OutputType>(-n);
 }
 
-ErrorOr<Partition> TreeParser::parse_partition(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, bool has_rows, bool has_columns, BlockSubsize block_subsize, u8 num_8x8, PartitionContextView above_partition_context, PartitionContextView left_partition_context, u32 row, u32 column, bool frame_is_intra)
+ErrorOr<Partition> TreeParser::parse_partition(BooleanDecoder& decoder, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, bool has_rows, bool has_columns, BlockSubsize block_subsize, u8 num_8x8, PartitionContextView above_partition_context, PartitionContextView left_partition_context, u32 row, u32 column, bool frame_is_intra)
 {
     // Tree array
     TreeSelection tree = { PartitionSplit };
@@ -100,12 +100,12 @@ ErrorOr<Partition> TreeParser::parse_partition(BitStream& bit_stream, Probabilit
         return probabilities[2];
     };
 
-    auto value = TRY(parse_tree<Partition>(bit_stream, tree, probability_getter));
+    auto value = TRY(parse_tree<Partition>(decoder, tree, probability_getter));
     counter.m_counts_partition[context][value]++;
     return value;
 }
 
-ErrorOr<PredictionMode> TreeParser::parse_default_intra_mode(BitStream& bit_stream, ProbabilityTables const& probability_table, BlockSubsize mi_size, FrameBlockContext above, FrameBlockContext left, Array<PredictionMode, 4> const& block_sub_modes, u8 index_x, u8 index_y)
+ErrorOr<PredictionMode> TreeParser::parse_default_intra_mode(BooleanDecoder& decoder, ProbabilityTables const& probability_table, BlockSubsize mi_size, FrameBlockContext above, FrameBlockContext left, Array<PredictionMode, 4> const& block_sub_modes, u8 index_x, u8 index_y)
 {
     // FIXME: This should use a struct for the above and left contexts.
 
@@ -130,12 +130,12 @@ ErrorOr<PredictionMode> TreeParser::parse_default_intra_mode(BitStream& bit_stre
     }
     u8 const* probabilities = probability_table.kf_y_mode_probs()[to_underlying(above_mode)][to_underlying(left_mode)];
 
-    auto value = TRY(parse_tree<PredictionMode>(bit_stream, tree, [&](u8 node) { return probabilities[node]; }));
+    auto value = TRY(parse_tree<PredictionMode>(decoder, tree, [&](u8 node) { return probabilities[node]; }));
     // Default intra mode is not counted.
     return value;
 }
 
-ErrorOr<PredictionMode> TreeParser::parse_default_uv_mode(BitStream& bit_stream, ProbabilityTables const& probability_table, PredictionMode y_mode)
+ErrorOr<PredictionMode> TreeParser::parse_default_uv_mode(BooleanDecoder& decoder, ProbabilityTables const& probability_table, PredictionMode y_mode)
 {
     // Tree
     TreeSelection tree = { intra_mode_tree };
@@ -143,12 +143,12 @@ ErrorOr<PredictionMode> TreeParser::parse_default_uv_mode(BitStream& bit_stream,
     // Probabilities
     u8 const* probabilities = probability_table.kf_uv_mode_prob()[to_underlying(y_mode)];
 
-    auto value = TRY(parse_tree<PredictionMode>(bit_stream, tree, [&](u8 node) { return probabilities[node]; }));
+    auto value = TRY(parse_tree<PredictionMode>(decoder, tree, [&](u8 node) { return probabilities[node]; }));
     // Default UV mode is not counted.
     return value;
 }
 
-ErrorOr<PredictionMode> TreeParser::parse_intra_mode(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, BlockSubsize mi_size)
+ErrorOr<PredictionMode> TreeParser::parse_intra_mode(BooleanDecoder& decoder, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, BlockSubsize mi_size)
 {
     // Tree
     TreeSelection tree = { intra_mode_tree };
@@ -157,12 +157,12 @@ ErrorOr<PredictionMode> TreeParser::parse_intra_mode(BitStream& bit_stream, Prob
     auto context = size_group_lookup[mi_size];
     u8 const* probabilities = probability_table.y_mode_probs()[context];
 
-    auto value = TRY(parse_tree<PredictionMode>(bit_stream, tree, [&](u8 node) { return probabilities[node]; }));
+    auto value = TRY(parse_tree<PredictionMode>(decoder, tree, [&](u8 node) { return probabilities[node]; }));
     counter.m_counts_intra_mode[context][to_underlying(value)]++;
     return value;
 }
 
-ErrorOr<PredictionMode> TreeParser::parse_sub_intra_mode(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter)
+ErrorOr<PredictionMode> TreeParser::parse_sub_intra_mode(BooleanDecoder& decoder, ProbabilityTables const& probability_table, SyntaxElementCounter& counter)
 {
     // Tree
     TreeSelection tree = { intra_mode_tree };
@@ -170,12 +170,12 @@ ErrorOr<PredictionMode> TreeParser::parse_sub_intra_mode(BitStream& bit_stream,
     // Probabilities
     u8 const* probabilities = probability_table.y_mode_probs()[0];
 
-    auto value = TRY(parse_tree<PredictionMode>(bit_stream, tree, [&](u8 node) { return probabilities[node]; }));
+    auto value = TRY(parse_tree<PredictionMode>(decoder, tree, [&](u8 node) { return probabilities[node]; }));
     counter.m_counts_intra_mode[0][to_underlying(value)]++;
     return value;
 }
 
-ErrorOr<PredictionMode> TreeParser::parse_uv_mode(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, PredictionMode y_mode)
+ErrorOr<PredictionMode> TreeParser::parse_uv_mode(BooleanDecoder& decoder, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, PredictionMode y_mode)
 {
     // Tree
     TreeSelection tree = { intra_mode_tree };
@@ -183,27 +183,27 @@ ErrorOr<PredictionMode> TreeParser::parse_uv_mode(BitStream& bit_stream, Probabi
     // Probabilities
     u8 const* probabilities = probability_table.uv_mode_probs()[to_underlying(y_mode)];
 
-    auto value = TRY(parse_tree<PredictionMode>(bit_stream, tree, [&](u8 node) { return probabilities[node]; }));
+    auto value = TRY(parse_tree<PredictionMode>(decoder, tree, [&](u8 node) { return probabilities[node]; }));
     counter.m_counts_uv_mode[to_underlying(y_mode)][to_underlying(value)]++;
     return value;
 }
 
-ErrorOr<u8> TreeParser::parse_segment_id(BitStream& bit_stream, Array<u8, 7> const& probabilities)
+ErrorOr<u8> TreeParser::parse_segment_id(BooleanDecoder& decoder, Array<u8, 7> const& probabilities)
 {
-    auto value = TRY(parse_tree<u8>(bit_stream, { segment_tree }, [&](u8 node) { return probabilities[node]; }));
+    auto value = TRY(parse_tree<u8>(decoder, { segment_tree }, [&](u8 node) { return probabilities[node]; }));
     // Segment ID is not counted.
     return value;
 }
 
-ErrorOr<bool> TreeParser::parse_segment_id_predicted(BitStream& bit_stream, Array<u8, 3> const& probabilities, u8 above_seg_pred_context, u8 left_seg_pred_context)
+ErrorOr<bool> TreeParser::parse_segment_id_predicted(BooleanDecoder& decoder, Array<u8, 3> const& probabilities, u8 above_seg_pred_context, u8 left_seg_pred_context)
 {
     auto context = left_seg_pred_context + above_seg_pred_context;
-    auto value = TRY(parse_tree<bool>(bit_stream, { binary_tree }, [&](u8) { return probabilities[context]; }));
+    auto value = TRY(parse_tree<bool>(decoder, { binary_tree }, [&](u8) { return probabilities[context]; }));
     // Segment ID prediction is not counted.
     return value;
 }
 
-ErrorOr<PredictionMode> TreeParser::parse_inter_mode(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, u8 mode_context_for_ref_frame_0)
+ErrorOr<PredictionMode> TreeParser::parse_inter_mode(BooleanDecoder& decoder, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, u8 mode_context_for_ref_frame_0)
 {
     // Tree
     TreeSelection tree = { inter_mode_tree };
@@ -211,12 +211,12 @@ ErrorOr<PredictionMode> TreeParser::parse_inter_mode(BitStream& bit_stream, Prob
     // Probabilities
     u8 const* probabilities = probability_table.inter_mode_probs()[mode_context_for_ref_frame_0];
 
-    auto value = TRY(parse_tree<u8>(bit_stream, tree, [&](u8 node) { return probabilities[node]; }));
+    auto value = TRY(parse_tree<u8>(decoder, tree, [&](u8 node) { return probabilities[node]; }));
     counter.m_counts_inter_mode[mode_context_for_ref_frame_0][value]++;
     return static_cast<PredictionMode>(value + to_underlying(PredictionMode::NearestMv));
 }
 
-ErrorOr<InterpolationFilter> TreeParser::parse_interpolation_filter(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, FrameBlockContext above, FrameBlockContext left)
+ErrorOr<InterpolationFilter> TreeParser::parse_interpolation_filter(BooleanDecoder& decoder, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, FrameBlockContext above, FrameBlockContext left)
 {
     // FIXME: Above and left context should be provided by a struct.
 
@@ -236,12 +236,12 @@ ErrorOr<InterpolationFilter> TreeParser::parse_interpolation_filter(BitStream& b
         context = above_interp;
     u8 const* probabilities = probability_table.interp_filter_probs()[context];
 
-    auto value = TRY(parse_tree<InterpolationFilter>(bit_stream, tree, [&](u8 node) { return probabilities[node]; }));
+    auto value = TRY(parse_tree<InterpolationFilter>(decoder, tree, [&](u8 node) { return probabilities[node]; }));
     counter.m_counts_interp_filter[context][to_underlying(value)]++;
     return value;
 }
 
-ErrorOr<bool> TreeParser::parse_skip(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, FrameBlockContext above, FrameBlockContext left)
+ErrorOr<bool> TreeParser::parse_skip(BooleanDecoder& decoder, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, FrameBlockContext above, FrameBlockContext left)
 {
     // Probabilities
     u8 context = 0;
@@ -249,12 +249,12 @@ ErrorOr<bool> TreeParser::parse_skip(BitStream& bit_stream, ProbabilityTables co
     context += static_cast<u8>(left.skip_coefficients);
     u8 probability = probability_table.skip_prob()[context];
 
-    auto value = TRY(parse_tree<bool>(bit_stream, { binary_tree }, [&](u8) { return probability; }));
+    auto value = TRY(parse_tree<bool>(decoder, { binary_tree }, [&](u8) { return probability; }));
     counter.m_counts_skip[context][value]++;
     return value;
 }
 
-ErrorOr<TransformSize> TreeParser::parse_tx_size(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, TransformSize max_tx_size, FrameBlockContext above, FrameBlockContext left)
+ErrorOr<TransformSize> TreeParser::parse_tx_size(BooleanDecoder& decoder, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, TransformSize max_tx_size, FrameBlockContext above, FrameBlockContext left)
 {
     // FIXME: Above and left contexts should be in structs.
 
@@ -280,12 +280,12 @@ ErrorOr<TransformSize> TreeParser::parse_tx_size(BitStream& bit_stream, Probabil
 
     u8 const* probabilities = probability_table.tx_probs()[max_tx_size][context];
 
-    auto value = TRY(parse_tree<TransformSize>(bit_stream, tree, [&](u8 node) { return probabilities[node]; }));
+    auto value = TRY(parse_tree<TransformSize>(decoder, tree, [&](u8 node) { return probabilities[node]; }));
     counter.m_counts_tx_size[max_tx_size][context][value]++;
     return value;
 }
 
-ErrorOr<bool> TreeParser::parse_block_is_inter_predicted(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, FrameBlockContext above, FrameBlockContext left)
+ErrorOr<bool> TreeParser::parse_block_is_inter_predicted(BooleanDecoder& decoder, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, FrameBlockContext above, FrameBlockContext left)
 {
     // FIXME: Above and left contexts should be in structs.
 
@@ -297,12 +297,12 @@ ErrorOr<bool> TreeParser::parse_block_is_inter_predicted(BitStream& bit_stream,
         context = 2 * static_cast<u8>(above.is_available ? above.is_intra_predicted() : left.is_intra_predicted());
     u8 probability = probability_table.is_inter_prob()[context];
 
-    auto value = TRY(parse_tree<bool>(bit_stream, { binary_tree }, [&](u8) { return probability; }));
+    auto value = TRY(parse_tree<bool>(decoder, { binary_tree }, [&](u8) { return probability; }));
     counter.m_counts_is_inter[context][value]++;
     return value;
 }
 
-ErrorOr<ReferenceMode> TreeParser::parse_comp_mode(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, ReferenceFrameType comp_fixed_ref, FrameBlockContext above, FrameBlockContext left)
+ErrorOr<ReferenceMode> TreeParser::parse_comp_mode(BooleanDecoder& decoder, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, ReferenceFrameType comp_fixed_ref, FrameBlockContext above, FrameBlockContext left)
 {
     // FIXME: Above and left contexts should be in structs.
 
@@ -337,12 +337,12 @@ ErrorOr<ReferenceMode> TreeParser::parse_comp_mode(BitStream& bit_stream, Probab
     }
     u8 probability = probability_table.comp_mode_prob()[context];
 
-    auto value = TRY(parse_tree<ReferenceMode>(bit_stream, { binary_tree }, [&](u8) { return probability; }));
+    auto value = TRY(parse_tree<ReferenceMode>(decoder, { binary_tree }, [&](u8) { return probability; }));
     counter.m_counts_comp_mode[context][value]++;
     return value;
 }
 
-ErrorOr<ReferenceIndex> TreeParser::parse_comp_ref(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, ReferenceFrameType comp_fixed_ref, ReferenceFramePair comp_var_ref, ReferenceIndex variable_reference_index, FrameBlockContext above, FrameBlockContext left)
+ErrorOr<ReferenceIndex> TreeParser::parse_comp_ref(BooleanDecoder& decoder, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, ReferenceFrameType comp_fixed_ref, ReferenceFramePair comp_var_ref, ReferenceIndex variable_reference_index, FrameBlockContext above, FrameBlockContext left)
 {
     // FIXME: Above and left contexts should be in structs.
 
@@ -420,12 +420,12 @@ ErrorOr<ReferenceIndex> TreeParser::parse_comp_ref(BitStream& bit_stream, Probab
 
     u8 probability = probability_table.comp_ref_prob()[context];
 
-    auto value = TRY(parse_tree<ReferenceIndex>(bit_stream, { binary_tree }, [&](u8) { return probability; }));
+    auto value = TRY(parse_tree<ReferenceIndex>(decoder, { binary_tree }, [&](u8) { return probability; }));
     counter.m_counts_comp_ref[context][to_underlying(value)]++;
     return value;
 }
 
-ErrorOr<bool> TreeParser::parse_single_ref_part_1(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, FrameBlockContext above, FrameBlockContext left)
+ErrorOr<bool> TreeParser::parse_single_ref_part_1(BooleanDecoder& decoder, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, FrameBlockContext above, FrameBlockContext left)
 {
     // FIXME: Above and left contexts should be in structs.
 
@@ -487,12 +487,12 @@ ErrorOr<bool> TreeParser::parse_single_ref_part_1(BitStream& bit_stream, Probabi
     }
     u8 probability = probability_table.single_ref_prob()[context][0];
 
-    auto value = TRY(parse_tree<bool>(bit_stream, { binary_tree }, [&](u8) { return probability; }));
+    auto value = TRY(parse_tree<bool>(decoder, { binary_tree }, [&](u8) { return probability; }));
     counter.m_counts_single_ref[context][0][value]++;
     return value;
 }
 
-ErrorOr<bool> TreeParser::parse_single_ref_part_2(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, FrameBlockContext above, FrameBlockContext left)
+ErrorOr<bool> TreeParser::parse_single_ref_part_2(BooleanDecoder& decoder, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, FrameBlockContext above, FrameBlockContext left)
 {
     // FIXME: Above and left contexts should be in structs.
 
@@ -573,78 +573,78 @@ ErrorOr<bool> TreeParser::parse_single_ref_part_2(BitStream& bit_stream, Probabi
     }
     u8 probability = probability_table.single_ref_prob()[context][1];
 
-    auto value = TRY(parse_tree<bool>(bit_stream, { binary_tree }, [&](u8) { return probability; }));
+    auto value = TRY(parse_tree<bool>(decoder, { binary_tree }, [&](u8) { return probability; }));
     counter.m_counts_single_ref[context][1][value]++;
     return value;
 }
 
-ErrorOr<MvJoint> TreeParser::parse_motion_vector_joint(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter)
+ErrorOr<MvJoint> TreeParser::parse_motion_vector_joint(BooleanDecoder& decoder, ProbabilityTables const& probability_table, SyntaxElementCounter& counter)
 {
-    auto value = TRY(parse_tree<MvJoint>(bit_stream, { mv_joint_tree }, [&](u8 node) { return probability_table.mv_joint_probs()[node]; }));
+    auto value = TRY(parse_tree<MvJoint>(decoder, { mv_joint_tree }, [&](u8 node) { return probability_table.mv_joint_probs()[node]; }));
     counter.m_counts_mv_joint[value]++;
     return value;
 }
 
-ErrorOr<bool> TreeParser::parse_motion_vector_sign(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, u8 component)
+ErrorOr<bool> TreeParser::parse_motion_vector_sign(BooleanDecoder& decoder, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, u8 component)
 {
-    auto value = TRY(parse_tree<bool>(bit_stream, { binary_tree }, [&](u8) { return probability_table.mv_sign_prob()[component]; }));
+    auto value = TRY(parse_tree<bool>(decoder, { binary_tree }, [&](u8) { return probability_table.mv_sign_prob()[component]; }));
     counter.m_counts_mv_sign[component][value]++;
     return value;
 }
 
-ErrorOr<MvClass> TreeParser::parse_motion_vector_class(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, u8 component)
+ErrorOr<MvClass> TreeParser::parse_motion_vector_class(BooleanDecoder& decoder, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, u8 component)
 {
     // Spec doesn't mention node, but the probabilities table has an extra dimension
     // so we will use node for that.
-    auto value = TRY(parse_tree<MvClass>(bit_stream, { mv_class_tree }, [&](u8 node) { return probability_table.mv_class_probs()[component][node]; }));
+    auto value = TRY(parse_tree<MvClass>(decoder, { mv_class_tree }, [&](u8 node) { return probability_table.mv_class_probs()[component][node]; }));
     counter.m_counts_mv_class[component][value]++;
     return value;
 }
 
-ErrorOr<bool> TreeParser::parse_motion_vector_class0_bit(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, u8 component)
+ErrorOr<bool> TreeParser::parse_motion_vector_class0_bit(BooleanDecoder& decoder, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, u8 component)
 {
-    auto value = TRY(parse_tree<bool>(bit_stream, { binary_tree }, [&](u8) { return probability_table.mv_class0_bit_prob()[component]; }));
+    auto value = TRY(parse_tree<bool>(decoder, { binary_tree }, [&](u8) { return probability_table.mv_class0_bit_prob()[component]; }));
     counter.m_counts_mv_class0_bit[component][value]++;
     return value;
 }
 
-ErrorOr<u8> TreeParser::parse_motion_vector_class0_fr(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, u8 component, bool class_0_bit)
+ErrorOr<u8> TreeParser::parse_motion_vector_class0_fr(BooleanDecoder& decoder, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, u8 component, bool class_0_bit)
 {
-    auto value = TRY(parse_tree<u8>(bit_stream, { mv_fr_tree }, [&](u8 node) { return probability_table.mv_class0_fr_probs()[component][class_0_bit][node]; }));
+    auto value = TRY(parse_tree<u8>(decoder, { mv_fr_tree }, [&](u8 node) { return probability_table.mv_class0_fr_probs()[component][class_0_bit][node]; }));
     counter.m_counts_mv_class0_fr[component][class_0_bit][value]++;
     return value;
 }
 
-ErrorOr<bool> TreeParser::parse_motion_vector_class0_hp(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, u8 component, bool use_hp)
+ErrorOr<bool> TreeParser::parse_motion_vector_class0_hp(BooleanDecoder& decoder, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, u8 component, bool use_hp)
 {
     TreeSelection tree { 1 };
     if (use_hp)
         tree = { binary_tree };
-    auto value = TRY(parse_tree<bool>(bit_stream, tree, [&](u8) { return probability_table.mv_class0_hp_prob()[component]; }));
+    auto value = TRY(parse_tree<bool>(decoder, tree, [&](u8) { return probability_table.mv_class0_hp_prob()[component]; }));
     counter.m_counts_mv_class0_hp[component][value]++;
     return value;
 }
 
-ErrorOr<bool> TreeParser::parse_motion_vector_bit(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, u8 component, u8 bit_index)
+ErrorOr<bool> TreeParser::parse_motion_vector_bit(BooleanDecoder& decoder, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, u8 component, u8 bit_index)
 {
-    auto value = TRY(parse_tree<bool>(bit_stream, { binary_tree }, [&](u8) { return probability_table.mv_bits_prob()[component][bit_index]; }));
+    auto value = TRY(parse_tree<bool>(decoder, { binary_tree }, [&](u8) { return probability_table.mv_bits_prob()[component][bit_index]; }));
     counter.m_counts_mv_bits[component][bit_index][value]++;
     return value;
 }
 
-ErrorOr<u8> TreeParser::parse_motion_vector_fr(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, u8 component)
+ErrorOr<u8> TreeParser::parse_motion_vector_fr(BooleanDecoder& decoder, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, u8 component)
 {
-    auto value = TRY(parse_tree<u8>(bit_stream, { mv_fr_tree }, [&](u8 node) { return probability_table.mv_fr_probs()[component][node]; }));
+    auto value = TRY(parse_tree<u8>(decoder, { mv_fr_tree }, [&](u8 node) { return probability_table.mv_fr_probs()[component][node]; }));
     counter.m_counts_mv_fr[component][value]++;
     return value;
 }
 
-ErrorOr<bool> TreeParser::parse_motion_vector_hp(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, u8 component, bool use_hp)
+ErrorOr<bool> TreeParser::parse_motion_vector_hp(BooleanDecoder& decoder, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, u8 component, bool use_hp)
 {
     TreeSelection tree { 1 };
     if (use_hp)
         tree = { binary_tree };
-    auto value = TRY(parse_tree<u8>(bit_stream, tree, [&](u8) { return probability_table.mv_hp_prob()[component]; }));
+    auto value = TRY(parse_tree<u8>(decoder, tree, [&](u8) { return probability_table.mv_hp_prob()[component]; }));
     counter.m_counts_mv_hp[component][value]++;
     return value;
 }
@@ -704,15 +704,15 @@ TokensContext TreeParser::get_context_for_other_tokens(Array<u8, 1024> token_cac
     return TokensContext { transform_size, plane > 0, is_inter, band, context };
 }
 
-ErrorOr<bool> TreeParser::parse_more_coefficients(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, TokensContext const& context)
+ErrorOr<bool> TreeParser::parse_more_coefficients(BooleanDecoder& decoder, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, TokensContext const& context)
 {
     auto probability = probability_table.coef_probs()[context.m_tx_size][context.m_is_uv_plane][context.m_is_inter][context.m_band][context.m_context_index][0];
-    auto value = TRY(parse_tree<u8>(bit_stream, { binary_tree }, [&](u8) { return probability; }));
+    auto value = TRY(parse_tree<u8>(decoder, { binary_tree }, [&](u8) { return probability; }));
     counter.m_counts_more_coefs[context.m_tx_size][context.m_is_uv_plane][context.m_is_inter][context.m_band][context.m_context_index][value]++;
     return value;
 }
 
-ErrorOr<Token> TreeParser::parse_token(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, TokensContext const& context)
+ErrorOr<Token> TreeParser::parse_token(BooleanDecoder& decoder, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, TokensContext const& context)
 {
     Function<u8(u8)> probability_getter = [&](u8 node) -> u8 {
         auto prob = probability_table.coef_probs()[context.m_tx_size][context.m_is_uv_plane][context.m_is_inter][context.m_band][context.m_context_index][min(2, 1 + node)];
@@ -725,7 +725,7 @@ ErrorOr<Token> TreeParser::parse_token(BitStream& bit_stream, ProbabilityTables
         return (pareto_table[x][node - 2] + pareto_table[x + 1][node - 2]) >> 1;
     };
 
-    auto value = TRY(parse_tree<Token>(bit_stream, { token_tree }, probability_getter));
+    auto value = TRY(parse_tree<Token>(decoder, { token_tree }, probability_getter));
     counter.m_counts_token[context.m_tx_size][context.m_is_uv_plane][context.m_is_inter][context.m_band][context.m_context_index][min(2, value)]++;
     return value;
 }

+ 29 - 29
Userland/Libraries/LibVideo/VP9/TreeParser.h

@@ -7,7 +7,7 @@
 
 #pragma once
 
-#include "BitStream.h"
+#include "BooleanDecoder.h"
 #include "ContextStorage.h"
 #include "Enums.h"
 #include "ProbabilityTables.h"
@@ -30,38 +30,38 @@ struct TokensContext {
 
 class TreeParser {
 public:
-    static ErrorOr<Partition> parse_partition(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, bool has_rows, bool has_columns, BlockSubsize block_subsize, u8 num_8x8, PartitionContextView above_partition_context, PartitionContextView left_partition_context, u32 row, u32 column, bool frame_is_intra);
-    static ErrorOr<PredictionMode> parse_default_intra_mode(BitStream&, ProbabilityTables const&, BlockSubsize mi_size, FrameBlockContext above, FrameBlockContext left, Array<PredictionMode, 4> const& block_sub_modes, u8 index_x, u8 index_y);
-    static ErrorOr<PredictionMode> parse_default_uv_mode(BitStream&, ProbabilityTables const&, PredictionMode y_mode);
-    static ErrorOr<PredictionMode> parse_intra_mode(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, BlockSubsize mi_size);
-    static ErrorOr<PredictionMode> parse_sub_intra_mode(BitStream&, ProbabilityTables const&, SyntaxElementCounter&);
-    static ErrorOr<PredictionMode> parse_uv_mode(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, PredictionMode y_mode);
-    static ErrorOr<u8> parse_segment_id(BitStream&, Array<u8, 7> const& probabilities);
-    static ErrorOr<bool> parse_segment_id_predicted(BitStream&, Array<u8, 3> const& probabilities, u8 above_seg_pred_context, u8 left_seg_pred_context);
-    static ErrorOr<PredictionMode> parse_inter_mode(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, u8 mode_context_for_ref_frame_0);
-    static ErrorOr<InterpolationFilter> parse_interpolation_filter(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, FrameBlockContext above, FrameBlockContext left);
-    static ErrorOr<bool> parse_skip(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, FrameBlockContext above, FrameBlockContext left);
-    static ErrorOr<TransformSize> parse_tx_size(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, TransformSize max_tx_size, FrameBlockContext above, FrameBlockContext left);
-    static ErrorOr<bool> parse_block_is_inter_predicted(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, FrameBlockContext above, FrameBlockContext left);
-    static ErrorOr<ReferenceMode> parse_comp_mode(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, ReferenceFrameType comp_fixed_ref, FrameBlockContext above, FrameBlockContext left);
-    static ErrorOr<ReferenceIndex> parse_comp_ref(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, ReferenceFrameType comp_fixed_ref, ReferenceFramePair comp_var_ref, ReferenceIndex variable_reference_index, FrameBlockContext above, FrameBlockContext left);
-    static ErrorOr<bool> parse_single_ref_part_1(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, FrameBlockContext above, FrameBlockContext left);
-    static ErrorOr<bool> parse_single_ref_part_2(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, FrameBlockContext above, FrameBlockContext left);
+    static ErrorOr<Partition> parse_partition(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, bool has_rows, bool has_columns, BlockSubsize block_subsize, u8 num_8x8, PartitionContextView above_partition_context, PartitionContextView left_partition_context, u32 row, u32 column, bool frame_is_intra);
+    static ErrorOr<PredictionMode> parse_default_intra_mode(BooleanDecoder&, ProbabilityTables const&, BlockSubsize mi_size, FrameBlockContext above, FrameBlockContext left, Array<PredictionMode, 4> const& block_sub_modes, u8 index_x, u8 index_y);
+    static ErrorOr<PredictionMode> parse_default_uv_mode(BooleanDecoder&, ProbabilityTables const&, PredictionMode y_mode);
+    static ErrorOr<PredictionMode> parse_intra_mode(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, BlockSubsize mi_size);
+    static ErrorOr<PredictionMode> parse_sub_intra_mode(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&);
+    static ErrorOr<PredictionMode> parse_uv_mode(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, PredictionMode y_mode);
+    static ErrorOr<u8> parse_segment_id(BooleanDecoder&, Array<u8, 7> const& probabilities);
+    static ErrorOr<bool> parse_segment_id_predicted(BooleanDecoder&, Array<u8, 3> const& probabilities, u8 above_seg_pred_context, u8 left_seg_pred_context);
+    static ErrorOr<PredictionMode> parse_inter_mode(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, u8 mode_context_for_ref_frame_0);
+    static ErrorOr<InterpolationFilter> parse_interpolation_filter(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, FrameBlockContext above, FrameBlockContext left);
+    static ErrorOr<bool> parse_skip(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, FrameBlockContext above, FrameBlockContext left);
+    static ErrorOr<TransformSize> parse_tx_size(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, TransformSize max_tx_size, FrameBlockContext above, FrameBlockContext left);
+    static ErrorOr<bool> parse_block_is_inter_predicted(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, FrameBlockContext above, FrameBlockContext left);
+    static ErrorOr<ReferenceMode> parse_comp_mode(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, ReferenceFrameType comp_fixed_ref, FrameBlockContext above, FrameBlockContext left);
+    static ErrorOr<ReferenceIndex> parse_comp_ref(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, ReferenceFrameType comp_fixed_ref, ReferenceFramePair comp_var_ref, ReferenceIndex variable_reference_index, FrameBlockContext above, FrameBlockContext left);
+    static ErrorOr<bool> parse_single_ref_part_1(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, FrameBlockContext above, FrameBlockContext left);
+    static ErrorOr<bool> parse_single_ref_part_2(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, FrameBlockContext above, FrameBlockContext left);
 
-    static ErrorOr<MvJoint> parse_motion_vector_joint(BitStream&, ProbabilityTables const&, SyntaxElementCounter&);
-    static ErrorOr<bool> parse_motion_vector_sign(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, u8 component);
-    static ErrorOr<MvClass> parse_motion_vector_class(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, u8 component);
-    static ErrorOr<bool> parse_motion_vector_class0_bit(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, u8 component);
-    static ErrorOr<u8> parse_motion_vector_class0_fr(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, u8 component, bool class_0_bit);
-    static ErrorOr<bool> parse_motion_vector_class0_hp(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, u8 component, bool use_hp);
-    static ErrorOr<bool> parse_motion_vector_bit(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, u8 component, u8 bit_index);
-    static ErrorOr<u8> parse_motion_vector_fr(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, u8 component);
-    static ErrorOr<bool> parse_motion_vector_hp(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, u8 component, bool use_hp);
+    static ErrorOr<MvJoint> parse_motion_vector_joint(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&);
+    static ErrorOr<bool> parse_motion_vector_sign(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, u8 component);
+    static ErrorOr<MvClass> parse_motion_vector_class(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, u8 component);
+    static ErrorOr<bool> parse_motion_vector_class0_bit(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, u8 component);
+    static ErrorOr<u8> parse_motion_vector_class0_fr(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, u8 component, bool class_0_bit);
+    static ErrorOr<bool> parse_motion_vector_class0_hp(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, u8 component, bool use_hp);
+    static ErrorOr<bool> parse_motion_vector_bit(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, u8 component, u8 bit_index);
+    static ErrorOr<u8> parse_motion_vector_fr(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, u8 component);
+    static ErrorOr<bool> parse_motion_vector_hp(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, u8 component, bool use_hp);
 
     static TokensContext get_context_for_first_token(NonZeroTokensView above_non_zero_tokens, NonZeroTokensView left_non_zero_tokens, TransformSize transform_size, u8 plane, u32 sub_block_column, u32 sub_block_row, bool is_inter, u8 band);
     static TokensContext get_context_for_other_tokens(Array<u8, 1024> token_cache, TransformSize transform_size, TransformSet transform_set, u8 plane, u16 token_position, bool is_inter, u8 band);
-    static ErrorOr<bool> parse_more_coefficients(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, TokensContext const& context);
-    static ErrorOr<Token> parse_token(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, TokensContext const& context);
+    static ErrorOr<bool> parse_more_coefficients(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, TokensContext const& context);
+    static ErrorOr<Token> parse_token(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, TokensContext const& context);
 };
 
 struct PartitionTreeContext {

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff