diff options
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/Context.h | 91 | ||||
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/ContextStorage.h | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/Parser.cpp | 29 | ||||
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/Parser.h | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/TreeParser.cpp | 8 | ||||
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/TreeParser.h | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/Utilities.h | 5 |
7 files changed, 96 insertions, 43 deletions
diff --git a/Userland/Libraries/LibVideo/VP9/Context.h b/Userland/Libraries/LibVideo/VP9/Context.h index b07bbd3f1d..5fb3e2414f 100644 --- a/Userland/Libraries/LibVideo/VP9/Context.h +++ b/Userland/Libraries/LibVideo/VP9/Context.h @@ -9,6 +9,7 @@ #include <AK/Array.h> #include <AK/Error.h> +#include <AK/FixedArray.h> #include <LibGfx/Size.h> #include <LibVideo/Color/CodingIndependentCodePoints.h> @@ -139,16 +140,49 @@ private: Vector2D<FrameBlockContext>& m_block_contexts; }; +static ErrorOr<NonZeroTokens> create_non_zero_tokens(u32 size_in_sub_blocks, bool subsampling) +{ + return NonZeroTokens { + TRY(FixedArray<bool>::try_create(size_in_sub_blocks)), + TRY(FixedArray<bool>::try_create(size_in_sub_blocks >>= subsampling)), + TRY(FixedArray<bool>::try_create(size_in_sub_blocks)), + }; +} + +template<typename T> +static Span<T> safe_slice(FixedArray<T>& array, u32 start, u32 size) +{ + return array.span().slice(start, min(size, array.size() - start)); +} + +static NonZeroTokensView create_non_zero_tokens_view(NonZeroTokens& non_zero_tokens, u32 start_in_sub_blocks, u32 size_in_sub_blocks, bool subsampling) +{ + NonZeroTokensView result; + // Y plane + result[0] = safe_slice(non_zero_tokens[0], start_in_sub_blocks, size_in_sub_blocks); + // UV planes + start_in_sub_blocks >>= subsampling; + size_in_sub_blocks >>= subsampling; + result[1] = safe_slice(non_zero_tokens[1], start_in_sub_blocks, size_in_sub_blocks); + result[2] = safe_slice(non_zero_tokens[2], start_in_sub_blocks, size_in_sub_blocks); + return result; +} + struct TileContext { public: - TileContext(FrameContext& frame_context, u32 rows_start, u32 rows_end, u32 columns_start, u32 columns_end) - : frame_context(frame_context) - , rows_start(rows_start) - , rows_end(rows_end) - , columns_start(columns_start) - , columns_end(columns_end) - , block_contexts_view(frame_context.m_block_contexts.view(rows_start, columns_start, rows_end - rows_start, columns_end - columns_start)) + static ErrorOr<TileContext> try_create(FrameContext& frame_context, u32 rows_start, u32 rows_end, u32 columns_start, u32 columns_end) { + auto context_view = frame_context.m_block_contexts.view(rows_start, columns_start, rows_end - rows_start, columns_end - columns_start); + + return TileContext { + frame_context, + rows_start, + rows_end, + columns_start, + columns_end, + context_view, + TRY(create_non_zero_tokens(blocks_to_sub_blocks(rows_end - rows_start), frame_context.color_config.subsampling_y)), + }; } Vector2D<FrameBlockContext> const& frame_block_contexts() const { return frame_context.block_contexts(); } @@ -158,20 +192,33 @@ public: u32 rows_end { 0 }; u32 columns_start { 0 }; u32 columns_end { 0 }; + u32 rows() const { return rows_end - rows_start; } + u32 columns() const { return columns_end - columns_start; } Vector2DView<FrameBlockContext> block_contexts_view; + + NonZeroTokens left_non_zero_tokens; }; struct BlockContext { - BlockContext(TileContext& tile_context, u32 row, u32 column, BlockSubsize size) - : frame_context(tile_context.frame_context) - , tile_context(tile_context) - , row(row) - , column(column) - , size(size) - , contexts_view(tile_context.block_contexts_view.view(row - tile_context.rows_start, column - tile_context.columns_start, - min<u32>(num_8x8_blocks_high_lookup[size], tile_context.frame_context.rows() - row), - min<u32>(num_8x8_blocks_wide_lookup[size], tile_context.frame_context.columns() - column))) + static BlockContext create(TileContext& tile_context, u32 row, u32 column, BlockSubsize size) { + auto contexts_view = tile_context.block_contexts_view.view( + row - tile_context.rows_start, + column - tile_context.columns_start, + min<u32>(num_8x8_blocks_high_lookup[size], tile_context.frame_context.rows() - row), + min<u32>(num_8x8_blocks_wide_lookup[size], tile_context.frame_context.columns() - column)); + + auto size_in_sub_blocks = block_size_to_sub_blocks(get_subsampled_block_size(size, false, false)); + + return BlockContext { + .frame_context = tile_context.frame_context, + .tile_context = tile_context, + .row = row, + .column = column, + .size = size, + .contexts_view = contexts_view, + .left_non_zero_tokens = create_non_zero_tokens_view(tile_context.left_non_zero_tokens, blocks_to_sub_blocks(row - tile_context.rows_start), size_in_sub_blocks.height(), tile_context.frame_context.color_config.subsampling_y), + }; } Vector2D<FrameBlockContext> const& frame_block_contexts() const { return frame_context.block_contexts(); } @@ -193,22 +240,24 @@ struct BlockContext { TransformSize transform_size { Transform_4x4 }; - ReferenceFramePair reference_frame_types; + ReferenceFramePair reference_frame_types {}; bool is_inter_predicted() const { return reference_frame_types.primary != ReferenceFrameType::None; } bool is_compound() const { return reference_frame_types.secondary != ReferenceFrameType::None; } - Array<PredictionMode, 4> sub_block_prediction_modes; + Array<PredictionMode, 4> sub_block_prediction_modes {}; PredictionMode y_prediction_mode() const { return sub_block_prediction_modes.last(); } PredictionMode& y_prediction_mode() { return sub_block_prediction_modes.last(); } PredictionMode uv_prediction_mode { 0 }; InterpolationFilter interpolation_filter { EightTap }; - Array<MotionVectorPair, 4> sub_block_motion_vectors; + Array<MotionVectorPair, 4> sub_block_motion_vectors {}; - Array<i32, 1024> residual_tokens; + Array<i32, 1024> residual_tokens {}; // Indexed by ReferenceFrame enum. - Array<u8, 4> mode_context; + Array<u8, 4> mode_context {}; + + NonZeroTokensView left_non_zero_tokens; }; struct BlockMotionVectorCandidateSet { diff --git a/Userland/Libraries/LibVideo/VP9/ContextStorage.h b/Userland/Libraries/LibVideo/VP9/ContextStorage.h index 144470a2b1..aefe3e6f97 100644 --- a/Userland/Libraries/LibVideo/VP9/ContextStorage.h +++ b/Userland/Libraries/LibVideo/VP9/ContextStorage.h @@ -248,4 +248,7 @@ struct ColorConfig { struct BlockMotionVectorCandidateSet; using BlockMotionVectorCandidates = ReferencePair<BlockMotionVectorCandidateSet>; +using NonZeroTokens = Array<FixedArray<bool>, 3>; +using NonZeroTokensView = Array<Span<bool>, 3>; + } diff --git a/Userland/Libraries/LibVideo/VP9/Parser.cpp b/Userland/Libraries/LibVideo/VP9/Parser.cpp index c9dd89c6a4..1300b66afc 100644 --- a/Userland/Libraries/LibVideo/VP9/Parser.cpp +++ b/Userland/Libraries/LibVideo/VP9/Parser.cpp @@ -864,7 +864,7 @@ DecoderErrorOr<void> Parser::decode_tiles(FrameContext& frame_context) auto columns_start = get_tile_offset(tile_col, frame_context.columns(), log2_dimensions.width()); auto columns_end = get_tile_offset(tile_col + 1, frame_context.columns(), log2_dimensions.width()); - auto tile_context = TileContext(frame_context, rows_start, rows_end, columns_start, columns_end); + auto tile_context = DECODER_TRY_ALLOC(TileContext::try_create(frame_context, rows_start, rows_end, columns_start, columns_end)); TRY_READ(m_bit_stream->init_bool(tile_size)); TRY(decode_tile(tile_context)); @@ -918,8 +918,8 @@ DecoderErrorOr<void> Parser::decode_tile(TileContext& tile_context) void Parser::clear_left_context(TileContext& tile_context) { - for (auto i = 0u; i < m_left_nonzero_context.size(); i++) - clear_context(m_left_nonzero_context[i], 2 * tile_context.frame_context.rows()); + for (auto& context_for_plane : tile_context.left_non_zero_tokens) + context_for_plane.fill_with(false); clear_context(m_left_seg_pred_context, tile_context.frame_context.rows()); clear_context(m_left_partition_context, tile_context.frame_context.superblock_rows() * 8); } @@ -972,7 +972,7 @@ DecoderErrorOr<void> Parser::decode_block(TileContext& tile_context, u32 row, u3 { auto above_context = row > 0 ? tile_context.frame_block_contexts().at(row - 1, column) : FrameBlockContext(); auto left_context = column > tile_context.columns_start ? tile_context.frame_block_contexts().at(row, column - 1) : FrameBlockContext(); - auto block_context = BlockContext(tile_context, row, column, subsize); + auto block_context = BlockContext::create(tile_context, row, column, subsize); TRY(mode_info(block_context, above_context, left_context)); auto had_residual_tokens = TRY(residual(block_context, above_context.is_available, left_context.is_available)); @@ -1355,9 +1355,9 @@ DecoderErrorOr<bool> Parser::residual(BlockContext& block_context, bool has_bloc bool block_had_non_zero_tokens = false; Array<u8, 1024> token_cache; for (u8 plane = 0; plane < 3; plane++) { - auto plane_subsampling_x = (plane > 0) ? block_context.frame_context.color_config.subsampling_x : 0; - auto plane_subsampling_y = (plane > 0) ? block_context.frame_context.color_config.subsampling_y : 0; - auto plane_size = ss_size_lookup[block_context.size < Block_8x8 ? Block_8x8 : block_context.size][plane_subsampling_x][plane_subsampling_y]; + auto plane_subsampling_x = (plane > 0) ? block_context.frame_context.color_config.subsampling_x : false; + auto plane_subsampling_y = (plane > 0) ? block_context.frame_context.color_config.subsampling_y : false; + auto plane_size = get_subsampled_block_size(block_context.size, plane_subsampling_x, plane_subsampling_y); auto transform_size = get_uv_transform_size(block_context.transform_size, plane_size); auto transform_size_in_sub_blocks = transform_size_to_sub_blocks(transform_size); auto block_size_in_sub_blocks = block_size_to_sub_blocks(plane_size); @@ -1380,8 +1380,8 @@ DecoderErrorOr<bool> Parser::residual(BlockContext& block_context, bool has_bloc auto frame_bottom_in_pixels = (blocks_to_pixels(block_context.frame_context.rows())) >> plane_subsampling_y; auto sub_block_index = 0; - for (auto y = 0; y < block_size_in_sub_blocks.height(); y += transform_size_in_sub_blocks) { - for (auto x = 0; x < block_size_in_sub_blocks.width(); x += transform_size_in_sub_blocks) { + for (u32 y = 0; y < block_size_in_sub_blocks.height(); y += transform_size_in_sub_blocks) { + for (u32 x = 0; x < block_size_in_sub_blocks.width(); x += transform_size_in_sub_blocks) { auto transform_x_in_px = base_x_in_pixels + sub_blocks_to_pixels(x); auto transform_y_in_px = base_y_in_pixels + sub_blocks_to_pixels(y); @@ -1403,11 +1403,10 @@ DecoderErrorOr<bool> Parser::residual(BlockContext& block_context, bool has_bloc for (; above_sub_block_context_index < above_sub_block_context_end; above_sub_block_context_index++) above_sub_block_context[above_sub_block_context_index] = sub_block_had_non_zero_tokens; - auto& left_sub_block_context = m_left_nonzero_context[plane]; - auto left_sub_block_context_index = pixels_to_sub_blocks(transform_y_in_px); - auto left_sub_block_context_end = min(left_sub_block_context_index + transform_size_in_sub_blocks, left_sub_block_context.size()); - for (; left_sub_block_context_index < left_sub_block_context_end; left_sub_block_context_index++) - left_sub_block_context[left_sub_block_context_index] = sub_block_had_non_zero_tokens; + auto& left_sub_block_context = block_context.left_non_zero_tokens[plane]; + auto transform_bottom_in_sub_blocks = min(y + transform_size_in_sub_blocks, left_sub_block_context.size()); + for (size_t inside_y = y; inside_y < transform_bottom_in_sub_blocks; inside_y++) + left_sub_block_context[inside_y] = sub_block_had_non_zero_tokens; sub_block_index++; } @@ -1459,7 +1458,7 @@ DecoderErrorOr<bool> Parser::tokens(BlockContext& block_context, size_t plane, u auto token_position = scan[coef_index]; TokensContext tokens_context; if (coef_index == 0) - tokens_context = TreeParser::get_context_for_first_token(block_context, m_above_nonzero_context, m_left_nonzero_context, transform_size, plane, sub_block_column, sub_block_row, block_context.is_inter_predicted(), band); + tokens_context = TreeParser::get_context_for_first_token(block_context, m_above_nonzero_context, block_context.left_non_zero_tokens, transform_size, plane, sub_block_column, sub_block_row, block_context.is_inter_predicted(), band); else tokens_context = TreeParser::get_context_for_other_tokens(token_cache, transform_size, transform_set, plane, token_position, block_context.is_inter_predicted(), band); diff --git a/Userland/Libraries/LibVideo/VP9/Parser.h b/Userland/Libraries/LibVideo/VP9/Parser.h index a764fb76c6..07460190f3 100644 --- a/Userland/Libraries/LibVideo/VP9/Parser.h +++ b/Userland/Libraries/LibVideo/VP9/Parser.h @@ -148,7 +148,6 @@ private: // FIXME: Move above and left contexts to structs Array<Vector<bool>, 3> m_above_nonzero_context; - Array<Vector<bool>, 3> m_left_nonzero_context; Vector<u8> m_above_seg_pred_context; Vector<u8> m_left_seg_pred_context; Vector<u8> m_above_partition_context; diff --git a/Userland/Libraries/LibVideo/VP9/TreeParser.cpp b/Userland/Libraries/LibVideo/VP9/TreeParser.cpp index a1dcb1dfaf..be3b5c3bd8 100644 --- a/Userland/Libraries/LibVideo/VP9/TreeParser.cpp +++ b/Userland/Libraries/LibVideo/VP9/TreeParser.cpp @@ -626,11 +626,9 @@ ErrorOr<bool> TreeParser::parse_motion_vector_hp(BitStream& bit_stream, Probabil return value; } -TokensContext TreeParser::get_context_for_first_token(BlockContext const& block_context, Array<Vector<bool>, 3> const& above_non_zero_tokens, Array<Vector<bool>, 3> const& left_non_zero_tokens, TransformSize transform_size, u8 plane, u32 sub_block_column, u32 sub_block_row, bool is_inter, u8 band) +TokensContext TreeParser::get_context_for_first_token(BlockContext const& block_context, Array<Vector<bool>, 3> const& above_non_zero_tokens, NonZeroTokensView left_non_zero_tokens_in_block, TransformSize transform_size, u8 plane, u32 sub_block_column, u32 sub_block_row, bool is_inter, u8 band) { auto subsampling_x = plane > 0 ? block_context.frame_context.color_config.subsampling_x : false; - auto subsampling_y = plane > 0 ? block_context.frame_context.color_config.subsampling_y : false; - auto transform_top_in_sub_blocks = (blocks_to_sub_blocks(block_context.row) >> subsampling_y) + sub_block_row; auto transform_left_in_sub_blocks = (blocks_to_sub_blocks(block_context.column) >> subsampling_x) + sub_block_column; u8 transform_size_in_sub_blocks = transform_size_to_sub_blocks(transform_size); bool above_has_non_zero_tokens = false; @@ -641,8 +639,8 @@ TokensContext TreeParser::get_context_for_first_token(BlockContext const& block_ } } bool left_has_non_zero_tokens = false; - for (u8 y = 0; y < transform_size_in_sub_blocks && y < left_non_zero_tokens[plane].size() - transform_top_in_sub_blocks; y++) { - if (left_non_zero_tokens[plane][transform_top_in_sub_blocks + y]) { + for (u8 y = 0; y < transform_size_in_sub_blocks && y < left_non_zero_tokens_in_block[plane].size() - sub_block_row; y++) { + if (left_non_zero_tokens_in_block[plane][sub_block_row + y]) { left_has_non_zero_tokens = true; break; } diff --git a/Userland/Libraries/LibVideo/VP9/TreeParser.h b/Userland/Libraries/LibVideo/VP9/TreeParser.h index 349a4d4f16..82fa9f6b11 100644 --- a/Userland/Libraries/LibVideo/VP9/TreeParser.h +++ b/Userland/Libraries/LibVideo/VP9/TreeParser.h @@ -87,7 +87,7 @@ public: static ErrorOr<u8> parse_motion_vector_fr(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, u8 component); static ErrorOr<bool> parse_motion_vector_hp(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, u8 component, bool use_hp); - static TokensContext get_context_for_first_token(BlockContext const& block_context, Array<Vector<bool>, 3> const& above_non_zero_tokens, Array<Vector<bool>, 3> const& 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_first_token(BlockContext const& block_context, Array<Vector<bool>, 3> const& above_non_zero_tokens, NonZeroTokensView left_non_zero_tokens, TransformSize transform_size, u8 plane, u32 sub_block_column, u32 sub_block_row, bool is_inter, u8 band); static TokensContext get_context_for_other_tokens(Array<u8, 1024> token_cache, TransformSize transform_size, TransformSet transform_set, u8 plane, u16 token_position, bool is_inter, u8 band); static ErrorOr<bool> parse_more_coefficients(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, TokensContext const& context); static ErrorOr<Token> parse_token(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, TokensContext const& context); diff --git a/Userland/Libraries/LibVideo/VP9/Utilities.h b/Userland/Libraries/LibVideo/VP9/Utilities.h index 027833c401..ebdab25fe2 100644 --- a/Userland/Libraries/LibVideo/VP9/Utilities.h +++ b/Userland/Libraries/LibVideo/VP9/Utilities.h @@ -45,6 +45,11 @@ inline T brev(C bit_count, T value) return result; } +inline BlockSubsize get_subsampled_block_size(BlockSubsize size, bool subsampling_x, bool subsampling_y) +{ + return ss_size_lookup[size < Block_8x8 ? Block_8x8 : size][subsampling_x][subsampling_y]; +} + inline Gfx::Size<u8> block_size_to_sub_blocks(BlockSubsize size) { return Gfx::Size<u8>(num_4x4_blocks_wide_lookup[size], num_4x4_blocks_high_lookup[size]); |