/*
 * Copyright (C) 2009 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 "OMXNodeInstance"
#include <android-base/macros.h>
#include <utils/Log.h>

#include <inttypes.h>

#include <media/stagefright/omx/OMXNodeInstance.h>
#include <media/stagefright/omx/OMXMaster.h>
#include <media/stagefright/omx/OMXUtils.h>
#include <android/IOMXBufferSource.h>

#include <media/openmax/OMX_Component.h>
#include <media/openmax/OMX_IndexExt.h>
#include <media/openmax/OMX_VideoExt.h>
#include <media/openmax/OMX_AsString.h>

#include <binder/IMemory.h>
#include <cutils/properties.h>
#include <gui/BufferQueue.h>
#include <media/hardware/HardwareAPI.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ColorUtils.h>
#include <media/stagefright/MediaErrors.h>
#include <utils/misc.h>
#include <utils/NativeHandle.h>
#include <media/OMXBuffer.h>
#include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>

#include <hidlmemory/mapping.h>

static const OMX_U32 kPortIndexInput = 0;
static const OMX_U32 kPortIndexOutput = 1;

#define CLOGW(fmt, ...) ALOGW("[%p:%s] " fmt, mHandle, mName, ##__VA_ARGS__)

#define CLOG_ERROR_IF(cond, fn, err, fmt, ...) \
    ALOGE_IF(cond, #fn "(%p:%s, " fmt ") ERROR: %s(%#x)", \
    mHandle, mName, ##__VA_ARGS__, asString(err), err)
#define CLOG_ERROR(fn, err, fmt, ...) CLOG_ERROR_IF(true, fn, err, fmt, ##__VA_ARGS__)
#define CLOG_IF_ERROR(fn, err, fmt, ...) \
    CLOG_ERROR_IF((err) != OMX_ErrorNone, fn, err, fmt, ##__VA_ARGS__)

#define CLOGI_(level, fn, fmt, ...) \
    ALOGI_IF(DEBUG >= (level), #fn "(%p:%s, " fmt ")", mHandle, mName, ##__VA_ARGS__)
#define CLOGD_(level, fn, fmt, ...) \
    ALOGD_IF(DEBUG >= (level), #fn "(%p:%s, " fmt ")", mHandle, mName, ##__VA_ARGS__)

#define CLOG_LIFE(fn, fmt, ...)     CLOGI_(ADebug::kDebugLifeCycle,     fn, fmt, ##__VA_ARGS__)
#define CLOG_STATE(fn, fmt, ...)    CLOGI_(ADebug::kDebugState,         fn, fmt, ##__VA_ARGS__)
#define CLOG_CONFIG(fn, fmt, ...)   CLOGI_(ADebug::kDebugConfig,        fn, fmt, ##__VA_ARGS__)
#define CLOG_INTERNAL(fn, fmt, ...) CLOGD_(ADebug::kDebugInternalState, fn, fmt, ##__VA_ARGS__)

#define CLOG_DEBUG_IF(cond, fn, fmt, ...) \
    ALOGD_IF(cond, #fn "(%p, " fmt ")", mHandle, ##__VA_ARGS__)

#define CLOG_BUFFER(fn, fmt, ...) \
    CLOG_DEBUG_IF(DEBUG >= ADebug::kDebugAll, fn, fmt, ##__VA_ARGS__)
#define CLOG_BUMPED_BUFFER(fn, fmt, ...) \
    CLOG_DEBUG_IF(DEBUG_BUMP >= ADebug::kDebugAll, fn, fmt, ##__VA_ARGS__)

/* buffer formatting */
#define BUFFER_FMT(port, fmt, ...) "%s:%u " fmt, portString(port), (port), ##__VA_ARGS__
#define NEW_BUFFER_FMT(buffer_id, port, fmt, ...) \
    BUFFER_FMT(port, fmt ") (#%zu => %#x", ##__VA_ARGS__, mActiveBuffers.size(), (buffer_id))

#define SIMPLE_BUFFER(port, size, data) BUFFER_FMT(port, "%zu@%p", (size), (data))
#define SIMPLE_NEW_BUFFER(buffer_id, port, size, data) \
    NEW_BUFFER_FMT(buffer_id, port, "%zu@%p", (size), (data))

#define EMPTY_BUFFER(addr, header, fenceFd) "%#x [%u@%p fc=%d]", \
    (addr), (header)->nAllocLen, (header)->pBuffer, (fenceFd)
#define FULL_BUFFER(addr, header, fenceFd) "%#" PRIxPTR " [%u@%p (%u..+%u) f=%x ts=%lld fc=%d]", \
    (intptr_t)(addr), (header)->nAllocLen, (header)->pBuffer, \
    (header)->nOffset, (header)->nFilledLen, (header)->nFlags, (header)->nTimeStamp, (fenceFd)

#define WITH_STATS_WRAPPER(fmt, ...) fmt " { IN=%zu/%zu OUT=%zu/%zu }", ##__VA_ARGS__, \
    mInputBuffersWithCodec.size(), mNumPortBuffers[kPortIndexInput], \
    mOutputBuffersWithCodec.size(), mNumPortBuffers[kPortIndexOutput]
// TRICKY: this is needed so formatting macros expand before substitution
#define WITH_STATS(fmt, ...) WITH_STATS_WRAPPER(fmt, ##__VA_ARGS__)

namespace android {

struct BufferMeta {
    explicit BufferMeta(
            const sp<IMemory> &mem, const sp<IHidlMemory> &hidlMemory,
            OMX_U32 portIndex, bool copy, OMX_U8 *backup)
        : mMem(mem),
          mHidlMemory(hidlMemory),
          mCopyFromOmx(portIndex == kPortIndexOutput && copy),
          mCopyToOmx(portIndex == kPortIndexInput && copy),
          mPortIndex(portIndex),
          mBackup(backup) {
    }

    explicit BufferMeta(OMX_U32 portIndex)
        : mCopyFromOmx(false),
          mCopyToOmx(false),
          mPortIndex(portIndex),
          mBackup(NULL) {
    }

    explicit BufferMeta(const sp<GraphicBuffer> &graphicBuffer, OMX_U32 portIndex)
        : mGraphicBuffer(graphicBuffer),
          mCopyFromOmx(false),
          mCopyToOmx(false),
          mPortIndex(portIndex),
          mBackup(NULL) {
    }

    OMX_U8 *getPointer() {
        return mMem.get() ? static_cast<OMX_U8*>(mMem->pointer()) :
                mHidlMemory.get() ? static_cast<OMX_U8*>(
                static_cast<void*>(mHidlMemory->getPointer())) : nullptr;
    }

    void CopyFromOMX(const OMX_BUFFERHEADERTYPE *header) {
        if (!mCopyFromOmx) {
            return;
        }

        // check component returns proper range
        sp<ABuffer> codec = getBuffer(header, true /* limit */);

        memcpy(getPointer() + header->nOffset, codec->data(), codec->size());
    }

    void CopyToOMX(const OMX_BUFFERHEADERTYPE *header) {
        if (!mCopyToOmx) {
            return;
        }

        memcpy(header->pBuffer + header->nOffset,
                getPointer() + header->nOffset,
                header->nFilledLen);
    }

    // return the codec buffer
    sp<ABuffer> getBuffer(const OMX_BUFFERHEADERTYPE *header, bool limit) {
        sp<ABuffer> buf = new ABuffer(header->pBuffer, header->nAllocLen);
        if (limit) {
            if (header->nOffset + header->nFilledLen > header->nOffset
                    && header->nOffset + header->nFilledLen <= header->nAllocLen) {
                buf->setRange(header->nOffset, header->nFilledLen);
            } else {
                buf->setRange(0, 0);
            }
        }
        return buf;
    }

    void setGraphicBuffer(const sp<GraphicBuffer> &graphicBuffer) {
        mGraphicBuffer = graphicBuffer;
    }

    void setNativeHandle(const sp<NativeHandle> &nativeHandle) {
        mNativeHandle = nativeHandle;
    }

    OMX_U32 getPortIndex() {
        return mPortIndex;
    }

    ~BufferMeta() {
        delete[] mBackup;
    }

private:
    sp<GraphicBuffer> mGraphicBuffer;
    sp<NativeHandle> mNativeHandle;
    sp<IMemory> mMem;
    sp<IHidlMemory> mHidlMemory;
    bool mCopyFromOmx;
    bool mCopyToOmx;
    OMX_U32 mPortIndex;
    OMX_U8 *mBackup;

    BufferMeta(const BufferMeta &);
    BufferMeta &operator=(const BufferMeta &);
};

// static
OMX_CALLBACKTYPE OMXNodeInstance::kCallbacks = {
    &OnEvent, &OnEmptyBufferDone, &OnFillBufferDone
};

static inline const char *portString(OMX_U32 portIndex) {
    switch (portIndex) {
        case kPortIndexInput:  return "Input";
        case kPortIndexOutput: return "Output";
        case ~0U:              return "All";
        default:               return "port";
    }
}

////////////////////////////////////////////////////////////////////////////////

// This provides the underlying Thread used by CallbackDispatcher.
// Note that deriving CallbackDispatcher from Thread does not work.

struct OMXNodeInstance::CallbackDispatcherThread : public Thread {
    explicit CallbackDispatcherThread(CallbackDispatcher *dispatcher)
        : mDispatcher(dispatcher) {
    }

private:
    CallbackDispatcher *mDispatcher;

    bool threadLoop();

    CallbackDispatcherThread(const CallbackDispatcherThread &);
    CallbackDispatcherThread &operator=(const CallbackDispatcherThread &);
};

////////////////////////////////////////////////////////////////////////////////

struct OMXNodeInstance::CallbackDispatcher : public RefBase {
    explicit CallbackDispatcher(const sp<OMXNodeInstance> &owner);

    // Posts |msg| to the listener's queue. If |realTime| is true, the listener thread is notified
    // that a new message is available on the queue. Otherwise, the message stays on the queue, but
    // the listener is not notified of it. It will process this message when a subsequent message
    // is posted with |realTime| set to true.
    void post(const omx_message &msg, bool realTime = true);

    bool loop();

protected:
    virtual ~CallbackDispatcher();

private:
    enum {
        // This is used for frame_rendered message batching, which will eventually end up in a
        // single AMessage in MediaCodec when it is signaled to the app. AMessage can contain
        // up-to 64 key-value pairs, and each frame_rendered message uses 2 keys, so the max
        // value for this would be 32. Nonetheless, limit this to 12 to which gives at least 10
        // mseconds of batching at 120Hz.
        kMaxQueueSize = 12,
    };

    Mutex mLock;

    sp<OMXNodeInstance> const mOwner;
    bool mDone;
    Condition mQueueChanged;
    std::list<omx_message> mQueue;

    sp<CallbackDispatcherThread> mThread;

    void dispatch(std::list<omx_message> &messages);

    CallbackDispatcher(const CallbackDispatcher &);
    CallbackDispatcher &operator=(const CallbackDispatcher &);
};

OMXNodeInstance::CallbackDispatcher::CallbackDispatcher(const sp<OMXNodeInstance> &owner)
    : mOwner(owner),
      mDone(false) {
    mThread = new CallbackDispatcherThread(this);
    mThread->run("OMXCallbackDisp", ANDROID_PRIORITY_FOREGROUND);
}

OMXNodeInstance::CallbackDispatcher::~CallbackDispatcher() {
    {
        Mutex::Autolock autoLock(mLock);

        mDone = true;
        mQueueChanged.signal();
    }

    // A join on self can happen if the last ref to CallbackDispatcher
    // is released within the CallbackDispatcherThread loop
    status_t status = mThread->join();
    if (status != WOULD_BLOCK) {
        // Other than join to self, the only other error return codes are
        // whatever readyToRun() returns, and we don't override that
        CHECK_EQ(status, (status_t)NO_ERROR);
    }
}

void OMXNodeInstance::CallbackDispatcher::post(const omx_message &msg, bool realTime) {
    Mutex::Autolock autoLock(mLock);

    mQueue.push_back(msg);
    if (realTime || mQueue.size() >= kMaxQueueSize) {
        mQueueChanged.signal();
    }
}

void OMXNodeInstance::CallbackDispatcher::dispatch(std::list<omx_message> &messages) {
    if (mOwner == NULL) {
        ALOGV("Would have dispatched a message to a node that's already gone.");
        return;
    }
    mOwner->onMessages(messages);
}

bool OMXNodeInstance::CallbackDispatcher::loop() {
    for (;;) {
        std::list<omx_message> messages;

        {
            Mutex::Autolock autoLock(mLock);
            while (!mDone && mQueue.empty()) {
                mQueueChanged.wait(mLock);
            }

            if (mDone) {
                break;
            }

            messages.swap(mQueue);
        }

        dispatch(messages);
    }

    return false;
}

////////////////////////////////////////////////////////////////////////////////

bool OMXNodeInstance::CallbackDispatcherThread::threadLoop() {
    return mDispatcher->loop();
}

////////////////////////////////////////////////////////////////////////////////

OMXNodeInstance::OMXNodeInstance(
        Omx *owner, const sp<IOMXObserver> &observer, const char *name)
    : mOwner(owner),
      mHandle(NULL),
      mObserver(observer),
      mDying(false),
      mSailed(false),
      mQueriedProhibitedExtensions(false),
      mQuirks(0),
      mBufferIDCount(0),
      mRestorePtsFailed(false),
      mMaxTimestampGapUs(0ll),
      mPrevOriginalTimeUs(-1ll),
      mPrevModifiedTimeUs(-1ll)
{
    mName = ADebug::GetDebugName(name);
    DEBUG = ADebug::GetDebugLevelFromProperty(name, "debug.stagefright.omx-debug");
    ALOGV("debug level for %s is %d", name, DEBUG);
    DEBUG_BUMP = DEBUG;
    mNumPortBuffers[0] = 0;
    mNumPortBuffers[1] = 0;
    mDebugLevelBumpPendingBuffers[0] = 0;
    mDebugLevelBumpPendingBuffers[1] = 0;
    mMetadataType[0] = kMetadataBufferTypeInvalid;
    mMetadataType[1] = kMetadataBufferTypeInvalid;
    mPortMode[0] = IOMX::kPortModePresetByteBuffer;
    mPortMode[1] = IOMX::kPortModePresetByteBuffer;
    mSecureBufferType[0] = kSecureBufferTypeUnknown;
    mSecureBufferType[1] = kSecureBufferTypeUnknown;
    mGraphicBufferEnabled[0] = false;
    mGraphicBufferEnabled[1] = false;
    mIsSecure = AString(name).endsWith(".secure");
    mLegacyAdaptiveExperiment = ADebug::isExperimentEnabled("legacy-adaptive");
}

OMXNodeInstance::~OMXNodeInstance() {
    free(mName);
    CHECK(mHandle == NULL);
}

void OMXNodeInstance::setHandle(OMX_HANDLETYPE handle) {
    CLOG_LIFE(allocateNode, "handle=%p", handle);
    CHECK(mHandle == NULL);
    mHandle = handle;
    if (handle != NULL) {
        mDispatcher = new CallbackDispatcher(this);
    }
}

sp<IOMXBufferSource> OMXNodeInstance::getBufferSource() {
    Mutex::Autolock autoLock(mOMXBufferSourceLock);
    return mOMXBufferSource;
}

void OMXNodeInstance::setBufferSource(const sp<IOMXBufferSource>& bufferSource) {
    Mutex::Autolock autoLock(mOMXBufferSourceLock);
    CLOG_INTERNAL(setBufferSource, "%p", bufferSource.get());
    mOMXBufferSource = bufferSource;
}

OMX_HANDLETYPE OMXNodeInstance::handle() {
    return mHandle;
}

sp<IOMXObserver> OMXNodeInstance::observer() {
    return mObserver;
}

status_t OMXNodeInstance::freeNode() {
    CLOG_LIFE(freeNode, "handle=%p", mHandle);
    static int32_t kMaxNumIterations = 10;

    // Transition the node from its current state all the way down
    // to "Loaded".
    // This ensures that all active buffers are properly freed even
    // for components that don't do this themselves on a call to
    // "FreeHandle".

    // The code below may trigger some more events to be dispatched
    // by the OMX component - we want to ignore them as our client
    // does not expect them.
    bool expected = false;
    if (!mDying.compare_exchange_strong(expected, true)) {
        // exit if we have already freed the node or doing so right now.
        // NOTE: this ensures that the block below executes at most once.
        ALOGV("Already dying");
        return OK;
    }

    OMX_STATETYPE state;
    CHECK_EQ(OMX_GetState(mHandle, &state), OMX_ErrorNone);
    switch (state) {
        case OMX_StateExecuting:
        {
            ALOGV("forcing Executing->Idle");
            sendCommand(OMX_CommandStateSet, OMX_StateIdle);
            OMX_ERRORTYPE err;
            int32_t iteration = 0;
            while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone
                    && state != OMX_StateIdle
                    && state != OMX_StateInvalid) {
                if (++iteration > kMaxNumIterations) {
                    CLOGW("failed to enter Idle state (now %s(%d), aborting.",
                            asString(state), state);
                    state = OMX_StateInvalid;
                    break;
                }

                usleep(100000);
            }
            CHECK_EQ(err, OMX_ErrorNone);

            if (state == OMX_StateInvalid) {
                break;
            }

            FALLTHROUGH_INTENDED;
        }

        case OMX_StateIdle:
        {
            ALOGV("forcing Idle->Loaded");
            sendCommand(OMX_CommandStateSet, OMX_StateLoaded);

            freeActiveBuffers();

            OMX_ERRORTYPE err;
            int32_t iteration = 0;
            while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone
                    && state != OMX_StateLoaded
                    && state != OMX_StateInvalid) {
                if (++iteration > kMaxNumIterations) {
                    CLOGW("failed to enter Loaded state (now %s(%d), aborting.",
                            asString(state), state);
                    state = OMX_StateInvalid;
                    break;
                }

                ALOGV("waiting for Loaded state...");
                usleep(100000);
            }
            CHECK_EQ(err, OMX_ErrorNone);

            FALLTHROUGH_INTENDED;
        }

        case OMX_StateLoaded:
        case OMX_StateInvalid:
            break;

        default:
            LOG_ALWAYS_FATAL("unknown state %s(%#x).", asString(state), state);
            break;
    }

    Mutex::Autolock _l(mLock);

    status_t err = mOwner->freeNode(this);

    mDispatcher.clear();
    mOMXBufferSource.clear();

    mHandle = NULL;
    CLOG_IF_ERROR(freeNode, err, "");
    free(mName);
    mName = NULL;

    ALOGV("OMXNodeInstance going away.");

    return err;
}

