mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 12:07:45 +00:00
LibVideo/VP9: Begin decoding VP9 blocks
This commit is contained in:
parent
2ce4155b42
commit
375dbad144
4 changed files with 135 additions and 8 deletions
|
@ -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);
|
||||||
|
|
|
@ -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 };
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 };
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue