Home | History | Annotate | Download | only in HAL3
      1 /* Copyright (c) 2012-2015, The Linux Foundataion. 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 #define ATRACE_TAG ATRACE_TAG_CAMERA
     30 
     31 #define LOG_TAG "QCamera3PostProc"
     32 //#define LOG_NDEBUG 0
     33 
     34 #include <stdlib.h>
     35 #include <utils/Errors.h>
     36 #include <utils/Trace.h>
     37 
     38 #include "QCamera3PostProc.h"
     39 #include "QCamera3HWI.h"
     40 #include "QCamera3Channel.h"
     41 #include "QCamera3Stream.h"
     42 
     43 namespace qcamera {
     44 
     45 /*===========================================================================
     46  * FUNCTION   : QCamera3PostProcessor
     47  *
     48  * DESCRIPTION: constructor of QCamera3PostProcessor.
     49  *
     50  * PARAMETERS :
     51  *   @cam_ctrl : ptr to HWI object
     52  *
     53  * RETURN     : None
     54  *==========================================================================*/
     55 QCamera3PostProcessor::QCamera3PostProcessor(QCamera3PicChannel* ch_ctrl)
     56     : m_parent(ch_ctrl),
     57       mJpegCB(NULL),
     58       mJpegUserData(NULL),
     59       mJpegClientHandle(0),
     60       mJpegSessionId(0),
     61       m_bThumbnailNeeded(TRUE),
     62       m_pReprocChannel(NULL),
     63       m_inputPPQ(releasePPInputData, this),
     64       m_inputFWKPPQ(NULL, this),
     65       m_ongoingPPQ(releaseOngoingPPData, this),
     66       m_inputJpegQ(releaseJpegData, this),
     67       m_ongoingJpegQ(releaseJpegData, this),
     68       m_inputRawQ(releasePPInputData, this),
     69       m_inputMetaQ(releaseMetadata, this),
     70       m_jpegSettingsQ(NULL, this)
     71 {
     72     memset(&mJpegHandle, 0, sizeof(mJpegHandle));
     73     pthread_mutex_init(&mReprocJobLock, NULL);
     74 }
     75 
     76 /*===========================================================================
     77  * FUNCTION   : ~QCamera3PostProcessor
     78  *
     79  * DESCRIPTION: deconstructor of QCamera3PostProcessor.
     80  *
     81  * PARAMETERS : None
     82  *
     83  * RETURN     : None
     84  *==========================================================================*/
     85 QCamera3PostProcessor::~QCamera3PostProcessor()
     86 {
     87     pthread_mutex_destroy(&mReprocJobLock);
     88 }
     89 
     90 /*===========================================================================
     91  * FUNCTION   : init
     92  *
     93  * DESCRIPTION: initialization of postprocessor
     94  *
     95  * PARAMETERS :
     96  *   @jpeg_cb      : callback to handle jpeg event from mm-camera-interface
     97  *   @user_data    : user data ptr for jpeg callback
     98  *
     99  * RETURN     : int32_t type of status
    100  *              NO_ERROR  -- success
    101  *              none-zero failure code
    102  *==========================================================================*/
    103 int32_t QCamera3PostProcessor::init(QCamera3Memory* mMemory,
    104                                     jpeg_encode_callback_t jpeg_cb,
    105                                     uint32_t postprocess_mask,
    106                                     void *user_data)
    107 {
    108     ATRACE_CALL();
    109     mJpegCB = jpeg_cb;
    110     mJpegUserData = user_data;
    111     mm_dimension max_size;
    112 
    113     //set max pic size
    114     memset(&max_size, 0, sizeof(mm_dimension));
    115     max_size.w =  m_parent->m_max_pic_dim.width;
    116     max_size.h =  m_parent->m_max_pic_dim.height;
    117 
    118     mJpegClientHandle = jpeg_open(&mJpegHandle,max_size);
    119     mJpegMem = mMemory;
    120     if(!mJpegClientHandle) {
    121         ALOGE("%s : jpeg_open did not work", __func__);
    122         return UNKNOWN_ERROR;
    123     }
    124     mPostProcMask = postprocess_mask;
    125     m_dataProcTh.launch(dataProcessRoutine, this);
    126 
    127     return NO_ERROR;
    128 }
    129 
    130 /*===========================================================================
    131  * FUNCTION   : deinit
    132  *
    133  * DESCRIPTION: de-initialization of postprocessor
    134  *
    135  * PARAMETERS : None
    136  *
    137  * RETURN     : int32_t type of status
    138  *              NO_ERROR  -- success
    139  *              none-zero failure code
    140  *==========================================================================*/
    141 int32_t QCamera3PostProcessor::deinit()
    142 {
    143     m_dataProcTh.exit();
    144 
    145     if (m_pReprocChannel != NULL) {
    146         m_pReprocChannel->stop();
    147         delete m_pReprocChannel;
    148         m_pReprocChannel = NULL;
    149     }
    150 
    151     if(mJpegClientHandle > 0) {
    152         int rc = mJpegHandle.close(mJpegClientHandle);
    153         CDBG_HIGH("%s: Jpeg closed, rc = %d, mJpegClientHandle = %x",
    154               __func__, rc, mJpegClientHandle);
    155         mJpegClientHandle = 0;
    156         memset(&mJpegHandle, 0, sizeof(mJpegHandle));
    157     }
    158 
    159     mJpegMem = NULL;
    160 
    161     return NO_ERROR;
    162 }
    163 
    164 /*===========================================================================
    165  * FUNCTION   : start
    166  *
    167  * DESCRIPTION: start postprocessor. Data process thread and data notify thread
    168  *              will be launched.
    169  *
    170  * PARAMETERS :
    171  *   @pMemory       : memory object representing buffers to store JPEG.
    172  *   @config        : reprocess configuration
    173  *   @metadata      : metadata for the reprocessing
    174  *
    175  * RETURN     : int32_t type of status
    176  *              NO_ERROR  -- success
    177  *              none-zero failure code
    178  *
    179  * NOTE       : if any reprocess is needed, a reprocess channel/stream
    180  *              will be started.
    181  *==========================================================================*/
    182 int32_t QCamera3PostProcessor::start(const reprocess_config_t &config,
    183         metadata_buffer_t *metadata)
    184 {
    185     int32_t rc = NO_ERROR;
    186     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
    187 
    188     if (hal_obj->needReprocess(mPostProcMask) || config.src_channel != m_parent) {
    189         if (m_pReprocChannel != NULL) {
    190             m_pReprocChannel->stop();
    191             delete m_pReprocChannel;
    192             m_pReprocChannel = NULL;
    193         }
    194 
    195         // if reprocess is needed, start reprocess channel
    196         QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
    197         CDBG("%s: Setting input channel as pInputChannel", __func__);
    198         m_pReprocChannel = hal_obj->addOfflineReprocChannel(config, m_parent, metadata);
    199         if (m_pReprocChannel == NULL) {
    200             ALOGE("%s: cannot add reprocess channel", __func__);
    201             return UNKNOWN_ERROR;
    202         }
    203 
    204         rc = m_pReprocChannel->start();
    205         if (rc != 0) {
    206             ALOGE("%s: cannot start reprocess channel", __func__);
    207             delete m_pReprocChannel;
    208             m_pReprocChannel = NULL;
    209             return rc;
    210         }
    211     }
    212     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_START_DATA_PROC, TRUE, FALSE);
    213 
    214     return rc;
    215 }
    216 
    217 /*===========================================================================
    218  * FUNCTION   : stop
    219  *
    220  * DESCRIPTION: stop postprocessor. Data process and notify thread will be stopped.
    221  *
    222  * PARAMETERS : None
    223  *
    224  * RETURN     : int32_t type of status
    225  *              NO_ERROR  -- success
    226  *              none-zero failure code
    227  *
    228  * NOTE       : reprocess channel will be stopped and deleted if there is any
    229  *==========================================================================*/
    230 int32_t QCamera3PostProcessor::stop()
    231 {
    232     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC, TRUE, TRUE);
    233 
    234     if (m_pReprocChannel != NULL) {
    235         m_pReprocChannel->stop();
    236         delete m_pReprocChannel;
    237         m_pReprocChannel = NULL;
    238     }
    239 
    240     return NO_ERROR;
    241 }
    242 
    243 /*===========================================================================
    244  * FUNCTION   : getFWKJpegEncodeConfig
    245  *
    246  * DESCRIPTION: function to prepare encoding job information
    247  *
    248  * PARAMETERS :
    249  *   @encode_parm   : param to be filled with encoding configuration
    250  *   @frame         : framework input buffer
    251  *   @jpeg_settings : jpeg settings to be applied for encoding
    252  *
    253  * RETURN     : int32_t type of status
    254  *              NO_ERROR  -- success
    255  *              none-zero failure code
    256  *==========================================================================*/
    257 int32_t QCamera3PostProcessor::getFWKJpegEncodeConfig(
    258         mm_jpeg_encode_params_t& encode_parm,
    259         qcamera_fwk_input_pp_data_t *frame,
    260         jpeg_settings_t *jpeg_settings)
    261 {
    262     CDBG("%s : E", __func__);
    263 
    264     if ((NULL == frame) || (NULL == jpeg_settings)) {
    265         return BAD_VALUE;
    266     }
    267 
    268     encode_parm.jpeg_cb = mJpegCB;
    269     encode_parm.userdata = mJpegUserData;
    270 
    271     if (jpeg_settings->thumbnail_size.width > 0 &&
    272             jpeg_settings->thumbnail_size.height > 0)
    273         m_bThumbnailNeeded = TRUE;
    274     else
    275         m_bThumbnailNeeded = FALSE;
    276     encode_parm.encode_thumbnail = m_bThumbnailNeeded;
    277 
    278     // get color format
    279     cam_format_t img_fmt = frame->reproc_config.stream_format;
    280     encode_parm.color_format = getColorfmtFromImgFmt(img_fmt);
    281 
    282     // get jpeg quality
    283     encode_parm.quality = jpeg_settings->jpeg_quality;
    284     if (encode_parm.quality <= 0) {
    285         encode_parm.quality = 85;
    286     }
    287 
    288     // get jpeg thumbnail quality
    289     encode_parm.thumb_quality = jpeg_settings->jpeg_thumb_quality;
    290 
    291     cam_frame_len_offset_t main_offset =
    292             frame->reproc_config.input_stream_plane_info.plane_info;
    293 
    294     encode_parm.num_src_bufs = 1;
    295     encode_parm.src_main_buf[0].index = 0;
    296     encode_parm.src_main_buf[0].buf_size = frame->input_buffer.frame_len;
    297     encode_parm.src_main_buf[0].buf_vaddr = (uint8_t *) frame->input_buffer.buffer;
    298     encode_parm.src_main_buf[0].fd = frame->input_buffer.fd;
    299     encode_parm.src_main_buf[0].format = MM_JPEG_FMT_YUV;
    300     encode_parm.src_main_buf[0].offset = main_offset;
    301 
    302     //Pass input thumbnail buffer info to encoder.
    303     //Note: Use main buffer to encode thumbnail
    304     if (m_bThumbnailNeeded == TRUE) {
    305         encode_parm.num_tmb_bufs = 1;
    306         encode_parm.src_thumb_buf[0] = encode_parm.src_main_buf[0];
    307     }
    308 
    309     //Pass output jpeg buffer info to encoder.
    310     //mJpegMem is allocated by framework.
    311     encode_parm.num_dst_bufs = 1;
    312     encode_parm.dest_buf[0].index = 0;
    313     encode_parm.dest_buf[0].buf_size = mJpegMem->getSize(
    314             jpeg_settings->out_buf_index);
    315     encode_parm.dest_buf[0].buf_vaddr = (uint8_t *)mJpegMem->getPtr(
    316             jpeg_settings->out_buf_index);
    317     encode_parm.dest_buf[0].fd = mJpegMem->getFd(
    318             jpeg_settings->out_buf_index);
    319     encode_parm.dest_buf[0].format = MM_JPEG_FMT_YUV;
    320     encode_parm.dest_buf[0].offset = main_offset;
    321 
    322     CDBG("%s : X", __func__);
    323     return NO_ERROR;
    324 }
    325 
    326 /*===========================================================================
    327  * FUNCTION   : getJpegEncodeConfig
    328  *
    329  * DESCRIPTION: function to prepare encoding job information
    330  *
    331  * PARAMETERS :
    332  *   @encode_parm   : param to be filled with encoding configuration
    333  *   #main_stream   : stream object where the input buffer comes from
    334  *   @jpeg_settings : jpeg settings to be applied for encoding
    335  *
    336  * RETURN     : int32_t type of status
    337  *              NO_ERROR  -- success
    338  *              none-zero failure code
    339  *==========================================================================*/
    340 int32_t QCamera3PostProcessor::getJpegEncodeConfig(
    341                 mm_jpeg_encode_params_t& encode_parm,
    342                 QCamera3Stream *main_stream,
    343                 jpeg_settings_t *jpeg_settings)
    344 {
    345     CDBG("%s : E", __func__);
    346     int32_t ret = NO_ERROR;
    347 
    348     encode_parm.jpeg_cb = mJpegCB;
    349     encode_parm.userdata = mJpegUserData;
    350 
    351     if (jpeg_settings->thumbnail_size.width > 0 &&
    352             jpeg_settings->thumbnail_size.height > 0)
    353         m_bThumbnailNeeded = TRUE;
    354     else
    355         m_bThumbnailNeeded = FALSE;
    356     encode_parm.encode_thumbnail = m_bThumbnailNeeded;
    357 
    358     // get color format
    359     cam_format_t img_fmt = CAM_FORMAT_YUV_420_NV12;  //default value
    360     main_stream->getFormat(img_fmt);
    361     encode_parm.color_format = getColorfmtFromImgFmt(img_fmt);
    362 
    363     //get rotation
    364     encode_parm.jpeg_orientation = jpeg_settings->jpeg_orientation;
    365 
    366     // get jpeg quality
    367     encode_parm.quality = jpeg_settings->jpeg_quality;
    368     if (encode_parm.quality <= 0) {
    369         encode_parm.quality = 85;
    370     }
    371 
    372     // get jpeg thumbnail quality
    373     encode_parm.thumb_quality = jpeg_settings->jpeg_thumb_quality;
    374 
    375     cam_frame_len_offset_t main_offset;
    376     memset(&main_offset, 0, sizeof(cam_frame_len_offset_t));
    377     main_stream->getFrameOffset(main_offset);
    378 
    379     // src buf config
    380     //Pass input main image buffer info to encoder.
    381     QCamera3Memory *pStreamMem = main_stream->getStreamBufs();
    382     if (pStreamMem == NULL) {
    383         ALOGE("%s: cannot get stream bufs from main stream", __func__);
    384         ret = BAD_VALUE;
    385         goto on_error;
    386     }
    387     encode_parm.num_src_bufs = MIN(pStreamMem->getCnt(), MM_JPEG_MAX_BUF);
    388     for (uint32_t i = 0; i < encode_parm.num_src_bufs; i++) {
    389         if (pStreamMem != NULL) {
    390             encode_parm.src_main_buf[i].index = i;
    391             encode_parm.src_main_buf[i].buf_size = pStreamMem->getSize(i);
    392             encode_parm.src_main_buf[i].buf_vaddr = (uint8_t *)pStreamMem->getPtr(i);
    393             encode_parm.src_main_buf[i].fd = pStreamMem->getFd(i);
    394             encode_parm.src_main_buf[i].format = MM_JPEG_FMT_YUV;
    395             encode_parm.src_main_buf[i].offset = main_offset;
    396         }
    397     }
    398 
    399     //Pass input thumbnail buffer info to encoder.
    400     //Note: Use main buffer to encode thumbnail
    401     if (m_bThumbnailNeeded == TRUE) {
    402         pStreamMem = main_stream->getStreamBufs();
    403         if (pStreamMem == NULL) {
    404             ALOGE("%s: cannot get stream bufs from thumb stream", __func__);
    405             ret = BAD_VALUE;
    406             goto on_error;
    407         }
    408         cam_frame_len_offset_t thumb_offset;
    409         memset(&thumb_offset, 0, sizeof(cam_frame_len_offset_t));
    410         main_stream->getFrameOffset(thumb_offset);
    411         encode_parm.num_tmb_bufs = MIN(pStreamMem->getCnt(), MM_JPEG_MAX_BUF);
    412         for (size_t i = 0; i < encode_parm.num_tmb_bufs; i++) {
    413             if (pStreamMem != NULL) {
    414                 encode_parm.src_thumb_buf[i].index = i;
    415                 encode_parm.src_thumb_buf[i].buf_size = pStreamMem->getSize(i);
    416                 encode_parm.src_thumb_buf[i].buf_vaddr = (uint8_t *)pStreamMem->getPtr(i);
    417                 encode_parm.src_thumb_buf[i].fd = pStreamMem->getFd(i);
    418                 encode_parm.src_thumb_buf[i].format = MM_JPEG_FMT_YUV;
    419                 encode_parm.src_thumb_buf[i].offset = thumb_offset;
    420             }
    421         }
    422     }
    423 
    424     //Pass output jpeg buffer info to encoder.
    425     //mJpegMem is allocated by framework.
    426     encode_parm.num_dst_bufs = 1;
    427     encode_parm.dest_buf[0].index = 0;
    428     encode_parm.dest_buf[0].buf_size = mJpegMem->getSize(
    429             jpeg_settings->out_buf_index);
    430     encode_parm.dest_buf[0].buf_vaddr = (uint8_t *)mJpegMem->getPtr(
    431             jpeg_settings->out_buf_index);
    432     encode_parm.dest_buf[0].fd = mJpegMem->getFd(
    433             jpeg_settings->out_buf_index);
    434     encode_parm.dest_buf[0].format = MM_JPEG_FMT_YUV;
    435     encode_parm.dest_buf[0].offset = main_offset;
    436 
    437     CDBG("%s : X", __func__);
    438     return NO_ERROR;
    439 
    440 on_error:
    441     CDBG("%s : X with error %d", __func__, ret);
    442     return ret;
    443 }
    444 
    445 /*===========================================================================
    446  * FUNCTION   : processData
    447  *
    448  * DESCRIPTION: enqueue data into dataProc thread
    449  *
    450  * PARAMETERS :
    451  *   @frame   : process frame
    452  *
    453  * RETURN     : int32_t type of status
    454  *              NO_ERROR  -- success
    455  *              none-zero failure code
    456  *
    457  * NOTE       : depends on if offline reprocess is needed, received frame will
    458  *              be sent to either input queue of postprocess or jpeg encoding
    459  *==========================================================================*/
    460 int32_t QCamera3PostProcessor::processData(mm_camera_super_buf_t *frame)
    461 {
    462     pthread_mutex_lock(&mReprocJobLock);
    463     // enqueue to post proc input queue
    464     m_inputPPQ.enqueue((void *)frame);
    465     if (!(m_inputMetaQ.isEmpty())) {
    466        CDBG("%s: meta queue is not empty, do next job", __func__);
    467        m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
    468     }
    469     pthread_mutex_unlock(&mReprocJobLock);
    470 
    471     return NO_ERROR;
    472 }
    473 
    474 /*===========================================================================
    475  * FUNCTION   : processData
    476  *
    477  * DESCRIPTION: enqueue data into dataProc thread
    478  *
    479  * PARAMETERS :
    480  *   @frame   : process frame
    481  *
    482  * RETURN     : int32_t type of status
    483  *              NO_ERROR  -- success
    484  *              none-zero failure code
    485  *
    486  * NOTE       : depends on if offline reprocess is needed, received frame will
    487  *              be sent to either input queue of postprocess or jpeg encoding
    488  *==========================================================================*/
    489 int32_t QCamera3PostProcessor::processData(qcamera_fwk_input_pp_data_t *frame)
    490 {
    491     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
    492     if (hal_obj->needReprocess(mPostProcMask) ||
    493             frame->reproc_config.src_channel != m_parent) {
    494         pthread_mutex_lock(&mReprocJobLock);
    495         // enqueu to post proc input queue
    496         m_inputFWKPPQ.enqueue((void *)frame);
    497         m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
    498         pthread_mutex_unlock(&mReprocJobLock);
    499     } else {
    500         jpeg_settings_t *jpeg_settings = (jpeg_settings_t *)m_jpegSettingsQ.dequeue();
    501 
    502         if (jpeg_settings == NULL) {
    503             ALOGE("%s: Cannot find jpeg settings", __func__);
    504             return BAD_VALUE;
    505         }
    506 
    507         CDBG_HIGH("%s: no need offline reprocess, sending to jpeg encoding", __func__);
    508         qcamera_hal3_jpeg_data_t *jpeg_job =
    509             (qcamera_hal3_jpeg_data_t *)malloc(sizeof(qcamera_hal3_jpeg_data_t));
    510         if (jpeg_job == NULL) {
    511             ALOGE("%s: No memory for jpeg job", __func__);
    512             return NO_MEMORY;
    513         }
    514 
    515         memset(jpeg_job, 0, sizeof(qcamera_hal3_jpeg_data_t));
    516         jpeg_job->fwk_frame = frame;
    517         jpeg_job->jpeg_settings = jpeg_settings;
    518         jpeg_job->metadata =
    519                 (metadata_buffer_t *) frame->metadata_buffer.buffer;
    520 
    521         // enqueu to jpeg input queue
    522         m_inputJpegQ.enqueue((void *)jpeg_job);
    523         m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
    524     }
    525 
    526     return NO_ERROR;
    527 }
    528 
    529 /*===========================================================================
    530  * FUNCTION   : processPPMetadata
    531  *
    532  * DESCRIPTION: enqueue data into dataProc thread
    533  *
    534  * PARAMETERS :
    535  *   @frame   : process metadata frame received from pic channel
    536  *
    537  * RETURN     : int32_t type of status
    538  *              NO_ERROR  -- success
    539  *              none-zero failure code
    540  *
    541  *==========================================================================*/
    542 int32_t QCamera3PostProcessor::processPPMetadata(mm_camera_super_buf_t *reproc_meta)
    543 {
    544    pthread_mutex_lock(&mReprocJobLock);
    545     // enqueue to metadata input queue
    546     m_inputMetaQ.enqueue((void *)reproc_meta);
    547     if (!(m_inputPPQ.isEmpty())) {
    548        CDBG("%s: pp queue is not empty, do next job", __func__);
    549        m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
    550     } else {
    551        CDBG("%s: pp queue is empty, not calling do next job", __func__);
    552     }
    553     pthread_mutex_unlock(&mReprocJobLock);
    554     return NO_ERROR;
    555 }
    556 
    557 /*===========================================================================
    558  * FUNCTION   : processJpegSettingData
    559  *
    560  * DESCRIPTION: enqueue jpegSetting into dataProc thread
    561  *
    562  * PARAMETERS :
    563  *   @jpeg_settings : jpeg settings data received from pic channel
    564  *
    565  * RETURN     : int32_t type of status
    566  *              NO_ERROR  -- success
    567  *              none-zero failure code
    568  *
    569  *==========================================================================*/
    570 int32_t QCamera3PostProcessor::processJpegSettingData(
    571         jpeg_settings_t *jpeg_settings)
    572 {
    573     if (!jpeg_settings) {
    574         ALOGE("%s: invalid jpeg settings pointer", __func__);
    575         return -EINVAL;
    576     }
    577     return m_jpegSettingsQ.enqueue((void *)jpeg_settings);
    578 }
    579 
    580 /*===========================================================================
    581  * FUNCTION   : processRawData
    582  *
    583  * DESCRIPTION: enqueue raw data into dataProc thread
    584  *
    585  * PARAMETERS :
    586  *   @frame   : process frame received from mm-camera-interface
    587  *
    588  * RETURN     : int32_t type of status
    589  *              NO_ERROR  -- success
    590  *              none-zero failure code
    591  *==========================================================================*/
    592 int32_t QCamera3PostProcessor::processRawData(mm_camera_super_buf_t *frame)
    593 {
    594     // enqueu to raw input queue
    595     m_inputRawQ.enqueue((void *)frame);
    596     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
    597     return NO_ERROR;
    598 }
    599 
    600 /*===========================================================================
    601  * FUNCTION   : processPPData
    602  *
    603  * DESCRIPTION: process received frame after reprocess.
    604  *
    605  * PARAMETERS :
    606  *   @frame   : received frame from reprocess channel.
    607  *
    608  * RETURN     : int32_t type of status
    609  *              NO_ERROR  -- success
    610  *              none-zero failure code
    611  *
    612  * NOTE       : The frame after reprocess need to send to jpeg encoding.
    613  *==========================================================================*/
    614 int32_t QCamera3PostProcessor::processPPData(mm_camera_super_buf_t *frame)
    615 {
    616     qcamera_hal3_pp_data_t *job = (qcamera_hal3_pp_data_t *)m_ongoingPPQ.dequeue();
    617 
    618     if (job == NULL || ((NULL == job->src_frame) && (NULL == job->fwk_src_frame))) {
    619         ALOGE("%s: Cannot find reprocess job", __func__);
    620         return BAD_VALUE;
    621     }
    622     if (job->jpeg_settings == NULL) {
    623         ALOGE("%s: Cannot find jpeg settings", __func__);
    624         return BAD_VALUE;
    625     }
    626 
    627     qcamera_hal3_jpeg_data_t *jpeg_job =
    628         (qcamera_hal3_jpeg_data_t *)malloc(sizeof(qcamera_hal3_jpeg_data_t));
    629     if (jpeg_job == NULL) {
    630         ALOGE("%s: No memory for jpeg job", __func__);
    631         return NO_MEMORY;
    632     }
    633 
    634     memset(jpeg_job, 0, sizeof(qcamera_hal3_jpeg_data_t));
    635     jpeg_job->src_frame = frame;
    636     if(frame != job->src_frame)
    637         jpeg_job->src_reproc_frame = job->src_frame;
    638     if (NULL == job->fwk_src_frame) {
    639         jpeg_job->metadata = job->metadata;
    640     } else {
    641         jpeg_job->metadata =
    642                 (metadata_buffer_t *) job->fwk_src_frame->metadata_buffer.buffer;
    643         jpeg_job->fwk_src_buffer = job->fwk_src_frame;
    644     }
    645     jpeg_job->src_metadata = job->src_metadata;
    646     jpeg_job->jpeg_settings = job->jpeg_settings;
    647 
    648     // free pp job buf
    649     free(job);
    650 
    651     // enqueu reprocessed frame to jpeg input queue
    652     m_inputJpegQ.enqueue((void *)jpeg_job);
    653 
    654     // wait up data proc thread
    655     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
    656 
    657     return NO_ERROR;
    658 }
    659 
    660 /*===========================================================================
    661  * FUNCTION   : findJpegJobByJobId
    662  *
    663  * DESCRIPTION: find a jpeg job from ongoing Jpeg queue by its job ID
    664  *
    665  * PARAMETERS :
    666  *   @jobId   : job Id of the job
    667  *
    668  * RETURN     : ptr to a jpeg job struct. NULL if not found.
    669  *
    670  * NOTE       : Currently only one job is sending to mm-jpeg-interface for jpeg
    671  *              encoding. Therefore simply dequeue from the ongoing Jpeg Queue
    672  *              will serve the purpose to find the jpeg job.
    673  *==========================================================================*/
    674 qcamera_hal3_jpeg_data_t *QCamera3PostProcessor::findJpegJobByJobId(uint32_t jobId)
    675 {
    676     qcamera_hal3_jpeg_data_t * job = NULL;
    677     if (jobId == 0) {
    678         ALOGE("%s: not a valid jpeg jobId", __func__);
    679         return NULL;
    680     }
    681 
    682     // currely only one jpeg job ongoing, so simply dequeue the head
    683     job = (qcamera_hal3_jpeg_data_t *)m_ongoingJpegQ.dequeue();
    684     return job;
    685 }
    686 
    687 /*===========================================================================
    688  * FUNCTION   : releasePPInputData
    689  *
    690  * DESCRIPTION: callback function to release post process input data node
    691  *
    692  * PARAMETERS :
    693  *   @data      : ptr to post process input data
    694  *   @user_data : user data ptr (QCamera3Reprocessor)
    695  *
    696  * RETURN     : None
    697  *==========================================================================*/
    698 void QCamera3PostProcessor::releasePPInputData(void *data, void *user_data)
    699 {
    700     QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
    701     if (NULL != pme) {
    702         pme->releaseSuperBuf((mm_camera_super_buf_t *)data);
    703     }
    704 }
    705 
    706 /*===========================================================================
    707  * FUNCTION   : releaseMetaData
    708  *
    709  * DESCRIPTION: callback function to release metadata camera buffer
    710  *
    711  * PARAMETERS :
    712  *   @data      : ptr to post process input data
    713  *   @user_data : user data ptr (QCamera3Reprocessor)
    714  *
    715  * RETURN     : None
    716  *==========================================================================*/
    717 void QCamera3PostProcessor::releaseMetadata(void *data, void *user_data)
    718 {
    719     QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
    720     if (NULL != pme) {
    721         pme->m_parent->metadataBufDone((mm_camera_super_buf_t *)data);
    722     }
    723 }
    724 
    725 /*===========================================================================
    726  * FUNCTION   : releaseJpegData
    727  *
    728  * DESCRIPTION: callback function to release jpeg job node
    729  *
    730  * PARAMETERS :
    731  *   @data      : ptr to ongoing jpeg job data
    732  *   @user_data : user data ptr (QCamera3Reprocessor)
    733  *
    734  * RETURN     : None
    735  *==========================================================================*/
    736 void QCamera3PostProcessor::releaseJpegData(void *data, void *user_data)
    737 {
    738     QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
    739     if (NULL != pme) {
    740         pme->releaseJpegJobData((qcamera_hal3_jpeg_data_t *)data);
    741     }
    742 }
    743 
    744 /*===========================================================================
    745  * FUNCTION   : releaseOngoingPPData
    746  *
    747  * DESCRIPTION: callback function to release ongoing postprocess job node
    748  *
    749  * PARAMETERS :
    750  *   @data      : ptr to onging postprocess job
    751  *   @user_data : user data ptr (QCamera3Reprocessor)
    752  *
    753  * RETURN     : None
    754  *==========================================================================*/
    755 void QCamera3PostProcessor::releaseOngoingPPData(void *data, void *user_data)
    756 {
    757     QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
    758     if (NULL != pme) {
    759         qcamera_hal3_pp_data_t *pp_job = (qcamera_hal3_pp_data_t *)data;
    760         if (NULL != pp_job->src_frame) {
    761             pme->releaseSuperBuf(pp_job->src_frame);
    762             free(pp_job->src_frame);
    763             if (NULL != pp_job->src_metadata) {
    764                 pme->m_parent->metadataBufDone(pp_job->src_metadata);
    765                 free(pp_job->src_metadata);
    766             }
    767             pp_job->src_frame = NULL;
    768             pp_job->metadata = NULL;
    769         }
    770 
    771         if (NULL != pp_job->fwk_src_frame) {
    772             free(pp_job->fwk_src_frame);
    773             pp_job->fwk_src_frame = NULL;
    774         }
    775     }
    776 }
    777 
    778 /*===========================================================================
    779  * FUNCTION   : releaseSuperBuf
    780  *
    781  * DESCRIPTION: function to release a superbuf frame by returning back to kernel
    782  *
    783  * PARAMETERS :
    784  *   @super_buf : ptr to the superbuf frame
    785  *
    786  * RETURN     : None
    787  *==========================================================================*/
    788 void QCamera3PostProcessor::releaseSuperBuf(mm_camera_super_buf_t *super_buf)
    789 {
    790     if (NULL != super_buf) {
    791         if (m_parent != NULL) {
    792             m_parent->bufDone(super_buf);
    793         }
    794     }
    795 }
    796 
    797 /*===========================================================================
    798  * FUNCTION   : releaseOfflineBuffers
    799  *
    800  * DESCRIPTION: function to release/unmap offline buffers if any
    801  *
    802  * PARAMETERS : None
    803  *
    804  * RETURN     : int32_t type of status
    805  *              NO_ERROR  -- success
    806  *              none-zero failure code
    807  *==========================================================================*/
    808 int32_t QCamera3PostProcessor::releaseOfflineBuffers()
    809 {
    810     int32_t rc = NO_ERROR;
    811 
    812     if(NULL != m_pReprocChannel) {
    813         rc = m_pReprocChannel->unmapOfflineBuffers(false);
    814     }
    815 
    816     return rc;
    817 }
    818 
    819 /*===========================================================================
    820  * FUNCTION   : releaseJpegJobData
    821  *
    822  * DESCRIPTION: function to release internal resources in jpeg job struct
    823  *
    824  * PARAMETERS :
    825  *   @job     : ptr to jpeg job struct
    826  *
    827  * RETURN     : None
    828  *
    829  * NOTE       : original source frame need to be queued back to kernel for
    830  *              future use. Output buf of jpeg job need to be released since
    831  *              it's allocated for each job. Exif object need to be deleted.
    832  *==========================================================================*/
    833 void QCamera3PostProcessor::releaseJpegJobData(qcamera_hal3_jpeg_data_t *job)
    834 {
    835     ATRACE_CALL();
    836     int32_t rc = NO_ERROR;
    837     CDBG("%s: E", __func__);
    838     if (NULL != job) {
    839         if (NULL != job->src_reproc_frame) {
    840             free(job->src_reproc_frame);
    841             job->src_reproc_frame = NULL;
    842         }
    843 
    844         if (NULL != job->src_frame) {
    845             if (NULL != m_pReprocChannel) {
    846                 rc = m_pReprocChannel->bufDone(job->src_frame);
    847                 if (NO_ERROR != rc)
    848                     ALOGE("%s: bufDone error: %d", __func__, rc);
    849             }
    850             free(job->src_frame);
    851             job->src_frame = NULL;
    852         }
    853 
    854         if (NULL != job->fwk_src_buffer) {
    855             free(job->fwk_src_buffer);
    856             job->fwk_src_buffer = NULL;
    857         } else if (NULL != job->src_metadata) {
    858             m_parent->metadataBufDone(job->src_metadata);
    859             free(job->src_metadata);
    860             job->src_metadata = NULL;
    861         }
    862 
    863         if (NULL != job->fwk_frame) {
    864             free(job->fwk_frame);
    865             job->fwk_frame = NULL;
    866         }
    867 
    868         if (NULL != job->pJpegExifObj) {
    869             delete job->pJpegExifObj;
    870             job->pJpegExifObj = NULL;
    871         }
    872 
    873         if (NULL != job->jpeg_settings) {
    874             free(job->jpeg_settings);
    875             job->jpeg_settings = NULL;
    876         }
    877     }
    878     /* Additional trigger to process any pending jobs in the input queue */
    879     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
    880     CDBG("%s: X", __func__);
    881 }
    882 
    883 /*===========================================================================
    884  * FUNCTION   : getColorfmtFromImgFmt
    885  *
    886  * DESCRIPTION: function to return jpeg color format based on its image format
    887  *
    888  * PARAMETERS :
    889  *   @img_fmt : image format
    890  *
    891  * RETURN     : jpeg color format that can be understandable by omx lib
    892  *==========================================================================*/
    893 mm_jpeg_color_format QCamera3PostProcessor::getColorfmtFromImgFmt(cam_format_t img_fmt)
    894 {
    895     switch (img_fmt) {
    896     case CAM_FORMAT_YUV_420_NV21:
    897         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
    898     case CAM_FORMAT_YUV_420_NV21_ADRENO:
    899         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
    900     case CAM_FORMAT_YUV_420_NV12:
    901         return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2;
    902     case CAM_FORMAT_YUV_420_YV12:
    903         return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2;
    904     case CAM_FORMAT_YUV_422_NV61:
    905         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V1;
    906     case CAM_FORMAT_YUV_422_NV16:
    907         return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V1;
    908     default:
    909         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
    910     }
    911 }
    912 
    913 /*===========================================================================
    914  * FUNCTION   : getJpegImgTypeFromImgFmt
    915  *
    916  * DESCRIPTION: function to return jpeg encode image type based on its image format
    917  *
    918  * PARAMETERS :
    919  *   @img_fmt : image format
    920  *
    921  * RETURN     : return jpeg source image format (YUV or Bitstream)
    922  *==========================================================================*/
    923 mm_jpeg_format_t QCamera3PostProcessor::getJpegImgTypeFromImgFmt(cam_format_t img_fmt)
    924 {
    925     switch (img_fmt) {
    926     case CAM_FORMAT_YUV_420_NV21:
    927     case CAM_FORMAT_YUV_420_NV21_ADRENO:
    928     case CAM_FORMAT_YUV_420_NV12:
    929     case CAM_FORMAT_YUV_420_YV12:
    930     case CAM_FORMAT_YUV_422_NV61:
    931     case CAM_FORMAT_YUV_422_NV16:
    932         return MM_JPEG_FMT_YUV;
    933     default:
    934         return MM_JPEG_FMT_YUV;
    935     }
    936 }
    937 
    938 /*===========================================================================
    939  * FUNCTION   : encodeFWKData
    940  *
    941  * DESCRIPTION: function to prepare encoding job information and send to
    942  *              mm-jpeg-interface to do the encoding job
    943  *
    944  * PARAMETERS :
    945  *   @jpeg_job_data : ptr to a struct saving job related information
    946  *   @needNewSess   : flag to indicate if a new jpeg encoding session need
    947  *                    to be created. After creation, this flag will be toggled
    948  *
    949  * RETURN     : int32_t type of status
    950  *              NO_ERROR  -- success
    951  *              none-zero failure code
    952  *==========================================================================*/
    953 int32_t QCamera3PostProcessor::encodeFWKData(qcamera_hal3_jpeg_data_t *jpeg_job_data,
    954         uint8_t &needNewSess)
    955 {
    956     CDBG("%s : E", __func__);
    957     int32_t ret = NO_ERROR;
    958     mm_jpeg_job_t jpg_job;
    959     uint32_t jobId = 0;
    960     qcamera_fwk_input_pp_data_t *recvd_frame = NULL;
    961     metadata_buffer_t *metadata = NULL;
    962     jpeg_settings_t *jpeg_settings = NULL;
    963     QCamera3HardwareInterface* hal_obj = NULL;
    964 
    965     if (NULL == jpeg_job_data) {
    966         ALOGE("%s: Invalid jpeg job", __func__);
    967         return BAD_VALUE;
    968     }
    969 
    970     recvd_frame = jpeg_job_data->fwk_frame;
    971     if (NULL == recvd_frame) {
    972         ALOGE("%s: Invalid input buffer", __func__);
    973         return BAD_VALUE;
    974     }
    975 
    976     metadata = jpeg_job_data->metadata;
    977     if (NULL == metadata) {
    978         ALOGE("%s: Invalid metadata buffer", __func__);
    979         return BAD_VALUE;
    980     }
    981 
    982     jpeg_settings = jpeg_job_data->jpeg_settings;
    983     if (NULL == jpeg_settings) {
    984         ALOGE("%s: Invalid jpeg settings buffer", __func__);
    985         return BAD_VALUE;
    986     }
    987 
    988     if ((NULL != jpeg_job_data->src_frame) && (NULL != jpeg_job_data->src_frame)) {
    989         ALOGE("%s: Unsupported case both framework and camera source buffers are invalid!",
    990                 __func__);
    991         return BAD_VALUE;
    992     }
    993 
    994     hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
    995 
    996     if (mJpegClientHandle <= 0) {
    997         ALOGE("%s: Error: bug here, mJpegClientHandle is 0", __func__);
    998         return UNKNOWN_ERROR;
    999     }
   1000 
   1001     cam_dimension_t src_dim;
   1002     memset(&src_dim, 0, sizeof(cam_dimension_t));
   1003     src_dim.width = recvd_frame->reproc_config.input_stream_dim.width;
   1004     src_dim.height = recvd_frame->reproc_config.input_stream_dim.height;
   1005 
   1006     cam_dimension_t dst_dim;
   1007     memset(&dst_dim, 0, sizeof(cam_dimension_t));
   1008     dst_dim.width = recvd_frame->reproc_config.output_stream_dim.width;
   1009     dst_dim.height = recvd_frame->reproc_config.output_stream_dim.height;
   1010 
   1011     CDBG_HIGH("%s: Need new session?:%d",__func__, needNewSess);
   1012     if (needNewSess) {
   1013         //creating a new session, so we must destroy the old one
   1014         if ( 0 < mJpegSessionId ) {
   1015             ret = mJpegHandle.destroy_session(mJpegSessionId);
   1016             if (ret != NO_ERROR) {
   1017                 ALOGE("%s: Error destroying an old jpeg encoding session, id = %d",
   1018                       __func__, mJpegSessionId);
   1019                 return ret;
   1020             }
   1021             mJpegSessionId = 0;
   1022         }
   1023         // create jpeg encoding session
   1024         mm_jpeg_encode_params_t encodeParam;
   1025         memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t));
   1026         encodeParam.main_dim.src_dim = src_dim;
   1027         encodeParam.main_dim.dst_dim = dst_dim;
   1028         encodeParam.thumb_dim.src_dim = src_dim;
   1029         encodeParam.thumb_dim.dst_dim = jpeg_settings->thumbnail_size;
   1030 
   1031         getFWKJpegEncodeConfig(encodeParam, recvd_frame, jpeg_settings);
   1032         CDBG_HIGH("%s: #src bufs:%d # tmb bufs:%d #dst_bufs:%d", __func__,
   1033                      encodeParam.num_src_bufs,encodeParam.num_tmb_bufs,encodeParam.num_dst_bufs);
   1034 
   1035         ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId);
   1036         if (ret != NO_ERROR) {
   1037             ALOGE("%s: Error creating a new jpeg encoding session, ret = %d", __func__, ret);
   1038             return ret;
   1039         }
   1040         needNewSess = FALSE;
   1041     }
   1042 
   1043     // Fill in new job
   1044     memset(&jpg_job, 0, sizeof(mm_jpeg_job_t));
   1045     jpg_job.job_type = JPEG_JOB_TYPE_ENCODE;
   1046     jpg_job.encode_job.session_id = mJpegSessionId;
   1047     jpg_job.encode_job.src_index = 0;
   1048     jpg_job.encode_job.dst_index = 0;
   1049 
   1050     cam_rect_t crop;
   1051     memset(&crop, 0, sizeof(cam_rect_t));
   1052     //TBD_later - Zoom event removed in stream
   1053     //main_stream->getCropInfo(crop);
   1054 
   1055     // main dim
   1056     jpg_job.encode_job.main_dim.src_dim = src_dim;
   1057     jpg_job.encode_job.main_dim.dst_dim = dst_dim;
   1058     jpg_job.encode_job.main_dim.crop = crop;
   1059 
   1060     // get exif data
   1061     QCamera3Exif *pJpegExifObj = m_parent->getExifData(metadata, jpeg_settings);
   1062     jpeg_job_data->pJpegExifObj = pJpegExifObj;
   1063     if (pJpegExifObj != NULL) {
   1064         jpg_job.encode_job.exif_info.exif_data = pJpegExifObj->getEntries();
   1065         jpg_job.encode_job.exif_info.numOfEntries =
   1066             pJpegExifObj->getNumOfEntries();
   1067     }
   1068 
   1069     // thumbnail dim
   1070     CDBG_HIGH("%s: Thumbnail needed:%d",__func__, m_bThumbnailNeeded);
   1071     if (m_bThumbnailNeeded == TRUE) {
   1072         memset(&crop, 0, sizeof(cam_rect_t));
   1073         jpg_job.encode_job.thumb_dim.dst_dim =
   1074                 jpeg_settings->thumbnail_size;
   1075 
   1076         if (!hal_obj->needRotationReprocess()) {
   1077             jpg_job.encode_job.rotation =
   1078                     jpeg_settings->jpeg_orientation;
   1079             CDBG_HIGH("%s: jpeg rotation is set to %d", __func__,
   1080                     jpg_job.encode_job.rotation);
   1081         } else if (jpeg_settings->jpeg_orientation  == 90 ||
   1082                 jpeg_settings->jpeg_orientation == 270) {
   1083             //swap the thumbnail destination width and height if it has
   1084             //already been rotated
   1085             int temp = jpg_job.encode_job.thumb_dim.dst_dim.width;
   1086             jpg_job.encode_job.thumb_dim.dst_dim.width =
   1087                     jpg_job.encode_job.thumb_dim.dst_dim.height;
   1088             jpg_job.encode_job.thumb_dim.dst_dim.height = temp;
   1089         }
   1090         jpg_job.encode_job.thumb_dim.src_dim = src_dim;
   1091         jpg_job.encode_job.thumb_dim.crop = crop;
   1092         jpg_job.encode_job.thumb_index = 0;
   1093     }
   1094 
   1095     if (metadata != NULL) {
   1096        //Fill in the metadata passed as parameter
   1097        jpg_job.encode_job.p_metadata = metadata;
   1098     } else {
   1099        ALOGE("%s: Metadata is null", __func__);
   1100     }
   1101 
   1102     jpg_job.encode_job.hal_version = CAM_HAL_V3;
   1103 
   1104     //Start jpeg encoding
   1105     ret = mJpegHandle.start_job(&jpg_job, &jobId);
   1106     if (ret == NO_ERROR) {
   1107         // remember job info
   1108         jpeg_job_data->jobId = jobId;
   1109     }
   1110 
   1111     CDBG("%s : X", __func__);
   1112     return ret;
   1113 }
   1114 
   1115 /*===========================================================================
   1116  * FUNCTION   : encodeData
   1117  *
   1118  * DESCRIPTION: function to prepare encoding job information and send to
   1119  *              mm-jpeg-interface to do the encoding job
   1120  *
   1121  * PARAMETERS :
   1122  *   @jpeg_job_data : ptr to a struct saving job related information
   1123  *   @needNewSess   : flag to indicate if a new jpeg encoding session need
   1124  *                    to be created. After creation, this flag will be toggled
   1125  *
   1126  * RETURN     : int32_t type of status
   1127  *              NO_ERROR  -- success
   1128  *              none-zero failure code
   1129  *==========================================================================*/
   1130 int32_t QCamera3PostProcessor::encodeData(qcamera_hal3_jpeg_data_t *jpeg_job_data,
   1131                           uint8_t &needNewSess)
   1132 {
   1133     ATRACE_CALL();
   1134     CDBG("%s : E", __func__);
   1135     int32_t ret = NO_ERROR;
   1136     mm_jpeg_job_t jpg_job;
   1137     uint32_t jobId = 0;
   1138     QCamera3Stream *main_stream = NULL;
   1139     mm_camera_buf_def_t *main_frame = NULL;
   1140     QCamera3Channel *srcChannel = NULL;
   1141     mm_camera_super_buf_t *recvd_frame = NULL;
   1142     metadata_buffer_t *metadata = NULL;
   1143     jpeg_settings_t *jpeg_settings = NULL;
   1144     QCamera3HardwareInterface* hal_obj = NULL;
   1145     bool needJpegRotation = false;
   1146 
   1147     hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
   1148     recvd_frame = jpeg_job_data->src_frame;
   1149     metadata = jpeg_job_data->metadata;
   1150     jpeg_settings = jpeg_job_data->jpeg_settings;
   1151 
   1152     CDBG("%s: encoding bufIndex: %u", __func__,
   1153         jpeg_job_data->src_frame->bufs[0]->buf_idx);
   1154 
   1155     QCamera3Channel *pChannel = NULL;
   1156     // first check picture channel
   1157     if (m_parent != NULL &&
   1158         m_parent->getMyHandle() == recvd_frame->ch_id) {
   1159         pChannel = m_parent;
   1160     }
   1161     // check reprocess channel if not found
   1162     if (pChannel == NULL) {
   1163         if (m_pReprocChannel != NULL &&
   1164             m_pReprocChannel->getMyHandle() == recvd_frame->ch_id) {
   1165             pChannel = m_pReprocChannel;
   1166         }
   1167     }
   1168 
   1169     srcChannel = pChannel;
   1170 
   1171     if (srcChannel == NULL) {
   1172         ALOGE("%s: No corresponding channel (ch_id = %d) exist, return here",
   1173               __func__, recvd_frame->ch_id);
   1174         return BAD_VALUE;
   1175     }
   1176 
   1177     // find snapshot frame and thumnail frame
   1178     //Note: In this version we will receive only snapshot frame.
   1179     for (int i = 0; i < recvd_frame->num_bufs; i++) {
   1180         QCamera3Stream *srcStream =
   1181             srcChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id);
   1182         if (srcStream != NULL) {
   1183             switch (srcStream->getMyType()) {
   1184             case CAM_STREAM_TYPE_SNAPSHOT:
   1185             case CAM_STREAM_TYPE_OFFLINE_PROC:
   1186                 main_stream = srcStream;
   1187                 main_frame = recvd_frame->bufs[i];
   1188                 break;
   1189             default:
   1190                 break;
   1191             }
   1192         }
   1193     }
   1194 
   1195     if(NULL == main_frame){
   1196        ALOGE("%s : Main frame is NULL", __func__);
   1197        return BAD_VALUE;
   1198     }
   1199 
   1200     QCamera3Memory *memObj = (QCamera3Memory *)main_frame->mem_info;
   1201     if (NULL == memObj) {
   1202         ALOGE("%s : Memeory Obj of main frame is NULL", __func__);
   1203         return NO_MEMORY;
   1204     }
   1205 
   1206     // clean and invalidate cache ops through mem obj of the frame
   1207     memObj->cleanInvalidateCache(main_frame->buf_idx);
   1208 
   1209     if (mJpegClientHandle <= 0) {
   1210         ALOGE("%s: Error: bug here, mJpegClientHandle is 0", __func__);
   1211         return UNKNOWN_ERROR;
   1212     }
   1213     cam_dimension_t src_dim;
   1214     memset(&src_dim, 0, sizeof(cam_dimension_t));
   1215     main_stream->getFrameDimension(src_dim);
   1216 
   1217     cam_dimension_t dst_dim;
   1218     memset(&dst_dim, 0, sizeof(cam_dimension_t));
   1219     srcChannel->getStreamByIndex(0)->getFrameDimension(dst_dim);
   1220 
   1221     needJpegRotation = hal_obj->needJpegRotation();
   1222     CDBG_HIGH("%s: Need new session?:%d",__func__, needNewSess);
   1223     if (needNewSess) {
   1224         //creating a new session, so we must destroy the old one
   1225         if ( 0 < mJpegSessionId ) {
   1226             ret = mJpegHandle.destroy_session(mJpegSessionId);
   1227             if (ret != NO_ERROR) {
   1228                 ALOGE("%s: Error destroying an old jpeg encoding session, id = %d",
   1229                       __func__, mJpegSessionId);
   1230                 return ret;
   1231             }
   1232             mJpegSessionId = 0;
   1233         }
   1234         // create jpeg encoding session
   1235         mm_jpeg_encode_params_t encodeParam;
   1236         memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t));
   1237         getJpegEncodeConfig(encodeParam, main_stream, jpeg_settings);
   1238         CDBG_HIGH("%s: #src bufs:%d # tmb bufs:%d #dst_bufs:%d", __func__,
   1239                      encodeParam.num_src_bufs,encodeParam.num_tmb_bufs,encodeParam.num_dst_bufs);
   1240         if (!needJpegRotation &&
   1241             (jpeg_settings->jpeg_orientation == 90 ||
   1242             jpeg_settings->jpeg_orientation == 270)) {
   1243            //swap src width and height, stride and scanline due to rotation
   1244            encodeParam.main_dim.src_dim.width = src_dim.height;
   1245            encodeParam.main_dim.src_dim.height = src_dim.width;
   1246            encodeParam.thumb_dim.src_dim.width = src_dim.height;
   1247            encodeParam.thumb_dim.src_dim.height = src_dim.width;
   1248 
   1249            int32_t temp = encodeParam.src_main_buf[0].offset.mp[0].stride;
   1250            encodeParam.src_main_buf[0].offset.mp[0].stride =
   1251               encodeParam.src_main_buf[0].offset.mp[0].scanline;
   1252            encodeParam.src_main_buf[0].offset.mp[0].scanline = temp;
   1253 
   1254            temp = encodeParam.src_thumb_buf[0].offset.mp[0].stride;
   1255            encodeParam.src_thumb_buf[0].offset.mp[0].stride =
   1256               encodeParam.src_thumb_buf[0].offset.mp[0].scanline;
   1257            encodeParam.src_thumb_buf[0].offset.mp[0].scanline = temp;
   1258         } else {
   1259            encodeParam.main_dim.src_dim  = src_dim;
   1260            encodeParam.thumb_dim.src_dim = src_dim;
   1261         }
   1262         encodeParam.main_dim.dst_dim = dst_dim;
   1263         encodeParam.thumb_dim.dst_dim = jpeg_settings->thumbnail_size;
   1264         if (needJpegRotation) {
   1265            encodeParam.rotation = jpeg_settings->jpeg_orientation;
   1266         }
   1267 
   1268 
   1269         ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId);
   1270         if (ret != NO_ERROR) {
   1271             ALOGE("%s: Error creating a new jpeg encoding session, ret = %d", __func__, ret);
   1272             return ret;
   1273         }
   1274         needNewSess = FALSE;
   1275     }
   1276 
   1277     // Fill in new job
   1278     memset(&jpg_job, 0, sizeof(mm_jpeg_job_t));
   1279     jpg_job.job_type = JPEG_JOB_TYPE_ENCODE;
   1280     jpg_job.encode_job.session_id = mJpegSessionId;
   1281     jpg_job.encode_job.src_index = main_frame->buf_idx;
   1282     jpg_job.encode_job.dst_index = 0;
   1283 
   1284     if (needJpegRotation) {
   1285         jpg_job.encode_job.rotation =
   1286                 jpeg_settings->jpeg_orientation;
   1287         CDBG("%s: %d: jpeg rotation is set to %d", __func__, __LINE__,
   1288                 jpg_job.encode_job.rotation);
   1289     }
   1290 
   1291     cam_rect_t crop;
   1292     memset(&crop, 0, sizeof(cam_rect_t));
   1293     //TBD_later - Zoom event removed in stream
   1294     //main_stream->getCropInfo(crop);
   1295 
   1296     // main dim
   1297     jpg_job.encode_job.main_dim.src_dim = src_dim;
   1298     jpg_job.encode_job.main_dim.dst_dim = dst_dim;
   1299     jpg_job.encode_job.main_dim.crop = crop;
   1300 
   1301     // get exif data
   1302     QCamera3Exif *pJpegExifObj = m_parent->getExifData(metadata, jpeg_settings);
   1303     jpeg_job_data->pJpegExifObj = pJpegExifObj;
   1304     if (pJpegExifObj != NULL) {
   1305         jpg_job.encode_job.exif_info.exif_data = pJpegExifObj->getEntries();
   1306         jpg_job.encode_job.exif_info.numOfEntries =
   1307             pJpegExifObj->getNumOfEntries();
   1308     }
   1309 
   1310     // thumbnail dim
   1311     CDBG_HIGH("%s: Thumbnail needed:%d",__func__, m_bThumbnailNeeded);
   1312     if (m_bThumbnailNeeded == TRUE) {
   1313         memset(&crop, 0, sizeof(cam_rect_t));
   1314         jpg_job.encode_job.thumb_dim.dst_dim =
   1315                 jpeg_settings->thumbnail_size;
   1316 
   1317       if (!needJpegRotation &&
   1318           (jpeg_settings->jpeg_orientation  == 90 ||
   1319            jpeg_settings->jpeg_orientation == 270)) {
   1320             //swap the thumbnail destination width and height if it has
   1321             //already been rotated
   1322             int temp = jpg_job.encode_job.thumb_dim.dst_dim.width;
   1323             jpg_job.encode_job.thumb_dim.dst_dim.width =
   1324                     jpg_job.encode_job.thumb_dim.dst_dim.height;
   1325             jpg_job.encode_job.thumb_dim.dst_dim.height = temp;
   1326 
   1327             jpg_job.encode_job.thumb_dim.src_dim.width = src_dim.height;
   1328             jpg_job.encode_job.thumb_dim.src_dim.height = src_dim.width;
   1329         } else {
   1330            jpg_job.encode_job.thumb_dim.src_dim = src_dim;
   1331         }
   1332         jpg_job.encode_job.thumb_dim.crop = crop;
   1333         jpg_job.encode_job.thumb_index = main_frame->buf_idx;
   1334     }
   1335 
   1336     if (metadata != NULL) {
   1337        //Fill in the metadata passed as parameter
   1338        jpg_job.encode_job.p_metadata = metadata;
   1339     } else {
   1340        ALOGE("%s: Metadata is null", __func__);
   1341     }
   1342 
   1343     jpg_job.encode_job.hal_version = CAM_HAL_V3;
   1344 
   1345     //Start jpeg encoding
   1346     ret = mJpegHandle.start_job(&jpg_job, &jobId);
   1347     if (ret == NO_ERROR) {
   1348         // remember job info
   1349         jpeg_job_data->jobId = jobId;
   1350     }
   1351 
   1352     CDBG("%s : X", __func__);
   1353     return ret;
   1354 }
   1355 
   1356 /*===========================================================================
   1357  * FUNCTION   : dataProcessRoutine
   1358  *
   1359  * DESCRIPTION: data process routine that handles input data either from input
   1360  *              Jpeg Queue to do jpeg encoding, or from input PP Queue to do
   1361  *              reprocess.
   1362  *
   1363  * PARAMETERS :
   1364  *   @data    : user data ptr (QCamera3PostProcessor)
   1365  *
   1366  * RETURN     : None
   1367  *==========================================================================*/
   1368 void *QCamera3PostProcessor::dataProcessRoutine(void *data)
   1369 {
   1370     int running = 1;
   1371     int ret;
   1372     uint8_t is_active = FALSE;
   1373     uint8_t needNewSess = TRUE;
   1374     mm_camera_super_buf_t *meta_buffer = NULL;
   1375     CDBG("%s: E", __func__);
   1376     QCamera3PostProcessor *pme = (QCamera3PostProcessor *)data;
   1377     QCameraCmdThread *cmdThread = &pme->m_dataProcTh;
   1378     cmdThread->setName("cam_data_proc");
   1379 
   1380     do {
   1381         do {
   1382             ret = cam_sem_wait(&cmdThread->cmd_sem);
   1383             if (ret != 0 && errno != EINVAL) {
   1384                 ALOGE("%s: cam_sem_wait error (%s)",
   1385                            __func__, strerror(errno));
   1386                 return NULL;
   1387             }
   1388         } while (ret != 0);
   1389 
   1390         // we got notified about new cmd avail in cmd queue
   1391         camera_cmd_type_t cmd = cmdThread->getCmd();
   1392         switch (cmd) {
   1393         case CAMERA_CMD_TYPE_START_DATA_PROC:
   1394             CDBG_HIGH("%s: start data proc", __func__);
   1395             is_active = TRUE;
   1396             needNewSess = TRUE;
   1397 
   1398             pme->m_ongoingPPQ.init();
   1399             pme->m_inputJpegQ.init();
   1400             pme->m_inputPPQ.init();
   1401             pme->m_inputFWKPPQ.init();
   1402             pme->m_inputRawQ.init();
   1403             pme->m_inputMetaQ.init();
   1404             cam_sem_post(&cmdThread->sync_sem);
   1405 
   1406             break;
   1407         case CAMERA_CMD_TYPE_STOP_DATA_PROC:
   1408             {
   1409                 CDBG_HIGH("%s: stop data proc", __func__);
   1410                 is_active = FALSE;
   1411 
   1412                 // cancel all ongoing jpeg jobs
   1413                 qcamera_hal3_jpeg_data_t *jpeg_job =
   1414                     (qcamera_hal3_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
   1415                 while (jpeg_job != NULL) {
   1416                     pme->mJpegHandle.abort_job(jpeg_job->jobId);
   1417 
   1418                     pme->releaseJpegJobData(jpeg_job);
   1419                     free(jpeg_job);
   1420 
   1421                     jpeg_job = (qcamera_hal3_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
   1422                 }
   1423 
   1424                 // destroy jpeg encoding session
   1425                 if ( 0 < pme->mJpegSessionId ) {
   1426                     pme->mJpegHandle.destroy_session(pme->mJpegSessionId);
   1427                     pme->mJpegSessionId = 0;
   1428                 }
   1429 
   1430                 needNewSess = TRUE;
   1431 
   1432                 // flush ongoing postproc Queue
   1433                 pme->m_ongoingPPQ.flush();
   1434 
   1435                 // flush input jpeg Queue
   1436                 pme->m_inputJpegQ.flush();
   1437 
   1438                 // flush input Postproc Queue
   1439                 pme->m_inputPPQ.flush();
   1440 
   1441                 // flush framework input Postproc Queue
   1442                 pme->m_inputFWKPPQ.flush();
   1443 
   1444                 // flush input raw Queue
   1445                 pme->m_inputRawQ.flush();
   1446 
   1447                 pme->m_inputMetaQ.flush();
   1448 
   1449                 // signal cmd is completed
   1450                 cam_sem_post(&cmdThread->sync_sem);
   1451             }
   1452             break;
   1453         case CAMERA_CMD_TYPE_DO_NEXT_JOB:
   1454             {
   1455                 CDBG_HIGH("%s: Do next job, active is %d", __func__, is_active);
   1456                 /* needNewSess is set to TRUE as postproc is not re-STARTed
   1457                  * anymore for every captureRequest */
   1458                 needNewSess = TRUE;
   1459                 if (is_active == TRUE) {
   1460                     // check if there is any ongoing jpeg jobs
   1461                     if (pme->m_ongoingJpegQ.isEmpty()) {
   1462                        CDBG("%s: ongoing jpeg queue is empty so doing the jpeg job", __func__);
   1463                         // no ongoing jpeg job, we are fine to send jpeg encoding job
   1464                         qcamera_hal3_jpeg_data_t *jpeg_job =
   1465                             (qcamera_hal3_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
   1466 
   1467                         if (NULL != jpeg_job) {
   1468                             // add into ongoing jpeg job Q
   1469                             pme->m_ongoingJpegQ.enqueue((void *)jpeg_job);
   1470 
   1471                             if (jpeg_job->fwk_frame) {
   1472                                 ret = pme->encodeFWKData(jpeg_job, needNewSess);
   1473                             } else {
   1474                                 ret = pme->encodeData(jpeg_job, needNewSess);
   1475                             }
   1476                             if (NO_ERROR != ret) {
   1477                                 // dequeue the last one
   1478                                 pme->m_ongoingJpegQ.dequeue(false);
   1479 
   1480                                 pme->releaseJpegJobData(jpeg_job);
   1481                                 free(jpeg_job);
   1482                             }
   1483                         }
   1484                     }
   1485 
   1486                     // check if there are any framework pp jobs
   1487                     if (!pme->m_inputFWKPPQ.isEmpty()) {
   1488                         qcamera_fwk_input_pp_data_t *fwk_frame =
   1489                                 (qcamera_fwk_input_pp_data_t *) pme->m_inputFWKPPQ.dequeue();
   1490                         if (NULL != fwk_frame) {
   1491                             qcamera_hal3_pp_data_t *pp_job =
   1492                                     (qcamera_hal3_pp_data_t *)malloc(sizeof(qcamera_hal3_pp_data_t));
   1493                             jpeg_settings_t *jpeg_settings =
   1494                                     (jpeg_settings_t *)pme->m_jpegSettingsQ.dequeue();
   1495                             if (pp_job != NULL) {
   1496                                 memset(pp_job, 0, sizeof(qcamera_hal3_pp_data_t));
   1497                                 pp_job->jpeg_settings = jpeg_settings;
   1498                                 if (pme->m_pReprocChannel != NULL) {
   1499                                    if (NO_ERROR != pme->m_pReprocChannel->extractCrop(fwk_frame)) {
   1500                                        ALOGE("%s: Failed to extract output crop", __func__);
   1501 	                            }
   1502                                     // add into ongoing PP job Q
   1503                                     pp_job->fwk_src_frame = fwk_frame;
   1504                                     pme->m_ongoingPPQ.enqueue((void *)pp_job);
   1505                                     ret = pme->m_pReprocChannel->doReprocessOffline(fwk_frame);
   1506                                     if (NO_ERROR != ret) {
   1507                                         // remove from ongoing PP job Q
   1508                                         pme->m_ongoingPPQ.dequeue(false);
   1509                                     }
   1510                                 } else {
   1511                                     ALOGE("%s: Reprocess channel is NULL", __func__);
   1512                                     ret = -1;
   1513                                 }
   1514                             } else {
   1515                                 ALOGE("%s: no mem for qcamera_hal3_pp_data_t", __func__);
   1516                                 ret = -1;
   1517                             }
   1518 
   1519                             if (0 != ret) {
   1520                                 // free pp_job
   1521                                 if (pp_job != NULL) {
   1522                                     free(pp_job);
   1523                                 }
   1524                                 // free frame
   1525                                 if (fwk_frame != NULL) {
   1526                                     free(fwk_frame);
   1527                                 }
   1528                             }
   1529                         }
   1530                     }
   1531 
   1532                     CDBG_HIGH("%s: dequeuing pp frame", __func__);
   1533                     pthread_mutex_lock(&pme->mReprocJobLock);
   1534                     if(!pme->m_inputPPQ.isEmpty() && !pme->m_inputMetaQ.isEmpty()) {
   1535                         mm_camera_super_buf_t *pp_frame =
   1536                             (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue();
   1537                         meta_buffer =
   1538                             (mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue();
   1539                         jpeg_settings_t *jpeg_settings =
   1540                            (jpeg_settings_t *)pme->m_jpegSettingsQ.dequeue();
   1541                         pthread_mutex_unlock(&pme->mReprocJobLock);
   1542                         qcamera_hal3_pp_data_t *pp_job =
   1543                             (qcamera_hal3_pp_data_t *)malloc(sizeof(qcamera_hal3_pp_data_t));
   1544                         if (pp_job != NULL) {
   1545                             memset(pp_job, 0, sizeof(qcamera_hal3_pp_data_t));
   1546                             pp_job->src_frame = pp_frame;
   1547                             pp_job->src_metadata = meta_buffer;
   1548                             pp_job->metadata =
   1549                                     (metadata_buffer_t *)meta_buffer->bufs[0]->buffer;
   1550                             pp_job->jpeg_settings = jpeg_settings;
   1551                             pme->m_ongoingPPQ.enqueue((void *)pp_job);
   1552                             if (pme->m_pReprocChannel != NULL) {
   1553                                 qcamera_fwk_input_pp_data_t fwk_frame;
   1554                                 memset(&fwk_frame, 0, sizeof(qcamera_fwk_input_pp_data_t));
   1555                                 ret = pme->m_pReprocChannel->extractFrameCropAndRotation(
   1556                                         pp_frame, meta_buffer->bufs[0],
   1557                                         pp_job->jpeg_settings,
   1558                                         fwk_frame);
   1559                                 if (NO_ERROR == ret) {
   1560                                     // add into ongoing PP job Q
   1561                                     ret = pme->m_pReprocChannel->doReprocessOffline(
   1562                                             &fwk_frame);
   1563                                     if (NO_ERROR != ret) {
   1564                                         // remove from ongoing PP job Q
   1565                                         pme->m_ongoingPPQ.dequeue(false);
   1566                                     }
   1567                                 }
   1568                             } else {
   1569                                 CDBG_HIGH("%s: No reprocess. Calling processPPData directly",
   1570                                     __func__);
   1571                                 ret = pme->processPPData(pp_frame);
   1572                             }
   1573                         } else {
   1574                             ALOGE("%s: no mem for qcamera_hal3_pp_data_t", __func__);
   1575                             ret = -1;
   1576                         }
   1577 
   1578                         if (0 != ret) {
   1579                             // free pp_job
   1580                             if (pp_job != NULL) {
   1581                                 free(pp_job);
   1582                             }
   1583                             // free frame
   1584                             if (pp_frame != NULL) {
   1585                                 pme->releaseSuperBuf(pp_frame);
   1586                                 free(pp_frame);
   1587                             }
   1588                             //free metadata
   1589                             if (NULL != meta_buffer) {
   1590                                 pme->m_parent->metadataBufDone(meta_buffer);
   1591                                 free(meta_buffer);
   1592                             }
   1593                         }
   1594                     } else {
   1595                         pthread_mutex_unlock(&pme->mReprocJobLock);
   1596                     }
   1597                 } else {
   1598                     // not active, simply return buf and do no op
   1599                     qcamera_hal3_jpeg_data_t *jpeg_job =
   1600                         (qcamera_hal3_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
   1601                     if (NULL != jpeg_job) {
   1602                         free(jpeg_job);
   1603                     }
   1604                     mm_camera_super_buf_t *super_buf;
   1605                     super_buf = (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue();
   1606                     if (NULL != super_buf) {
   1607                         pme->releaseSuperBuf(super_buf);
   1608                         free(super_buf);
   1609                     }
   1610                     super_buf = (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue();
   1611                     if (NULL != super_buf) {
   1612                         pme->releaseSuperBuf(super_buf);
   1613                         free(super_buf);
   1614                     }
   1615                     mm_camera_super_buf_t *metadata = (mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue();
   1616                     if (metadata != NULL) {
   1617                         pme->m_parent->metadataBufDone(metadata);
   1618                         free(metadata);
   1619                     }
   1620                     qcamera_fwk_input_pp_data_t *fwk_frame =
   1621                             (qcamera_fwk_input_pp_data_t *) pme->m_inputFWKPPQ.dequeue();
   1622                     if (NULL != fwk_frame) {
   1623                         free(fwk_frame);
   1624                     }
   1625                 }
   1626             }
   1627             break;
   1628         case CAMERA_CMD_TYPE_EXIT:
   1629             running = 0;
   1630             break;
   1631         default:
   1632             break;
   1633         }
   1634     } while (running);
   1635     CDBG("%s: X", __func__);
   1636     return NULL;
   1637 }
   1638 
   1639 /*===========================================================================
   1640  * FUNCTION   : QCamera3Exif
   1641  *
   1642  * DESCRIPTION: constructor of QCamera3Exif
   1643  *
   1644  * PARAMETERS : None
   1645  *
   1646  * RETURN     : None
   1647  *==========================================================================*/
   1648 QCamera3Exif::QCamera3Exif()
   1649     : m_nNumEntries(0)
   1650 {
   1651     memset(m_Entries, 0, sizeof(m_Entries));
   1652 }
   1653 
   1654 /*===========================================================================
   1655  * FUNCTION   : ~QCamera3Exif
   1656  *
   1657  * DESCRIPTION: deconstructor of QCamera3Exif. Will release internal memory ptr.
   1658  *
   1659  * PARAMETERS : None
   1660  *
   1661  * RETURN     : None
   1662  *==========================================================================*/
   1663 QCamera3Exif::~QCamera3Exif()
   1664 {
   1665     for (uint32_t i = 0; i < m_nNumEntries; i++) {
   1666         switch (m_Entries[i].tag_entry.type) {
   1667             case EXIF_BYTE:
   1668                 {
   1669                     if (m_Entries[i].tag_entry.count > 1 &&
   1670                             m_Entries[i].tag_entry.data._bytes != NULL) {
   1671                         free(m_Entries[i].tag_entry.data._bytes);
   1672                         m_Entries[i].tag_entry.data._bytes = NULL;
   1673                     }
   1674                 }
   1675                 break;
   1676             case EXIF_ASCII:
   1677                 {
   1678                     if (m_Entries[i].tag_entry.data._ascii != NULL) {
   1679                         free(m_Entries[i].tag_entry.data._ascii);
   1680                         m_Entries[i].tag_entry.data._ascii = NULL;
   1681                     }
   1682                 }
   1683                 break;
   1684             case EXIF_SHORT:
   1685                 {
   1686                     if (m_Entries[i].tag_entry.count > 1 &&
   1687                             m_Entries[i].tag_entry.data._shorts != NULL) {
   1688                         free(m_Entries[i].tag_entry.data._shorts);
   1689                         m_Entries[i].tag_entry.data._shorts = NULL;
   1690                     }
   1691                 }
   1692                 break;
   1693             case EXIF_LONG:
   1694                 {
   1695                     if (m_Entries[i].tag_entry.count > 1 &&
   1696                             m_Entries[i].tag_entry.data._longs != NULL) {
   1697                         free(m_Entries[i].tag_entry.data._longs);
   1698                         m_Entries[i].tag_entry.data._longs = NULL;
   1699                     }
   1700                 }
   1701                 break;
   1702             case EXIF_RATIONAL:
   1703                 {
   1704                     if (m_Entries[i].tag_entry.count > 1 &&
   1705                             m_Entries[i].tag_entry.data._rats != NULL) {
   1706                         free(m_Entries[i].tag_entry.data._rats);
   1707                         m_Entries[i].tag_entry.data._rats = NULL;
   1708                     }
   1709                 }
   1710                 break;
   1711             case EXIF_UNDEFINED:
   1712                 {
   1713                     if (m_Entries[i].tag_entry.data._undefined != NULL) {
   1714                         free(m_Entries[i].tag_entry.data._undefined);
   1715                         m_Entries[i].tag_entry.data._undefined = NULL;
   1716                     }
   1717                 }
   1718                 break;
   1719             case EXIF_SLONG:
   1720                 {
   1721                     if (m_Entries[i].tag_entry.count > 1 &&
   1722                             m_Entries[i].tag_entry.data._slongs != NULL) {
   1723                         free(m_Entries[i].tag_entry.data._slongs);
   1724                         m_Entries[i].tag_entry.data._slongs = NULL;
   1725                     }
   1726                 }
   1727                 break;
   1728             case EXIF_SRATIONAL:
   1729                 {
   1730                     if (m_Entries[i].tag_entry.count > 1 &&
   1731                             m_Entries[i].tag_entry.data._srats != NULL) {
   1732                         free(m_Entries[i].tag_entry.data._srats);
   1733                         m_Entries[i].tag_entry.data._srats = NULL;
   1734                     }
   1735                 }
   1736                 break;
   1737             default:
   1738                 ALOGE("%s: Error, Unknown type",__func__);
   1739                 break;
   1740         }
   1741     }
   1742 }
   1743 
   1744 /*===========================================================================
   1745  * FUNCTION   : addEntry
   1746  *
   1747  * DESCRIPTION: function to add an entry to exif data
   1748  *
   1749  * PARAMETERS :
   1750  *   @tagid   : exif tag ID
   1751  *   @type    : data type
   1752  *   @count   : number of data in uint of its type
   1753  *   @data    : input data ptr
   1754  *
   1755  * RETURN     : int32_t type of status
   1756  *              NO_ERROR  -- success
   1757  *              none-zero failure code
   1758  *==========================================================================*/
   1759 int32_t QCamera3Exif::addEntry(exif_tag_id_t tagid,
   1760                               exif_tag_type_t type,
   1761                               uint32_t count,
   1762                               void *data)
   1763 {
   1764     int32_t rc = NO_ERROR;
   1765     if(m_nNumEntries >= MAX_HAL3_EXIF_TABLE_ENTRIES) {
   1766         ALOGE("%s: Number of entries exceeded limit", __func__);
   1767         return NO_MEMORY;
   1768     }
   1769 
   1770     m_Entries[m_nNumEntries].tag_id = tagid;
   1771     m_Entries[m_nNumEntries].tag_entry.type = type;
   1772     m_Entries[m_nNumEntries].tag_entry.count = count;
   1773     m_Entries[m_nNumEntries].tag_entry.copy = 1;
   1774     switch (type) {
   1775         case EXIF_BYTE:
   1776             {
   1777                 if (count > 1) {
   1778                     uint8_t *values = (uint8_t *)malloc(count);
   1779                     if (values == NULL) {
   1780                         ALOGE("%s: No memory for byte array", __func__);
   1781                         rc = NO_MEMORY;
   1782                     } else {
   1783                         memcpy(values, data, count);
   1784                         m_Entries[m_nNumEntries].tag_entry.data._bytes = values;
   1785                     }
   1786                 } else {
   1787                     m_Entries[m_nNumEntries].tag_entry.data._byte =
   1788                         *(uint8_t *)data;
   1789                 }
   1790             }
   1791             break;
   1792         case EXIF_ASCII:
   1793             {
   1794                 char *str = NULL;
   1795                 str = (char *)malloc(count + 1);
   1796                 if (str == NULL) {
   1797                     ALOGE("%s: No memory for ascii string", __func__);
   1798                     rc = NO_MEMORY;
   1799                 } else {
   1800                     memset(str, 0, count + 1);
   1801                     memcpy(str, data, count);
   1802                     m_Entries[m_nNumEntries].tag_entry.data._ascii = str;
   1803                 }
   1804             }
   1805             break;
   1806         case EXIF_SHORT:
   1807             {
   1808                 if (count > 1) {
   1809                     uint16_t *values =
   1810                         (uint16_t *)malloc(count * sizeof(uint16_t));
   1811                     if (values == NULL) {
   1812                         ALOGE("%s: No memory for short array", __func__);
   1813                         rc = NO_MEMORY;
   1814                     } else {
   1815                         memcpy(values, data, count * sizeof(uint16_t));
   1816                         m_Entries[m_nNumEntries].tag_entry.data._shorts =values;
   1817                     }
   1818                 } else {
   1819                     m_Entries[m_nNumEntries].tag_entry.data._short =
   1820                         *(uint16_t *)data;
   1821                 }
   1822             }
   1823             break;
   1824         case EXIF_LONG:
   1825             {
   1826                 if (count > 1) {
   1827                     uint32_t *values =
   1828                         (uint32_t *)malloc(count * sizeof(uint32_t));
   1829                     if (values == NULL) {
   1830                         ALOGE("%s: No memory for long array", __func__);
   1831                         rc = NO_MEMORY;
   1832                     } else {
   1833                         memcpy(values, data, count * sizeof(uint32_t));
   1834                         m_Entries[m_nNumEntries].tag_entry.data._longs = values;
   1835                     }
   1836                 } else {
   1837                     m_Entries[m_nNumEntries].tag_entry.data._long =
   1838                         *(uint32_t *)data;
   1839                 }
   1840             }
   1841             break;
   1842         case EXIF_RATIONAL:
   1843             {
   1844                 if (count > 1) {
   1845                     rat_t *values = (rat_t *)malloc(count * sizeof(rat_t));
   1846                     if (values == NULL) {
   1847                         ALOGE("%s: No memory for rational array", __func__);
   1848                         rc = NO_MEMORY;
   1849                     } else {
   1850                         memcpy(values, data, count * sizeof(rat_t));
   1851                         m_Entries[m_nNumEntries].tag_entry.data._rats = values;
   1852                     }
   1853                 } else {
   1854                     m_Entries[m_nNumEntries].tag_entry.data._rat =
   1855                         *(rat_t *)data;
   1856                 }
   1857             }
   1858             break;
   1859         case EXIF_UNDEFINED:
   1860             {
   1861                 uint8_t *values = (uint8_t *)malloc(count);
   1862                 if (values == NULL) {
   1863                     ALOGE("%s: No memory for undefined array", __func__);
   1864                     rc = NO_MEMORY;
   1865                 } else {
   1866                     memcpy(values, data, count);
   1867                     m_Entries[m_nNumEntries].tag_entry.data._undefined = values;
   1868                 }
   1869             }
   1870             break;
   1871         case EXIF_SLONG:
   1872             {
   1873                 if (count > 1) {
   1874                     int32_t *values =
   1875                         (int32_t *)malloc(count * sizeof(int32_t));
   1876                     if (values == NULL) {
   1877                         ALOGE("%s: No memory for signed long array", __func__);
   1878                         rc = NO_MEMORY;
   1879                     } else {
   1880                         memcpy(values, data, count * sizeof(int32_t));
   1881                         m_Entries[m_nNumEntries].tag_entry.data._slongs =values;
   1882                     }
   1883                 } else {
   1884                     m_Entries[m_nNumEntries].tag_entry.data._slong =
   1885                         *(int32_t *)data;
   1886                 }
   1887             }
   1888             break;
   1889         case EXIF_SRATIONAL:
   1890             {
   1891                 if (count > 1) {
   1892                     srat_t *values = (srat_t *)malloc(count * sizeof(srat_t));
   1893                     if (values == NULL) {
   1894                         ALOGE("%s: No memory for sign rational array",__func__);
   1895                         rc = NO_MEMORY;
   1896                     } else {
   1897                         memcpy(values, data, count * sizeof(srat_t));
   1898                         m_Entries[m_nNumEntries].tag_entry.data._srats = values;
   1899                     }
   1900                 } else {
   1901                     m_Entries[m_nNumEntries].tag_entry.data._srat =
   1902                         *(srat_t *)data;
   1903                 }
   1904             }
   1905             break;
   1906         default:
   1907             ALOGE("%s: Error, Unknown type",__func__);
   1908             break;
   1909     }
   1910 
   1911     // Increase number of entries
   1912     m_nNumEntries++;
   1913     return rc;
   1914 }
   1915 
   1916 }; // namespace qcamera
   1917