Home | History | Annotate | Download | only in src
      1 /* Copyright (c) 2012-2014, 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 #define ATRACE_TAG ATRACE_TAG_CAMERA
     31 
     32 #include <pthread.h>
     33 #include <errno.h>
     34 #include <sys/ioctl.h>
     35 #include <sys/types.h>
     36 #include <sys/stat.h>
     37 #include <sys/prctl.h>
     38 #include <fcntl.h>
     39 #include <poll.h>
     40 #include <cutils/trace.h>
     41 #include <math.h>
     42 
     43 #include "mm_jpeg_dbg.h"
     44 #include "mm_jpeg_interface.h"
     45 #include "mm_jpeg.h"
     46 #include "mm_jpeg_inlines.h"
     47 
     48 #ifdef LOAD_ADSP_RPC_LIB
     49 #include <dlfcn.h>
     50 #include <stdlib.h>
     51 #endif
     52 
     53 #define ENCODING_MODE_PARALLEL 1
     54 
     55 #define META_KEYFILE QCAMERA_DUMP_FRM_LOCATION"metadata.key"
     56 
     57 /**
     58  * minimal resolution needed for normal mode of ops
     59  */
     60 #define MM_JPEG_MIN_NOM_RESOLUTION 7680000 /*8MP*/
     61 
     62 OMX_ERRORTYPE mm_jpeg_ebd(OMX_HANDLETYPE hComponent,
     63     OMX_PTR pAppData,
     64     OMX_BUFFERHEADERTYPE* pBuffer);
     65 OMX_ERRORTYPE mm_jpeg_fbd(OMX_HANDLETYPE hComponent,
     66     OMX_PTR pAppData,
     67     OMX_BUFFERHEADERTYPE* pBuffer);
     68 OMX_ERRORTYPE mm_jpeg_event_handler(OMX_HANDLETYPE hComponent,
     69     OMX_PTR pAppData,
     70     OMX_EVENTTYPE eEvent,
     71     OMX_U32 nData1,
     72     OMX_U32 nData2,
     73     OMX_PTR pEventData);
     74 
     75 static int32_t mm_jpegenc_destroy_job(mm_jpeg_job_session_t *p_session);
     76 static void mm_jpegenc_job_done(mm_jpeg_job_session_t *p_session);
     77 mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_dst_ptr(
     78   mm_jpeg_queue_t* queue, void * dst_ptr);
     79 static OMX_ERRORTYPE mm_jpeg_session_configure(mm_jpeg_job_session_t *p_session);
     80 
     81 /** mm_jpeg_session_send_buffers:
     82  *
     83  *  Arguments:
     84  *    @data: job session
     85  *
     86  *  Return:
     87  *       OMX error values
     88  *
     89  *  Description:
     90  *       Send the buffers to OMX layer
     91  *
     92  **/
     93 OMX_ERRORTYPE mm_jpeg_session_send_buffers(void *data)
     94 {
     95   uint32_t i = 0;
     96   mm_jpeg_job_session_t* p_session = (mm_jpeg_job_session_t *)data;
     97   OMX_ERRORTYPE ret = OMX_ErrorNone;
     98   QOMX_BUFFER_INFO lbuffer_info;
     99   mm_jpeg_encode_params_t *p_params = &p_session->params;
    100 
    101   memset(&lbuffer_info, 0x0, sizeof(QOMX_BUFFER_INFO));
    102   for (i = 0; i < p_params->num_src_bufs; i++) {
    103     CDBG("%s:%d] Source buffer %d", __func__, __LINE__, i);
    104     lbuffer_info.fd = (OMX_U32)p_params->src_main_buf[i].fd;
    105     ret = OMX_UseBuffer(p_session->omx_handle, &(p_session->p_in_omx_buf[i]), 0,
    106       &lbuffer_info, p_params->src_main_buf[i].buf_size,
    107       p_params->src_main_buf[i].buf_vaddr);
    108     if (ret) {
    109       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
    110       return ret;
    111     }
    112   }
    113 
    114   for (i = 0; i < p_params->num_tmb_bufs; i++) {
    115     CDBG("%s:%d] Source buffer %d", __func__, __LINE__, i);
    116     lbuffer_info.fd = (OMX_U32)p_params->src_thumb_buf[i].fd;
    117     ret = OMX_UseBuffer(p_session->omx_handle,
    118         &(p_session->p_in_omx_thumb_buf[i]), 2,
    119         &lbuffer_info, p_params->src_thumb_buf[i].buf_size,
    120         p_params->src_thumb_buf[i].buf_vaddr);
    121     if (ret) {
    122       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
    123       return ret;
    124     }
    125   }
    126 
    127   for (i = 0; i < p_params->num_dst_bufs; i++) {
    128     CDBG("%s:%d] Dest buffer %d", __func__, __LINE__, i);
    129     ret = OMX_UseBuffer(p_session->omx_handle, &(p_session->p_out_omx_buf[i]),
    130       1, NULL, p_params->dest_buf[i].buf_size,
    131       p_params->dest_buf[i].buf_vaddr);
    132     if (ret) {
    133       CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
    134       return ret;
    135     }
    136   }
    137   CDBG("%s:%d]", __func__, __LINE__);
    138   return ret;
    139 }
    140 
    141 
    142 /** mm_jpeg_session_free_buffers:
    143  *
    144  *  Arguments:
    145  *    @data: job session
    146  *
    147  *  Return:
    148  *       OMX error values
    149  *
    150  *  Description:
    151  *       Free the buffers from OMX layer
    152  *
    153  **/
    154 OMX_ERRORTYPE mm_jpeg_session_free_buffers(void *data)
    155 {
    156   OMX_ERRORTYPE ret = OMX_ErrorNone;
    157   uint32_t i = 0;
    158   mm_jpeg_job_session_t* p_session = (mm_jpeg_job_session_t *)data;
    159   mm_jpeg_encode_params_t *p_params = &p_session->params;
    160 
    161   for (i = 0; i < p_params->num_src_bufs; i++) {
    162     CDBG("%s:%d] Source buffer %d", __func__, __LINE__, i);
    163     ret = OMX_FreeBuffer(p_session->omx_handle, 0, p_session->p_in_omx_buf[i]);
    164     if (ret) {
    165       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
    166       return ret;
    167     }
    168   }
    169 
    170   for (i = 0; i < p_params->num_tmb_bufs; i++) {
    171     CDBG("%s:%d] Source buffer %d", __func__, __LINE__, i);
    172     ret = OMX_FreeBuffer(p_session->omx_handle, 2, p_session->p_in_omx_thumb_buf[i]);
    173     if (ret) {
    174       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
    175       return ret;
    176     }
    177   }
    178 
    179   for (i = 0; i < p_params->num_dst_bufs; i++) {
    180     CDBG("%s:%d] Dest buffer %d", __func__, __LINE__, i);
    181     ret = OMX_FreeBuffer(p_session->omx_handle, 1, p_session->p_out_omx_buf[i]);
    182     if (ret) {
    183       CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
    184       return ret;
    185     }
    186   }
    187   CDBG("%s:%d]", __func__, __LINE__);
    188   return ret;
    189 }
    190 
    191 
    192 
    193 
    194 /** mm_jpeg_session_change_state:
    195  *
    196  *  Arguments:
    197  *    @p_session: job session
    198  *    @new_state: new state to be transitioned to
    199  *    @p_exec: transition function
    200  *
    201  *  Return:
    202  *       OMX error values
    203  *
    204  *  Description:
    205  *       This method is used for state transition
    206  *
    207  **/
    208 OMX_ERRORTYPE mm_jpeg_session_change_state(mm_jpeg_job_session_t* p_session,
    209   OMX_STATETYPE new_state,
    210   mm_jpeg_transition_func_t p_exec)
    211 {
    212   OMX_ERRORTYPE ret = OMX_ErrorNone;
    213   OMX_STATETYPE current_state;
    214   CDBG("%s:%d] new_state %d p_exec %p", __func__, __LINE__,
    215     new_state, p_exec);
    216 
    217 
    218   pthread_mutex_lock(&p_session->lock);
    219 
    220   ret = OMX_GetState(p_session->omx_handle, &current_state);
    221 
    222   if (ret) {
    223     pthread_mutex_unlock(&p_session->lock);
    224     return ret;
    225   }
    226 
    227   if (current_state == new_state) {
    228     pthread_mutex_unlock(&p_session->lock);
    229     return OMX_ErrorNone;
    230   }
    231 
    232   p_session->state_change_pending = OMX_TRUE;
    233   pthread_mutex_unlock(&p_session->lock);
    234   ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandStateSet,
    235     new_state, NULL);
    236   pthread_mutex_lock(&p_session->lock);
    237   if (ret) {
    238     CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
    239     pthread_mutex_unlock(&p_session->lock);
    240     return OMX_ErrorIncorrectStateTransition;
    241   }
    242   CDBG("%s:%d] ", __func__, __LINE__);
    243   if ((OMX_ErrorNone != p_session->error_flag) &&
    244       (OMX_ErrorOverflow != p_session->error_flag)) {
    245     CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, p_session->error_flag);
    246     pthread_mutex_unlock(&p_session->lock);
    247     return p_session->error_flag;
    248   }
    249   if (p_exec) {
    250     ret = p_exec(p_session);
    251     if (ret) {
    252       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
    253       pthread_mutex_unlock(&p_session->lock);
    254       return ret;
    255     }
    256   }
    257   CDBG("%s:%d] ", __func__, __LINE__);
    258   if (p_session->state_change_pending) {
    259     CDBG("%s:%d] before wait", __func__, __LINE__);
    260     pthread_cond_wait(&p_session->cond, &p_session->lock);
    261     CDBG("%s:%d] after wait", __func__, __LINE__);
    262   }
    263   pthread_mutex_unlock(&p_session->lock);
    264   CDBG("%s:%d] ", __func__, __LINE__);
    265   return ret;
    266 }
    267 
    268 /** mm_jpeg_session_create:
    269  *
    270  *  Arguments:
    271  *    @p_session: job session
    272  *
    273  *  Return:
    274  *       OMX error types
    275  *
    276  *  Description:
    277  *       Create a jpeg encode session
    278  *
    279  **/
    280 OMX_ERRORTYPE mm_jpeg_session_create(mm_jpeg_job_session_t* p_session)
    281 {
    282   OMX_ERRORTYPE rc = OMX_ErrorNone;
    283   mm_jpeg_obj *my_obj = (mm_jpeg_obj *) p_session->jpeg_obj;
    284   char *omx_lib = "OMX.qcom.image.jpeg.encoder";
    285 
    286   pthread_mutex_init(&p_session->lock, NULL);
    287   pthread_cond_init(&p_session->cond, NULL);
    288   cirq_reset(&p_session->cb_q);
    289   p_session->state_change_pending = OMX_FALSE;
    290   p_session->abort_state = MM_JPEG_ABORT_NONE;
    291   p_session->error_flag = OMX_ErrorNone;
    292   p_session->ebd_count = 0;
    293   p_session->fbd_count = 0;
    294   p_session->encode_pid = -1;
    295   p_session->config = OMX_FALSE;
    296   p_session->exif_count_local = 0;
    297   p_session->auto_out_buf = OMX_FALSE;
    298 
    299   p_session->omx_callbacks.EmptyBufferDone = mm_jpeg_ebd;
    300   p_session->omx_callbacks.FillBufferDone = mm_jpeg_fbd;
    301   p_session->omx_callbacks.EventHandler = mm_jpeg_event_handler;
    302 
    303   p_session->thumb_from_main = 0;
    304 #ifdef MM_JPEG_USE_PIPELINE
    305   p_session->thumb_from_main = 1;
    306   omx_lib = "OMX.qcom.image.jpeg.encoder_pipeline";
    307 #endif
    308 
    309   rc = OMX_GetHandle(&p_session->omx_handle,
    310       omx_lib,
    311       (void *)p_session,
    312       &p_session->omx_callbacks);
    313   if (OMX_ErrorNone != rc) {
    314     CDBG_ERROR("%s:%d] OMX_GetHandle failed (%d)", __func__, __LINE__, rc);
    315     return rc;
    316   }
    317 
    318   my_obj->num_sessions++;
    319 
    320   return rc;
    321 }
    322 
    323 
    324 
    325 /** mm_jpeg_session_destroy:
    326  *
    327  *  Arguments:
    328  *    @p_session: job session
    329  *
    330  *  Return:
    331  *       none
    332  *
    333  *  Description:
    334  *       Destroy a jpeg encode session
    335  *
    336  **/
    337 void mm_jpeg_session_destroy(mm_jpeg_job_session_t* p_session)
    338 {
    339   OMX_ERRORTYPE rc = OMX_ErrorNone;
    340   OMX_STATETYPE state;
    341   mm_jpeg_obj *my_obj = (mm_jpeg_obj *) p_session->jpeg_obj;
    342 
    343   CDBG("%s:%d] E", __func__, __LINE__);
    344   if (NULL == p_session->omx_handle) {
    345     CDBG_ERROR("%s:%d] invalid handle", __func__, __LINE__);
    346     return;
    347   }
    348 
    349   rc = OMX_GetState(p_session->omx_handle, &state);
    350 
    351   //Check state before state transition
    352   if ((state == OMX_StateExecuting) || (state == OMX_StatePause)) {
    353     rc = mm_jpeg_session_change_state(p_session, OMX_StateIdle, NULL);
    354     if (rc) {
    355       CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
    356     }
    357   }
    358 
    359   rc = OMX_GetState(p_session->omx_handle, &state);
    360 
    361   if (state == OMX_StateIdle) {
    362     rc = mm_jpeg_session_change_state(p_session, OMX_StateLoaded,
    363       mm_jpeg_session_free_buffers);
    364     if (rc) {
    365       CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
    366     }
    367   }
    368 
    369   rc = OMX_FreeHandle(p_session->omx_handle);
    370   if (0 != rc) {
    371     CDBG_ERROR("%s:%d] OMX_FreeHandle failed (%d)", __func__, __LINE__, rc);
    372   }
    373   p_session->omx_handle = NULL;
    374 
    375   pthread_mutex_destroy(&p_session->lock);
    376   pthread_cond_destroy(&p_session->cond);
    377 
    378   if (NULL != p_session->meta_enc_key) {
    379     free(p_session->meta_enc_key);
    380     p_session->meta_enc_key = NULL;
    381   }
    382 
    383   my_obj->num_sessions--;
    384 
    385   // Destroy next session
    386   if (p_session->next_session) {
    387     mm_jpeg_session_destroy(p_session->next_session);
    388   }
    389 
    390   CDBG_HIGH("%s:%d] Session destroy successful. X", __func__, __LINE__);
    391 }
    392 
    393 
    394 
    395 /** mm_jpeg_session_config_main_buffer_offset:
    396  *
    397  *  Arguments:
    398  *    @p_session: job session
    399  *
    400  *  Return:
    401  *       OMX error values
    402  *
    403  *  Description:
    404  *       Configure the buffer offsets
    405  *
    406  **/
    407 OMX_ERRORTYPE mm_jpeg_session_config_main_buffer_offset(
    408   mm_jpeg_job_session_t* p_session)
    409 {
    410   OMX_ERRORTYPE rc = 0;
    411   OMX_INDEXTYPE buffer_index;
    412   QOMX_YUV_FRAME_INFO frame_info;
    413   size_t totalSize = 0;
    414   mm_jpeg_encode_params_t *p_params = &p_session->params;
    415 
    416   mm_jpeg_buf_t *p_src_buf =
    417     &p_params->src_main_buf[0];
    418 
    419   memset(&frame_info, 0x0, sizeof(QOMX_YUV_FRAME_INFO));
    420 
    421   frame_info.cbcrStartOffset[0] = p_src_buf->offset.mp[0].len;
    422   frame_info.cbcrStartOffset[1] = p_src_buf->offset.mp[1].len;
    423   frame_info.yOffset = p_src_buf->offset.mp[0].offset;
    424   frame_info.cbcrOffset[0] = p_src_buf->offset.mp[1].offset;
    425   frame_info.cbcrOffset[1] = p_src_buf->offset.mp[2].offset;
    426   totalSize = p_src_buf->buf_size;
    427 
    428   rc = OMX_GetExtensionIndex(p_session->omx_handle,
    429     QOMX_IMAGE_EXT_BUFFER_OFFSET_NAME, &buffer_index);
    430   if (rc != OMX_ErrorNone) {
    431     CDBG_ERROR("%s:%d] Failed", __func__, __LINE__);
    432     return rc;
    433   }
    434 
    435   CDBG_HIGH("%s:%d] yOffset = %d, cbcrOffset = (%d %d), totalSize = %zd,"
    436     "cbcrStartOffset = (%d %d)", __func__, __LINE__,
    437     (int)frame_info.yOffset,
    438     (int)frame_info.cbcrOffset[0],
    439     (int)frame_info.cbcrOffset[1],
    440     totalSize,
    441     (int)frame_info.cbcrStartOffset[0],
    442     (int)frame_info.cbcrStartOffset[1]);
    443 
    444   rc = OMX_SetParameter(p_session->omx_handle, buffer_index, &frame_info);
    445   if (rc != OMX_ErrorNone) {
    446     CDBG_ERROR("%s:%d] Failed", __func__, __LINE__);
    447     return rc;
    448   }
    449   return rc;
    450 }
    451 
    452 /** mm_jpeg_encoding_mode:
    453  *
    454  *  Arguments:
    455  *    @p_session: job session
    456  *
    457  *  Return:
    458  *       OMX error values
    459  *
    460  *  Description:
    461  *       Configure the serial or parallel encoding
    462  *       mode
    463  *
    464  **/
    465 OMX_ERRORTYPE mm_jpeg_encoding_mode(
    466   mm_jpeg_job_session_t* p_session)
    467 {
    468   OMX_ERRORTYPE rc = 0;
    469   OMX_INDEXTYPE indextype;
    470   QOMX_ENCODING_MODE encoding_mode;
    471 
    472   rc = OMX_GetExtensionIndex(p_session->omx_handle,
    473     QOMX_IMAGE_EXT_ENCODING_MODE_NAME, &indextype);
    474   if (rc != OMX_ErrorNone) {
    475     CDBG_ERROR("%s:%d] Failed", __func__, __LINE__);
    476     return rc;
    477   }
    478 
    479   if (ENCODING_MODE_PARALLEL) {
    480     encoding_mode = OMX_Parallel_Encoding;
    481   } else {
    482     encoding_mode = OMX_Serial_Encoding;
    483   }
    484   CDBG("%s:%d] encoding mode = %d ", __func__, __LINE__,
    485     (int)encoding_mode);
    486   rc = OMX_SetParameter(p_session->omx_handle, indextype, &encoding_mode);
    487   if (rc != OMX_ErrorNone) {
    488     CDBG_ERROR("%s:%d] Failed", __func__, __LINE__);
    489     return rc;
    490   }
    491   return rc;
    492 }
    493 
    494 /** mm_jpeg_get_speed:
    495  *
    496  *  Arguments:
    497  *    @p_session: job session
    498  *
    499  *  Return:
    500  *       ops speed type for jpeg
    501  *
    502  *  Description:
    503  *      Configure normal or high speed jpeg
    504  *
    505  **/
    506 QOMX_JPEG_SPEED_MODE mm_jpeg_get_speed(
    507   mm_jpeg_job_session_t* p_session)
    508 {
    509   mm_jpeg_encode_params_t *p_params = &p_session->params;
    510   cam_dimension_t *p_dim = &p_params->main_dim.src_dim;
    511   if (p_params->burst_mode ||
    512     (MM_JPEG_MIN_NOM_RESOLUTION < (p_dim->width * p_dim->height))) {
    513     return QOMX_JPEG_SPEED_MODE_HIGH;
    514   }
    515   return QOMX_JPEG_SPEED_MODE_NORMAL;
    516 }
    517 
    518 /** mm_jpeg_speed_mode:
    519  *
    520  *  Arguments:
    521  *    @p_session: job session
    522  *
    523  *  Return:
    524  *       OMX error values
    525  *
    526  *  Description:
    527  *      Configure normal or high speed jpeg
    528  *
    529  **/
    530 OMX_ERRORTYPE mm_jpeg_speed_mode(
    531   mm_jpeg_job_session_t* p_session)
    532 {
    533   OMX_ERRORTYPE rc = 0;
    534   OMX_INDEXTYPE indextype;
    535   QOMX_JPEG_SPEED jpeg_speed;
    536 
    537   rc = OMX_GetExtensionIndex(p_session->omx_handle,
    538     QOMX_IMAGE_EXT_JPEG_SPEED_NAME, &indextype);
    539   if (rc != OMX_ErrorNone) {
    540     CDBG_ERROR("%s:%d] Failed", __func__, __LINE__);
    541     return rc;
    542   }
    543 
    544   jpeg_speed.speedMode = mm_jpeg_get_speed(p_session);
    545   CDBG_HIGH("%s:%d] speed %d", __func__, __LINE__, jpeg_speed.speedMode);
    546 
    547   rc = OMX_SetParameter(p_session->omx_handle, indextype, &jpeg_speed);
    548   if (rc != OMX_ErrorNone) {
    549     CDBG_ERROR("%s:%d] Failed", __func__, __LINE__);
    550     return rc;
    551   }
    552   return rc;
    553 }
    554 
    555 
    556 /** mm_jpeg_mem_ops:
    557  *
    558  *  Arguments:
    559  *    @p_session: job session
    560  *
    561  *  Return:
    562  *       OMX error values
    563  *
    564  *  Description:
    565  *       Configure the serial or parallel encoding
    566  *       mode
    567  *
    568  **/
    569 OMX_ERRORTYPE mm_jpeg_mem_ops(
    570   mm_jpeg_job_session_t* p_session)
    571 {
    572   OMX_ERRORTYPE rc = 0;
    573   OMX_INDEXTYPE indextype;
    574   QOMX_MEM_OPS mem_ops;
    575   mm_jpeg_encode_params_t *p_params = &p_session->params;
    576 
    577   mem_ops.get_memory = p_params->get_memory;
    578 
    579   rc = OMX_GetExtensionIndex(p_session->omx_handle,
    580     QOMX_IMAGE_EXT_MEM_OPS_NAME, &indextype);
    581   if (rc != OMX_ErrorNone) {
    582     CDBG_ERROR("%s:%d] Failed", __func__, __LINE__);
    583     return rc;
    584   }
    585 
    586   rc = OMX_SetParameter(p_session->omx_handle, indextype, &mem_ops);
    587   if (rc != OMX_ErrorNone) {
    588     CDBG_ERROR("%s:%d] Failed", __func__, __LINE__);
    589     return rc;
    590   }
    591   return rc;
    592 }
    593 
    594 /** mm_jpeg_metadata:
    595  *
    596  *  Arguments:
    597  *    @p_session: job session
    598  *
    599  *  Return:
    600  *       OMX error values
    601  *
    602  *  Description:
    603  *       Pass meta data
    604  *
    605  **/
    606 OMX_ERRORTYPE mm_jpeg_metadata(
    607   mm_jpeg_job_session_t* p_session)
    608 {
    609   OMX_ERRORTYPE rc = OMX_ErrorNone;
    610   OMX_INDEXTYPE indexType;
    611   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
    612   QOMX_METADATA lMeta;
    613 
    614   rc = OMX_GetExtensionIndex(p_session->omx_handle,
    615       QOMX_IMAGE_EXT_METADATA_NAME, &indexType);
    616 
    617   if (rc != OMX_ErrorNone) {
    618     CDBG_ERROR("%s:%d] Failed", __func__, __LINE__);
    619     return rc;
    620   }
    621 
    622   lMeta.metadata = (OMX_U8 *)p_jobparams->p_metadata;
    623   lMeta.metaPayloadSize = sizeof(*p_jobparams->p_metadata);
    624   lMeta.mobicat_mask = p_jobparams->mobicat_mask;
    625 
    626   rc = OMX_SetConfig(p_session->omx_handle, indexType, &lMeta);
    627   if (rc != OMX_ErrorNone) {
    628     CDBG_ERROR("%s:%d] Failed", __func__, __LINE__);
    629     return rc;
    630   }
    631   return OMX_ErrorNone;
    632 }
    633 
    634 /** mm_jpeg_meta_enc_key:
    635  *
    636  *  Arguments:
    637  *    @p_session: job session
    638  *
    639  *  Return:
    640  *       OMX error values
    641  *
    642  *  Description:
    643  *       Pass metadata encrypt key
    644  *
    645  **/
    646 OMX_ERRORTYPE mm_jpeg_meta_enc_key(
    647   mm_jpeg_job_session_t* p_session)
    648 {
    649   OMX_ERRORTYPE rc = OMX_ErrorNone;
    650   OMX_INDEXTYPE indexType;
    651   QOMX_META_ENC_KEY lKey;
    652 
    653   lKey.metaKey = p_session->meta_enc_key;
    654   lKey.keyLen = p_session->meta_enc_keylen;
    655 
    656   if ((!lKey.metaKey) || (!lKey.keyLen)){
    657     CDBG_ERROR("%s:%d] Key is invalid", __func__, __LINE__);
    658     return OMX_ErrorNone;
    659   }
    660 
    661   rc = OMX_GetExtensionIndex(p_session->omx_handle,
    662       QOMX_IMAGE_EXT_META_ENC_KEY_NAME, &indexType);
    663 
    664   if (rc != OMX_ErrorNone) {
    665     CDBG_ERROR("%s:%d] Failed", __func__, __LINE__);
    666     return rc;
    667   }
    668 
    669   rc = OMX_SetConfig(p_session->omx_handle, indexType, &lKey);
    670   if (rc != OMX_ErrorNone) {
    671     CDBG_ERROR("%s:%d] Failed", __func__, __LINE__);
    672     return rc;
    673   }
    674   return OMX_ErrorNone;
    675 }
    676 
    677 /** map_jpeg_format:
    678  *
    679  *  Arguments:
    680  *    @color_fmt: color format
    681  *
    682  *  Return:
    683  *       OMX color format
    684  *
    685  *  Description:
    686  *       Map mmjpeg color format to OMX color format
    687  *
    688  **/
    689 int map_jpeg_format(mm_jpeg_color_format color_fmt)
    690 {
    691   switch (color_fmt) {
    692   case MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2:
    693     return (int)OMX_QCOM_IMG_COLOR_FormatYVU420SemiPlanar;
    694   case MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2:
    695     return (int)OMX_COLOR_FormatYUV420SemiPlanar;
    696   case MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V1:
    697     return (int)OMX_QCOM_IMG_COLOR_FormatYVU422SemiPlanar;
    698   case MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V1:
    699     return (int)OMX_COLOR_FormatYUV422SemiPlanar;
    700   case MM_JPEG_COLOR_FORMAT_YCRCBLP_H1V2:
    701     return (int)OMX_QCOM_IMG_COLOR_FormatYVU422SemiPlanar_h1v2;
    702   case MM_JPEG_COLOR_FORMAT_YCBCRLP_H1V2:
    703     return (int)OMX_QCOM_IMG_COLOR_FormatYUV422SemiPlanar_h1v2;
    704   case MM_JPEG_COLOR_FORMAT_YCRCBLP_H1V1:
    705     return (int)OMX_QCOM_IMG_COLOR_FormatYVU444SemiPlanar;
    706   case MM_JPEG_COLOR_FORMAT_YCBCRLP_H1V1:
    707     return (int)OMX_QCOM_IMG_COLOR_FormatYUV444SemiPlanar;
    708   case MM_JPEG_COLOR_FORMAT_MONOCHROME:
    709      return (int)OMX_COLOR_FormatMonochrome;
    710   default:
    711     CDBG_ERROR("%s:%d] invalid format %d", __func__, __LINE__, color_fmt);
    712     return (int)OMX_QCOM_IMG_COLOR_FormatYVU420SemiPlanar;
    713   }
    714 }
    715 
    716 /** mm_jpeg_session_config_port:
    717  *
    718  *  Arguments:
    719  *    @p_session: job session
    720  *
    721  *  Return:
    722  *       OMX error values
    723  *
    724  *  Description:
    725  *       Configure OMX ports
    726  *
    727  **/
    728 OMX_ERRORTYPE mm_jpeg_session_config_ports(mm_jpeg_job_session_t* p_session)
    729 {
    730   OMX_ERRORTYPE ret = OMX_ErrorNone;
    731   mm_jpeg_encode_params_t *p_params = &p_session->params;
    732   OMX_CONFIG_ROTATIONTYPE rotate;
    733 
    734   mm_jpeg_buf_t *p_src_buf =
    735     &p_params->src_main_buf[0];
    736 
    737   p_session->inputPort.nPortIndex = 0;
    738   p_session->outputPort.nPortIndex = 1;
    739   p_session->inputTmbPort.nPortIndex = 2;
    740 
    741   ret = OMX_GetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
    742     &p_session->inputPort);
    743   if (ret) {
    744     CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
    745     return ret;
    746   }
    747 
    748   ret = OMX_GetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
    749     &p_session->inputTmbPort);
    750   if (ret) {
    751     CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
    752     return ret;
    753   }
    754 
    755   ret = OMX_GetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
    756     &p_session->outputPort);
    757   if (ret) {
    758     CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
    759     return ret;
    760   }
    761 
    762   p_session->inputPort.format.image.nFrameWidth =
    763     (OMX_U32)p_params->main_dim.src_dim.width;
    764   p_session->inputPort.format.image.nFrameHeight =
    765     (OMX_U32)p_params->main_dim.src_dim.height;
    766   p_session->inputPort.format.image.nStride =
    767     p_src_buf->offset.mp[0].stride;
    768   p_session->inputPort.format.image.nSliceHeight =
    769     (OMX_U32)p_src_buf->offset.mp[0].scanline;
    770   p_session->inputPort.format.image.eColorFormat =
    771     map_jpeg_format(p_params->color_format);
    772   p_session->inputPort.nBufferSize =
    773     p_params->src_main_buf[0/*p_jobparams->src_index*/].buf_size;
    774   p_session->inputPort.nBufferCountActual = (OMX_U32)p_params->num_src_bufs;
    775   ret = OMX_SetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
    776     &p_session->inputPort);
    777   if (ret) {
    778     CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
    779     return ret;
    780   }
    781 
    782   if (p_session->params.encode_thumbnail) {
    783     mm_jpeg_buf_t *p_tmb_buf =
    784       &p_params->src_thumb_buf[0];
    785     p_session->inputTmbPort.format.image.nFrameWidth =
    786       (OMX_U32)p_params->thumb_dim.src_dim.width;
    787     p_session->inputTmbPort.format.image.nFrameHeight =
    788       (OMX_U32)p_params->thumb_dim.src_dim.height;
    789     p_session->inputTmbPort.format.image.nStride =
    790       p_tmb_buf->offset.mp[0].stride;
    791     p_session->inputTmbPort.format.image.nSliceHeight =
    792       (OMX_U32)p_tmb_buf->offset.mp[0].scanline;
    793     p_session->inputTmbPort.format.image.eColorFormat =
    794       map_jpeg_format(p_params->thumb_color_format);
    795     p_session->inputTmbPort.nBufferSize =
    796       p_params->src_thumb_buf[0].buf_size;
    797     p_session->inputTmbPort.nBufferCountActual = (OMX_U32)p_params->num_tmb_bufs;
    798 
    799     ret = OMX_SetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
    800       &p_session->inputTmbPort);
    801 
    802     if (ret) {
    803       CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
    804       return ret;
    805     }
    806 
    807     // Enable thumbnail port
    808     ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandPortEnable,
    809         p_session->inputTmbPort.nPortIndex, NULL);
    810 
    811     if (ret) {
    812       CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
    813       return ret;
    814     }
    815   } else {
    816     // Disable thumbnail port
    817     ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandPortDisable,
    818         p_session->inputTmbPort.nPortIndex, NULL);
    819 
    820     if (ret) {
    821       CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
    822       return ret;
    823     }
    824   }
    825 
    826   p_session->outputPort.nBufferSize =
    827     p_params->dest_buf[0].buf_size;
    828   p_session->outputPort.nBufferCountActual = (OMX_U32)p_params->num_dst_bufs;
    829   ret = OMX_SetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
    830     &p_session->outputPort);
    831   if (ret) {
    832     CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
    833     return ret;
    834   }
    835 
    836   /* set rotation */
    837   memset(&rotate, 0, sizeof(rotate));
    838   rotate.nPortIndex = 1;
    839   rotate.nRotation = (OMX_S32)p_params->rotation;
    840   ret = OMX_SetConfig(p_session->omx_handle, OMX_IndexConfigCommonRotate,
    841       &rotate);
    842   if (OMX_ErrorNone != ret) {
    843     CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
    844     return ret;
    845   }
    846   CDBG("%s:%d] Set rotation to %d at port_idx = %d", __func__, __LINE__,
    847       (int)p_params->rotation, (int)rotate.nPortIndex);
    848 
    849   return ret;
    850 }
    851 
    852 /** mm_jpeg_get_thumbnail_crop
    853  *
    854  *  Arguments:
    855  *    @p_thumb_dim: thumbnail dimension
    856  *    @p_main_dim: main image dimension
    857  *    @crop_width : flag indicating if width needs to be cropped
    858  *
    859  *  Return:
    860  *       OMX error values
    861  *
    862  *  Description:
    863  *    If the main image and thumbnail ascpect ratios are differnt,
    864  *    re-calculate the thumbnail crop info to prevent distortion
    865  *
    866  */
    867 OMX_ERRORTYPE mm_jpeg_get_thumbnail_crop(mm_jpeg_dim_t *p_thumb_dim,
    868   mm_jpeg_dim_t *p_main_dim, uint8_t crop_width) {
    869   OMX_ERRORTYPE ret = OMX_ErrorNone;
    870   int cropped_width = 0, cropped_height = 0;
    871 
    872   if (crop_width) {
    873    //Keep height constant
    874    cropped_height = p_thumb_dim->src_dim.height;
    875    cropped_width = floor((cropped_height * p_thumb_dim->dst_dim.width) /
    876       p_thumb_dim->dst_dim.height);
    877   } else {
    878     //Keep width constant
    879     cropped_width = p_thumb_dim->src_dim.width;
    880     cropped_height = floor((cropped_width * p_thumb_dim->dst_dim.height) /
    881       p_thumb_dim->dst_dim.width);
    882   }
    883   p_thumb_dim->crop.left = floor(p_thumb_dim->src_dim.width - cropped_width) / 2;
    884   p_thumb_dim->crop.top = floor(p_thumb_dim->src_dim.height - cropped_height) / 2;
    885   p_thumb_dim->crop.width = cropped_width;
    886   p_thumb_dim->crop.height = cropped_height;
    887 
    888   CDBG_HIGH("%s %d New thumbnail crop: left %d, top %d, crop width %d, crop height %d",
    889     __func__, __LINE__, p_thumb_dim->crop.left, p_thumb_dim->crop.top,
    890     p_thumb_dim->crop.width, p_thumb_dim->crop.height);
    891 
    892   return ret;
    893 }
    894 
    895 /** mm_jpeg_omx_config_thumbnail:
    896  *
    897  *  Arguments:
    898  *    @p_session: job session
    899  *
    900  *  Return:
    901  *       OMX error values
    902  *
    903  *  Description:
    904  *       Configure OMX ports
    905  *
    906  **/
    907 OMX_ERRORTYPE mm_jpeg_session_config_thumbnail(mm_jpeg_job_session_t* p_session)
    908 {
    909   OMX_ERRORTYPE ret = OMX_ErrorNone;
    910   QOMX_THUMBNAIL_INFO thumbnail_info;
    911   OMX_INDEXTYPE thumb_indextype;
    912   mm_jpeg_encode_params_t *p_params = &p_session->params;
    913   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
    914   mm_jpeg_dim_t *p_thumb_dim = &p_jobparams->thumb_dim;
    915   mm_jpeg_dim_t *p_main_dim = &p_jobparams->main_dim;
    916   QOMX_YUV_FRAME_INFO *p_frame_info = &thumbnail_info.tmbOffset;
    917   mm_jpeg_buf_t *p_tmb_buf = &p_params->src_thumb_buf[p_jobparams->thumb_index];
    918 
    919   CDBG_HIGH("%s:%d] encode_thumbnail %u", __func__, __LINE__,
    920     p_params->encode_thumbnail);
    921   if (OMX_FALSE == p_params->encode_thumbnail) {
    922     return ret;
    923   }
    924 
    925   if ((p_thumb_dim->dst_dim.width == 0) || (p_thumb_dim->dst_dim.height == 0)) {
    926     CDBG_ERROR("%s:%d] Error invalid output dim for thumbnail",
    927       __func__, __LINE__);
    928     return OMX_ErrorBadParameter;
    929   }
    930 
    931   if ((p_thumb_dim->src_dim.width == 0) || (p_thumb_dim->src_dim.height == 0)) {
    932     CDBG_ERROR("%s:%d] Error invalid input dim for thumbnail",
    933       __func__, __LINE__);
    934     return OMX_ErrorBadParameter;
    935   }
    936 
    937   if ((p_thumb_dim->crop.width == 0) || (p_thumb_dim->crop.height == 0)) {
    938     p_thumb_dim->crop.width = p_thumb_dim->src_dim.width;
    939     p_thumb_dim->crop.height = p_thumb_dim->src_dim.height;
    940   }
    941 
    942   /* check crop boundary */
    943   if ((p_thumb_dim->crop.width + p_thumb_dim->crop.left > p_thumb_dim->src_dim.width) ||
    944     (p_thumb_dim->crop.height + p_thumb_dim->crop.top > p_thumb_dim->src_dim.height)) {
    945     CDBG_ERROR("%s:%d] invalid crop boundary (%d, %d) offset (%d, %d) out of (%d, %d)",
    946       __func__, __LINE__,
    947       p_thumb_dim->crop.width,
    948       p_thumb_dim->crop.height,
    949       p_thumb_dim->crop.left,
    950       p_thumb_dim->crop.top,
    951       p_thumb_dim->src_dim.width,
    952       p_thumb_dim->src_dim.height);
    953     return OMX_ErrorBadParameter;
    954   }
    955 
    956   memset(&thumbnail_info, 0x0, sizeof(QOMX_THUMBNAIL_INFO));
    957   ret = OMX_GetExtensionIndex(p_session->omx_handle,
    958     QOMX_IMAGE_EXT_THUMBNAIL_NAME,
    959     &thumb_indextype);
    960   if (ret) {
    961     CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
    962     return ret;
    963   }
    964 
    965   /* fill thumbnail info */
    966   thumbnail_info.scaling_enabled = 1;
    967   thumbnail_info.input_width = (OMX_U32)p_thumb_dim->src_dim.width;
    968   thumbnail_info.input_height = (OMX_U32)p_thumb_dim->src_dim.height;
    969   thumbnail_info.rotation = (OMX_U32)p_params->thumb_rotation;
    970   thumbnail_info.quality = (OMX_U32)p_params->thumb_quality;
    971   thumbnail_info.output_width = (OMX_U32)p_thumb_dim->dst_dim.width;
    972   thumbnail_info.output_height = (OMX_U32)p_thumb_dim->dst_dim.height;
    973 
    974   if (p_session->thumb_from_main) {
    975     if ((p_session->params.thumb_rotation == 90 ||
    976       p_session->params.thumb_rotation == 270) &&
    977       (p_session->params.rotation == 0 ||
    978       p_session->params.rotation == 180)) {
    979 
    980       thumbnail_info.output_width = (OMX_U32)p_thumb_dim->dst_dim.height;
    981       thumbnail_info.output_height = (OMX_U32)p_thumb_dim->dst_dim.width;
    982       thumbnail_info.rotation = p_session->params.rotation;
    983     }
    984   } else if ((p_thumb_dim->dst_dim.width > p_thumb_dim->src_dim.width) ||
    985     (p_thumb_dim->dst_dim.height > p_thumb_dim->src_dim.height)) {
    986     CDBG_ERROR("%s:%d] Incorrect thumbnail dim %dx%d resetting to %dx%d",
    987       __func__, __LINE__, p_thumb_dim->dst_dim.width,
    988       p_thumb_dim->dst_dim.height, p_thumb_dim->src_dim.width,
    989       p_thumb_dim->src_dim.height);
    990     thumbnail_info.output_width = (OMX_U32)p_thumb_dim->src_dim.width;
    991     thumbnail_info.output_height = (OMX_U32)p_thumb_dim->src_dim.height;
    992   }
    993 
    994   //If the main image and thumbnail aspect ratio are different, reset the
    995   // thumbnail crop info to avoid distortion
    996   double main_aspect_ratio = (double)p_main_dim->dst_dim.width /
    997     (double)p_main_dim->dst_dim.height;
    998   double thumb_aspect_ratio = (double)thumbnail_info.output_width /
    999     (double)thumbnail_info.output_height;
   1000 
   1001   if ((thumb_aspect_ratio - main_aspect_ratio) > ASPECT_TOLERANCE) {
   1002     mm_jpeg_get_thumbnail_crop(p_thumb_dim, p_main_dim, 0);
   1003   } else if((main_aspect_ratio - thumb_aspect_ratio) > ASPECT_TOLERANCE){
   1004     mm_jpeg_get_thumbnail_crop(p_thumb_dim, p_main_dim, 1);
   1005   }
   1006 
   1007   //Fill thumbnail crop info
   1008   thumbnail_info.crop_info.nWidth = (OMX_U32)p_thumb_dim->crop.width;
   1009   thumbnail_info.crop_info.nHeight = (OMX_U32)p_thumb_dim->crop.height;
   1010   thumbnail_info.crop_info.nLeft = p_thumb_dim->crop.left;
   1011   thumbnail_info.crop_info.nTop = p_thumb_dim->crop.top;
   1012 
   1013   //If main image cropping/scaling is enabled, thumb FOV should be within
   1014   //main image FOV
   1015   if ((p_main_dim->crop.width != p_main_dim->src_dim.width) ||
   1016     (p_main_dim->crop.height != p_main_dim->src_dim.height)) {
   1017     if ((p_thumb_dim->crop.left < p_main_dim->crop.left) ||
   1018       ((p_thumb_dim->crop.left + p_thumb_dim->crop.width) >
   1019       (p_main_dim->crop.left + p_main_dim->crop.width)) ||
   1020       (p_thumb_dim->crop.top < p_main_dim->crop.top) ||
   1021       ((p_thumb_dim->crop.top + p_thumb_dim->crop.height) >
   1022       (p_main_dim->crop.top + p_main_dim->crop.height))) {
   1023        //Reset the FOV for the thumbnail
   1024        CDBG_HIGH("%s:%d] Resetting the thumbnail FOV wrt main image",
   1025          __func__, __LINE__);
   1026        thumbnail_info.crop_info.nLeft = p_main_dim->crop.left;
   1027        thumbnail_info.crop_info.nTop = p_main_dim->crop.height;
   1028        if ((p_thumb_dim->crop.width > p_main_dim->crop.width) ||
   1029          (p_thumb_dim->crop.height > p_main_dim->crop.height)) {
   1030          thumbnail_info.crop_info.nWidth = p_main_dim->crop.width;
   1031          thumbnail_info.crop_info.nHeight = p_main_dim->crop.height;
   1032        }
   1033      }
   1034   }
   1035 
   1036   memset(p_frame_info, 0x0, sizeof(*p_frame_info));
   1037 
   1038   p_frame_info->cbcrStartOffset[0] = p_tmb_buf->offset.mp[0].len;
   1039   p_frame_info->cbcrStartOffset[1] = p_tmb_buf->offset.mp[1].len;
   1040   p_frame_info->yOffset = p_tmb_buf->offset.mp[0].offset;
   1041   p_frame_info->cbcrOffset[0] = p_tmb_buf->offset.mp[1].offset;
   1042   p_frame_info->cbcrOffset[1] = p_tmb_buf->offset.mp[2].offset;
   1043 
   1044   ret = OMX_SetConfig(p_session->omx_handle, thumb_indextype,
   1045     &thumbnail_info);
   1046   if (ret) {
   1047     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
   1048     return ret;
   1049   }
   1050 
   1051   return ret;
   1052 }
   1053 
   1054 /** mm_jpeg_session_config_main_crop:
   1055  *
   1056  *  Arguments:
   1057  *    @p_session: job session
   1058  *
   1059  *  Return:
   1060  *       OMX error values
   1061  *
   1062  *  Description:
   1063  *       Configure main image crop
   1064  *
   1065  **/
   1066 OMX_ERRORTYPE mm_jpeg_session_config_main_crop(mm_jpeg_job_session_t *p_session)
   1067 {
   1068   OMX_CONFIG_RECTTYPE rect_type_in, rect_type_out;
   1069   OMX_ERRORTYPE ret = OMX_ErrorNone;
   1070   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
   1071   mm_jpeg_dim_t *dim = &p_jobparams->main_dim;
   1072 
   1073   if ((dim->crop.width == 0) || (dim->crop.height == 0)) {
   1074     dim->crop.width = dim->src_dim.width;
   1075     dim->crop.height = dim->src_dim.height;
   1076   }
   1077   /* error check first */
   1078   if ((dim->crop.width + dim->crop.left > dim->src_dim.width) ||
   1079     (dim->crop.height + dim->crop.top > dim->src_dim.height)) {
   1080     CDBG_ERROR("%s:%d] invalid crop boundary (%d, %d) out of (%d, %d)",
   1081       __func__, __LINE__,
   1082       dim->crop.width + dim->crop.left,
   1083       dim->crop.height + dim->crop.top,
   1084       dim->src_dim.width,
   1085       dim->src_dim.height);
   1086     return OMX_ErrorBadParameter;
   1087   }
   1088 
   1089   memset(&rect_type_in, 0, sizeof(rect_type_in));
   1090   memset(&rect_type_out, 0, sizeof(rect_type_out));
   1091   rect_type_in.nPortIndex = 0;
   1092   rect_type_out.nPortIndex = 0;
   1093 
   1094   if ((dim->src_dim.width != dim->crop.width) ||
   1095     (dim->src_dim.height != dim->crop.height) ||
   1096     (dim->src_dim.width != dim->dst_dim.width) ||
   1097     (dim->src_dim.height != dim->dst_dim.height)) {
   1098     /* Scaler information */
   1099     rect_type_in.nWidth = CEILING2(dim->crop.width);
   1100     rect_type_in.nHeight = CEILING2(dim->crop.height);
   1101     rect_type_in.nLeft = dim->crop.left;
   1102     rect_type_in.nTop = dim->crop.top;
   1103 
   1104     if (dim->dst_dim.width && dim->dst_dim.height) {
   1105       rect_type_out.nWidth = (OMX_U32)dim->dst_dim.width;
   1106       rect_type_out.nHeight = (OMX_U32)dim->dst_dim.height;
   1107     }
   1108   }
   1109 
   1110   ret = OMX_SetConfig(p_session->omx_handle, OMX_IndexConfigCommonInputCrop,
   1111     &rect_type_in);
   1112   if (OMX_ErrorNone != ret) {
   1113     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
   1114     return ret;
   1115   }
   1116 
   1117   CDBG_HIGH("%s:%d] OMX_IndexConfigCommonInputCrop w = %d, h = %d, l = %d, t = %d,"
   1118     " port_idx = %d", __func__, __LINE__,
   1119     (int)rect_type_in.nWidth, (int)rect_type_in.nHeight,
   1120     (int)rect_type_in.nLeft, (int)rect_type_in.nTop,
   1121     (int)rect_type_in.nPortIndex);
   1122 
   1123   ret = OMX_SetConfig(p_session->omx_handle, OMX_IndexConfigCommonOutputCrop,
   1124     &rect_type_out);
   1125   if (OMX_ErrorNone != ret) {
   1126     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
   1127     return ret;
   1128   }
   1129   CDBG("%s:%d] OMX_IndexConfigCommonOutputCrop w = %d, h = %d,"
   1130     " port_idx = %d", __func__, __LINE__,
   1131     (int)rect_type_out.nWidth, (int)rect_type_out.nHeight,
   1132     (int)rect_type_out.nPortIndex);
   1133 
   1134   return ret;
   1135 }
   1136 
   1137 /** mm_jpeg_session_config_main:
   1138  *
   1139  *  Arguments:
   1140  *    @p_session: job session
   1141  *
   1142  *  Return:
   1143  *       OMX error values
   1144  *
   1145  *  Description:
   1146  *       Configure main image
   1147  *
   1148  **/
   1149 OMX_ERRORTYPE mm_jpeg_session_config_main(mm_jpeg_job_session_t *p_session)
   1150 {
   1151   OMX_ERRORTYPE rc = OMX_ErrorNone;
   1152 
   1153   /* config port */
   1154   CDBG_HIGH("%s:%d] config port", __func__, __LINE__);
   1155   rc = mm_jpeg_session_config_ports(p_session);
   1156   if (OMX_ErrorNone != rc) {
   1157     CDBG_ERROR("%s: config port failed", __func__);
   1158     return rc;
   1159   }
   1160 
   1161   /* config buffer offset */
   1162   CDBG("%s:%d] config main buf offset", __func__, __LINE__);
   1163   rc = mm_jpeg_session_config_main_buffer_offset(p_session);
   1164   if (OMX_ErrorNone != rc) {
   1165     CDBG_ERROR("%s: config buffer offset failed", __func__);
   1166     return rc;
   1167   }
   1168 
   1169   /* set the encoding mode */
   1170   rc = mm_jpeg_encoding_mode(p_session);
   1171   if (OMX_ErrorNone != rc) {
   1172     CDBG_ERROR("%s: config encoding mode failed", __func__);
   1173     return rc;
   1174   }
   1175 
   1176   /* set the metadata encrypt key */
   1177   rc = mm_jpeg_meta_enc_key(p_session);
   1178   if (OMX_ErrorNone != rc) {
   1179     CDBG_ERROR("%s: config session failed", __func__);
   1180     return rc;
   1181   }
   1182 
   1183   /* set the mem ops */
   1184   rc = mm_jpeg_mem_ops(p_session);
   1185   if (OMX_ErrorNone != rc) {
   1186     CDBG_ERROR("%s: config mem ops failed", __func__);
   1187     return rc;
   1188   }
   1189   /* set the jpeg speed mode */
   1190   rc = mm_jpeg_speed_mode(p_session);
   1191   if (OMX_ErrorNone != rc) {
   1192     CDBG_ERROR("%s: config speed mode failed", __func__);
   1193     return rc;
   1194   }
   1195 
   1196   return rc;
   1197 }
   1198 
   1199 /** mm_jpeg_session_config_common:
   1200  *
   1201  *  Arguments:
   1202  *    @p_session: job session
   1203  *
   1204  *  Return:
   1205  *       OMX error values
   1206  *
   1207  *  Description:
   1208  *       Configure common parameters
   1209  *
   1210  **/
   1211 OMX_ERRORTYPE mm_jpeg_session_config_common(mm_jpeg_job_session_t *p_session)
   1212 {
   1213   OMX_ERRORTYPE rc = OMX_ErrorNone;
   1214   OMX_INDEXTYPE exif_idx;
   1215   OMX_CONFIG_ROTATIONTYPE rotate;
   1216   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
   1217   QOMX_EXIF_INFO exif_info;
   1218 
   1219   /* set rotation */
   1220   memset(&rotate, 0, sizeof(rotate));
   1221   rotate.nPortIndex = 1;
   1222   rotate.nRotation = (OMX_S32)p_jobparams->rotation;
   1223   rc = OMX_SetConfig(p_session->omx_handle, OMX_IndexConfigCommonRotate,
   1224     &rotate);
   1225   if (OMX_ErrorNone != rc) {
   1226       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, rc);
   1227       return rc;
   1228   }
   1229   CDBG("%s:%d] Set rotation to %d at port_idx = %d", __func__, __LINE__,
   1230     (int)p_jobparams->rotation, (int)rotate.nPortIndex);
   1231 
   1232   /* Set Exif data*/
   1233   memset(&p_session->exif_info_local[0], 0, sizeof(p_session->exif_info_local));
   1234   rc = OMX_GetExtensionIndex(p_session->omx_handle, QOMX_IMAGE_EXT_EXIF_NAME,
   1235     &exif_idx);
   1236   if (OMX_ErrorNone != rc) {
   1237     CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, rc);
   1238     return rc;
   1239   }
   1240 
   1241   CDBG("%s:%d] Num of exif entries passed from HAL: %d", __func__, __LINE__,
   1242       (int)p_jobparams->exif_info.numOfEntries);
   1243   if (p_jobparams->exif_info.numOfEntries > 0) {
   1244     rc = OMX_SetConfig(p_session->omx_handle, exif_idx,
   1245         &p_jobparams->exif_info);
   1246     if (OMX_ErrorNone != rc) {
   1247       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, rc);
   1248       return rc;
   1249     }
   1250   }
   1251   /*parse aditional exif data from the metadata*/
   1252   exif_info.numOfEntries = 0;
   1253   exif_info.exif_data = &p_session->exif_info_local[0];
   1254   process_meta_data(p_jobparams->p_metadata, &exif_info,
   1255     &p_jobparams->cam_exif_params, p_jobparams->hal_version);
   1256   /* After Parse metadata */
   1257   p_session->exif_count_local = (int)exif_info.numOfEntries;
   1258 
   1259   if (exif_info.numOfEntries > 0) {
   1260     /* set exif tags */
   1261     CDBG("%s:%d] exif tags from metadata count %d", __func__, __LINE__,
   1262       (int)exif_info.numOfEntries);
   1263 
   1264     rc = OMX_SetConfig(p_session->omx_handle, exif_idx,
   1265       &exif_info);
   1266     if (OMX_ErrorNone != rc) {
   1267       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, rc);
   1268       return rc;
   1269     }
   1270   }
   1271 
   1272   return rc;
   1273 }
   1274 
   1275 
   1276 
   1277 
   1278 /** mm_jpeg_session_abort:
   1279  *
   1280  *  Arguments:
   1281  *    @p_session: jpeg session
   1282  *
   1283  *  Return:
   1284  *       OMX_BOOL
   1285  *
   1286  *  Description:
   1287  *       Abort ongoing job
   1288  *
   1289  **/
   1290 OMX_BOOL mm_jpeg_session_abort(mm_jpeg_job_session_t *p_session)
   1291 {
   1292   OMX_ERRORTYPE ret = OMX_ErrorNone;
   1293   int rc = 0;
   1294 
   1295   CDBG("%s:%d] E", __func__, __LINE__);
   1296   pthread_mutex_lock(&p_session->lock);
   1297   if (MM_JPEG_ABORT_NONE != p_session->abort_state) {
   1298     pthread_mutex_unlock(&p_session->lock);
   1299     CDBG_HIGH("%s:%d] **** ALREADY ABORTED", __func__, __LINE__);
   1300     return 0;
   1301   }
   1302   p_session->abort_state = MM_JPEG_ABORT_INIT;
   1303   if (OMX_TRUE == p_session->encoding) {
   1304     p_session->state_change_pending = OMX_TRUE;
   1305 
   1306     CDBG_HIGH("%s:%d] **** ABORTING", __func__, __LINE__);
   1307     pthread_mutex_unlock(&p_session->lock);
   1308 
   1309     ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandStateSet,
   1310     OMX_StateIdle, NULL);
   1311 
   1312     if (ret != OMX_ErrorNone) {
   1313       CDBG_ERROR("%s:%d] OMX_SendCommand returned error %d", __func__, __LINE__, ret);
   1314       return 1;
   1315     }
   1316     rc = mm_jpegenc_destroy_job(p_session);
   1317     if (rc != 0) {
   1318       CDBG_ERROR("%s:%d] Destroy job returned error %d", __func__, __LINE__, rc);
   1319     }
   1320 
   1321     pthread_mutex_lock(&p_session->lock);
   1322     if (MM_JPEG_ABORT_INIT == p_session->abort_state) {
   1323       CDBG("%s:%d] before wait", __func__, __LINE__);
   1324       pthread_cond_wait(&p_session->cond, &p_session->lock);
   1325     }
   1326     CDBG("%s:%d] after wait", __func__, __LINE__);
   1327   }
   1328   p_session->abort_state = MM_JPEG_ABORT_DONE;
   1329   pthread_mutex_unlock(&p_session->lock);
   1330 
   1331 
   1332   // Abort next session
   1333   if (p_session->next_session) {
   1334     mm_jpeg_session_abort(p_session->next_session);
   1335   }
   1336 
   1337   CDBG("%s:%d] X", __func__, __LINE__);
   1338   return 0;
   1339 }
   1340 
   1341 
   1342 /** mm_jpeg_configure_params
   1343  *
   1344  *  Arguments:
   1345  *    @p_session: encode session
   1346  *
   1347  *  Return:
   1348  *       none
   1349  *
   1350  *  Description:
   1351  *       Configure the job specific params
   1352  *
   1353  **/
   1354 static OMX_ERRORTYPE mm_jpeg_configure_job_params(
   1355   mm_jpeg_job_session_t *p_session)
   1356 {
   1357   OMX_ERRORTYPE ret = OMX_ErrorNone;
   1358   OMX_IMAGE_PARAM_QFACTORTYPE q_factor;
   1359   QOMX_WORK_BUFFER work_buffer;
   1360   OMX_INDEXTYPE work_buffer_index;
   1361   mm_jpeg_encode_params_t *p_params = &p_session->params;
   1362   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
   1363   int i;
   1364 
   1365   /* common config */
   1366   ret = mm_jpeg_session_config_common(p_session);
   1367   if (OMX_ErrorNone != ret) {
   1368     CDBG_ERROR("%s:%d] config common failed", __func__, __LINE__);
   1369 
   1370   }
   1371 
   1372   /* config Main Image crop */
   1373   CDBG("%s:%d] config main crop", __func__, __LINE__);
   1374   ret = mm_jpeg_session_config_main_crop(p_session);
   1375   if (OMX_ErrorNone != ret) {
   1376     CDBG_ERROR("%s: config crop failed", __func__);
   1377     return ret;
   1378   }
   1379 
   1380   /* set quality */
   1381   memset(&q_factor, 0, sizeof(q_factor));
   1382   q_factor.nPortIndex = 0;
   1383   q_factor.nQFactor = p_params->quality;
   1384   ret = OMX_SetConfig(p_session->omx_handle, OMX_IndexParamQFactor, &q_factor);
   1385   CDBG("%s:%d] config QFactor: %d", __func__, __LINE__, (int)q_factor.nQFactor);
   1386   if (OMX_ErrorNone != ret) {
   1387     CDBG_ERROR("%s:%d] Error setting Q factor %d", __func__, __LINE__, ret);
   1388     return ret;
   1389   }
   1390 
   1391   /* config thumbnail */
   1392   ret = mm_jpeg_session_config_thumbnail(p_session);
   1393   if (OMX_ErrorNone != ret) {
   1394     CDBG_ERROR("%s:%d] config thumbnail img failed", __func__, __LINE__);
   1395     return ret;
   1396   }
   1397 
   1398   //Pass the ION buffer to be used as o/p for HW
   1399   memset(&work_buffer, 0x0, sizeof(QOMX_WORK_BUFFER));
   1400   ret = OMX_GetExtensionIndex(p_session->omx_handle,
   1401     QOMX_IMAGE_EXT_WORK_BUFFER_NAME,
   1402     &work_buffer_index);
   1403   if (ret) {
   1404     CDBG_ERROR("%s:%d] Error getting work buffer index %d",
   1405       __func__, __LINE__, ret);
   1406     return ret;
   1407   }
   1408   work_buffer.fd = p_session->work_buffer.p_pmem_fd;
   1409   work_buffer.vaddr = p_session->work_buffer.addr;
   1410   work_buffer.length = (uint32_t)p_session->work_buffer.size;
   1411   CDBG_ERROR("%s:%d] Work buffer %d %p WorkBufSize: %d", __func__, __LINE__,
   1412     work_buffer.fd, work_buffer.vaddr, work_buffer.length);
   1413 
   1414   ret = OMX_SetConfig(p_session->omx_handle, work_buffer_index,
   1415     &work_buffer);
   1416   if (ret) {
   1417     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
   1418     return ret;
   1419   }
   1420 
   1421   /* set metadata */
   1422   ret = mm_jpeg_metadata(p_session);
   1423   if (OMX_ErrorNone != ret) {
   1424     CDBG_ERROR("%s: config makernote data failed", __func__);
   1425     return ret;
   1426   }
   1427 
   1428   /* set QTable */
   1429   for (i = 0; i < QTABLE_MAX; i++) {
   1430     if (p_jobparams->qtable_set[i]) {
   1431       ret = OMX_SetConfig(p_session->omx_handle,
   1432         OMX_IndexParamQuantizationTable, &p_jobparams->qtable[i]);
   1433       if (OMX_ErrorNone != ret) {
   1434         CDBG_ERROR("%s:%d] set QTable Error", __func__, __LINE__);
   1435         return ret;
   1436       }
   1437     }
   1438   }
   1439 
   1440   return ret;
   1441 }
   1442 
   1443 /** mm_jpeg_session_configure:
   1444  *
   1445  *  Arguments:
   1446  *    @data: encode session
   1447  *
   1448  *  Return:
   1449  *       none
   1450  *
   1451  *  Description:
   1452  *       Configure the session
   1453  *
   1454  **/
   1455 static OMX_ERRORTYPE mm_jpeg_session_configure(mm_jpeg_job_session_t *p_session)
   1456 {
   1457   OMX_ERRORTYPE ret = OMX_ErrorNone;
   1458 
   1459   CDBG("%s:%d] E ", __func__, __LINE__);
   1460 
   1461   MM_JPEG_CHK_ABORT(p_session, ret, error);
   1462 
   1463   /* config main img */
   1464   ret = mm_jpeg_session_config_main(p_session);
   1465   if (OMX_ErrorNone != ret) {
   1466     CDBG_ERROR("%s:%d] config main img failed", __func__, __LINE__);
   1467     goto error;
   1468   }
   1469   ret = mm_jpeg_session_change_state(p_session, OMX_StateIdle,
   1470     mm_jpeg_session_send_buffers);
   1471   if (ret) {
   1472     CDBG_ERROR("%s:%d] change state to idle failed %d",
   1473       __func__, __LINE__, ret);
   1474     goto error;
   1475   }
   1476 
   1477   ret = mm_jpeg_session_change_state(p_session, OMX_StateExecuting,
   1478     NULL);
   1479   if (ret) {
   1480     CDBG_ERROR("%s:%d] change state to executing failed %d",
   1481       __func__, __LINE__, ret);
   1482     goto error;
   1483   }
   1484 
   1485 error:
   1486   CDBG("%s:%d] X ret %d", __func__, __LINE__, ret);
   1487   return ret;
   1488 }
   1489 
   1490 
   1491 
   1492 
   1493 
   1494 
   1495 /** mm_jpeg_session_encode:
   1496  *
   1497  *  Arguments:
   1498  *    @p_session: encode session
   1499  *
   1500  *  Return:
   1501  *       OMX_ERRORTYPE
   1502  *
   1503  *  Description:
   1504  *       Start the encoding
   1505  *
   1506  **/
   1507 static OMX_ERRORTYPE mm_jpeg_session_encode(mm_jpeg_job_session_t *p_session)
   1508 {
   1509   OMX_ERRORTYPE ret = OMX_ErrorNone;
   1510   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
   1511 
   1512   pthread_mutex_lock(&p_session->lock);
   1513   p_session->abort_state = MM_JPEG_ABORT_NONE;
   1514   p_session->encoding = OMX_FALSE;
   1515   pthread_mutex_unlock(&p_session->lock);
   1516 
   1517   if (p_session->thumb_from_main) {
   1518     if (0 > p_jobparams->src_index) {
   1519       CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
   1520       ret = OMX_ErrorUnsupportedIndex;
   1521       goto error;
   1522     }
   1523     p_jobparams->thumb_index = (uint32_t)p_jobparams->src_index;
   1524     p_jobparams->thumb_dim.crop = p_jobparams->main_dim.crop;
   1525   }
   1526 
   1527   if (OMX_FALSE == p_session->config) {
   1528     ret = mm_jpeg_session_configure(p_session);
   1529     if (ret) {
   1530       CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
   1531       goto error;
   1532     }
   1533     p_session->config = OMX_TRUE;
   1534   }
   1535 
   1536   ret = mm_jpeg_configure_job_params(p_session);
   1537   if (ret) {
   1538       CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
   1539       goto error;
   1540   }
   1541   pthread_mutex_lock(&p_session->lock);
   1542   p_session->encoding = OMX_TRUE;
   1543   pthread_mutex_unlock(&p_session->lock);
   1544 
   1545   MM_JPEG_CHK_ABORT(p_session, ret, error);
   1546 
   1547 #ifdef MM_JPEG_DUMP_INPUT
   1548   char filename[256];
   1549   snprintf(filename, sizeof(filename),
   1550       QCAMERA_DUMP_FRM_LOCATION"jpeg/mm_jpeg_int%d.yuv", p_session->ebd_count);
   1551   DUMP_TO_FILE(filename,
   1552     p_session->p_in_omx_buf[p_jobparams->src_index]->pBuffer,
   1553     (size_t)p_session->p_in_omx_buf[p_jobparams->src_index]->nAllocLen);
   1554 #endif
   1555 
   1556   ret = OMX_EmptyThisBuffer(p_session->omx_handle,
   1557     p_session->p_in_omx_buf[p_jobparams->src_index]);
   1558   if (ret) {
   1559     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
   1560     goto error;
   1561   }
   1562 
   1563   if (p_session->params.encode_thumbnail) {
   1564 #ifdef MM_JPEG_DUMP_INPUT
   1565   char thumb_filename[FILENAME_MAX];
   1566   snprintf(thumb_filename, sizeof(thumb_filename),
   1567     QCAMERA_DUMP_FRM_LOCATION"jpeg/mm_jpeg_int_t%d.yuv", p_session->ebd_count);
   1568   DUMP_TO_FILE(filename,
   1569     p_session->p_in_omx_thumb_buf[p_jobparams->thumb_index]->pBuffer,
   1570     (size_t)p_session->p_in_omx_thumb_buf[p_jobparams->thumb_index]->nAllocLen);
   1571 #endif
   1572     ret = OMX_EmptyThisBuffer(p_session->omx_handle,
   1573         p_session->p_in_omx_thumb_buf[p_jobparams->thumb_index]);
   1574     if (ret) {
   1575       CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
   1576       goto error;
   1577     }
   1578   }
   1579 
   1580   ret = OMX_FillThisBuffer(p_session->omx_handle,
   1581     p_session->p_out_omx_buf[p_jobparams->dst_index]);
   1582   if (ret) {
   1583     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
   1584     goto error;
   1585   }
   1586 
   1587   MM_JPEG_CHK_ABORT(p_session, ret, error);
   1588 
   1589 error:
   1590 
   1591   CDBG("%s:%d] X ", __func__, __LINE__);
   1592   return ret;
   1593 }
   1594 
   1595 /** mm_jpeg_process_encoding_job:
   1596  *
   1597  *  Arguments:
   1598  *    @my_obj: jpeg client
   1599  *    @job_node: job node
   1600  *
   1601  *  Return:
   1602  *       0 for success -1 otherwise
   1603  *
   1604  *  Description:
   1605  *       Start the encoding job
   1606  *
   1607  **/
   1608 int32_t mm_jpeg_process_encoding_job(mm_jpeg_obj *my_obj, mm_jpeg_job_q_node_t* job_node)
   1609 {
   1610   mm_jpeg_q_data_t qdata;
   1611   int32_t rc = 0;
   1612   OMX_ERRORTYPE ret = OMX_ErrorNone;
   1613   mm_jpeg_job_session_t *p_session = NULL;
   1614   uint32_t buf_idx;
   1615 
   1616   /* check if valid session */
   1617   p_session = mm_jpeg_get_session(my_obj, job_node->enc_info.job_id);
   1618   if (NULL == p_session) {
   1619     CDBG_ERROR("%s:%d] invalid job id %x", __func__, __LINE__,
   1620         job_node->enc_info.job_id);
   1621     return -1;
   1622   }
   1623 
   1624   CDBG("%s:%d] before dequeue session %d",
   1625                 __func__, __LINE__, ret);
   1626 
   1627   /* dequeue available omx handle */
   1628   qdata = mm_jpeg_queue_deq(p_session->session_handle_q);
   1629   p_session = qdata.p;
   1630 
   1631   if (NULL == p_session) {
   1632     CDBG_HIGH("%s:%d] No available sessions %d",
   1633           __func__, __LINE__, ret);
   1634     /* No available handles */
   1635     qdata.p = job_node;
   1636     mm_jpeg_queue_enq_head(&my_obj->job_mgr.job_queue, qdata);
   1637 
   1638     CDBG_HIGH("%s:%d]end enqueue %d",
   1639               __func__, __LINE__, ret);
   1640     return rc;
   1641 
   1642   }
   1643 
   1644   p_session->auto_out_buf = OMX_FALSE;
   1645   if (job_node->enc_info.encode_job.dst_index < 0) {
   1646     /* dequeue available output buffer idx */
   1647     qdata = mm_jpeg_queue_deq(p_session->out_buf_q);
   1648     buf_idx = qdata.u32;
   1649 
   1650     if (0U == buf_idx) {
   1651       CDBG_ERROR("%s:%d] No available output buffers %d",
   1652           __func__, __LINE__, ret);
   1653       return OMX_ErrorUndefined;
   1654     }
   1655 
   1656     buf_idx--;
   1657 
   1658     job_node->enc_info.encode_job.dst_index = (int32_t)buf_idx;
   1659     p_session->auto_out_buf = OMX_TRUE;
   1660   }
   1661 
   1662   /* sent encode cmd to OMX, queue job into ongoing queue */
   1663   qdata.p = job_node;
   1664   rc = mm_jpeg_queue_enq(&my_obj->ongoing_job_q, qdata);
   1665   if (rc) {
   1666     CDBG_ERROR("%s:%d] jpeg enqueue failed %d",
   1667       __func__, __LINE__, ret);
   1668     goto error;
   1669   }
   1670 
   1671   p_session->encode_job = job_node->enc_info.encode_job;
   1672   p_session->jobId = job_node->enc_info.job_id;
   1673   ret = mm_jpeg_session_encode(p_session);
   1674   if (ret) {
   1675     CDBG_ERROR("%s:%d] encode session failed", __func__, __LINE__);
   1676     goto error;
   1677   }
   1678 
   1679   CDBG_HIGH("%s:%d] Success X ", __func__, __LINE__);
   1680   return rc;
   1681 
   1682 error:
   1683 
   1684   if ((OMX_ErrorNone != ret) &&
   1685     (NULL != p_session->params.jpeg_cb)) {
   1686     p_session->job_status = JPEG_JOB_STATUS_ERROR;
   1687     CDBG_ERROR("%s:%d] send jpeg error callback %d", __func__, __LINE__,
   1688       p_session->job_status);
   1689     p_session->params.jpeg_cb(p_session->job_status,
   1690       p_session->client_hdl,
   1691       p_session->jobId,
   1692       NULL,
   1693       p_session->params.userdata);
   1694   }
   1695 
   1696   /*remove the job*/
   1697   mm_jpegenc_job_done(p_session);
   1698   CDBG("%s:%d] Error X ", __func__, __LINE__);
   1699 
   1700   return rc;
   1701 }
   1702 
   1703 
   1704 
   1705 /** mm_jpeg_jobmgr_thread:
   1706  *
   1707  *  Arguments:
   1708  *    @my_obj: jpeg object
   1709  *
   1710  *  Return:
   1711  *       0 for success else failure
   1712  *
   1713  *  Description:
   1714  *       job manager thread main function
   1715  *
   1716  **/
   1717 static void *mm_jpeg_jobmgr_thread(void *data)
   1718 {
   1719   mm_jpeg_q_data_t qdata;
   1720   int rc = 0;
   1721   int running = 1;
   1722   uint32_t num_ongoing_jobs = 0;
   1723   mm_jpeg_obj *my_obj = (mm_jpeg_obj*)data;
   1724   mm_jpeg_job_cmd_thread_t *cmd_thread = &my_obj->job_mgr;
   1725   mm_jpeg_job_q_node_t* node = NULL;
   1726   prctl(PR_SET_NAME, (unsigned long)"mm_jpeg_thread", 0, 0, 0);
   1727 
   1728   do {
   1729     do {
   1730       rc = cam_sem_wait(&cmd_thread->job_sem);
   1731       if (rc != 0 && errno != EINVAL) {
   1732         CDBG_ERROR("%s: cam_sem_wait error (%s)",
   1733           __func__, strerror(errno));
   1734         return NULL;
   1735       }
   1736     } while (rc != 0);
   1737 
   1738     /* check ongoing q size */
   1739     num_ongoing_jobs = mm_jpeg_queue_get_size(&my_obj->ongoing_job_q);
   1740     if (num_ongoing_jobs >= NUM_MAX_JPEG_CNCURRENT_JOBS) {
   1741       CDBG("%s:%d] ongoing job already reach max %d", __func__,
   1742         __LINE__, num_ongoing_jobs);
   1743       continue;
   1744     }
   1745 
   1746     pthread_mutex_lock(&my_obj->job_lock);
   1747     /* can go ahead with new work */
   1748     qdata = mm_jpeg_queue_deq(&cmd_thread->job_queue);
   1749     node = (mm_jpeg_job_q_node_t*)qdata.p;
   1750     if (node != NULL) {
   1751       switch (node->type) {
   1752       case MM_JPEG_CMD_TYPE_JOB:
   1753         rc = mm_jpeg_process_encoding_job(my_obj, node);
   1754         break;
   1755       case MM_JPEG_CMD_TYPE_DECODE_JOB:
   1756         rc = mm_jpegdec_process_decoding_job(my_obj, node);
   1757         break;
   1758       case MM_JPEG_CMD_TYPE_EXIT:
   1759       default:
   1760         /* free node */
   1761         free(node);
   1762         /* set running flag to false */
   1763         running = 0;
   1764         break;
   1765       }
   1766     }
   1767     pthread_mutex_unlock(&my_obj->job_lock);
   1768 
   1769   } while (running);
   1770   return NULL;
   1771 }
   1772 
   1773 /** mm_jpeg_jobmgr_thread_launch:
   1774  *
   1775  *  Arguments:
   1776  *    @my_obj: jpeg object
   1777  *
   1778  *  Return:
   1779  *       0 for success else failure
   1780  *
   1781  *  Description:
   1782  *       launches the job manager thread
   1783  *
   1784  **/
   1785 int32_t mm_jpeg_jobmgr_thread_launch(mm_jpeg_obj *my_obj)
   1786 {
   1787   int32_t rc = 0;
   1788   mm_jpeg_job_cmd_thread_t *job_mgr = &my_obj->job_mgr;
   1789 
   1790   cam_sem_init(&job_mgr->job_sem, 0);
   1791   mm_jpeg_queue_init(&job_mgr->job_queue);
   1792 
   1793   /* launch the thread */
   1794   pthread_create(&job_mgr->pid,
   1795     NULL,
   1796     mm_jpeg_jobmgr_thread,
   1797     (void *)my_obj);
   1798   pthread_setname_np(job_mgr->pid, "CAM_jpeg_jobmgr");
   1799   return rc;
   1800 }
   1801 
   1802 /** mm_jpeg_jobmgr_thread_release:
   1803  *
   1804  *  Arguments:
   1805  *    @my_obj: jpeg object
   1806  *
   1807  *  Return:
   1808  *       0 for success else failure
   1809  *
   1810  *  Description:
   1811  *       Releases the job manager thread
   1812  *
   1813  **/
   1814 int32_t mm_jpeg_jobmgr_thread_release(mm_jpeg_obj * my_obj)
   1815 {
   1816   mm_jpeg_q_data_t qdata;
   1817   int32_t rc = 0;
   1818   mm_jpeg_job_cmd_thread_t * cmd_thread = &my_obj->job_mgr;
   1819   mm_jpeg_job_q_node_t* node =
   1820     (mm_jpeg_job_q_node_t *)malloc(sizeof(mm_jpeg_job_q_node_t));
   1821   if (NULL == node) {
   1822     CDBG_ERROR("%s: No memory for mm_jpeg_job_q_node_t", __func__);
   1823     return -1;
   1824   }
   1825 
   1826   memset(node, 0, sizeof(mm_jpeg_job_q_node_t));
   1827   node->type = MM_JPEG_CMD_TYPE_EXIT;
   1828 
   1829   qdata.p = node;
   1830   mm_jpeg_queue_enq(&cmd_thread->job_queue, qdata);
   1831   cam_sem_post(&cmd_thread->job_sem);
   1832 
   1833   /* wait until cmd thread exits */
   1834   if (pthread_join(cmd_thread->pid, NULL) != 0) {
   1835     CDBG("%s: pthread dead already", __func__);
   1836   }
   1837   mm_jpeg_queue_deinit(&cmd_thread->job_queue);
   1838 
   1839   cam_sem_destroy(&cmd_thread->job_sem);
   1840   memset(cmd_thread, 0, sizeof(mm_jpeg_job_cmd_thread_t));
   1841   return rc;
   1842 }
   1843 
   1844 /** mm_jpeg_init:
   1845  *
   1846  *  Arguments:
   1847  *    @my_obj: jpeg object
   1848  *
   1849  *  Return:
   1850  *       0 for success else failure
   1851  *
   1852  *  Description:
   1853  *       Initializes the jpeg client
   1854  *
   1855  **/
   1856 int32_t mm_jpeg_init(mm_jpeg_obj *my_obj)
   1857 {
   1858   int32_t rc = 0;
   1859   uint32_t work_buf_size;
   1860   unsigned int i = 0;
   1861   unsigned int initial_workbufs_cnt = 1;
   1862 
   1863   /* init locks */
   1864   pthread_mutex_init(&my_obj->job_lock, NULL);
   1865 
   1866   /* init ongoing job queue */
   1867   rc = mm_jpeg_queue_init(&my_obj->ongoing_job_q);
   1868   if (0 != rc) {
   1869     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
   1870     pthread_mutex_destroy(&my_obj->job_lock);
   1871     return -1;
   1872   }
   1873 
   1874 
   1875   /* init job semaphore and launch jobmgr thread */
   1876   CDBG("%s:%d] Launch jobmgr thread rc %d", __func__, __LINE__, rc);
   1877   rc = mm_jpeg_jobmgr_thread_launch(my_obj);
   1878   if (0 != rc) {
   1879     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
   1880     mm_jpeg_queue_deinit(&my_obj->ongoing_job_q);
   1881     pthread_mutex_destroy(&my_obj->job_lock);
   1882     return -1;
   1883   }
   1884 
   1885   /* set work buf size from max picture size */
   1886   if (my_obj->max_pic_w <= 0 || my_obj->max_pic_h <= 0) {
   1887     CDBG_ERROR("%s:%d] Width and height are not valid "
   1888       "dimensions, cannot calc work buf size",__func__, __LINE__);
   1889     mm_jpeg_jobmgr_thread_release(my_obj);
   1890     mm_jpeg_queue_deinit(&my_obj->ongoing_job_q);
   1891     pthread_mutex_destroy(&my_obj->job_lock);
   1892     return -1;
   1893   }
   1894   work_buf_size = CEILING64((uint32_t)my_obj->max_pic_w) *
   1895     CEILING64((uint32_t)my_obj->max_pic_h) * 3U / 2U;
   1896   for (i = 0; i < initial_workbufs_cnt; i++) {
   1897     my_obj->ionBuffer[i].size = CEILING32(work_buf_size);
   1898     CDBG_HIGH("Max picture size %d x %d, WorkBufSize = %zu",
   1899         my_obj->max_pic_w, my_obj->max_pic_h, my_obj->ionBuffer[i].size);
   1900 
   1901     my_obj->ionBuffer[i].addr = (uint8_t *)buffer_allocate(&my_obj->ionBuffer[i], 1);
   1902     if (NULL == my_obj->ionBuffer[i].addr) {
   1903       while (i--) {
   1904         buffer_deallocate(&my_obj->ionBuffer[i]);
   1905       }
   1906       mm_jpeg_jobmgr_thread_release(my_obj);
   1907       mm_jpeg_queue_deinit(&my_obj->ongoing_job_q);
   1908       pthread_mutex_destroy(&my_obj->job_lock);
   1909       CDBG_ERROR("%s:%d] Ion allocation failed",__func__, __LINE__);
   1910       return -1;
   1911     }
   1912   }
   1913 
   1914   my_obj->work_buf_cnt = i;
   1915 
   1916   /* load OMX */
   1917   if (OMX_ErrorNone != OMX_Init()) {
   1918     /* roll back in error case */
   1919     CDBG_ERROR("%s:%d] OMX_Init failed (%d)", __func__, __LINE__, rc);
   1920     for (i = 0; i < initial_workbufs_cnt; i++) {
   1921       buffer_deallocate(&my_obj->ionBuffer[i]);
   1922     }
   1923     mm_jpeg_jobmgr_thread_release(my_obj);
   1924     mm_jpeg_queue_deinit(&my_obj->ongoing_job_q);
   1925     pthread_mutex_destroy(&my_obj->job_lock);
   1926   }
   1927 
   1928 #ifdef LOAD_ADSP_RPC_LIB
   1929   my_obj->adsprpc_lib_handle = dlopen("libadsprpc.so", RTLD_NOW);
   1930   if (NULL == my_obj->adsprpc_lib_handle) {
   1931     CDBG_ERROR("%s:%d] Cannot load the library", __func__, __LINE__);
   1932     /* not returning error here bcoz even if this loading fails
   1933         we can go ahead with SW JPEG enc */
   1934   }
   1935 #endif
   1936 
   1937   return rc;
   1938 }
   1939 
   1940 /** mm_jpeg_deinit:
   1941  *
   1942  *  Arguments:
   1943  *    @my_obj: jpeg object
   1944  *
   1945  *  Return:
   1946  *       0 for success else failure
   1947  *
   1948  *  Description:
   1949  *       Deinits the jpeg client
   1950  *
   1951  **/
   1952 int32_t mm_jpeg_deinit(mm_jpeg_obj *my_obj)
   1953 {
   1954   int32_t rc = 0;
   1955   uint32_t i = 0;
   1956 
   1957   /* release jobmgr thread */
   1958   rc = mm_jpeg_jobmgr_thread_release(my_obj);
   1959   if (0 != rc) {
   1960     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
   1961   }
   1962 
   1963   /* unload OMX engine */
   1964   OMX_Deinit();
   1965 
   1966   /* deinit ongoing job and cb queue */
   1967   rc = mm_jpeg_queue_deinit(&my_obj->ongoing_job_q);
   1968   if (0 != rc) {
   1969     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
   1970   }
   1971 
   1972   for (i = 0; i < my_obj->work_buf_cnt; i++) {
   1973     /*Release the ION buffer*/
   1974     rc = buffer_deallocate(&my_obj->ionBuffer[i]);
   1975     if (0 != rc) {
   1976       CDBG_ERROR("%s:%d] Error releasing ION buffer", __func__, __LINE__);
   1977     }
   1978   }
   1979 
   1980   /* destroy locks */
   1981   pthread_mutex_destroy(&my_obj->job_lock);
   1982 
   1983   return rc;
   1984 }
   1985 
   1986 /** mm_jpeg_new_client:
   1987  *
   1988  *  Arguments:
   1989  *    @my_obj: jpeg object
   1990  *
   1991  *  Return:
   1992  *       0 for success else failure
   1993  *
   1994  *  Description:
   1995  *       Create new jpeg client
   1996  *
   1997  **/
   1998 uint32_t mm_jpeg_new_client(mm_jpeg_obj *my_obj)
   1999 {
   2000   uint32_t client_hdl = 0;
   2001   uint8_t idx;
   2002   int i = 0;
   2003 
   2004   if (my_obj->num_clients >= MAX_JPEG_CLIENT_NUM) {
   2005     CDBG_ERROR("%s: num of clients reached limit", __func__);
   2006     return client_hdl;
   2007   }
   2008 
   2009   for (idx = 0; idx < MAX_JPEG_CLIENT_NUM; idx++) {
   2010     if (0 == my_obj->clnt_mgr[idx].is_used) {
   2011       break;
   2012     }
   2013   }
   2014 
   2015   if (idx < MAX_JPEG_CLIENT_NUM) {
   2016     /* client session avail */
   2017     /* generate client handler by index */
   2018     client_hdl = mm_jpeg_util_generate_handler(idx);
   2019 
   2020     /* update client session */
   2021     my_obj->clnt_mgr[idx].is_used = 1;
   2022     my_obj->clnt_mgr[idx].client_handle = client_hdl;
   2023 
   2024     pthread_mutex_init(&my_obj->clnt_mgr[idx].lock, NULL);
   2025     for (i = 0; i < MM_JPEG_MAX_SESSION; i++) {
   2026       memset(&my_obj->clnt_mgr[idx].session[i], 0x0, sizeof(mm_jpeg_job_session_t));
   2027     }
   2028 
   2029     /* increse client count */
   2030     my_obj->num_clients++;
   2031   }
   2032 
   2033   return client_hdl;
   2034 }
   2035 
   2036 /** mm_jpeg_start_job:
   2037  *
   2038  *  Arguments:
   2039  *    @my_obj: jpeg object
   2040  *    @client_hdl: client handle
   2041  *    @job: pointer to encode job
   2042  *    @jobId: job id
   2043  *
   2044  *  Return:
   2045  *       0 for success else failure
   2046  *
   2047  *  Description:
   2048  *       Start the encoding job
   2049  *
   2050  **/
   2051 int32_t mm_jpeg_start_job(mm_jpeg_obj *my_obj,
   2052   mm_jpeg_job_t *job,
   2053   uint32_t *job_id)
   2054 {
   2055   mm_jpeg_q_data_t qdata;
   2056   int32_t rc = -1;
   2057   uint8_t session_idx = 0;
   2058   uint8_t client_idx = 0;
   2059   mm_jpeg_job_q_node_t* node = NULL;
   2060   mm_jpeg_job_session_t *p_session = NULL;
   2061   mm_jpeg_encode_job_t *p_jobparams  = &job->encode_job;
   2062 
   2063   *job_id = 0;
   2064 
   2065   /* check if valid session */
   2066   session_idx = GET_SESSION_IDX(p_jobparams->session_id);
   2067   client_idx = GET_CLIENT_IDX(p_jobparams->session_id);
   2068   CDBG_HIGH("%s:%d] session_idx %d client idx %d", __func__, __LINE__,
   2069     session_idx, client_idx);
   2070 
   2071   if ((session_idx >= MM_JPEG_MAX_SESSION) ||
   2072     (client_idx >= MAX_JPEG_CLIENT_NUM)) {
   2073     CDBG_ERROR("%s:%d] invalid session id %x", __func__, __LINE__,
   2074       job->encode_job.session_id);
   2075     return rc;
   2076   }
   2077 
   2078   p_session = &my_obj->clnt_mgr[client_idx].session[session_idx];
   2079   if (OMX_FALSE == p_session->active) {
   2080     CDBG_ERROR("%s:%d] session not active %x", __func__, __LINE__,
   2081       job->encode_job.session_id);
   2082     return rc;
   2083   }
   2084 
   2085   if ((p_jobparams->src_index >= (int32_t)p_session->params.num_src_bufs) ||
   2086     (p_jobparams->dst_index >= (int32_t)p_session->params.num_dst_bufs)) {
   2087     CDBG_ERROR("%s:%d] invalid buffer indices", __func__, __LINE__);
   2088     return rc;
   2089   }
   2090 
   2091   /* enqueue new job into todo job queue */
   2092   node = (mm_jpeg_job_q_node_t *)malloc(sizeof(mm_jpeg_job_q_node_t));
   2093   if (NULL == node) {
   2094     CDBG_ERROR("%s: No memory for mm_jpeg_job_q_node_t", __func__);
   2095     return -1;
   2096   }
   2097 
   2098   ATRACE_INT("Camera:JPEG",
   2099       (int32_t)((uint32_t)session_idx<<16 | ++p_session->job_index));
   2100 
   2101   *job_id = job->encode_job.session_id |
   2102     (((uint32_t)p_session->job_hist++ % JOB_HIST_MAX) << 16);
   2103 
   2104   memset(node, 0, sizeof(mm_jpeg_job_q_node_t));
   2105   node->enc_info.encode_job = job->encode_job;
   2106   if (p_session->thumb_from_main) {
   2107     node->enc_info.encode_job.thumb_dim.src_dim =
   2108       node->enc_info.encode_job.main_dim.src_dim;
   2109     node->enc_info.encode_job.thumb_dim.crop =
   2110       node->enc_info.encode_job.main_dim.crop;
   2111   }
   2112   node->enc_info.job_id = *job_id;
   2113   node->enc_info.client_handle = p_session->client_hdl;
   2114   node->type = MM_JPEG_CMD_TYPE_JOB;
   2115 
   2116 
   2117 
   2118   qdata.p = node;
   2119   rc = mm_jpeg_queue_enq(&my_obj->job_mgr.job_queue, qdata);
   2120   if (0 == rc) {
   2121       cam_sem_post(&my_obj->job_mgr.job_sem);
   2122   }
   2123 
   2124   CDBG_HIGH("%s:%d] X", __func__, __LINE__);
   2125 
   2126   return rc;
   2127 }
   2128 
   2129 
   2130 
   2131 /** mm_jpeg_abort_job:
   2132  *
   2133  *  Arguments:
   2134  *    @my_obj: jpeg object
   2135  *    @client_hdl: client handle
   2136  *    @jobId: job id
   2137  *
   2138  *  Return:
   2139  *       0 for success else failure
   2140  *
   2141  *  Description:
   2142  *       Abort the encoding session
   2143  *
   2144  **/
   2145 int32_t mm_jpeg_abort_job(mm_jpeg_obj *my_obj,
   2146   uint32_t jobId)
   2147 {
   2148   int32_t rc = -1;
   2149   mm_jpeg_job_q_node_t *node = NULL;
   2150   mm_jpeg_job_session_t *p_session = NULL;
   2151 
   2152   CDBG("%s:%d] ", __func__, __LINE__);
   2153   pthread_mutex_lock(&my_obj->job_lock);
   2154 
   2155   /* abort job if in todo queue */
   2156   node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->job_mgr.job_queue, jobId);
   2157   if (NULL != node) {
   2158     free(node);
   2159     goto abort_done;
   2160   }
   2161 
   2162   /* abort job if in ongoing queue */
   2163   node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->ongoing_job_q, jobId);
   2164   if (NULL != node) {
   2165     /* find job that is OMX ongoing, ask OMX to abort the job */
   2166     p_session = mm_jpeg_get_session(my_obj, node->enc_info.job_id);
   2167     if (p_session) {
   2168       mm_jpeg_session_abort(p_session);
   2169     } else {
   2170       CDBG_ERROR("%s:%d] Invalid job id 0x%x", __func__, __LINE__,
   2171         node->enc_info.job_id);
   2172     }
   2173     free(node);
   2174     goto abort_done;
   2175   }
   2176 
   2177 abort_done:
   2178   pthread_mutex_unlock(&my_obj->job_lock);
   2179 
   2180   return rc;
   2181 }
   2182 
   2183 
   2184 #ifdef MM_JPEG_READ_META_KEYFILE
   2185 static int32_t mm_jpeg_read_meta_keyfile(mm_jpeg_job_session_t *p_session,
   2186     const char *filename)
   2187 {
   2188   int rc = 0;
   2189   FILE *fp = NULL;
   2190   size_t file_size = 0;
   2191   fp = fopen(filename, "r");
   2192   if (!fp) {
   2193     CDBG_ERROR("%s:%d] Key not present", __func__, __LINE__);
   2194     return -1;
   2195   }
   2196   fseek(fp, 0, SEEK_END);
   2197   file_size = (size_t)ftell(fp);
   2198   fseek(fp, 0, SEEK_SET);
   2199 
   2200   p_session->meta_enc_key = (uint8_t *) malloc((file_size + 1) * sizeof(uint8_t));
   2201 
   2202   if (!p_session->meta_enc_key) {
   2203     CDBG_ERROR("%s:%d] error", __func__, __LINE__);
   2204     return -1;
   2205   }
   2206 
   2207   fread(p_session->meta_enc_key, 1, file_size, fp);
   2208   fclose(fp);
   2209 
   2210   p_session->meta_enc_keylen = file_size;
   2211 
   2212   return rc;
   2213 }
   2214 #endif // MM_JPEG_READ_META_KEYFILE
   2215 
   2216 /** mm_jpeg_create_session:
   2217  *
   2218  *  Arguments:
   2219  *    @my_obj: jpeg object
   2220  *    @client_hdl: client handle
   2221  *    @p_params: pointer to encode params
   2222  *    @p_session_id: session id
   2223  *
   2224  *  Return:
   2225  *       0 for success else failure
   2226  *
   2227  *  Description:
   2228  *       Start the encoding session
   2229  *
   2230  **/
   2231 int32_t mm_jpeg_create_session(mm_jpeg_obj *my_obj,
   2232   uint32_t client_hdl,
   2233   mm_jpeg_encode_params_t *p_params,
   2234   uint32_t* p_session_id)
   2235 {
   2236   mm_jpeg_q_data_t qdata;
   2237   int32_t rc = 0;
   2238   OMX_ERRORTYPE ret = OMX_ErrorNone;
   2239   uint8_t clnt_idx = 0;
   2240   int session_idx = -1;
   2241   mm_jpeg_job_session_t *p_session = NULL;
   2242   mm_jpeg_job_session_t * p_prev_session = NULL;
   2243   *p_session_id = 0;
   2244   uint32_t i = 0;
   2245   uint32_t num_omx_sessions;
   2246   uint32_t work_buf_size;
   2247   mm_jpeg_queue_t *p_session_handle_q, *p_out_buf_q;
   2248   uint32_t work_bufs_need;
   2249   char trace_tag[32];
   2250 
   2251   /* validate the parameters */
   2252   if ((p_params->num_src_bufs > MM_JPEG_MAX_BUF)
   2253     || (p_params->num_dst_bufs > MM_JPEG_MAX_BUF)) {
   2254     CDBG_ERROR("%s:%d] invalid num buffers", __func__, __LINE__);
   2255     return -1;
   2256   }
   2257 
   2258   /* check if valid client */
   2259   clnt_idx = mm_jpeg_util_get_index_by_handler(client_hdl);
   2260   if (clnt_idx >= MAX_JPEG_CLIENT_NUM) {
   2261     CDBG_ERROR("%s: invalid client with handler (%d)", __func__, client_hdl);
   2262     return -1;
   2263   }
   2264 
   2265   num_omx_sessions = 1;
   2266   if (p_params->burst_mode) {
   2267     num_omx_sessions = MM_JPEG_CONCURRENT_SESSIONS_COUNT;
   2268   }
   2269   work_bufs_need = my_obj->num_sessions + num_omx_sessions;
   2270   if (work_bufs_need > MM_JPEG_CONCURRENT_SESSIONS_COUNT) {
   2271     work_bufs_need = MM_JPEG_CONCURRENT_SESSIONS_COUNT;
   2272   }
   2273   CDBG_HIGH("%s:%d] >>>> Work bufs need %d", __func__, __LINE__, work_bufs_need);
   2274   work_buf_size = CEILING64((uint32_t)my_obj->max_pic_w) *
   2275       CEILING64((uint32_t)my_obj->max_pic_h) * 3 / 2;
   2276   for (i = my_obj->work_buf_cnt; i < work_bufs_need; i++) {
   2277      my_obj->ionBuffer[i].size = CEILING32(work_buf_size);
   2278      CDBG_HIGH("Max picture size %d x %d, WorkBufSize = %zu",
   2279          my_obj->max_pic_w, my_obj->max_pic_h, my_obj->ionBuffer[i].size);
   2280 
   2281      my_obj->ionBuffer[i].addr = (uint8_t *)buffer_allocate(&my_obj->ionBuffer[i], 1);
   2282      if (NULL == my_obj->ionBuffer[i].addr) {
   2283        CDBG_ERROR("%s:%d] Ion allocation failed",__func__, __LINE__);
   2284        goto error1;
   2285      }
   2286      my_obj->work_buf_cnt++;
   2287   }
   2288 
   2289   /* init omx handle queue */
   2290   p_session_handle_q = (mm_jpeg_queue_t *) malloc(sizeof(*p_session_handle_q));
   2291   if (NULL == p_session_handle_q) {
   2292     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
   2293     goto error1;
   2294   }
   2295   rc = mm_jpeg_queue_init(p_session_handle_q);
   2296   if (0 != rc) {
   2297     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
   2298     free(p_session_handle_q);
   2299     goto error1;
   2300   }
   2301 
   2302   /* init output buf queue */
   2303   p_out_buf_q = (mm_jpeg_queue_t *) malloc(sizeof(*p_out_buf_q));
   2304   if (NULL == p_out_buf_q) {
   2305     CDBG_ERROR("%s:%d] Error: Cannot allocate memory\n", __func__, __LINE__);
   2306     return -1;
   2307   }
   2308 
   2309   /* init omx handle queue */
   2310   rc = mm_jpeg_queue_init(p_out_buf_q);
   2311   if (0 != rc) {
   2312     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
   2313     free(p_out_buf_q);
   2314     goto error1;
   2315   }
   2316 
   2317   for (i = 0; i < num_omx_sessions; i++) {
   2318     uint32_t buf_idx = 0U;
   2319     session_idx = mm_jpeg_get_new_session_idx(my_obj, clnt_idx, &p_session);
   2320     if (session_idx < 0 || NULL == p_session) {
   2321       CDBG_ERROR("%s:%d] invalid session id (%d)", __func__, __LINE__, session_idx);
   2322       goto error2;
   2323     }
   2324 
   2325     snprintf(trace_tag, sizeof(trace_tag), "Camera:JPEGsession%d", session_idx);
   2326     ATRACE_INT(trace_tag, 1);
   2327 
   2328     p_session->job_index = 0;
   2329 
   2330     p_session->next_session = NULL;
   2331 
   2332     if (p_prev_session) {
   2333       p_prev_session->next_session = p_session;
   2334     }
   2335     p_prev_session = p_session;
   2336 
   2337     buf_idx = my_obj->num_sessions + i;
   2338     if (buf_idx < MM_JPEG_CONCURRENT_SESSIONS_COUNT) {
   2339       p_session->work_buffer = my_obj->ionBuffer[buf_idx];
   2340     } else {
   2341       p_session->work_buffer.addr = NULL;
   2342       p_session->work_buffer.ion_fd = -1;
   2343       p_session->work_buffer.p_pmem_fd = -1;
   2344     }
   2345 
   2346     p_session->jpeg_obj = (void*)my_obj; /* save a ptr to jpeg_obj */
   2347 
   2348     ret = mm_jpeg_session_create(p_session);
   2349     if (OMX_ErrorNone != ret) {
   2350       p_session->active = OMX_FALSE;
   2351       CDBG_ERROR("%s:%d] jpeg session create failed", __func__, __LINE__);
   2352       goto error2;
   2353     }
   2354 
   2355     uint32_t session_id = (JOB_ID_MAGICVAL << 24) |
   2356         ((uint32_t)session_idx << 8) | clnt_idx;
   2357 
   2358     if (!*p_session_id) {
   2359       *p_session_id = session_id;
   2360     }
   2361 
   2362     /*copy the params*/
   2363     p_session->params = *p_params;
   2364     if (p_session->thumb_from_main) {
   2365       memcpy(p_session->params.src_thumb_buf, p_session->params.src_main_buf,
   2366         sizeof(p_session->params.src_thumb_buf));
   2367       p_session->params.num_tmb_bufs =  p_session->params.num_src_bufs;
   2368       if (!p_session->params.encode_thumbnail) {
   2369          p_session->params.num_tmb_bufs = 0;
   2370       }
   2371       p_session->params.thumb_dim.src_dim = p_session->params.main_dim.src_dim;
   2372       p_session->params.thumb_dim.crop = p_session->params.main_dim.crop;
   2373     }
   2374     p_session->client_hdl = client_hdl;
   2375     p_session->sessionId = session_id;
   2376     p_session->session_handle_q = p_session_handle_q;
   2377     p_session->out_buf_q = p_out_buf_q;
   2378 
   2379     qdata.p = p_session;
   2380     mm_jpeg_queue_enq(p_session_handle_q, qdata);
   2381 
   2382     p_session->meta_enc_key = NULL;
   2383     p_session->meta_enc_keylen = 0;
   2384 
   2385 #ifdef MM_JPEG_READ_META_KEYFILE
   2386     mm_jpeg_read_meta_keyfile(p_session, META_KEYFILE);
   2387 #endif
   2388 
   2389     if (OMX_FALSE == p_session->config) {
   2390       rc = mm_jpeg_session_configure(p_session);
   2391       if (rc) {
   2392         CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
   2393         goto error2;
   2394       }
   2395       p_session->config = OMX_TRUE;
   2396     }
   2397     p_session->num_omx_sessions = num_omx_sessions;
   2398 
   2399     CDBG_HIGH("%s:%d] session id %x", __func__, __LINE__, session_id);
   2400   }
   2401 
   2402   // Queue the output buf indexes
   2403   for (i = 0; i < p_params->num_dst_bufs; i++) {
   2404     qdata.u32 = i + 1;
   2405     mm_jpeg_queue_enq(p_out_buf_q, qdata);
   2406   }
   2407 
   2408   return rc;
   2409 
   2410 error1:
   2411   rc = -1;
   2412 error2:
   2413   if (NULL != p_session) {
   2414     ATRACE_INT(trace_tag, 0);
   2415   }
   2416   return rc;
   2417 }
   2418 
   2419 /** mm_jpegenc_destroy_job
   2420  *
   2421  *  Arguments:
   2422  *    @p_session: Session obj
   2423  *
   2424  *  Return:
   2425  *       0 for success else failure
   2426  *
   2427  *  Description:
   2428  *       Destroy the job based paramenters
   2429  *
   2430  **/
   2431 static int32_t mm_jpegenc_destroy_job(mm_jpeg_job_session_t *p_session)
   2432 {
   2433   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
   2434   int i = 0, rc = 0;
   2435 
   2436   CDBG_HIGH("%s:%d] Exif entry count %d %d", __func__, __LINE__,
   2437     (int)p_jobparams->exif_info.numOfEntries,
   2438     (int)p_session->exif_count_local);
   2439   for (i = 0; i < p_session->exif_count_local; i++) {
   2440     rc = releaseExifEntry(&p_session->exif_info_local[i]);
   2441     if (rc) {
   2442       CDBG_ERROR("%s:%d] Exif release failed (%d)", __func__, __LINE__, rc);
   2443     }
   2444   }
   2445   p_session->exif_count_local = 0;
   2446 
   2447   return rc;
   2448 }
   2449 
   2450 /** mm_jpeg_session_encode:
   2451  *
   2452  *  Arguments:
   2453  *    @p_session: encode session
   2454  *
   2455  *  Return:
   2456  *       OMX_ERRORTYPE
   2457  *
   2458  *  Description:
   2459  *       Start the encoding
   2460  *
   2461  **/
   2462 static void mm_jpegenc_job_done(mm_jpeg_job_session_t *p_session)
   2463 {
   2464   mm_jpeg_q_data_t qdata;
   2465   mm_jpeg_obj *my_obj = (mm_jpeg_obj *)p_session->jpeg_obj;
   2466   mm_jpeg_job_q_node_t *node = NULL;
   2467 
   2468   /*Destroy job related params*/
   2469   mm_jpegenc_destroy_job(p_session);
   2470 
   2471   /*remove the job*/
   2472   node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->ongoing_job_q,
   2473     p_session->jobId);
   2474   if (node) {
   2475     free(node);
   2476   }
   2477   p_session->encoding = OMX_FALSE;
   2478 
   2479   // Queue to available sessions
   2480   qdata.p = p_session;
   2481   mm_jpeg_queue_enq(p_session->session_handle_q, qdata);
   2482 
   2483   if (p_session->auto_out_buf) {
   2484     //Queue out buf index
   2485     qdata.u32 = (uint32_t)(p_session->encode_job.dst_index + 1);
   2486     mm_jpeg_queue_enq(p_session->out_buf_q, qdata);
   2487   }
   2488 
   2489   /* wake up jobMgr thread to work on new job if there is any */
   2490   cam_sem_post(&my_obj->job_mgr.job_sem);
   2491 }
   2492 
   2493 /** mm_jpeg_destroy_session:
   2494  *
   2495  *  Arguments:
   2496  *    @my_obj: jpeg object
   2497  *    @session_id: session index
   2498  *
   2499  *  Return:
   2500  *       0 for success else failure
   2501  *
   2502  *  Description:
   2503  *       Destroy the encoding session
   2504  *
   2505  **/
   2506 int32_t mm_jpeg_destroy_session(mm_jpeg_obj *my_obj,
   2507   mm_jpeg_job_session_t *p_session)
   2508 {
   2509   mm_jpeg_q_data_t qdata;
   2510   int32_t rc = 0;
   2511   mm_jpeg_job_q_node_t *node = NULL;
   2512   uint32_t session_id = 0;
   2513   mm_jpeg_job_session_t *p_cur_sess;
   2514   char trace_tag[32];
   2515 
   2516   if (NULL == p_session) {
   2517     CDBG_ERROR("%s:%d] invalid session", __func__, __LINE__);
   2518     return rc;
   2519   }
   2520 
   2521   session_id = p_session->sessionId;
   2522 
   2523   pthread_mutex_lock(&my_obj->job_lock);
   2524 
   2525   /* abort job if in todo queue */
   2526   CDBG_HIGH("%s:%d] abort todo jobs", __func__, __LINE__);
   2527   node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id);
   2528   while (NULL != node) {
   2529     free(node);
   2530     node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id);
   2531   }
   2532 
   2533   /* abort job if in ongoing queue */
   2534   CDBG_HIGH("%s:%d] abort ongoing jobs", __func__, __LINE__);
   2535   node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id);
   2536   while (NULL != node) {
   2537     free(node);
   2538     node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id);
   2539   }
   2540 
   2541   /* abort the current session */
   2542   mm_jpeg_session_abort(p_session);
   2543   mm_jpeg_session_destroy(p_session);
   2544 
   2545   p_cur_sess = p_session;
   2546 
   2547   do {
   2548     mm_jpeg_remove_session_idx(my_obj, p_cur_sess->sessionId);
   2549   } while (NULL != (p_cur_sess = p_cur_sess->next_session));
   2550 
   2551 
   2552   pthread_mutex_unlock(&my_obj->job_lock);
   2553 
   2554   while (1) {
   2555     qdata = mm_jpeg_queue_deq(p_session->session_handle_q);
   2556     if (NULL == qdata.p)
   2557       break;
   2558   }
   2559   mm_jpeg_queue_deinit(p_session->session_handle_q);
   2560   free(p_session->session_handle_q);
   2561   p_session->session_handle_q = NULL;
   2562 
   2563   while (1) {
   2564     qdata = mm_jpeg_queue_deq(p_session->out_buf_q);
   2565     if (0U == qdata.u32)
   2566       break;
   2567   }
   2568   mm_jpeg_queue_deinit(p_session->out_buf_q);
   2569   free(p_session->out_buf_q);
   2570   p_session->out_buf_q = NULL;
   2571 
   2572 
   2573   /* wake up jobMgr thread to work on new job if there is any */
   2574   cam_sem_post(&my_obj->job_mgr.job_sem);
   2575 
   2576   snprintf(trace_tag, sizeof(trace_tag), "Camera:JPEGsession%d", GET_SESSION_IDX(session_id));
   2577   ATRACE_INT(trace_tag, 0);
   2578 
   2579   CDBG_HIGH("%s:%d] destroy session successful. X", __func__, __LINE__);
   2580 
   2581   return rc;
   2582 }
   2583 
   2584 
   2585 
   2586 
   2587 /** mm_jpeg_destroy_session:
   2588  *
   2589  *  Arguments:
   2590  *    @my_obj: jpeg object
   2591  *    @session_id: session index
   2592  *
   2593  *  Return:
   2594  *       0 for success else failure
   2595  *
   2596  *  Description:
   2597  *       Destroy the encoding session
   2598  *
   2599  **/
   2600 int32_t mm_jpeg_destroy_session_unlocked(mm_jpeg_obj *my_obj,
   2601   mm_jpeg_job_session_t *p_session)
   2602 {
   2603   int32_t rc = -1;
   2604   mm_jpeg_job_q_node_t *node = NULL;
   2605   uint32_t session_id = 0;
   2606   if (NULL == p_session) {
   2607     CDBG_ERROR("%s:%d] invalid session", __func__, __LINE__);
   2608     return rc;
   2609   }
   2610 
   2611   session_id = p_session->sessionId;
   2612 
   2613   /* abort job if in todo queue */
   2614   CDBG("%s:%d] abort todo jobs", __func__, __LINE__);
   2615   node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id);
   2616   while (NULL != node) {
   2617     free(node);
   2618     node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id);
   2619   }
   2620 
   2621   /* abort job if in ongoing queue */
   2622   CDBG("%s:%d] abort ongoing jobs", __func__, __LINE__);
   2623   node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id);
   2624   while (NULL != node) {
   2625     free(node);
   2626     node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id);
   2627   }
   2628 
   2629   /* abort the current session */
   2630   mm_jpeg_session_abort(p_session);
   2631   //mm_jpeg_remove_session_idx(my_obj, session_id);
   2632 
   2633   return rc;
   2634 }
   2635 
   2636 /** mm_jpeg_destroy_session:
   2637  *
   2638  *  Arguments:
   2639  *    @my_obj: jpeg object
   2640  *    @session_id: session index
   2641  *
   2642  *  Return:
   2643  *       0 for success else failure
   2644  *
   2645  *  Description:
   2646  *       Destroy the encoding session
   2647  *
   2648  **/
   2649 int32_t mm_jpeg_destroy_session_by_id(mm_jpeg_obj *my_obj, uint32_t session_id)
   2650 {
   2651   mm_jpeg_job_session_t *p_session = mm_jpeg_get_session(my_obj, session_id);
   2652 
   2653   return mm_jpeg_destroy_session(my_obj, p_session);
   2654 }
   2655 
   2656 
   2657 
   2658 /** mm_jpeg_close:
   2659  *
   2660  *  Arguments:
   2661  *    @my_obj: jpeg object
   2662  *    @client_hdl: client handle
   2663  *
   2664  *  Return:
   2665  *       0 for success else failure
   2666  *
   2667  *  Description:
   2668  *       Close the jpeg client
   2669  *
   2670  **/
   2671 int32_t mm_jpeg_close(mm_jpeg_obj *my_obj, uint32_t client_hdl)
   2672 {
   2673   int32_t rc = -1;
   2674   uint8_t clnt_idx = 0;
   2675   int i = 0;
   2676 
   2677   /* check if valid client */
   2678   clnt_idx = mm_jpeg_util_get_index_by_handler(client_hdl);
   2679   if (clnt_idx >= MAX_JPEG_CLIENT_NUM) {
   2680     CDBG_ERROR("%s: invalid client with handler (%d)", __func__, client_hdl);
   2681     return rc;
   2682   }
   2683 
   2684   CDBG("%s:%d] E", __func__, __LINE__);
   2685 
   2686   /* abort all jobs from the client */
   2687   pthread_mutex_lock(&my_obj->job_lock);
   2688 
   2689   CDBG("%s:%d] ", __func__, __LINE__);
   2690 
   2691   for (i = 0; i < MM_JPEG_MAX_SESSION; i++) {
   2692     if (OMX_TRUE == my_obj->clnt_mgr[clnt_idx].session[i].active)
   2693       mm_jpeg_destroy_session_unlocked(my_obj,
   2694         &my_obj->clnt_mgr[clnt_idx].session[i]);
   2695   }
   2696 
   2697   CDBG("%s:%d] ", __func__, __LINE__);
   2698 
   2699 #ifdef LOAD_ADSP_RPC_LIB
   2700   if (NULL != my_obj->adsprpc_lib_handle) {
   2701     dlclose(my_obj->adsprpc_lib_handle);
   2702     my_obj->adsprpc_lib_handle = NULL;
   2703   }
   2704 #endif
   2705 
   2706   pthread_mutex_unlock(&my_obj->job_lock);
   2707   CDBG("%s:%d] ", __func__, __LINE__);
   2708 
   2709   /* invalidate client session */
   2710   pthread_mutex_destroy(&my_obj->clnt_mgr[clnt_idx].lock);
   2711   memset(&my_obj->clnt_mgr[clnt_idx], 0, sizeof(mm_jpeg_client_t));
   2712 
   2713   rc = 0;
   2714   CDBG("%s:%d] X", __func__, __LINE__);
   2715   return rc;
   2716 }
   2717 
   2718 OMX_ERRORTYPE mm_jpeg_ebd(OMX_HANDLETYPE hComponent,
   2719   OMX_PTR pAppData,
   2720   OMX_BUFFERHEADERTYPE *pBuffer)
   2721 {
   2722   mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData;
   2723 
   2724   CDBG_HIGH("%s:%d] count %d ", __func__, __LINE__, p_session->ebd_count);
   2725   pthread_mutex_lock(&p_session->lock);
   2726   p_session->ebd_count++;
   2727   pthread_mutex_unlock(&p_session->lock);
   2728   return 0;
   2729 }
   2730 
   2731 OMX_ERRORTYPE mm_jpeg_fbd(OMX_HANDLETYPE hComponent,
   2732   OMX_PTR pAppData,
   2733   OMX_BUFFERHEADERTYPE *pBuffer)
   2734 {
   2735   OMX_ERRORTYPE ret = OMX_ErrorNone;
   2736   mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData;
   2737   mm_jpeg_output_t output_buf;
   2738   CDBG_HIGH("%s:%d] count %d ", __func__, __LINE__, p_session->fbd_count);
   2739   CDBG_HIGH("[KPI Perf] : PROFILE_JPEG_FBD");
   2740 
   2741   pthread_mutex_lock(&p_session->lock);
   2742   ATRACE_INT("Camera:JPEG",
   2743       (int32_t)((uint32_t)GET_SESSION_IDX(
   2744         p_session->sessionId)<<16 | --p_session->job_index));
   2745   if (MM_JPEG_ABORT_NONE != p_session->abort_state) {
   2746     pthread_mutex_unlock(&p_session->lock);
   2747     return ret;
   2748   }
   2749 
   2750   p_session->fbd_count++;
   2751   if (NULL != p_session->params.jpeg_cb) {
   2752 
   2753     p_session->job_status = JPEG_JOB_STATUS_DONE;
   2754     output_buf.buf_filled_len = (uint32_t)pBuffer->nFilledLen;
   2755     output_buf.buf_vaddr = pBuffer->pBuffer;
   2756     output_buf.fd = 0;
   2757     CDBG_HIGH("%s:%d] send jpeg callback %d buf 0x%p len %u JobID %u",
   2758       __func__, __LINE__,
   2759       p_session->job_status, pBuffer->pBuffer,
   2760       (unsigned int)pBuffer->nFilledLen, p_session->jobId);
   2761     p_session->params.jpeg_cb(p_session->job_status,
   2762       p_session->client_hdl,
   2763       p_session->jobId,
   2764       &output_buf,
   2765       p_session->params.userdata);
   2766 
   2767     mm_jpegenc_job_done(p_session);
   2768 
   2769   }
   2770   pthread_mutex_unlock(&p_session->lock);
   2771   CDBG("%s:%d] ", __func__, __LINE__);
   2772 
   2773   return ret;
   2774 }
   2775 
   2776 
   2777 
   2778 OMX_ERRORTYPE mm_jpeg_event_handler(OMX_HANDLETYPE hComponent,
   2779   OMX_PTR pAppData,
   2780   OMX_EVENTTYPE eEvent,
   2781   OMX_U32 nData1,
   2782   OMX_U32 nData2,
   2783   OMX_PTR pEventData)
   2784 {
   2785   mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData;
   2786 
   2787   CDBG("%s:%d] %d %d %d state %d", __func__, __LINE__, eEvent, (int)nData1,
   2788     (int)nData2, p_session->abort_state);
   2789 
   2790   pthread_mutex_lock(&p_session->lock);
   2791 
   2792   if (MM_JPEG_ABORT_INIT == p_session->abort_state) {
   2793     p_session->abort_state = MM_JPEG_ABORT_DONE;
   2794     pthread_cond_signal(&p_session->cond);
   2795     pthread_mutex_unlock(&p_session->lock);
   2796     return OMX_ErrorNone;
   2797   }
   2798 
   2799   if (eEvent == OMX_EventError) {
   2800     p_session->error_flag = nData2;
   2801     if (p_session->encoding == OMX_TRUE) {
   2802       CDBG_ERROR("%s:%d] Error during encoding", __func__, __LINE__);
   2803 
   2804       /* send jpeg callback */
   2805       if (NULL != p_session->params.jpeg_cb) {
   2806         p_session->job_status = JPEG_JOB_STATUS_ERROR;
   2807         CDBG_ERROR("%s:%d] send jpeg error callback %d", __func__, __LINE__,
   2808           p_session->job_status);
   2809         p_session->params.jpeg_cb(p_session->job_status,
   2810           p_session->client_hdl,
   2811           p_session->jobId,
   2812           NULL,
   2813           p_session->params.userdata);
   2814       }
   2815 
   2816       /* remove from ready queue */
   2817       mm_jpegenc_job_done(p_session);
   2818     }
   2819     pthread_cond_signal(&p_session->cond);
   2820   } else if (eEvent == OMX_EventCmdComplete) {
   2821     if (p_session->state_change_pending == OMX_TRUE) {
   2822       p_session->state_change_pending = OMX_FALSE;
   2823       pthread_cond_signal(&p_session->cond);
   2824     }
   2825   }
   2826 
   2827   pthread_mutex_unlock(&p_session->lock);
   2828   CDBG("%s:%d]", __func__, __LINE__);
   2829   return OMX_ErrorNone;
   2830 }
   2831 
   2832 
   2833 
   2834 /* remove the first job from the queue with matching client handle */
   2835 mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_client_id(
   2836   mm_jpeg_queue_t* queue, uint32_t client_hdl)
   2837 {
   2838   mm_jpeg_q_node_t* node = NULL;
   2839   mm_jpeg_job_q_node_t* data = NULL;
   2840   mm_jpeg_job_q_node_t* job_node = NULL;
   2841   struct cam_list *head = NULL;
   2842   struct cam_list *pos = NULL;
   2843 
   2844   pthread_mutex_lock(&queue->lock);
   2845   head = &queue->head.list;
   2846   pos = head->next;
   2847   while(pos != head) {
   2848     node = member_of(pos, mm_jpeg_q_node_t, list);
   2849     data = (mm_jpeg_job_q_node_t *)node->data.p;
   2850 
   2851     if (data && (data->enc_info.client_handle == client_hdl)) {
   2852       CDBG_HIGH("%s:%d] found matching client handle", __func__, __LINE__);
   2853       job_node = data;
   2854       cam_list_del_node(&node->list);
   2855       queue->size--;
   2856       free(node);
   2857       CDBG_HIGH("%s: queue size = %d", __func__, queue->size);
   2858       break;
   2859     }
   2860     pos = pos->next;
   2861   }
   2862 
   2863   pthread_mutex_unlock(&queue->lock);
   2864 
   2865   return job_node;
   2866 }
   2867 
   2868 /* remove the first job from the queue with matching session id */
   2869 mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_session_id(
   2870   mm_jpeg_queue_t* queue, uint32_t session_id)
   2871 {
   2872   mm_jpeg_q_node_t* node = NULL;
   2873   mm_jpeg_job_q_node_t* data = NULL;
   2874   mm_jpeg_job_q_node_t* job_node = NULL;
   2875   struct cam_list *head = NULL;
   2876   struct cam_list *pos = NULL;
   2877 
   2878   pthread_mutex_lock(&queue->lock);
   2879   head = &queue->head.list;
   2880   pos = head->next;
   2881   while(pos != head) {
   2882     node = member_of(pos, mm_jpeg_q_node_t, list);
   2883     data = (mm_jpeg_job_q_node_t *)node->data.p;
   2884 
   2885     if (data && (data->enc_info.encode_job.session_id == session_id)) {
   2886       CDBG_HIGH("%s:%d] found matching session id", __func__, __LINE__);
   2887       job_node = data;
   2888       cam_list_del_node(&node->list);
   2889       queue->size--;
   2890       free(node);
   2891       CDBG_HIGH("%s: queue size = %d", __func__, queue->size);
   2892       break;
   2893     }
   2894     pos = pos->next;
   2895   }
   2896 
   2897   pthread_mutex_unlock(&queue->lock);
   2898 
   2899   return job_node;
   2900 }
   2901 
   2902 /* remove job from the queue with matching job id */
   2903 mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_job_id(
   2904   mm_jpeg_queue_t* queue, uint32_t job_id)
   2905 {
   2906   mm_jpeg_q_node_t* node = NULL;
   2907   mm_jpeg_job_q_node_t* data = NULL;
   2908   mm_jpeg_job_q_node_t* job_node = NULL;
   2909   struct cam_list *head = NULL;
   2910   struct cam_list *pos = NULL;
   2911   uint32_t lq_job_id;
   2912 
   2913   pthread_mutex_lock(&queue->lock);
   2914   head = &queue->head.list;
   2915   pos = head->next;
   2916   while(pos != head) {
   2917     node = member_of(pos, mm_jpeg_q_node_t, list);
   2918     data = (mm_jpeg_job_q_node_t *)node->data.p;
   2919 
   2920     if(NULL == data) {
   2921       CDBG_ERROR("%s:%d] Data is NULL", __func__, __LINE__);
   2922       pthread_mutex_unlock(&queue->lock);
   2923       return NULL;
   2924     }
   2925 
   2926     if (data->type == MM_JPEG_CMD_TYPE_DECODE_JOB) {
   2927       lq_job_id = data->dec_info.job_id;
   2928     } else {
   2929       lq_job_id = data->enc_info.job_id;
   2930     }
   2931 
   2932     if (data && (lq_job_id == job_id)) {
   2933       CDBG_HIGH("%s:%d] found matching job id", __func__, __LINE__);
   2934       job_node = data;
   2935       cam_list_del_node(&node->list);
   2936       queue->size--;
   2937       free(node);
   2938       break;
   2939     }
   2940     pos = pos->next;
   2941   }
   2942 
   2943   pthread_mutex_unlock(&queue->lock);
   2944 
   2945   return job_node;
   2946 }
   2947 
   2948 /* remove job from the queue with matching job id */
   2949 mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_unlk(
   2950   mm_jpeg_queue_t* queue, uint32_t job_id)
   2951 {
   2952   mm_jpeg_q_node_t* node = NULL;
   2953   mm_jpeg_job_q_node_t* data = NULL;
   2954   mm_jpeg_job_q_node_t* job_node = NULL;
   2955   struct cam_list *head = NULL;
   2956   struct cam_list *pos = NULL;
   2957 
   2958   head = &queue->head.list;
   2959   pos = head->next;
   2960   while(pos != head) {
   2961     node = member_of(pos, mm_jpeg_q_node_t, list);
   2962     data = (mm_jpeg_job_q_node_t *)node->data.p;
   2963 
   2964     if (data && (data->enc_info.job_id == job_id)) {
   2965       job_node = data;
   2966       cam_list_del_node(&node->list);
   2967       queue->size--;
   2968       free(node);
   2969       break;
   2970     }
   2971     pos = pos->next;
   2972   }
   2973 
   2974   return job_node;
   2975 }
   2976