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