LibMedia: Move CICP values from CodedFrame to Track

All our current demuxers have these constant for an entire track, so we
don't need to get them for every frame we output.
This commit is contained in:
Zaggy1024 2025-11-03 18:13:48 -06:00 committed by Jelle Raaijmakers
parent 22585db022
commit 634e5ff491
6 changed files with 31 additions and 34 deletions

View file

@ -6,21 +6,15 @@
#pragma once
#include <LibMedia/Color/CodingIndependentCodePoints.h>
namespace Media {
class CodedVideoFrameData {
public:
CodedVideoFrameData(CodingIndependentCodePoints container_cicp)
: m_container_cicp(container_cicp)
CodedVideoFrameData()
{
}
CodingIndependentCodePoints container_cicp() const { return m_container_cicp; }
private:
CodingIndependentCodePoints m_container_cicp;
};
}

View file

@ -83,6 +83,7 @@ static Track track_from_track_entry(TrackEntry const& track_entry)
track.set_video_data({
.pixel_width = video_track->pixel_width,
.pixel_height = video_track->pixel_height,
.cicp = video_track->color_format.to_cicp(),
});
}
}
@ -208,8 +209,7 @@ DecoderErrorOr<CodedFrame> MatroskaDemuxer::get_next_sample_for_track(Track cons
auto flags = status.block->only_keyframes() ? FrameFlags::Keyframe : FrameFlags::None;
auto aux_data = [&] -> CodedFrame::AuxiliaryData {
if (track.type() == TrackType::Video) {
auto cicp = MUST(m_reader.track_for_track_number(track.identifier()))->video_track()->color_format.to_cicp();
return CodedVideoFrameData(cicp);
return CodedVideoFrameData();
}
if (track.type() == TrackType::Audio) {
return CodedAudioFrameData();

View file

@ -147,9 +147,24 @@ DecoderErrorOr<Track> FFmpegDemuxer::get_track_for_stream_index(u32 stream_index
Track track(type, stream_index, name, language);
if (type == TrackType::Video) {
auto color_primaries = static_cast<ColorPrimaries>(stream.codecpar->color_primaries);
auto transfer_characteristics = static_cast<TransferCharacteristics>(stream.codecpar->color_trc);
auto matrix_coefficients = static_cast<MatrixCoefficients>(stream.codecpar->color_space);
auto color_range = [stream] {
switch (stream.codecpar->color_range) {
case AVColorRange::AVCOL_RANGE_MPEG:
return VideoFullRangeFlag::Studio;
case AVColorRange::AVCOL_RANGE_JPEG:
return VideoFullRangeFlag::Full;
default:
return VideoFullRangeFlag::Unspecified;
}
}();
track.set_video_data({
.pixel_width = static_cast<u64>(stream.codecpar->width),
.pixel_height = static_cast<u64>(stream.codecpar->height),
.cicp = CodingIndependentCodePoints(color_primaries, transfer_characteristics, matrix_coefficients, color_range),
});
}
@ -242,20 +257,7 @@ DecoderErrorOr<CodedFrame> FFmpegDemuxer::get_next_sample_for_track(Track const&
auto auxiliary_data = [&]() -> CodedFrame::AuxiliaryData {
if (track.type() == TrackType::Video) {
auto color_primaries = static_cast<ColorPrimaries>(stream.codecpar->color_primaries);
auto transfer_characteristics = static_cast<TransferCharacteristics>(stream.codecpar->color_trc);
auto matrix_coefficients = static_cast<MatrixCoefficients>(stream.codecpar->color_space);
auto color_range = [stream] {
switch (stream.codecpar->color_range) {
case AVColorRange::AVCOL_RANGE_MPEG:
return VideoFullRangeFlag::Studio;
case AVColorRange::AVCOL_RANGE_JPEG:
return VideoFullRangeFlag::Full;
default:
return VideoFullRangeFlag::Unspecified;
}
}();
return CodedVideoFrameData(CodingIndependentCodePoints(color_primaries, transfer_characteristics, matrix_coefficients, color_range));
return CodedVideoFrameData();
}
if (track.type() == TrackType::Audio) {
return CodedAudioFrameData();

View file

@ -124,26 +124,25 @@ bool VideoDataProvider::ThreadData::should_thread_exit() const
return m_exit;
}
void VideoDataProvider::ThreadData::set_cicp_values(VideoFrame& frame, CodedFrame const& coded_frame)
void VideoDataProvider::ThreadData::set_cicp_values(VideoFrame& frame)
{
// Convert the frame for display.
auto& cicp = frame.cicp();
auto container_cicp = coded_frame.auxiliary_data().get<CodedVideoFrameData>().container_cicp();
cicp.adopt_specified_values(container_cicp);
cicp.default_code_points_if_unspecified({ ColorPrimaries::BT709, TransferCharacteristics::BT709, MatrixCoefficients::BT709, VideoFullRangeFlag::Studio });
auto& frame_cicp = frame.cicp();
auto const& container_cicp = m_track.video_data().cicp;
frame_cicp.adopt_specified_values(container_cicp);
frame_cicp.default_code_points_if_unspecified({ ColorPrimaries::BT709, TransferCharacteristics::BT709, MatrixCoefficients::BT709, VideoFullRangeFlag::Studio });
// BT.470 M, B/G, BT.601, BT.709 and BT.2020 have a similar transfer function to sRGB, so other applications
// (Chromium, VLC) forgo transfer characteristics conversion. We will emulate that behavior by
// handling those as sRGB instead, which causes no transfer function change in the output,
// unless display color management is later implemented.
switch (cicp.transfer_characteristics()) {
switch (frame_cicp.transfer_characteristics()) {
case TransferCharacteristics::BT470BG:
case TransferCharacteristics::BT470M:
case TransferCharacteristics::BT601:
case TransferCharacteristics::BT709:
case TransferCharacteristics::BT2020BitDepth10:
case TransferCharacteristics::BT2020BitDepth12:
cicp.set_transfer_characteristics(TransferCharacteristics::SRGB);
frame_cicp.set_transfer_characteristics(TransferCharacteristics::SRGB);
break;
default:
break;
@ -304,7 +303,7 @@ bool VideoDataProvider::ThreadData::handle_seek()
}
auto current_frame = frame_result.release_value();
set_cicp_values(*current_frame, coded_frame);
set_cicp_values(*current_frame);
if (is_desired_decoded_frame(*current_frame)) {
auto locker = take_lock();
m_queue.clear();
@ -383,7 +382,7 @@ void VideoDataProvider::ThreadData::push_data_and_decode_some_frames()
}
auto frame = frame_result.release_value();
set_cicp_values(*frame, coded_frame);
set_cicp_values(*frame);
auto bitmap_result = frame->to_bitmap();
if (bitmap_result.is_error()) {

View file

@ -64,7 +64,7 @@ private:
void seek(AK::Duration timestamp, SeekMode, SeekCompletionHandler&&);
bool should_thread_exit() const;
static void set_cicp_values(VideoFrame&, CodedFrame const&);
void set_cicp_values(VideoFrame&);
void queue_frame(TimedImage&&);
bool handle_seek();
template<typename T>

View file

@ -12,6 +12,7 @@
#include <AK/Types.h>
#include <AK/Utf16String.h>
#include <AK/Variant.h>
#include <LibMedia/Color/CodingIndependentCodePoints.h>
namespace Media {
@ -26,6 +27,7 @@ class Track {
struct VideoData {
u64 pixel_width { 0 };
u64 pixel_height { 0 };
CodingIndependentCodePoints cicp;
};
public: