1/*
2 *
3 * Copyright 2012 Samsung Electronics S.LSI Co. LTD
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/*
19 * @file       Exynos_OMX_Component_Register.c
20 * @brief      Exynos OpenMAX IL Component Register
21 * @author     SeungBeom Kim (sbcrux.kim@samsung.com)
22 * @version    2.0.0
23 * @history
24 *    2012.02.20 : Create
25 */
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <dlfcn.h>
30#include <sys/types.h>
31#include <dirent.h>
32#include <errno.h>
33#include <assert.h>
34#include <dirent.h>
35
36#include "OMX_Component.h"
37#include "Exynos_OSAL_Memory.h"
38#include "Exynos_OSAL_ETC.h"
39#include "Exynos_OSAL_Library.h"
40#include "Exynos_OMX_Component_Register.h"
41#include "Exynos_OMX_Macros.h"
42
43#undef  EXYNOS_LOG_TAG
44#define EXYNOS_LOG_TAG    "EXYNOS_COMP_REGS"
45#define EXYNOS_LOG_OFF
46#include "Exynos_OSAL_Log.h"
47
48OMX_ERRORTYPE Exynos_OMX_Component_Register(EXYNOS_OMX_COMPONENT_REGLIST **compList, OMX_U32 *compNum)
49{
50    OMX_ERRORTYPE  ret = OMX_ErrorNone;
51    int            componentNum = 0, roleNum = 0, totalCompNum = 0;
52    int            read;
53    char          *libName;
54    size_t         len;
55    const char    *errorMsg;
56    DIR           *dir;
57    struct dirent *d;
58
59    int (*Exynos_OMX_COMPONENT_Library_Register)(ExynosRegisterComponentType **exynosComponents);
60    ExynosRegisterComponentType **exynosComponentsTemp;
61    EXYNOS_OMX_COMPONENT_REGLIST *componentList;
62
63    FunctionIn();
64
65    dir = opendir(EXYNOS_OMX_INSTALL_PATH);
66    if (dir == NULL) {
67        ret = OMX_ErrorUndefined;
68        goto EXIT;
69    }
70
71    componentList = (EXYNOS_OMX_COMPONENT_REGLIST *)Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_COMPONENT_REGLIST) * MAX_OMX_COMPONENT_NUM);
72    Exynos_OSAL_Memset(componentList, 0, sizeof(EXYNOS_OMX_COMPONENT_REGLIST) * MAX_OMX_COMPONENT_NUM);
73    libName = Exynos_OSAL_Malloc(MAX_OMX_COMPONENT_LIBNAME_SIZE);
74
75    while ((d = readdir(dir)) != NULL) {
76        OMX_HANDLETYPE soHandle;
77        Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s", d->d_name);
78
79        if (Exynos_OSAL_Strncmp(d->d_name, "libOMX.Exynos.", Exynos_OSAL_Strlen("libOMX.Exynos.")) == 0) {
80            Exynos_OSAL_Memset(libName, 0, MAX_OMX_COMPONENT_LIBNAME_SIZE);
81            Exynos_OSAL_Strcpy(libName, EXYNOS_OMX_INSTALL_PATH);
82            Exynos_OSAL_Strcat(libName, d->d_name);
83            Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Path & libName : %s", libName);
84            if ((soHandle = Exynos_OSAL_dlopen(libName, RTLD_NOW)) != NULL) {
85                Exynos_OSAL_dlerror();    /* clear error*/
86                if ((Exynos_OMX_COMPONENT_Library_Register = Exynos_OSAL_dlsym(soHandle, "Exynos_OMX_COMPONENT_Library_Register")) != NULL) {
87                    int i = 0;
88                    unsigned int j = 0;
89
90                    componentNum = (*Exynos_OMX_COMPONENT_Library_Register)(NULL);
91                    exynosComponentsTemp = (ExynosRegisterComponentType **)Exynos_OSAL_Malloc(sizeof(ExynosRegisterComponentType*) * componentNum);
92                    for (i = 0; i < componentNum; i++) {
93                        exynosComponentsTemp[i] = Exynos_OSAL_Malloc(sizeof(ExynosRegisterComponentType));
94                        Exynos_OSAL_Memset(exynosComponentsTemp[i], 0, sizeof(ExynosRegisterComponentType));
95                    }
96                    (*Exynos_OMX_COMPONENT_Library_Register)(exynosComponentsTemp);
97
98                    for (i = 0; i < componentNum; i++) {
99                        Exynos_OSAL_Strcpy(componentList[totalCompNum].component.componentName, exynosComponentsTemp[i]->componentName);
100                        for (j = 0; j < exynosComponentsTemp[i]->totalRoleNum; j++)
101                            Exynos_OSAL_Strcpy(componentList[totalCompNum].component.roles[j], exynosComponentsTemp[i]->roles[j]);
102                        componentList[totalCompNum].component.totalRoleNum = exynosComponentsTemp[i]->totalRoleNum;
103
104                        Exynos_OSAL_Strcpy(componentList[totalCompNum].libName, libName);
105
106                        totalCompNum++;
107                    }
108                    for (i = 0; i < componentNum; i++) {
109                        Exynos_OSAL_Free(exynosComponentsTemp[i]);
110                    }
111
112                    Exynos_OSAL_Free(exynosComponentsTemp);
113                } else {
114                    if ((errorMsg = Exynos_OSAL_dlerror()) != NULL)
115                        Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "dlsym failed: %s", errorMsg);
116                }
117                Exynos_OSAL_dlclose(soHandle);
118            } else {
119                Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "dlopen failed: %s", Exynos_OSAL_dlerror());
120            }
121        } else {
122            /* not a component name line. skip */
123            continue;
124        }
125    }
126
127    Exynos_OSAL_Free(libName);
128
129    closedir(dir);
130
131    *compList = componentList;
132    *compNum = totalCompNum;
133
134EXIT:
135    FunctionOut();
136
137    return ret;
138}
139
140OMX_ERRORTYPE Exynos_OMX_Component_Unregister(EXYNOS_OMX_COMPONENT_REGLIST *componentList)
141{
142    OMX_ERRORTYPE ret = OMX_ErrorNone;
143
144    Exynos_OSAL_Free(componentList);
145
146EXIT:
147    return ret;
148}
149
150OMX_ERRORTYPE Exynos_OMX_ComponentAPICheck(OMX_COMPONENTTYPE *component)
151{
152    OMX_ERRORTYPE ret = OMX_ErrorNone;
153
154    if ((NULL == component->GetComponentVersion)    ||
155        (NULL == component->SendCommand)            ||
156        (NULL == component->GetParameter)           ||
157        (NULL == component->SetParameter)           ||
158        (NULL == component->GetConfig)              ||
159        (NULL == component->SetConfig)              ||
160        (NULL == component->GetExtensionIndex)      ||
161        (NULL == component->GetState)               ||
162        (NULL == component->ComponentTunnelRequest) ||
163        (NULL == component->UseBuffer)              ||
164        (NULL == component->AllocateBuffer)         ||
165        (NULL == component->FreeBuffer)             ||
166        (NULL == component->EmptyThisBuffer)        ||
167        (NULL == component->FillThisBuffer)         ||
168        (NULL == component->SetCallbacks)           ||
169        (NULL == component->ComponentDeInit)        ||
170        (NULL == component->UseEGLImage)            ||
171        (NULL == component->ComponentRoleEnum))
172        ret = OMX_ErrorInvalidComponent;
173    else
174        ret = OMX_ErrorNone;
175
176    return ret;
177}
178
179OMX_ERRORTYPE Exynos_OMX_ComponentLoad(EXYNOS_OMX_COMPONENT *exynos_component)
180{
181    OMX_ERRORTYPE      ret = OMX_ErrorNone;
182    OMX_HANDLETYPE     libHandle;
183    OMX_COMPONENTTYPE *pOMXComponent;
184
185    FunctionIn();
186
187    OMX_ERRORTYPE (*Exynos_OMX_ComponentInit)(OMX_HANDLETYPE hComponent, OMX_STRING componentName);
188
189    libHandle = Exynos_OSAL_dlopen((OMX_STRING)exynos_component->libName, RTLD_NOW);
190    if (!libHandle) {
191        ret = OMX_ErrorInvalidComponentName;
192        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInvalidComponentName, Line:%d", __LINE__);
193        goto EXIT;
194    }
195
196    Exynos_OMX_ComponentInit = Exynos_OSAL_dlsym(libHandle, "Exynos_OMX_ComponentInit");
197    if (!Exynos_OMX_ComponentInit) {
198        Exynos_OSAL_dlclose(libHandle);
199        ret = OMX_ErrorInvalidComponent;
200        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInvalidComponent, Line:%d", __LINE__);
201        goto EXIT;
202    }
203
204    pOMXComponent = (OMX_COMPONENTTYPE *)Exynos_OSAL_Malloc(sizeof(OMX_COMPONENTTYPE));
205    INIT_SET_SIZE_VERSION(pOMXComponent, OMX_COMPONENTTYPE);
206    ret = (*Exynos_OMX_ComponentInit)((OMX_HANDLETYPE)pOMXComponent, (OMX_STRING)exynos_component->componentName);
207    if (ret != OMX_ErrorNone) {
208        Exynos_OSAL_Free(pOMXComponent);
209        Exynos_OSAL_dlclose(libHandle);
210        ret = OMX_ErrorInvalidComponent;
211        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInvalidComponent, Line:%d", __LINE__);
212        goto EXIT;
213    } else {
214        if (Exynos_OMX_ComponentAPICheck(pOMXComponent) != OMX_ErrorNone) {
215            if (NULL != pOMXComponent->ComponentDeInit)
216                pOMXComponent->ComponentDeInit(pOMXComponent);
217            Exynos_OSAL_Free(pOMXComponent);
218            Exynos_OSAL_dlclose(libHandle);
219            ret = OMX_ErrorInvalidComponent;
220            Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInvalidComponent, Line:%d", __LINE__);
221            goto EXIT;
222        }
223        exynos_component->libHandle = libHandle;
224        exynos_component->pOMXComponent = pOMXComponent;
225        ret = OMX_ErrorNone;
226    }
227
228EXIT:
229    FunctionOut();
230
231    return ret;
232}
233
234OMX_ERRORTYPE Exynos_OMX_ComponentUnload(EXYNOS_OMX_COMPONENT *exynos_component)
235{
236    OMX_ERRORTYPE ret = OMX_ErrorNone;
237    OMX_COMPONENTTYPE *pOMXComponent = NULL;
238
239    FunctionIn();
240
241    if (!exynos_component) {
242        ret = OMX_ErrorBadParameter;
243        goto EXIT;
244    }
245
246    pOMXComponent = exynos_component->pOMXComponent;
247    if (pOMXComponent != NULL) {
248        pOMXComponent->ComponentDeInit(pOMXComponent);
249        Exynos_OSAL_Free(pOMXComponent);
250        exynos_component->pOMXComponent = NULL;
251    }
252
253    if (exynos_component->libHandle != NULL) {
254        Exynos_OSAL_dlclose(exynos_component->libHandle);
255        exynos_component->libHandle = NULL;
256    }
257
258EXIT:
259    FunctionOut();
260
261    return ret;
262}
263
264