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
OMX_Init(void)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
OMX_Deinit(void)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
OMX_ComponentNameEnum(OMX_OUT OMX_STRING cComponentName,OMX_IN OMX_U32 nNameLength,OMX_IN OMX_U32 nIndex)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
OMX_GetHandle(OMX_OUT OMX_HANDLETYPE * pHandle,OMX_IN OMX_STRING cComponentName,OMX_IN OMX_PTR pAppData,OMX_IN OMX_CALLBACKTYPE * pCallBacks)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
OMX_FreeHandle(OMX_IN OMX_HANDLETYPE hComponent)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
OMX_SetupTunnel(OMX_IN OMX_HANDLETYPE __maybe_unused hOutput,OMX_IN OMX_U32 __maybe_unused nPortOutput,OMX_IN OMX_HANDLETYPE __maybe_unused hInput,OMX_IN OMX_U32 __maybe_unused nPortInput)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
OMX_GetContentPipe(OMX_OUT OMX_HANDLETYPE __maybe_unused * hPipe,OMX_IN OMX_STRING __maybe_unused szURI)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
OMX_GetComponentsOfRole(OMX_IN OMX_STRING __maybe_unused role,OMX_INOUT OMX_U32 __maybe_unused * pNumComps,OMX_INOUT OMX_U8 __maybe_unused ** compNames)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
OMX_GetRolesOfComponent(OMX_IN OMX_STRING compName,OMX_INOUT OMX_U32 * pNumRoles,OMX_OUT OMX_U8 ** roles)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