0

gfx::HDRMetadata: Add AGTM support

Unlike other HDR metadata structures, the parsing of AGTM is nontrivial,
and so it is plumbed in un-parsed form until it needs to be consumed.

Bug: 395659818
Change-Id: I03dcd113098ac9073ca75ddced45c58b057e98a8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6249701
Reviewed-by: Xiaohan Wang <xhwang@chromium.org>
Commit-Queue: ccameron chromium <ccameron@chromium.org>
Reviewed-by: Antonio Sartori <antoniosartori@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1421354}
This commit is contained in:
Christopher Cameron
2025-02-18 06:07:07 -08:00
committed by Chromium LUCI CQ
parent 822406b57e
commit 5a2a2b45eb
11 changed files with 138 additions and 11 deletions

@ -13,6 +13,7 @@ namespace media {
WebMColorMetadata::WebMColorMetadata() = default;
WebMColorMetadata::WebMColorMetadata(const WebMColorMetadata& rhs) = default;
WebMColorMetadata::~WebMColorMetadata() = default;
WebMColorVolumeMetadataParser::WebMColorVolumeMetadataParser() = default;
WebMColorVolumeMetadataParser::~WebMColorVolumeMetadataParser() = default;

@ -30,6 +30,7 @@ struct MEDIA_EXPORT WebMColorMetadata {
WebMColorMetadata();
WebMColorMetadata(const WebMColorMetadata& rhs);
~WebMColorMetadata();
};
// Parser for WebM MasteringMetadata within Colour element:

@ -171,6 +171,9 @@ float ToLinear(ColorSpace::TransferID id, float v) {
} // namespace
ColorTransform::RuntimeOptions::RuntimeOptions() = default;
ColorTransform::RuntimeOptions::~RuntimeOptions() = default;
class ColorTransformMatrix;
class ColorTransformSkTransferFn;
class ColorTransformFromLinear;

@ -38,7 +38,12 @@ class COLOR_SPACE_EXPORT ColorTransform {
// Parameters that may be specified when the transform is applied. Changing
// these parameters will change the uniforms for a single SkShader.
struct RuntimeOptions {
struct COLOR_SPACE_EXPORT RuntimeOptions {
RuntimeOptions();
RuntimeOptions(const RuntimeOptions&) = delete;
RuntimeOptions& operator=(const RuntimeOptions&) = delete;
~RuntimeOptions();
// Offset and multiplier used when sampling textures;
float offset = 0.f;
float multiplier = 1.f;

@ -9,6 +9,7 @@
#include "skia/ext/skcolorspace_primaries.h"
#include "third_party/skia/include/core/SkColorSpace.h"
#include "third_party/skia/include/core/SkData.h"
namespace gfx {
@ -50,6 +51,43 @@ std::string HdrMetadataExtendedRange::ToString() const {
return ss.str();
}
HdrMetadataAgtm::HdrMetadataAgtm() = default;
HdrMetadataAgtm::HdrMetadataAgtm(const void* payload, size_t size)
: payload(SkData::MakeWithCopy(payload, size)) {}
HdrMetadataAgtm::HdrMetadataAgtm(sk_sp<SkData> payload)
: payload(std::move(payload)) {}
HdrMetadataAgtm::HdrMetadataAgtm(const HdrMetadataAgtm& other) = default;
HdrMetadataAgtm& HdrMetadataAgtm::operator=(const HdrMetadataAgtm& other) =
default;
HdrMetadataAgtm::~HdrMetadataAgtm() = default;
std::string HdrMetadataAgtm::ToString() const {
return "agtm placeholder";
}
bool HdrMetadataAgtm::operator==(const HdrMetadataAgtm& rhs) const {
if (!payload) {
return !rhs.payload;
}
return payload->equals(rhs.payload.get());
}
HDRMetadata::HDRMetadata() = default;
HDRMetadata::HDRMetadata(const HdrMetadataSmpteSt2086& smpte_st_2086,
const HdrMetadataCta861_3& cta_861_3)
: smpte_st_2086(smpte_st_2086), cta_861_3(cta_861_3) {}
HDRMetadata::HDRMetadata(const HdrMetadataSmpteSt2086& smpte_st_2086)
: smpte_st_2086(smpte_st_2086) {}
HDRMetadata::HDRMetadata(const HdrMetadataCta861_3& cta_861_3)
: cta_861_3(cta_861_3) {}
HDRMetadata::HDRMetadata(const HDRMetadata& rhs) = default;
HDRMetadata& HDRMetadata::operator=(const HDRMetadata& rhs) = default;
HDRMetadata::~HDRMetadata() = default;
// static
HDRMetadata HDRMetadata::PopulateUnspecifiedWithDefaults(
const std::optional<gfx::HDRMetadata>& hdr_metadata) {
@ -94,6 +132,9 @@ std::string HDRMetadata::ToString() const {
if (extended_range) {
ss << "extended_range:" << extended_range->ToString() << ", ";
}
if (agtm) {
ss << "agtm:" << agtm->ToString() << ", ";
}
ss << "}";
return ss.str();
}

@ -128,6 +128,23 @@ struct COLOR_SPACE_EXPORT HdrMetadataExtendedRange {
}
};
struct COLOR_SPACE_EXPORT HdrMetadataAgtm {
HdrMetadataAgtm();
explicit HdrMetadataAgtm(sk_sp<SkData> payload);
HdrMetadataAgtm(const void* payload, size_t size);
HdrMetadataAgtm(const HdrMetadataAgtm& other);
HdrMetadataAgtm& operator=(const HdrMetadataAgtm& other);
~HdrMetadataAgtm();
std::string ToString() const;
bool operator==(const HdrMetadataAgtm& rhs) const;
bool operator!=(const HdrMetadataAgtm& rhs) const { return !(*this == rhs); }
// The raw encoded AGTM metadata payload.
sk_sp<SkData> payload;
};
// HDR metadata common for HDR10 and WebM/VP9-based HDR formats.
struct COLOR_SPACE_EXPORT HDRMetadata {
// Mastering display color volume (MDCV) metadata.
@ -142,16 +159,17 @@ struct COLOR_SPACE_EXPORT HDRMetadata {
// Brightness points for extended range color spaces.
std::optional<HdrMetadataExtendedRange> extended_range;
HDRMetadata() = default;
// Agtm metadata.
std::optional<HdrMetadataAgtm> agtm;
HDRMetadata();
HDRMetadata(const HdrMetadataSmpteSt2086& smpte_st_2086,
const HdrMetadataCta861_3& cta_861_3)
: smpte_st_2086(smpte_st_2086), cta_861_3(cta_861_3) {}
explicit HDRMetadata(const HdrMetadataSmpteSt2086& smpte_st_2086)
: smpte_st_2086(smpte_st_2086) {}
explicit HDRMetadata(const HdrMetadataCta861_3& cta_861_3)
: cta_861_3(cta_861_3) {}
HDRMetadata(const HDRMetadata& rhs) = default;
HDRMetadata& operator=(const HDRMetadata& rhs) = default;
const HdrMetadataCta861_3& cta_861_3);
explicit HDRMetadata(const HdrMetadataSmpteSt2086& smpte_st_2086);
explicit HDRMetadata(const HdrMetadataCta861_3& cta_861_3);
HDRMetadata(const HDRMetadata& rhs);
HDRMetadata& operator=(const HDRMetadata& rhs);
~HDRMetadata();
bool IsValid() const {
return (cta_861_3 && cta_861_3->IsValid()) ||
@ -171,7 +189,8 @@ struct COLOR_SPACE_EXPORT HDRMetadata {
bool operator==(const HDRMetadata& rhs) const {
return cta_861_3 == rhs.cta_861_3 && smpte_st_2086 == rhs.smpte_st_2086 &&
ndwl == rhs.ndwl && extended_range == rhs.extended_range;
ndwl == rhs.ndwl && extended_range == rhs.extended_range &&
agtm == rhs.agtm;
}
bool operator!=(const HDRMetadata& rhs) const { return !(*this == rhs); }

@ -503,6 +503,10 @@ mojom("hdr_metadata") {
mojom = "gfx.mojom.HdrMetadataExtendedRange"
cpp = "::gfx::HdrMetadataExtendedRange"
},
{
mojom = "gfx.mojom.HdrMetadataAgtm"
cpp = "::gfx::HdrMetadataAgtm"
},
{
mojom = "gfx.mojom.HDRMetadata"
cpp = "::gfx::HDRMetadata"

@ -34,10 +34,17 @@ struct HdrMetadataExtendedRange {
float desired_headroom;
};
// Mojo equivalent of gfx::HdrMetadataAgtm. No validation is done on any of
// these values during deserialization.
struct HdrMetadataAgtm {
array<uint8> payload;
};
// Mojo equivalent of gfx::HDRMetadata.
struct HDRMetadata {
HdrMetadataSmpteSt2086? smpte_st_2086;
HdrMetadataCta861_3? cta_861_3;
HdrMetadataNdwl? ndwl;
HdrMetadataExtendedRange? extended_range;
HdrMetadataAgtm? agtm;
};

@ -42,6 +42,17 @@ bool StructTraits<gfx::mojom::HdrMetadataExtendedRangeDataView,
return true;
}
bool StructTraits<gfx::mojom::HdrMetadataAgtmDataView, gfx::HdrMetadataAgtm>::
Read(gfx::mojom::HdrMetadataAgtmDataView data,
gfx::HdrMetadataAgtm* output) {
ArrayDataView<uint8_t> payload;
data.GetPayloadDataView(&payload);
if (!payload.is_null()) {
output->payload = SkData::MakeWithCopy(payload.data(), payload.size());
}
return true;
}
bool StructTraits<gfx::mojom::HDRMetadataDataView, gfx::HDRMetadata>::Read(
gfx::mojom::HDRMetadataDataView data,
gfx::HDRMetadata* output) {
@ -57,6 +68,9 @@ bool StructTraits<gfx::mojom::HDRMetadataDataView, gfx::HDRMetadata>::Read(
if (!data.ReadExtendedRange(&output->extended_range)) {
return false;
}
if (!data.ReadAgtm(&output->agtm)) {
return false;
}
return true;
}

@ -5,6 +5,7 @@
#ifndef UI_GFX_MOJOM_HDR_METADATA_MOJOM_TRAITS_H_
#define UI_GFX_MOJOM_HDR_METADATA_MOJOM_TRAITS_H_
#include "third_party/skia/include/core/SkData.h"
#include "ui/gfx/hdr_metadata.h"
#include "ui/gfx/mojom/hdr_metadata.mojom.h"
@ -65,6 +66,21 @@ struct StructTraits<gfx::mojom::HdrMetadataExtendedRangeDataView,
gfx::HdrMetadataExtendedRange* output);
};
template <>
struct StructTraits<gfx::mojom::HdrMetadataAgtmDataView, gfx::HdrMetadataAgtm> {
static std::vector<uint8_t> payload(const gfx::HdrMetadataAgtm& input) {
std::vector<uint8_t> result;
if (input.payload) {
result.assign(input.payload->bytes(),
std::next(input.payload->bytes(), input.payload->size()));
}
return result;
}
static bool Read(gfx::mojom::HdrMetadataAgtmDataView data,
gfx::HdrMetadataAgtm* output);
};
template <>
struct StructTraits<gfx::mojom::HDRMetadataDataView, gfx::HDRMetadata> {
static const std::optional<gfx::HdrMetadataCta861_3>& cta_861_3(
@ -83,6 +99,10 @@ struct StructTraits<gfx::mojom::HDRMetadataDataView, gfx::HDRMetadata> {
const gfx::HDRMetadata& input) {
return input.extended_range;
}
static const std::optional<gfx::HdrMetadataAgtm>& agtm(
const gfx::HDRMetadata& input) {
return input.agtm;
}
static bool Read(gfx::mojom::HDRMetadataDataView data,
gfx::HDRMetadata* output);

@ -343,21 +343,33 @@ TEST_F(StructTraitsTest, HDRMetadata) {
// Include CTA 861.3.
input.cta_861_3.emplace(123, 456);
EXPECT_NE(input, output);
mojo::test::SerializeAndDeserialize<gfx::mojom::HDRMetadata>(input, output);
EXPECT_EQ(input, output);
// Include SMPTE ST 2086.
input.smpte_st_2086.emplace(SkNamedPrimaries::kRec2020, 789, 123);
EXPECT_NE(input, output);
mojo::test::SerializeAndDeserialize<gfx::mojom::HDRMetadata>(input, output);
EXPECT_EQ(input, output);
// Include SDR white level.
input.ndwl.emplace(123.f);
EXPECT_NE(input, output);
mojo::test::SerializeAndDeserialize<gfx::mojom::HDRMetadata>(input, output);
EXPECT_EQ(input, output);
// Include extended range.
input.extended_range.emplace(10.f, 4.f);
EXPECT_NE(input, output);
mojo::test::SerializeAndDeserialize<gfx::mojom::HDRMetadata>(input, output);
EXPECT_EQ(input, output);
// Include agtm.
const size_t agtm_size = 4;
const uint8_t agtm_data[agtm_size] = {0xde, 0xad, 0xbe, 0xef};
input.agtm.emplace(agtm_data, agtm_size);
EXPECT_NE(input, output);
mojo::test::SerializeAndDeserialize<gfx::mojom::HDRMetadata>(input, output);
EXPECT_EQ(input, output);
}