diff --git a/Userland/Libraries/LibVideo/VP9/Decoder.cpp b/Userland/Libraries/LibVideo/VP9/Decoder.cpp index 8e6c1849c0..b4eafbf941 100644 --- a/Userland/Libraries/LibVideo/VP9/Decoder.cpp +++ b/Userland/Libraries/LibVideo/VP9/Decoder.cpp @@ -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(get_base_quantizer_index(block_context) + offset)); } -DecoderErrorOr Decoder::reconstruct(u8 plane, BlockContext const& block_context, u32 transform_block_x, u32 transform_block_y, TXSize transform_block_size) +DecoderErrorOr Decoder::reconstruct(u8 plane, BlockContext const& block_context, u32 transform_block_x, u32 transform_block_y, TXSize transform_block_size, u8 transform_type) { // 8.6.2 Reconstruct process @@ -1100,7 +1100,7 @@ DecoderErrorOr 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. // The inverse transform outputs are stored back to the Dequant buffer. - TRY(inverse_transform_2d(block_context, dequantized, log2_of_block_size)); + TRY(inverse_transform_2d(block_context, dequantized, log2_of_block_size, transform_type)); // 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). @@ -1653,7 +1653,7 @@ inline DecoderErrorOr Decoder::inverse_asymmetric_discrete_sine_transform( return inverse_asymmetric_discrete_sine_transform_16(bit_depth, data); } -DecoderErrorOr Decoder::inverse_transform_2d(BlockContext const& block_context, Span dequantized, u8 log2_of_block_size) +DecoderErrorOr Decoder::inverse_transform_2d(BlockContext const& block_context, Span dequantized, u8 log2_of_block_size, u8 transform_type) { // 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. @@ -1676,7 +1676,7 @@ DecoderErrorOr Decoder::inverse_transform_2d(BlockContext const& block_con TRY(inverse_walsh_hadamard_transform(row, log2_of_block_size, 2)); continue; } - switch (m_parser->m_tx_type) { + switch (transform_type) { case DCT_DCT: case ADST_DCT: // Otherwise, if TxType is equal to DCT_DCT or TxType is equal to ADST_DCT, apply an inverse DCT as @@ -1716,7 +1716,7 @@ DecoderErrorOr Decoder::inverse_transform_2d(BlockContext const& block_con TRY(inverse_walsh_hadamard_transform(column, log2_of_block_size, 2)); continue; } - switch (m_parser->m_tx_type) { + switch (transform_type) { case DCT_DCT: case DCT_ADST: // Otherwise, if TxType is equal to DCT_DCT or TxType is equal to DCT_ADST, apply an inverse DCT as diff --git a/Userland/Libraries/LibVideo/VP9/Decoder.h b/Userland/Libraries/LibVideo/VP9/Decoder.h index 19f4ccff59..fddcb569cb 100644 --- a/Userland/Libraries/LibVideo/VP9/Decoder.h +++ b/Userland/Libraries/LibVideo/VP9/Decoder.h @@ -81,10 +81,10 @@ private: static u16 get_ac_quantizer(BlockContext const&, u8 plane); // (8.6.2) Reconstruct process - DecoderErrorOr reconstruct(u8 plane, BlockContext const&, u32 transform_block_x, u32 transform_block_y, TXSize transform_block_size); + DecoderErrorOr reconstruct(u8 plane, BlockContext const&, u32 transform_block_x, u32 transform_block_y, TXSize transform_block_size, u8 transform_type); // (8.7) Inverse transform process - DecoderErrorOr inverse_transform_2d(BlockContext const&, Span dequantized, u8 log2_of_block_size); + DecoderErrorOr inverse_transform_2d(BlockContext const&, Span dequantized, u8 log2_of_block_size, u8 transform_type); // (8.7.1) 1D Transforms // (8.7.1.1) Butterfly functions diff --git a/Userland/Libraries/LibVideo/VP9/Parser.cpp b/Userland/Libraries/LibVideo/VP9/Parser.cpp index 6ee811b401..e8ffd00c14 100644 --- a/Userland/Libraries/LibVideo/VP9/Parser.cpp +++ b/Userland/Libraries/LibVideo/VP9/Parser.cpp @@ -1344,6 +1344,20 @@ 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)]); } +static u8 select_transform_type(BlockContext const& block_context, u8 plane, TXSize tx_size, u32 block_index) +{ + if (plane > 0 || tx_size == TX_32x32) + return DCT_DCT; + if (tx_size == TX_4x4) { + if (block_context.frame_context.is_lossless() || block_context.is_inter_predicted()) + return DCT_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.y_prediction_mode())]; +} + DecoderErrorOr Parser::residual(BlockContext& block_context, bool has_block_above, bool has_block_left) { bool had_residual_tokens = false; @@ -1381,9 +1395,10 @@ DecoderErrorOr Parser::residual(BlockContext& block_context, bool has_bloc 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)); if (!block_context.should_skip_residuals) { - non_zero = TRY(tokens(block_context, plane, start_x, start_y, tx_size, block_index)); + auto transform_type = 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)); had_residual_tokens = had_residual_tokens || non_zero; - TRY(m_decoder.reconstruct(plane, block_context, start_x, start_y, tx_size)); + TRY(m_decoder.reconstruct(plane, block_context, start_x, start_y, tx_size, transform_type)); } } @@ -1406,16 +1421,42 @@ DecoderErrorOr Parser::residual(BlockContext& block_context, bool has_bloc return had_residual_tokens; } -DecoderErrorOr Parser::tokens(BlockContext& block_context, size_t plane, u32 start_x, u32 start_y, TXSize tx_size, u32 block_index) +static u32 const* get_scan(TXSize tx_size, u8 transform_type) +{ + if (tx_size == TX_4x4) { + if (transform_type == ADST_DCT) + return row_scan_4x4; + if (transform_type == DCT_ADST) + return col_scan_4x4; + return default_scan_4x4; + } + if (tx_size == TX_8x8) { + if (transform_type == ADST_DCT) + return row_scan_8x8; + if (transform_type == DCT_ADST) + return col_scan_8x8; + return default_scan_8x8; + } + if (tx_size == TX_16x16) { + if (transform_type == ADST_DCT) + return row_scan_16x16; + if (transform_type == DCT_ADST) + return col_scan_16x16; + return default_scan_16x16; + } + return default_scan_32x32; +} + +DecoderErrorOr Parser::tokens(BlockContext& block_context, size_t plane, u32 start_x, u32 start_y, TXSize tx_size, u8 transform_type) { u32 segment_eob = 16 << (tx_size << 1); - auto const* scan = get_scan(block_context, plane, tx_size, block_index); + auto const* scan = get_scan(tx_size, transform_type); auto check_eob = true; u32 c = 0; for (; c < segment_eob; c++) { auto pos = scan[c]; auto band = (tx_size == TX_4x4) ? coefband_4x4[c] : coefband_8x8plus[c]; - 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, m_tx_type, plane, start_x, start_y, pos, block_context.is_inter_predicted(), band, c); + 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, c); if (check_eob) { auto more_coefs = TRY_READ(TreeParser::parse_more_coefficients(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, tokens_context)); if (!more_coefs) @@ -1438,42 +1479,6 @@ DecoderErrorOr Parser::tokens(BlockContext& block_context, size_t plane, u return c > 0; } -u32 const* Parser::get_scan(BlockContext const& block_context, size_t plane, TXSize tx_size, u32 block_index) -{ - if (plane > 0 || tx_size == TX_32x32) { - m_tx_type = DCT_DCT; - } else if (tx_size == TX_4x4) { - if (block_context.frame_context.is_lossless() || block_context.is_inter_predicted()) - m_tx_type = DCT_DCT; - else - m_tx_type = mode_to_txfm_map[to_underlying(block_context.size < Block_8x8 ? block_context.sub_block_prediction_modes[block_index] : block_context.y_prediction_mode())]; - } else { - m_tx_type = mode_to_txfm_map[to_underlying(block_context.y_prediction_mode())]; - } - if (tx_size == TX_4x4) { - if (m_tx_type == ADST_DCT) - return row_scan_4x4; - if (m_tx_type == DCT_ADST) - return col_scan_4x4; - return default_scan_4x4; - } - if (tx_size == TX_8x8) { - if (m_tx_type == ADST_DCT) - return row_scan_8x8; - if (m_tx_type == DCT_ADST) - return col_scan_8x8; - return default_scan_8x8; - } - if (tx_size == TX_16x16) { - if (m_tx_type == ADST_DCT) - return row_scan_16x16; - if (m_tx_type == DCT_ADST) - return col_scan_16x16; - return default_scan_16x16; - } - return default_scan_32x32; -} - DecoderErrorOr Parser::read_coef(u8 bit_depth, Token token) { auto cat = extra_bits[token][0]; diff --git a/Userland/Libraries/LibVideo/VP9/Parser.h b/Userland/Libraries/LibVideo/VP9/Parser.h index 29ecfb219b..5be850589e 100644 --- a/Userland/Libraries/LibVideo/VP9/Parser.h +++ b/Userland/Libraries/LibVideo/VP9/Parser.h @@ -117,8 +117,7 @@ private: DecoderErrorOr read_motion_vector(BlockContext const&, BlockMotionVectorCandidates const&, ReferenceIndex); DecoderErrorOr read_single_motion_vector_component(u8 component); DecoderErrorOr residual(BlockContext&, bool has_block_above, bool has_block_left); - DecoderErrorOr tokens(BlockContext&, size_t plane, u32 x, u32 y, TXSize tx_size, u32 block_index); - u32 const* get_scan(BlockContext const&, size_t plane, TXSize tx_size, u32 block_index); + DecoderErrorOr tokens(BlockContext&, size_t plane, u32 x, u32 y, TXSize tx_size, u8 transform_type); DecoderErrorOr read_coef(u8 bit_depth, Token token); /* (6.5) Motion Vector Prediction */ @@ -158,7 +157,6 @@ private: Vector m_frame_store[NUM_REF_FRAMES][3]; - u8 m_tx_type { 0 }; u8 m_token_cache[1024]; i32 m_tokens[1024]; bool m_use_hp { false };