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