mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-22 04:25:13 +00:00
LibVideo: Add CICP parsing to MatroskaReader
This will allow correct independent code points to be selected from VP9 in WebM, since the VP9 bitstream does not specify them independently.
This commit is contained in:
parent
cd127b65c3
commit
b87398341b
Notes:
sideshowbarker
2024-07-17 05:07:35 +09:00
Author: https://github.com/Zaggy1024 Commit: https://github.com/SerenityOS/serenity/commit/b87398341b Pull-request: https://github.com/SerenityOS/serenity/pull/15542 Reviewed-by: https://github.com/ADKaster ✅ Reviewed-by: https://github.com/Hendiadyoin1 Reviewed-by: https://github.com/davidot Reviewed-by: https://github.com/gmta
4 changed files with 106 additions and 1 deletions
|
@ -93,6 +93,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
auto uv_subsampling_x = vp9_decoder.get_uv_subsampling_x();
|
||||
Gfx::IntSize uv_size { y_size.width() >> uv_subsampling_x, y_size.height() >> uv_subsampling_y };
|
||||
auto cicp = vp9_decoder.get_cicp_color_space();
|
||||
video_track.color_format.replace_code_points_if_specified(cicp);
|
||||
cicp.default_code_points_if_unspecified(Video::ColorPrimaries::BT709, Video::TransferCharacteristics::BT709, Video::MatrixCoefficients::BT709);
|
||||
|
||||
auto color_converter_result = Video::ColorConverter::create(vp9_decoder.get_bit_depth(), cicp);
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <AK/OwnPtr.h>
|
||||
#include <AK/String.h>
|
||||
#include <AK/Utf8View.h>
|
||||
#include <LibVideo/Color/CodingIndependentCodePoints.h>
|
||||
|
||||
namespace Video {
|
||||
|
||||
|
@ -50,9 +51,49 @@ public:
|
|||
Metadata = 33,
|
||||
};
|
||||
|
||||
enum class ColorRange : u8 {
|
||||
Unspecified = 0,
|
||||
Broadcast = 1,
|
||||
Full = 2,
|
||||
UseCICP = 3, // defined by MatrixCoefficients / TransferCharacteristics
|
||||
};
|
||||
|
||||
struct ColorFormat {
|
||||
ColorPrimaries color_primaries = ColorPrimaries::Unspecified;
|
||||
TransferCharacteristics transfer_characteristics = TransferCharacteristics::Unspecified;
|
||||
MatrixCoefficients matrix_coefficients = MatrixCoefficients::Unspecified;
|
||||
u64 bits_per_channel = 0;
|
||||
ColorRange range = ColorRange::Unspecified;
|
||||
|
||||
Video::ColorRange full_or_studio_range() const
|
||||
{
|
||||
// FIXME: Figure out what UseCICP should do here. Matroska specification did not
|
||||
// seem to explain in the 'colour' section. When this is fixed, change
|
||||
// replace_code_points_if_specified to match.
|
||||
VERIFY(range == ColorRange::Full || range == ColorRange::Broadcast);
|
||||
if (range == ColorRange::Full)
|
||||
return Video::ColorRange::Full;
|
||||
return Video::ColorRange::Studio;
|
||||
}
|
||||
|
||||
void replace_code_points_if_specified(CodingIndependentCodePoints& cicp) const
|
||||
{
|
||||
if (color_primaries != ColorPrimaries::Unspecified)
|
||||
cicp.set_color_primaries(color_primaries);
|
||||
if (transfer_characteristics != TransferCharacteristics::Unspecified)
|
||||
cicp.set_transfer_characteristics(transfer_characteristics);
|
||||
if (matrix_coefficients != MatrixCoefficients::Unspecified)
|
||||
cicp.set_matrix_coefficients(matrix_coefficients);
|
||||
if (range != ColorRange::Unspecified && range != ColorRange::UseCICP)
|
||||
cicp.set_color_range(full_or_studio_range());
|
||||
}
|
||||
};
|
||||
|
||||
struct VideoTrack {
|
||||
u64 pixel_width;
|
||||
u64 pixel_height;
|
||||
|
||||
ColorFormat color_format;
|
||||
};
|
||||
|
||||
struct AudioTrack {
|
||||
|
@ -93,7 +134,7 @@ private:
|
|||
FlyString m_codec_id;
|
||||
|
||||
union {
|
||||
VideoTrack m_video_track;
|
||||
VideoTrack m_video_track {};
|
||||
AudioTrack m_audio_track;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -26,6 +26,8 @@ constexpr u32 CLUSTER_ELEMENT_ID = 0x1F43B675;
|
|||
constexpr u32 TIMESTAMP_SCALE_ID = 0x2AD7B1;
|
||||
constexpr u32 MUXING_APP_ID = 0x4D80;
|
||||
constexpr u32 WRITING_APP_ID = 0x5741;
|
||||
|
||||
// Tracks
|
||||
constexpr u32 TRACK_ENTRY_ID = 0xAE;
|
||||
constexpr u32 TRACK_NUMBER_ID = 0xD7;
|
||||
constexpr u32 TRACK_UID_ID = 0x73C5;
|
||||
|
@ -34,10 +36,21 @@ constexpr u32 TRACK_LANGUAGE_ID = 0x22B59C;
|
|||
constexpr u32 TRACK_CODEC_ID = 0x86;
|
||||
constexpr u32 TRACK_VIDEO_ID = 0xE0;
|
||||
constexpr u32 TRACK_AUDIO_ID = 0xE1;
|
||||
|
||||
// Video
|
||||
constexpr u32 PIXEL_WIDTH_ID = 0xB0;
|
||||
constexpr u32 PIXEL_HEIGHT_ID = 0xBA;
|
||||
constexpr u32 COLOR_ENTRY_ID = 0x55B0;
|
||||
constexpr u32 PRIMARIES_ID = 0x55BB;
|
||||
constexpr u32 TRANSFER_CHARACTERISTICS_ID = 0x55BA;
|
||||
constexpr u32 MATRIX_COEFFICIENTS_ID = 0x55B1;
|
||||
constexpr u32 BITS_PER_CHANNEL_ID = 0x55B2;
|
||||
|
||||
// Audio
|
||||
constexpr u32 CHANNELS_ID = 0x9F;
|
||||
constexpr u32 BIT_DEPTH_ID = 0x6264;
|
||||
|
||||
// Clusters
|
||||
constexpr u32 SIMPLE_BLOCK_ID = 0xA3;
|
||||
constexpr u32 TIMESTAMP_ID = 0xE7;
|
||||
|
||||
|
@ -264,6 +277,51 @@ OwnPtr<TrackEntry> MatroskaReader::parse_track_entry()
|
|||
return track_entry;
|
||||
}
|
||||
|
||||
Optional<TrackEntry::ColorFormat> MatroskaReader::parse_video_color_information()
|
||||
{
|
||||
TrackEntry::ColorFormat color_format {};
|
||||
|
||||
auto success = parse_master_element("Colour"sv, [&](u64 element_id) {
|
||||
switch (element_id) {
|
||||
case PRIMARIES_ID: {
|
||||
auto primaries_result = read_u64_element();
|
||||
CHECK_HAS_VALUE(primaries_result);
|
||||
color_format.color_primaries = static_cast<ColorPrimaries>(primaries_result.value());
|
||||
dbgln_if(MATROSKA_TRACE_DEBUG, "Read Colour's Primaries attribute: {}", color_primaries_to_string(color_format.color_primaries));
|
||||
break;
|
||||
}
|
||||
case TRANSFER_CHARACTERISTICS_ID: {
|
||||
auto transfer_characteristics_result = read_u64_element();
|
||||
CHECK_HAS_VALUE(transfer_characteristics_result);
|
||||
color_format.transfer_characteristics = static_cast<TransferCharacteristics>(transfer_characteristics_result.value());
|
||||
dbgln_if(MATROSKA_TRACE_DEBUG, "Read Colour's TransferCharacteristics attribute: {}", transfer_characteristics_to_string(color_format.transfer_characteristics));
|
||||
break;
|
||||
}
|
||||
case MATRIX_COEFFICIENTS_ID: {
|
||||
auto matrix_coefficients_result = read_u64_element();
|
||||
CHECK_HAS_VALUE(matrix_coefficients_result);
|
||||
color_format.matrix_coefficients = static_cast<MatrixCoefficients>(matrix_coefficients_result.value());
|
||||
dbgln_if(MATROSKA_TRACE_DEBUG, "Read Colour's MatrixCoefficients attribute: {}", matrix_coefficients_to_string(color_format.matrix_coefficients));
|
||||
break;
|
||||
}
|
||||
case BITS_PER_CHANNEL_ID: {
|
||||
auto bits_per_channel_result = read_u64_element();
|
||||
CHECK_HAS_VALUE(bits_per_channel_result);
|
||||
color_format.bits_per_channel = bits_per_channel_result.value();
|
||||
dbgln_if(MATROSKA_TRACE_DEBUG, "Read Colour's BitsPerChannel attribute: {}", color_format.bits_per_channel);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return read_unknown_element();
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
if (!success)
|
||||
return {};
|
||||
return color_format;
|
||||
}
|
||||
|
||||
Optional<TrackEntry::VideoTrack> MatroskaReader::parse_video_track_information()
|
||||
{
|
||||
TrackEntry::VideoTrack video_track {};
|
||||
|
@ -279,6 +337,10 @@ Optional<TrackEntry::VideoTrack> MatroskaReader::parse_video_track_information()
|
|||
CHECK_HAS_VALUE(pixel_height);
|
||||
video_track.pixel_height = pixel_height.value();
|
||||
dbgln_if(MATROSKA_TRACE_DEBUG, "Read VideoTrack's PixelHeight attribute: {}", pixel_height.value());
|
||||
} else if (element_id == COLOR_ENTRY_ID) {
|
||||
auto color_information_result = parse_video_color_information();
|
||||
CHECK_HAS_VALUE(color_information_result);
|
||||
video_track.color_format = color_information_result.value();
|
||||
} else {
|
||||
return read_unknown_element();
|
||||
}
|
||||
|
|
|
@ -159,6 +159,7 @@ private:
|
|||
bool parse_tracks(MatroskaDocument&);
|
||||
OwnPtr<TrackEntry> parse_track_entry();
|
||||
Optional<TrackEntry::VideoTrack> parse_video_track_information();
|
||||
Optional<TrackEntry::ColorFormat> parse_video_color_information();
|
||||
Optional<TrackEntry::AudioTrack> parse_audio_track_information();
|
||||
OwnPtr<Cluster> parse_cluster();
|
||||
OwnPtr<Block> parse_simple_block();
|
||||
|
|
Loading…
Add table
Reference in a new issue