1 /*Copyright (c) 2012-2014, 2016, The Linux Foundation. All rights reserved.
2 
3 Redistribution and use in source and binary forms, with or without
4 modification, are permitted provided that the following conditions are
5 met:
6     * Redistributions of source code must retain the above copyright
7       notice, this list of conditions and the following disclaimer.
8     * Redistributions in binary form must reproduce the above
9       copyright notice, this list of conditions and the following
10       disclaimer in the documentation and/or other materials provided
11       with the distribution.
12     * Neither the name of The Linux Foundation nor the names of its
13       contributors may be used to endorse or promote products derived
14       from this software without specific prior written permission.
15 
16 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/
27 
28 #define LOG_NDEBUG 0
29 #define LOG_NIDEBUG 0
30 #define LOG_TAG "qomx_image_core"
31 
32 // System dependencies
33 #include <dlfcn.h>
34 #include <malloc.h>
35 #include <string.h>
36 #include <utils/Log.h>
37 
38 // OpenMAX dependencies
39 #include "qomx_core.h"
40 
41 #define BUFF_SIZE 255
42 
43 static omx_core_t *g_omxcore;
44 static pthread_mutex_t g_omxcore_lock = PTHREAD_MUTEX_INITIALIZER;
45 static int g_omxcore_cnt = 0;
46 
47 //Map the library name with the component name
48 static const comp_info_t g_comp_info[] =
49 {
50   { "OMX.qcom.image.jpeg.encoder", "libqomx_jpegenc.so" },
51   { "OMX.qcom.image.jpeg.decoder", "libqomx_jpegdec.so" },
52   { "OMX.qcom.image.jpeg.encoder_pipeline", "libqomx_jpegenc_pipe.so" }
53 };
54 
55 static int get_idx_from_handle(OMX_IN OMX_HANDLETYPE *ahComp, int *acompIndex,
56   int *ainstanceIndex);
57 
58 /*==============================================================================
59 * Function : OMX_Init
60 * Parameters: None
61 * Description: This is the first call that is made to the OMX Core
62 * and initializes the OMX IL core
63 ==============================================================================*/
OMX_Init()64 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Init()
65 {
66   OMX_ERRORTYPE rc = OMX_ErrorNone;
67   int i = 0;
68   int comp_cnt = sizeof(g_comp_info)/sizeof(g_comp_info[0]);
69 
70   pthread_mutex_lock(&g_omxcore_lock);
71 
72   /* check if core is created */
73   if (g_omxcore) {
74     g_omxcore_cnt++;
75     pthread_mutex_unlock(&g_omxcore_lock);
76     return rc;
77   }
78 
79   if (comp_cnt > OMX_COMP_MAX_NUM) {
80     ALOGE("%s:%d] cannot exceed max number of components",
81       __func__, __LINE__);
82     pthread_mutex_unlock(&g_omxcore_lock);
83     return OMX_ErrorUndefined;
84   }
85   /* create new global object */
86   g_omxcore = malloc(sizeof(omx_core_t));
87   if (g_omxcore) {
88     memset(g_omxcore, 0x0, sizeof(omx_core_t));
89 
90     /* populate the library name and component name */
91     for (i = 0; i < comp_cnt; i++) {
92       g_omxcore->component[i].comp_name = g_comp_info[i].comp_name;
93       g_omxcore->component[i].lib_name = g_comp_info[i].lib_name;
94     }
95     g_omxcore->comp_cnt = comp_cnt;
96     g_omxcore_cnt++;
97   } else {
98     rc = OMX_ErrorInsufficientResources;
99   }
100   pthread_mutex_unlock(&g_omxcore_lock);
101   ALOGI("%s:%d] Complete %d", __func__, __LINE__, comp_cnt);
102   return rc;
103 }
104 
105 /*==============================================================================
106 * Function : OMX_Deinit
107 * Parameters: None
108 * Return Value : OMX_ERRORTYPE
109 * Description: Deinit all the OMX components
110 ==============================================================================*/
OMX_Deinit()111 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Deinit()
112 {
113   pthread_mutex_lock(&g_omxcore_lock);
114 
115   if (g_omxcore_cnt == 1) {
116     if (g_omxcore) {
117       free(g_omxcore);
118       g_omxcore = NULL;
119     }
120   }
121   if (g_omxcore_cnt) {
122     g_omxcore_cnt--;
123   }
124 
125   ALOGI("%s:%d] Complete", __func__, __LINE__);
126   pthread_mutex_unlock(&g_omxcore_lock);
127   return OMX_ErrorNone;
128 }
129 
130 /*==============================================================================
131 * Function : get_comp_from_list
132 * Parameters: componentName
133 * Return Value : component_index
134 * Description: If the componnt is already present in the list, return the
135 * component index. If not return the next index to create the component.
136 ==============================================================================*/
get_comp_from_list(char * comp_name)137 static int get_comp_from_list(char *comp_name)
138 {
139   int index = -1, i = 0;
140 
141   if (NULL == comp_name)
142     return -1;
143 
144   for (i = 0; i < g_omxcore->comp_cnt; i++) {
145     if (!strcmp(g_omxcore->component[i].comp_name, comp_name)) {
146       index = i;
147       break;
148     }
149   }
150   return index;
151 }
152 
153 /*==============================================================================
154 * Function : get_free_inst_idx
155 * Parameters: p_comp
156 * Return Value : The next instance index if available
157 * Description: Get the next available index for to store the new instance of the
158 *            component being created.
159 *============================================================================*/
get_free_inst_idx(omx_core_component_t * p_comp)160 static int get_free_inst_idx(omx_core_component_t *p_comp)
161 {
162   int idx = -1, i = 0;
163 
164   for (i = 0; i < OMX_COMP_MAX_INSTANCES; i++) {
165     if (NULL == p_comp->handle[i]) {
166       idx = i;
167       break;
168     }
169   }
170   return idx;
171 }
172 
173 /*==============================================================================
174 * Function : OMX_GetHandle
175 * Parameters: handle, componentName, appData, callbacks
176 * Return Value : OMX_ERRORTYPE
177 * Description: Construct and load the requested omx library
178 ==============================================================================*/
OMX_GetHandle(OMX_OUT OMX_HANDLETYPE * handle,OMX_IN OMX_STRING componentName,OMX_IN OMX_PTR appData,OMX_IN OMX_CALLBACKTYPE * callBacks)179 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_GetHandle(
180   OMX_OUT OMX_HANDLETYPE* handle,
181   OMX_IN OMX_STRING componentName,
182   OMX_IN OMX_PTR appData,
183   OMX_IN OMX_CALLBACKTYPE* callBacks)
184 {
185   OMX_ERRORTYPE rc = OMX_ErrorNone;
186   int comp_idx = 0, inst_idx = 0;
187   char libName[BUFF_SIZE] = {0};
188   void *p_obj = NULL;
189   OMX_COMPONENTTYPE *p_comp = NULL;
190   omx_core_component_t *p_core_comp = NULL;
191   OMX_BOOL close_handle = OMX_FALSE;
192 
193   if (NULL == handle) {
194     ALOGE("%s:%d] Error invalid input ", __func__, __LINE__);
195     return OMX_ErrorBadParameter;
196   }
197 
198   pthread_mutex_lock(&g_omxcore_lock);
199 
200   comp_idx = get_comp_from_list(componentName);
201   if (comp_idx < 0) {
202     ALOGE("%s:%d] Cannot find the component", __func__, __LINE__);
203     pthread_mutex_unlock(&g_omxcore_lock);
204     return OMX_ErrorInvalidComponent;
205   }
206   p_core_comp = &g_omxcore->component[comp_idx];
207 
208   *handle = NULL;
209 
210   //If component already present get the instance index
211   inst_idx = get_free_inst_idx(p_core_comp);
212   if (inst_idx < 0) {
213     ALOGE("%s:%d] Cannot alloc new instance", __func__, __LINE__);
214     rc = OMX_ErrorInvalidComponent;
215     goto error;
216   }
217 
218   if (FALSE == p_core_comp->open) {
219     /* load the library */
220     p_core_comp->lib_handle = dlopen(p_core_comp->lib_name, RTLD_NOW);
221     if (NULL == p_core_comp->lib_handle) {
222       ALOGE("%s:%d] Cannot load the library", __func__, __LINE__);
223       rc = OMX_ErrorInvalidComponent;
224       goto error;
225     }
226 
227     p_core_comp->open = TRUE;
228     /* Init the component and get component functions */
229     p_core_comp->create_comp_func = dlsym(p_core_comp->lib_handle,
230       "create_component_fns");
231     p_core_comp->get_instance = dlsym(p_core_comp->lib_handle, "getInstance");
232 
233     close_handle = OMX_TRUE;
234     if (!p_core_comp->create_comp_func || !p_core_comp->get_instance) {
235       ALOGE("%s:%d] Cannot maps the symbols", __func__, __LINE__);
236       rc = OMX_ErrorInvalidComponent;
237       goto error;
238     }
239   }
240 
241   /* Call the function from the address to create the obj */
242   p_obj = (*p_core_comp->get_instance)();
243   ALOGI("%s:%d] get instance pts is %p", __func__, __LINE__, p_obj);
244   if (NULL == p_obj) {
245     ALOGE("%s:%d] Error cannot create object", __func__, __LINE__);
246     rc = OMX_ErrorInvalidComponent;
247     goto error;
248   }
249 
250   /* Call the function from the address to get the func ptrs */
251   p_comp = (*p_core_comp->create_comp_func)(p_obj);
252   if (NULL == p_comp) {
253     ALOGE("%s:%d] Error cannot create component", __func__, __LINE__);
254     rc = OMX_ErrorInvalidComponent;
255     goto error;
256   }
257 
258   *handle = p_core_comp->handle[inst_idx] = (OMX_HANDLETYPE)p_comp;
259 
260   ALOGD("%s:%d] handle = %p Instanceindex = %d,"
261     "comp_idx %d g_ptr %p", __func__, __LINE__,
262     p_core_comp->handle[inst_idx], inst_idx,
263     comp_idx, g_omxcore);
264 
265   p_comp->SetCallbacks(p_comp, callBacks, appData);
266   pthread_mutex_unlock(&g_omxcore_lock);
267   ALOGI("%s:%d] Success", __func__, __LINE__);
268   return OMX_ErrorNone;
269 
270 error:
271 
272   if (OMX_TRUE == close_handle) {
273     dlclose(p_core_comp->lib_handle);
274     p_core_comp->lib_handle = NULL;
275   }
276   pthread_mutex_unlock(&g_omxcore_lock);
277   ALOGE("%s:%d] Error %d", __func__, __LINE__, rc);
278   return rc;
279 }
280 
281 /*==============================================================================
282 * Function : getIndexFromComponent
283 * Parameters: handle,
284 * Return Value : Component present - true or false, Instance Index, Component
285 * Index
286 * Description: Check if the handle is present in the list and get the component
287 * index and instance index for the component handle.
288 ==============================================================================*/
get_idx_from_handle(OMX_IN OMX_HANDLETYPE * ahComp,int * aCompIdx,int * aInstIdx)289 static int get_idx_from_handle(OMX_IN OMX_HANDLETYPE *ahComp, int *aCompIdx,
290   int *aInstIdx)
291 {
292   int i = 0, j = 0;
293   for (i = 0; i < g_omxcore->comp_cnt; i++) {
294     for (j = 0; j < OMX_COMP_MAX_INSTANCES; j++) {
295       if ((OMX_COMPONENTTYPE *)g_omxcore->component[i].handle[j] ==
296         (OMX_COMPONENTTYPE *)ahComp) {
297         ALOGD("%s:%d] comp_idx %d inst_idx %d", __func__, __LINE__, i, j);
298         *aCompIdx = i;
299         *aInstIdx = j;
300         return TRUE;
301       }
302     }
303   }
304   return FALSE;
305 }
306 
307 /*==============================================================================
308 * Function : is_comp_active
309 * Parameters: p_core_comp
310 * Return Value : int
311 * Description: Check if the component has any active instances
312 ==============================================================================*/
is_comp_active(omx_core_component_t * p_core_comp)313 static uint8_t is_comp_active(omx_core_component_t *p_core_comp)
314 {
315   uint8_t i = 0;
316   for (i = 0; i < OMX_COMP_MAX_INSTANCES; i++) {
317     if (NULL != p_core_comp->handle[i]) {
318       return TRUE;
319     }
320   }
321   return FALSE;
322 }
323 
324 /*==============================================================================
325 * Function : OMX_FreeHandle
326 * Parameters: hComp
327 * Return Value : OMX_ERRORTYPE
328 * Description: Deinit the omx component and remove it from the global list
329 ==============================================================================*/
OMX_FreeHandle(OMX_IN OMX_HANDLETYPE hComp)330 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_FreeHandle(
331   OMX_IN OMX_HANDLETYPE hComp)
332 {
333   OMX_ERRORTYPE rc = OMX_ErrorNone;
334   int comp_idx, inst_idx;
335   OMX_COMPONENTTYPE *p_comp = NULL;
336   omx_core_component_t *p_core_comp = NULL;
337 
338   ALOGV("%s:%d] ", __func__, __LINE__);
339   if (hComp == NULL) {
340     return OMX_ErrorBadParameter;
341   }
342 
343   pthread_mutex_lock(&g_omxcore_lock);
344 
345   p_comp = (OMX_COMPONENTTYPE *)hComp;
346   if (FALSE == get_idx_from_handle(hComp, &comp_idx, &inst_idx)) {
347     ALOGE("%s:%d] Error invalid component", __func__, __LINE__);
348     pthread_mutex_unlock(&g_omxcore_lock);
349     return OMX_ErrorInvalidComponent;
350   }
351 
352 
353   //Deinit the component;
354   rc = p_comp->ComponentDeInit(hComp);
355   if (rc != OMX_ErrorNone) {
356     /* Remove the handle from the comp structure */
357     ALOGE("%s:%d] Error comp deinit failed", __func__, __LINE__);
358     pthread_mutex_unlock(&g_omxcore_lock);
359     return OMX_ErrorInvalidComponent;
360   }
361   p_core_comp = &g_omxcore->component[comp_idx];
362   p_core_comp->handle[inst_idx] = NULL;
363   if (!is_comp_active(p_core_comp)) {
364     rc = dlclose(p_core_comp->lib_handle);
365     p_core_comp->lib_handle = NULL;
366     p_core_comp->get_instance = NULL;
367     p_core_comp->create_comp_func = NULL;
368     p_core_comp->open = FALSE;
369   } else {
370     ALOGI("%s:%d] Error Component is still Active", __func__, __LINE__);
371   }
372   pthread_mutex_unlock(&g_omxcore_lock);
373   ALOGV("%s:%d] Success", __func__, __LINE__);
374   return rc;
375 }
376