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 <inttypes.h> 19 20 #include <OMX_Core.h> 21 #include <OMX_Component.h> 22 #include <dlfcn.h> 23 24 #include "isv_omxcore.h" 25 #include "isv_omxcomponent.h" 26 #include "isv_profile.h" 27 28 #include "OMX_adaptor.h" 29 30 //#define LOG_NDEBUG 0 31 #undef LOG_TAG 32 #define LOG_TAG "isv-omxil" 33 34 #define WRS_CORE_NAME "libwrs_omxil_core_pvwrapped.so" 35 #define CORE_NUMBER 1 36 #ifdef USE_MEDIASDK 37 #define MSDK_CORE_NAME "libmfx_omx_core.so" 38 #undef CORE_NUMBER 39 #define CORE_NUMBER 2 40 #endif 41 42 43 using namespace android; 44 45 static unsigned int g_initialized = 0; 46 static unsigned int g_nr_instances = 0; 47 static unsigned int g_nr_comp = 0; 48 49 static pthread_mutex_t g_module_lock = PTHREAD_MUTEX_INITIALIZER; 50 static ISVOMXCore g_cores[CORE_NUMBER]; 51 static Vector<ISVComponent*> g_isv_components; 52 53 MRM_OMX_Adaptor* g_mrm_omx_adaptor = NULL; 54 55 /********************************************************************************** 56 * core entry 57 */ 58 59 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Init(void) 60 { 61 int ret; 62 ALOGD_IF(ISV_CORE_DEBUG, "%s: enter", __func__); 63 64 pthread_mutex_lock(&g_module_lock); 65 if (!g_initialized) { 66 for (OMX_U32 i = 0; i < CORE_NUMBER; i++) { 67 68 void* libHandle = NULL; 69 if (i == 0) 70 libHandle = dlopen(WRS_CORE_NAME, RTLD_LAZY); 71 #ifdef USE_MEDIASDK 72 else 73 libHandle = dlopen(MSDK_CORE_NAME, RTLD_LAZY); 74 #endif 75 if (libHandle != NULL) { 76 g_cores[i].mLibHandle = libHandle; 77 g_cores[i].mInit = (ISVOMXCore::InitFunc)dlsym(libHandle, "OMX_Init"); 78 g_cores[i].mDeinit = (ISVOMXCore::DeinitFunc)dlsym(libHandle, "OMX_Deinit"); 79 80 g_cores[i].mComponentNameEnum = 81 (ISVOMXCore::ComponentNameEnumFunc)dlsym(libHandle, "OMX_ComponentNameEnum"); 82 83 g_cores[i].mGetHandle = (ISVOMXCore::GetHandleFunc)dlsym(libHandle, "OMX_GetHandle"); 84 g_cores[i].mFreeHandle = (ISVOMXCore::FreeHandleFunc)dlsym(libHandle, "OMX_FreeHandle"); 85 86 g_cores[i].mGetRolesOfComponentHandle = 87 (ISVOMXCore::GetRolesOfComponentFunc)dlsym( 88 libHandle, "OMX_GetRolesOfComponent"); 89 if (g_cores[i].mInit != NULL) { 90 (*(g_cores[i].mInit))(); 91 } 92 if (g_cores[i].mComponentNameEnum != NULL) { 93 // calculating number of components registered inside given OMX core 94 char tmpComponentName[OMX_MAX_STRINGNAME_SIZE] = { 0 }; 95 OMX_U32 tmpIndex = 0; 96 while (OMX_ErrorNone == ((*(g_cores[i].mComponentNameEnum))(tmpComponentName, OMX_MAX_STRINGNAME_SIZE, tmpIndex))) { 97 tmpIndex++; 98 ALOGD_IF(ISV_CORE_DEBUG, "OMX IL core: declares component %s", tmpComponentName); 99 } 100 g_cores[i].mNumComponents = tmpIndex; 101 g_nr_comp += g_cores[i].mNumComponents; 102 ALOGD_IF(ISV_CORE_DEBUG, 103 "OMX IL core: contains %" PRIu32 " components", 104 g_cores[i].mNumComponents); 105 } 106 } else { 107 pthread_mutex_unlock(&g_module_lock); 108 ALOGW("OMX IL core not found"); 109 } 110 } 111 g_mrm_omx_adaptor = MRM_OMX_Adaptor::getInstance(); 112 g_mrm_omx_adaptor->MRM_OMX_Init(); 113 g_initialized = 1; 114 } 115 pthread_mutex_unlock(&g_module_lock); 116 117 ALOGD_IF(ISV_CORE_DEBUG, "%s: exit done", __func__); 118 return OMX_ErrorNone; 119 } 120 121 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Deinit(void) 122 { 123 ALOGD_IF(ISV_CORE_DEBUG, "%s: enter", __func__); 124 OMX_ERRORTYPE ret = OMX_ErrorNone; 125 126 ALOGV("%s: enter", __func__); 127 if (g_initialized == 0) 128 return OMX_ErrorNone; 129 130 pthread_mutex_lock(&g_module_lock); 131 for (OMX_U32 i = 0; i < CORE_NUMBER; i++) { 132 if (g_cores[i].mDeinit != NULL) { 133 (*(g_cores[i].mDeinit))(); 134 } 135 } 136 pthread_mutex_unlock(&g_module_lock); 137 138 if (g_mrm_omx_adaptor != NULL) { 139 g_mrm_omx_adaptor = NULL; 140 } 141 142 g_initialized = 0; 143 144 ALOGD_IF(ISV_CORE_DEBUG, "%s: exit %d", __func__, ret); 145 return ret; 146 } 147 148 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_ComponentNameEnum( 149 OMX_OUT OMX_STRING cComponentName, 150 OMX_IN OMX_U32 nNameLength, 151 OMX_IN OMX_U32 nIndex) 152 { 153 ALOGD_IF(ISV_CORE_DEBUG, "%s: enter", __func__); 154 pthread_mutex_lock(&g_module_lock); 155 OMX_U32 relativeIndex = nIndex; 156 if (nIndex >= g_nr_comp) { 157 pthread_mutex_unlock(&g_module_lock); 158 ALOGD_IF(ISV_CORE_DEBUG, "%s: exit done", __func__); 159 return OMX_ErrorNoMore; 160 } 161 162 for (OMX_U32 i = 0; i < CORE_NUMBER; i++) { 163 if (g_cores[i].mLibHandle == NULL) { 164 continue; 165 } 166 if (relativeIndex < g_cores[i].mNumComponents) { 167 pthread_mutex_unlock(&g_module_lock); 168 ALOGD_IF(ISV_CORE_DEBUG, "%s: found %" PRIu32 "th component %s", 169 __func__, nIndex, cComponentName); 170 return ((*(g_cores[i].mComponentNameEnum))(cComponentName, nNameLength, relativeIndex)); 171 } else relativeIndex -= g_cores[i].mNumComponents; 172 } 173 pthread_mutex_unlock(&g_module_lock); 174 ALOGD_IF(ISV_CORE_DEBUG, "%s: exit error!!!", __func__); 175 return OMX_ErrorUndefined; 176 } 177 178 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_GetHandle( 179 OMX_OUT OMX_HANDLETYPE* pHandle, 180 OMX_IN OMX_STRING cComponentName, 181 OMX_IN OMX_PTR pAppData, 182 OMX_IN OMX_CALLBACKTYPE *pCallBacks) 183 { 184 struct list *entry; 185 OMX_ERRORTYPE ret; 186 OMX_HANDLETYPE tempHandle; 187 ALOGD_IF(ISV_CORE_DEBUG, "%s: enter, try to get %s", __func__, cComponentName); 188 pthread_mutex_lock(&g_module_lock); 189 190 // create a isv component instant 191 ISVComponent *pISVComponent = new ISVComponent(pAppData); 192 if (!pISVComponent) { 193 ALOGE("%s: failed to alloc isv omx component", __func__); 194 pthread_mutex_unlock(&g_module_lock); 195 return OMX_ErrorInsufficientResources; 196 } 197 198 OMX_CALLBACKTYPE *pISVCallBacks = pISVComponent->getCallBacks(pCallBacks); 199 if (!pISVCallBacks) { 200 ALOGE("%s: failed to get isv callback functions", __func__); 201 pthread_mutex_unlock(&g_module_lock); 202 return OMX_ErrorInsufficientResources; 203 } 204 205 ret = g_mrm_omx_adaptor->MRM_OMX_CheckIfFullLoad(cComponentName); 206 if (ret == OMX_ErrorInsufficientResources) { 207 ALOGE("OMX_GetHandle failed. codec under full load status from media resource manager.\ 208 return OMX_ErrorInsufficientResources"); 209 pthread_mutex_unlock(&g_module_lock); 210 return OMX_ErrorInsufficientResources; 211 } 212 213 /* find the real component*/ 214 for (OMX_U32 i = 0; i < CORE_NUMBER; i++) { 215 if (g_cores[i].mLibHandle == NULL) { 216 continue; 217 } 218 219 OMX_ERRORTYPE omx_res = (*(g_cores[i].mGetHandle))( 220 &tempHandle, 221 const_cast<char *>(cComponentName), 222 pAppData, pISVCallBacks); 223 if(omx_res == OMX_ErrorNone) { 224 pISVComponent->setComponent(static_cast<OMX_COMPONENTTYPE*>(tempHandle), &g_cores[i]); 225 g_isv_components.push_back(pISVComponent); 226 *pHandle = pISVComponent->getBaseComponent(); 227 228 ALOGD_IF(ISV_CORE_DEBUG, "%s: found component %s, pHandle %p", __func__, cComponentName, *pHandle); 229 230 // set component into media resource manager adaptor 231 g_mrm_omx_adaptor->MRM_OMX_SetComponent(tempHandle, cComponentName); 232 233 pthread_mutex_unlock(&g_module_lock); 234 return OMX_ErrorNone; 235 } else if(omx_res == OMX_ErrorInsufficientResources) { 236 pthread_mutex_unlock(&g_module_lock); 237 delete pISVComponent; 238 pISVComponent = NULL; 239 return OMX_ErrorInsufficientResources; 240 } 241 } 242 pthread_mutex_unlock(&g_module_lock); 243 244 delete pISVComponent; 245 pISVComponent = NULL; 246 ALOGD_IF(ISV_CORE_DEBUG, "%s(): exit failure, %s not found", __func__, cComponentName); 247 return OMX_ErrorInvalidComponent; 248 } 249 250 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_FreeHandle( 251 OMX_IN OMX_HANDLETYPE hComponent) 252 { 253 OMX_ERRORTYPE ret; 254 255 ALOGD_IF(ISV_CORE_DEBUG, "%s: enter, try to free component hanle %p", __func__, hComponent); 256 pthread_mutex_lock(&g_module_lock); 257 258 for (OMX_U32 i = 0; i < g_isv_components.size(); i++) { 259 ISVComponent *pComp = g_isv_components.itemAt(i); 260 if (static_cast<OMX_HANDLETYPE>(pComp->getBaseComponent()) == hComponent) { 261 // remove it in media resource manager before call pComp->freeComponent 262 g_mrm_omx_adaptor->MRM_OMX_RemoveComponent(pComp->getComponent()); 263 OMX_ERRORTYPE omx_res = pComp->freeComponent(); 264 if (omx_res != OMX_ErrorNone) { 265 ALOGE("%s: free OMX handle %p failed", __func__, hComponent); 266 pthread_mutex_unlock(&g_module_lock); 267 return omx_res; 268 } 269 delete pComp; 270 g_isv_components.removeAt(i); 271 ALOGD_IF(ISV_CORE_DEBUG, "%s: free component %p success", __func__, hComponent); 272 pthread_mutex_unlock(&g_module_lock); 273 return OMX_ErrorNone; 274 } 275 } 276 pthread_mutex_unlock(&g_module_lock); 277 ALOGE("%s(): exit failure, component %p not found", __func__, hComponent); 278 return OMX_ErrorInvalidComponent; 279 } 280 281 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_SetupTunnel( 282 OMX_IN OMX_HANDLETYPE __maybe_unused hOutput, 283 OMX_IN OMX_U32 __maybe_unused nPortOutput, 284 OMX_IN OMX_HANDLETYPE __maybe_unused hInput, 285 OMX_IN OMX_U32 __maybe_unused nPortInput) 286 { 287 return OMX_ErrorNotImplemented; 288 } 289 290 OMX_API OMX_ERRORTYPE OMX_GetContentPipe( 291 OMX_OUT OMX_HANDLETYPE __maybe_unused *hPipe, 292 OMX_IN OMX_STRING __maybe_unused szURI) 293 { 294 return OMX_ErrorNotImplemented; 295 } 296 297 OMX_API OMX_ERRORTYPE OMX_GetComponentsOfRole ( 298 OMX_IN OMX_STRING __maybe_unused role, 299 OMX_INOUT OMX_U32 __maybe_unused *pNumComps, 300 OMX_INOUT OMX_U8 __maybe_unused **compNames) 301 { 302 ALOGD_IF(ISV_CORE_DEBUG, "%s: enter", __func__); 303 return OMX_ErrorNotImplemented; 304 } 305 306 OMX_API OMX_ERRORTYPE OMX_GetRolesOfComponent ( 307 OMX_IN OMX_STRING compName, 308 OMX_INOUT OMX_U32 *pNumRoles, 309 OMX_OUT OMX_U8 **roles) 310 { 311 ALOGD_IF(ISV_CORE_DEBUG, "%s: enter", __func__); 312 pthread_mutex_lock(&g_module_lock); 313 for (OMX_U32 j = 0; j < CORE_NUMBER; j++) { 314 if (g_cores[j].mLibHandle == NULL) { 315 continue; 316 } 317 318 OMX_U32 numRoles; 319 OMX_ERRORTYPE err = (*(g_cores[j].mGetRolesOfComponentHandle))( 320 const_cast<OMX_STRING>(compName), &numRoles, NULL); 321 322 if (err != OMX_ErrorNone) { 323 continue; 324 } 325 326 if (numRoles > 0) { 327 OMX_U8 **array = new OMX_U8 *[numRoles]; 328 for (OMX_U32 i = 0; i < numRoles; ++i) { 329 array[i] = new OMX_U8[OMX_MAX_STRINGNAME_SIZE]; 330 } 331 332 OMX_U32 numRoles2 = numRoles; 333 err = (*(g_cores[j].mGetRolesOfComponentHandle))( 334 const_cast<OMX_STRING>(compName), &numRoles2, array); 335 336 *pNumRoles = numRoles; 337 for (OMX_U32 i = 0; i < numRoles; i++) { 338 if (i < numRoles-1) 339 roles[i+1] = roles[i] + OMX_MAX_STRINGNAME_SIZE; 340 341 strncpy((OMX_STRING)&roles[i][0], 342 (const OMX_STRING)&array[i][0], OMX_MAX_STRINGNAME_SIZE); 343 delete[] array[i]; 344 array[i] = NULL; 345 } 346 347 delete[] array; 348 array = NULL; 349 } 350 351 pthread_mutex_unlock(&g_module_lock); 352 ALOGD_IF(ISV_CORE_DEBUG, "%s: exit done", __func__); 353 return OMX_ErrorNone; 354 } 355 pthread_mutex_unlock(&g_module_lock); 356 357 ALOGE("%s: invalid component", __func__); 358 return OMX_ErrorInvalidComponent; 359 } 360 361