diff options
Diffstat (limited to 'Userland/Libraries/LibVideo/VP9')
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/Context.h | 18 | ||||
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/Decoder.cpp | 19 | ||||
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/Decoder.h | 4 | ||||
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/Enums.h | 5 | ||||
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/Parser.cpp | 217 | ||||
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/Parser.h | 36 | ||||
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/ProbabilityTables.cpp | 6 | ||||
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/ProbabilityTables.h | 6 |
8 files changed, 165 insertions, 146 deletions
diff --git a/Userland/Libraries/LibVideo/VP9/Context.h b/Userland/Libraries/LibVideo/VP9/Context.h index 042ab1bef2..1319a95a00 100644 --- a/Userland/Libraries/LibVideo/VP9/Context.h +++ b/Userland/Libraries/LibVideo/VP9/Context.h @@ -255,6 +255,13 @@ struct FrameContext { public: u8 profile { 0 }; + FrameType type { FrameType::KeyFrame }; + bool is_inter_predicted() const { return type == FrameType::InterFrame; } + + bool error_resilient_mode { false }; + bool parallel_decoding_mode { false }; + bool should_replace_probability_context { false }; + bool shows_a_frame() const { return m_frame_show_mode != FrameShowMode::DoNotShowFrame; } bool shows_a_new_frame() const { return m_frame_show_mode == FrameShowMode::CreateAndShowNewFrame; } bool shows_existing_frame() const { return m_frame_show_mode == FrameShowMode::ShowExistingFrame; } @@ -268,6 +275,11 @@ public: ColorConfig color_config {}; + u8 reference_frames_to_update_flags { 0 }; + bool should_update_reference_frame_at_index(u8 index) const { return (reference_frames_to_update_flags & (1 << index)) != 0; } + + u8 probability_context_index { 0 }; + Gfx::Size<u32> size() const { return m_size; } ErrorOr<void> set_size(Gfx::Size<u32> size) { @@ -287,6 +299,12 @@ public: Gfx::Size<u32> render_size { 0, 0 }; + // This group of fields is only needed for inter-predicted frames. + Array<u8, 3> reference_frame_indices; + Array<bool, LastFrame + 3> reference_frame_sign_biases; + bool high_precision_motion_vectors_allowed { false }; + InterpolationFilter interpolation_filter { InterpolationFilter::Switchable }; + u16 header_size_in_bytes { 0 }; private: diff --git a/Userland/Libraries/LibVideo/VP9/Decoder.cpp b/Userland/Libraries/LibVideo/VP9/Decoder.cpp index 25a467ddf5..d40f441feb 100644 --- a/Userland/Libraries/LibVideo/VP9/Decoder.cpp +++ b/Userland/Libraries/LibVideo/VP9/Decoder.cpp @@ -234,10 +234,10 @@ u8 Decoder::merge_probs(int const* tree, int index, u8* probs, u8* counts, u8 co return left_count + right_count; } -DecoderErrorOr<void> Decoder::adapt_coef_probs() +DecoderErrorOr<void> Decoder::adapt_coef_probs(bool is_inter_predicted_frame) { u8 update_factor; - if (m_parser->m_frame_is_intra || m_parser->m_last_frame_type != KeyFrame) + if (!is_inter_predicted_frame || m_parser->m_previous_frame_type != FrameType::KeyFrame) update_factor = 112; else update_factor = 128; @@ -279,7 +279,7 @@ DecoderErrorOr<void> Decoder::adapt_coef_probs() } \ } while (0) -DecoderErrorOr<void> Decoder::adapt_non_coef_probs() +DecoderErrorOr<void> Decoder::adapt_non_coef_probs(FrameContext const& frame_context) { auto& probs = *m_parser->m_probability_tables; auto& counter = *m_parser->m_syntax_element_counter; @@ -295,7 +295,7 @@ DecoderErrorOr<void> Decoder::adapt_non_coef_probs() ADAPT_TREE(intra_mode, uv_mode, uv_mode, INTER_MODE_CONTEXTS); ADAPT_TREE(partition, partition, partition, INTER_MODE_CONTEXTS); ADAPT_PROB_TABLE(skip, SKIP_CONTEXTS); - if (m_parser->m_interpolation_filter == Switchable) { + if (frame_context.interpolation_filter == Switchable) { ADAPT_TREE(interp_filter, interp_filter, interp_filter, INTERP_FILTER_CONTEXTS); } if (m_parser->m_tx_mode == TXModeSelect) { @@ -317,7 +317,7 @@ DecoderErrorOr<void> Decoder::adapt_non_coef_probs() for (size_t j = 0; j < CLASS0_SIZE; j++) adapt_probs(mv_fr_tree, probs.mv_class0_fr_probs()[i][j], counter.m_counts_mv_class0_fr[i][j]); adapt_probs(mv_fr_tree, probs.mv_fr_probs()[i], counter.m_counts_mv_fr[i]); - if (m_parser->m_allow_high_precision_mv) { + if (frame_context.high_precision_motion_vectors_allowed) { probs.mv_class0_hp_prob()[i] = adapt_prob(probs.mv_class0_hp_prob()[i], counter.m_counts_mv_class0_hp[i]); probs.mv_hp_prob()[i] = adapt_prob(probs.mv_hp_prob()[i], counter.m_counts_mv_hp[i]); } @@ -787,7 +787,7 @@ DecoderErrorOr<void> Decoder::predict_inter_block(u8 plane, BlockContext const& // A variable refIdx specifying which reference frame is being used is set equal to // ref_frame_idx[ ref_frame[ refList ] - LAST_FRAME ]. - auto reference_frame_index = m_parser->m_ref_frame_idx[m_parser->m_ref_frame[ref_list] - LastFrame]; + auto reference_frame_index = block_context.frame_context.reference_frame_indices[m_parser->m_ref_frame[ref_list] - LastFrame]; // It is a requirement of bitstream conformance that all the following conditions are satisfied: // − 2 * FrameWidth >= RefFrameWidth[ refIdx ] @@ -1757,9 +1757,8 @@ DecoderErrorOr<void> Decoder::update_reference_frames(FrameContext const& frame_ // 1. For each value of i from 0 to NUM_REF_FRAMES - 1, the following applies if bit i of refresh_frame_flags // is equal to 1 (i.e. if (refresh_frame_flags>>i)&1 is equal to 1): - auto refresh_flags = m_parser->m_refresh_frame_flags; - for (auto i = 0; i < NUM_REF_FRAMES; i++) { - if ((refresh_flags & 1) != 0) { + for (u8 i = 0; i < NUM_REF_FRAMES; i++) { + if (frame_context.should_update_reference_frame_at_index(i)) { // − RefFrameWidth[ i ] is set equal to FrameWidth. // − RefFrameHeight[ i ] is set equal to FrameHeight. m_parser->m_ref_frame_size[i] = frame_context.size(); @@ -1801,8 +1800,6 @@ DecoderErrorOr<void> Decoder::update_reference_frames(FrameContext const& frame_ } } } - - refresh_flags >>= 1; } // 2. If show_existing_frame is equal to 0, the following applies: diff --git a/Userland/Libraries/LibVideo/VP9/Decoder.h b/Userland/Libraries/LibVideo/VP9/Decoder.h index 6bf719b0cc..8e33f14025 100644 --- a/Userland/Libraries/LibVideo/VP9/Decoder.h +++ b/Userland/Libraries/LibVideo/VP9/Decoder.h @@ -51,8 +51,8 @@ private: /* (8.4) Probability Adaptation Process */ u8 merge_prob(u8 pre_prob, u8 count_0, u8 count_1, u8 count_sat, u8 max_update_factor); u8 merge_probs(int const* tree, int index, u8* probs, u8* counts, u8 count_sat, u8 max_update_factor); - DecoderErrorOr<void> adapt_coef_probs(); - DecoderErrorOr<void> adapt_non_coef_probs(); + DecoderErrorOr<void> adapt_coef_probs(bool is_inter_predicted_frame); + DecoderErrorOr<void> adapt_non_coef_probs(FrameContext const&); void adapt_probs(int const* tree, u8* probs, u8* counts); u8 adapt_prob(u8 prob, u8 counts[2]); diff --git a/Userland/Libraries/LibVideo/VP9/Enums.h b/Userland/Libraries/LibVideo/VP9/Enums.h index e9a8d94d56..2e6d549094 100644 --- a/Userland/Libraries/LibVideo/VP9/Enums.h +++ b/Userland/Libraries/LibVideo/VP9/Enums.h @@ -11,9 +11,10 @@ namespace Video::VP9 { -enum FrameType { +enum class FrameType { KeyFrame, - NonKeyFrame + IntraOnlyFrame, + InterFrame }; enum ColorSpace : u8 { diff --git a/Userland/Libraries/LibVideo/VP9/Parser.cpp b/Userland/Libraries/LibVideo/VP9/Parser.cpp index 08185617d0..4d9fad65d6 100644 --- a/Userland/Libraries/LibVideo/VP9/Parser.cpp +++ b/Userland/Libraries/LibVideo/VP9/Parser.cpp @@ -90,19 +90,20 @@ DecoderErrorOr<FrameContext> Parser::parse_frame(ReadonlyBytes frame_data) // 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); - m_probability_tables->load_probs(m_frame_context_idx); - m_probability_tables->load_probs2(m_frame_context_idx); + m_probability_tables->load_probs(frame_context.probability_context_index); + 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()); + TRY(compressed_header(frame_context)); TRY_READ(m_bit_stream->exit_bool()); TRY(m_decoder.allocate_buffers(frame_context)); TRY(decode_tiles(frame_context)); - TRY(refresh_probs()); + TRY(refresh_probs(frame_context)); + m_previous_frame_type = frame_context.type; m_previous_frame_size = frame_context.size(); m_previous_show_frame = frame_context.shows_a_frame(); m_previous_color_config = frame_context.color_config; @@ -119,28 +120,21 @@ bool Parser::trailing_bits() return true; } -DecoderErrorOr<void> Parser::refresh_probs() +DecoderErrorOr<void> Parser::refresh_probs(FrameContext const& frame_context) { - if (!m_error_resilient_mode && !m_frame_parallel_decoding_mode) { - m_probability_tables->load_probs(m_frame_context_idx); - TRY(m_decoder.adapt_coef_probs()); - if (!m_frame_is_intra) { - m_probability_tables->load_probs2(m_frame_context_idx); - TRY(m_decoder.adapt_non_coef_probs()); + if (!frame_context.error_resilient_mode && !frame_context.parallel_decoding_mode) { + m_probability_tables->load_probs(frame_context.probability_context_index); + TRY(m_decoder.adapt_coef_probs(frame_context.is_inter_predicted())); + if (frame_context.is_inter_predicted()) { + m_probability_tables->load_probs2(frame_context.probability_context_index); + TRY(m_decoder.adapt_non_coef_probs(frame_context)); } } - if (m_refresh_frame_context) - m_probability_tables->save_probs(m_frame_context_idx); + if (frame_context.should_replace_probability_context) + m_probability_tables->save_probs(frame_context.probability_context_index); return {}; } -DecoderErrorOr<FrameType> Parser::read_frame_type() -{ - if (TRY_READ(m_bit_stream->read_bit())) - return NonKeyFrame; - return KeyFrame; -} - DecoderErrorOr<ColorRange> Parser::read_color_range() { if (TRY_READ(m_bit_stream->read_bit())) @@ -165,83 +159,106 @@ DecoderErrorOr<FrameContext> Parser::uncompressed_header() return DecoderError::corrupted("uncompressed_header: Profile 3 reserved bit was non-zero"sv); if (TRY_READ(m_bit_stream->read_bit())) { - m_refresh_frame_flags = 0; m_loop_filter_level = 0; frame_context.set_existing_frame_to_show(TRY_READ(m_bit_stream->read_bits(3))); return frame_context; } - m_last_frame_type = m_frame_type; - m_frame_type = TRY(read_frame_type()); + bool is_keyframe = !TRY_READ(m_bit_stream->read_bit()); + if (!TRY_READ(m_bit_stream->read_bit())) frame_context.set_frame_hidden(); - m_error_resilient_mode = TRY_READ(m_bit_stream->read_bit()); + + frame_context.error_resilient_mode = TRY_READ(m_bit_stream->read_bit()); + + FrameType type; Gfx::Size<u32> frame_size; Gfx::Size<u32> render_size; + u8 reference_frames_to_update_flags = 0xFF; // Save frame to all reference indices by default. - if (m_frame_type == KeyFrame) { + enum class ResetProbabilities : u8 { + No = 0, + // 1 also means No here, but we don't need to do anything with the No case. + OnlyCurrent = 2, + All = 3, + }; + ResetProbabilities reset_frame_context = ResetProbabilities::All; + + 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)); - m_refresh_frame_flags = 0xFF; - m_frame_is_intra = true; } else { - m_frame_is_intra = !frame_context.shows_a_frame() && TRY_READ(m_bit_stream->read_bit()); - - if (!m_error_resilient_mode) { - m_reset_frame_context = TRY_READ(m_bit_stream->read_bits(2)); + if (!frame_context.shows_a_frame() && TRY_READ(m_bit_stream->read_bit())) { + type = FrameType::IntraOnlyFrame; } else { - m_reset_frame_context = 0; + type = FrameType::InterFrame; + reset_frame_context = ResetProbabilities::No; } - if (m_frame_is_intra) { + if (!frame_context.error_resilient_mode) + reset_frame_context = static_cast<ResetProbabilities>(TRY_READ(m_bit_stream->read_bits(2))); + + if (type == FrameType::IntraOnlyFrame) { TRY(frame_sync_code()); frame_context.color_config = frame_context.profile > 0 ? TRY(parse_color_config(frame_context)) : ColorConfig(); - m_refresh_frame_flags = TRY_READ(m_bit_stream->read_f8()); + 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 { - m_refresh_frame_flags = TRY_READ(m_bit_stream->read_f8()); + reference_frames_to_update_flags = TRY_READ(m_bit_stream->read_f8()); for (auto i = 0; i < 3; i++) { - m_ref_frame_idx[i] = TRY_READ(m_bit_stream->read_bits(3)); - m_ref_frame_sign_bias[LastFrame + i] = TRY_READ(m_bit_stream->read_bit()); + frame_context.reference_frame_indices[i] = TRY_READ(m_bit_stream->read_bits(3)); + frame_context.reference_frame_sign_biases[LastFrame + i] = TRY_READ(m_bit_stream->read_bit()); } - frame_size = TRY(parse_frame_size_with_refs()); + frame_size = TRY(parse_frame_size_with_refs(frame_context.reference_frame_indices)); render_size = TRY(parse_render_size(frame_size)); - m_allow_high_precision_mv = TRY_READ(m_bit_stream->read_bit()); - TRY(read_interpolation_filter()); + frame_context.high_precision_motion_vectors_allowed = TRY_READ(m_bit_stream->read_bit()); + frame_context.interpolation_filter = TRY(read_interpolation_filter()); } } - DECODER_TRY_ALLOC(frame_context.set_size(frame_size)); - frame_context.render_size = render_size; - TRY(compute_image_size(frame_context)); - - if (!m_error_resilient_mode) { - m_refresh_frame_context = TRY_READ(m_bit_stream->read_bit()); - m_frame_parallel_decoding_mode = TRY_READ(m_bit_stream->read_bit()); - } else { - m_refresh_frame_context = false; - m_frame_parallel_decoding_mode = true; + 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()); } - m_frame_context_idx = TRY_READ(m_bit_stream->read_bits(2)); - if (m_frame_is_intra || m_error_resilient_mode) { + u8 probability_context_index = TRY_READ(m_bit_stream->read_bits(2)); + switch (reset_frame_context) { + case ResetProbabilities::All: setup_past_independence(); - if (m_frame_type == KeyFrame || m_error_resilient_mode || m_reset_frame_context == 3) { - for (auto i = 0; i < 4; i++) { - m_probability_tables->save_probs(i); - } - } else if (m_reset_frame_context == 2) { - m_probability_tables->save_probs(m_frame_context_idx); + for (auto i = 0; i < 4; i++) { + m_probability_tables->save_probs(i); } - m_frame_context_idx = 0; + probability_context_index = 0; + break; + case ResetProbabilities::OnlyCurrent: + setup_past_independence(); + m_probability_tables->save_probs(probability_context_index); + probability_context_index = 0; + break; + default: + break; } + frame_context.type = type; + DECODER_TRY_ALLOC(frame_context.set_size(frame_size)); + frame_context.render_size = render_size; + TRY(compute_image_size(frame_context)); + + frame_context.reference_frames_to_update_flags = reference_frames_to_update_flags; + frame_context.parallel_decoding_mode = parallel_decoding_mode; + + frame_context.should_replace_probability_context = should_replace_probability_context; + frame_context.probability_context_index = probability_context_index; + TRY(loop_filter_params()); TRY(quantization_params()); TRY(segmentation_params()); @@ -325,10 +342,10 @@ DecoderErrorOr<Gfx::Size<u32>> Parser::parse_render_size(Gfx::Size<u32> frame_si return Gfx::Size<u32> { TRY_READ(m_bit_stream->read_f16()) + 1, TRY_READ(m_bit_stream->read_f16()) + 1 }; } -DecoderErrorOr<Gfx::Size<u32>> Parser::parse_frame_size_with_refs() +DecoderErrorOr<Gfx::Size<u32>> Parser::parse_frame_size_with_refs(Array<u8, 3> const& reference_indices) { Optional<Gfx::Size<u32>> size; - for (auto frame_index : m_ref_frame_idx) { + for (auto frame_index : reference_indices) { if (TRY_READ(m_bit_stream->read_bit())) { size.emplace(m_ref_frame_size[frame_index]); break; @@ -364,18 +381,16 @@ DecoderErrorOr<void> Parser::compute_image_size(FrameContext& frame_context) // d. error_resilient_mode is equal to 0. // e. FrameIsIntra is equal to 0. // Otherwise, UsePrevFrameMvs is set equal to 0. - m_use_prev_frame_mvs = !first_invoke && same_size && m_previous_show_frame && !m_error_resilient_mode && !m_frame_is_intra; + m_use_prev_frame_mvs = !first_invoke && same_size && m_previous_show_frame && !frame_context.error_resilient_mode && frame_context.is_inter_predicted(); return {}; } -DecoderErrorOr<void> Parser::read_interpolation_filter() +DecoderErrorOr<InterpolationFilter> Parser::read_interpolation_filter() { if (TRY_READ(m_bit_stream->read_bit())) { - m_interpolation_filter = Switchable; - } else { - m_interpolation_filter = literal_to_type[TRY_READ(m_bit_stream->read_bits(2))]; + return InterpolationFilter::Switchable; } - return {}; + return literal_to_type[TRY_READ(m_bit_stream->read_bits(2))]; } DecoderErrorOr<void> Parser::loop_filter_params() @@ -519,23 +534,23 @@ void Parser::setup_past_independence() m_probability_tables->reset_probs(); } -DecoderErrorOr<void> Parser::compressed_header() +DecoderErrorOr<void> Parser::compressed_header(FrameContext& frame_context) { TRY(read_tx_mode()); if (m_tx_mode == TXModeSelect) TRY(tx_mode_probs()); TRY(read_coef_probs()); TRY(read_skip_prob()); - if (!m_frame_is_intra) { + if (frame_context.is_inter_predicted()) { TRY(read_inter_mode_probs()); - if (m_interpolation_filter == Switchable) + if (frame_context.interpolation_filter == Switchable) TRY(read_interp_filter_probs()); TRY(read_is_inter_probs()); - TRY(frame_reference_mode()); + TRY(frame_reference_mode(frame_context)); TRY(frame_reference_mode_probs()); TRY(read_y_mode_probs()); TRY(read_partition_probs()); - TRY(mv_probs()); + TRY(mv_probs(frame_context)); } return {}; } @@ -670,13 +685,13 @@ DecoderErrorOr<void> Parser::read_is_inter_probs() return {}; } -DecoderErrorOr<void> Parser::frame_reference_mode() +DecoderErrorOr<void> Parser::frame_reference_mode(FrameContext& frame_context) { // FIXME: These fields and the ones set in setup_compound_reference_mode should probably be contained by a field, // since they are all used to set the reference frames later in one function (I think). auto compound_reference_allowed = false; for (size_t i = 2; i <= REFS_PER_FRAME; i++) { - if (m_ref_frame_sign_bias[i] != m_ref_frame_sign_bias[1]) + if (frame_context.reference_frame_sign_biases[i] != frame_context.reference_frame_sign_biases[1]) compound_reference_allowed = true; } if (compound_reference_allowed) { @@ -689,7 +704,7 @@ DecoderErrorOr<void> Parser::frame_reference_mode() m_reference_mode = CompoundReference; else m_reference_mode = ReferenceModeSelect; - setup_compound_reference_mode(); + setup_compound_reference_mode(frame_context); } } else { m_reference_mode = SingleReference; @@ -743,7 +758,7 @@ DecoderErrorOr<void> Parser::read_partition_probs() return {}; } -DecoderErrorOr<void> Parser::mv_probs() +DecoderErrorOr<void> Parser::mv_probs(FrameContext const& frame_context) { for (auto j = 0; j < MV_JOINTS - 1; j++) { auto& mv_joint_probs = m_probability_tables->mv_joint_probs(); @@ -778,7 +793,7 @@ DecoderErrorOr<void> Parser::mv_probs() } } - if (m_allow_high_precision_mv) { + if (frame_context.high_precision_motion_vectors_allowed) { 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(); @@ -798,13 +813,13 @@ DecoderErrorOr<u8> Parser::update_mv_prob(u8 prob) return prob; } -void Parser::setup_compound_reference_mode() +void Parser::setup_compound_reference_mode(FrameContext& frame_context) { - if (m_ref_frame_sign_bias[LastFrame] == m_ref_frame_sign_bias[GoldenFrame]) { + if (frame_context.reference_frame_sign_biases[LastFrame] == frame_context.reference_frame_sign_biases[GoldenFrame]) { m_comp_fixed_ref = AltRefFrame; m_comp_var_ref[0] = LastFrame; m_comp_var_ref[1] = GoldenFrame; - } else if (m_ref_frame_sign_bias[LastFrame] == m_ref_frame_sign_bias[AltRefFrame]) { + } else if (frame_context.reference_frame_sign_biases[LastFrame] == frame_context.reference_frame_sign_biases[AltRefFrame]) { m_comp_fixed_ref = GoldenFrame; m_comp_var_ref[0] = LastFrame; m_comp_var_ref[1] = AltRefFrame; @@ -903,7 +918,7 @@ DecoderErrorOr<void> Parser::decode_partition(TileContext& tile_context, u32 row auto half_block_8x8 = num_8x8 >> 1; bool has_rows = (row + half_block_8x8) < tile_context.frame_context.rows(); bool has_cols = (column + half_block_8x8) < tile_context.frame_context.columns(); - auto partition = TRY_READ(TreeParser::parse_partition(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, has_rows, has_cols, subsize, num_8x8, m_above_partition_context, m_left_partition_context, row, column, m_frame_is_intra)); + auto partition = TRY_READ(TreeParser::parse_partition(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, has_rows, has_cols, subsize, num_8x8, m_above_partition_context, m_left_partition_context, row, column, !tile_context.frame_context.is_inter_predicted())); auto child_subsize = subsize_lookup[partition][subsize]; if (child_subsize < Block_8x8 || partition == PartitionNone) { @@ -962,10 +977,10 @@ DecoderErrorOr<void> Parser::decode_block(TileContext& tile_context, u32 row, u3 DecoderErrorOr<void> Parser::mode_info(BlockContext& block_context, FrameBlockContext above_context, FrameBlockContext left_context) { - if (m_frame_is_intra) - TRY(intra_frame_mode_info(block_context, above_context, left_context)); - else + if (block_context.frame_context.is_inter_predicted()) TRY(inter_frame_mode_info(block_context, above_context, left_context)); + else + TRY(intra_frame_mode_info(block_context, above_context, left_context)); return {}; } @@ -1143,7 +1158,7 @@ DecoderErrorOr<void> Parser::intra_block_mode_info(BlockContext& block_context) DecoderErrorOr<void> Parser::inter_block_mode_info(BlockContext& block_context, FrameBlockContext above_context, FrameBlockContext left_context) { - TRY(read_ref_frames(above_context, left_context)); + TRY(read_ref_frames(block_context, above_context, left_context)); for (auto j = 0; j < 2; j++) { if (m_ref_frame[j] > IntraFrame) { find_mv_refs(block_context, m_ref_frame[j], -1); @@ -1156,10 +1171,10 @@ DecoderErrorOr<void> Parser::inter_block_mode_info(BlockContext& block_context, } else if (block_context.size >= Block_8x8) { m_y_mode = TRY_READ(TreeParser::parse_inter_mode(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, m_mode_context[m_ref_frame[0]])); } - if (m_interpolation_filter == Switchable) + if (block_context.frame_context.interpolation_filter == Switchable) m_interp_filter = TRY_READ(TreeParser::parse_interpolation_filter(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, above_context, left_context)); else - m_interp_filter = m_interpolation_filter; + m_interp_filter = block_context.frame_context.interpolation_filter; if (block_context.size < Block_8x8) { m_num_4x4_w = num_4x4_blocks_wide_lookup[block_context.size]; m_num_4x4_h = num_4x4_blocks_high_lookup[block_context.size]; @@ -1170,7 +1185,7 @@ DecoderErrorOr<void> Parser::inter_block_mode_info(BlockContext& block_context, for (auto j = 0; j < 1 + is_compound; j++) append_sub8x8_mvs(block_context, idy * 2 + idx, j); } - TRY(assign_mv(is_compound)); + TRY(assign_mv(block_context, is_compound)); for (auto y = 0; y < m_num_4x4_h; y++) { for (auto x = 0; x < m_num_4x4_w; x++) { auto block = (idy + y) * 2 + idx + x; @@ -1183,7 +1198,7 @@ DecoderErrorOr<void> Parser::inter_block_mode_info(BlockContext& block_context, } return {}; } - TRY(assign_mv(is_compound)); + TRY(assign_mv(block_context, is_compound)); for (auto ref_list = 0; ref_list < 1 + is_compound; ref_list++) { for (auto block = 0; block < 4; block++) { m_block_mvs[ref_list][block] = m_mv[ref_list]; @@ -1192,7 +1207,7 @@ DecoderErrorOr<void> Parser::inter_block_mode_info(BlockContext& block_context, return {}; } -DecoderErrorOr<void> Parser::read_ref_frames(FrameBlockContext above_context, FrameBlockContext left_context) +DecoderErrorOr<void> Parser::read_ref_frames(BlockContext& block_context, FrameBlockContext above_context, FrameBlockContext left_context) { if (seg_feature_active(SEG_LVL_REF_FRAME)) { m_ref_frame[0] = static_cast<ReferenceFrameType>(m_feature_data[m_segment_id][SEG_LVL_REF_FRAME]); @@ -1206,8 +1221,8 @@ DecoderErrorOr<void> Parser::read_ref_frames(FrameBlockContext above_context, Fr comp_mode = m_reference_mode; if (comp_mode == CompoundReference) { // FIXME: Make reference frame pairs be indexed by an enum of FixedReference or VariableReference? - auto fixed_reference_index = m_ref_frame_sign_bias[m_comp_fixed_ref]; - auto variable_reference_index = fixed_reference_index == 0 ? 1 : 0; + auto fixed_reference_index = block_context.frame_context.reference_frame_sign_biases[m_comp_fixed_ref]; + auto variable_reference_index = !fixed_reference_index; // FIXME: Create an enum for compound frame references using names Primary and Secondary. auto comp_ref = TRY_READ(TreeParser::parse_comp_ref(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, m_comp_fixed_ref, m_comp_var_ref, variable_reference_index, above_context, left_context)); @@ -1228,12 +1243,12 @@ DecoderErrorOr<void> Parser::read_ref_frames(FrameBlockContext above_context, Fr return {}; } -DecoderErrorOr<void> Parser::assign_mv(bool is_compound) +DecoderErrorOr<void> Parser::assign_mv(BlockContext const& block_context, bool is_compound) { m_mv[1] = {}; for (auto i = 0; i < 1 + is_compound; i++) { if (m_y_mode == PredictionMode::NewMv) { - TRY(read_mv(i)); + TRY(read_mv(block_context, i)); } else if (m_y_mode == PredictionMode::NearestMv) { m_mv[i] = m_nearest_mv[i]; } else if (m_y_mode == PredictionMode::NearMv) { @@ -1245,9 +1260,9 @@ DecoderErrorOr<void> Parser::assign_mv(bool is_compound) return {}; } -DecoderErrorOr<void> Parser::read_mv(u8 ref) +DecoderErrorOr<void> Parser::read_mv(BlockContext const& block_context, u8 ref) { - m_use_hp = m_allow_high_precision_mv && use_mv_hp(m_best_mv[ref]); + m_use_hp = block_context.frame_context.high_precision_motion_vectors_allowed && use_mv_hp(m_best_mv[ref]); MotionVector diff_mv; auto mv_joint = TRY_READ(TreeParser::parse_motion_vector_joint(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter)); if (mv_joint == MvJointHzvnz || mv_joint == MvJointHnzvnz) @@ -1507,10 +1522,10 @@ void Parser::if_same_ref_frame_add_mv(BlockContext const& block_context, MotionV } } -void Parser::scale_mv(u8 ref_list, ReferenceFrameType ref_frame) +void Parser::scale_mv(FrameContext const& frame_context, u8 ref_list, ReferenceFrameType ref_frame) { auto candidate_frame = m_candidate_frame[ref_list]; - if (m_ref_frame_sign_bias[candidate_frame] != m_ref_frame_sign_bias[ref_frame]) + if (frame_context.reference_frame_sign_biases[candidate_frame] != frame_context.reference_frame_sign_biases[ref_frame]) m_candidate_mv[ref_list] *= -1; } @@ -1520,11 +1535,11 @@ void Parser::if_diff_ref_frame_add_mv(BlockContext const& block_context, MotionV get_block_mv(block_context, candidate_vector, ref_list, use_prev); auto mvs_are_same = m_candidate_mv[0] == m_candidate_mv[1]; if (m_candidate_frame[0] > ReferenceFrameType::IntraFrame && m_candidate_frame[0] != ref_frame) { - scale_mv(0, ref_frame); + scale_mv(block_context.frame_context, 0, ref_frame); add_mv_ref_list(0); } if (m_candidate_frame[1] > ReferenceFrameType::IntraFrame && m_candidate_frame[1] != ref_frame && !mvs_are_same) { - scale_mv(1, ref_frame); + scale_mv(block_context.frame_context, 1, ref_frame); add_mv_ref_list(1); } } @@ -1629,7 +1644,7 @@ void Parser::find_best_ref_mvs(BlockContext& block_context, u8 ref_list) auto delta = m_ref_list_mv[i]; auto delta_row = delta.row(); auto delta_column = delta.column(); - if (!m_allow_high_precision_mv || !use_mv_hp(delta)) { + if (!block_context.frame_context.high_precision_motion_vectors_allowed || !use_mv_hp(delta)) { if (delta_row & 1) delta_row += delta_row > 0 ? -1 : 1; if (delta_column & 1) diff --git a/Userland/Libraries/LibVideo/VP9/Parser.h b/Userland/Libraries/LibVideo/VP9/Parser.h index 70fe837e21..0898a47641 100644 --- a/Userland/Libraries/LibVideo/VP9/Parser.h +++ b/Userland/Libraries/LibVideo/VP9/Parser.h @@ -52,7 +52,7 @@ private: /* (6.1) Frame Syntax */ bool trailing_bits(); - DecoderErrorOr<void> refresh_probs(); + DecoderErrorOr<void> refresh_probs(FrameContext const&); /* (6.2) Uncompressed Header Syntax */ DecoderErrorOr<FrameContext> uncompressed_header(); @@ -60,10 +60,10 @@ private: DecoderErrorOr<ColorConfig> parse_color_config(FrameContext const&); DecoderErrorOr<void> set_frame_size_and_compute_image_size(); DecoderErrorOr<Gfx::Size<u32>> parse_frame_size(); - DecoderErrorOr<Gfx::Size<u32>> parse_frame_size_with_refs(); + DecoderErrorOr<Gfx::Size<u32>> parse_frame_size_with_refs(Array<u8, 3> const& reference_indices); DecoderErrorOr<Gfx::Size<u32>> parse_render_size(Gfx::Size<u32> frame_size); DecoderErrorOr<void> compute_image_size(FrameContext&); - DecoderErrorOr<void> read_interpolation_filter(); + DecoderErrorOr<InterpolationFilter> read_interpolation_filter(); DecoderErrorOr<void> loop_filter_params(); DecoderErrorOr<void> quantization_params(); DecoderErrorOr<i8> read_delta_q(); @@ -75,7 +75,7 @@ private: void setup_past_independence(); /* (6.3) Compressed Header Syntax */ - DecoderErrorOr<void> compressed_header(); + DecoderErrorOr<void> compressed_header(FrameContext&); DecoderErrorOr<void> read_tx_mode(); DecoderErrorOr<void> tx_mode_probs(); DecoderErrorOr<u8> diff_update_prob(u8 prob); @@ -87,13 +87,13 @@ private: DecoderErrorOr<void> read_inter_mode_probs(); DecoderErrorOr<void> read_interp_filter_probs(); DecoderErrorOr<void> read_is_inter_probs(); - DecoderErrorOr<void> frame_reference_mode(); + DecoderErrorOr<void> frame_reference_mode(FrameContext&); DecoderErrorOr<void> frame_reference_mode_probs(); DecoderErrorOr<void> read_y_mode_probs(); DecoderErrorOr<void> read_partition_probs(); - DecoderErrorOr<void> mv_probs(); + DecoderErrorOr<void> mv_probs(FrameContext const&); DecoderErrorOr<u8> update_mv_prob(u8 prob); - void setup_compound_reference_mode(); + void setup_compound_reference_mode(FrameContext&); /* (6.4) Decode Tiles Syntax */ DecoderErrorOr<void> decode_tiles(FrameContext&); @@ -115,9 +115,9 @@ private: DecoderErrorOr<void> read_is_inter(FrameBlockContext above_context, FrameBlockContext left_context); DecoderErrorOr<void> intra_block_mode_info(BlockContext&); DecoderErrorOr<void> inter_block_mode_info(BlockContext&, FrameBlockContext above_context, FrameBlockContext left_context); - DecoderErrorOr<void> read_ref_frames(FrameBlockContext above_context, FrameBlockContext left_context); - DecoderErrorOr<void> assign_mv(bool is_compound); - DecoderErrorOr<void> read_mv(u8 ref); + DecoderErrorOr<void> read_ref_frames(BlockContext&, FrameBlockContext above_context, FrameBlockContext left_context); + DecoderErrorOr<void> assign_mv(BlockContext const&, bool is_compound); + DecoderErrorOr<void> read_mv(BlockContext const&, u8 ref); DecoderErrorOr<i32> read_mv_component(u8 component); DecoderErrorOr<bool> residual(BlockContext&, bool has_block_above, bool has_block_left); DecoderErrorOr<bool> tokens(BlockContext&, size_t plane, u32 x, u32 y, TXSize tx_size, u32 block_index); @@ -135,32 +135,20 @@ private: void get_block_mv(BlockContext const&, MotionVector candidate_vector, u8 ref_list, bool use_prev); void if_same_ref_frame_add_mv(BlockContext const&, MotionVector candidate_vector, ReferenceFrameType ref_frame, bool use_prev); void if_diff_ref_frame_add_mv(BlockContext const&, MotionVector candidate_vector, ReferenceFrameType ref_frame, bool use_prev); - void scale_mv(u8 ref_list, ReferenceFrameType ref_frame); + void scale_mv(FrameContext const&, u8 ref_list, ReferenceFrameType ref_frame); void add_mv_ref_list(u8 ref_list); Gfx::Point<size_t> get_decoded_point_for_plane(FrameContext const&, u32 row, u32 column, u8 plane); Gfx::Size<size_t> get_decoded_size_for_plane(FrameContext const&, u8 plane); - u8 m_refresh_frame_flags { 0 }; u8 m_loop_filter_level { 0 }; u8 m_loop_filter_sharpness { 0 }; bool m_loop_filter_delta_enabled { false }; - FrameType m_frame_type { FrameType::KeyFrame }; - FrameType m_last_frame_type { FrameType::KeyFrame }; - bool m_error_resilient_mode { false }; - bool m_frame_is_intra { false }; - u8 m_reset_frame_context { 0 }; - bool m_allow_high_precision_mv { false }; - u8 m_ref_frame_idx[3]; - u8 m_ref_frame_sign_bias[LastFrame + 3]; - bool m_refresh_frame_context { false }; - bool m_frame_parallel_decoding_mode { false }; - u8 m_frame_context_idx { 0 }; bool m_is_first_compute_image_size_invoke { true }; Gfx::Size<u32> m_previous_frame_size { 0, 0 }; bool m_previous_show_frame { false }; ColorConfig m_previous_color_config; - InterpolationFilter m_interpolation_filter { 0xf }; + FrameType m_previous_frame_type { FrameType::KeyFrame }; u8 m_base_q_idx { 0 }; i8 m_delta_q_y_dc { 0 }; i8 m_delta_q_uv_dc { 0 }; diff --git a/Userland/Libraries/LibVideo/VP9/ProbabilityTables.cpp b/Userland/Libraries/LibVideo/VP9/ProbabilityTables.cpp index bc8c49a562..2ecf4fb3ad 100644 --- a/Userland/Libraries/LibVideo/VP9/ProbabilityTables.cpp +++ b/Userland/Libraries/LibVideo/VP9/ProbabilityTables.cpp @@ -1171,7 +1171,7 @@ KfUVModeProbs const& ProbabilityTables::kf_uv_mode_prob() const return constant_kf_uv_mode_prob; } -void ProbabilityTables::save_probs(size_t index) +void ProbabilityTables::save_probs(u8 index) { m_saved_probability_tables[index] = m_current_probability_table; } @@ -1201,7 +1201,7 @@ void ProbabilityTables::reset_probs() __builtin_memcpy(m_current_probability_table.coef_probs, default_coef_probs, sizeof(CoefProbs)); } -void ProbabilityTables::load_probs(size_t index) +void ProbabilityTables::load_probs(u8 index) { auto old_table = m_current_probability_table; m_current_probability_table = m_saved_probability_tables.at(index); @@ -1209,7 +1209,7 @@ void ProbabilityTables::load_probs(size_t index) __builtin_memcpy(m_current_probability_table.tx_probs, old_table.tx_probs, sizeof(TxProbs)); } -void ProbabilityTables::load_probs2(size_t index) +void ProbabilityTables::load_probs2(u8 index) { auto new_table = m_saved_probability_tables.at(index); __builtin_memcpy(m_current_probability_table.skip_prob, new_table.skip_prob, sizeof(SkipProb)); diff --git a/Userland/Libraries/LibVideo/VP9/ProbabilityTables.h b/Userland/Libraries/LibVideo/VP9/ProbabilityTables.h index 1f42382880..15096f8f67 100644 --- a/Userland/Libraries/LibVideo/VP9/ProbabilityTables.h +++ b/Userland/Libraries/LibVideo/VP9/ProbabilityTables.h @@ -42,10 +42,10 @@ typedef u8 CoefProbs[TX_SIZES][BLOCK_TYPES][REF_TYPES][COEF_BANDS][PREV_COEF_CON class ProbabilityTables final { public: - void save_probs(size_t index); + void save_probs(u8 index); void reset_probs(); - void load_probs(size_t index); - void load_probs2(size_t index); + void load_probs(u8 index); + void load_probs2(u8 index); ParetoTable const& pareto_table() const; KfPartitionProbs const& kf_partition_probs() const; |