mirror of
https://github.com/RGBCube/serenity
synced 2025-05-17 21:15:06 +00:00
257 lines
7.2 KiB
C++
257 lines
7.2 KiB
C++
/*
|
|
* Copyright (c) 2021, Hunter Salyer <thefalsehonesty@gmail.com>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include "TreeParser.h"
|
|
#include "LookupTables.h"
|
|
|
|
namespace Video::VP9 {
|
|
|
|
int TreeParser::parse_tree(SyntaxElementType type)
|
|
{
|
|
auto tree_selection = select_tree(type);
|
|
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;
|
|
}
|
|
|
|
/*
|
|
* 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
|
|
*/
|
|
TreeParser::TreeSelection TreeParser::select_tree(SyntaxElementType type)
|
|
{
|
|
switch (type) {
|
|
case SyntaxElementType::Partition:
|
|
if (m_has_rows && m_has_cols)
|
|
return { partition_tree };
|
|
if (m_has_cols)
|
|
return { cols_partition_tree };
|
|
if (m_has_rows)
|
|
return { rows_partition_tree };
|
|
return { PartitionSplit };
|
|
case SyntaxElementType::DefaultIntraMode:
|
|
case SyntaxElementType::DefaultUVMode:
|
|
case SyntaxElementType::IntraMode:
|
|
case SyntaxElementType::SubIntraMode:
|
|
case SyntaxElementType::UVMode:
|
|
return { intra_mode_tree };
|
|
case SyntaxElementType::SegmentID:
|
|
return { segment_tree };
|
|
case SyntaxElementType::Skip:
|
|
case SyntaxElementType::SegIDPredicted:
|
|
case SyntaxElementType::IsInter:
|
|
case SyntaxElementType::CompMode:
|
|
case SyntaxElementType::CompRef:
|
|
case SyntaxElementType::SingleRefP1:
|
|
case SyntaxElementType::SingleRefP2:
|
|
case SyntaxElementType::MVSign:
|
|
case SyntaxElementType::MVClass0Bit:
|
|
case SyntaxElementType::MVBit:
|
|
case SyntaxElementType::MoreCoefs:
|
|
return { binary_tree };
|
|
case SyntaxElementType::TXSize:
|
|
if (m_max_tx_size == TX_32x32)
|
|
return { tx_size_32_tree };
|
|
if (m_max_tx_size == TX_16x16)
|
|
return { tx_size_16_tree };
|
|
return { tx_size_8_tree };
|
|
case SyntaxElementType::InterMode:
|
|
return { inter_mode_tree };
|
|
case SyntaxElementType::InterpFilter:
|
|
return { interp_filter_tree };
|
|
case SyntaxElementType::MVJoint:
|
|
return { mv_joint_tree };
|
|
case SyntaxElementType::MVClass:
|
|
return { mv_class_tree };
|
|
case SyntaxElementType::MVClass0FR:
|
|
case SyntaxElementType::MVFR:
|
|
return { mv_fr_tree };
|
|
case SyntaxElementType::MVClass0HP:
|
|
case SyntaxElementType::MVHP:
|
|
if (m_use_hp)
|
|
return { binary_tree };
|
|
return { 1 };
|
|
case SyntaxElementType::Token:
|
|
return { token_tree };
|
|
}
|
|
VERIFY_NOT_REACHED();
|
|
}
|
|
|
|
/*
|
|
* Select a probability with which to read a boolean when decoding a tree, as specified in section 9.3.2
|
|
*/
|
|
u8 TreeParser::select_tree_probability(SyntaxElementType type, u8 node)
|
|
{
|
|
switch (type) {
|
|
case SyntaxElementType::Partition:
|
|
return calculate_partition_probability(node);
|
|
case SyntaxElementType::DefaultIntraMode:
|
|
break;
|
|
case SyntaxElementType::DefaultUVMode:
|
|
break;
|
|
case SyntaxElementType::IntraMode:
|
|
break;
|
|
case SyntaxElementType::SubIntraMode:
|
|
break;
|
|
case SyntaxElementType::UVMode:
|
|
break;
|
|
case SyntaxElementType::SegmentID:
|
|
break;
|
|
case SyntaxElementType::Skip:
|
|
break;
|
|
case SyntaxElementType::SegIDPredicted:
|
|
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;
|
|
}
|
|
TODO();
|
|
}
|
|
|
|
u8 TreeParser::calculate_partition_probability(u8 node)
|
|
{
|
|
int node2;
|
|
if (m_has_rows && m_has_cols) {
|
|
node2 = node;
|
|
} else if (m_has_cols) {
|
|
node2 = 1;
|
|
} else {
|
|
node2 = 2;
|
|
}
|
|
|
|
u32 above = 0;
|
|
u32 left = 0;
|
|
auto bsl = mi_width_log2_lookup[m_block_subsize];
|
|
auto block_offset = mi_width_log2_lookup[Block_64x64] - bsl;
|
|
for (auto i = 0; i < m_num_8x8; i++) {
|
|
above |= m_above_partition_context[m_col + i];
|
|
left |= m_left_partition_context[m_row + i];
|
|
}
|
|
above = (above & (1 << block_offset)) > 0;
|
|
left = (left & (1 << block_offset)) > 0;
|
|
m_ctx = bsl * 4 + left * 2 + above;
|
|
if (m_frame_is_intra)
|
|
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)
|
|
: m_is_single_value(false)
|
|
, m_value { .m_tree = values }
|
|
{
|
|
}
|
|
|
|
TreeParser::TreeSelection::TreeSelection(int value)
|
|
: m_is_single_value(true)
|
|
, m_value { .m_value = value }
|
|
{
|
|
}
|
|
|
|
}
|