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