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