Home | History | Annotate | Download | only in qomx_core
      1 /*Copyright (c) 2012, 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 #include <utils/Log.h>
     32 
     33 #include "qomx_core.h"
     34 
     35 #define BUFF_SIZE 255
     36 
     37 static omx_core_t *g_omxcore;
     38 static pthread_mutex_t g_omxcore_lock = PTHREAD_MUTEX_INITIALIZER;
     39 static int g_omxcore_cnt = 0;
     40 
     41 //Map the library name with the component name
     42 static const comp_info_t g_comp_info[] =
     43 {
     44   { "OMX.qcom.image.jpeg.encoder", "libqomx_jpegenc.so" },
     45   { "OMX.qcom.image.jpeg.decoder", "libqomx_jpegdec.so" }
     46 };
     47 
     48 static int get_idx_from_handle(OMX_IN OMX_HANDLETYPE *ahComp, int *acompIndex,
     49   int *ainstanceIndex);
     50 
     51 /*==============================================================================
     52 * Function : OMX_Init
     53 * Parameters: None
     54 * Description: This is the first call that is made to the OMX Core
     55 * and initializes the OMX IL core
     56 ==============================================================================*/
     57 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Init()
     58 {
     59   OMX_ERRORTYPE rc = OMX_ErrorNone;
     60   int i = 0;
     61   int comp_cnt = sizeof(g_comp_info)/sizeof(g_comp_info[0]);
     62 
     63   pthread_mutex_lock(&g_omxcore_lock);
     64 
     65   /* check if core is created */
     66   if (g_omxcore) {
     67     g_omxcore_cnt++;
     68     pthread_mutex_unlock(&g_omxcore_lock);
     69     return rc;
     70   }
     71 
     72   if (comp_cnt > OMX_COMP_MAX_NUM) {
     73     ALOGE("%s:%d] cannot exceed max number of components",
     74       __func__, __LINE__);
     75     pthread_mutex_unlock(&g_omxcore_lock);
     76     return OMX_ErrorUndefined;
     77   }
     78   /* create new global object */
     79   g_omxcore = malloc(sizeof(omx_core_t));
     80   if (g_omxcore) {
     81     memset(g_omxcore, 0x0, sizeof(omx_core_t));
     82 
     83     /* populate the library name and component name */
     84     for (i = 0; i < comp_cnt; i++) {
     85       g_omxcore->component[i].comp_name = g_comp_info[i].comp_name;
     86       g_omxcore->component[i].lib_name = g_comp_info[i].lib_name;
     87     }
     88     g_omxcore->comp_cnt = comp_cnt;
     89     g_omxcore_cnt++;
     90   } else {
     91     rc = OMX_ErrorInsufficientResources;
     92   }
     93   pthread_mutex_unlock(&g_omxcore_lock);
     94   ALOGI("%s:%d] Complete %d", __func__, __LINE__, comp_cnt);
     95   return rc;
     96 }
     97 
     98 /*==============================================================================
     99 * Function : OMX_Deinit
    100 * Parameters: None
    101 * Return Value : OMX_ERRORTYPE
    102 * Description: Deinit all the OMX components
    103 ==============================================================================*/
    104 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Deinit()
    105 {
    106   pthread_mutex_lock(&g_omxcore_lock);
    107 
    108   if (g_omxcore_cnt == 1) {
    109     if (g_omxcore) {
    110       free(g_omxcore);
    111       g_omxcore = NULL;
    112     }
    113   }
    114   if (g_omxcore_cnt) {
    115     g_omxcore_cnt--;
    116   }
    117 
    118   ALOGI("%s:%d] Complete", __func__, __LINE__);
    119   pthread_mutex_unlock(&g_omxcore_lock);
    120   return OMX_ErrorNone;
    121 }
    122 
    123 /*==============================================================================
    124 * Function : get_comp_from_list
    125 * Parameters: componentName
    126 * Return Value : component_index
    127 * Description: If the componnt is already present in the list, return the
    128 * component index. If not return the next index to create the component.
    129 ==============================================================================*/
    130 static int get_comp_from_list(char *comp_name)
    131 {
    132   int index = -1, i = 0;
    133 
    134   if (NULL == comp_name)
    135     return -1;
    136 
    137   for (i = 0; i < g_omxcore->comp_cnt; i++) {
    138     if (!strcmp(g_omxcore->component[i].comp_name, comp_name)) {
    139       index = i;
    140       break;
    141     }
    142   }
    143   return index;
    144 }
    145 
    146 /*==============================================================================
    147 * Function : get_free_inst_idx
    148 * Parameters: p_comp
    149 * Return Value : The next instance index if available
    150 * Description: Get the next available index for to store the new instance of the
    151 *            component being created.
    152 *============================================================================*/
    153 static int get_free_inst_idx(omx_core_component_t *p_comp)
    154 {
    155   int idx = -1, i = 0;
    156 
    157   for (i = 0; i < OMX_COMP_MAX_INSTANCES; i++) {
    158     if (NULL == p_comp->handle[i]) {
    159       idx = i;
    160       break;
    161     }
    162   }
    163   return idx;
    164 }
    165 
    166 /*==============================================================================
    167 * Function : OMX_GetHandle
    168 * Parameters: handle, componentName, appData, callbacks
    169 * Return Value : OMX_ERRORTYPE
    170 * Description: Construct and load the requested omx library
    171 ==============================================================================*/
    172 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_GetHandle(
    173   OMX_OUT OMX_HANDLETYPE* handle,
    174   OMX_IN OMX_STRING componentName,
    175   OMX_IN OMX_PTR appData,
    176   OMX_IN OMX_CALLBACKTYPE* callBacks)
    177 {
    178   OMX_ERRORTYPE rc = OMX_ErrorNone;
    179   int comp_idx = 0, inst_idx = 0;
    180   char libName[BUFF_SIZE] = {0};
    181   void *p_obj = NULL;
    182   OMX_COMPONENTTYPE *p_comp = NULL;
    183   omx_core_component_t *p_core_comp = NULL;
    184   OMX_BOOL close_handle = OMX_FALSE;
    185 
    186   if (NULL == handle) {
    187     ALOGE("%s:%d] Error invalid input ", __func__, __LINE__);
    188     return OMX_ErrorBadParameter;
    189   }
    190 
    191   pthread_mutex_lock(&g_omxcore_lock);
    192 
    193   comp_idx = get_comp_from_list(componentName);
    194   if (comp_idx < 0) {
    195     ALOGE("%s:%d] Cannot find the component", __func__, __LINE__);
    196     pthread_mutex_unlock(&g_omxcore_lock);
    197     return OMX_ErrorInvalidComponent;
    198   }
    199   p_core_comp = &g_omxcore->component[comp_idx];
    200 
    201   *handle = NULL;
    202 
    203   //If component already present get the instance index
    204   inst_idx = get_free_inst_idx(p_core_comp);
    205   if (inst_idx < 0) {
    206     ALOGE("%s:%d] Cannot alloc new instance", __func__, __LINE__);
    207     rc = OMX_ErrorInvalidComponent;
    208     goto error;
    209   }
    210 
    211   if (FALSE == p_core_comp->open) {
    212     /* load the library */
    213     p_core_comp->lib_handle = dlopen(p_core_comp->lib_name, RTLD_NOW);
    214     if (NULL == p_core_comp->lib_handle) {
    215       ALOGE("%s:%d] Cannot load the library", __func__, __LINE__);
    216       rc = OMX_ErrorInvalidComponent;
    217       goto error;
    218     }
    219 
    220     p_core_comp->open = TRUE;
    221     /* Init the component and get component functions */
    222     p_core_comp->create_comp_func = dlsym(p_core_comp->lib_handle,
    223       "create_component_fns");
    224     p_core_comp->get_instance = dlsym(p_core_comp->lib_handle, "getInstance");
    225 
    226     close_handle = OMX_TRUE;
    227     if (!p_core_comp->create_comp_func || !p_core_comp->get_instance) {
    228       ALOGE("%s:%d] Cannot maps the symbols", __func__, __LINE__);
    229       rc = OMX_ErrorInvalidComponent;
    230       goto error;
    231     }
    232   }
    233 
    234   /* Call the function from the address to create the obj */
    235   p_obj = (*p_core_comp->get_instance)();
    236   ALOGI("%s:%d] get instance pts is %p", __func__, __LINE__, p_obj);
    237   if (NULL == p_obj) {
    238     ALOGE("%s:%d] Error cannot create object", __func__, __LINE__);
    239     rc = OMX_ErrorInvalidComponent;
    240     goto error;
    241   }
    242 
    243   /* Call the function from the address to get the func ptrs */
    244   p_comp = (*p_core_comp->create_comp_func)(p_obj);
    245   if (NULL == p_comp) {
    246     ALOGE("%s:%d] Error cannot create component", __func__, __LINE__);
    247     rc = OMX_ErrorInvalidComponent;
    248     goto error;
    249   }
    250 
    251   *handle = p_core_comp->handle[inst_idx] = (OMX_HANDLETYPE)p_comp;
    252 
    253   ALOGD("%s:%d] handle = %p Instanceindex = %d,"
    254     "comp_idx %d g_ptr %p", __func__, __LINE__,
    255     p_core_comp->handle[inst_idx], inst_idx,
    256     comp_idx, g_omxcore);
    257 
    258   p_comp->SetCallbacks(p_comp, callBacks, appData);
    259   pthread_mutex_unlock(&g_omxcore_lock);
    260   ALOGI("%s:%d] Success", __func__, __LINE__);
    261   return OMX_ErrorNone;
    262 
    263 error:
    264 
    265   if (OMX_TRUE == close_handle) {
    266     dlclose(p_core_comp->lib_handle);
    267     p_core_comp->lib_handle = NULL;
    268   }
    269   pthread_mutex_unlock(&g_omxcore_lock);
    270   ALOGE("%s:%d] Error %d", __func__, __LINE__, rc);
    271   return rc;
    272 }
    273 
    274 /*==============================================================================
    275 * Function : getIndexFromComponent
    276 * Parameters: handle,
    277 * Return Value : Component present - true or false, Instance Index, Component
    278 * Index
    279 * Description: Check if the handle is present in the list and get the component
    280 * index and instance index for the component handle.
    281 ==============================================================================*/
    282 static int get_idx_from_handle(OMX_IN OMX_HANDLETYPE *ahComp, int *aCompIdx,
    283   int *aInstIdx)
    284 {
    285   int i = 0, j = 0;
    286   for (i = 0; i < g_omxcore->comp_cnt; i++) {
    287     for (j = 0; j < OMX_COMP_MAX_INSTANCES; j++) {
    288       if ((OMX_COMPONENTTYPE *)g_omxcore->component[i].handle[j] ==
    289         (OMX_COMPONENTTYPE *)ahComp) {
    290         ALOGD("%s:%d] comp_idx %d inst_idx %d", __func__, __LINE__, i, j);
    291         *aCompIdx = i;
    292         *aInstIdx = j;
    293         return TRUE;
    294       }
    295     }
    296   }
    297   return FALSE;
    298 }
    299 
    300 /*==============================================================================
    301 * Function : is_comp_active
    302 * Parameters: p_core_comp
    303 * Return Value : int
    304 * Description: Check if the component has any active instances
    305 ==============================================================================*/
    306 static uint8_t is_comp_active(omx_core_component_t *p_core_comp)
    307 {
    308   uint8_t i = 0;
    309   for (i = 0; i < OMX_COMP_MAX_INSTANCES; i++) {
    310     if (NULL != p_core_comp->handle[i]) {
    311       return TRUE;
    312     }
    313   }
    314   return FALSE;
    315 }
    316 
    317 /*==============================================================================
    318 * Function : OMX_FreeHandle
    319 * Parameters: hComp
    320 * Return Value : OMX_ERRORTYPE
    321 * Description: Deinit the omx component and remove it from the global list
    322 ==============================================================================*/
    323 OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_FreeHandle(
    324   OMX_IN OMX_HANDLETYPE hComp)
    325 {
    326   OMX_ERRORTYPE rc = OMX_ErrorNone;
    327   int comp_idx, inst_idx;
    328   OMX_COMPONENTTYPE *p_comp = NULL;
    329   omx_core_component_t *p_core_comp = NULL;
    330 
    331   ALOGV("%s:%d] ", __func__, __LINE__);
    332   if (hComp == NULL) {
    333     return OMX_ErrorBadParameter;
    334   }
    335 
    336   pthread_mutex_lock(&g_omxcore_lock);
    337 
    338   p_comp = (OMX_COMPONENTTYPE *)hComp;
    339   if (FALSE == get_idx_from_handle(hComp, &comp_idx, &inst_idx)) {
    340     ALOGE("%s:%d] Error invalid component", __func__, __LINE__);
    341     pthread_mutex_unlock(&g_omxcore_lock);
    342     return OMX_ErrorInvalidComponent;
    343   }
    344 
    345 
    346   //Deinit the component;
    347   rc = p_comp->ComponentDeInit(hComp);
    348   if (rc != OMX_ErrorNone) {
    349     /* Remove the handle from the comp structure */
    350     ALOGE("%s:%d] Error comp deinit failed", __func__, __LINE__);
    351     pthread_mutex_unlock(&g_omxcore_lock);
    352     return OMX_ErrorInvalidComponent;
    353   }
    354   p_core_comp = &g_omxcore->component[comp_idx];
    355   p_core_comp->handle[inst_idx] = NULL;
    356   if (!is_comp_active(p_core_comp)) {
    357     rc = dlclose(p_core_comp->lib_handle);
    358     p_core_comp->lib_handle = NULL;
    359     p_core_comp->get_instance = NULL;
    360     p_core_comp->create_comp_func = NULL;
    361     p_core_comp->open = FALSE;
    362   } else {
    363     ALOGI("%s:%d] Error Component is still Active", __func__, __LINE__);
    364   }
    365   pthread_mutex_unlock(&g_omxcore_lock);
    366   ALOGV("%s:%d] Success", __func__, __LINE__);
    367   return rc;
    368 }
    369