/*
 * 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.
 */

//#define LOG_NDEBUG 0
#define LOG_TAG "ColorUtils"

#include <inttypes.h>
#include <arpa/inet.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ALookup.h>
#include <media/stagefright/foundation/ColorUtils.h>

namespace android {

// shortcut names for brevity in the following tables
typedef ColorAspects CA;
typedef ColorUtils CU;

#define HI_UINT16(a) (((a) >> 8) & 0xFF)
#define LO_UINT16(a) ((a) & 0xFF)

const static
ALookup<CU::ColorRange, CA::Range> sRanges{
    {
        { CU::kColorRangeLimited, CA::RangeLimited },
        { CU::kColorRangeFull, CA::RangeFull },
        { CU::kColorRangeUnspecified, CA::RangeUnspecified },
    }
};

const static
ALookup<CU::ColorStandard, std::pair<CA::Primaries, CA::MatrixCoeffs>> sStandards {
    {
        { CU::kColorStandardUnspecified,    { CA::PrimariesUnspecified, CA::MatrixUnspecified } },
        { CU::kColorStandardBT709,          { CA::PrimariesBT709_5, CA::MatrixBT709_5 } },
        { CU::kColorStandardBT601_625,      { CA::PrimariesBT601_6_625, CA::MatrixBT601_6 } },
        { CU::kColorStandardBT601_625_Unadjusted,
                                            // this is a really close match
                                            { CA::PrimariesBT601_6_625, CA::MatrixBT709_5 } },
        { CU::kColorStandardBT601_525,      { CA::PrimariesBT601_6_525, CA::MatrixBT601_6 } },
        { CU::kColorStandardBT601_525_Unadjusted,
                                            { CA::PrimariesBT601_6_525, CA::MatrixSMPTE240M } },
        { CU::kColorStandardBT2020,         { CA::PrimariesBT2020, CA::MatrixBT2020 } },
        { CU::kColorStandardBT2020Constant, { CA::PrimariesBT2020, CA::MatrixBT2020Constant } },
        { CU::kColorStandardBT470M,         { CA::PrimariesBT470_6M, CA::MatrixBT470_6M } },
        // NOTE: there is no close match to the matrix used by standard film, chose closest
        { CU::kColorStandardFilm,           { CA::PrimariesGenericFilm, CA::MatrixBT2020 } },
    }
};

const static
ALookup<CU::ColorTransfer, CA::Transfer> sTransfers{
    {
        { CU::kColorTransferUnspecified,    CA::TransferUnspecified },
        { CU::kColorTransferLinear,         CA::TransferLinear },
        { CU::kColorTransferSRGB,           CA::TransferSRGB },
        { CU::kColorTransferSMPTE_170M,     CA::TransferSMPTE170M },
        { CU::kColorTransferGamma22,        CA::TransferGamma22 },
        { CU::kColorTransferGamma28,        CA::TransferGamma28 },
        { CU::kColorTransferST2084,         CA::TransferST2084 },
        { CU::kColorTransferHLG,            CA::TransferHLG },
    }
};

static bool isValid(ColorAspects::Primaries p) {
    return p <= ColorAspects::PrimariesOther;
}

static bool isDefined(ColorAspects::Primaries p) {
    return p <= ColorAspects::PrimariesBT2020;
}

static bool isValid(ColorAspects::MatrixCoeffs c) {
    return c <= ColorAspects::MatrixOther;
}

static bool isDefined(ColorAspects::MatrixCoeffs c) {
    return c <= ColorAspects::MatrixBT2020Constant;
}

//static
int32_t ColorUtils::wrapColorAspectsIntoColorStandard(
        ColorAspects::Primaries primaries, ColorAspects::MatrixCoeffs coeffs) {
    ColorStandard res;
    if (sStandards.map(std::make_pair(primaries, coeffs), &res)) {
        return res;
    } else if (!isValid(primaries) || !isValid(coeffs)) {
        return kColorStandardUnspecified;
    }

    // check platform media limits
    uint32_t numPrimaries = ColorAspects::PrimariesBT2020 + 1;
    if (isDefined(primaries) && isDefined(coeffs)) {
        return kColorStandardExtendedStart + primaries + coeffs * numPrimaries;
    } else {
        return kColorStandardVendorStart + primaries + coeffs * 0x100;
    }
}

//static
status_t ColorUtils::unwrapColorAspectsFromColorStandard(
        int32_t standard,
        ColorAspects::Primaries *primaries, ColorAspects::MatrixCoeffs *coeffs) {
    std::pair<ColorAspects::Primaries, ColorAspects::MatrixCoeffs> res;
    if (sStandards.map((ColorStandard)standard, &res)) {
        *primaries = res.first;
        *coeffs = res.second;
        return OK;
    }

    int32_t start = kColorStandardExtendedStart;
    int32_t numPrimaries = ColorAspects::PrimariesBT2020 + 1;
    int32_t numCoeffs = ColorAspects::MatrixBT2020Constant + 1;
    if (standard >= (int32_t)kColorStandardVendorStart) {
        start = kColorStandardVendorStart;
        numPrimaries = ColorAspects::PrimariesOther + 1; // 0x100
        numCoeffs = ColorAspects::MatrixOther + 1; // 0x100;
    }
    if (standard >= start && standard < start + numPrimaries * numCoeffs) {
        int32_t product = standard - start;
        *primaries = (ColorAspects::Primaries)(product % numPrimaries);
        *coeffs = (ColorAspects::MatrixCoeffs)(product / numPrimaries);
        return OK;
    }
    *primaries = ColorAspects::PrimariesOther;
    *coeffs = ColorAspects::MatrixOther;
    return BAD_VALUE;
}

static bool isValid(ColorAspects::Range r) {
    return r <= ColorAspects::RangeOther;
}

static bool isDefined(ColorAspects::Range r) {
    return r <= ColorAspects::RangeLimited;
}

//  static
int32_t ColorUtils::wrapColorAspectsIntoColorRange(ColorAspects::Range range) {
    ColorRange res;
    if (sRanges.map(range, &res)) {
        return res;
    } else if (!isValid(range)) {
        return kColorRangeUnspecified;
    } else {
        CHECK(!isDefined(range));
        // all platform values are in sRanges
        return kColorRangeVendorStart + range;
    }
}

//static
status_t ColorUtils::unwrapColorAspectsFromColorRange(
        int32_t range, ColorAspects::Range *aspect) {
    if (sRanges.map((ColorRange)range, aspect)) {
        return OK;
    }

    int32_t start = kColorRangeVendorStart;
    int32_t numRanges = ColorAspects::RangeOther + 1; // 0x100
    if (range >= start && range < start + numRanges) {
        *aspect = (ColorAspects::Range)(range - start);
        return OK;
    }
    *aspect = ColorAspects::RangeOther;
    return BAD_VALUE;
}

static bool isValid(ColorAspects::Transfer t) {
    return t <= ColorAspects::TransferOther;
}

static bool isDefined(ColorAspects::Transfer t) {
    return t <= ColorAspects::TransferHLG
            || (t >= ColorAspects::TransferSMPTE240M && t <= ColorAspects::TransferST428);
}

//  static
int32_t ColorUtils::wrapColorAspectsIntoColorTransfer(
        ColorAspects::Transfer transfer) {
    ColorTransfer res;
    if (sTransfers.map(transfer, &res)) {
        return res;
    } else if (!isValid(transfer)) {
        return kColorTransferUnspecified;
    } else if (isDefined(transfer)) {
        return kColorTransferExtendedStart + transfer;
    } else {
        // all platform values are in sRanges
        return kColorTransferVendorStart + transfer;
    }
}

//static
status_t ColorUtils::unwrapColorAspectsFromColorTransfer(
        int32_t transfer, ColorAspects::Transfer *aspect) {
    if (sTransfers.map((ColorTransfer)transfer, aspect)) {
        return OK;
    }

    int32_t start = kColorTransferExtendedStart;
    int32_t numTransfers = ColorAspects::TransferST428 + 1;
    if (transfer >= (int32_t)kColorTransferVendorStart) {
        start = kColorTransferVendorStart;
        numTransfers = ColorAspects::TransferOther + 1; // 0x100
    }
    if (transfer >= start && transfer < start + numTransfers) {
        *aspect = (ColorAspects::Transfer)(transfer - start);
        return OK;
    }
    *aspect = ColorAspects::TransferOther;
    return BAD_VALUE;
}

// static
status_t ColorUtils::convertPlatformColorAspectsToCodecAspects(
    int32_t range, int32_t standard, int32_t transfer, ColorAspects &aspects) {
    status_t res1 = unwrapColorAspectsFromColorRange(range, &aspects.mRange);
    status_t res2 = unwrapColorAspectsFromColorStandard(
            standard, &aspects.mPrimaries, &aspects.mMatrixCoeffs);
    status_t res3 = unwrapColorAspectsFromColorTransfer(transfer, &aspects.mTransfer);
    return res1 != OK ? res1 : (res2 != OK ? res2 : res3);
}

// static
status_t ColorUtils::convertCodecColorAspectsToPlatformAspects(
    const ColorAspects &aspects, int32_t *range, int32_t *standard, int32_t *transfer) {
    *range = wrapColorAspectsIntoColorRange(aspects.mRange);
    *standard = wrapColorAspectsIntoColorStandard(aspects.mPrimaries, aspects.mMatrixCoeffs);
    *transfer = wrapColorAspectsIntoColorTransfer(aspects.mTransfer);
    if (isValid(aspects.mRange) && isValid(aspects.mPrimaries)
            && isValid(aspects.mMatrixCoeffs) && isValid(aspects.mTransfer)) {
        return OK;
    } else {
        return BAD_VALUE;
    }
}

const static
ALookup<int32_t, ColorAspects::Primaries> sIsoPrimaries {
    {
        { 1, ColorAspects::PrimariesBT709_5 },
        { 2, ColorAspects::PrimariesUnspecified },
        { 4, ColorAspects::PrimariesBT470_6M },
        { 5, ColorAspects::PrimariesBT601_6_625 },
        { 6, ColorAspects::PrimariesBT601_6_525 /* main */},
        { 7, ColorAspects::PrimariesBT601_6_525 },
        // -- ITU T.832 201201 ends here
        { 8, ColorAspects::PrimariesGenericFilm },
        { 9, ColorAspects::PrimariesBT2020 },
        { 10, ColorAspects::PrimariesOther /* XYZ */ },
    }
};

const static
ALookup<int32_t, ColorAspects::Transfer> sIsoTransfers {
    {
        { 1, ColorAspects::TransferSMPTE170M /* main */},
        { 2, ColorAspects::TransferUnspecified },
        { 4, ColorAspects::TransferGamma22 },
        { 5, ColorAspects::TransferGamma28 },
        { 6, ColorAspects::TransferSMPTE170M },
        { 7, ColorAspects::TransferSMPTE240M },
        { 8, ColorAspects::TransferLinear },
        { 9, ColorAspects::TransferOther /* log 100:1 */ },
        { 10, ColorAspects::TransferOther /* log 316:1 */ },
        { 11, ColorAspects::TransferXvYCC },
        { 12, ColorAspects::TransferBT1361 },
        { 13, ColorAspects::TransferSRGB },
        // -- ITU T.832 201201 ends here
        { 14, ColorAspects::TransferSMPTE170M },
        { 15, ColorAspects::TransferSMPTE170M },
        { 16, ColorAspects::TransferST2084 },
        { 17, ColorAspects::TransferST428 },
        { 18, ColorAspects::TransferHLG },
    }
};

const static
ALookup<int32_t, ColorAspects::MatrixCoeffs> sIsoMatrixCoeffs {
    {
        { 0, ColorAspects::MatrixOther },
        { 1, ColorAspects::MatrixBT709_5 },
        { 2, ColorAspects::MatrixUnspecified },
        { 4, ColorAspects::MatrixBT470_6M },
        { 6, ColorAspects::MatrixBT601_6 /* main */ },
        { 5, ColorAspects::MatrixBT601_6 },
        { 7, ColorAspects::MatrixSMPTE240M },
        { 8, ColorAspects::MatrixOther /* YCgCo */ },
        // -- ITU T.832 201201 ends here
        { 9, ColorAspects::MatrixBT2020 },
        { 10, ColorAspects::MatrixBT2020Constant },
    }
};

// static
void ColorUtils::convertCodecColorAspectsToIsoAspects(
        const ColorAspects &aspects,
        int32_t *primaries, int32_t *transfer, int32_t *coeffs, bool *fullRange) {
    if (aspects.mPrimaries == ColorAspects::PrimariesOther ||
            !sIsoPrimaries.map(aspects.mPrimaries, primaries)) {
        CHECK(sIsoPrimaries.map(ColorAspects::PrimariesUnspecified, primaries));
    }
    if (aspects.mTransfer == ColorAspects::TransferOther ||
            !sIsoTransfers.map(aspects.mTransfer, transfer)) {
        CHECK(sIsoTransfers.map(ColorAspects::TransferUnspecified, transfer));
    }
    if (aspects.mMatrixCoeffs == ColorAspects::MatrixOther ||
            !sIsoMatrixCoeffs.map(aspects.mMatrixCoeffs, coeffs)) {
        CHECK(sIsoMatrixCoeffs.map(ColorAspects::MatrixUnspecified, coeffs));
    }
    *fullRange = aspects.mRange == ColorAspects::RangeFull;
}

// static
void ColorUtils::convertIsoColorAspectsToCodecAspects(
        int32_t primaries, int32_t transfer, int32_t coeffs, bool fullRange,
        ColorAspects &aspects) {
    if (!sIsoPrimaries.map(primaries, &aspects.mPrimaries)) {
        aspects.mPrimaries = ColorAspects::PrimariesUnspecified;
    }
    if (!sIsoTransfers.map(transfer, &aspects.mTransfer)) {
        aspects.mTransfer = ColorAspects::TransferUnspecified;
    }
    if (!sIsoMatrixCoeffs.map(coeffs, &aspects.mMatrixCoeffs)) {
        aspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
    }
    aspects.mRange = fullRange ? ColorAspects::RangeFull : ColorAspects::RangeLimited;
}

// static
ColorAspects ColorUtils::unpackToColorAspects(uint32_t packed) {
    ColorAspects aspects;
    aspects.mRange        = (ColorAspects::Range)((packed >> 24) & 0xFF);
    aspects.mPrimaries    = (ColorAspects::Primaries)((packed >> 16) & 0xFF);
    aspects.mMatrixCoeffs = (ColorAspects::MatrixCoeffs)((packed >> 8) & 0xFF);
    aspects.mTransfer     = (ColorAspects::Transfer)(packed & 0xFF);

    return aspects;
}

// static
uint32_t ColorUtils::packToU32(const ColorAspects &aspects) {
    return (aspects.mRange << 24) | (aspects.mPrimaries << 16)
            | (aspects.mMatrixCoeffs << 8) | aspects.mTransfer;
}

// static
void ColorUtils::setDefaultCodecColorAspectsIfNeeded(
        ColorAspects &aspects, int32_t width, int32_t height) {
    ColorAspects::MatrixCoeffs coeffs;
    ColorAspects::Primaries primaries;

    // Default to BT2020, BT709 or BT601 based on size. Allow 2.35:1 aspect ratio. Limit BT601
    // to PAL or smaller, BT2020 to 4K or larger, leaving BT709 for all resolutions in between.
    if (width >= 3840 || height >= 3840 || width * (int64_t)height >= 3840 * 1634) {
        primaries = ColorAspects::PrimariesBT2020;
        coeffs = ColorAspects::MatrixBT2020;
    } else if ((width <= 720 && height > 480 && height <= 576)
            || (height <= 720 && width > 480 && width <= 576)) {
        primaries = ColorAspects::PrimariesBT601_6_625;
        coeffs = ColorAspects::MatrixBT601_6;
    } else if ((width <= 720 && height <= 480) || (height <= 720 && width <= 480)) {
        primaries = ColorAspects::PrimariesBT601_6_525;
        coeffs = ColorAspects::MatrixBT601_6;
    } else {
        primaries = ColorAspects::PrimariesBT709_5;
        coeffs = ColorAspects::MatrixBT709_5;
    }

    if (aspects.mRange == ColorAspects::RangeUnspecified) {
        aspects.mRange = ColorAspects::RangeLimited;
    }

    if (aspects.mPrimaries == ColorAspects::PrimariesUnspecified) {
        aspects.mPrimaries = primaries;
    }
    if (aspects.mMatrixCoeffs == ColorAspects::MatrixUnspecified) {
        aspects.mMatrixCoeffs = coeffs;
    }
    if (aspects.mTransfer == ColorAspects::TransferUnspecified) {
        aspects.mTransfer = ColorAspects::TransferSMPTE170M;
    }
}

// TODO: move this into a Video HAL
ALookup<CU::ColorStandard, std::pair<CA::Primaries, CA::MatrixCoeffs>> sStandardFallbacks {
    {
        { CU::kColorStandardBT601_625, { CA::PrimariesBT709_5, CA::MatrixBT470_6M } },
        { CU::kColorStandardBT601_625, { CA::PrimariesBT709_5, CA::MatrixBT601_6 } },
        { CU::kColorStandardBT709,     { CA::PrimariesBT709_5, CA::MatrixSMPTE240M } },
        { CU::kColorStandardBT709,     { CA::PrimariesBT709_5, CA::MatrixBT2020 } },
        { CU::kColorStandardBT601_525, { CA::PrimariesBT709_5, CA::MatrixBT2020Constant } },

        { CU::kColorStandardBT2020Constant,
                                       { CA::PrimariesBT470_6M, CA::MatrixBT2020Constant } },

        { CU::kColorStandardBT601_625, { CA::PrimariesBT601_6_625, CA::MatrixBT470_6M } },
        { CU::kColorStandardBT601_525, { CA::PrimariesBT601_6_625, CA::MatrixBT2020Constant } },

        { CU::kColorStandardBT601_525, { CA::PrimariesBT601_6_525, CA::MatrixBT470_6M } },
        { CU::kColorStandardBT601_525, { CA::PrimariesBT601_6_525, CA::MatrixBT2020Constant } },

        { CU::kColorStandardBT2020Constant,
                                       { CA::PrimariesGenericFilm, CA::MatrixBT2020Constant } },
    }
};

ALookup<CU::ColorStandard, CA::Primaries> sStandardPrimariesFallbacks {
    {
        { CU::kColorStandardFilm,                 CA::PrimariesGenericFilm },
        { CU::kColorStandardBT470M,               CA::PrimariesBT470_6M },
        { CU::kColorStandardBT2020,               CA::PrimariesBT2020 },
        { CU::kColorStandardBT601_525_Unadjusted, CA::PrimariesBT601_6_525 },
        { CU::kColorStandardBT601_625_Unadjusted, CA::PrimariesBT601_6_625 },
    }
};

static ALookup<android_dataspace, android_dataspace> sLegacyDataSpaceToV0 {
    {
        { HAL_DATASPACE_SRGB, HAL_DATASPACE_V0_SRGB },
        { HAL_DATASPACE_BT709, HAL_DATASPACE_V0_BT709 },
        { HAL_DATASPACE_SRGB_LINEAR, HAL_DATASPACE_V0_SRGB_LINEAR },
        { HAL_DATASPACE_BT601_525, HAL_DATASPACE_V0_BT601_525 },
        { HAL_DATASPACE_BT601_625, HAL_DATASPACE_V0_BT601_625 },
        { HAL_DATASPACE_JFIF, HAL_DATASPACE_V0_JFIF },
    }
};

bool ColorUtils::convertDataSpaceToV0(android_dataspace &dataSpace) {
    (void)sLegacyDataSpaceToV0.lookup(dataSpace, &dataSpace);
    return (dataSpace & 0xC000FFFF) == 0;
}

bool ColorUtils::checkIfAspectsChangedAndUnspecifyThem(
        ColorAspects &aspects, const ColorAspects &orig, bool usePlatformAspects) {
    // remove changed aspects (change them to Unspecified)
    bool changed = false;
    if (aspects.mRange && aspects.mRange != orig.mRange) {
        aspects.mRange = ColorAspects::RangeUnspecified;
        changed = true;
    }
    if (aspects.mPrimaries && aspects.mPrimaries != orig.mPrimaries) {
        aspects.mPrimaries = ColorAspects::PrimariesUnspecified;
        if (usePlatformAspects) {
            aspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
        }
        changed = true;
    }
    if (aspects.mMatrixCoeffs && aspects.mMatrixCoeffs != orig.mMatrixCoeffs) {
        aspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
        if (usePlatformAspects) {
            aspects.mPrimaries = ColorAspects::PrimariesUnspecified;
        }
        changed = true;
    }
    if (aspects.mTransfer && aspects.mTransfer != orig.mTransfer) {
        aspects.mTransfer = ColorAspects::TransferUnspecified;
        changed = true;
    }
    return changed;
}

// static
android_dataspace ColorUtils::getDataSpaceForColorAspects(ColorAspects &aspects, bool mayExpand) {
    // This platform implementation never expands color space (e.g. returns an expanded
    // dataspace to use where the codec does in-the-background color space conversion)
    mayExpand = false;

    if (aspects.mRange == ColorAspects::RangeUnspecified
            || aspects.mPrimaries == ColorAspects::PrimariesUnspecified
            || aspects.mMatrixCoeffs == ColorAspects::MatrixUnspecified
            || aspects.mTransfer == ColorAspects::TransferUnspecified) {
        ALOGW("expected specified color aspects (%u:%u:%u:%u)",
                aspects.mRange, aspects.mPrimaries, aspects.mMatrixCoeffs, aspects.mTransfer);
    }

    // default to video range and transfer
    ColorRange range = kColorRangeLimited;
    ColorTransfer transfer = kColorTransferSMPTE_170M;
    (void)sRanges.map(aspects.mRange, &range);
    (void)sTransfers.map(aspects.mTransfer, &transfer);

    ColorStandard standard = kColorStandardBT709;
    auto pair = std::make_pair(aspects.mPrimaries, aspects.mMatrixCoeffs);
    if (!sStandards.map(pair, &standard)) {
        if (!sStandardFallbacks.map(pair, &standard)) {
            (void)sStandardPrimariesFallbacks.map(aspects.mPrimaries, &standard);

            if (aspects.mMatrixCoeffs == ColorAspects::MatrixBT2020Constant) {
                range = kColorRangeFull;
            }
        }
    }

    android_dataspace dataSpace = (android_dataspace)(
            (range << HAL_DATASPACE_RANGE_SHIFT) | (standard << HAL_DATASPACE_STANDARD_SHIFT) |
            (transfer << HAL_DATASPACE_TRANSFER_SHIFT));
    (void)sLegacyDataSpaceToV0.rlookup(dataSpace, &dataSpace);

    if (!mayExpand) {
        // update codec aspects based on dataspace
        convertPlatformColorAspectsToCodecAspects(range, standard, transfer, aspects);
    }
    return dataSpace;
}

// static
void ColorUtils::getColorConfigFromFormat(
        const sp<AMessage> &format, int32_t *range, int32_t *standard, int32_t *transfer) {
    if (!format->findInt32("color-range", range)) {
        *range = kColorRangeUnspecified;
    }
    if (!format->findInt32("color-standard", standard)) {
        *standard = kColorStandardUnspecified;
    }
    if (!format->findInt32("color-transfer", transfer)) {
        *transfer = kColorTransferUnspecified;
    }
}

// static
void ColorUtils::copyColorConfig(const sp<AMessage> &source, sp<AMessage> &target) {
    // 0 values are unspecified
    int32_t value;
    if (source->findInt32("color-range", &value)) {
        target->setInt32("color-range", value);
    }
    if (source->findInt32("color-standard", &value)) {
        target->setInt32("color-standard", value);
    }
    if (source->findInt32("color-transfer", &value)) {
        target->setInt32("color-transfer", value);
    }
}

// static
void ColorUtils::getColorAspectsFromFormat(const sp<AMessage> &format, ColorAspects &aspects) {
    int32_t range, standard, transfer;
    getColorConfigFromFormat(format, &range, &standard, &transfer);

    if (convertPlatformColorAspectsToCodecAspects(
            range, standard, transfer, aspects) != OK) {
        ALOGW("Ignoring illegal color aspects(R:%d(%s), S:%d(%s), T:%d(%s))",
                range, asString((ColorRange)range),
                standard, asString((ColorStandard)standard),
                transfer, asString((ColorTransfer)transfer));
        // Invalid values were converted to unspecified !params!, but otherwise were not changed
        // For encoders, we leave these as is. For decoders, we will use default values.
    }
    ALOGV("Got color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) "
          "from format (out:R:%d(%s), S:%d(%s), T:%d(%s))",
            aspects.mRange, asString(aspects.mRange),
            aspects.mPrimaries, asString(aspects.mPrimaries),
            aspects.mMatrixCoeffs, asString(aspects.mMatrixCoeffs),
            aspects.mTransfer, asString(aspects.mTransfer),
            range, asString((ColorRange)range),
            standard, asString((ColorStandard)standard),
            transfer, asString((ColorTransfer)transfer));
}

// static
void ColorUtils::setColorAspectsIntoFormat(
        const ColorAspects &aspects, sp<AMessage> &format, bool force) {
    int32_t range = 0, standard = 0, transfer = 0;
    convertCodecColorAspectsToPlatformAspects(aspects, &range, &standard, &transfer);
    // save set values to base output format
    // (encoder input format will read back actually supported values by the codec)
    if (range != 0 || force) {
        format->setInt32("color-range", range);
    }
    if (standard != 0 || force) {
        format->setInt32("color-standard", standard);
    }
    if (transfer != 0 || force) {
        format->setInt32("color-transfer", transfer);
    }
    ALOGV("Setting color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) "
          "into format (out:R:%d(%s), S:%d(%s), T:%d(%s))",
            aspects.mRange, asString(aspects.mRange),
            aspects.mPrimaries, asString(aspects.mPrimaries),
            aspects.mMatrixCoeffs, asString(aspects.mMatrixCoeffs),
            aspects.mTransfer, asString(aspects.mTransfer),
            range, asString((ColorRange)range),
            standard, asString((ColorStandard)standard),
            transfer, asString((ColorTransfer)transfer));
}

// static
void ColorUtils::setHDRStaticInfoIntoFormat(
        const HDRStaticInfo &info, sp<AMessage> &format) {
    sp<ABuffer> infoBuffer = new ABuffer(25);

    // Convert the data in infoBuffer to little endian format as defined by CTA-861-3
    uint8_t *data = infoBuffer->data();
    // Static_Metadata_Descriptor_ID
    data[0] = info.mID;

    // display primary 0
    data[1] = LO_UINT16(info.sType1.mR.x);
    data[2] = HI_UINT16(info.sType1.mR.x);
    data[3] = LO_UINT16(info.sType1.mR.y);
    data[4] = HI_UINT16(info.sType1.mR.y);

    // display primary 1
    data[5] = LO_UINT16(info.sType1.mG.x);
    data[6] = HI_UINT16(info.sType1.mG.x);
    data[7] = LO_UINT16(info.sType1.mG.y);
    data[8] = HI_UINT16(info.sType1.mG.y);

    // display primary 2
    data[9] = LO_UINT16(info.sType1.mB.x);
    data[10] = HI_UINT16(info.sType1.mB.x);
    data[11] = LO_UINT16(info.sType1.mB.y);
    data[12] = HI_UINT16(info.sType1.mB.y);

    // white point
    data[13] = LO_UINT16(info.sType1.mW.x);
    data[14] = HI_UINT16(info.sType1.mW.x);
    data[15] = LO_UINT16(info.sType1.mW.y);
    data[16] = HI_UINT16(info.sType1.mW.y);

    // MaxDisplayLuminance
    data[17] = LO_UINT16(info.sType1.mMaxDisplayLuminance);
    data[18] = HI_UINT16(info.sType1.mMaxDisplayLuminance);

    // MinDisplayLuminance
    data[19] = LO_UINT16(info.sType1.mMinDisplayLuminance);
    data[20] = HI_UINT16(info.sType1.mMinDisplayLuminance);

    // MaxContentLightLevel
    data[21] = LO_UINT16(info.sType1.mMaxContentLightLevel);
    data[22] = HI_UINT16(info.sType1.mMaxContentLightLevel);

    // MaxFrameAverageLightLevel
    data[23] = LO_UINT16(info.sType1.mMaxFrameAverageLightLevel);
    data[24] = HI_UINT16(info.sType1.mMaxFrameAverageLightLevel);

    format->setBuffer("hdr-static-info", infoBuffer);
}

// a simple method copied from Utils.cpp
static uint16_t U16LE_AT(const uint8_t *ptr) {
    return ptr[0] | (ptr[1] << 8);
}

// static
bool ColorUtils::getHDRStaticInfoFromFormat(const sp<AMessage> &format, HDRStaticInfo *info) {
    sp<ABuffer> buf;
    if (!format->findBuffer("hdr-static-info", &buf)) {
        return false;
    }

    // TODO: Make this more flexible when adding more members to HDRStaticInfo
    if (buf->size() != 25 /* static Metadata Type 1 size */) {
        ALOGW("Ignore invalid HDRStaticInfo with size: %zu", buf->size());
        return false;
    }

    const uint8_t *data = buf->data();
    if (*data != HDRStaticInfo::kType1) {
        ALOGW("Unsupported static Metadata Type %u", *data);
        return false;
    }

    info->mID = HDRStaticInfo::kType1;
    info->sType1.mR.x = U16LE_AT(&data[1]);
    info->sType1.mR.y = U16LE_AT(&data[3]);
    info->sType1.mG.x = U16LE_AT(&data[5]);
    info->sType1.mG.y = U16LE_AT(&data[7]);
    info->sType1.mB.x = U16LE_AT(&data[9]);
    info->sType1.mB.y = U16LE_AT(&data[11]);
    info->sType1.mW.x = U16LE_AT(&data[13]);
    info->sType1.mW.y = U16LE_AT(&data[15]);
    info->sType1.mMaxDisplayLuminance = U16LE_AT(&data[17]);
    info->sType1.mMinDisplayLuminance = U16LE_AT(&data[19]);
    info->sType1.mMaxContentLightLevel = U16LE_AT(&data[21]);
    info->sType1.mMaxFrameAverageLightLevel = U16LE_AT(&data[23]);

    ALOGV("Got HDRStaticInfo from config (R: %u %u, G: %u %u, B: %u, %u, W: %u, %u, "
            "MaxDispL: %u, MinDispL: %u, MaxContentL: %u, MaxFrameAvgL: %u)",
            info->sType1.mR.x, info->sType1.mR.y, info->sType1.mG.x, info->sType1.mG.y,
            info->sType1.mB.x, info->sType1.mB.y, info->sType1.mW.x, info->sType1.mW.y,
            info->sType1.mMaxDisplayLuminance, info->sType1.mMinDisplayLuminance,
            info->sType1.mMaxContentLightLevel, info->sType1.mMaxFrameAverageLightLevel);
    return true;
}

}  // namespace android