status_t OMXNodeInstance::sendCommand(
        OMX_COMMANDTYPE cmd, OMX_S32 param) {
    const sp<IOMXBufferSource> bufferSource(getBufferSource());
    if (bufferSource != NULL && cmd == OMX_CommandStateSet) {
        if (param == OMX_StateIdle) {
            // Initiating transition from Executing -> Idle
            // ACodec is waiting for all buffers to be returned, do NOT
            // submit any more buffers to the codec.
            bufferSource->onOmxIdle();
        } else if (param == OMX_StateLoaded) {
            // Initiating transition from Idle/Executing -> Loaded
            // Buffers are about to be freed.
            bufferSource->onOmxLoaded();
            setBufferSource(NULL);
        }

        // fall through
    }

    Mutex::Autolock autoLock(mLock);

    if (cmd == OMX_CommandStateSet) {
        // There are no configurations past first StateSet command.
        mSailed = true;
    }

    // bump internal-state debug level for 2 input and output frames past a command
    {
        Mutex::Autolock _l(mDebugLock);
        bumpDebugLevel_l(2 /* numInputBuffers */, 2 /* numOutputBuffers */);
    }

    const char *paramString =
        cmd == OMX_CommandStateSet ? asString((OMX_STATETYPE)param) : portString(param);
    CLOG_STATE(sendCommand, "%s(%d), %s(%d)", asString(cmd), cmd, paramString, param);
    OMX_ERRORTYPE err = OMX_SendCommand(mHandle, cmd, param, NULL);
    CLOG_IF_ERROR(sendCommand, err, "%s(%d), %s(%d)", asString(cmd), cmd, paramString, param);
    return StatusFromOMXError(err);
}

bool OMXNodeInstance::isProhibitedIndex_l(OMX_INDEXTYPE index) {
    // these extensions can only be used from OMXNodeInstance, not by clients directly.
    static const char *restricted_extensions[] = {
        "OMX.google.android.index.storeMetaDataInBuffers",
        "OMX.google.android.index.storeANWBufferInMetadata",
        "OMX.google.android.index.prepareForAdaptivePlayback",
        "OMX.google.android.index.configureVideoTunnelMode",
        "OMX.google.android.index.useAndroidNativeBuffer2",
        "OMX.google.android.index.useAndroidNativeBuffer",
        "OMX.google.android.index.enableAndroidNativeBuffers",
        "OMX.google.android.index.allocateNativeHandle",
        "OMX.google.android.index.getAndroidNativeBufferUsage",
    };

    if ((index > OMX_IndexComponentStartUnused && index < OMX_IndexComponentEndUnused)
            || (index > OMX_IndexPortStartUnused && index < OMX_IndexPortEndUnused)
            || (index > OMX_IndexAudioStartUnused && index < OMX_IndexAudioEndUnused)
            || (index > OMX_IndexVideoStartUnused && index < OMX_IndexVideoEndUnused)
            || (index > OMX_IndexCommonStartUnused && index < OMX_IndexCommonEndUnused)
            || (index > (OMX_INDEXTYPE)OMX_IndexExtAudioStartUnused
                    && index < (OMX_INDEXTYPE)OMX_IndexExtAudioEndUnused)
            || (index > (OMX_INDEXTYPE)OMX_IndexExtVideoStartUnused
                    && index < (OMX_INDEXTYPE)OMX_IndexExtVideoEndUnused)
            || (index > (OMX_INDEXTYPE)OMX_IndexExtOtherStartUnused
                    && index < (OMX_INDEXTYPE)OMX_IndexExtOtherEndUnused)) {
        return false;
    }

    if (!mQueriedProhibitedExtensions) {
        for (size_t i = 0; i < NELEM(restricted_extensions); ++i) {
            OMX_INDEXTYPE ext;
            if (OMX_GetExtensionIndex(mHandle, (OMX_STRING)restricted_extensions[i], &ext) == OMX_ErrorNone) {
                mProhibitedExtensions.add(ext);
            }
        }
        mQueriedProhibitedExtensions = true;
    }

    return mProhibitedExtensions.indexOf(index) >= 0;
}

status_t OMXNodeInstance::getParameter(
        OMX_INDEXTYPE index, void *params, size_t /* size */) {
    Mutex::Autolock autoLock(mLock);

    if (isProhibitedIndex_l(index)) {
        android_errorWriteLog(0x534e4554, "29422020");
        return BAD_INDEX;
    }

    OMX_ERRORTYPE err = OMX_GetParameter(mHandle, index, params);
    OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index;
    // some errors are expected for getParameter
    if (err != OMX_ErrorNoMore) {
        CLOG_IF_ERROR(getParameter, err, "%s(%#x)", asString(extIndex), index);
    }
    return StatusFromOMXError(err);
}

