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