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

LibVideo/VP9: Start parsing residuals (6.4.21-6.4.23)

Additionally, this uncovered a couple bugs with existing code,
so those have been fixed. Currently, parsing a whole video does
fail because we are now using a new calculation for frame width,
but it hasn't been fully implemented yet.
This commit is contained in:
FalseHonesty 2021-06-26 16:30:44 -04:00 committed by Andreas Kling
parent cbff7c386a
commit 66628053d4
4 changed files with 131 additions and 8 deletions

View file

@ -44,9 +44,10 @@ bool Decoder::parse_frame(ByteBuffer const& frame_data)
SAFE_CALL(compressed_header()); SAFE_CALL(compressed_header());
dbgln("Finished reading compressed header"); dbgln("Finished reading compressed header");
SAFE_CALL(m_bit_stream->exit_bool()); SAFE_CALL(m_bit_stream->exit_bool());
dbgln("Finished reading frame!");
SAFE_CALL(decode_tiles()); SAFE_CALL(decode_tiles());
dbgln("Finished reading frame!");
return true; return true;
} }
@ -354,7 +355,7 @@ bool Decoder::tile_info()
u16 Decoder::calc_min_log2_tile_cols() u16 Decoder::calc_min_log2_tile_cols()
{ {
auto min_log_2 = 0u; auto min_log_2 = 0u;
while ((u8)(MAX_TILE_WIDTH_B64 << min_log_2) < m_sb64_cols) while ((u32)(MAX_TILE_WIDTH_B64 << min_log_2) < m_sb64_cols)
min_log_2++; min_log_2++;
return min_log_2; return min_log_2;
} }
@ -780,8 +781,6 @@ bool Decoder::decode_partition(u32 row, u32 col, u8 block_subsize)
m_has_cols = (col + half_block_8x8) < m_mi_cols; m_has_cols = (col + half_block_8x8) < m_mi_cols;
auto partition = m_tree_parser->parse_tree(SyntaxElementType::Partition); auto partition = m_tree_parser->parse_tree(SyntaxElementType::Partition);
dbgln("Parsed partition value {}", partition);
auto subsize = subsize_lookup[partition][block_subsize]; auto subsize = subsize_lookup[partition][block_subsize];
if (subsize < Block_8x8 || partition == PartitionNone) { if (subsize < Block_8x8 || partition == PartitionNone) {
SAFE_CALL(decode_block(row, col, subsize)); SAFE_CALL(decode_block(row, col, subsize));
@ -816,7 +815,10 @@ bool Decoder::decode_block(u32 row, u32 col, u8 subsize)
m_available_u = row > 0; m_available_u = row > 0;
m_available_l = col > m_mi_col_start; m_available_l = col > m_mi_col_start;
SAFE_CALL(mode_info()); SAFE_CALL(mode_info());
m_eob_total = 0;
SAFE_CALL(residual());
// FIXME: Finish implementing // FIXME: Finish implementing
// note: when finished, re-enable calculate_default_intra_mode_probability's usage of m_sub_modes
return true; return true;
} }
@ -1104,6 +1106,81 @@ bool Decoder::read_mv(u8)
return true; return true;
} }
bool Decoder::residual()
{
auto block_size = m_mi_size < Block_8x8 ? Block_8x8 : static_cast<BlockSubsize>(m_mi_size);
for (size_t plane = 0; plane < 3; plane++) {
auto tx_size = (plane > 0) ? get_uv_tx_size() : m_tx_size;
auto step = 1 << tx_size;
auto plane_size = get_plane_block_size(block_size, plane);
auto num_4x4_w = num_4x4_blocks_wide_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_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;
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++) {
SAFE_CALL(predict_inter(plane, base_x + (4 * x), base_y + (4 * y), 4, 4, (y * num_4x4_w) + x));
}
}
} else {
SAFE_CALL(predict_inter(plane, base_x, base_y, num_4x4_w * 4, num_4x4_h * 4, 0));
}
}
auto max_x = (m_mi_cols * 8) >> sub_x;
auto max_y = (m_mi_rows * 8) >> sub_y;
auto block_index = 0;
for (auto y = 0; y < num_4x4_h; y += step) {
for (auto x = 0; x < num_4x4_w; x += step) {
auto start_x = base_x + (4 * x);
auto start_y = base_y + (4 * y);
auto non_zero = false;
if (start_x < max_x && start_y < max_y) {
if (!m_is_inter)
SAFE_CALL(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));
if (!m_skip) {
non_zero = tokens(plane, start_x, start_y, tx_size, block_index);
SAFE_CALL(reconstruct(plane, start_x, start_y, tx_size));
}
}
auto above_sub_context = m_above_nonzero_context[plane];
auto left_sub_context = m_left_nonzero_context[plane];
above_sub_context.resize_and_keep_capacity((start_x >> 2) + step);
left_sub_context.resize_and_keep_capacity((start_y >> 2) + step);
for (auto i = 0; i < step; i++) {
above_sub_context[(start_x >> 2) + i] = non_zero;
left_sub_context[(start_y >> 2) + i] = non_zero;
}
block_index++;
}
}
}
return true;
}
TXSize Decoder::get_uv_tx_size()
{
if (m_mi_size < Block_8x8)
return TX_4x4;
return min(m_tx_size, max_txsize_lookup[get_plane_block_size(m_mi_size, 1)]);
}
BlockSubsize Decoder::get_plane_block_size(u32 subsize, u8 plane)
{
auto sub_x = (plane > 0) ? m_subsampling_x : 0;
auto sub_y = (plane > 0) ? m_subsampling_y : 0;
return ss_size_lookup[subsize][sub_x][sub_y];
}
bool Decoder::tokens(size_t, u32, u32, TXSize, u32)
{
// TODO: Implement
return true;
}
bool Decoder::find_mv_refs(ReferenceFrame, int) bool Decoder::find_mv_refs(ReferenceFrame, int)
{ {
// TODO: Implement // TODO: Implement
@ -1122,6 +1199,24 @@ bool Decoder::append_sub8x8_mvs(u8, u8)
return true; return true;
} }
bool Decoder::predict_intra(size_t, u32, u32, bool, bool, bool, TXSize, u32)
{
// TODO: Implement
return true;
}
bool Decoder::predict_inter(size_t, u32, u32, u32, u32, u32)
{
// TODO: Implement
return true;
}
bool Decoder::reconstruct(size_t, u32, u32, TXSize)
{
// TODO: Implement
return true;
}
void Decoder::dump_info() void Decoder::dump_info()
{ {
dbgln("Frame dimensions: {}x{}", m_frame_width, m_frame_height); dbgln("Frame dimensions: {}x{}", m_frame_width, m_frame_height);

View file

@ -107,12 +107,23 @@ private:
bool read_ref_frames(); bool read_ref_frames();
bool assign_mv(bool is_compound); bool assign_mv(bool is_compound);
bool read_mv(u8 ref); bool read_mv(u8 ref);
bool residual();
TXSize get_uv_tx_size();
BlockSubsize get_plane_block_size(u32 subsize, u8 plane);
bool tokens(size_t plane, u32 x, u32 y, TXSize size, u32 index);
/* (6.5) Motion Vector Prediction */ /* (6.5) Motion Vector Prediction */
bool find_mv_refs(ReferenceFrame, int block); bool find_mv_refs(ReferenceFrame, int block);
bool find_best_ref_mvs(int ref_list); bool find_best_ref_mvs(int ref_list);
bool append_sub8x8_mvs(u8 block, u8 ref_list); bool append_sub8x8_mvs(u8 block, u8 ref_list);
/* (8.5) Prediction Processes */
bool predict_intra(size_t plane, u32 x, u32 y, bool have_left, bool have_above, bool not_on_right, TXSize tx_size, u32 block_index);
bool predict_inter(size_t plane, u32 x, u32 y, u32 w, u32 h, u32 block_index);
/* (8.6) Reconstruction and Dequantization */
bool reconstruct(size_t plane, u32 x, u32 y, TXSize size);
u8 m_profile { 0 }; u8 m_profile { 0 };
u8 m_frame_to_show_map_index { 0 }; u8 m_frame_to_show_map_index { 0 };
u16 m_header_size_in_bytes { 0 }; u16 m_header_size_in_bytes { 0 };
@ -209,6 +220,7 @@ private:
Vector<Vector<Vector<IntraMode>>> m_sub_modes; // FIXME: Can we make these fixed sized allocations? Vector<Vector<Vector<IntraMode>>> m_sub_modes; // FIXME: Can we make these fixed sized allocations?
u32 m_ref_frame_width[NUM_REF_FRAMES]; u32 m_ref_frame_width[NUM_REF_FRAMES];
u32 m_ref_frame_height[NUM_REF_FRAMES]; u32 m_ref_frame_height[NUM_REF_FRAMES];
u32 m_eob_total { 0 };
bool m_use_hp { false }; bool m_use_hp { false };

View file

@ -200,4 +200,20 @@ static constexpr TXSize max_txsize_lookup[BLOCK_SIZES] = {
TX_32x32, TX_32x32,
}; };
static constexpr BlockSubsize ss_size_lookup[BLOCK_SIZES][2][2] = {
{ { Block_4x4, Block_Invalid }, { Block_Invalid, Block_Invalid } },
{ { Block_4x8, Block_4x4 }, { Block_Invalid, Block_Invalid } },
{ { Block_8x4, Block_Invalid }, { Block_4x4, Block_Invalid } },
{ { Block_8x8, Block_8x4 }, { Block_4x8, Block_4x4 } },
{ { Block_8x16, Block_8x8 }, { Block_Invalid, Block_4x8 } },
{ { Block_16x8, Block_Invalid }, { Block_8x8, Block_8x4 } },
{ { Block_16x16, Block_16x8 }, { Block_8x16, Block_8x8 } },
{ { Block_16x32, Block_16x16 }, { Block_Invalid, Block_8x16 } },
{ { Block_32x16, Block_Invalid }, { Block_16x16, Block_16x8 } },
{ { Block_32x32, Block_32x16 }, { Block_16x32, Block_16x16 } },
{ { Block_32x64, Block_32x32 }, { Block_Invalid, Block_16x32 } },
{ { Block_64x32, Block_Invalid }, { Block_32x32, Block_32x16 } },
{ { Block_64x64, Block_64x32 }, { Block_32x64, Block_32x32 } },
};
} }