status_t OMXNodeInstance::setParameter(
        OMX_INDEXTYPE index, const void *params, size_t size) {
    Mutex::Autolock autoLock(mLock);
    OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index;
    CLOG_CONFIG(setParameter, "%s(%#x), %zu@%p)", asString(extIndex), index, size, params);

    if (extIndex == OMX_IndexParamMaxFrameDurationForBitrateControl) {
        return setMaxPtsGapUs(params, size);
    }

    if (isProhibitedIndex_l(index)) {
        android_errorWriteLog(0x534e4554, "29422020");
        return BAD_INDEX;
    }

    OMX_ERRORTYPE err = OMX_SetParameter(
            mHandle, index, const_cast<void *>(params));
    CLOG_IF_ERROR(setParameter, err, "%s(%#x)", asString(extIndex), index);
    return StatusFromOMXError(err);
}

status_t OMXNodeInstance::getConfig(
        OMX_INDEXTYPE index, void *params, size_t /* size */) {
    Mutex::Autolock autoLock(mLock);

    if (isProhibitedIndex_l(index)) {
        android_errorWriteLog(0x534e4554, "29422020");
        return BAD_INDEX;
    }

    OMX_ERRORTYPE err = OMX_GetConfig(mHandle, index, params);
    OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index;
    // some errors are expected for getConfig
    if (err != OMX_ErrorNoMore) {
        CLOG_IF_ERROR(getConfig, err, "%s(%#x)", asString(extIndex), index);
    }
    return StatusFromOMXError(err);
}

status_t OMXNodeInstance::setConfig(
        OMX_INDEXTYPE index, const void *params, size_t size) {
    Mutex::Autolock autoLock(mLock);
    OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index;
    CLOG_CONFIG(setConfig, "%s(%#x), %zu@%p)", asString(extIndex), index, size, params);

    if (isProhibitedIndex_l(index)) {
        android_errorWriteLog(0x534e4554, "29422020");
        return BAD_INDEX;
    }

    OMX_ERRORTYPE err = OMX_SetConfig(
            mHandle, index, const_cast<void *>(params));
    CLOG_IF_ERROR(setConfig, err, "%s(%#x)", asString(extIndex), index);
    return StatusFromOMXError(err);
}

status_t OMXNodeInstance::setPortMode(OMX_U32 portIndex, IOMX::PortMode mode) {
    Mutex::Autolock autoLock(mLock);

    if (portIndex >= NELEM(mPortMode)) {
        ALOGE("b/31385713, portIndex(%u)", portIndex);
        android_errorWriteLog(0x534e4554, "31385713");
        return BAD_VALUE;
    }

    if (mSailed || mNumPortBuffers[portIndex] > 0) {
        android_errorWriteLog(0x534e4554, "29422020");
        return INVALID_OPERATION;
    }

    CLOG_CONFIG(setPortMode, "%s(%d), port %d", asString(mode), mode, portIndex);

    status_t err = OK;
    switch (mode) {
    case IOMX::kPortModeDynamicANWBuffer:
    {
        if (portIndex == kPortIndexOutput) {
            if (mLegacyAdaptiveExperiment) {
                CLOG_INTERNAL(setPortMode, "Legacy adaptive experiment: "
                        "not setting port mode to %s(%d) on output",
                        asString(mode), mode);
                err = StatusFromOMXError(OMX_ErrorUnsupportedIndex);
                break;
            }

            err = enableNativeBuffers_l(
                    portIndex, OMX_TRUE /*graphic*/, OMX_TRUE);
            if (err != OK) {
                break;
            }
        }
        (void)enableNativeBuffers_l(portIndex, OMX_FALSE /*graphic*/, OMX_FALSE);
        err = storeMetaDataInBuffers_l(portIndex, OMX_TRUE, NULL);
        break;
    }

    case IOMX::kPortModeDynamicNativeHandle:
    {
        if (portIndex != kPortIndexInput) {
            CLOG_ERROR(setPortMode, BAD_VALUE,
                    "%s(%d) mode is only supported on input port", asString(mode), mode);
            err = BAD_VALUE;
            break;
        }
        (void)enableNativeBuffers_l(portIndex, OMX_TRUE /*graphic*/, OMX_FALSE);
        (void)enableNativeBuffers_l(portIndex, OMX_FALSE /*graphic*/, OMX_FALSE);

        MetadataBufferType metaType = kMetadataBufferTypeNativeHandleSource;
        err = storeMetaDataInBuffers_l(portIndex, OMX_TRUE, &metaType);
        break;
    }

    case IOMX::kPortModePresetSecureBuffer:
    {
        // Allow on both input and output.
        (void)storeMetaDataInBuffers_l(portIndex, OMX_FALSE, NULL);
        (void)enableNativeBuffers_l(portIndex, OMX_TRUE /*graphic*/, OMX_FALSE);
        err = enableNativeBuffers_l(portIndex, OMX_FALSE /*graphic*/, OMX_TRUE);
        break;
    }

    case IOMX::kPortModePresetANWBuffer:
    {
        if (portIndex != kPortIndexOutput) {
            CLOG_ERROR(setPortMode, BAD_VALUE,
                    "%s(%d) mode is only supported on output port", asString(mode), mode);
            err = BAD_VALUE;
            break;
        }

        // Check if we're simulating legacy mode with metadata mode,
        // if so, enable metadata mode.
        if (mLegacyAdaptiveExperiment) {
            if (storeMetaDataInBuffers_l(portIndex, OMX_TRUE, NULL) == OK) {
                CLOG_INTERNAL(setPortMode, "Legacy adaptive experiment: "
                        "metdata mode enabled successfully");
                break;
            }

            CLOG_INTERNAL(setPortMode, "Legacy adaptive experiment: "
                    "unable to enable metadata mode on output");

            mLegacyAdaptiveExperiment = false;
        }

        // Disable secure buffer and enable graphic buffer
        (void)enableNativeBuffers_l(portIndex, OMX_FALSE /*graphic*/, OMX_FALSE);
        err = enableNativeBuffers_l(portIndex, OMX_TRUE /*graphic*/, OMX_TRUE);
        if (err != OK) {
            break;
        }

        // Not running experiment, or metadata is not supported.
        // Disable metadata mode and use legacy mode.
        (void)storeMetaDataInBuffers_l(portIndex, OMX_FALSE, NULL);
        break;
    }

    case IOMX::kPortModePresetByteBuffer:
    {
        // Disable secure buffer, native buffer and metadata.
        (void)enableNativeBuffers_l(portIndex, OMX_TRUE /*graphic*/, OMX_FALSE);
        (void)enableNativeBuffers_l(portIndex, OMX_FALSE /*graphic*/, OMX_FALSE);
        (void)storeMetaDataInBuffers_l(portIndex, OMX_FALSE, NULL);
        break;
    }

    default:
        CLOG_ERROR(setPortMode, BAD_VALUE, "invalid port mode %d", mode);
        err = BAD_VALUE;
        break;
    }

    if (err == OK) {
        mPortMode[portIndex] = mode;
    }
    return err;
}

status_t OMXNodeInstance::enableNativeBuffers_l(
        OMX_U32 portIndex, OMX_BOOL graphic, OMX_BOOL enable) {
    if (portIndex >= NELEM(mSecureBufferType)) {
        ALOGE("b/31385713, portIndex(%u)", portIndex);
        android_errorWriteLog(0x534e4554, "31385713");
        return BAD_VALUE;
    }

    CLOG_CONFIG(enableNativeBuffers, "%s:%u%s, %d", portString(portIndex), portIndex,
                graphic ? ", graphic" : "", enable);
    OMX_STRING name = const_cast<OMX_STRING>(
            graphic ? "OMX.google.android.index.enableAndroidNativeBuffers"
                    : "OMX.google.android.index.allocateNativeHandle");

    OMX_INDEXTYPE index;
    OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);

    if (err == OMX_ErrorNone) {
        EnableAndroidNativeBuffersParams params;
        InitOMXParams(&params);
        params.nPortIndex = portIndex;
        params.enable = enable;

        err = OMX_SetParameter(mHandle, index, &params);
        CLOG_IF_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d", name, index,
                      portString(portIndex), portIndex, enable);
        if (!graphic) {
            if (err == OMX_ErrorNone) {
                mSecureBufferType[portIndex] =
                    enable ? kSecureBufferTypeNativeHandle : kSecureBufferTypeOpaque;
            } else if (mSecureBufferType[portIndex] == kSecureBufferTypeUnknown) {
                mSecureBufferType[portIndex] = kSecureBufferTypeOpaque;
            }
        } else {
            if (err == OMX_ErrorNone) {
                mGraphicBufferEnabled[portIndex] = enable;
            } else if (enable) {
                mGraphicBufferEnabled[portIndex] = false;
            }
        }
    } else {
        CLOG_ERROR_IF(enable, getExtensionIndex, err, "%s", name);
        if (!graphic) {
            // Extension not supported, check for manual override with system property
            // This is a temporary workaround until partners support the OMX extension
            if (property_get_bool("media.mediadrmservice.enable", false)) {
                CLOG_CONFIG(enableNativeBuffers, "system property override: using native-handles");
                mSecureBufferType[portIndex] = kSecureBufferTypeNativeHandle;
            } else if (mSecureBufferType[portIndex] == kSecureBufferTypeUnknown) {
                mSecureBufferType[portIndex] = kSecureBufferTypeOpaque;
            }
            err = OMX_ErrorNone;
        }
    }

    return StatusFromOMXError(err);
}

status_t OMXNodeInstance::getGraphicBufferUsage(
        OMX_U32 portIndex, OMX_U32* usage) {
    Mutex::Autolock autoLock(mLock);

    OMX_INDEXTYPE index;
    OMX_STRING name = const_cast<OMX_STRING>(
            "OMX.google.android.index.getAndroidNativeBufferUsage");
    OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);

    if (err != OMX_ErrorNone) {
        CLOG_ERROR(getExtensionIndex, err, "%s", name);
        return StatusFromOMXError(err);
    }

    GetAndroidNativeBufferUsageParams params;
    InitOMXParams(&params);
    params.nPortIndex = portIndex;

    err = OMX_GetParameter(mHandle, index, &params);
    if (err != OMX_ErrorNone) {
        CLOG_ERROR(getParameter, err, "%s(%#x): %s:%u", name, index,
                portString(portIndex), portIndex);
        return StatusFromOMXError(err);
    }

    *usage = params.nUsage;

    return OK;
}

