diff options
author | FalseHonesty <thefalsehonesty@gmail.com> | 2021-06-26 16:30:44 -0400 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-07-10 21:28:56 +0200 |
commit | 66628053d49880090e64d515e13500b466658bea (patch) | |
tree | 59ff15651c5480992a85439e16b8bfa790004aca /Userland/Libraries/LibVideo/VP9 | |
parent | cbff7c386a820a5ab9e12c3228957b91959bc6c6 (diff) | |
download | serenity-66628053d49880090e64d515e13500b466658bea.zip |
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.
Diffstat (limited to 'Userland/Libraries/LibVideo/VP9')
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/Decoder.cpp | 103 | ||||
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/Decoder.h | 12 | ||||
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/LookupTables.h | 16 | ||||
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/TreeParser.cpp | 8 |
4 files changed, 131 insertions, 8 deletions
diff --git a/Userland/Libraries/LibVideo/VP9/Decoder.cpp b/Userland/Libraries/LibVideo/VP9/Decoder.cpp index 447521ed00..82fb7eccae 100644 --- a/Userland/Libraries/LibVideo/VP9/Decoder.cpp +++ b/Userland/Libraries/LibVideo/VP9/Decoder.cpp @@ -44,9 +44,10 @@ bool Decoder::parse_frame(ByteBuffer const& frame_data) SAFE_CALL(compressed_header()); dbgln("Finished reading compressed header"); SAFE_CALL(m_bit_stream->exit_bool()); - dbgln("Finished reading frame!"); SAFE_CALL(decode_tiles()); + + dbgln("Finished reading frame!"); return true; } @@ -354,7 +355,7 @@ bool Decoder::tile_info() u16 Decoder::calc_min_log2_tile_cols() { 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++; 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; auto partition = m_tree_parser->parse_tree(SyntaxElementType::Partition); - dbgln("Parsed partition value {}", partition); - auto subsize = subsize_lookup[partition][block_subsize]; if (subsize < Block_8x8 || partition == PartitionNone) { 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_l = col > m_mi_col_start; SAFE_CALL(mode_info()); + m_eob_total = 0; + SAFE_CALL(residual()); // FIXME: Finish implementing + // note: when finished, re-enable calculate_default_intra_mode_probability's usage of m_sub_modes return true; } @@ -1104,6 +1106,81 @@ bool Decoder::read_mv(u8) 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) { // TODO: Implement @@ -1122,6 +1199,24 @@ bool Decoder::append_sub8x8_mvs(u8, u8) 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() { dbgln("Frame dimensions: {}x{}", m_frame_width, m_frame_height); diff --git a/Userland/Libraries/LibVideo/VP9/Decoder.h b/Userland/Libraries/LibVideo/VP9/Decoder.h index f10709bd21..f373f8cede 100644 --- a/Userland/Libraries/LibVideo/VP9/Decoder.h +++ b/Userland/Libraries/LibVideo/VP9/Decoder.h @@ -107,12 +107,23 @@ private: bool read_ref_frames(); bool assign_mv(bool is_compound); 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 */ bool find_mv_refs(ReferenceFrame, int block); bool find_best_ref_mvs(int 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_frame_to_show_map_index { 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? u32 m_ref_frame_width[NUM_REF_FRAMES]; u32 m_ref_frame_height[NUM_REF_FRAMES]; + u32 m_eob_total { 0 }; bool m_use_hp { false }; diff --git a/Userland/Libraries/LibVideo/VP9/LookupTables.h b/Userland/Libraries/LibVideo/VP9/LookupTables.h index 29334114f9..df0edeb185 100644 --- a/Userland/Libraries/LibVideo/VP9/LookupTables.h +++ b/Userland/Libraries/LibVideo/VP9/LookupTables.h @@ -200,4 +200,20 @@ static constexpr TXSize max_txsize_lookup[BLOCK_SIZES] = { 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 } }, +}; + } diff --git a/Userland/Libraries/LibVideo/VP9/TreeParser.cpp b/Userland/Libraries/LibVideo/VP9/TreeParser.cpp index df6091c32e..42a160184d 100644 --- a/Userland/Libraries/LibVideo/VP9/TreeParser.cpp +++ b/Userland/Libraries/LibVideo/VP9/TreeParser.cpp @@ -207,17 +207,17 @@ u8 TreeParser::calculate_default_intra_mode_probability(u8 node) { u32 above_mode, left_mode; 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] : 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] : DcPred; } else { if (m_idy) { above_mode = m_decoder.m_block_sub_modes[m_idx]; } 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] : DcPred; } @@ -225,7 +225,7 @@ u8 TreeParser::calculate_default_intra_mode_probability(u8 node) if (m_idx) { left_mode = m_decoder.m_block_sub_modes[m_idy * 2]; } 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] : DcPred; } |