1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef COLOR_UTILS_H_
18 
19 #define COLOR_UTILS_H_
20 
21 #include <stdint.h>
22 
23 #define STRINGIFY_ENUMS
24 
25 #include <media/stagefright/foundation/AMessage.h>
26 
27 #include <media/hardware/VideoAPI.h>
28 #include <system/graphics.h>
29 
30 namespace android {
31 
32 struct ColorUtils {
33     /*
34      * Media-platform color constants. MediaCodec uses (an extended version of) platform-defined
35      * constants that are derived from HAL_DATASPACE, since these are directly exposed to the user.
36      * We extend the values to maintain the richer set of information defined inside media
37      * containers and bitstreams that are not supported by the platform. We also expect vendors
38      * to extend some of these values with vendor-specific values. These are separated into a
39      * vendor-extension section so they won't collide with future platform values.
40      */
41 
42     /**
43      * graphic.h constants changed in Android 8.0 after ColorStandard values were already public
44      * in Android 7.0. We will not deal with the break in graphic.h here, but list the public
45      * Android SDK MediaFormat values here.
46      */
47     enum ColorStandard : uint32_t {
48         kColorStandardUnspecified =          0,
49         kColorStandardBT709 =                1,
50         kColorStandardBT601_625 =            2,
51         kColorStandardBT601_625_Unadjusted = 3, // not in SDK
52         kColorStandardBT601_525 =            4,
53         kColorStandardBT601_525_Unadjusted = 5, // not in SDK
54         kColorStandardBT2020 =               6,
55         kColorStandardBT2020Constant =       7, // not in SDK
56         kColorStandardBT470M =               8, // not in SDK
57         kColorStandardFilm =                 9, // not in SDK
58         kColorStandardDCI_P3 =               10, // not in SDK, new in Android 8.0
59 
60         /* This marks a section of color-standard values that are not supported by graphics HAL,
61            but track defined color primaries-matrix coefficient combinations in media.
62            These are stable for a given release. */
63         kColorStandardExtendedStart = 64,
64 
65         /* This marks a section of color-standard values that are not supported by graphics HAL
66            nor using media defined color primaries or matrix coefficients. These may differ per
67            device. */
68         kColorStandardVendorStart = 0x10000,
69     };
70 
71     enum ColorTransfer : uint32_t  {
72         kColorTransferUnspecified = 0,
73         kColorTransferLinear =      1,
74         kColorTransferSRGB =        2,
75         kColorTransferSMPTE_170M =  3, // not in SDK
76         kColorTransferGamma22 =     4, // not in SDK
77         kColorTransferGamma28 =     5, // not in SDK
78         kColorTransferST2084 =      6,
79         kColorTransferHLG =         7,
80         kColorTransferGamma26 =     8, // not in SDK, new in Android 8.0
81 
82         /* This marks a section of color-transfer values that are not supported by graphics HAL,
83            but track media-defined color-transfer. These are stable for a given release. */
84         kColorTransferExtendedStart = 32,
85 
86         /* This marks a section of color-transfer values that are not supported by graphics HAL
87            nor defined by media. These may differ per device. */
88         kColorTransferVendorStart = 0x10000,
89     };
90 
91     enum ColorRange : uint32_t  {
92         kColorRangeUnspecified = 0,
93         kColorRangeFull =        1,
94         kColorRangeLimited =     2,
95 
96         /* This marks a section of color-transfer values that are not supported by graphics HAL,
97            but track media-defined color-transfer. These are stable for a given release. */
98         kColorRangeExtendedStart = 8,
99 
100         /* This marks a section of color-transfer values that are not supported by graphics HAL
101            nor defined by media. These may differ per device. */
102         kColorRangeVendorStart = 0x10000,
103     };
104 
105     /*
106      * Static utilities for codec support
107      */
108 
109     // using int32_t for media range/standard/transfers to denote extended ranges
110     // wrap methods change invalid aspects to the Unspecified value
111     static int32_t wrapColorAspectsIntoColorStandard(
112             ColorAspects::Primaries primaries, ColorAspects::MatrixCoeffs coeffs);
113     static int32_t wrapColorAspectsIntoColorRange(ColorAspects::Range range);
114     static int32_t wrapColorAspectsIntoColorTransfer(ColorAspects::Transfer transfer);
115 
116     // unwrap methods change invalid aspects to the Other value
117     static status_t unwrapColorAspectsFromColorRange(
118             int32_t range, ColorAspects::Range *aspect);
119     static status_t unwrapColorAspectsFromColorTransfer(
120             int32_t transfer, ColorAspects::Transfer *aspect);
121     static status_t unwrapColorAspectsFromColorStandard(
122             int32_t standard,
123             ColorAspects::Primaries *primaries, ColorAspects::MatrixCoeffs *coeffs);
124 
125     static status_t convertPlatformColorAspectsToCodecAspects(
126             int32_t range, int32_t standard, int32_t transfer, ColorAspects &aspects);
127     static status_t convertCodecColorAspectsToPlatformAspects(
128             const ColorAspects &aspects, int32_t *range, int32_t *standard, int32_t *transfer);
129 
130     // converts Other values to Unspecified
131     static void convertCodecColorAspectsToIsoAspects(
132             const ColorAspects &aspects,
133             int32_t *primaries, int32_t *transfer, int32_t *coeffs, bool *fullRange);
134     // converts unsupported values to Other
135     static void convertIsoColorAspectsToCodecAspects(
136             int32_t primaries, int32_t transfer, int32_t coeffs, bool fullRange,
137             ColorAspects &aspects);
138 
139     // unpack a uint32_t to a full ColorAspects struct
140     static ColorAspects unpackToColorAspects(uint32_t packed);
141 
142     // pack a full ColorAspects struct into a uint32_t
143     static uint32_t packToU32(const ColorAspects &aspects);
144 
145     // updates Unspecified color aspects to their defaults based on the video size
146     static void setDefaultCodecColorAspectsIfNeeded(
147             ColorAspects &aspects, int32_t width, int32_t height);
148 
149     // it returns the closest dataSpace for given color |aspects|. if |mayExpand| is true, it allows
150     // returning a larger dataSpace that contains the color space given by |aspects|, and is better
151     // suited to blending. This requires implicit color space conversion on part of the device.
152     static android_dataspace getDataSpaceForColorAspects(ColorAspects &aspects, bool mayExpand);
153 
154     // converts |dataSpace| to a V0 enum, and returns true if dataSpace is an aspect-only value
155     static bool convertDataSpaceToV0(android_dataspace &dataSpace);
156 
157     // compares |aspect| to |orig|. Returns |true| if any aspects have changed, except if they
158     // changed to Unspecified value. It also sets the changed values to Unspecified in |aspect|.
159     static bool checkIfAspectsChangedAndUnspecifyThem(
160             ColorAspects &aspects, const ColorAspects &orig, bool usePlatformAspects = false);
161 
162     // finds color config in format, defaulting them to 0.
163     static void getColorConfigFromFormat(
164             const sp<AMessage> &format, int *range, int *standard, int *transfer);
165 
166     // copies existing color config from |source| to |target|.
167     static void copyColorConfig(const sp<AMessage> &source, sp<AMessage> &target);
168 
169     // finds color config in format as ColorAspects, defaulting them to 0.
170     static void getColorAspectsFromFormat(const sp<AMessage> &format, ColorAspects &aspects);
171 
172     // writes |aspects| into format. iff |force| is false, Unspecified values are not
173     // written.
174     static void setColorAspectsIntoFormat(
175             const ColorAspects &aspects, sp<AMessage> &format, bool force = false);
176 
177     // finds HDR metadata in format as HDRStaticInfo, defaulting them to 0.
178     // Return |true| if could find HDR metadata in format. Otherwise, return |false|.
179     static bool getHDRStaticInfoFromFormat(const sp<AMessage> &format, HDRStaticInfo *info);
180 
181     // writes |info| into format.
182     static void setHDRStaticInfoIntoFormat(const HDRStaticInfo &info, sp<AMessage> &format);
183 };
184 
185 inline static const char *asString(android::ColorUtils::ColorStandard i, const char *def = "??") {
186     using namespace android;
187     switch (i) {
188         case ColorUtils::kColorStandardUnspecified:          return "Unspecified";
189         case ColorUtils::kColorStandardBT709:                return "BT709";
190         case ColorUtils::kColorStandardBT601_625:            return "BT601_625";
191         case ColorUtils::kColorStandardBT601_625_Unadjusted: return "BT601_625_Unadjusted";
192         case ColorUtils::kColorStandardBT601_525:            return "BT601_525";
193         case ColorUtils::kColorStandardBT601_525_Unadjusted: return "BT601_525_Unadjusted";
194         case ColorUtils::kColorStandardBT2020:               return "BT2020";
195         case ColorUtils::kColorStandardBT2020Constant:       return "BT2020Constant";
196         case ColorUtils::kColorStandardBT470M:               return "BT470M";
197         case ColorUtils::kColorStandardFilm:                 return "Film";
198         case ColorUtils::kColorStandardDCI_P3:               return "DCI_P3";
199         default:                                             return def;
200     }
201 }
202 
203 inline static const char *asString(android::ColorUtils::ColorTransfer i, const char *def = "??") {
204     using namespace android;
205     switch (i) {
206         case ColorUtils::kColorTransferUnspecified: return "Unspecified";
207         case ColorUtils::kColorTransferLinear:      return "Linear";
208         case ColorUtils::kColorTransferSRGB:        return "SRGB";
209         case ColorUtils::kColorTransferSMPTE_170M:  return "SMPTE_170M";
210         case ColorUtils::kColorTransferGamma22:     return "Gamma22";
211         case ColorUtils::kColorTransferGamma28:     return "Gamma28";
212         case ColorUtils::kColorTransferST2084:      return "ST2084";
213         case ColorUtils::kColorTransferHLG:         return "HLG";
214         case ColorUtils::kColorTransferGamma26:     return "Gamma26";
215         default:                                    return def;
216     }
217 }
218 
219 inline static const char *asString(android::ColorUtils::ColorRange i, const char *def = "??") {
220     using namespace android;
221     switch (i) {
222         case ColorUtils::kColorRangeUnspecified: return "Unspecified";
223         case ColorUtils::kColorRangeFull:        return "Full";
224         case ColorUtils::kColorRangeLimited:     return "Limited";
225         default:                                 return def;
226     }
227 }
228 
229 }  // namespace android
230 
231 #endif  // COLOR_UTILS_H_
232 
233