1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 03:57:44 +00:00

LibVideo: Implement VP9 intra-predicted frame decoding

The first keyframe of the test video can be decoded with these changes.

Raw memory allocations in the Parser have been replaced with Vector or
Array to avoid memory leaks and OOBs.
This commit is contained in:
Zaggy1024 2022-10-08 21:54:20 -05:00 committed by Andrew Kaster
parent da9ff31166
commit 1514004cd5
10 changed files with 1445 additions and 146 deletions

View file

@ -212,17 +212,17 @@ u8 TreeParser::calculate_default_intra_mode_probability(u8 node)
u32 above_mode, left_mode;
if (m_decoder.m_mi_size >= Block_8x8) {
above_mode = AVAIL_U
? m_decoder.m_sub_modes[(m_decoder.m_mi_row - 1) * m_decoder.m_mi_cols * 4 + m_decoder.m_mi_col * 4 + 2]
? m_decoder.m_sub_modes[m_decoder.get_image_index(m_decoder.m_mi_row - 1, m_decoder.m_mi_col)][2]
: DcPred;
left_mode = AVAIL_L
? m_decoder.m_sub_modes[m_decoder.m_mi_row * m_decoder.m_mi_cols * 4 + (m_decoder.m_mi_col - 1) * 4 + 1]
? m_decoder.m_sub_modes[m_decoder.get_image_index(m_decoder.m_mi_row, m_decoder.m_mi_col - 1)][1]
: DcPred;
} else {
if (m_idy) {
above_mode = m_decoder.m_block_sub_modes[m_idx];
} else {
above_mode = AVAIL_U
? m_decoder.m_sub_modes[(m_decoder.m_mi_row - 1) * m_decoder.m_mi_cols * 4 + m_decoder.m_mi_col * 4 + 2 + m_idx]
? m_decoder.m_sub_modes[m_decoder.get_image_index(m_decoder.m_mi_row - 1, m_decoder.m_mi_col)][2 + m_idx]
: DcPred;
}
@ -230,7 +230,7 @@ u8 TreeParser::calculate_default_intra_mode_probability(u8 node)
left_mode = m_decoder.m_block_sub_modes[m_idy * 2];
} else {
left_mode = AVAIL_L
? m_decoder.m_sub_modes[m_decoder.m_mi_row * m_decoder.m_mi_cols * 4 + (m_decoder.m_mi_col - 1) * 4 + 1 + m_idy * 2]
? m_decoder.m_sub_modes[m_decoder.get_image_index(m_decoder.m_mi_row, m_decoder.m_mi_col - 1)][1 + m_idy * 2]
: DcPred;
}
}
@ -544,12 +544,16 @@ u8 TreeParser::calculate_tx_size_probability(u8 node)
{
auto above = m_decoder.m_max_tx_size;
auto left = m_decoder.m_max_tx_size;
auto u_pos = (m_decoder.m_mi_row - 1) * m_decoder.m_mi_cols + m_decoder.m_mi_col;
if (AVAIL_U && !m_decoder.m_skips[u_pos])
above = m_decoder.m_tx_sizes[u_pos];
auto l_pos = m_decoder.m_mi_row * m_decoder.m_mi_cols + m_decoder.m_mi_col - 1;
if (AVAIL_L && !m_decoder.m_skips[l_pos])
left = m_decoder.m_tx_sizes[l_pos];
if (AVAIL_U) {
auto u_pos = (m_decoder.m_mi_row - 1) * m_decoder.m_mi_cols + m_decoder.m_mi_col;
if (!m_decoder.m_skips[u_pos])
above = m_decoder.m_tx_sizes[u_pos];
}
if (AVAIL_L) {
auto l_pos = m_decoder.m_mi_row * m_decoder.m_mi_cols + m_decoder.m_mi_col - 1;
if (!m_decoder.m_skips[l_pos])
left = m_decoder.m_tx_sizes[l_pos];
}
if (!AVAIL_L)
left = above;
if (!AVAIL_U)
@ -582,20 +586,14 @@ u8 TreeParser::calculate_interp_filter_probability(u8 node)
return m_decoder.m_probability_tables->interp_filter_probs()[m_ctx][node];
}
u8 TreeParser::calculate_token_probability(u8 node)
void TreeParser::set_tokens_variables(u8 band, u32 c, u32 plane, TXSize tx_size, u32 pos)
{
auto prob = m_decoder.m_probability_tables->coef_probs()[m_tx_size][m_plane > 0][m_decoder.m_is_inter][m_band][m_ctx][min(2, 1 + node)];
if (node < 2)
return prob;
auto x = (prob - 1) / 2;
auto& pareto_table = m_decoder.m_probability_tables->pareto_table();
if (prob & 1)
return pareto_table[x][node - 2];
return (pareto_table[x][node - 2] + pareto_table[x + 1][node - 2]) >> 1;
}
m_band = band;
m_c = c;
m_plane = plane;
m_tx_size = tx_size;
m_pos = pos;
u8 TreeParser::calculate_more_coefs_probability()
{
if (m_c == 0) {
auto sx = m_plane > 0 ? m_decoder.m_subsampling_x : 0;
auto sy = m_plane > 0 ? m_decoder.m_subsampling_y : 0;
@ -618,7 +616,7 @@ u8 TreeParser::calculate_more_coefs_probability()
auto n = 4 << m_tx_size;
auto i = m_pos / n;
auto j = m_pos % n;
auto a = (i - 1) * n + j;
auto a = i > 0 ? (i - 1) * n + j : 0;
auto a2 = i * n + j - 1;
if (i > 0 && j > 0) {
if (m_decoder.m_tx_type == DCT_ADST) {
@ -640,9 +638,25 @@ u8 TreeParser::calculate_more_coefs_probability()
}
m_ctx = (1 + m_decoder.m_token_cache[neighbor_0] + m_decoder.m_token_cache[neighbor_1]) >> 1;
}
}
u8 TreeParser::calculate_more_coefs_probability()
{
return m_decoder.m_probability_tables->coef_probs()[m_tx_size][m_plane > 0][m_decoder.m_is_inter][m_band][m_ctx][0];
}
u8 TreeParser::calculate_token_probability(u8 node)
{
auto prob = m_decoder.m_probability_tables->coef_probs()[m_tx_size][m_plane > 0][m_decoder.m_is_inter][m_band][m_ctx][min(2, 1 + node)];
if (node < 2)
return prob;
auto x = (prob - 1) / 2;
auto& pareto_table = m_decoder.m_probability_tables->pareto_table();
if (prob & 1)
return pareto_table[x][node - 2];
return (pareto_table[x][node - 2] + pareto_table[x + 1][node - 2]) >> 1;
}
void TreeParser::count_syntax_element(SyntaxElementType type, int value)
{
switch (type) {