1 /* 2 * Copyright (C) 2012 Intel Corporation. All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 */ 17 18 #include <OMX_Core.h> 19 #include <OMX_Component.h> 20 #include <dlfcn.h> 21 22 #include "isv_omxcore.h" 23 #include "isv_omxcomponent.h" 24 #include "isv_profile.h" 25 26 //#define LOG_NDEBUG 0 27 #undef LOG_TAG 28 #define LOG_TAG "isv-omxil" 29 30 #define WRS_CORE_NAME "libwrs_omxil_core_pvwrapped.so" 31 #define CORE_NUMBER 1 32 #ifdef USE_MEDIASDK 33 #define MSDK_CORE_NAME "libmfx_omx_core.so" 34 #undef CORE_NUMBER 35 #define CORE_NUMBER 2 36 #endif 37 38 39 using namespace android; 40 41 static unsigned int g_initialized = 0; 42 static unsigned int g_nr_instances = 0; 43 static unsigned int g_nr_comp = 0; 44 45 static pthread_mutex_t g_module_lock = PTHREAD_MUTEX_INITIALIZER; 46 static ISVOMXCore g_cores[CORE_NUMBER]; 47 static Vector<ISVComponent*> g_isv_components; 48 49 /********************************************************************************** 50 * core entry 51 */ 52 53 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Init(void) 54 { 55 int ret; 56 ALOGD_IF(ISV_CORE_DEBUG, "%s: enter", __func__); 57 58 pthread_mutex_lock(&g_module_lock); 59 if (!g_initialized) { 60 for (OMX_U32 i = 0; i < CORE_NUMBER; i++) { 61 62 void* libHandle = NULL; 63 if (i == 0) 64 libHandle = dlopen(WRS_CORE_NAME, RTLD_LAZY); 65 #ifdef USE_MEDIASDK 66 else 67 libHandle = dlopen(MSDK_CORE_NAME, RTLD_LAZY); 68 #endif 69 if (libHandle != NULL) { 70 g_cores[i].mLibHandle = libHandle; 71 g_cores[i].mInit = (ISVOMXCore::InitFunc)dlsym(libHandle, "OMX_Init"); 72 g_cores[i].mDeinit = (ISVOMXCore::DeinitFunc)dlsym(libHandle, "OMX_Deinit"); 73 74 g_cores[i].mComponentNameEnum = 75 (ISVOMXCore::ComponentNameEnumFunc)dlsym(libHandle, "OMX_ComponentNameEnum"); 76 77 g_cores[i].mGetHandle = (ISVOMXCore::GetHandleFunc)dlsym(libHandle, "OMX_GetHandle"); 78 g_cores[i].mFreeHandle = (ISVOMXCore::FreeHandleFunc)dlsym(libHandle, "OMX_FreeHandle"); 79 80 g_cores[i].mGetRolesOfComponentHandle = 81 (ISVOMXCore::GetRolesOfComponentFunc)dlsym( 82 libHandle, "OMX_GetRolesOfComponent"); 83 if (g_cores[i].mInit != NULL) { 84 (*(g_cores[i].mInit))(); 85 } 86 if (g_cores[i].mComponentNameEnum != NULL) { 87 // calculating number of components registered inside given OMX core 88 char tmpComponentName[OMX_MAX_STRINGNAME_SIZE] = { 0 }; 89 OMX_U32 tmpIndex = 0; 90 while (OMX_ErrorNone == ((*(g_cores[i].mComponentNameEnum))(tmpComponentName, OMX_MAX_STRINGNAME_SIZE, tmpIndex))) { 91 tmpIndex++; 92 ALOGD_IF(ISV_CORE_DEBUG, "OMX IL core: declares component %s", tmpComponentName); 93 } 94 g_cores[i].mNumComponents = tmpIndex; 95 g_nr_comp += g_cores[i].mNumComponents; 96 ALOGD_IF(ISV_CORE_DEBUG, "OMX IL core: contains %ld components", g_cores[i].mNumComponents); 97 } 98 } else { 99 pthread_mutex_unlock(&g_module_lock); 100 ALOGW("OMX IL core not found"); 101 } 102 } 103 g_initialized = 1; 104 } 105 pthread_mutex_unlock(&g_module_lock); 106 107 ALOGD_IF(ISV_CORE_DEBUG, "%s: exit done", __func__); 108 return OMX_ErrorNone; 109 } 110 111 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Deinit(void) 112 { 113 ALOGD_IF(ISV_CORE_DEBUG, "%s: enter", __func__); 114 OMX_ERRORTYPE ret = OMX_ErrorNone; 115 116 ALOGV("%s: enter", __func__); 117 if (g_initialized == 0) 118 return OMX_ErrorNone; 119 120 pthread_mutex_lock(&g_module_lock); 121 for (OMX_U32 i = 0; i < CORE_NUMBER; i++) { 122 if (g_cores[i].mDeinit != NULL) { 123 (*(g_cores[i].mDeinit))(); 124 } 125 } 126 pthread_mutex_unlock(&g_module_lock); 127 128 g_initialized = 0; 129 130 ALOGD_IF(ISV_CORE_DEBUG, "%s: exit %d", __func__, ret); 131 return ret; 132 } 133 134 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_ComponentNameEnum( 135 OMX_OUT OMX_STRING cComponentName, 136 OMX_IN OMX_U32 nNameLength, 137 OMX_IN OMX_U32 nIndex) 138 { 139 ALOGD_IF(ISV_CORE_DEBUG, "%s: enter", __func__); 140 pthread_mutex_lock(&g_module_lock); 141 OMX_U32 relativeIndex = nIndex; 142 if (nIndex >= g_nr_comp) { 143 pthread_mutex_unlock(&g_module_lock); 144 ALOGD_IF(ISV_CORE_DEBUG, "%s: exit done", __func__); 145 return OMX_ErrorNoMore; 146 } 147 148 for (OMX_U32 i = 0; i < CORE_NUMBER; i++) { 149 if (g_cores[i].mLibHandle == NULL) { 150 continue; 151 } 152 if (relativeIndex < g_cores[i].mNumComponents) { 153 pthread_mutex_unlock(&g_module_lock); 154 ALOGD_IF(ISV_CORE_DEBUG, "%s: found %luth component %s", __func__, nIndex, cComponentName); 155 return ((*(g_cores[i].mComponentNameEnum))(cComponentName, nNameLength, relativeIndex)); 156 } else relativeIndex -= g_cores[i].mNumComponents; 157 } 158 pthread_mutex_unlock(&g_module_lock); 159 ALOGD_IF(ISV_CORE_DEBUG, "%s: exit error!!!", __func__); 160 return OMX_ErrorUndefined; 161 } 162 163 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_GetHandle( 164 OMX_OUT OMX_HANDLETYPE* pHandle, 165 OMX_IN OMX_STRING cComponentName, 166 OMX_IN OMX_PTR pAppData, 167 OMX_IN OMX_CALLBACKTYPE *pCallBacks) 168 { 169 struct list *entry; 170 OMX_ERRORTYPE ret; 171 OMX_HANDLETYPE tempHandle; 172 ALOGD_IF(ISV_CORE_DEBUG, "%s: enter, try to get %s", __func__, cComponentName); 173 pthread_mutex_lock(&g_module_lock); 174 175 // create a isv component instant 176 ISVComponent *pISVComponent = new ISVComponent(pAppData); 177 if (!pISVComponent) { 178 ALOGE("%s: failed to alloc isv omx component", __func__); 179 pthread_mutex_unlock(&g_module_lock); 180 return OMX_ErrorInsufficientResources; 181 } 182 183 OMX_CALLBACKTYPE *pISVCallBacks = pISVComponent->getCallBacks(pCallBacks); 184 if (!pISVCallBacks) { 185 ALOGE("%s: failed to get isv callback functions", __func__); 186 pthread_mutex_unlock(&g_module_lock); 187 return OMX_ErrorInsufficientResources; 188 } 189 190 /* find the real component*/ 191 for (OMX_U32 i = 0; i < CORE_NUMBER; i++) { 192 if (g_cores[i].mLibHandle == NULL) { 193 continue; 194 } 195 196 OMX_ERRORTYPE omx_res = (*(g_cores[i].mGetHandle))( 197 &tempHandle, 198 const_cast<char *>(cComponentName), 199 pAppData, pISVCallBacks); 200 if(omx_res == OMX_ErrorNone) { 201 pISVComponent->setComponent(static_cast<OMX_COMPONENTTYPE*>(tempHandle), &g_cores[i]); 202 g_isv_components.push_back(pISVComponent); 203 *pHandle = pISVComponent->getBaseComponent(); 204 205 ALOGD_IF(ISV_CORE_DEBUG, "%s: found component %s, pHandle %p", __func__, cComponentName, *pHandle); 206 pthread_mutex_unlock(&g_module_lock); 207 return OMX_ErrorNone; 208 } 209 } 210 pthread_mutex_unlock(&g_module_lock); 211 212 delete pISVComponent; 213 pISVComponent = NULL; 214 ALOGD_IF(ISV_CORE_DEBUG, "%s(): exit failure, %s not found", __func__, cComponentName); 215 return OMX_ErrorInvalidComponent; 216 } 217 218 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_FreeHandle( 219 OMX_IN OMX_HANDLETYPE hComponent) 220 { 221 OMX_ERRORTYPE ret; 222 223 ALOGD_IF(ISV_CORE_DEBUG, "%s: enter, try to free component hanle %p", __func__, hComponent); 224 pthread_mutex_lock(&g_module_lock); 225 226 for (OMX_U32 i = 0; i < g_isv_components.size(); i++) { 227 ISVComponent *pComp = g_isv_components.itemAt(i); 228 if (static_cast<OMX_HANDLETYPE>(pComp->getBaseComponent()) == hComponent) { 229 OMX_ERRORTYPE omx_res = pComp->freeComponent(); 230 if (omx_res != OMX_ErrorNone) { 231 ALOGE("%s: free OMX handle %p failed", __func__, hComponent); 232 pthread_mutex_unlock(&g_module_lock); 233 return omx_res; 234 } 235 delete pComp; 236 g_isv_components.removeAt(i); 237 ALOGD_IF(ISV_CORE_DEBUG, "%s: free component %p success", __func__, hComponent); 238 pthread_mutex_unlock(&g_module_lock); 239 return OMX_ErrorNone; 240 } 241 } 242 pthread_mutex_unlock(&g_module_lock); 243 ALOGE("%s(): exit failure, component %p not found", __func__, hComponent); 244 return OMX_ErrorInvalidComponent; 245 } 246 247 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_SetupTunnel( 248 OMX_IN OMX_HANDLETYPE __maybe_unused hOutput, 249 OMX_IN OMX_U32 __maybe_unused nPortOutput, 250 OMX_IN OMX_HANDLETYPE __maybe_unused hInput, 251 OMX_IN OMX_U32 __maybe_unused nPortInput) 252 { 253 return OMX_ErrorNotImplemented; 254 } 255 256 OMX_API OMX_ERRORTYPE OMX_GetContentPipe( 257 OMX_OUT OMX_HANDLETYPE __maybe_unused *hPipe, 258 OMX_IN OMX_STRING __maybe_unused szURI) 259 { 260 return OMX_ErrorNotImplemented; 261 } 262 263 OMX_API OMX_ERRORTYPE OMX_GetComponentsOfRole ( 264 OMX_IN OMX_STRING __maybe_unused role, 265 OMX_INOUT OMX_U32 __maybe_unused *pNumComps, 266 OMX_INOUT OMX_U8 __maybe_unused **compNames) 267 { 268 ALOGD_IF(ISV_CORE_DEBUG, "%s: enter", __func__); 269 return OMX_ErrorNotImplemented; 270 } 271 272 OMX_API OMX_ERRORTYPE OMX_GetRolesOfComponent ( 273 OMX_IN OMX_STRING compName, 274 OMX_INOUT OMX_U32 *pNumRoles, 275 OMX_OUT OMX_U8 **roles) 276 { 277 ALOGD_IF(ISV_CORE_DEBUG, "%s: enter", __func__); 278 pthread_mutex_lock(&g_module_lock); 279 for (OMX_U32 j = 0; j < CORE_NUMBER; j++) { 280 if (g_cores[j].mLibHandle == NULL) { 281 continue; 282 } 283 284 OMX_U32 numRoles; 285 OMX_ERRORTYPE err = (*(g_cores[j].mGetRolesOfComponentHandle))( 286 const_cast<OMX_STRING>(compName), &numRoles, NULL); 287 288 if (err != OMX_ErrorNone) { 289 continue; 290 } 291 292 if (numRoles > 0) { 293 OMX_U8 **array = new OMX_U8 *[numRoles]; 294 for (OMX_U32 i = 0; i < numRoles; ++i) { 295 array[i] = new OMX_U8[OMX_MAX_STRINGNAME_SIZE]; 296 } 297 298 OMX_U32 numRoles2 = numRoles; 299 err = (*(g_cores[j].mGetRolesOfComponentHandle))( 300 const_cast<OMX_STRING>(compName), &numRoles2, array); 301 302 *pNumRoles = numRoles; 303 for (OMX_U32 i = 0; i < numRoles; i++) { 304 if (i < numRoles-1) 305 roles[i+1] = roles[i] + OMX_MAX_STRINGNAME_SIZE; 306 307 strncpy((OMX_STRING)&roles[i][0], 308 (const OMX_STRING)&array[i][0], OMX_MAX_STRINGNAME_SIZE); 309 delete[] array[i]; 310 array[i] = NULL; 311 } 312 313 delete[] array; 314 array = NULL; 315 } 316 317 pthread_mutex_unlock(&g_module_lock); 318 ALOGD_IF(ISV_CORE_DEBUG, "%s: exit done", __func__); 319 return OMX_ErrorNone; 320 } 321 pthread_mutex_unlock(&g_module_lock); 322 323 ALOGE("%s: invalid component", __func__); 324 return OMX_ErrorInvalidComponent; 325 } 326 327