1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 05:57:44 +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]);
}
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?
@ -736,12 +736,12 @@ MotionVector Decoder::clamp_motion_vector(u8 plane, MotionVector vector)
// The output array clampedMv is specified by the following steps:
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.
i32 mb_to_top_edge = -(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>(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>(block_row)) * MI_SIZE) * 16) >> subsampling_y;
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_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_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>(block_column)) * MI_SIZE) * 16) >> subsampling_x;
i32 subpel_left = (INTERP_EXTEND + ((blocks_wide * MI_SIZE) >> subsampling_x)) << SUBPEL_BITS;
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);
// 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
// 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
// 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 {};
}
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
// 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.
Array<u16, maximum_block_size> predicted_buffer;
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& {
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.
Array<u16, maximum_block_size> second_predicted_buffer;
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 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);
// (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
MotionVector select_motion_vector(u8 plane, u8 ref_list, u32 block_index);
// (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
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
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 */

View file

@ -929,16 +929,14 @@ size_t Parser::get_image_index(u32 row, u32 column) const
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_available_u = row > 0;
m_available_l = col > m_mi_col_start;
TRY(mode_info());
auto above_context = row > 0 ? m_frame_block_contexts.at(row - 1, column) : FrameBlockContext();
auto left_context = column > m_mi_col_start ? m_frame_block_contexts.at(row, column - 1) : FrameBlockContext();
TRY(mode_info(row, column, above_context, left_context));
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)
m_skip = true;
@ -947,36 +945,34 @@ DecoderErrorOr<void> Parser::decode_block(u32 row, u32 col, BlockSubsize subsize
// See here:
// 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_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 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 {};
}
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)
TRY(intra_frame_mode_info());
TRY(intra_frame_mode_info(above_context, left_context));
else
TRY(inter_frame_mode_info());
TRY(inter_frame_mode_info(row, column, above_context, left_context));
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(read_skip());
TRY(read_tx_size(true));
TRY(read_skip(above_context, left_context));
TRY(read_tx_size(above_context, left_context, true));
m_ref_frame[0] = IntraFrame;
m_ref_frame[1] = None;
m_is_inter = false;
// 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.
auto above_context = get_above_context();
auto left_context = get_left_context();
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));
for (auto& block_sub_mode : m_block_sub_modes)
@ -1011,26 +1007,12 @@ DecoderErrorOr<void> Parser::intra_segment_id()
return {};
}
FrameBlockContext Parser::get_above_context() const
{
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()
DecoderErrorOr<void> Parser::read_skip(FrameBlockContext above_context, FrameBlockContext left_context)
{
if (seg_feature_active(SEG_LVL_SKIP)) {
m_skip = true;
} 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 {};
}
@ -1040,37 +1022,37 @@ bool Parser::seg_feature_active(u8 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];
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
m_tx_size = min(m_max_tx_size, tx_mode_to_biggest_tx_size[m_tx_mode]);
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(read_skip());
TRY(read_is_inter());
TRY(read_tx_size(!m_skip || !m_is_inter));
TRY(inter_segment_id(row, column));
TRY(read_skip(above_context, left_context));
TRY(read_is_inter(above_context, left_context));
TRY(read_tx_size(above_context, left_context, !m_skip || !m_is_inter));
if (m_is_inter) {
TRY(inter_block_mode_info());
TRY(inter_block_mode_info(row, column, above_context, left_context));
} else {
TRY(intra_block_mode_info());
}
return {};
}
DecoderErrorOr<void> Parser::inter_segment_id()
DecoderErrorOr<void> Parser::inter_segment_id(u32 row, u32 column)
{
if (!m_segmentation_enabled) {
m_segment_id = 0;
return {};
}
auto predicted_segment_id = get_segment_id();
auto predicted_segment_id = get_segment_id(row, column);
if (!m_segmentation_update_map) {
m_segment_id = predicted_segment_id;
return {};
@ -1080,48 +1062,48 @@ DecoderErrorOr<void> Parser::inter_segment_id()
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)
m_segment_id = predicted_segment_id;
else
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++) {
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.
if (index < m_above_seg_pred_context.size())
m_above_seg_pred_context[index] = seg_id_predicted;
}
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.
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 {};
}
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 bh = num_8x8_blocks_high_lookup[m_mi_size];
auto xmis = min(m_mi_cols - m_mi_col, (u32)bw);
auto ymis = min(m_mi_rows - m_mi_row, (u32)bh);
auto xmis = min(m_mi_cols - column, (u32)bw);
auto ymis = min(m_mi_rows - row, (u32)bh);
u8 segment = 7;
for (size_t y = 0; y < ymis; y++) {
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;
}
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))
m_is_inter = m_feature_data[m_segment_id][SEG_LVL_REF_FRAME] != IntraFrame;
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 {};
}
@ -1152,13 +1134,13 @@ DecoderErrorOr<void> Parser::intra_block_mode_info()
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++) {
if (m_ref_frame[j] > IntraFrame) {
find_mv_refs(m_ref_frame[j], -1);
find_best_ref_mvs(j);
find_mv_refs(row, column, m_ref_frame[j], -1);
find_best_ref_mvs(row, column, j);
}
}
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]]));
}
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
m_interp_filter = m_interpolation_filter;
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]]));
if (m_y_mode == PredictionMode::NearestMv || m_y_mode == PredictionMode::NearMv) {
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));
for (auto y = 0; y < m_num_4x4_h; y++) {
@ -1203,7 +1185,7 @@ DecoderErrorOr<void> Parser::inter_block_mode_info()
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)) {
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 {};
}
ReferenceMode comp_mode;
auto above_context = get_above_context();
auto left_context = get_left_context();
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));
else
@ -1311,7 +1291,7 @@ Gfx::Size<size_t> Parser::get_decoded_size_for_plane(u8 plane)
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);
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 sub_x = (plane > 0) ? m_subsampling_x : 0;
auto sub_y = (plane > 0) ? m_subsampling_y : 0;
auto base_x = (m_mi_col * 8) >> sub_x;
auto base_y = (m_mi_row * 8) >> sub_y;
auto base_x = (column * 8) >> sub_x;
auto base_y = (row * 8) >> sub_y;
if (m_is_inter) {
if (m_mi_size < Block_8x8) {
for (auto y = 0; y < num_4x4_h; y++) {
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 {
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;
@ -1345,7 +1325,7 @@ DecoderErrorOr<void> Parser::residual()
auto non_zero = false;
if (start_x < max_x && start_y < max_y) {
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) {
non_zero = TRY(tokens(plane, start_x, start_y, tx_size, block_index));
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];
// 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_bottom_edge = 8 * ((static_cast<i32>(m_mi_rows) - blocks_high - 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>(row)) * 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_right_edge = 8 * ((static_cast<i32>(m_mi_cols) - blocks_wide - 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>(column)) * MI_SIZE);
return {
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];
vector = clamp_mv(vector, MV_BORDER);
vector = clamp_mv(row, column, vector, MV_BORDER);
}
// 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;
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[1] = {};
MotionVector base_coordinates = MotionVector(m_mi_row, m_mi_col);
MotionVector base_coordinates = MotionVector(row, column);
for (auto i = 0u; i < 2; 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_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) {
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_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];
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)
@ -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;
}
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++) {
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 = { 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];
@ -1655,10 +1635,10 @@ void Parser::find_best_ref_mvs(u8 ref_list)
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];
find_mv_refs(m_ref_frame[ref_list], block);
find_mv_refs(row, column, m_ref_frame[ref_list], block);
auto destination_index = 0;
if (block == 0) {
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_recenter_nonneg(u8 v, u8 m);
DecoderErrorOr<void> read_coef_probs();
FrameBlockContext get_above_context() const;
FrameBlockContext get_left_context() const;
DecoderErrorOr<void> read_skip_prob();
DecoderErrorOr<void> read_inter_mode_probs();
DecoderErrorOr<void> read_interp_filter_probs();
@ -105,24 +103,24 @@ private:
DecoderErrorOr<void> decode_tile();
void clear_left_context();
DecoderErrorOr<void> decode_partition(u32 row, u32 column, BlockSubsize subsize);
DecoderErrorOr<void> decode_block(u32 row, u32 col, BlockSubsize subsize);
DecoderErrorOr<void> mode_info();
DecoderErrorOr<void> intra_frame_mode_info();
DecoderErrorOr<void> decode_block(u32 row, u32 column, BlockSubsize subsize);
DecoderErrorOr<void> mode_info(u32 row, u32 column, FrameBlockContext above_context, FrameBlockContext left_context);
DecoderErrorOr<void> intra_frame_mode_info(FrameBlockContext above_context, FrameBlockContext left_context);
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);
DecoderErrorOr<void> read_tx_size(bool allow_select);
DecoderErrorOr<void> inter_frame_mode_info();
DecoderErrorOr<void> inter_segment_id();
u8 get_segment_id();
DecoderErrorOr<void> read_is_inter();
DecoderErrorOr<void> read_tx_size(FrameBlockContext above_context, FrameBlockContext left_context, bool allow_select);
DecoderErrorOr<void> inter_frame_mode_info(u32 row, u32 column, FrameBlockContext above_context, FrameBlockContext left_context);
DecoderErrorOr<void> inter_segment_id(u32 row, u32 column);
u8 get_segment_id(u32 row, u32 column);
DecoderErrorOr<void> read_is_inter(FrameBlockContext above_context, FrameBlockContext left_context);
DecoderErrorOr<void> intra_block_mode_info();
DecoderErrorOr<void> inter_block_mode_info();
DecoderErrorOr<void> read_ref_frames();
DecoderErrorOr<void> inter_block_mode_info(u32 row, u32 column, FrameBlockContext above_context, FrameBlockContext left_context);
DecoderErrorOr<void> read_ref_frames(FrameBlockContext above_context, FrameBlockContext left_context);
DecoderErrorOr<void> assign_mv(bool is_compound);
DecoderErrorOr<void> read_mv(u8 ref);
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();
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);
@ -130,13 +128,13 @@ private:
DecoderErrorOr<i32> read_coef(Token token);
/* (6.5) Motion Vector Prediction */
void find_mv_refs(ReferenceFrameType, i32 block);
void find_best_ref_mvs(u8 ref_list);
void find_mv_refs(u32 row, u32 column, ReferenceFrameType, i32 block);
void find_best_ref_mvs(u32 row, u32 column, u8 ref_list);
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);
void clamp_mv_ref(u8 i);
MotionVector clamp_mv(MotionVector mvec, i32 border);
void clamp_mv_ref(u32 row, u32 column, u8 i);
MotionVector clamp_mv(u32 row, u32 column, MotionVector mvec, i32 border);
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 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_col_start { 0 };
u32 m_mi_col_end { 0 };
u32 m_mi_row { 0 };
u32 m_mi_col { 0 };
BlockSubsize m_mi_size { 0 };
bool m_available_u { false };
bool m_available_l { false };
u8 m_segment_id { 0 };
// 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