/*
 * Copyright (C) 2013 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.
 */

#include <inttypes.h>

//#define LOG_NDEBUG 0
#define LOG_TAG "GoldfishVideoDecoderOMXComponent"
#include <utils/Log.h>

#include "GoldfishVideoDecoderOMXComponent.h"

#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ALooper.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/foundation/MediaDefs.h>
#include <media/hardware/HardwareAPI.h>

namespace android {

template<class T>
static void InitOMXParams(T *params) {
    params->nSize = sizeof(T);
    params->nVersion.s.nVersionMajor = 1;
    params->nVersion.s.nVersionMinor = 0;
    params->nVersion.s.nRevision = 0;
    params->nVersion.s.nStep = 0;
}

GoldfishVideoDecoderOMXComponent::GoldfishVideoDecoderOMXComponent(
        const char *name,
        const char *componentRole,
        OMX_VIDEO_CODINGTYPE codingType,
        const CodecProfileLevel *profileLevels,
        size_t numProfileLevels,
        int32_t width,
        int32_t height,
        const OMX_CALLBACKTYPE *callbacks,
        OMX_PTR appData,
        OMX_COMPONENTTYPE **component)
        : SimpleGoldfishOMXComponent(name, callbacks, appData, component),
        mIsAdaptive(false),
        mAdaptiveMaxWidth(0),
        mAdaptiveMaxHeight(0),
        mWidth(width),
        mHeight(height),
        mCropLeft(0),
        mCropTop(0),
        mCropWidth(width),
        mCropHeight(height),
        mOutputFormat(OMX_COLOR_FormatYUV420Planar),
        mOutputPortSettingsChange(NONE),
        mUpdateColorAspects(false),
        mMinInputBufferSize(384), // arbitrary, using one uncompressed macroblock
        mMinCompressionRatio(1),  // max input size is normally the output size
        mComponentRole(componentRole),
        mCodingType(codingType),
        mProfileLevels(profileLevels),
        mNumProfileLevels(numProfileLevels) {

    // init all the color aspects to be Unspecified.
    memset(&mDefaultColorAspects, 0, sizeof(ColorAspects));
    memset(&mBitstreamColorAspects, 0, sizeof(ColorAspects));
    memset(&mFinalColorAspects, 0, sizeof(ColorAspects));
    memset(&mHdrStaticInfo, 0, sizeof(HDRStaticInfo));
}

void GoldfishVideoDecoderOMXComponent::initPorts(
        OMX_U32 numInputBuffers,
        OMX_U32 inputBufferSize,
        OMX_U32 numOutputBuffers,
        const char *mimeType,
        OMX_U32 minCompressionRatio) {
    initPorts(numInputBuffers, numInputBuffers, inputBufferSize,
            numOutputBuffers, numOutputBuffers, mimeType, minCompressionRatio);
}

void GoldfishVideoDecoderOMXComponent::initPorts(
        OMX_U32 numMinInputBuffers,
        OMX_U32 numInputBuffers,
        OMX_U32 inputBufferSize,
        OMX_U32 numMinOutputBuffers,
        OMX_U32 numOutputBuffers,
        const char *mimeType,
        OMX_U32 minCompressionRatio) {
    mMinInputBufferSize = inputBufferSize;
    mMinCompressionRatio = minCompressionRatio;

    OMX_PARAM_PORTDEFINITIONTYPE def;
    InitOMXParams(&def);

    def.nPortIndex = kInputPortIndex;
    def.eDir = OMX_DirInput;
    def.nBufferCountMin = numMinInputBuffers;
    def.nBufferCountActual = numInputBuffers;
    def.nBufferSize = inputBufferSize;
    def.bEnabled = OMX_TRUE;
    def.bPopulated = OMX_FALSE;
    def.eDomain = OMX_PortDomainVideo;
    def.bBuffersContiguous = OMX_FALSE;
    def.nBufferAlignment = 1;

    def.format.video.cMIMEType = const_cast<char *>(mimeType);
    def.format.video.pNativeRender = NULL;
    /* size is initialized in updatePortDefinitions() */
    def.format.video.nBitrate = 0;
    def.format.video.xFramerate = 0;
    def.format.video.bFlagErrorConcealment = OMX_FALSE;
    def.format.video.eCompressionFormat = mCodingType;
    def.format.video.eColorFormat = OMX_COLOR_FormatUnused;
    def.format.video.pNativeWindow = NULL;

    addPort(def);

    def.nPortIndex = kOutputPortIndex;
    def.eDir = OMX_DirOutput;
    def.nBufferCountMin = numMinOutputBuffers;
    def.nBufferCountActual = numOutputBuffers;
    def.bEnabled = OMX_TRUE;
    def.bPopulated = OMX_FALSE;
    def.eDomain = OMX_PortDomainVideo;
    def.bBuffersContiguous = OMX_FALSE;
    def.nBufferAlignment = 2;

    def.format.video.cMIMEType = const_cast<char *>("video/raw");
    def.format.video.pNativeRender = NULL;
    /* size is initialized in updatePortDefinitions() */
    def.format.video.nBitrate = 0;
    def.format.video.xFramerate = 0;
    def.format.video.bFlagErrorConcealment = OMX_FALSE;
    def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
    def.format.video.pNativeWindow = NULL;

    addPort(def);

    updatePortDefinitions(true /* updateCrop */, true /* updateInputSize */);
}

void GoldfishVideoDecoderOMXComponent::updatePortDefinitions(bool updateCrop, bool updateInputSize) {
    OMX_PARAM_PORTDEFINITIONTYPE *outDef = &editPortInfo(kOutputPortIndex)->mDef;
    outDef->format.video.nFrameWidth = outputBufferWidth();
    outDef->format.video.nFrameHeight = outputBufferHeight();
    outDef->format.video.eColorFormat = mOutputFormat;
    outDef->format.video.nSliceHeight = outDef->format.video.nFrameHeight;

    int32_t bpp = (mOutputFormat == OMX_COLOR_FormatYUV420Planar16) ? 2 : 1;
    outDef->format.video.nStride = outDef->format.video.nFrameWidth * bpp;
    outDef->nBufferSize =
            (outDef->format.video.nStride * outDef->format.video.nSliceHeight * 3) / 2;

    OMX_PARAM_PORTDEFINITIONTYPE *inDef = &editPortInfo(kInputPortIndex)->mDef;
    inDef->format.video.nFrameWidth = mWidth;
    inDef->format.video.nFrameHeight = mHeight;
    // input port is compressed, hence it has no stride
    inDef->format.video.nStride = 0;
    inDef->format.video.nSliceHeight = 0;

    // when output format changes, input buffer size does not actually change
    if (updateInputSize) {
        inDef->nBufferSize = max(
                outDef->nBufferSize / mMinCompressionRatio,
                max(mMinInputBufferSize, inDef->nBufferSize));
    }

    if (updateCrop) {
        mCropLeft = 0;
        mCropTop = 0;
        mCropWidth = mWidth;
        mCropHeight = mHeight;
    }
}


uint32_t GoldfishVideoDecoderOMXComponent::outputBufferWidth() {
    return max(mIsAdaptive ? mAdaptiveMaxWidth : 0, mWidth);
}

uint32_t GoldfishVideoDecoderOMXComponent::outputBufferHeight() {
    return max(mIsAdaptive ? mAdaptiveMaxHeight : 0, mHeight);
}

void GoldfishVideoDecoderOMXComponent::handlePortSettingsChange(
        bool *portWillReset, uint32_t width, uint32_t height,
        OMX_COLOR_FORMATTYPE outputFormat,
        CropSettingsMode cropSettingsMode, bool fakeStride) {
    *portWillReset = false;
    bool sizeChanged = (width != mWidth || height != mHeight);
    bool formatChanged = (outputFormat != mOutputFormat);
    bool updateCrop = (cropSettingsMode == kCropUnSet);
    bool cropChanged = (cropSettingsMode == kCropChanged);
    bool strideChanged = false;
    if (fakeStride) {
        OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kOutputPortIndex)->mDef;
        if (def->format.video.nStride != (OMX_S32)width
                || def->format.video.nSliceHeight != (OMX_U32)height) {
            strideChanged = true;
        }
    }

