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

LibVideo/VP9: Replace (DCT|ADST)_(DCT_ADST) with struct TransformSet

Those previous constants were only set and used to select the first and
second transforms done by the Decoder class. By turning it into a
struct, we can make the code a bit more legible while keeping those
transform modes the same size as before or smaller.
This commit is contained in:
Zaggy1024 2022-11-25 20:45:56 -06:00 committed by Andreas Kling
parent 062da60443
commit facb779b99
9 changed files with 65 additions and 55 deletions

View file

@ -1066,7 +1066,7 @@ u16 Decoder::get_ac_quantizer(BlockContext const& block_context, u8 plane)
return ac_q(block_context.frame_context.color_config.bit_depth, static_cast<u8>(get_base_quantizer_index(block_context) + offset)); return ac_q(block_context.frame_context.color_config.bit_depth, static_cast<u8>(get_base_quantizer_index(block_context) + offset));
} }
DecoderErrorOr<void> Decoder::reconstruct(u8 plane, BlockContext const& block_context, u32 transform_block_x, u32 transform_block_y, TXSize transform_block_size, u8 transform_type) DecoderErrorOr<void> Decoder::reconstruct(u8 plane, BlockContext const& block_context, u32 transform_block_x, u32 transform_block_y, TXSize transform_block_size, TransformSet transform_set)
{ {
// 8.6.2 Reconstruct process // 8.6.2 Reconstruct process
@ -1100,7 +1100,7 @@ DecoderErrorOr<void> Decoder::reconstruct(u8 plane, BlockContext const& block_co
// 3. Invoke the 2D inverse transform block process defined in section 8.7.2 with the variable n as input. // 3. Invoke the 2D inverse transform block process defined in section 8.7.2 with the variable n as input.
// The inverse transform outputs are stored back to the Dequant buffer. // The inverse transform outputs are stored back to the Dequant buffer.
TRY(inverse_transform_2d(block_context, dequantized, log2_of_block_size, transform_type)); TRY(inverse_transform_2d(block_context, dequantized, log2_of_block_size, transform_set));
// 4. CurrFrame[ plane ][ y + i ][ x + j ] is set equal to Clip1( CurrFrame[ plane ][ y + i ][ x + j ] + Dequant[ i ][ j ] ) // 4. CurrFrame[ plane ][ y + i ][ x + j ] is set equal to Clip1( CurrFrame[ plane ][ y + i ][ x + j ] + Dequant[ i ][ j ] )
// for i = 0..(n0-1) and j = 0..(n0-1). // for i = 0..(n0-1) and j = 0..(n0-1).
@ -1653,7 +1653,7 @@ inline DecoderErrorOr<void> Decoder::inverse_asymmetric_discrete_sine_transform(
return inverse_asymmetric_discrete_sine_transform_16(bit_depth, data); return inverse_asymmetric_discrete_sine_transform_16(bit_depth, data);
} }
DecoderErrorOr<void> Decoder::inverse_transform_2d(BlockContext const& block_context, Span<Intermediate> dequantized, u8 log2_of_block_size, u8 transform_type) DecoderErrorOr<void> Decoder::inverse_transform_2d(BlockContext const& block_context, Span<Intermediate> dequantized, u8 log2_of_block_size, TransformSet transform_set)
{ {
// This process performs a 2D inverse transform for an array of size 2^n by 2^n stored in the 2D array Dequant. // This process performs a 2D inverse transform for an array of size 2^n by 2^n stored in the 2D array Dequant.
// The input to this process is a variable n (log2_of_block_size) that specifies the base 2 logarithm of the width of the transform. // The input to this process is a variable n (log2_of_block_size) that specifies the base 2 logarithm of the width of the transform.
@ -1676,9 +1676,8 @@ DecoderErrorOr<void> Decoder::inverse_transform_2d(BlockContext const& block_con
TRY(inverse_walsh_hadamard_transform(row, log2_of_block_size, 2)); TRY(inverse_walsh_hadamard_transform(row, log2_of_block_size, 2));
continue; continue;
} }
switch (transform_type) { switch (transform_set.second_transform) {
case DCT_DCT: case TransformType::DCT:
case ADST_DCT:
// Otherwise, if TxType is equal to DCT_DCT or TxType is equal to ADST_DCT, apply an inverse DCT as // Otherwise, if TxType is equal to DCT_DCT or TxType is equal to ADST_DCT, apply an inverse DCT as
// follows: // follows:
// 1. Invoke the inverse DCT permutation process as specified in section 8.7.1.2 with the input variable n. // 1. Invoke the inverse DCT permutation process as specified in section 8.7.1.2 with the input variable n.
@ -1686,8 +1685,7 @@ DecoderErrorOr<void> Decoder::inverse_transform_2d(BlockContext const& block_con
// 2. Invoke the inverse DCT process as specified in section 8.7.1.3 with the input variable n. // 2. Invoke the inverse DCT process as specified in section 8.7.1.3 with the input variable n.
TRY(inverse_discrete_cosine_transform(block_context.frame_context.color_config.bit_depth, row, log2_of_block_size)); TRY(inverse_discrete_cosine_transform(block_context.frame_context.color_config.bit_depth, row, log2_of_block_size));
break; break;
case DCT_ADST: case TransformType::ADST:
case ADST_ADST:
// 4. Otherwise (TxType is equal to DCT_ADST or TxType is equal to ADST_ADST), invoke the inverse ADST // 4. Otherwise (TxType is equal to DCT_ADST or TxType is equal to ADST_ADST), invoke the inverse ADST
// process as specified in section 8.7.1.9 with input variable n. // process as specified in section 8.7.1.9 with input variable n.
TRY(inverse_asymmetric_discrete_sine_transform(block_context.frame_context.color_config.bit_depth, row, log2_of_block_size)); TRY(inverse_asymmetric_discrete_sine_transform(block_context.frame_context.color_config.bit_depth, row, log2_of_block_size));
@ -1716,9 +1714,8 @@ DecoderErrorOr<void> Decoder::inverse_transform_2d(BlockContext const& block_con
TRY(inverse_walsh_hadamard_transform(column, log2_of_block_size, 2)); TRY(inverse_walsh_hadamard_transform(column, log2_of_block_size, 2));
continue; continue;
} }
switch (transform_type) { switch (transform_set.first_transform) {
case DCT_DCT: case TransformType::DCT:
case DCT_ADST:
// Otherwise, if TxType is equal to DCT_DCT or TxType is equal to DCT_ADST, apply an inverse DCT as // Otherwise, if TxType is equal to DCT_DCT or TxType is equal to DCT_ADST, apply an inverse DCT as
// follows: // follows:
// 1. Invoke the inverse DCT permutation process as specified in section 8.7.1.2 with the input variable n. // 1. Invoke the inverse DCT permutation process as specified in section 8.7.1.2 with the input variable n.
@ -1726,8 +1723,7 @@ DecoderErrorOr<void> Decoder::inverse_transform_2d(BlockContext const& block_con
// 2. Invoke the inverse DCT process as specified in section 8.7.1.3 with the input variable n. // 2. Invoke the inverse DCT process as specified in section 8.7.1.3 with the input variable n.
TRY(inverse_discrete_cosine_transform(block_context.frame_context.color_config.bit_depth, column, log2_of_block_size)); TRY(inverse_discrete_cosine_transform(block_context.frame_context.color_config.bit_depth, column, log2_of_block_size));
break; break;
case ADST_DCT: case TransformType::ADST:
case ADST_ADST:
// 4. Otherwise (TxType is equal to ADST_DCT or TxType is equal to ADST_ADST), invoke the inverse ADST // 4. Otherwise (TxType is equal to ADST_DCT or TxType is equal to ADST_ADST), invoke the inverse ADST
// process as specified in section 8.7.1.9 with input variable n. // process as specified in section 8.7.1.9 with input variable n.
TRY(inverse_asymmetric_discrete_sine_transform(block_context.frame_context.color_config.bit_depth, column, log2_of_block_size)); TRY(inverse_asymmetric_discrete_sine_transform(block_context.frame_context.color_config.bit_depth, column, log2_of_block_size));

View file

@ -81,10 +81,10 @@ private:
static u16 get_ac_quantizer(BlockContext const&, u8 plane); static u16 get_ac_quantizer(BlockContext const&, u8 plane);
// (8.6.2) Reconstruct process // (8.6.2) Reconstruct process
DecoderErrorOr<void> reconstruct(u8 plane, BlockContext const&, u32 transform_block_x, u32 transform_block_y, TXSize transform_block_size, u8 transform_type); DecoderErrorOr<void> reconstruct(u8 plane, BlockContext const&, u32 transform_block_x, u32 transform_block_y, TXSize transform_block_size, TransformSet);
// (8.7) Inverse transform process // (8.7) Inverse transform process
DecoderErrorOr<void> inverse_transform_2d(BlockContext const&, Span<Intermediate> dequantized, u8 log2_of_block_size, u8 transform_type); DecoderErrorOr<void> inverse_transform_2d(BlockContext const&, Span<Intermediate> dequantized, u8 log2_of_block_size, TransformSet);
// (8.7.1) 1D Transforms // (8.7.1) 1D Transforms
// (8.7.1.1) Butterfly functions // (8.7.1.1) Butterfly functions

View file

@ -60,6 +60,21 @@ enum TXSize : u8 {
TX_32x32 = 3, TX_32x32 = 3,
}; };
enum class TransformType : u8 {
DCT = 0,
ADST = 1,
};
struct TransformSet {
TransformType first_transform : 1;
TransformType second_transform : 1;
bool operator==(TransformSet const& other) const
{
return first_transform == other.first_transform && second_transform == other.second_transform;
}
};
enum ReferenceMode : u8 { enum ReferenceMode : u8 {
SingleReference = 0, SingleReference = 0,
CompoundReference = 1, CompoundReference = 1,

File diff suppressed because one or more lines are too long

View file

@ -1344,13 +1344,13 @@ static TXSize get_uv_tx_size(bool subsampling_x, bool subsampling_y, TXSize tx_s
return min(tx_size, max_txsize_lookup[get_plane_block_size(subsampling_x, subsampling_y, size, 1)]); return min(tx_size, max_txsize_lookup[get_plane_block_size(subsampling_x, subsampling_y, size, 1)]);
} }
static u8 select_transform_type(BlockContext const& block_context, u8 plane, TXSize tx_size, u32 block_index) static TransformSet select_transform_type(BlockContext const& block_context, u8 plane, TXSize tx_size, u32 block_index)
{ {
if (plane > 0 || tx_size == TX_32x32) if (plane > 0 || tx_size == TX_32x32)
return DCT_DCT; return TransformSet { TransformType::DCT, TransformType::DCT };
if (tx_size == TX_4x4) { if (tx_size == TX_4x4) {
if (block_context.frame_context.is_lossless() || block_context.is_inter_predicted()) if (block_context.frame_context.is_lossless() || block_context.is_inter_predicted())
return DCT_DCT; return TransformSet { TransformType::DCT, TransformType::DCT };
return mode_to_txfm_map[to_underlying(block_context.size < Block_8x8 ? block_context.sub_block_prediction_modes[block_index] : block_context.y_prediction_mode())]; return mode_to_txfm_map[to_underlying(block_context.size < Block_8x8 ? block_context.sub_block_prediction_modes[block_index] : block_context.y_prediction_mode())];
} }
@ -1395,10 +1395,10 @@ DecoderErrorOr<bool> Parser::residual(BlockContext& block_context, bool has_bloc
if (!block_context.is_inter_predicted()) if (!block_context.is_inter_predicted())
TRY(m_decoder.predict_intra(plane, block_context, start_x, start_y, has_block_left || x > 0, has_block_above || y > 0, (x + step) < num_4x4_w, tx_size, block_index)); TRY(m_decoder.predict_intra(plane, block_context, start_x, start_y, has_block_left || x > 0, has_block_above || y > 0, (x + step) < num_4x4_w, tx_size, block_index));
if (!block_context.should_skip_residuals) { if (!block_context.should_skip_residuals) {
auto transform_type = select_transform_type(block_context, plane, tx_size, block_index); auto transform_set = select_transform_type(block_context, plane, tx_size, block_index);
non_zero = TRY(tokens(block_context, plane, start_x, start_y, tx_size, transform_type)); non_zero = TRY(tokens(block_context, plane, start_x, start_y, tx_size, transform_set));
had_residual_tokens = had_residual_tokens || non_zero; had_residual_tokens = had_residual_tokens || non_zero;
TRY(m_decoder.reconstruct(plane, block_context, start_x, start_y, tx_size, transform_type)); TRY(m_decoder.reconstruct(plane, block_context, start_x, start_y, tx_size, transform_set));
} }
} }
@ -1421,42 +1421,45 @@ DecoderErrorOr<bool> Parser::residual(BlockContext& block_context, bool has_bloc
return had_residual_tokens; return had_residual_tokens;
} }
static u16 const* get_scan(TXSize tx_size, u8 transform_type) static u16 const* get_scan(TXSize tx_size, TransformSet transform_set)
{ {
constexpr TransformSet adst_dct { TransformType::ADST, TransformType::DCT };
constexpr TransformSet dct_adst { TransformType::DCT, TransformType::ADST };
if (tx_size == TX_4x4) { if (tx_size == TX_4x4) {
if (transform_type == ADST_DCT) if (transform_set == adst_dct)
return row_scan_4x4; return row_scan_4x4;
if (transform_type == DCT_ADST) if (transform_set == dct_adst)
return col_scan_4x4; return col_scan_4x4;
return default_scan_4x4; return default_scan_4x4;
} }
if (tx_size == TX_8x8) { if (tx_size == TX_8x8) {
if (transform_type == ADST_DCT) if (transform_set == adst_dct)
return row_scan_8x8; return row_scan_8x8;
if (transform_type == DCT_ADST) if (transform_set == dct_adst)
return col_scan_8x8; return col_scan_8x8;
return default_scan_8x8; return default_scan_8x8;
} }
if (tx_size == TX_16x16) { if (tx_size == TX_16x16) {
if (transform_type == ADST_DCT) if (transform_set == adst_dct)
return row_scan_16x16; return row_scan_16x16;
if (transform_type == DCT_ADST) if (transform_set == dct_adst)
return col_scan_16x16; return col_scan_16x16;
return default_scan_16x16; return default_scan_16x16;
} }
return default_scan_32x32; return default_scan_32x32;
} }
DecoderErrorOr<bool> Parser::tokens(BlockContext& block_context, size_t plane, u32 start_x, u32 start_y, TXSize tx_size, u8 transform_type) DecoderErrorOr<bool> Parser::tokens(BlockContext& block_context, size_t plane, u32 start_x, u32 start_y, TXSize tx_size, TransformSet transform_set)
{ {
u16 segment_eob = 16 << (tx_size << 1); u16 segment_eob = 16 << (tx_size << 1);
auto const* scan = get_scan(tx_size, transform_type); auto const* scan = get_scan(tx_size, transform_set);
auto check_eob = true; auto check_eob = true;
u16 coef_index = 0; u16 coef_index = 0;
for (; coef_index < segment_eob; coef_index++) { for (; coef_index < segment_eob; coef_index++) {
auto pos = scan[coef_index]; auto pos = scan[coef_index];
auto band = (tx_size == TX_4x4) ? coefband_4x4[coef_index] : coefband_8x8plus[coef_index]; auto band = (tx_size == TX_4x4) ? coefband_4x4[coef_index] : coefband_8x8plus[coef_index];
auto tokens_context = TreeParser::get_tokens_context(block_context.frame_context.color_config.subsampling_x, block_context.frame_context.color_config.subsampling_y, block_context.frame_context.rows(), block_context.frame_context.columns(), m_above_nonzero_context, m_left_nonzero_context, m_token_cache, tx_size, transform_type, plane, start_x, start_y, pos, block_context.is_inter_predicted(), band, coef_index); auto tokens_context = TreeParser::get_tokens_context(block_context.frame_context.color_config.subsampling_x, block_context.frame_context.color_config.subsampling_y, block_context.frame_context.rows(), block_context.frame_context.columns(), m_above_nonzero_context, m_left_nonzero_context, m_token_cache, tx_size, transform_set, plane, start_x, start_y, pos, block_context.is_inter_predicted(), band, coef_index);
if (check_eob) { if (check_eob) {
auto more_coefs = TRY_READ(TreeParser::parse_more_coefficients(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, tokens_context)); auto more_coefs = TRY_READ(TreeParser::parse_more_coefficients(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, tokens_context));
if (!more_coefs) if (!more_coefs)

View file

@ -117,7 +117,7 @@ private:
DecoderErrorOr<MotionVector> read_motion_vector(BlockContext const&, BlockMotionVectorCandidates const&, ReferenceIndex); DecoderErrorOr<MotionVector> read_motion_vector(BlockContext const&, BlockMotionVectorCandidates const&, ReferenceIndex);
DecoderErrorOr<i32> read_single_motion_vector_component(u8 component); DecoderErrorOr<i32> read_single_motion_vector_component(u8 component);
DecoderErrorOr<bool> residual(BlockContext&, bool has_block_above, bool has_block_left); DecoderErrorOr<bool> residual(BlockContext&, bool has_block_above, bool has_block_left);
DecoderErrorOr<bool> tokens(BlockContext&, size_t plane, u32 x, u32 y, TXSize tx_size, u8 transform_type); DecoderErrorOr<bool> tokens(BlockContext&, size_t plane, u32 x, u32 y, TXSize tx_size, TransformSet);
DecoderErrorOr<i32> read_coef(u8 bit_depth, Token token); DecoderErrorOr<i32> read_coef(u8 bit_depth, Token token);
/* (6.5) Motion Vector Prediction */ /* (6.5) Motion Vector Prediction */

View file

@ -43,10 +43,6 @@ namespace Video::VP9 {
#define PARTITION_TYPES 4 #define PARTITION_TYPES 4
#define TX_SIZES 4 #define TX_SIZES 4
#define TX_MODES 5 #define TX_MODES 5
#define DCT_DCT 0
#define ADST_DCT 1
#define DCT_ADST 2
#define ADST_ADST 3
#define MB_MODE_COUNT 14 #define MB_MODE_COUNT 14
#define INTRA_MODES 10 #define INTRA_MODES 10
#define INTER_MODES 4 #define INTER_MODES 4

View file

@ -624,7 +624,7 @@ ErrorOr<bool> TreeParser::parse_motion_vector_hp(BitStream& bit_stream, Probabil
return value; 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, u8 token_cache[1024], TXSize tx_size, u8 tx_type, u8 plane, u32 start_x, u32 start_y, u16 position, bool is_inter, u8 band, u16 coef_index) 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, u8 token_cache[1024], TXSize tx_size, TransformSet transform_set, u8 plane, u32 start_x, u32 start_y, u16 position, bool is_inter, u8 band, u16 coef_index)
{ {
u8 context; u8 context;
if (coef_index == 0) { if (coef_index == 0) {
@ -652,10 +652,10 @@ TokensContext TreeParser::get_tokens_context(bool subsampling_x, bool subsamplin
auto a = i > 0 ? (i - 1) * n + j : 0; auto a = i > 0 ? (i - 1) * n + j : 0;
auto a2 = i * n + j - 1; auto a2 = i * n + j - 1;
if (i > 0 && j > 0) { if (i > 0 && j > 0) {
if (tx_type == DCT_ADST) { if (transform_set == TransformSet { TransformType::DCT, TransformType::ADST }) {
neighbor_0 = a; neighbor_0 = a;
neighbor_1 = a; neighbor_1 = a;
} else if (tx_type == ADST_DCT) { } else if (transform_set == TransformSet { TransformType::ADST, TransformType::DCT }) {
neighbor_0 = a2; neighbor_0 = a2;
neighbor_1 = a2; neighbor_1 = a2;
} else { } else {

View file

@ -76,7 +76,7 @@ public:
static ErrorOr<u8> parse_motion_vector_fr(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, u8 component); 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 ErrorOr<bool> parse_motion_vector_hp(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, u8 component, bool use_hp);
static TokensContext 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, u8 token_cache[1024], TXSize tx_size, u8 tx_type, u8 plane, u32 start_x, u32 start_y, u16 position, bool is_inter, u8 band, u16 coef_index); static TokensContext 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, u8 token_cache[1024], TXSize, TransformSet, u8 plane, u32 start_x, u32 start_y, u16 position, bool is_inter, u8 band, u16 coef_index);
static ErrorOr<bool> parse_more_coefficients(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, TokensContext const& context); 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); static ErrorOr<Token> parse_token(BitStream&, ProbabilityTables const&, SyntaxElementCounter&, TokensContext const& context);
}; };