diff --git a/Userland/Libraries/LibVideo/VP9/Decoder.cpp b/Userland/Libraries/LibVideo/VP9/Decoder.cpp index d335352b95..4c2b741157 100644 --- a/Userland/Libraries/LibVideo/VP9/Decoder.cpp +++ b/Userland/Libraries/LibVideo/VP9/Decoder.cpp @@ -828,7 +828,7 @@ bool Decoder::intra_frame_mode_info() m_ref_frame[1] = None; m_is_inter = false; if (m_mi_size >= Block_8x8) { - m_default_intra_mode = static_cast(m_tree_parser->parse_tree(SyntaxElementType::DefaultIntraMode)); + m_default_intra_mode = m_tree_parser->parse_tree(SyntaxElementType::DefaultIntraMode); m_y_mode = m_default_intra_mode; for (auto b = 0; b < 4; b++) m_sub_modes[b] = m_y_mode; @@ -837,7 +837,7 @@ bool Decoder::intra_frame_mode_info() m_num_4x4_h = num_4x4_blocks_high_lookup[m_mi_size]; for (auto idy = 0; idy < 2; idy += m_num_4x4_h) { for (auto idx = 0; idx < 2; idx += m_num_4x4_w) { - m_default_intra_mode = static_cast(m_tree_parser->parse_tree(SyntaxElementType::DefaultIntraMode)); + m_default_intra_mode = m_tree_parser->parse_tree(SyntaxElementType::DefaultIntraMode); for (auto y = 0; y < m_num_4x4_h; y++) { for (auto x = 0; x < m_num_4x4_w; x++) { auto index = (idy + y) * 2 + idx + x; @@ -850,14 +850,14 @@ bool Decoder::intra_frame_mode_info() } m_y_mode = m_default_intra_mode; } - m_uv_mode = m_tree_parser->parse_tree(SyntaxElementType::DefaultUVMode); + m_uv_mode = m_tree_parser->parse_tree(SyntaxElementType::DefaultUVMode); return true; } bool Decoder::intra_segment_id() { if (m_segmentation_enabled && m_segmentation_update_map) { - m_segment_id = m_tree_parser->parse_tree(SyntaxElementType::SegmentID); + m_segment_id = m_tree_parser->parse_tree(SyntaxElementType::SegmentID); } else { m_segment_id = 0; } @@ -867,9 +867,9 @@ bool Decoder::intra_segment_id() bool Decoder::read_skip() { if (seg_feature_active(SEG_LVL_SKIP)) { - m_skip = 1; + m_skip = true; } else { - m_skip = m_tree_parser->parse_tree(SyntaxElementType::Skip); + m_skip = m_tree_parser->parse_tree(SyntaxElementType::Skip); } return true; } @@ -883,7 +883,7 @@ bool Decoder::read_tx_size(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 = static_cast(m_tree_parser->parse_tree(SyntaxElementType::TXSize)); + m_tx_size = m_tree_parser->parse_tree(SyntaxElementType::TXSize); } else { m_tx_size = min(m_max_tx_size, tx_mode_to_biggest_tx_size[m_tx_mode]); } @@ -892,7 +892,87 @@ bool Decoder::read_tx_size(bool allow_select) bool Decoder::inter_frame_mode_info() { - // FIXME: Implement + m_left_ref_frame[0] = m_available_l ? m_ref_frames[m_mi_row][m_mi_col - 1][0] : IntraFrame; + m_above_ref_frame[0] = m_available_u ? m_ref_frames[m_mi_row - 1][m_mi_col][0] : IntraFrame; + m_left_ref_frame[1] = m_available_l ? m_ref_frames[m_mi_row][m_mi_col - 1][1] : None; + m_above_ref_frame[1] = m_available_u ? m_ref_frames[m_mi_row - 1][m_mi_col][1] : None; + m_left_intra = m_left_ref_frame[0] <= IntraFrame; + m_above_intra = m_above_ref_frame[0] <= IntraFrame; + m_left_single = m_left_ref_frame[1] <= None; + m_above_single = m_above_ref_frame[1] <= None; + SAFE_CALL(inter_segment_id()); + SAFE_CALL(read_skip()); + SAFE_CALL(read_is_inter()); + SAFE_CALL(read_tx_size(!m_skip || !m_is_inter)); + if (m_is_inter) { + SAFE_CALL(inter_block_mode_info()); + } else { + SAFE_CALL(intra_block_mode_info()); + } + return true; +} + +bool Decoder::inter_segment_id() +{ + if (!m_segmentation_enabled) { + m_segment_id = 0; + return true; + } + auto predicted_segment_id = get_segment_id(); + if (!m_segmentation_update_map) { + m_segment_id = predicted_segment_id; + return true; + } + if (!m_segmentation_temporal_update) { + m_segment_id = m_tree_parser->parse_tree(SyntaxElementType::SegmentID); + return true; + } + + auto seg_id_predicted = m_tree_parser->parse_tree(SyntaxElementType::SegIDPredicted); + if (seg_id_predicted) + m_segment_id = predicted_segment_id; + else + m_segment_id = m_tree_parser->parse_tree(SyntaxElementType::SegmentID); + for (auto i = 0u; i < num_8x8_blocks_wide_lookup[m_mi_size]; i++) + m_above_seg_pred_context[m_mi_col + i] = seg_id_predicted; + for (auto i = 0u; i < num_8x8_blocks_high_lookup[m_mi_size]; i++) + m_left_seg_pred_context[m_mi_row + i] = seg_id_predicted; + return true; +} + +u8 Decoder::get_segment_id() +{ + 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); + u8 segment = 7; + for (auto y = 0u; y < ymis; y++) { + for (auto x = 0u; x < xmis; x++) { + segment = min(segment, m_prev_segment_ids[m_mi_row + y][m_mi_col + x]); + } + } + return segment; +} + +bool Decoder::read_is_inter() +{ + 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 = m_tree_parser->parse_tree(SyntaxElementType::IsInter); + return true; +} + +bool Decoder::inter_block_mode_info() +{ + // TODO: Implement + return true; +} + +bool Decoder::intra_block_mode_info() +{ + // TODO: Implement return true; } diff --git a/Userland/Libraries/LibVideo/VP9/Decoder.h b/Userland/Libraries/LibVideo/VP9/Decoder.h index dbcce81d57..db8e9583cd 100644 --- a/Userland/Libraries/LibVideo/VP9/Decoder.h +++ b/Userland/Libraries/LibVideo/VP9/Decoder.h @@ -92,8 +92,13 @@ private: bool read_skip(); bool seg_feature_active(u8 feature); bool read_tx_size(bool allow_select); - bool inter_frame_mode_info(); + bool inter_segment_id(); + u8 get_segment_id(); + bool read_is_inter(); + bool inter_block_mode_info(); + + bool intra_block_mode_info(); u8 m_profile { 0 }; u8 m_frame_to_show_map_index { 0 }; @@ -158,8 +163,8 @@ private: u32 m_mi_size { 0 }; bool m_available_u { false }; bool m_available_l { false }; - int m_segment_id { 0 }; - int m_skip { false }; + u8 m_segment_id { 0 }; + bool m_skip { false }; u8 m_num_8x8 { 0 }; bool m_has_rows { false }; bool m_has_cols { false }; @@ -176,6 +181,14 @@ private: u8 m_num_4x4_w { 0 }; u8 m_num_4x4_h { 0 }; u8 m_uv_mode { 0 }; // FIXME: Is u8 the right size? + ReferenceFrame m_left_ref_frame[2]; + ReferenceFrame m_above_ref_frame[2]; + Vector>> m_ref_frames; // TODO: Can we make these fixed sized allocations? + bool m_left_intra { false }; + bool m_above_intra { false }; + bool m_left_single { false }; + bool m_above_single { false }; + Vector> m_prev_segment_ids; bool m_use_hp { false }; diff --git a/Userland/Libraries/LibVideo/VP9/TreeParser.cpp b/Userland/Libraries/LibVideo/VP9/TreeParser.cpp index bb8f90e8c9..54b050a4b5 100644 --- a/Userland/Libraries/LibVideo/VP9/TreeParser.cpp +++ b/Userland/Libraries/LibVideo/VP9/TreeParser.cpp @@ -10,7 +10,8 @@ namespace Video::VP9 { -int TreeParser::parse_tree(SyntaxElementType type) +template +T TreeParser::parse_tree(SyntaxElementType type) { auto tree_selection = select_tree(type); int value; @@ -25,9 +26,15 @@ int TreeParser::parse_tree(SyntaxElementType type) value = -n; } count_syntax_element(type, value); - return value; + return static_cast(value); } +template int TreeParser::parse_tree(SyntaxElementType); +template bool TreeParser::parse_tree(SyntaxElementType); +template u8 TreeParser::parse_tree(SyntaxElementType); +template IntraMode TreeParser::parse_tree(SyntaxElementType); +template TXSize TreeParser::parse_tree(SyntaxElementType); + /* * Select a tree value based on the type of syntax element being parsed, as well as some parser state, as specified in section 9.3.1 */ diff --git a/Userland/Libraries/LibVideo/VP9/TreeParser.h b/Userland/Libraries/LibVideo/VP9/TreeParser.h index d22e378a52..e22ac08ee7 100644 --- a/Userland/Libraries/LibVideo/VP9/TreeParser.h +++ b/Userland/Libraries/LibVideo/VP9/TreeParser.h @@ -41,7 +41,8 @@ public: TreeSelectionValue m_value; }; - int parse_tree(SyntaxElementType type); + template + T parse_tree(SyntaxElementType type); TreeSelection select_tree(SyntaxElementType type); u8 select_tree_probability(SyntaxElementType type, u8 node); void count_syntax_element(SyntaxElementType type, int value);