mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 07:30:19 +00:00
LibVideo: Allow the VP9 decoder to decode ultra high resolution video
Previously, some integer overflows and truncations were causing parsing errors for 4K videos, with those fixed it can fully decode 8K video. This adds a test to ensure that 4K video will continue to be decoded. Note: There seems to be unexpectedly high memory usage while decoding them, causing 8K video to require more than a gigabyte of RAM. (!!!)
This commit is contained in:
parent
f894e8be62
commit
41cb705b47
Notes:
sideshowbarker
2024-07-17 07:06:47 +09:00
Author: https://github.com/Zaggy1024 Commit: https://github.com/SerenityOS/serenity/commit/41cb705b47 Pull-request: https://github.com/SerenityOS/serenity/pull/15541 Reviewed-by: https://github.com/FireFox317 Reviewed-by: https://github.com/gmta
6 changed files with 21 additions and 9 deletions
|
@ -7,3 +7,4 @@ foreach(source IN LISTS TEST_SOURCES)
|
|||
endforeach()
|
||||
|
||||
install(FILES vp9_in_webm.webm DESTINATION usr/Tests/LibVideo)
|
||||
install(FILES vp9_4k.webm DESTINATION usr/Tests/LibVideo)
|
||||
|
|
|
@ -9,14 +9,15 @@
|
|||
#include <LibVideo/MatroskaReader.h>
|
||||
#include <LibVideo/VP9/Decoder.h>
|
||||
|
||||
TEST_CASE(webm_in_vp9)
|
||||
static void decode_video(StringView path, size_t expected_frame_count)
|
||||
{
|
||||
auto matroska_document = Video::MatroskaReader::MatroskaReader::parse_matroska_from_file("./vp9_in_webm.webm"sv);
|
||||
auto matroska_document = Video::MatroskaReader::MatroskaReader::parse_matroska_from_file(path);
|
||||
VERIFY(matroska_document);
|
||||
auto video_track_optional = matroska_document->track_for_track_type(Video::TrackEntry::TrackType::Video);
|
||||
VERIFY(video_track_optional.has_value());
|
||||
auto video_track_entry = video_track_optional.value();
|
||||
|
||||
size_t frame_count = 0;
|
||||
size_t cluster_index, block_index, frame_index;
|
||||
Video::VP9::Decoder vp9_decoder;
|
||||
|
||||
|
@ -29,9 +30,19 @@ TEST_CASE(webm_in_vp9)
|
|||
|
||||
for (frame_index = 0; frame_index < block.frames().size(); frame_index++) {
|
||||
MUST(vp9_decoder.decode(block.frames()[frame_index]));
|
||||
frame_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
VERIFY(frame_count == expected_frame_count);
|
||||
}
|
||||
|
||||
VERIFY(cluster_index == 1 && block_index == 25 && frame_index == 1);
|
||||
TEST_CASE(webm_in_vp9)
|
||||
{
|
||||
decode_video("./vp9_in_webm.webm"sv, 25);
|
||||
}
|
||||
|
||||
BENCHMARK_CASE(vp9_4k)
|
||||
{
|
||||
decode_video("./vp9_4k.webm"sv, 2);
|
||||
}
|
||||
|
|
BIN
Tests/LibVideo/vp9_4k.webm
Normal file
BIN
Tests/LibVideo/vp9_4k.webm
Normal file
Binary file not shown.
|
@ -1097,7 +1097,7 @@ inline i32 Decoder::round_2(T value, u8 bits)
|
|||
|
||||
inline bool check_bounds(i64 value, u8 bits)
|
||||
{
|
||||
const i64 maximum = (1u << (bits - 1u)) - 1u;
|
||||
i64 const maximum = (1ll << (bits - 1ll)) - 1ll;
|
||||
return value >= ~maximum && value <= maximum;
|
||||
}
|
||||
|
||||
|
|
|
@ -979,8 +979,8 @@ DecoderErrorOr<void> Parser::decode_block(u32 row, u32 col, BlockSubsize subsize
|
|||
// 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(num_8x8_blocks_high_lookup[subsize], m_mi_rows - row);
|
||||
auto maximum_block_x = min(num_8x8_blocks_wide_lookup[subsize], m_mi_cols - col);
|
||||
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 - col);
|
||||
|
||||
for (size_t y = 0; y < maximum_block_y; y++) {
|
||||
for (size_t x = 0; x < maximum_block_x; x++) {
|
||||
|
@ -1337,7 +1337,7 @@ DecoderErrorOr<i32> Parser::read_mv_component(u8 component)
|
|||
return (mv_sign ? -1 : 1) * static_cast<i32>(mag);
|
||||
}
|
||||
|
||||
Gfx::Point<size_t> Parser::get_decoded_point_for_plane(u8 column, u8 row, u8 plane)
|
||||
Gfx::Point<size_t> Parser::get_decoded_point_for_plane(u32 column, u32 row, u8 plane)
|
||||
{
|
||||
if (plane == 0)
|
||||
return { column * 8, row * 8 };
|
||||
|
|
|
@ -141,7 +141,7 @@ private:
|
|||
void scale_mv(u8 ref_list, ReferenceFrame ref_frame);
|
||||
void add_mv_ref_list(u8 ref_list);
|
||||
|
||||
Gfx::Point<size_t> get_decoded_point_for_plane(u8 row, u8 column, u8 plane);
|
||||
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);
|
||||
|
||||
u8 m_profile { 0 };
|
||||
|
|
Loading…
Reference in a new issue