summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorZaggy1024 <zaggy1024@gmail.com>2022-11-23 16:51:57 -0600
committerAndreas Kling <kling@serenityos.org>2022-11-30 08:28:30 +0100
commitbefcd479ae0e37dfbd69bc5d9f1016adc941e39d (patch)
treebc7ceb7ca94680c069998a781fa71a1a2d25b6e8 /Userland
parent448a8b8efb95f653460f150e676bb6b43d5e6af0 (diff)
downloadserenity-befcd479ae0e37dfbd69bc5d9f1016adc941e39d.zip
LibVideo/VP9: Add Frame, Tile and Block context structs
These are used to pass context needed for decoding, with mutability scoped only to the sections that the function receiving the contexts needs to modify. This allows lifetimes of data to be more explicit rather than being stored in fields, as well as preventing tile threads from modifying outside their allowed bounds.
Diffstat (limited to 'Userland')
-rw-r--r--Userland/Libraries/LibVideo/VP9/Context.h103
-rw-r--r--Userland/Libraries/LibVideo/VP9/Decoder.cpp86
-rw-r--r--Userland/Libraries/LibVideo/VP9/Decoder.h18
-rw-r--r--Userland/Libraries/LibVideo/VP9/Parser.cpp462
-rw-r--r--Userland/Libraries/LibVideo/VP9/Parser.h109
5 files changed, 423 insertions, 355 deletions
diff --git a/Userland/Libraries/LibVideo/VP9/Context.h b/Userland/Libraries/LibVideo/VP9/Context.h
index 7443a96d4b..b37560229f 100644
--- a/Userland/Libraries/LibVideo/VP9/Context.h
+++ b/Userland/Libraries/LibVideo/VP9/Context.h
@@ -12,9 +12,8 @@
#include <LibGfx/Size.h>
#include <LibVideo/Color/CodingIndependentCodePoints.h>
-#include <AK/Format.h>
-
#include "Enums.h"
+#include "LookupTables.h"
#include "MotionVector.h"
namespace Video::VP9 {
@@ -153,7 +152,7 @@ public:
}
template<typename OtherT, typename Function>
- void copy_to(Vector2D<OtherT>& other, Function function)
+ void copy_to(Vector2D<OtherT>& other, Function function) const
{
VERIFY(width() <= other.width());
VERIFY(height() <= other.height());
@@ -163,7 +162,7 @@ public:
}
}
- void copy_to(Vector2D<T>& other)
+ void copy_to(Vector2D<T>& other) const
{
VERIFY(width() <= other.width());
VERIFY(height() <= other.height());
@@ -238,4 +237,100 @@ struct PersistentBlockContext {
u8 segment_id { 0 };
};
+struct FrameContext {
+public:
+ u8 profile { 0 };
+
+ bool shows_existing_frame() const { return m_show_existing_frame; }
+ u8 existing_frame_index() const { return m_existing_frame_index; }
+ void set_existing_frame_to_show(u8 index)
+ {
+ m_show_existing_frame = true;
+ m_existing_frame_index = index;
+ }
+
+ Gfx::Size<u32> size() const { return m_size; }
+ ErrorOr<void> set_size(Gfx::Size<u32> size)
+ {
+ m_size = size;
+
+ // From spec, compute_image_size( )
+ m_rows = (size.height() + 7u) >> 3u;
+ m_columns = (size.width() + 7u) >> 3u;
+ return m_block_contexts.try_resize(m_rows, m_columns);
+ }
+ u32 rows() const { return m_rows; }
+ u32 columns() const { return m_columns; }
+ u32 superblock_rows() const { return (rows() + 7u) >> 3u; }
+ u32 superblock_columns() const { return (columns() + 7u) >> 3u; }
+
+ Vector2D<FrameBlockContext> const& block_contexts() const { return m_block_contexts; }
+
+ Gfx::Size<u32> render_size { 0, 0 };
+
+ u16 header_size_in_bytes { 0 };
+
+private:
+ friend struct TileContext;
+
+ bool m_show_existing_frame { false };
+ u8 m_existing_frame_index { 0 };
+
+ Gfx::Size<u32> m_size { 0, 0 };
+ u32 m_rows { 0 };
+ u32 m_columns { 0 };
+ // FIXME: From spec: NOTE – We are using a 2D array to store the SubModes for clarity. It is possible to reduce memory
+ // consumption by only storing one intra mode for each 8x8 horizontal and vertical position, i.e. to use two 1D
+ // arrays instead.
+ // I think should also apply to other fields that are only accessed relative to the current block. Worth looking
+ // into how much of this context needs to be stored for the whole frame vs a row or column from the current tile.
+ Vector2D<FrameBlockContext> m_block_contexts;
+};
+
+struct TileContext {
+public:
+ TileContext(FrameContext& frame_context, u32 rows_start, u32 rows_end, u32 columns_start, u32 columns_end)
+ : frame_context(frame_context)
+ , rows_start(rows_start)
+ , rows_end(rows_end)
+ , columns_start(columns_start)
+ , columns_end(columns_end)
+ , block_contexts_view(frame_context.m_block_contexts.view(rows_start, columns_start, rows_end - rows_start, columns_end - columns_start))
+ {
+ }
+
+ Vector2D<FrameBlockContext> const& frame_block_contexts() const { return frame_context.block_contexts(); }
+
+ FrameContext const& frame_context;
+ u32 rows_start { 0 };
+ u32 rows_end { 0 };
+ u32 columns_start { 0 };
+ u32 columns_end { 0 };
+ Vector2DView<FrameBlockContext> block_contexts_view;
+};
+
+struct BlockContext {
+ BlockContext(TileContext& tile_context, u32 row, u32 column, BlockSubsize size)
+ : frame_context(tile_context.frame_context)
+ , tile_context(tile_context)
+ , row(row)
+ , column(column)
+ , size(size)
+ , contexts_view(tile_context.block_contexts_view.view(row - tile_context.rows_start, column - tile_context.columns_start,
+ min<u32>(num_8x8_blocks_high_lookup[size], tile_context.frame_context.rows() - row),
+ min<u32>(num_8x8_blocks_wide_lookup[size], tile_context.frame_context.columns() - column)))
+ {
+ }
+
+ Vector2D<FrameBlockContext> const& frame_block_contexts() const { return frame_context.block_contexts(); }
+
+ FrameContext const& frame_context;
+ TileContext const& tile_context;
+ u32 row { 0 };
+ u32 column { 0 };
+ BlockSubsize size;
+
+ Vector2DView<FrameBlockContext> contexts_view;
+};
+
}
diff --git a/Userland/Libraries/LibVideo/VP9/Decoder.cpp b/Userland/Libraries/LibVideo/VP9/Decoder.cpp
index f4bae29a9c..e03800866d 100644
--- a/Userland/Libraries/LibVideo/VP9/Decoder.cpp
+++ b/Userland/Libraries/LibVideo/VP9/Decoder.cpp
@@ -55,7 +55,7 @@ DecoderErrorOr<void> Decoder::decode_frame(ReadonlyBytes frame_data)
{
// 1. The syntax elements for the coded frame are extracted as specified in sections 6 and 7. The syntax
// tables include function calls indicating when the block decode processes should be triggered.
- TRY(m_parser->parse_frame(frame_data));
+ auto frame_context = TRY(m_parser->parse_frame(frame_data));
// 2. If loop_filter_level is not equal to 0, the loop filter process as specified in section 8.8 is invoked once the
// coded frame has been decoded.
@@ -70,17 +70,17 @@ DecoderErrorOr<void> Decoder::decode_frame(ReadonlyBytes frame_data)
// 4. The output process as specified in section 8.9 is invoked.
if (m_parser->m_show_frame)
- TRY(create_video_frame());
+ TRY(create_video_frame(frame_context));
// 5. The reference frame update process as specified in section 8.10 is invoked.
- TRY(update_reference_frames());
+ TRY(update_reference_frames(frame_context));
return {};
}
-DecoderErrorOr<void> Decoder::create_video_frame()
+DecoderErrorOr<void> Decoder::create_video_frame(FrameContext const& frame_context)
{
- u32 decoded_y_width = m_parser->m_mi_cols * 8;
- Gfx::Size<u32> output_y_size = m_parser->m_frame_size;
+ u32 decoded_y_width = frame_context.columns() * 8;
+ Gfx::Size<u32> output_y_size = frame_context.size();
auto decoded_uv_width = decoded_y_width >> m_parser->m_subsampling_x;
Gfx::Size<u32> output_uv_size = {
output_y_size.width() >> m_parser->m_subsampling_x,
@@ -125,10 +125,10 @@ inline size_t buffer_size(Gfx::Size<size_t> size)
return buffer_size(size.width(), size.height());
}
-DecoderErrorOr<void> Decoder::allocate_buffers()
+DecoderErrorOr<void> Decoder::allocate_buffers(FrameContext const& frame_context)
{
for (size_t plane = 0; plane < 3; plane++) {
- auto size = m_parser->get_decoded_size_for_plane(plane);
+ auto size = m_parser->get_decoded_size_for_plane(frame_context, plane);
auto& output_buffer = get_output_buffer(plane);
output_buffer.clear_with_capacity();
@@ -329,7 +329,7 @@ u8 Decoder::adapt_prob(u8 prob, u8 counts[2])
return merge_prob(prob, counts[0], counts[1], COUNT_SAT, MAX_UPDATE_FACTOR);
}
-DecoderErrorOr<void> Decoder::predict_intra(u8 plane, u32 x, u32 y, bool have_left, bool have_above, bool not_on_right, TXSize tx_size, u32 block_index)
+DecoderErrorOr<void> Decoder::predict_intra(u8 plane, BlockContext const& block_context, u32 x, u32 y, bool have_left, bool have_above, bool not_on_right, TXSize tx_size, u32 block_index)
{
auto& frame_buffer = get_output_buffer(plane);
@@ -346,7 +346,7 @@ DecoderErrorOr<void> Decoder::predict_intra(u8 plane, u32 x, u32 y, bool have_le
PredictionMode mode;
if (plane > 0)
mode = m_parser->m_uv_mode;
- else if (m_parser->m_mi_size >= Block_8x8)
+ else if (block_context.size >= Block_8x8)
mode = m_parser->m_y_mode;
else
mode = m_parser->m_block_sub_modes[block_index];
@@ -363,8 +363,8 @@ DecoderErrorOr<void> Decoder::predict_intra(u8 plane, u32 x, u32 y, bool have_le
// − maxY is set equal to ((MiRows * 8) >> subsampling_y) - 1.
auto subsampling_x = plane > 0 ? m_parser->m_subsampling_x : false;
auto subsampling_y = plane > 0 ? m_parser->m_subsampling_y : false;
- auto max_x = ((m_parser->m_mi_cols * 8u) >> subsampling_x) - 1u;
- auto max_y = ((m_parser->m_mi_rows * 8u) >> subsampling_y) - 1u;
+ auto max_x = ((block_context.frame_context.columns() * 8u) >> subsampling_x) - 1u;
+ auto max_y = ((block_context.frame_context.rows() * 8u) >> subsampling_y) - 1u;
auto const frame_buffer_at = [&](u32 row, u32 column) -> u16& {
const auto frame_stride = max_x + 1u;
@@ -665,7 +665,7 @@ DecoderErrorOr<void> Decoder::predict_intra(u8 plane, u32 x, u32 y, bool have_le
return {};
}
-MotionVector Decoder::select_motion_vector(u8 plane, u8 ref_list, u32 block_index)
+MotionVector Decoder::select_motion_vector(u8 plane, BlockContext const& block_context, u8 ref_list, u32 block_index)
{
// The inputs to this process are:
// − a variable plane specifying which plane is being predicted,
@@ -697,7 +697,7 @@ MotionVector Decoder::select_motion_vector(u8 plane, u8 ref_list, u32 block_inde
// The motion vector array mv is derived as follows:
// − If plane is equal to 0, or MiSize is greater than or equal to BLOCK_8X8, mv is set equal to
// BlockMvs[ refList ][ blockIdx ].
- if (plane == 0 || m_parser->m_mi_size >= Block_8x8)
+ if (plane == 0 || block_context.size >= Block_8x8)
return m_parser->m_block_mvs[ref_list][block_index];
// − Otherwise, if subsampling_x is equal to 0 and subsampling_y is equal to 0, mv is set equal to
// BlockMvs[ refList ][ blockIdx ].
@@ -721,7 +721,7 @@ MotionVector Decoder::select_motion_vector(u8 plane, u8 ref_list, u32 block_inde
+ m_parser->m_block_mvs[ref_list][2] + m_parser->m_block_mvs[ref_list][3]);
}
-MotionVector Decoder::clamp_motion_vector(u8 plane, u32 block_row, u32 block_column, MotionVector vector)
+MotionVector Decoder::clamp_motion_vector(u8 plane, BlockContext const& block_context, u32 block_row, u32 block_column, MotionVector vector)
{
// FIXME: This function is named very similarly to Parser::clamp_mv. Rename one or the other?
@@ -734,14 +734,14 @@ MotionVector Decoder::clamp_motion_vector(u8 plane, u32 block_row, u32 block_col
bool subsampling_y = plane > 0 ? m_parser->m_subsampling_y : false;
// The output array clampedMv is specified by the following steps:
- i32 blocks_high = num_8x8_blocks_high_lookup[m_parser->m_mi_size];
+ i32 blocks_high = num_8x8_blocks_high_lookup[block_context.size];
// Casts must be done here to prevent subtraction underflow from wrapping the values.
i32 mb_to_top_edge = -(static_cast<i32>(block_row * MI_SIZE) * 16) >> subsampling_y;
- i32 mb_to_bottom_edge = (((static_cast<i32>(m_parser->m_mi_rows) - blocks_high - static_cast<i32>(block_row)) * MI_SIZE) * 16) >> subsampling_y;
+ i32 mb_to_bottom_edge = (((static_cast<i32>(block_context.frame_context.rows()) - blocks_high - static_cast<i32>(block_row)) * MI_SIZE) * 16) >> subsampling_y;
- i32 blocks_wide = num_8x8_blocks_wide_lookup[m_parser->m_mi_size];
+ i32 blocks_wide = num_8x8_blocks_wide_lookup[block_context.size];
i32 mb_to_left_edge = -(static_cast<i32>(block_column * MI_SIZE) * 16) >> subsampling_x;
- i32 mb_to_right_edge = (((static_cast<i32>(m_parser->m_mi_cols) - blocks_wide - static_cast<i32>(block_column)) * MI_SIZE) * 16) >> subsampling_x;
+ i32 mb_to_right_edge = (((static_cast<i32>(block_context.frame_context.columns()) - blocks_wide - static_cast<i32>(block_column)) * MI_SIZE) * 16) >> subsampling_x;
i32 subpel_left = (INTERP_EXTEND + ((blocks_wide * MI_SIZE) >> subsampling_x)) << SUBPEL_BITS;
i32 subpel_right = subpel_left - SUBPEL_SHIFTS;
@@ -753,16 +753,16 @@ MotionVector Decoder::clamp_motion_vector(u8 plane, u32 block_row, u32 block_col
};
}
-DecoderErrorOr<void> Decoder::predict_inter_block(u8 plane, u8 ref_list, u32 block_row, u32 block_column, u32 x, u32 y, u32 width, u32 height, u32 block_index, Span<u16> block_buffer)
+DecoderErrorOr<void> Decoder::predict_inter_block(u8 plane, BlockContext const& block_context, u8 ref_list, u32 block_row, u32 block_column, u32 x, u32 y, u32 width, u32 height, u32 block_index, Span<u16> block_buffer)
{
VERIFY(width <= maximum_block_dimensions && height <= maximum_block_dimensions);
// 2. The motion vector selection process in section 8.5.2.1 is invoked with plane, refList, blockIdx as inputs
// and the output being the motion vector mv.
- auto motion_vector = select_motion_vector(plane, ref_list, block_index);
+ auto motion_vector = select_motion_vector(plane, block_context, ref_list, block_index);
// 3. The motion vector clamping process in section 8.5.2.2 is invoked with plane, mv as inputs and the output
// being the clamped motion vector clampedMv
- auto clamped_vector = clamp_motion_vector(plane, block_row, block_column, motion_vector);
+ auto clamped_vector = clamp_motion_vector(plane, block_context, block_row, block_column, motion_vector);
// 4. The motion vector scaling process in section 8.5.2.3 is invoked with plane, refList, x, y, clampedMv as
// inputs and the output being the initial location startX, startY, and the step sizes stepX, stepY.
@@ -791,10 +791,10 @@ DecoderErrorOr<void> Decoder::predict_inter_block(u8 plane, u8 ref_list, u32 blo
if (m_parser->m_frame_store[reference_frame_index][plane].is_empty())
return DecoderError::format(DecoderErrorCategory::Corrupted, "Attempted to use reference frame {} that has not been saved", reference_frame_index);
auto ref_frame_size = m_parser->m_ref_frame_size[reference_frame_index];
- auto double_frame_size = m_parser->m_frame_size.scaled_by(2);
+ auto double_frame_size = block_context.frame_context.size().scaled_by(2);
if (double_frame_size.width() < ref_frame_size.width() || double_frame_size.height() < ref_frame_size.height())
return DecoderError::format(DecoderErrorCategory::Corrupted, "Inter frame size is too small relative to reference frame {}", reference_frame_index);
- if (!ref_frame_size.scaled_by(16).contains(m_parser->m_frame_size))
+ if (!ref_frame_size.scaled_by(16).contains(block_context.frame_context.size()))
return DecoderError::format(DecoderErrorCategory::Corrupted, "Inter frame size is too large relative to reference frame {}", reference_frame_index);
// FIXME: Convert all the operations in this function to vector operations supported by
@@ -804,8 +804,8 @@ DecoderErrorOr<void> Decoder::predict_inter_block(u8 plane, u8 ref_list, u32 blo
// A variable yScale is set equal to (RefFrameHeight[ refIdx ] << REF_SCALE_SHIFT) / FrameHeight.
// (xScale and yScale specify the size of the reference frame relative to the current frame in units where 16 is
// equivalent to the reference frame having the same size.)
- i32 x_scale = (ref_frame_size.width() << REF_SCALE_SHIFT) / m_parser->m_frame_size.width();
- i32 y_scale = (ref_frame_size.height() << REF_SCALE_SHIFT) / m_parser->m_frame_size.height();
+ i32 x_scale = (ref_frame_size.width() << REF_SCALE_SHIFT) / block_context.frame_context.size().width();
+ i32 y_scale = (ref_frame_size.height() << REF_SCALE_SHIFT) / block_context.frame_context.size().height();
// The variable baseX is set equal to (x * xScale) >> REF_SCALE_SHIFT.
// The variable baseY is set equal to (y * yScale) >> REF_SCALE_SHIFT.
@@ -923,7 +923,7 @@ DecoderErrorOr<void> Decoder::predict_inter_block(u8 plane, u8 ref_list, u32 blo
return {};
}
-DecoderErrorOr<void> Decoder::predict_inter(u8 plane, u32 block_row, u32 block_column, u32 x, u32 y, u32 width, u32 height, u32 block_index)
+DecoderErrorOr<void> Decoder::predict_inter(u8 plane, BlockContext const& block_context, u32 x, u32 y, u32 width, u32 height, u32 block_index)
{
// The inter prediction process is invoked for inter coded blocks. When MiSize is smaller than BLOCK_8X8, the
// prediction is done with a granularity of 4x4 samples, otherwise the whole plane is predicted at the same time.
@@ -942,7 +942,7 @@ DecoderErrorOr<void> Decoder::predict_inter(u8 plane, u32 block_row, u32 block_c
// 2. through 5.
Array<u16, maximum_block_size> predicted_buffer;
auto predicted_span = predicted_buffer.span().trim(width * height);
- TRY(predict_inter_block(plane, 0, block_row, block_column, x, y, width, height, block_index, predicted_span));
+ TRY(predict_inter_block(plane, block_context, 0, block_context.row, block_context.column, x, y, width, height, block_index, predicted_span));
auto predicted_buffer_at = [&](Span<u16> buffer, u32 row, u32 column) -> u16& {
return buffer[row * width + column];
};
@@ -952,8 +952,8 @@ DecoderErrorOr<void> Decoder::predict_inter(u8 plane, u32 block_row, u32 block_c
// The inter predicted samples are then derived as follows:
auto& frame_buffer = get_output_buffer(plane);
VERIFY(!frame_buffer.is_empty());
- auto frame_width = (m_parser->m_mi_cols * 8u) >> (plane > 0 ? m_parser->m_subsampling_x : false);
- auto frame_height = (m_parser->m_mi_rows * 8u) >> (plane > 0 ? m_parser->m_subsampling_y : false);
+ auto frame_width = (block_context.frame_context.columns() * 8u) >> (plane > 0 ? m_parser->m_subsampling_x : false);
+ auto frame_height = (block_context.frame_context.rows() * 8u) >> (plane > 0 ? m_parser->m_subsampling_y : false);
auto frame_buffer_at = [&](u32 row, u32 column) -> u16& {
return frame_buffer[row * frame_width + column];
};
@@ -976,7 +976,7 @@ DecoderErrorOr<void> Decoder::predict_inter(u8 plane, u32 block_row, u32 block_c
// for i = 0..h-1 and j = 0..w-1.
Array<u16, maximum_block_size> second_predicted_buffer;
auto second_predicted_span = second_predicted_buffer.span().trim(width * height);
- TRY(predict_inter_block(plane, 1, block_row, block_column, x, y, width, height, block_index, second_predicted_span));
+ TRY(predict_inter_block(plane, block_context, 1, block_context.row, block_context.column, x, y, width, height, block_index, second_predicted_span));
for (auto i = 0u; i < height_in_frame_buffer; i++) {
for (auto j = 0u; j < width_in_frame_buffer; j++)
@@ -1055,7 +1055,7 @@ u16 Decoder::get_ac_quant(u8 plane)
return ac_q(static_cast<u8>(get_qindex() + offset));
}
-DecoderErrorOr<void> Decoder::reconstruct(u8 plane, u32 transform_block_x, u32 transform_block_y, TXSize transform_block_size)
+DecoderErrorOr<void> Decoder::reconstruct(u8 plane, BlockContext const& block_context, u32 transform_block_x, u32 transform_block_y, TXSize transform_block_size)
{
// 8.6.2 Reconstruct process
@@ -1096,8 +1096,8 @@ DecoderErrorOr<void> Decoder::reconstruct(u8 plane, u32 transform_block_x, u32 t
auto& current_buffer = get_output_buffer(plane);
auto subsampling_x = (plane > 0 ? m_parser->m_subsampling_x : 0);
auto subsampling_y = (plane > 0 ? m_parser->m_subsampling_y : 0);
- auto frame_width = (m_parser->m_mi_cols * 8) >> subsampling_x;
- auto frame_height = (m_parser->m_mi_rows * 8) >> subsampling_y;
+ auto frame_width = (block_context.frame_context.columns() * 8) >> subsampling_x;
+ auto frame_height = (block_context.frame_context.rows() * 8) >> subsampling_y;
auto width_in_frame_buffer = min(block_size, frame_width - transform_block_x);
auto height_in_frame_buffer = min(block_size, frame_height - transform_block_y);
@@ -1742,7 +1742,7 @@ DecoderErrorOr<void> Decoder::inverse_transform_2d(Span<Intermediate> dequantize
return {};
}
-DecoderErrorOr<void> Decoder::update_reference_frames()
+DecoderErrorOr<void> Decoder::update_reference_frames(FrameContext const& frame_context)
{
// This process is invoked as the final step in decoding a frame.
// The inputs to this process are the samples in the current frame CurrFrame[ plane ][ x ][ y ].
@@ -1756,7 +1756,7 @@ DecoderErrorOr<void> Decoder::update_reference_frames()
if ((refresh_flags & 1) != 0) {
// − RefFrameWidth[ i ] is set equal to FrameWidth.
// − RefFrameHeight[ i ] is set equal to FrameHeight.
- m_parser->m_ref_frame_size[i] = m_parser->m_frame_size;
+ m_parser->m_ref_frame_size[i] = frame_context.size();
// − RefSubsamplingX[ i ] is set equal to subsampling_x.
m_parser->m_ref_subsampling_x[i] = m_parser->m_subsampling_x;
// − RefSubsamplingY[ i ] is set equal to subsampling_y.
@@ -1773,9 +1773,9 @@ DecoderErrorOr<void> Decoder::update_reference_frames()
// FIXME: Frame width is not equal to the buffer's stride. If we store the stride of the buffer with the reference
// frame, we can just copy the framebuffer data instead. Alternatively, we should crop the output framebuffer.
for (auto plane = 0u; plane < 3; plane++) {
- auto width = m_parser->m_frame_size.width();
- auto height = m_parser->m_frame_size.height();
- auto stride = m_parser->m_mi_cols * 8;
+ auto width = frame_context.size().width();
+ auto height = frame_context.size().height();
+ auto stride = frame_context.columns() * 8;
if (plane > 0) {
width = (width + m_parser->m_subsampling_x) >> m_parser->m_subsampling_x;
@@ -1800,8 +1800,8 @@ DecoderErrorOr<void> Decoder::update_reference_frames()
}
// 2. If show_existing_frame is equal to 0, the following applies:
- if (!m_parser->m_show_existing_frame) {
- DECODER_TRY_ALLOC(m_parser->m_previous_block_contexts.try_resize_to_match_other_vector2d(m_parser->m_frame_block_contexts));
+ if (!frame_context.shows_existing_frame()) {
+ DECODER_TRY_ALLOC(m_parser->m_previous_block_contexts.try_resize_to_match_other_vector2d(frame_context.block_contexts()));
// − PrevRefFrames[ row ][ col ][ list ] is set equal to RefFrames[ row ][ col ][ list ] for row = 0..MiRows-1,
// for col = 0..MiCols-1, for list = 0..1.
// − PrevMvs[ row ][ col ][ list ][ comp ] is set equal to Mvs[ row ][ col ][ list ][ comp ] for row = 0..MiRows-1,
@@ -1812,8 +1812,8 @@ DecoderErrorOr<void> Decoder::update_reference_frames()
// − show_existing_frame is equal to 0,
// − segmentation_enabled is equal to 1,
// − segmentation_update_map is equal to 1.
- bool keep_segment_ids = !m_parser->m_show_existing_frame && m_parser->m_segmentation_enabled && m_parser->m_segmentation_update_map;
- m_parser->m_frame_block_contexts.copy_to(m_parser->m_previous_block_contexts, [keep_segment_ids](FrameBlockContext context) {
+ bool keep_segment_ids = !frame_context.shows_existing_frame() && m_parser->m_segmentation_enabled && m_parser->m_segmentation_update_map;
+ frame_context.block_contexts().copy_to(m_parser->m_previous_block_contexts, [keep_segment_ids](FrameBlockContext context) {
auto persistent_context = PersistentBlockContext(context);
if (!keep_segment_ids)
persistent_context.segment_id = 0;
diff --git a/Userland/Libraries/LibVideo/VP9/Decoder.h b/Userland/Libraries/LibVideo/VP9/Decoder.h
index 1a3506f33d..94543a8ee9 100644
--- a/Userland/Libraries/LibVideo/VP9/Decoder.h
+++ b/Userland/Libraries/LibVideo/VP9/Decoder.h
@@ -42,9 +42,9 @@ private:
static constexpr size_t maximum_transform_size = 32ULL * 32ULL;
DecoderErrorOr<void> decode_frame(ReadonlyBytes);
- DecoderErrorOr<void> create_video_frame();
+ DecoderErrorOr<void> create_video_frame(FrameContext const&);
- DecoderErrorOr<void> allocate_buffers();
+ DecoderErrorOr<void> allocate_buffers(FrameContext const&);
Vector<Intermediate>& get_temp_buffer(u8 plane);
Vector<u16>& get_output_buffer(u8 plane);
@@ -58,18 +58,18 @@ private:
/* (8.5) Prediction Processes */
// (8.5.1) Intra prediction process
- DecoderErrorOr<void> predict_intra(u8 plane, u32 x, u32 y, bool have_left, bool have_above, bool not_on_right, TXSize tx_size, u32 block_index);
+ DecoderErrorOr<void> predict_intra(u8 plane, BlockContext const& block_context, u32 x, u32 y, bool have_left, bool have_above, bool not_on_right, TXSize tx_size, u32 block_index);
// (8.5.1) Inter prediction process
- DecoderErrorOr<void> predict_inter(u8 plane, u32 block_row, u32 block_column, u32 x, u32 y, u32 width, u32 height, u32 block_index);
+ DecoderErrorOr<void> predict_inter(u8 plane, BlockContext const& block_context, u32 x, u32 y, u32 width, u32 height, u32 block_index);
// (8.5.2.1) Motion vector selection process
- MotionVector select_motion_vector(u8 plane, u8 ref_list, u32 block_index);
+ MotionVector select_motion_vector(u8 plane, BlockContext const&, u8 ref_list, u32 block_index);
// (8.5.2.2) Motion vector clamping process
- MotionVector clamp_motion_vector(u8 plane, u32 block_row, u32 block_column, MotionVector vector);
+ MotionVector clamp_motion_vector(u8 plane, BlockContext const&, u32 block_row, u32 block_column, MotionVector vector);
// (8.5.2.3) Motion vector scaling process
DecoderErrorOr<MotionVector> scale_motion_vector(u8 plane, u8 ref_list, u32 x, u32 y, MotionVector vector);
// From (8.5.1) Inter prediction process, steps 2-5
- DecoderErrorOr<void> predict_inter_block(u8 plane, u8 ref_list, u32 block_row, u32 block_column, u32 x, u32 y, u32 width, u32 height, u32 block_index, Span<u16> block_buffer);
+ DecoderErrorOr<void> predict_inter_block(u8 plane, BlockContext const&, u8 ref_list, u32 block_row, u32 block_column, u32 x, u32 y, u32 width, u32 height, u32 block_index, Span<u16> block_buffer);
/* (8.6) Reconstruction and Dequantization */
@@ -84,7 +84,7 @@ private:
u16 get_ac_quant(u8 plane);
// (8.6.2) Reconstruct process
- DecoderErrorOr<void> reconstruct(u8 plane, u32 transform_block_x, u32 transform_block_y, TXSize transform_block_size);
+ DecoderErrorOr<void> reconstruct(u8 plane, BlockContext const&, u32 transform_block_x, u32 transform_block_y, TXSize transform_block_size);
// (8.7) Inverse transform process
DecoderErrorOr<void> inverse_transform_2d(Span<Intermediate> dequantized, u8 log2_of_block_size);
@@ -140,7 +140,7 @@ private:
inline DecoderErrorOr<void> inverse_asymmetric_discrete_sine_transform(Span<Intermediate> data, u8 log2_of_block_size);
/* (8.10) Reference Frame Update Process */
- DecoderErrorOr<void> update_reference_frames();
+ DecoderErrorOr<void> update_reference_frames(FrameContext const&);
inline CodingIndependentCodePoints get_cicp_color_space();
diff --git a/Userland/Libraries/LibVideo/VP9/Parser.cpp b/Userland/Libraries/LibVideo/VP9/Parser.cpp
index da8fb7311b..89cb7ef8ef 100644
--- a/Userland/Libraries/LibVideo/VP9/Parser.cpp
+++ b/Userland/Libraries/LibVideo/VP9/Parser.cpp
@@ -79,30 +79,34 @@ Vector<size_t> Parser::parse_superframe_sizes(ReadonlyBytes frame_data)
}
/* (6.1) */
-DecoderErrorOr<void> Parser::parse_frame(ReadonlyBytes frame_data)
+DecoderErrorOr<FrameContext> Parser::parse_frame(ReadonlyBytes frame_data)
{
m_bit_stream = make<BitStream>(frame_data.data(), frame_data.size());
m_syntax_element_counter = make<SyntaxElementCounter>();
- TRY(uncompressed_header());
+ auto frame_context = TRY(uncompressed_header());
if (!trailing_bits())
return DecoderError::corrupted("Trailing bits were non-zero"sv);
- if (m_header_size_in_bytes == 0)
+ // 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_syntax_element_counter->clear_counts();
- TRY_READ(m_bit_stream->init_bool(m_header_size_in_bytes));
+ TRY_READ(m_bit_stream->init_bool(frame_context.header_size_in_bytes));
TRY(compressed_header());
TRY_READ(m_bit_stream->exit_bool());
- TRY(m_decoder.allocate_buffers());
+ TRY(m_decoder.allocate_buffers(frame_context));
- TRY(decode_tiles());
+ TRY(decode_tiles(frame_context));
TRY(refresh_probs());
- return {};
+ m_previous_frame_size = frame_context.size();
+ m_previous_show_frame = m_show_frame;
+
+ return frame_context;
}
bool Parser::trailing_bits()
@@ -144,23 +148,25 @@ DecoderErrorOr<ColorRange> Parser::read_color_range()
}
/* (6.2) */
-DecoderErrorOr<void> Parser::uncompressed_header()
+DecoderErrorOr<FrameContext> Parser::uncompressed_header()
{
+ FrameContext frame_context;
+
auto frame_marker = TRY_READ(m_bit_stream->read_bits(2));
if (frame_marker != 2)
return DecoderError::corrupted("uncompressed_header: Frame marker must be 2"sv);
+
auto profile_low_bit = TRY_READ(m_bit_stream->read_bit());
auto profile_high_bit = TRY_READ(m_bit_stream->read_bit());
- m_profile = (profile_high_bit << 1u) + profile_low_bit;
- if (m_profile == 3 && TRY_READ(m_bit_stream->read_bit()))
+ frame_context.profile = (profile_high_bit << 1u) + profile_low_bit;
+ if (frame_context.profile == 3 && TRY_READ(m_bit_stream->read_bit()))
return DecoderError::corrupted("uncompressed_header: Profile 3 reserved bit was non-zero"sv);
- m_show_existing_frame = TRY_READ(m_bit_stream->read_bit());
- if (m_show_existing_frame) {
- m_frame_to_show_map_index = TRY_READ(m_bit_stream->read_bits(3));
- m_header_size_in_bytes = 0;
+
+ if (TRY_READ(m_bit_stream->read_bit())) {
m_refresh_frame_flags = 0;
m_loop_filter_level = 0;
- return {};
+ 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;
@@ -168,11 +174,14 @@ DecoderErrorOr<void> Parser::uncompressed_header()
m_show_frame = TRY_READ(m_bit_stream->read_bit());
m_error_resilient_mode = TRY_READ(m_bit_stream->read_bit());
+ Gfx::Size<u32> frame_size;
+ Gfx::Size<u32> render_size;
+
if (m_frame_type == KeyFrame) {
TRY(frame_sync_code());
- TRY(color_config());
- m_frame_size = TRY(frame_size());
- m_render_size = TRY(render_size(m_frame_size));
+ TRY(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 {
@@ -186,8 +195,8 @@ DecoderErrorOr<void> Parser::uncompressed_header()
if (m_frame_is_intra) {
TRY(frame_sync_code());
- if (m_profile > 0) {
- TRY(color_config());
+ if (frame_context.profile > 0) {
+ TRY(color_config(frame_context));
} else {
m_color_space = Bt601;
m_subsampling_x = true;
@@ -196,22 +205,24 @@ DecoderErrorOr<void> Parser::uncompressed_header()
}
m_refresh_frame_flags = TRY_READ(m_bit_stream->read_f8());
- m_frame_size = TRY(frame_size());
- m_render_size = TRY(render_size(m_frame_size));
+ 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());
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());
}
- m_frame_size = TRY(frame_size_with_refs());
- m_render_size = TRY(render_size(m_frame_size));
+ frame_size = TRY(parse_frame_size_with_refs());
+ render_size = TRY(parse_render_size(frame_size));
m_allow_high_precision_mv = TRY_READ(m_bit_stream->read_bit());
TRY(read_interpolation_filter());
}
}
- compute_image_size();
+ 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());
@@ -237,11 +248,11 @@ DecoderErrorOr<void> Parser::uncompressed_header()
TRY(loop_filter_params());
TRY(quantization_params());
TRY(segmentation_params());
- TRY(tile_info());
+ TRY(tile_info(frame_context));
- m_header_size_in_bytes = TRY_READ(m_bit_stream->read_f16());
+ frame_context.header_size_in_bytes = TRY_READ(m_bit_stream->read_f16());
- return {};
+ return frame_context;
}
DecoderErrorOr<void> Parser::frame_sync_code()
@@ -255,9 +266,9 @@ DecoderErrorOr<void> Parser::frame_sync_code()
return {};
}
-DecoderErrorOr<void> Parser::color_config()
+DecoderErrorOr<void> Parser::color_config(FrameContext const& frame_context)
{
- if (m_profile >= 2) {
+ if (frame_context.profile >= 2) {
m_bit_depth = TRY_READ(m_bit_stream->read_bit()) ? 12 : 10;
} else {
m_bit_depth = 8;
@@ -269,7 +280,7 @@ DecoderErrorOr<void> Parser::color_config()
if (color_space != RGB) {
m_color_range = TRY(read_color_range());
- if (m_profile == 1 || m_profile == 3) {
+ if (frame_context.profile == 1 || frame_context.profile == 3) {
m_subsampling_x = TRY_READ(m_bit_stream->read_bit());
m_subsampling_y = TRY_READ(m_bit_stream->read_bit());
if (TRY_READ(m_bit_stream->read_bit()))
@@ -280,7 +291,7 @@ DecoderErrorOr<void> Parser::color_config()
}
} else {
m_color_range = ColorRange::Full;
- if (m_profile == 1 || m_profile == 3) {
+ if (frame_context.profile == 1 || frame_context.profile == 3) {
m_subsampling_x = false;
m_subsampling_y = false;
if (TRY_READ(m_bit_stream->read_bit()))
@@ -290,19 +301,19 @@ DecoderErrorOr<void> Parser::color_config()
return {};
}
-DecoderErrorOr<Gfx::Size<u32>> Parser::frame_size()
+DecoderErrorOr<Gfx::Size<u32>> Parser::parse_frame_size()
{
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::render_size(Gfx::Size<u32> frame_size)
+DecoderErrorOr<Gfx::Size<u32>> Parser::parse_render_size(Gfx::Size<u32> frame_size)
{
if (!TRY_READ(m_bit_stream->read_bit()))
return frame_size;
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::frame_size_with_refs()
+DecoderErrorOr<Gfx::Size<u32>> Parser::parse_frame_size_with_refs()
{
Optional<Gfx::Size<u32>> size;
for (auto frame_index : m_ref_frame_idx) {
@@ -315,29 +326,23 @@ DecoderErrorOr<Gfx::Size<u32>> Parser::frame_size_with_refs()
if (size.has_value())
return size.value();
- return TRY(frame_size());
+ return TRY(parse_frame_size());
}
-void Parser::compute_image_size()
+DecoderErrorOr<void> Parser::compute_image_size(FrameContext& frame_context)
{
- auto new_cols = (m_frame_size.width() + 7u) >> 3u;
- auto new_rows = (m_frame_size.height() + 7u) >> 3u;
-
// 7.2.6 Compute image size semantics
// When compute_image_size is invoked, the following ordered steps occur:
// 1. If this is the first time compute_image_size is invoked, or if either FrameWidth or FrameHeight have
// changed in value compared to the previous time this function was invoked, then the segmentation map is
// cleared to all zeros by setting SegmentId[ row ][ col ] equal to 0 for row = 0..MiRows-1 and col =
// 0..MiCols-1.
- bool first_invoke = !m_mi_cols && !m_mi_rows;
- bool same_size = m_mi_cols == new_cols && m_mi_rows == new_rows;
- if (first_invoke || !same_size) {
- // FIXME: Does this ever do anything? Segment IDs are already reset every frame. It's also suspicious
- // that spec refers to this as SegmentId rather than SegmentIds (plural). Is this supposed to
- // refer to PrevSegmentIds?
- for (size_t i = 0; i < m_frame_block_contexts.size(); i++)
- m_frame_block_contexts[i].segment_id = 0;
- }
+ // FIXME: What does this mean? SegmentIds is scoped to one frame, so it will not contain values here. It's
+ // also suspicious that spec refers to this as SegmentId rather than SegmentIds (plural). Is this
+ // supposed to refer to PrevSegmentIds?
+ bool first_invoke = m_is_first_compute_image_size_invoke;
+ m_is_first_compute_image_size_invoke = false;
+ bool same_size = m_previous_frame_size == frame_context.size();
// 2. The variable UsePrevFrameMvs is set equal to 1 if all of the following conditions are true:
// a. This is not the first time compute_image_size is invoked.
@@ -347,13 +352,8 @@ void Parser::compute_image_size()
// 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_prev_show_frame && !m_error_resilient_mode && !m_frame_is_intra;
- m_prev_show_frame = m_show_frame;
-
- m_mi_cols = new_cols;
- m_mi_rows = new_rows;
- m_sb64_cols = (m_mi_cols + 7u) >> 3u;
- m_sb64_rows = (m_mi_rows + 7u) >> 3u;
+ m_use_prev_frame_mvs = !first_invoke && same_size && m_previous_show_frame && !m_error_resilient_mode && !m_frame_is_intra;
+ return {};
}
DecoderErrorOr<void> Parser::read_interpolation_filter()
@@ -452,10 +452,11 @@ DecoderErrorOr<u8> Parser::read_prob()
return 255;
}
-DecoderErrorOr<void> Parser::tile_info()
+DecoderErrorOr<void> Parser::tile_info(FrameContext& frame_context)
{
- auto min_log2_tile_cols = calc_min_log2_tile_cols();
- auto max_log2_tile_cols = calc_max_log2_tile_cols();
+ auto superblock_columns = frame_context.superblock_columns();
+ auto min_log2_tile_cols = calc_min_log2_tile_cols(superblock_columns);
+ auto max_log2_tile_cols = calc_max_log2_tile_cols(superblock_columns);
m_tile_cols_log2 = min_log2_tile_cols;
while (m_tile_cols_log2 < max_log2_tile_cols) {
if (TRY_READ(m_bit_stream->read_bit()))
@@ -470,18 +471,18 @@ DecoderErrorOr<void> Parser::tile_info()
return {};
}
-u16 Parser::calc_min_log2_tile_cols()
+u16 Parser::calc_min_log2_tile_cols(u32 superblock_columns)
{
auto min_log_2 = 0u;
- while ((u32)(MAX_TILE_WIDTH_B64 << min_log_2) < m_sb64_cols)
+ while ((u32)(MAX_TILE_WIDTH_B64 << min_log_2) < superblock_columns)
min_log_2++;
return min_log_2;
}
-u16 Parser::calc_max_log2_tile_cols()
+u16 Parser::calc_max_log2_tile_cols(u32 superblock_columns)
{
u16 max_log_2 = 1;
- while ((m_sb64_cols >> max_log_2) >= MIN_TILE_WIDTH_B64)
+ while ((superblock_columns >> max_log_2) >= MIN_TILE_WIDTH_B64)
max_log_2++;
return max_log_2 - 1;
}
@@ -494,7 +495,7 @@ void Parser::setup_past_independence()
m_feature_enabled[i][j] = false;
}
}
- m_previous_block_contexts.reset();
+ m_previous_block_contexts.reset();
m_segmentation_abs_or_delta_update = false;
m_loop_filter_delta_enabled = true;
m_loop_filter_ref_deltas[IntraFrame] = 1;
@@ -802,18 +803,12 @@ void Parser::setup_compound_reference_mode()
}
}
-DecoderErrorOr<void> Parser::allocate_tile_data()
-{
- DECODER_TRY_ALLOC(m_frame_block_contexts.try_resize(m_mi_rows, m_mi_cols));
- return {};
-}
-
-DecoderErrorOr<void> Parser::decode_tiles()
+DecoderErrorOr<void> Parser::decode_tiles(FrameContext& frame_context)
{
auto tile_cols = 1 << m_tile_cols_log2;
auto tile_rows = 1 << m_tile_rows_log2;
- TRY(allocate_tile_data());
- clear_above_context();
+ clear_above_context(frame_context);
+
for (auto tile_row = 0; tile_row < tile_rows; tile_row++) {
for (auto tile_col = 0; tile_col < tile_cols; tile_col++) {
auto last_tile = (tile_row == tile_rows - 1) && (tile_col == tile_cols - 1);
@@ -823,12 +818,15 @@ DecoderErrorOr<void> Parser::decode_tiles()
else
tile_size = TRY_READ(m_bit_stream->read_bits(32));
- m_mi_row_start = get_tile_offset(tile_row, m_mi_rows, m_tile_rows_log2);
- m_mi_row_end = get_tile_offset(tile_row + 1, m_mi_rows, m_tile_rows_log2);
- m_mi_col_start = get_tile_offset(tile_col, m_mi_cols, m_tile_cols_log2);
- m_mi_col_end = get_tile_offset(tile_col + 1, m_mi_cols, m_tile_cols_log2);
+ auto rows_start = get_tile_offset(tile_row, frame_context.rows(), m_tile_rows_log2);
+ auto rows_end = get_tile_offset(tile_row + 1, frame_context.rows(), m_tile_rows_log2);
+ auto columns_start = get_tile_offset(tile_col, frame_context.columns(), m_tile_cols_log2);
+ auto columns_end = get_tile_offset(tile_col + 1, frame_context.columns(), m_tile_cols_log2);
+
+ auto tile_context = TileContext(frame_context, rows_start, rows_end, columns_start, columns_end);
+
TRY_READ(m_bit_stream->init_bool(tile_size));
- TRY(decode_tile());
+ TRY(decode_tile(tile_context));
TRY_READ(m_bit_stream->exit_bool());
}
}
@@ -851,12 +849,12 @@ void Parser::clear_context(Vector<Vector<T>>& context, size_t outer_size, size_t
clear_context(sub_vector, inner_size);
}
-void Parser::clear_above_context()
+void Parser::clear_above_context(FrameContext& frame_context)
{
for (auto i = 0u; i < m_above_nonzero_context.size(); i++)
- clear_context(m_above_nonzero_context[i], 2 * m_mi_cols);
- clear_context(m_above_seg_pred_context, m_mi_cols);
- clear_context(m_above_partition_context, m_sb64_cols * 8);
+ clear_context(m_above_nonzero_context[i], 2 * frame_context.columns());
+ clear_context(m_above_seg_pred_context, frame_context.columns());
+ clear_context(m_above_partition_context, frame_context.superblock_columns() * 8);
}
u32 Parser::get_tile_offset(u32 tile_num, u32 mis, u32 tile_size_log2)
@@ -866,51 +864,51 @@ u32 Parser::get_tile_offset(u32 tile_num, u32 mis, u32 tile_size_log2)
return min(offset, mis);
}
-DecoderErrorOr<void> Parser::decode_tile()
+DecoderErrorOr<void> Parser::decode_tile(TileContext& tile_context)
{
- for (auto row = m_mi_row_start; row < m_mi_row_end; row += 8) {
- clear_left_context();
- for (auto col = m_mi_col_start; col < m_mi_col_end; col += 8) {
- TRY(decode_partition(row, col, Block_64x64));
+ for (auto row = tile_context.rows_start; row < tile_context.rows_end; row += 8) {
+ clear_left_context(tile_context);
+ for (auto col = tile_context.columns_start; col < tile_context.columns_end; col += 8) {
+ TRY(decode_partition(tile_context, row, col, Block_64x64));
}
}
return {};
}
-void Parser::clear_left_context()
+void Parser::clear_left_context(TileContext& tile_context)
{
for (auto i = 0u; i < m_left_nonzero_context.size(); i++)
- clear_context(m_left_nonzero_context[i], 2 * m_mi_rows);
- clear_context(m_left_seg_pred_context, m_mi_rows);
- clear_context(m_left_partition_context, m_sb64_rows * 8);
+ clear_context(m_left_nonzero_context[i], 2 * tile_context.frame_context.rows());
+ clear_context(m_left_seg_pred_context, tile_context.frame_context.rows());
+ clear_context(m_left_partition_context, tile_context.frame_context.superblock_rows() * 8);
}
-DecoderErrorOr<void> Parser::decode_partition(u32 row, u32 column, BlockSubsize subsize)
+DecoderErrorOr<void> Parser::decode_partition(TileContext& tile_context, u32 row, u32 column, BlockSubsize subsize)
{
- if (row >= m_mi_rows || column >= m_mi_cols)
+ if (row >= tile_context.frame_context.rows() || column >= tile_context.frame_context.columns())
return {};
u8 num_8x8 = num_8x8_blocks_wide_lookup[subsize];
auto half_block_8x8 = num_8x8 >> 1;
- bool has_rows = (row + half_block_8x8) < m_mi_rows;
- bool has_cols = (column + half_block_8x8) < m_mi_cols;
+ 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 child_subsize = subsize_lookup[partition][subsize];
if (child_subsize < Block_8x8 || partition == PartitionNone) {
- TRY(decode_block(row, column, child_subsize));
+ TRY(decode_block(tile_context, row, column, child_subsize));
} else if (partition == PartitionHorizontal) {
- TRY(decode_block(row, column, child_subsize));
+ TRY(decode_block(tile_context, row, column, child_subsize));
if (has_rows)
- TRY(decode_block(row + half_block_8x8, column, child_subsize));
+ TRY(decode_block(tile_context, row + half_block_8x8, column, child_subsize));
} else if (partition == PartitionVertical) {
- TRY(decode_block(row, column, child_subsize));
+ TRY(decode_block(tile_context, row, column, child_subsize));
if (has_cols)
- TRY(decode_block(row, column + half_block_8x8, child_subsize));
+ TRY(decode_block(tile_context, row, column + half_block_8x8, child_subsize));
} else {
- TRY(decode_partition(row, column, child_subsize));
- TRY(decode_partition(row, column + half_block_8x8, child_subsize));
- TRY(decode_partition(row + half_block_8x8, column, child_subsize));
- TRY(decode_partition(row + half_block_8x8, column + half_block_8x8, child_subsize));
+ TRY(decode_partition(tile_context, row, column, child_subsize));
+ TRY(decode_partition(tile_context, row, column + half_block_8x8, child_subsize));
+ TRY(decode_partition(tile_context, row + half_block_8x8, column, child_subsize));
+ TRY(decode_partition(tile_context, row + half_block_8x8, column + half_block_8x8, child_subsize));
}
if (subsize == Block_8x8 || partition != PartitionSplit) {
auto above_context = 15 >> b_width_log2_lookup[child_subsize];
@@ -923,65 +921,62 @@ DecoderErrorOr<void> Parser::decode_partition(u32 row, u32 column, BlockSubsize
return {};
}
-size_t Parser::get_image_index(u32 row, u32 column) const
+size_t Parser::get_image_index(FrameContext const& frame_context, u32 row, u32 column) const
{
- VERIFY(row < m_mi_rows && column < m_mi_cols);
- return row * m_mi_cols + column;
+ VERIFY(row < frame_context.rows() && column < frame_context.columns());
+ return row * frame_context.columns() + column;
}
-DecoderErrorOr<void> Parser::decode_block(u32 row, u32 column, BlockSubsize subsize)
+DecoderErrorOr<void> Parser::decode_block(TileContext& tile_context, u32 row, u32 column, BlockSubsize subsize)
{
- m_mi_size = subsize;
- auto above_context = row > 0 ? m_frame_block_contexts.at(row - 1, column) : FrameBlockContext();
- auto left_context = column > m_mi_col_start ? m_frame_block_contexts.at(row, column - 1) : FrameBlockContext();
- TRY(mode_info(row, column, above_context, left_context));
- auto had_residual_tokens = TRY(residual(row, column, above_context.is_available, left_context.is_available));
+ auto above_context = row > 0 ? tile_context.frame_block_contexts().at(row - 1, column) : FrameBlockContext();
+ auto left_context = column > tile_context.columns_start ? tile_context.frame_block_contexts().at(row, column - 1) : FrameBlockContext();
+ auto block_context = BlockContext(tile_context, row, column, subsize);
+
+ TRY(mode_info(block_context, above_context, left_context));
+ auto had_residual_tokens = TRY(residual(block_context, above_context.is_available, left_context.is_available));
if (m_is_inter && subsize >= Block_8x8 && !had_residual_tokens)
m_skip = true;
- // Spec doesn't specify whether it might index outside the frame here, but it seems that it can. Ensure that we don't
- // write out of bounds. This check seems consistent with libvpx.
- // See here:
- // https://github.com/webmproject/libvpx/blob/705bf9de8c96cfe5301451f1d7e5c90a41c64e5f/vp9/decoder/vp9_decodeframe.c#L917
- auto maximum_block_y = min<u32>(num_8x8_blocks_high_lookup[subsize], m_mi_rows - row);
- auto maximum_block_x = min<u32>(num_8x8_blocks_wide_lookup[subsize], m_mi_cols - column);
-
- for (size_t y = 0; y < maximum_block_y; y++) {
- for (size_t x = 0; x < maximum_block_x; x++)
- m_frame_block_contexts.at(row + y, column + x) = FrameBlockContext { true, m_skip, m_tx_size, m_y_mode, m_block_sub_modes, m_interp_filter, m_ref_frame, m_block_mvs, m_segment_id };
+ for (size_t y = 0; y < block_context.contexts_view.height(); y++) {
+ for (size_t x = 0; x < block_context.contexts_view.width(); x++) {
+ auto sub_block_context = FrameBlockContext { true, m_skip, m_tx_size, m_y_mode, m_block_sub_modes, m_interp_filter, m_ref_frame, m_block_mvs, m_segment_id };
+ block_context.contexts_view.at(y, x) = sub_block_context;
+ VERIFY(block_context.frame_block_contexts().at(row + y, column + x).tx_size == sub_block_context.tx_size);
+ }
}
return {};
}
-DecoderErrorOr<void> Parser::mode_info(u32 row, u32 column, FrameBlockContext above_context, FrameBlockContext left_context)
+DecoderErrorOr<void> Parser::mode_info(BlockContext& block_context, FrameBlockContext above_context, FrameBlockContext left_context)
{
if (m_frame_is_intra)
- TRY(intra_frame_mode_info(above_context, left_context));
+ TRY(intra_frame_mode_info(block_context, above_context, left_context));
else
- TRY(inter_frame_mode_info(row, column, above_context, left_context));
+ TRY(inter_frame_mode_info(block_context, above_context, left_context));
return {};
}
-DecoderErrorOr<void> Parser::intra_frame_mode_info(FrameBlockContext above_context, FrameBlockContext left_context)
+DecoderErrorOr<void> Parser::intra_frame_mode_info(BlockContext& block_context, FrameBlockContext above_context, FrameBlockContext left_context)
{
TRY(intra_segment_id());
TRY(read_skip(above_context, left_context));
- TRY(read_tx_size(above_context, left_context, true));
+ TRY(read_tx_size(block_context, above_context, left_context, true));
m_ref_frame[0] = IntraFrame;
m_ref_frame[1] = None;
m_is_inter = false;
// FIXME: This if statement is also present in parse_default_intra_mode. The selection of parameters for
// the probability table lookup should be inlined here.
- if (m_mi_size >= Block_8x8) {
- m_y_mode = TRY_READ(TreeParser::parse_default_intra_mode(*m_bit_stream, *m_probability_tables, m_mi_size, above_context, left_context, m_block_sub_modes, 0, 0));
+ if (block_context.size >= Block_8x8) {
+ m_y_mode = TRY_READ(TreeParser::parse_default_intra_mode(*m_bit_stream, *m_probability_tables, block_context.size, above_context, left_context, m_block_sub_modes, 0, 0));
for (auto& block_sub_mode : m_block_sub_modes)
block_sub_mode = m_y_mode;
} else {
- m_num_4x4_w = num_4x4_blocks_wide_lookup[m_mi_size];
- m_num_4x4_h = num_4x4_blocks_high_lookup[m_mi_size];
+ m_num_4x4_w = num_4x4_blocks_wide_lookup[block_context.size];
+ m_num_4x4_h = num_4x4_blocks_high_lookup[block_context.size];
for (auto idy = 0; idy < 2; idy += m_num_4x4_h) {
for (auto idx = 0; idx < 2; idx += m_num_4x4_w) {
- auto sub_mode = TRY_READ(TreeParser::parse_default_intra_mode(*m_bit_stream, *m_probability_tables, m_mi_size, above_context, left_context, m_block_sub_modes, idx, idy));
+ auto sub_mode = TRY_READ(TreeParser::parse_default_intra_mode(*m_bit_stream, *m_probability_tables, block_context.size, above_context, left_context, m_block_sub_modes, idx, idy));
for (auto y = 0; y < m_num_4x4_h; y++) {
for (auto x = 0; x < m_num_4x4_w; x++) {
@@ -1021,37 +1016,38 @@ bool Parser::seg_feature_active(u8 feature)
return m_segmentation_enabled && m_feature_enabled[m_segment_id][feature];
}
-DecoderErrorOr<void> Parser::read_tx_size(FrameBlockContext above_context, FrameBlockContext left_context, bool allow_select)
+DecoderErrorOr<void> Parser::read_tx_size(BlockContext const& block_context, FrameBlockContext above_context, FrameBlockContext left_context, bool allow_select)
{
- m_max_tx_size = max_txsize_lookup[m_mi_size];
- if (allow_select && m_tx_mode == TXModeSelect && m_mi_size >= Block_8x8)
+ // FIXME: This probably doesn't need to set max_tx_size, and can also return the TXSize it reads.
+ m_max_tx_size = max_txsize_lookup[block_context.size];
+ if (allow_select && m_tx_mode == TXModeSelect && block_context.size >= Block_8x8)
m_tx_size = TRY_READ(TreeParser::parse_tx_size(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, m_max_tx_size, above_context, left_context));
else
m_tx_size = min(m_max_tx_size, tx_mode_to_biggest_tx_size[m_tx_mode]);
return {};
}
-DecoderErrorOr<void> Parser::inter_frame_mode_info(u32 row, u32 column, FrameBlockContext above_context, FrameBlockContext left_context)
+DecoderErrorOr<void> Parser::inter_frame_mode_info(BlockContext& block_context, FrameBlockContext above_context, FrameBlockContext left_context)
{
- TRY(inter_segment_id(row, column));
+ TRY(inter_segment_id(block_context));
TRY(read_skip(above_context, left_context));
TRY(read_is_inter(above_context, left_context));
- TRY(read_tx_size(above_context, left_context, !m_skip || !m_is_inter));
+ TRY(read_tx_size(block_context, above_context, left_context, !m_skip || !m_is_inter));
if (m_is_inter) {
- TRY(inter_block_mode_info(row, column, above_context, left_context));
+ TRY(inter_block_mode_info(block_context, above_context, left_context));
} else {
- TRY(intra_block_mode_info());
+ TRY(intra_block_mode_info(block_context));
}
return {};
}
-DecoderErrorOr<void> Parser::inter_segment_id(u32 row, u32 column)
+DecoderErrorOr<void> Parser::inter_segment_id(BlockContext const& block_context)
{
if (!m_segmentation_enabled) {
m_segment_id = 0;
return {};
}
- auto predicted_segment_id = get_segment_id(row, column);
+ auto predicted_segment_id = get_segment_id(block_context);
if (!m_segmentation_update_map) {
m_segment_id = predicted_segment_id;
return {};
@@ -1061,37 +1057,37 @@ DecoderErrorOr<void> Parser::inter_segment_id(u32 row, u32 column)
return {};
}
- auto seg_id_predicted = TRY_READ(TreeParser::parse_segment_id_predicted(*m_bit_stream, m_segmentation_pred_prob, m_left_seg_pred_context[row], m_above_seg_pred_context[column]));
+ auto seg_id_predicted = TRY_READ(TreeParser::parse_segment_id_predicted(*m_bit_stream, m_segmentation_pred_prob, m_left_seg_pred_context[block_context.row], m_above_seg_pred_context[block_context.column]));
if (seg_id_predicted)
m_segment_id = predicted_segment_id;
else
m_segment_id = TRY_READ(TreeParser::parse_segment_id(*m_bit_stream, m_segmentation_tree_probs));
- for (size_t i = 0; i < num_8x8_blocks_wide_lookup[m_mi_size]; i++) {
- auto index = column + i;
+ for (size_t i = 0; i < num_8x8_blocks_wide_lookup[block_context.size]; i++) {
+ auto index = block_context.column + i;
// (7.4.1) AboveSegPredContext[ i ] only needs to be set to 0 for i = 0..MiCols-1.
if (index < m_above_seg_pred_context.size())
m_above_seg_pred_context[index] = seg_id_predicted;
}
- for (size_t i = 0; i < num_8x8_blocks_high_lookup[m_mi_size]; i++) {
- auto index = row + i;
+ for (size_t i = 0; i < num_8x8_blocks_high_lookup[block_context.size]; i++) {
+ auto index = block_context.row + i;
// (7.4.1) LeftSegPredContext[ i ] only needs to be set to 0 for i = 0..MiRows-1.
if (index < m_above_seg_pred_context.size())
- m_left_seg_pred_context[row + i] = seg_id_predicted;
+ m_left_seg_pred_context[block_context.row + i] = seg_id_predicted;
}
return {};
}
-u8 Parser::get_segment_id(u32 row, u32 column)
+u8 Parser::get_segment_id(BlockContext const& block_context)
{
- auto bw = num_8x8_blocks_wide_lookup[m_mi_size];
- auto bh = num_8x8_blocks_high_lookup[m_mi_size];
- auto xmis = min(m_mi_cols - column, (u32)bw);
- auto ymis = min(m_mi_rows - row, (u32)bh);
+ auto bw = num_8x8_blocks_wide_lookup[block_context.size];
+ auto bh = num_8x8_blocks_high_lookup[block_context.size];
+ auto xmis = min(block_context.frame_context.columns() - block_context.column, (u32)bw);
+ auto ymis = min(block_context.frame_context.rows() - block_context.row, (u32)bh);
u8 segment = 7;
for (size_t y = 0; y < ymis; y++) {
for (size_t x = 0; x < xmis; x++) {
- segment = min(segment, m_previous_block_contexts.index_at(row + y, column + x));
+ segment = min(segment, m_previous_block_contexts.index_at(block_context.row + y, block_context.column + x));
}
}
return segment;
@@ -1106,17 +1102,17 @@ DecoderErrorOr<void> Parser::read_is_inter(FrameBlockContext above_context, Fram
return {};
}
-DecoderErrorOr<void> Parser::intra_block_mode_info()
+DecoderErrorOr<void> Parser::intra_block_mode_info(BlockContext& block_context)
{
m_ref_frame[0] = IntraFrame;
m_ref_frame[1] = None;
- if (m_mi_size >= Block_8x8) {
- m_y_mode = TRY_READ(TreeParser::parse_intra_mode(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, m_mi_size));
+ if (block_context.size >= Block_8x8) {
+ m_y_mode = TRY_READ(TreeParser::parse_intra_mode(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, block_context.size));
for (auto& block_sub_mode : m_block_sub_modes)
block_sub_mode = m_y_mode;
} else {
- m_num_4x4_w = num_4x4_blocks_wide_lookup[m_mi_size];
- m_num_4x4_h = num_4x4_blocks_high_lookup[m_mi_size];
+ m_num_4x4_w = num_4x4_blocks_wide_lookup[block_context.size];
+ m_num_4x4_h = num_4x4_blocks_high_lookup[block_context.size];
PredictionMode sub_intra_mode;
for (auto idy = 0; idy < 2; idy += m_num_4x4_h) {
for (auto idx = 0; idx < 2; idx += m_num_4x4_w) {
@@ -1133,34 +1129,34 @@ DecoderErrorOr<void> Parser::intra_block_mode_info()
return {};
}
-DecoderErrorOr<void> Parser::inter_block_mode_info(u32 row, u32 column, FrameBlockContext above_context, FrameBlockContext left_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));
for (auto j = 0; j < 2; j++) {
if (m_ref_frame[j] > IntraFrame) {
- find_mv_refs(row, column, m_ref_frame[j], -1);
- find_best_ref_mvs(row, column, j);
+ find_mv_refs(block_context, m_ref_frame[j], -1);
+ find_best_ref_mvs(block_context, j);
}
}
auto is_compound = m_ref_frame[1] > IntraFrame;
if (seg_feature_active(SEG_LVL_SKIP)) {
m_y_mode = PredictionMode::ZeroMv;
- } else if (m_mi_size >= Block_8x8) {
+ } 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)
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;
- if (m_mi_size < Block_8x8) {
- m_num_4x4_w = num_4x4_blocks_wide_lookup[m_mi_size];
- m_num_4x4_h = num_4x4_blocks_high_lookup[m_mi_size];
+ 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];
for (auto idy = 0; idy < 2; idy += m_num_4x4_h) {
for (auto idx = 0; idx < 2; idx += m_num_4x4_w) {
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_y_mode == PredictionMode::NearestMv || m_y_mode == PredictionMode::NearMv) {
for (auto j = 0; j < 1 + is_compound; j++)
- append_sub8x8_mvs(row, column, idy * 2 + idx, j);
+ append_sub8x8_mvs(block_context, idy * 2 + idx, j);
}
TRY(assign_mv(is_compound));
for (auto y = 0; y < m_num_4x4_h; y++) {
@@ -1277,46 +1273,47 @@ DecoderErrorOr<i32> Parser::read_mv_component(u8 component)
return (mv_sign ? -1 : 1) * static_cast<i32>(magnitude);
}
-Gfx::Point<size_t> Parser::get_decoded_point_for_plane(u32 column, u32 row, u8 plane)
+Gfx::Point<size_t> Parser::get_decoded_point_for_plane(FrameContext const& frame_context, u32 column, u32 row, u8 plane)
{
+ (void)frame_context;
if (plane == 0)
return { column * 8, row * 8 };
return { (column * 8) >> m_subsampling_x, (row * 8) >> m_subsampling_y };
}
-Gfx::Size<size_t> Parser::get_decoded_size_for_plane(u8 plane)
+Gfx::Size<size_t> Parser::get_decoded_size_for_plane(FrameContext const& frame_context, u8 plane)
{
- auto point = get_decoded_point_for_plane(m_mi_cols, m_mi_rows, plane);
+ auto point = get_decoded_point_for_plane(frame_context, frame_context.columns(), frame_context.rows(), plane);
return { point.x(), point.y() };
}
-DecoderErrorOr<bool> Parser::residual(u32 row, u32 column, bool has_block_above, bool has_block_left)
+DecoderErrorOr<bool> Parser::residual(BlockContext& block_context, bool has_block_above, bool has_block_left)
{
bool had_residual_tokens = false;
- auto block_size = m_mi_size < Block_8x8 ? Block_8x8 : static_cast<BlockSubsize>(m_mi_size);
+ auto block_size = block_context.size < Block_8x8 ? Block_8x8 : block_context.size;
for (u8 plane = 0; plane < 3; plane++) {
- auto tx_size = (plane > 0) ? get_uv_tx_size() : m_tx_size;
+ auto tx_size = (plane > 0) ? get_uv_tx_size(block_context.size) : m_tx_size;
auto step = 1 << tx_size;
auto plane_size = get_plane_block_size(block_size, plane);
auto num_4x4_w = num_4x4_blocks_wide_lookup[plane_size];
auto num_4x4_h = num_4x4_blocks_high_lookup[plane_size];
auto sub_x = (plane > 0) ? m_subsampling_x : 0;
auto sub_y = (plane > 0) ? m_subsampling_y : 0;
- auto base_x = (column * 8) >> sub_x;
- auto base_y = (row * 8) >> sub_y;
+ auto base_x = (block_context.column * 8) >> sub_x;
+ auto base_y = (block_context.row * 8) >> sub_y;
if (m_is_inter) {
- if (m_mi_size < Block_8x8) {
+ if (block_context.size < Block_8x8) {
for (auto y = 0; y < num_4x4_h; y++) {
for (auto x = 0; x < num_4x4_w; x++) {
- TRY(m_decoder.predict_inter(plane, row, column, base_x + (4 * x), base_y + (4 * y), 4, 4, (y * num_4x4_w) + x));
+ TRY(m_decoder.predict_inter(plane, block_context, base_x + (4 * x), base_y + (4 * y), 4, 4, (y * num_4x4_w) + x));
}
}
} else {
- TRY(m_decoder.predict_inter(plane, row, column, base_x, base_y, num_4x4_w * 4, num_4x4_h * 4, 0));
+ TRY(m_decoder.predict_inter(plane, block_context, base_x, base_y, num_4x4_w * 4, num_4x4_h * 4, 0));
}
}
- auto max_x = (m_mi_cols * 8) >> sub_x;
- auto max_y = (m_mi_rows * 8) >> sub_y;
+ auto max_x = (block_context.frame_context.columns() * 8) >> sub_x;
+ auto max_y = (block_context.frame_context.rows() * 8) >> sub_y;
auto block_index = 0;
for (auto y = 0; y < num_4x4_h; y += step) {
for (auto x = 0; x < num_4x4_w; x += step) {
@@ -1325,11 +1322,11 @@ DecoderErrorOr<bool> Parser::residual(u32 row, u32 column, bool has_block_above,
auto non_zero = false;
if (start_x < max_x && start_y < max_y) {
if (!m_is_inter)
- TRY(m_decoder.predict_intra(plane, start_x, start_y, has_block_left || x > 0, has_block_above || y > 0, (x + step) < num_4x4_w, tx_size, block_index));
+ TRY(m_decoder.predict_intra(plane, block_context, start_x, start_y, has_block_left || x > 0, has_block_above || y > 0, (x + step) < num_4x4_w, tx_size, block_index));
if (!m_skip) {
- non_zero = TRY(tokens(plane, start_x, start_y, tx_size, block_index));
+ non_zero = TRY(tokens(block_context, plane, start_x, start_y, tx_size, block_index));
had_residual_tokens = had_residual_tokens || non_zero;
- TRY(m_decoder.reconstruct(plane, start_x, start_y, tx_size));
+ TRY(m_decoder.reconstruct(plane, block_context, start_x, start_y, tx_size));
}
}
@@ -1352,11 +1349,11 @@ DecoderErrorOr<bool> Parser::residual(u32 row, u32 column, bool has_block_above,
return had_residual_tokens;
}
-TXSize Parser::get_uv_tx_size()
+TXSize Parser::get_uv_tx_size(BlockSubsize size)
{
- if (m_mi_size < Block_8x8)
+ if (size < Block_8x8)
return TX_4x4;
- return min(m_tx_size, max_txsize_lookup[get_plane_block_size(m_mi_size, 1)]);
+ return min(m_tx_size, max_txsize_lookup[get_plane_block_size(size, 1)]);
}
BlockSubsize Parser::get_plane_block_size(u32 subsize, u8 plane)
@@ -1366,16 +1363,16 @@ BlockSubsize Parser::get_plane_block_size(u32 subsize, u8 plane)
return ss_size_lookup[subsize][sub_x][sub_y];
}
-DecoderErrorOr<bool> Parser::tokens(size_t plane, u32 start_x, u32 start_y, TXSize tx_size, u32 block_index)
+DecoderErrorOr<bool> Parser::tokens(BlockContext& block_context, size_t plane, u32 start_x, u32 start_y, TXSize tx_size, u32 block_index)
{
u32 segment_eob = 16 << (tx_size << 1);
- auto const* scan = get_scan(plane, tx_size, block_index);
+ auto const* scan = get_scan(block_context, plane, tx_size, block_index);
auto check_eob = true;
u32 c = 0;
for (; c < segment_eob; c++) {
auto pos = scan[c];
auto band = (tx_size == TX_4x4) ? coefband_4x4[c] : coefband_8x8plus[c];
- auto tokens_context = TreeParser::get_tokens_context(m_subsampling_x, m_subsampling_y, m_mi_rows, m_mi_cols, m_above_nonzero_context, m_left_nonzero_context, m_token_cache, tx_size, m_tx_type, plane, start_x, start_y, pos, m_is_inter, band, c);
+ auto tokens_context = TreeParser::get_tokens_context(m_subsampling_x, m_subsampling_y, block_context.frame_context.rows(), block_context.frame_context.columns(), m_above_nonzero_context, m_left_nonzero_context, m_token_cache, tx_size, m_tx_type, plane, start_x, start_y, pos, m_is_inter, band, c);
if (check_eob) {
auto more_coefs = TRY_READ(TreeParser::parse_more_coefficients(*m_bit_stream, *m_probability_tables, *m_syntax_element_counter, tokens_context));
if (!more_coefs)
@@ -1398,7 +1395,7 @@ DecoderErrorOr<bool> Parser::tokens(size_t plane, u32 start_x, u32 start_y, TXSi
return c > 0;
}
-u32 const* Parser::get_scan(size_t plane, TXSize tx_size, u32 block_index)
+u32 const* Parser::get_scan(BlockContext const& block_context, size_t plane, TXSize tx_size, u32 block_index)
{
if (plane > 0 || tx_size == TX_32x32) {
m_tx_type = DCT_DCT;
@@ -1406,7 +1403,7 @@ u32 const* Parser::get_scan(size_t plane, TXSize tx_size, u32 block_index)
if (m_lossless || m_is_inter)
m_tx_type = DCT_DCT;
else
- m_tx_type = mode_to_txfm_map[to_underlying(m_mi_size < Block_8x8 ? m_block_sub_modes[block_index] : m_y_mode)];
+ m_tx_type = mode_to_txfm_map[to_underlying(block_context.size < Block_8x8 ? m_block_sub_modes[block_index] : m_y_mode)];
} else {
m_tx_type = mode_to_txfm_map[to_underlying(m_y_mode)];
}
@@ -1452,15 +1449,15 @@ DecoderErrorOr<i32> Parser::read_coef(Token token)
return coef;
}
-bool Parser::is_inside(i32 row, i32 column)
+static bool is_inside(TileContext const& tile_context, MotionVector vector)
{
- if (row < 0)
+ if (vector.row() < 0)
return false;
- if (column < 0)
+ if (vector.column() < 0)
return false;
- u32 row_positive = row;
- u32 column_positive = column;
- return row_positive < m_mi_rows && column_positive >= m_mi_col_start && column_positive < m_mi_col_end;
+ u32 row_positive = vector.row();
+ u32 column_positive = vector.column();
+ return row_positive < tile_context.frame_context.rows() && column_positive >= tile_context.columns_start && column_positive < tile_context.columns_end;
}
void Parser::add_mv_ref_list(u8 ref_list)
@@ -1474,23 +1471,23 @@ void Parser::add_mv_ref_list(u8 ref_list)
m_ref_mv_count++;
}
-void Parser::get_block_mv(u32 candidate_row, u32 candidate_column, u8 ref_list, bool use_prev)
+void Parser::get_block_mv(BlockContext const& block_context, MotionVector candidate_vector, u8 ref_list, bool use_prev)
{
if (use_prev) {
- auto const& prev_context = m_previous_block_contexts.at(candidate_row, candidate_column);
+ auto const& prev_context = m_previous_block_contexts.at(candidate_vector.row(), candidate_vector.column());
m_candidate_mv[ref_list] = prev_context.primary_motion_vector_pair[ref_list];
m_candidate_frame[ref_list] = prev_context.ref_frames[ref_list];
} else {
- auto const& current_context = m_frame_block_contexts.at(candidate_row, candidate_column);
+ auto const& current_context = block_context.frame_block_contexts().at(candidate_vector.row(), candidate_vector.column());
m_candidate_mv[ref_list] = current_context.primary_motion_vector_pair()[ref_list];
m_candidate_frame[ref_list] = current_context.ref_frames[ref_list];
}
}
-void Parser::if_same_ref_frame_add_mv(u32 candidate_row, u32 candidate_column, ReferenceFrameType ref_frame, bool use_prev)
+void Parser::if_same_ref_frame_add_mv(BlockContext const& block_context, MotionVector candidate_vector, ReferenceFrameType ref_frame, bool use_prev)
{
for (auto ref_list = 0u; ref_list < 2; ref_list++) {
- get_block_mv(candidate_row, candidate_column, ref_list, use_prev);
+ get_block_mv(block_context, candidate_vector, ref_list, use_prev);
if (m_candidate_frame[ref_list] == ref_frame) {
add_mv_ref_list(ref_list);
return;
@@ -1505,10 +1502,10 @@ void Parser::scale_mv(u8 ref_list, ReferenceFrameType ref_frame)
m_candidate_mv[ref_list] *= -1;
}
-void Parser::if_diff_ref_frame_add_mv(u32 candidate_row, u32 candidate_column, ReferenceFrameType ref_frame, bool use_prev)
+void Parser::if_diff_ref_frame_add_mv(BlockContext const& block_context, MotionVector candidate_vector, ReferenceFrameType ref_frame, bool use_prev)
{
for (auto ref_list = 0u; ref_list < 2; ref_list++)
- get_block_mv(candidate_row, candidate_column, ref_list, use_prev);
+ 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);
@@ -1520,16 +1517,16 @@ void Parser::if_diff_ref_frame_add_mv(u32 candidate_row, u32 candidate_column, R
}
}
-MotionVector Parser::clamp_mv(u32 row, u32 column, MotionVector vector, i32 border)
+MotionVector Parser::clamp_mv(BlockContext const& block_context, MotionVector vector, i32 border)
{
- i32 blocks_high = num_8x8_blocks_high_lookup[m_mi_size];
+ i32 blocks_high = num_8x8_blocks_high_lookup[block_context.size];
// Casts must be done here to prevent subtraction underflow from wrapping the values.
- i32 mb_to_top_edge = -8 * (static_cast<i32>(row) * MI_SIZE);
- i32 mb_to_bottom_edge = 8 * ((static_cast<i32>(m_mi_rows) - blocks_high - static_cast<i32>(row)) * MI_SIZE);
+ i32 mb_to_top_edge = -8 * (static_cast<i32>(block_context.row) * MI_SIZE);
+ i32 mb_to_bottom_edge = 8 * ((static_cast<i32>(block_context.frame_context.rows()) - blocks_high - static_cast<i32>(block_context.row)) * MI_SIZE);
- i32 blocks_wide = num_8x8_blocks_wide_lookup[m_mi_size];
- i32 mb_to_left_edge = -8 * (static_cast<i32>(column) * MI_SIZE);
- i32 mb_to_right_edge = 8 * ((static_cast<i32>(m_mi_cols) - blocks_wide - static_cast<i32>(column)) * MI_SIZE);
+ i32 blocks_wide = num_8x8_blocks_wide_lookup[block_context.size];
+ i32 mb_to_left_edge = -8 * (static_cast<i32>(block_context.column) * MI_SIZE);
+ i32 mb_to_right_edge = 8 * ((static_cast<i32>(block_context.frame_context.columns()) - blocks_wide - static_cast<i32>(block_context.column)) * MI_SIZE);
return {
clip_3(mb_to_top_edge - border, mb_to_bottom_edge + border, vector.row()),
@@ -1537,14 +1534,15 @@ MotionVector Parser::clamp_mv(u32 row, u32 column, MotionVector vector, i32 bord
};
}
-void Parser::clamp_mv_ref(u32 row, u32 column, u8 i)
+void Parser::clamp_mv_ref(BlockContext const& block_context, u8 i)
{
+ // FIXME: This seems silly and should probably just be written inline in the one place it's used.
MotionVector& vector = m_ref_list_mv[i];
- vector = clamp_mv(row, column, vector, MV_BORDER);
+ vector = clamp_mv(block_context, vector, MV_BORDER);
}
// 6.5.1 Find MV refs syntax
-void Parser::find_mv_refs(u32 row, u32 column, ReferenceFrameType reference_frame, i32 block)
+void Parser::find_mv_refs(BlockContext& block_context, ReferenceFrameType reference_frame, i32 block)
{
m_ref_mv_count = 0;
bool different_ref_found = false;
@@ -1553,15 +1551,15 @@ void Parser::find_mv_refs(u32 row, u32 column, ReferenceFrameType reference_fram
m_ref_list_mv[0] = {};
m_ref_list_mv[1] = {};
- MotionVector base_coordinates = MotionVector(row, column);
+ MotionVector base_coordinates = MotionVector(block_context.row, block_context.column);
for (auto i = 0u; i < 2; i++) {
- auto offset_vector = mv_ref_blocks[m_mi_size][i];
+ auto offset_vector = mv_ref_blocks[block_context.size][i];
auto candidate = base_coordinates + offset_vector;
- if (is_inside(candidate.row(), candidate.column())) {
+ if (is_inside(block_context.tile_context, candidate)) {
different_ref_found = true;
- auto context = m_frame_block_contexts.at(candidate.row(), candidate.column());
+ auto context = block_context.frame_block_contexts().at(candidate.row(), candidate.column());
context_counter += mode_2_counter[to_underlying(context.y_mode)];
for (auto ref_list = 0u; ref_list < 2; ref_list++) {
@@ -1584,28 +1582,28 @@ void Parser::find_mv_refs(u32 row, u32 column, ReferenceFrameType reference_fram
}
for (auto i = 2u; i < MVREF_NEIGHBOURS; i++) {
- MotionVector candidate = base_coordinates + mv_ref_blocks[m_mi_size][i];
- if (is_inside(candidate.row(), candidate.column())) {
+ MotionVector candidate = base_coordinates + mv_ref_blocks[block_context.size][i];
+ if (is_inside(block_context.tile_context, candidate)) {
different_ref_found = true;
- if_same_ref_frame_add_mv(candidate.row(), candidate.column(), reference_frame, false);
+ if_same_ref_frame_add_mv(block_context, candidate, reference_frame, false);
}
}
if (m_use_prev_frame_mvs)
- if_same_ref_frame_add_mv(row, column, reference_frame, true);
+ if_same_ref_frame_add_mv(block_context, base_coordinates, reference_frame, true);
if (different_ref_found) {
for (auto i = 0u; i < MVREF_NEIGHBOURS; i++) {
- MotionVector candidate = base_coordinates + mv_ref_blocks[m_mi_size][i];
- if (is_inside(candidate.row(), candidate.column()))
- if_diff_ref_frame_add_mv(candidate.row(), candidate.column(), reference_frame, false);
+ MotionVector candidate = base_coordinates + mv_ref_blocks[block_context.size][i];
+ if (is_inside(block_context.tile_context, candidate))
+ if_diff_ref_frame_add_mv(block_context, candidate, reference_frame, false);
}
}
if (m_use_prev_frame_mvs)
- if_diff_ref_frame_add_mv(row, column, reference_frame, true);
+ if_diff_ref_frame_add_mv(block_context, base_coordinates, reference_frame, true);
m_mode_context[reference_frame] = counter_to_context[context_counter];
for (auto i = 0u; i < MAX_MV_REF_CANDIDATES; i++)
- clamp_mv_ref(row, column, i);
+ clamp_mv_ref(block_context, i);
}
bool Parser::use_mv_hp(MotionVector const& vector)
@@ -1613,7 +1611,7 @@ bool Parser::use_mv_hp(MotionVector const& vector)
return (abs(vector.row()) >> 3) < COMPANDED_MVREF_THRESH && (abs(vector.column()) >> 3) < COMPANDED_MVREF_THRESH;
}
-void Parser::find_best_ref_mvs(u32 row, u32 column, u8 ref_list)
+void Parser::find_best_ref_mvs(BlockContext& block_context, u8 ref_list)
{
for (auto i = 0u; i < MAX_MV_REF_CANDIDATES; i++) {
auto delta = m_ref_list_mv[i];
@@ -1626,7 +1624,7 @@ void Parser::find_best_ref_mvs(u32 row, u32 column, u8 ref_list)
delta_column += delta_column > 0 ? -1 : 1;
}
delta = { delta_row, delta_column };
- m_ref_list_mv[i] = clamp_mv(row, column, delta, (BORDERINPIXELS - INTERP_EXTEND) << 3);
+ m_ref_list_mv[i] = clamp_mv(block_context, delta, (BORDERINPIXELS - INTERP_EXTEND) << 3);
}
m_nearest_mv[ref_list] = m_ref_list_mv[0];
@@ -1634,10 +1632,10 @@ void Parser::find_best_ref_mvs(u32 row, u32 column, u8 ref_list)
m_best_mv[ref_list] = m_ref_list_mv[0];
}
-void Parser::append_sub8x8_mvs(u32 row, u32 column, i32 block, u8 ref_list)
+void Parser::append_sub8x8_mvs(BlockContext& block_context, i32 block, u8 ref_list)
{
MotionVector sub_8x8_mvs[2];
- find_mv_refs(row, column, m_ref_frame[ref_list], block);
+ find_mv_refs(block_context, m_ref_frame[ref_list], block);
auto destination_index = 0;
if (block == 0) {
for (auto i = 0u; i < 2; i++)
diff --git a/Userland/Libraries/LibVideo/VP9/Parser.h b/Userland/Libraries/LibVideo/VP9/Parser.h
index 5dd6e7772b..d8ff606b05 100644
--- a/Userland/Libraries/LibVideo/VP9/Parser.h
+++ b/Userland/Libraries/LibVideo/VP9/Parser.h
@@ -34,7 +34,7 @@ class Parser {
public:
explicit Parser(Decoder&);
~Parser();
- DecoderErrorOr<void> parse_frame(ReadonlyBytes);
+ DecoderErrorOr<FrameContext> parse_frame(ReadonlyBytes);
private:
/* Annex B: Superframes are a method of storing multiple coded frames into a single chunk
@@ -49,30 +49,29 @@ private:
void clear_context(Vector<T>& context, size_t size);
template<typename T>
void clear_context(Vector<Vector<T>>& context, size_t outer_size, size_t inner_size);
- DecoderErrorOr<void> allocate_tile_data();
/* (6.1) Frame Syntax */
bool trailing_bits();
DecoderErrorOr<void> refresh_probs();
/* (6.2) Uncompressed Header Syntax */
- DecoderErrorOr<void> uncompressed_header();
+ DecoderErrorOr<FrameContext> uncompressed_header();
DecoderErrorOr<void> frame_sync_code();
- DecoderErrorOr<void> color_config();
+ DecoderErrorOr<void> color_config(FrameContext const&);
DecoderErrorOr<void> set_frame_size_and_compute_image_size();
- DecoderErrorOr<Gfx::Size<u32>> frame_size();
- DecoderErrorOr<Gfx::Size<u32>> frame_size_with_refs();
- DecoderErrorOr<Gfx::Size<u32>> render_size(Gfx::Size<u32> frame_size);
- void compute_image_size();
+ DecoderErrorOr<Gfx::Size<u32>> parse_frame_size();
+ DecoderErrorOr<Gfx::Size<u32>> parse_frame_size_with_refs();
+ DecoderErrorOr<Gfx::Size<u32>> parse_render_size(Gfx::Size<u32> frame_size);
+ DecoderErrorOr<void> compute_image_size(FrameContext&);
DecoderErrorOr<void> read_interpolation_filter();
DecoderErrorOr<void> loop_filter_params();
DecoderErrorOr<void> quantization_params();
DecoderErrorOr<i8> read_delta_q();
DecoderErrorOr<void> segmentation_params();
DecoderErrorOr<u8> read_prob();
- DecoderErrorOr<void> tile_info();
- u16 calc_min_log2_tile_cols();
- u16 calc_max_log2_tile_cols();
+ DecoderErrorOr<void> tile_info(FrameContext&);
+ u16 calc_min_log2_tile_cols(u32 superblock_columns);
+ u16 calc_max_log2_tile_cols(u32 superblock_columns);
void setup_past_independence();
/* (6.3) Compressed Header Syntax */
@@ -97,58 +96,53 @@ private:
void setup_compound_reference_mode();
/* (6.4) Decode Tiles Syntax */
- DecoderErrorOr<void> decode_tiles();
- void clear_above_context();
+ DecoderErrorOr<void> decode_tiles(FrameContext&);
+ void clear_above_context(FrameContext&);
u32 get_tile_offset(u32 tile_num, u32 mis, u32 tile_size_log2);
- DecoderErrorOr<void> decode_tile();
- void clear_left_context();
- DecoderErrorOr<void> decode_partition(u32 row, u32 column, BlockSubsize subsize);
- DecoderErrorOr<void> decode_block(u32 row, u32 column, BlockSubsize subsize);
- DecoderErrorOr<void> mode_info(u32 row, u32 column, FrameBlockContext above_context, FrameBlockContext left_context);
- DecoderErrorOr<void> intra_frame_mode_info(FrameBlockContext above_context, FrameBlockContext left_context);
+ DecoderErrorOr<void> decode_tile(TileContext&);
+ void clear_left_context(TileContext&);
+ DecoderErrorOr<void> decode_partition(TileContext&, u32 row, u32 column, BlockSubsize subsize);
+ DecoderErrorOr<void> decode_block(TileContext&, u32 row, u32 column, BlockSubsize subsize);
+ DecoderErrorOr<void> mode_info(BlockContext&, FrameBlockContext above_context, FrameBlockContext left_context);
+ DecoderErrorOr<void> intra_frame_mode_info(BlockContext&, FrameBlockContext above_context, FrameBlockContext left_context);
DecoderErrorOr<void> intra_segment_id();
DecoderErrorOr<void> read_skip(FrameBlockContext above_context, FrameBlockContext left_context);
bool seg_feature_active(u8 feature);
- DecoderErrorOr<void> read_tx_size(FrameBlockContext above_context, FrameBlockContext left_context, bool allow_select);
- DecoderErrorOr<void> inter_frame_mode_info(u32 row, u32 column, FrameBlockContext above_context, FrameBlockContext left_context);
- DecoderErrorOr<void> inter_segment_id(u32 row, u32 column);
- u8 get_segment_id(u32 row, u32 column);
+ DecoderErrorOr<void> read_tx_size(BlockContext const&, FrameBlockContext above_context, FrameBlockContext left_context, bool allow_select);
+ DecoderErrorOr<void> inter_frame_mode_info(BlockContext&, FrameBlockContext above_context, FrameBlockContext left_context);
+ DecoderErrorOr<void> inter_segment_id(BlockContext const&);
+ u8 get_segment_id(BlockContext const&);
DecoderErrorOr<void> read_is_inter(FrameBlockContext above_context, FrameBlockContext left_context);
- DecoderErrorOr<void> intra_block_mode_info();
- DecoderErrorOr<void> inter_block_mode_info(u32 row, u32 column, 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<i32> read_mv_component(u8 component);
- DecoderErrorOr<bool> residual(u32 row, u32 column, bool has_block_above, bool has_block_left);
- TXSize get_uv_tx_size();
+ DecoderErrorOr<bool> residual(BlockContext&, bool has_block_above, bool has_block_left);
+ TXSize get_uv_tx_size(BlockSubsize size);
BlockSubsize get_plane_block_size(u32 subsize, u8 plane);
- DecoderErrorOr<bool> tokens(size_t plane, u32 x, u32 y, TXSize tx_size, u32 block_index);
- u32 const* get_scan(size_t plane, TXSize tx_size, u32 block_index);
+ DecoderErrorOr<bool> tokens(BlockContext&, size_t plane, u32 x, u32 y, TXSize tx_size, u32 block_index);
+ u32 const* get_scan(BlockContext const&, size_t plane, TXSize tx_size, u32 block_index);
DecoderErrorOr<i32> read_coef(Token token);
/* (6.5) Motion Vector Prediction */
- void find_mv_refs(u32 row, u32 column, ReferenceFrameType, i32 block);
- void find_best_ref_mvs(u32 row, u32 column, u8 ref_list);
+ void find_mv_refs(BlockContext&, ReferenceFrameType, i32 block);
+ void find_best_ref_mvs(BlockContext&, u8 ref_list);
bool use_mv_hp(MotionVector const& delta_mv);
- void append_sub8x8_mvs(u32 row, u32 column, i32 block, u8 ref_list);
- bool is_inside(i32 row, i32 column);
- void clamp_mv_ref(u32 row, u32 column, u8 i);
- MotionVector clamp_mv(u32 row, u32 column, MotionVector mvec, i32 border);
- size_t get_image_index(u32 row, u32 column) const;
- void get_block_mv(u32 candidate_row, u32 candidate_column, u8 ref_list, bool use_prev);
- void if_same_ref_frame_add_mv(u32 candidate_row, u32 candidate_column, ReferenceFrameType ref_frame, bool use_prev);
- void if_diff_ref_frame_add_mv(u32 candidate_row, u32 candidate_column, ReferenceFrameType ref_frame, bool use_prev);
+ void append_sub8x8_mvs(BlockContext&, i32 block, u8 ref_list);
+ void clamp_mv_ref(BlockContext const&, u8 i);
+ MotionVector clamp_mv(BlockContext const&, MotionVector vector, i32 border);
+ size_t get_image_index(FrameContext const&, u32 row, u32 column) const;
+ 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 add_mv_ref_list(u8 ref_list);
- Gfx::Point<size_t> get_decoded_point_for_plane(u32 row, u32 column, u8 plane);
- Gfx::Size<size_t> get_decoded_size_for_plane(u8 plane);
+ 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_profile { 0 };
- bool m_show_existing_frame { false };
- u8 m_frame_to_show_map_index { 0 };
- u16 m_header_size_in_bytes { 0 };
u8 m_refresh_frame_flags { 0 };
u8 m_loop_filter_level { 0 };
u8 m_loop_filter_sharpness { 0 };
@@ -156,7 +150,6 @@ private:
FrameType m_frame_type { FrameType::KeyFrame };
FrameType m_last_frame_type { FrameType::KeyFrame };
bool m_show_frame { false };
- bool m_prev_show_frame { false };
bool m_error_resilient_mode { false };
bool m_frame_is_intra { false };
u8 m_reset_frame_context { 0 };
@@ -171,13 +164,9 @@ private:
ColorRange m_color_range;
bool m_subsampling_x { false };
bool m_subsampling_y { false };
- Gfx::Size<u32> m_frame_size { 0, 0 };
- Gfx::Size<u32> m_render_size { 0, 0 };
- bool m_render_and_frame_size_different { false };
- u32 m_mi_cols { 0 };
- u32 m_mi_rows { 0 };
- u32 m_sb64_cols { 0 };
- u32 m_sb64_rows { 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 };
InterpolationFilter m_interpolation_filter { 0xf };
u8 m_base_q_idx { 0 };
i8 m_delta_q_y_dc { 0 };
@@ -205,12 +194,6 @@ private:
Vector<u8> m_above_partition_context;
Vector<u8> m_left_partition_context;
- // FIXME: Move (some?) mi_.. to an array of struct since they are usually used together.
- u32 m_mi_row_start { 0 };
- u32 m_mi_row_end { 0 };
- u32 m_mi_col_start { 0 };
- u32 m_mi_col_end { 0 };
- BlockSubsize m_mi_size { 0 };
u8 m_segment_id { 0 };
// FIXME: Should this be an enum?
// skip equal to 0 indicates that there may be some transform coefficients to read for this block; skip equal to 1
@@ -219,7 +202,6 @@ private:
// skip may be set to 0 even if transform blocks contain immediate end of block markers.
bool m_skip { false };
TXSize m_max_tx_size { TX_4x4 };
- BlockSubsize m_block_subsize { BlockSubsize::Block_4x4 };
TXSize m_tx_size { TX_4x4 };
ReferenceFramePair m_ref_frame;
bool m_is_inter { false };
@@ -253,13 +235,6 @@ private:
// FIXME: Use Array<MotionVectorPair, 4> instead.
Array<Array<MotionVector, 4>, 2> m_block_mvs;
- // FIXME: From spec: NOTE – We are using a 2D array to store the SubModes for clarity. It is possible to reduce memory
- // consumption by only storing one intra mode for each 8x8 horizontal and vertical position, i.e. to use two 1D
- // arrays instead.
- // I think should also apply to other fields that are only accessed relative to the current block. Worth looking
- // into how much of this context needs to be stored for the whole frame vs a row or column from the current tile.
- Vector2D<FrameBlockContext> m_frame_block_contexts;
-
MotionVectorPair m_candidate_mv;
ReferenceFramePair m_candidate_frame;
u8 m_ref_mv_count { 0 };