isv_omxcore.cpp revision d6acef05e41af96ff00f2c579e3f9c96cb1a0530
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
39using namespace android;
40
41static unsigned int g_initialized = 0;
42static unsigned int g_nr_instances = 0;
43static unsigned int g_nr_comp = 0;
44
45static pthread_mutex_t g_module_lock = PTHREAD_MUTEX_INITIALIZER;
46static ISVOMXCore g_cores[CORE_NUMBER];
47static Vector<ISVComponent*> g_isv_components;
48
49/**********************************************************************************
50 * core entry
51 */
52
53OMX_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
111OMX_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
134OMX_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
163OMX_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
218OMX_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
247OMX_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
256OMX_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
263OMX_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
272OMX_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