Home | History | Annotate | Download | only in src
      1 /* Copyright (c) 2013, 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  */
     29 
     30 #include <pthread.h>
     31 #include <errno.h>
     32 #include <sys/ioctl.h>
     33 #include <sys/types.h>
     34 #include <sys/stat.h>
     35 #include <fcntl.h>
     36 #include <poll.h>
     37 
     38 #include "mm_jpeg_dbg.h"
     39 #include "mm_jpeg_interface.h"
     40 #include "mm_jpeg.h"
     41 #include "mm_jpeg_inlines.h"
     42 
     43 OMX_ERRORTYPE mm_jpegdec_ebd(OMX_HANDLETYPE hComponent,
     44   OMX_PTR pAppData,
     45   OMX_BUFFERHEADERTYPE *pBuffer);
     46 OMX_ERRORTYPE mm_jpegdec_fbd(OMX_HANDLETYPE hComponent,
     47     OMX_PTR pAppData,
     48     OMX_BUFFERHEADERTYPE* pBuffer);
     49 OMX_ERRORTYPE mm_jpegdec_event_handler(OMX_HANDLETYPE hComponent,
     50     OMX_PTR pAppData,
     51     OMX_EVENTTYPE eEvent,
     52     OMX_U32 nData1,
     53     OMX_U32 nData2,
     54     OMX_PTR pEventData);
     55 
     56 
     57 /** mm_jpegdec_destroy_job
     58  *
     59  *  Arguments:
     60  *    @p_session: Session obj
     61  *
     62  *  Return:
     63  *       0 for success else failure
     64  *
     65  *  Description:
     66  *       Destroy the job based paramenters
     67  *
     68  **/
     69 static int32_t mm_jpegdec_destroy_job(mm_jpeg_job_session_t *p_session)
     70 {
     71   mm_jpeg_decode_job_t *p_jobparams = &p_session->decode_job;
     72   int32_t rc = 0;
     73 
     74   return rc;
     75 }
     76 
     77 /** mm_jpeg_job_done:
     78  *
     79  *  Arguments:
     80  *    @p_session: decode session
     81  *
     82  *  Return:
     83  *       OMX_ERRORTYPE
     84  *
     85  *  Description:
     86  *       Finalize the job
     87  *
     88  **/
     89 static void mm_jpegdec_job_done(mm_jpeg_job_session_t *p_session)
     90 {
     91   mm_jpeg_obj *my_obj = (mm_jpeg_obj *)p_session->jpeg_obj;
     92   mm_jpeg_job_q_node_t *node = NULL;
     93 
     94   /*Destroy job related params*/
     95   mm_jpegdec_destroy_job(p_session);
     96 
     97   /*remove the job*/
     98   node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->ongoing_job_q,
     99     p_session->jobId);
    100   if (node) {
    101     free(node);
    102   }
    103   p_session->encoding = OMX_FALSE;
    104 
    105   /* wake up jobMgr thread to work on new job if there is any */
    106   cam_sem_post(&my_obj->job_mgr.job_sem);
    107 }
    108 
    109 
    110 /** mm_jpegdec_session_send_buffers:
    111  *
    112  *  Arguments:
    113  *    @data: job session
    114  *
    115  *  Return:
    116  *       OMX error values
    117  *
    118  *  Description:
    119  *       Send the buffers to OMX layer
    120  *
    121  **/
    122 OMX_ERRORTYPE mm_jpegdec_session_send_buffers(void *data)
    123 {
    124   uint32_t i = 0;
    125   mm_jpeg_job_session_t* p_session = (mm_jpeg_job_session_t *)data;
    126   OMX_ERRORTYPE ret = OMX_ErrorNone;
    127   QOMX_BUFFER_INFO lbuffer_info;
    128   mm_jpeg_decode_params_t *p_params = &p_session->dec_params;
    129   mm_jpeg_decode_job_t *p_jobparams = &p_session->decode_job;
    130 
    131   memset(&lbuffer_info, 0x0, sizeof(QOMX_BUFFER_INFO));
    132   for (i = 0; i < p_params->num_src_bufs; i++) {
    133     CDBG("%s:%d] Source buffer %d", __func__, __LINE__, i);
    134     lbuffer_info.fd = p_params->src_main_buf[i].fd;
    135     ret = OMX_UseBuffer(p_session->omx_handle, &(p_session->p_in_omx_buf[i]), 0,
    136       &lbuffer_info, p_params->src_main_buf[i].buf_size,
    137       p_params->src_main_buf[i].buf_vaddr);
    138     if (ret) {
    139       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
    140       return ret;
    141     }
    142   }
    143 
    144   CDBG("%s:%d]", __func__, __LINE__);
    145   return ret;
    146 }
    147 
    148 /** mm_jpeg_session_free_buffers:
    149  *
    150  *  Arguments:
    151  *    @data: job session
    152  *
    153  *  Return:
    154  *       OMX error values
    155  *
    156  *  Description:
    157  *       Free the buffers from OMX layer
    158  *
    159  **/
    160 OMX_ERRORTYPE mm_jpegdec_session_free_buffers(void *data)
    161 {
    162   OMX_ERRORTYPE ret = OMX_ErrorNone;
    163   uint32_t i = 0;
    164   mm_jpeg_job_session_t* p_session = (mm_jpeg_job_session_t *)data;
    165   mm_jpeg_decode_params_t *p_params = &p_session->dec_params;
    166   mm_jpeg_decode_job_t *p_jobparams = &p_session->decode_job;
    167 
    168   for (i = 0; i < p_params->num_src_bufs; i++) {
    169     CDBG("%s:%d] Source buffer %d", __func__, __LINE__, i);
    170     ret = OMX_FreeBuffer(p_session->omx_handle, 0, p_session->p_in_omx_buf[i]);
    171     if (ret) {
    172       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
    173       return ret;
    174     }
    175   }
    176 
    177   for (i = 0; i < p_params->num_dst_bufs; i++) {
    178     CDBG("%s:%d] Dest buffer %d", __func__, __LINE__, i);
    179     ret = OMX_FreeBuffer(p_session->omx_handle, 1, p_session->p_out_omx_buf[i]);
    180     if (ret) {
    181       CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
    182       return ret;
    183     }
    184   }
    185   CDBG("%s:%d]", __func__, __LINE__);
    186   return ret;
    187 }
    188 
    189 /** mm_jpegdec_session_create:
    190  *
    191  *  Arguments:
    192  *    @p_session: job session
    193  *
    194  *  Return:
    195  *       OMX error types
    196  *
    197  *  Description:
    198  *       Create a jpeg encode session
    199  *
    200  **/
    201 OMX_ERRORTYPE mm_jpegdec_session_create(mm_jpeg_job_session_t* p_session)
    202 {
    203   OMX_ERRORTYPE rc = OMX_ErrorNone;
    204   mm_jpeg_cirq_t *p_cirq = NULL;
    205 
    206   pthread_mutex_init(&p_session->lock, NULL);
    207   pthread_cond_init(&p_session->cond, NULL);
    208   cirq_reset(&p_session->cb_q);
    209   p_session->state_change_pending = OMX_FALSE;
    210   p_session->abort_state = MM_JPEG_ABORT_NONE;
    211   p_session->error_flag = OMX_ErrorNone;
    212   p_session->ebd_count = 0;
    213   p_session->fbd_count = 0;
    214   p_session->encode_pid = -1;
    215   p_session->config = OMX_FALSE;
    216 
    217   p_session->omx_callbacks.EmptyBufferDone = mm_jpegdec_ebd;
    218   p_session->omx_callbacks.FillBufferDone = mm_jpegdec_fbd;
    219   p_session->omx_callbacks.EventHandler = mm_jpegdec_event_handler;
    220   p_session->exif_count_local = 0;
    221 
    222   rc = OMX_GetHandle(&p_session->omx_handle,
    223     "OMX.qcom.image.jpeg.decoder",
    224     (void *)p_session,
    225     &p_session->omx_callbacks);
    226 
    227   if (OMX_ErrorNone != rc) {
    228     CDBG_ERROR("%s:%d] OMX_GetHandle failed (%d)", __func__, __LINE__, rc);
    229     return rc;
    230   }
    231   return rc;
    232 }
    233 
    234 /** mm_jpegdec_session_destroy:
    235  *
    236  *  Arguments:
    237  *    @p_session: job session
    238  *
    239  *  Return:
    240  *       none
    241  *
    242  *  Description:
    243  *       Destroy a jpeg encode session
    244  *
    245  **/
    246 void mm_jpegdec_session_destroy(mm_jpeg_job_session_t* p_session)
    247 {
    248   OMX_ERRORTYPE rc = OMX_ErrorNone;
    249 
    250   CDBG("%s:%d] E", __func__, __LINE__);
    251   if (NULL == p_session->omx_handle) {
    252     CDBG_ERROR("%s:%d] invalid handle", __func__, __LINE__);
    253     return;
    254   }
    255 
    256   rc = mm_jpeg_session_change_state(p_session, OMX_StateIdle, NULL);
    257   if (rc) {
    258     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
    259   }
    260 
    261   rc = mm_jpeg_session_change_state(p_session, OMX_StateLoaded,
    262     mm_jpegdec_session_free_buffers);
    263   if (rc) {
    264     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
    265   }
    266 
    267   rc = OMX_FreeHandle(p_session->omx_handle);
    268   if (0 != rc) {
    269     CDBG_ERROR("%s:%d] OMX_FreeHandle failed (%d)", __func__, __LINE__, rc);
    270   }
    271   p_session->omx_handle = NULL;
    272 
    273 
    274   pthread_mutex_destroy(&p_session->lock);
    275   pthread_cond_destroy(&p_session->cond);
    276   CDBG("%s:%d] X", __func__, __LINE__);
    277 }
    278 
    279 /** mm_jpeg_session_config_port:
    280  *
    281  *  Arguments:
    282  *    @p_session: job session
    283  *
    284  *  Return:
    285  *       OMX error values
    286  *
    287  *  Description:
    288  *       Configure OMX ports
    289  *
    290  **/
    291 OMX_ERRORTYPE mm_jpegdec_session_config_ports(mm_jpeg_job_session_t* p_session)
    292 {
    293   OMX_ERRORTYPE ret = OMX_ErrorNone;
    294   mm_jpeg_decode_params_t *p_params = &p_session->dec_params;
    295   mm_jpeg_decode_job_t *p_jobparams = &p_session->decode_job;
    296 
    297   mm_jpeg_buf_t *p_src_buf =
    298     &p_params->src_main_buf[p_jobparams->src_index];
    299 
    300   p_session->inputPort.nPortIndex = 0;
    301   p_session->outputPort.nPortIndex = 1;
    302 
    303 
    304   ret = OMX_GetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
    305     &p_session->inputPort);
    306   if (ret) {
    307     CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
    308     return ret;
    309   }
    310 
    311   ret = OMX_GetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
    312     &p_session->outputPort);
    313   if (ret) {
    314     CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
    315     return ret;
    316   }
    317 
    318   p_session->inputPort.format.image.nFrameWidth =
    319     p_jobparams->main_dim.src_dim.width;
    320   p_session->inputPort.format.image.nFrameHeight =
    321     p_jobparams->main_dim.src_dim.height;
    322   p_session->inputPort.format.image.nStride =
    323     p_src_buf->offset.mp[0].stride;
    324   p_session->inputPort.format.image.nSliceHeight =
    325     p_src_buf->offset.mp[0].scanline;
    326   p_session->inputPort.format.image.eColorFormat =
    327     map_jpeg_format(p_params->color_format);
    328   p_session->inputPort.nBufferSize =
    329     p_params->src_main_buf[p_jobparams->src_index].buf_size;
    330   p_session->inputPort.nBufferCountActual = p_params->num_src_bufs;
    331   ret = OMX_SetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
    332     &p_session->inputPort);
    333   if (ret) {
    334     CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
    335     return ret;
    336   }
    337 
    338   return ret;
    339 }
    340 
    341 
    342 /** mm_jpegdec_session_config_main:
    343  *
    344  *  Arguments:
    345  *    @p_session: job session
    346  *
    347  *  Return:
    348  *       OMX error values
    349  *
    350  *  Description:
    351  *       Configure main image
    352  *
    353  **/
    354 OMX_ERRORTYPE mm_jpegdec_session_config_main(mm_jpeg_job_session_t *p_session)
    355 {
    356   OMX_ERRORTYPE rc = OMX_ErrorNone;
    357   OMX_IMAGE_PARAM_QFACTORTYPE q_factor;
    358   mm_jpeg_decode_params_t *p_params = &p_session->dec_params;
    359   mm_jpeg_decode_job_t *p_jobparams = &p_session->decode_job;
    360 
    361   /* config port */
    362   CDBG("%s:%d] config port", __func__, __LINE__);
    363   rc = mm_jpegdec_session_config_ports(p_session);
    364   if (OMX_ErrorNone != rc) {
    365     CDBG_ERROR("%s: config port failed", __func__);
    366     return rc;
    367   }
    368 
    369 
    370   /* TODO: config crop */
    371 
    372   return rc;
    373 }
    374 
    375 /** mm_jpeg_session_configure:
    376  *
    377  *  Arguments:
    378  *    @data: encode session
    379  *
    380  *  Return:
    381  *       none
    382  *
    383  *  Description:
    384  *       Configure the session
    385  *
    386  **/
    387 static OMX_ERRORTYPE mm_jpegdec_session_configure(mm_jpeg_job_session_t *p_session)
    388 {
    389   OMX_ERRORTYPE ret = OMX_ErrorNone;
    390   mm_jpeg_decode_params_t *p_params = &p_session->dec_params;
    391   mm_jpeg_decode_job_t *p_jobparams = &p_session->decode_job;
    392   mm_jpeg_obj *my_obj = (mm_jpeg_obj *)p_session->jpeg_obj;
    393 
    394   CDBG("%s:%d] E ", __func__, __LINE__);
    395 
    396   MM_JPEG_CHK_ABORT(p_session, ret, error);
    397 
    398   /* config main img */
    399   ret = mm_jpegdec_session_config_main(p_session);
    400   if (OMX_ErrorNone != ret) {
    401     CDBG_ERROR("%s:%d] config main img failed", __func__, __LINE__);
    402     goto error;
    403   }
    404 
    405   /* TODO: common config (if needed) */
    406 
    407   ret = mm_jpeg_session_change_state(p_session, OMX_StateIdle,
    408     mm_jpegdec_session_send_buffers);
    409   if (ret) {
    410     CDBG_ERROR("%s:%d] change state to idle failed %d",
    411       __func__, __LINE__, ret);
    412     goto error;
    413   }
    414 
    415   ret = mm_jpeg_session_change_state(p_session, OMX_StateExecuting,
    416     NULL);
    417   if (ret) {
    418     CDBG_ERROR("%s:%d] change state to executing failed %d",
    419       __func__, __LINE__, ret);
    420     goto error;
    421   }
    422 
    423 error:
    424   CDBG("%s:%d] X ret %d", __func__, __LINE__, ret);
    425   return ret;
    426 }
    427 
    428 static OMX_ERRORTYPE mm_jpeg_session_port_enable(
    429     mm_jpeg_job_session_t *p_session,
    430     OMX_U32 nPortIndex,
    431     OMX_BOOL wait)
    432 {
    433   OMX_ERRORTYPE ret = OMX_ErrorNone;
    434   OMX_EVENTTYPE lEvent;
    435 
    436   pthread_mutex_lock(&p_session->lock);
    437   p_session->event_pending = OMX_TRUE;
    438   pthread_mutex_unlock(&p_session->lock);
    439 
    440   ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandPortEnable,
    441       nPortIndex, NULL);
    442 
    443   if (ret) {
    444     CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
    445     return ret;
    446   }
    447 
    448   if (wait == OMX_TRUE) {
    449     // Wait for cmd complete
    450     pthread_mutex_lock(&p_session->lock);
    451     if (p_session->event_pending == OMX_TRUE) {
    452       CDBG("%s:%d] before wait", __func__, __LINE__);
    453       pthread_cond_wait(&p_session->cond, &p_session->lock);
    454       lEvent = p_session->omxEvent;
    455       CDBG("%s:%d] after wait", __func__, __LINE__);
    456     }
    457     lEvent = p_session->omxEvent;
    458     pthread_mutex_unlock(&p_session->lock);
    459 
    460     if (lEvent != OMX_EventCmdComplete) {
    461       CDBG("%s:%d] Unexpected event %d", __func__, __LINE__,lEvent);
    462       return OMX_ErrorUndefined;
    463     }
    464   }
    465   return OMX_ErrorNone;
    466 }
    467 
    468 static OMX_ERRORTYPE mm_jpeg_session_port_disable(
    469     mm_jpeg_job_session_t *p_session,
    470     OMX_U32 nPortIndex,
    471     OMX_BOOL wait)
    472 {
    473   OMX_ERRORTYPE ret = OMX_ErrorNone;
    474   OMX_EVENTTYPE lEvent;
    475 
    476   pthread_mutex_lock(&p_session->lock);
    477   p_session->event_pending = OMX_TRUE;
    478   pthread_mutex_unlock(&p_session->lock);
    479 
    480   ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandPortDisable,
    481       nPortIndex, NULL);
    482 
    483   if (ret) {
    484     CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
    485     return ret;
    486   }
    487   if (wait == OMX_TRUE) {
    488     // Wait for cmd complete
    489     pthread_mutex_lock(&p_session->lock);
    490     if (p_session->event_pending == OMX_TRUE) {
    491       CDBG("%s:%d] before wait", __func__, __LINE__);
    492       pthread_cond_wait(&p_session->cond, &p_session->lock);
    493 
    494       CDBG("%s:%d] after wait", __func__, __LINE__);
    495     }
    496     lEvent = p_session->omxEvent;
    497     pthread_mutex_unlock(&p_session->lock);
    498 
    499     if (lEvent != OMX_EventCmdComplete) {
    500       CDBG("%s:%d] Unexpected event %d", __func__, __LINE__,lEvent);
    501       return OMX_ErrorUndefined;
    502     }
    503   }
    504   return OMX_ErrorNone;
    505 }
    506 
    507 
    508 /** mm_jpegdec_session_decode:
    509  *
    510  *  Arguments:
    511  *    @p_session: encode session
    512  *
    513  *  Return:
    514  *       OMX_ERRORTYPE
    515  *
    516  *  Description:
    517  *       Start the encoding
    518  *
    519  **/
    520 static OMX_ERRORTYPE mm_jpegdec_session_decode(mm_jpeg_job_session_t *p_session)
    521 {
    522   OMX_ERRORTYPE ret = OMX_ErrorNone;
    523   mm_jpeg_decode_params_t *p_params = &p_session->dec_params;
    524   mm_jpeg_decode_job_t *p_jobparams = &p_session->decode_job;
    525   int dest_idx = 0;
    526   mm_jpeg_obj *my_obj = (mm_jpeg_obj *)p_session->jpeg_obj;
    527   OMX_EVENTTYPE lEvent;
    528   OMX_U32 i;
    529   QOMX_BUFFER_INFO lbuffer_info;
    530 
    531   pthread_mutex_lock(&p_session->lock);
    532   p_session->abort_state = MM_JPEG_ABORT_NONE;
    533   p_session->encoding = OMX_FALSE;
    534   pthread_mutex_unlock(&p_session->lock);
    535 
    536   if (OMX_FALSE == p_session->config) {
    537     ret = mm_jpegdec_session_configure(p_session);
    538     if (ret) {
    539       CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
    540       goto error;
    541     }
    542     p_session->config = OMX_TRUE;
    543   }
    544 
    545   pthread_mutex_lock(&p_session->lock);
    546   p_session->encoding = OMX_TRUE;
    547   pthread_mutex_unlock(&p_session->lock);
    548 
    549   MM_JPEG_CHK_ABORT(p_session, ret, error);
    550 
    551   p_session->event_pending = OMX_TRUE;
    552 
    553   ret = OMX_EmptyThisBuffer(p_session->omx_handle,
    554     p_session->p_in_omx_buf[p_jobparams->src_index]);
    555   if (ret) {
    556     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
    557     goto error;
    558   }
    559 
    560   // Wait for port settings changed
    561   pthread_mutex_lock(&p_session->lock);
    562   if (p_session->event_pending == OMX_TRUE) {
    563     CDBG("%s:%d] before wait", __func__, __LINE__);
    564     pthread_cond_wait(&p_session->cond, &p_session->lock);
    565   }
    566   lEvent = p_session->omxEvent;
    567   CDBG("%s:%d] after wait", __func__, __LINE__);
    568   pthread_mutex_unlock(&p_session->lock);
    569 
    570   if (lEvent != OMX_EventPortSettingsChanged) {
    571     CDBG("%s:%d] Unexpected event %d", __func__, __LINE__,lEvent);
    572     goto error;
    573   }
    574 
    575   // Disable output port (wait)
    576   mm_jpeg_session_port_disable(p_session,
    577       p_session->outputPort.nPortIndex,
    578       OMX_TRUE);
    579 
    580   // Get port definition
    581   ret = OMX_GetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
    582       &p_session->outputPort);
    583   if (ret) {
    584     CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
    585     return ret;
    586   }
    587 
    588   // Set port definition
    589   p_session->outputPort.format.image.nFrameWidth =
    590     p_jobparams->main_dim.dst_dim.width;
    591   p_session->outputPort.format.image.nFrameHeight =
    592     p_jobparams->main_dim.dst_dim.height;
    593   p_session->outputPort.format.image.eColorFormat =
    594     map_jpeg_format(p_params->color_format);
    595 
    596   p_session->outputPort.nBufferSize =
    597      p_params->dest_buf[p_jobparams->dst_index].buf_size;
    598    p_session->outputPort.nBufferCountActual = p_params->num_dst_bufs;
    599 
    600    p_session->outputPort.format.image.nSliceHeight =
    601        p_params->dest_buf[p_jobparams->dst_index].offset.mp[0].scanline;
    602    p_session->outputPort.format.image.nStride =
    603        p_params->dest_buf[p_jobparams->dst_index].offset.mp[0].stride;
    604 
    605    ret = OMX_SetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
    606      &p_session->outputPort);
    607    if (ret) {
    608      CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
    609      return ret;
    610    }
    611 
    612   // Enable port (no wait)
    613   mm_jpeg_session_port_enable(p_session,
    614       p_session->outputPort.nPortIndex,
    615       OMX_FALSE);
    616 
    617   memset(&lbuffer_info, 0x0, sizeof(QOMX_BUFFER_INFO));
    618   // Use buffers
    619   for (i = 0; i < p_params->num_dst_bufs; i++) {
    620     lbuffer_info.fd = p_params->dest_buf[i].fd;
    621     CDBG("%s:%d] Dest buffer %d", __func__, __LINE__, i);
    622     ret = OMX_UseBuffer(p_session->omx_handle, &(p_session->p_out_omx_buf[i]),
    623         1, &lbuffer_info, p_params->dest_buf[i].buf_size,
    624         p_params->dest_buf[i].buf_vaddr);
    625     if (ret) {
    626       CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
    627       return ret;
    628     }
    629   }
    630 
    631   // Wait for port enable completion
    632   pthread_mutex_lock(&p_session->lock);
    633   if (p_session->event_pending == OMX_TRUE) {
    634     CDBG("%s:%d] before wait", __func__, __LINE__);
    635     pthread_cond_wait(&p_session->cond, &p_session->lock);
    636     lEvent = p_session->omxEvent;
    637     CDBG("%s:%d] after wait", __func__, __LINE__);
    638   }
    639   lEvent = p_session->omxEvent;
    640   pthread_mutex_unlock(&p_session->lock);
    641 
    642   if (lEvent != OMX_EventCmdComplete) {
    643     CDBG("%s:%d] Unexpected event %d", __func__, __LINE__,lEvent);
    644     goto error;
    645   }
    646 
    647   ret = OMX_FillThisBuffer(p_session->omx_handle,
    648     p_session->p_out_omx_buf[p_jobparams->dst_index]);
    649   if (ret) {
    650     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
    651     goto error;
    652   }
    653 
    654   MM_JPEG_CHK_ABORT(p_session, ret, error);
    655 
    656 error:
    657 
    658   CDBG("%s:%d] X ", __func__, __LINE__);
    659   return ret;
    660 }
    661 
    662 /** mm_jpegdec_process_decoding_job:
    663  *
    664  *  Arguments:
    665  *    @my_obj: jpeg client
    666  *    @job_node: job node
    667  *
    668  *  Return:
    669  *       0 for success -1 otherwise
    670  *
    671  *  Description:
    672  *       Start the encoding job
    673  *
    674  **/
    675 int32_t mm_jpegdec_process_decoding_job(mm_jpeg_obj *my_obj, mm_jpeg_job_q_node_t* job_node)
    676 {
    677   int32_t rc = 0;
    678   OMX_ERRORTYPE ret = OMX_ErrorNone;
    679   mm_jpeg_job_session_t *p_session = NULL;
    680   mm_jpeg_job_q_node_t *node = NULL;
    681 
    682   /* check if valid session */
    683   p_session = mm_jpeg_get_session(my_obj, job_node->dec_info.job_id);
    684   if (NULL == p_session) {
    685     CDBG_ERROR("%s:%d] invalid job id %x", __func__, __LINE__,
    686       job_node->dec_info.job_id);
    687     return -1;
    688   }
    689 
    690   /* sent encode cmd to OMX, queue job into ongoing queue */
    691   rc = mm_jpeg_queue_enq(&my_obj->ongoing_job_q, job_node);
    692   if (rc) {
    693     CDBG_ERROR("%s:%d] jpeg enqueue failed %d",
    694       __func__, __LINE__, ret);
    695     goto error;
    696   }
    697 
    698   p_session->decode_job = job_node->dec_info.decode_job;
    699   p_session->jobId = job_node->dec_info.job_id;
    700   ret = mm_jpegdec_session_decode(p_session);
    701   if (ret) {
    702     CDBG_ERROR("%s:%d] encode session failed", __func__, __LINE__);
    703     goto error;
    704   }
    705 
    706   CDBG("%s:%d] Success X ", __func__, __LINE__);
    707   return rc;
    708 
    709 error:
    710 
    711   if ((OMX_ErrorNone != ret) &&
    712     (NULL != p_session->dec_params.jpeg_cb)) {
    713     p_session->job_status = JPEG_JOB_STATUS_ERROR;
    714     CDBG("%s:%d] send jpeg error callback %d", __func__, __LINE__,
    715       p_session->job_status);
    716     p_session->dec_params.jpeg_cb(p_session->job_status,
    717       p_session->client_hdl,
    718       p_session->jobId,
    719       NULL,
    720       p_session->dec_params.userdata);
    721   }
    722 
    723   /*remove the job*/
    724   mm_jpegdec_job_done(p_session);
    725   CDBG("%s:%d] Error X ", __func__, __LINE__);
    726 
    727   return rc;
    728 }
    729 
    730 /** mm_jpeg_start_decode_job:
    731  *
    732  *  Arguments:
    733  *    @my_obj: jpeg object
    734  *    @client_hdl: client handle
    735  *    @job: pointer to encode job
    736  *    @jobId: job id
    737  *
    738  *  Return:
    739  *       0 for success else failure
    740  *
    741  *  Description:
    742  *       Start the encoding job
    743  *
    744  **/
    745 int32_t mm_jpegdec_start_decode_job(mm_jpeg_obj *my_obj,
    746   mm_jpeg_job_t *job,
    747   uint32_t *job_id)
    748 {
    749   int32_t rc = -1;
    750   uint8_t session_idx = 0;
    751   uint8_t client_idx = 0;
    752   mm_jpeg_job_q_node_t* node = NULL;
    753   mm_jpeg_job_session_t *p_session = NULL;
    754   mm_jpeg_decode_job_t *p_jobparams  = &job->decode_job;
    755 
    756   *job_id = 0;
    757 
    758   /* check if valid session */
    759   session_idx = GET_SESSION_IDX(p_jobparams->session_id);
    760   client_idx = GET_CLIENT_IDX(p_jobparams->session_id);
    761   CDBG("%s:%d] session_idx %d client idx %d", __func__, __LINE__,
    762     session_idx, client_idx);
    763 
    764   if ((session_idx >= MM_JPEG_MAX_SESSION) ||
    765     (client_idx >= MAX_JPEG_CLIENT_NUM)) {
    766     CDBG_ERROR("%s:%d] invalid session id %x", __func__, __LINE__,
    767       job->decode_job.session_id);
    768     return rc;
    769   }
    770 
    771   p_session = &my_obj->clnt_mgr[client_idx].session[session_idx];
    772   if (OMX_FALSE == p_session->active) {
    773     CDBG_ERROR("%s:%d] session not active %x", __func__, __LINE__,
    774       job->decode_job.session_id);
    775     return rc;
    776   }
    777 
    778   if ((p_jobparams->src_index >= p_session->dec_params.num_src_bufs) ||
    779     (p_jobparams->dst_index >= p_session->dec_params.num_dst_bufs)) {
    780     CDBG_ERROR("%s:%d] invalid buffer indices", __func__, __LINE__);
    781     return rc;
    782   }
    783 
    784   /* enqueue new job into todo job queue */
    785   node = (mm_jpeg_job_q_node_t *)malloc(sizeof(mm_jpeg_job_q_node_t));
    786   if (NULL == node) {
    787     CDBG_ERROR("%s: No memory for mm_jpeg_job_q_node_t", __func__);
    788     return -1;
    789   }
    790 
    791   *job_id = job->decode_job.session_id |
    792     ((p_session->job_hist++ % JOB_HIST_MAX) << 16);
    793 
    794   memset(node, 0, sizeof(mm_jpeg_job_q_node_t));
    795   node->dec_info.decode_job = job->decode_job;
    796   node->dec_info.job_id = *job_id;
    797   node->dec_info.client_handle = p_session->client_hdl;
    798   node->type = MM_JPEG_CMD_TYPE_DECODE_JOB;
    799 
    800   rc = mm_jpeg_queue_enq(&my_obj->job_mgr.job_queue, node);
    801   if (0 == rc) {
    802     cam_sem_post(&my_obj->job_mgr.job_sem);
    803   }
    804 
    805   return rc;
    806 }
    807 
    808 /** mm_jpegdec_create_session:
    809  *
    810  *  Arguments:
    811  *    @my_obj: jpeg object
    812  *    @client_hdl: client handle
    813  *    @p_params: pointer to encode params
    814  *    @p_session_id: session id
    815  *
    816  *  Return:
    817  *       0 for success else failure
    818  *
    819  *  Description:
    820  *       Start the encoding session
    821  *
    822  **/
    823 int32_t mm_jpegdec_create_session(mm_jpeg_obj *my_obj,
    824   uint32_t client_hdl,
    825   mm_jpeg_decode_params_t *p_params,
    826   uint32_t* p_session_id)
    827 {
    828   int32_t rc = 0;
    829   OMX_ERRORTYPE ret = OMX_ErrorNone;
    830   uint8_t clnt_idx = 0;
    831   int session_idx = -1;
    832   mm_jpeg_job_session_t *p_session = NULL;
    833   *p_session_id = 0;
    834 
    835   /* validate the parameters */
    836   if ((p_params->num_src_bufs > MM_JPEG_MAX_BUF)
    837     || (p_params->num_dst_bufs > MM_JPEG_MAX_BUF)) {
    838     CDBG_ERROR("%s:%d] invalid num buffers", __func__, __LINE__);
    839     return rc;
    840   }
    841 
    842   /* check if valid client */
    843   clnt_idx = mm_jpeg_util_get_index_by_handler(client_hdl);
    844   if (clnt_idx >= MAX_JPEG_CLIENT_NUM) {
    845     CDBG_ERROR("%s: invalid client with handler (%d)", __func__, client_hdl);
    846     return rc;
    847   }
    848 
    849   session_idx = mm_jpeg_get_new_session_idx(my_obj, clnt_idx, &p_session);
    850   if (session_idx < 0) {
    851     CDBG_ERROR("%s:%d] invalid session id (%d)", __func__, __LINE__, session_idx);
    852     return rc;
    853   }
    854 
    855   ret = mm_jpegdec_session_create(p_session);
    856   if (OMX_ErrorNone != ret) {
    857     p_session->active = OMX_FALSE;
    858     CDBG_ERROR("%s:%d] jpeg session create failed", __func__, __LINE__);
    859     return rc;
    860   }
    861 
    862   *p_session_id = (JOB_ID_MAGICVAL << 24) | (session_idx << 8) | clnt_idx;
    863 
    864   /*copy the params*/
    865   p_session->dec_params = *p_params;
    866   p_session->client_hdl = client_hdl;
    867   p_session->sessionId = *p_session_id;
    868   p_session->jpeg_obj = (void*)my_obj; /* save a ptr to jpeg_obj */
    869   CDBG("%s:%d] session id %x", __func__, __LINE__, *p_session_id);
    870 
    871   return rc;
    872 }
    873 
    874 /** mm_jpegdec_destroy_session:
    875  *
    876  *  Arguments:
    877  *    @my_obj: jpeg object
    878  *    @session_id: session index
    879  *
    880  *  Return:
    881  *       0 for success else failure
    882  *
    883  *  Description:
    884  *       Destroy the encoding session
    885  *
    886  **/
    887 int32_t mm_jpegdec_destroy_session(mm_jpeg_obj *my_obj,
    888   mm_jpeg_job_session_t *p_session)
    889 {
    890   int32_t rc = 0;
    891   uint8_t clnt_idx = 0;
    892   mm_jpeg_job_q_node_t *node = NULL;
    893   OMX_BOOL ret = OMX_FALSE;
    894 
    895   if (NULL == p_session) {
    896     CDBG_ERROR("%s:%d] invalid session", __func__, __LINE__);
    897     return rc;
    898   }
    899   uint32_t session_id = p_session->sessionId;
    900   pthread_mutex_lock(&my_obj->job_lock);
    901 
    902   /* abort job if in todo queue */
    903   CDBG("%s:%d] abort todo jobs", __func__, __LINE__);
    904   node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id);
    905   while (NULL != node) {
    906     free(node);
    907     node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id);
    908   }
    909 
    910   /* abort job if in ongoing queue */
    911   CDBG("%s:%d] abort ongoing jobs", __func__, __LINE__);
    912   node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id);
    913   while (NULL != node) {
    914     free(node);
    915     node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id);
    916   }
    917 
    918   /* abort the current session */
    919   mm_jpeg_session_abort(p_session);
    920   mm_jpegdec_session_destroy(p_session);
    921   mm_jpeg_remove_session_idx(my_obj, session_id);
    922   pthread_mutex_unlock(&my_obj->job_lock);
    923 
    924   /* wake up jobMgr thread to work on new job if there is any */
    925   cam_sem_post(&my_obj->job_mgr.job_sem);
    926   CDBG("%s:%d] X", __func__, __LINE__);
    927 
    928   return rc;
    929 }
    930 
    931 /** mm_jpegdec_destroy_session_by_id:
    932  *
    933  *  Arguments:
    934  *    @my_obj: jpeg object
    935  *    @session_id: session index
    936  *
    937  *  Return:
    938  *       0 for success else failure
    939  *
    940  *  Description:
    941  *       Destroy the encoding session
    942  *
    943  **/
    944 int32_t mm_jpegdec_destroy_session_by_id(mm_jpeg_obj *my_obj, uint32_t session_id)
    945 {
    946   int32_t rc = 0;
    947   mm_jpeg_job_session_t *p_session = mm_jpeg_get_session(my_obj, session_id);
    948 
    949   if (NULL == p_session) {
    950     CDBG_ERROR("%s:%d] session is not valid", __func__, __LINE__);
    951     return rc;
    952   }
    953 
    954   return mm_jpegdec_destroy_session(my_obj, p_session);
    955 }
    956 
    957 
    958 
    959 OMX_ERRORTYPE mm_jpegdec_ebd(OMX_HANDLETYPE hComponent,
    960   OMX_PTR pAppData,
    961   OMX_BUFFERHEADERTYPE *pBuffer)
    962 {
    963   OMX_ERRORTYPE ret = OMX_ErrorNone;
    964   mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData;
    965 
    966   CDBG("%s:%d] count %d ", __func__, __LINE__, p_session->ebd_count);
    967   pthread_mutex_lock(&p_session->lock);
    968   p_session->ebd_count++;
    969   pthread_mutex_unlock(&p_session->lock);
    970   return 0;
    971 }
    972 
    973 OMX_ERRORTYPE mm_jpegdec_fbd(OMX_HANDLETYPE hComponent,
    974   OMX_PTR pAppData,
    975   OMX_BUFFERHEADERTYPE *pBuffer)
    976 {
    977   OMX_ERRORTYPE ret = OMX_ErrorNone;
    978   mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData;
    979   uint32_t i = 0;
    980   int rc = 0;
    981   mm_jpeg_output_t output_buf;
    982 
    983   CDBG("%s:%d] count %d ", __func__, __LINE__, p_session->fbd_count);
    984 
    985   pthread_mutex_lock(&p_session->lock);
    986 
    987   if (MM_JPEG_ABORT_NONE != p_session->abort_state) {
    988     pthread_mutex_unlock(&p_session->lock);
    989     return ret;
    990   }
    991 
    992   p_session->fbd_count++;
    993   if (NULL != p_session->dec_params.jpeg_cb) {
    994     p_session->job_status = JPEG_JOB_STATUS_DONE;
    995     output_buf.buf_filled_len = (uint32_t)pBuffer->nFilledLen;
    996     output_buf.buf_vaddr = pBuffer->pBuffer;
    997     output_buf.fd = 0;
    998     CDBG("%s:%d] send jpeg callback %d", __func__, __LINE__,
    999       p_session->job_status);
   1000     p_session->dec_params.jpeg_cb(p_session->job_status,
   1001       p_session->client_hdl,
   1002       p_session->jobId,
   1003       &output_buf,
   1004       p_session->dec_params.userdata);
   1005 
   1006     /* remove from ready queue */
   1007     mm_jpegdec_job_done(p_session);
   1008   }
   1009   pthread_mutex_unlock(&p_session->lock);
   1010   CDBG("%s:%d] ", __func__, __LINE__);
   1011 
   1012   return ret;
   1013 }
   1014 
   1015 OMX_ERRORTYPE mm_jpegdec_event_handler(OMX_HANDLETYPE hComponent,
   1016   OMX_PTR pAppData,
   1017   OMX_EVENTTYPE eEvent,
   1018   OMX_U32 nData1,
   1019   OMX_U32 nData2,
   1020   OMX_PTR pEventData)
   1021 {
   1022   mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData;
   1023 
   1024   CDBG("%s:%d] %d %d %d state %d", __func__, __LINE__, eEvent, (int)nData1,
   1025     (int)nData2, p_session->abort_state);
   1026 
   1027   CDBG("%s:%d] AppData=%p ", __func__, __LINE__, pAppData);
   1028 
   1029   pthread_mutex_lock(&p_session->lock);
   1030   p_session->omxEvent = eEvent;
   1031   if (MM_JPEG_ABORT_INIT == p_session->abort_state) {
   1032     p_session->abort_state = MM_JPEG_ABORT_DONE;
   1033     pthread_cond_signal(&p_session->cond);
   1034     pthread_mutex_unlock(&p_session->lock);
   1035     return OMX_ErrorNone;
   1036   }
   1037 
   1038   if (eEvent == OMX_EventError) {
   1039     if (p_session->encoding == OMX_TRUE) {
   1040       CDBG("%s:%d] Error during encoding", __func__, __LINE__);
   1041 
   1042       /* send jpeg callback */
   1043       if (NULL != p_session->dec_params.jpeg_cb) {
   1044         p_session->job_status = JPEG_JOB_STATUS_ERROR;
   1045         CDBG("%s:%d] send jpeg error callback %d", __func__, __LINE__,
   1046           p_session->job_status);
   1047         p_session->dec_params.jpeg_cb(p_session->job_status,
   1048           p_session->client_hdl,
   1049           p_session->jobId,
   1050           NULL,
   1051           p_session->dec_params.userdata);
   1052       }
   1053 
   1054       /* remove from ready queue */
   1055       mm_jpegdec_job_done(p_session);
   1056     }
   1057     pthread_cond_signal(&p_session->cond);
   1058   } else if (eEvent == OMX_EventCmdComplete) {
   1059     p_session->state_change_pending = OMX_FALSE;
   1060     p_session->event_pending = OMX_FALSE;
   1061     pthread_cond_signal(&p_session->cond);
   1062   }  else if (eEvent == OMX_EventPortSettingsChanged) {
   1063     p_session->event_pending = OMX_FALSE;
   1064     pthread_cond_signal(&p_session->cond);
   1065   }
   1066 
   1067   pthread_mutex_unlock(&p_session->lock);
   1068   CDBG("%s:%d]", __func__, __LINE__);
   1069   return OMX_ErrorNone;
   1070 }
   1071 
   1072 /** mm_jpegdec_abort_job:
   1073  *
   1074  *  Arguments:
   1075  *    @my_obj: jpeg object
   1076  *    @client_hdl: client handle
   1077  *    @jobId: job id
   1078  *
   1079  *  Return:
   1080  *       0 for success else failure
   1081  *
   1082  *  Description:
   1083  *       Abort the encoding session
   1084  *
   1085  **/
   1086 int32_t mm_jpegdec_abort_job(mm_jpeg_obj *my_obj,
   1087   uint32_t jobId)
   1088 {
   1089   int32_t rc = -1;
   1090   uint8_t clnt_idx = 0;
   1091   mm_jpeg_job_q_node_t *node = NULL;
   1092   OMX_BOOL ret = OMX_FALSE;
   1093   mm_jpeg_job_session_t *p_session = NULL;
   1094 
   1095   CDBG("%s:%d] ", __func__, __LINE__);
   1096   pthread_mutex_lock(&my_obj->job_lock);
   1097 
   1098   /* abort job if in todo queue */
   1099   node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->job_mgr.job_queue, jobId);
   1100   if (NULL != node) {
   1101     free(node);
   1102     goto abort_done;
   1103   }
   1104 
   1105   /* abort job if in ongoing queue */
   1106   node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->ongoing_job_q, jobId);
   1107   if (NULL != node) {
   1108     /* find job that is OMX ongoing, ask OMX to abort the job */
   1109     p_session = mm_jpeg_get_session(my_obj, node->dec_info.job_id);
   1110     if (p_session) {
   1111       mm_jpeg_session_abort(p_session);
   1112     } else {
   1113       CDBG_ERROR("%s:%d] Invalid job id 0x%x", __func__, __LINE__,
   1114         node->dec_info.job_id);
   1115     }
   1116     free(node);
   1117     goto abort_done;
   1118   }
   1119 
   1120 abort_done:
   1121   pthread_mutex_unlock(&my_obj->job_lock);
   1122 
   1123   return rc;
   1124 }
   1125 /** mm_jpegdec_init:
   1126  *
   1127  *  Arguments:
   1128  *    @my_obj: jpeg object
   1129  *
   1130  *  Return:
   1131  *       0 for success else failure
   1132  *
   1133  *  Description:
   1134  *       Initializes the jpeg client
   1135  *
   1136  **/
   1137 int32_t mm_jpegdec_init(mm_jpeg_obj *my_obj)
   1138 {
   1139   int32_t rc = 0;
   1140 
   1141   /* init locks */
   1142   pthread_mutex_init(&my_obj->job_lock, NULL);
   1143 
   1144   /* init ongoing job queue */
   1145   rc = mm_jpeg_queue_init(&my_obj->ongoing_job_q);
   1146   if (0 != rc) {
   1147     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
   1148     return -1;
   1149   }
   1150 
   1151   /* init job semaphore and launch jobmgr thread */
   1152   CDBG("%s:%d] Launch jobmgr thread rc %d", __func__, __LINE__, rc);
   1153   rc = mm_jpeg_jobmgr_thread_launch(my_obj);
   1154   if (0 != rc) {
   1155     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
   1156     return -1;
   1157   }
   1158 
   1159   /* load OMX */
   1160   if (OMX_ErrorNone != OMX_Init()) {
   1161     /* roll back in error case */
   1162     CDBG_ERROR("%s:%d] OMX_Init failed (%d)", __func__, __LINE__, rc);
   1163     mm_jpeg_jobmgr_thread_release(my_obj);
   1164     mm_jpeg_queue_deinit(&my_obj->ongoing_job_q);
   1165     pthread_mutex_destroy(&my_obj->job_lock);
   1166   }
   1167 
   1168   return rc;
   1169 }
   1170 
   1171 /** mm_jpegdec_deinit:
   1172  *
   1173  *  Arguments:
   1174  *    @my_obj: jpeg object
   1175  *
   1176  *  Return:
   1177  *       0 for success else failure
   1178  *
   1179  *  Description:
   1180  *       Deinits the jpeg client
   1181  *
   1182  **/
   1183 int32_t mm_jpegdec_deinit(mm_jpeg_obj *my_obj)
   1184 {
   1185   int32_t rc = 0;
   1186 
   1187   /* release jobmgr thread */
   1188   rc = mm_jpeg_jobmgr_thread_release(my_obj);
   1189   if (0 != rc) {
   1190     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
   1191   }
   1192 
   1193   /* unload OMX engine */
   1194   OMX_Deinit();
   1195 
   1196   /* deinit ongoing job and cb queue */
   1197   rc = mm_jpeg_queue_deinit(&my_obj->ongoing_job_q);
   1198   if (0 != rc) {
   1199     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
   1200   }
   1201 
   1202   /* destroy locks */
   1203   pthread_mutex_destroy(&my_obj->job_lock);
   1204 
   1205   return rc;
   1206 }
   1207