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