diff options
author | Zaggy1024 <zaggy1024@gmail.com> | 2023-02-13 17:13:16 -0600 |
---|---|---|
committer | Jelle Raaijmakers <jelle@gmta.nl> | 2023-04-23 23:14:30 +0200 |
commit | 1fcac52e770e1f3c2806b76125ae740f5204f9c3 (patch) | |
tree | e55f780e88155bf64212300c0d0fabdec94642d5 | |
parent | a8604d93566820bd9bc96c7ee7d5072e66261121 (diff) | |
download | serenity-1fcac52e770e1f3c2806b76125ae740f5204f9c3.zip |
LibVideo/VP9: Count syntax elements in TileContext, and sum at the end
Syntax element counters were previously accessed across tiles, which
would cause a race condition updating the counts in a tile-threaded
mode.
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/Context.h | 30 | ||||
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/Decoder.cpp | 10 | ||||
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/Decoder.h | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/Parser.cpp | 65 | ||||
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/Parser.h | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/SyntaxElementCounter.cpp | 53 | ||||
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/SyntaxElementCounter.h | 5 |
7 files changed, 120 insertions, 48 deletions
diff --git a/Userland/Libraries/LibVideo/VP9/Context.h b/Userland/Libraries/LibVideo/VP9/Context.h index 4cd7c996fc..6ed68d012b 100644 --- a/Userland/Libraries/LibVideo/VP9/Context.h +++ b/Userland/Libraries/LibVideo/VP9/Context.h @@ -21,6 +21,7 @@ #include "Enums.h" #include "LookupTables.h" #include "MotionVector.h" +#include "SyntaxElementCounter.h" #include "Utilities.h" namespace Video::VP9 { @@ -33,20 +34,23 @@ enum class FrameShowMode { struct FrameContext { public: - FrameContext(ReadonlyBytes data, + static ErrorOr<FrameContext> create(ReadonlyBytes data, Vector2D<FrameBlockContext>& contexts) - : stream(data) - , bit_stream(MaybeOwned<Stream>(stream)) - , m_block_contexts(contexts) { + return FrameContext( + TRY(try_make<FixedMemoryStream>(data)), + TRY(try_make<SyntaxElementCounter>()), + contexts); } FrameContext(FrameContext const&) = delete; FrameContext(FrameContext&&) = default; - FixedMemoryStream stream; + NonnullOwnPtr<FixedMemoryStream> stream; BigEndianInputBitStream bit_stream; + NonnullOwnPtr<SyntaxElementCounter> counter; + u8 profile { 0 }; FrameType type { FrameType::KeyFrame }; @@ -139,6 +143,16 @@ public: private: friend struct TileContext; + FrameContext(NonnullOwnPtr<FixedMemoryStream> stream, + NonnullOwnPtr<SyntaxElementCounter> counter, + Vector2D<FrameBlockContext>& contexts) + : stream(move(stream)) + , bit_stream(MaybeOwned<Stream>(*this->stream)) + , counter(move(counter)) + , m_block_contexts(contexts) + { + } + FrameShowMode m_frame_show_mode { FrameShowMode::CreateAndShowNewFrame }; u8 m_existing_frame_index { 0 }; @@ -194,12 +208,13 @@ public: auto height = rows_end - rows_start; auto context_view = frame_context.m_block_contexts.view(rows_start, columns_start, height, width); - auto bit_stream = DECODER_TRY_ALLOC(try_make<BigEndianInputBitStream>(DECODER_TRY_ALLOC(try_make<FixedMemoryStream>(frame_context.stream)))); + auto bit_stream = DECODER_TRY_ALLOC(try_make<BigEndianInputBitStream>(DECODER_TRY_ALLOC(try_make<FixedMemoryStream>(*frame_context.stream)))); auto decoder = DECODER_TRY(DecoderErrorCategory::Corrupted, BooleanDecoder::initialize(move(bit_stream), tile_size)); return TileContext { frame_context, move(decoder), + DECODER_TRY_ALLOC(try_make<SyntaxElementCounter>()), rows_start, rows_end, columns_start, @@ -218,6 +233,7 @@ public: FrameContext const& frame_context; BooleanDecoder decoder; + NonnullOwnPtr<SyntaxElementCounter> counter; u32 rows_start { 0 }; u32 rows_end { 0 }; u32 columns_start { 0 }; @@ -250,6 +266,7 @@ struct BlockContext { .frame_context = tile_context.frame_context, .tile_context = tile_context, .decoder = tile_context.decoder, + .counter = *tile_context.counter, .row = row, .column = column, .size = size, @@ -266,6 +283,7 @@ struct BlockContext { FrameContext const& frame_context; TileContext const& tile_context; BooleanDecoder& decoder; + SyntaxElementCounter& counter; u32 row { 0 }; u32 column { 0 }; BlockSubsize size; diff --git a/Userland/Libraries/LibVideo/VP9/Decoder.cpp b/Userland/Libraries/LibVideo/VP9/Decoder.cpp index 5a6d0da999..a01a5681fb 100644 --- a/Userland/Libraries/LibVideo/VP9/Decoder.cpp +++ b/Userland/Libraries/LibVideo/VP9/Decoder.cpp @@ -239,10 +239,10 @@ u32 Decoder::merge_probs(int const* tree, int index, u8* probs, u32* counts, u8 return left_count + right_count; } -DecoderErrorOr<void> Decoder::adapt_coef_probs(bool is_inter_predicted_frame) +DecoderErrorOr<void> Decoder::adapt_coef_probs(FrameContext const& frame_context) { u8 update_factor; - if (!is_inter_predicted_frame || m_parser->m_previous_frame_type != FrameType::KeyFrame) + if (!frame_context.is_inter_predicted() || m_parser->m_previous_frame_type != FrameType::KeyFrame) update_factor = 112; else update_factor = 128; @@ -255,10 +255,10 @@ DecoderErrorOr<void> Decoder::adapt_coef_probs(bool is_inter_predicted_frame) for (size_t l = 0; l < max_l; l++) { auto& coef_probs = m_parser->m_probability_tables->coef_probs()[t][i][j][k][l]; merge_probs(small_token_tree, 2, coef_probs, - m_parser->m_syntax_element_counter->m_counts_token[t][i][j][k][l], + frame_context.counter->m_counts_token[t][i][j][k][l], 24, update_factor); merge_probs(binary_tree, 0, coef_probs, - m_parser->m_syntax_element_counter->m_counts_more_coefs[t][i][j][k][l], + frame_context.counter->m_counts_more_coefs[t][i][j][k][l], 24, update_factor); } } @@ -287,7 +287,7 @@ DecoderErrorOr<void> Decoder::adapt_coef_probs(bool is_inter_predicted_frame) 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; + auto& counter = *frame_context.counter; ADAPT_PROB_TABLE(is_inter, IS_INTER_CONTEXTS); ADAPT_PROB_TABLE(comp_mode, COMP_MODE_CONTEXTS); ADAPT_PROB_TABLE(comp_ref, REF_CONTEXTS); diff --git a/Userland/Libraries/LibVideo/VP9/Decoder.h b/Userland/Libraries/LibVideo/VP9/Decoder.h index 96b164b0fd..9d219bbe1c 100644 --- a/Userland/Libraries/LibVideo/VP9/Decoder.h +++ b/Userland/Libraries/LibVideo/VP9/Decoder.h @@ -50,7 +50,7 @@ private: /* (8.4) Probability Adaptation Process */ u8 merge_prob(u8 pre_prob, u32 count_0, u32 count_1, u8 count_sat, u8 max_update_factor); u32 merge_probs(int const* tree, int index, u8* probs, u32* counts, u8 count_sat, u8 max_update_factor); - DecoderErrorOr<void> adapt_coef_probs(bool is_inter_predicted_frame); + DecoderErrorOr<void> adapt_coef_probs(FrameContext const&); DecoderErrorOr<void> adapt_non_coef_probs(FrameContext const&); void adapt_probs(int const* tree, u8* probs, u32* counts); u8 adapt_prob(u8 prob, u32 counts[2]); diff --git a/Userland/Libraries/LibVideo/VP9/Parser.cpp b/Userland/Libraries/LibVideo/VP9/Parser.cpp index 4d2ef95e54..360423d7d1 100644 --- a/Userland/Libraries/LibVideo/VP9/Parser.cpp +++ b/Userland/Libraries/LibVideo/VP9/Parser.cpp @@ -83,19 +83,17 @@ DecoderErrorOr<FrameContext> Parser::parse_frame(ReadonlyBytes frame_data) { if (!m_probability_tables) m_probability_tables = DECODER_TRY_ALLOC(try_make<ProbabilityTables>()); - m_syntax_element_counter = make<SyntaxElementCounter>(); // 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 }; + auto frame_context = DECODER_TRY_ALLOC(FrameContext::create(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); 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(compressed_header(frame_context)); @@ -123,7 +121,7 @@ DecoderErrorOr<void> Parser::refresh_probs(FrameContext const& frame_context) { 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())); + TRY(m_decoder.adapt_coef_probs(frame_context)); 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)); @@ -875,7 +873,7 @@ DecoderErrorOr<void> 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 = frame_context.stream.remaining(); + tile_size = frame_context.stream->remaining(); else tile_size = TRY_READ(frame_context.bit_stream.read_bits(32)); @@ -891,6 +889,7 @@ DecoderErrorOr<void> Parser::decode_tiles(FrameContext& frame_context) auto tile_context = TRY(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)); + *frame_context.counter += *tile_context.counter; TRY_READ(frame_context.bit_stream.discard(tile_size)); } } @@ -927,7 +926,7 @@ DecoderErrorOr<void> 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(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 partition = TRY_READ(TreeParser::parse_partition(tile_context.decoder, *m_probability_tables, *tile_context.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) { @@ -1038,7 +1037,7 @@ DecoderErrorOr<bool> 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(block_context.decoder, *m_probability_tables, *m_syntax_element_counter, above_context, left_context)); + return TRY_READ(TreeParser::parse_skip(block_context.decoder, *m_probability_tables, block_context.counter, above_context, left_context)); } bool Parser::seg_feature_active(BlockContext const& block_context, u8 feature) @@ -1050,7 +1049,7 @@ DecoderErrorOr<TransformSize> 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(block_context.decoder, *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, block_context.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)]); } @@ -1120,7 +1119,7 @@ DecoderErrorOr<bool> 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(block_context.decoder, *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, block_context.counter, above_context, left_context)); } DecoderErrorOr<void> Parser::intra_block_mode_info(BlockContext& block_context) @@ -1129,14 +1128,14 @@ DecoderErrorOr<void> 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(block_context.decoder, *m_probability_tables, *m_syntax_element_counter, block_context.size)); + auto mode = TRY_READ(TreeParser::parse_intra_mode(block_context.decoder, *m_probability_tables, block_context.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(block_context.decoder, *m_probability_tables, *m_syntax_element_counter)); + auto sub_intra_mode = TRY_READ(TreeParser::parse_sub_intra_mode(block_context.decoder, *m_probability_tables, block_context.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; @@ -1144,7 +1143,7 @@ DecoderErrorOr<void> Parser::intra_block_mode_info(BlockContext& block_context) } } } - 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())); + block_context.uv_prediction_mode = TRY_READ(TreeParser::parse_uv_mode(block_context.decoder, *m_probability_tables, block_context.counter, block_context.y_prediction_mode())); return {}; } @@ -1166,17 +1165,17 @@ DecoderErrorOr<void> 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(block_context.decoder, *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, block_context.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(block_context.decoder, *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, block_context.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(block_context.decoder, *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, block_context.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()) @@ -1209,7 +1208,7 @@ DecoderErrorOr<void> 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(block_context.decoder, *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, block_context.counter, fixed_reference, above_context, left_context)); if (compound_mode == CompoundReference) { auto variable_references = block_context.frame_context.variable_reference_types; @@ -1218,7 +1217,7 @@ DecoderErrorOr<void> 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(block_context.decoder, *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, block_context.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]; @@ -1227,9 +1226,9 @@ DecoderErrorOr<void> 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(block_context.decoder, *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, block_context.counter, above_context, left_context)); if (single_ref_p1) { - 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)); + auto single_ref_p2 = TRY_READ(TreeParser::parse_single_ref_part_2(block_context.decoder, *m_probability_tables, block_context.counter, above_context, left_context)); primary_type = single_ref_p2 ? ReferenceFrameType::AltRefFrame : ReferenceFrameType::GoldenFrame; } block_context.reference_frame_types = { primary_type, ReferenceFrameType::None }; @@ -1274,35 +1273,35 @@ DecoderErrorOr<MotionVector> 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(block_context.decoder, *m_probability_tables, *m_syntax_element_counter)); + auto joint = TRY_READ(TreeParser::parse_motion_vector_joint(block_context.decoder, *m_probability_tables, block_context.counter)); if ((joint & MotionVectorNonZeroRow) != 0) - delta_vector.set_row(TRY(read_single_motion_vector_component(block_context.decoder, 0, use_high_precision))); + delta_vector.set_row(TRY(read_single_motion_vector_component(block_context.decoder, block_context.counter, 0, use_high_precision))); if ((joint & MotionVectorNonZeroColumn) != 0) - delta_vector.set_column(TRY(read_single_motion_vector_component(block_context.decoder, 1, use_high_precision))); + delta_vector.set_column(TRY(read_single_motion_vector_component(block_context.decoder, block_context.counter, 1, use_high_precision))); return candidates[reference_index].best_vector + delta_vector; } // read_mv_component( comp ) in the spec. -DecoderErrorOr<i32> Parser::read_single_motion_vector_component(BooleanDecoder& decoder, u8 component, bool use_high_precision) +DecoderErrorOr<i32> Parser::read_single_motion_vector_component(BooleanDecoder& decoder, SyntaxElementCounter& counter, u8 component, bool use_high_precision) { - 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)); + auto mv_sign = TRY_READ(TreeParser::parse_motion_vector_sign(decoder, *m_probability_tables, counter, component)); + auto mv_class = TRY_READ(TreeParser::parse_motion_vector_class(decoder, *m_probability_tables, counter, component)); u32 magnitude; if (mv_class == MvClass0) { - 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)); + auto mv_class0_bit = TRY_READ(TreeParser::parse_motion_vector_class0_bit(decoder, *m_probability_tables, counter, component)); + auto mv_class0_fr = TRY_READ(TreeParser::parse_motion_vector_class0_fr(decoder, *m_probability_tables, counter, component, mv_class0_bit)); + auto mv_class0_hp = TRY_READ(TreeParser::parse_motion_vector_class0_hp(decoder, *m_probability_tables, 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(decoder, *m_probability_tables, *m_syntax_element_counter, component, i)); + auto mv_bit = TRY_READ(TreeParser::parse_motion_vector_bit(decoder, *m_probability_tables, counter, component, i)); bits |= mv_bit << i; } magnitude = CLASS0_SIZE << (mv_class + 2); - 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)); + auto mv_fr = TRY_READ(TreeParser::parse_motion_vector_fr(decoder, *m_probability_tables, counter, component)); + auto mv_hp = TRY_READ(TreeParser::parse_motion_vector_hp(decoder, *m_probability_tables, counter, component, use_high_precision)); magnitude += ((bits << 3) | (mv_fr << 1) | mv_hp) + 1; } return (mv_sign ? -1 : 1) * static_cast<i32>(magnitude); @@ -1452,10 +1451,10 @@ DecoderErrorOr<bool> 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(block_context.decoder, *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, block_context.counter, tokens_context))) break; - auto token = TRY_READ(TreeParser::parse_token(block_context.decoder, *m_probability_tables, *m_syntax_element_counter, tokens_context)); + auto token = TRY_READ(TreeParser::parse_token(block_context.decoder, *m_probability_tables, block_context.counter, tokens_context)); token_cache[token_position] = energy_class[token]; i32 coef; diff --git a/Userland/Libraries/LibVideo/VP9/Parser.h b/Userland/Libraries/LibVideo/VP9/Parser.h index ddb3c5603e..c5d874853f 100644 --- a/Userland/Libraries/LibVideo/VP9/Parser.h +++ b/Userland/Libraries/LibVideo/VP9/Parser.h @@ -108,7 +108,7 @@ private: DecoderErrorOr<void> read_ref_frames(BlockContext&, FrameBlockContext above_context, FrameBlockContext left_context); DecoderErrorOr<MotionVectorPair> get_motion_vector(BlockContext const&, BlockMotionVectorCandidates const&); DecoderErrorOr<MotionVector> read_motion_vector(BlockContext const&, BlockMotionVectorCandidates const&, ReferenceIndex); - DecoderErrorOr<i32> read_single_motion_vector_component(BooleanDecoder&, u8 component, bool use_high_precision); + DecoderErrorOr<i32> read_single_motion_vector_component(BooleanDecoder&, SyntaxElementCounter&, u8 component, bool use_high_precision); DecoderErrorOr<bool> residual(BlockContext&, bool has_block_above, bool has_block_left); DecoderErrorOr<bool> tokens(BlockContext&, size_t plane, u32 x, u32 y, TransformSize, TransformSet, Array<u8, 1024> token_cache); DecoderErrorOr<i32> read_coef(BooleanDecoder&, u8 bit_depth, Token token); @@ -140,7 +140,6 @@ private: Vector2D<PersistentBlockContext> m_previous_block_contexts; OwnPtr<ProbabilityTables> m_probability_tables; - OwnPtr<SyntaxElementCounter> m_syntax_element_counter; Decoder& m_decoder; }; diff --git a/Userland/Libraries/LibVideo/VP9/SyntaxElementCounter.cpp b/Userland/Libraries/LibVideo/VP9/SyntaxElementCounter.cpp index 5bf7676fe2..cec285dd1c 100644 --- a/Userland/Libraries/LibVideo/VP9/SyntaxElementCounter.cpp +++ b/Userland/Libraries/LibVideo/VP9/SyntaxElementCounter.cpp @@ -5,10 +5,11 @@ */ #include "SyntaxElementCounter.h" +#include <AK/Format.h> namespace Video::VP9 { -void SyntaxElementCounter::clear_counts() +SyntaxElementCounter::SyntaxElementCounter() { __builtin_memset(m_counts_intra_mode, 0, sizeof(m_counts_intra_mode)); __builtin_memset(m_counts_uv_mode, 0, sizeof(m_counts_uv_mode)); @@ -34,4 +35,54 @@ void SyntaxElementCounter::clear_counts() __builtin_memset(m_counts_more_coefs, 0, sizeof(m_counts_more_coefs)); } +template<typename T, size_t size> +static void sum_arrays(T (&destination)[size], const T (&left)[size], const T (&right)[size]) +{ + for (size_t i = 0; i < size; i++) { + destination[i] = left[i] + right[i]; + } +} + +template<typename T, size_t size, size_t size_2> +static void sum_arrays(T (&destination)[size][size_2], const T (&left)[size][size_2], const T (&right)[size][size_2]) +{ + for (size_t i = 0; i < size; i++) { + sum_arrays(destination[i], left[i], right[i]); + } +} + +SyntaxElementCounter SyntaxElementCounter::operator+(SyntaxElementCounter const& other) const +{ + SyntaxElementCounter result; + sum_arrays(result.m_counts_intra_mode, this->m_counts_intra_mode, other.m_counts_intra_mode); + sum_arrays(result.m_counts_uv_mode, this->m_counts_uv_mode, other.m_counts_uv_mode); + sum_arrays(result.m_counts_partition, this->m_counts_partition, other.m_counts_partition); + sum_arrays(result.m_counts_interp_filter, this->m_counts_interp_filter, other.m_counts_interp_filter); + sum_arrays(result.m_counts_inter_mode, this->m_counts_inter_mode, other.m_counts_inter_mode); + sum_arrays(result.m_counts_tx_size, this->m_counts_tx_size, other.m_counts_tx_size); + sum_arrays(result.m_counts_is_inter, this->m_counts_is_inter, other.m_counts_is_inter); + sum_arrays(result.m_counts_comp_mode, this->m_counts_comp_mode, other.m_counts_comp_mode); + sum_arrays(result.m_counts_single_ref, this->m_counts_single_ref, other.m_counts_single_ref); + sum_arrays(result.m_counts_comp_ref, this->m_counts_comp_ref, other.m_counts_comp_ref); + sum_arrays(result.m_counts_skip, this->m_counts_skip, other.m_counts_skip); + sum_arrays(result.m_counts_mv_joint, this->m_counts_mv_joint, other.m_counts_mv_joint); + sum_arrays(result.m_counts_mv_sign, this->m_counts_mv_sign, other.m_counts_mv_sign); + sum_arrays(result.m_counts_mv_class, this->m_counts_mv_class, other.m_counts_mv_class); + sum_arrays(result.m_counts_mv_class0_bit, this->m_counts_mv_class0_bit, other.m_counts_mv_class0_bit); + sum_arrays(result.m_counts_mv_class0_fr, this->m_counts_mv_class0_fr, other.m_counts_mv_class0_fr); + sum_arrays(result.m_counts_mv_class0_hp, this->m_counts_mv_class0_hp, other.m_counts_mv_class0_hp); + sum_arrays(result.m_counts_mv_bits, this->m_counts_mv_bits, other.m_counts_mv_bits); + sum_arrays(result.m_counts_mv_fr, this->m_counts_mv_fr, other.m_counts_mv_fr); + sum_arrays(result.m_counts_mv_hp, this->m_counts_mv_hp, other.m_counts_mv_hp); + sum_arrays(result.m_counts_token, this->m_counts_token, other.m_counts_token); + sum_arrays(result.m_counts_more_coefs, this->m_counts_more_coefs, other.m_counts_more_coefs); + return result; +} + +SyntaxElementCounter& SyntaxElementCounter::operator+=(SyntaxElementCounter const& other) +{ + *this = *this + other; + return *this; +} + } diff --git a/Userland/Libraries/LibVideo/VP9/SyntaxElementCounter.h b/Userland/Libraries/LibVideo/VP9/SyntaxElementCounter.h index 54abbb6d95..04ab57d1d1 100644 --- a/Userland/Libraries/LibVideo/VP9/SyntaxElementCounter.h +++ b/Userland/Libraries/LibVideo/VP9/SyntaxElementCounter.h @@ -13,6 +13,8 @@ namespace Video::VP9 { class SyntaxElementCounter final { public: + SyntaxElementCounter(); + /* (8.3) Clear Counts Process */ void clear_counts(); @@ -38,6 +40,9 @@ public: u32 m_counts_mv_hp[2][2]; u32 m_counts_token[TX_SIZES][BLOCK_TYPES][REF_TYPES][COEF_BANDS][PREV_COEF_CONTEXTS][UNCONSTRAINED_NODES]; u32 m_counts_more_coefs[TX_SIZES][BLOCK_TYPES][REF_TYPES][COEF_BANDS][PREV_COEF_CONTEXTS][2]; + + SyntaxElementCounter operator+(SyntaxElementCounter const&) const; + SyntaxElementCounter& operator+=(SyntaxElementCounter const&); }; } |