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

LibVideo/VP9: Begin decoding VP9 blocks

This commit is contained in:
FalseHonesty 2021-01-31 00:16:46 -05:00 committed by Andreas Kling
parent 2ce4155b42
commit 375dbad144
4 changed files with 135 additions and 8 deletions

View file

@ -16,6 +16,7 @@ Decoder::Decoder()
: m_probability_tables(make<ProbabilityTables>()) : m_probability_tables(make<ProbabilityTables>())
, m_tree_parser(make<TreeParser>(*m_probability_tables)) , m_tree_parser(make<TreeParser>(*m_probability_tables))
{ {
m_tree_parser->set_segmentation_tree_probs(m_segmentation_tree_probs);
} }
bool Decoder::parse_frame(const ByteBuffer& frame_data) bool Decoder::parse_frame(const ByteBuffer& frame_data)
@ -307,18 +308,18 @@ i8 Decoder::read_delta_q()
bool Decoder::segmentation_params() bool Decoder::segmentation_params()
{ {
auto segmentation_enabled = m_bit_stream->read_bit(); m_segmentation_enabled = m_bit_stream->read_bit();
if (!segmentation_enabled) if (!m_segmentation_enabled)
return true; return true;
auto segmentation_update_map = m_bit_stream->read_bit(); m_segmentation_update_map = m_bit_stream->read_bit();
if (segmentation_update_map) { if (m_segmentation_update_map) {
for (auto i = 0; i < 7; i++) { for (auto i = 0; i < 7; i++) {
m_segmentation_tree_probs[i] = read_prob(); m_segmentation_tree_probs[i] = read_prob();
} }
auto segmentation_temporal_update = m_bit_stream->read_bit(); m_segmentation_temporal_update = m_bit_stream->read_bit();
for (auto i = 0; i < 3; i++) { for (auto i = 0; i < 3; i++) {
m_segmentation_pred_prob[i] = segmentation_temporal_update ? read_prob() : 255; m_segmentation_pred_prob[i] = m_segmentation_temporal_update ? read_prob() : 255;
} }
} }
@ -808,11 +809,94 @@ bool Decoder::decode_partition(u32 row, u32 col, u8 block_subsize)
auto partition = m_tree_parser->parse_tree(SyntaxElementType::Partition); auto partition = m_tree_parser->parse_tree(SyntaxElementType::Partition);
dbgln("Parsed partition value {}", partition); dbgln("Parsed partition value {}", partition);
auto subsize = subsize_lookup[partition][block_subsize];
if (subsize < Block_8x8 || partition == PartitionNone) {
if (!decode_block(row, col, subsize))
return false;
} else if (partition == PartitionHorizontal) {
if (!decode_block(row, col, subsize))
return false;
// FIXME: if (hasRows)
// decode_block(r + halfBlock8x8, c, subsize)
}
// FIXME: Finish implementing partition decoding // FIXME: Finish implementing partition decoding
return true; return true;
} }
bool Decoder::decode_block(u32 row, u32 col, u8 subsize)
{
m_mi_row = row;
m_tree_parser->set_mi_row(m_mi_row);
m_mi_col = col;
m_tree_parser->set_mi_col(m_mi_col);
m_mi_size = subsize;
m_available_u = row > 0;
m_tree_parser->set_available_u(m_available_u);
m_available_l = col > m_mi_col_start;
m_tree_parser->set_available_l(m_available_l);
if (!mode_info())
return false;
// FIXME: Finish implementing
return true;
}
bool Decoder::mode_info()
{
if (m_frame_is_intra)
return intra_frame_mode_info();
return inter_frame_mode_info();
}
bool Decoder::intra_frame_mode_info()
{
if (!intra_segment_id())
return false;
if (!read_skip())
return false;
if (!read_tx_size(true))
return false;
// FIXME: Finish implementing
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);
} else {
m_segment_id = 0;
}
return true;
}
bool Decoder::read_skip()
{
if (seg_feature_active(SEG_LVL_SKIP)) {
m_skip = 1;
} else {
m_skip = m_tree_parser->parse_tree(SyntaxElementType::Skip);
}
return true;
}
bool Decoder::seg_feature_active(u8 feature)
{
return m_segmentation_enabled && m_feature_enabled[m_segment_id][feature];
}
bool Decoder::read_tx_size(bool allow_select)
{
// FIXME: Implement
(void)allow_select;
return true;
}
bool Decoder::inter_frame_mode_info()
{
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

@ -83,6 +83,15 @@ private:
bool decode_tile(); bool decode_tile();
bool clear_left_context(); bool clear_left_context();
bool decode_partition(u32 row, u32 col, u8 block_subsize); bool decode_partition(u32 row, u32 col, u8 block_subsize);
bool decode_block(u32 row, u32 col, u8 subsize);
bool mode_info();
bool intra_frame_mode_info();
bool intra_segment_id();
bool read_skip();
bool seg_feature_active(u8 feature);
bool read_tx_size(bool allow_select);
bool inter_frame_mode_info();
u8 m_profile { 0 }; u8 m_profile { 0 };
u8 m_frame_to_show_map_index { 0 }; u8 m_frame_to_show_map_index { 0 };
@ -123,6 +132,9 @@ private:
u8 m_segmentation_pred_prob[3]; u8 m_segmentation_pred_prob[3];
bool m_feature_enabled[8][4]; bool m_feature_enabled[8][4];
u8 m_feature_data[8][4]; u8 m_feature_data[8][4];
bool m_segmentation_enabled { false };
bool m_segmentation_update_map { false };
bool m_segmentation_temporal_update { false };
bool m_segmentation_abs_or_delta_update { false }; bool m_segmentation_abs_or_delta_update { false };
u16 m_tile_cols_log2 { 0 }; u16 m_tile_cols_log2 { 0 };
u16 m_tile_rows_log2 { 0 }; u16 m_tile_rows_log2 { 0 };
@ -139,6 +151,13 @@ private:
u32 m_mi_row_end { 0 }; u32 m_mi_row_end { 0 };
u32 m_mi_col_start { 0 }; u32 m_mi_col_start { 0 };
u32 m_mi_col_end { 0 }; u32 m_mi_col_end { 0 };
u32 m_mi_row { 0 };
u32 m_mi_col { 0 };
u32 m_mi_size { 0 };
bool m_available_u { false };
bool m_available_l { false };
int m_segment_id { 0 };
int m_skip { false };
bool m_use_hp { false }; bool m_use_hp { false };

View file

@ -108,9 +108,9 @@ u8 TreeParser::select_tree_probability(SyntaxElementType type, u8 node)
case SyntaxElementType::UVMode: case SyntaxElementType::UVMode:
break; break;
case SyntaxElementType::SegmentID: case SyntaxElementType::SegmentID:
break; return m_segmentation_tree_probs[node];
case SyntaxElementType::Skip: case SyntaxElementType::Skip:
break; return calculate_skip_probability();
case SyntaxElementType::SegIDPredicted: case SyntaxElementType::SegIDPredicted:
break; break;
case SyntaxElementType::IsInter: case SyntaxElementType::IsInter:
@ -182,6 +182,18 @@ u8 TreeParser::calculate_partition_probability(u8 node)
return m_probability_tables.partition_probs()[m_ctx][node2]; return m_probability_tables.partition_probs()[m_ctx][node2];
} }
u8 TreeParser::calculate_skip_probability()
{
m_ctx = 0;
if (m_available_u) {
// FIXME: m_ctx += m_skips[m_mi_row - 1][m_mi_col];
}
if (m_available_l) {
// FIXME: m_ctx += m_skips[m_mi_row][m_mi_col - 1];
}
return m_probability_tables.skip_prob()[m_ctx];
}
void TreeParser::count_syntax_element(SyntaxElementType type, int value) void TreeParser::count_syntax_element(SyntaxElementType type, int value)
{ {
switch (type) { switch (type) {
@ -195,6 +207,7 @@ void TreeParser::count_syntax_element(SyntaxElementType type, int value)
case SyntaxElementType::UVMode: case SyntaxElementType::UVMode:
break; break;
case SyntaxElementType::Skip: case SyntaxElementType::Skip:
m_syntax_element_counter->m_counts_skip[m_ctx][value]++;
break; break;
case SyntaxElementType::IsInter: case SyntaxElementType::IsInter:
break; break;

View file

@ -57,9 +57,15 @@ public:
void set_row(u32 row) { m_row = row; } void set_row(u32 row) { m_row = row; }
void set_frame_is_intra(bool frame_is_intra) { m_frame_is_intra = frame_is_intra; } void set_frame_is_intra(bool frame_is_intra) { m_frame_is_intra = frame_is_intra; }
void set_syntax_element_counter(SyntaxElementCounter* syntax_element_counter) { m_syntax_element_counter = syntax_element_counter; } void set_syntax_element_counter(SyntaxElementCounter* syntax_element_counter) { m_syntax_element_counter = syntax_element_counter; }
void set_segmentation_tree_probs(u8* segmentation_tree_probs) { m_segmentation_tree_probs = segmentation_tree_probs; }
void set_available_u(bool available_u) { m_available_u = available_u; }
void set_available_l(bool available_l) { m_available_l = available_l; }
void set_mi_row(u32 mi_row) { m_mi_row = mi_row; }
void set_mi_col(u32 mi_col) { m_mi_col = mi_col; }
private: private:
u8 calculate_partition_probability(u8 node); u8 calculate_partition_probability(u8 node);
u8 calculate_skip_probability();
ProbabilityTables& m_probability_tables; ProbabilityTables& m_probability_tables;
BitStream* m_bit_stream { nullptr }; BitStream* m_bit_stream { nullptr };
@ -79,6 +85,11 @@ private:
u32 m_col { 0 }; u32 m_col { 0 };
u32 m_row { 0 }; u32 m_row { 0 };
bool m_frame_is_intra { false }; bool m_frame_is_intra { false };
u8* m_segmentation_tree_probs { nullptr };
bool m_available_u { false };
bool m_available_l { false };
u32 m_mi_col { 0 };
u32 m_mi_row { 0 };
}; };
} }