浏览代码

LibVideo/VP9: Begin decoding tiles

FalseHonesty 4 年之前
父节点
当前提交
cfd65eafa9

+ 86 - 5
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);

+ 18 - 7
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;

+ 3 - 0
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
 };
 
 }

+ 67 - 0
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,
+    }
+};
 
 }