summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibVideo/VP9
diff options
context:
space:
mode:
authorZaggy1024 <zaggy1024@gmail.com>2022-11-22 21:55:02 -0600
committerAndreas Kling <kling@serenityos.org>2022-11-30 08:28:30 +0100
commit90f16c78fa3c03f80802f62c176b1a3d00353374 (patch)
tree701afafc13261a60aa16b1e601ebcefe29e3dee0 /Userland/Libraries/LibVideo/VP9
parent40bc987fe330146f20d6950945c43cd068a927ca (diff)
downloadserenity-90f16c78fa3c03f80802f62c176b1a3d00353374.zip
LibVideo/VP9: Move fields set in uncompressed_header() to FrameContext
Diffstat (limited to 'Userland/Libraries/LibVideo/VP9')
-rw-r--r--Userland/Libraries/LibVideo/VP9/Context.h18
-rw-r--r--Userland/Libraries/LibVideo/VP9/Decoder.cpp19
-rw-r--r--Userland/Libraries/LibVideo/VP9/Decoder.h4
-rw-r--r--Userland/Libraries/LibVideo/VP9/Enums.h5
-rw-r--r--Userland/Libraries/LibVideo/VP9/Parser.cpp217
-rw-r--r--Userland/Libraries/LibVideo/VP9/Parser.h36
-rw-r--r--Userland/Libraries/LibVideo/VP9/ProbabilityTables.cpp6
-rw-r--r--Userland/Libraries/LibVideo/VP9/ProbabilityTables.h6
8 files changed, 165 insertions, 146 deletions
diff --git a/Userland/Libraries/LibVideo/VP9/Context.h b/Userland/Libraries/LibVideo/VP9/Context.h
index 042ab1bef2..1319a95a00 100644
--- a/Userland/Libraries/LibVideo/VP9/Context.h
+++ b/Userland/Libraries/LibVideo/VP9/Context.h
@@ -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:
diff --git a/Userland/Libraries/LibVideo/VP9/Decoder.cpp b/Userland/Libraries/LibVideo/VP9/Decoder.cpp
index 25a467ddf5..d40f441feb 100644
--- a/Userland/Libraries/LibVideo/VP9/Decoder.cpp
+++ b/Userland/Libraries/LibVideo/VP9/Decoder.cpp
@@ -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:
diff --git a/Userland/Libraries/LibVideo/VP9/Decoder.h b/Userland/Libraries/LibVideo/VP9/Decoder.h
index 6bf719b0cc..8e33f14025 100644
--- a/Userland/Libraries/LibVideo/VP9/Decoder.h
+++ b/Userland/Libraries/LibVideo/VP9/Decoder.h
@@ -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]);
diff --git a/Userland/Libraries/LibVideo/VP9/Enums.h b/Userland/Libraries/LibVideo/VP9/Enums.h
index e9a8d94d56..2e6d549094 100644
--- a/Userland/Libraries/LibVideo/VP9/Enums.h
+++ b/Userland/Libraries/LibVideo/VP9/Enums.h
@@ -11,9 +11,10 @@
namespace Video::VP9 {
-enum FrameType {
+enum class FrameType {
KeyFrame,
- NonKeyFrame
+ IntraOnlyFrame,
+ InterFrame
};
enum ColorSpace : u8 {
diff --git a/Userland/Libraries/LibVideo/VP9/Parser.cpp b/Userland/Libraries/LibVideo/VP9/Parser.cpp
index 08185617d0..4d9fad65d6 100644
--- a/Userland/Libraries/LibVideo/VP9/Parser.cpp
+++ b/Userland/Libraries/LibVideo/VP9/Parser.cpp
@@ -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,83 +159,106 @@ 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());
}
}
- 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;
+ 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());
}
- m_frame_context_idx = TRY_READ(m_bit_stream->read_bits(2));
- if (m_frame_is_intra || m_error_resilient_mode) {
+ u8 probability_context_index = TRY_READ(m_bit_stream->read_bits(2));
+ switch (reset_frame_context) {
+ case ResetProbabilities::All:
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);
+ for (auto i = 0; i < 4; i++) {
+ m_probability_tables->save_probs(i);
}
- m_frame_context_idx = 0;
+ 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));
+
+ frame_context.reference_frames_to_update_flags = reference_frames_to_update_flags;
+ frame_context.parallel_decoding_mode = parallel_decoding_mode;
+
+ 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());
TRY(segmentation_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)
diff --git a/Userland/Libraries/LibVideo/VP9/Parser.h b/Userland/Libraries/LibVideo/VP9/Parser.h
index 70fe837e21..0898a47641 100644
--- a/Userland/Libraries/LibVideo/VP9/Parser.h
+++ b/Userland/Libraries/LibVideo/VP9/Parser.h
@@ -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 };
diff --git a/Userland/Libraries/LibVideo/VP9/ProbabilityTables.cpp b/Userland/Libraries/LibVideo/VP9/ProbabilityTables.cpp
index bc8c49a562..2ecf4fb3ad 100644
--- a/Userland/Libraries/LibVideo/VP9/ProbabilityTables.cpp
+++ b/Userland/Libraries/LibVideo/VP9/ProbabilityTables.cpp
@@ -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));
diff --git a/Userland/Libraries/LibVideo/VP9/ProbabilityTables.h b/Userland/Libraries/LibVideo/VP9/ProbabilityTables.h
index 1f42382880..15096f8f67 100644
--- a/Userland/Libraries/LibVideo/VP9/ProbabilityTables.h
+++ b/Userland/Libraries/LibVideo/VP9/ProbabilityTables.h
@@ -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;