    if (formatChanged || sizeChanged || cropChanged || strideChanged) {
        if (formatChanged) {
            ALOGD("formatChanged: 0x%08x -> 0x%08x", mOutputFormat, outputFormat);
        }
        mOutputFormat = outputFormat;
        mWidth = width;
        mHeight = height;

        if ((sizeChanged && !mIsAdaptive)
            || width > mAdaptiveMaxWidth
            || height > mAdaptiveMaxHeight
            || formatChanged) {
            if (mIsAdaptive) {
                if (width > mAdaptiveMaxWidth) {
                    mAdaptiveMaxWidth = width;
                }
                if (height > mAdaptiveMaxHeight) {
                    mAdaptiveMaxHeight = height;
                }
            }
            updatePortDefinitions(updateCrop);
            notify(OMX_EventPortSettingsChanged, kOutputPortIndex, 0, NULL);
            mOutputPortSettingsChange = AWAITING_DISABLED;
            *portWillReset = true;
        } else {
            updatePortDefinitions(updateCrop);

            if (fakeStride) {
                // MAJOR HACK that is not pretty, it's just to fool the renderer to read the correct
                // data.
                // Some software decoders (e.g. SoftMPEG4) fill decoded frame directly to output
                // buffer without considering the output buffer stride and slice height. So this is
                // used to signal how the buffer is arranged.  The alternative is to re-arrange the
                // output buffer in SoftMPEG4, but that results in memcopies.
                OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kOutputPortIndex)->mDef;
                def->format.video.nStride = mWidth;
                def->format.video.nSliceHeight = mHeight;
            }

            notify(OMX_EventPortSettingsChanged, kOutputPortIndex,
                   OMX_IndexConfigCommonOutputCrop, NULL);
        }
    } else if (mUpdateColorAspects) {
        notify(OMX_EventPortSettingsChanged, kOutputPortIndex,
                kDescribeColorAspectsIndex, NULL);
        mUpdateColorAspects = false;
    }
}