status_t OMXNodeInstance::storeMetaDataInBuffers_l(
        OMX_U32 portIndex, OMX_BOOL enable, MetadataBufferType *type) {
    if (mSailed) {
        android_errorWriteLog(0x534e4554, "29422020");
        return INVALID_OPERATION;
    }
    if (portIndex != kPortIndexInput && portIndex != kPortIndexOutput) {
        android_errorWriteLog(0x534e4554, "26324358");
        if (type != NULL) {
            *type = kMetadataBufferTypeInvalid;
        }
        return BAD_VALUE;
    }

    OMX_INDEXTYPE index;
    OMX_STRING name = const_cast<OMX_STRING>(
            "OMX.google.android.index.storeMetaDataInBuffers");

    OMX_STRING nativeBufferName = const_cast<OMX_STRING>(
            "OMX.google.android.index.storeANWBufferInMetadata");
    MetadataBufferType negotiatedType;
    MetadataBufferType requestedType = type != NULL ? *type : kMetadataBufferTypeANWBuffer;

    StoreMetaDataInBuffersParams params;
    InitOMXParams(&params);
    params.nPortIndex = portIndex;
    params.bStoreMetaData = enable;

    OMX_ERRORTYPE err =
        requestedType == kMetadataBufferTypeANWBuffer
                ? OMX_GetExtensionIndex(mHandle, nativeBufferName, &index)
                : OMX_ErrorUnsupportedIndex;
    OMX_ERRORTYPE xerr = err;
    if (err == OMX_ErrorNone) {
        err = OMX_SetParameter(mHandle, index, &params);
        if (err == OMX_ErrorNone) {
            name = nativeBufferName; // set name for debugging
            negotiatedType = requestedType;
        }
    }
    if (err != OMX_ErrorNone) {
        err = OMX_GetExtensionIndex(mHandle, name, &index);
        xerr = err;
        if (err == OMX_ErrorNone) {
            negotiatedType =
                requestedType == kMetadataBufferTypeANWBuffer
                        ? kMetadataBufferTypeGrallocSource : requestedType;
            err = OMX_SetParameter(mHandle, index, &params);
        }
        if (err == OMX_ErrorBadParameter) {
            err = OMX_ErrorUnsupportedIndex;
        }
    }

    // don't log loud error if component does not support metadata mode on the output
    if (err != OMX_ErrorNone) {
        if (err == OMX_ErrorUnsupportedIndex && portIndex == kPortIndexOutput) {
            CLOGW("component does not support metadata mode; using fallback");
        } else if (xerr != OMX_ErrorNone) {
            CLOG_ERROR(getExtensionIndex, xerr, "%s", name);
        } else {
            CLOG_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d type=%d", name, index,
                    portString(portIndex), portIndex, enable, negotiatedType);
        }
        negotiatedType = mMetadataType[portIndex];
    } else {
        if (!enable) {
            negotiatedType = kMetadataBufferTypeInvalid;
        }
        mMetadataType[portIndex] = negotiatedType;
    }
    CLOG_CONFIG(storeMetaDataInBuffers, "%s:%u %srequested %s:%d negotiated %s:%d",
            portString(portIndex), portIndex, enable ? "" : "UN",
            asString(requestedType), requestedType, asString(negotiatedType), negotiatedType);

    if (type != NULL) {
        *type = negotiatedType;
    }

    return StatusFromOMXError(err);
}

status_t OMXNodeInstance::prepareForAdaptivePlayback(
        OMX_U32 portIndex, OMX_BOOL enable, OMX_U32 maxFrameWidth,
        OMX_U32 maxFrameHeight) {
    Mutex::Autolock autolock(mLock);
    if (mSailed) {
        android_errorWriteLog(0x534e4554, "29422020");
        return INVALID_OPERATION;
    }
    CLOG_CONFIG(prepareForAdaptivePlayback, "%s:%u en=%d max=%ux%u",
            portString(portIndex), portIndex, enable, maxFrameWidth, maxFrameHeight);

    if (mLegacyAdaptiveExperiment) {
        CLOG_INTERNAL(prepareForAdaptivePlayback,
                "Legacy adaptive experiment: reporting success");
        return OK;
    }

    OMX_INDEXTYPE index;
    OMX_STRING name = const_cast<OMX_STRING>(
            "OMX.google.android.index.prepareForAdaptivePlayback");

    OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
    if (err != OMX_ErrorNone) {
        CLOG_ERROR_IF(enable, getExtensionIndex, err, "%s", name);
        return StatusFromOMXError(err);
    }

    PrepareForAdaptivePlaybackParams params;
    InitOMXParams(&params);
    params.nPortIndex = portIndex;
    params.bEnable = enable;
    params.nMaxFrameWidth = maxFrameWidth;
    params.nMaxFrameHeight = maxFrameHeight;

    err = OMX_SetParameter(mHandle, index, &params);
    CLOG_IF_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d max=%ux%u", name, index,
            portString(portIndex), portIndex, enable, maxFrameWidth, maxFrameHeight);
    return StatusFromOMXError(err);
}

status_t OMXNodeInstance::configureVideoTunnelMode(
        OMX_U32 portIndex, OMX_BOOL tunneled, OMX_U32 audioHwSync,
        native_handle_t **sidebandHandle) {
    Mutex::Autolock autolock(mLock);
    if (mSailed) {
        android_errorWriteLog(0x534e4554, "29422020");
        return INVALID_OPERATION;
    }
    CLOG_CONFIG(configureVideoTunnelMode, "%s:%u tun=%d sync=%u",
            portString(portIndex), portIndex, tunneled, audioHwSync);

    OMX_INDEXTYPE index;
    OMX_STRING name = const_cast<OMX_STRING>(
            "OMX.google.android.index.configureVideoTunnelMode");

    OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
    if (err != OMX_ErrorNone) {
        CLOG_ERROR_IF(tunneled, getExtensionIndex, err, "%s", name);
        return StatusFromOMXError(err);
    }

    ConfigureVideoTunnelModeParams tunnelParams;
    InitOMXParams(&tunnelParams);
    tunnelParams.nPortIndex = portIndex;
    tunnelParams.bTunneled = tunneled;
    tunnelParams.nAudioHwSync = audioHwSync;
    err = OMX_SetParameter(mHandle, index, &tunnelParams);
    if (err != OMX_ErrorNone) {
        CLOG_ERROR(setParameter, err, "%s(%#x): %s:%u tun=%d sync=%u", name, index,
                portString(portIndex), portIndex, tunneled, audioHwSync);
        return StatusFromOMXError(err);
    }

    err = OMX_GetParameter(mHandle, index, &tunnelParams);
    if (err != OMX_ErrorNone) {
        CLOG_ERROR(getParameter, err, "%s(%#x): %s:%u tun=%d sync=%u", name, index,
                portString(portIndex), portIndex, tunneled, audioHwSync);
        return StatusFromOMXError(err);
    }
    if (sidebandHandle) {
        *sidebandHandle = (native_handle_t*)tunnelParams.pSidebandWindow;
    }

    return OK;
}

status_t OMXNodeInstance::useBuffer(
        OMX_U32 portIndex, const OMXBuffer &omxBuffer, IOMX::buffer_id *buffer) {
    if (buffer == NULL) {
        ALOGE("b/25884056");
        return BAD_VALUE;
    }

    if (portIndex >= NELEM(mNumPortBuffers)) {
        return BAD_VALUE;
    }

    Mutex::Autolock autoLock(mLock);
    if (!mSailed) {
        ALOGE("b/35467458");
        android_errorWriteLog(0x534e4554, "35467458");
        return BAD_VALUE;
    }

    switch (omxBuffer.mBufferType) {
        case OMXBuffer::kBufferTypePreset: {
            if (mPortMode[portIndex] != IOMX::kPortModeDynamicANWBuffer
                    && mPortMode[portIndex] != IOMX::kPortModeDynamicNativeHandle) {
                break;
            }
            return useBuffer_l(portIndex, NULL, NULL, buffer);
        }

        case OMXBuffer::kBufferTypeSharedMem: {
            if (mPortMode[portIndex] != IOMX::kPortModePresetByteBuffer
                    && mPortMode[portIndex] != IOMX::kPortModeDynamicANWBuffer) {
                break;
            }
            return useBuffer_l(portIndex, omxBuffer.mMem, NULL, buffer);
        }

        case OMXBuffer::kBufferTypeANWBuffer: {
            if (mPortMode[portIndex] != IOMX::kPortModePresetANWBuffer) {
                break;
            }
            return useGraphicBuffer_l(portIndex, omxBuffer.mGraphicBuffer, buffer);
        }

        case OMXBuffer::kBufferTypeHidlMemory: {
                if (mPortMode[portIndex] != IOMX::kPortModePresetByteBuffer
                        && mPortMode[portIndex] != IOMX::kPortModeDynamicANWBuffer
                        && mPortMode[portIndex] != IOMX::kPortModeDynamicNativeHandle) {
                    break;
                }
                sp<IHidlMemory> hidlMemory = mapMemory(omxBuffer.mHidlMemory);
                if (hidlMemory == nullptr) {
                    ALOGE("OMXNodeInstance useBuffer() failed to map memory");
                    return NO_MEMORY;
                }
                return useBuffer_l(portIndex, NULL, hidlMemory, buffer);
        }
        default:
            return BAD_VALUE;
            break;
    }

    ALOGE("b/77486542 : bufferType = %d vs. portMode = %d",
          omxBuffer.mBufferType, mPortMode[portIndex]);
    android_errorWriteLog(0x534e4554, "77486542");
    return INVALID_OPERATION;
}

status_t OMXNodeInstance::useBuffer_l(
        OMX_U32 portIndex, const sp<IMemory> &params,
        const sp<IHidlMemory> &hParams, IOMX::buffer_id *buffer) {
    BufferMeta *buffer_meta;
    OMX_BUFFERHEADERTYPE *header;
    OMX_ERRORTYPE err = OMX_ErrorNone;
    bool isMetadata = mMetadataType[portIndex] != kMetadataBufferTypeInvalid;

    if (!isMetadata && mGraphicBufferEnabled[portIndex]) {
        ALOGE("b/62948670");
        android_errorWriteLog(0x534e4554, "62948670");
        return INVALID_OPERATION;
    }

    size_t paramsSize;
    void* paramsPointer;
    if (params != NULL && hParams != NULL) {
        return BAD_VALUE;
    }
    if (params != NULL) {
        paramsPointer = params->pointer();
        paramsSize = params->size();
    } else if (hParams != NULL) {
        paramsPointer = hParams->getPointer();
        paramsSize = hParams->getSize();
    } else {
        paramsPointer = nullptr;
    }

    OMX_U32 allottedSize;
    if (isMetadata) {
        if (mMetadataType[portIndex] == kMetadataBufferTypeGrallocSource) {
            allottedSize = sizeof(VideoGrallocMetadata);
        } else if (mMetadataType[portIndex] == kMetadataBufferTypeANWBuffer) {
            allottedSize = sizeof(VideoNativeMetadata);
        } else if (mMetadataType[portIndex] == kMetadataBufferTypeNativeHandleSource) {
            allottedSize = sizeof(VideoNativeHandleMetadata);
        } else {
            return BAD_VALUE;
        }
    } else {
        // NULL params is allowed only in metadata mode.
        if (paramsPointer == nullptr) {
            ALOGE("b/25884056");
            return BAD_VALUE;
        }
        allottedSize = paramsSize;
    }

    bool isOutputGraphicMetadata = (portIndex == kPortIndexOutput) &&
            (mMetadataType[portIndex] == kMetadataBufferTypeGrallocSource ||
                    mMetadataType[portIndex] == kMetadataBufferTypeANWBuffer);

    uint32_t requiresAllocateBufferBit =
        (portIndex == kPortIndexInput)
            ? kRequiresAllocateBufferOnInputPorts
            : kRequiresAllocateBufferOnOutputPorts;

    // we use useBuffer for output metadata regardless of quirks
    if (!isOutputGraphicMetadata && (mQuirks & requiresAllocateBufferBit)) {
        // metadata buffers are not connected cross process; only copy if not meta.
        buffer_meta = new BufferMeta(
                    params, hParams, portIndex, !isMetadata /* copy */, NULL /* data */);

        err = OMX_AllocateBuffer(
                mHandle, &header, portIndex, buffer_meta, allottedSize);

        if (err != OMX_ErrorNone) {
            CLOG_ERROR(allocateBuffer, err,
                    SIMPLE_BUFFER(portIndex, (size_t)allottedSize,
                            paramsPointer));
        }
    } else {
        OMX_U8 *data = NULL;

        // metadata buffers are not connected cross process
        // use a backup buffer instead of the actual buffer
        if (isMetadata) {
            data = new (std::nothrow) OMX_U8[allottedSize];
            if (data == NULL) {
                return NO_MEMORY;
            }
            memset(data, 0, allottedSize);

            buffer_meta = new BufferMeta(
                    params, hParams, portIndex, false /* copy */, data);
        } else {
            data = static_cast<OMX_U8 *>(paramsPointer);

            buffer_meta = new BufferMeta(
                    params, hParams, portIndex, false /* copy */, NULL);
        }

        err = OMX_UseBuffer(
                mHandle, &header, portIndex, buffer_meta,
                allottedSize, data);

        if (err != OMX_ErrorNone) {
            CLOG_ERROR(useBuffer, err, SIMPLE_BUFFER(
                    portIndex, (size_t)allottedSize, data));
        }
    }

    if (err != OMX_ErrorNone) {
        delete buffer_meta;
        buffer_meta = NULL;

        *buffer = 0;

        return StatusFromOMXError(err);
    }

    CHECK_EQ(header->pAppPrivate, buffer_meta);

    *buffer = makeBufferID(header);

    addActiveBuffer(portIndex, *buffer);

    sp<IOMXBufferSource> bufferSource(getBufferSource());
    if (bufferSource != NULL && portIndex == kPortIndexInput) {
        bufferSource->onInputBufferAdded(*buffer);
    }

    CLOG_BUFFER(useBuffer, NEW_BUFFER_FMT(
            *buffer, portIndex, "%u(%zu)@%p", allottedSize, paramsSize, paramsPointer));
    return OK;
}

