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

LibVideo/VP9: Move fields set in uncompressed_header() to FrameContext

This commit is contained in:
Zaggy1024 2022-11-22 21:55:02 -06:00 committed by Andreas Kling
parent 40bc987fe3
commit 90f16c78fa
8 changed files with 165 additions and 146 deletions

View file

@ -255,6 +255,13 @@ struct FrameContext {
public:
u8 profile { 0 };
FrameType type { FrameType::KeyFrame };
bool is_inter_predicted() const { return type == FrameType::InterFrame; }
bool error_resilient_mode { false };
bool parallel_decoding_mode { false };
bool should_replace_probability_context { false };
bool shows_a_frame() const { return m_frame_show_mode != FrameShowMode::DoNotShowFrame; }
bool shows_a_new_frame() const { return m_frame_show_mode == FrameShowMode::CreateAndShowNewFrame; }
bool shows_existing_frame() const { return m_frame_show_mode == FrameShowMode::ShowExistingFrame; }
@ -268,6 +275,11 @@ public:
ColorConfig color_config {};
u8 reference_frames_to_update_flags { 0 };
bool should_update_reference_frame_at_index(u8 index) const { return (reference_frames_to_update_flags & (1 << index)) != 0; }
u8 probability_context_index { 0 };
Gfx::Size<u32> size() const { return m_size; }
ErrorOr<void> set_size(Gfx::Size<u32> size)
{
@ -287,6 +299,12 @@ public:
Gfx::Size<u32> render_size { 0, 0 };
// This group of fields is only needed for inter-predicted frames.
Array<u8, 3> reference_frame_indices;
Array<bool, LastFrame + 3> reference_frame_sign_biases;
bool high_precision_motion_vectors_allowed { false };
InterpolationFilter interpolation_filter { InterpolationFilter::Switchable };
u16 header_size_in_bytes { 0 };
private:

View file

@ -234,10 +234,10 @@ u8 Decoder::merge_probs(int const* tree, int index, u8* probs, u8* counts, u8 co
return left_count + right_count;
}
DecoderErrorOr<void> Decoder::adapt_coef_probs()
DecoderErrorOr<void> Decoder::adapt_coef_probs(bool is_inter_predicted_frame)
{
u8 update_factor;
if (m_parser->m_frame_is_intra || m_parser->m_last_frame_type != KeyFrame)
if (!is_inter_predicted_frame || m_parser->m_previous_frame_type != FrameType::KeyFrame)
update_factor = 112;
else
update_factor = 128;
@ -279,7 +279,7 @@ DecoderErrorOr<void> Decoder::adapt_coef_probs()
} \
} while (0)
DecoderErrorOr<void> Decoder::adapt_non_coef_probs()
DecoderErrorOr<void> Decoder::adapt_non_coef_probs(FrameContext const& frame_context)
{
auto& probs = *m_parser->m_probability_tables;
auto& counter = *m_parser->m_syntax_element_counter;
@ -295,7 +295,7 @@ DecoderErrorOr<void> Decoder::adapt_non_coef_probs()
ADAPT_TREE(intra_mode, uv_mode, uv_mode, INTER_MODE_CONTEXTS);
ADAPT_TREE(partition, partition, partition, INTER_MODE_CONTEXTS);
ADAPT_PROB_TABLE(skip, SKIP_CONTEXTS);
if (m_parser->m_interpolation_filter == Switchable) {
if (frame_context.interpolation_filter == Switchable) {
ADAPT_TREE(interp_filter, interp_filter, interp_filter, INTERP_FILTER_CONTEXTS);
}
if (m_parser->m_tx_mode == TXModeSelect) {
@ -317,7 +317,7 @@ DecoderErrorOr<void> Decoder::adapt_non_coef_probs()
for (size_t j = 0; j < CLASS0_SIZE; j++)
adapt_probs(mv_fr_tree, probs.mv_class0_fr_probs()[i][j], counter.m_counts_mv_class0_fr[i][j]);
adapt_probs(mv_fr_tree, probs.mv_fr_probs()[i], counter.m_counts_mv_fr[i]);
if (m_parser->m_allow_high_precision_mv) {
if (frame_context.high_precision_motion_vectors_allowed) {
probs.mv_class0_hp_prob()[i] = adapt_prob(probs.mv_class0_hp_prob()[i], counter.m_counts_mv_class0_hp[i]);
probs.mv_hp_prob()[i] = adapt_prob(probs.mv_hp_prob()[i], counter.m_counts_mv_hp[i]);
}
@ -787,7 +787,7 @@ DecoderErrorOr<void> Decoder::predict_inter_block(u8 plane, BlockContext const&
// A variable refIdx specifying which reference frame is being used is set equal to
// ref_frame_idx[ ref_frame[ refList ] - LAST_FRAME ].
auto reference_frame_index = m_parser->m_ref_frame_idx[m_parser->m_ref_frame[ref_list] - LastFrame];
auto reference_frame_index = block_context.frame_context.reference_frame_indices[m_parser->m_ref_frame[ref_list] - LastFrame];
// It is a requirement of bitstream conformance that all the following conditions are satisfied:
// 2 * FrameWidth >= RefFrameWidth[ refIdx ]
@ -1757,9 +1757,8 @@ DecoderErrorOr<void> Decoder::update_reference_frames(FrameContext const& frame_
// 1. For each value of i from 0 to NUM_REF_FRAMES - 1, the following applies if bit i of refresh_frame_flags
// is equal to 1 (i.e. if (refresh_frame_flags>>i)&1 is equal to 1):
auto refresh_flags = m_parser->m_refresh_frame_flags;
for (auto i = 0; i < NUM_REF_FRAMES; i++) {
if ((refresh_flags & 1) != 0) {
for (u8 i = 0; i < NUM_REF_FRAMES; i++) {
if (frame_context.should_update_reference_frame_at_index(i)) {
// RefFrameWidth[ i ] is set equal to FrameWidth.
// RefFrameHeight[ i ] is set equal to FrameHeight.
m_parser->m_ref_frame_size[i] = frame_context.size();
@ -1801,8 +1800,6 @@ DecoderErrorOr<void> Decoder::update_reference_frames(FrameContext const& frame_
}
}
}
refresh_flags >>= 1;
}
// 2. If show_existing_frame is equal to 0, the following applies:

View file

@ -51,8 +51,8 @@ private:
/* (8.4) Probability Adaptation Process */
u8 merge_prob(u8 pre_prob, u8 count_0, u8 count_1, u8 count_sat, u8 max_update_factor);
u8 merge_probs(int const* tree, int index, u8* probs, u8* counts, u8 count_sat, u8 max_update_factor);
DecoderErrorOr<void> adapt_coef_probs();
DecoderErrorOr<void> adapt_non_coef_probs();
DecoderErrorOr<void> adapt_coef_probs(bool is_inter_predicted_frame);
DecoderErrorOr<void> adapt_non_coef_probs(FrameContext const&);
void adapt_probs(int const* tree, u8* probs, u8* counts);
u8 adapt_prob(u8 prob, u8 counts[2]);

View file

@ -11,9 +11,10 @@
namespace Video::VP9 {
enum FrameType {
enum class FrameType {
KeyFrame,
NonKeyFrame
IntraOnlyFrame,
InterFrame
};
enum ColorSpace : u8 {

View file

@ -90,19 +90,20 @@ DecoderErrorOr<FrameContext> Parser::parse_frame(ReadonlyBytes frame_data)
// FIXME: This should not be an error. Spec says that we consume padding bits until the end of the sample.
if (frame_context.header_size_in_bytes == 0)
return DecoderError::corrupted("Frame header is zero-sized"sv);
m_probability_tables->load_probs(m_frame_context_idx);
m_probability_tables->load_probs2(m_frame_context_idx);
m_probability_tables->load_probs(frame_context.probability_context_index);
m_probability_tables->load_probs2(frame_context.probability_context_index);
m_syntax_element_counter->clear_counts();
TRY_READ(m_bit_stream->init_bool(frame_context.header_size_in_bytes));
TRY(compressed_header());
TRY(compressed_header(frame_context));
TRY_READ(m_bit_stream->exit_bool());
TRY(m_decoder.allocate_buffers(frame_context));
TRY(decode_tiles(frame_context));
TRY(refresh_probs());
TRY(refresh_probs(frame_context));
m_previous_frame_type = frame_context.type;
m_previous_frame_size = frame_context.size();
m_previous_show_frame = frame_context.shows_a_frame();
m_previous_color_config = frame_context.color_config;
@ -119,28 +120,21 @@ bool Parser::trailing_bits()
return true;
}
DecoderErrorOr<void> Parser::refresh_probs()
DecoderErrorOr<void> Parser::refresh_probs(FrameContext const& frame_context)
{
if (!m_error_resilient_mode && !m_frame_parallel_decoding_mode) {
m_probability_tables->load_probs(m_frame_context_idx);
TRY(m_decoder.adapt_coef_probs());
if (!m_frame_is_intra) {
m_probability_tables->load_probs2(m_frame_context_idx);
TRY(m_decoder.adapt_non_coef_probs());
if (!frame_context.error_resilient_mode && !frame_context.parallel_decoding_mode) {
m_probability_tables->load_probs(frame_context.probability_context_index);
TRY(m_decoder.adapt_coef_probs(frame_context.is_inter_predicted()));
if (frame_context.is_inter_predicted()) {
m_probability_tables->load_probs2(frame_context.probability_context_index);
TRY(m_decoder.adapt_non_coef_probs(frame_context));
}
}
if (m_refresh_frame_context)
m_probability_tables->save_probs(m_frame_context_idx);
if (frame_context.should_replace_probability_context)
m_probability_tables->save_probs(frame_context.probability_context_index);
return {};
}
DecoderErrorOr<FrameType> Parser::read_frame_type()
{
if (TRY_READ(m_bit_stream->read_bit()))
return NonKeyFrame;
return KeyFrame;
}
DecoderErrorOr<ColorRange> Parser::read_color_range()
{
if (TRY_READ(m_bit_stream->read_bit()))
@ -165,82 +159,105 @@ DecoderErrorOr<FrameContext> Parser::uncompressed_header()
return DecoderError::corrupted("uncompressed_header: Profile 3 reserved bit was non-zero"sv);
if (TRY_READ(m_bit_stream->read_bit())) {
m_refresh_frame_flags = 0;
m_loop_filter_level = 0;
frame_context.set_existing_frame_to_show(TRY_READ(m_bit_stream->read_bits(3)));
return frame_context;
}
m_last_frame_type = m_frame_type;
m_frame_type = TRY(read_frame_type());
bool is_keyframe = !TRY_READ(m_bit_stream->read_bit());
if (!TRY_READ(m_bit_stream->read_bit()))
frame_context.set_frame_hidden();
m_error_resilient_mode = TRY_READ(m_bit_stream->read_bit());
frame_context.error_resilient_mode = TRY_READ(m_bit_stream->read_bit());
FrameType type;
Gfx::Size<u32> frame_size;
Gfx::Size<u32> render_size;
u8 reference_frames_to_update_flags = 0xFF; // Save frame to all reference indices by default.
if (m_frame_type == KeyFrame) {
enum class ResetProbabilities : u8 {
No = 0,
// 1 also means No here, but we don't need to do anything with the No case.
OnlyCurrent = 2,
All = 3,
};
ResetProbabilities reset_frame_context = ResetProbabilities::All;
if (is_keyframe) {
type = FrameType::KeyFrame;
TRY(frame_sync_code());
frame_context.color_config = TRY(parse_color_config(frame_context));
frame_size = TRY(parse_frame_size());
render_size = TRY(parse_render_size(frame_size));
m_refresh_frame_flags = 0xFF;
m_frame_is_intra = true;
} else {
m_frame_is_intra = !frame_context.shows_a_frame() && TRY_READ(m_bit_stream->read_bit());
if (!m_error_resilient_mode) {
m_reset_frame_context = TRY_READ(m_bit_stream->read_bits(2));
if (!frame_context.shows_a_frame() && TRY_READ(m_bit_stream->read_bit())) {
type = FrameType::IntraOnlyFrame;
} else {
m_reset_frame_context = 0;
type = FrameType::InterFrame;
reset_frame_context = ResetProbabilities::No;
}
if (m_frame_is_intra) {
if (!frame_context.error_resilient_mode)
reset_frame_context = static_cast<ResetProbabilities>(TRY_READ(m_bit_stream->read_bits(2)));
if (type == FrameType::IntraOnlyFrame) {
TRY(frame_sync_code());
frame_context.color_config = frame_context.profile > 0 ? TRY(parse_color_config(frame_context)) : ColorConfig();
m_refresh_frame_flags = TRY_READ(m_bit_stream->read_f8());
reference_frames_to_update_flags = TRY_READ(m_bit_stream->read_f8());
frame_size = TRY(parse_frame_size());
render_size = TRY(parse_render_size(frame_size));
} else {
m_refresh_frame_flags = TRY_READ(m_bit_stream->read_f8());
reference_frames_to_update_flags = TRY_READ(m_bit_stream->read_f8());
for (auto i = 0; i < 3; i++) {
m_ref_frame_idx[i] = TRY_READ(m_bit_stream->read_bits(3));
m_ref_frame_sign_bias[LastFrame + i] = TRY_READ(m_bit_stream->read_bit());
frame_context.reference_frame_indices[i] = TRY_READ(m_bit_stream->read_bits(3));
frame_context.reference_frame_sign_biases[LastFrame + i] = TRY_READ(m_bit_stream->read_bit());
}
frame_size = TRY(parse_frame_size_with_refs());
frame_size = TRY(parse_frame_size_with_refs(frame_context.reference_frame_indices));
render_size = TRY(parse_render_size(frame_size));
m_allow_high_precision_mv = TRY_READ(m_bit_stream->read_bit());
TRY(read_interpolation_filter());
frame_context.high_precision_motion_vectors_allowed = TRY_READ(m_bit_stream->read_bit());
frame_context.interpolation_filter = TRY(read_interpolation_filter());
}
}
bool should_replace_probability_context = false;
bool parallel_decoding_mode = true;
if (!frame_context.error_resilient_mode) {
should_replace_probability_context = TRY_READ(m_bit_stream->read_bit());
parallel_decoding_mode = TRY_READ(m_bit_stream->read_bit());
}
u8 probability_context_index = TRY_READ(m_bit_stream->read_bits(2));
switch (reset_frame_context) {
case ResetProbabilities::All:
setup_past_independence();
for (auto i = 0; i < 4; i++) {
m_probability_tables->save_probs(i);
}
probability_context_index = 0;
break;
case ResetProbabilities::OnlyCurrent:
setup_past_independence();
m_probability_tables->save_probs(probability_context_index);
probability_context_index = 0;
break;
default:
break;
}
frame_context.type = type;
DECODER_TRY_ALLOC(frame_context.set_size(frame_size));
frame_context.render_size = render_size;
TRY(compute_image_size(frame_context));
if (!m_error_resilient_mode) {
m_refresh_frame_context = TRY_READ(m_bit_stream->read_bit());
m_frame_parallel_decoding_mode = TRY_READ(m_bit_stream->read_bit());
} else {
m_refresh_frame_context = false;
m_frame_parallel_decoding_mode = true;
}
frame_context.reference_frames_to_update_flags = reference_frames_to_update_flags;
frame_context.parallel_decoding_mode = parallel_decoding_mode;
m_frame_context_idx = TRY_READ(m_bit_stream->read_bits(2));
if (m_frame_is_intra || m_error_resilient_mode) {
setup_past_independence();
if (m_frame_type == KeyFrame || m_error_resilient_mode || m_reset_frame_context == 3) {
for (auto i = 0; i < 4; i++) {
m_probability_tables->save_probs(i);
}
} else if (m_reset_frame_context == 2) {
m_probability_tables->save_probs(m_frame_context_idx);
}
m_frame_context_idx = 0;
}
frame_context.should_replace_probability_context = should_replace_probability_context;
frame_context.probability_context_index = probability_context_index;
TRY(loop_filter_params());
TRY(quantization_params());
@ -325,10 +342,10 @@ DecoderErrorOr<Gfx::Size<u32>> Parser::parse_render_size(Gfx::Size<u32> frame_si
return Gfx::Size<u32> { TRY_READ(m_bit_stream->read_f16()) + 1, TRY_READ(m_bit_stream->read_f16()) + 1 };
}
DecoderErrorOr<Gfx::Size<u32>> Parser::parse_frame_size_with_refs()
DecoderErrorOr<Gfx::Size<u32>> Parser::parse_frame_size_with_refs(Array<u8, 3> const& reference_indices)
{
Optional<Gfx::Size<u32>> size;
for (auto frame_index : m_ref_frame_idx) {
for (auto frame_index : reference_indices) {
if (TRY_READ(m_bit_stream->read_bit())) {
size.emplace(m_ref_frame_size[frame_index]);
break;
@ -364,18 +381,16 @@ DecoderErrorOr<void> Parser::compute_image_size(FrameContext& frame_context)
// d. error_resilient_mode is equal to 0.
// e. FrameIsIntra is equal to 0.
// Otherwise, UsePrevFrameMvs is set equal to 0.
m_use_prev_frame_mvs = !first_invoke && same_size && m_previous_show_frame && !m_error_resilient_mode && !m_frame_is_intra;
m_use_prev_frame_mvs = !first_invoke && same_size && m_previous_show_frame && !frame_context.error_resilient_mode && frame_context.is_inter_predicted();
return {};
}
DecoderErrorOr<void> Parser::read_interpolation_filter()
DecoderErrorOr<InterpolationFilter> Parser::read_interpolation_filter()
{
if (TRY_READ(m_bit_stream->read_bit())) {
m_interpolation_filter = Switchable;
} else {
m_interpolation_filter = literal_to_type[TRY_READ(m_bit_stream->read_bits(2))];
return InterpolationFilter::Switchable;
}
return {};
return literal_to_type[TRY_READ(m_bit_stream->read_bits(2))];
}
DecoderErrorOr<void> Parser::loop_filter_params()
@ -519,23 +534,23 @@ void Parser::setup_past_independence()
m_probability_tables->reset_probs();
}
DecoderErrorOr<void> Parser::compressed_header()
DecoderErrorOr<void> Parser::compressed_header(FrameContext& frame_context)
{
TRY(read_tx_mode());
if (m_tx_mode == TXModeSelect)
TRY(tx_mode_probs());
TRY(read_coef_probs());
TRY(read_skip_prob());
if (!m_frame_is_intra) {
if (frame_context.is_inter_predicted()) {
TRY(read_inter_mode_probs());
if (m_interpolation_filter == Switchable)
if (frame_context.interpolation_filter == Switchable)
TRY(read_interp_filter_probs());
TRY(read_is_inter_probs());
TRY(frame_reference_mode());
TRY(frame_reference_mode(frame_context));
TRY(frame_reference_mode_probs());
TRY(read_y_mode_probs());
TRY(read_partition_probs());
TRY(mv_probs());
TRY(mv_probs(frame_context));
}
return {};
}
@ -670,13 +685,13 @@ DecoderErrorOr<void> Parser::read_is_inter_probs()
return {};
}
DecoderErrorOr<void> Parser::frame_reference_mode()
DecoderErrorOr<void> Parser::frame_reference_mode(FrameContext& frame_context)
{
// FIXME: These fields and the ones set in setup_compound_reference_mode should probably be contained by a field,
// since they are all used to set the reference frames later in one function (I think).
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])
if (frame_context.reference_frame_sign_biases[i] != frame_context.reference_frame_sign_biases[1])
compound_reference_allowed = true;
}
if (compound_reference_allowed) {
@ -689,7 +704,7 @@ DecoderErrorOr<void> Parser::frame_reference_mode()
m_reference_mode = CompoundReference;
else
m_reference_mode = ReferenceModeSelect;
setup_compound_reference_mode();
setup_compound_reference_mode(frame_context);
}
} else {
m_reference_mode = SingleReference;
@ -743,7 +758,7 @@ DecoderErrorOr<void> Parser::read_partition_probs()
return {};
}
DecoderErrorOr<void> Parser::mv_probs()
DecoderErrorOr<void> Parser::mv_probs(FrameContext const& frame_context)
{
for (auto j = 0; j < MV_JOINTS - 1; j++) {
auto& mv_joint_probs = m_probability_tables->mv_joint_probs();
@ -778,7 +793,7 @@ DecoderErrorOr<void> Parser::mv_probs()
}
}
if (m_allow_high_precision_mv) {
if (frame_context.high_precision_motion_vectors_allowed) {
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();
@ -798,13 +813,13 @@ DecoderErrorOr<u8> Parser::update_mv_prob(u8 prob)
return prob;
}
void Parser::setup_compound_reference_mode()
void Parser::setup_compound_reference_mode(FrameContext& frame_context)
{
if (m_ref_frame_sign_bias[LastFrame] == m_ref_frame_sign_bias[GoldenFrame]) {
if (frame_context.reference_frame_sign_biases[LastFrame] == frame_context.reference_frame_sign_biases[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]) {
} else if (frame_context.reference_frame_sign_biases[LastFrame] == frame_context.reference_frame_sign_biases[AltRefFrame]) {
m_comp_fixed_ref = GoldenFrame;
m_comp_var_ref[0] = LastFrame;
m_comp_var_ref[1] = AltRefFrame;
@ -903,7 +918,7 @@ DecoderErrorOr<void> Parser::decode_partition(TileContext& tile_context, u32 row
auto half_block_8x8 = num_8x8 >> 1;
bool has_rows = (row + half_block_8x8) < tile_context.frame_context.rows();
bool has_cols = (column + half_block_8x8) < tile_context.frame_context.columns();
auto partition = TRY_READ(TreeParser::parse_partition(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, has_rows, has_cols, subsize, num_8x8, m_above_partition_context, m_left_partition_context, row, column, m_frame_is_intra));
auto partition = TRY_READ(TreeParser::parse_partition(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, has_rows, has_cols, subsize, num_8x8, m_above_partition_context, m_left_partition_context, row, column, !tile_context.frame_context.is_inter_predicted()));
auto child_subsize = subsize_lookup[partition][subsize];
if (child_subsize < Block_8x8 || partition == PartitionNone) {
@ -962,10 +977,10 @@ DecoderErrorOr<void> Parser::decode_block(TileContext& tile_context, u32 row, u3
DecoderErrorOr<void> Parser::mode_info(BlockContext& block_context, FrameBlockContext above_context, FrameBlockContext left_context)
{
if (m_frame_is_intra)
TRY(intra_frame_mode_info(block_context, above_context, left_context));
else
if (block_context.frame_context.is_inter_predicted())
TRY(inter_frame_mode_info(block_context, above_context, left_context));
else
TRY(intra_frame_mode_info(block_context, above_context, left_context));
return {};
}
@ -1143,7 +1158,7 @@ DecoderErrorOr<void> Parser::intra_block_mode_info(BlockContext& block_context)
DecoderErrorOr<void> Parser::inter_block_mode_info(BlockContext& block_context, FrameBlockContext above_context, FrameBlockContext left_context)
{
TRY(read_ref_frames(above_context, left_context));
TRY(read_ref_frames(block_context, above_context, left_context));
for (auto j = 0; j < 2; j++) {
if (m_ref_frame[j] > IntraFrame) {
find_mv_refs(block_context, m_ref_frame[j], -1);
@ -1156,10 +1171,10 @@ DecoderErrorOr<void> Parser::inter_block_mode_info(BlockContext& block_context,
} else if (block_context.size >= Block_8x8) {
m_y_mode = TRY_READ(TreeParser::parse_inter_mode(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, m_mode_context[m_ref_frame[0]]));
}
if (m_interpolation_filter == Switchable)
if (block_context.frame_context.interpolation_filter == Switchable)
m_interp_filter = TRY_READ(TreeParser::parse_interpolation_filter(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, above_context, left_context));
else
m_interp_filter = m_interpolation_filter;
m_interp_filter = block_context.frame_context.interpolation_filter;
if (block_context.size < Block_8x8) {
m_num_4x4_w = num_4x4_blocks_wide_lookup[block_context.size];
m_num_4x4_h = num_4x4_blocks_high_lookup[block_context.size];
@ -1170,7 +1185,7 @@ DecoderErrorOr<void> Parser::inter_block_mode_info(BlockContext& block_context,
for (auto j = 0; j < 1 + is_compound; j++)
append_sub8x8_mvs(block_context, idy * 2 + idx, j);
}
TRY(assign_mv(is_compound));
TRY(assign_mv(block_context, is_compound));
for (auto y = 0; y < m_num_4x4_h; y++) {
for (auto x = 0; x < m_num_4x4_w; x++) {
auto block = (idy + y) * 2 + idx + x;
@ -1183,7 +1198,7 @@ DecoderErrorOr<void> Parser::inter_block_mode_info(BlockContext& block_context,
}
return {};
}
TRY(assign_mv(is_compound));
TRY(assign_mv(block_context, is_compound));
for (auto ref_list = 0; ref_list < 1 + is_compound; ref_list++) {
for (auto block = 0; block < 4; block++) {
m_block_mvs[ref_list][block] = m_mv[ref_list];
@ -1192,7 +1207,7 @@ DecoderErrorOr<void> Parser::inter_block_mode_info(BlockContext& block_context,
return {};
}
DecoderErrorOr<void> Parser::read_ref_frames(FrameBlockContext above_context, FrameBlockContext left_context)
DecoderErrorOr<void> Parser::read_ref_frames(BlockContext& block_context, FrameBlockContext above_context, FrameBlockContext left_context)
{
if (seg_feature_active(SEG_LVL_REF_FRAME)) {
m_ref_frame[0] = static_cast<ReferenceFrameType>(m_feature_data[m_segment_id][SEG_LVL_REF_FRAME]);
@ -1206,8 +1221,8 @@ DecoderErrorOr<void> Parser::read_ref_frames(FrameBlockContext above_context, Fr
comp_mode = m_reference_mode;
if (comp_mode == CompoundReference) {
// FIXME: Make reference frame pairs be indexed by an enum of FixedReference or VariableReference?
auto fixed_reference_index = m_ref_frame_sign_bias[m_comp_fixed_ref];
auto variable_reference_index = fixed_reference_index == 0 ? 1 : 0;
auto fixed_reference_index = block_context.frame_context.reference_frame_sign_biases[m_comp_fixed_ref];
auto variable_reference_index = !fixed_reference_index;
// FIXME: Create an enum for compound frame references using names Primary and Secondary.
auto comp_ref = TRY_READ(TreeParser::parse_comp_ref(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, m_comp_fixed_ref, m_comp_var_ref, variable_reference_index, above_context, left_context));
@ -1228,12 +1243,12 @@ DecoderErrorOr<void> Parser::read_ref_frames(FrameBlockContext above_context, Fr
return {};
}
DecoderErrorOr<void> Parser::assign_mv(bool is_compound)
DecoderErrorOr<void> Parser::assign_mv(BlockContext const& block_context, bool is_compound)
{
m_mv[1] = {};
for (auto i = 0; i < 1 + is_compound; i++) {
if (m_y_mode == PredictionMode::NewMv) {
TRY(read_mv(i));
TRY(read_mv(block_context, i));
} else if (m_y_mode == PredictionMode::NearestMv) {
m_mv[i] = m_nearest_mv[i];
} else if (m_y_mode == PredictionMode::NearMv) {
@ -1245,9 +1260,9 @@ DecoderErrorOr<void> Parser::assign_mv(bool is_compound)
return {};
}
DecoderErrorOr<void> Parser::read_mv(u8 ref)
DecoderErrorOr<void> Parser::read_mv(BlockContext const& block_context, u8 ref)
{
m_use_hp = m_allow_high_precision_mv && use_mv_hp(m_best_mv[ref]);
m_use_hp = block_context.frame_context.high_precision_motion_vectors_allowed && use_mv_hp(m_best_mv[ref]);
MotionVector diff_mv;
auto mv_joint = TRY_READ(TreeParser::parse_motion_vector_joint(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter));
if (mv_joint == MvJointHzvnz || mv_joint == MvJointHnzvnz)
@ -1507,10 +1522,10 @@ void Parser::if_same_ref_frame_add_mv(BlockContext const& block_context, MotionV
}
}
void Parser::scale_mv(u8 ref_list, ReferenceFrameType ref_frame)
void Parser::scale_mv(FrameContext const& frame_context, u8 ref_list, ReferenceFrameType ref_frame)
{
auto candidate_frame = m_candidate_frame[ref_list];
if (m_ref_frame_sign_bias[candidate_frame] != m_ref_frame_sign_bias[ref_frame])
if (frame_context.reference_frame_sign_biases[candidate_frame] != frame_context.reference_frame_sign_biases[ref_frame])
m_candidate_mv[ref_list] *= -1;
}
@ -1520,11 +1535,11 @@ void Parser::if_diff_ref_frame_add_mv(BlockContext const& block_context, MotionV
get_block_mv(block_context, candidate_vector, ref_list, use_prev);
auto mvs_are_same = m_candidate_mv[0] == m_candidate_mv[1];
if (m_candidate_frame[0] > ReferenceFrameType::IntraFrame && m_candidate_frame[0] != ref_frame) {
scale_mv(0, ref_frame);
scale_mv(block_context.frame_context, 0, ref_frame);
add_mv_ref_list(0);
}
if (m_candidate_frame[1] > ReferenceFrameType::IntraFrame && m_candidate_frame[1] != ref_frame && !mvs_are_same) {
scale_mv(1, ref_frame);
scale_mv(block_context.frame_context, 1, ref_frame);
add_mv_ref_list(1);
}
}
@ -1629,7 +1644,7 @@ void Parser::find_best_ref_mvs(BlockContext& block_context, u8 ref_list)
auto delta = m_ref_list_mv[i];
auto delta_row = delta.row();
auto delta_column = delta.column();
if (!m_allow_high_precision_mv || !use_mv_hp(delta)) {
if (!block_context.frame_context.high_precision_motion_vectors_allowed || !use_mv_hp(delta)) {
if (delta_row & 1)
delta_row += delta_row > 0 ? -1 : 1;
if (delta_column & 1)

View file

@ -52,7 +52,7 @@ private:
/* (6.1) Frame Syntax */
bool trailing_bits();
DecoderErrorOr<void> refresh_probs();
DecoderErrorOr<void> refresh_probs(FrameContext const&);
/* (6.2) Uncompressed Header Syntax */
DecoderErrorOr<FrameContext> uncompressed_header();
@ -60,10 +60,10 @@ private:
DecoderErrorOr<ColorConfig> parse_color_config(FrameContext const&);
DecoderErrorOr<void> set_frame_size_and_compute_image_size();
DecoderErrorOr<Gfx::Size<u32>> parse_frame_size();
DecoderErrorOr<Gfx::Size<u32>> parse_frame_size_with_refs();
DecoderErrorOr<Gfx::Size<u32>> parse_frame_size_with_refs(Array<u8, 3> const& reference_indices);
DecoderErrorOr<Gfx::Size<u32>> parse_render_size(Gfx::Size<u32> frame_size);
DecoderErrorOr<void> compute_image_size(FrameContext&);
DecoderErrorOr<void> read_interpolation_filter();
DecoderErrorOr<InterpolationFilter> read_interpolation_filter();
DecoderErrorOr<void> loop_filter_params();
DecoderErrorOr<void> quantization_params();
DecoderErrorOr<i8> read_delta_q();
@ -75,7 +75,7 @@ private:
void setup_past_independence();
/* (6.3) Compressed Header Syntax */
DecoderErrorOr<void> compressed_header();
DecoderErrorOr<void> compressed_header(FrameContext&);
DecoderErrorOr<void> read_tx_mode();
DecoderErrorOr<void> tx_mode_probs();
DecoderErrorOr<u8> diff_update_prob(u8 prob);
@ -87,13 +87,13 @@ private:
DecoderErrorOr<void> read_inter_mode_probs();
DecoderErrorOr<void> read_interp_filter_probs();
DecoderErrorOr<void> read_is_inter_probs();
DecoderErrorOr<void> frame_reference_mode();
DecoderErrorOr<void> frame_reference_mode(FrameContext&);
DecoderErrorOr<void> frame_reference_mode_probs();
DecoderErrorOr<void> read_y_mode_probs();
DecoderErrorOr<void> read_partition_probs();
DecoderErrorOr<void> mv_probs();
DecoderErrorOr<void> mv_probs(FrameContext const&);
DecoderErrorOr<u8> update_mv_prob(u8 prob);
void setup_compound_reference_mode();
void setup_compound_reference_mode(FrameContext&);
/* (6.4) Decode Tiles Syntax */
DecoderErrorOr<void> decode_tiles(FrameContext&);
@ -115,9 +115,9 @@ private:
DecoderErrorOr<void> read_is_inter(FrameBlockContext above_context, FrameBlockContext left_context);
DecoderErrorOr<void> intra_block_mode_info(BlockContext&);
DecoderErrorOr<void> inter_block_mode_info(BlockContext&, FrameBlockContext above_context, FrameBlockContext left_context);
DecoderErrorOr<void> read_ref_frames(FrameBlockContext above_context, FrameBlockContext left_context);
DecoderErrorOr<void> assign_mv(bool is_compound);
DecoderErrorOr<void> read_mv(u8 ref);
DecoderErrorOr<void> read_ref_frames(BlockContext&, FrameBlockContext above_context, FrameBlockContext left_context);
DecoderErrorOr<void> assign_mv(BlockContext const&, bool is_compound);
DecoderErrorOr<void> read_mv(BlockContext const&, u8 ref);
DecoderErrorOr<i32> read_mv_component(u8 component);
DecoderErrorOr<bool> residual(BlockContext&, bool has_block_above, bool has_block_left);
DecoderErrorOr<bool> tokens(BlockContext&, size_t plane, u32 x, u32 y, TXSize tx_size, u32 block_index);
@ -135,32 +135,20 @@ private:
void get_block_mv(BlockContext const&, MotionVector candidate_vector, u8 ref_list, bool use_prev);
void if_same_ref_frame_add_mv(BlockContext const&, MotionVector candidate_vector, ReferenceFrameType ref_frame, bool use_prev);
void if_diff_ref_frame_add_mv(BlockContext const&, MotionVector candidate_vector, ReferenceFrameType ref_frame, bool use_prev);
void scale_mv(u8 ref_list, ReferenceFrameType ref_frame);
void scale_mv(FrameContext const&, u8 ref_list, ReferenceFrameType ref_frame);
void add_mv_ref_list(u8 ref_list);
Gfx::Point<size_t> get_decoded_point_for_plane(FrameContext const&, u32 row, u32 column, u8 plane);
Gfx::Size<size_t> get_decoded_size_for_plane(FrameContext const&, u8 plane);
u8 m_refresh_frame_flags { 0 };
u8 m_loop_filter_level { 0 };
u8 m_loop_filter_sharpness { 0 };
bool m_loop_filter_delta_enabled { false };
FrameType m_frame_type { FrameType::KeyFrame };
FrameType m_last_frame_type { FrameType::KeyFrame };
bool m_error_resilient_mode { false };
bool m_frame_is_intra { false };
u8 m_reset_frame_context { 0 };
bool m_allow_high_precision_mv { false };
u8 m_ref_frame_idx[3];
u8 m_ref_frame_sign_bias[LastFrame + 3];
bool m_refresh_frame_context { false };
bool m_frame_parallel_decoding_mode { false };
u8 m_frame_context_idx { 0 };
bool m_is_first_compute_image_size_invoke { true };
Gfx::Size<u32> m_previous_frame_size { 0, 0 };
bool m_previous_show_frame { false };
ColorConfig m_previous_color_config;
InterpolationFilter m_interpolation_filter { 0xf };
FrameType m_previous_frame_type { FrameType::KeyFrame };
u8 m_base_q_idx { 0 };
i8 m_delta_q_y_dc { 0 };
i8 m_delta_q_uv_dc { 0 };

View file

@ -1171,7 +1171,7 @@ KfUVModeProbs const& ProbabilityTables::kf_uv_mode_prob() const
return constant_kf_uv_mode_prob;
}
void ProbabilityTables::save_probs(size_t index)
void ProbabilityTables::save_probs(u8 index)
{
m_saved_probability_tables[index] = m_current_probability_table;
}
@ -1201,7 +1201,7 @@ void ProbabilityTables::reset_probs()
__builtin_memcpy(m_current_probability_table.coef_probs, default_coef_probs, sizeof(CoefProbs));
}
void ProbabilityTables::load_probs(size_t index)
void ProbabilityTables::load_probs(u8 index)
{
auto old_table = m_current_probability_table;
m_current_probability_table = m_saved_probability_tables.at(index);
@ -1209,7 +1209,7 @@ void ProbabilityTables::load_probs(size_t index)
__builtin_memcpy(m_current_probability_table.tx_probs, old_table.tx_probs, sizeof(TxProbs));
}
void ProbabilityTables::load_probs2(size_t index)
void ProbabilityTables::load_probs2(u8 index)
{
auto new_table = m_saved_probability_tables.at(index);
__builtin_memcpy(m_current_probability_table.skip_prob, new_table.skip_prob, sizeof(SkipProb));

View file

@ -42,10 +42,10 @@ typedef u8 CoefProbs[TX_SIZES][BLOCK_TYPES][REF_TYPES][COEF_BANDS][PREV_COEF_CON
class ProbabilityTables final {
public:
void save_probs(size_t index);
void save_probs(u8 index);
void reset_probs();
void load_probs(size_t index);
void load_probs2(size_t index);
void load_probs(u8 index);
void load_probs2(u8 index);
ParetoTable const& pareto_table() const;
KfPartitionProbs const& kf_partition_probs() const;