blob: 20662ed8c3fc075649c57589f6a507f4af25909f [file] [log] [blame]
/* ------------------------------------------------------------------
* Copyright (C) 1998-2009 PacketVideo
*
* 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 "pv_omxdefs.h"
#include "OMX_Component.h"
#include "OMX_Core.h"
#include "omx_interface.h"
#include "pvlogger.h"
#include "oscl_base.h"
#include "oscl_file_find.h"
#include "oscl_library_list.h"
#include "oscl_shared_library.h"
#include "oscl_configfile_list.h"
#include "osclconfig_lib.h"
#include "oscl_string.h"
#include "oscl_mem.h"
#include "oscl_stdstring.h"
#include "pv_omx_config_parser.h"
#define MAX_PATHNAME_LENGTH 512
#ifndef USE_CML2_CONFIG
#define MAX_NUMBER_OF_OMX_CORES 10
#define MAX_NUMBER_OF_OMX_COMPONENTS 50
#endif /* USE_CML2_CONFIG */
typedef class OMXMasterCoreGlobalData
{
public:
OMXMasterCoreGlobalData()
: iNumMasterOMXInstances(1),
iInterface(NULL),
iOMXLibrary(NULL),
iMasterRegistry(NULL),
iOMXCompHandles(NULL),
iTotalNumOMXComponents(0),
iNumOMXCores(0)
{
};
//Counter of number of instances - so that init and deinit is done only once
OMX_U32 iNumMasterOMXInstances;
// Array of interfaces
void *iInterface;
// ptr to array of ptrs to libraries
void *iOMXLibrary;
// ptr to registry of all omx components from various cores
void *iMasterRegistry;
// ptr to array of component handles (when a component is instantiated - needed to be able to free the component)
void *iOMXCompHandles;
// total number of all componenents from various cores
OMX_U32 iTotalNumOMXComponents;
// number of omx cores from different vendors
OMX_U32 iNumOMXCores;
} OMXMasterCoreGlobalData;
typedef struct PVOMXMasterRegistryStruct
{
OMX_U8 CompName[PV_OMX_MAX_COMPONENT_NAME_LENGTH];
OMX_U8 CompRole[PV_OMX_MAX_COMPONENT_NAME_LENGTH];
OMX_BOOL bHWAccelerated;
OMX_U32 OMXCoreIndex;
OMX_U32 CompIndex;
} PVOMXMasterRegistryStruct;
typedef struct PVOMXCompHandles
{
OMX_HANDLETYPE handle;
OMX_U32 OMXCoreIndex;
} PVOMXCompHandles;
// helper function to obtain the registry index for a given handle
// NOTE: 2 or more instances of the player/author are using this same OmxCompHandles array
// However,the component handles recorded into the array or deleted from it by one instance/thread don't
// affect other handles in other instances. In other words, for most purposes - it is safe to search through the array without
// actually locking it - even if another
// instance of the player/author modifies this array (by adding or deleting its own component handles) in the meanwhile.
static OMX_ERRORTYPE GetRegIndexForHandle(OMX_HANDLETYPE hComponent, OMX_U32 &index, OMXMasterCoreGlobalData *data)
{
// we need to first find the handle among instantiated components
// then we retrieve the core based on component handle
// locking and unlocking of global data takes place outside of this method if necessary
PVOMXCompHandles *pOMXCompHandles = (PVOMXCompHandles*)(data->iOMXCompHandles);
if (pOMXCompHandles == NULL)
{
return OMX_ErrorComponentNotFound;
}
for (index = 0; index < MAX_NUMBER_OF_OMX_COMPONENTS; index++)
{
// go through the list of supported components and find the component handle
if (pOMXCompHandles[index].handle == hComponent)
{
// found a matching handle
break;
}
}
if (index == MAX_NUMBER_OF_OMX_COMPONENTS)
{
// could not find a component with the given name
return OMX_ErrorComponentNotFound;
}
return OMX_ErrorNone;
}
// ALL the standard OpenMAX IL core functions are implemented below
static OMX_ERRORTYPE _OMX_MasterInit(OMXMasterCoreGlobalData *data)
{
OMX_ERRORTYPE Status = OMX_ErrorNone;
OMX_U32 jj;
OMX_U32 index;
OMX_U32 master_index = 0;
OMX_U32 component_index = 0;
/*
** Step 1. Populate all the config files present in the specified path.
** Step 2. Populate all the libraries from the .cfg files that claim to support the OMX_INTERFACE_ID.
** Step 3. For these libraries, validate whether they really support the ID by doing a QueryInterface().
*/
// Step 1
OsclConfigFileList aCfgList;
OSCL_HeapString<OsclMemAllocator> configFilePath = PV_DYNAMIC_LOADING_CONFIG_FILE_PATH;
aCfgList.Populate(configFilePath, OsclConfigFileList::ESortByName);
// array of ptrs to various cores, one for every valid configuration
OMXInterface** pInterface = (OMXInterface**)OSCL_MALLOC(aCfgList.Size() * sizeof(OMXInterface *));
if (pInterface == NULL)
{
return OMX_ErrorInsufficientResources;
}
// set the global ptr to this array
data->iInterface = (void*)pInterface;
// array of ptrs to the omx shared libraries, one for every valid configuration
OsclSharedLibrary** pLibrary = (OsclSharedLibrary**)OSCL_MALLOC(aCfgList.Size() * sizeof(OsclSharedLibrary *));
if (pLibrary == NULL)
{
return OMX_ErrorInsufficientResources;
}
// set the global ptr to this array
//
data->iOMXLibrary = (void*)pLibrary;
for (uint ii = 0; ii < aCfgList.Size(); ii++)
{
// Step 2
OsclLibraryList libList;
libList.Populate(OMX_INTERFACE_ID, aCfgList.GetConfigfileAt(ii));
for (uint jj = 0; (jj < libList.Size()) && ((data->iNumOMXCores) < aCfgList.Size()); jj++)
{
OsclSharedLibrary* lib = OSCL_NEW(OsclSharedLibrary, ());
if (lib->LoadLib(libList.GetLibraryPathAt(jj)) == OsclLibSuccess)
{
OsclAny* interfacePtr = NULL;
// Step 3
OsclLibStatus result = lib->QueryInterface(OMX_INTERFACE_ID, (OsclAny*&)interfacePtr);
if (result == OsclLibSuccess && interfacePtr != NULL)
{
pLibrary[(data->iNumOMXCores)] = lib;
OMXInterface* coreIntPtr = OSCL_DYNAMIC_CAST(OMXInterface*, interfacePtr);
pInterface[(data->iNumOMXCores)] = coreIntPtr;
(data->iNumOMXCores)++;
continue;
}
}
lib->Close();
OSCL_DELETE(lib);
}
}
// allocate space for the OMX component registry
PVOMXMasterRegistryStruct* pOMXMasterRegistry = (PVOMXMasterRegistryStruct*)OSCL_MALLOC(MAX_NUMBER_OF_OMX_COMPONENTS * sizeof(PVOMXMasterRegistryStruct));
if (pOMXMasterRegistry == NULL)
{
return OMX_ErrorInsufficientResources;
}
data->iMasterRegistry = (void*)pOMXMasterRegistry;
PVOMXCompHandles* pOMXCompHandles = (PVOMXCompHandles*)OSCL_MALLOC(MAX_NUMBER_OF_OMX_COMPONENTS * sizeof(PVOMXCompHandles));
if (pOMXCompHandles == NULL)
{
return OMX_ErrorInsufficientResources;
}
data->iOMXCompHandles = (void*)pOMXCompHandles;
// init the array
memset(pOMXCompHandles, 0, MAX_NUMBER_OF_OMX_COMPONENTS*sizeof(PVOMXCompHandles));
// loop over all cores
master_index = 0;
OMX_STRING ComponentName = (OMX_STRING)OSCL_MALLOC(PV_OMX_MAX_COMPONENT_NAME_LENGTH * sizeof(OMX_U8));
for (jj = 0; jj < data->iNumOMXCores; jj++)
{
// first call OMX_Init
Status = (*(pInterface[jj]->GetpOMX_Init()))();
if (Status == OMX_ErrorNone)
{
// enumerate components to get their number etc.
OMX_ERRORTYPE stat = OMX_ErrorNone;
index = 0;
while (stat != OMX_ErrorNoMore)
{
// clear, then get next component name
memset(ComponentName, 0, PV_OMX_MAX_COMPONENT_NAME_LENGTH*sizeof(OMX_U8));
stat = (*(pInterface[jj]->GetpOMX_ComponentNameEnum()))(
ComponentName,
PV_OMX_MAX_COMPONENT_NAME_LENGTH,
index);
if (stat == OMX_ErrorNoMore)
break;
// check number roles of the component
OMX_U32 numRoles;
numRoles = 0;
stat = (*(pInterface[jj]->GetpOMX_GetRolesOfComponent()))(
ComponentName,
&numRoles,
NULL);
if ((numRoles > 0) && (stat == OMX_ErrorNone))
{
// allocate space for roles of the component
OMX_U32 role;
OMX_U8 **ComponentRoles = (OMX_U8**)OSCL_MALLOC(numRoles * sizeof(OMX_U8 *));
for (role = 0; role < numRoles; role++)
ComponentRoles[role] = (OMX_U8*)OSCL_MALLOC(PV_OMX_MAX_COMPONENT_NAME_LENGTH * sizeof(OMX_U8));
// get the array of strings with component roles
stat = (*(pInterface[jj]->GetpOMX_GetRolesOfComponent()))(
ComponentName,
&numRoles,
ComponentRoles);
//register all components separately in master registry
if (stat == OMX_ErrorNone)
{
for (role = 0; (role < numRoles) && (master_index < MAX_NUMBER_OF_OMX_COMPONENTS); role++)
{
strncpy((OMX_STRING)pOMXMasterRegistry[master_index].CompName, ComponentName, PV_OMX_MAX_COMPONENT_NAME_LENGTH);
strncpy((OMX_STRING)pOMXMasterRegistry[master_index].CompRole, (OMX_STRING)ComponentRoles[role], PV_OMX_MAX_COMPONENT_NAME_LENGTH);
pOMXMasterRegistry[master_index].OMXCoreIndex = jj;
pOMXMasterRegistry[master_index].CompIndex = component_index;
if (strstr(ComponentName, "OMX.PV.")) {
pOMXMasterRegistry[master_index].bHWAccelerated = OMX_FALSE;
} else {
pOMXMasterRegistry[master_index].bHWAccelerated = OMX_TRUE;
}
master_index++;
}
}
// dealloc space for component roles
for (role = 0; role < numRoles; role++)
OSCL_FREE(ComponentRoles[role]);
OSCL_FREE(ComponentRoles);
} // done with roles of component represented by index
index++; // get next component from the jj-th core
component_index++; // increase the global component index
} // done with all components from jj-th core
} // end of if(Status==OMX_ErrorNone)
}//end of for loop
// at this point, all cores were init, and all components registered
OSCL_FREE(ComponentName);
data->iTotalNumOMXComponents = master_index;
return OMX_ErrorNone;
}
//this routine is needed to avoid a longjmp clobber warning
static void _Try_OMX_MasterInit(int32& aError, OMX_ERRORTYPE& aStatus, OMXMasterCoreGlobalData *data)
{
OSCL_TRY(aError, aStatus = _OMX_MasterInit(data););
}
//this routine is needed to avoid a longjmp clobber warning
static void _Try_OMX_MasterCreate(int32& aError, OMXMasterCoreGlobalData*& aData)
{
OSCL_TRY(aError, aData = OSCL_NEW(OMXMasterCoreGlobalData, ()););
}
OSCL_EXPORT_REF OMX_ERRORTYPE OMX_MasterInit()
{
OMX_ERRORTYPE status = OMX_ErrorNone;
//Check the global instance counter and only init OMX on the first call
int32 error;
OMXMasterCoreGlobalData* data = (OMXMasterCoreGlobalData*)OsclSingletonRegistry::lockAndGetInstance(OSCL_SINGLETON_ID_OMXMASTERCORE, error);
if (data)
{
// If singleton was already created
//Just update the instance counter.
data->iNumMasterOMXInstances++;
//Release the singleton.
OsclSingletonRegistry::registerInstanceAndUnlock(data, OSCL_SINGLETON_ID_OMXMASTERCORE, error);
if (error)
{
status = OMX_ErrorUndefined;
return status;
}
}
else
{
//First call
//create the OMX Master Core singleton data
_Try_OMX_MasterCreate(error, data);
if (error != OsclErrNone)
{
status = OMX_ErrorInsufficientResources;//some leave happened.
}
//If create succeeded, then init the OMX globals.
if (status == OMX_ErrorNone)
{
_Try_OMX_MasterInit(error, status, data);
if (error != OsclErrNone)
{
status = OMX_ErrorUndefined;//probably no memory.
}
}
//Release the singleton.
OsclSingletonRegistry::registerInstanceAndUnlock(data, OSCL_SINGLETON_ID_OMXMASTERCORE, error);
if (error)
{
//registry error
status = OMX_ErrorUndefined;
return status;
}
}
if (error && status == OMX_ErrorNone)
status = OMX_ErrorUndefined;//registry error
return status;
}
static OMX_ERRORTYPE _OMX_MasterDeinit(OMXMasterCoreGlobalData *data)
{
OMX_U32 jj;
OMX_ERRORTYPE Status = OMX_ErrorNone;
//free master registry
data->iTotalNumOMXComponents = 0;
PVOMXMasterRegistryStruct* pOMXMasterRegistry = (PVOMXMasterRegistryStruct*)(data->iMasterRegistry);
if (pOMXMasterRegistry)
OSCL_FREE(pOMXMasterRegistry);
data->iMasterRegistry = NULL;
PVOMXCompHandles* pOMXCompHandles = (PVOMXCompHandles*)(data->iOMXCompHandles);
if (pOMXCompHandles)
OSCL_FREE(pOMXCompHandles);
data->iOMXCompHandles = NULL;
OMXInterface** pInterface = (OMXInterface**)(data->iInterface);
//call Deinit for each core
if (pInterface)
{
for (jj = 0; jj < data->iNumOMXCores; jj++)
{
Status = (*(pInterface[jj]->GetpOMX_Deinit()))();
// interface delete will take place as part of library closing
}
OSCL_FREE(pInterface);
data->iInterface = NULL;
}
OsclSharedLibrary** pLibrary = (OsclSharedLibrary**)(data->iOMXLibrary);
if (pLibrary)
{
for (jj = 0; jj < data->iNumOMXCores; jj++)
{
if (pLibrary[jj])
{
pLibrary[jj]->Close();
#if 1 //JJDBG
OSCL_DELETE(pLibrary[jj]);
#endif
}
}
OSCL_FREE(pLibrary);
data->iOMXLibrary = NULL;
}
data->iNumOMXCores = 0;
return OMX_ErrorNone;
}
//this routine is needed to avoid a longjmp clobber warning.
static void _Try_OMX_MasterDeinit(int32 &aError, OMX_ERRORTYPE& aStatus, OMXMasterCoreGlobalData* data)
{
OSCL_TRY(aError, aStatus = _OMX_MasterDeinit(data););
}
//this routine is needed to avoid a longjmp clobber warning.
static void _Try_Data_MasterCleanup(int32 &aError, OMXMasterCoreGlobalData* aData)
{
OSCL_TRY(aError, OSCL_DELETE(aData););
}
OSCL_EXPORT_REF OMX_ERRORTYPE OMX_MasterDeinit()
{
OMX_ERRORTYPE status = OMX_ErrorNone;
//Check the global instance counter and only cleanup OMX on the last call.
int32 error;
OMXMasterCoreGlobalData* data = (OMXMasterCoreGlobalData*)OsclSingletonRegistry::lockAndGetInstance(OSCL_SINGLETON_ID_OMXMASTERCORE, error);
if (data)
{
data->iNumMasterOMXInstances--;
if (data->iNumMasterOMXInstances == 0)
{
//Cleanup the OMX globals.
_Try_OMX_MasterDeinit(error, status, data);
if (error != OsclErrNone)
status = OMX_ErrorUndefined;//some leave happened.
//Regardless of the cleanup result, cleanup the OMX singleton.
_Try_Data_MasterCleanup(error, data);
data = NULL;
if (error != OsclErrNone)
status = OMX_ErrorUndefined;//some leave happened.
}
}
//Release the singleton.
OsclSingletonRegistry::registerInstanceAndUnlock(data, OSCL_SINGLETON_ID_OMXMASTERCORE, error);
return status;
}
OSCL_EXPORT_REF OMX_ERRORTYPE OMX_APIENTRY OMX_MasterComponentNameEnum(
OMX_OUT OMX_STRING cComponentName,
OMX_IN OMX_U32 nNameLength,
OMX_IN OMX_U32 nIndex)
{
OSCL_UNUSED_ARG(nNameLength);
OMX_U32 ii;
OSCL_UNUSED_ARG(nNameLength);
int32 error;
// this method just reads from the master registry (which does not change) - so no lock is needed
OMXMasterCoreGlobalData* data = (OMXMasterCoreGlobalData*)OsclSingletonRegistry::getInstance(OSCL_SINGLETON_ID_OMXMASTERCORE, error);
if (data)
{
PVOMXMasterRegistryStruct* pOMXMasterRegistry = (PVOMXMasterRegistryStruct*)(data->iMasterRegistry);
if (NULL == pOMXMasterRegistry)
{
return OMX_ErrorNoMore;
}
// go through alll the components and find the one with the correct index
for (ii = 0; ii < data->iTotalNumOMXComponents; ii++)
{
if (pOMXMasterRegistry[ii].CompIndex == nIndex)
{
oscl_strncpy((OMX_STRING)cComponentName,
(OMX_STRING)pOMXMasterRegistry[ii].CompName,
PV_OMX_MAX_COMPONENT_NAME_LENGTH);
break;
}
}
if (ii == data->iTotalNumOMXComponents)
{
return OMX_ErrorNoMore;
}
return OMX_ErrorNone;
}
else
{
return OMX_ErrorNoMore;
}
}
OSCL_EXPORT_REF OMX_ERRORTYPE OMX_APIENTRY OMX_MasterGetHandle(
OMX_OUT OMX_HANDLETYPE* pHandle,
OMX_IN OMX_STRING cComponentName,
OMX_IN OMX_PTR pAppData,
OMX_IN OMX_CALLBACKTYPE* pCallBacks,
OMX_BOOL bHWAccelerated)
{
OMX_ERRORTYPE Status = OMX_ErrorNone;
OMX_U32 ii, kk;
int32 error;
OMXMasterCoreGlobalData* data = (OMXMasterCoreGlobalData*)OsclSingletonRegistry::lockAndGetInstance(OSCL_SINGLETON_ID_OMXMASTERCORE, error);
if (data)
{
PVOMXMasterRegistryStruct* pOMXMasterRegistry = (PVOMXMasterRegistryStruct*)(data->iMasterRegistry);
OMXInterface** pInterface = (OMXInterface**)(data->iInterface);
PVOMXCompHandles* pOMXCompHandles = (PVOMXCompHandles*)(data->iOMXCompHandles);
if ((pOMXMasterRegistry == NULL) || (pInterface == NULL) || (pOMXCompHandles == NULL))
{
// unlock singleton before returning
OsclSingletonRegistry::registerInstanceAndUnlock(data, OSCL_SINGLETON_ID_OMXMASTERCORE, error);
if (error)
{
//registry error
Status = OMX_ErrorUndefined;
return Status;
}
return OMX_ErrorInsufficientResources;
}
OMX_S32 hwCodecFoundWhenSoftwareCodecIsRequested = -1;
for (ii = 0; ii < (data->iTotalNumOMXComponents); ii++)
{
// go through the list of supported components and find the component based on its name (identifier)
if (!oscl_strcmp((OMX_STRING)pOMXMasterRegistry[ii].CompName, cComponentName))
{
// when we are not requesting a HW accelelrated codec
// we prefer to find a software-based codec.
if (!bHWAccelerated) {
if (!pOMXMasterRegistry[ii].bHWAccelerated)
{
break;
}
else if (hwCodecFoundWhenSoftwareCodecIsRequested == -1)
{
// Store the first hardware-based codec found
// In case we could not find any software-based codec, we will
// use this hareware-based codec
hwCodecFoundWhenSoftwareCodecIsRequested = ii;
}
} else {
break;
}
}
}
if (ii == (data->iTotalNumOMXComponents) && hwCodecFoundWhenSoftwareCodecIsRequested == -1)
{
// could not find a component with the given name
OsclSingletonRegistry::registerInstanceAndUnlock(data, OSCL_SINGLETON_ID_OMXMASTERCORE, error);
if (error)
{
//registry error
Status = OMX_ErrorUndefined;
return Status;
}
return OMX_ErrorComponentNotFound;
}
else if (hwCodecFoundWhenSoftwareCodecIsRequested != -1)
{
ii = hwCodecFoundWhenSoftwareCodecIsRequested;
}
// call the appropriate GetHandle for the component
// save component handle with the OMX core index, so it can be retrieved
// later when freehandle is called
// find an empty slot to write the pair handle/index:
for (kk = 0; kk < MAX_NUMBER_OF_OMX_COMPONENTS; kk++)
{
if (pOMXCompHandles[kk].handle == NULL)
{
break;
}
}
if (kk == MAX_NUMBER_OF_OMX_COMPONENTS)
{
// no empty slot was found
return OMX_ErrorComponentNotFound;
}
OMX_U32 index = pOMXMasterRegistry[ii].OMXCoreIndex;
Status = (*(pInterface[index]->GetpOMX_GetHandle()))(pHandle, cComponentName, pAppData, pCallBacks);
if (Status == OMX_ErrorNone)
{
// write the pair handle/index
pOMXCompHandles[kk].handle = *pHandle;
pOMXCompHandles[kk].OMXCoreIndex = index;
}
OsclSingletonRegistry::registerInstanceAndUnlock(data, OSCL_SINGLETON_ID_OMXMASTERCORE, error);
if (error)
{
//registry error
Status = OMX_ErrorUndefined;
}
return Status;
}
else
{
OsclSingletonRegistry::registerInstanceAndUnlock(data, OSCL_SINGLETON_ID_OMXMASTERCORE, error);
if (error)
{
//registry error
Status = OMX_ErrorUndefined;
return Status;
}
return OMX_ErrorInsufficientResources;
}
}
OSCL_EXPORT_REF OMX_ERRORTYPE OMX_APIENTRY OMX_MasterFreeHandle(OMX_IN OMX_HANDLETYPE hComponent)
{
OMX_ERRORTYPE Status = OMX_ErrorNone;
OMX_U32 RegIndex;
int32 error;
OMXMasterCoreGlobalData* data = (OMXMasterCoreGlobalData*)OsclSingletonRegistry::lockAndGetInstance(OSCL_SINGLETON_ID_OMXMASTERCORE, error);
if (data)
{
PVOMXCompHandles* pOMXCompHandles = (PVOMXCompHandles*)(data->iOMXCompHandles);
OMXInterface** pInterface = (OMXInterface**)(data->iInterface);
if ((pOMXCompHandles == NULL) || (pInterface == NULL))
{
OsclSingletonRegistry::registerInstanceAndUnlock(data, OSCL_SINGLETON_ID_OMXMASTERCORE, error);
if (error)
{
//registry error
Status = OMX_ErrorUndefined;
return Status;
}
return OMX_ErrorInsufficientResources;
}
// get the core index for the handle
Status = GetRegIndexForHandle(hComponent, RegIndex, data);
if (OMX_ErrorNone != Status)
{
OsclSingletonRegistry::registerInstanceAndUnlock(data, OSCL_SINGLETON_ID_OMXMASTERCORE, error);
return Status;
}
// call the appropriate GetHandle for the component
OMX_U32 index = pOMXCompHandles[RegIndex].OMXCoreIndex;
Status = (*(pInterface[index]->GetpOMX_FreeHandle()))(hComponent);
//we're done with this, so get rid of the component handle
pOMXCompHandles[RegIndex].handle = NULL;
OsclSingletonRegistry::registerInstanceAndUnlock(data, OSCL_SINGLETON_ID_OMXMASTERCORE, error);
if (error)
{
//registry error
Status = OMX_ErrorUndefined;
}
return Status;
}
else
{
OsclSingletonRegistry::registerInstanceAndUnlock(data, OSCL_SINGLETON_ID_OMXMASTERCORE, error);
return OMX_ErrorInsufficientResources;
}
}
OSCL_EXPORT_REF OMX_ERRORTYPE OMX_MasterSetupTunnel(
OMX_IN OMX_HANDLETYPE hOutput,
OMX_IN OMX_U32 nPortOutput,
OMX_IN OMX_HANDLETYPE hInput,
OMX_IN OMX_U32 nPortInput)
{
OMX_ERRORTYPE Status;
OMX_U32 RegIndex1;
OMX_U32 RegIndex2;
int32 error;
// no need to lock - a different instance/thread does not affect the global array searches in this thread
OMXMasterCoreGlobalData* data = (OMXMasterCoreGlobalData*)OsclSingletonRegistry::getInstance(OSCL_SINGLETON_ID_OMXMASTERCORE, error);
if (data)
{
Status = GetRegIndexForHandle(hOutput, RegIndex1, data);
if (OMX_ErrorNone != Status)
{
return Status;
}
Status = GetRegIndexForHandle(hInput, RegIndex2, data);
if (OMX_ErrorNone != Status)
{
return Status;
}
PVOMXCompHandles* pOMXCompHandles = (PVOMXCompHandles*)(data->iOMXCompHandles);
OMXInterface** pInterface = (OMXInterface**)(data->iInterface);
if ((pOMXCompHandles == NULL) || (pInterface == NULL))
{
return OMX_ErrorInsufficientResources;
}
//if (pOMXCompHandles[RegIndex1].OMXCoreIndex != pOMXCompHandles[RegIndex2].OMXCoreIndex)
//{
// the components are from different omx cores
// it is not clear if setting up a tunnel between them is supported
// return OMX_ErrorNotImplemented;
//}
OMX_U32 index = pOMXCompHandles[RegIndex1].OMXCoreIndex;
Status = (*(pInterface[index]->GetpOMX_SetupTunnel()))(
hOutput,
nPortOutput,
hInput,
nPortInput);
return Status;
}
else
{
return OMX_ErrorInsufficientResources;
}
}
OSCL_EXPORT_REF OMX_ERRORTYPE OMX_MasterGetContentPipe(
OMX_OUT OMX_HANDLETYPE *hPipe,
OMX_IN OMX_STRING szURI)
{
OMX_ERRORTYPE Status = OMX_ErrorNotImplemented;
OMX_U32 ii;
int32 error;
// no need to lock
OMXMasterCoreGlobalData* data = (OMXMasterCoreGlobalData*)OsclSingletonRegistry::getInstance(OSCL_SINGLETON_ID_OMXMASTERCORE, error);
if (data)
{
// try to get the content pipe from any of the omx cores
// return the first valid one
OMXInterface** pInterface = (OMXInterface**)(data->iInterface);
if (pInterface)
{
for (ii = 0; ii < data->iNumOMXCores; ii++)
{
Status = (*(pInterface[ii]->GetpOMX_GetContentPipe()))(hPipe, szURI);
if (OMX_ErrorNone == Status)
{
break;
}
}
}
else
{
return OMX_ErrorInsufficientResources;
}
}
else
{
return OMX_ErrorInsufficientResources;
}
return Status;
}
OSCL_EXPORT_REF OMX_ERRORTYPE OMX_MasterGetComponentsOfRole(
OMX_IN OMX_STRING role,
OMX_INOUT OMX_U32 *pNumComps,
OMX_INOUT OMX_U8 **compNames)
{
OMX_U32 ii;
// initialize the number of components found to 0
*pNumComps = 0;
int32 error;
// no need to lock - just reading from master registry that does not change
OMXMasterCoreGlobalData* data = (OMXMasterCoreGlobalData*)OsclSingletonRegistry::getInstance(OSCL_SINGLETON_ID_OMXMASTERCORE, error);
if (data)
{
PVOMXMasterRegistryStruct* pOMXMasterRegistry = (PVOMXMasterRegistryStruct*)(data->iMasterRegistry);
if (pOMXMasterRegistry == NULL)
{
return OMX_ErrorNone;
}
// go through all components and check if they support the given role
for (ii = 0; ii < data->iTotalNumOMXComponents; ii++)
{
// if the role matches, increment the counter and record the comp. name
if (!oscl_strcmp((OMX_STRING)pOMXMasterRegistry[ii].CompRole, role))
{
// if a placeholder for compNames is provided, copy the component name into it
if (NULL != compNames)
{
oscl_strncpy((OMX_STRING)compNames[*pNumComps],
(OMX_STRING)pOMXMasterRegistry[ii].CompName,
PV_OMX_MAX_COMPONENT_NAME_LENGTH);
}
// increment the counter
*pNumComps = (*pNumComps + 1);
}
}
}
return OMX_ErrorNone;
}
OSCL_EXPORT_REF OMX_ERRORTYPE OMX_MasterGetRolesOfComponent(
OMX_IN OMX_STRING compName,
OMX_INOUT OMX_U32* pNumRoles,
OMX_OUT OMX_U8** roles)
{
OMX_U32 ii;
*pNumRoles = 0;
int32 error;
// no need to lock - just reading from master registry that does not change
OMXMasterCoreGlobalData* data = (OMXMasterCoreGlobalData*)OsclSingletonRegistry::getInstance(OSCL_SINGLETON_ID_OMXMASTERCORE, error);
if (data)
{
PVOMXMasterRegistryStruct* pOMXMasterRegistry = (PVOMXMasterRegistryStruct*)(data->iMasterRegistry);
if (pOMXMasterRegistry == NULL)
{
return OMX_ErrorNone;
}
// go through all components
for (ii = 0; ii < data->iTotalNumOMXComponents; ii++)
{
// if the name matches, increment the counter and record the comp. role
if (!oscl_strcmp((OMX_STRING)pOMXMasterRegistry[ii].CompName, compName))
{
// if a placeholder for roles is provided, copy the component role into it
if (NULL != roles)
{
oscl_strncpy((OMX_STRING)roles[*pNumRoles],
(OMX_STRING)pOMXMasterRegistry[ii].CompRole,
PV_OMX_MAX_COMPONENT_NAME_LENGTH);
}
// increment the counter
*pNumRoles = (*pNumRoles + 1);
}
}
}
return OMX_ErrorNone;
}
OMX_BOOL PV_OMXConfigParser(
OMX_PTR aInputParameters,
OMX_PTR aOutputParameters)
{
OMXConfigParserInputs* pInputs;
pInputs = (OMXConfigParserInputs*) aInputParameters;
if (NULL != pInputs->cComponentRole)
{
if (0 == oscl_strncmp(pInputs->cComponentRole, (OMX_STRING)"audio_decoder", oscl_strlen("audio_decoder")))
{
OMX_S32 Status;
pvAudioConfigParserInputs aInputs;
aInputs.inPtr = pInputs->inPtr;
aInputs.inBytes = pInputs->inBytes;
if (0 == oscl_strcmp(pInputs->cComponentRole, (OMX_STRING)"audio_decoder.wma"))
{
aInputs.iMimeType = PVMF_MIME_WMA;
}
else if (0 == oscl_strcmp(pInputs->cComponentRole, (OMX_STRING)"audio_decoder.aac"))
{
aInputs.iMimeType = PVMF_MIME_AAC_SIZEHDR;
}
else if (0 == oscl_strcmp(pInputs->cComponentRole, (OMX_STRING)"audio_decoder.amr"))
{
aInputs.iMimeType = PVMF_MIME_AMR;
}
else if (0 == oscl_strcmp(pInputs->cComponentRole, (OMX_STRING)"audio_decoder.amrnb"))
{
aInputs.iMimeType = PVMF_MIME_AMR;
}
else if (0 == oscl_strcmp(pInputs->cComponentRole, (OMX_STRING)"audio_decoder.amrwb"))
{
aInputs.iMimeType = PVMF_MIME_AMRWB;
}
else if (0 == oscl_strcmp(pInputs->cComponentRole, (OMX_STRING)"audio_decoder.mp3"))
{
aInputs.iMimeType = PVMF_MIME_MP3;
}
else
{
return OMX_FALSE;
}
Status = pv_audio_config_parser(&aInputs, (pvAudioConfigParserOutputs *)aOutputParameters);
if (0 == Status)
{
return OMX_FALSE;
}
}
else if (0 == oscl_strncmp(pInputs->cComponentRole, (OMX_STRING)"video_decoder", oscl_strlen("video_decoder")))
{
OMX_S32 Status;
pvVideoConfigParserInputs aInputs;
aInputs.inPtr = pInputs->inPtr;
aInputs.inBytes = pInputs->inBytes;
if (0 == oscl_strcmp(pInputs->cComponentRole, (OMX_STRING)"video_decoder.wmv"))
{
aInputs.iMimeType = PVMF_MIME_WMV;
}
else if (0 == oscl_strcmp(pInputs->cComponentRole, (OMX_STRING)"video_decoder.avc"))
{
aInputs.iMimeType = PVMF_MIME_H264_VIDEO;
}
else if (0 == oscl_strcmp(pInputs->cComponentRole, (OMX_STRING)"video_decoder.mpeg4"))
{
aInputs.iMimeType = PVMF_MIME_M4V;
}
else if (0 == oscl_strcmp(pInputs->cComponentRole, (OMX_STRING)"video_decoder.h263"))
{
aInputs.iMimeType = PVMF_MIME_H2632000;
}
else
{
return OMX_FALSE;
}
Status = pv_video_config_parser(&aInputs, (pvVideoConfigParserOutputs *)aOutputParameters);
if (0 != Status)
{
return OMX_FALSE;
}
}
else
{
return OMX_FALSE;
}
}
else
{
return OMX_FALSE;
}
return OMX_TRUE;
}
OSCL_EXPORT_REF OMX_BOOL OMX_MasterConfigParser(
OMX_PTR aInputParameters,
OMX_PTR aOutputParameters)
{
OMX_BOOL Status = OMX_FALSE;
OMX_U32 ii;
int32 error;
OMXMasterCoreGlobalData* data = (OMXMasterCoreGlobalData*)OsclSingletonRegistry::getInstance(OSCL_SINGLETON_ID_OMXMASTERCORE, error);
if (data)
{
// try to get the omxconfigparser from omx cores
// return the first valid one
OMXInterface** pInterface = (OMXInterface**)(data->iInterface);
PVOMXMasterRegistryStruct* pOMXMasterRegistry = (PVOMXMasterRegistryStruct*)(data->iMasterRegistry);
if (pOMXMasterRegistry == NULL)
{
return Status;
}
if (pInterface)
{
for (ii = 0; ii < (data->iTotalNumOMXComponents); ii++)
{
if (!oscl_strcmp((OMX_STRING)pOMXMasterRegistry[ii].CompRole, ((OMXConfigParserInputs*)aInputParameters)->cComponentRole))
{
// go through the list of supported components and find the component based on its name (identifier)
if (!oscl_strcmp((OMX_STRING)pOMXMasterRegistry[ii].CompName, ((OMXConfigParserInputs*)aInputParameters)->cComponentName))
{
// found a matching name
break;
}
}
}
if (ii == (data->iTotalNumOMXComponents))
{
return Status;
}
OMX_U32 index = pOMXMasterRegistry[ii].OMXCoreIndex;
if (pInterface[index]->GetpOMXConfigParser() == NULL)
{
//The OMX core does not have config parser - use PV config parser
Status = PV_OMXConfigParser(aInputParameters, aOutputParameters);
}
else
{
Status = (*(pInterface[index]->GetpOMXConfigParser()))(aInputParameters, aOutputParameters);
}
}
else
{
return Status;
}
}
return Status;
}