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