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