diff --git a/Userland/Libraries/LibVideo/VP9/ContextStorage.h b/Userland/Libraries/LibVideo/VP9/ContextStorage.h index 3b56c969b5b..755033452a2 100644 --- a/Userland/Libraries/LibVideo/VP9/ContextStorage.h +++ b/Userland/Libraries/LibVideo/VP9/ContextStorage.h @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -257,4 +258,14 @@ using SegmentationPredictionContextView = Span; using PartitionContext = FixedArray; using PartitionContextView = Span; +struct ReferenceFrame { + Gfx::Size size { 0, 0 }; + bool subsampling_x { false }; + bool subsampling_y { false }; + u8 bit_depth { 0 }; + Array, 3> frame_planes {}; + + bool is_valid() { return bit_depth > 0; } +}; + } diff --git a/Userland/Libraries/LibVideo/VP9/Decoder.cpp b/Userland/Libraries/LibVideo/VP9/Decoder.cpp index c281a8a05dc..3212b752b76 100644 --- a/Userland/Libraries/LibVideo/VP9/Decoder.cpp +++ b/Userland/Libraries/LibVideo/VP9/Decoder.cpp @@ -797,13 +797,13 @@ DecoderErrorOr Decoder::predict_inter_block(u8 plane, BlockContext const& // − 2 * FrameHeight >= RefFrameHeight[ refIdx ] // − FrameWidth <= 16 * RefFrameWidth[ refIdx ] // − FrameHeight <= 16 * RefFrameHeight[ refIdx ] - if (m_parser->m_frame_store[reference_frame_index][plane].is_empty()) + auto& reference_frame = m_parser->m_reference_frames[reference_frame_index]; + if (!reference_frame.is_valid()) 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 = 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()) + if (double_frame_size.width() < reference_frame.size.width() || double_frame_size.height() < reference_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(block_context.frame_context.size())) + if (!reference_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 @@ -813,8 +813,8 @@ DecoderErrorOr Decoder::predict_inter_block(u8 plane, BlockContext const& // 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) / block_context.frame_context.size().width(); - i32 y_scale = (ref_frame_size.height() << REF_SCALE_SHIFT) / block_context.frame_context.size().height(); + i32 x_scale = (reference_frame.size.width() << REF_SCALE_SHIFT) / block_context.frame_context.size().width(); + i32 y_scale = (reference_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. @@ -868,8 +868,8 @@ DecoderErrorOr Decoder::predict_inter_block(u8 plane, BlockContext const& // The output from this process is the 2D array named pred containing inter predicted samples. // A variable ref specifying the reference frame contents is set equal to FrameStore[ refIdx ]. - auto& reference_frame_buffer = m_parser->m_frame_store[reference_frame_index][plane]; - auto reference_frame_width = m_parser->m_ref_frame_size[reference_frame_index].width() >> subsampling_x; + auto& reference_frame_buffer = reference_frame.frame_planes[plane]; + auto reference_frame_width = reference_frame.size.width() >> subsampling_x; auto reference_frame_buffer_at = [&](u32 row, u32 column) -> u16& { return reference_frame_buffer[row * reference_frame_width + column]; }; @@ -881,8 +881,8 @@ DecoderErrorOr Decoder::predict_inter_block(u8 plane, BlockContext const& // The variable lastX is set equal to ( (RefFrameWidth[ refIdx ] + subX) >> subX) - 1. // The variable lastY is set equal to ( (RefFrameHeight[ refIdx ] + subY) >> subY) - 1. // (lastX and lastY specify the coordinates of the bottom right sample of the reference plane.) - i32 scaled_right = ((m_parser->m_ref_frame_size[reference_frame_index].width() + subsampling_x) >> subsampling_x) - 1; - i32 scaled_bottom = ((m_parser->m_ref_frame_size[reference_frame_index].height() + subsampling_y) >> subsampling_y) - 1; + i32 scaled_right = ((reference_frame.size.width() + subsampling_x) >> subsampling_x) - 1; + i32 scaled_bottom = ((reference_frame.size.height() + subsampling_y) >> subsampling_y) - 1; // The variable intermediateHeight specifying the height required for the intermediate array is set equal to (((h - // 1) * yStep + 15) >> 4) + 8. @@ -1761,15 +1761,17 @@ DecoderErrorOr Decoder::update_reference_frames(FrameContext const& frame_ // is equal to 1 (i.e. if (refresh_frame_flags>>i)&1 is equal to 1): for (u8 i = 0; i < NUM_REF_FRAMES; i++) { if (frame_context.should_update_reference_frame_at_index(i)) { + auto& reference_frame = m_parser->m_reference_frames[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(); + reference_frame.size = frame_context.size(); // − RefSubsamplingX[ i ] is set equal to subsampling_x. - m_parser->m_ref_subsampling_x[i] = frame_context.color_config.subsampling_x; + reference_frame.subsampling_x = frame_context.color_config.subsampling_x; // − RefSubsamplingY[ i ] is set equal to subsampling_y. - m_parser->m_ref_subsampling_y[i] = frame_context.color_config.subsampling_y; + reference_frame.subsampling_y = frame_context.color_config.subsampling_y; // − RefBitDepth[ i ] is set equal to BitDepth. - m_parser->m_ref_bit_depth[i] = frame_context.color_config.bit_depth; + reference_frame.bit_depth = frame_context.color_config.bit_depth; // − FrameStore[ i ][ 0 ][ y ][ x ] is set equal to CurrFrame[ 0 ][ y ][ x ] for x = 0..FrameWidth-1, for y = // 0..FrameHeight-1. @@ -1791,7 +1793,7 @@ DecoderErrorOr Decoder::update_reference_frames(FrameContext const& frame_ } auto original_buffer = get_output_buffer(plane); - auto& frame_store_buffer = m_parser->m_frame_store[i][plane]; + auto& frame_store_buffer = reference_frame.frame_planes[plane]; frame_store_buffer.resize_and_keep_capacity(width * height); for (auto x = 0u; x < width; x++) { diff --git a/Userland/Libraries/LibVideo/VP9/Parser.cpp b/Userland/Libraries/LibVideo/VP9/Parser.cpp index 1e65a11a917..ae60ae8f0cf 100644 --- a/Userland/Libraries/LibVideo/VP9/Parser.cpp +++ b/Userland/Libraries/LibVideo/VP9/Parser.cpp @@ -357,7 +357,9 @@ DecoderErrorOr> Parser::parse_frame_size_with_refs(Array c Optional> size; for (auto frame_index : reference_indices) { if (TRY_READ(m_bit_stream->read_bit())) { - size.emplace(m_ref_frame_size[frame_index]); + if (!m_reference_frames[frame_index].is_valid()) + return DecoderError::corrupted("Frame size referenced a frame that does not exist"sv); + size.emplace(m_reference_frames[frame_index].size); break; } } diff --git a/Userland/Libraries/LibVideo/VP9/Parser.h b/Userland/Libraries/LibVideo/VP9/Parser.h index 96b42754f6d..f22b77417e4 100644 --- a/Userland/Libraries/LibVideo/VP9/Parser.h +++ b/Userland/Libraries/LibVideo/VP9/Parser.h @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -139,13 +138,7 @@ private: bool m_previous_should_use_absolute_segment_base_quantizer; Array, MAX_SEGMENTS> m_previous_segmentation_features; - // FIXME: Move these to a struct to store together in one array. - Gfx::Size m_ref_frame_size[NUM_REF_FRAMES]; - bool m_ref_subsampling_x[NUM_REF_FRAMES]; - bool m_ref_subsampling_y[NUM_REF_FRAMES]; - u8 m_ref_bit_depth[NUM_REF_FRAMES]; - - Vector m_frame_store[NUM_REF_FRAMES][3]; + ReferenceFrame m_reference_frames[NUM_REF_FRAMES]; Vector2D m_reusable_frame_block_contexts; Vector2D m_previous_block_contexts;