status_t OMXNodeInstance::useGraphicBuffer2_l(
        OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
        IOMX::buffer_id *buffer) {
    if (graphicBuffer == NULL || buffer == NULL) {
        ALOGE("b/25884056");
        return BAD_VALUE;
    }

    // port definition
    OMX_PARAM_PORTDEFINITIONTYPE def;
    InitOMXParams(&def);
    def.nPortIndex = portIndex;
    OMX_ERRORTYPE err = OMX_GetParameter(mHandle, OMX_IndexParamPortDefinition, &def);
    if (err != OMX_ErrorNone) {
        OMX_INDEXTYPE index = OMX_IndexParamPortDefinition;
        CLOG_ERROR(getParameter, err, "%s(%#x): %s:%u",
                asString(index), index, portString(portIndex), portIndex);
        return UNKNOWN_ERROR;
    }

    BufferMeta *bufferMeta = new BufferMeta(graphicBuffer, portIndex);

    OMX_BUFFERHEADERTYPE *header = NULL;
    OMX_U8* bufferHandle = const_cast<OMX_U8*>(
            reinterpret_cast<const OMX_U8*>(graphicBuffer->handle));

    err = OMX_UseBuffer(
            mHandle,
            &header,
            portIndex,
            bufferMeta,
            def.nBufferSize,
            bufferHandle);

    if (err != OMX_ErrorNone) {
        CLOG_ERROR(useBuffer, err, BUFFER_FMT(portIndex, "%u@%p", def.nBufferSize, bufferHandle));
        delete bufferMeta;
        bufferMeta = NULL;
        *buffer = 0;
        return StatusFromOMXError(err);
    }

    CHECK_EQ(header->pBuffer, bufferHandle);
    CHECK_EQ(header->pAppPrivate, bufferMeta);

    *buffer = makeBufferID(header);

    addActiveBuffer(portIndex, *buffer);
    CLOG_BUFFER(useGraphicBuffer2, NEW_BUFFER_FMT(
            *buffer, portIndex, "%u@%p", def.nBufferSize, bufferHandle));
    return OK;
}

// XXX: This function is here for backwards compatibility.  Once the OMX
// implementations have been updated this can be removed and useGraphicBuffer2
// can be renamed to useGraphicBuffer.
status_t OMXNodeInstance::useGraphicBuffer_l(
        OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
        IOMX::buffer_id *buffer) {
    if (graphicBuffer == NULL || buffer == NULL) {
        ALOGE("b/25884056");
        return BAD_VALUE;
    }

    // First, see if we're in metadata mode. We could be running an experiment to simulate
    // legacy behavior (preallocated buffers) on devices that supports meta.
    if (mMetadataType[portIndex] != kMetadataBufferTypeInvalid) {
        return useGraphicBufferWithMetadata_l(
                portIndex, graphicBuffer, buffer);
    }

    if (!mGraphicBufferEnabled[portIndex]) {
        // Report error if this is not in graphic buffer mode.
        ALOGE("b/62948670");
        android_errorWriteLog(0x534e4554, "62948670");
        return INVALID_OPERATION;
    }

    // See if the newer version of the extension is present.
    OMX_INDEXTYPE index;
    if (OMX_GetExtensionIndex(
            mHandle,
            const_cast<OMX_STRING>("OMX.google.android.index.useAndroidNativeBuffer2"),
            &index) == OMX_ErrorNone) {
        return useGraphicBuffer2_l(portIndex, graphicBuffer, buffer);
    }

    OMX_STRING name = const_cast<OMX_STRING>(
        "OMX.google.android.index.useAndroidNativeBuffer");
    OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
    if (err != OMX_ErrorNone) {
        CLOG_ERROR(getExtensionIndex, err, "%s", name);
        return StatusFromOMXError(err);
    }

    BufferMeta *bufferMeta = new BufferMeta(graphicBuffer, portIndex);

    OMX_BUFFERHEADERTYPE *header;

    OMX_VERSIONTYPE ver;
    ver.s.nVersionMajor = 1;
    ver.s.nVersionMinor = 0;
    ver.s.nRevision = 0;
    ver.s.nStep = 0;
    UseAndroidNativeBufferParams params = {
        sizeof(UseAndroidNativeBufferParams), ver, portIndex, bufferMeta,
        &header, graphicBuffer,
    };

    err = OMX_SetParameter(mHandle, index, &params);

    if (err != OMX_ErrorNone) {
        CLOG_ERROR(setParameter, err, "%s(%#x): %s:%u meta=%p GB=%p", name, index,
                portString(portIndex), portIndex, bufferMeta, graphicBuffer->handle);

        delete bufferMeta;
        bufferMeta = NULL;

        *buffer = 0;

        return StatusFromOMXError(err);
    }

    CHECK_EQ(header->pAppPrivate, bufferMeta);

    *buffer = makeBufferID(header);

    addActiveBuffer(portIndex, *buffer);
    CLOG_BUFFER(useGraphicBuffer, NEW_BUFFER_FMT(
            *buffer, portIndex, "GB=%p", graphicBuffer->handle));
    return OK;
}

status_t OMXNodeInstance::useGraphicBufferWithMetadata_l(
        OMX_U32 portIndex, const sp<GraphicBuffer> &graphicBuffer,
        IOMX::buffer_id *buffer) {
    if (portIndex != kPortIndexOutput) {
        return BAD_VALUE;
    }

    if (mMetadataType[portIndex] != kMetadataBufferTypeGrallocSource &&
            mMetadataType[portIndex] != kMetadataBufferTypeANWBuffer) {
        return BAD_VALUE;
    }

    status_t err = useBuffer_l(portIndex, NULL, NULL, buffer);
    if (err != OK) {
        return err;
    }

    OMX_BUFFERHEADERTYPE *header = findBufferHeader(*buffer, portIndex);

    return updateGraphicBufferInMeta_l(portIndex, graphicBuffer, *buffer, header);

}

status_t OMXNodeInstance::updateGraphicBufferInMeta_l(
        OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
        IOMX::buffer_id buffer, OMX_BUFFERHEADERTYPE *header) {
    // No need to check |graphicBuffer| since NULL is valid for it as below.
    if (header == NULL) {
        ALOGE("b/25884056");
        return BAD_VALUE;
    }

    if (portIndex != kPortIndexInput && portIndex != kPortIndexOutput) {
        return BAD_VALUE;
    }

    BufferMeta *bufferMeta = (BufferMeta *)(header->pAppPrivate);
    sp<ABuffer> data = bufferMeta->getBuffer(header, false /* limit */);
    bufferMeta->setGraphicBuffer(graphicBuffer);
    MetadataBufferType metaType = mMetadataType[portIndex];
    if (metaType == kMetadataBufferTypeGrallocSource
            && data->capacity() >= sizeof(VideoGrallocMetadata)) {
        VideoGrallocMetadata &metadata = *(VideoGrallocMetadata *)(data->data());
        metadata.eType = kMetadataBufferTypeGrallocSource;
        metadata.pHandle = graphicBuffer == NULL ? NULL : graphicBuffer->handle;
    } else if (metaType == kMetadataBufferTypeANWBuffer
            && data->capacity() >= sizeof(VideoNativeMetadata)) {
        VideoNativeMetadata &metadata = *(VideoNativeMetadata *)(data->data());
        metadata.eType = kMetadataBufferTypeANWBuffer;
        metadata.pBuffer = graphicBuffer == NULL ? NULL : graphicBuffer->getNativeBuffer();
        metadata.nFenceFd = -1;
    } else {
        CLOG_ERROR(updateGraphicBufferInMeta, BAD_VALUE, "%s:%u, %#x bad type (%d) or size (%u)",
            portString(portIndex), portIndex, buffer, mMetadataType[portIndex], header->nAllocLen);
        return BAD_VALUE;
    }

    CLOG_BUFFER(updateGraphicBufferInMeta, "%s:%u, %#x := %p",
            portString(portIndex), portIndex, buffer,
            graphicBuffer == NULL ? NULL : graphicBuffer->handle);
    return OK;
}

status_t OMXNodeInstance::updateNativeHandleInMeta_l(
        OMX_U32 portIndex, const sp<NativeHandle>& nativeHandle,
        IOMX::buffer_id buffer, OMX_BUFFERHEADERTYPE *header) {
    // No need to check |nativeHandle| since NULL is valid for it as below.
    if (header == NULL) {
        ALOGE("b/25884056");
        return BAD_VALUE;
    }

    if (portIndex != kPortIndexInput && portIndex != kPortIndexOutput) {
        return BAD_VALUE;
    }

    BufferMeta *bufferMeta = (BufferMeta *)(header->pAppPrivate);
    sp<ABuffer> data = bufferMeta->getBuffer(header, false /* limit */);
    bufferMeta->setNativeHandle(nativeHandle);
    if (mMetadataType[portIndex] == kMetadataBufferTypeNativeHandleSource
            && data->capacity() >= sizeof(VideoNativeHandleMetadata)) {
        VideoNativeHandleMetadata &metadata = *(VideoNativeHandleMetadata *)(data->data());
        metadata.eType = mMetadataType[portIndex];
        metadata.pHandle =
            nativeHandle == NULL ? NULL : const_cast<native_handle*>(nativeHandle->handle());
    } else {
        CLOG_ERROR(updateNativeHandleInMeta, BAD_VALUE, "%s:%u, %#x bad type (%d) or size (%zu)",
            portString(portIndex), portIndex, buffer, mMetadataType[portIndex], data->capacity());
        return BAD_VALUE;
    }

    CLOG_BUFFER(updateNativeHandleInMeta, "%s:%u, %#x := %p",
            portString(portIndex), portIndex, buffer,
            nativeHandle == NULL ? NULL : nativeHandle->handle());
    return OK;
}

status_t OMXNodeInstance::setInputSurface(
        const sp<IOMXBufferSource> &bufferSource) {
    Mutex::Autolock autolock(mLock);

    status_t err;

    // only allow graphic source on input port, when there are no allocated buffers yet
    if (mNumPortBuffers[kPortIndexInput] > 0) {
        android_errorWriteLog(0x534e4554, "29422020");
        return INVALID_OPERATION;
    }

    if (getBufferSource() != NULL) {
        return ALREADY_EXISTS;
    }

    err = storeMetaDataInBuffers_l(kPortIndexInput, OMX_TRUE, NULL);
    if (err != OK) {
        return err;
    }

    // Retrieve the width and height of the graphic buffer, set when the
    // codec was configured.
    OMX_PARAM_PORTDEFINITIONTYPE def;
    InitOMXParams(&def);
    def.nPortIndex = kPortIndexInput;
    OMX_ERRORTYPE oerr = OMX_GetParameter(
            mHandle, OMX_IndexParamPortDefinition, &def);
    if (oerr != OMX_ErrorNone) {
        OMX_INDEXTYPE index = OMX_IndexParamPortDefinition;
        CLOG_ERROR(getParameter, oerr, "%s(%#x): %s:%u", asString(index),
                index, portString(kPortIndexInput), kPortIndexInput);
        return UNKNOWN_ERROR;
    }

    if (def.format.video.eColorFormat != OMX_COLOR_FormatAndroidOpaque) {
        CLOGW("createInputSurface requires COLOR_FormatSurface "
                "(AndroidOpaque) color format instead of %s(%#x)",
                asString(def.format.video.eColorFormat), def.format.video.eColorFormat);
        return INVALID_OPERATION;
    }

    if (def.format.video.nFrameWidth == 0
            || def.format.video.nFrameHeight == 0) {
        ALOGE("Invalid video dimension %ux%u",
                def.format.video.nFrameWidth,
                def.format.video.nFrameHeight);
        return BAD_VALUE;
    }

    setBufferSource(bufferSource);
    return OK;
}

