Home | History | Annotate | Download | only in qomx_core
      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 <log/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 ==============================================================================*/
     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 ==============================================================================*/
    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 ==============================================================================*/
    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 *============================================================================*/
    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 ==============================================================================*/
    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 ==============================================================================*/
    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 ==============================================================================*/
    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 ==============================================================================*/
    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