1 /*
2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "api/video/color_space.h"
12
13 namespace webrtc {
14 namespace {
15 // Try to convert |enum_value| into the enum class T. |enum_bitmask| is created
16 // by the funciton below. Returns true if conversion was successful, false
17 // otherwise.
18 template <typename T>
SetFromUint8(uint8_t enum_value,uint64_t enum_bitmask,T * out)19 bool SetFromUint8(uint8_t enum_value, uint64_t enum_bitmask, T* out) {
20 if ((enum_value < 64) && ((enum_bitmask >> enum_value) & 1)) {
21 *out = static_cast<T>(enum_value);
22 return true;
23 }
24 return false;
25 }
26
27 // This function serves as an assert for the constexpr function below. It's on
28 // purpose not declared as constexpr so that it causes a build problem if enum
29 // values of 64 or above are used. The bitmask and the code generating it would
30 // have to be extended if the standard is updated to include enum values >= 64.
EnumMustBeLessThan64()31 int EnumMustBeLessThan64() {
32 return -1;
33 }
34
35 template <typename T, size_t N>
MakeMask(const int index,const int length,T (& values)[N])36 constexpr int MakeMask(const int index, const int length, T (&values)[N]) {
37 return length > 1
38 ? (MakeMask(index, 1, values) +
39 MakeMask(index + 1, length - 1, values))
40 : (static_cast<uint8_t>(values[index]) < 64
41 ? (uint64_t{1} << static_cast<uint8_t>(values[index]))
42 : EnumMustBeLessThan64());
43 }
44
45 // Create a bitmask where each bit corresponds to one potential enum value.
46 // |values| should be an array listing all possible enum values. The bit is set
47 // to one if the corresponding enum exists. Only works for enums with values
48 // less than 64.
49 template <typename T, size_t N>
CreateEnumBitmask(T (& values)[N])50 constexpr uint64_t CreateEnumBitmask(T (&values)[N]) {
51 return MakeMask(0, N, values);
52 }
53
SetChromaSitingFromUint8(uint8_t enum_value,ColorSpace::ChromaSiting * chroma_siting)54 bool SetChromaSitingFromUint8(uint8_t enum_value,
55 ColorSpace::ChromaSiting* chroma_siting) {
56 constexpr ColorSpace::ChromaSiting kChromaSitings[] = {
57 ColorSpace::ChromaSiting::kUnspecified,
58 ColorSpace::ChromaSiting::kCollocated, ColorSpace::ChromaSiting::kHalf};
59 constexpr uint64_t enum_bitmask = CreateEnumBitmask(kChromaSitings);
60
61 return SetFromUint8(enum_value, enum_bitmask, chroma_siting);
62 }
63
64 } // namespace
65
66 ColorSpace::ColorSpace() = default;
67 ColorSpace::ColorSpace(const ColorSpace& other) = default;
68 ColorSpace::ColorSpace(ColorSpace&& other) = default;
69 ColorSpace& ColorSpace::operator=(const ColorSpace& other) = default;
70
ColorSpace(PrimaryID primaries,TransferID transfer,MatrixID matrix,RangeID range)71 ColorSpace::ColorSpace(PrimaryID primaries,
72 TransferID transfer,
73 MatrixID matrix,
74 RangeID range)
75 : ColorSpace(primaries,
76 transfer,
77 matrix,
78 range,
79 ChromaSiting::kUnspecified,
80 ChromaSiting::kUnspecified,
81 nullptr) {}
82
ColorSpace(PrimaryID primaries,TransferID transfer,MatrixID matrix,RangeID range,ChromaSiting chroma_siting_horz,ChromaSiting chroma_siting_vert,const HdrMetadata * hdr_metadata)83 ColorSpace::ColorSpace(PrimaryID primaries,
84 TransferID transfer,
85 MatrixID matrix,
86 RangeID range,
87 ChromaSiting chroma_siting_horz,
88 ChromaSiting chroma_siting_vert,
89 const HdrMetadata* hdr_metadata)
90 : primaries_(primaries),
91 transfer_(transfer),
92 matrix_(matrix),
93 range_(range),
94 chroma_siting_horizontal_(chroma_siting_horz),
95 chroma_siting_vertical_(chroma_siting_vert),
96 hdr_metadata_(hdr_metadata ? absl::make_optional(*hdr_metadata)
97 : absl::nullopt) {}
98
primaries() const99 ColorSpace::PrimaryID ColorSpace::primaries() const {
100 return primaries_;
101 }
102
transfer() const103 ColorSpace::TransferID ColorSpace::transfer() const {
104 return transfer_;
105 }
106
matrix() const107 ColorSpace::MatrixID ColorSpace::matrix() const {
108 return matrix_;
109 }
110
range() const111 ColorSpace::RangeID ColorSpace::range() const {
112 return range_;
113 }
114
chroma_siting_horizontal() const115 ColorSpace::ChromaSiting ColorSpace::chroma_siting_horizontal() const {
116 return chroma_siting_horizontal_;
117 }
118
chroma_siting_vertical() const119 ColorSpace::ChromaSiting ColorSpace::chroma_siting_vertical() const {
120 return chroma_siting_vertical_;
121 }
122
hdr_metadata() const123 const HdrMetadata* ColorSpace::hdr_metadata() const {
124 return hdr_metadata_ ? &*hdr_metadata_ : nullptr;
125 }
126
set_primaries_from_uint8(uint8_t enum_value)127 bool ColorSpace::set_primaries_from_uint8(uint8_t enum_value) {
128 constexpr PrimaryID kPrimaryIds[] = {
129 PrimaryID::kBT709, PrimaryID::kUnspecified, PrimaryID::kBT470M,
130 PrimaryID::kBT470BG, PrimaryID::kSMPTE170M, PrimaryID::kSMPTE240M,
131 PrimaryID::kFILM, PrimaryID::kBT2020, PrimaryID::kSMPTEST428,
132 PrimaryID::kSMPTEST431, PrimaryID::kSMPTEST432, PrimaryID::kJEDECP22};
133 constexpr uint64_t enum_bitmask = CreateEnumBitmask(kPrimaryIds);
134
135 return SetFromUint8(enum_value, enum_bitmask, &primaries_);
136 }
137
set_transfer_from_uint8(uint8_t enum_value)138 bool ColorSpace::set_transfer_from_uint8(uint8_t enum_value) {
139 constexpr TransferID kTransferIds[] = {
140 TransferID::kBT709, TransferID::kUnspecified,
141 TransferID::kGAMMA22, TransferID::kGAMMA28,
142 TransferID::kSMPTE170M, TransferID::kSMPTE240M,
143 TransferID::kLINEAR, TransferID::kLOG,
144 TransferID::kLOG_SQRT, TransferID::kIEC61966_2_4,
145 TransferID::kBT1361_ECG, TransferID::kIEC61966_2_1,
146 TransferID::kBT2020_10, TransferID::kBT2020_12,
147 TransferID::kSMPTEST2084, TransferID::kSMPTEST428,
148 TransferID::kARIB_STD_B67};
149 constexpr uint64_t enum_bitmask = CreateEnumBitmask(kTransferIds);
150
151 return SetFromUint8(enum_value, enum_bitmask, &transfer_);
152 }
153
set_matrix_from_uint8(uint8_t enum_value)154 bool ColorSpace::set_matrix_from_uint8(uint8_t enum_value) {
155 constexpr MatrixID kMatrixIds[] = {
156 MatrixID::kRGB, MatrixID::kBT709, MatrixID::kUnspecified,
157 MatrixID::kFCC, MatrixID::kBT470BG, MatrixID::kSMPTE170M,
158 MatrixID::kSMPTE240M, MatrixID::kYCOCG, MatrixID::kBT2020_NCL,
159 MatrixID::kBT2020_CL, MatrixID::kSMPTE2085, MatrixID::kCDNCLS,
160 MatrixID::kCDCLS, MatrixID::kBT2100_ICTCP};
161 constexpr uint64_t enum_bitmask = CreateEnumBitmask(kMatrixIds);
162
163 return SetFromUint8(enum_value, enum_bitmask, &matrix_);
164 }
165
set_range_from_uint8(uint8_t enum_value)166 bool ColorSpace::set_range_from_uint8(uint8_t enum_value) {
167 constexpr RangeID kRangeIds[] = {RangeID::kInvalid, RangeID::kLimited,
168 RangeID::kFull, RangeID::kDerived};
169 constexpr uint64_t enum_bitmask = CreateEnumBitmask(kRangeIds);
170
171 return SetFromUint8(enum_value, enum_bitmask, &range_);
172 }
173
set_chroma_siting_horizontal_from_uint8(uint8_t enum_value)174 bool ColorSpace::set_chroma_siting_horizontal_from_uint8(uint8_t enum_value) {
175 return SetChromaSitingFromUint8(enum_value, &chroma_siting_horizontal_);
176 }
177
set_chroma_siting_vertical_from_uint8(uint8_t enum_value)178 bool ColorSpace::set_chroma_siting_vertical_from_uint8(uint8_t enum_value) {
179 return SetChromaSitingFromUint8(enum_value, &chroma_siting_vertical_);
180 }
181
set_hdr_metadata(const HdrMetadata * hdr_metadata)182 void ColorSpace::set_hdr_metadata(const HdrMetadata* hdr_metadata) {
183 hdr_metadata_ =
184 hdr_metadata ? absl::make_optional(*hdr_metadata) : absl::nullopt;
185 }
186
187 } // namespace webrtc
188