From 6192a33e79df20d23d0ddd968f1448b710ebb75a Mon Sep 17 00:00:00 2001 From: Zaggy1024 Date: Sun, 6 Nov 2022 15:02:24 -0600 Subject: LibVideo: Move parsing of Partition to its own TreeParser function This adds a tree-parsing function that can be called statically from specific trees' implementations in TreeParser, of which Partition is the first. This way, all calls to tree parses will take the context they need to be able to select a tree and probabilities, which will allow removal of the state dependence in TreeParser on fields from itself and Parser. --- Userland/Libraries/LibVideo/VP9/Parser.cpp | 2 +- Userland/Libraries/LibVideo/VP9/TreeParser.cpp | 119 +++++++++++++++---------- Userland/Libraries/LibVideo/VP9/TreeParser.h | 20 ++++- 3 files changed, 91 insertions(+), 50 deletions(-) (limited to 'Userland/Libraries/LibVideo') diff --git a/Userland/Libraries/LibVideo/VP9/Parser.cpp b/Userland/Libraries/LibVideo/VP9/Parser.cpp index 3e092aa355..0af35b176e 100644 --- a/Userland/Libraries/LibVideo/VP9/Parser.cpp +++ b/Userland/Libraries/LibVideo/VP9/Parser.cpp @@ -916,7 +916,7 @@ DecoderErrorOr Parser::decode_partition(u32 row, u32 col, BlockSubsize blo m_has_cols = (col + half_block_8x8) < m_mi_cols; m_row = row; m_col = col; - auto partition = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::Partition)); + auto partition = TRY_READ(TreeParser::parse_partition(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, m_has_rows, m_has_cols, m_block_subsize, m_num_8x8, m_above_partition_context, m_left_partition_context, row, col, m_frame_is_intra)); auto subsize = subsize_lookup[partition][block_subsize]; if (subsize < Block_8x8 || partition == PartitionNone) { diff --git a/Userland/Libraries/LibVideo/VP9/TreeParser.cpp b/Userland/Libraries/LibVideo/VP9/TreeParser.cpp index c385cc6e89..8fc4fc8270 100644 --- a/Userland/Libraries/LibVideo/VP9/TreeParser.cpp +++ b/Userland/Libraries/LibVideo/VP9/TreeParser.cpp @@ -5,10 +5,12 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include + +#include "TreeParser.h" #include "Enums.h" #include "LookupTables.h" #include "Parser.h" -#include "TreeParser.h" namespace Video::VP9 { @@ -18,9 +20,9 @@ ErrorOr TreeParser::parse_tree(SyntaxElementType type) auto tree_selection = select_tree(type); int value; if (tree_selection.is_single_value()) { - value = tree_selection.get_single_value(); + value = tree_selection.single_value(); } else { - auto tree = tree_selection.get_tree_value(); + auto tree = tree_selection.tree(); int n = 0; do { n = tree[n + TRY(m_decoder.m_bit_stream->read_bool(select_tree_probability(type, n >> 1)))]; @@ -43,20 +45,71 @@ template ErrorOr TreeParser::parse_tree(SyntaxElementType); template ErrorOr TreeParser::parse_tree(SyntaxElementType); template ErrorOr TreeParser::parse_tree(SyntaxElementType); +template +inline ErrorOr parse_tree_new(BitStream& bit_stream, TreeParser::TreeSelection tree_selection, Function const& probability_getter) +{ + if (tree_selection.is_single_value()) + return static_cast(tree_selection.single_value()); + + int const* tree = tree_selection.tree(); + int n = 0; + do { + u8 node = n >> 1; + n = tree[n + TRY(bit_stream.read_bool(probability_getter(node)))]; + } while (n > 0); + + return static_cast(-n); +} + +inline void increment_counter(u8& counter) +{ + counter = min(static_cast(counter) + 1, 255); +} + +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, Vector const& above_partition_context, Vector const& left_partition_context, u32 row, u32 column, bool frame_is_intra) +{ + // Tree array + TreeParser::TreeSelection tree = { PartitionSplit }; + if (has_rows && has_columns) + tree = { partition_tree }; + else if (has_rows) + tree = { rows_partition_tree }; + else if (has_columns) + tree = { cols_partition_tree }; + + // Probability array + u32 above = 0; + u32 left = 0; + auto bsl = mi_width_log2_lookup[block_subsize]; + auto block_offset = mi_width_log2_lookup[Block_64x64] - bsl; + for (auto i = 0; i < num_8x8; i++) { + above |= above_partition_context[column + i]; + left |= left_partition_context[row + i]; + } + above = (above & (1 << block_offset)) > 0; + left = (left & (1 << block_offset)) > 0; + auto context = bsl * 4 + left * 2 + above; + u8 const* probabilities = frame_is_intra ? probability_table.kf_partition_probs()[context] : probability_table.partition_probs()[context]; + + Function probability_getter = [&](u8 node) { + if (has_rows && has_columns) + return probabilities[node]; + if (has_columns) + return probabilities[1]; + return probabilities[2]; + }; + + auto value = TRY(parse_tree_new(bit_stream, tree, probability_getter)); + increment_counter(counter.m_counts_partition[context][value]); + return value; +} + /* * Select a tree value based on the type of syntax element being parsed, as well as some parser state, as specified in section 9.3.1 */ TreeParser::TreeSelection TreeParser::select_tree(SyntaxElementType type) { switch (type) { - case SyntaxElementType::Partition: - if (m_decoder.m_has_rows && m_decoder.m_has_cols) - return { partition_tree }; - if (m_decoder.m_has_cols) - return { cols_partition_tree }; - if (m_decoder.m_has_rows) - return { rows_partition_tree }; - return { PartitionSplit }; case SyntaxElementType::DefaultIntraMode: case SyntaxElementType::DefaultUVMode: case SyntaxElementType::IntraMode: @@ -101,6 +154,8 @@ TreeParser::TreeSelection TreeParser::select_tree(SyntaxElementType type) return { 1 }; case SyntaxElementType::Token: return { token_tree }; + default: + break; } VERIFY_NOT_REACHED(); } @@ -111,8 +166,6 @@ TreeParser::TreeSelection TreeParser::select_tree(SyntaxElementType type) u8 TreeParser::select_tree_probability(SyntaxElementType type, u8 node) { switch (type) { - case SyntaxElementType::Partition: - return calculate_partition_probability(node); case SyntaxElementType::DefaultIntraMode: return calculate_default_intra_mode_probability(node); case SyntaxElementType::DefaultUVMode: @@ -171,8 +224,10 @@ u8 TreeParser::select_tree_probability(SyntaxElementType type, u8 node) return calculate_token_probability(node); case SyntaxElementType::MoreCoefs: return calculate_more_coefs_probability(); + default: + break; } - TODO(); + VERIFY_NOT_REACHED(); } #define ABOVE_FRAME_0 m_decoder.m_above_ref_frame[0] @@ -186,33 +241,6 @@ u8 TreeParser::select_tree_probability(SyntaxElementType type, u8 node) #define ABOVE_SINGLE m_decoder.m_above_single #define LEFT_SINGLE m_decoder.m_left_single -u8 TreeParser::calculate_partition_probability(u8 node) -{ - int node2; - if (m_decoder.m_has_rows && m_decoder.m_has_cols) { - node2 = node; - } else if (m_decoder.m_has_cols) { - node2 = 1; - } else { - node2 = 2; - } - - u32 above = 0; - u32 left = 0; - auto bsl = mi_width_log2_lookup[m_decoder.m_block_subsize]; - auto block_offset = mi_width_log2_lookup[Block_64x64] - bsl; - for (auto i = 0; i < m_decoder.m_num_8x8; i++) { - above |= m_decoder.m_above_partition_context[m_decoder.m_col + i]; - left |= m_decoder.m_left_partition_context[m_decoder.m_row + i]; - } - above = (above & (1 << block_offset)) > 0; - left = (left & (1 << block_offset)) > 0; - m_ctx = bsl * 4 + left * 2 + above; - if (m_decoder.m_frame_is_intra) - return m_decoder.m_probability_tables->kf_partition_probs()[m_ctx][node2]; - return m_decoder.m_probability_tables->partition_probs()[m_ctx][node2]; -} - u8 TreeParser::calculate_default_intra_mode_probability(u8 node) { PredictionMode above_mode, left_mode; @@ -670,12 +698,9 @@ u8 TreeParser::calculate_token_probability(u8 node) void TreeParser::count_syntax_element(SyntaxElementType type, int value) { auto increment = [](u8& count) { - count = min(static_cast(count) + 1, 255); + increment_counter(count); }; switch (type) { - case SyntaxElementType::Partition: - increment(m_decoder.m_syntax_element_counter->m_counts_partition[m_ctx][value]); - return; case SyntaxElementType::IntraMode: case SyntaxElementType::SubIntraMode: increment(m_decoder.m_syntax_element_counter->m_counts_intra_mode[m_ctx][value]); @@ -753,8 +778,10 @@ void TreeParser::count_syntax_element(SyntaxElementType type, int value) case SyntaxElementType::SegIDPredicted: // No counting required return; + default: + break; } - TODO(); + VERIFY_NOT_REACHED(); } } diff --git a/Userland/Libraries/LibVideo/VP9/TreeParser.h b/Userland/Libraries/LibVideo/VP9/TreeParser.h index 3ac5d06a93..18b890bea6 100644 --- a/Userland/Libraries/LibVideo/VP9/TreeParser.h +++ b/Userland/Libraries/LibVideo/VP9/TreeParser.h @@ -23,6 +23,7 @@ public: { } + // FIXME: Move or remove this class once it is unused in the header. class TreeSelection { public: union TreeSelectionValue { @@ -43,8 +44,8 @@ public: } bool is_single_value() const { return m_is_single_value; } - int get_single_value() const { return m_value.m_value; } - int const* get_tree_value() const { return m_value.m_tree; } + int single_value() const { return m_value.m_value; } + int const* tree() const { return m_value.m_tree; } private: bool m_is_single_value; @@ -61,6 +62,8 @@ public: /* (9.3.4) */ void count_syntax_element(SyntaxElementType type, int value); + static ErrorOr parse_partition(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, bool has_rows, bool has_columns, BlockSubsize block_subsize, u8 num_8x8, Vector const& above_partition_context, Vector const& left_partition_context, u32 row, u32 column, bool frame_is_intra); + void set_default_intra_mode_variables(u8 idx, u8 idy) { m_idx = idx; @@ -93,7 +96,6 @@ public: } private: - u8 calculate_partition_probability(u8 node); u8 calculate_default_intra_mode_probability(u8 node); u8 calculate_default_uv_mode_probability(u8 node); u8 calculate_intra_mode_probability(u8 node); @@ -137,4 +139,16 @@ private: u8 m_mv_class0_bit { 0xFF }; }; +struct PartitionTreeContext { + bool has_rows; + bool has_columns; + BlockSubsize block_subsize; + u8 num_8x8; + Vector const& above_partition_context; + Vector const& left_partition_context; + u32 row; + u32 column; + bool frame_is_intra; +}; + } -- cgit v1.2.3