summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Userland/Libraries/LibVideo/VP9/Context.h91
-rw-r--r--Userland/Libraries/LibVideo/VP9/ContextStorage.h3
-rw-r--r--Userland/Libraries/LibVideo/VP9/Parser.cpp29
-rw-r--r--Userland/Libraries/LibVideo/VP9/Parser.h1
-rw-r--r--Userland/Libraries/LibVideo/VP9/TreeParser.cpp8
-rw-r--r--Userland/Libraries/LibVideo/VP9/TreeParser.h2
-rw-r--r--Userland/Libraries/LibVideo/VP9/Utilities.h5
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]);