View file

@ -207,17 +207,17 @@ u8 TreeParser::calculate_default_intra_mode_probability(u8 node)
{ {
u32 above_mode, left_mode; u32 above_mode, left_mode;
if (m_decoder.m_mi_size >= Block_8x8) { if (m_decoder.m_mi_size >= Block_8x8) {
above_mode = AVAIL_U above_mode = false // FIXME: AVAIL_U
? m_decoder.m_sub_modes[m_decoder.m_mi_row - 1][m_decoder.m_mi_col][2] ? m_decoder.m_sub_modes[m_decoder.m_mi_row - 1][m_decoder.m_mi_col][2]
: DcPred; : DcPred;
left_mode = AVAIL_L left_mode = false // FIXME: AVAIL_L
? m_decoder.m_sub_modes[m_decoder.m_mi_row][m_decoder.m_mi_col - 1][1] ? m_decoder.m_sub_modes[m_decoder.m_mi_row][m_decoder.m_mi_col - 1][1]
: DcPred; : DcPred;
} else { } else {
if (m_idy) { if (m_idy) {
above_mode = m_decoder.m_block_sub_modes[m_idx]; above_mode = m_decoder.m_block_sub_modes[m_idx];
} else { } else {
above_mode = AVAIL_U above_mode = false // FIXME: AVAIL_U
? m_decoder.m_sub_modes[m_decoder.m_mi_row - 1][m_decoder.m_mi_col][2 + m_idx] ? m_decoder.m_sub_modes[m_decoder.m_mi_row - 1][m_decoder.m_mi_col][2 + m_idx]
: DcPred; : DcPred;
} }
@ -225,7 +225,7 @@ u8 TreeParser::calculate_default_intra_mode_probability(u8 node)
if (m_idx) { if (m_idx) {
left_mode = m_decoder.m_block_sub_modes[m_idy * 2]; left_mode = m_decoder.m_block_sub_modes[m_idy * 2];
} else { } else {
left_mode = AVAIL_L left_mode = false // FIXME: AVAIL_L
? m_decoder.m_sub_modes[m_decoder.m_mi_row][m_decoder.m_mi_col - 1][1 + m_idy * 2] ? m_decoder.m_sub_modes[m_decoder.m_mi_row][m_decoder.m_mi_col - 1][1 + m_idy * 2]
: DcPred; : DcPred;
} }