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 #include <pthread.h>
     31 #include <errno.h>
     32 #include <sys/ioctl.h>
     33 #include <sys/types.h>
     34 #include <sys/stat.h>
     35 #include <sys/prctl.h>
     36 #include <fcntl.h>
     37 #include <poll.h>
     38 
     39 #include "mm_jpeg_dbg.h"
     40 #include "mm_jpeg_interface.h"
     41 #include "mm_jpeg.h"
     42 
     43 /* define max num of supported concurrent jpeg jobs by OMX engine.
     44  * Current, only one per time */
     45 #define NUM_MAX_JPEG_CNCURRENT_JOBS 1
     46 
     47 #define JOB_ID_MAGICVAL 0x1
     48 #define JOB_HIST_MAX 10000
     49 
     50 /** DUMP_TO_FILE:
     51  *  @filename: file name
     52  *  @p_addr: address of the buffer
     53  *  @len: buffer length
     54  *
     55  *  dump the image to the file
     56  **/
     57 #define DUMP_TO_FILE(filename, p_addr, len) ({ \
     58   int rc = 0; \
     59   FILE *fp = fopen(filename, "w+"); \
     60   if (fp) { \
     61     rc = fwrite(p_addr, 1, len, fp); \
     62     CDBG_HIGH("%s:%d] written size %d", __func__, __LINE__, len); \
     63     fclose(fp); \
     64   } else { \
     65     CDBG_ERROR("%s:%d] open %s failed", __func__, __LINE__, filename); \
     66   } \
     67 })
     68 
     69 /** DUMP_TO_FILE2:
     70  *  @filename: file name
     71  *  @p_addr: address of the buffer
     72  *  @len: buffer length
     73  *
     74  *  dump the image to the file if the memory is non-contiguous
     75  **/
     76 #define DUMP_TO_FILE2(filename, p_addr1, len1, paddr2, len2) ({ \
     77   int rc = 0; \
     78   FILE *fp = fopen(filename, "w+"); \
     79   if (fp) { \
     80     rc = fwrite(p_addr1, 1, len1, fp); \
     81     rc = fwrite(p_addr2, 1, len2, fp); \
     82     CDBG_HIGH("%s:%d] written %d %d", __func__, __LINE__, len1, len2); \
     83     fclose(fp); \
     84   } else { \
     85     CDBG_ERROR("%s:%d] open %s failed", __func__, __LINE__, filename); \
     86   } \
     87 })
     88 
     89 /** MM_JPEG_CHK_ABORT:
     90  *  @p: client pointer
     91  *  @ret: return value
     92  *  @label: label to jump to
     93  *
     94  *  check the abort failure
     95  **/
     96 #define MM_JPEG_CHK_ABORT(p, ret, label) ({ \
     97   if (OMX_TRUE == p->abort_flag) { \
     98     CDBG_ERROR("%s:%d] jpeg abort", __func__, __LINE__); \
     99     ret = OMX_ErrorNone; \
    100     goto label; \
    101   } \
    102 })
    103 
    104 #define GET_CLIENT_IDX(x) ((x) & 0xff)
    105 #define GET_SESSION_IDX(x) (((x) >> 8) & 0xff)
    106 #define GET_JOB_IDX(x) (((x) >> 16) & 0xff)
    107 
    108 OMX_ERRORTYPE mm_jpeg_ebd(OMX_HANDLETYPE hComponent,
    109     OMX_PTR pAppData,
    110     OMX_BUFFERHEADERTYPE* pBuffer);
    111 OMX_ERRORTYPE mm_jpeg_fbd(OMX_HANDLETYPE hComponent,
    112     OMX_PTR pAppData,
    113     OMX_BUFFERHEADERTYPE* pBuffer);
    114 OMX_ERRORTYPE mm_jpeg_event_handler(OMX_HANDLETYPE hComponent,
    115     OMX_PTR pAppData,
    116     OMX_EVENTTYPE eEvent,
    117     OMX_U32 nData1,
    118     OMX_U32 nData2,
    119     OMX_PTR pEventData);
    120 
    121 /** cirq_reset:
    122  *
    123  *  Arguments:
    124  *    @q: circular queue
    125  *
    126  *  Return:
    127  *       none
    128  *
    129  *  Description:
    130  *       Resets the circular queue
    131  *
    132  **/
    133 static inline void cirq_reset(mm_jpeg_cirq_t *q)
    134 {
    135   q->front = 0;
    136   q->rear = 0;
    137   q->count = 0;
    138   pthread_mutex_init(&q->lock, NULL);
    139 }
    140 
    141 /** cirq_empty:
    142  *
    143  *  Arguments:
    144  *    @q: circular queue
    145  *
    146  *  Return:
    147  *       none
    148  *
    149  *  Description:
    150  *       check if the curcular queue is empty
    151  *
    152  **/
    153 #define cirq_empty(q) (q->count == 0)
    154 
    155 /** cirq_full:
    156  *
    157  *  Arguments:
    158  *    @q: circular queue
    159  *
    160  *  Return:
    161  *       none
    162  *
    163  *  Description:
    164  *       check if the curcular queue is full
    165  *
    166  **/
    167 #define cirq_full(q) (q->count == MM_JPEG_CIRQ_SIZE)
    168 
    169 /** cirq_enqueue:
    170  *
    171  *  Arguments:
    172  *    @q: circular queue
    173  *    @data: data to be inserted
    174  *
    175  *  Return:
    176  *       true/false
    177  *
    178  *  Description:
    179  *       enqueue an element into circular queue
    180  *
    181  **/
    182 #define cirq_enqueue(q, type, data) ({ \
    183   int rc = 0; \
    184   pthread_mutex_lock(&q->lock); \
    185   if (cirq_full(q)) { \
    186     rc = -1; \
    187   } else { \
    188     q->type[q->rear] = data; \
    189     q->rear = (q->rear + 1) % MM_JPEG_CIRQ_SIZE; \
    190     q->count++; \
    191   } \
    192   pthread_mutex_unlock(&q->lock); \
    193   rc; \
    194 })
    195 
    196 /** cirq_dequeue:
    197  *
    198  *  Arguments:
    199  *    @q: circular queue
    200  *    @data: data to be popped
    201  *
    202  *  Return:
    203  *       true/false
    204  *
    205  *  Description:
    206  *       dequeue an element from the circular queue
    207  *
    208  **/
    209 #define cirq_dequeue(q, type, data) ({ \
    210   int rc = 0; \
    211   pthread_mutex_lock(&q->lock); \
    212   if (cirq_empty(q)) { \
    213     pthread_mutex_unlock(&q->lock); \
    214     rc = -1; \
    215   } else { \
    216     data = q->type[q->front]; \
    217     q->count--; \
    218   } \
    219   pthread_mutex_unlock(&q->lock); \
    220   rc; \
    221 })
    222 
    223 /**
    224  *
    225  * special queue functions for job queue
    226  **/
    227 mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_client_id(
    228   mm_jpeg_queue_t* queue, uint32_t client_hdl);
    229 mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_job_id(
    230   mm_jpeg_queue_t* queue, uint32_t job_id);
    231 mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_session_id(
    232   mm_jpeg_queue_t* queue, uint32_t session_id);
    233 mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_unlk(
    234   mm_jpeg_queue_t* queue, uint32_t job_id);
    235 
    236 /** mm_jpeg_pending_func_t:
    237  *
    238  * Intermediate function for transition change
    239  **/
    240 typedef OMX_ERRORTYPE (*mm_jpeg_transition_func_t)(void *);
    241 
    242 
    243 /** mm_jpeg_queue_func_t:
    244  *
    245  * Intermediate function for queue operation
    246  **/
    247 typedef void (*mm_jpeg_queue_func_t)(void *);
    248 
    249 /** mm_jpeg_session_send_buffers:
    250  *
    251  *  Arguments:
    252  *    @data: job session
    253  *
    254  *  Return:
    255  *       OMX error values
    256  *
    257  *  Description:
    258  *       Send the buffers to OMX layer
    259  *
    260  **/
    261 OMX_ERRORTYPE mm_jpeg_session_send_buffers(void *data)
    262 {
    263   uint32_t i = 0;
    264   mm_jpeg_job_session_t* p_session = (mm_jpeg_job_session_t *)data;
    265   OMX_ERRORTYPE ret = OMX_ErrorNone;
    266   QOMX_BUFFER_INFO lbuffer_info;
    267   mm_jpeg_encode_params_t *p_params = &p_session->params;
    268   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
    269 
    270   memset(&lbuffer_info, 0x0, sizeof(QOMX_BUFFER_INFO));
    271   for (i = 0; i < p_params->num_src_bufs; i++) {
    272     CDBG("%s:%d] Source buffer %d", __func__, __LINE__, i);
    273     lbuffer_info.fd = p_params->src_main_buf[i].fd;
    274     ret = OMX_UseBuffer(p_session->omx_handle, &(p_session->p_in_omx_buf[i]), 0,
    275       &lbuffer_info, p_params->src_main_buf[i].buf_size,
    276       p_params->src_main_buf[i].buf_vaddr);
    277     if (ret) {
    278       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
    279       return ret;
    280     }
    281   }
    282 
    283   for (i = 0; i < p_params->num_tmb_bufs; i++) {
    284     CDBG("%s:%d] Source buffer %d", __func__, __LINE__, i);
    285     lbuffer_info.fd = p_params->src_thumb_buf[i].fd;
    286     ret = OMX_UseBuffer(p_session->omx_handle,
    287         &(p_session->p_in_omx_thumb_buf[i]), 2,
    288         &lbuffer_info, p_params->src_thumb_buf[i].buf_size,
    289         p_params->src_thumb_buf[i].buf_vaddr);
    290     if (ret) {
    291       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
    292       return ret;
    293     }
    294   }
    295 
    296   for (i = 0; i < p_params->num_dst_bufs; i++) {
    297     CDBG("%s:%d] Dest buffer %d", __func__, __LINE__, i);
    298     ret = OMX_UseBuffer(p_session->omx_handle, &(p_session->p_out_omx_buf[i]),
    299       1, NULL, p_params->dest_buf[i].buf_size,
    300       p_params->dest_buf[i].buf_vaddr);
    301     if (ret) {
    302       CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
    303       return ret;
    304     }
    305   }
    306   CDBG("%s:%d]", __func__, __LINE__);
    307   return ret;
    308 }
    309 
    310 /** mm_jpeg_session_free_buffers:
    311  *
    312  *  Arguments:
    313  *    @data: job session
    314  *
    315  *  Return:
    316  *       OMX error values
    317  *
    318  *  Description:
    319  *       Free the buffers from OMX layer
    320  *
    321  **/
    322 OMX_ERRORTYPE mm_jpeg_session_free_buffers(void *data)
    323 {
    324   OMX_ERRORTYPE ret = OMX_ErrorNone;
    325   uint32_t i = 0;
    326   mm_jpeg_job_session_t* p_session = (mm_jpeg_job_session_t *)data;
    327   mm_jpeg_encode_params_t *p_params = &p_session->params;
    328   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
    329 
    330   for (i = 0; i < p_params->num_src_bufs; i++) {
    331     CDBG("%s:%d] Source buffer %d", __func__, __LINE__, i);
    332     ret = OMX_FreeBuffer(p_session->omx_handle, 0, p_session->p_in_omx_buf[i]);
    333     if (ret) {
    334       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
    335       return ret;
    336     }
    337   }
    338 
    339   for (i = 0; i < p_params->num_tmb_bufs; i++) {
    340     CDBG("%s:%d] Source buffer %d", __func__, __LINE__, i);
    341     ret = OMX_FreeBuffer(p_session->omx_handle, 2, p_session->p_in_omx_thumb_buf[i]);
    342     if (ret) {
    343       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
    344       return ret;
    345     }
    346   }
    347 
    348   for (i = 0; i < p_params->num_dst_bufs; i++) {
    349     CDBG("%s:%d] Dest buffer %d", __func__, __LINE__, i);
    350     ret = OMX_FreeBuffer(p_session->omx_handle, 1, p_session->p_out_omx_buf[i]);
    351     if (ret) {
    352       CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
    353       return ret;
    354     }
    355   }
    356   CDBG("%s:%d]", __func__, __LINE__);
    357   return ret;
    358 }
    359 
    360 /** mm_jpeg_session_change_state:
    361  *
    362  *  Arguments:
    363  *    @p_session: job session
    364  *    @new_state: new state to be transitioned to
    365  *    @p_exec: transition function
    366  *
    367  *  Return:
    368  *       OMX error values
    369  *
    370  *  Description:
    371  *       This method is used for state transition
    372  *
    373  **/
    374 OMX_ERRORTYPE mm_jpeg_session_change_state(mm_jpeg_job_session_t* p_session,
    375   OMX_STATETYPE new_state,
    376   mm_jpeg_transition_func_t p_exec)
    377 {
    378   OMX_ERRORTYPE ret = OMX_ErrorNone;
    379   OMX_STATETYPE current_state;
    380   CDBG("%s:%d] new_state %d p_exec %p", __func__, __LINE__,
    381     new_state, p_exec);
    382 
    383 
    384   pthread_mutex_lock(&p_session->lock);
    385 
    386   ret = OMX_GetState(p_session->omx_handle, &current_state);
    387 
    388   if (ret) {
    389     pthread_mutex_unlock(&p_session->lock);
    390     return ret;
    391   }
    392 
    393   if (current_state == new_state) {
    394     pthread_mutex_unlock(&p_session->lock);
    395     return OMX_ErrorNone;
    396   }
    397 
    398   p_session->state_change_pending = OMX_TRUE;
    399   ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandStateSet,
    400     new_state, NULL);
    401   if (ret) {
    402     CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
    403     pthread_mutex_unlock(&p_session->lock);
    404     return OMX_ErrorIncorrectStateTransition;
    405   }
    406   CDBG("%s:%d] ", __func__, __LINE__);
    407   if (OMX_ErrorNone != p_session->error_flag) {
    408     CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, p_session->error_flag);
    409     pthread_mutex_unlock(&p_session->lock);
    410     return p_session->error_flag;
    411   }
    412   if (p_exec) {
    413     ret = p_exec(p_session);
    414     if (ret) {
    415       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
    416       pthread_mutex_unlock(&p_session->lock);
    417       return ret;
    418     }
    419   }
    420   CDBG("%s:%d] ", __func__, __LINE__);
    421   if (p_session->state_change_pending) {
    422     CDBG("%s:%d] before wait", __func__, __LINE__);
    423     pthread_cond_wait(&p_session->cond, &p_session->lock);
    424     CDBG("%s:%d] after wait", __func__, __LINE__);
    425   }
    426   pthread_mutex_unlock(&p_session->lock);
    427   CDBG("%s:%d] ", __func__, __LINE__);
    428   return ret;
    429 }
    430 
    431 /** mm_jpeg_session_create:
    432  *
    433  *  Arguments:
    434  *    @p_session: job session
    435  *
    436  *  Return:
    437  *       OMX error types
    438  *
    439  *  Description:
    440  *       Create a jpeg encode session
    441  *
    442  **/
    443 OMX_ERRORTYPE mm_jpeg_session_create(mm_jpeg_job_session_t* p_session)
    444 {
    445   OMX_ERRORTYPE rc = OMX_ErrorNone;
    446   mm_jpeg_cirq_t *p_cirq = NULL;
    447 
    448   pthread_mutex_init(&p_session->lock, NULL);
    449   pthread_cond_init(&p_session->cond, NULL);
    450   cirq_reset(&p_session->cb_q);
    451   p_session->state_change_pending = OMX_FALSE;
    452   p_session->abort_flag = OMX_FALSE;
    453   p_session->error_flag = OMX_ErrorNone;
    454   p_session->ebd_count = 0;
    455   p_session->fbd_count = 0;
    456   p_session->encode_pid = -1;
    457   p_session->config = OMX_FALSE;
    458   p_session->exif_count_local = 0;
    459 
    460   p_session->omx_callbacks.EmptyBufferDone = mm_jpeg_ebd;
    461   p_session->omx_callbacks.FillBufferDone = mm_jpeg_fbd;
    462   p_session->omx_callbacks.EventHandler = mm_jpeg_event_handler;
    463   rc = OMX_GetHandle(&p_session->omx_handle,
    464     "OMX.qcom.image.jpeg.encoder",
    465     (void *)p_session,
    466     &p_session->omx_callbacks);
    467 
    468   if (OMX_ErrorNone != rc) {
    469     CDBG_ERROR("%s:%d] OMX_GetHandle failed (%d)", __func__, __LINE__, rc);
    470     return rc;
    471   }
    472   return rc;
    473 }
    474 
    475 /** mm_jpeg_session_destroy:
    476  *
    477  *  Arguments:
    478  *    @p_session: job session
    479  *
    480  *  Return:
    481  *       none
    482  *
    483  *  Description:
    484  *       Destroy a jpeg encode session
    485  *
    486  **/
    487 void mm_jpeg_session_destroy(mm_jpeg_job_session_t* p_session)
    488 {
    489   OMX_ERRORTYPE rc = OMX_ErrorNone;
    490 
    491   CDBG("%s:%d] E", __func__, __LINE__);
    492   if (NULL == p_session->omx_handle) {
    493     CDBG_ERROR("%s:%d] invalid handle", __func__, __LINE__);
    494     return;
    495   }
    496 
    497   rc = mm_jpeg_session_change_state(p_session, OMX_StateIdle, NULL);
    498   if (rc) {
    499     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
    500   }
    501 
    502   rc = mm_jpeg_session_change_state(p_session, OMX_StateLoaded,
    503     mm_jpeg_session_free_buffers);
    504   if (rc) {
    505     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
    506   }
    507 
    508   rc = OMX_FreeHandle(p_session->omx_handle);
    509   if (0 != rc) {
    510     CDBG_ERROR("%s:%d] OMX_FreeHandle failed (%d)", __func__, __LINE__, rc);
    511   }
    512   p_session->omx_handle = NULL;
    513 
    514   pthread_mutex_destroy(&p_session->lock);
    515   pthread_cond_destroy(&p_session->cond);
    516   CDBG("%s:%d] X", __func__, __LINE__);
    517 }
    518 
    519 /** mm_jpeg_session_config_main_buffer_offset:
    520  *
    521  *  Arguments:
    522  *    @p_session: job session
    523  *
    524  *  Return:
    525  *       OMX error values
    526  *
    527  *  Description:
    528  *       Configure the buffer offsets
    529  *
    530  **/
    531 OMX_ERRORTYPE mm_jpeg_session_config_main_buffer_offset(
    532   mm_jpeg_job_session_t* p_session)
    533 {
    534   OMX_ERRORTYPE rc = 0;
    535   int32_t i = 0;
    536   OMX_INDEXTYPE buffer_index;
    537   QOMX_YUV_FRAME_INFO frame_info;
    538   int32_t totalSize = 0;
    539   mm_jpeg_encode_params_t *p_params = &p_session->params;
    540   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
    541 
    542   mm_jpeg_buf_t *p_src_buf =
    543     &p_params->src_main_buf[p_jobparams->src_index];
    544 
    545   memset(&frame_info, 0x0, sizeof(QOMX_YUV_FRAME_INFO));
    546 
    547   frame_info.cbcrStartOffset[0] = p_src_buf->offset.mp[0].len;
    548   frame_info.cbcrStartOffset[1] = p_src_buf->offset.mp[1].len;
    549   frame_info.yOffset = p_src_buf->offset.mp[0].offset;
    550   frame_info.cbcrOffset[0] = p_src_buf->offset.mp[1].offset;
    551   frame_info.cbcrOffset[1] = p_src_buf->offset.mp[2].offset;
    552   totalSize = p_src_buf->buf_size;
    553 
    554   rc = OMX_GetExtensionIndex(p_session->omx_handle,
    555     QOMX_IMAGE_EXT_BUFFER_OFFSET_NAME, &buffer_index);
    556   if (rc != OMX_ErrorNone) {
    557     CDBG_ERROR("%s:%d] Failed", __func__, __LINE__);
    558     return rc;
    559   }
    560 
    561   CDBG_HIGH("%s:%d] yOffset = %d, cbcrOffset = (%d %d), totalSize = %d,"
    562     "cbcrStartOffset = (%d %d)", __func__, __LINE__,
    563     (int)frame_info.yOffset,
    564     (int)frame_info.cbcrOffset[0],
    565     (int)frame_info.cbcrOffset[1],
    566     totalSize,
    567     (int)frame_info.cbcrStartOffset[0],
    568     (int)frame_info.cbcrStartOffset[1]);
    569 
    570   rc = OMX_SetParameter(p_session->omx_handle, buffer_index, &frame_info);
    571   if (rc != OMX_ErrorNone) {
    572     CDBG_ERROR("%s:%d] Failed", __func__, __LINE__);
    573     return rc;
    574   }
    575   return rc;
    576 }
    577 
    578 /** mm_jpeg_encoding_mode:
    579  *
    580  *  Arguments:
    581  *    @p_session: job session
    582  *
    583  *  Return:
    584  *       OMX error values
    585  *
    586  *  Description:
    587  *       Configure the serial or parallel encoding
    588  *       mode
    589  *
    590  **/
    591 OMX_ERRORTYPE mm_jpeg_encoding_mode(
    592   mm_jpeg_job_session_t* p_session)
    593 {
    594   OMX_ERRORTYPE rc = 0;
    595   int32_t i = 0;
    596   OMX_INDEXTYPE indextype;
    597   QOMX_ENCODING_MODE encoding_mode;
    598   int32_t totalSize = 0;
    599   mm_jpeg_encode_params_t *p_params = &p_session->params;
    600   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
    601 
    602   rc = OMX_GetExtensionIndex(p_session->omx_handle,
    603     QOMX_IMAGE_EXT_ENCODING_MODE_NAME, &indextype);
    604   if (rc != OMX_ErrorNone) {
    605     CDBG_ERROR("%s:%d] Failed", __func__, __LINE__);
    606     return rc;
    607   }
    608 
    609   CDBG_HIGH("%s:%d] OMX_Serial_Encoding = %d, OMX_Parallel_Encoding = %d ", __func__, __LINE__,
    610     (int)OMX_Serial_Encoding,
    611     (int)OMX_Parallel_Encoding);
    612 
    613   encoding_mode = OMX_Serial_Encoding;
    614   rc = OMX_SetParameter(p_session->omx_handle, indextype, &encoding_mode);
    615   if (rc != OMX_ErrorNone) {
    616     CDBG_ERROR("%s:%d] Failed", __func__, __LINE__);
    617     return rc;
    618   }
    619   return rc;
    620 }
    621 
    622 /** map_jpeg_format:
    623  *
    624  *  Arguments:
    625  *    @color_fmt: color format
    626  *
    627  *  Return:
    628  *       OMX color format
    629  *
    630  *  Description:
    631  *       Map mmjpeg color format to OMX color format
    632  *
    633  **/
    634 int map_jpeg_format(mm_jpeg_color_format color_fmt)
    635 {
    636   switch (color_fmt) {
    637   case MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2:
    638     return (int)OMX_QCOM_IMG_COLOR_FormatYVU420SemiPlanar;
    639   case MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2:
    640     return (int)OMX_COLOR_FormatYUV420SemiPlanar;
    641   case MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V1:
    642     return (int)OMX_QCOM_IMG_COLOR_FormatYVU422SemiPlanar;
    643   case MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V1:
    644     return (int)OMX_COLOR_FormatYUV422SemiPlanar;
    645   case MM_JPEG_COLOR_FORMAT_YCRCBLP_H1V2:
    646     return (int)OMX_QCOM_IMG_COLOR_FormatYVU422SemiPlanar_h1v2;
    647   case MM_JPEG_COLOR_FORMAT_YCBCRLP_H1V2:
    648     return (int)OMX_QCOM_IMG_COLOR_FormatYUV422SemiPlanar_h1v2;
    649   case MM_JPEG_COLOR_FORMAT_YCRCBLP_H1V1:
    650     return (int)OMX_QCOM_IMG_COLOR_FormatYVU444SemiPlanar;
    651   case MM_JPEG_COLOR_FORMAT_YCBCRLP_H1V1:
    652     return (int)OMX_QCOM_IMG_COLOR_FormatYUV444SemiPlanar;
    653   default:
    654     CDBG_ERROR("%s:%d] invalid format %d", __func__, __LINE__, color_fmt);
    655     return (int)OMX_QCOM_IMG_COLOR_FormatYVU420SemiPlanar;
    656   }
    657 }
    658 
    659 /** mm_jpeg_session_config_port:
    660  *
    661  *  Arguments:
    662  *    @p_session: job session
    663  *
    664  *  Return:
    665  *       OMX error values
    666  *
    667  *  Description:
    668  *       Configure OMX ports
    669  *
    670  **/
    671 OMX_ERRORTYPE mm_jpeg_session_config_ports(mm_jpeg_job_session_t* p_session)
    672 {
    673   OMX_ERRORTYPE ret = OMX_ErrorNone;
    674   mm_jpeg_encode_params_t *p_params = &p_session->params;
    675   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
    676 
    677   mm_jpeg_buf_t *p_src_buf =
    678     &p_params->src_main_buf[p_jobparams->src_index];
    679 
    680   p_session->inputPort.nPortIndex = 0;
    681   p_session->outputPort.nPortIndex = 1;
    682   p_session->inputTmbPort.nPortIndex = 2;
    683 
    684   ret = OMX_GetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
    685     &p_session->inputPort);
    686   if (ret) {
    687     CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
    688     return ret;
    689   }
    690 
    691   ret = OMX_GetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
    692     &p_session->inputTmbPort);
    693   if (ret) {
    694     CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
    695     return ret;
    696   }
    697 
    698   ret = OMX_GetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
    699     &p_session->outputPort);
    700   if (ret) {
    701     CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
    702     return ret;
    703   }
    704 
    705   p_session->inputPort.format.image.nFrameWidth =
    706     p_jobparams->main_dim.src_dim.width;
    707   p_session->inputPort.format.image.nFrameHeight =
    708     p_jobparams->main_dim.src_dim.height;
    709   p_session->inputPort.format.image.nStride =
    710     p_src_buf->offset.mp[0].stride;
    711   p_session->inputPort.format.image.nSliceHeight =
    712     p_src_buf->offset.mp[0].scanline;
    713   p_session->inputPort.format.image.eColorFormat =
    714     map_jpeg_format(p_params->color_format);
    715   p_session->inputPort.nBufferSize =
    716     p_params->src_main_buf[p_jobparams->src_index].buf_size;
    717   p_session->inputPort.nBufferCountActual = p_params->num_src_bufs;
    718   ret = OMX_SetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
    719     &p_session->inputPort);
    720   if (ret) {
    721     CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
    722     return ret;
    723   }
    724 
    725   if (p_session->params.encode_thumbnail) {
    726     mm_jpeg_buf_t *p_tmb_buf =
    727       &p_params->src_thumb_buf[p_jobparams->thumb_index];
    728     p_session->inputTmbPort.format.image.nFrameWidth =
    729       p_jobparams->thumb_dim.src_dim.width;
    730     p_session->inputTmbPort.format.image.nFrameHeight =
    731       p_jobparams->thumb_dim.src_dim.height;
    732     p_session->inputTmbPort.format.image.nStride =
    733       p_tmb_buf->offset.mp[0].stride;
    734     p_session->inputTmbPort.format.image.nSliceHeight =
    735       p_tmb_buf->offset.mp[0].scanline;
    736     p_session->inputTmbPort.format.image.eColorFormat =
    737       map_jpeg_format(p_params->color_format);
    738     p_session->inputTmbPort.nBufferSize =
    739       p_params->src_thumb_buf[p_jobparams->thumb_index].buf_size;
    740     p_session->inputTmbPort.nBufferCountActual = p_params->num_tmb_bufs;
    741     ret = OMX_SetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
    742       &p_session->inputTmbPort);
    743 
    744     if (ret) {
    745       CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
    746       return ret;
    747     }
    748 
    749     // Enable thumbnail port
    750     ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandPortEnable,
    751         p_session->inputTmbPort.nPortIndex, NULL);
    752 
    753     if (ret) {
    754       CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
    755       return ret;
    756     }
    757   } else {
    758     // Disable thumbnail port
    759     ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandPortDisable,
    760         p_session->inputTmbPort.nPortIndex, NULL);
    761 
    762     if (ret) {
    763       CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
    764       return ret;
    765     }
    766   }
    767 
    768   p_session->outputPort.nBufferSize =
    769     p_params->dest_buf[p_jobparams->dst_index].buf_size;
    770   p_session->outputPort.nBufferCountActual = p_params->num_dst_bufs;
    771   ret = OMX_SetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
    772     &p_session->outputPort);
    773   if (ret) {
    774     CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
    775     return ret;
    776   }
    777 
    778   return ret;
    779 }
    780 
    781 /** mm_jpeg_omx_config_thumbnail:
    782  *
    783  *  Arguments:
    784  *    @p_session: job session
    785  *
    786  *  Return:
    787  *       OMX error values
    788  *
    789  *  Description:
    790  *       Configure OMX ports
    791  *
    792  **/
    793 OMX_ERRORTYPE mm_jpeg_session_config_thumbnail(mm_jpeg_job_session_t* p_session)
    794 {
    795   OMX_ERRORTYPE ret = OMX_ErrorNone;
    796   QOMX_THUMBNAIL_INFO thumbnail_info;
    797   OMX_INDEXTYPE thumb_indextype;
    798   OMX_BOOL encode_thumbnail = OMX_FALSE;
    799   mm_jpeg_encode_params_t *p_params = &p_session->params;
    800   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
    801   mm_jpeg_dim_t *p_thumb_dim = &p_jobparams->thumb_dim;
    802   mm_jpeg_dim_t *p_main_dim = &p_jobparams->main_dim;
    803   QOMX_YUV_FRAME_INFO *p_frame_info = &thumbnail_info.tmbOffset;
    804   mm_jpeg_buf_t *p_tmb_buf = &p_params->src_thumb_buf[p_jobparams->thumb_index];
    805 
    806   CDBG_HIGH("%s:%d] encode_thumbnail %d", __func__, __LINE__,
    807     p_params->encode_thumbnail);
    808   if (OMX_FALSE == p_params->encode_thumbnail) {
    809     return ret;
    810   }
    811 
    812   if ((p_thumb_dim->dst_dim.width == 0) || (p_thumb_dim->dst_dim.height == 0)) {
    813     CDBG_ERROR("%s:%d] Error invalid output dim for thumbnail",
    814       __func__, __LINE__);
    815     return OMX_ErrorBadParameter;
    816   }
    817 
    818   if ((p_thumb_dim->src_dim.width == 0) || (p_thumb_dim->src_dim.height == 0)) {
    819     CDBG_ERROR("%s:%d] Error invalid input dim for thumbnail",
    820       __func__, __LINE__);
    821     return OMX_ErrorBadParameter;
    822   }
    823 
    824   if ((p_thumb_dim->crop.width == 0) || (p_thumb_dim->crop.height == 0)) {
    825     p_thumb_dim->crop.width = p_thumb_dim->src_dim.width;
    826     p_thumb_dim->crop.height = p_thumb_dim->src_dim.height;
    827   }
    828 
    829   /* check crop boundary */
    830   if ((p_thumb_dim->crop.width + p_thumb_dim->crop.left > p_thumb_dim->src_dim.width) ||
    831     (p_thumb_dim->crop.height + p_thumb_dim->crop.top > p_thumb_dim->src_dim.height)) {
    832     CDBG_ERROR("%s:%d] invalid crop boundary (%d, %d) offset (%d, %d) out of (%d, %d)",
    833       __func__, __LINE__,
    834       p_thumb_dim->crop.width,
    835       p_thumb_dim->crop.height,
    836       p_thumb_dim->crop.left,
    837       p_thumb_dim->crop.top,
    838       p_thumb_dim->src_dim.width,
    839       p_thumb_dim->src_dim.height);
    840     return OMX_ErrorBadParameter;
    841   }
    842 
    843   memset(&thumbnail_info, 0x0, sizeof(QOMX_THUMBNAIL_INFO));
    844   ret = OMX_GetExtensionIndex(p_session->omx_handle,
    845     QOMX_IMAGE_EXT_THUMBNAIL_NAME,
    846     &thumb_indextype);
    847   if (ret) {
    848     CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
    849     return ret;
    850   }
    851 
    852   /* fill thumbnail info */
    853   thumbnail_info.scaling_enabled = 1;
    854   thumbnail_info.input_width = p_thumb_dim->src_dim.width;
    855   thumbnail_info.input_height = p_thumb_dim->src_dim.height;
    856   thumbnail_info.crop_info.nWidth = p_thumb_dim->crop.width;
    857   thumbnail_info.crop_info.nHeight = p_thumb_dim->crop.height;
    858   thumbnail_info.crop_info.nLeft = p_thumb_dim->crop.left;
    859   thumbnail_info.crop_info.nTop = p_thumb_dim->crop.top;
    860 
    861   if ((p_main_dim->src_dim.width < p_thumb_dim->src_dim.width) ||
    862     (p_main_dim->src_dim.height < p_thumb_dim->src_dim.height)) {
    863     CDBG_ERROR("%s:%d] Improper thumbnail dim %dx%d resetting to %dx%d",
    864       __func__, __LINE__,
    865       p_thumb_dim->src_dim.width,
    866       p_thumb_dim->src_dim.height,
    867       p_main_dim->src_dim.width,
    868       p_main_dim->src_dim.height);
    869     thumbnail_info.input_width = p_main_dim->src_dim.width;
    870     thumbnail_info.input_height = p_main_dim->src_dim.height;
    871     if ((thumbnail_info.crop_info.nWidth > thumbnail_info.input_width)
    872       || (thumbnail_info.crop_info.nHeight > thumbnail_info.input_height)) {
    873       thumbnail_info.crop_info.nLeft = 0;
    874       thumbnail_info.crop_info.nTop = 0;
    875       thumbnail_info.crop_info.nWidth = thumbnail_info.input_width;
    876       thumbnail_info.crop_info.nHeight = thumbnail_info.input_height;
    877     }
    878   }
    879 
    880   if ((p_thumb_dim->dst_dim.width > p_thumb_dim->src_dim.width)
    881     || (p_thumb_dim->dst_dim.height > p_thumb_dim->src_dim.height)) {
    882     CDBG_ERROR("%s:%d] Incorrect thumbnail dim %dx%d resetting to %dx%d",
    883       __func__, __LINE__,
    884       p_thumb_dim->dst_dim.width,
    885       p_thumb_dim->dst_dim.height,
    886       p_thumb_dim->src_dim.width,
    887       p_thumb_dim->src_dim.height);
    888     thumbnail_info.output_width = p_thumb_dim->src_dim.width;
    889     thumbnail_info.output_height = p_thumb_dim->src_dim.height;
    890   } else {
    891     thumbnail_info.output_width = p_thumb_dim->dst_dim.width;
    892     thumbnail_info.output_height = p_thumb_dim->dst_dim.height;
    893   }
    894 
    895   memset(p_frame_info, 0x0, sizeof(*p_frame_info));
    896 
    897   p_frame_info->cbcrStartOffset[0] = p_tmb_buf->offset.mp[0].len;
    898   p_frame_info->cbcrStartOffset[1] = p_tmb_buf->offset.mp[1].len;
    899   p_frame_info->yOffset = p_tmb_buf->offset.mp[0].offset;
    900   p_frame_info->cbcrOffset[0] = p_tmb_buf->offset.mp[1].offset;
    901   p_frame_info->cbcrOffset[1] = p_tmb_buf->offset.mp[2].offset;
    902 
    903   ret = OMX_SetConfig(p_session->omx_handle, thumb_indextype,
    904     &thumbnail_info);
    905   if (ret) {
    906     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
    907     return ret;
    908   }
    909 
    910   return ret;
    911 }
    912 
    913 /** mm_jpeg_session_config_main_crop:
    914  *
    915  *  Arguments:
    916  *    @p_session: job session
    917  *
    918  *  Return:
    919  *       OMX error values
    920  *
    921  *  Description:
    922  *       Configure main image crop
    923  *
    924  **/
    925 OMX_ERRORTYPE mm_jpeg_session_config_main_crop(mm_jpeg_job_session_t *p_session)
    926 {
    927   OMX_CONFIG_RECTTYPE rect_type_in, rect_type_out;
    928   OMX_ERRORTYPE ret = OMX_ErrorNone;
    929   mm_jpeg_encode_params_t *p_params = &p_session->params;
    930   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
    931   mm_jpeg_dim_t *dim = &p_jobparams->main_dim;
    932 
    933   if ((dim->crop.width == 0) || (dim->crop.height == 0)) {
    934     dim->crop.width = dim->src_dim.width;
    935     dim->crop.height = dim->src_dim.height;
    936   }
    937   /* error check first */
    938   if ((dim->crop.width + dim->crop.left > dim->src_dim.width) ||
    939     (dim->crop.height + dim->crop.top > dim->src_dim.height)) {
    940     CDBG_ERROR("%s:%d] invalid crop boundary (%d, %d) out of (%d, %d)",
    941       __func__, __LINE__,
    942       dim->crop.width + dim->crop.left,
    943       dim->crop.height + dim->crop.top,
    944       dim->src_dim.width,
    945       dim->src_dim.height);
    946     return OMX_ErrorBadParameter;
    947   }
    948 
    949   memset(&rect_type_in, 0, sizeof(rect_type_in));
    950   memset(&rect_type_out, 0, sizeof(rect_type_out));
    951   rect_type_in.nPortIndex = 0;
    952   rect_type_out.nPortIndex = 0;
    953 
    954   if ((dim->src_dim.width != dim->crop.width) ||
    955     (dim->src_dim.height != dim->crop.height) ||
    956     (dim->src_dim.width != dim->dst_dim.width) ||
    957     (dim->src_dim.height != dim->dst_dim.height)) {
    958     /* Scaler information */
    959     rect_type_in.nWidth = CEILING2(dim->crop.width);
    960     rect_type_in.nHeight = CEILING2(dim->crop.height);
    961     rect_type_in.nLeft = dim->crop.left;
    962     rect_type_in.nTop = dim->crop.top;
    963 
    964     if (dim->dst_dim.width && dim->dst_dim.height) {
    965       rect_type_out.nWidth = dim->dst_dim.width;
    966       rect_type_out.nHeight = dim->dst_dim.height;
    967     }
    968   }
    969 
    970   ret = OMX_SetConfig(p_session->omx_handle, OMX_IndexConfigCommonInputCrop,
    971     &rect_type_in);
    972   if (OMX_ErrorNone != ret) {
    973     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
    974     return ret;
    975   }
    976 
    977   CDBG("%s:%d] OMX_IndexConfigCommonInputCrop w = %d, h = %d, l = %d, t = %d,"
    978     " port_idx = %d", __func__, __LINE__,
    979     (int)rect_type_in.nWidth, (int)rect_type_in.nHeight,
    980     (int)rect_type_in.nLeft, (int)rect_type_in.nTop,
    981     (int)rect_type_in.nPortIndex);
    982 
    983   ret = OMX_SetConfig(p_session->omx_handle, OMX_IndexConfigCommonOutputCrop,
    984     &rect_type_out);
    985   if (OMX_ErrorNone != ret) {
    986     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
    987     return ret;
    988   }
    989   CDBG("%s:%d] OMX_IndexConfigCommonOutputCrop w = %d, h = %d,"
    990     " port_idx = %d", __func__, __LINE__,
    991     (int)rect_type_out.nWidth, (int)rect_type_out.nHeight,
    992     (int)rect_type_out.nPortIndex);
    993 
    994   return ret;
    995 }
    996 
    997 /** mm_jpeg_session_config_main:
    998  *
    999  *  Arguments:
   1000  *    @p_session: job session
   1001  *
   1002  *  Return:
   1003  *       OMX error values
   1004  *
   1005  *  Description:
   1006  *       Configure main image
   1007  *
   1008  **/
   1009 OMX_ERRORTYPE mm_jpeg_session_config_main(mm_jpeg_job_session_t *p_session)
   1010 {
   1011   OMX_ERRORTYPE rc = OMX_ErrorNone;
   1012   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
   1013 
   1014   /* config port */
   1015   CDBG("%s:%d] config port", __func__, __LINE__);
   1016   rc = mm_jpeg_session_config_ports(p_session);
   1017   if (OMX_ErrorNone != rc) {
   1018     CDBG_ERROR("%s: config port failed", __func__);
   1019     return rc;
   1020   }
   1021 
   1022   /* config buffer offset */
   1023   CDBG("%s:%d] config main buf offset", __func__, __LINE__);
   1024   rc = mm_jpeg_session_config_main_buffer_offset(p_session);
   1025   if (OMX_ErrorNone != rc) {
   1026     CDBG_ERROR("%s: config buffer offset failed", __func__);
   1027     return rc;
   1028   }
   1029 
   1030   /* set the encoding mode */
   1031   mm_jpeg_encoding_mode(p_session);
   1032 
   1033   return rc;
   1034 }
   1035 
   1036 /** mm_jpeg_session_config_common:
   1037  *
   1038  *  Arguments:
   1039  *    @p_session: job session
   1040  *
   1041  *  Return:
   1042  *       OMX error values
   1043  *
   1044  *  Description:
   1045  *       Configure common parameters
   1046  *
   1047  **/
   1048 OMX_ERRORTYPE mm_jpeg_session_config_common(mm_jpeg_job_session_t *p_session)
   1049 {
   1050   OMX_ERRORTYPE rc = OMX_ErrorNone;
   1051   int i;
   1052   OMX_INDEXTYPE exif_idx;
   1053   OMX_CONFIG_ROTATIONTYPE rotate;
   1054   mm_jpeg_encode_params_t *p_params = &p_session->params;
   1055   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
   1056   QOMX_EXIF_INFO exif_info;
   1057 
   1058   /* set rotation */
   1059   memset(&rotate, 0, sizeof(rotate));
   1060   rotate.nPortIndex = 1;
   1061   rotate.nRotation = p_jobparams->rotation;
   1062   rc = OMX_SetConfig(p_session->omx_handle, OMX_IndexConfigCommonRotate,
   1063     &rotate);
   1064   if (OMX_ErrorNone != rc) {
   1065       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, rc);
   1066       return rc;
   1067   }
   1068   CDBG("%s:%d] Set rotation to %d at port_idx = %d", __func__, __LINE__,
   1069     (int)p_jobparams->rotation, (int)rotate.nPortIndex);
   1070 
   1071   /* Set Exif data*/
   1072   memset(&p_session->exif_info_local[0], 0, sizeof(p_session->exif_info_local));
   1073 
   1074 
   1075     /* set exif tags */
   1076     rc = OMX_GetExtensionIndex(p_session->omx_handle, QOMX_IMAGE_EXT_EXIF_NAME,
   1077       &exif_idx);
   1078   if (OMX_ErrorNone != rc) {
   1079     CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, rc);
   1080     return rc;
   1081   }
   1082   CDBG_HIGH("%s:%d] Num of exif entries passed from HAL: %d", __func__, __LINE__,
   1083       (int)p_jobparams->exif_info.numOfEntries);
   1084   if (p_jobparams->exif_info.numOfEntries > 0) {
   1085      rc = OMX_SetConfig(p_session->omx_handle, exif_idx,
   1086       &p_jobparams->exif_info);
   1087     if (OMX_ErrorNone != rc) {
   1088       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, rc);
   1089       return rc;
   1090     }
   1091   }
   1092   /*parse aditional exif data from the metadata if present*/
   1093   if ((NULL != p_jobparams->p_metadata_v3) ||
   1094     (NULL != p_jobparams->p_metadata_v1)) {
   1095     exif_info.numOfEntries = 0;
   1096     exif_info.exif_data = &p_session->exif_info_local[0];
   1097 
   1098     if (NULL != p_jobparams->p_metadata_v3) {
   1099       process_meta_data_v3(p_jobparams->p_metadata_v3,
   1100           &exif_info, &p_jobparams->cam_exif_params);
   1101     } else {
   1102       process_meta_data_v1(p_jobparams->p_metadata_v1,
   1103         &exif_info, &p_jobparams->cam_exif_params);
   1104     }
   1105     /* After Parse metadata */
   1106     p_session->exif_count_local = exif_info.numOfEntries;
   1107 
   1108     if (exif_info.numOfEntries > 0) {
   1109       /* set exif tags */
   1110       CDBG("%s:%d] exif tags from metadata count %d", __func__, __LINE__,
   1111         (int)exif_info.numOfEntries);
   1112       rc = OMX_SetConfig(p_session->omx_handle, exif_idx,
   1113       &exif_info);
   1114     if (OMX_ErrorNone != rc) {
   1115       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, rc);
   1116       return rc;
   1117       }
   1118     }
   1119   } else {
   1120     CDBG_ERROR("%s:%d] Metadata is null", __func__, __LINE__, rc);
   1121   }
   1122 
   1123   return rc;
   1124 }
   1125 
   1126 /** mm_jpeg_session_abort:
   1127  *
   1128  *  Arguments:
   1129  *    @p_session: jpeg session
   1130  *
   1131  *  Return:
   1132  *       OMX_BOOL
   1133  *
   1134  *  Description:
   1135  *       Abort ongoing job
   1136  *
   1137  **/
   1138 OMX_BOOL mm_jpeg_session_abort(mm_jpeg_job_session_t *p_session)
   1139 {
   1140   OMX_ERRORTYPE ret = OMX_ErrorNone;
   1141 
   1142   CDBG("%s:%d] E", __func__, __LINE__);
   1143   pthread_mutex_lock(&p_session->lock);
   1144   if (OMX_TRUE == p_session->abort_flag) {
   1145     pthread_mutex_unlock(&p_session->lock);
   1146     CDBG("%s:%d] **** ALREADY ABORTED", __func__, __LINE__);
   1147     return 0;
   1148   }
   1149   p_session->abort_flag = OMX_TRUE;
   1150   if (OMX_TRUE == p_session->encoding) {
   1151     p_session->state_change_pending = OMX_TRUE;
   1152 
   1153     CDBG("%s:%d] **** ABORTING", __func__, __LINE__);
   1154 
   1155     ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandStateSet,
   1156     OMX_StateIdle, NULL);
   1157 
   1158     if (ret != OMX_ErrorNone) {
   1159       CDBG("%s:%d] OMX_SendCommand returned error %d", __func__, __LINE__, ret);
   1160       pthread_mutex_unlock(&p_session->lock);
   1161       return 1;
   1162     }
   1163     ret = mm_jpeg_destroy_job(p_session);
   1164     if (ret != 0) {
   1165       CDBG("%s:%d] Destroy job returned error %d", __func__, __LINE__, rc);
   1166     }
   1167 
   1168     CDBG("%s:%d] before wait", __func__, __LINE__);
   1169     pthread_cond_wait(&p_session->cond, &p_session->lock);
   1170     CDBG("%s:%d] after wait", __func__, __LINE__);
   1171   }
   1172   pthread_mutex_unlock(&p_session->lock);
   1173   CDBG("%s:%d] X", __func__, __LINE__);
   1174   return 0;
   1175 }
   1176 
   1177 /** mm_jpeg_get_job_idx:
   1178  *
   1179  *  Arguments:
   1180  *    @my_obj: jpeg object
   1181  *    @client_idx: client index
   1182  *
   1183  *  Return:
   1184  *       job index
   1185  *
   1186  *  Description:
   1187  *       Get job index by client id
   1188  *
   1189  **/
   1190 inline int mm_jpeg_get_new_session_idx(mm_jpeg_obj *my_obj, int client_idx,
   1191   mm_jpeg_job_session_t **pp_session)
   1192 {
   1193   int i = 0;
   1194   int index = -1;
   1195   for (i = 0; i < MM_JPEG_MAX_SESSION; i++) {
   1196     pthread_mutex_lock(&my_obj->clnt_mgr[client_idx].lock);
   1197     if (!my_obj->clnt_mgr[client_idx].session[i].active) {
   1198       *pp_session = &my_obj->clnt_mgr[client_idx].session[i];
   1199       my_obj->clnt_mgr[client_idx].session[i].active = OMX_TRUE;
   1200       index = i;
   1201       pthread_mutex_unlock(&my_obj->clnt_mgr[client_idx].lock);
   1202       break;
   1203     }
   1204     pthread_mutex_unlock(&my_obj->clnt_mgr[client_idx].lock);
   1205   }
   1206   return index;
   1207 }
   1208 
   1209 /** mm_jpeg_get_job_idx:
   1210  *
   1211  *  Arguments:
   1212  *    @my_obj: jpeg object
   1213  *    @client_idx: client index
   1214  *
   1215  *  Return:
   1216  *       job index
   1217  *
   1218  *  Description:
   1219  *       Get job index by client id
   1220  *
   1221  **/
   1222 inline void mm_jpeg_remove_session_idx(mm_jpeg_obj *my_obj, uint32_t job_id)
   1223 {
   1224   int client_idx =  GET_CLIENT_IDX(job_id);
   1225   int session_idx= GET_SESSION_IDX(job_id);
   1226   CDBG("%s:%d] client_idx %d session_idx %d", __func__, __LINE__,
   1227     client_idx, session_idx);
   1228   pthread_mutex_lock(&my_obj->clnt_mgr[client_idx].lock);
   1229   my_obj->clnt_mgr[client_idx].session[session_idx].active = OMX_FALSE;
   1230   pthread_mutex_unlock(&my_obj->clnt_mgr[client_idx].lock);
   1231 }
   1232 
   1233 /** mm_jpeg_get_session_idx:
   1234  *
   1235  *  Arguments:
   1236  *    @my_obj: jpeg object
   1237  *    @client_idx: client index
   1238  *
   1239  *  Return:
   1240  *       job index
   1241  *
   1242  *  Description:
   1243  *       Get job index by client id
   1244  *
   1245  **/
   1246 inline mm_jpeg_job_session_t *mm_jpeg_get_session(mm_jpeg_obj *my_obj, uint32_t job_id)
   1247 {
   1248   mm_jpeg_job_session_t *p_session = NULL;
   1249   int client_idx =  GET_CLIENT_IDX(job_id);
   1250   int session_idx= GET_SESSION_IDX(job_id);
   1251 
   1252   CDBG("%s:%d] client_idx %d session_idx %d", __func__, __LINE__,
   1253     client_idx, session_idx);
   1254   if ((session_idx >= MM_JPEG_MAX_SESSION) ||
   1255     (client_idx >= MAX_JPEG_CLIENT_NUM)) {
   1256     CDBG_ERROR("%s:%d] invalid job id %x", __func__, __LINE__,
   1257       job_id);
   1258     return NULL;
   1259   }
   1260   pthread_mutex_lock(&my_obj->clnt_mgr[client_idx].lock);
   1261   p_session = &my_obj->clnt_mgr[client_idx].session[session_idx];
   1262   pthread_mutex_unlock(&my_obj->clnt_mgr[client_idx].lock);
   1263   return p_session;
   1264 }
   1265 
   1266 /** mm_jpeg_configure_params
   1267  *
   1268  *  Arguments:
   1269  *    @p_session: encode session
   1270  *
   1271  *  Return:
   1272  *       none
   1273  *
   1274  *  Description:
   1275  *       Configure the job specific params
   1276  *
   1277  **/
   1278 static OMX_ERRORTYPE mm_jpeg_configure_job_params(
   1279   mm_jpeg_job_session_t *p_session)
   1280 {
   1281   OMX_ERRORTYPE ret = OMX_ErrorNone;
   1282   OMX_IMAGE_PARAM_QFACTORTYPE q_factor;
   1283   mm_jpeg_encode_params_t *p_params = &p_session->params;
   1284   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
   1285 
   1286     /* common config */
   1287   ret = mm_jpeg_session_config_common(p_session);
   1288   if (OMX_ErrorNone != ret) {
   1289     CDBG_ERROR("%s:%d] config common failed", __func__, __LINE__);
   1290 
   1291   }
   1292 
   1293   /* config Main Image crop */
   1294   CDBG("%s:%d] config main crop", __func__, __LINE__);
   1295   ret = mm_jpeg_session_config_main_crop(p_session);
   1296   if (OMX_ErrorNone != ret) {
   1297     CDBG_ERROR("%s: config crop failed", __func__);
   1298     return ret;
   1299   }
   1300 
   1301   /* set quality */
   1302   memset(&q_factor, 0, sizeof(q_factor));
   1303   q_factor.nPortIndex = 0;
   1304   q_factor.nQFactor = p_params->quality;
   1305   ret = OMX_SetConfig(p_session->omx_handle, OMX_IndexParamQFactor, &q_factor);
   1306   CDBG("%s:%d] config QFactor: %d", __func__, __LINE__, (int)q_factor.nQFactor);
   1307   if (OMX_ErrorNone != ret) {
   1308     CDBG_ERROR("%s:%d] Error setting Q factor %d", __func__, __LINE__, ret);
   1309     return ret;
   1310   }
   1311 
   1312   /* config thumbnail */
   1313   ret = mm_jpeg_session_config_thumbnail(p_session);
   1314   if (OMX_ErrorNone != ret) {
   1315     CDBG_ERROR("%s:%d] config thumbnail img failed", __func__, __LINE__);
   1316     return ret;
   1317   }
   1318 
   1319   return ret;
   1320 }
   1321 /** mm_jpeg_session_configure:
   1322  *
   1323  *  Arguments:
   1324  *    @data: encode session
   1325  *
   1326  *  Return:
   1327  *       none
   1328  *
   1329  *  Description:
   1330  *       Configure the session
   1331  *
   1332  **/
   1333 static OMX_ERRORTYPE mm_jpeg_session_configure(mm_jpeg_job_session_t *p_session)
   1334 {
   1335   OMX_ERRORTYPE ret = OMX_ErrorNone;
   1336   mm_jpeg_encode_params_t *p_params = &p_session->params;
   1337   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
   1338   mm_jpeg_obj *my_obj = (mm_jpeg_obj *)p_session->jpeg_obj;
   1339 
   1340   CDBG("%s:%d] E ", __func__, __LINE__);
   1341 
   1342   MM_JPEG_CHK_ABORT(p_session, ret, error);
   1343 
   1344   /* config main img */
   1345   ret = mm_jpeg_session_config_main(p_session);
   1346   if (OMX_ErrorNone != ret) {
   1347     CDBG_ERROR("%s:%d] config main img failed", __func__, __LINE__);
   1348     goto error;
   1349   }
   1350   ret = mm_jpeg_session_change_state(p_session, OMX_StateIdle,
   1351     mm_jpeg_session_send_buffers);
   1352   if (ret) {
   1353     CDBG_ERROR("%s:%d] change state to idle failed %d",
   1354       __func__, __LINE__, ret);
   1355     goto error;
   1356   }
   1357 
   1358   ret = mm_jpeg_session_change_state(p_session, OMX_StateExecuting,
   1359     NULL);
   1360   if (ret) {
   1361     CDBG_ERROR("%s:%d] change state to executing failed %d",
   1362       __func__, __LINE__, ret);
   1363     goto error;
   1364   }
   1365 
   1366 error:
   1367   CDBG("%s:%d] X ret %d", __func__, __LINE__, ret);
   1368   return ret;
   1369 }
   1370 
   1371 /** mm_jpeg_session_encode:
   1372  *
   1373  *  Arguments:
   1374  *    @p_session: encode session
   1375  *
   1376  *  Return:
   1377  *       OMX_ERRORTYPE
   1378  *
   1379  *  Description:
   1380  *       Start the encoding
   1381  *
   1382  **/
   1383 static inline void mm_jpeg_job_done(mm_jpeg_job_session_t *p_session)
   1384 {
   1385   mm_jpeg_obj *my_obj = (mm_jpeg_obj *)p_session->jpeg_obj;
   1386   mm_jpeg_job_q_node_t *node = NULL;
   1387 
   1388   /*Destroy job related params*/
   1389   mm_jpeg_destroy_job(p_session);
   1390 
   1391   /*remove the job*/
   1392   node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->ongoing_job_q,
   1393     p_session->jobId);
   1394   if (node) {
   1395     free(node);
   1396   }
   1397   p_session->encoding = OMX_FALSE;
   1398 
   1399   /* wake up jobMgr thread to work on new job if there is any */
   1400   cam_sem_post(&my_obj->job_mgr.job_sem);
   1401 }
   1402 
   1403 /** mm_jpeg_session_encode:
   1404  *
   1405  *  Arguments:
   1406  *    @p_session: encode session
   1407  *
   1408  *  Return:
   1409  *       OMX_ERRORTYPE
   1410  *
   1411  *  Description:
   1412  *       Start the encoding
   1413  *
   1414  **/
   1415 static OMX_ERRORTYPE mm_jpeg_session_encode(mm_jpeg_job_session_t *p_session)
   1416 {
   1417   OMX_ERRORTYPE ret = OMX_ErrorNone;
   1418   mm_jpeg_encode_params_t *p_params = &p_session->params;
   1419   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
   1420   int dest_idx = 0;
   1421   mm_jpeg_obj *my_obj = (mm_jpeg_obj *)p_session->jpeg_obj;
   1422 
   1423   pthread_mutex_lock(&p_session->lock);
   1424   p_session->abort_flag = OMX_FALSE;
   1425   p_session->encoding = OMX_FALSE;
   1426   pthread_mutex_unlock(&p_session->lock);
   1427 
   1428   if (OMX_FALSE == p_session->config) {
   1429     ret = mm_jpeg_session_configure(p_session);
   1430     if (ret) {
   1431       CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
   1432       goto error;
   1433     }
   1434     p_session->config = OMX_TRUE;
   1435   }
   1436 
   1437   ret = mm_jpeg_configure_job_params(p_session);
   1438   if (ret) {
   1439       CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
   1440       goto error;
   1441   }
   1442   pthread_mutex_lock(&p_session->lock);
   1443   p_session->encoding = OMX_TRUE;
   1444   pthread_mutex_unlock(&p_session->lock);
   1445 
   1446   MM_JPEG_CHK_ABORT(p_session, ret, error);
   1447 
   1448 #ifdef MM_JPEG_DUMP_INPUT
   1449   DUMP_TO_FILE("/data/mm_jpeg_int.yuv",
   1450     p_session->p_in_omx_buf[p_jobparams->src_index]->pBuffer,
   1451     (int)p_session->p_in_omx_buf[p_jobparams->src_index]->nAllocLen);
   1452 #endif
   1453 
   1454   ret = OMX_EmptyThisBuffer(p_session->omx_handle,
   1455     p_session->p_in_omx_buf[p_jobparams->src_index]);
   1456   if (ret) {
   1457     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
   1458     goto error;
   1459   }
   1460 
   1461   if (p_session->params.encode_thumbnail) {
   1462     ret = OMX_EmptyThisBuffer(p_session->omx_handle,
   1463         p_session->p_in_omx_thumb_buf[p_jobparams->thumb_index]);
   1464     if (ret) {
   1465       CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
   1466       goto error;
   1467     }
   1468   }
   1469 
   1470   ret = OMX_FillThisBuffer(p_session->omx_handle,
   1471     p_session->p_out_omx_buf[p_jobparams->dst_index]);
   1472   if (ret) {
   1473     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
   1474     goto error;
   1475   }
   1476 
   1477   MM_JPEG_CHK_ABORT(p_session, ret, error);
   1478 
   1479 error:
   1480 
   1481   CDBG("%s:%d] X ", __func__, __LINE__);
   1482   return ret;
   1483 }
   1484 
   1485 /** mm_jpeg_process_encoding_job:
   1486  *
   1487  *  Arguments:
   1488  *    @my_obj: jpeg client
   1489  *    @job_node: job node
   1490  *
   1491  *  Return:
   1492  *       0 for success -1 otherwise
   1493  *
   1494  *  Description:
   1495  *       Start the encoding job
   1496  *
   1497  **/
   1498 int32_t mm_jpeg_process_encoding_job(mm_jpeg_obj *my_obj, mm_jpeg_job_q_node_t* job_node)
   1499 {
   1500   int32_t rc = 0;
   1501   OMX_ERRORTYPE ret = OMX_ErrorNone;
   1502   mm_jpeg_job_session_t *p_session = NULL;
   1503   mm_jpeg_job_q_node_t *node = NULL;
   1504 
   1505   /* check if valid session */
   1506   p_session = mm_jpeg_get_session(my_obj, job_node->enc_info.job_id);
   1507   if (NULL == p_session) {
   1508     CDBG_ERROR("%s:%d] invalid job id %x", __func__, __LINE__,
   1509       job_node->enc_info.job_id);
   1510     return -1;
   1511   }
   1512 
   1513   /* sent encode cmd to OMX, queue job into ongoing queue */
   1514   rc = mm_jpeg_queue_enq(&my_obj->ongoing_job_q, job_node);
   1515   if (rc) {
   1516     CDBG_ERROR("%s:%d] jpeg enqueue failed %d",
   1517       __func__, __LINE__, ret);
   1518     goto error;
   1519   }
   1520 
   1521   p_session->encode_job = job_node->enc_info.encode_job;
   1522   p_session->jobId = job_node->enc_info.job_id;
   1523   ret = mm_jpeg_session_encode(p_session);
   1524   if (ret) {
   1525     CDBG_ERROR("%s:%d] encode session failed", __func__, __LINE__);
   1526     goto error;
   1527   }
   1528 
   1529   CDBG("%s:%d] Success X ", __func__, __LINE__);
   1530   return rc;
   1531 
   1532 error:
   1533 
   1534   if ((OMX_ErrorNone != ret) &&
   1535     (NULL != p_session->params.jpeg_cb)) {
   1536     p_session->job_status = JPEG_JOB_STATUS_ERROR;
   1537     CDBG("%s:%d] send jpeg error callback %d", __func__, __LINE__,
   1538       p_session->job_status);
   1539     p_session->params.jpeg_cb(p_session->job_status,
   1540       p_session->client_hdl,
   1541       p_session->jobId,
   1542       NULL,
   1543       p_session->params.userdata);
   1544   }
   1545 
   1546   /*remove the job*/
   1547   mm_jpeg_job_done(p_session);
   1548   CDBG("%s:%d] Error X ", __func__, __LINE__);
   1549 
   1550   return rc;
   1551 }
   1552 
   1553 /** mm_jpeg_jobmgr_thread:
   1554  *
   1555  *  Arguments:
   1556  *    @my_obj: jpeg object
   1557  *
   1558  *  Return:
   1559  *       0 for success else failure
   1560  *
   1561  *  Description:
   1562  *       job manager thread main function
   1563  *
   1564  **/
   1565 static void *mm_jpeg_jobmgr_thread(void *data)
   1566 {
   1567   int rc = 0;
   1568   int running = 1;
   1569   uint32_t num_ongoing_jobs = 0;
   1570   mm_jpeg_obj *my_obj = (mm_jpeg_obj*)data;
   1571   mm_jpeg_job_cmd_thread_t *cmd_thread = &my_obj->job_mgr;
   1572   mm_jpeg_job_q_node_t* node = NULL;
   1573   prctl(PR_SET_NAME, (unsigned long)"mm_jpeg_thread", 0, 0, 0);
   1574 
   1575   do {
   1576     do {
   1577       rc = cam_sem_wait(&cmd_thread->job_sem);
   1578       if (rc != 0 && errno != EINVAL) {
   1579         CDBG_ERROR("%s: cam_sem_wait error (%s)",
   1580           __func__, strerror(errno));
   1581         return NULL;
   1582       }
   1583     } while (rc != 0);
   1584 
   1585     /* check ongoing q size */
   1586     num_ongoing_jobs = mm_jpeg_queue_get_size(&my_obj->ongoing_job_q);
   1587     if (num_ongoing_jobs >= NUM_MAX_JPEG_CNCURRENT_JOBS) {
   1588       CDBG("%s:%d] ongoing job already reach max %d", __func__,
   1589         __LINE__, num_ongoing_jobs);
   1590       continue;
   1591     }
   1592 
   1593     pthread_mutex_lock(&my_obj->job_lock);
   1594     /* can go ahead with new work */
   1595     node = (mm_jpeg_job_q_node_t*)mm_jpeg_queue_deq(&cmd_thread->job_queue);
   1596     if (node != NULL) {
   1597       switch (node->type) {
   1598       case MM_JPEG_CMD_TYPE_JOB:
   1599         rc = mm_jpeg_process_encoding_job(my_obj, node);
   1600         break;
   1601       case MM_JPEG_CMD_TYPE_EXIT:
   1602       default:
   1603         /* free node */
   1604         free(node);
   1605         /* set running flag to false */
   1606         running = 0;
   1607         break;
   1608       }
   1609     }
   1610     pthread_mutex_unlock(&my_obj->job_lock);
   1611 
   1612   } while (running);
   1613   return NULL;
   1614 }
   1615 
   1616 /** mm_jpeg_jobmgr_thread_launch:
   1617  *
   1618  *  Arguments:
   1619  *    @my_obj: jpeg object
   1620  *
   1621  *  Return:
   1622  *       0 for success else failure
   1623  *
   1624  *  Description:
   1625  *       launches the job manager thread
   1626  *
   1627  **/
   1628 int32_t mm_jpeg_jobmgr_thread_launch(mm_jpeg_obj *my_obj)
   1629 {
   1630   int32_t rc = 0;
   1631   mm_jpeg_job_cmd_thread_t *job_mgr = &my_obj->job_mgr;
   1632 
   1633   cam_sem_init(&job_mgr->job_sem, 0);
   1634   mm_jpeg_queue_init(&job_mgr->job_queue);
   1635 
   1636   /* launch the thread */
   1637   pthread_create(&job_mgr->pid,
   1638     NULL,
   1639     mm_jpeg_jobmgr_thread,
   1640     (void *)my_obj);
   1641   return rc;
   1642 }
   1643 
   1644 /** mm_jpeg_jobmgr_thread_release:
   1645  *
   1646  *  Arguments:
   1647  *    @my_obj: jpeg object
   1648  *
   1649  *  Return:
   1650  *       0 for success else failure
   1651  *
   1652  *  Description:
   1653  *       Releases the job manager thread
   1654  *
   1655  **/
   1656 int32_t mm_jpeg_jobmgr_thread_release(mm_jpeg_obj * my_obj)
   1657 {
   1658   int32_t rc = 0;
   1659   mm_jpeg_job_cmd_thread_t * cmd_thread = &my_obj->job_mgr;
   1660   mm_jpeg_job_q_node_t* node =
   1661     (mm_jpeg_job_q_node_t *)malloc(sizeof(mm_jpeg_job_q_node_t));
   1662   if (NULL == node) {
   1663     CDBG_ERROR("%s: No memory for mm_jpeg_job_q_node_t", __func__);
   1664     return -1;
   1665   }
   1666 
   1667   memset(node, 0, sizeof(mm_jpeg_job_q_node_t));
   1668   node->type = MM_JPEG_CMD_TYPE_EXIT;
   1669 
   1670   mm_jpeg_queue_enq(&cmd_thread->job_queue, node);
   1671   cam_sem_post(&cmd_thread->job_sem);
   1672 
   1673   /* wait until cmd thread exits */
   1674   if (pthread_join(cmd_thread->pid, NULL) != 0) {
   1675     CDBG("%s: pthread dead already", __func__);
   1676   }
   1677   mm_jpeg_queue_deinit(&cmd_thread->job_queue);
   1678 
   1679   cam_sem_destroy(&cmd_thread->job_sem);
   1680   memset(cmd_thread, 0, sizeof(mm_jpeg_job_cmd_thread_t));
   1681   return rc;
   1682 }
   1683 
   1684 /** mm_jpeg_init:
   1685  *
   1686  *  Arguments:
   1687  *    @my_obj: jpeg object
   1688  *
   1689  *  Return:
   1690  *       0 for success else failure
   1691  *
   1692  *  Description:
   1693  *       Initializes the jpeg client
   1694  *
   1695  **/
   1696 int32_t mm_jpeg_init(mm_jpeg_obj *my_obj)
   1697 {
   1698   int32_t rc = 0;
   1699 
   1700   /* init locks */
   1701   pthread_mutex_init(&my_obj->job_lock, NULL);
   1702 
   1703   /* init ongoing job queue */
   1704   rc = mm_jpeg_queue_init(&my_obj->ongoing_job_q);
   1705   if (0 != rc) {
   1706     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
   1707     return -1;
   1708   }
   1709 
   1710   /* init job semaphore and launch jobmgr thread */
   1711   CDBG("%s:%d] Launch jobmgr thread rc %d", __func__, __LINE__, rc);
   1712   rc = mm_jpeg_jobmgr_thread_launch(my_obj);
   1713   if (0 != rc) {
   1714     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
   1715     return -1;
   1716   }
   1717 
   1718   /* load OMX */
   1719   if (OMX_ErrorNone != OMX_Init()) {
   1720     /* roll back in error case */
   1721     CDBG_ERROR("%s:%d] OMX_Init failed (%d)", __func__, __LINE__, rc);
   1722     mm_jpeg_jobmgr_thread_release(my_obj);
   1723     mm_jpeg_queue_deinit(&my_obj->ongoing_job_q);
   1724     pthread_mutex_destroy(&my_obj->job_lock);
   1725   }
   1726 
   1727   return rc;
   1728 }
   1729 
   1730 /** mm_jpeg_deinit:
   1731  *
   1732  *  Arguments:
   1733  *    @my_obj: jpeg object
   1734  *
   1735  *  Return:
   1736  *       0 for success else failure
   1737  *
   1738  *  Description:
   1739  *       Deinits the jpeg client
   1740  *
   1741  **/
   1742 int32_t mm_jpeg_deinit(mm_jpeg_obj *my_obj)
   1743 {
   1744   int32_t rc = 0;
   1745 
   1746   /* release jobmgr thread */
   1747   rc = mm_jpeg_jobmgr_thread_release(my_obj);
   1748   if (0 != rc) {
   1749     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
   1750   }
   1751 
   1752   /* unload OMX engine */
   1753   OMX_Deinit();
   1754 
   1755   /* deinit ongoing job and cb queue */
   1756   rc = mm_jpeg_queue_deinit(&my_obj->ongoing_job_q);
   1757   if (0 != rc) {
   1758     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
   1759   }
   1760 
   1761   /* destroy locks */
   1762   pthread_mutex_destroy(&my_obj->job_lock);
   1763 
   1764   return rc;
   1765 }
   1766 
   1767 /** mm_jpeg_new_client:
   1768  *
   1769  *  Arguments:
   1770  *    @my_obj: jpeg object
   1771  *
   1772  *  Return:
   1773  *       0 for success else failure
   1774  *
   1775  *  Description:
   1776  *       Create new jpeg client
   1777  *
   1778  **/
   1779 uint32_t mm_jpeg_new_client(mm_jpeg_obj *my_obj)
   1780 {
   1781   uint32_t client_hdl = 0;
   1782   uint8_t idx;
   1783   int i = 0;
   1784 
   1785   if (my_obj->num_clients >= MAX_JPEG_CLIENT_NUM) {
   1786     CDBG_ERROR("%s: num of clients reached limit", __func__);
   1787     return client_hdl;
   1788   }
   1789 
   1790   for (idx = 0; idx < MAX_JPEG_CLIENT_NUM; idx++) {
   1791     if (0 == my_obj->clnt_mgr[idx].is_used) {
   1792       break;
   1793     }
   1794   }
   1795 
   1796   if (idx < MAX_JPEG_CLIENT_NUM) {
   1797     /* client session avail */
   1798     /* generate client handler by index */
   1799     client_hdl = mm_jpeg_util_generate_handler(idx);
   1800 
   1801     /* update client session */
   1802     my_obj->clnt_mgr[idx].is_used = 1;
   1803     my_obj->clnt_mgr[idx].client_handle = client_hdl;
   1804 
   1805     pthread_mutex_init(&my_obj->clnt_mgr[idx].lock, NULL);
   1806     for (i = 0; i < MM_JPEG_MAX_SESSION; i++) {
   1807       memset(&my_obj->clnt_mgr[idx].session[i], 0x0, sizeof(mm_jpeg_job_session_t));
   1808     }
   1809 
   1810     /* increse client count */
   1811     my_obj->num_clients++;
   1812   }
   1813 
   1814   return client_hdl;
   1815 }
   1816 
   1817 /** mm_jpeg_start_job:
   1818  *
   1819  *  Arguments:
   1820  *    @my_obj: jpeg object
   1821  *    @client_hdl: client handle
   1822  *    @job: pointer to encode job
   1823  *    @jobId: job id
   1824  *
   1825  *  Return:
   1826  *       0 for success else failure
   1827  *
   1828  *  Description:
   1829  *       Start the encoding job
   1830  *
   1831  **/
   1832 int32_t mm_jpeg_start_job(mm_jpeg_obj *my_obj,
   1833   mm_jpeg_job_t *job,
   1834   uint32_t *job_id)
   1835 {
   1836   int32_t rc = -1;
   1837   uint8_t session_idx = 0;
   1838   uint8_t client_idx = 0;
   1839   mm_jpeg_job_q_node_t* node = NULL;
   1840   mm_jpeg_job_session_t *p_session = NULL;
   1841   mm_jpeg_encode_job_t *p_jobparams  = &job->encode_job;
   1842 
   1843   *job_id = 0;
   1844 
   1845   /* check if valid session */
   1846   session_idx = GET_SESSION_IDX(p_jobparams->session_id);
   1847   client_idx = GET_CLIENT_IDX(p_jobparams->session_id);
   1848   CDBG("%s:%d] session_idx %d client idx %d", __func__, __LINE__,
   1849     session_idx, client_idx);
   1850 
   1851   if ((session_idx >= MM_JPEG_MAX_SESSION) ||
   1852     (client_idx >= MAX_JPEG_CLIENT_NUM)) {
   1853     CDBG_ERROR("%s:%d] invalid session id %x", __func__, __LINE__,
   1854       job->encode_job.session_id);
   1855     return rc;
   1856   }
   1857 
   1858   p_session = &my_obj->clnt_mgr[client_idx].session[session_idx];
   1859   if (OMX_FALSE == p_session->active) {
   1860     CDBG_ERROR("%s:%d] session not active %x", __func__, __LINE__,
   1861       job->encode_job.session_id);
   1862     return rc;
   1863   }
   1864 
   1865   if ((p_jobparams->src_index >= p_session->params.num_src_bufs) ||
   1866     (p_jobparams->dst_index >= p_session->params.num_dst_bufs)) {
   1867     CDBG_ERROR("%s:%d] invalid buffer indices", __func__, __LINE__);
   1868     return rc;
   1869   }
   1870 
   1871   /* enqueue new job into todo job queue */
   1872   node = (mm_jpeg_job_q_node_t *)malloc(sizeof(mm_jpeg_job_q_node_t));
   1873   if (NULL == node) {
   1874     CDBG_ERROR("%s: No memory for mm_jpeg_job_q_node_t", __func__);
   1875     return -1;
   1876   }
   1877 
   1878   *job_id = job->encode_job.session_id |
   1879     ((p_session->job_hist++ % JOB_HIST_MAX) << 16);
   1880 
   1881   memset(node, 0, sizeof(mm_jpeg_job_q_node_t));
   1882   node->enc_info.encode_job = job->encode_job;
   1883   node->enc_info.job_id = *job_id;
   1884   node->enc_info.client_handle = p_session->client_hdl;
   1885   node->type = MM_JPEG_CMD_TYPE_JOB;
   1886 
   1887   rc = mm_jpeg_queue_enq(&my_obj->job_mgr.job_queue, node);
   1888   if (0 == rc) {
   1889     cam_sem_post(&my_obj->job_mgr.job_sem);
   1890   }
   1891 
   1892   return rc;
   1893 }
   1894 
   1895 /** mm_jpeg_abort_job:
   1896  *
   1897  *  Arguments:
   1898  *    @my_obj: jpeg object
   1899  *    @client_hdl: client handle
   1900  *    @jobId: job id
   1901  *
   1902  *  Return:
   1903  *       0 for success else failure
   1904  *
   1905  *  Description:
   1906  *       Abort the encoding session
   1907  *
   1908  **/
   1909 int32_t mm_jpeg_abort_job(mm_jpeg_obj *my_obj,
   1910   uint32_t jobId)
   1911 {
   1912   int32_t rc = -1;
   1913   uint8_t clnt_idx = 0;
   1914   mm_jpeg_job_q_node_t *node = NULL;
   1915   OMX_BOOL ret = OMX_FALSE;
   1916   mm_jpeg_job_session_t *p_session = NULL;
   1917 
   1918   CDBG("%s:%d] ", __func__, __LINE__);
   1919   pthread_mutex_lock(&my_obj->job_lock);
   1920 
   1921   /* abort job if in todo queue */
   1922   node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->job_mgr.job_queue, jobId);
   1923   if (NULL != node) {
   1924     free(node);
   1925     goto abort_done;
   1926   }
   1927 
   1928   /* abort job if in ongoing queue */
   1929   node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->ongoing_job_q, jobId);
   1930   if (NULL != node) {
   1931     /* find job that is OMX ongoing, ask OMX to abort the job */
   1932     p_session = mm_jpeg_get_session(my_obj, node->enc_info.job_id);
   1933     if (p_session) {
   1934       mm_jpeg_session_abort(p_session);
   1935     } else {
   1936       CDBG_ERROR("%s:%d] Invalid job id 0x%x", __func__, __LINE__,
   1937         node->enc_info.job_id);
   1938     }
   1939     free(node);
   1940     goto abort_done;
   1941   }
   1942 
   1943 abort_done:
   1944   pthread_mutex_unlock(&my_obj->job_lock);
   1945 
   1946   return rc;
   1947 }
   1948 
   1949 /** mm_jpeg_create_session:
   1950  *
   1951  *  Arguments:
   1952  *    @my_obj: jpeg object
   1953  *    @client_hdl: client handle
   1954  *    @p_params: pointer to encode params
   1955  *    @p_session_id: session id
   1956  *
   1957  *  Return:
   1958  *       0 for success else failure
   1959  *
   1960  *  Description:
   1961  *       Start the encoding session
   1962  *
   1963  **/
   1964 int32_t mm_jpeg_create_session(mm_jpeg_obj *my_obj,
   1965   uint32_t client_hdl,
   1966   mm_jpeg_encode_params_t *p_params,
   1967   uint32_t* p_session_id)
   1968 {
   1969   int32_t rc = 0;
   1970   OMX_ERRORTYPE ret = OMX_ErrorNone;
   1971   uint8_t clnt_idx = 0;
   1972   int session_idx = -1;
   1973   mm_jpeg_job_session_t *p_session = NULL;
   1974   *p_session_id = 0;
   1975 
   1976   /* validate the parameters */
   1977   if ((p_params->num_src_bufs > MM_JPEG_MAX_BUF)
   1978     || (p_params->num_dst_bufs > MM_JPEG_MAX_BUF)) {
   1979     CDBG_ERROR("%s:%d] invalid num buffers", __func__, __LINE__);
   1980     return -1;
   1981   }
   1982 
   1983   /* check if valid client */
   1984   clnt_idx = mm_jpeg_util_get_index_by_handler(client_hdl);
   1985   if (clnt_idx >= MAX_JPEG_CLIENT_NUM) {
   1986     CDBG_ERROR("%s: invalid client with handler (%d)", __func__, client_hdl);
   1987     return -1;
   1988   }
   1989 
   1990   session_idx = mm_jpeg_get_new_session_idx(my_obj, clnt_idx, &p_session);
   1991   if (session_idx < 0) {
   1992     CDBG_ERROR("%s:%d] invalid session id (%d)", __func__, __LINE__, session_idx);
   1993     return -1;
   1994   }
   1995 
   1996   ret = mm_jpeg_session_create(p_session);
   1997   if (OMX_ErrorNone != ret) {
   1998     p_session->active = OMX_FALSE;
   1999     CDBG_ERROR("%s:%d] jpeg session create failed", __func__, __LINE__);
   2000     return ret;
   2001   }
   2002 
   2003   *p_session_id = (JOB_ID_MAGICVAL << 24) | (session_idx << 8) | clnt_idx;
   2004 
   2005   /*copy the params*/
   2006   p_session->params = *p_params;
   2007   p_session->client_hdl = client_hdl;
   2008   p_session->sessionId = *p_session_id;
   2009   p_session->jpeg_obj = (void*)my_obj; /* save a ptr to jpeg_obj */
   2010   CDBG("%s:%d] session id %x", __func__, __LINE__, *p_session_id);
   2011 
   2012   return ret;
   2013 }
   2014 /** mm_jpeg_destroy_job
   2015  *
   2016  *  Arguments:
   2017  *    @p_session: Session obj
   2018  *
   2019  *  Return:
   2020  *       0 for success else failure
   2021  *
   2022  *  Description:
   2023  *       Destroy the job based paramenters
   2024  *
   2025  **/
   2026 int32_t mm_jpeg_destroy_job(mm_jpeg_job_session_t *p_session)
   2027 {
   2028   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
   2029   int i = 0, rc = 0;
   2030 
   2031   CDBG_HIGH("%s:%d] Exif entry count %d %d", __func__, __LINE__,
   2032     (int)p_jobparams->exif_info.numOfEntries,
   2033     (int)p_session->exif_count_local);
   2034   for (i = 0; i < p_session->exif_count_local; i++) {
   2035     rc = releaseExifEntry(&p_session->exif_info_local[i]);
   2036     if (rc) {
   2037       CDBG_ERROR("%s:%d] Exif release failed (%d)", __func__, __LINE__, rc);
   2038     }
   2039   }
   2040   p_session->exif_count_local = 0;
   2041 
   2042   return rc;
   2043 }
   2044 
   2045 /** mm_jpeg_destroy_session:
   2046  *
   2047  *  Arguments:
   2048  *    @my_obj: jpeg object
   2049  *    @session_id: session index
   2050  *
   2051  *  Return:
   2052  *       0 for success else failure
   2053  *
   2054  *  Description:
   2055  *       Destroy the encoding session
   2056  *
   2057  **/
   2058 int32_t mm_jpeg_destroy_session(mm_jpeg_obj *my_obj,
   2059   mm_jpeg_job_session_t *p_session)
   2060 {
   2061   int32_t rc = 0;
   2062   uint8_t clnt_idx = 0;
   2063   mm_jpeg_job_q_node_t *node = NULL;
   2064   OMX_BOOL ret = OMX_FALSE;
   2065   uint32_t session_id = p_session->sessionId;
   2066 
   2067   if (NULL == p_session) {
   2068     CDBG_ERROR("%s:%d] invalid session", __func__, __LINE__);
   2069     return rc;
   2070   }
   2071 
   2072   pthread_mutex_lock(&my_obj->job_lock);
   2073 
   2074   /* abort job if in todo queue */
   2075   CDBG("%s:%d] abort todo jobs", __func__, __LINE__);
   2076   node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id);
   2077   while (NULL != node) {
   2078     free(node);
   2079     node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id);
   2080   }
   2081 
   2082   /* abort job if in ongoing queue */
   2083   CDBG("%s:%d] abort ongoing jobs", __func__, __LINE__);
   2084   node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id);
   2085   while (NULL != node) {
   2086     free(node);
   2087     node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id);
   2088   }
   2089 
   2090   /* abort the current session */
   2091   mm_jpeg_session_abort(p_session);
   2092   mm_jpeg_session_destroy(p_session);
   2093   mm_jpeg_remove_session_idx(my_obj, session_id);
   2094   pthread_mutex_unlock(&my_obj->job_lock);
   2095 
   2096   /* wake up jobMgr thread to work on new job if there is any */
   2097   cam_sem_post(&my_obj->job_mgr.job_sem);
   2098   CDBG("%s:%d] X", __func__, __LINE__);
   2099 
   2100   return rc;
   2101 }
   2102 
   2103 /** mm_jpeg_destroy_session:
   2104  *
   2105  *  Arguments:
   2106  *    @my_obj: jpeg object
   2107  *    @session_id: session index
   2108  *
   2109  *  Return:
   2110  *       0 for success else failure
   2111  *
   2112  *  Description:
   2113  *       Destroy the encoding session
   2114  *
   2115  **/
   2116 int32_t mm_jpeg_destroy_session_unlocked(mm_jpeg_obj *my_obj,
   2117   mm_jpeg_job_session_t *p_session)
   2118 {
   2119   int32_t rc = -1;
   2120   uint8_t clnt_idx = 0;
   2121   mm_jpeg_job_q_node_t *node = NULL;
   2122   OMX_BOOL ret = OMX_FALSE;
   2123   uint32_t session_id = p_session->sessionId;
   2124 
   2125   if (NULL == p_session) {
   2126     CDBG_ERROR("%s:%d] invalid session", __func__, __LINE__);
   2127     return rc;
   2128   }
   2129 
   2130   /* abort job if in todo queue */
   2131   CDBG("%s:%d] abort todo jobs", __func__, __LINE__);
   2132   node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id);
   2133   while (NULL != node) {
   2134     free(node);
   2135     node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id);
   2136   }
   2137 
   2138   /* abort job if in ongoing queue */
   2139   CDBG("%s:%d] abort ongoing jobs", __func__, __LINE__);
   2140   node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id);
   2141   while (NULL != node) {
   2142     free(node);
   2143     node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id);
   2144   }
   2145 
   2146   /* abort the current session */
   2147   mm_jpeg_session_abort(p_session);
   2148   mm_jpeg_remove_session_idx(my_obj, session_id);
   2149 
   2150   return rc;
   2151 }
   2152 
   2153 /** mm_jpeg_destroy_session:
   2154  *
   2155  *  Arguments:
   2156  *    @my_obj: jpeg object
   2157  *    @session_id: session index
   2158  *
   2159  *  Return:
   2160  *       0 for success else failure
   2161  *
   2162  *  Description:
   2163  *       Destroy the encoding session
   2164  *
   2165  **/
   2166 int32_t mm_jpeg_destroy_session_by_id(mm_jpeg_obj *my_obj, uint32_t session_id)
   2167 {
   2168   mm_jpeg_job_session_t *p_session = mm_jpeg_get_session(my_obj, session_id);
   2169 
   2170   return mm_jpeg_destroy_session(my_obj, p_session);
   2171 }
   2172 
   2173 /** mm_jpeg_close:
   2174  *
   2175  *  Arguments:
   2176  *    @my_obj: jpeg object
   2177  *    @client_hdl: client handle
   2178  *
   2179  *  Return:
   2180  *       0 for success else failure
   2181  *
   2182  *  Description:
   2183  *       Close the jpeg client
   2184  *
   2185  **/
   2186 int32_t mm_jpeg_close(mm_jpeg_obj *my_obj, uint32_t client_hdl)
   2187 {
   2188   int32_t rc = -1;
   2189   uint8_t clnt_idx = 0;
   2190   mm_jpeg_job_q_node_t *node = NULL;
   2191   OMX_BOOL ret = OMX_FALSE;
   2192   int i = 0;
   2193 
   2194   /* check if valid client */
   2195   clnt_idx = mm_jpeg_util_get_index_by_handler(client_hdl);
   2196   if (clnt_idx >= MAX_JPEG_CLIENT_NUM) {
   2197     CDBG_ERROR("%s: invalid client with handler (%d)", __func__, client_hdl);
   2198     return rc;
   2199   }
   2200 
   2201   CDBG("%s:%d] E", __func__, __LINE__);
   2202 
   2203   /* abort all jobs from the client */
   2204   pthread_mutex_lock(&my_obj->job_lock);
   2205 
   2206   CDBG("%s:%d] ", __func__, __LINE__);
   2207 
   2208   for (i = 0; i < MM_JPEG_MAX_SESSION; i++) {
   2209     if (OMX_TRUE == my_obj->clnt_mgr[clnt_idx].session[i].active)
   2210       mm_jpeg_destroy_session_unlocked(my_obj,
   2211         &my_obj->clnt_mgr[clnt_idx].session[i]);
   2212   }
   2213 
   2214   CDBG("%s:%d] ", __func__, __LINE__);
   2215 
   2216   pthread_mutex_unlock(&my_obj->job_lock);
   2217   CDBG("%s:%d] ", __func__, __LINE__);
   2218 
   2219   /* invalidate client session */
   2220   pthread_mutex_destroy(&my_obj->clnt_mgr[clnt_idx].lock);
   2221   memset(&my_obj->clnt_mgr[clnt_idx], 0, sizeof(mm_jpeg_client_t));
   2222 
   2223   rc = 0;
   2224   CDBG("%s:%d] X", __func__, __LINE__);
   2225   return rc;
   2226 }
   2227 
   2228 OMX_ERRORTYPE mm_jpeg_ebd(OMX_HANDLETYPE hComponent,
   2229   OMX_PTR pAppData,
   2230   OMX_BUFFERHEADERTYPE *pBuffer)
   2231 {
   2232   OMX_ERRORTYPE ret = OMX_ErrorNone;
   2233   mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData;
   2234 
   2235   CDBG("%s:%d] count %d ", __func__, __LINE__, p_session->ebd_count);
   2236   pthread_mutex_lock(&p_session->lock);
   2237   p_session->ebd_count++;
   2238   pthread_mutex_unlock(&p_session->lock);
   2239   return 0;
   2240 }
   2241 
   2242 OMX_ERRORTYPE mm_jpeg_fbd(OMX_HANDLETYPE hComponent,
   2243   OMX_PTR pAppData,
   2244   OMX_BUFFERHEADERTYPE *pBuffer)
   2245 {
   2246   OMX_ERRORTYPE ret = OMX_ErrorNone;
   2247   mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData;
   2248   uint32_t i = 0;
   2249   int rc = 0;
   2250   mm_jpeg_output_t output_buf;
   2251 
   2252   CDBG("%s:%d] count %d ", __func__, __LINE__, p_session->fbd_count);
   2253 
   2254   if (OMX_TRUE == p_session->abort_flag) {
   2255     pthread_cond_signal(&p_session->cond);
   2256     return ret;
   2257   }
   2258 
   2259   pthread_mutex_lock(&p_session->lock);
   2260   p_session->fbd_count++;
   2261   if (NULL != p_session->params.jpeg_cb) {
   2262     p_session->job_status = JPEG_JOB_STATUS_DONE;
   2263     output_buf.buf_filled_len = (uint32_t)pBuffer->nFilledLen;
   2264     output_buf.buf_vaddr = pBuffer->pBuffer;
   2265     output_buf.fd = 0;
   2266     CDBG("%s:%d] send jpeg callback %d", __func__, __LINE__,
   2267       p_session->job_status);
   2268     p_session->params.jpeg_cb(p_session->job_status,
   2269       p_session->client_hdl,
   2270       p_session->jobId,
   2271       &output_buf,
   2272       p_session->params.userdata);
   2273 
   2274     /* remove from ready queue */
   2275     mm_jpeg_job_done(p_session);
   2276   }
   2277   pthread_mutex_unlock(&p_session->lock);
   2278   CDBG("%s:%d] ", __func__, __LINE__);
   2279 
   2280   return ret;
   2281 }
   2282 
   2283 OMX_ERRORTYPE mm_jpeg_event_handler(OMX_HANDLETYPE hComponent,
   2284   OMX_PTR pAppData,
   2285   OMX_EVENTTYPE eEvent,
   2286   OMX_U32 nData1,
   2287   OMX_U32 nData2,
   2288   OMX_PTR pEventData)
   2289 {
   2290   mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData;
   2291 
   2292   CDBG("%s:%d] %d %d %d", __func__, __LINE__, eEvent, (int)nData1,
   2293     (int)nData2);
   2294 
   2295   pthread_mutex_lock(&p_session->lock);
   2296 
   2297   if (OMX_TRUE == p_session->abort_flag) {
   2298     pthread_cond_signal(&p_session->cond);
   2299     pthread_mutex_unlock(&p_session->lock);
   2300     return OMX_ErrorNone;
   2301   }
   2302 
   2303   if (eEvent == OMX_EventError) {
   2304     p_session->error_flag = OMX_ErrorHardware;
   2305     if (p_session->encoding == OMX_TRUE) {
   2306       CDBG("%s:%d] Error during encoding", __func__, __LINE__);
   2307 
   2308       /* send jpeg callback */
   2309       if (NULL != p_session->params.jpeg_cb) {
   2310         p_session->job_status = JPEG_JOB_STATUS_ERROR;
   2311         CDBG("%s:%d] send jpeg error callback %d", __func__, __LINE__,
   2312           p_session->job_status);
   2313         p_session->params.jpeg_cb(p_session->job_status,
   2314           p_session->client_hdl,
   2315           p_session->jobId,
   2316           NULL,
   2317           p_session->params.userdata);
   2318       }
   2319 
   2320       /* remove from ready queue */
   2321       mm_jpeg_job_done(p_session);
   2322     }
   2323     pthread_cond_signal(&p_session->cond);
   2324   } else if (eEvent == OMX_EventCmdComplete) {
   2325     if (p_session->state_change_pending == OMX_TRUE) {
   2326       p_session->state_change_pending = OMX_FALSE;
   2327       pthread_cond_signal(&p_session->cond);
   2328     }
   2329   }
   2330 
   2331   pthread_mutex_unlock(&p_session->lock);
   2332   CDBG("%s:%d]", __func__, __LINE__);
   2333   return OMX_ErrorNone;
   2334 }
   2335 
   2336 /* remove the first job from the queue with matching client handle */
   2337 mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_client_id(
   2338   mm_jpeg_queue_t* queue, uint32_t client_hdl)
   2339 {
   2340   mm_jpeg_q_node_t* node = NULL;
   2341   mm_jpeg_job_q_node_t* data = NULL;
   2342   mm_jpeg_job_q_node_t* job_node = NULL;
   2343   struct cam_list *head = NULL;
   2344   struct cam_list *pos = NULL;
   2345 
   2346   pthread_mutex_lock(&queue->lock);
   2347   head = &queue->head.list;
   2348   pos = head->next;
   2349   while(pos != head) {
   2350     node = member_of(pos, mm_jpeg_q_node_t, list);
   2351     data = (mm_jpeg_job_q_node_t *)node->data;
   2352 
   2353     if (data && (data->enc_info.client_handle == client_hdl)) {
   2354       CDBG_HIGH("%s:%d] found matching client handle", __func__, __LINE__);
   2355       job_node = data;
   2356       cam_list_del_node(&node->list);
   2357       queue->size--;
   2358       free(node);
   2359       CDBG_HIGH("%s: queue size = %d", __func__, queue->size);
   2360       break;
   2361     }
   2362     pos = pos->next;
   2363   }
   2364 
   2365   pthread_mutex_unlock(&queue->lock);
   2366 
   2367   return job_node;
   2368 }
   2369 
   2370 /* remove the first job from the queue with matching session id */
   2371 mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_session_id(
   2372   mm_jpeg_queue_t* queue, uint32_t session_id)
   2373 {
   2374   mm_jpeg_q_node_t* node = NULL;
   2375   mm_jpeg_job_q_node_t* data = NULL;
   2376   mm_jpeg_job_q_node_t* job_node = NULL;
   2377   struct cam_list *head = NULL;
   2378   struct cam_list *pos = NULL;
   2379 
   2380   pthread_mutex_lock(&queue->lock);
   2381   head = &queue->head.list;
   2382   pos = head->next;
   2383   while(pos != head) {
   2384     node = member_of(pos, mm_jpeg_q_node_t, list);
   2385     data = (mm_jpeg_job_q_node_t *)node->data;
   2386 
   2387     if (data && (data->enc_info.encode_job.session_id == session_id)) {
   2388       CDBG_HIGH("%s:%d] found matching session id", __func__, __LINE__);
   2389       job_node = data;
   2390       cam_list_del_node(&node->list);
   2391       queue->size--;
   2392       free(node);
   2393       CDBG_HIGH("%s: queue size = %d", __func__, queue->size);
   2394       break;
   2395     }
   2396     pos = pos->next;
   2397   }
   2398 
   2399   pthread_mutex_unlock(&queue->lock);
   2400 
   2401   return job_node;
   2402 }
   2403 
   2404 /* remove job from the queue with matching job id */
   2405 mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_job_id(
   2406   mm_jpeg_queue_t* queue, uint32_t job_id)
   2407 {
   2408   mm_jpeg_q_node_t* node = NULL;
   2409   mm_jpeg_job_q_node_t* data = NULL;
   2410   mm_jpeg_job_q_node_t* job_node = NULL;
   2411   struct cam_list *head = NULL;
   2412   struct cam_list *pos = NULL;
   2413 
   2414   pthread_mutex_lock(&queue->lock);
   2415   head = &queue->head.list;
   2416   pos = head->next;
   2417   while(pos != head) {
   2418     node = member_of(pos, mm_jpeg_q_node_t, list);
   2419     data = (mm_jpeg_job_q_node_t *)node->data;
   2420 
   2421     if (data && (data->enc_info.job_id == job_id)) {
   2422       CDBG_HIGH("%s:%d] found matching job id", __func__, __LINE__);
   2423       job_node = data;
   2424       cam_list_del_node(&node->list);
   2425       queue->size--;
   2426       free(node);
   2427       break;
   2428     }
   2429     pos = pos->next;
   2430   }
   2431 
   2432   pthread_mutex_unlock(&queue->lock);
   2433 
   2434   return job_node;
   2435 }
   2436 
   2437 /* remove job from the queue with matching job id */
   2438 mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_unlk(
   2439   mm_jpeg_queue_t* queue, uint32_t job_id)
   2440 {
   2441   mm_jpeg_q_node_t* node = NULL;
   2442   mm_jpeg_job_q_node_t* data = NULL;
   2443   mm_jpeg_job_q_node_t* job_node = NULL;
   2444   struct cam_list *head = NULL;
   2445   struct cam_list *pos = NULL;
   2446 
   2447   head = &queue->head.list;
   2448   pos = head->next;
   2449   while(pos != head) {
   2450     node = member_of(pos, mm_jpeg_q_node_t, list);
   2451     data = (mm_jpeg_job_q_node_t *)node->data;
   2452 
   2453     if (data && (data->enc_info.job_id == job_id)) {
   2454       job_node = data;
   2455       cam_list_del_node(&node->list);
   2456       queue->size--;
   2457       free(node);
   2458       break;
   2459     }
   2460     pos = pos->next;
   2461   }
   2462 
   2463   return job_node;
   2464 }
   2465