1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 14:07:45 +00:00

LibVideo/VP9: Move segmentation id prediction context to TileContext

These can also be stored in the same places as the non-zero tokens
contexts.
This commit is contained in:
Zaggy1024 2022-11-28 04:56:04 -06:00 committed by Andreas Kling
parent 9df72080a1
commit 1fe22f2141
5 changed files with 31 additions and 19 deletions

View file

@ -175,7 +175,7 @@ static NonZeroTokensView create_non_zero_tokens_view(NonZeroTokens& non_zero_tok
struct TileContext { struct TileContext {
public: public:
static ErrorOr<TileContext> try_create(FrameContext& frame_context, u32 rows_start, u32 rows_end, u32 columns_start, u32 columns_end, NonZeroTokensView above_non_zero_tokens) static ErrorOr<TileContext> try_create(FrameContext& frame_context, u32 rows_start, u32 rows_end, u32 columns_start, u32 columns_end, NonZeroTokensView above_non_zero_tokens, SegmentationPredictionContextView above_segmentation_ids)
{ {
auto context_view = frame_context.m_block_contexts.view(rows_start, columns_start, rows_end - rows_start, columns_end - columns_start); auto context_view = frame_context.m_block_contexts.view(rows_start, columns_start, rows_end - rows_start, columns_end - columns_start);
@ -187,7 +187,9 @@ public:
columns_end, columns_end,
context_view, context_view,
above_non_zero_tokens, above_non_zero_tokens,
above_segmentation_ids,
TRY(create_non_zero_tokens(blocks_to_sub_blocks(rows_end - rows_start), frame_context.color_config.subsampling_y)), TRY(create_non_zero_tokens(blocks_to_sub_blocks(rows_end - rows_start), frame_context.color_config.subsampling_y)),
TRY(SegmentationPredictionContext::try_create(rows_end - rows_start)),
}; };
} }
@ -203,7 +205,9 @@ public:
Vector2DView<FrameBlockContext> block_contexts_view; Vector2DView<FrameBlockContext> block_contexts_view;
NonZeroTokensView above_non_zero_tokens; NonZeroTokensView above_non_zero_tokens;
SegmentationPredictionContextView above_segmentation_ids;
NonZeroTokens left_non_zero_tokens; NonZeroTokens left_non_zero_tokens;
SegmentationPredictionContext left_segmentation_ids;
}; };
struct BlockContext { struct BlockContext {
@ -215,6 +219,7 @@ struct BlockContext {
min<u32>(num_8x8_blocks_high_lookup[size], tile_context.frame_context.rows() - row), 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)); min<u32>(num_8x8_blocks_wide_lookup[size], tile_context.frame_context.columns() - column));
auto size_in_blocks = block_size_to_blocks(size);
auto size_in_sub_blocks = block_size_to_sub_blocks(get_subsampled_block_size(size, false, false)); auto size_in_sub_blocks = block_size_to_sub_blocks(get_subsampled_block_size(size, false, false));
return BlockContext { return BlockContext {
@ -225,7 +230,9 @@ struct BlockContext {
.size = size, .size = size,
.contexts_view = contexts_view, .contexts_view = contexts_view,
.above_non_zero_tokens = create_non_zero_tokens_view(tile_context.above_non_zero_tokens, blocks_to_sub_blocks(column - tile_context.columns_start), size_in_sub_blocks.width(), tile_context.frame_context.color_config.subsampling_x), .above_non_zero_tokens = create_non_zero_tokens_view(tile_context.above_non_zero_tokens, blocks_to_sub_blocks(column - tile_context.columns_start), size_in_sub_blocks.width(), tile_context.frame_context.color_config.subsampling_x),
.above_segmentation_ids = safe_slice(tile_context.above_segmentation_ids, column - tile_context.columns_start, size_in_blocks.width()),
.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), .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),
.left_segmentation_ids = safe_slice(tile_context.left_segmentation_ids.span(), row - tile_context.rows_start, size_in_blocks.height()),
}; };
} }
@ -266,7 +273,9 @@ struct BlockContext {
Array<u8, 4> mode_context {}; Array<u8, 4> mode_context {};
NonZeroTokensView above_non_zero_tokens; NonZeroTokensView above_non_zero_tokens;
SegmentationPredictionContextView above_segmentation_ids;
NonZeroTokensView left_non_zero_tokens; NonZeroTokensView left_non_zero_tokens;
SegmentationPredictionContextView left_segmentation_ids;
}; };
struct BlockMotionVectorCandidateSet { struct BlockMotionVectorCandidateSet {

View file

@ -251,4 +251,7 @@ using BlockMotionVectorCandidates = ReferencePair<BlockMotionVectorCandidateSet>
using NonZeroTokens = Array<FixedArray<bool>, 3>; using NonZeroTokens = Array<FixedArray<bool>, 3>;
using NonZeroTokensView = Array<Span<bool>, 3>; using NonZeroTokensView = Array<Span<bool>, 3>;
using SegmentationPredictionContext = FixedArray<u8>;
using SegmentationPredictionContextView = Span<u8>;
} }

