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