mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 12:27:34 +00:00
LibVideo/VP9: Parse compressed header data
This patch adds compressed header parsing to the VP9 decoder (section 6.4 of the spec). This is the final decoder step before we can start to decode tiles.
This commit is contained in:
parent
e821b349b2
commit
f9899fc17f
2 changed files with 336 additions and 0 deletions
|
@ -38,6 +38,16 @@ bool Decoder::parse_frame(const ByteBuffer& frame_data)
|
|||
m_probability_tables->load_probs(m_frame_context_idx);
|
||||
m_probability_tables->load_probs2(m_frame_context_idx);
|
||||
m_syntax_element_counter->clear_counts();
|
||||
|
||||
if (!m_bit_stream->init_bool(m_header_size_in_bytes))
|
||||
return false;
|
||||
dbgln("Reading compressed header");
|
||||
if (!compressed_header())
|
||||
return false;
|
||||
dbgln("Finished reading compressed header");
|
||||
if (!m_bit_stream->exit_bool())
|
||||
return false;
|
||||
dbgln("Finished reading frame!");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -403,6 +413,306 @@ bool Decoder::trailing_bits()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Decoder::compressed_header()
|
||||
{
|
||||
read_tx_mode();
|
||||
if (m_tx_mode == TXModeSelect) {
|
||||
tx_mode_probs();
|
||||
}
|
||||
read_coef_probs();
|
||||
read_skip_prob();
|
||||
if (!m_frame_is_intra) {
|
||||
read_inter_mode_probs();
|
||||
if (m_interpolation_filter == Switchable) {
|
||||
read_interp_filter_probs();
|
||||
}
|
||||
read_is_inter_probs();
|
||||
frame_reference_mode();
|
||||
frame_reference_mode_probs();
|
||||
read_y_mode_probs();
|
||||
read_partition_probs();
|
||||
mv_probs();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Decoder::read_tx_mode()
|
||||
{
|
||||
if (m_lossless) {
|
||||
m_tx_mode = Only4x4;
|
||||
} else {
|
||||
auto tx_mode = m_bit_stream->read_literal(2);
|
||||
if (tx_mode == Allow32x32) {
|
||||
tx_mode += m_bit_stream->read_literal(1);
|
||||
}
|
||||
m_tx_mode = static_cast<TXMode>(tx_mode);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Decoder::tx_mode_probs()
|
||||
{
|
||||
auto& tx_probs = m_probability_tables->tx_probs();
|
||||
for (auto i = 0; i < TX_SIZE_CONTEXTS; i++) {
|
||||
for (auto j = 0; j < TX_SIZES - 3; j++) {
|
||||
tx_probs[TX8x8][i][j] = diff_update_prob(tx_probs[TX8x8][i][j]);
|
||||
}
|
||||
}
|
||||
for (auto i = 0; i < TX_SIZE_CONTEXTS; i++) {
|
||||
for (auto j = 0; j < TX_SIZES - 2; j++) {
|
||||
tx_probs[TX16x16][i][j] = diff_update_prob(tx_probs[TX16x16][i][j]);
|
||||
}
|
||||
}
|
||||
for (auto i = 0; i < TX_SIZE_CONTEXTS; i++) {
|
||||
for (auto j = 0; j < TX_SIZES - 1; j++) {
|
||||
tx_probs[TX32x32][i][j] = diff_update_prob(tx_probs[TX32x32][i][j]);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
u8 Decoder::diff_update_prob(u8 prob)
|
||||
{
|
||||
if (m_bit_stream->read_bool(252)) {
|
||||
auto delta_prob = decode_term_subexp();
|
||||
prob = inv_remap_prob(delta_prob, prob);
|
||||
}
|
||||
return prob;
|
||||
}
|
||||
|
||||
u8 Decoder::decode_term_subexp()
|
||||
{
|
||||
if (m_bit_stream->read_literal(1) == 0)
|
||||
return m_bit_stream->read_literal(4);
|
||||
if (m_bit_stream->read_literal(1) == 0)
|
||||
return m_bit_stream->read_literal(4) + 16;
|
||||
if (m_bit_stream->read_literal(1) == 0)
|
||||
return m_bit_stream->read_literal(4) + 32;
|
||||
|
||||
auto v = m_bit_stream->read_literal(7);
|
||||
if (v < 65)
|
||||
return v + 64;
|
||||
return (v << 1u) - 1 + m_bit_stream->read_literal(1);
|
||||
}
|
||||
|
||||
u8 Decoder::inv_remap_prob(u8 delta_prob, u8 prob)
|
||||
{
|
||||
u8 m = prob - 1;
|
||||
auto v = inv_map_table[delta_prob];
|
||||
if ((m << 1u) <= 255)
|
||||
return 1 + inv_recenter_nonneg(v, m);
|
||||
return 255 - inv_recenter_nonneg(v, 254 - m);
|
||||
}
|
||||
|
||||
u8 Decoder::inv_recenter_nonneg(u8 v, u8 m)
|
||||
{
|
||||
if (v > 2 * m)
|
||||
return v;
|
||||
if (v & 1u)
|
||||
return m - ((v + 1u) >> 1u);
|
||||
return m + (v >> 1u);
|
||||
}
|
||||
|
||||
bool Decoder::read_coef_probs()
|
||||
{
|
||||
auto max_tx_size = tx_mode_to_biggest_tx_size[m_tx_mode];
|
||||
for (auto tx_size = TX4x4; tx_size <= max_tx_size; tx_size = static_cast<TXSize>(static_cast<int>(tx_size) + 1)) {
|
||||
auto update_probs = m_bit_stream->read_literal(1);
|
||||
if (update_probs == 1) {
|
||||
for (auto i = 0; i < 2; i++) {
|
||||
for (auto j = 0; j < 2; j++) {
|
||||
for (auto k = 0; k < 6; k++) {
|
||||
auto max_l = (k == 0) ? 3 : 6;
|
||||
for (auto l = 0; l < max_l; l++) {
|
||||
for (auto m = 0; m < 3; m++) {
|
||||
auto& coef_probs = m_probability_tables->coef_probs()[tx_size];
|
||||
coef_probs[i][j][k][l][m] = diff_update_prob(coef_probs[i][j][k][l][m]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Decoder::read_skip_prob()
|
||||
{
|
||||
for (auto i = 0; i < SKIP_CONTEXTS; i++)
|
||||
m_probability_tables->skip_prob()[i] = diff_update_prob(m_probability_tables->skip_prob()[i]);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Decoder::read_inter_mode_probs()
|
||||
{
|
||||
for (auto i = 0; i < INTER_MODE_CONTEXTS; i++) {
|
||||
for (auto j = 0; j < INTER_MODES - 1; j++)
|
||||
m_probability_tables->inter_mode_probs()[i][j] = diff_update_prob(m_probability_tables->inter_mode_probs()[i][j]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Decoder::read_interp_filter_probs()
|
||||
{
|
||||
for (auto i = 0; i < INTERP_FILTER_CONTEXTS; i++) {
|
||||
for (auto j = 0; j < SWITCHABLE_FILTERS - 1; j++)
|
||||
m_probability_tables->interp_filter_probs()[i][j] = diff_update_prob(m_probability_tables->interp_filter_probs()[i][j]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Decoder::read_is_inter_probs()
|
||||
{
|
||||
for (auto i = 0; i < IS_INTER_CONTEXTS; i++)
|
||||
m_probability_tables->is_inter_prob()[i] = diff_update_prob(m_probability_tables->is_inter_prob()[i]);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Decoder::frame_reference_mode()
|
||||
{
|
||||
auto compound_reference_allowed = false;
|
||||
for (size_t i = 2; i <= REFS_PER_FRAME; i++) {
|
||||
if (m_ref_frame_sign_bias[i] != m_ref_frame_sign_bias[1])
|
||||
compound_reference_allowed = true;
|
||||
}
|
||||
if (compound_reference_allowed) {
|
||||
auto non_single_reference = m_bit_stream->read_literal(1);
|
||||
if (non_single_reference == 0) {
|
||||
m_reference_mode = SingleReference;
|
||||
} else {
|
||||
auto reference_select = m_bit_stream->read_literal(1);
|
||||
if (reference_select == 0)
|
||||
m_reference_mode = CompoundReference;
|
||||
else
|
||||
m_reference_mode = ReferenceModeSelect;
|
||||
setup_compound_reference_mode();
|
||||
}
|
||||
} else {
|
||||
m_reference_mode = SingleReference;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Decoder::frame_reference_mode_probs()
|
||||
{
|
||||
if (m_reference_mode == ReferenceModeSelect) {
|
||||
for (auto i = 0; i < COMP_MODE_CONTEXTS; i++) {
|
||||
auto& comp_mode_prob = m_probability_tables->comp_mode_prob();
|
||||
comp_mode_prob[i] = diff_update_prob(comp_mode_prob[i]);
|
||||
}
|
||||
}
|
||||
if (m_reference_mode != CompoundReference) {
|
||||
for (auto i = 0; i < REF_CONTEXTS; i++) {
|
||||
auto& single_ref_prob = m_probability_tables->single_ref_prob();
|
||||
single_ref_prob[i][0] = diff_update_prob(single_ref_prob[i][0]);
|
||||
single_ref_prob[i][1] = diff_update_prob(single_ref_prob[i][1]);
|
||||
}
|
||||
}
|
||||
if (m_reference_mode != SingleReference) {
|
||||
for (auto i = 0; i < REF_CONTEXTS; i++) {
|
||||
auto& comp_ref_prob = m_probability_tables->comp_ref_prob();
|
||||
comp_ref_prob[i] = diff_update_prob(comp_ref_prob[i]);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Decoder::read_y_mode_probs()
|
||||
{
|
||||
for (auto i = 0; i < BLOCK_SIZE_GROUPS; i++) {
|
||||
for (auto j = 0; j < INTRA_MODES - 1; j++) {
|
||||
auto& y_mode_probs = m_probability_tables->y_mode_probs();
|
||||
y_mode_probs[i][j] = diff_update_prob(y_mode_probs[i][j]);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Decoder::read_partition_probs()
|
||||
{
|
||||
for (auto i = 0; i < PARTITION_CONTEXTS; i++) {
|
||||
for (auto j = 0; j < PARTITION_TYPES - 1; j++) {
|
||||
auto& partition_probs = m_probability_tables->partition_probs();
|
||||
partition_probs[i][j] = diff_update_prob(partition_probs[i][j]);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Decoder::mv_probs()
|
||||
{
|
||||
for (auto j = 0; j < MV_JOINTS - 1; j++) {
|
||||
auto& mv_joint_probs = m_probability_tables->mv_joint_probs();
|
||||
mv_joint_probs[j] = update_mv_prob(mv_joint_probs[j]);
|
||||
}
|
||||
|
||||
for (auto i = 0; i < 2; i++) {
|
||||
auto& mv_sign_prob = m_probability_tables->mv_sign_prob();
|
||||
mv_sign_prob[i] = update_mv_prob(mv_sign_prob[i]);
|
||||
for (auto j = 0; j < MV_CLASSES - 1; j++) {
|
||||
auto& mv_class_probs = m_probability_tables->mv_class_probs();
|
||||
mv_class_probs[i][j] = update_mv_prob(mv_class_probs[i][j]);
|
||||
}
|
||||
auto& mv_class0_bit_prob = m_probability_tables->mv_class0_bit_prob();
|
||||
mv_class0_bit_prob[i] = update_mv_prob(mv_class0_bit_prob[i]);
|
||||
for (auto j = 0; j < MV_OFFSET_BITS; j++) {
|
||||
auto& mv_bits_prob = m_probability_tables->mv_bits_prob();
|
||||
mv_bits_prob[i][j] = update_mv_prob(mv_bits_prob[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto i = 0; i < 2; i++) {
|
||||
for (auto j = 0; j < CLASS0_SIZE; j++) {
|
||||
for (auto k = 0; k < MV_FR_SIZE - 1; k++) {
|
||||
auto& mv_class0_fr_probs = m_probability_tables->mv_class0_fr_probs();
|
||||
mv_class0_fr_probs[i][j][k] = update_mv_prob(mv_class0_fr_probs[i][j][k]);
|
||||
}
|
||||
}
|
||||
for (auto k = 0; k < MV_FR_SIZE - 1; k++) {
|
||||
auto& mv_fr_probs = m_probability_tables->mv_fr_probs();
|
||||
mv_fr_probs[i][k] = update_mv_prob(mv_fr_probs[i][k]);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_allow_high_precision_mv) {
|
||||
for (auto i = 0; i < 2; i++) {
|
||||
auto& mv_class0_hp_prob = m_probability_tables->mv_class0_hp_prob();
|
||||
auto& mv_hp_prob = m_probability_tables->mv_hp_prob();
|
||||
mv_class0_hp_prob[i] = update_mv_prob(mv_class0_hp_prob[i]);
|
||||
mv_hp_prob[i] = update_mv_prob(mv_hp_prob[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
u8 Decoder::update_mv_prob(u8 prob)
|
||||
{
|
||||
if (m_bit_stream->read_bool(252)) {
|
||||
return (m_bit_stream->read_literal(7) << 1u) | 1u;
|
||||
}
|
||||
return prob;
|
||||
}
|
||||
|
||||
bool Decoder::setup_compound_reference_mode()
|
||||
{
|
||||
if (m_ref_frame_sign_bias[LastFrame] == m_ref_frame_sign_bias[GoldenFrame]) {
|
||||
m_comp_fixed_ref = AltRefFrame;
|
||||
m_comp_var_ref[0] = LastFrame;
|
||||
m_comp_var_ref[1] = GoldenFrame;
|
||||
} else if (m_ref_frame_sign_bias[LastFrame] == m_ref_frame_sign_bias[AltRefFrame]) {
|
||||
m_comp_fixed_ref = GoldenFrame;
|
||||
m_comp_var_ref[0] = LastFrame;
|
||||
m_comp_var_ref[1] = AltRefFrame;
|
||||
} else {
|
||||
m_comp_fixed_ref = LastFrame;
|
||||
m_comp_var_ref[0] = GoldenFrame;
|
||||
m_comp_var_ref[1] = AltRefFrame;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Decoder::dump_info()
|
||||
{
|
||||
dbgln("Frame dimensions: {}x{}", m_frame_width, m_frame_height);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue