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

LibVideo/VP9: Split/clean up the token tree-parsing context function

Since the context information for parsing residual tokens changes based
on whether we're parsing the first coefficient or subsequent ones, the
TreeParser::get_tokens_context function was split into two new ones to
allow them to read more cleanly. All variables now have meaningful
names to aid in readability as well.

The math used in the function for the first token was changed to
be more friendly to tile- or block-specific coordinates to facilitate
range-restricted Spans of the above and left context arrays.
This commit is contained in:
Zaggy1024 2022-11-28 00:15:53 -06:00 committed by Andreas Kling
parent 3667f9bf2c
commit 06082d310f
3 changed files with 68 additions and 52 deletions

View file

@ -7,10 +7,12 @@
#include <AK/Function.h>
#include "Context.h"
#include "Enums.h"
#include "LookupTables.h"
#include "Parser.h"
#include "TreeParser.h"
#include "Utilities.h"
namespace Video::VP9 {
@ -624,54 +626,62 @@ ErrorOr<bool> TreeParser::parse_motion_vector_hp(BitStream& bit_stream, Probabil
return value;
}
TokensContext TreeParser::get_tokens_context(bool subsampling_x, bool subsampling_y, u32 rows, u32 columns, Array<Vector<bool>, 3> const& above_nonzero_context, Array<Vector<bool>, 3> const& left_nonzero_context, Array<u8, 1024> token_cache, TransformSize transform_size, TransformSet transform_set, u8 plane, u32 start_x, u32 start_y, u16 position, bool is_inter, u8 band, u16 coef_index)
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)
{
u8 context;
if (coef_index == 0) {
auto sx = plane > 0 ? subsampling_x : false;
auto sy = plane > 0 ? subsampling_y : false;
auto max_x = (2 * columns) >> sx;
auto max_y = (2 * rows) >> sy;
u8 numpts = 1 << transform_size;
auto x4 = start_x >> 2;
auto y4 = start_y >> 2;
u32 above = 0;
u32 left = 0;
for (size_t i = 0; i < numpts; i++) {
if (x4 + i < max_x)
above |= above_nonzero_context[plane][x4 + i];
if (y4 + i < max_y)
left |= left_nonzero_context[plane][y4 + i];
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;
for (u8 x = 0; x < transform_size_in_sub_blocks && x < above_non_zero_tokens[plane].size() - transform_left_in_sub_blocks; x++) {
if (above_non_zero_tokens[plane][transform_left_in_sub_blocks + x]) {
above_has_non_zero_tokens = true;
break;
}
context = above + left;
} else {
u32 neighbor_0, neighbor_1;
auto n = 4 << transform_size;
auto i = position / n;
auto j = position % n;
auto a = i > 0 ? (i - 1) * n + j : 0;
auto a2 = i * n + j - 1;
if (i > 0 && j > 0) {
if (transform_set == TransformSet { TransformType::DCT, TransformType::ADST }) {
neighbor_0 = a;
neighbor_1 = a;
} else if (transform_set == TransformSet { TransformType::ADST, TransformType::DCT }) {
neighbor_0 = a2;
neighbor_1 = a2;
} else {
neighbor_0 = a;
neighbor_1 = a2;
}
} else if (i > 0) {
neighbor_0 = a;
neighbor_1 = a;
} else {
neighbor_0 = a2;
neighbor_1 = a2;
}
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]) {
left_has_non_zero_tokens = true;
break;
}
context = (1 + token_cache[neighbor_0] + token_cache[neighbor_1]) >> 1;
}
u8 context = above_has_non_zero_tokens + left_has_non_zero_tokens;
return TokensContext { transform_size, plane > 0, is_inter, band, context };
}
TokensContext TreeParser::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)
{
auto transform_size_in_pixels = sub_blocks_to_pixels(transform_size_to_sub_blocks(transform_size));
auto log2_of_transform_size = transform_size + 2;
auto pixel_y = token_position >> log2_of_transform_size;
auto pixel_x = token_position - (pixel_y << log2_of_transform_size);
auto above_token_energy = pixel_y > 0 ? (pixel_y - 1) * transform_size_in_pixels + pixel_x : 0;
auto left_token_energy = pixel_y * transform_size_in_pixels + pixel_x - 1;
u32 neighbor_a, neighbor_b;
if (pixel_y > 0 && pixel_x > 0) {
if (transform_set == TransformSet { TransformType::DCT, TransformType::ADST }) {
neighbor_a = above_token_energy;
neighbor_b = above_token_energy;
} else if (transform_set == TransformSet { TransformType::ADST, TransformType::DCT }) {
neighbor_a = left_token_energy;
neighbor_b = left_token_energy;
} else {
neighbor_a = above_token_energy;
neighbor_b = left_token_energy;
}
} else if (pixel_y > 0) {
neighbor_a = above_token_energy;
neighbor_b = above_token_energy;
} else {
neighbor_a = left_token_energy;
neighbor_b = left_token_energy;
}
u8 context = (1 + token_cache[neighbor_a] + token_cache[neighbor_b]) >> 1;
return TokensContext { transform_size, plane > 0, is_inter, band, context };
}