status_t OMXNodeInstance::allocateSecureBuffer(
        OMX_U32 portIndex, size_t size, IOMX::buffer_id *buffer,
        void **buffer_data, sp<NativeHandle> *native_handle) {
    if (buffer == NULL || buffer_data == NULL || native_handle == NULL) {
        ALOGE("b/25884056");
        return BAD_VALUE;
    }

    if (portIndex >= NELEM(mSecureBufferType)) {
        ALOGE("b/31385713, portIndex(%u)", portIndex);
        android_errorWriteLog(0x534e4554, "31385713");
        return BAD_VALUE;
    }

    Mutex::Autolock autoLock(mLock);

    if (!mSailed) {
        ALOGE("b/35467458");
        android_errorWriteLog(0x534e4554, "35467458");
        return BAD_VALUE;
    }
    if (mPortMode[portIndex] != IOMX::kPortModePresetSecureBuffer) {
        ALOGE("b/77486542");
        android_errorWriteLog(0x534e4554, "77486542");
        return INVALID_OPERATION;
    }
    BufferMeta *buffer_meta = new BufferMeta(portIndex);

    OMX_BUFFERHEADERTYPE *header;

    OMX_ERRORTYPE err = OMX_AllocateBuffer(
            mHandle, &header, portIndex, buffer_meta, size);

    if (err != OMX_ErrorNone) {
        CLOG_ERROR(allocateBuffer, err, BUFFER_FMT(portIndex, "%zu@", size));
        delete buffer_meta;
        buffer_meta = NULL;

        *buffer = 0;

        return StatusFromOMXError(err);
    }

    CHECK_EQ(header->pAppPrivate, buffer_meta);

    *buffer = makeBufferID(header);
    if (mSecureBufferType[portIndex] == kSecureBufferTypeNativeHandle) {
        *buffer_data = NULL;
        *native_handle = NativeHandle::create(
                (native_handle_t *)header->pBuffer, false /* ownsHandle */);
    } else {
        *buffer_data = header->pBuffer;
        *native_handle = NULL;
    }

    addActiveBuffer(portIndex, *buffer);

    sp<IOMXBufferSource> bufferSource(getBufferSource());
    if (bufferSource != NULL && portIndex == kPortIndexInput) {
        bufferSource->onInputBufferAdded(*buffer);
    }
    CLOG_BUFFER(allocateSecureBuffer, NEW_BUFFER_FMT(
            *buffer, portIndex, "%zu@%p:%p", size, *buffer_data,
            *native_handle == NULL ? NULL : (*native_handle)->handle()));

    return OK;
}

status_t OMXNodeInstance::freeBuffer(
        OMX_U32 portIndex, IOMX::buffer_id buffer) {
    Mutex::Autolock autoLock(mLock);
    CLOG_BUFFER(freeBuffer, "%s:%u %#x", portString(portIndex), portIndex, buffer);

    removeActiveBuffer(portIndex, buffer);

    OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, portIndex);
    if (header == NULL) {
        ALOGE("b/25884056");
        return BAD_VALUE;
    }
    BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate);

    OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header);
    CLOG_IF_ERROR(freeBuffer, err, "%s:%u %#x", portString(portIndex), portIndex, buffer);

    delete buffer_meta;
    buffer_meta = NULL;
    invalidateBufferID(buffer);

    return StatusFromOMXError(err);
}

status_t OMXNodeInstance::fillBuffer(
        IOMX::buffer_id buffer, const OMXBuffer &omxBuffer, int fenceFd) {
    Mutex::Autolock autoLock(mLock);

    OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, kPortIndexOutput);
    if (header == NULL) {
        ALOGE("b/25884056");
        return BAD_VALUE;
    }

    if (omxBuffer.mBufferType == OMXBuffer::kBufferTypeANWBuffer) {
        status_t err = updateGraphicBufferInMeta_l(
                kPortIndexOutput, omxBuffer.mGraphicBuffer, buffer, header);

        if (err != OK) {
            CLOG_ERROR(fillBuffer, err, FULL_BUFFER(
                    (intptr_t)header->pBuffer, header, fenceFd));
            return err;
        }
    } else if (omxBuffer.mBufferType != OMXBuffer::kBufferTypePreset) {
        return BAD_VALUE;
    }

    header->nFilledLen = 0;
    header->nOffset = 0;
    header->nFlags = 0;

    // meta now owns fenceFd
    status_t res = storeFenceInMeta_l(header, fenceFd, kPortIndexOutput);
    if (res != OK) {
        CLOG_ERROR(fillBuffer::storeFenceInMeta, res, EMPTY_BUFFER(buffer, header, fenceFd));
        return res;
    }

    {
        Mutex::Autolock _l(mDebugLock);
        mOutputBuffersWithCodec.add(header);
        CLOG_BUMPED_BUFFER(fillBuffer, WITH_STATS(EMPTY_BUFFER(buffer, header, fenceFd)));
    }

    OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header);
    if (err != OMX_ErrorNone) {
        CLOG_ERROR(fillBuffer, err, EMPTY_BUFFER(buffer, header, fenceFd));
        Mutex::Autolock _l(mDebugLock);
        mOutputBuffersWithCodec.remove(header);
    }
    return StatusFromOMXError(err);
}

status_t OMXNodeInstance::emptyBuffer(
        buffer_id buffer, const OMXBuffer &omxBuffer,
        OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
    Mutex::Autolock autoLock(mLock);

    switch (omxBuffer.mBufferType) {
    case OMXBuffer::kBufferTypePreset:
        return emptyBuffer_l(
                buffer, omxBuffer.mRangeOffset, omxBuffer.mRangeLength,
                flags, timestamp, fenceFd);

    case OMXBuffer::kBufferTypeANWBuffer:
        return emptyGraphicBuffer_l(
                buffer, omxBuffer.mGraphicBuffer, flags, timestamp, fenceFd);

    case OMXBuffer::kBufferTypeNativeHandle:
        return emptyNativeHandleBuffer_l(
                buffer, omxBuffer.mNativeHandle, flags, timestamp, fenceFd);

    default:
        break;
    }

    return BAD_VALUE;
}

status_t OMXNodeInstance::emptyBuffer_l(
        IOMX::buffer_id buffer,
        OMX_U32 rangeOffset, OMX_U32 rangeLength,
        OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {

    // no emptybuffer if using input surface
    if (getBufferSource() != NULL) {
        android_errorWriteLog(0x534e4554, "29422020");
        return INVALID_OPERATION;
    }

    OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, kPortIndexInput);
    if (header == NULL) {
        ALOGE("b/25884056");
        return BAD_VALUE;
    }
    BufferMeta *buffer_meta =
        static_cast<BufferMeta *>(header->pAppPrivate);

    // set up proper filled length if component is configured for gralloc metadata mode
    // ignore rangeOffset in this case (as client may be assuming ANW meta buffers).
    if (mMetadataType[kPortIndexInput] == kMetadataBufferTypeGrallocSource) {
        header->nFilledLen = rangeLength ? sizeof(VideoGrallocMetadata) : 0;
        header->nOffset = 0;
    } else {
        // rangeLength and rangeOffset must be a subset of the allocated data in the buffer.
        // corner case: we permit rangeOffset == end-of-buffer with rangeLength == 0.
        if (rangeOffset > header->nAllocLen
                || rangeLength > header->nAllocLen - rangeOffset) {
            CLOG_ERROR(emptyBuffer, OMX_ErrorBadParameter, FULL_BUFFER(NULL, header, fenceFd));
            if (fenceFd >= 0) {
                ::close(fenceFd);
            }
            return BAD_VALUE;
        }
        header->nFilledLen = rangeLength;
        header->nOffset = rangeOffset;

        buffer_meta->CopyToOMX(header);
    }

    return emptyBuffer_l(header, flags, timestamp, (intptr_t)buffer, fenceFd);
}

// log queued buffer activity for the next few input and/or output frames
// if logging at internal state level
void OMXNodeInstance::bumpDebugLevel_l(size_t numInputBuffers, size_t numOutputBuffers) {
    if (DEBUG == ADebug::kDebugInternalState) {
        DEBUG_BUMP = ADebug::kDebugAll;
        if (numInputBuffers > 0) {
            mDebugLevelBumpPendingBuffers[kPortIndexInput] = numInputBuffers;
        }
        if (numOutputBuffers > 0) {
            mDebugLevelBumpPendingBuffers[kPortIndexOutput] = numOutputBuffers;
        }
    }
}

void OMXNodeInstance::unbumpDebugLevel_l(size_t portIndex) {
    if (mDebugLevelBumpPendingBuffers[portIndex]) {
        --mDebugLevelBumpPendingBuffers[portIndex];
    }
    if (!mDebugLevelBumpPendingBuffers[0]
            && !mDebugLevelBumpPendingBuffers[1]) {
        DEBUG_BUMP = DEBUG;
    }
}

status_t OMXNodeInstance::storeFenceInMeta_l(
        OMX_BUFFERHEADERTYPE *header, int fenceFd, OMX_U32 portIndex) {
    // propagate fence if component supports it; wait for it otherwise
    OMX_U32 metaSize = portIndex == kPortIndexInput ? header->nFilledLen : header->nAllocLen;
    if (mMetadataType[portIndex] == kMetadataBufferTypeANWBuffer
            && metaSize >= sizeof(VideoNativeMetadata)) {
        VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)(header->pBuffer);
        if (nativeMeta.nFenceFd >= 0) {
            ALOGE("fence (%d) already exists in meta", nativeMeta.nFenceFd);
            if (fenceFd >= 0) {
                ::close(fenceFd);
            }
            return ALREADY_EXISTS;
        }
        nativeMeta.nFenceFd = fenceFd;
    } else if (fenceFd >= 0) {
        CLOG_BUFFER(storeFenceInMeta, "waiting for fence %d", fenceFd);
        sp<Fence> fence = new Fence(fenceFd);
        return fence->wait(IOMX::kFenceTimeoutMs);
    }
    return OK;
}

int OMXNodeInstance::retrieveFenceFromMeta_l(
        OMX_BUFFERHEADERTYPE *header, OMX_U32 portIndex) {
    OMX_U32 metaSize = portIndex == kPortIndexInput ? header->nAllocLen : header->nFilledLen;
    int fenceFd = -1;
    if (mMetadataType[portIndex] == kMetadataBufferTypeANWBuffer
            && header->nAllocLen >= sizeof(VideoNativeMetadata)) {
        VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)(header->pBuffer);
        if (nativeMeta.eType == kMetadataBufferTypeANWBuffer) {
            fenceFd = nativeMeta.nFenceFd;
            nativeMeta.nFenceFd = -1;
        }
        if (metaSize < sizeof(nativeMeta) && fenceFd >= 0) {
            CLOG_ERROR(foundFenceInEmptyMeta, BAD_VALUE, FULL_BUFFER(
                    NULL, header, nativeMeta.nFenceFd));
            fenceFd = -1;
        }
    }
    return fenceFd;
}

