Skip to content

Commit 41cb705

Browse files
Zaggy1024ADKaster
authored andcommitted
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. (!!!)
1 parent f894e8b commit 41cb705

File tree

6 files changed

+20
-8
lines changed

6 files changed

+20
-8
lines changed

Tests/LibVideo/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ foreach(source IN LISTS TEST_SOURCES)
77
endforeach()
88

99
install(FILES vp9_in_webm.webm DESTINATION usr/Tests/LibVideo)
10+
install(FILES vp9_4k.webm DESTINATION usr/Tests/LibVideo)

Tests/LibVideo/TestVP9Decode.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@
99
#include <LibVideo/MatroskaReader.h>
1010
#include <LibVideo/VP9/Decoder.h>
1111

12-
TEST_CASE(webm_in_vp9)
12+
static void decode_video(StringView path, size_t expected_frame_count)
1313
{
14-
auto matroska_document = Video::MatroskaReader::MatroskaReader::parse_matroska_from_file("./vp9_in_webm.webm"sv);
14+
auto matroska_document = Video::MatroskaReader::MatroskaReader::parse_matroska_from_file(path);
1515
VERIFY(matroska_document);
1616
auto video_track_optional = matroska_document->track_for_track_type(Video::TrackEntry::TrackType::Video);
1717
VERIFY(video_track_optional.has_value());
1818
auto video_track_entry = video_track_optional.value();
1919

20+
size_t frame_count = 0;
2021
size_t cluster_index, block_index, frame_index;
2122
Video::VP9::Decoder vp9_decoder;
2223

@@ -29,9 +30,19 @@ TEST_CASE(webm_in_vp9)
2930

3031
for (frame_index = 0; frame_index < block.frames().size(); frame_index++) {
3132
MUST(vp9_decoder.decode(block.frames()[frame_index]));
33+
frame_count++;
3234
}
3335
}
3436
}
37+
VERIFY(frame_count == expected_frame_count);
38+
}
3539

36-
VERIFY(cluster_index == 1 && block_index == 25 && frame_index == 1);
40+
TEST_CASE(webm_in_vp9)
41+
{
42+
decode_video("./vp9_in_webm.webm"sv, 25);
43+
}
44+
45+
BENCHMARK_CASE(vp9_4k)
46+
{
47+
decode_video("./vp9_4k.webm"sv, 2);
3748
}

Tests/LibVideo/vp9_4k.webm

98.9 KB
Binary file not shown.

Userland/Libraries/LibVideo/VP9/Decoder.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1097,7 +1097,7 @@ inline i32 Decoder::round_2(T value, u8 bits)
10971097

10981098
inline bool check_bounds(i64 value, u8 bits)
10991099
{
1100-
const i64 maximum = (1u << (bits - 1u)) - 1u;
1100+
i64 const maximum = (1ll << (bits - 1ll)) - 1ll;
11011101
return value >= ~maximum && value <= maximum;
11021102
}
11031103

Userland/Libraries/LibVideo/VP9/Parser.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -979,8 +979,8 @@ DecoderErrorOr<void> Parser::decode_block(u32 row, u32 col, BlockSubsize subsize
979979
// write out of bounds. This check seems consistent with libvpx.
980980
// See here:
981981
// https://github.com/webmproject/libvpx/blob/705bf9de8c96cfe5301451f1d7e5c90a41c64e5f/vp9/decoder/vp9_decodeframe.c#L917
982-
auto maximum_block_y = min(num_8x8_blocks_high_lookup[subsize], m_mi_rows - row);
983-
auto maximum_block_x = min(num_8x8_blocks_wide_lookup[subsize], m_mi_cols - col);
982+
auto maximum_block_y = min<u32>(num_8x8_blocks_high_lookup[subsize], m_mi_rows - row);
983+
auto maximum_block_x = min<u32>(num_8x8_blocks_wide_lookup[subsize], m_mi_cols - col);
984984

985985
for (size_t y = 0; y < maximum_block_y; y++) {
986986
for (size_t x = 0; x < maximum_block_x; x++) {
@@ -1337,7 +1337,7 @@ DecoderErrorOr<i32> Parser::read_mv_component(u8 component)
13371337
return (mv_sign ? -1 : 1) * static_cast<i32>(mag);
13381338
}
13391339

1340-
Gfx::Point<size_t> Parser::get_decoded_point_for_plane(u8 column, u8 row, u8 plane)
1340+
Gfx::Point<size_t> Parser::get_decoded_point_for_plane(u32 column, u32 row, u8 plane)
13411341
{
13421342
if (plane == 0)
13431343
return { column * 8, row * 8 };

Userland/Libraries/LibVideo/VP9/Parser.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ class Parser {
141141
void scale_mv(u8 ref_list, ReferenceFrame ref_frame);
142142
void add_mv_ref_list(u8 ref_list);
143143

144-
Gfx::Point<size_t> get_decoded_point_for_plane(u8 row, u8 column, u8 plane);
144+
Gfx::Point<size_t> get_decoded_point_for_plane(u32 row, u32 column, u8 plane);
145145
Gfx::Size<size_t> get_decoded_size_for_plane(u8 plane);
146146

147147
u8 m_profile { 0 };

0 commit comments

Comments
 (0)