View file

@ -851,6 +851,7 @@ DecoderErrorOr<void> Parser::decode_tiles(FrameContext& frame_context)
clear_above_context(frame_context); clear_above_context(frame_context);
NonZeroTokens above_non_zero_tokens = DECODER_TRY_ALLOC(create_non_zero_tokens(blocks_to_sub_blocks(frame_context.columns()), frame_context.color_config.subsampling_x)); NonZeroTokens above_non_zero_tokens = DECODER_TRY_ALLOC(create_non_zero_tokens(blocks_to_sub_blocks(frame_context.columns()), frame_context.color_config.subsampling_x));
SegmentationPredictionContext above_segmentation_ids = DECODER_TRY_ALLOC(SegmentationPredictionContext::try_create(frame_context.columns()));
// FIXME: To implement tiled decoding, we'll need to pre-parse the tile positions and sizes into a 2D vector of ReadonlyBytes, // FIXME: To implement tiled decoding, we'll need to pre-parse the tile positions and sizes into a 2D vector of ReadonlyBytes,
// then run through each column of tiles in top to bottom order afterward. Each column can be sent to a worker thread // then run through each column of tiles in top to bottom order afterward. Each column can be sent to a worker thread
@ -871,8 +872,9 @@ DecoderErrorOr<void> Parser::decode_tiles(FrameContext& frame_context)
auto columns_end = get_tile_offset(tile_col + 1, frame_context.columns(), log2_dimensions.width()); auto columns_end = get_tile_offset(tile_col + 1, frame_context.columns(), log2_dimensions.width());
auto above_non_zero_tokens_view = create_non_zero_tokens_view(above_non_zero_tokens, blocks_to_sub_blocks(columns_start), blocks_to_sub_blocks(columns_end - columns_start), frame_context.color_config.subsampling_x); auto above_non_zero_tokens_view = create_non_zero_tokens_view(above_non_zero_tokens, blocks_to_sub_blocks(columns_start), blocks_to_sub_blocks(columns_end - columns_start), frame_context.color_config.subsampling_x);
auto above_segmentation_ids_for_tile = safe_slice(above_segmentation_ids.span(), columns_start, columns_end - columns_start);
auto tile_context = DECODER_TRY_ALLOC(TileContext::try_create(frame_context, rows_start, rows_end, columns_start, columns_end, above_non_zero_tokens_view)); auto tile_context = DECODER_TRY_ALLOC(TileContext::try_create(frame_context, rows_start, rows_end, columns_start, columns_end, above_non_zero_tokens_view, above_segmentation_ids_for_tile));
TRY_READ(m_bit_stream->init_bool(tile_size)); TRY_READ(m_bit_stream->init_bool(tile_size));
TRY(decode_tile(tile_context)); TRY(decode_tile(tile_context));
@ -900,7 +902,6 @@ void Parser::clear_context(Vector<Vector<T>>& context, size_t outer_size, size_t
void Parser::clear_above_context(FrameContext& frame_context) void Parser::clear_above_context(FrameContext& frame_context)
{ {
clear_context(m_above_seg_pred_context, frame_context.columns());
clear_context(m_above_partition_context, frame_context.superblock_columns() * 8); clear_context(m_above_partition_context, frame_context.superblock_columns() * 8);
} }
@ -926,7 +927,7 @@ void Parser::clear_left_context(TileContext& tile_context)
{ {
for (auto& context_for_plane : tile_context.left_non_zero_tokens) for (auto& context_for_plane : tile_context.left_non_zero_tokens)
context_for_plane.fill_with(false); context_for_plane.fill_with(false);
clear_context(m_left_seg_pred_context, tile_context.frame_context.rows()); tile_context.left_segmentation_ids.fill_with(0);
clear_context(m_left_partition_context, tile_context.frame_context.superblock_rows() * 8); clear_context(m_left_partition_context, tile_context.frame_context.superblock_rows() * 8);
} }
@ -1095,24 +1096,20 @@ DecoderErrorOr<void> Parser::set_inter_segment_id(BlockContext& block_context)
return {}; return {};
} }
auto seg_id_predicted = TRY_READ(TreeParser::parse_segment_id_predicted(*m_bit_stream, block_context.frame_context.predicted_segment_id_tree_probabilities, m_left_seg_pred_context[block_context.row], m_above_seg_pred_context[block_context.column])); auto above_segmentation_id = block_context.tile_context.above_segmentation_ids[block_context.row - block_context.tile_context.rows_start];
auto left_segmentation_id = block_context.tile_context.left_segmentation_ids[block_context.column - block_context.tile_context.columns_start];
auto seg_id_predicted = TRY_READ(TreeParser::parse_segment_id_predicted(*m_bit_stream, block_context.frame_context.predicted_segment_id_tree_probabilities, above_segmentation_id, left_segmentation_id));
if (seg_id_predicted) if (seg_id_predicted)
block_context.segment_id = predicted_segment_id; block_context.segment_id = predicted_segment_id;
else else
block_context.segment_id = TRY_READ(TreeParser::parse_segment_id(*m_bit_stream, block_context.frame_context.full_segment_id_tree_probabilities)); block_context.segment_id = TRY_READ(TreeParser::parse_segment_id(*m_bit_stream, block_context.frame_context.full_segment_id_tree_probabilities));
for (size_t i = 0; i < num_8x8_blocks_wide_lookup[block_context.size]; i++) {
auto index = block_context.column + i;
// (7.4.1) AboveSegPredContext[ i ] only needs to be set to 0 for i = 0..MiCols-1. // (7.4.1) AboveSegPredContext[ i ] only needs to be set to 0 for i = 0..MiCols-1.
if (index < m_above_seg_pred_context.size()) // This is taken care of by the slicing in BlockContext.
m_above_seg_pred_context[index] = seg_id_predicted; block_context.above_segmentation_ids.fill(seg_id_predicted);
}
for (size_t i = 0; i < num_8x8_blocks_high_lookup[block_context.size]; i++) {
auto index = block_context.row + i;
// (7.4.1) LeftSegPredContext[ i ] only needs to be set to 0 for i = 0..MiRows-1. // (7.4.1) LeftSegPredContext[ i ] only needs to be set to 0 for i = 0..MiRows-1.
if (index < m_above_seg_pred_context.size()) // This is taken care of by the slicing in BlockContext.
m_left_seg_pred_context[block_context.row + i] = seg_id_predicted; block_context.left_segmentation_ids.fill(seg_id_predicted);
}
return {}; return {};
} }