void GoldfishVideoDecoderOMXComponent::dumpColorAspects(const ColorAspects &colorAspects) {
    ALOGD("dumpColorAspects: (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) ",
            colorAspects.mRange, asString(colorAspects.mRange),
            colorAspects.mPrimaries, asString(colorAspects.mPrimaries),
            colorAspects.mMatrixCoeffs, asString(colorAspects.mMatrixCoeffs),
            colorAspects.mTransfer, asString(colorAspects.mTransfer));
}

bool GoldfishVideoDecoderOMXComponent::colorAspectsDiffer(
        const ColorAspects &a, const ColorAspects &b) {
    if (a.mRange != b.mRange
        || a.mPrimaries != b.mPrimaries
        || a.mTransfer != b.mTransfer
        || a.mMatrixCoeffs != b.mMatrixCoeffs) {
        return true;
    }
    return false;
}

void GoldfishVideoDecoderOMXComponent::updateFinalColorAspects(
        const ColorAspects &otherAspects, const ColorAspects &preferredAspects) {
    Mutex::Autolock autoLock(mColorAspectsLock);
    ColorAspects newAspects;
    newAspects.mRange = preferredAspects.mRange != ColorAspects::RangeUnspecified ?
        preferredAspects.mRange : otherAspects.mRange;
    newAspects.mPrimaries = preferredAspects.mPrimaries != ColorAspects::PrimariesUnspecified ?
        preferredAspects.mPrimaries : otherAspects.mPrimaries;
    newAspects.mTransfer = preferredAspects.mTransfer != ColorAspects::TransferUnspecified ?
        preferredAspects.mTransfer : otherAspects.mTransfer;
    newAspects.mMatrixCoeffs = preferredAspects.mMatrixCoeffs != ColorAspects::MatrixUnspecified ?
        preferredAspects.mMatrixCoeffs : otherAspects.mMatrixCoeffs;

    // Check to see if need update mFinalColorAspects.
    if (colorAspectsDiffer(mFinalColorAspects, newAspects)) {
        mFinalColorAspects = newAspects;
        mUpdateColorAspects = true;
    }
}

status_t GoldfishVideoDecoderOMXComponent::handleColorAspectsChange() {
    int perference = getColorAspectPreference();
    ALOGD("Color Aspects preference: %d ", perference);

    if (perference == kPreferBitstream) {
        updateFinalColorAspects(mDefaultColorAspects, mBitstreamColorAspects);
    } else if (perference == kPreferContainer) {
        updateFinalColorAspects(mBitstreamColorAspects, mDefaultColorAspects);
    } else {
        return OMX_ErrorUnsupportedSetting;
    }
    return OK;
}

