blob: b889a02f9dff65346416ac7c31a12571bf7b6c22 [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef COLOR_UTILS_H_
#define COLOR_UTILS_H_
#include <stdint.h>
#define STRINGIFY_ENUMS
#include <media/stagefright/foundation/AMessage.h>
#include <media/hardware/VideoAPI.h>
#include <system/graphics.h>
namespace android {
struct ColorUtils {
/*
* Media-platform color constants. MediaCodec uses (an extended version of) platform-defined
* constants that are derived from HAL_DATASPACE, since these are directly exposed to the user.
* We extend the values to maintain the richer set of information defined inside media
* containers and bitstreams that are not supported by the platform. We also expect vendors
* to extend some of these values with vendor-specific values. These are separated into a
* vendor-extension section so they won't collide with future platform values.
*/
#define GET_HAL_ENUM(class, name) HAL_DATASPACE_##class##name
#define GET_HAL_BITFIELD(class, name) (GET_HAL_ENUM(class, _##name) >> GET_HAL_ENUM(class, _SHIFT))
enum ColorStandard : uint32_t {
kColorStandardUnspecified = GET_HAL_BITFIELD(STANDARD, UNSPECIFIED),
kColorStandardBT709 = GET_HAL_BITFIELD(STANDARD, BT709),
kColorStandardBT601_625 = GET_HAL_BITFIELD(STANDARD, BT601_625),
kColorStandardBT601_625_Unadjusted = GET_HAL_BITFIELD(STANDARD, BT601_625_UNADJUSTED),
kColorStandardBT601_525 = GET_HAL_BITFIELD(STANDARD, BT601_525),
kColorStandardBT601_525_Unadjusted = GET_HAL_BITFIELD(STANDARD, BT601_525_UNADJUSTED),
kColorStandardBT2020 = GET_HAL_BITFIELD(STANDARD, BT2020),
kColorStandardBT2020Constant = GET_HAL_BITFIELD(STANDARD, BT2020_CONSTANT_LUMINANCE),
kColorStandardBT470M = GET_HAL_BITFIELD(STANDARD, BT470M),
kColorStandardFilm = GET_HAL_BITFIELD(STANDARD, FILM),
kColorStandardMax = GET_HAL_BITFIELD(STANDARD, MASK),
/* This marks a section of color-standard values that are not supported by graphics HAL,
but track defined color primaries-matrix coefficient combinations in media.
These are stable for a given release. */
kColorStandardExtendedStart = kColorStandardMax + 1,
/* This marks a section of color-standard values that are not supported by graphics HAL
nor using media defined color primaries or matrix coefficients. These may differ per
device. */
kColorStandardVendorStart = 0x10000,
};
enum ColorTransfer : uint32_t {
kColorTransferUnspecified = GET_HAL_BITFIELD(TRANSFER, UNSPECIFIED),
kColorTransferLinear = GET_HAL_BITFIELD(TRANSFER, LINEAR),
kColorTransferSRGB = GET_HAL_BITFIELD(TRANSFER, SRGB),
kColorTransferSMPTE_170M = GET_HAL_BITFIELD(TRANSFER, SMPTE_170M),
kColorTransferGamma22 = GET_HAL_BITFIELD(TRANSFER, GAMMA2_2),
kColorTransferGamma28 = GET_HAL_BITFIELD(TRANSFER, GAMMA2_8),
kColorTransferST2084 = GET_HAL_BITFIELD(TRANSFER, ST2084),
kColorTransferHLG = GET_HAL_BITFIELD(TRANSFER, HLG),
kColorTransferMax = GET_HAL_BITFIELD(TRANSFER, MASK),
/* This marks a section of color-transfer values that are not supported by graphics HAL,
but track media-defined color-transfer. These are stable for a given release. */
kColorTransferExtendedStart = kColorTransferMax + 1,
/* This marks a section of color-transfer values that are not supported by graphics HAL
nor defined by media. These may differ per device. */
kColorTransferVendorStart = 0x10000,
};
enum ColorRange : uint32_t {
kColorRangeUnspecified = GET_HAL_BITFIELD(RANGE, UNSPECIFIED),
kColorRangeFull = GET_HAL_BITFIELD(RANGE, FULL),
kColorRangeLimited = GET_HAL_BITFIELD(RANGE, LIMITED),
kColorRangeMax = GET_HAL_BITFIELD(RANGE, MASK),
/* This marks a section of color-transfer values that are not supported by graphics HAL,
but track media-defined color-transfer. These are stable for a given release. */
kColorRangeExtendedStart = kColorRangeMax + 1,
/* This marks a section of color-transfer values that are not supported by graphics HAL
nor defined by media. These may differ per device. */
kColorRangeVendorStart = 0x10000,
};
#undef GET_HAL_BITFIELD
#undef GET_HAL_ENUM
/*
* Static utilities for codec support
*/
// using int32_t for media range/standard/transfers to denote extended ranges
// wrap methods change invalid aspects to the Unspecified value
static int32_t wrapColorAspectsIntoColorStandard(
ColorAspects::Primaries primaries, ColorAspects::MatrixCoeffs coeffs);
static int32_t wrapColorAspectsIntoColorRange(ColorAspects::Range range);
static int32_t wrapColorAspectsIntoColorTransfer(ColorAspects::Transfer transfer);
// unwrap methods change invalid aspects to the Other value
static status_t unwrapColorAspectsFromColorRange(
int32_t range, ColorAspects::Range *aspect);
static status_t unwrapColorAspectsFromColorTransfer(
int32_t transfer, ColorAspects::Transfer *aspect);
static status_t unwrapColorAspectsFromColorStandard(
int32_t standard,
ColorAspects::Primaries *primaries, ColorAspects::MatrixCoeffs *coeffs);
static status_t convertPlatformColorAspectsToCodecAspects(
int32_t range, int32_t standard, int32_t transfer, ColorAspects &aspects);
static status_t convertCodecColorAspectsToPlatformAspects(
const ColorAspects &aspects, int32_t *range, int32_t *standard, int32_t *transfer);
// converts Other values to Unspecified
static void convertCodecColorAspectsToIsoAspects(
const ColorAspects &aspects,
int32_t *primaries, int32_t *transfer, int32_t *coeffs, bool *fullRange);
// converts unsupported values to Other
static void convertIsoColorAspectsToCodecAspects(
int32_t primaries, int32_t transfer, int32_t coeffs, bool fullRange,
ColorAspects &aspects);
// unpack a uint32_t to a full ColorAspects struct
static ColorAspects unpackToColorAspects(uint32_t packed);
// pack a full ColorAspects struct into a uint32_t
static uint32_t packToU32(const ColorAspects &aspects);
// updates Unspecified color aspects to their defaults based on the video size
static void setDefaultCodecColorAspectsIfNeeded(
ColorAspects &aspects, int32_t width, int32_t height);
// it returns the closest dataSpace for given color |aspects|. if |mayExpand| is true, it allows
// returning a larger dataSpace that contains the color space given by |aspects|, and is better
// suited to blending. This requires implicit color space conversion on part of the device.
static android_dataspace getDataSpaceForColorAspects(ColorAspects &aspects, bool mayExpand);
// converts |dataSpace| to a V0 enum, and returns true if dataSpace is an aspect-only value
static bool convertDataSpaceToV0(android_dataspace &dataSpace);
// compares |aspect| to |orig|. Returns |true| if any aspects have changed, except if they
// changed to Unspecified value. It also sets the changed values to Unspecified in |aspect|.
static bool checkIfAspectsChangedAndUnspecifyThem(
ColorAspects &aspects, const ColorAspects &orig, bool usePlatformAspects = false);
// finds color config in format, defaulting them to 0.
static void getColorConfigFromFormat(
const sp<AMessage> &format, int *range, int *standard, int *transfer);
// copies existing color config from |source| to |target|.
static void copyColorConfig(const sp<AMessage> &source, sp<AMessage> &target);
// finds color config in format as ColorAspects, defaulting them to 0.
static void getColorAspectsFromFormat(const sp<AMessage> &format, ColorAspects &aspects);
// writes |aspects| into format. iff |force| is false, Unspecified values are not
// written.
static void setColorAspectsIntoFormat(
const ColorAspects &aspects, sp<AMessage> &format, bool force = false);
// finds HDR metadata in format as HDRStaticInfo, defaulting them to 0.
// Return |true| if could find HDR metadata in format. Otherwise, return |false|.
static bool getHDRStaticInfoFromFormat(const sp<AMessage> &format, HDRStaticInfo *info);
// writes |info| into format.
static void setHDRStaticInfoIntoFormat(const HDRStaticInfo &info, sp<AMessage> &format);
};
inline static const char *asString(android::ColorUtils::ColorStandard i, const char *def = "??") {
using namespace android;
switch (i) {
case ColorUtils::kColorStandardUnspecified: return "Unspecified";
case ColorUtils::kColorStandardBT709: return "BT709";
case ColorUtils::kColorStandardBT601_625: return "BT601_625";
case ColorUtils::kColorStandardBT601_625_Unadjusted: return "BT601_625_Unadjusted";
case ColorUtils::kColorStandardBT601_525: return "BT601_525";
case ColorUtils::kColorStandardBT601_525_Unadjusted: return "BT601_525_Unadjusted";
case ColorUtils::kColorStandardBT2020: return "BT2020";
case ColorUtils::kColorStandardBT2020Constant: return "BT2020Constant";
case ColorUtils::kColorStandardBT470M: return "BT470M";
case ColorUtils::kColorStandardFilm: return "Film";
default: return def;
}
}
inline static const char *asString(android::ColorUtils::ColorTransfer i, const char *def = "??") {
using namespace android;
switch (i) {
case ColorUtils::kColorTransferUnspecified: return "Unspecified";
case ColorUtils::kColorTransferLinear: return "Linear";
case ColorUtils::kColorTransferSRGB: return "SRGB";
case ColorUtils::kColorTransferSMPTE_170M: return "SMPTE_170M";
case ColorUtils::kColorTransferGamma22: return "Gamma22";
case ColorUtils::kColorTransferGamma28: return "Gamma28";
case ColorUtils::kColorTransferST2084: return "ST2084";
case ColorUtils::kColorTransferHLG: return "HLG";
default: return def;
}
}
inline static const char *asString(android::ColorUtils::ColorRange i, const char *def = "??") {
using namespace android;
switch (i) {
case ColorUtils::kColorRangeUnspecified: return "Unspecified";
case ColorUtils::kColorRangeFull: return "Full";
case ColorUtils::kColorRangeLimited: return "Limited";
default: return def;
}
}
} // namespace android
#endif // COLOR_UTILS_H_