1
Fork 0
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:
FalseHonesty 2021-06-05 16:45:00 -04:00 committed by Andreas Kling
parent e821b349b2
commit f9899fc17f
2 changed files with 336 additions and 0 deletions

View file

@ -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);