diff options
author | FalseHonesty <thefalsehonesty@gmail.com> | 2021-01-29 19:00:21 -0500 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-06-30 11:03:51 +0200 |
commit | cfd65eafa9bf706ed2bcbc397e4b35bc5f12b4ab (patch) | |
tree | e93c10b889fd6b9da4dd3e2edfb712c13322e265 | |
parent | f9899fc17fa95046c507f2858cb802634d1fb2e9 (diff) | |
download | serenity-cfd65eafa9bf706ed2bcbc397e4b35bc5f12b4ab.zip |
LibVideo/VP9: Begin decoding tiles
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/Decoder.cpp | 91 | ||||
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/Decoder.h | 25 | ||||
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/Enums.h | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/LookupTables.h | 67 |
4 files changed, 174 insertions, 12 deletions
diff --git a/Userland/Libraries/LibVideo/VP9/Decoder.cpp b/Userland/Libraries/LibVideo/VP9/Decoder.cpp index d9a206530c..b102c895fb 100644 --- a/Userland/Libraries/LibVideo/VP9/Decoder.cpp +++ b/Userland/Libraries/LibVideo/VP9/Decoder.cpp @@ -22,7 +22,6 @@ bool Decoder::parse_frame(const ByteBuffer& frame_data) m_bit_stream = make<BitStream>(frame_data.data(), frame_data.size()); m_syntax_element_counter = make<SyntaxElementCounter>(); - m_start_bit_pos = m_bit_stream->get_position(); if (!uncompressed_header()) return false; dbgln("Finished reading uncompressed header"); @@ -48,6 +47,8 @@ bool Decoder::parse_frame(const ByteBuffer& frame_data) if (!m_bit_stream->exit_bool()) return false; dbgln("Finished reading frame!"); + + decode_tiles(); return true; } @@ -366,8 +367,8 @@ bool Decoder::tile_info() u16 Decoder::calc_min_log2_tile_cols() { - auto min_log_2 = 0; - while ((MAX_TILE_WIDTH_B64 << min_log_2) < m_sb64_cols) + auto min_log_2 = 0u; + while ((u8)(MAX_TILE_WIDTH_B64 << min_log_2) < m_sb64_cols) min_log_2++; return min_log_2; } @@ -389,8 +390,8 @@ bool Decoder::setup_past_independence() } } m_segmentation_abs_or_delta_update = false; - for (auto row = 0; row < m_mi_rows; row++) { - for (auto col = 0; col < m_mi_cols; col++) { + for (auto row = 0u; row < m_mi_rows; row++) { + for (auto col = 0u; col < m_mi_cols; col++) { // TODO: m_prev_segment_ids[row][col] = 0; } } @@ -713,6 +714,86 @@ bool Decoder::setup_compound_reference_mode() return true; } +bool Decoder::decode_tiles() +{ + auto tile_cols = 1 << m_tile_cols_log2; + auto tile_rows = 1 << m_tile_rows_log2; + if (!clear_above_context()) + return false; + for (auto tile_row = 0; tile_row < tile_rows; tile_row++) { + for (auto tile_col = 0; tile_col < tile_cols; tile_col++) { + auto last_tile = (tile_row == tile_rows - 1) && (tile_col == tile_cols - 1); + // FIXME: Spec has `sz -= tile_size + 4`, but I think we don't need this because our bit stream manages how much data we have left? + auto tile_size = last_tile ? m_bit_stream->bytes_remaining() : m_bit_stream->read_f(32); + m_mi_row_start = get_tile_offset(tile_row, m_mi_rows, m_tile_rows_log2); + m_mi_row_end = get_tile_offset(tile_row + 1, m_mi_rows, m_tile_rows_log2); + m_mi_col_start = get_tile_offset(tile_col, m_mi_cols, m_tile_cols_log2); + m_mi_col_end = get_tile_offset(tile_col + 1, m_mi_cols, m_tile_cols_log2); + m_bit_stream->init_bool(tile_size); + decode_tile(); + m_bit_stream->exit_bool(); + } + } + + return true; +} + +bool Decoder::clear_above_context() +{ + // FIXME + // When this function is invoked the arrays AboveNonzeroContext, AbovePartitionContext, AboveSegPredContext should be set equal to 0. + // AboveNonzeroContext[0..2][0..MiCols*2-1] = 0 + // AboveSegPredContext[0..MiCols-1] = 0 + // AbovePartitionContext[0..Sb64Cols*8-1] = 0 + return true; +} + +u32 Decoder::get_tile_offset(u32 tile_num, u32 mis, u32 tile_size_log2) +{ + u32 super_blocks = (mis + 7) >> 3u; + u32 offset = ((tile_num * super_blocks) >> tile_size_log2) << 3u; + return min(offset, mis); +} + +bool Decoder::decode_tile() +{ + for (auto row = m_mi_row_start; row < m_mi_row_end; row += 8) { + if (!clear_left_context()) + return false; + for (auto col = m_mi_col_start; col < m_mi_col_end; col += 8) { + if (!decode_partition(row, col, Block_64x64)) + return false; + } + } + return true; +} + +bool Decoder::clear_left_context() +{ + // FIXME + // When this function is invoked the arrays LeftNonzeroContext, LeftPartitionContext, LeftSegPredContext should be set equal to 0. + // LeftNonzeroContext[0..2][0..MiRows*2-1] = 0 + // LeftSegPredContext[0..MiRows-1] = 0 + // LeftPartitionContext[0..Sb64Rows*8-1] = 0 + return true; +} + +bool Decoder::decode_partition(u32 row, u32 col, u8 block_subsize) +{ + if (row >= m_mi_rows || col >= m_mi_cols) + return false; + auto num_8x8 = num_8x8_blocks_wide_lookup[block_subsize]; + auto half_block_8x8 = num_8x8 >> 1; + auto has_rows = (row + half_block_8x8) < m_mi_rows; + auto has_cols = (col + half_block_8x8) < m_mi_cols; + + // FIXME: Parse partition (type: T) as specified by spec in section 9.3 + (void)has_rows; + (void)has_cols; + + 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 ed4cb7ce88..3ccc62888f 100644 --- a/Userland/Libraries/LibVideo/VP9/Decoder.h +++ b/Userland/Libraries/LibVideo/VP9/Decoder.h @@ -75,7 +75,13 @@ private: u8 update_mv_prob(u8 prob); bool setup_compound_reference_mode(); - u64 m_start_bit_pos { 0 }; + bool decode_tiles(); + bool clear_above_context(); + u32 get_tile_offset(u32 tile_num, u32 mis, u32 tile_size_log2); + bool decode_tile(); + bool clear_left_context(); + bool decode_partition(u32 row, u32 col, u8 block_subsize); + u8 m_profile { 0 }; u8 m_frame_to_show_map_index { 0 }; u16 m_header_size_in_bytes { 0 }; @@ -100,15 +106,15 @@ private: ColorRange m_color_range; bool m_subsampling_x { false }; bool m_subsampling_y { false }; - u16 m_frame_width { 0 }; - u16 m_frame_height { 0 }; + u32 m_frame_width { 0 }; + u32 m_frame_height { 0 }; u16 m_render_width { 0 }; u16 m_render_height { 0 }; bool m_render_and_frame_size_different { false }; - u16 m_mi_cols { 0 }; - u16 m_mi_rows { 0 }; - u16 m_sb64_cols { 0 }; - u16 m_sb64_rows { 0 }; + u32 m_mi_cols { 0 }; + u32 m_mi_rows { 0 }; + u32 m_sb64_cols { 0 }; + u32 m_sb64_rows { 0 }; InterpolationFilter m_interpolation_filter; bool m_lossless { false }; u8 m_segmentation_tree_probs[7]; @@ -121,6 +127,11 @@ private: i8 m_loop_filter_ref_deltas[MAX_REF_FRAMES]; i8 m_loop_filter_mode_deltas[2]; + u32 m_mi_row_start { 0 }; + u32 m_mi_row_end { 0 }; + u32 m_mi_col_start { 0 }; + u32 m_mi_col_end { 0 }; + TXMode m_tx_mode; ReferenceMode m_reference_mode; ReferenceFrame m_comp_fixed_ref; diff --git a/Userland/Libraries/LibVideo/VP9/Enums.h b/Userland/Libraries/LibVideo/VP9/Enums.h index aaea93101f..577c2f0524 100644 --- a/Userland/Libraries/LibVideo/VP9/Enums.h +++ b/Userland/Libraries/LibVideo/VP9/Enums.h @@ -6,6 +6,8 @@ #pragma once +#include "Symbols.h" + namespace Video::VP9 { enum FrameType { @@ -79,6 +81,7 @@ enum BlockSubsize : u8 { Block_32x64 = 10, Block_64x32 = 11, Block_64x64 = 12, + Block_Invalid = BLOCK_INVALID }; } diff --git a/Userland/Libraries/LibVideo/VP9/LookupTables.h b/Userland/Libraries/LibVideo/VP9/LookupTables.h index 0c5ea89113..66ea5473ff 100644 --- a/Userland/Libraries/LibVideo/VP9/LookupTables.h +++ b/Userland/Libraries/LibVideo/VP9/LookupTables.h @@ -30,5 +30,72 @@ static constexpr u8 inv_map_table[MAX_PROB] = { 226, 227, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 253 }; +static constexpr u8 num_8x8_blocks_wide_lookup[BLOCK_SIZES] = { 1, 1, 1, 1, 1, 2, 2, 2, 4, 4, 4, 8, 8 }; +static constexpr BlockSubsize subsize_lookup[PARTITION_TYPES][BLOCK_SIZES] = { + { + // PARTITION_NONE + Block_4x4, + Block_4x8, + Block_8x4, + Block_8x8, + Block_8x16, + Block_16x8, + Block_16x16, + Block_16x32, + Block_32x16, + Block_32x32, + Block_32x64, + Block_64x32, + Block_64x64, + }, + { + // PARTITION_HORZ + Block_Invalid, + Block_Invalid, + Block_Invalid, + Block_8x4, + Block_Invalid, + Block_Invalid, + Block_16x8, + Block_Invalid, + Block_Invalid, + Block_32x16, + Block_Invalid, + Block_Invalid, + Block_64x32, + }, + { + // PARTITION_VERT + Block_Invalid, + Block_Invalid, + Block_Invalid, + Block_4x8, + Block_Invalid, + Block_Invalid, + Block_8x16, + Block_Invalid, + Block_Invalid, + Block_16x32, + Block_Invalid, + Block_Invalid, + Block_32x64, + }, + { + // PARTITION_SPLIT + Block_Invalid, + Block_Invalid, + Block_Invalid, + Block_4x4, + Block_Invalid, + Block_Invalid, + Block_8x8, + Block_Invalid, + Block_Invalid, + Block_16x16, + Block_Invalid, + Block_Invalid, + Block_32x32, + } +}; } |