/**
 * Copyright (C) 2019 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 "omxUtils.h"

sp<IMediaPlayerService> mediaPlayerService = NULL;
sp<IOMXNode> mOMXNode = 0;
sp<IOMX> mOMX;
omx_message msg;
Mutex mLock;
Condition mMessageAddedCondition;
int32_t mLastMsgGeneration;
int32_t mCurGeneration;
List<omx_message> mMessageQueue;
bool mUseTreble;
int numCallbackEmptyBufferDone;

struct CodecObserver : public BnOMXObserver {
 public:
    CodecObserver(int32_t gen)
            : mGeneration(gen) {
    }

    void onMessages(const std::list<omx_message> &messages) override;
    int32_t mGeneration;

 protected:
    virtual ~CodecObserver() {
    }
};
struct DeathNotifier : public IBinder::DeathRecipient,
        public ::android::hardware::hidl_death_recipient {
    explicit DeathNotifier() {
    }

    virtual void binderDied(const wp<IBinder> &) {
        ALOGE("Binder Died");
        exit (EXIT_FAILURE);
    }

    virtual void serviceDied(
            uint64_t /* cookie */,
            const wp<::android::hidl::base::V1_0::IBase>& /* who */) {
        ALOGE("Service Died");
        exit (EXIT_FAILURE);
    }
};
sp<DeathNotifier> mDeathNotifier;
void handleMessages(int32_t gen, const std::list<omx_message> &messages) {
    Mutex::Autolock autoLock(mLock);
    for (std::list<omx_message>::const_iterator it = messages.cbegin();
            it != messages.cend();) {
        mMessageQueue.push_back(*it);
        const omx_message &msg = *it++;
        if (msg.type == omx_message::EMPTY_BUFFER_DONE) {
            numCallbackEmptyBufferDone++;
        }
        mLastMsgGeneration = gen;
    }
    mMessageAddedCondition.signal();
}
void CodecObserver::onMessages(const std::list<omx_message> &messages) {
    handleMessages(mGeneration, messages);
}

status_t dequeueMessageForNode(omx_message *msg, int64_t timeoutUs) {
    int64_t finishBy = ALooper::GetNowUs() + timeoutUs;
    status_t err = OK;

    while (err != TIMED_OUT) {
        Mutex::Autolock autoLock(mLock);
        if (mLastMsgGeneration < mCurGeneration) {
            mMessageQueue.clear();
        }
        // Messages are queued in batches, if the last batch queued is
        // from a node that already expired, discard those messages.
        List<omx_message>::iterator it = mMessageQueue.begin();
        while (it != mMessageQueue.end()) {
            *msg = *it;
            mMessageQueue.erase(it);
            return OK;
        }
        if (timeoutUs < 0) {
            err = mMessageAddedCondition.wait(mLock);
        } else {
            err = mMessageAddedCondition.waitRelative(
                    mLock, (finishBy - ALooper::GetNowUs()) * 1000);
        }
    }
    return err;
}
void omxUtilsCheckCmdExecution(char *name) {
    status_t err = dequeueMessageForNode(&msg, DEFAULT_TIMEOUT);
    if (err == TIMED_OUT) {
        ALOGE("[omxUtils] OMX command timed out for %s, exiting the app", name);
        exit (EXIT_FAILURE);
    }
}
void omxExitOnError(status_t ret) {
    if (ret != OK) {
        exit (EXIT_FAILURE);
    }
}
status_t omxUtilsInit(char *codecName) {
    android::ProcessState::self()->startThreadPool();
    if (property_get_bool("persist.media.treble_omx", true)) {
        using namespace ::android::hardware::media::omx::V1_0;
        sp<IOmx> tOmx = IOmx::getService();
        if (tOmx == nullptr) {
            return NO_INIT;
        }
        mOMX = new utils::LWOmx(tOmx);
        mUseTreble = true;
    } else {
        sp<IServiceManager> sm = defaultServiceManager();
        sp<IBinder> binder = sm->getService(String16("media.player"));
        sp<IMediaPlayerService> mediaPlayerService = interface_cast
                <IMediaPlayerService> (binder);
        if (mediaPlayerService == NULL) {
            return NO_INIT;
        }
        mOMX = mediaPlayerService->getOMX();
        if (mOMX == NULL) {
            return NO_INIT;
        }
        mUseTreble = false;
    }
    sp<CodecObserver> observer = new CodecObserver(++mCurGeneration);
    status_t ret = mOMX->allocateNode(codecName, observer, &mOMXNode);
    if (ret == OK) {
        mDeathNotifier = new DeathNotifier();
        if (mUseTreble) {
            auto tOmxNode = mOMXNode->getHalInterface();
            if (tOmxNode != NULL) {
                tOmxNode->linkToDeath(mDeathNotifier, 0);
            } else {
                ALOGE("No HAL Interface");
                exit (EXIT_FAILURE);
            }
        } else {
            IInterface::asBinder(mOMXNode)->linkToDeath(mDeathNotifier);
        }
    }
    numCallbackEmptyBufferDone = 0;
    return ret;
}
status_t omxUtilsGetParameter(int portIndex,
                              OMX_PARAM_PORTDEFINITIONTYPE *params) {
    InitOMXParams(params);
    params->nPortIndex = portIndex;
    return mOMXNode->getParameter(OMX_IndexParamPortDefinition, params,
                                  sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
}
status_t omxUtilsSetParameter(int portIndex,
                              OMX_PARAM_PORTDEFINITIONTYPE *params) {
    InitOMXParams(params);
    params->nPortIndex = portIndex;
    return mOMXNode->setParameter(OMX_IndexParamPortDefinition, params,
                                  sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
}
status_t omxUtilsSetPortMode(OMX_U32 portIndex, IOMX::PortMode mode) {
    return mOMXNode->setPortMode(portIndex, mode);
}
status_t omxUtilsUseBuffer(OMX_U32 portIndex, const OMXBuffer &omxBuf,
                           android::BnOMX::buffer_id *buffer) {
    return mOMXNode->useBuffer(portIndex, omxBuf, buffer);
}
status_t omxUtilsSendCommand(OMX_COMMANDTYPE cmd, OMX_S32 param) {
    int ret = mOMXNode->sendCommand(cmd, param);
    omxUtilsCheckCmdExecution((char *) __FUNCTION__);
    return ret;
}
status_t omxUtilsEmptyBuffer(android::BnOMX::buffer_id buffer,
                             const OMXBuffer &omxBuf, OMX_U32 flags,
                             OMX_TICKS timestamp, int fenceFd) {
    return mOMXNode->emptyBuffer(buffer, omxBuf, flags, timestamp, fenceFd);
}
status_t omxUtilsFillBuffer(android::BnOMX::buffer_id buffer,
                            const OMXBuffer &omxBuf, int fenceFd) {
    return mOMXNode->fillBuffer(buffer, omxBuf, fenceFd);
}
status_t omxUtilsFreeBuffer(OMX_U32 portIndex,
                            android::BnOMX::buffer_id buffer) {
    return mOMXNode->freeBuffer(portIndex, buffer);
}
status_t omxUtilsFreeNode() {
    return mOMXNode->freeNode();
}
