diff options
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/Decoder.cpp | 34 | ||||
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/Parser.cpp | 60 | ||||
-rw-r--r-- | Userland/Libraries/LibVideo/VP9/Parser.h | 18 |
3 files changed, 48 insertions, 64 deletions
diff --git a/Userland/Libraries/LibVideo/VP9/Decoder.cpp b/Userland/Libraries/LibVideo/VP9/Decoder.cpp index 318216c963..bbe8b52c4e 100644 --- a/Userland/Libraries/LibVideo/VP9/Decoder.cpp +++ b/Userland/Libraries/LibVideo/VP9/Decoder.cpp @@ -87,13 +87,10 @@ DecoderErrorOr<void> Decoder::decode_frame(ReadonlyBytes frame_data) DecoderErrorOr<void> Decoder::create_video_frame() { - size_t decoded_y_width = m_parser->m_mi_cols * 8; - Gfx::Size<size_t> output_y_size = { - m_parser->m_frame_width, - m_parser->m_frame_height, - }; + u32 decoded_y_width = m_parser->m_mi_cols * 8; + Gfx::Size<u32> output_y_size = m_parser->m_frame_size; auto decoded_uv_width = decoded_y_width >> m_parser->m_subsampling_x; - Gfx::Size<size_t> output_uv_size = { + Gfx::Size<u32> output_uv_size = { output_y_size.width() >> m_parser->m_subsampling_x, output_y_size.height() >> m_parser->m_subsampling_y, }; @@ -816,11 +813,11 @@ DecoderErrorOr<void> Decoder::predict_inter_block(u8 plane, u8 ref_list, u32 x, // − FrameHeight <= 16 * RefFrameHeight[ refIdx ] 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); - if (2 * m_parser->m_frame_width < m_parser->m_ref_frame_width[reference_frame_index] - || 2 * m_parser->m_frame_height < m_parser->m_ref_frame_height[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); + 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 (m_parser->m_frame_width > 16 * m_parser->m_ref_frame_width[reference_frame_index] - || m_parser->m_frame_height > 16 * m_parser->m_ref_frame_height[reference_frame_index]) + if (!ref_frame_size.scaled_by(16).contains(m_parser->m_frame_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 @@ -830,8 +827,8 @@ DecoderErrorOr<void> Decoder::predict_inter_block(u8 plane, u8 ref_list, u32 x, // 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 = (m_parser->m_ref_frame_width[reference_frame_index] << REF_SCALE_SHIFT) / m_parser->m_frame_width; - i32 y_scale = (m_parser->m_ref_frame_height[reference_frame_index] << REF_SCALE_SHIFT) / m_parser->m_frame_height; + 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(); // The variable baseX is set equal to (x * xScale) >> REF_SCALE_SHIFT. // The variable baseY is set equal to (y * yScale) >> REF_SCALE_SHIFT. @@ -885,7 +882,7 @@ DecoderErrorOr<void> Decoder::predict_inter_block(u8 plane, u8 ref_list, u32 x, // 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_width[reference_frame_index] >> subsampling_x; + auto reference_frame_width = m_parser->m_ref_frame_size[reference_frame_index].width() >> subsampling_x; auto reference_frame_buffer_at = [&](u32 row, u32 column) -> u16& { return reference_frame_buffer[row * reference_frame_width + column]; }; @@ -898,8 +895,8 @@ DecoderErrorOr<void> Decoder::predict_inter_block(u8 plane, u8 ref_list, u32 x, // 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_width[reference_frame_index] + subsampling_x) >> subsampling_x) - 1; - i32 scaled_bottom = ((m_parser->m_ref_frame_height[reference_frame_index] + subsampling_y) >> subsampling_y) - 1; + 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; // The variable intermediateHeight specifying the height required for the intermediate array is set equal to (((h - // 1) * yStep + 15) >> 4) + 8. @@ -1779,9 +1776,8 @@ DecoderErrorOr<void> Decoder::update_reference_frames() for (auto i = 0; i < NUM_REF_FRAMES; i++) { if ((refresh_flags & 1) != 0) { // − RefFrameWidth[ i ] is set equal to FrameWidth. - m_parser->m_ref_frame_width[i] = m_parser->m_frame_width; // − RefFrameHeight[ i ] is set equal to FrameHeight. - m_parser->m_ref_frame_height[i] = m_parser->m_frame_height; + m_parser->m_ref_frame_size[i] = m_parser->m_frame_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. @@ -1798,8 +1794,8 @@ 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_width; - auto height = m_parser->m_frame_height; + auto width = m_parser->m_frame_size.width(); + auto height = m_parser->m_frame_size.height(); auto stride = m_parser->m_mi_cols * 8; if (plane > 0) { diff --git a/Userland/Libraries/LibVideo/VP9/Parser.cpp b/Userland/Libraries/LibVideo/VP9/Parser.cpp index 300c3bca36..2355b9ae1b 100644 --- a/Userland/Libraries/LibVideo/VP9/Parser.cpp +++ b/Userland/Libraries/LibVideo/VP9/Parser.cpp @@ -168,8 +168,8 @@ DecoderErrorOr<void> Parser::uncompressed_header() if (m_frame_type == KeyFrame) { TRY(frame_sync_code()); TRY(color_config()); - TRY(frame_size()); - TRY(render_size()); + m_frame_size = TRY(frame_size()); + m_render_size = TRY(render_size(m_frame_size)); m_refresh_frame_flags = 0xFF; m_frame_is_intra = true; } else { @@ -193,20 +193,23 @@ DecoderErrorOr<void> Parser::uncompressed_header() } m_refresh_frame_flags = TRY_READ(m_bit_stream->read_f8()); - TRY(frame_size()); - TRY(render_size()); + m_frame_size = TRY(frame_size()); + m_render_size = TRY(render_size(m_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()); } - TRY(frame_size_with_refs()); + m_frame_size = TRY(frame_size_with_refs()); + m_render_size = TRY(render_size(m_frame_size)); m_allow_high_precision_mv = TRY_READ(m_bit_stream->read_bit()); TRY(read_interpolation_filter()); } } + compute_image_size(); + if (!m_error_resilient_mode) { m_refresh_frame_context = TRY_READ(m_bit_stream->read_bit()); m_frame_parallel_decoding_mode = TRY_READ(m_bit_stream->read_bit()); @@ -284,51 +287,38 @@ DecoderErrorOr<void> Parser::color_config() return {}; } -DecoderErrorOr<void> Parser::frame_size() +DecoderErrorOr<Gfx::Size<u32>> Parser::frame_size() { - m_frame_width = TRY_READ(m_bit_stream->read_f16()) + 1; - m_frame_height = TRY_READ(m_bit_stream->read_f16()) + 1; - compute_image_size(); - return {}; + return Gfx::Size<u32> { TRY_READ(m_bit_stream->read_f16()) + 1, TRY_READ(m_bit_stream->read_f16()) + 1 }; } -DecoderErrorOr<void> Parser::render_size() +DecoderErrorOr<Gfx::Size<u32>> Parser::render_size(Gfx::Size<u32> frame_size) { - if (TRY_READ(m_bit_stream->read_bit())) { - m_render_width = TRY_READ(m_bit_stream->read_f16()) + 1; - m_render_height = TRY_READ(m_bit_stream->read_f16()) + 1; - } else { - m_render_width = m_frame_width; - m_render_height = m_frame_height; - } - return {}; + 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<void> Parser::frame_size_with_refs() +DecoderErrorOr<Gfx::Size<u32>> Parser::frame_size_with_refs() { - bool found_ref; + Optional<Gfx::Size<u32>> size; for (auto frame_index : m_ref_frame_idx) { - found_ref = TRY_READ(m_bit_stream->read_bit()); - if (found_ref) { - m_frame_width = m_ref_frame_width[frame_index]; - m_frame_height = m_ref_frame_height[frame_index]; + if (TRY_READ(m_bit_stream->read_bit())) { + size.emplace(m_ref_frame_size[frame_index]); break; } } - if (!found_ref) { - TRY(frame_size()); - } else { - compute_image_size(); - } + if (size.has_value()) + return size.value(); - return render_size(); + return TRY(frame_size()); } void Parser::compute_image_size() { - auto new_cols = (m_frame_width + 7u) >> 3u; - auto new_rows = (m_frame_height + 7u) >> 3u; + 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: @@ -1728,8 +1718,8 @@ void Parser::append_sub8x8_mvs(i32 block, u8 ref_list) void Parser::dump_info() { - outln("Frame dimensions: {}x{}", m_frame_width, m_frame_height); - outln("Render dimensions: {}x{}", m_render_width, m_render_height); + outln("Frame dimensions: {}x{}", m_frame_size.width(), m_frame_size.height()); + outln("Render dimensions: {}x{}", m_render_size.width(), m_render_size.height()); outln("Bit depth: {}", m_bit_depth); outln("Show frame: {}", m_show_frame); } diff --git a/Userland/Libraries/LibVideo/VP9/Parser.h b/Userland/Libraries/LibVideo/VP9/Parser.h index 154a85a4ca..7d72a24014 100644 --- a/Userland/Libraries/LibVideo/VP9/Parser.h +++ b/Userland/Libraries/LibVideo/VP9/Parser.h @@ -11,7 +11,7 @@ #include <AK/OwnPtr.h> #include <AK/Span.h> #include <AK/Vector.h> -#include <LibGfx/Forward.h> +#include <LibGfx/Size.h> #include <LibVideo/Color/CodingIndependentCodePoints.h> #include <LibVideo/DecoderError.h> @@ -60,9 +60,10 @@ private: DecoderErrorOr<void> uncompressed_header(); DecoderErrorOr<void> frame_sync_code(); DecoderErrorOr<void> color_config(); - DecoderErrorOr<void> frame_size(); - DecoderErrorOr<void> render_size(); - DecoderErrorOr<void> frame_size_with_refs(); + 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<void> read_interpolation_filter(); DecoderErrorOr<void> loop_filter_params(); @@ -171,10 +172,8 @@ private: ColorRange m_color_range; bool m_subsampling_x { false }; bool m_subsampling_y { false }; - u32 m_frame_width { 0 }; - u32 m_frame_height { 0 }; - u16 m_render_width { 0 }; - u16 m_render_height { 0 }; + 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 }; @@ -257,8 +256,7 @@ private: MotionVector m_nearest_mv[2]; MotionVector m_best_mv[2]; // FIXME: Move these to a struct to store together in one array. - u32 m_ref_frame_width[NUM_REF_FRAMES]; - u32 m_ref_frame_height[NUM_REF_FRAMES]; + Gfx::Size<u32> 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]; |