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