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