mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 15:48:12 +00:00
LibVideo/VP9: Successfully parse partition syntax element
This commit is contained in:
parent
7ff6315246
commit
2ce4155b42
6 changed files with 165 additions and 66 deletions
|
@ -23,6 +23,7 @@ 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_tree_parser->set_bit_stream(m_bit_stream);
|
||||
m_tree_parser->set_syntax_element_counter(m_syntax_element_counter);
|
||||
|
||||
if (!uncompressed_header())
|
||||
return false;
|
||||
|
@ -743,13 +744,20 @@ bool Decoder::decode_tiles()
|
|||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void clear_context(T* context, size_t size)
|
||||
{
|
||||
if (!(*context))
|
||||
*context = static_cast<T>(malloc(size));
|
||||
else
|
||||
__builtin_memset(*context, 0, size);
|
||||
}
|
||||
|
||||
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
|
||||
clear_context(&m_above_nonzero_context, sizeof(u8) * 3 * m_mi_cols * 2);
|
||||
clear_context(&m_above_seg_pred_context, sizeof(u8) * m_mi_cols);
|
||||
clear_context(&m_above_partition_context, sizeof(u8) * m_sb64_cols * 8);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -777,11 +785,9 @@ bool Decoder::decode_tile()
|
|||
|
||||
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
|
||||
clear_context(&m_left_nonzero_context, sizeof(u8) * 3 * m_mi_rows * 2);
|
||||
clear_context(&m_left_seg_pred_context, sizeof(u8) * m_mi_rows);
|
||||
clear_context(&m_left_partition_context, sizeof(u8) * m_sb64_rows * 8);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -815,4 +821,20 @@ void Decoder::dump_info()
|
|||
dbgln("Interpolation filter: {}", (u8)m_interpolation_filter);
|
||||
}
|
||||
|
||||
Decoder::~Decoder()
|
||||
{
|
||||
if (m_above_nonzero_context)
|
||||
free(m_above_nonzero_context);
|
||||
if (m_left_nonzero_context)
|
||||
free(m_left_nonzero_context);
|
||||
if (m_above_seg_pred_context)
|
||||
free(m_above_seg_pred_context);
|
||||
if (m_left_seg_pred_context)
|
||||
free(m_left_seg_pred_context);
|
||||
if (m_above_partition_context)
|
||||
free(m_above_partition_context);
|
||||
if (m_left_partition_context)
|
||||
free(m_left_partition_context);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ namespace Video::VP9 {
|
|||
class Decoder {
|
||||
public:
|
||||
Decoder();
|
||||
~Decoder();
|
||||
bool parse_frame(const ByteBuffer&);
|
||||
void dump_info();
|
||||
|
||||
|
@ -128,6 +129,12 @@ private:
|
|||
i8 m_loop_filter_ref_deltas[MAX_REF_FRAMES];
|
||||
i8 m_loop_filter_mode_deltas[2];
|
||||
|
||||
u8** m_above_nonzero_context { nullptr };
|
||||
u8** m_left_nonzero_context { nullptr };
|
||||
u8* m_above_seg_pred_context { nullptr };
|
||||
u8* m_left_seg_pred_context { nullptr };
|
||||
u8* m_above_partition_context { nullptr };
|
||||
u8* m_left_partition_context { nullptr };
|
||||
u32 m_mi_row_start { 0 };
|
||||
u32 m_mi_row_end { 0 };
|
||||
u32 m_mi_col_start { 0 };
|
||||
|
|
|
@ -10,28 +10,28 @@ namespace Video::VP9 {
|
|||
|
||||
void SyntaxElementCounter::clear_counts()
|
||||
{
|
||||
__builtin_memset(counts_intra_mode, 0, BLOCK_SIZE_GROUPS * INTRA_MODES);
|
||||
__builtin_memset(counts_uv_mode, 0, INTRA_MODES * INTRA_MODES);
|
||||
__builtin_memset(counts_partition, 0, PARTITION_CONTEXTS * PARTITION_TYPES);
|
||||
__builtin_memset(counts_interp_filter, 0, INTERP_FILTER_CONTEXTS * SWITCHABLE_FILTERS);
|
||||
__builtin_memset(counts_inter_mode, 0, INTER_MODE_CONTEXTS * INTER_MODES);
|
||||
__builtin_memset(counts_tx_size, 0, TX_SIZES * TX_SIZE_CONTEXTS * TX_SIZES);
|
||||
__builtin_memset(counts_is_inter, 0, IS_INTER_CONTEXTS * 2);
|
||||
__builtin_memset(counts_comp_mode, 0, COMP_MODE_CONTEXTS * 2);
|
||||
__builtin_memset(counts_single_ref, 0, REF_CONTEXTS * 2 * 2);
|
||||
__builtin_memset(counts_comp_ref, 0, REF_CONTEXTS * 2);
|
||||
__builtin_memset(counts_skip, 0, SKIP_CONTEXTS * 2);
|
||||
__builtin_memset(counts_mv_joint, 0, MV_JOINTS);
|
||||
__builtin_memset(counts_mv_sign, 0, 2 * 2);
|
||||
__builtin_memset(counts_mv_class, 0, 2 * MV_CLASSES);
|
||||
__builtin_memset(counts_mv_class0_bit, 0, 2 * CLASS0_SIZE);
|
||||
__builtin_memset(counts_mv_class0_fr, 0, 2 * CLASS0_SIZE * MV_FR_SIZE);
|
||||
__builtin_memset(counts_mv_class0_hp, 0, 2 * 2);
|
||||
__builtin_memset(counts_mv_bits, 0, 2 * MV_OFFSET_BITS * 2);
|
||||
__builtin_memset(counts_mv_fr, 0, 2 * MV_FR_SIZE);
|
||||
__builtin_memset(counts_mv_hp, 0, 2 * 2);
|
||||
__builtin_memset(counts_token, 0, TX_SIZES * BLOCK_TYPES * REF_TYPES * COEF_BANDS * PREV_COEF_CONTEXTS * UNCONSTRAINED_NODES);
|
||||
__builtin_memset(counts_more_coefs, 0, TX_SIZES * BLOCK_TYPES * REF_TYPES * COEF_BANDS * PREV_COEF_CONTEXTS * 2);
|
||||
__builtin_memset(m_counts_intra_mode, 0, BLOCK_SIZE_GROUPS * INTRA_MODES);
|
||||
__builtin_memset(m_counts_uv_mode, 0, INTRA_MODES * INTRA_MODES);
|
||||
__builtin_memset(m_counts_partition, 0, PARTITION_CONTEXTS * PARTITION_TYPES);
|
||||
__builtin_memset(m_counts_interp_filter, 0, INTERP_FILTER_CONTEXTS * SWITCHABLE_FILTERS);
|
||||
__builtin_memset(m_counts_inter_mode, 0, INTER_MODE_CONTEXTS * INTER_MODES);
|
||||
__builtin_memset(m_counts_tx_size, 0, TX_SIZES * TX_SIZE_CONTEXTS * TX_SIZES);
|
||||
__builtin_memset(m_counts_is_inter, 0, IS_INTER_CONTEXTS * 2);
|
||||
__builtin_memset(m_counts_comp_mode, 0, COMP_MODE_CONTEXTS * 2);
|
||||
__builtin_memset(m_counts_single_ref, 0, REF_CONTEXTS * 2 * 2);
|
||||
__builtin_memset(m_counts_comp_ref, 0, REF_CONTEXTS * 2);
|
||||
__builtin_memset(m_counts_skip, 0, SKIP_CONTEXTS * 2);
|
||||
__builtin_memset(m_counts_mv_joint, 0, MV_JOINTS);
|
||||
__builtin_memset(m_counts_mv_sign, 0, 2 * 2);
|
||||
__builtin_memset(m_counts_mv_class, 0, 2 * MV_CLASSES);
|
||||
__builtin_memset(m_counts_mv_class0_bit, 0, 2 * CLASS0_SIZE);
|
||||
__builtin_memset(m_counts_mv_class0_fr, 0, 2 * CLASS0_SIZE * MV_FR_SIZE);
|
||||
__builtin_memset(m_counts_mv_class0_hp, 0, 2 * 2);
|
||||
__builtin_memset(m_counts_mv_bits, 0, 2 * MV_OFFSET_BITS * 2);
|
||||
__builtin_memset(m_counts_mv_fr, 0, 2 * MV_FR_SIZE);
|
||||
__builtin_memset(m_counts_mv_hp, 0, 2 * 2);
|
||||
__builtin_memset(m_counts_token, 0, TX_SIZES * BLOCK_TYPES * REF_TYPES * COEF_BANDS * PREV_COEF_CONTEXTS * UNCONSTRAINED_NODES);
|
||||
__builtin_memset(m_counts_more_coefs, 0, TX_SIZES * BLOCK_TYPES * REF_TYPES * COEF_BANDS * PREV_COEF_CONTEXTS * 2);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -46,29 +46,28 @@ class SyntaxElementCounter final {
|
|||
public:
|
||||
void clear_counts();
|
||||
|
||||
private:
|
||||
u8 counts_intra_mode[BLOCK_SIZE_GROUPS][INTRA_MODES];
|
||||
u8 counts_uv_mode[INTRA_MODES][INTRA_MODES];
|
||||
u8 counts_partition[PARTITION_CONTEXTS][PARTITION_TYPES];
|
||||
u8 counts_interp_filter[INTERP_FILTER_CONTEXTS][SWITCHABLE_FILTERS];
|
||||
u8 counts_inter_mode[INTER_MODE_CONTEXTS][INTER_MODES];
|
||||
u8 counts_tx_size[TX_SIZES][TX_SIZE_CONTEXTS][TX_SIZES];
|
||||
u8 counts_is_inter[IS_INTER_CONTEXTS][2];
|
||||
u8 counts_comp_mode[COMP_MODE_CONTEXTS][2];
|
||||
u8 counts_single_ref[REF_CONTEXTS][2][2];
|
||||
u8 counts_comp_ref[REF_CONTEXTS][2];
|
||||
u8 counts_skip[SKIP_CONTEXTS][2];
|
||||
u8 counts_mv_joint[MV_JOINTS];
|
||||
u8 counts_mv_sign[2][2];
|
||||
u8 counts_mv_class[2][MV_CLASSES];
|
||||
u8 counts_mv_class0_bit[2][CLASS0_SIZE];
|
||||
u8 counts_mv_class0_fr[2][CLASS0_SIZE][MV_FR_SIZE];
|
||||
u8 counts_mv_class0_hp[2][2];
|
||||
u8 counts_mv_bits[2][MV_OFFSET_BITS][2];
|
||||
u8 counts_mv_fr[2][MV_FR_SIZE];
|
||||
u8 counts_mv_hp[2][2];
|
||||
u8 counts_token[TX_SIZES][BLOCK_TYPES][REF_TYPES][COEF_BANDS][PREV_COEF_CONTEXTS][UNCONSTRAINED_NODES];
|
||||
u8 counts_more_coefs[TX_SIZES][BLOCK_TYPES][REF_TYPES][COEF_BANDS][PREV_COEF_CONTEXTS][2];
|
||||
u8 m_counts_intra_mode[BLOCK_SIZE_GROUPS][INTRA_MODES];
|
||||
u8 m_counts_uv_mode[INTRA_MODES][INTRA_MODES];
|
||||
u8 m_counts_partition[PARTITION_CONTEXTS][PARTITION_TYPES];
|
||||
u8 m_counts_interp_filter[INTERP_FILTER_CONTEXTS][SWITCHABLE_FILTERS];
|
||||
u8 m_counts_inter_mode[INTER_MODE_CONTEXTS][INTER_MODES];
|
||||
u8 m_counts_tx_size[TX_SIZES][TX_SIZE_CONTEXTS][TX_SIZES];
|
||||
u8 m_counts_is_inter[IS_INTER_CONTEXTS][2];
|
||||
u8 m_counts_comp_mode[COMP_MODE_CONTEXTS][2];
|
||||
u8 m_counts_single_ref[REF_CONTEXTS][2][2];
|
||||
u8 m_counts_comp_ref[REF_CONTEXTS][2];
|
||||
u8 m_counts_skip[SKIP_CONTEXTS][2];
|
||||
u8 m_counts_mv_joint[MV_JOINTS];
|
||||
u8 m_counts_mv_sign[2][2];
|
||||
u8 m_counts_mv_class[2][MV_CLASSES];
|
||||
u8 m_counts_mv_class0_bit[2][CLASS0_SIZE];
|
||||
u8 m_counts_mv_class0_fr[2][CLASS0_SIZE][MV_FR_SIZE];
|
||||
u8 m_counts_mv_class0_hp[2][2];
|
||||
u8 m_counts_mv_bits[2][MV_OFFSET_BITS][2];
|
||||
u8 m_counts_mv_fr[2][MV_FR_SIZE];
|
||||
u8 m_counts_mv_hp[2][2];
|
||||
u8 m_counts_token[TX_SIZES][BLOCK_TYPES][REF_TYPES][COEF_BANDS][PREV_COEF_CONTEXTS][UNCONSTRAINED_NODES];
|
||||
u8 m_counts_more_coefs[TX_SIZES][BLOCK_TYPES][REF_TYPES][COEF_BANDS][PREV_COEF_CONTEXTS][2];
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -12,14 +12,19 @@ namespace Video::VP9 {
|
|||
int TreeParser::parse_tree(SyntaxElementType type)
|
||||
{
|
||||
auto tree_selection = select_tree(type);
|
||||
if (tree_selection.is_single_value())
|
||||
return tree_selection.get_single_value();
|
||||
auto tree = tree_selection.get_tree_value();
|
||||
int n = 0;
|
||||
do {
|
||||
n = tree[n + m_bit_stream->read_bool(select_tree_probability(type, n >> 1))];
|
||||
} while (n > 0);
|
||||
return -n;
|
||||
int value;
|
||||
if (tree_selection.is_single_value()) {
|
||||
value = tree_selection.get_single_value();
|
||||
} else {
|
||||
auto tree = tree_selection.get_tree_value();
|
||||
int n = 0;
|
||||
do {
|
||||
n = tree[n + m_bit_stream->read_bool(select_tree_probability(type, n >> 1))];
|
||||
} while (n > 0);
|
||||
value = -n;
|
||||
}
|
||||
count_syntax_element(type, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -171,10 +176,70 @@ u8 TreeParser::calculate_partition_probability(u8 node)
|
|||
}
|
||||
above = (above & (1 << block_offset)) > 0;
|
||||
left = (left & (1 << block_offset)) > 0;
|
||||
auto ctx = bsl * 4 + left * 2 + above;
|
||||
m_ctx = bsl * 4 + left * 2 + above;
|
||||
if (m_frame_is_intra)
|
||||
return m_probability_tables.kf_partition_probs()[ctx][node2];
|
||||
return m_probability_tables.partition_probs()[ctx][node2];
|
||||
return m_probability_tables.kf_partition_probs()[m_ctx][node2];
|
||||
return m_probability_tables.partition_probs()[m_ctx][node2];
|
||||
}
|
||||
|
||||
void TreeParser::count_syntax_element(SyntaxElementType type, int value)
|
||||
{
|
||||
switch (type) {
|
||||
case SyntaxElementType::Partition:
|
||||
m_syntax_element_counter->m_counts_partition[m_ctx][value]++;
|
||||
break;
|
||||
case SyntaxElementType::IntraMode:
|
||||
break;
|
||||
case SyntaxElementType::SubIntraMode:
|
||||
break;
|
||||
case SyntaxElementType::UVMode:
|
||||
break;
|
||||
case SyntaxElementType::Skip:
|
||||
break;
|
||||
case SyntaxElementType::IsInter:
|
||||
break;
|
||||
case SyntaxElementType::CompMode:
|
||||
break;
|
||||
case SyntaxElementType::CompRef:
|
||||
break;
|
||||
case SyntaxElementType::SingleRefP1:
|
||||
break;
|
||||
case SyntaxElementType::SingleRefP2:
|
||||
break;
|
||||
case SyntaxElementType::MVSign:
|
||||
break;
|
||||
case SyntaxElementType::MVClass0Bit:
|
||||
break;
|
||||
case SyntaxElementType::MVBit:
|
||||
break;
|
||||
case SyntaxElementType::TXSize:
|
||||
break;
|
||||
case SyntaxElementType::InterMode:
|
||||
break;
|
||||
case SyntaxElementType::InterpFilter:
|
||||
break;
|
||||
case SyntaxElementType::MVJoint:
|
||||
break;
|
||||
case SyntaxElementType::MVClass:
|
||||
break;
|
||||
case SyntaxElementType::MVClass0FR:
|
||||
break;
|
||||
case SyntaxElementType::MVClass0HP:
|
||||
break;
|
||||
case SyntaxElementType::MVFR:
|
||||
break;
|
||||
case SyntaxElementType::MVHP:
|
||||
break;
|
||||
case SyntaxElementType::Token:
|
||||
break;
|
||||
case SyntaxElementType::MoreCoefs:
|
||||
break;
|
||||
case SyntaxElementType::DefaultIntraMode:
|
||||
case SyntaxElementType::DefaultUVMode:
|
||||
case SyntaxElementType::SegmentID:
|
||||
case SyntaxElementType::SegIDPredicted:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TreeParser::TreeSelection::TreeSelection(const int* values)
|
||||
|
|
|
@ -42,6 +42,7 @@ public:
|
|||
int 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);
|
||||
|
||||
void set_bit_stream(BitStream* bit_stream) { m_bit_stream = bit_stream; }
|
||||
void set_has_rows(bool has_rows) { m_has_rows = has_rows; }
|
||||
|
@ -55,12 +56,17 @@ public:
|
|||
void set_col(u32 col) { m_col = col; }
|
||||
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_syntax_element_counter(SyntaxElementCounter* syntax_element_counter) { m_syntax_element_counter = syntax_element_counter; }
|
||||
|
||||
private:
|
||||
u8 calculate_partition_probability(u8 node);
|
||||
|
||||
ProbabilityTables& m_probability_tables;
|
||||
BitStream* m_bit_stream { nullptr };
|
||||
SyntaxElementCounter* m_syntax_element_counter { nullptr };
|
||||
|
||||
// m_ctx is a member variable because it is required for syntax element counting (section 9.3.4)
|
||||
u8 m_ctx { 0 };
|
||||
|
||||
bool m_has_rows { false };
|
||||
bool m_has_cols { false };
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue