From fb0c226da3b060dfdc9c4b9e24c3d1fa1dde470b Mon Sep 17 00:00:00 2001 From: Zaggy1024 Date: Sat, 11 Feb 2023 19:35:26 -0600 Subject: [PATCH] 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! --- Userland/Libraries/LibVideo/CMakeLists.txt | 2 +- Userland/Libraries/LibVideo/VP9/BitStream.cpp | 168 ------- Userland/Libraries/LibVideo/VP9/BitStream.h | 59 --- .../Libraries/LibVideo/VP9/BooleanDecoder.cpp | 87 ++++ .../Libraries/LibVideo/VP9/BooleanDecoder.h | 41 ++ Userland/Libraries/LibVideo/VP9/Context.h | 25 +- Userland/Libraries/LibVideo/VP9/Parser.cpp | 468 +++++++++--------- Userland/Libraries/LibVideo/VP9/Parser.h | 56 +-- .../Libraries/LibVideo/VP9/TreeParser.cpp | 116 ++--- Userland/Libraries/LibVideo/VP9/TreeParser.h | 58 +-- 10 files changed, 499 insertions(+), 581 deletions(-) delete mode 100644 Userland/Libraries/LibVideo/VP9/BitStream.cpp delete mode 100644 Userland/Libraries/LibVideo/VP9/BitStream.h create mode 100644 Userland/Libraries/LibVideo/VP9/BooleanDecoder.cpp create mode 100644 Userland/Libraries/LibVideo/VP9/BooleanDecoder.h diff --git a/Userland/Libraries/LibVideo/CMakeLists.txt b/Userland/Libraries/LibVideo/CMakeLists.txt index eb237587d6..6b658cbfb0 100644 --- a/Userland/Libraries/LibVideo/CMakeLists.txt +++ b/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 diff --git a/Userland/Libraries/LibVideo/VP9/BitStream.cpp b/Userland/Libraries/LibVideo/VP9/BitStream.cpp deleted file mode 100644 index e9f6ba371c..0000000000 --- a/Userland/Libraries/LibVideo/VP9/BitStream.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) 2021, Hunter Salyer - * Copyright (c) 2022, Gregory Bertilson - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include - -#include "BitStream.h" - -namespace Video::VP9 { - -ErrorOr 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 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 BitStream::read_bit() -{ - auto value = TRY(read_bits(1)); - VERIFY(value <= 2); - return value != 0; -} - -ErrorOr BitStream::read_f8() -{ - return TRY(read_bits(8)); -} - -ErrorOr BitStream::read_f16() -{ - return TRY(read_bits(16)); -} - -/* 9.2.1 */ -ErrorOr 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 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 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 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 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; -} - -} diff --git a/Userland/Libraries/LibVideo/VP9/BitStream.h b/Userland/Libraries/LibVideo/VP9/BitStream.h deleted file mode 100644 index 4ea7afee9e..0000000000 --- a/Userland/Libraries/LibVideo/VP9/BitStream.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2021, Hunter Salyer - * Copyright (c) 2022, Gregory Bertilson - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include -#include - -namespace Video::VP9 { - -class BitStream { -public: - BitStream(u8 const* data, size_t size) - : m_data_ptr(data) - , m_end_ptr(data + size) - { - } - - ErrorOr read_bit(); - - ErrorOr read_bits(u8 bit_count); - /* (9.1) */ - ErrorOr read_f8(); - ErrorOr read_f16(); - - /* (9.2) */ - ErrorOr init_bool(size_t bytes); - ErrorOr read_bool(u8 probability); - ErrorOr exit_bool(); - ErrorOr read_literal(u8 bit_count); - size_t range_coding_bits_remaining(); - - /* (4.9.2) */ - ErrorOr read_s(size_t n); - - u64 get_position(); - size_t bytes_remaining(); - size_t bits_remaining(); - -private: - ErrorOr 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 }; -}; - -} diff --git a/Userland/Libraries/LibVideo/VP9/BooleanDecoder.cpp b/Userland/Libraries/LibVideo/VP9/BooleanDecoder.cpp new file mode 100644 index 0000000000..457bc3b721 --- /dev/null +++ b/Userland/Libraries/LibVideo/VP9/BooleanDecoder.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2021, Hunter Salyer + * Copyright (c) 2022, Gregory Bertilson + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +#include "BooleanDecoder.h" + +namespace Video::VP9 { + +/* 9.2.1 */ +ErrorOr BooleanDecoder::initialize(MaybeOwned bit_stream, size_t bytes) +{ + VERIFY(bit_stream->is_aligned_to_byte_boundary()); + auto value = TRY(bit_stream->read_value()); + 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 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(bits_to_shift_into_range)); + m_bits_left -= bits_to_shift_into_range; + } + + return return_bool; +} + +ErrorOr 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 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 {}; +} + +} diff --git a/Userland/Libraries/LibVideo/VP9/BooleanDecoder.h b/Userland/Libraries/LibVideo/VP9/BooleanDecoder.h new file mode 100644 index 0000000000..0d5f2cb4df --- /dev/null +++ b/Userland/Libraries/LibVideo/VP9/BooleanDecoder.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021, Hunter Salyer + * Copyright (c) 2022, Gregory Bertilson + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include + +namespace Video::VP9 { + +class BooleanDecoder { +public: + /* (9.2) */ + static ErrorOr initialize(MaybeOwned bit_stream, size_t bytes); + ErrorOr read_bool(u8 probability); + ErrorOr read_literal(u8 bits); + size_t bits_remaining() const; + ErrorOr finish_decode(); + +private: + BooleanDecoder(MaybeOwned&& 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 m_bit_stream; + u8 m_value { 0 }; + u8 m_range { 0 }; + u64 m_bits_left { 0 }; +}; + +} diff --git a/Userland/Libraries/LibVideo/VP9/Context.h b/Userland/Libraries/LibVideo/VP9/Context.h index a86c621fda..ab410ab4f5 100644 --- a/Userland/Libraries/LibVideo/VP9/Context.h +++ b/Userland/Libraries/LibVideo/VP9/Context.h @@ -8,11 +8,14 @@ #pragma once #include +#include #include #include +#include #include #include +#include "BooleanDecoder.h" #include "ContextStorage.h" #include "Enums.h" #include "LookupTables.h" @@ -29,11 +32,20 @@ enum class FrameShowMode { struct FrameContext { public: - FrameContext(Vector2D& contexts) - : m_block_contexts(contexts) + FrameContext(ReadonlyBytes data, + Vector2D& contexts) + : stream(data) + , bit_stream(MaybeOwned(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 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 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(TRY(try_make(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 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; diff --git a/Userland/Libraries/LibVideo/VP9/Parser.cpp b/Userland/Libraries/LibVideo/VP9/Parser.cpp index c7e7443237..81ce1cac21 100644 --- a/Userland/Libraries/LibVideo/VP9/Parser.cpp +++ b/Userland/Libraries/LibVideo/VP9/Parser.cpp @@ -6,6 +6,7 @@ */ #include +#include #include #include @@ -82,12 +83,13 @@ Vector Parser::parse_superframe_sizes(ReadonlyBytes frame_data) /* (6.1) */ DecoderErrorOr Parser::parse_frame(ReadonlyBytes frame_data) { - m_bit_stream = make(frame_data.data(), frame_data.size()); m_syntax_element_counter = make(); - auto frame_context = TRY(uncompressed_header()); - if (!trailing_bits()) - return DecoderError::corrupted("Trailing bits were non-zero"sv); + // NOTE: m_reusable_frame_block_contexts does not need to retain any data between frame decodes. + // This is only stored so that we don't need to allocate a frame's block contexts on each + // call to this function, since it will rarely change sizes. + FrameContext frame_context { frame_data, m_reusable_frame_block_contexts }; + TRY(uncompressed_header(frame_context)); // FIXME: This should not be an error. Spec says that we consume padding bits until the end of the sample. if (frame_context.header_size_in_bytes == 0) return DecoderError::corrupted("Frame header is zero-sized"sv); @@ -95,9 +97,7 @@ DecoderErrorOr Parser::parse_frame(ReadonlyBytes frame_data) m_probability_tables->load_probs2(frame_context.probability_context_index); m_syntax_element_counter->clear_counts(); - TRY_READ(m_bit_stream->init_bool(frame_context.header_size_in_bytes)); TRY(compressed_header(frame_context)); - TRY_READ(m_bit_stream->exit_bool()); TRY(m_decoder.allocate_buffers(frame_context)); @@ -119,15 +119,6 @@ DecoderErrorOr Parser::parse_frame(ReadonlyBytes frame_data) return frame_context; } -bool Parser::trailing_bits() -{ - while (m_bit_stream->bits_remaining() & 7u) { - if (MUST(m_bit_stream->read_bit())) - return false; - } - return true; -} - DecoderErrorOr Parser::refresh_probs(FrameContext const& frame_context) { if (!frame_context.error_resilient_mode && !frame_context.parallel_decoding_mode) { @@ -143,43 +134,39 @@ DecoderErrorOr Parser::refresh_probs(FrameContext const& frame_context) return {}; } -DecoderErrorOr Parser::read_video_full_range_flag() +DecoderErrorOr Parser::read_video_full_range_flag(BigEndianInputBitStream& bit_stream) { - if (TRY_READ(m_bit_stream->read_bit())) + if (TRY_READ(bit_stream.read_bit())) return VideoFullRangeFlag::Full; return VideoFullRangeFlag::Studio; } /* (6.2) */ -DecoderErrorOr Parser::uncompressed_header() +DecoderErrorOr Parser::uncompressed_header(FrameContext& frame_context) { - // NOTE: m_reusable_frame_block_contexts does not need to retain any data between frame decodes. - // This is only stored so that we don't need to allocate a frame's block contexts on each - // call to this function, since it will rarely change sizes. - FrameContext frame_context { m_reusable_frame_block_contexts }; frame_context.color_config = m_previous_color_config; - auto frame_marker = TRY_READ(m_bit_stream->read_bits(2)); + auto frame_marker = TRY_READ(frame_context.bit_stream.read_bits(2)); if (frame_marker != 2) return DecoderError::corrupted("uncompressed_header: Frame marker must be 2"sv); - auto profile_low_bit = TRY_READ(m_bit_stream->read_bit()); - auto profile_high_bit = TRY_READ(m_bit_stream->read_bit()); + auto profile_low_bit = TRY_READ(frame_context.bit_stream.read_bit()); + auto profile_high_bit = TRY_READ(frame_context.bit_stream.read_bit()); frame_context.profile = (profile_high_bit << 1u) + profile_low_bit; - if (frame_context.profile == 3 && TRY_READ(m_bit_stream->read_bit())) + if (frame_context.profile == 3 && TRY_READ(frame_context.bit_stream.read_bit())) return DecoderError::corrupted("uncompressed_header: Profile 3 reserved bit was non-zero"sv); - if (TRY_READ(m_bit_stream->read_bit())) { - frame_context.set_existing_frame_to_show(TRY_READ(m_bit_stream->read_bits(3))); - return frame_context; + if (TRY_READ(frame_context.bit_stream.read_bit())) { + frame_context.set_existing_frame_to_show(TRY_READ(frame_context.bit_stream.read_bits(3))); + return {}; } - bool is_keyframe = !TRY_READ(m_bit_stream->read_bit()); + bool is_keyframe = !TRY_READ(frame_context.bit_stream.read_bit()); - if (!TRY_READ(m_bit_stream->read_bit())) + if (!TRY_READ(frame_context.bit_stream.read_bit())) frame_context.set_frame_hidden(); - frame_context.error_resilient_mode = TRY_READ(m_bit_stream->read_bit()); + frame_context.error_resilient_mode = TRY_READ(frame_context.bit_stream.read_bit()); FrameType type; @@ -197,12 +184,12 @@ DecoderErrorOr Parser::uncompressed_header() if (is_keyframe) { type = FrameType::KeyFrame; - TRY(frame_sync_code()); - frame_context.color_config = TRY(parse_color_config(frame_context)); - frame_size = TRY(parse_frame_size()); - render_size = TRY(parse_render_size(frame_size)); + TRY(frame_sync_code(frame_context.bit_stream)); + frame_context.color_config = TRY(parse_color_config(frame_context.bit_stream, frame_context.profile)); + frame_size = TRY(parse_frame_size(frame_context.bit_stream)); + render_size = TRY(parse_render_size(frame_context.bit_stream, frame_size)); } else { - if (!frame_context.shows_a_frame() && TRY_READ(m_bit_stream->read_bit())) { + if (!frame_context.shows_a_frame() && TRY_READ(frame_context.bit_stream.read_bit())) { type = FrameType::IntraOnlyFrame; } else { type = FrameType::InterFrame; @@ -210,37 +197,41 @@ DecoderErrorOr Parser::uncompressed_header() } if (!frame_context.error_resilient_mode) - reset_frame_context = static_cast(TRY_READ(m_bit_stream->read_bits(2))); + reset_frame_context = static_cast(TRY_READ(frame_context.bit_stream.read_bits(2))); if (type == FrameType::IntraOnlyFrame) { - TRY(frame_sync_code()); + TRY(frame_sync_code(frame_context.bit_stream)); - frame_context.color_config = frame_context.profile > 0 ? TRY(parse_color_config(frame_context)) : ColorConfig(); - - reference_frames_to_update_flags = TRY_READ(m_bit_stream->read_f8()); - frame_size = TRY(parse_frame_size()); - render_size = TRY(parse_render_size(frame_size)); - } else { - reference_frames_to_update_flags = TRY_READ(m_bit_stream->read_bits(NUM_REF_FRAMES)); - for (auto i = 0; i < REFS_PER_FRAME; i++) { - frame_context.reference_frame_indices[i] = TRY_READ(m_bit_stream->read_bits(LOG2_OF_NUM_REF_FRAMES)); - frame_context.reference_frame_sign_biases[ReferenceFrameType::LastFrame + i] = TRY_READ(m_bit_stream->read_bit()); + if (frame_context.profile == 0) { + frame_context.color_config = ColorConfig(); + } else { + frame_context.color_config = TRY(parse_color_config(frame_context.bit_stream, frame_context.profile)); } - frame_size = TRY(parse_frame_size_with_refs(frame_context.reference_frame_indices)); - render_size = TRY(parse_render_size(frame_size)); - frame_context.high_precision_motion_vectors_allowed = TRY_READ(m_bit_stream->read_bit()); - frame_context.interpolation_filter = TRY(read_interpolation_filter()); + + reference_frames_to_update_flags = TRY_READ(frame_context.bit_stream.read_bits(8)); + frame_size = TRY(parse_frame_size(frame_context.bit_stream)); + render_size = TRY(parse_render_size(frame_context.bit_stream, frame_size)); + } else { + reference_frames_to_update_flags = TRY_READ(frame_context.bit_stream.read_bits(NUM_REF_FRAMES)); + for (auto i = 0; i < REFS_PER_FRAME; i++) { + frame_context.reference_frame_indices[i] = TRY_READ(frame_context.bit_stream.read_bits(LOG2_OF_NUM_REF_FRAMES)); + frame_context.reference_frame_sign_biases[ReferenceFrameType::LastFrame + i] = TRY_READ(frame_context.bit_stream.read_bit()); + } + frame_size = TRY(parse_frame_size_with_refs(frame_context.bit_stream, frame_context.reference_frame_indices)); + render_size = TRY(parse_render_size(frame_context.bit_stream, frame_size)); + frame_context.high_precision_motion_vectors_allowed = TRY_READ(frame_context.bit_stream.read_bit()); + frame_context.interpolation_filter = TRY(read_interpolation_filter(frame_context.bit_stream)); } } bool should_replace_probability_context = false; bool parallel_decoding_mode = true; if (!frame_context.error_resilient_mode) { - should_replace_probability_context = TRY_READ(m_bit_stream->read_bit()); - parallel_decoding_mode = TRY_READ(m_bit_stream->read_bit()); + should_replace_probability_context = TRY_READ(frame_context.bit_stream.read_bit()); + parallel_decoding_mode = TRY_READ(frame_context.bit_stream.read_bit()); } - u8 probability_context_index = TRY_READ(m_bit_stream->read_bits(2)); + u8 probability_context_index = TRY_READ(frame_context.bit_stream.read_bits(2)); switch (reset_frame_context) { case ResetProbabilities::All: setup_past_independence(); @@ -274,44 +265,42 @@ DecoderErrorOr Parser::uncompressed_header() TRY(segmentation_params(frame_context)); TRY(parse_tile_counts(frame_context)); - frame_context.header_size_in_bytes = TRY_READ(m_bit_stream->read_f16()); + frame_context.header_size_in_bytes = TRY_READ(frame_context.bit_stream.read_bits(16)); - return frame_context; -} - -DecoderErrorOr Parser::frame_sync_code() -{ - if (TRY_READ(m_bit_stream->read_f8()) != 0x49) - return DecoderError::corrupted("frame_sync_code: Byte 0 was not 0x49."sv); - if (TRY_READ(m_bit_stream->read_f8()) != 0x83) - return DecoderError::corrupted("frame_sync_code: Byte 1 was not 0x83."sv); - if (TRY_READ(m_bit_stream->read_f8()) != 0x42) - return DecoderError::corrupted("frame_sync_code: Byte 2 was not 0x42."sv); + frame_context.bit_stream.align_to_byte_boundary(); return {}; } -DecoderErrorOr Parser::parse_color_config(FrameContext const& frame_context) +DecoderErrorOr Parser::frame_sync_code(BigEndianInputBitStream& bit_stream) +{ + if (TRY_READ(bit_stream.read_bits(24)) != 0x498342) { + return DecoderError::corrupted("frame sync code was not 0x498342."sv); + } + return {}; +} + +DecoderErrorOr Parser::parse_color_config(BigEndianInputBitStream& bit_stream, u8 profile) { // (6.2.2) color_config( ) u8 bit_depth; - if (frame_context.profile >= 2) { - bit_depth = TRY_READ(m_bit_stream->read_bit()) ? 12 : 10; + if (profile >= 2) { + bit_depth = TRY_READ(bit_stream.read_bit()) ? 12 : 10; } else { bit_depth = 8; } - auto color_space = static_cast(TRY_READ(m_bit_stream->read_bits(3))); + auto color_space = static_cast(TRY_READ(bit_stream.read_bits(3))); VERIFY(color_space <= ColorSpace::RGB); VideoFullRangeFlag video_full_range_flag; bool subsampling_x, subsampling_y; if (color_space != ColorSpace::RGB) { - video_full_range_flag = TRY(read_video_full_range_flag()); - if (frame_context.profile == 1 || frame_context.profile == 3) { - subsampling_x = TRY_READ(m_bit_stream->read_bit()); - subsampling_y = TRY_READ(m_bit_stream->read_bit()); - if (TRY_READ(m_bit_stream->read_bit())) + video_full_range_flag = TRY(read_video_full_range_flag(bit_stream)); + if (profile == 1 || profile == 3) { + subsampling_x = TRY_READ(bit_stream.read_bit()); + subsampling_y = TRY_READ(bit_stream.read_bit()); + if (TRY_READ(bit_stream.read_bit())) return DecoderError::corrupted("color_config: Subsampling reserved zero was set"sv); } else { subsampling_x = true; @@ -319,10 +308,10 @@ DecoderErrorOr Parser::parse_color_config(FrameContext const& frame } } else { video_full_range_flag = VideoFullRangeFlag::Full; - if (frame_context.profile == 1 || frame_context.profile == 3) { + if (profile == 1 || profile == 3) { subsampling_x = false; subsampling_y = false; - if (TRY_READ(m_bit_stream->read_bit())) + if (TRY_READ(bit_stream.read_bit())) return DecoderError::corrupted("color_config: RGB reserved zero was set"sv); } else { // FIXME: Spec does not specify the subsampling value here. Is this an error or should we set a default? @@ -333,12 +322,12 @@ DecoderErrorOr Parser::parse_color_config(FrameContext const& frame return ColorConfig { bit_depth, color_space, video_full_range_flag, subsampling_x, subsampling_y }; } -DecoderErrorOr> Parser::parse_frame_size() +DecoderErrorOr> Parser::parse_frame_size(BigEndianInputBitStream& bit_stream) { - return Gfx::Size { TRY_READ(m_bit_stream->read_f16()) + 1, TRY_READ(m_bit_stream->read_f16()) + 1 }; + return Gfx::Size { TRY_READ(bit_stream.read_bits(16)) + 1, TRY_READ(bit_stream.read_bits(16)) + 1 }; } -DecoderErrorOr> Parser::parse_render_size(Gfx::Size frame_size) +DecoderErrorOr> Parser::parse_render_size(BigEndianInputBitStream& bit_stream, Gfx::Size frame_size) { // FIXME: This function should save this bit as a value in the FrameContext. The bit can be // used in files where the pixel aspect ratio changes between samples in the video. @@ -347,16 +336,16 @@ DecoderErrorOr> Parser::parse_render_size(Gfx::Size frame_si // ratio should be retained and the new render size determined based on that. // See the Firefox source code here: // https://searchfox.org/mozilla-central/source/dom/media/platforms/wrappers/MediaChangeMonitor.cpp#268-276 - if (!TRY_READ(m_bit_stream->read_bit())) + if (!TRY_READ(bit_stream.read_bit())) return frame_size; - return Gfx::Size { TRY_READ(m_bit_stream->read_f16()) + 1, TRY_READ(m_bit_stream->read_f16()) + 1 }; + return Gfx::Size { TRY_READ(bit_stream.read_bits(16)) + 1, TRY_READ(bit_stream.read_bits(16)) + 1 }; } -DecoderErrorOr> Parser::parse_frame_size_with_refs(Array const& reference_indices) +DecoderErrorOr> Parser::parse_frame_size_with_refs(BigEndianInputBitStream& bit_stream, Array const& reference_indices) { Optional> size; for (auto frame_index : reference_indices) { - if (TRY_READ(m_bit_stream->read_bit())) { + if (TRY_READ(bit_stream.read_bit())) { if (!m_reference_frames[frame_index].is_valid()) return DecoderError::corrupted("Frame size referenced a frame that does not exist"sv); size.emplace(m_reference_frames[frame_index].size); @@ -367,7 +356,7 @@ DecoderErrorOr> Parser::parse_frame_size_with_refs(Array c if (size.has_value()) return size.value(); - return TRY(parse_frame_size()); + return TRY(parse_frame_size(bit_stream)); } DecoderErrorOr Parser::compute_image_size(FrameContext& frame_context) @@ -397,30 +386,40 @@ DecoderErrorOr Parser::compute_image_size(FrameContext& frame_context) return {}; } -DecoderErrorOr Parser::read_interpolation_filter() +DecoderErrorOr Parser::read_interpolation_filter(BigEndianInputBitStream& bit_stream) { - if (TRY_READ(m_bit_stream->read_bit())) { + if (TRY_READ(bit_stream.read_bit())) { return InterpolationFilter::Switchable; } - return literal_to_type[TRY_READ(m_bit_stream->read_bits(2))]; + return literal_to_type[TRY_READ(bit_stream.read_bits(2))]; +} + +template +static ErrorOr read_signed(BigEndianInputBitStream& bit_stream, u8 bits) +{ + auto value_unsigned = static_cast(TRY(bit_stream.read_bits(bits))); + if (TRY(bit_stream.read_bit())) + return -value_unsigned; + return value_unsigned; } DecoderErrorOr Parser::loop_filter_params(FrameContext& frame_context) { - frame_context.loop_filter_level = TRY_READ(m_bit_stream->read_bits(6)); - frame_context.loop_filter_sharpness = TRY_READ(m_bit_stream->read_bits(3)); - frame_context.loop_filter_delta_enabled = TRY_READ(m_bit_stream->read_bit()); + // FIXME: These should be moved to their own struct to return here. + frame_context.loop_filter_level = TRY_READ(frame_context.bit_stream.read_bits(6)); + frame_context.loop_filter_sharpness = TRY_READ(frame_context.bit_stream.read_bits(3)); + frame_context.loop_filter_delta_enabled = TRY_READ(frame_context.bit_stream.read_bit()); auto reference_deltas = m_previous_loop_filter_ref_deltas; auto mode_deltas = m_previous_loop_filter_mode_deltas; - if (frame_context.loop_filter_delta_enabled && TRY_READ(m_bit_stream->read_bit())) { + if (frame_context.loop_filter_delta_enabled && TRY_READ(frame_context.bit_stream.read_bit())) { for (auto& loop_filter_ref_delta : reference_deltas) { - if (TRY_READ(m_bit_stream->read_bit())) - loop_filter_ref_delta = TRY_READ(m_bit_stream->read_s(6)); + if (TRY_READ(frame_context.bit_stream.read_bit())) + loop_filter_ref_delta = TRY_READ(read_signed(frame_context.bit_stream, 6)); } for (auto& loop_filter_mode_delta : mode_deltas) { - if (TRY_READ(m_bit_stream->read_bit())) - loop_filter_mode_delta = TRY_READ(m_bit_stream->read_s(6)); + if (TRY_READ(frame_context.bit_stream.read_bit())) + loop_filter_mode_delta = TRY_READ(read_signed(frame_context.bit_stream, 6)); } } frame_context.loop_filter_reference_deltas = reference_deltas; @@ -431,56 +430,56 @@ DecoderErrorOr Parser::loop_filter_params(FrameContext& frame_context) DecoderErrorOr Parser::quantization_params(FrameContext& frame_context) { - frame_context.base_quantizer_index = TRY_READ(m_bit_stream->read_f8()); - frame_context.y_dc_quantizer_index_delta = TRY(read_delta_q()); - frame_context.uv_dc_quantizer_index_delta = TRY(read_delta_q()); - frame_context.uv_ac_quantizer_index_delta = TRY(read_delta_q()); + frame_context.base_quantizer_index = TRY_READ(frame_context.bit_stream.read_bits(8)); + frame_context.y_dc_quantizer_index_delta = TRY(read_delta_q(frame_context.bit_stream)); + frame_context.uv_dc_quantizer_index_delta = TRY(read_delta_q(frame_context.bit_stream)); + frame_context.uv_ac_quantizer_index_delta = TRY(read_delta_q(frame_context.bit_stream)); return {}; } -DecoderErrorOr Parser::read_delta_q() +DecoderErrorOr Parser::read_delta_q(BigEndianInputBitStream& bit_stream) { - if (TRY_READ(m_bit_stream->read_bit())) - return TRY_READ(m_bit_stream->read_s(4)); + if (TRY_READ(bit_stream.read_bit())) + return TRY_READ(read_signed(bit_stream, 4)); return 0; } DecoderErrorOr Parser::segmentation_params(FrameContext& frame_context) { - frame_context.segmentation_enabled = TRY_READ(m_bit_stream->read_bit()); + frame_context.segmentation_enabled = TRY_READ(frame_context.bit_stream.read_bit()); if (!frame_context.segmentation_enabled) return {}; frame_context.should_use_absolute_segment_base_quantizer = m_previous_should_use_absolute_segment_base_quantizer; frame_context.segmentation_features = m_previous_segmentation_features; - if (TRY_READ(m_bit_stream->read_bit())) { + if (TRY_READ(frame_context.bit_stream.read_bit())) { frame_context.use_full_segment_id_tree = true; for (auto& segmentation_tree_prob : frame_context.full_segment_id_tree_probabilities) - segmentation_tree_prob = TRY(read_prob()); + segmentation_tree_prob = TRY(read_prob(frame_context.bit_stream)); - if (TRY_READ(m_bit_stream->read_bit())) { + if (TRY_READ(frame_context.bit_stream.read_bit())) { frame_context.use_predicted_segment_id_tree = true; for (auto& segmentation_pred_prob : frame_context.predicted_segment_id_tree_probabilities) - segmentation_pred_prob = TRY(read_prob()); + segmentation_pred_prob = TRY(read_prob(frame_context.bit_stream)); } } - auto segmentation_update_data = (TRY_READ(m_bit_stream->read_bit())); + auto segmentation_update_data = (TRY_READ(frame_context.bit_stream.read_bit())); if (!segmentation_update_data) return {}; - frame_context.should_use_absolute_segment_base_quantizer = TRY_READ(m_bit_stream->read_bit()); + frame_context.should_use_absolute_segment_base_quantizer = TRY_READ(frame_context.bit_stream.read_bit()); for (auto i = 0; i < MAX_SEGMENTS; i++) { for (auto j = 0; j < SEG_LVL_MAX; j++) { auto& feature = frame_context.segmentation_features[i][j]; - feature.enabled = TRY_READ(m_bit_stream->read_bit()); + feature.enabled = TRY_READ(frame_context.bit_stream.read_bit()); if (feature.enabled) { auto bits_to_read = segmentation_feature_bits[j]; - feature.value = TRY_READ(m_bit_stream->read_bits(bits_to_read)); + feature.value = TRY_READ(frame_context.bit_stream.read_bits(bits_to_read)); if (segmentation_feature_signed[j]) { - if (TRY_READ(m_bit_stream->read_bit())) + if (TRY_READ(frame_context.bit_stream.read_bit())) feature.value = -feature.value; } } @@ -490,10 +489,10 @@ DecoderErrorOr Parser::segmentation_params(FrameContext& frame_context) return {}; } -DecoderErrorOr Parser::read_prob() +DecoderErrorOr Parser::read_prob(BigEndianInputBitStream& bit_stream) { - if (TRY_READ(m_bit_stream->read_bit())) - return TRY_READ(m_bit_stream->read_f8()); + if (TRY_READ(bit_stream.read_bit())) + return TRY_READ(bit_stream.read_bits(8)); return 255; } @@ -520,15 +519,15 @@ DecoderErrorOr Parser::parse_tile_counts(FrameContext& frame_context) auto log2_of_tile_columns = calc_min_log2_of_tile_columns(superblock_columns); auto log2_of_tile_columns_maximum = calc_max_log2_tile_cols(superblock_columns); while (log2_of_tile_columns < log2_of_tile_columns_maximum) { - if (TRY_READ(m_bit_stream->read_bit())) + if (TRY_READ(frame_context.bit_stream.read_bit())) log2_of_tile_columns++; else break; } - u16 log2_of_tile_rows = TRY_READ(m_bit_stream->read_bit()); + u16 log2_of_tile_rows = TRY_READ(frame_context.bit_stream.read_bit()); if (log2_of_tile_rows > 0) { - log2_of_tile_rows += TRY_READ(m_bit_stream->read_bit()); + log2_of_tile_rows += TRY_READ(frame_context.bit_stream.read_bit()); } frame_context.log2_of_tile_counts = Gfx::Size(log2_of_tile_columns, log2_of_tile_rows); return {}; @@ -550,78 +549,80 @@ void Parser::setup_past_independence() DecoderErrorOr Parser::compressed_header(FrameContext& frame_context) { - frame_context.transform_mode = TRY(read_tx_mode(frame_context)); + auto decoder = TRY_READ(BooleanDecoder::initialize(MaybeOwned(frame_context.bit_stream), frame_context.header_size_in_bytes)); + frame_context.transform_mode = TRY(read_tx_mode(decoder, frame_context)); if (frame_context.transform_mode == TransformMode::Select) - TRY(tx_mode_probs()); - TRY(read_coef_probs(frame_context.transform_mode)); - TRY(read_skip_prob()); + TRY(tx_mode_probs(decoder)); + TRY(read_coef_probs(decoder, frame_context.transform_mode)); + TRY(read_skip_prob(decoder)); if (frame_context.is_inter_predicted()) { - TRY(read_inter_mode_probs()); + TRY(read_inter_mode_probs(decoder)); if (frame_context.interpolation_filter == Switchable) - TRY(read_interp_filter_probs()); - TRY(read_is_inter_probs()); - TRY(frame_reference_mode(frame_context)); - TRY(frame_reference_mode_probs(frame_context)); - TRY(read_y_mode_probs()); - TRY(read_partition_probs()); - TRY(mv_probs(frame_context)); + TRY(read_interp_filter_probs(decoder)); + TRY(read_is_inter_probs(decoder)); + TRY(frame_reference_mode(frame_context, decoder)); + TRY(frame_reference_mode_probs(decoder, frame_context)); + TRY(read_y_mode_probs(decoder)); + TRY(read_partition_probs(decoder)); + TRY(mv_probs(decoder, frame_context)); } + TRY_READ(decoder.finish_decode()); return {}; } -DecoderErrorOr Parser::read_tx_mode(FrameContext const& frame_context) +DecoderErrorOr Parser::read_tx_mode(BooleanDecoder& decoder, FrameContext const& frame_context) { if (frame_context.is_lossless()) { return TransformMode::Only_4x4; } - auto tx_mode = TRY_READ(m_bit_stream->read_literal(2)); + auto tx_mode = TRY_READ(decoder.read_literal(2)); if (tx_mode == to_underlying(TransformMode::Allow_32x32)) - tx_mode += TRY_READ(m_bit_stream->read_literal(1)); + tx_mode += TRY_READ(decoder.read_literal(1)); return static_cast(tx_mode); } -DecoderErrorOr Parser::tx_mode_probs() +DecoderErrorOr Parser::tx_mode_probs(BooleanDecoder& decoder) { auto& tx_probs = m_probability_tables->tx_probs(); for (auto i = 0; i < TX_SIZE_CONTEXTS; i++) { for (auto j = 0; j < TX_SIZES - 3; j++) - tx_probs[Transform_8x8][i][j] = TRY(diff_update_prob(tx_probs[Transform_8x8][i][j])); + tx_probs[Transform_8x8][i][j] = TRY(diff_update_prob(decoder, tx_probs[Transform_8x8][i][j])); } for (auto i = 0; i < TX_SIZE_CONTEXTS; i++) { for (auto j = 0; j < TX_SIZES - 2; j++) - tx_probs[Transform_16x16][i][j] = TRY(diff_update_prob(tx_probs[Transform_16x16][i][j])); + tx_probs[Transform_16x16][i][j] = TRY(diff_update_prob(decoder, tx_probs[Transform_16x16][i][j])); } for (auto i = 0; i < TX_SIZE_CONTEXTS; i++) { for (auto j = 0; j < TX_SIZES - 1; j++) - tx_probs[Transform_32x32][i][j] = TRY(diff_update_prob(tx_probs[Transform_32x32][i][j])); + tx_probs[Transform_32x32][i][j] = TRY(diff_update_prob(decoder, tx_probs[Transform_32x32][i][j])); } return {}; } -DecoderErrorOr Parser::diff_update_prob(u8 prob) +DecoderErrorOr Parser::diff_update_prob(BooleanDecoder& decoder, u8 prob) { - auto update_prob = TRY_READ(m_bit_stream->read_bool(252)); + auto update_prob = TRY_READ(decoder.read_bool(252)); if (update_prob) { - auto delta_prob = TRY(decode_term_subexp()); + auto delta_prob = TRY(decode_term_subexp(decoder)); prob = inv_remap_prob(delta_prob, prob); } return prob; } -DecoderErrorOr Parser::decode_term_subexp() +DecoderErrorOr Parser::decode_term_subexp(BooleanDecoder& decoder) { - if (TRY_READ(m_bit_stream->read_literal(1)) == 0) - return TRY_READ(m_bit_stream->read_literal(4)); - if (TRY_READ(m_bit_stream->read_literal(1)) == 0) - return TRY_READ(m_bit_stream->read_literal(4)) + 16; - if (TRY_READ(m_bit_stream->read_literal(1)) == 0) - return TRY_READ(m_bit_stream->read_literal(5)) + 32; + if (TRY_READ(decoder.read_literal(1)) == 0) + return TRY_READ(decoder.read_literal(4)); + if (TRY_READ(decoder.read_literal(1)) == 0) + return TRY_READ(decoder.read_literal(4)) + 16; + if (TRY_READ(decoder.read_literal(1)) == 0) + return TRY_READ(decoder.read_literal(5)) + 32; - auto v = TRY_READ(m_bit_stream->read_literal(7)); + auto v = TRY_READ(decoder.read_literal(7)); if (v < 65) return v + 64; - return (v << 1u) - 1 + TRY_READ(m_bit_stream->read_literal(1)); + return (v << 1u) - 1 + TRY_READ(decoder.read_literal(1)); } u8 Parser::inv_remap_prob(u8 delta_prob, u8 prob) @@ -642,11 +643,11 @@ u8 Parser::inv_recenter_nonneg(u8 v, u8 m) return m + (v >> 1u); } -DecoderErrorOr Parser::read_coef_probs(TransformMode transform_mode) +DecoderErrorOr Parser::read_coef_probs(BooleanDecoder& decoder, TransformMode transform_mode) { auto max_tx_size = tx_mode_to_biggest_tx_size[to_underlying(transform_mode)]; for (u8 transform_size = 0; transform_size <= max_tx_size; transform_size++) { - auto update_probs = TRY_READ(m_bit_stream->read_literal(1)); + auto update_probs = TRY_READ(decoder.read_literal(1)); if (update_probs == 1) { for (auto i = 0; i < 2; i++) { for (auto j = 0; j < 2; j++) { @@ -655,7 +656,7 @@ DecoderErrorOr Parser::read_coef_probs(TransformMode transform_mode) for (auto l = 0; l < max_l; l++) { for (auto m = 0; m < 3; m++) { auto& prob = m_probability_tables->coef_probs()[transform_size][i][j][k][l][m]; - prob = TRY(diff_update_prob(prob)); + prob = TRY(diff_update_prob(decoder, prob)); } } } @@ -666,35 +667,35 @@ DecoderErrorOr Parser::read_coef_probs(TransformMode transform_mode) return {}; } -DecoderErrorOr Parser::read_skip_prob() +DecoderErrorOr Parser::read_skip_prob(BooleanDecoder& decoder) { for (auto i = 0; i < SKIP_CONTEXTS; i++) - m_probability_tables->skip_prob()[i] = TRY(diff_update_prob(m_probability_tables->skip_prob()[i])); + m_probability_tables->skip_prob()[i] = TRY(diff_update_prob(decoder, m_probability_tables->skip_prob()[i])); return {}; } -DecoderErrorOr Parser::read_inter_mode_probs() +DecoderErrorOr Parser::read_inter_mode_probs(BooleanDecoder& decoder) { for (auto i = 0; i < INTER_MODE_CONTEXTS; i++) { for (auto j = 0; j < INTER_MODES - 1; j++) - m_probability_tables->inter_mode_probs()[i][j] = TRY(diff_update_prob(m_probability_tables->inter_mode_probs()[i][j])); + m_probability_tables->inter_mode_probs()[i][j] = TRY(diff_update_prob(decoder, m_probability_tables->inter_mode_probs()[i][j])); } return {}; } -DecoderErrorOr Parser::read_interp_filter_probs() +DecoderErrorOr Parser::read_interp_filter_probs(BooleanDecoder& decoder) { for (auto i = 0; i < INTERP_FILTER_CONTEXTS; i++) { for (auto j = 0; j < SWITCHABLE_FILTERS - 1; j++) - m_probability_tables->interp_filter_probs()[i][j] = TRY(diff_update_prob(m_probability_tables->interp_filter_probs()[i][j])); + m_probability_tables->interp_filter_probs()[i][j] = TRY(diff_update_prob(decoder, m_probability_tables->interp_filter_probs()[i][j])); } return {}; } -DecoderErrorOr Parser::read_is_inter_probs() +DecoderErrorOr Parser::read_is_inter_probs(BooleanDecoder& decoder) { for (auto i = 0; i < IS_INTER_CONTEXTS; i++) - m_probability_tables->is_inter_prob()[i] = TRY(diff_update_prob(m_probability_tables->is_inter_prob()[i])); + m_probability_tables->is_inter_prob()[i] = TRY(diff_update_prob(decoder, m_probability_tables->is_inter_prob()[i])); return {}; } @@ -716,7 +717,7 @@ static void setup_compound_reference_mode(FrameContext& frame_context) frame_context.variable_reference_types = variable_references; } -DecoderErrorOr Parser::frame_reference_mode(FrameContext& frame_context) +DecoderErrorOr Parser::frame_reference_mode(FrameContext& frame_context, BooleanDecoder& decoder) { auto compound_reference_allowed = false; for (size_t i = 2; i <= REFS_PER_FRAME; i++) { @@ -725,11 +726,11 @@ DecoderErrorOr Parser::frame_reference_mode(FrameContext& frame_context) } ReferenceMode reference_mode; if (compound_reference_allowed) { - auto non_single_reference = TRY_READ(m_bit_stream->read_literal(1)); + auto non_single_reference = TRY_READ(decoder.read_literal(1)); if (non_single_reference == 0) { reference_mode = SingleReference; } else { - auto reference_select = TRY_READ(m_bit_stream->read_literal(1)); + auto reference_select = TRY_READ(decoder.read_literal(1)); if (reference_select == 0) reference_mode = CompoundReference; else @@ -744,71 +745,71 @@ DecoderErrorOr Parser::frame_reference_mode(FrameContext& frame_context) return {}; } -DecoderErrorOr Parser::frame_reference_mode_probs(FrameContext const& frame_context) +DecoderErrorOr Parser::frame_reference_mode_probs(BooleanDecoder& decoder, FrameContext const& frame_context) { if (frame_context.reference_mode == ReferenceModeSelect) { for (auto i = 0; i < COMP_MODE_CONTEXTS; i++) { auto& comp_mode_prob = m_probability_tables->comp_mode_prob(); - comp_mode_prob[i] = TRY(diff_update_prob(comp_mode_prob[i])); + comp_mode_prob[i] = TRY(diff_update_prob(decoder, comp_mode_prob[i])); } } if (frame_context.reference_mode != CompoundReference) { for (auto i = 0; i < REF_CONTEXTS; i++) { auto& single_ref_prob = m_probability_tables->single_ref_prob(); - single_ref_prob[i][0] = TRY(diff_update_prob(single_ref_prob[i][0])); - single_ref_prob[i][1] = TRY(diff_update_prob(single_ref_prob[i][1])); + single_ref_prob[i][0] = TRY(diff_update_prob(decoder, single_ref_prob[i][0])); + single_ref_prob[i][1] = TRY(diff_update_prob(decoder, single_ref_prob[i][1])); } } if (frame_context.reference_mode != SingleReference) { for (auto i = 0; i < REF_CONTEXTS; i++) { auto& comp_ref_prob = m_probability_tables->comp_ref_prob(); - comp_ref_prob[i] = TRY(diff_update_prob(comp_ref_prob[i])); + comp_ref_prob[i] = TRY(diff_update_prob(decoder, comp_ref_prob[i])); } } return {}; } -DecoderErrorOr Parser::read_y_mode_probs() +DecoderErrorOr Parser::read_y_mode_probs(BooleanDecoder& decoder) { for (auto i = 0; i < BLOCK_SIZE_GROUPS; i++) { for (auto j = 0; j < INTRA_MODES - 1; j++) { auto& y_mode_probs = m_probability_tables->y_mode_probs(); - y_mode_probs[i][j] = TRY(diff_update_prob(y_mode_probs[i][j])); + y_mode_probs[i][j] = TRY(diff_update_prob(decoder, y_mode_probs[i][j])); } } return {}; } -DecoderErrorOr Parser::read_partition_probs() +DecoderErrorOr Parser::read_partition_probs(BooleanDecoder& decoder) { for (auto i = 0; i < PARTITION_CONTEXTS; i++) { for (auto j = 0; j < PARTITION_TYPES - 1; j++) { auto& partition_probs = m_probability_tables->partition_probs(); - partition_probs[i][j] = TRY(diff_update_prob(partition_probs[i][j])); + partition_probs[i][j] = TRY(diff_update_prob(decoder, partition_probs[i][j])); } } return {}; } -DecoderErrorOr Parser::mv_probs(FrameContext const& frame_context) +DecoderErrorOr Parser::mv_probs(BooleanDecoder& decoder, FrameContext const& frame_context) { for (auto j = 0; j < MV_JOINTS - 1; j++) { auto& mv_joint_probs = m_probability_tables->mv_joint_probs(); - mv_joint_probs[j] = TRY(update_mv_prob(mv_joint_probs[j])); + mv_joint_probs[j] = TRY(update_mv_prob(decoder, mv_joint_probs[j])); } for (auto i = 0; i < 2; i++) { auto& mv_sign_prob = m_probability_tables->mv_sign_prob(); - mv_sign_prob[i] = TRY(update_mv_prob(mv_sign_prob[i])); + mv_sign_prob[i] = TRY(update_mv_prob(decoder, mv_sign_prob[i])); for (auto j = 0; j < MV_CLASSES - 1; j++) { auto& mv_class_probs = m_probability_tables->mv_class_probs(); - mv_class_probs[i][j] = TRY(update_mv_prob(mv_class_probs[i][j])); + mv_class_probs[i][j] = TRY(update_mv_prob(decoder, mv_class_probs[i][j])); } auto& mv_class0_bit_prob = m_probability_tables->mv_class0_bit_prob(); - mv_class0_bit_prob[i] = TRY(update_mv_prob(mv_class0_bit_prob[i])); + mv_class0_bit_prob[i] = TRY(update_mv_prob(decoder, mv_class0_bit_prob[i])); for (auto j = 0; j < MV_OFFSET_BITS; j++) { auto& mv_bits_prob = m_probability_tables->mv_bits_prob(); - mv_bits_prob[i][j] = TRY(update_mv_prob(mv_bits_prob[i][j])); + mv_bits_prob[i][j] = TRY(update_mv_prob(decoder, mv_bits_prob[i][j])); } } @@ -816,12 +817,12 @@ DecoderErrorOr Parser::mv_probs(FrameContext const& frame_context) for (auto j = 0; j < CLASS0_SIZE; j++) { for (auto k = 0; k < MV_FR_SIZE - 1; k++) { auto& mv_class0_fr_probs = m_probability_tables->mv_class0_fr_probs(); - mv_class0_fr_probs[i][j][k] = TRY(update_mv_prob(mv_class0_fr_probs[i][j][k])); + mv_class0_fr_probs[i][j][k] = TRY(update_mv_prob(decoder, mv_class0_fr_probs[i][j][k])); } } for (auto k = 0; k < MV_FR_SIZE - 1; k++) { auto& mv_fr_probs = m_probability_tables->mv_fr_probs(); - mv_fr_probs[i][k] = TRY(update_mv_prob(mv_fr_probs[i][k])); + mv_fr_probs[i][k] = TRY(update_mv_prob(decoder, mv_fr_probs[i][k])); } } @@ -829,18 +830,18 @@ DecoderErrorOr Parser::mv_probs(FrameContext const& frame_context) for (auto i = 0; i < 2; i++) { auto& mv_class0_hp_prob = m_probability_tables->mv_class0_hp_prob(); auto& mv_hp_prob = m_probability_tables->mv_hp_prob(); - mv_class0_hp_prob[i] = TRY(update_mv_prob(mv_class0_hp_prob[i])); - mv_hp_prob[i] = TRY(update_mv_prob(mv_hp_prob[i])); + mv_class0_hp_prob[i] = TRY(update_mv_prob(decoder, mv_class0_hp_prob[i])); + mv_hp_prob[i] = TRY(update_mv_prob(decoder, mv_hp_prob[i])); } } return {}; } -DecoderErrorOr Parser::update_mv_prob(u8 prob) +DecoderErrorOr Parser::update_mv_prob(BooleanDecoder& decoder, u8 prob) { - if (TRY_READ(m_bit_stream->read_bool(252))) { - return (TRY_READ(m_bit_stream->read_literal(7)) << 1u) | 1u; + if (TRY_READ(decoder.read_bool(252))) { + return (TRY_READ(decoder.read_literal(7)) << 1u) | 1u; } return prob; } @@ -871,9 +872,9 @@ DecoderErrorOr Parser::decode_tiles(FrameContext& frame_context) auto last_tile = (tile_row == tile_rows - 1) && (tile_col == tile_cols - 1); size_t tile_size; if (last_tile) - tile_size = m_bit_stream->bytes_remaining(); + tile_size = frame_context.stream.remaining(); else - tile_size = TRY_READ(m_bit_stream->read_bits(32)); + tile_size = TRY_READ(frame_context.bit_stream.read_bits(32)); auto rows_start = get_tile_offset(tile_row, frame_context.rows(), log2_dimensions.height()); auto rows_end = get_tile_offset(tile_row + 1, frame_context.rows(), log2_dimensions.height()); @@ -885,11 +886,9 @@ DecoderErrorOr Parser::decode_tiles(FrameContext& frame_context) auto above_non_zero_tokens_view = create_non_zero_tokens_view(above_non_zero_tokens, blocks_to_sub_blocks(columns_start), blocks_to_sub_blocks(columns_end - columns_start), frame_context.color_config.subsampling_x); auto above_segmentation_ids_for_tile = safe_slice(above_segmentation_ids.span(), columns_start, columns_end - columns_start); - auto tile_context = DECODER_TRY_ALLOC(TileContext::try_create(frame_context, rows_start, rows_end, columns_start, columns_end, above_partition_context_for_tile, above_non_zero_tokens_view, above_segmentation_ids_for_tile)); - - TRY_READ(m_bit_stream->init_bool(tile_size)); + auto tile_context = DECODER_TRY_ALLOC(TileContext::try_create(frame_context, tile_size, rows_start, rows_end, columns_start, columns_end, above_partition_context_for_tile, above_non_zero_tokens_view, above_segmentation_ids_for_tile)); TRY(decode_tile(tile_context)); - TRY_READ(m_bit_stream->exit_bool()); + TRY_READ(frame_context.bit_stream.discard(tile_size)); } } return {}; @@ -903,6 +902,7 @@ DecoderErrorOr Parser::decode_tile(TileContext& tile_context) TRY(decode_partition(tile_context, row, col, Block_64x64)); } } + TRY_READ(tile_context.decoder.finish_decode()); return {}; } @@ -924,7 +924,7 @@ DecoderErrorOr Parser::decode_partition(TileContext& tile_context, u32 row bool has_cols = (column + half_block_8x8) < tile_context.frame_context.columns(); u32 row_in_tile = row - tile_context.rows_start; u32 column_in_tile = column - tile_context.columns_start; - auto partition = TRY_READ(TreeParser::parse_partition(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, has_rows, has_cols, subsize, num_8x8, tile_context.above_partition_context, tile_context.left_partition_context.span(), row_in_tile, column_in_tile, !tile_context.frame_context.is_inter_predicted())); + auto partition = TRY_READ(TreeParser::parse_partition(tile_context.decoder, *m_probability_tables, *m_syntax_element_counter, has_rows, has_cols, subsize, num_8x8, tile_context.above_partition_context, tile_context.left_partition_context.span(), row_in_tile, column_in_tile, !tile_context.frame_context.is_inter_predicted())); auto child_subsize = subsize_lookup[partition][subsize]; if (child_subsize < Block_8x8 || partition == PartitionNone) { @@ -1000,14 +1000,14 @@ DecoderErrorOr Parser::intra_frame_mode_info(BlockContext& block_context, // FIXME: This if statement is also present in parse_default_intra_mode. The selection of parameters for // the probability table lookup should be inlined here. if (block_context.size >= Block_8x8) { - auto mode = TRY_READ(TreeParser::parse_default_intra_mode(*m_bit_stream, *m_probability_tables, block_context.size, above_context, left_context, block_context.sub_block_prediction_modes, 0, 0)); + auto mode = TRY_READ(TreeParser::parse_default_intra_mode(block_context.decoder, *m_probability_tables, block_context.size, above_context, left_context, block_context.sub_block_prediction_modes, 0, 0)); for (auto& block_sub_mode : block_context.sub_block_prediction_modes) block_sub_mode = mode; } else { auto size_in_sub_blocks = block_context.get_size_in_sub_blocks(); for (auto idy = 0; idy < 2; idy += size_in_sub_blocks.height()) { for (auto idx = 0; idx < 2; idx += size_in_sub_blocks.width()) { - auto sub_mode = TRY_READ(TreeParser::parse_default_intra_mode(*m_bit_stream, *m_probability_tables, block_context.size, above_context, left_context, block_context.sub_block_prediction_modes, idx, idy)); + auto sub_mode = TRY_READ(TreeParser::parse_default_intra_mode(block_context.decoder, *m_probability_tables, block_context.size, above_context, left_context, block_context.sub_block_prediction_modes, idx, idy)); for (auto y = 0; y < size_in_sub_blocks.height(); y++) { for (auto x = 0; x < size_in_sub_blocks.width(); x++) { @@ -1018,14 +1018,14 @@ DecoderErrorOr Parser::intra_frame_mode_info(BlockContext& block_context, } } } - block_context.uv_prediction_mode = TRY_READ(TreeParser::parse_default_uv_mode(*m_bit_stream, *m_probability_tables, block_context.y_prediction_mode())); + block_context.uv_prediction_mode = TRY_READ(TreeParser::parse_default_uv_mode(block_context.decoder, *m_probability_tables, block_context.y_prediction_mode())); return {}; } DecoderErrorOr Parser::set_intra_segment_id(BlockContext& block_context) { if (block_context.frame_context.segmentation_enabled && block_context.frame_context.use_full_segment_id_tree) - block_context.segment_id = TRY_READ(TreeParser::parse_segment_id(*m_bit_stream, block_context.frame_context.full_segment_id_tree_probabilities)); + block_context.segment_id = TRY_READ(TreeParser::parse_segment_id(block_context.decoder, block_context.frame_context.full_segment_id_tree_probabilities)); else block_context.segment_id = 0; return {}; @@ -1035,7 +1035,7 @@ DecoderErrorOr Parser::read_should_skip_residuals(BlockContext& block_cont { if (seg_feature_active(block_context, SEG_LVL_SKIP)) return true; - return TRY_READ(TreeParser::parse_skip(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, above_context, left_context)); + return TRY_READ(TreeParser::parse_skip(block_context.decoder, *m_probability_tables, *m_syntax_element_counter, above_context, left_context)); } bool Parser::seg_feature_active(BlockContext const& block_context, u8 feature) @@ -1047,7 +1047,7 @@ DecoderErrorOr Parser::read_tx_size(BlockContext& block_context, { auto max_tx_size = max_txsize_lookup[block_context.size]; if (allow_select && block_context.frame_context.transform_mode == TransformMode::Select && block_context.size >= Block_8x8) - return (TRY_READ(TreeParser::parse_tx_size(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, max_tx_size, above_context, left_context))); + return (TRY_READ(TreeParser::parse_tx_size(block_context.decoder, *m_probability_tables, *m_syntax_element_counter, max_tx_size, above_context, left_context))); return min(max_tx_size, tx_mode_to_biggest_tx_size[to_underlying(block_context.frame_context.transform_mode)]); } @@ -1077,17 +1077,17 @@ DecoderErrorOr Parser::set_inter_segment_id(BlockContext& block_context) return {}; } if (!block_context.frame_context.use_predicted_segment_id_tree) { - block_context.segment_id = TRY_READ(TreeParser::parse_segment_id(*m_bit_stream, block_context.frame_context.full_segment_id_tree_probabilities)); + block_context.segment_id = TRY_READ(TreeParser::parse_segment_id(block_context.decoder, block_context.frame_context.full_segment_id_tree_probabilities)); return {}; } auto above_segmentation_id = block_context.tile_context.above_segmentation_ids[block_context.row - block_context.tile_context.rows_start]; auto left_segmentation_id = block_context.tile_context.left_segmentation_ids[block_context.column - block_context.tile_context.columns_start]; - auto seg_id_predicted = TRY_READ(TreeParser::parse_segment_id_predicted(*m_bit_stream, block_context.frame_context.predicted_segment_id_tree_probabilities, above_segmentation_id, left_segmentation_id)); + auto seg_id_predicted = TRY_READ(TreeParser::parse_segment_id_predicted(block_context.decoder, block_context.frame_context.predicted_segment_id_tree_probabilities, above_segmentation_id, left_segmentation_id)); if (seg_id_predicted) block_context.segment_id = predicted_segment_id; else - block_context.segment_id = TRY_READ(TreeParser::parse_segment_id(*m_bit_stream, block_context.frame_context.full_segment_id_tree_probabilities)); + block_context.segment_id = TRY_READ(TreeParser::parse_segment_id(block_context.decoder, block_context.frame_context.full_segment_id_tree_probabilities)); // (7.4.1) AboveSegPredContext[ i ] only needs to be set to 0 for i = 0..MiCols-1. // This is taken care of by the slicing in BlockContext. @@ -1117,7 +1117,7 @@ DecoderErrorOr Parser::read_is_inter(BlockContext& block_context, FrameBlo { if (seg_feature_active(block_context, SEG_LVL_REF_FRAME)) return block_context.frame_context.segmentation_features[block_context.segment_id][SEG_LVL_REF_FRAME].value != ReferenceFrameType::None; - return TRY_READ(TreeParser::parse_block_is_inter_predicted(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, above_context, left_context)); + return TRY_READ(TreeParser::parse_block_is_inter_predicted(block_context.decoder, *m_probability_tables, *m_syntax_element_counter, above_context, left_context)); } DecoderErrorOr Parser::intra_block_mode_info(BlockContext& block_context) @@ -1126,14 +1126,14 @@ DecoderErrorOr Parser::intra_block_mode_info(BlockContext& block_context) VERIFY(!block_context.is_inter_predicted()); auto& sub_modes = block_context.sub_block_prediction_modes; if (block_context.size >= Block_8x8) { - auto mode = TRY_READ(TreeParser::parse_intra_mode(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, block_context.size)); + auto mode = TRY_READ(TreeParser::parse_intra_mode(block_context.decoder, *m_probability_tables, *m_syntax_element_counter, block_context.size)); for (auto& block_sub_mode : sub_modes) block_sub_mode = mode; } else { auto size_in_sub_blocks = block_context.get_size_in_sub_blocks(); for (auto idy = 0; idy < 2; idy += size_in_sub_blocks.height()) { for (auto idx = 0; idx < 2; idx += size_in_sub_blocks.width()) { - auto sub_intra_mode = TRY_READ(TreeParser::parse_sub_intra_mode(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter)); + auto sub_intra_mode = TRY_READ(TreeParser::parse_sub_intra_mode(block_context.decoder, *m_probability_tables, *m_syntax_element_counter)); for (auto y = 0; y < size_in_sub_blocks.height(); y++) { for (auto x = 0; x < size_in_sub_blocks.width(); x++) sub_modes[(idy + y) * 2 + idx + x] = sub_intra_mode; @@ -1141,7 +1141,7 @@ DecoderErrorOr Parser::intra_block_mode_info(BlockContext& block_context) } } } - block_context.uv_prediction_mode = TRY_READ(TreeParser::parse_uv_mode(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, block_context.y_prediction_mode())); + block_context.uv_prediction_mode = TRY_READ(TreeParser::parse_uv_mode(block_context.decoder, *m_probability_tables, *m_syntax_element_counter, block_context.y_prediction_mode())); return {}; } @@ -1163,17 +1163,17 @@ DecoderErrorOr Parser::inter_block_mode_info(BlockContext& block_context, if (seg_feature_active(block_context, SEG_LVL_SKIP)) { block_context.y_prediction_mode() = PredictionMode::ZeroMv; } else if (block_context.size >= Block_8x8) { - block_context.y_prediction_mode() = TRY_READ(TreeParser::parse_inter_mode(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, block_context.mode_context[block_context.reference_frame_types.primary])); + block_context.y_prediction_mode() = TRY_READ(TreeParser::parse_inter_mode(block_context.decoder, *m_probability_tables, *m_syntax_element_counter, block_context.mode_context[block_context.reference_frame_types.primary])); } if (block_context.frame_context.interpolation_filter == Switchable) - block_context.interpolation_filter = TRY_READ(TreeParser::parse_interpolation_filter(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, above_context, left_context)); + block_context.interpolation_filter = TRY_READ(TreeParser::parse_interpolation_filter(block_context.decoder, *m_probability_tables, *m_syntax_element_counter, above_context, left_context)); else block_context.interpolation_filter = block_context.frame_context.interpolation_filter; if (block_context.size < Block_8x8) { auto size_in_sub_blocks = block_context.get_size_in_sub_blocks(); for (auto idy = 0; idy < 2; idy += size_in_sub_blocks.height()) { for (auto idx = 0; idx < 2; idx += size_in_sub_blocks.width()) { - block_context.y_prediction_mode() = TRY_READ(TreeParser::parse_inter_mode(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, block_context.mode_context[block_context.reference_frame_types.primary])); + block_context.y_prediction_mode() = TRY_READ(TreeParser::parse_inter_mode(block_context.decoder, *m_probability_tables, *m_syntax_element_counter, block_context.mode_context[block_context.reference_frame_types.primary])); if (block_context.y_prediction_mode() == PredictionMode::NearestMv || block_context.y_prediction_mode() == PredictionMode::NearMv) { select_best_sub_block_reference_motion_vectors(block_context, motion_vector_candidates, idy * 2 + idx, ReferenceIndex::Primary); if (block_context.is_compound()) @@ -1206,7 +1206,7 @@ DecoderErrorOr Parser::read_ref_frames(BlockContext& block_context, FrameB ReferenceMode compound_mode = block_context.frame_context.reference_mode; auto fixed_reference = block_context.frame_context.fixed_reference_type; if (compound_mode == ReferenceModeSelect) - compound_mode = TRY_READ(TreeParser::parse_comp_mode(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, fixed_reference, above_context, left_context)); + compound_mode = TRY_READ(TreeParser::parse_comp_mode(block_context.decoder, *m_probability_tables, *m_syntax_element_counter, fixed_reference, above_context, left_context)); if (compound_mode == CompoundReference) { auto variable_references = block_context.frame_context.variable_reference_types; @@ -1215,7 +1215,7 @@ DecoderErrorOr Parser::read_ref_frames(BlockContext& block_context, FrameB if (block_context.frame_context.reference_frame_sign_biases[fixed_reference]) swap(fixed_reference_index, variable_reference_index); - auto variable_reference_selection = TRY_READ(TreeParser::parse_comp_ref(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, fixed_reference, variable_references, variable_reference_index, above_context, left_context)); + auto variable_reference_selection = TRY_READ(TreeParser::parse_comp_ref(block_context.decoder, *m_probability_tables, *m_syntax_element_counter, fixed_reference, variable_references, variable_reference_index, above_context, left_context)); block_context.reference_frame_types[fixed_reference_index] = fixed_reference; block_context.reference_frame_types[variable_reference_index] = variable_references[variable_reference_selection]; @@ -1224,9 +1224,9 @@ DecoderErrorOr Parser::read_ref_frames(BlockContext& block_context, FrameB // FIXME: Maybe consolidate this into a tree. Context is different between part 1 and 2 but still, it would look nice here. ReferenceFrameType primary_type = ReferenceFrameType::LastFrame; - auto single_ref_p1 = TRY_READ(TreeParser::parse_single_ref_part_1(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, above_context, left_context)); + auto single_ref_p1 = TRY_READ(TreeParser::parse_single_ref_part_1(block_context.decoder, *m_probability_tables, *m_syntax_element_counter, above_context, left_context)); if (single_ref_p1) { - auto single_ref_p2 = TRY_READ(TreeParser::parse_single_ref_part_2(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, above_context, left_context)); + auto single_ref_p2 = TRY_READ(TreeParser::parse_single_ref_part_2(block_context.decoder, *m_probability_tables, *m_syntax_element_counter, above_context, left_context)); primary_type = single_ref_p2 ? ReferenceFrameType::AltRefFrame : ReferenceFrameType::GoldenFrame; } block_context.reference_frame_types = { primary_type, ReferenceFrameType::None }; @@ -1271,35 +1271,35 @@ DecoderErrorOr Parser::read_motion_vector(BlockContext const& bloc { auto use_high_precision = block_context.frame_context.high_precision_motion_vectors_allowed && should_use_high_precision_motion_vector(candidates[reference_index].best_vector); MotionVector delta_vector; - auto joint = TRY_READ(TreeParser::parse_motion_vector_joint(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter)); + auto joint = TRY_READ(TreeParser::parse_motion_vector_joint(block_context.decoder, *m_probability_tables, *m_syntax_element_counter)); if ((joint & MotionVectorNonZeroRow) != 0) - delta_vector.set_row(TRY(read_single_motion_vector_component(0, use_high_precision))); + delta_vector.set_row(TRY(read_single_motion_vector_component(block_context.decoder, 0, use_high_precision))); if ((joint & MotionVectorNonZeroColumn) != 0) - delta_vector.set_column(TRY(read_single_motion_vector_component(1, use_high_precision))); + delta_vector.set_column(TRY(read_single_motion_vector_component(block_context.decoder, 1, use_high_precision))); return candidates[reference_index].best_vector + delta_vector; } // read_mv_component( comp ) in the spec. -DecoderErrorOr Parser::read_single_motion_vector_component(u8 component, bool use_high_precision) +DecoderErrorOr Parser::read_single_motion_vector_component(BooleanDecoder& decoder, u8 component, bool use_high_precision) { - auto mv_sign = TRY_READ(TreeParser::parse_motion_vector_sign(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, component)); - auto mv_class = TRY_READ(TreeParser::parse_motion_vector_class(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, component)); + auto mv_sign = TRY_READ(TreeParser::parse_motion_vector_sign(decoder, *m_probability_tables, *m_syntax_element_counter, component)); + auto mv_class = TRY_READ(TreeParser::parse_motion_vector_class(decoder, *m_probability_tables, *m_syntax_element_counter, component)); u32 magnitude; if (mv_class == MvClass0) { - auto mv_class0_bit = TRY_READ(TreeParser::parse_motion_vector_class0_bit(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, component)); - auto mv_class0_fr = TRY_READ(TreeParser::parse_motion_vector_class0_fr(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, component, mv_class0_bit)); - auto mv_class0_hp = TRY_READ(TreeParser::parse_motion_vector_class0_hp(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, component, use_high_precision)); + auto mv_class0_bit = TRY_READ(TreeParser::parse_motion_vector_class0_bit(decoder, *m_probability_tables, *m_syntax_element_counter, component)); + auto mv_class0_fr = TRY_READ(TreeParser::parse_motion_vector_class0_fr(decoder, *m_probability_tables, *m_syntax_element_counter, component, mv_class0_bit)); + auto mv_class0_hp = TRY_READ(TreeParser::parse_motion_vector_class0_hp(decoder, *m_probability_tables, *m_syntax_element_counter, component, use_high_precision)); magnitude = ((mv_class0_bit << 3) | (mv_class0_fr << 1) | mv_class0_hp) + 1; } else { u32 bits = 0; for (u8 i = 0; i < mv_class; i++) { - auto mv_bit = TRY_READ(TreeParser::parse_motion_vector_bit(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, component, i)); + auto mv_bit = TRY_READ(TreeParser::parse_motion_vector_bit(decoder, *m_probability_tables, *m_syntax_element_counter, component, i)); bits |= mv_bit << i; } magnitude = CLASS0_SIZE << (mv_class + 2); - auto mv_fr = TRY_READ(TreeParser::parse_motion_vector_fr(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, component)); - auto mv_hp = TRY_READ(TreeParser::parse_motion_vector_hp(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, component, use_high_precision)); + auto mv_fr = TRY_READ(TreeParser::parse_motion_vector_fr(decoder, *m_probability_tables, *m_syntax_element_counter, component)); + auto mv_hp = TRY_READ(TreeParser::parse_motion_vector_hp(decoder, *m_probability_tables, *m_syntax_element_counter, component, use_high_precision)); magnitude += ((bits << 3) | (mv_fr << 1) | mv_hp) + 1; } return (mv_sign ? -1 : 1) * static_cast(magnitude); @@ -1449,10 +1449,10 @@ DecoderErrorOr Parser::tokens(BlockContext& block_context, size_t plane, u else tokens_context = TreeParser::get_context_for_other_tokens(token_cache, transform_size, transform_set, plane, token_position, block_context.is_inter_predicted(), band); - if (check_for_more_coefficients && !TRY_READ(TreeParser::parse_more_coefficients(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, tokens_context))) + if (check_for_more_coefficients && !TRY_READ(TreeParser::parse_more_coefficients(block_context.decoder, *m_probability_tables, *m_syntax_element_counter, tokens_context))) break; - auto token = TRY_READ(TreeParser::parse_token(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, tokens_context)); + auto token = TRY_READ(TreeParser::parse_token(block_context.decoder, *m_probability_tables, *m_syntax_element_counter, tokens_context)); token_cache[token_position] = energy_class[token]; i32 coef; @@ -1460,7 +1460,7 @@ DecoderErrorOr Parser::tokens(BlockContext& block_context, size_t plane, u coef = 0; check_for_more_coefficients = false; } else { - coef = TRY(read_coef(block_context.frame_context.color_config.bit_depth, token)); + coef = TRY(read_coef(block_context.decoder, block_context.frame_context.color_config.bit_depth, token)); check_for_more_coefficients = true; } block_context.residual_tokens[token_position] = coef; @@ -1469,22 +1469,22 @@ DecoderErrorOr Parser::tokens(BlockContext& block_context, size_t plane, u return coef_index > 0; } -DecoderErrorOr Parser::read_coef(u8 bit_depth, Token token) +DecoderErrorOr Parser::read_coef(BooleanDecoder& decoder, u8 bit_depth, Token token) { auto cat = extra_bits[token][0]; auto num_extra = extra_bits[token][1]; i32 coef = extra_bits[token][2]; if (token == DctValCat6) { for (size_t e = 0; e < (u8)(bit_depth - 8); e++) { - auto high_bit = TRY_READ(m_bit_stream->read_bool(255)); + auto high_bit = TRY_READ(decoder.read_bool(255)); coef += high_bit << (5 + bit_depth - e); } } for (size_t e = 0; e < num_extra; e++) { - auto coef_bit = TRY_READ(m_bit_stream->read_bool(cat_probs[cat][e])); + auto coef_bit = TRY_READ(decoder.read_bool(cat_probs[cat][e])); coef += coef_bit << (num_extra - 1 - e); } - bool sign_bit = TRY_READ(m_bit_stream->read_literal(1)); + bool sign_bit = TRY_READ(decoder.read_literal(1)); coef = sign_bit ? -coef : coef; return coef; } diff --git a/Userland/Libraries/LibVideo/VP9/Parser.h b/Userland/Libraries/LibVideo/VP9/Parser.h index 3a9f0cdcd2..ddb3c5603e 100644 --- a/Userland/Libraries/LibVideo/VP9/Parser.h +++ b/Userland/Libraries/LibVideo/VP9/Parser.h @@ -14,7 +14,6 @@ #include #include -#include "BitStream.h" #include "ContextStorage.h" #include "LookupTables.h" #include "MotionVector.h" @@ -45,48 +44,48 @@ private: * See also section 5.26. */ Vector parse_superframe_sizes(ReadonlyBytes); - DecoderErrorOr read_video_full_range_flag(); + DecoderErrorOr read_video_full_range_flag(BigEndianInputBitStream&); /* (6.1) Frame Syntax */ bool trailing_bits(); DecoderErrorOr refresh_probs(FrameContext const&); /* (6.2) Uncompressed Header Syntax */ - DecoderErrorOr uncompressed_header(); - DecoderErrorOr frame_sync_code(); - DecoderErrorOr parse_color_config(FrameContext const&); - DecoderErrorOr> parse_frame_size(); - DecoderErrorOr> parse_frame_size_with_refs(Array const& reference_indices); - DecoderErrorOr> parse_render_size(Gfx::Size frame_size); + DecoderErrorOr uncompressed_header(FrameContext& frame_context); + DecoderErrorOr frame_sync_code(BigEndianInputBitStream&); + DecoderErrorOr parse_color_config(BigEndianInputBitStream&, u8 profile); + DecoderErrorOr> parse_frame_size(BigEndianInputBitStream&); + DecoderErrorOr> parse_frame_size_with_refs(BigEndianInputBitStream&, Array const& reference_indices); + DecoderErrorOr> parse_render_size(BigEndianInputBitStream&, Gfx::Size frame_size); DecoderErrorOr compute_image_size(FrameContext&); - DecoderErrorOr read_interpolation_filter(); + DecoderErrorOr read_interpolation_filter(BigEndianInputBitStream&); DecoderErrorOr loop_filter_params(FrameContext&); DecoderErrorOr quantization_params(FrameContext&); - DecoderErrorOr read_delta_q(); + DecoderErrorOr read_delta_q(BigEndianInputBitStream&); DecoderErrorOr segmentation_params(FrameContext&); - DecoderErrorOr read_prob(); + DecoderErrorOr read_prob(BigEndianInputBitStream&); DecoderErrorOr parse_tile_counts(FrameContext&); void setup_past_independence(); /* (6.3) Compressed Header Syntax */ DecoderErrorOr compressed_header(FrameContext&); - DecoderErrorOr read_tx_mode(FrameContext const&); - DecoderErrorOr tx_mode_probs(); - DecoderErrorOr diff_update_prob(u8 prob); - DecoderErrorOr decode_term_subexp(); + DecoderErrorOr read_tx_mode(BooleanDecoder&, FrameContext const&); + DecoderErrorOr tx_mode_probs(BooleanDecoder&); + DecoderErrorOr diff_update_prob(BooleanDecoder&, u8 prob); + DecoderErrorOr decode_term_subexp(BooleanDecoder&); u8 inv_remap_prob(u8 delta_prob, u8 prob); u8 inv_recenter_nonneg(u8 v, u8 m); - DecoderErrorOr read_coef_probs(TransformMode); - DecoderErrorOr read_skip_prob(); - DecoderErrorOr read_inter_mode_probs(); - DecoderErrorOr read_interp_filter_probs(); - DecoderErrorOr read_is_inter_probs(); - DecoderErrorOr frame_reference_mode(FrameContext&); - DecoderErrorOr frame_reference_mode_probs(FrameContext const&); - DecoderErrorOr read_y_mode_probs(); - DecoderErrorOr read_partition_probs(); - DecoderErrorOr mv_probs(FrameContext const&); - DecoderErrorOr update_mv_prob(u8 prob); + DecoderErrorOr read_coef_probs(BooleanDecoder&, TransformMode); + DecoderErrorOr read_skip_prob(BooleanDecoder&); + DecoderErrorOr read_inter_mode_probs(BooleanDecoder&); + DecoderErrorOr read_interp_filter_probs(BooleanDecoder&); + DecoderErrorOr read_is_inter_probs(BooleanDecoder&); + DecoderErrorOr frame_reference_mode(FrameContext&, BooleanDecoder&); + DecoderErrorOr frame_reference_mode_probs(BooleanDecoder&, FrameContext const&); + DecoderErrorOr read_y_mode_probs(BooleanDecoder&); + DecoderErrorOr read_partition_probs(BooleanDecoder&); + DecoderErrorOr mv_probs(BooleanDecoder&, FrameContext const&); + DecoderErrorOr update_mv_prob(BooleanDecoder&, u8 prob); /* (6.4) Decode Tiles Syntax */ DecoderErrorOr decode_tiles(FrameContext&); @@ -109,10 +108,10 @@ private: DecoderErrorOr read_ref_frames(BlockContext&, FrameBlockContext above_context, FrameBlockContext left_context); DecoderErrorOr get_motion_vector(BlockContext const&, BlockMotionVectorCandidates const&); DecoderErrorOr read_motion_vector(BlockContext const&, BlockMotionVectorCandidates const&, ReferenceIndex); - DecoderErrorOr read_single_motion_vector_component(u8 component, bool use_high_precision); + DecoderErrorOr read_single_motion_vector_component(BooleanDecoder&, u8 component, bool use_high_precision); DecoderErrorOr residual(BlockContext&, bool has_block_above, bool has_block_left); DecoderErrorOr tokens(BlockContext&, size_t plane, u32 x, u32 y, TransformSize, TransformSet, Array token_cache); - DecoderErrorOr read_coef(u8 bit_depth, Token token); + DecoderErrorOr 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 m_reusable_frame_block_contexts; Vector2D m_previous_block_contexts; - OwnPtr m_bit_stream; OwnPtr m_probability_tables; OwnPtr m_syntax_element_counter; Decoder& m_decoder; diff --git a/Userland/Libraries/LibVideo/VP9/TreeParser.cpp b/Userland/Libraries/LibVideo/VP9/TreeParser.cpp index 83be1d389b..2e62e27468 100644 --- a/Userland/Libraries/LibVideo/VP9/TreeParser.cpp +++ b/Userland/Libraries/LibVideo/VP9/TreeParser.cpp @@ -51,7 +51,7 @@ private: }; template -inline ErrorOr parse_tree(BitStream& bit_stream, TreeSelection tree_selection, Function const& probability_getter) +inline ErrorOr parse_tree(BooleanDecoder& decoder, TreeSelection tree_selection, Function const& probability_getter) { // 9.3.3: The tree decoding function. if (tree_selection.is_single_value()) @@ -61,13 +61,13 @@ inline ErrorOr 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(-n); } -ErrorOr 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 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 TreeParser::parse_partition(BitStream& bit_stream, Probabilit return probabilities[2]; }; - auto value = TRY(parse_tree(bit_stream, tree, probability_getter)); + auto value = TRY(parse_tree(decoder, tree, probability_getter)); counter.m_counts_partition[context][value]++; return value; } -ErrorOr TreeParser::parse_default_intra_mode(BitStream& bit_stream, ProbabilityTables const& probability_table, BlockSubsize mi_size, FrameBlockContext above, FrameBlockContext left, Array const& block_sub_modes, u8 index_x, u8 index_y) +ErrorOr TreeParser::parse_default_intra_mode(BooleanDecoder& decoder, ProbabilityTables const& probability_table, BlockSubsize mi_size, FrameBlockContext above, FrameBlockContext left, Array 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 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(bit_stream, tree, [&](u8 node) { return probabilities[node]; })); + auto value = TRY(parse_tree(decoder, tree, [&](u8 node) { return probabilities[node]; })); // Default intra mode is not counted. return value; } -ErrorOr TreeParser::parse_default_uv_mode(BitStream& bit_stream, ProbabilityTables const& probability_table, PredictionMode y_mode) +ErrorOr 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 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(bit_stream, tree, [&](u8 node) { return probabilities[node]; })); + auto value = TRY(parse_tree(decoder, tree, [&](u8 node) { return probabilities[node]; })); // Default UV mode is not counted. return value; } -ErrorOr TreeParser::parse_intra_mode(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, BlockSubsize mi_size) +ErrorOr 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 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(bit_stream, tree, [&](u8 node) { return probabilities[node]; })); + auto value = TRY(parse_tree(decoder, tree, [&](u8 node) { return probabilities[node]; })); counter.m_counts_intra_mode[context][to_underlying(value)]++; return value; } -ErrorOr TreeParser::parse_sub_intra_mode(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter) +ErrorOr TreeParser::parse_sub_intra_mode(BooleanDecoder& decoder, ProbabilityTables const& probability_table, SyntaxElementCounter& counter) { // Tree TreeSelection tree = { intra_mode_tree }; @@ -170,12 +170,12 @@ ErrorOr TreeParser::parse_sub_intra_mode(BitStream& bit_stream, // Probabilities u8 const* probabilities = probability_table.y_mode_probs()[0]; - auto value = TRY(parse_tree(bit_stream, tree, [&](u8 node) { return probabilities[node]; })); + auto value = TRY(parse_tree(decoder, tree, [&](u8 node) { return probabilities[node]; })); counter.m_counts_intra_mode[0][to_underlying(value)]++; return value; } -ErrorOr TreeParser::parse_uv_mode(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, PredictionMode y_mode) +ErrorOr 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 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(bit_stream, tree, [&](u8 node) { return probabilities[node]; })); + auto value = TRY(parse_tree(decoder, tree, [&](u8 node) { return probabilities[node]; })); counter.m_counts_uv_mode[to_underlying(y_mode)][to_underlying(value)]++; return value; } -ErrorOr TreeParser::parse_segment_id(BitStream& bit_stream, Array const& probabilities) +ErrorOr TreeParser::parse_segment_id(BooleanDecoder& decoder, Array const& probabilities) { - auto value = TRY(parse_tree(bit_stream, { segment_tree }, [&](u8 node) { return probabilities[node]; })); + auto value = TRY(parse_tree(decoder, { segment_tree }, [&](u8 node) { return probabilities[node]; })); // Segment ID is not counted. return value; } -ErrorOr TreeParser::parse_segment_id_predicted(BitStream& bit_stream, Array const& probabilities, u8 above_seg_pred_context, u8 left_seg_pred_context) +ErrorOr TreeParser::parse_segment_id_predicted(BooleanDecoder& decoder, Array 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(bit_stream, { binary_tree }, [&](u8) { return probabilities[context]; })); + auto value = TRY(parse_tree(decoder, { binary_tree }, [&](u8) { return probabilities[context]; })); // Segment ID prediction is not counted. return value; } -ErrorOr TreeParser::parse_inter_mode(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, u8 mode_context_for_ref_frame_0) +ErrorOr 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 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(bit_stream, tree, [&](u8 node) { return probabilities[node]; })); + auto value = TRY(parse_tree(decoder, tree, [&](u8 node) { return probabilities[node]; })); counter.m_counts_inter_mode[mode_context_for_ref_frame_0][value]++; return static_cast(value + to_underlying(PredictionMode::NearestMv)); } -ErrorOr TreeParser::parse_interpolation_filter(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, FrameBlockContext above, FrameBlockContext left) +ErrorOr 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 TreeParser::parse_interpolation_filter(BitStream& b context = above_interp; u8 const* probabilities = probability_table.interp_filter_probs()[context]; - auto value = TRY(parse_tree(bit_stream, tree, [&](u8 node) { return probabilities[node]; })); + auto value = TRY(parse_tree(decoder, tree, [&](u8 node) { return probabilities[node]; })); counter.m_counts_interp_filter[context][to_underlying(value)]++; return value; } -ErrorOr TreeParser::parse_skip(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, FrameBlockContext above, FrameBlockContext left) +ErrorOr TreeParser::parse_skip(BooleanDecoder& decoder, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, FrameBlockContext above, FrameBlockContext left) { // Probabilities u8 context = 0; @@ -249,12 +249,12 @@ ErrorOr TreeParser::parse_skip(BitStream& bit_stream, ProbabilityTables co context += static_cast(left.skip_coefficients); u8 probability = probability_table.skip_prob()[context]; - auto value = TRY(parse_tree(bit_stream, { binary_tree }, [&](u8) { return probability; })); + auto value = TRY(parse_tree(decoder, { binary_tree }, [&](u8) { return probability; })); counter.m_counts_skip[context][value]++; return value; } -ErrorOr TreeParser::parse_tx_size(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, TransformSize max_tx_size, FrameBlockContext above, FrameBlockContext left) +ErrorOr 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 TreeParser::parse_tx_size(BitStream& bit_stream, Probabil u8 const* probabilities = probability_table.tx_probs()[max_tx_size][context]; - auto value = TRY(parse_tree(bit_stream, tree, [&](u8 node) { return probabilities[node]; })); + auto value = TRY(parse_tree(decoder, tree, [&](u8 node) { return probabilities[node]; })); counter.m_counts_tx_size[max_tx_size][context][value]++; return value; } -ErrorOr TreeParser::parse_block_is_inter_predicted(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, FrameBlockContext above, FrameBlockContext left) +ErrorOr 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 TreeParser::parse_block_is_inter_predicted(BitStream& bit_stream, context = 2 * static_cast(above.is_available ? above.is_intra_predicted() : left.is_intra_predicted()); u8 probability = probability_table.is_inter_prob()[context]; - auto value = TRY(parse_tree(bit_stream, { binary_tree }, [&](u8) { return probability; })); + auto value = TRY(parse_tree(decoder, { binary_tree }, [&](u8) { return probability; })); counter.m_counts_is_inter[context][value]++; return value; } -ErrorOr TreeParser::parse_comp_mode(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, ReferenceFrameType comp_fixed_ref, FrameBlockContext above, FrameBlockContext left) +ErrorOr 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 TreeParser::parse_comp_mode(BitStream& bit_stream, Probab } u8 probability = probability_table.comp_mode_prob()[context]; - auto value = TRY(parse_tree(bit_stream, { binary_tree }, [&](u8) { return probability; })); + auto value = TRY(parse_tree(decoder, { binary_tree }, [&](u8) { return probability; })); counter.m_counts_comp_mode[context][value]++; return value; } -ErrorOr 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 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 TreeParser::parse_comp_ref(BitStream& bit_stream, Probab u8 probability = probability_table.comp_ref_prob()[context]; - auto value = TRY(parse_tree(bit_stream, { binary_tree }, [&](u8) { return probability; })); + auto value = TRY(parse_tree(decoder, { binary_tree }, [&](u8) { return probability; })); counter.m_counts_comp_ref[context][to_underlying(value)]++; return value; } -ErrorOr TreeParser::parse_single_ref_part_1(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, FrameBlockContext above, FrameBlockContext left) +ErrorOr 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 TreeParser::parse_single_ref_part_1(BitStream& bit_stream, Probabi } u8 probability = probability_table.single_ref_prob()[context][0]; - auto value = TRY(parse_tree(bit_stream, { binary_tree }, [&](u8) { return probability; })); + auto value = TRY(parse_tree(decoder, { binary_tree }, [&](u8) { return probability; })); counter.m_counts_single_ref[context][0][value]++; return value; } -ErrorOr TreeParser::parse_single_ref_part_2(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, FrameBlockContext above, FrameBlockContext left) +ErrorOr 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 TreeParser::parse_single_ref_part_2(BitStream& bit_stream, Probabi } u8 probability = probability_table.single_ref_prob()[context][1]; - auto value = TRY(parse_tree(bit_stream, { binary_tree }, [&](u8) { return probability; })); + auto value = TRY(parse_tree(decoder, { binary_tree }, [&](u8) { return probability; })); counter.m_counts_single_ref[context][1][value]++; return value; } -ErrorOr TreeParser::parse_motion_vector_joint(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter) +ErrorOr TreeParser::parse_motion_vector_joint(BooleanDecoder& decoder, ProbabilityTables const& probability_table, SyntaxElementCounter& counter) { - auto value = TRY(parse_tree(bit_stream, { mv_joint_tree }, [&](u8 node) { return probability_table.mv_joint_probs()[node]; })); + auto value = TRY(parse_tree(decoder, { mv_joint_tree }, [&](u8 node) { return probability_table.mv_joint_probs()[node]; })); counter.m_counts_mv_joint[value]++; return value; } -ErrorOr TreeParser::parse_motion_vector_sign(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, u8 component) +ErrorOr TreeParser::parse_motion_vector_sign(BooleanDecoder& decoder, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, u8 component) { - auto value = TRY(parse_tree(bit_stream, { binary_tree }, [&](u8) { return probability_table.mv_sign_prob()[component]; })); + auto value = TRY(parse_tree(decoder, { binary_tree }, [&](u8) { return probability_table.mv_sign_prob()[component]; })); counter.m_counts_mv_sign[component][value]++; return value; } -ErrorOr TreeParser::parse_motion_vector_class(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, u8 component) +ErrorOr 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(bit_stream, { mv_class_tree }, [&](u8 node) { return probability_table.mv_class_probs()[component][node]; })); + auto value = TRY(parse_tree(decoder, { mv_class_tree }, [&](u8 node) { return probability_table.mv_class_probs()[component][node]; })); counter.m_counts_mv_class[component][value]++; return value; } -ErrorOr TreeParser::parse_motion_vector_class0_bit(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, u8 component) +ErrorOr TreeParser::parse_motion_vector_class0_bit(BooleanDecoder& decoder, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, u8 component) { - auto value = TRY(parse_tree(bit_stream, { binary_tree }, [&](u8) { return probability_table.mv_class0_bit_prob()[component]; })); + auto value = TRY(parse_tree(decoder, { binary_tree }, [&](u8) { return probability_table.mv_class0_bit_prob()[component]; })); counter.m_counts_mv_class0_bit[component][value]++; return value; } -ErrorOr TreeParser::parse_motion_vector_class0_fr(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, u8 component, bool class_0_bit) +ErrorOr 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(bit_stream, { mv_fr_tree }, [&](u8 node) { return probability_table.mv_class0_fr_probs()[component][class_0_bit][node]; })); + auto value = TRY(parse_tree(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 TreeParser::parse_motion_vector_class0_hp(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, u8 component, bool use_hp) +ErrorOr 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(bit_stream, tree, [&](u8) { return probability_table.mv_class0_hp_prob()[component]; })); + auto value = TRY(parse_tree(decoder, tree, [&](u8) { return probability_table.mv_class0_hp_prob()[component]; })); counter.m_counts_mv_class0_hp[component][value]++; return value; } -ErrorOr TreeParser::parse_motion_vector_bit(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, u8 component, u8 bit_index) +ErrorOr TreeParser::parse_motion_vector_bit(BooleanDecoder& decoder, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, u8 component, u8 bit_index) { - auto value = TRY(parse_tree(bit_stream, { binary_tree }, [&](u8) { return probability_table.mv_bits_prob()[component][bit_index]; })); + auto value = TRY(parse_tree(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 TreeParser::parse_motion_vector_fr(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, u8 component) +ErrorOr TreeParser::parse_motion_vector_fr(BooleanDecoder& decoder, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, u8 component) { - auto value = TRY(parse_tree(bit_stream, { mv_fr_tree }, [&](u8 node) { return probability_table.mv_fr_probs()[component][node]; })); + auto value = TRY(parse_tree(decoder, { mv_fr_tree }, [&](u8 node) { return probability_table.mv_fr_probs()[component][node]; })); counter.m_counts_mv_fr[component][value]++; return value; } -ErrorOr TreeParser::parse_motion_vector_hp(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, u8 component, bool use_hp) +ErrorOr 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(bit_stream, tree, [&](u8) { return probability_table.mv_hp_prob()[component]; })); + auto value = TRY(parse_tree(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 token_cac return TokensContext { transform_size, plane > 0, is_inter, band, context }; } -ErrorOr TreeParser::parse_more_coefficients(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, TokensContext const& context) +ErrorOr 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(bit_stream, { binary_tree }, [&](u8) { return probability; })); + auto value = TRY(parse_tree(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 TreeParser::parse_token(BitStream& bit_stream, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, TokensContext const& context) +ErrorOr TreeParser::parse_token(BooleanDecoder& decoder, ProbabilityTables const& probability_table, SyntaxElementCounter& counter, TokensContext const& context) { Function 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 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(bit_stream, { token_tree }, probability_getter)); + auto value = TRY(parse_tree(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; } diff --git a/Userland/Libraries/LibVideo/VP9/TreeParser.h b/Userland/Libraries/LibVideo/VP9/TreeParser.h index 93457747bb..8b0c684ae7 100644 --- a/Userland/Libraries/LibVideo/VP9/TreeParser.h +++ b/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 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 parse_default_intra_mode(BitStream&, ProbabilityTables const&, BlockSubsize mi_size, FrameBlockContext above, FrameBlockContext left, Array const& block_sub_modes, u8 index_x, u8 index_y); - static ErrorOr parse_default_uv_mode(BitStream&, ProbabilityTables const&, PredictionMode y_mode); - static ErrorOr parse_intra_mode(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, BlockSubsize mi_size); - static ErrorOr parse_sub_intra_mode(BitStream&, ProbabilityTables const&, SyntaxElementCounter&); - static ErrorOr parse_uv_mode(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, PredictionMode y_mode); - static ErrorOr parse_segment_id(BitStream&, Array const& probabilities); - static ErrorOr parse_segment_id_predicted(BitStream&, Array const& probabilities, u8 above_seg_pred_context, u8 left_seg_pred_context); - static ErrorOr parse_inter_mode(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, u8 mode_context_for_ref_frame_0); - static ErrorOr parse_interpolation_filter(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, FrameBlockContext above, FrameBlockContext left); - static ErrorOr parse_skip(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, FrameBlockContext above, FrameBlockContext left); - static ErrorOr parse_tx_size(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, TransformSize max_tx_size, FrameBlockContext above, FrameBlockContext left); - static ErrorOr parse_block_is_inter_predicted(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, FrameBlockContext above, FrameBlockContext left); - static ErrorOr parse_comp_mode(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, ReferenceFrameType comp_fixed_ref, FrameBlockContext above, FrameBlockContext left); - static ErrorOr 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 parse_single_ref_part_1(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, FrameBlockContext above, FrameBlockContext left); - static ErrorOr parse_single_ref_part_2(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, FrameBlockContext above, FrameBlockContext left); + static ErrorOr 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 parse_default_intra_mode(BooleanDecoder&, ProbabilityTables const&, BlockSubsize mi_size, FrameBlockContext above, FrameBlockContext left, Array const& block_sub_modes, u8 index_x, u8 index_y); + static ErrorOr parse_default_uv_mode(BooleanDecoder&, ProbabilityTables const&, PredictionMode y_mode); + static ErrorOr parse_intra_mode(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, BlockSubsize mi_size); + static ErrorOr parse_sub_intra_mode(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&); + static ErrorOr parse_uv_mode(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, PredictionMode y_mode); + static ErrorOr parse_segment_id(BooleanDecoder&, Array const& probabilities); + static ErrorOr parse_segment_id_predicted(BooleanDecoder&, Array const& probabilities, u8 above_seg_pred_context, u8 left_seg_pred_context); + static ErrorOr parse_inter_mode(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, u8 mode_context_for_ref_frame_0); + static ErrorOr parse_interpolation_filter(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, FrameBlockContext above, FrameBlockContext left); + static ErrorOr parse_skip(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, FrameBlockContext above, FrameBlockContext left); + static ErrorOr parse_tx_size(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, TransformSize max_tx_size, FrameBlockContext above, FrameBlockContext left); + static ErrorOr parse_block_is_inter_predicted(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, FrameBlockContext above, FrameBlockContext left); + static ErrorOr parse_comp_mode(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, ReferenceFrameType comp_fixed_ref, FrameBlockContext above, FrameBlockContext left); + static ErrorOr 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 parse_single_ref_part_1(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, FrameBlockContext above, FrameBlockContext left); + static ErrorOr parse_single_ref_part_2(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, FrameBlockContext above, FrameBlockContext left); - static ErrorOr parse_motion_vector_joint(BitStream&, ProbabilityTables const&, SyntaxElementCounter&); - static ErrorOr parse_motion_vector_sign(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, u8 component); - static ErrorOr parse_motion_vector_class(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, u8 component); - static ErrorOr parse_motion_vector_class0_bit(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, u8 component); - static ErrorOr parse_motion_vector_class0_fr(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, u8 component, bool class_0_bit); - static ErrorOr parse_motion_vector_class0_hp(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, u8 component, bool use_hp); - static ErrorOr parse_motion_vector_bit(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, u8 component, u8 bit_index); - static ErrorOr parse_motion_vector_fr(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, u8 component); - static ErrorOr parse_motion_vector_hp(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, u8 component, bool use_hp); + static ErrorOr parse_motion_vector_joint(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&); + static ErrorOr parse_motion_vector_sign(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, u8 component); + static ErrorOr parse_motion_vector_class(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, u8 component); + static ErrorOr parse_motion_vector_class0_bit(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, u8 component); + static ErrorOr parse_motion_vector_class0_fr(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, u8 component, bool class_0_bit); + static ErrorOr parse_motion_vector_class0_hp(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, u8 component, bool use_hp); + static ErrorOr parse_motion_vector_bit(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, u8 component, u8 bit_index); + static ErrorOr parse_motion_vector_fr(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, u8 component); + static ErrorOr 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 token_cache, TransformSize transform_size, TransformSet transform_set, u8 plane, u16 token_position, bool is_inter, u8 band); - static ErrorOr parse_more_coefficients(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, TokensContext const& context); - static ErrorOr parse_token(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, TokensContext const& context); + static ErrorOr parse_more_coefficients(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, TokensContext const& context); + static ErrorOr parse_token(BooleanDecoder&, ProbabilityTables const&, SyntaxElementCounter&, TokensContext const& context); }; struct PartitionTreeContext {