1 /*
2  * wrs_core.cpp, Wind River OpenMax-IL Core
3  *
4  * Copyright (c) 2009-2010 Wind River Systems, Inc.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 
23 #include <pthread.h>
24 
25 #include <OMX_Core.h>
26 #include <OMX_Component.h>
27 
28 #include <list.h>
29 #include <cmodule.h>
30 #include <componentbase.h>
31 
32 //#define LOG_NDEBUG 0
33 
34 #define LOG_TAG "wrs-omxil-core"
35 #include <log.h>
36 
37 static unsigned int g_initialized = 0;
38 static unsigned int g_nr_instances = 0;
39 
40 static struct list *g_module_list = NULL;
41 static pthread_mutex_t g_module_lock = PTHREAD_MUTEX_INITIALIZER;
42 
construct_components(const char * config_file_name)43 static struct list *construct_components(const char *config_file_name)
44 {
45     FILE *config_file;
46     char library_name[OMX_MAX_STRINGNAME_SIZE];
47     char config_file_path[256];
48     struct list *head = NULL;
49 
50     strncpy(config_file_path, "/etc/", 256);
51     strncat(config_file_path, config_file_name, 256);
52     config_file = fopen(config_file_path, "r");
53     if (!config_file) {
54         strncpy(config_file_path, "./", 256);
55         strncat(config_file_path, config_file_name, 256);
56         config_file = fopen(config_file_path, "r");
57         if (!config_file) {
58             LOGE("not found file %s\n", config_file_name);
59             return NULL;
60         }
61     }
62 
63     while (fscanf(config_file, "%s", library_name) > 0) {
64         CModule *cmodule;
65         struct list *entry;
66         OMX_ERRORTYPE ret;
67 
68         library_name[OMX_MAX_STRINGNAME_SIZE-1] = '\0';
69 
70         /* skip libraries starting with # */
71         if (library_name[0] == '#')
72             continue;
73 
74         cmodule = new CModule(&library_name[0]);
75         if (!cmodule)
76             continue;
77 
78         LOGI("found component library %s\n", library_name);
79 
80         ret = cmodule->Load(MODULE_LAZY);
81         if (ret != OMX_ErrorNone)
82             goto delete_cmodule;
83 
84         ret = cmodule->QueryComponentNameAndRoles();
85         if (ret != OMX_ErrorNone)
86             goto unload_cmodule;
87 
88         entry = list_alloc(cmodule);
89         if (!entry)
90             goto unload_cmodule;
91         head = __list_add_tail(head, entry);
92 
93         cmodule->Unload();
94         LOGI("module %s:%s added to component list\n",
95              cmodule->GetLibraryName(), cmodule->GetComponentName());
96 
97         continue;
98 
99     unload_cmodule:
100         cmodule->Unload();
101     delete_cmodule:
102         delete cmodule;
103     }
104 
105     fclose(config_file);
106     return head;
107 }
108 
destruct_components(struct list * head)109 static struct list *destruct_components(struct list *head)
110 {
111     struct list *entry, *next;
112 
113     list_foreach_safe(head, entry, next) {
114         CModule *cmodule = static_cast<CModule *>(entry->data);
115 
116         head = __list_delete(head, entry);
117         delete cmodule;
118     }
119 
120     return head;
121 }
122 
OMX_Init(void)123 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Init(void)
124 {
125     LOGV("%s(): enter", __FUNCTION__);
126 
127     pthread_mutex_lock(&g_module_lock);
128     if (!g_initialized) {
129         g_module_list = construct_components("wrs_omxil_components.list");
130         if (!g_module_list) {
131             pthread_mutex_unlock(&g_module_lock);
132             LOGE("%s(): exit failure, construct_components failed",
133                  __FUNCTION__);
134             return OMX_ErrorInsufficientResources;
135         }
136 
137         g_initialized = 1;
138     }
139     pthread_mutex_unlock(&g_module_lock);
140 
141     LOGV("%s(): exit done", __FUNCTION__);
142     return OMX_ErrorNone;
143 }
144 
OMX_Deinit(void)145 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Deinit(void)
146 {
147     OMX_ERRORTYPE ret = OMX_ErrorNone;
148 
149     LOGV("%s(): enter", __FUNCTION__);
150 
151     pthread_mutex_lock(&g_module_lock);
152     if (!g_nr_instances)
153         g_module_list = destruct_components(g_module_list);
154     else
155         ret = OMX_ErrorUndefined;
156     pthread_mutex_unlock(&g_module_lock);
157 
158     g_initialized = 0;
159 
160     LOGV("%s(): exit done (ret : 0x%08x)", __FUNCTION__, ret);
161     return ret;
162 }
163 
OMX_ComponentNameEnum(OMX_OUT OMX_STRING cComponentName,OMX_IN OMX_U32 nNameLength,OMX_IN OMX_U32 nIndex)164 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_ComponentNameEnum(
165     OMX_OUT OMX_STRING cComponentName,
166     OMX_IN OMX_U32 nNameLength,
167     OMX_IN OMX_U32 nIndex)
168 {
169     CModule *cmodule;
170     struct list *entry;
171     OMX_STRING cname;
172 
173     pthread_mutex_lock(&g_module_lock);
174     entry = __list_entry(g_module_list, nIndex);
175     if (!entry) {
176         pthread_mutex_unlock(&g_module_lock);
177         return OMX_ErrorNoMore;
178     }
179     pthread_mutex_unlock(&g_module_lock);
180 
181     cmodule = static_cast<CModule *>(entry->data);
182     cname = cmodule->GetComponentName();
183 
184     strncpy(cComponentName, cname, nNameLength);
185 
186     LOGV("%s(): found %u th component %s", __FUNCTION__, nIndex, cname);
187     return OMX_ErrorNone;
188 }
189 
OMX_GetHandle(OMX_OUT OMX_HANDLETYPE * pHandle,OMX_IN OMX_STRING cComponentName,OMX_IN OMX_PTR pAppData,OMX_IN OMX_CALLBACKTYPE * pCallBacks)190 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_GetHandle(
191     OMX_OUT OMX_HANDLETYPE* pHandle,
192     OMX_IN OMX_STRING cComponentName,
193     OMX_IN OMX_PTR pAppData,
194     OMX_IN OMX_CALLBACKTYPE *pCallBacks)
195 {
196     struct list *entry;
197     OMX_ERRORTYPE ret;
198 
199     LOGV("%s(): enter, try to get %s", __FUNCTION__, cComponentName);
200 
201     pthread_mutex_lock(&g_module_lock);
202     list_foreach(g_module_list, entry) {
203         CModule *cmodule;
204         OMX_STRING cname;
205 
206         cmodule = static_cast<CModule *>(entry->data);
207 
208         cname = cmodule->GetComponentName();
209         if (!strcmp(cComponentName, cname)) {
210             ComponentBase *cbase = NULL;
211 
212             ret = cmodule->Load(MODULE_NOW);
213             if (ret != OMX_ErrorNone) {
214                 LOGE("%s(): exit failure, cmodule->Load failed\n",
215                      __FUNCTION__);
216                 goto unlock_list;
217             }
218 
219             ret = cmodule->InstantiateComponent(&cbase);
220             if (ret != OMX_ErrorNone){
221                 LOGE("%s(): exit failure, cmodule->Instantiate failed\n",
222                      __FUNCTION__);
223                 goto unload_cmodule;
224             }
225 
226             ret = cbase->GetHandle(pHandle, pAppData, pCallBacks);
227             if (ret != OMX_ErrorNone) {
228                 LOGE("%s(): exit failure, cbase->GetHandle failed\n",
229                      __FUNCTION__);
230                 goto delete_cbase;
231             }
232 
233             cbase->SetCModule(cmodule);
234 
235             g_nr_instances++;
236             pthread_mutex_unlock(&g_module_lock);
237 
238             LOGI("get handle of component %s successfully", cComponentName);
239             LOGV("%s(): exit done\n", __FUNCTION__);
240             return OMX_ErrorNone;
241 
242         delete_cbase:
243             delete cbase;
244         unload_cmodule:
245             cmodule->Unload();
246         unlock_list:
247             pthread_mutex_unlock(&g_module_lock);
248 
249             LOGE("%s(): exit failure, (ret : 0x%08x)\n", __FUNCTION__, ret);
250             return ret;
251         }
252     }
253     pthread_mutex_unlock(&g_module_lock);
254 
255     LOGE("%s(): exit failure, %s not found", __FUNCTION__, cComponentName);
256     return OMX_ErrorInvalidComponent;
257 }
258 
OMX_FreeHandle(OMX_IN OMX_HANDLETYPE hComponent)259 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_FreeHandle(
260     OMX_IN OMX_HANDLETYPE hComponent)
261 {
262     ComponentBase *cbase;
263     CModule *cmodule;
264     OMX_ERRORTYPE ret;
265     char cname[OMX_MAX_STRINGNAME_SIZE];
266 
267     if (!hComponent)
268         return OMX_ErrorBadParameter;
269 
270     cbase = static_cast<ComponentBase *>
271         (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
272     if (!cbase) {
273         LOGE("%s(): exit failure, cannot find cbase pointer\n",
274              __FUNCTION__);
275         return OMX_ErrorBadParameter;
276     }
277     strcpy(&cname[0], cbase->GetName());
278 
279     LOGV("%s(): enter, try to free %s", __FUNCTION__, cbase->GetName());
280 
281 
282     ret = cbase->FreeHandle(hComponent);
283     if (ret != OMX_ErrorNone) {
284         LOGE("%s(): exit failure, cbase->FreeHandle() failed (ret = 0x%08x)\n",
285              __FUNCTION__, ret);
286         return ret;
287     }
288 
289     pthread_mutex_lock(&g_module_lock);
290     g_nr_instances--;
291     pthread_mutex_unlock(&g_module_lock);
292 
293     cmodule = cbase->GetCModule();
294     if (!cmodule)
295         LOGE("fatal error, %s does not have cmodule\n", cbase->GetName());
296 
297     delete cbase;
298 
299     if (cmodule)
300         cmodule->Unload();
301 
302     LOGI("free handle of component %s successfully", cname);
303     LOGV("%s(): exit done", __FUNCTION__);
304     return OMX_ErrorNone;
305 }
306 
OMX_GetComponentsOfRole(OMX_IN OMX_STRING role,OMX_INOUT OMX_U32 * pNumComps,OMX_INOUT OMX_U8 ** compNames)307 OMX_API OMX_ERRORTYPE OMX_GetComponentsOfRole (
308     OMX_IN OMX_STRING role,
309     OMX_INOUT OMX_U32 *pNumComps,
310     OMX_INOUT OMX_U8  **compNames)
311 {
312     struct list *entry;
313     OMX_U32 nr_comps = 0, copied_nr_comps = 0;
314 
315     pthread_mutex_lock(&g_module_lock);
316     list_foreach(g_module_list, entry) {
317         CModule *cmodule;
318         OMX_STRING cname;
319         bool having_role;
320 
321         cmodule = static_cast<CModule *>(entry->data);
322 
323         having_role = cmodule->QueryHavingThisRole(role);
324         if (having_role) {
325             if (compNames && compNames[nr_comps]) {
326                 cname = cmodule->GetComponentName();
327                 strncpy((OMX_STRING)&compNames[nr_comps][0], cname,
328                         OMX_MAX_STRINGNAME_SIZE);
329                 copied_nr_comps++;
330                 LOGV("%s(): component %s has %s role", __FUNCTION__,
331                      cname, role);
332             }
333             nr_comps++;
334         }
335     }
336     pthread_mutex_unlock(&g_module_lock);
337 
338     if (!copied_nr_comps)
339         *pNumComps = nr_comps;
340     else {
341         if (copied_nr_comps != *pNumComps)
342             return OMX_ErrorBadParameter;
343     }
344 
345     return OMX_ErrorNone;
346 }
347 
OMX_GetRolesOfComponent(OMX_IN OMX_STRING compName,OMX_INOUT OMX_U32 * pNumRoles,OMX_OUT OMX_U8 ** roles)348 OMX_API OMX_ERRORTYPE OMX_GetRolesOfComponent (
349     OMX_IN OMX_STRING compName,
350     OMX_INOUT OMX_U32 *pNumRoles,
351     OMX_OUT OMX_U8 **roles)
352 {
353     struct list *entry;
354 
355     pthread_mutex_lock(&g_module_lock);
356     list_foreach(g_module_list, entry) {
357         CModule *cmodule;
358         OMX_STRING cname;
359 
360         cmodule = static_cast<CModule *>(entry->data);
361 
362         cname = cmodule->GetComponentName();
363         if (!strcmp(compName, cname)) {
364             pthread_mutex_unlock(&g_module_lock);
365 #if LOG_NDEBUG
366             return cmodule->GetComponentRoles(pNumRoles, roles);
367 #else
368             OMX_ERRORTYPE ret;
369             ret = cmodule->GetComponentRoles(pNumRoles, roles);
370             if (ret != OMX_ErrorNone) {
371                 OMX_U32 i;
372 
373                 for (i = 0; i < *pNumRoles; i++) {
374                     LOGV("%s(): component %s has %s role", __FUNCTION__,
375                          compName, &roles[i][0]);
376                 }
377             }
378             return ret;
379 #endif
380         }
381     }
382     pthread_mutex_unlock(&g_module_lock);
383 
384     return OMX_ErrorInvalidComponent;
385 }
386