View file

@ -147,8 +147,6 @@ private:
Array<Array<SegmentFeature, SEG_LVL_MAX>, MAX_SEGMENTS> m_previous_segmentation_features; Array<Array<SegmentFeature, SEG_LVL_MAX>, MAX_SEGMENTS> m_previous_segmentation_features;
// FIXME: Move above and left contexts to structs // FIXME: Move above and left contexts to structs
Vector<u8> m_above_seg_pred_context;
Vector<u8> m_left_seg_pred_context;
Vector<u8> m_above_partition_context; Vector<u8> m_above_partition_context;
Vector<u8> m_left_partition_context; Vector<u8> m_left_partition_context;

View file

@ -50,6 +50,11 @@ inline BlockSubsize get_subsampled_block_size(BlockSubsize size, bool subsamplin
return ss_size_lookup[size < Block_8x8 ? Block_8x8 : size][subsampling_x][subsampling_y]; return ss_size_lookup[size < Block_8x8 ? Block_8x8 : size][subsampling_x][subsampling_y];
} }
inline Gfx::Size<u8> block_size_to_blocks(BlockSubsize size)
{
return Gfx::Size<u8>(num_8x8_blocks_wide_lookup[size], num_8x8_blocks_high_lookup[size]);
}
inline Gfx::Size<u8> block_size_to_sub_blocks(BlockSubsize size) 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]); return Gfx::Size<u8>(num_4x4_blocks_wide_lookup[size], num_4x4_blocks_high_lookup[size]);