/*
* Copyright (c) 2009-2011 Intel Corporation.  All rights reserved.
*
* 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.
*/

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

#include "WrsOMXPlugin.h"

#include <dlfcn.h>

#include <HardwareAPI.h>
#include <media/stagefright/foundation/ADebug.h>

namespace android {

OMXPluginBase *createOMXPlugin() {
    return new WrsOMXPlugin;
}

WrsOMXPlugin::WrsOMXPlugin()
{
#ifdef TARGET_HAS_ISV
   AddCore("libisv_omx_core.so");
#else
   AddCore("libwrs_omxil_core_pvwrapped.so");
#if defined(USE_MEDIASDK)
   AddCore("libmfx_omx_core.so");
#endif
#endif
}

OMX_ERRORTYPE WrsOMXPlugin::AddCore(const char* coreName)
{
   void* libHandle = dlopen(coreName, RTLD_NOW);

   if (libHandle != NULL) {
        WrsOMXCore* core = (WrsOMXCore*)calloc(1,sizeof(WrsOMXCore));

        if (!core) {
            dlclose(libHandle);
            return OMX_ErrorUndefined;
        }
        // set plugin lib handle and methods
        core->mLibHandle = libHandle;
        core->mInit = (WrsOMXCore::InitFunc)dlsym(libHandle, "OMX_Init");
        core->mDeinit = (WrsOMXCore::DeinitFunc)dlsym(libHandle, "OMX_Deinit");

        core->mComponentNameEnum =
            (WrsOMXCore::ComponentNameEnumFunc)dlsym(libHandle, "OMX_ComponentNameEnum");

        core->mGetHandle = (WrsOMXCore::GetHandleFunc)dlsym(libHandle, "OMX_GetHandle");
        core->mFreeHandle = (WrsOMXCore::FreeHandleFunc)dlsym(libHandle, "OMX_FreeHandle");

        core->mGetRolesOfComponentHandle =
            (WrsOMXCore::GetRolesOfComponentFunc)dlsym(
                    libHandle, "OMX_GetRolesOfComponent");
        if (core->mInit != NULL) {
            (*(core->mInit))();
        }
        if (core->mComponentNameEnum != NULL) {
            // calculating number of components registered inside given OMX core
            char tmpComponentName[OMX_MAX_STRINGNAME_SIZE] = { 0 };
            OMX_U32 tmpIndex = 0;
            while (OMX_ErrorNone == ((*(core->mComponentNameEnum))(tmpComponentName, OMX_MAX_STRINGNAME_SIZE, tmpIndex))) {
                tmpIndex++;
            ALOGI("OMX IL core %s: declares component %s", coreName, tmpComponentName);
            }
            core->mNumComponents = tmpIndex;
            ALOGI("OMX IL core %s: contains %u components", coreName, core->mNumComponents);
        }
        // add plugin to the vector
        mCores.push_back(core);
    }
    else {
        ALOGW("OMX IL core %s not found", coreName);
        return OMX_ErrorUndefined; // Do we need to return error message
    }
    return OMX_ErrorNone;
}

WrsOMXPlugin::~WrsOMXPlugin() {
    for (OMX_U32 i = 0; i < mCores.size(); i++) {
       if (mCores[i] != NULL && mCores[i]->mLibHandle != NULL) {
          (*(mCores[i]->mDeinit))();

          dlclose(mCores[i]->mLibHandle);
          free(mCores[i]);
       }
    }
}

OMX_ERRORTYPE WrsOMXPlugin::makeComponentInstance(
        const char *name,
        const OMX_CALLBACKTYPE *callbacks,
        OMX_PTR appData,
        OMX_COMPONENTTYPE **component) {
    for (OMX_U32 i = 0; i < mCores.size(); i++) {
        if (mCores[i] != NULL) {
            if (mCores[i]->mLibHandle == NULL) {
                continue;
            }

            OMX_ERRORTYPE omx_res = (*(mCores[i]->mGetHandle))(
                reinterpret_cast<OMX_HANDLETYPE *>(component),
                const_cast<char *>(name),
                appData, const_cast<OMX_CALLBACKTYPE *>(callbacks));
            if(omx_res == OMX_ErrorNone) {
                Mutex::Autolock autoLock(mMutex);
                WrsOMXComponent comp;

                comp.mComponent = *component;
                comp.mCore = mCores[i];

                mComponents.push_back(comp);
                return OMX_ErrorNone;
            } else if(omx_res == OMX_ErrorInsufficientResources) {
                return OMX_ErrorInsufficientResources;
            }
        }
    }
    return OMX_ErrorInvalidComponentName;
}

OMX_ERRORTYPE WrsOMXPlugin::destroyComponentInstance(
        OMX_COMPONENTTYPE *component) {
    Mutex::Autolock autoLock(mMutex);
    for (OMX_U32 i = 0; i < mComponents.size(); i++) {
        if (mComponents[i].mComponent == component) {
            if (mComponents[i].mCore == NULL || mComponents[i].mCore->mLibHandle == NULL) {
                return OMX_ErrorUndefined;
            }
            OMX_ERRORTYPE omx_res = (*(mComponents[i].mCore->mFreeHandle))(reinterpret_cast<OMX_HANDLETYPE *>(component));
            mComponents.erase(mComponents.begin() + i);
            return omx_res;
        }
    }
    return OMX_ErrorInvalidComponent;
}

OMX_ERRORTYPE WrsOMXPlugin::enumerateComponents(
        OMX_STRING name,
        size_t size,
        OMX_U32 index) {
    // returning components
    OMX_U32 relativeIndex = index;
    for (OMX_U32 i = 0; i < mCores.size(); i++) {
        if (mCores[i]->mLibHandle == NULL) {
           continue;
        }
        if (relativeIndex < mCores[i]->mNumComponents) return ((*(mCores[i]->mComponentNameEnum))(name, size, relativeIndex));
        else relativeIndex -= mCores[i]->mNumComponents;
    }
    return OMX_ErrorNoMore;
}

OMX_ERRORTYPE WrsOMXPlugin::getRolesOfComponent(
        const char *name,
        Vector<String8> *roles) {
    roles->clear();
    for (OMX_U32 j = 0; j < mCores.size(); j++) {
        if (mCores[j]->mLibHandle == NULL) {
           continue;
        }

        OMX_U32 numRoles;
        OMX_ERRORTYPE err = (*(mCores[j]->mGetRolesOfComponentHandle))(
                const_cast<OMX_STRING>(name), &numRoles, NULL);

        if (err != OMX_ErrorNone) {
            continue;
        }

        if (numRoles > 0) {
            OMX_U8 **array = new OMX_U8 *[numRoles];
            for (OMX_U32 i = 0; i < numRoles; ++i) {
                array[i] = new OMX_U8[OMX_MAX_STRINGNAME_SIZE];
            }

            OMX_U32 numRoles2 = numRoles;
            err = (*(mCores[j]->mGetRolesOfComponentHandle))(
                    const_cast<OMX_STRING>(name), &numRoles2, array);

            CHECK_EQ(err, OMX_ErrorNone);
            CHECK_EQ(numRoles, numRoles2);

            for (OMX_U32 i = 0; i < numRoles; ++i) {
                String8 s((const char *)array[i]);
                roles->push(s);

                delete[] array[i];
                array[i] = NULL;
            }

            delete[] array;
            array = NULL;
        }
        return OMX_ErrorNone;
    }
    return OMX_ErrorInvalidComponent;
}

}  // namespace android