status_t OMXNodeInstance::emptyBuffer_l(
        OMX_BUFFERHEADERTYPE *header, OMX_U32 flags, OMX_TICKS timestamp,
        intptr_t debugAddr, int fenceFd) {
    header->nFlags = flags;
    header->nTimeStamp = timestamp;

    status_t res = storeFenceInMeta_l(header, fenceFd, kPortIndexInput);
    if (res != OK) {
        CLOG_ERROR(emptyBuffer::storeFenceInMeta, res, WITH_STATS(
                FULL_BUFFER(debugAddr, header, fenceFd)));
        return res;
    }

    {
        Mutex::Autolock _l(mDebugLock);
        mInputBuffersWithCodec.add(header);

        // bump internal-state debug level for 2 input frames past a buffer with CSD
        if ((flags & OMX_BUFFERFLAG_CODECCONFIG) != 0) {
            bumpDebugLevel_l(2 /* numInputBuffers */, 0 /* numOutputBuffers */);
        }

        CLOG_BUMPED_BUFFER(emptyBuffer, WITH_STATS(FULL_BUFFER(debugAddr, header, fenceFd)));
    }

    OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header);
    CLOG_IF_ERROR(emptyBuffer, err, FULL_BUFFER(debugAddr, header, fenceFd));

    {
        Mutex::Autolock _l(mDebugLock);
        if (err != OMX_ErrorNone) {
            mInputBuffersWithCodec.remove(header);
        } else if (!(flags & OMX_BUFFERFLAG_CODECCONFIG)) {
            unbumpDebugLevel_l(kPortIndexInput);
        }
    }

    return StatusFromOMXError(err);
}

// like emptyBuffer, but the data is already in header->pBuffer
status_t OMXNodeInstance::emptyGraphicBuffer_l(
        IOMX::buffer_id buffer, const sp<GraphicBuffer> &graphicBuffer,
        OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
    OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, kPortIndexInput);
    if (header == NULL) {
        ALOGE("b/25884056");
        return BAD_VALUE;
    }

    status_t err = updateGraphicBufferInMeta_l(
            kPortIndexInput, graphicBuffer, buffer, header);
    if (err != OK) {
        CLOG_ERROR(emptyGraphicBuffer, err, FULL_BUFFER(
                (intptr_t)header->pBuffer, header, fenceFd));
        return err;
    }

    int64_t codecTimeUs = getCodecTimestamp(timestamp);

    header->nOffset = 0;
    if (graphicBuffer == NULL) {
        header->nFilledLen = 0;
    } else if (mMetadataType[kPortIndexInput] == kMetadataBufferTypeGrallocSource) {
        header->nFilledLen = sizeof(VideoGrallocMetadata);
    } else {
        header->nFilledLen = sizeof(VideoNativeMetadata);
    }
    return emptyBuffer_l(header, flags, codecTimeUs, (intptr_t)header->pBuffer, fenceFd);
}

status_t OMXNodeInstance::setMaxPtsGapUs(const void *params, size_t size) {
    if (params == NULL || size != sizeof(OMX_PARAM_U32TYPE)) {
        CLOG_ERROR(setMaxPtsGapUs, BAD_VALUE, "invalid params (%p,%zu)", params, size);
        return BAD_VALUE;
    }

    // The incoming number is an int32_t contained in OMX_U32.
    // Cast to int32_t first then int64_t.
    mMaxTimestampGapUs = (int32_t)((OMX_PARAM_U32TYPE*)params)->nU32;

    return OK;
}

int64_t OMXNodeInstance::getCodecTimestamp(OMX_TICKS timestamp) {
    int64_t originalTimeUs = timestamp;

    if (mMaxTimestampGapUs > 0ll) {
        /* Cap timestamp gap between adjacent frames to specified max
         *
         * In the scenario of cast mirroring, encoding could be suspended for
         * prolonged periods. Limiting the pts gap to workaround the problem
         * where encoder's rate control logic produces huge frames after a
         * long period of suspension.
         */
        if (mPrevOriginalTimeUs >= 0ll) {
            int64_t timestampGapUs = originalTimeUs - mPrevOriginalTimeUs;
            timestamp = (timestampGapUs < mMaxTimestampGapUs ?
                timestampGapUs : mMaxTimestampGapUs) + mPrevModifiedTimeUs;
        }
        ALOGV("IN  timestamp: %lld -> %lld",
            static_cast<long long>(originalTimeUs),
            static_cast<long long>(timestamp));
    } else if (mMaxTimestampGapUs < 0ll) {
        /*
         * Apply a fixed timestamp gap between adjacent frames.
         *
         * This is used by scenarios like still image capture where timestamps
         * on frames could go forward or backward. Some encoders may silently
         * drop frames when it goes backward (or even stay unchanged).
         */
        if (mPrevOriginalTimeUs >= 0ll) {
            timestamp = mPrevModifiedTimeUs - mMaxTimestampGapUs;
        }
        ALOGV("IN  timestamp: %lld -> %lld",
            static_cast<long long>(originalTimeUs),
            static_cast<long long>(timestamp));
    }

    mPrevOriginalTimeUs = originalTimeUs;
    mPrevModifiedTimeUs = timestamp;

    if (mMaxTimestampGapUs != 0ll && !mRestorePtsFailed) {
        mOriginalTimeUs.add(timestamp, originalTimeUs);
    }

    return timestamp;
}

status_t OMXNodeInstance::emptyNativeHandleBuffer_l(
        IOMX::buffer_id buffer, const sp<NativeHandle> &nativeHandle,
        OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
    OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, kPortIndexInput);
    if (header == NULL) {
        ALOGE("b/25884056");
        return BAD_VALUE;
    }

    status_t err = updateNativeHandleInMeta_l(
            kPortIndexInput, nativeHandle, buffer, header);
    if (err != OK) {
        CLOG_ERROR(emptyNativeHandleBuffer_l, err, FULL_BUFFER(
                (intptr_t)header->pBuffer, header, fenceFd));
        return err;
    }

    header->nOffset = 0;
    header->nFilledLen = (nativeHandle == NULL) ? 0 : sizeof(VideoNativeMetadata);

    return emptyBuffer_l(header, flags, timestamp, (intptr_t)header->pBuffer, fenceFd);
}

void OMXNodeInstance::codecBufferFilled(omx_message &msg) {
    Mutex::Autolock autoLock(mLock);

    if (mMaxTimestampGapUs == 0ll || mRestorePtsFailed) {
        return;
    }

    OMX_U32 &flags = msg.u.extended_buffer_data.flags;
    OMX_TICKS &timestamp = msg.u.extended_buffer_data.timestamp;

    if (!(flags & OMX_BUFFERFLAG_CODECCONFIG)) {
        ssize_t index = mOriginalTimeUs.indexOfKey(timestamp);
        if (index >= 0) {
            ALOGV("OUT timestamp: %lld -> %lld",
                    static_cast<long long>(timestamp),
                    static_cast<long long>(mOriginalTimeUs[index]));
            timestamp = mOriginalTimeUs[index];
            mOriginalTimeUs.removeItemsAt(index);
        } else {
            // giving up the effort as encoder doesn't appear to preserve pts
            ALOGW("giving up limiting timestamp gap (pts = %lld)", timestamp);
            mRestorePtsFailed = true;
        }
    }
}

status_t OMXNodeInstance::getExtensionIndex(
        const char *parameterName, OMX_INDEXTYPE *index) {
    Mutex::Autolock autoLock(mLock);

    OMX_ERRORTYPE err = OMX_GetExtensionIndex(
            mHandle, const_cast<char *>(parameterName), index);

    return StatusFromOMXError(err);
}

status_t OMXNodeInstance::dispatchMessage(const omx_message &msg) {
    mDispatcher->post(msg, true /*realTime*/);
    return OK;
}

status_t OMXNodeInstance::setQuirks(OMX_U32 quirks) {
    if (quirks & ~kQuirksMask) {
        return BAD_VALUE;
    }

    mQuirks = quirks;

    return OK;
}

bool OMXNodeInstance::handleMessage(omx_message &msg) {
    if (msg.type == omx_message::FILL_BUFFER_DONE) {
        OMX_BUFFERHEADERTYPE *buffer =
            findBufferHeader(msg.u.extended_buffer_data.buffer, kPortIndexOutput);
        if (buffer == NULL) {
            ALOGE("b/25884056");
            return false;
        }

        {
            Mutex::Autolock _l(mDebugLock);
            mOutputBuffersWithCodec.remove(buffer);

            CLOG_BUMPED_BUFFER(
                    FBD, WITH_STATS(FULL_BUFFER(
                            msg.u.extended_buffer_data.buffer, buffer, msg.fenceFd)));

            unbumpDebugLevel_l(kPortIndexOutput);
        }

        BufferMeta *buffer_meta =
            static_cast<BufferMeta *>(buffer->pAppPrivate);

        if (buffer->nOffset + buffer->nFilledLen < buffer->nOffset
                || buffer->nOffset + buffer->nFilledLen > buffer->nAllocLen) {
            CLOG_ERROR(onFillBufferDone, OMX_ErrorBadParameter,
                    FULL_BUFFER(NULL, buffer, msg.fenceFd));
        }
        buffer_meta->CopyFromOMX(buffer);

        // fix up the buffer info (especially timestamp) if needed
        codecBufferFilled(msg);
    } else if (msg.type == omx_message::EMPTY_BUFFER_DONE) {
        OMX_BUFFERHEADERTYPE *buffer =
            findBufferHeader(msg.u.buffer_data.buffer, kPortIndexInput);
        if (buffer == NULL) {
            return false;
        }

        {
            Mutex::Autolock _l(mDebugLock);
            mInputBuffersWithCodec.remove(buffer);

            CLOG_BUMPED_BUFFER(
                    EBD, WITH_STATS(EMPTY_BUFFER(msg.u.buffer_data.buffer, buffer, msg.fenceFd)));
        }

        const sp<IOMXBufferSource> bufferSource(getBufferSource());

        if (bufferSource != NULL) {
            // This is one of the buffers used exclusively by IOMXBufferSource.
            // Don't dispatch a message back to ACodec, since it doesn't
            // know that anyone asked to have the buffer emptied and will
            // be very confused.
            bufferSource->onInputBufferEmptied(
                    msg.u.buffer_data.buffer, OMXFenceParcelable(msg.fenceFd));
            return true;
        }
    } else if (msg.type == omx_message::EVENT &&
            msg.u.event_data.event == OMX_EventDataSpaceChanged) {
        handleDataSpaceChanged(msg);
    }

    return false;
}

bool OMXNodeInstance::handleDataSpaceChanged(omx_message &msg) {
    android_dataspace dataSpace = (android_dataspace) msg.u.event_data.data1;
    android_dataspace origDataSpace = dataSpace;

    if (!ColorUtils::convertDataSpaceToV0(dataSpace)) {
        // Do not process the data space change, don't notify client either
        return true;
    }

    android_pixel_format pixelFormat = (android_pixel_format)msg.u.event_data.data3;

    ColorAspects requestedAspects = ColorUtils::unpackToColorAspects(msg.u.event_data.data2);
    ColorAspects aspects = requestedAspects; // initially requested aspects

    // request color aspects to encode
    OMX_INDEXTYPE index;
    status_t err = getExtensionIndex(
            "OMX.google.android.index.describeColorAspects", &index);
    if (err == OK) {
        // V0 dataspace
        DescribeColorAspectsParams params;
        InitOMXParams(&params);
        params.nPortIndex = kPortIndexInput;
        params.nDataSpace = origDataSpace;
        params.nPixelFormat = pixelFormat;
        params.bDataSpaceChanged = OMX_TRUE;
        params.sAspects = requestedAspects;

        err = getConfig(index, &params, sizeof(params));
        if (err == OK) {
            aspects = params.sAspects;
            ALOGD("Codec resolved it to (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)",
                    params.sAspects.mRange, asString(params.sAspects.mRange),
                    params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries),
                    params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs),
                    params.sAspects.mTransfer, asString(params.sAspects.mTransfer),
                    err, asString(err));
        } else {
            params.sAspects = aspects;
            err = OK;
        }
        params.bDataSpaceChanged = OMX_FALSE;
        for (int triesLeft = 2; --triesLeft >= 0; ) {
            status_t err = setConfig(index, &params, sizeof(params));
            if (err == OK) {
                err = getConfig(index, &params, sizeof(params));
            }
            if (err != OK || !ColorUtils::checkIfAspectsChangedAndUnspecifyThem(
                    params.sAspects, aspects)) {
                // if we can't set or get color aspects, still communicate dataspace to client
                break;
            }

            ALOGW_IF(triesLeft == 0, "Codec repeatedly changed requested ColorAspects.");
        }
    }

    ALOGV("Set color aspects to (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)",
            aspects.mRange, asString(aspects.mRange),
            aspects.mPrimaries, asString(aspects.mPrimaries),
            aspects.mMatrixCoeffs, asString(aspects.mMatrixCoeffs),
            aspects.mTransfer, asString(aspects.mTransfer),
            err, asString(err));

    // signal client that the dataspace has changed; this will update the output format
    // TODO: we should tie this to an output buffer somehow, and signal the change
    // just before the output buffer is returned to the client, but there are many
    // ways this could fail (e.g. flushing), and we are not yet supporting this scenario.

    msg.u.event_data.data1 = (OMX_U32) dataSpace;
    msg.u.event_data.data2 = (OMX_U32) ColorUtils::packToU32(aspects);

    return false;
}