void GoldfishVideoDecoderOMXComponent::copyYV12FrameToOutputBuffer(
        uint8_t *dst, const uint8_t *srcY, const uint8_t *srcU, const uint8_t *srcV,
        size_t srcYStride, size_t srcUStride, size_t srcVStride) {
    OMX_PARAM_PORTDEFINITIONTYPE *outDef = &editPortInfo(kOutputPortIndex)->mDef;
    int32_t bpp = (outDef->format.video.eColorFormat == OMX_COLOR_FormatYUV420Planar16) ? 2 : 1;

    size_t dstYStride = outputBufferWidth() * bpp;
    size_t dstUVStride = dstYStride / 2;
    size_t dstHeight = outputBufferHeight();
    uint8_t *dstStart = dst;

    for (size_t i = 0; i < mHeight; ++i) {
         memcpy(dst, srcY, mWidth * bpp);
         srcY += srcYStride;
         dst += dstYStride;
    }

    dst = dstStart + dstYStride * dstHeight;
    for (size_t i = 0; i < mHeight / 2; ++i) {
         memcpy(dst, srcU, mWidth / 2 * bpp);
         srcU += srcUStride;
         dst += dstUVStride;
    }

    dst = dstStart + (5 * dstYStride * dstHeight) / 4;
    for (size_t i = 0; i < mHeight / 2; ++i) {
         memcpy(dst, srcV, mWidth / 2 * bpp);
         srcV += srcVStride;
         dst += dstUVStride;
    }
}

