Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8338519b authored by Lajos Molnar's avatar Lajos Molnar Committed by Ronghua Wu
Browse files

stagefright: pass color aspects into codecs

Bug: 25975353
Change-Id: Ie2cdb845769f5ec3561a099f96e8f4dd406299ef
parent ddfef426
Loading
Loading
Loading
Loading
+10 −2
Original line number Diff line number Diff line
@@ -290,6 +290,8 @@ private:

    bool mTunneled;

    OMX_INDEXTYPE mDescribeColorAspectsIndex;

    status_t setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode);
    status_t allocateBuffersOnPort(OMX_U32 portIndex);
    status_t freeBuffersOnPort(OMX_U32 portIndex);
@@ -341,16 +343,22 @@ private:
    status_t setSupportedOutputFormat(bool getLegacyFlexibleFormat);

    status_t setupVideoDecoder(
            const char *mime, const sp<AMessage> &msg, bool usingNativeBuffers);
            const char *mime, const sp<AMessage> &msg, bool usingNativeBuffers,
            sp<AMessage> &outputformat);

    status_t setupVideoEncoder(
            const char *mime, const sp<AMessage> &msg);
            const char *mime, const sp<AMessage> &msg, sp<AMessage> &outputformat);

    status_t setVideoFormatOnPort(
            OMX_U32 portIndex,
            int32_t width, int32_t height,
            OMX_VIDEO_CODINGTYPE compressionFormat, float frameRate = -1.0);

    status_t setColorAspects(
        OMX_U32 portIndex, int32_t width, int32_t height, const sp<AMessage> &msg,
        sp<AMessage> &format);
    status_t getColorAspects(OMX_U32 portIndex, sp<AMessage> &format);

    typedef struct drcParams {
        int32_t drcCut;
        int32_t drcBoost;
+116 −1
Original line number Diff line number Diff line
@@ -19,12 +19,16 @@
#define CODEC_BASE_H_

#include <stdint.h>
#include <media/IOMX.h>

#include <media/IOMX.h>
#include <media/MediaCodecInfo.h>
#include <media/stagefright/foundation/AHandler.h>
#include <media/hardware/HardwareAPI.h>

#include <utils/NativeHandle.h>

#include <system/graphics.h>

namespace android {

struct ABuffer;
@@ -89,6 +93,117 @@ struct CodecBase : public AHandler {
        DISALLOW_EVIL_CONSTRUCTORS(PortDescription);
    };

    /*
     * Codec-related defines
     */

    /**********************************************************************************************/

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

    enum ColorStandard : uint32_t {
        kColorStandardUnspecified =
                HAL_DATASPACE_STANDARD_UNSPECIFIED >> HAL_DATASPACE_STANDARD_SHIFT,
        kColorStandardBT709 =     HAL_DATASPACE_STANDARD_BT709 >> HAL_DATASPACE_STANDARD_SHIFT,
        kColorStandardBT601_625 = HAL_DATASPACE_STANDARD_BT601_625 >> HAL_DATASPACE_STANDARD_SHIFT,
        kColorStandardBT601_625_Unadjusted =
                HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED >> HAL_DATASPACE_STANDARD_SHIFT,
        kColorStandardBT601_525 = HAL_DATASPACE_STANDARD_BT601_525 >> HAL_DATASPACE_STANDARD_SHIFT,
        kColorStandardBT601_525_Unadjusted =
                HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED >> HAL_DATASPACE_STANDARD_SHIFT,
        kColorStandardBT2020 =    HAL_DATASPACE_STANDARD_BT2020 >> HAL_DATASPACE_STANDARD_SHIFT,
        kColorStandardBT2020Constant =
                HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE >> HAL_DATASPACE_STANDARD_SHIFT,
        kColorStandardBT470M =    HAL_DATASPACE_STANDARD_BT470M >> HAL_DATASPACE_STANDARD_SHIFT,
        kColorStandardFilm =      HAL_DATASPACE_STANDARD_FILM >> HAL_DATASPACE_STANDARD_SHIFT,
        kColorStandardMax =       HAL_DATASPACE_STANDARD_MASK >> HAL_DATASPACE_STANDARD_SHIFT,

        /* 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 =
                HAL_DATASPACE_TRANSFER_UNSPECIFIED >> HAL_DATASPACE_TRANSFER_SHIFT,
        kColorTransferLinear =      HAL_DATASPACE_TRANSFER_LINEAR >> HAL_DATASPACE_TRANSFER_SHIFT,
        kColorTransferSRGB =        HAL_DATASPACE_TRANSFER_SRGB >> HAL_DATASPACE_TRANSFER_SHIFT,
        kColorTransferSMPTE_170M =
                HAL_DATASPACE_TRANSFER_SMPTE_170M >> HAL_DATASPACE_TRANSFER_SHIFT,
        kColorTransferGamma22 =     HAL_DATASPACE_TRANSFER_GAMMA2_2 >> HAL_DATASPACE_TRANSFER_SHIFT,
        kColorTransferGamma28 =     HAL_DATASPACE_TRANSFER_GAMMA2_8 >> HAL_DATASPACE_TRANSFER_SHIFT,
        kColorTransferST2084 =      HAL_DATASPACE_TRANSFER_ST2084 >> HAL_DATASPACE_TRANSFER_SHIFT,
        kColorTransferHLG =         HAL_DATASPACE_TRANSFER_HLG >> HAL_DATASPACE_TRANSFER_SHIFT,
        kColorTransferMax =         HAL_DATASPACE_TRANSFER_MASK >> HAL_DATASPACE_TRANSFER_SHIFT,

        /* 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 = HAL_DATASPACE_RANGE_UNSPECIFIED >> HAL_DATASPACE_RANGE_SHIFT,
        kColorRangeFull =        HAL_DATASPACE_RANGE_FULL >> HAL_DATASPACE_RANGE_SHIFT,
        kColorRangeLimited =     HAL_DATASPACE_RANGE_LIMITED >> HAL_DATASPACE_RANGE_SHIFT,
        kColorRangeMax =         HAL_DATASPACE_RANGE_MASK >> HAL_DATASPACE_RANGE_SHIFT,

        /* 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,
    };

    /*
     * Static utilities for codec support
     */

    // using int32_t for media range/standard/transfers to denote extended ranges
    static int32_t wrapColorAspectsIntoColorStandard(
            ColorAspects::Primaries primaries, ColorAspects::MatrixCoeffs coeffs);
    static int32_t wrapColorAspectsIntoColorRange(ColorAspects::Range range);
    static int32_t wrapColorAspectsIntoColorTransfer(ColorAspects::Transfer transfer);

    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);

    // updates unspecified range, standard and transfer values to their defaults
    static void setDefaultPlatformColorAspectsIfNeeded(
            int32_t &range, int32_t &standard, int32_t &transfer,
            int32_t width, int32_t height);
    static void setDefaultCodecColorAspectsIfNeeded(
            ColorAspects &aspects, int32_t width, int32_t height);

protected:
    CodecBase();
    virtual ~CodecBase();
+68 −0
Original line number Diff line number Diff line
/*
 * Copyright 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 A_LOOKUP_H_

#define A_LOOKUP_H_

#include <utility>
#include <vector>

namespace android {

template<typename T, typename U>
struct ALookup {
    ALookup(std::initializer_list<std::pair<T, U>> list);

    bool lookup(const T& from, U *to);
    bool rlookup(const U& from, T *to);
    inline bool map(const T& from, U *to) { return lookup(from, to); }
    inline bool map(const U& from, T *to) { return rlookup(from, to); }

private:
    std::vector<std::pair<T, U>> mTable;
};

template<typename T, typename U>
ALookup<T, U>::ALookup(std::initializer_list<std::pair<T, U>> list)
    : mTable(list) {
}

template<typename T, typename U>
bool ALookup<T, U>::lookup(const T& from, U *to) {
    for (auto elem : mTable) {
        if (elem.first == from) {
            *to = elem.second;
            return true;
        }
    }
    return false;
}

template<typename T, typename U>
bool ALookup<T, U>::rlookup(const U& from, T *to) {
    for (auto elem : mTable) {
        if (elem.second == from) {
            *to = elem.first;
            return true;
        }
    }
    return false;
}

} // namespace android

#endif  // A_UTILS_H_
+122 −6
Original line number Diff line number Diff line
@@ -511,7 +511,8 @@ ACodec::ACodec()
      mTimePerFrameUs(-1ll),
      mTimePerCaptureUs(-1ll),
      mCreateInputBuffersSuspended(false),
      mTunneled(false) {
      mTunneled(false),
      mDescribeColorAspectsIndex((OMX_INDEXTYPE)0) {
    mUninitializedState = new UninitializedState(this);
    mLoadedState = new LoadedState(this);
    mLoadedToIdleState = new LoadedToIdleState(this);
@@ -1940,9 +1941,9 @@ status_t ACodec::configureCodec(
        }

        if (encoder) {
            err = setupVideoEncoder(mime, msg);
            err = setupVideoEncoder(mime, msg, outputFormat);
        } else {
            err = setupVideoDecoder(mime, msg, haveNativeWindow);
            err = setupVideoDecoder(mime, msg, haveNativeWindow, outputFormat);
        }

        if (err != OK) {
@@ -2003,7 +2004,7 @@ status_t ACodec::configureCodec(
                        // fallback is not supported for protected playback
                        err = PERMISSION_DENIED;
                    } else if (err == OK) {
                        err = setupVideoDecoder(mime, msg, false);
                        err = setupVideoDecoder(mime, msg, false, outputFormat);
                    }
                }
            }
@@ -3010,7 +3011,8 @@ static status_t GetMimeTypeForVideoCoding(
}

status_t ACodec::setupVideoDecoder(
        const char *mime, const sp<AMessage> &msg, bool haveNativeWindow) {
        const char *mime, const sp<AMessage> &msg, bool haveNativeWindow,
        sp<AMessage> &outputFormat) {
    int32_t width, height;
    if (!msg->findInt32("width", &width)
            || !msg->findInt32("height", &height)) {
@@ -3073,10 +3075,113 @@ status_t ACodec::setupVideoDecoder(
        return err;
    }

    err = setColorAspects(
            kPortIndexOutput, width, height, msg, outputFormat);
    if (err != OK) {
        ALOGI("Falling back to presets as component does not describe color aspects.");
        err = OK;
    }

    return err;
}

status_t ACodec::setColorAspects(
        OMX_U32 portIndex, int32_t width, int32_t height, const sp<AMessage> &msg,
        sp<AMessage> &format) {
    DescribeColorAspectsParams params;
    InitOMXParams(&params);
    params.nPortIndex = portIndex;

    // 0 values are unspecified
    int32_t range = 0, standard = 0, transfer = 0;
    if (portIndex == kPortIndexInput) {
        // Encoders allow overriding default aspects with 0 if specified by format. Decoders do not.
        setDefaultPlatformColorAspectsIfNeeded(range, standard, transfer, width, height);
    }
    (void)msg->findInt32("color-range", &range);
    (void)msg->findInt32("color-standard", &standard);
    (void)msg->findInt32("color-transfer", &transfer);

    if (convertPlatformColorAspectsToCodecAspects(
            range, standard, transfer, params.sAspects) != OK) {
        ALOGW("[%s] Ignoring illegal color aspects(range=%d, standard=%d, transfer=%d)",
                mComponentName.c_str(), range, standard, 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.
    }

    // set defaults for decoders.
    if (portIndex != kPortIndexInput) {
        setDefaultCodecColorAspectsIfNeeded(params.sAspects, width, height);
        convertCodecColorAspectsToPlatformAspects(params.sAspects, &range, &standard, &transfer);
    }

    // save updated values to base output format (encoder input format will read back actually
    // supported values by the codec)
    if (range != 0) {
        format->setInt32("color-range", range);
    }
    if (standard != 0) {
        format->setInt32("color-standard", standard);
    }
    if (transfer != 0) {
        format->setInt32("color-transfer", transfer);
    }

    // communicate color aspects to codec
    status_t err = mOMX->getExtensionIndex(
            mNode, "OMX.google.android.index.describeColorAspects", &mDescribeColorAspectsIndex);
    if (err != OK) {
        mDescribeColorAspectsIndex = (OMX_INDEXTYPE)0;
        return err;
    }

    return mOMX->setConfig(mNode, mDescribeColorAspectsIndex, &params, sizeof(params));
}

status_t ACodec::getColorAspects(OMX_U32 portIndex, sp<AMessage> &format) {
    if (!mDescribeColorAspectsIndex) {
        return ERROR_UNSUPPORTED;
    }

    DescribeColorAspectsParams params;
    InitOMXParams(&params);
    params.nPortIndex = portIndex;
    ColorAspects &aspects = params.sAspects;
    aspects.mRange = ColorAspects::RangeUnspecified;
    aspects.mPrimaries = ColorAspects::PrimariesUnspecified;
    aspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
    aspects.mTransfer = ColorAspects::TransferUnspecified;

    status_t err = mOMX->getConfig(mNode, mDescribeColorAspectsIndex, &params, sizeof(params));
    if (err != OK) {
        return err;
    }

    // keep non-standard codec values in extension ranges
    int32_t range, standard, transfer;
    if (convertCodecColorAspectsToPlatformAspects(
            params.sAspects, &range, &standard, &transfer) != OK) {
        ALOGW("[%s] Ignoring invalid color aspects(range=%u, primaries=%u, coeffs=%u, transfer=%u)",
                mComponentName.c_str(),
                aspects.mRange, aspects.mPrimaries, aspects.mMatrixCoeffs, aspects.mTransfer);
    }

    // save specified values to format
    if (range != 0) {
        format->setInt32("color-range", range);
    }
    if (standard != 0) {
        format->setInt32("color-standard", standard);
    }
    if (transfer != 0) {
        format->setInt32("color-transfer", transfer);
    }
    return OK;
}

status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) {
status_t ACodec::setupVideoEncoder(
        const char *mime, const sp<AMessage> &msg, sp<AMessage> &outputFormat) {
    int32_t tmp;
    if (!msg->findInt32("color-format", &tmp)) {
        return INVALID_OPERATION;
@@ -3247,6 +3352,15 @@ status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) {
            break;
    }

    // Set up color aspects on input, but propagate them to the output format, as they will
    // not be read back from encoder.
    err = setColorAspects(
            kPortIndexInput, width, height, msg, outputFormat);
    if (err != OK) {
        ALOGI("[%s] cannot encode color aspects. Ignoring.", mComponentName.c_str());
        err = OK;
    }

    if (err == OK) {
        ALOGI("setupVideoEncoder succeeded");
    }
@@ -4220,6 +4334,8 @@ status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
                        break;
                    }

                    (void)getColorAspects(portIndex, notify);

                    OMX_CONFIG_RECTTYPE rect;
                    InitOMXParams(&rect);
                    rect.nPortIndex = portIndex;
+275 −0

File changed.

Preview size limit exceeded, changes collapsed.