void OMXNodeInstance::onMessages(std::list<omx_message> &messages) {
    for (std::list<omx_message>::iterator it = messages.begin(); it != messages.end(); ) {
        if (handleMessage(*it)) {
            messages.erase(it++);
        } else {
            ++it;
        }
    }

    if (!messages.empty()) {
        mObserver->onMessages(messages);
    }
}

void OMXNodeInstance::onObserverDied() {
    ALOGE("!!! Observer died. Quickly, do something, ... anything...");

    // Try to force shutdown of the node and hope for the best.
    freeNode();
}

// OMXNodeInstance::OnEvent calls OMX::OnEvent, which then calls here.
// Don't try to acquire mLock here -- in rare circumstances this will hang.
void OMXNodeInstance::onEvent(
        OMX_EVENTTYPE event, OMX_U32 arg1, OMX_U32 arg2) {
    const char *arg1String = "??";
    const char *arg2String = "??";
    ADebug::Level level = ADebug::kDebugInternalState;

    switch (event) {
        case OMX_EventCmdComplete:
            arg1String = asString((OMX_COMMANDTYPE)arg1);
            switch (arg1) {
                case OMX_CommandStateSet:
                    arg2String = asString((OMX_STATETYPE)arg2);
                    level = ADebug::kDebugState;
                    break;
                case OMX_CommandFlush:
                case OMX_CommandPortEnable:
                {
                    // bump internal-state debug level for 2 input and output frames
                    Mutex::Autolock _l(mDebugLock);
                    bumpDebugLevel_l(2 /* numInputBuffers */, 2 /* numOutputBuffers */);
                    FALLTHROUGH_INTENDED;
                }
                default:
                    arg2String = portString(arg2);
            }
            break;
        case OMX_EventError:
            arg1String = asString((OMX_ERRORTYPE)arg1);
            level = ADebug::kDebugLifeCycle;
            break;
        case OMX_EventPortSettingsChanged:
            arg2String = asString((OMX_INDEXEXTTYPE)arg2);
            FALLTHROUGH_INTENDED;
        default:
            arg1String = portString(arg1);
    }

    CLOGI_(level, onEvent, "%s(%x), %s(%x), %s(%x)",
            asString(event), event, arg1String, arg1, arg2String, arg2);
    const sp<IOMXBufferSource> bufferSource(getBufferSource());

    if (bufferSource != NULL
            && event == OMX_EventCmdComplete
            && arg1 == OMX_CommandStateSet
            && arg2 == OMX_StateExecuting) {
        bufferSource->onOmxExecuting();
    }

    // allow configuration if we return to the loaded state
    if (event == OMX_EventCmdComplete
            && arg1 == OMX_CommandStateSet
            && arg2 == OMX_StateLoaded) {
        mSailed = false;
    }
}

// static
OMX_ERRORTYPE OMXNodeInstance::OnEvent(
        OMX_IN OMX_HANDLETYPE /* hComponent */,
        OMX_IN OMX_PTR pAppData,
        OMX_IN OMX_EVENTTYPE eEvent,
        OMX_IN OMX_U32 nData1,
        OMX_IN OMX_U32 nData2,
        OMX_IN OMX_PTR pEventData) {
    if (pAppData == NULL) {
        ALOGE("b/25884056");
        return OMX_ErrorBadParameter;
    }
    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
    if (instance->mDying) {
        return OMX_ErrorNone;
    }

    instance->onEvent(eEvent, nData1, nData2);

    // output rendered events are not processed as regular events until they hit the observer
    if (eEvent == OMX_EventOutputRendered) {
        if (pEventData == NULL) {
            return OMX_ErrorBadParameter;
        }

        // process data from array
        OMX_VIDEO_RENDEREVENTTYPE *renderData = (OMX_VIDEO_RENDEREVENTTYPE *)pEventData;
        for (size_t i = 0; i < nData1; ++i) {
            omx_message msg;
            msg.type = omx_message::FRAME_RENDERED;
            msg.fenceFd = -1;
            msg.u.render_data.timestamp = renderData[i].nMediaTimeUs;
            msg.u.render_data.nanoTime = renderData[i].nSystemTimeNs;
            bool realTime = msg.u.render_data.timestamp == INT64_MAX;
            instance->mDispatcher->post(msg, realTime);
        }
        return OMX_ErrorNone;
    }

    omx_message msg;
    msg.type = omx_message::EVENT;
    msg.fenceFd = -1;
    msg.u.event_data.event = eEvent;
    msg.u.event_data.data1 = nData1;
    msg.u.event_data.data2 = nData2;

    instance->mDispatcher->post(msg, true /* realTime */);

    return OMX_ErrorNone;
}

// static
OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone(
        OMX_IN OMX_HANDLETYPE /* hComponent */,
        OMX_IN OMX_PTR pAppData,
        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
    if (pAppData == NULL) {
        ALOGE("b/25884056");
        return OMX_ErrorBadParameter;
    }
    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
    if (instance->mDying) {
        return OMX_ErrorNone;
    }
    int fenceFd = instance->retrieveFenceFromMeta_l(pBuffer, kPortIndexOutput);

    omx_message msg;
    msg.type = omx_message::EMPTY_BUFFER_DONE;
    msg.fenceFd = fenceFd;
    msg.u.buffer_data.buffer = instance->findBufferID(pBuffer);
    instance->mDispatcher->post(msg);

    return OMX_ErrorNone;
}

// static
OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone(
        OMX_IN OMX_HANDLETYPE /* hComponent */,
        OMX_IN OMX_PTR pAppData,
        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
    if (pAppData == NULL) {
        ALOGE("b/25884056");
        return OMX_ErrorBadParameter;
    }
    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
    if (instance->mDying) {
        return OMX_ErrorNone;
    }
    int fenceFd = instance->retrieveFenceFromMeta_l(pBuffer, kPortIndexOutput);

    omx_message msg;
    msg.type = omx_message::FILL_BUFFER_DONE;
    msg.fenceFd = fenceFd;
    msg.u.extended_buffer_data.buffer = instance->findBufferID(pBuffer);
    msg.u.extended_buffer_data.range_offset = pBuffer->nOffset;
    msg.u.extended_buffer_data.range_length = pBuffer->nFilledLen;
    msg.u.extended_buffer_data.flags = pBuffer->nFlags;
    msg.u.extended_buffer_data.timestamp = pBuffer->nTimeStamp;
    instance->mDispatcher->post(msg);

    return OMX_ErrorNone;
}

void OMXNodeInstance::addActiveBuffer(OMX_U32 portIndex, IOMX::buffer_id id) {
    ActiveBuffer active;
    active.mPortIndex = portIndex;
    active.mID = id;
    mActiveBuffers.push(active);

    if (portIndex < NELEM(mNumPortBuffers)) {
        ++mNumPortBuffers[portIndex];
    }
}

void OMXNodeInstance::removeActiveBuffer(
        OMX_U32 portIndex, IOMX::buffer_id id) {
    for (size_t i = 0; i < mActiveBuffers.size(); ++i) {
        if (mActiveBuffers[i].mPortIndex == portIndex
                && mActiveBuffers[i].mID == id) {
            mActiveBuffers.removeItemsAt(i);

            if (portIndex < NELEM(mNumPortBuffers)) {
                --mNumPortBuffers[portIndex];
            }
            return;
        }
    }

     CLOGW("Attempt to remove an active buffer [%#x] we know nothing about...", id);
}

void OMXNodeInstance::freeActiveBuffers() {
    // Make sure to count down here, as freeBuffer will in turn remove
    // the active buffer from the vector...
    for (size_t i = mActiveBuffers.size(); i > 0;) {
        i--;
        freeBuffer(mActiveBuffers[i].mPortIndex, mActiveBuffers[i].mID);
    }
}

IOMX::buffer_id OMXNodeInstance::makeBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) {
    if (bufferHeader == NULL) {
        return 0;
    }
    Mutex::Autolock autoLock(mBufferIDLock);
    IOMX::buffer_id buffer;
    do { // handle the very unlikely case of ID overflow
        if (++mBufferIDCount == 0) {
            ++mBufferIDCount;
        }
        buffer = (IOMX::buffer_id)mBufferIDCount;
    } while (mBufferIDToBufferHeader.indexOfKey(buffer) >= 0);
    mBufferIDToBufferHeader.add(buffer, bufferHeader);
    mBufferHeaderToBufferID.add(bufferHeader, buffer);
    return buffer;
}

OMX_BUFFERHEADERTYPE *OMXNodeInstance::findBufferHeader(
        IOMX::buffer_id buffer, OMX_U32 portIndex) {
    if (buffer == 0) {
        return NULL;
    }
    Mutex::Autolock autoLock(mBufferIDLock);
    ssize_t index = mBufferIDToBufferHeader.indexOfKey(buffer);
    if (index < 0) {
        CLOGW("findBufferHeader: buffer %u not found", buffer);
        return NULL;
    }
    OMX_BUFFERHEADERTYPE *header = mBufferIDToBufferHeader.valueAt(index);
    BufferMeta *buffer_meta =
        static_cast<BufferMeta *>(header->pAppPrivate);
    if (buffer_meta->getPortIndex() != portIndex) {
        CLOGW("findBufferHeader: buffer %u found but with incorrect port index.", buffer);
        android_errorWriteLog(0x534e4554, "28816827");
        return NULL;
    }
    return header;
}

IOMX::buffer_id OMXNodeInstance::findBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) {
    if (bufferHeader == NULL) {
        return 0;
    }
    Mutex::Autolock autoLock(mBufferIDLock);
    ssize_t index = mBufferHeaderToBufferID.indexOfKey(bufferHeader);
    if (index < 0) {
        CLOGW("findBufferID: bufferHeader %p not found", bufferHeader);
        return 0;
    }
    return mBufferHeaderToBufferID.valueAt(index);
}

void OMXNodeInstance::invalidateBufferID(IOMX::buffer_id buffer) {
    if (buffer == 0) {
        return;
    }
    Mutex::Autolock autoLock(mBufferIDLock);
    ssize_t index = mBufferIDToBufferHeader.indexOfKey(buffer);
    if (index < 0) {
        CLOGW("invalidateBufferID: buffer %u not found", buffer);
        return;
    }
    mBufferHeaderToBufferID.removeItem(mBufferIDToBufferHeader.valueAt(index));
    mBufferIDToBufferHeader.removeItemsAt(index);
}

}  // namespace android
