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

LibVideo/VP9: Remove m_mi_row and col fields from the parser

These are now passed as parameters to each function that uses them.
These will later be moved to a struct to further reduce the amount of
parameters that get passed around.

Above and left per-frame block contexts are now also parameters passed
to the functions that use them instead of being retrieved when needed
from a field. This will allow them to be more easily moved to a tile-
specific context later.
This commit is contained in:
Zaggy1024 2022-11-20 17:25:51 -06:00 committed by Andreas Kling
parent 4a4aa697d9
commit 10d207959d
4 changed files with 94 additions and 120 deletions

View file

@ -721,7 +721,7 @@ MotionVector Decoder::select_motion_vector(u8 plane, u8 ref_list, u32 block_inde
+ m_parser->m_block_mvs[ref_list][2] + m_parser->m_block_mvs[ref_list][3]); + m_parser->m_block_mvs[ref_list][2] + m_parser->m_block_mvs[ref_list][3]);
} }
MotionVector Decoder::clamp_motion_vector(u8 plane, MotionVector vector) MotionVector Decoder::clamp_motion_vector(u8 plane, u32 block_row, u32 block_column, MotionVector vector)
{ {
// FIXME: This function is named very similarly to Parser::clamp_mv. Rename one or the other? // FIXME: This function is named very similarly to Parser::clamp_mv. Rename one or the other?
@ -736,12 +736,12 @@ MotionVector Decoder::clamp_motion_vector(u8 plane, MotionVector vector)
// The output array clampedMv is specified by the following steps: // The output array clampedMv is specified by the following steps:
i32 blocks_high = num_8x8_blocks_high_lookup[m_parser->m_mi_size]; i32 blocks_high = num_8x8_blocks_high_lookup[m_parser->m_mi_size];
// Casts must be done here to prevent subtraction underflow from wrapping the values. // Casts must be done here to prevent subtraction underflow from wrapping the values.
i32 mb_to_top_edge = -(static_cast<i32>(m_parser->m_mi_row * MI_SIZE) * 16) >> subsampling_y; i32 mb_to_top_edge = -(static_cast<i32>(block_row * MI_SIZE) * 16) >> subsampling_y;
i32 mb_to_bottom_edge = (((static_cast<i32>(m_parser->m_mi_rows) - blocks_high - static_cast<i32>(m_parser->m_mi_row)) * MI_SIZE) * 16) >> subsampling_y; i32 mb_to_bottom_edge = (((static_cast<i32>(m_parser->m_mi_rows) - blocks_high - static_cast<i32>(block_row)) * MI_SIZE) * 16) >> subsampling_y;
i32 blocks_wide = num_8x8_blocks_wide_lookup[m_parser->m_mi_size]; i32 blocks_wide = num_8x8_blocks_wide_lookup[m_parser->m_mi_size];
i32 mb_to_left_edge = -(static_cast<i32>(m_parser->m_mi_col * MI_SIZE) * 16) >> subsampling_x; i32 mb_to_left_edge = -(static_cast<i32>(block_column * MI_SIZE) * 16) >> subsampling_x;
i32 mb_to_right_edge = (((static_cast<i32>(m_parser->m_mi_cols) - blocks_wide - static_cast<i32>(m_parser->m_mi_col)) * MI_SIZE) * 16) >> subsampling_x; i32 mb_to_right_edge = (((static_cast<i32>(m_parser->m_mi_cols) - blocks_wide - static_cast<i32>(block_column)) * MI_SIZE) * 16) >> subsampling_x;
i32 subpel_left = (INTERP_EXTEND + ((blocks_wide * MI_SIZE) >> subsampling_x)) << SUBPEL_BITS; i32 subpel_left = (INTERP_EXTEND + ((blocks_wide * MI_SIZE) >> subsampling_x)) << SUBPEL_BITS;
i32 subpel_right = subpel_left - SUBPEL_SHIFTS; i32 subpel_right = subpel_left - SUBPEL_SHIFTS;
@ -753,7 +753,7 @@ MotionVector Decoder::clamp_motion_vector(u8 plane, MotionVector vector)
}; };
} }
DecoderErrorOr<void> Decoder::predict_inter_block(u8 plane, u8 ref_list, u32 x, u32 y, u32 width, u32 height, u32 block_index, Span<u16> block_buffer) DecoderErrorOr<void> Decoder::predict_inter_block(u8 plane, u8 ref_list, u32 block_row, u32 block_column, u32 x, u32 y, u32 width, u32 height, u32 block_index, Span<u16> block_buffer)
{ {
VERIFY(width <= maximum_block_dimensions && height <= maximum_block_dimensions); VERIFY(width <= maximum_block_dimensions && height <= maximum_block_dimensions);
// 2. The motion vector selection process in section 8.5.2.1 is invoked with plane, refList, blockIdx as inputs // 2. The motion vector selection process in section 8.5.2.1 is invoked with plane, refList, blockIdx as inputs
@ -762,7 +762,7 @@ DecoderErrorOr<void> Decoder::predict_inter_block(u8 plane, u8 ref_list, u32 x,
// 3. The motion vector clamping process in section 8.5.2.2 is invoked with plane, mv as inputs and the output // 3. The motion vector clamping process in section 8.5.2.2 is invoked with plane, mv as inputs and the output
// being the clamped motion vector clampedMv // being the clamped motion vector clampedMv
auto clamped_vector = clamp_motion_vector(plane, motion_vector); auto clamped_vector = clamp_motion_vector(plane, block_row, block_column, motion_vector);
// 4. The motion vector scaling process in section 8.5.2.3 is invoked with plane, refList, x, y, clampedMv as // 4. The motion vector scaling process in section 8.5.2.3 is invoked with plane, refList, x, y, clampedMv as
// inputs and the output being the initial location startX, startY, and the step sizes stepX, stepY. // inputs and the output being the initial location startX, startY, and the step sizes stepX, stepY.
@ -923,7 +923,7 @@ DecoderErrorOr<void> Decoder::predict_inter_block(u8 plane, u8 ref_list, u32 x,
return {}; return {};
} }
DecoderErrorOr<void> Decoder::predict_inter(u8 plane, u32 x, u32 y, u32 width, u32 height, u32 block_index) DecoderErrorOr<void> Decoder::predict_inter(u8 plane, u32 block_row, u32 block_column, u32 x, u32 y, u32 width, u32 height, u32 block_index)
{ {
// The inter prediction process is invoked for inter coded blocks. When MiSize is smaller than BLOCK_8X8, the // The inter prediction process is invoked for inter coded blocks. When MiSize is smaller than BLOCK_8X8, the
// prediction is done with a granularity of 4x4 samples, otherwise the whole plane is predicted at the same time. // prediction is done with a granularity of 4x4 samples, otherwise the whole plane is predicted at the same time.
@ -942,7 +942,7 @@ DecoderErrorOr<void> Decoder::predict_inter(u8 plane, u32 x, u32 y, u32 width, u
// 2. through 5. // 2. through 5.
Array<u16, maximum_block_size> predicted_buffer; Array<u16, maximum_block_size> predicted_buffer;
auto predicted_span = predicted_buffer.span().trim(width * height); auto predicted_span = predicted_buffer.span().trim(width * height);
TRY(predict_inter_block(plane, 0, x, y, width, height, block_index, predicted_span)); TRY(predict_inter_block(plane, 0, block_row, block_column, x, y, width, height, block_index, predicted_span));
auto predicted_buffer_at = [&](Span<u16> buffer, u32 row, u32 column) -> u16& { auto predicted_buffer_at = [&](Span<u16> buffer, u32 row, u32 column) -> u16& {
return buffer[row * width + column]; return buffer[row * width + column];
}; };
@ -976,7 +976,7 @@ DecoderErrorOr<void> Decoder::predict_inter(u8 plane, u32 x, u32 y, u32 width, u
// for i = 0..h-1 and j = 0..w-1. // for i = 0..h-1 and j = 0..w-1.
Array<u16, maximum_block_size> second_predicted_buffer; Array<u16, maximum_block_size> second_predicted_buffer;
auto second_predicted_span = second_predicted_buffer.span().trim(width * height); auto second_predicted_span = second_predicted_buffer.span().trim(width * height);
TRY(predict_inter_block(plane, 1, x, y, width, height, block_index, second_predicted_span)); TRY(predict_inter_block(plane, 1, block_row, block_column, x, y, width, height, block_index, second_predicted_span));
for (auto i = 0u; i < height_in_frame_buffer; i++) { for (auto i = 0u; i < height_in_frame_buffer; i++) {
for (auto j = 0u; j < width_in_frame_buffer; j++) for (auto j = 0u; j < width_in_frame_buffer; j++)

View file

@ -61,15 +61,15 @@ private:
DecoderErrorOr<void> predict_intra(u8 plane, u32 x, u32 y, bool have_left, bool have_above, bool not_on_right, TXSize tx_size, u32 block_index); DecoderErrorOr<void> predict_intra(u8 plane, u32 x, u32 y, bool have_left, bool have_above, bool not_on_right, TXSize tx_size, u32 block_index);
// (8.5.1) Inter prediction process // (8.5.1) Inter prediction process
DecoderErrorOr<void> predict_inter(u8 plane, u32 x, u32 y, u32 width, u32 height, u32 block_index); DecoderErrorOr<void> predict_inter(u8 plane, u32 block_row, u32 block_column, u32 x, u32 y, u32 width, u32 height, u32 block_index);
// (8.5.2.1) Motion vector selection process // (8.5.2.1) Motion vector selection process
MotionVector select_motion_vector(u8 plane, u8 ref_list, u32 block_index); MotionVector select_motion_vector(u8 plane, u8 ref_list, u32 block_index);
// (8.5.2.2) Motion vector clamping process // (8.5.2.2) Motion vector clamping process
MotionVector clamp_motion_vector(u8 plane, MotionVector vector); MotionVector clamp_motion_vector(u8 plane, u32 block_row, u32 block_column, MotionVector vector);
// (8.5.2.3) Motion vector scaling process // (8.5.2.3) Motion vector scaling process
DecoderErrorOr<MotionVector> scale_motion_vector(u8 plane, u8 ref_list, u32 x, u32 y, MotionVector vector); DecoderErrorOr<MotionVector> scale_motion_vector(u8 plane, u8 ref_list, u32 x, u32 y, MotionVector vector);
// From (8.5.1) Inter prediction process, steps 2-5 // From (8.5.1) Inter prediction process, steps 2-5
DecoderErrorOr<void> predict_inter_block(u8 plane, u8 ref_list, u32 x, u32 y, u32 width, u32 height, u32 block_index, Span<u16> block_buffer); DecoderErrorOr<void> predict_inter_block(u8 plane, u8 ref_list, u32 block_row, u32 block_column, u32 x, u32 y, u32 width, u32 height, u32 block_index, Span<u16> block_buffer);
/* (8.6) Reconstruction and Dequantization */ /* (8.6) Reconstruction and Dequantization */

View file

@ -929,16 +929,14 @@ size_t Parser::get_image_index(u32 row, u32 column) const
return row * m_mi_cols + column; return row * m_mi_cols + column;
} }
DecoderErrorOr<void> Parser::decode_block(u32 row, u32 col, BlockSubsize subsize) DecoderErrorOr<void> Parser::decode_block(u32 row, u32 column, BlockSubsize subsize)
{ {
m_mi_row = row;
m_mi_col = col;
m_mi_size = subsize; m_mi_size = subsize;
m_available_u = row > 0; auto above_context = row > 0 ? m_frame_block_contexts.at(row - 1, column) : FrameBlockContext();
m_available_l = col > m_mi_col_start; auto left_context = column > m_mi_col_start ? m_frame_block_contexts.at(row, column - 1) : FrameBlockContext();
TRY(mode_info()); TRY(mode_info(row, column, above_context, left_context));
m_eob_total = 0; m_eob_total = 0;
TRY(residual()); TRY(residual(row, column, above_context.is_available, left_context.is_available));
if (m_is_inter && subsize >= Block_8x8 && m_eob_total == 0) if (m_is_inter && subsize >= Block_8x8 && m_eob_total == 0)
m_skip = true; m_skip = true;
@ -947,36 +945,34 @@ DecoderErrorOr<void> Parser::decode_block(u32 row, u32 col, BlockSubsize subsize
// See here: // See here:
// https://github.com/webmproject/libvpx/blob/705bf9de8c96cfe5301451f1d7e5c90a41c64e5f/vp9/decoder/vp9_decodeframe.c#L917 // https://github.com/webmproject/libvpx/blob/705bf9de8c96cfe5301451f1d7e5c90a41c64e5f/vp9/decoder/vp9_decodeframe.c#L917
auto maximum_block_y = min<u32>(num_8x8_blocks_high_lookup[subsize], m_mi_rows - row); auto maximum_block_y = min<u32>(num_8x8_blocks_high_lookup[subsize], m_mi_rows - row);
auto maximum_block_x = min<u32>(num_8x8_blocks_wide_lookup[subsize], m_mi_cols - col); auto maximum_block_x = min<u32>(num_8x8_blocks_wide_lookup[subsize], m_mi_cols - column);
for (size_t y = 0; y < maximum_block_y; y++) { for (size_t y = 0; y < maximum_block_y; y++) {
for (size_t x = 0; x < maximum_block_x; x++) for (size_t x = 0; x < maximum_block_x; x++)
m_frame_block_contexts.at(row + y, col + x) = FrameBlockContext { true, m_skip, m_tx_size, m_y_mode, m_block_sub_modes, m_interp_filter, m_ref_frame, m_block_mvs, m_segment_id }; m_frame_block_contexts.at(row + y, column + x) = FrameBlockContext { true, m_skip, m_tx_size, m_y_mode, m_block_sub_modes, m_interp_filter, m_ref_frame, m_block_mvs, m_segment_id };
} }
return {}; return {};
} }
DecoderErrorOr<void> Parser::mode_info() DecoderErrorOr<void> Parser::mode_info(u32 row, u32 column, FrameBlockContext above_context, FrameBlockContext left_context)
{ {
if (m_frame_is_intra) if (m_frame_is_intra)
TRY(intra_frame_mode_info()); TRY(intra_frame_mode_info(above_context, left_context));
else else
TRY(inter_frame_mode_info()); TRY(inter_frame_mode_info(row, column, above_context, left_context));
return {}; return {};
} }
DecoderErrorOr<void> Parser::intra_frame_mode_info() DecoderErrorOr<void> Parser::intra_frame_mode_info(FrameBlockContext above_context, FrameBlockContext left_context)
{ {
TRY(intra_segment_id()); TRY(intra_segment_id());
TRY(read_skip()); TRY(read_skip(above_context, left_context));
TRY(read_tx_size(true)); TRY(read_tx_size(above_context, left_context, true));
m_ref_frame[0] = IntraFrame; m_ref_frame[0] = IntraFrame;
m_ref_frame[1] = None; m_ref_frame[1] = None;
m_is_inter = false; m_is_inter = false;
// FIXME: This if statement is also present in parse_default_intra_mode. The selection of parameters for // FIXME: This if statement is also present in parse_default_intra_mode. The selection of parameters for
// the probability table lookup should be inlined here. // the probability table lookup should be inlined here.
auto above_context = get_above_context();
auto left_context = get_left_context();
if (m_mi_size >= Block_8x8) { if (m_mi_size >= Block_8x8) {
m_y_mode = TRY_READ(TreeParser::parse_default_intra_mode(*m_bit_stream, *m_probability_tables, m_mi_size, above_context, left_context, m_block_sub_modes, 0, 0)); m_y_mode = TRY_READ(TreeParser::parse_default_intra_mode(*m_bit_stream, *m_probability_tables, m_mi_size, above_context, left_context, m_block_sub_modes, 0, 0));
for (auto& block_sub_mode : m_block_sub_modes) for (auto& block_sub_mode : m_block_sub_modes)
@ -1011,26 +1007,12 @@ DecoderErrorOr<void> Parser::intra_segment_id()
return {}; return {};
} }
FrameBlockContext Parser::get_above_context() const DecoderErrorOr<void> Parser::read_skip(FrameBlockContext above_context, FrameBlockContext left_context)
{
if (!m_available_u)
return FrameBlockContext { .is_available = false };
return m_frame_block_contexts.at(m_mi_row - 1, m_mi_col);
}
FrameBlockContext Parser::get_left_context() const
{
if (!m_available_l)
return FrameBlockContext { .is_available = false };
return m_frame_block_contexts.at(m_mi_row, m_mi_col - 1);
}
DecoderErrorOr<void> Parser::read_skip()
{ {
if (seg_feature_active(SEG_LVL_SKIP)) { if (seg_feature_active(SEG_LVL_SKIP)) {
m_skip = true; m_skip = true;
} else { } else {
m_skip = TRY_READ(TreeParser::parse_skip(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, get_above_context(), get_left_context())); m_skip = TRY_READ(TreeParser::parse_skip(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, above_context, left_context));
} }
return {}; return {};
} }
@ -1040,37 +1022,37 @@ bool Parser::seg_feature_active(u8 feature)
return m_segmentation_enabled && m_feature_enabled[m_segment_id][feature]; return m_segmentation_enabled && m_feature_enabled[m_segment_id][feature];
} }
DecoderErrorOr<void> Parser::read_tx_size(bool allow_select) DecoderErrorOr<void> Parser::read_tx_size(FrameBlockContext above_context, FrameBlockContext left_context, bool allow_select)
{ {
m_max_tx_size = max_txsize_lookup[m_mi_size]; m_max_tx_size = max_txsize_lookup[m_mi_size];
if (allow_select && m_tx_mode == TXModeSelect && m_mi_size >= Block_8x8) if (allow_select && m_tx_mode == TXModeSelect && m_mi_size >= Block_8x8)
m_tx_size = TRY_READ(TreeParser::parse_tx_size(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, m_max_tx_size, get_above_context(), get_left_context())); m_tx_size = TRY_READ(TreeParser::parse_tx_size(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, m_max_tx_size, above_context, left_context));
else else
m_tx_size = min(m_max_tx_size, tx_mode_to_biggest_tx_size[m_tx_mode]); m_tx_size = min(m_max_tx_size, tx_mode_to_biggest_tx_size[m_tx_mode]);
return {}; return {};
} }
DecoderErrorOr<void> Parser::inter_frame_mode_info() DecoderErrorOr<void> Parser::inter_frame_mode_info(u32 row, u32 column, FrameBlockContext above_context, FrameBlockContext left_context)
{ {
TRY(inter_segment_id()); TRY(inter_segment_id(row, column));
TRY(read_skip()); TRY(read_skip(above_context, left_context));
TRY(read_is_inter()); TRY(read_is_inter(above_context, left_context));
TRY(read_tx_size(!m_skip || !m_is_inter)); TRY(read_tx_size(above_context, left_context, !m_skip || !m_is_inter));
if (m_is_inter) { if (m_is_inter) {
TRY(inter_block_mode_info()); TRY(inter_block_mode_info(row, column, above_context, left_context));
} else { } else {
TRY(intra_block_mode_info()); TRY(intra_block_mode_info());
} }
return {}; return {};
} }
DecoderErrorOr<void> Parser::inter_segment_id() DecoderErrorOr<void> Parser::inter_segment_id(u32 row, u32 column)
{ {
if (!m_segmentation_enabled) { if (!m_segmentation_enabled) {
m_segment_id = 0; m_segment_id = 0;
return {}; return {};
} }
auto predicted_segment_id = get_segment_id(); auto predicted_segment_id = get_segment_id(row, column);
if (!m_segmentation_update_map) { if (!m_segmentation_update_map) {
m_segment_id = predicted_segment_id; m_segment_id = predicted_segment_id;
return {}; return {};
@ -1080,48 +1062,48 @@ DecoderErrorOr<void> Parser::inter_segment_id()
return {}; return {};
} }
auto seg_id_predicted = TRY_READ(TreeParser::parse_segment_id_predicted(*m_bit_stream, m_segmentation_pred_prob, m_left_seg_pred_context[m_mi_row], m_above_seg_pred_context[m_mi_col])); auto seg_id_predicted = TRY_READ(TreeParser::parse_segment_id_predicted(*m_bit_stream, m_segmentation_pred_prob, m_left_seg_pred_context[row], m_above_seg_pred_context[column]));
if (seg_id_predicted) if (seg_id_predicted)
m_segment_id = predicted_segment_id; m_segment_id = predicted_segment_id;
else else
m_segment_id = TRY_READ(TreeParser::parse_segment_id(*m_bit_stream, m_segmentation_tree_probs)); m_segment_id = TRY_READ(TreeParser::parse_segment_id(*m_bit_stream, m_segmentation_tree_probs));
for (size_t i = 0; i < num_8x8_blocks_wide_lookup[m_mi_size]; i++) { for (size_t i = 0; i < num_8x8_blocks_wide_lookup[m_mi_size]; i++) {
auto index = m_mi_col + i; auto index = 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()) if (index < m_above_seg_pred_context.size())
m_above_seg_pred_context[index] = seg_id_predicted; m_above_seg_pred_context[index] = seg_id_predicted;
} }
for (size_t i = 0; i < num_8x8_blocks_high_lookup[m_mi_size]; i++) { for (size_t i = 0; i < num_8x8_blocks_high_lookup[m_mi_size]; i++) {
auto index = m_mi_row + i; auto index = 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()) if (index < m_above_seg_pred_context.size())
m_left_seg_pred_context[m_mi_row + i] = seg_id_predicted; m_left_seg_pred_context[row + i] = seg_id_predicted;
} }
return {}; return {};
} }
u8 Parser::get_segment_id() u8 Parser::get_segment_id(u32 row, u32 column)
{ {
auto bw = num_8x8_blocks_wide_lookup[m_mi_size]; auto bw = num_8x8_blocks_wide_lookup[m_mi_size];
auto bh = num_8x8_blocks_high_lookup[m_mi_size]; auto bh = num_8x8_blocks_high_lookup[m_mi_size];
auto xmis = min(m_mi_cols - m_mi_col, (u32)bw); auto xmis = min(m_mi_cols - column, (u32)bw);
auto ymis = min(m_mi_rows - m_mi_row, (u32)bh); auto ymis = min(m_mi_rows - row, (u32)bh);
u8 segment = 7; u8 segment = 7;
for (size_t y = 0; y < ymis; y++) { for (size_t y = 0; y < ymis; y++) {
for (size_t x = 0; x < xmis; x++) { for (size_t x = 0; x < xmis; x++) {
segment = min(segment, m_previous_block_contexts.index_at(m_mi_row + y, m_mi_col + x)); segment = min(segment, m_previous_block_contexts.index_at(row + y, column + x));
} }
} }
return segment; return segment;
} }
DecoderErrorOr<void> Parser::read_is_inter() DecoderErrorOr<void> Parser::read_is_inter(FrameBlockContext above_context, FrameBlockContext left_context)
{ {
if (seg_feature_active(SEG_LVL_REF_FRAME)) if (seg_feature_active(SEG_LVL_REF_FRAME))
m_is_inter = m_feature_data[m_segment_id][SEG_LVL_REF_FRAME] != IntraFrame; m_is_inter = m_feature_data[m_segment_id][SEG_LVL_REF_FRAME] != IntraFrame;
else else
m_is_inter = TRY_READ(TreeParser::parse_block_is_inter_predicted(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, get_above_context(), get_left_context())); m_is_inter = TRY_READ(TreeParser::parse_block_is_inter_predicted(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, above_context, left_context));
return {}; return {};
} }
@ -1152,13 +1134,13 @@ DecoderErrorOr<void> Parser::intra_block_mode_info()
return {}; return {};
} }
DecoderErrorOr<void> Parser::inter_block_mode_info() DecoderErrorOr<void> Parser::inter_block_mode_info(u32 row, u32 column, FrameBlockContext above_context, FrameBlockContext left_context)
{ {
TRY(read_ref_frames()); TRY(read_ref_frames(above_context, left_context));
for (auto j = 0; j < 2; j++) { for (auto j = 0; j < 2; j++) {
if (m_ref_frame[j] > IntraFrame) { if (m_ref_frame[j] > IntraFrame) {
find_mv_refs(m_ref_frame[j], -1); find_mv_refs(row, column, m_ref_frame[j], -1);
find_best_ref_mvs(j); find_best_ref_mvs(row, column, j);
} }
} }
auto is_compound = m_ref_frame[1] > IntraFrame; auto is_compound = m_ref_frame[1] > IntraFrame;
@ -1168,7 +1150,7 @@ DecoderErrorOr<void> Parser::inter_block_mode_info()
m_y_mode = TRY_READ(TreeParser::parse_inter_mode(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, m_mode_context[m_ref_frame[0]])); m_y_mode = TRY_READ(TreeParser::parse_inter_mode(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, m_mode_context[m_ref_frame[0]]));
} }
if (m_interpolation_filter == Switchable) if (m_interpolation_filter == Switchable)
m_interp_filter = TRY_READ(TreeParser::parse_interpolation_filter(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, get_above_context(), get_left_context())); m_interp_filter = TRY_READ(TreeParser::parse_interpolation_filter(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, above_context, left_context));
else else
m_interp_filter = m_interpolation_filter; m_interp_filter = m_interpolation_filter;
if (m_mi_size < Block_8x8) { if (m_mi_size < Block_8x8) {
@ -1179,7 +1161,7 @@ DecoderErrorOr<void> Parser::inter_block_mode_info()
m_y_mode = TRY_READ(TreeParser::parse_inter_mode(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, m_mode_context[m_ref_frame[0]])); m_y_mode = TRY_READ(TreeParser::parse_inter_mode(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, m_mode_context[m_ref_frame[0]]));
if (m_y_mode == PredictionMode::NearestMv || m_y_mode == PredictionMode::NearMv) { if (m_y_mode == PredictionMode::NearestMv || m_y_mode == PredictionMode::NearMv) {
for (auto j = 0; j < 1 + is_compound; j++) for (auto j = 0; j < 1 + is_compound; j++)
append_sub8x8_mvs(idy * 2 + idx, j); append_sub8x8_mvs(row, column, idy * 2 + idx, j);
} }
TRY(assign_mv(is_compound)); TRY(assign_mv(is_compound));
for (auto y = 0; y < m_num_4x4_h; y++) { for (auto y = 0; y < m_num_4x4_h; y++) {
@ -1203,7 +1185,7 @@ DecoderErrorOr<void> Parser::inter_block_mode_info()
return {}; return {};
} }
DecoderErrorOr<void> Parser::read_ref_frames() DecoderErrorOr<void> Parser::read_ref_frames(FrameBlockContext above_context, FrameBlockContext left_context)
{ {
if (seg_feature_active(SEG_LVL_REF_FRAME)) { if (seg_feature_active(SEG_LVL_REF_FRAME)) {
m_ref_frame[0] = static_cast<ReferenceFrameType>(m_feature_data[m_segment_id][SEG_LVL_REF_FRAME]); m_ref_frame[0] = static_cast<ReferenceFrameType>(m_feature_data[m_segment_id][SEG_LVL_REF_FRAME]);
@ -1211,8 +1193,6 @@ DecoderErrorOr<void> Parser::read_ref_frames()
return {}; return {};
} }
ReferenceMode comp_mode; ReferenceMode comp_mode;
auto above_context = get_above_context();
auto left_context = get_left_context();
if (m_reference_mode == ReferenceModeSelect) if (m_reference_mode == ReferenceModeSelect)
comp_mode = TRY_READ(TreeParser::parse_comp_mode(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, m_comp_fixed_ref, above_context, left_context)); comp_mode = TRY_READ(TreeParser::parse_comp_mode(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, m_comp_fixed_ref, above_context, left_context));
else else
@ -1311,7 +1291,7 @@ Gfx::Size<size_t> Parser::get_decoded_size_for_plane(u8 plane)
return { point.x(), point.y() }; return { point.x(), point.y() };
} }
DecoderErrorOr<void> Parser::residual() DecoderErrorOr<void> Parser::residual(u32 row, u32 column, bool has_block_above, bool has_block_left)
{ {
auto block_size = m_mi_size < Block_8x8 ? Block_8x8 : static_cast<BlockSubsize>(m_mi_size); auto block_size = m_mi_size < Block_8x8 ? Block_8x8 : static_cast<BlockSubsize>(m_mi_size);
for (u8 plane = 0; plane < 3; plane++) { for (u8 plane = 0; plane < 3; plane++) {
@ -1322,17 +1302,17 @@ DecoderErrorOr<void> Parser::residual()
auto num_4x4_h = num_4x4_blocks_high_lookup[plane_size]; auto num_4x4_h = num_4x4_blocks_high_lookup[plane_size];
auto sub_x = (plane > 0) ? m_subsampling_x : 0; auto sub_x = (plane > 0) ? m_subsampling_x : 0;
auto sub_y = (plane > 0) ? m_subsampling_y : 0; auto sub_y = (plane > 0) ? m_subsampling_y : 0;
auto base_x = (m_mi_col * 8) >> sub_x; auto base_x = (column * 8) >> sub_x;
auto base_y = (m_mi_row * 8) >> sub_y; auto base_y = (row * 8) >> sub_y;
if (m_is_inter) { if (m_is_inter) {
if (m_mi_size < Block_8x8) { if (m_mi_size < Block_8x8) {
for (auto y = 0; y < num_4x4_h; y++) { for (auto y = 0; y < num_4x4_h; y++) {
for (auto x = 0; x < num_4x4_w; x++) { for (auto x = 0; x < num_4x4_w; x++) {
TRY(m_decoder.predict_inter(plane, base_x + (4 * x), base_y + (4 * y), 4, 4, (y * num_4x4_w) + x)); TRY(m_decoder.predict_inter(plane, row, column, base_x + (4 * x), base_y + (4 * y), 4, 4, (y * num_4x4_w) + x));
} }
} }
} else { } else {
TRY(m_decoder.predict_inter(plane, base_x, base_y, num_4x4_w * 4, num_4x4_h * 4, 0)); TRY(m_decoder.predict_inter(plane, row, column, base_x, base_y, num_4x4_w * 4, num_4x4_h * 4, 0));
} }
} }
auto max_x = (m_mi_cols * 8) >> sub_x; auto max_x = (m_mi_cols * 8) >> sub_x;
@ -1345,7 +1325,7 @@ DecoderErrorOr<void> Parser::residual()
auto non_zero = false; auto non_zero = false;
if (start_x < max_x && start_y < max_y) { if (start_x < max_x && start_y < max_y) {
if (!m_is_inter) if (!m_is_inter)
TRY(m_decoder.predict_intra(plane, start_x, start_y, m_available_l || x > 0, m_available_u || y > 0, (x + step) < num_4x4_w, tx_size, block_index)); TRY(m_decoder.predict_intra(plane, start_x, start_y, has_block_left || x > 0, has_block_above || y > 0, (x + step) < num_4x4_w, tx_size, block_index));
if (!m_skip) { if (!m_skip) {
non_zero = TRY(tokens(plane, start_x, start_y, tx_size, block_index)); non_zero = TRY(tokens(plane, start_x, start_y, tx_size, block_index));
TRY(m_decoder.reconstruct(plane, start_x, start_y, tx_size)); TRY(m_decoder.reconstruct(plane, start_x, start_y, tx_size));
@ -1541,16 +1521,16 @@ void Parser::if_diff_ref_frame_add_mv(u32 candidate_row, u32 candidate_column, R
} }
} }
MotionVector Parser::clamp_mv(MotionVector vector, i32 border) MotionVector Parser::clamp_mv(u32 row, u32 column, MotionVector vector, i32 border)
{ {
i32 blocks_high = num_8x8_blocks_high_lookup[m_mi_size]; i32 blocks_high = num_8x8_blocks_high_lookup[m_mi_size];
// Casts must be done here to prevent subtraction underflow from wrapping the values. // Casts must be done here to prevent subtraction underflow from wrapping the values.
i32 mb_to_top_edge = -8 * (static_cast<i32>(m_mi_row) * MI_SIZE); i32 mb_to_top_edge = -8 * (static_cast<i32>(row) * MI_SIZE);
i32 mb_to_bottom_edge = 8 * ((static_cast<i32>(m_mi_rows) - blocks_high - static_cast<i32>(m_mi_row)) * MI_SIZE); i32 mb_to_bottom_edge = 8 * ((static_cast<i32>(m_mi_rows) - blocks_high - static_cast<i32>(row)) * MI_SIZE);
i32 blocks_wide = num_8x8_blocks_wide_lookup[m_mi_size]; i32 blocks_wide = num_8x8_blocks_wide_lookup[m_mi_size];
i32 mb_to_left_edge = -8 * (static_cast<i32>(m_mi_col) * MI_SIZE); i32 mb_to_left_edge = -8 * (static_cast<i32>(column) * MI_SIZE);
i32 mb_to_right_edge = 8 * ((static_cast<i32>(m_mi_cols) - blocks_wide - static_cast<i32>(m_mi_col)) * MI_SIZE); i32 mb_to_right_edge = 8 * ((static_cast<i32>(m_mi_cols) - blocks_wide - static_cast<i32>(column)) * MI_SIZE);
return { return {
clip_3(mb_to_top_edge - border, mb_to_bottom_edge + border, vector.row()), clip_3(mb_to_top_edge - border, mb_to_bottom_edge + border, vector.row()),
@ -1558,14 +1538,14 @@ MotionVector Parser::clamp_mv(MotionVector vector, i32 border)
}; };
} }
void Parser::clamp_mv_ref(u8 i) void Parser::clamp_mv_ref(u32 row, u32 column, u8 i)
{ {
MotionVector& vector = m_ref_list_mv[i]; MotionVector& vector = m_ref_list_mv[i];
vector = clamp_mv(vector, MV_BORDER); vector = clamp_mv(row, column, vector, MV_BORDER);
} }
// 6.5.1 Find MV refs syntax // 6.5.1 Find MV refs syntax
void Parser::find_mv_refs(ReferenceFrameType reference_frame, i32 block) void Parser::find_mv_refs(u32 row, u32 column, ReferenceFrameType reference_frame, i32 block)
{ {
m_ref_mv_count = 0; m_ref_mv_count = 0;
bool different_ref_found = false; bool different_ref_found = false;
@ -1574,7 +1554,7 @@ void Parser::find_mv_refs(ReferenceFrameType reference_frame, i32 block)
m_ref_list_mv[0] = {}; m_ref_list_mv[0] = {};
m_ref_list_mv[1] = {}; m_ref_list_mv[1] = {};
MotionVector base_coordinates = MotionVector(m_mi_row, m_mi_col); MotionVector base_coordinates = MotionVector(row, column);
for (auto i = 0u; i < 2; i++) { for (auto i = 0u; i < 2; i++) {
auto offset_vector = mv_ref_blocks[m_mi_size][i]; auto offset_vector = mv_ref_blocks[m_mi_size][i];
@ -1612,7 +1592,7 @@ void Parser::find_mv_refs(ReferenceFrameType reference_frame, i32 block)
} }
} }
if (m_use_prev_frame_mvs) if (m_use_prev_frame_mvs)
if_same_ref_frame_add_mv(m_mi_row, m_mi_col, reference_frame, true); if_same_ref_frame_add_mv(row, column, reference_frame, true);
if (different_ref_found) { if (different_ref_found) {
for (auto i = 0u; i < MVREF_NEIGHBOURS; i++) { for (auto i = 0u; i < MVREF_NEIGHBOURS; i++) {
@ -1622,11 +1602,11 @@ void Parser::find_mv_refs(ReferenceFrameType reference_frame, i32 block)
} }
} }
if (m_use_prev_frame_mvs) if (m_use_prev_frame_mvs)
if_diff_ref_frame_add_mv(m_mi_row, m_mi_col, reference_frame, true); if_diff_ref_frame_add_mv(row, column, reference_frame, true);
m_mode_context[reference_frame] = counter_to_context[context_counter]; m_mode_context[reference_frame] = counter_to_context[context_counter];
for (auto i = 0u; i < MAX_MV_REF_CANDIDATES; i++) for (auto i = 0u; i < MAX_MV_REF_CANDIDATES; i++)
clamp_mv_ref(i); clamp_mv_ref(row, column, i);
} }
bool Parser::use_mv_hp(MotionVector const& vector) bool Parser::use_mv_hp(MotionVector const& vector)
@ -1634,7 +1614,7 @@ bool Parser::use_mv_hp(MotionVector const& vector)
return (abs(vector.row()) >> 3) < COMPANDED_MVREF_THRESH && (abs(vector.column()) >> 3) < COMPANDED_MVREF_THRESH; return (abs(vector.row()) >> 3) < COMPANDED_MVREF_THRESH && (abs(vector.column()) >> 3) < COMPANDED_MVREF_THRESH;
} }
void Parser::find_best_ref_mvs(u8 ref_list) void Parser::find_best_ref_mvs(u32 row, u32 column, u8 ref_list)
{ {
for (auto i = 0u; i < MAX_MV_REF_CANDIDATES; i++) { for (auto i = 0u; i < MAX_MV_REF_CANDIDATES; i++) {
auto delta = m_ref_list_mv[i]; auto delta = m_ref_list_mv[i];
@ -1647,7 +1627,7 @@ void Parser::find_best_ref_mvs(u8 ref_list)
delta_column += delta_column > 0 ? -1 : 1; delta_column += delta_column > 0 ? -1 : 1;
} }
delta = { delta_row, delta_column }; delta = { delta_row, delta_column };
m_ref_list_mv[i] = clamp_mv(delta, (BORDERINPIXELS - INTERP_EXTEND) << 3); m_ref_list_mv[i] = clamp_mv(row, column, delta, (BORDERINPIXELS - INTERP_EXTEND) << 3);
} }
m_nearest_mv[ref_list] = m_ref_list_mv[0]; m_nearest_mv[ref_list] = m_ref_list_mv[0];
@ -1655,10 +1635,10 @@ void Parser::find_best_ref_mvs(u8 ref_list)
m_best_mv[ref_list] = m_ref_list_mv[0]; m_best_mv[ref_list] = m_ref_list_mv[0];
} }
void Parser::append_sub8x8_mvs(i32 block, u8 ref_list) void Parser::append_sub8x8_mvs(u32 row, u32 column, i32 block, u8 ref_list)
{ {
MotionVector sub_8x8_mvs[2]; MotionVector sub_8x8_mvs[2];
find_mv_refs(m_ref_frame[ref_list], block); find_mv_refs(row, column, m_ref_frame[ref_list], block);
auto destination_index = 0; auto destination_index = 0;
if (block == 0) { if (block == 0) {
for (auto i = 0u; i < 2; i++) for (auto i = 0u; i < 2; i++)

View file

@ -84,8 +84,6 @@ private:
u8 inv_remap_prob(u8 delta_prob, u8 prob); u8 inv_remap_prob(u8 delta_prob, u8 prob);
u8 inv_recenter_nonneg(u8 v, u8 m); u8 inv_recenter_nonneg(u8 v, u8 m);
DecoderErrorOr<void> read_coef_probs(); DecoderErrorOr<void> read_coef_probs();
FrameBlockContext get_above_context() const;
FrameBlockContext get_left_context() const;
DecoderErrorOr<void> read_skip_prob(); DecoderErrorOr<void> read_skip_prob();
DecoderErrorOr<void> read_inter_mode_probs(); DecoderErrorOr<void> read_inter_mode_probs();
DecoderErrorOr<void> read_interp_filter_probs(); DecoderErrorOr<void> read_interp_filter_probs();
@ -105,24 +103,24 @@ private:
DecoderErrorOr<void> decode_tile(); DecoderErrorOr<void> decode_tile();
void clear_left_context(); void clear_left_context();
DecoderErrorOr<void> decode_partition(u32 row, u32 column, BlockSubsize subsize); DecoderErrorOr<void> decode_partition(u32 row, u32 column, BlockSubsize subsize);
DecoderErrorOr<void> decode_block(u32 row, u32 col, BlockSubsize subsize); DecoderErrorOr<void> decode_block(u32 row, u32 column, BlockSubsize subsize);
DecoderErrorOr<void> mode_info(); DecoderErrorOr<void> mode_info(u32 row, u32 column, FrameBlockContext above_context, FrameBlockContext left_context);
DecoderErrorOr<void> intra_frame_mode_info(); DecoderErrorOr<void> intra_frame_mode_info(FrameBlockContext above_context, FrameBlockContext left_context);
DecoderErrorOr<void> intra_segment_id(); DecoderErrorOr<void> intra_segment_id();
DecoderErrorOr<void> read_skip(); DecoderErrorOr<void> read_skip(FrameBlockContext above_context, FrameBlockContext left_context);
bool seg_feature_active(u8 feature); bool seg_feature_active(u8 feature);
DecoderErrorOr<void> read_tx_size(bool allow_select); DecoderErrorOr<void> read_tx_size(FrameBlockContext above_context, FrameBlockContext left_context, bool allow_select);
DecoderErrorOr<void> inter_frame_mode_info(); DecoderErrorOr<void> inter_frame_mode_info(u32 row, u32 column, FrameBlockContext above_context, FrameBlockContext left_context);
DecoderErrorOr<void> inter_segment_id(); DecoderErrorOr<void> inter_segment_id(u32 row, u32 column);
u8 get_segment_id(); u8 get_segment_id(u32 row, u32 column);
DecoderErrorOr<void> read_is_inter(); DecoderErrorOr<void> read_is_inter(FrameBlockContext above_context, FrameBlockContext left_context);
DecoderErrorOr<void> intra_block_mode_info(); DecoderErrorOr<void> intra_block_mode_info();
DecoderErrorOr<void> inter_block_mode_info(); DecoderErrorOr<void> inter_block_mode_info(u32 row, u32 column, FrameBlockContext above_context, FrameBlockContext left_context);
DecoderErrorOr<void> read_ref_frames(); DecoderErrorOr<void> read_ref_frames(FrameBlockContext above_context, FrameBlockContext left_context);
DecoderErrorOr<void> assign_mv(bool is_compound); DecoderErrorOr<void> assign_mv(bool is_compound);
DecoderErrorOr<void> read_mv(u8 ref); DecoderErrorOr<void> read_mv(u8 ref);
DecoderErrorOr<i32> read_mv_component(u8 component); DecoderErrorOr<i32> read_mv_component(u8 component);
DecoderErrorOr<void> residual(); DecoderErrorOr<void> residual(u32 row, u32 column, bool has_block_above, bool has_block_left);
TXSize get_uv_tx_size(); TXSize get_uv_tx_size();
BlockSubsize get_plane_block_size(u32 subsize, u8 plane); BlockSubsize get_plane_block_size(u32 subsize, u8 plane);
DecoderErrorOr<bool> tokens(size_t plane, u32 x, u32 y, TXSize tx_size, u32 block_index); DecoderErrorOr<bool> tokens(size_t plane, u32 x, u32 y, TXSize tx_size, u32 block_index);
@ -130,13 +128,13 @@ private:
DecoderErrorOr<i32> read_coef(Token token); DecoderErrorOr<i32> read_coef(Token token);
/* (6.5) Motion Vector Prediction */ /* (6.5) Motion Vector Prediction */
void find_mv_refs(ReferenceFrameType, i32 block); void find_mv_refs(u32 row, u32 column, ReferenceFrameType, i32 block);
void find_best_ref_mvs(u8 ref_list); void find_best_ref_mvs(u32 row, u32 column, u8 ref_list);
bool use_mv_hp(MotionVector const& delta_mv); bool use_mv_hp(MotionVector const& delta_mv);
void append_sub8x8_mvs(i32 block, u8 ref_list); void append_sub8x8_mvs(u32 row, u32 column, i32 block, u8 ref_list);
bool is_inside(i32 row, i32 column); bool is_inside(i32 row, i32 column);
void clamp_mv_ref(u8 i); void clamp_mv_ref(u32 row, u32 column, u8 i);
MotionVector clamp_mv(MotionVector mvec, i32 border); MotionVector clamp_mv(u32 row, u32 column, MotionVector mvec, i32 border);
size_t get_image_index(u32 row, u32 column) const; size_t get_image_index(u32 row, u32 column) const;
void get_block_mv(u32 candidate_row, u32 candidate_column, u8 ref_list, bool use_prev); void get_block_mv(u32 candidate_row, u32 candidate_column, u8 ref_list, bool use_prev);
void if_same_ref_frame_add_mv(u32 candidate_row, u32 candidate_column, ReferenceFrameType ref_frame, bool use_prev); void if_same_ref_frame_add_mv(u32 candidate_row, u32 candidate_column, ReferenceFrameType ref_frame, bool use_prev);
@ -212,11 +210,7 @@ private:
u32 m_mi_row_end { 0 }; u32 m_mi_row_end { 0 };
u32 m_mi_col_start { 0 }; u32 m_mi_col_start { 0 };
u32 m_mi_col_end { 0 }; u32 m_mi_col_end { 0 };
u32 m_mi_row { 0 };
u32 m_mi_col { 0 };
BlockSubsize m_mi_size { 0 }; BlockSubsize m_mi_size { 0 };
bool m_available_u { false };
bool m_available_l { false };
u8 m_segment_id { 0 }; u8 m_segment_id { 0 };
// FIXME: Should this be an enum? // FIXME: Should this be an enum?
// skip equal to 0 indicates that there may be some transform coefficients to read for this block; skip equal to 1 // skip equal to 0 indicates that there may be some transform coefficients to read for this block; skip equal to 1