blob: d91482457d4cdf759959e425470fd94ff670e276 [file] [log] [blame]
Avi Drissman3e1a26c2022-09-15 20:26:031// Copyright 2022 The Chromium Authors
Christopher Cameronb69145262022-09-13 17:06:392// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Elly Fong-Jonesa8ea66f12024-07-24 18:37:105#ifdef UNSAFE_BUFFERS_BUILD
6// TODO(crbug.com/354829279): Remove this and convert code to safer constructs.
7#pragma allow_unsafe_buffers
8#endif
9
Christopher Cameronb69145262022-09-13 17:06:3910#include "ui/gfx/hdr_metadata_mac.h"
11#include "ui/gfx/hdr_metadata.h"
12
13#include <simd/simd.h>
14
15namespace gfx {
16
Avi Drissman28154a62023-08-22 04:06:4517base::apple::ScopedCFTypeRef<CFDataRef> GenerateContentLightLevelInfo(
Arthur Sonzogni3eb9fd512024-02-09 12:20:4318 const std::optional<gfx::HDRMetadata>& hdr_metadata) {
Christopher Cameron52f82ba02023-06-08 19:06:0419 if (!hdr_metadata || !hdr_metadata->cta_861_3 ||
20 hdr_metadata->cta_861_3->max_content_light_level == 0.f ||
21 hdr_metadata->cta_861_3->max_frame_average_light_level == 0.f) {
Avi Drissman28154a62023-08-22 04:06:4522 return base::apple::ScopedCFTypeRef<CFDataRef>();
Christopher Camerone08ac3e32022-10-19 11:37:4623 }
24
Christopher Cameronb69145262022-09-13 17:06:3925 // This is a SMPTEST2086 Content Light Level Information box.
26 struct ContentLightLevelInfoSEI {
27 uint16_t max_content_light_level;
28 uint16_t max_frame_average_light_level;
29 } __attribute__((packed, aligned(2)));
30 static_assert(sizeof(ContentLightLevelInfoSEI) == 4, "Must be 4 bytes");
31
32 // Values are stored in big-endian...
33 ContentLightLevelInfoSEI sei;
34 sei.max_content_light_level =
Christopher Cameron52f82ba02023-06-08 19:06:0435 __builtin_bswap16(hdr_metadata->cta_861_3->max_content_light_level);
Christopher Cameronb69145262022-09-13 17:06:3936 sei.max_frame_average_light_level =
Christopher Cameron52f82ba02023-06-08 19:06:0437 __builtin_bswap16(hdr_metadata->cta_861_3->max_frame_average_light_level);
Christopher Cameronb69145262022-09-13 17:06:3938
Avi Drissman28154a62023-08-22 04:06:4539 return base::apple::ScopedCFTypeRef<CFDataRef>(
Christopher Cameronb69145262022-09-13 17:06:3940 CFDataCreate(nullptr, reinterpret_cast<const UInt8*>(&sei), 4));
41}
42
Avi Drissman28154a62023-08-22 04:06:4543base::apple::ScopedCFTypeRef<CFDataRef> GenerateMasteringDisplayColorVolume(
Arthur Sonzogni3eb9fd512024-02-09 12:20:4344 const std::optional<gfx::HDRMetadata>& hdr_metadata) {
Christopher Cameronb69145262022-09-13 17:06:3945 // This is a SMPTEST2086 Mastering Display Color Volume box.
46 struct MasteringDisplayColorVolumeSEI {
47 vector_ushort2 primaries[3]; // GBR
48 vector_ushort2 white_point;
49 uint32_t luminance_max;
50 uint32_t luminance_min;
51 } __attribute__((packed, aligned(4)));
52 static_assert(sizeof(MasteringDisplayColorVolumeSEI) == 24,
53 "Must be 24 bytes");
54
Christopher Camerone08ac3e32022-10-19 11:37:4655 // Make a copy with all values populated, and which we can manipulate.
Christopher Cameronef71a52a2023-05-18 15:30:1856 auto md =
57 HDRMetadata::PopulateUnspecifiedWithDefaults(hdr_metadata).smpte_st_2086;
Christopher Cameronb69145262022-09-13 17:06:3958
59 constexpr float kColorCoordinateUpperBound = 50000.0f;
Christopher Cameronb69145262022-09-13 17:06:3960 constexpr float kUnitOfMasteringLuminance = 10000.0f;
Christopher Cameron52f82ba02023-06-08 19:06:0461 md->luminance_max *= kUnitOfMasteringLuminance;
62 md->luminance_min *= kUnitOfMasteringLuminance;
Christopher Cameronb69145262022-09-13 17:06:3963
64 // Values are stored in big-endian...
65 MasteringDisplayColorVolumeSEI sei;
Christopher Cameron52f82ba02023-06-08 19:06:0466 const auto& primaries = md->primaries;
Christopher Cameron22d153d2022-11-11 21:18:4667 sei.primaries[0].x =
68 __builtin_bswap16(primaries.fGX * kColorCoordinateUpperBound + 0.5f);
69 sei.primaries[0].y =
70 __builtin_bswap16(primaries.fGY * kColorCoordinateUpperBound + 0.5f);
71 sei.primaries[1].x =
72 __builtin_bswap16(primaries.fBX * kColorCoordinateUpperBound + 0.5f);
73 sei.primaries[1].y =
74 __builtin_bswap16(primaries.fBY * kColorCoordinateUpperBound + 0.5f);
75 sei.primaries[2].x =
76 __builtin_bswap16(primaries.fRX * kColorCoordinateUpperBound + 0.5f);
77 sei.primaries[2].y =
78 __builtin_bswap16(primaries.fRY * kColorCoordinateUpperBound + 0.5f);
79 sei.white_point.x =
80 __builtin_bswap16(primaries.fWX * kColorCoordinateUpperBound + 0.5f);
81 sei.white_point.y =
82 __builtin_bswap16(primaries.fWY * kColorCoordinateUpperBound + 0.5f);
Christopher Cameron52f82ba02023-06-08 19:06:0483 sei.luminance_max = __builtin_bswap32(md->luminance_max + 0.5f);
84 sei.luminance_min = __builtin_bswap32(md->luminance_min + 0.5f);
Christopher Cameronb69145262022-09-13 17:06:3985
Avi Drissman28154a62023-08-22 04:06:4586 return base::apple::ScopedCFTypeRef<CFDataRef>(
Christopher Cameronb69145262022-09-13 17:06:3987 CFDataCreate(nullptr, reinterpret_cast<const UInt8*>(&sei), 24));
88}
89
Christopher Cameron1fceb6a2024-11-27 15:38:1590base::apple::ScopedCFTypeRef<CFDataRef> GenerateAmbientViewingEnvironment() {
91 // The AMVE box is documented in Technical Note 3145.
92 // https://developer.apple.com/documentation/technotes/tn3145-hdr-video-metadata
93 struct AmveSEI {
94 uint32_t ambient_illuminance;
95 uint16_t ambient_light_x;
96 uint16_t ambient_light_y;
97 } __attribute__((packed, aligned(2)));
98 static_assert(sizeof(AmveSEI) == 8, "Must be 8 bytes");
99
100 // The actual values specified in the AMVE box have no effect on rendering. In
101 // fact, the full box does not even need to be specified (just an single byte
102 // set to 0 will have the same effect). Use the default values set by iPhone
103 // HDR videos (314 nits, just to be safe.
104 AmveSEI sei;