OMX_ERRORTYPE GoldfishVideoDecoderOMXComponent::internalGetParameter(
        OMX_INDEXTYPE index, OMX_PTR params) {
    switch (index) {
        case OMX_IndexParamVideoPortFormat:
        {
            OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
                (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;

            if (!isValidOMXParam(formatParams)) {
                return OMX_ErrorBadParameter;
            }

            if (formatParams->nPortIndex > kMaxPortIndex) {
                return OMX_ErrorBadPortIndex;
            }

            if (formatParams->nIndex != 0) {
                return OMX_ErrorNoMore;
            }

            if (formatParams->nPortIndex == kInputPortIndex) {
                formatParams->eCompressionFormat = mCodingType;
                formatParams->eColorFormat = OMX_COLOR_FormatUnused;
                formatParams->xFramerate = 0;
            } else {
                CHECK_EQ(formatParams->nPortIndex, 1u);

                formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused;
                formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar;
                formatParams->xFramerate = 0;
            }

            return OMX_ErrorNone;
        }

        case OMX_IndexParamVideoProfileLevelQuerySupported:
        {
            OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevel =
                  (OMX_VIDEO_PARAM_PROFILELEVELTYPE *) params;

            if (!isValidOMXParam(profileLevel)) {
                return OMX_ErrorBadParameter;
            }

            if (profileLevel->nPortIndex != kInputPortIndex) {
                ALOGE("Invalid port index: %" PRIu32, profileLevel->nPortIndex);
                return OMX_ErrorUnsupportedIndex;
            }

            if (profileLevel->nProfileIndex >= mNumProfileLevels) {
                return OMX_ErrorNoMore;
            }

            profileLevel->eProfile = mProfileLevels[profileLevel->nProfileIndex].mProfile;
            profileLevel->eLevel   = mProfileLevels[profileLevel->nProfileIndex].mLevel;
            return OMX_ErrorNone;
        }

        default:
            return SimpleGoldfishOMXComponent::internalGetParameter(index, params);
    }
}

OMX_ERRORTYPE GoldfishVideoDecoderOMXComponent::internalSetParameter(
        OMX_INDEXTYPE index, const OMX_PTR params) {
    // Include extension index OMX_INDEXEXTTYPE.
    const int32_t indexFull = index;

    switch (indexFull) {
        case OMX_IndexParamStandardComponentRole:
        {
            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
                (const OMX_PARAM_COMPONENTROLETYPE *)params;

            if (!isValidOMXParam(roleParams)) {
                return OMX_ErrorBadParameter;
            }

            if (strncmp((const char *)roleParams->cRole,
                        mComponentRole,
                        OMX_MAX_STRINGNAME_SIZE - 1)) {
                return OMX_ErrorUndefined;
            }

            return OMX_ErrorNone;
        }

        case OMX_IndexParamVideoPortFormat:
        {
            OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
                (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;

            if (!isValidOMXParam(formatParams)) {
                return OMX_ErrorBadParameter;
            }

            if (formatParams->nPortIndex > kMaxPortIndex) {
                return OMX_ErrorBadPortIndex;
            }

            if (formatParams->nPortIndex == kInputPortIndex) {
                if (formatParams->eCompressionFormat != mCodingType
                        || formatParams->eColorFormat != OMX_COLOR_FormatUnused) {
                    return OMX_ErrorUnsupportedSetting;
                }
            } else {
                if (formatParams->eCompressionFormat != OMX_VIDEO_CodingUnused
                        || formatParams->eColorFormat != OMX_COLOR_FormatYUV420Planar) {
                    return OMX_ErrorUnsupportedSetting;
                }
            }

            return OMX_ErrorNone;
        }

        case kPrepareForAdaptivePlaybackIndex:
        {
            const PrepareForAdaptivePlaybackParams* adaptivePlaybackParams =
                    (const PrepareForAdaptivePlaybackParams *)params;

            if (!isValidOMXParam(adaptivePlaybackParams)) {
                return OMX_ErrorBadParameter;
            }

            mIsAdaptive = adaptivePlaybackParams->bEnable;
            if (mIsAdaptive) {
                mAdaptiveMaxWidth = adaptivePlaybackParams->nMaxFrameWidth;
                mAdaptiveMaxHeight = adaptivePlaybackParams->nMaxFrameHeight;
                mWidth = mAdaptiveMaxWidth;
                mHeight = mAdaptiveMaxHeight;
            } else {
                mAdaptiveMaxWidth = 0;
                mAdaptiveMaxHeight = 0;
            }
            updatePortDefinitions(true /* updateCrop */, true /* updateInputSize */);
            return OMX_ErrorNone;
        }

        case OMX_IndexParamPortDefinition:
        {
            OMX_PARAM_PORTDEFINITIONTYPE *newParams =
                (OMX_PARAM_PORTDEFINITIONTYPE *)params;

            if (!isValidOMXParam(newParams)) {
                return OMX_ErrorBadParameter;
            }

            OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &newParams->format.video;
            OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(newParams->nPortIndex)->mDef;

            uint32_t oldWidth = def->format.video.nFrameWidth;
            uint32_t oldHeight = def->format.video.nFrameHeight;
            uint32_t newWidth = video_def->nFrameWidth;
            uint32_t newHeight = video_def->nFrameHeight;
            // We need width, height, stride and slice-height to be non-zero and sensible.
            // These values were chosen to prevent integer overflows further down the line, and do
            // not indicate support for 32kx32k video.
            if (newWidth > 32768 || newHeight > 32768
                    || video_def->nStride > 32768 || video_def->nStride < -32768
                    || video_def->nSliceHeight > 32768) {
                ALOGE("b/22885421");
                return OMX_ErrorBadParameter;
            }
            if (newWidth != oldWidth || newHeight != oldHeight) {
                bool outputPort = (newParams->nPortIndex == kOutputPortIndex);
                if (outputPort) {
                    // only update (essentially crop) if size changes
                    mWidth = newWidth;
                    mHeight = newHeight;

                    updatePortDefinitions(true /* updateCrop */, true /* updateInputSize */);
                    // reset buffer size based on frame size
                    newParams->nBufferSize = def->nBufferSize;
                } else {
                    // For input port, we only set nFrameWidth and nFrameHeight. Buffer size
                    // is updated when configuring the output port using the max-frame-size,
                    // though client can still request a larger size.
                    def->format.video.nFrameWidth = newWidth;
                    def->format.video.nFrameHeight = newHeight;
                }
            }
            return SimpleGoldfishOMXComponent::internalSetParameter(index, params);
        }

        default:
            return SimpleGoldfishOMXComponent::internalSetParameter(index, params);
    }
}

OMX_ERRORTYPE GoldfishVideoDecoderOMXComponent::getConfig(
        OMX_INDEXTYPE index, OMX_PTR params) {
    switch ((int)index) {
        case OMX_IndexConfigCommonOutputCrop:
        {
            OMX_CONFIG_RECTTYPE *rectParams = (OMX_CONFIG_RECTTYPE *)params;

            if (!isValidOMXParam(rectParams)) {
                return OMX_ErrorBadParameter;
            }

            if (rectParams->nPortIndex != kOutputPortIndex) {
                return OMX_ErrorUndefined;
            }

            rectParams->nLeft = mCropLeft;
            rectParams->nTop = mCropTop;
            rectParams->nWidth = mCropWidth;
            rectParams->nHeight = mCropHeight;

            return OMX_ErrorNone;
        }
        case kDescribeColorAspectsIndex:
        {
            if (!supportsDescribeColorAspects()) {
                return OMX_ErrorUnsupportedIndex;
            }

            DescribeColorAspectsParams* colorAspectsParams =
                    (DescribeColorAspectsParams *)params;

            if (!isValidOMXParam(colorAspectsParams)) {
                return OMX_ErrorBadParameter;
            }

            if (colorAspectsParams->nPortIndex != kOutputPortIndex) {
                return OMX_ErrorBadParameter;
            }

            colorAspectsParams->sAspects = mFinalColorAspects;
            if (colorAspectsParams->bRequestingDataSpace || colorAspectsParams->bDataSpaceChanged) {
                return OMX_ErrorUnsupportedSetting;
            }

            return OMX_ErrorNone;
        }

        case kDescribeHdrStaticInfoIndex:
        {
            if (!supportDescribeHdrStaticInfo()) {
                return OMX_ErrorUnsupportedIndex;
            }

            DescribeHDRStaticInfoParams* hdrStaticInfoParams =
                    (DescribeHDRStaticInfoParams *)params;

            if (!isValidOMXParam(hdrStaticInfoParams)) {
                return OMX_ErrorBadParameter;
            }

            if (hdrStaticInfoParams->nPortIndex != kOutputPortIndex) {
                return OMX_ErrorBadPortIndex;
            }

            hdrStaticInfoParams->sInfo = mHdrStaticInfo;

            return OMX_ErrorNone;
        }

        case kDescribeHdr10PlusInfoIndex:
        {
            if (!supportDescribeHdr10PlusInfo()) {
                return OMX_ErrorUnsupportedIndex;
            }

            if (mHdr10PlusOutputs.size() > 0) {
                auto it = mHdr10PlusOutputs.begin();

                auto info = (*it).get();

                DescribeHDR10PlusInfoParams* outParams =
                        (DescribeHDR10PlusInfoParams *)params;

                outParams->nParamSizeUsed = info->size();

                // If the buffer provided by the client does not have enough
                // storage, return the size only and do not remove the param yet.
                if (outParams->nParamSize >= info->size()) {
                    memcpy(outParams->nValue, info->data(), info->size());
                    mHdr10PlusOutputs.erase(it);
                }
                return OMX_ErrorNone;
            }
            return OMX_ErrorUnderflow;
        }

        default:
            return OMX_ErrorUnsupportedIndex;
    }
}

OMX_ERRORTYPE GoldfishVideoDecoderOMXComponent::internalSetConfig(
        OMX_INDEXTYPE index, const OMX_PTR params, bool *frameConfig){
    switch ((int)index) {
        case kDescribeColorAspectsIndex:
        {
            if (!supportsDescribeColorAspects()) {
                return OMX_ErrorUnsupportedIndex;
            }
            const DescribeColorAspectsParams* colorAspectsParams =
                    (const DescribeColorAspectsParams *)params;

            if (!isValidOMXParam(colorAspectsParams)) {
                return OMX_ErrorBadParameter;
            }

            if (colorAspectsParams->nPortIndex != kOutputPortIndex) {
                return OMX_ErrorBadParameter;
            }

            // Update color aspects if necessary.
            if (colorAspectsDiffer(colorAspectsParams->sAspects, mDefaultColorAspects)) {
                mDefaultColorAspects = colorAspectsParams->sAspects;
                status_t err = handleColorAspectsChange();
                CHECK(err == OK);
            }
            return OMX_ErrorNone;
        }

        case kDescribeHdrStaticInfoIndex:
        {
            if (!supportDescribeHdrStaticInfo()) {
                return OMX_ErrorUnsupportedIndex;
            }

            const DescribeHDRStaticInfoParams* hdrStaticInfoParams =
                    (DescribeHDRStaticInfoParams *)params;

            if (!isValidOMXParam(hdrStaticInfoParams)) {
                return OMX_ErrorBadParameter;
            }

            if (hdrStaticInfoParams->nPortIndex != kOutputPortIndex) {
                return OMX_ErrorBadPortIndex;
            }

            mHdrStaticInfo = hdrStaticInfoParams->sInfo;
            updatePortDefinitions(false);

            return OMX_ErrorNone;
        }

        case kDescribeHdr10PlusInfoIndex:
        {
            if (!supportDescribeHdr10PlusInfo()) {
                return OMX_ErrorUnsupportedIndex;
            }

            const DescribeHDR10PlusInfoParams* inParams =
                    (DescribeHDR10PlusInfoParams *)params;

            if (*frameConfig) {
                // This is a request to append to the current frame config set.
                // For now, we only support kDescribeHdr10PlusInfoIndex, which
                // we simply replace with the last set value.
                if (mHdr10PlusInputs.size() > 0) {
                    *(--mHdr10PlusInputs.end()) = ABuffer::CreateAsCopy(
                            inParams->nValue, inParams->nParamSizeUsed);
                } else {
                    ALOGW("Ignoring kDescribeHdr10PlusInfoIndex: append to "
                            "frame config while no frame config is present");
                }
            } else {
                // This is a frame config, setting *frameConfig to true so that
                // the client marks the next queued input frame to apply it.
                *frameConfig = true;
                mHdr10PlusInputs.push_back(ABuffer::CreateAsCopy(
                        inParams->nValue, inParams->nParamSizeUsed));
            }
            return OMX_ErrorNone;
        }

        default:
            return OMX_ErrorUnsupportedIndex;
    }
}

sp<ABuffer> GoldfishVideoDecoderOMXComponent::dequeueInputFrameConfig() {
    auto it = mHdr10PlusInputs.begin();
    sp<ABuffer> info = *it;
    mHdr10PlusInputs.erase(it);
    return info;
}

void GoldfishVideoDecoderOMXComponent::queueOutputFrameConfig(const sp<ABuffer> &info) {
    mHdr10PlusOutputs.push_back(info);
    notify(OMX_EventConfigUpdate,
           kOutputPortIndex,
           kDescribeHdr10PlusInfoIndex,
           NULL);
}

OMX_ERRORTYPE GoldfishVideoDecoderOMXComponent::getExtensionIndex(
        const char *name, OMX_INDEXTYPE *index) {
    if (!strcmp(name, "OMX.google.android.index.prepareForAdaptivePlayback")) {
        *(int32_t*)index = kPrepareForAdaptivePlaybackIndex;
        return OMX_ErrorNone;
    } else if (!strcmp(name, "OMX.google.android.index.describeColorAspects")
                && supportsDescribeColorAspects()) {
        *(int32_t*)index = kDescribeColorAspectsIndex;
        return OMX_ErrorNone;
    } else if (!strcmp(name, "OMX.google.android.index.describeHDRStaticInfo")
            && supportDescribeHdrStaticInfo()) {
        *(int32_t*)index = kDescribeHdrStaticInfoIndex;
        return OMX_ErrorNone;
    } else if (!strcmp(name, "OMX.google.android.index.describeHDR10PlusInfo")
            && supportDescribeHdr10PlusInfo()) {
        *(int32_t*)index = kDescribeHdr10PlusInfoIndex;
        return OMX_ErrorNone;
    }

    return SimpleGoldfishOMXComponent::getExtensionIndex(name, index);
}

bool GoldfishVideoDecoderOMXComponent::supportsDescribeColorAspects() {
    return getColorAspectPreference() != kNotSupported;
}

int GoldfishVideoDecoderOMXComponent::getColorAspectPreference() {
    return kNotSupported;
}

bool GoldfishVideoDecoderOMXComponent::supportDescribeHdrStaticInfo() {
    return false;
}

bool GoldfishVideoDecoderOMXComponent::supportDescribeHdr10PlusInfo() {
    return false;
}

void GoldfishVideoDecoderOMXComponent::onReset() {
    mOutputPortSettingsChange = NONE;
}

void GoldfishVideoDecoderOMXComponent::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
    if (portIndex != kOutputPortIndex) {
        return;
    }

    switch (mOutputPortSettingsChange) {
        case NONE:
            break;

        case AWAITING_DISABLED:
        {
            CHECK(!enabled);
            mOutputPortSettingsChange = AWAITING_ENABLED;
            break;
        }

        default:
        {
            CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
            CHECK(enabled);
            mOutputPortSettingsChange = NONE;
            break;
        }
    }
}

}  // namespace android
