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 
     30 #define LOG_TAG "QCamera3PostProc"
     31 //#define LOG_NDEBUG 0
     32 
     33 #include <stdlib.h>
     34 #include <utils/Errors.h>
     35 
     36 #include "QCamera3PostProc.h"
     37 #include "QCamera3HWI.h"
     38 #include "QCamera3Channel.h"
     39 #include "QCamera3Stream.h"
     40 
     41 namespace qcamera {
     42 
     43 /*===========================================================================
     44  * FUNCTION   : QCamera3PostProcessor
     45  *
     46  * DESCRIPTION: constructor of QCamera3PostProcessor.
     47  *
     48  * PARAMETERS :
     49  *   @cam_ctrl : ptr to HWI object
     50  *
     51  * RETURN     : None
     52  *==========================================================================*/
     53 QCamera3PostProcessor::QCamera3PostProcessor(QCamera3PicChannel* ch_ctrl)
     54     : m_parent(ch_ctrl),
     55       mJpegCB(NULL),
     56       mJpegUserData(NULL),
     57       mJpegClientHandle(0),
     58       mJpegSessionId(0),
     59       m_pJpegExifObj(NULL),
     60       m_bThumbnailNeeded(TRUE),
     61       m_pReprocChannel(NULL),
     62       m_inputPPQ(releasePPInputData, this),
     63       m_ongoingPPQ(releaseOngoingPPData, this),
     64       m_inputJpegQ(releaseJpegData, this),
     65       m_ongoingJpegQ(releaseJpegData, this),
     66       m_inputRawQ(releasePPInputData, this),
     67       m_inputMetaQ(releaseMetaData, this),
     68       m_jpegSettingsQ(releaseJpegSetting, this)
     69 {
     70     memset(&mJpegHandle, 0, sizeof(mJpegHandle));
     71     pthread_mutex_init(&mReprocJobLock, NULL);
     72 }
     73 
     74 /*===========================================================================
     75  * FUNCTION   : ~QCamera3PostProcessor
     76  *
     77  * DESCRIPTION: deconstructor of QCamera3PostProcessor.
     78  *
     79  * PARAMETERS : None
     80  *
     81  * RETURN     : None
     82  *==========================================================================*/
     83 QCamera3PostProcessor::~QCamera3PostProcessor()
     84 {
     85     if (m_pJpegExifObj != NULL) {
     86         delete m_pJpegExifObj;
     87         m_pJpegExifObj = NULL;
     88     }
     89     pthread_mutex_destroy(&mReprocJobLock);
     90 }
     91 
     92 /*===========================================================================
     93  * FUNCTION   : init
     94  *
     95  * DESCRIPTION: initialization of postprocessor
     96  *
     97  * PARAMETERS :
     98  *   @jpeg_cb      : callback to handle jpeg event from mm-camera-interface
     99  *   @user_data    : user data ptr for jpeg callback
    100  *
    101  * RETURN     : int32_t type of status
    102  *              NO_ERROR  -- success
    103  *              none-zero failure code
    104  *==========================================================================*/
    105 int32_t QCamera3PostProcessor::init(QCamera3Memory* mMemory,
    106                                     jpeg_encode_callback_t jpeg_cb, void *user_data)
    107 {
    108     mJpegCB = jpeg_cb;
    109     mJpegUserData = user_data;
    110     mJpegMem = mMemory;
    111     mJpegClientHandle = jpeg_open(&mJpegHandle);
    112     if(!mJpegClientHandle) {
    113         ALOGE("%s : jpeg_open did not work", __func__);
    114         return UNKNOWN_ERROR;
    115     }
    116 
    117     m_dataProcTh.launch(dataProcessRoutine, this);
    118 
    119     return NO_ERROR;
    120 }
    121 
    122 /*===========================================================================
    123  * FUNCTION   : deinit
    124  *
    125  * DESCRIPTION: de-initialization of postprocessor
    126  *
    127  * PARAMETERS : None
    128  *
    129  * RETURN     : int32_t type of status
    130  *              NO_ERROR  -- success
    131  *              none-zero failure code
    132  *==========================================================================*/
    133 int32_t QCamera3PostProcessor::deinit()
    134 {
    135     m_dataProcTh.exit();
    136 
    137     if (m_pReprocChannel != NULL) {
    138         m_pReprocChannel->stop();
    139         delete m_pReprocChannel;
    140         m_pReprocChannel = NULL;
    141     }
    142 
    143     if(mJpegClientHandle > 0) {
    144         int rc = mJpegHandle.close(mJpegClientHandle);
    145         ALOGD("%s: Jpeg closed, rc = %d, mJpegClientHandle = %x",
    146               __func__, rc, mJpegClientHandle);
    147         mJpegClientHandle = 0;
    148         memset(&mJpegHandle, 0, sizeof(mJpegHandle));
    149     }
    150 
    151     mJpegMem = NULL;
    152 
    153     return NO_ERROR;
    154 }
    155 
    156 /*===========================================================================
    157  * FUNCTION   : start
    158  *
    159  * DESCRIPTION: start postprocessor. Data process thread and data notify thread
    160  *              will be launched.
    161  *
    162  * PARAMETERS :
    163  *   @pMemory       : memory object representing buffers to store JPEG.
    164  *   @pInputChannel : Input channel obj ptr that possibly needs reprocess
    165  *   @metadata      : metadata for the reprocessing
    166  *
    167  * RETURN     : int32_t type of status
    168  *              NO_ERROR  -- success
    169  *              none-zero failure code
    170  *
    171  * NOTE       : if any reprocess is needed, a reprocess channel/stream
    172  *              will be started.
    173  *==========================================================================*/
    174 int32_t QCamera3PostProcessor::start(QCamera3Channel *pInputChannel,
    175                                      metadata_buffer_t *metadata)
    176 {
    177     int32_t rc = NO_ERROR;
    178     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
    179 
    180     if (hal_obj->needReprocess()) {
    181 
    182         while (!m_inputMetaQ.isEmpty()) {
    183            m_pReprocChannel->metadataBufDone((mm_camera_super_buf_t *)m_inputMetaQ.dequeue());
    184         }
    185         if (m_pReprocChannel != NULL) {
    186             m_pReprocChannel->stop();
    187             delete m_pReprocChannel;
    188             m_pReprocChannel = NULL;
    189         }
    190 
    191         // if reprocess is needed, start reprocess channel
    192         QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
    193         ALOGV("%s: Setting input channel as pInputChannel", __func__);
    194         m_pReprocChannel = hal_obj->addOfflineReprocChannel(pInputChannel, m_parent, metadata);
    195         if (m_pReprocChannel == NULL) {
    196             ALOGE("%s: cannot add reprocess channel", __func__);
    197             return UNKNOWN_ERROR;
    198         }
    199 
    200         rc = m_pReprocChannel->start();
    201         if (rc != 0) {
    202             ALOGE("%s: cannot start reprocess channel", __func__);
    203             delete m_pReprocChannel;
    204             m_pReprocChannel = NULL;
    205             return rc;
    206         }
    207     }
    208     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_START_DATA_PROC, FALSE, FALSE);
    209 
    210     return rc;
    211 }
    212 
    213 /*===========================================================================
    214  * FUNCTION   : stop
    215  *
    216  * DESCRIPTION: stop postprocessor. Data process and notify thread will be stopped.
    217  *
    218  * PARAMETERS : None
    219  *
    220  * RETURN     : int32_t type of status
    221  *              NO_ERROR  -- success
    222  *              none-zero failure code
    223  *
    224  * NOTE       : reprocess channel will be stopped and deleted if there is any
    225  *==========================================================================*/
    226 int32_t QCamera3PostProcessor::stop()
    227 {
    228     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC, TRUE, TRUE);
    229 
    230     if (m_pReprocChannel != NULL) {
    231         m_pReprocChannel->stop();
    232         delete m_pReprocChannel;
    233         m_pReprocChannel = NULL;
    234     }
    235 
    236     return NO_ERROR;
    237 }
    238 
    239 /*===========================================================================
    240  * FUNCTION   : getJpegEncodeConfig
    241  *
    242  * DESCRIPTION: function to prepare encoding job information
    243  *
    244  * PARAMETERS :
    245  *   @encode_parm   : param to be filled with encoding configuration
    246  *   #main_stream   : stream object where the input buffer comes from
    247  *   @jpeg_settings : jpeg settings to be applied for encoding
    248  *
    249  * RETURN     : int32_t type of status
    250  *              NO_ERROR  -- success
    251  *              none-zero failure code
    252  *==========================================================================*/
    253 int32_t QCamera3PostProcessor::getJpegEncodeConfig(
    254                 mm_jpeg_encode_params_t& encode_parm,
    255                 QCamera3Stream *main_stream,
    256                 jpeg_settings_t *jpeg_settings)
    257 {
    258     ALOGV("%s : E", __func__);
    259     int32_t ret = NO_ERROR;
    260 
    261     encode_parm.jpeg_cb = mJpegCB;
    262     encode_parm.userdata = mJpegUserData;
    263 
    264     if (jpeg_settings->thumbnail_size.width > 0 &&
    265             jpeg_settings->thumbnail_size.height > 0)
    266         m_bThumbnailNeeded = TRUE;
    267     else
    268         m_bThumbnailNeeded = FALSE;
    269     encode_parm.encode_thumbnail = m_bThumbnailNeeded;
    270 
    271     // get color format
    272     cam_format_t img_fmt = CAM_FORMAT_YUV_420_NV12;  //default value
    273     main_stream->getFormat(img_fmt);
    274     encode_parm.color_format = getColorfmtFromImgFmt(img_fmt);
    275 
    276     // get jpeg quality
    277     encode_parm.quality = jpeg_settings->jpeg_quality;
    278 
    279     // get jpeg thumbnail quality
    280     encode_parm.thumb_quality = jpeg_settings->jpeg_thumb_quality;
    281 
    282     cam_frame_len_offset_t main_offset;
    283     memset(&main_offset, 0, sizeof(cam_frame_len_offset_t));
    284     main_stream->getFrameOffset(main_offset);
    285 
    286     // src buf config
    287     //Pass input main image buffer info to encoder.
    288     QCamera3Memory *pStreamMem = main_stream->getStreamBufs();
    289     if (pStreamMem == NULL) {
    290         ALOGE("%s: cannot get stream bufs from main stream", __func__);
    291         ret = BAD_VALUE;
    292         goto on_error;
    293     }
    294     encode_parm.num_src_bufs = pStreamMem->getCnt();
    295     for (uint32_t i = 0; i < encode_parm.num_src_bufs; i++) {
    296         if (pStreamMem != NULL) {
    297             encode_parm.src_main_buf[i].index = i;
    298             encode_parm.src_main_buf[i].buf_size = pStreamMem->getSize(i);
    299             encode_parm.src_main_buf[i].buf_vaddr = (uint8_t *)pStreamMem->getPtr(i);
    300             encode_parm.src_main_buf[i].fd = pStreamMem->getFd(i);
    301             encode_parm.src_main_buf[i].format = MM_JPEG_FMT_YUV;
    302             encode_parm.src_main_buf[i].offset = main_offset;
    303         }
    304     }
    305 
    306     //Pass input thumbnail buffer info to encoder.
    307     //Note: In this version thumb_stream = main_stream
    308     if (m_bThumbnailNeeded == TRUE) {
    309         pStreamMem = main_stream->getStreamBufs();
    310         if (pStreamMem == NULL) {
    311             ALOGE("%s: cannot get stream bufs from thumb stream", __func__);
    312             ret = BAD_VALUE;
    313             goto on_error;
    314         }
    315         cam_frame_len_offset_t thumb_offset;
    316         memset(&thumb_offset, 0, sizeof(cam_frame_len_offset_t));
    317         main_stream->getFrameOffset(thumb_offset);
    318         encode_parm.num_tmb_bufs = pStreamMem->getCnt();
    319         for (int i = 0; i < pStreamMem->getCnt(); i++) {
    320             if (pStreamMem != NULL) {
    321                 encode_parm.src_thumb_buf[i].index = i;
    322                 encode_parm.src_thumb_buf[i].buf_size = pStreamMem->getSize(i);
    323                 encode_parm.src_thumb_buf[i].buf_vaddr = (uint8_t *)pStreamMem->getPtr(i);
    324                 encode_parm.src_thumb_buf[i].fd = pStreamMem->getFd(i);
    325                 encode_parm.src_thumb_buf[i].format = MM_JPEG_FMT_YUV;
    326                 encode_parm.src_thumb_buf[i].offset = thumb_offset;
    327             }
    328         }
    329     }
    330 
    331     //Pass output jpeg buffer info to encoder.
    332     //mJpegMem is allocated by framework.
    333     encode_parm.num_dst_bufs = 1;
    334     encode_parm.dest_buf[0].index = 0;
    335     encode_parm.dest_buf[0].buf_size = mJpegMem->getSize(
    336             jpeg_settings->out_buf_index);
    337     encode_parm.dest_buf[0].buf_vaddr = (uint8_t *)mJpegMem->getPtr(
    338             jpeg_settings->out_buf_index);
    339     encode_parm.dest_buf[0].fd = mJpegMem->getFd(
    340             jpeg_settings->out_buf_index);
    341     encode_parm.dest_buf[0].format = MM_JPEG_FMT_YUV;
    342     encode_parm.dest_buf[0].offset = main_offset;
    343 
    344     ALOGV("%s : X", __func__);
    345     return NO_ERROR;
    346 
    347 on_error:
    348 
    349     ALOGV("%s : X with error %d", __func__, ret);
    350     return ret;
    351 }
    352 
    353 /*===========================================================================
    354  * FUNCTION   : processData
    355  *
    356  * DESCRIPTION: enqueue data into dataProc thread
    357  *
    358  * PARAMETERS :
    359  *   @frame   : process frame received from mm-camera-interface
    360  *
    361  * RETURN     : int32_t type of status
    362  *              NO_ERROR  -- success
    363  *              none-zero failure code
    364  *
    365  * NOTE       : depends on if offline reprocess is needed, received frame will
    366  *              be sent to either input queue of postprocess or jpeg encoding
    367  *==========================================================================*/
    368 int32_t QCamera3PostProcessor::processData(mm_camera_super_buf_t *frame)
    369 {
    370     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
    371     if (hal_obj->needReprocess()) {
    372         pthread_mutex_lock(&mReprocJobLock);
    373         // enqueu to post proc input queue
    374         m_inputPPQ.enqueue((void *)frame);
    375         if (!(m_inputMetaQ.isEmpty())) {
    376            ALOGV("%s: meta queue is not empty, do next job", __func__);
    377            m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
    378         }
    379         pthread_mutex_unlock(&mReprocJobLock);
    380     } else {
    381         ALOGD("%s: no need offline reprocess, sending to jpeg encoding", __func__);
    382         qcamera_jpeg_data_t *jpeg_job =
    383             (qcamera_jpeg_data_t *)malloc(sizeof(qcamera_jpeg_data_t));
    384         if (jpeg_job == NULL) {
    385             ALOGE("%s: No memory for jpeg job", __func__);
    386             return NO_MEMORY;
    387         }
    388 
    389         memset(jpeg_job, 0, sizeof(qcamera_jpeg_data_t));
    390         jpeg_job->src_frame = frame;
    391 
    392         // enqueu to jpeg input queue
    393         m_inputJpegQ.enqueue((void *)jpeg_job);
    394         m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
    395     }
    396 
    397     return NO_ERROR;
    398 }
    399 
    400 /*===========================================================================
    401  * FUNCTION   : processPPMetadata
    402  *
    403  * DESCRIPTION: enqueue data into dataProc thread
    404  *
    405  * PARAMETERS :
    406  *   @frame   : process metadata frame received from pic channel
    407  *
    408  * RETURN     : int32_t type of status
    409  *              NO_ERROR  -- success
    410  *              none-zero failure code
    411  *
    412  *==========================================================================*/
    413 int32_t QCamera3PostProcessor::processPPMetadata(metadata_buffer_t *reproc_meta)
    414 {
    415    pthread_mutex_lock(&mReprocJobLock);
    416     // enqueue to metadata input queue
    417     m_inputMetaQ.enqueue((void *)reproc_meta);
    418     if (!(m_inputPPQ.isEmpty())) {
    419        ALOGI("%s: pp queue is not empty, do next job", __func__);
    420        m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
    421     } else {
    422        ALOGI("%s: pp queue is empty, not calling do next job", __func__);
    423     }
    424     pthread_mutex_unlock(&mReprocJobLock);
    425     return NO_ERROR;
    426 }
    427 
    428 /*===========================================================================
    429  * FUNCTION   : processJpegSettingData
    430  *
    431  * DESCRIPTION: enqueue jpegSetting into dataProc thread
    432  *
    433  * PARAMETERS :
    434  *   @jpeg_settings : jpeg settings data received from pic channel
    435  *
    436  * RETURN     : int32_t type of status
    437  *              NO_ERROR  -- success
    438  *              none-zero failure code
    439  *
    440  *==========================================================================*/
    441 int32_t QCamera3PostProcessor::processJpegSettingData(
    442         jpeg_settings_t *jpeg_settings)
    443 {
    444     if (!jpeg_settings) {
    445         ALOGE("%s: invalid jpeg settings pointer", __func__);
    446         return -EINVAL;
    447     }
    448     return m_jpegSettingsQ.enqueue((void *)jpeg_settings);
    449 }
    450 
    451 /*===========================================================================
    452  * FUNCTION   : processRawData
    453  *
    454  * DESCRIPTION: enqueue raw data into dataProc thread
    455  *
    456  * PARAMETERS :
    457  *   @frame   : process frame received from mm-camera-interface
    458  *
    459  * RETURN     : int32_t type of status
    460  *              NO_ERROR  -- success
    461  *              none-zero failure code
    462  *==========================================================================*/
    463 int32_t QCamera3PostProcessor::processRawData(mm_camera_super_buf_t *frame)
    464 {
    465     // enqueu to raw input queue
    466     m_inputRawQ.enqueue((void *)frame);
    467     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
    468     return NO_ERROR;
    469 }
    470 
    471 /*===========================================================================
    472  * FUNCTION   : processPPData
    473  *
    474  * DESCRIPTION: process received frame after reprocess.
    475  *
    476  * PARAMETERS :
    477  *   @frame   : received frame from reprocess channel.
    478  *
    479  * RETURN     : int32_t type of status
    480  *              NO_ERROR  -- success
    481  *              none-zero failure code
    482  *
    483  * NOTE       : The frame after reprocess need to send to jpeg encoding.
    484  *==========================================================================*/
    485 int32_t QCamera3PostProcessor::processPPData(mm_camera_super_buf_t *frame)
    486 {
    487     qcamera_pp_data_t *job = (qcamera_pp_data_t *)m_ongoingPPQ.dequeue();
    488     jpeg_settings_t *jpeg_settings = (jpeg_settings_t *)m_jpegSettingsQ.dequeue();
    489 
    490     if (job == NULL || job->src_frame == NULL) {
    491         ALOGE("%s: Cannot find reprocess job", __func__);
    492         return BAD_VALUE;
    493     }
    494     if (jpeg_settings == NULL) {
    495         ALOGE("%s: Cannot find jpeg settings", __func__);
    496         return BAD_VALUE;
    497     }
    498 
    499     qcamera_jpeg_data_t *jpeg_job =
    500         (qcamera_jpeg_data_t *)malloc(sizeof(qcamera_jpeg_data_t));
    501     if (jpeg_job == NULL) {
    502         ALOGE("%s: No memory for jpeg job", __func__);
    503         return NO_MEMORY;
    504     }
    505 
    506     memset(jpeg_job, 0, sizeof(qcamera_jpeg_data_t));
    507     jpeg_job->src_frame = frame;
    508     jpeg_job->src_reproc_frame = job->src_frame;
    509     jpeg_job->metadata = job->metadata;
    510     jpeg_job->jpeg_settings = jpeg_settings;
    511 
    512     // free pp job buf
    513     free(job);
    514 
    515     // enqueu reprocessed frame to jpeg input queue
    516     m_inputJpegQ.enqueue((void *)jpeg_job);
    517 
    518     // wait up data proc thread
    519     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
    520 
    521     return NO_ERROR;
    522 }
    523 
    524 /*===========================================================================
    525  * FUNCTION   : findJpegJobByJobId
    526  *
    527  * DESCRIPTION: find a jpeg job from ongoing Jpeg queue by its job ID
    528  *
    529  * PARAMETERS :
    530  *   @jobId   : job Id of the job
    531  *
    532  * RETURN     : ptr to a jpeg job struct. NULL if not found.
    533  *
    534  * NOTE       : Currently only one job is sending to mm-jpeg-interface for jpeg
    535  *              encoding. Therefore simply dequeue from the ongoing Jpeg Queue
    536  *              will serve the purpose to find the jpeg job.
    537  *==========================================================================*/
    538 qcamera_jpeg_data_t *QCamera3PostProcessor::findJpegJobByJobId(uint32_t jobId)
    539 {
    540     qcamera_jpeg_data_t * job = NULL;
    541     if (jobId == 0) {
    542         ALOGE("%s: not a valid jpeg jobId", __func__);
    543         return NULL;
    544     }
    545 
    546     // currely only one jpeg job ongoing, so simply dequeue the head
    547     job = (qcamera_jpeg_data_t *)m_ongoingJpegQ.dequeue();
    548     return job;
    549 }
    550 
    551 /*===========================================================================
    552  * FUNCTION   : releasePPInputData
    553  *
    554  * DESCRIPTION: callback function to release post process input data node
    555  *
    556  * PARAMETERS :
    557  *   @data      : ptr to post process input data
    558  *   @user_data : user data ptr (QCamera3Reprocessor)
    559  *
    560  * RETURN     : None
    561  *==========================================================================*/
    562 void QCamera3PostProcessor::releasePPInputData(void *data, void *user_data)
    563 {
    564     QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
    565     if (NULL != pme) {
    566         pme->releaseSuperBuf((mm_camera_super_buf_t *)data);
    567     }
    568 }
    569 
    570 /*===========================================================================
    571  * FUNCTION   : releaseMetaData
    572  *
    573  * DESCRIPTION: callback function to release meta data node
    574  *
    575  * PARAMETERS :
    576  *   @data      : ptr to post process input data
    577  *   @user_data : user data ptr (QCamera3Reprocessor)
    578  *
    579  * RETURN     : None
    580  *==========================================================================*/
    581 void QCamera3PostProcessor::releaseMetaData(void *data, void * /*user_data*/)
    582 {
    583     metadata_buffer_t *metadata = (metadata_buffer_t *)data;
    584     if (metadata != NULL)
    585         free(metadata);
    586 }
    587 
    588 /*===========================================================================
    589  * FUNCTION   : releaseJpegSetting
    590  *
    591  * DESCRIPTION: callback function to release meta data node
    592  *
    593  * PARAMETERS :
    594  *   @data      : ptr to post process input data
    595  *   @user_data : user data ptr (QCamera3Reprocessor)
    596  *
    597  * RETURN     : None
    598  *==========================================================================*/
    599 void QCamera3PostProcessor::releaseJpegSetting(void *data, void * /*user_data*/)
    600 {
    601     jpeg_settings_t *jpegSetting = (jpeg_settings_t *)data;
    602     if (jpegSetting != NULL)
    603         free(jpegSetting);
    604 }
    605 
    606 /*===========================================================================
    607  * FUNCTION   : releaseJpegData
    608  *
    609  * DESCRIPTION: callback function to release jpeg job node
    610  *
    611  * PARAMETERS :
    612  *   @data      : ptr to ongoing jpeg job data
    613  *   @user_data : user data ptr (QCamera3Reprocessor)
    614  *
    615  * RETURN     : None
    616  *==========================================================================*/
    617 void QCamera3PostProcessor::releaseJpegData(void *data, void *user_data)
    618 {
    619     QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
    620     if (NULL != pme) {
    621         pme->releaseJpegJobData((qcamera_jpeg_data_t *)data);
    622     }
    623 }
    624 
    625 /*===========================================================================
    626  * FUNCTION   : releaseOngoingPPData
    627  *
    628  * DESCRIPTION: callback function to release ongoing postprocess job node
    629  *
    630  * PARAMETERS :
    631  *   @data      : ptr to onging postprocess job
    632  *   @user_data : user data ptr (QCamera3Reprocessor)
    633  *
    634  * RETURN     : None
    635  *==========================================================================*/
    636 void QCamera3PostProcessor::releaseOngoingPPData(void *data, void *user_data)
    637 {
    638     QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
    639     if (NULL != pme) {
    640         qcamera_pp_data_t *pp_job = (qcamera_pp_data_t *)data;
    641         if (NULL != pp_job->src_frame) {
    642             pme->releaseSuperBuf(pp_job->src_frame);
    643             free(pp_job->src_frame);
    644             free(pp_job->metadata);
    645             pp_job->src_frame = NULL;
    646             pp_job->metadata = NULL;
    647         }
    648     }
    649 }
    650 
    651 /*===========================================================================
    652  * FUNCTION   : releaseSuperBuf
    653  *
    654  * DESCRIPTION: function to release a superbuf frame by returning back to kernel
    655  *
    656  * PARAMETERS :
    657  *   @super_buf : ptr to the superbuf frame
    658  *
    659  * RETURN     : None
    660  *==========================================================================*/
    661 void QCamera3PostProcessor::releaseSuperBuf(mm_camera_super_buf_t *super_buf)
    662 {
    663     if (NULL != super_buf) {
    664         if (m_parent != NULL) {
    665             m_parent->bufDone(super_buf);
    666         }
    667     }
    668 }
    669 
    670 /*===========================================================================
    671  * FUNCTION   : releaseJpegJobData
    672  *
    673  * DESCRIPTION: function to release internal resources in jpeg job struct
    674  *
    675  * PARAMETERS :
    676  *   @job     : ptr to jpeg job struct
    677  *
    678  * RETURN     : None
    679  *
    680  * NOTE       : original source frame need to be queued back to kernel for
    681  *              future use. Output buf of jpeg job need to be released since
    682  *              it's allocated for each job. Exif object need to be deleted.
    683  *==========================================================================*/
    684 void QCamera3PostProcessor::releaseJpegJobData(qcamera_jpeg_data_t *job)
    685 {
    686     ALOGV("%s: E", __func__);
    687     if (NULL != job) {
    688         if (NULL != job->src_reproc_frame) {
    689             free(job->src_reproc_frame);
    690             job->src_reproc_frame = NULL;
    691         }
    692 
    693         if (NULL != job->src_frame) {
    694             free(job->src_frame);
    695             job->src_frame = NULL;
    696         }
    697 
    698         if (NULL != job->metadata) {
    699             free(job->metadata);
    700             job->metadata = NULL;
    701         }
    702 
    703         if (NULL != job->jpeg_settings) {
    704             free(job->jpeg_settings);
    705             job->jpeg_settings = NULL;
    706         }
    707     }
    708     ALOGV("%s: X", __func__);
    709 }
    710 
    711 /*===========================================================================
    712  * FUNCTION   : getColorfmtFromImgFmt
    713  *
    714  * DESCRIPTION: function to return jpeg color format based on its image format
    715  *
    716  * PARAMETERS :
    717  *   @img_fmt : image format
    718  *
    719  * RETURN     : jpeg color format that can be understandable by omx lib
    720  *==========================================================================*/
    721 mm_jpeg_color_format QCamera3PostProcessor::getColorfmtFromImgFmt(cam_format_t img_fmt)
    722 {
    723     switch (img_fmt) {
    724     case CAM_FORMAT_YUV_420_NV21:
    725         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
    726     case CAM_FORMAT_YUV_420_NV21_ADRENO:
    727         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
    728     case CAM_FORMAT_YUV_420_NV12:
    729         return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2;
    730     case CAM_FORMAT_YUV_420_YV12:
    731         return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2;
    732     case CAM_FORMAT_YUV_422_NV61:
    733         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V1;
    734     case CAM_FORMAT_YUV_422_NV16:
    735         return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V1;
    736     default:
    737         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
    738     }
    739 }
    740 
    741 /*===========================================================================
    742  * FUNCTION   : getJpegImgTypeFromImgFmt
    743  *
    744  * DESCRIPTION: function to return jpeg encode image type based on its image format
    745  *
    746  * PARAMETERS :
    747  *   @img_fmt : image format
    748  *
    749  * RETURN     : return jpeg source image format (YUV or Bitstream)
    750  *==========================================================================*/
    751 mm_jpeg_format_t QCamera3PostProcessor::getJpegImgTypeFromImgFmt(cam_format_t img_fmt)
    752 {
    753     switch (img_fmt) {
    754     case CAM_FORMAT_YUV_420_NV21:
    755     case CAM_FORMAT_YUV_420_NV21_ADRENO:
    756     case CAM_FORMAT_YUV_420_NV12:
    757     case CAM_FORMAT_YUV_420_YV12:
    758     case CAM_FORMAT_YUV_422_NV61:
    759     case CAM_FORMAT_YUV_422_NV16:
    760         return MM_JPEG_FMT_YUV;
    761     default:
    762         return MM_JPEG_FMT_YUV;
    763     }
    764 }
    765 
    766 /*===========================================================================
    767  * FUNCTION   : encodeData
    768  *
    769  * DESCRIPTION: function to prepare encoding job information and send to
    770  *              mm-jpeg-interface to do the encoding job
    771  *
    772  * PARAMETERS :
    773  *   @jpeg_job_data : ptr to a struct saving job related information
    774  *   @needNewSess   : flag to indicate if a new jpeg encoding session need
    775  *                    to be created. After creation, this flag will be toggled
    776  *
    777  * RETURN     : int32_t type of status
    778  *              NO_ERROR  -- success
    779  *              none-zero failure code
    780  *==========================================================================*/
    781 int32_t QCamera3PostProcessor::encodeData(qcamera_jpeg_data_t *jpeg_job_data,
    782                           uint8_t &needNewSess)
    783 {
    784     ALOGV("%s : E", __func__);
    785     int32_t ret = NO_ERROR;
    786     mm_jpeg_job_t jpg_job;
    787     uint32_t jobId = 0;
    788     QCamera3Stream *main_stream = NULL;
    789     mm_camera_buf_def_t *main_frame = NULL;
    790     QCamera3Stream *thumb_stream = NULL;
    791     mm_camera_buf_def_t *thumb_frame = NULL;
    792     QCamera3Channel *srcChannel = NULL;
    793     mm_camera_super_buf_t *recvd_frame = NULL;
    794     metadata_buffer_t *metadata = NULL;
    795     jpeg_settings_t *jpeg_settings = NULL;
    796     QCamera3HardwareInterface* hal_obj = NULL;
    797 
    798 
    799     hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
    800     recvd_frame = jpeg_job_data->src_frame;
    801     metadata = jpeg_job_data->metadata;
    802     jpeg_settings = jpeg_job_data->jpeg_settings;
    803 
    804     QCamera3Channel *pChannel = NULL;
    805     // first check picture channel
    806     if (m_parent != NULL &&
    807         m_parent->getMyHandle() == recvd_frame->ch_id) {
    808         pChannel = m_parent;
    809     }
    810     // check reprocess channel if not found
    811     if (pChannel == NULL) {
    812         if (m_pReprocChannel != NULL &&
    813             m_pReprocChannel->getMyHandle() == recvd_frame->ch_id) {
    814             pChannel = m_pReprocChannel;
    815         }
    816     }
    817 
    818     srcChannel = pChannel;
    819 
    820     if (srcChannel == NULL) {
    821         ALOGE("%s: No corresponding channel (ch_id = %d) exist, return here",
    822               __func__, recvd_frame->ch_id);
    823         return BAD_VALUE;
    824     }
    825 
    826     // find snapshot frame and thumnail frame
    827     //Note: In this version we will receive only snapshot frame.
    828     for (int i = 0; i < recvd_frame->num_bufs; i++) {
    829         QCamera3Stream *srcStream =
    830             srcChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id);
    831         if (srcStream != NULL) {
    832             switch (srcStream->getMyType()) {
    833             case CAM_STREAM_TYPE_SNAPSHOT:
    834             case CAM_STREAM_TYPE_NON_ZSL_SNAPSHOT:
    835             case CAM_STREAM_TYPE_OFFLINE_PROC:
    836                 main_stream = srcStream;
    837                 main_frame = recvd_frame->bufs[i];
    838                 break;
    839             case CAM_STREAM_TYPE_PREVIEW:
    840             case CAM_STREAM_TYPE_POSTVIEW:
    841                 thumb_stream = srcStream;
    842                 thumb_frame = recvd_frame->bufs[i];
    843                 break;
    844             default:
    845                 break;
    846             }
    847         }
    848     }
    849 
    850     if(NULL == main_frame){
    851        ALOGE("%s : Main frame is NULL", __func__);
    852        return BAD_VALUE;
    853     }
    854 
    855     QCamera3Memory *memObj = (QCamera3Memory *)main_frame->mem_info;
    856     if (NULL == memObj) {
    857         ALOGE("%s : Memeory Obj of main frame is NULL", __func__);
    858         return NO_MEMORY;
    859     }
    860 
    861     // clean and invalidate cache ops through mem obj of the frame
    862     memObj->cleanInvalidateCache(main_frame->buf_idx);
    863 
    864     if (thumb_frame != NULL) {
    865         QCamera3Memory *thumb_memObj = (QCamera3Memory *)thumb_frame->mem_info;
    866         if (NULL != thumb_memObj) {
    867             // clean and invalidate cache ops through mem obj of the frame
    868             thumb_memObj->cleanInvalidateCache(thumb_frame->buf_idx);
    869         }
    870     }
    871 
    872     if (mJpegClientHandle <= 0) {
    873         ALOGE("%s: Error: bug here, mJpegClientHandle is 0", __func__);
    874         return UNKNOWN_ERROR;
    875     }
    876 
    877     ALOGD("%s: Need new session?:%d",__func__, needNewSess);
    878     if (needNewSess) {
    879         //creating a new session, so we must destroy the old one
    880         if ( 0 < mJpegSessionId ) {
    881             ret = mJpegHandle.destroy_session(mJpegSessionId);
    882             if (ret != NO_ERROR) {
    883                 ALOGE("%s: Error destroying an old jpeg encoding session, id = %d",
    884                       __func__, mJpegSessionId);
    885                 return ret;
    886             }
    887             mJpegSessionId = 0;
    888         }
    889         // create jpeg encoding session
    890         mm_jpeg_encode_params_t encodeParam;
    891         memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t));
    892 
    893         getJpegEncodeConfig(encodeParam, main_stream, jpeg_settings);
    894         ALOGD("%s: #src bufs:%d # tmb bufs:%d #dst_bufs:%d", __func__,
    895                      encodeParam.num_src_bufs,encodeParam.num_tmb_bufs,encodeParam.num_dst_bufs);
    896         ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId);
    897         if (ret != NO_ERROR) {
    898             ALOGE("%s: Error creating a new jpeg encoding session, ret = %d", __func__, ret);
    899             return ret;
    900         }
    901         needNewSess = FALSE;
    902     }
    903 
    904     // Fill in new job
    905     memset(&jpg_job, 0, sizeof(mm_jpeg_job_t));
    906     jpg_job.job_type = JPEG_JOB_TYPE_ENCODE;
    907     jpg_job.encode_job.session_id = mJpegSessionId;
    908     jpg_job.encode_job.src_index = main_frame->buf_idx;
    909     jpg_job.encode_job.dst_index = 0;
    910 
    911     cam_rect_t crop;
    912     memset(&crop, 0, sizeof(cam_rect_t));
    913     //TBD_later - Zoom event removed in stream
    914     //main_stream->getCropInfo(crop);
    915 
    916     cam_dimension_t src_dim;
    917     memset(&src_dim, 0, sizeof(cam_dimension_t));
    918     main_stream->getFrameDimension(src_dim);
    919 
    920     cam_dimension_t dst_dim;
    921     memset(&dst_dim, 0, sizeof(cam_dimension_t));
    922     srcChannel->getStreamByIndex(0)->getFrameDimension(dst_dim);
    923 
    924     // main dim
    925     jpg_job.encode_job.main_dim.src_dim = src_dim;
    926     jpg_job.encode_job.main_dim.dst_dim = dst_dim;
    927     jpg_job.encode_job.main_dim.crop = crop;
    928 
    929     // get exif data
    930     if (m_pJpegExifObj != NULL) {
    931         delete m_pJpegExifObj;
    932         m_pJpegExifObj = NULL;
    933     }
    934     m_pJpegExifObj = m_parent->getExifData(metadata, jpeg_settings);
    935     if (m_pJpegExifObj != NULL) {
    936         jpg_job.encode_job.exif_info.exif_data = m_pJpegExifObj->getEntries();
    937         jpg_job.encode_job.exif_info.numOfEntries =
    938           m_pJpegExifObj->getNumOfEntries();
    939     }
    940     // thumbnail dim
    941     ALOGD("%s: Thumbnail needed:%d",__func__, m_bThumbnailNeeded);
    942     if (m_bThumbnailNeeded == TRUE) {
    943         if (thumb_stream == NULL) {
    944             // need jpeg thumbnail, but no postview/preview stream exists
    945             // we use the main stream/frame to encode thumbnail
    946             thumb_stream = main_stream;
    947             thumb_frame = main_frame;
    948         }
    949         memset(&crop, 0, sizeof(cam_rect_t));
    950         //TBD_later - Zoom event removed in stream
    951         //thumb_stream->getCropInfo(crop);
    952         jpg_job.encode_job.thumb_dim.dst_dim =
    953                 jpeg_settings->thumbnail_size;
    954 
    955         if (!hal_obj->needRotationReprocess()) {
    956             memset(&src_dim, 0, sizeof(cam_dimension_t));
    957             thumb_stream->getFrameDimension(src_dim);
    958             jpg_job.encode_job.rotation =
    959                     jpeg_settings->jpeg_orientation;
    960             ALOGD("%s: jpeg rotation is set to %d", __func__,
    961                     jpg_job.encode_job.rotation);
    962         } else if (jpeg_settings->jpeg_orientation  == 90 ||
    963                 jpeg_settings->jpeg_orientation == 270) {
    964            //swap the thumbnail destination width and height if it has already been rotated
    965             int temp = jpg_job.encode_job.thumb_dim.dst_dim.width;
    966             jpg_job.encode_job.thumb_dim.dst_dim.width =
    967                     jpg_job.encode_job.thumb_dim.dst_dim.height;
    968             jpg_job.encode_job.thumb_dim.dst_dim.height = temp;
    969         }
    970         jpg_job.encode_job.thumb_dim.src_dim = src_dim;
    971         jpg_job.encode_job.thumb_dim.crop = crop;
    972         jpg_job.encode_job.thumb_index = thumb_frame->buf_idx;
    973     }
    974 
    975     if (metadata != NULL) {
    976        //Fill in the metadata passed as parameter
    977        jpg_job.encode_job.p_metadata_v3 = metadata;
    978     } else {
    979        ALOGE("%s: Metadata is null", __func__);
    980     }
    981     //Not required here
    982     //jpg_job.encode_job.cam_exif_params = m_parent->mExifParams;
    983     //Start jpeg encoding
    984     ret = mJpegHandle.start_job(&jpg_job, &jobId);
    985     if (ret == NO_ERROR) {
    986         // remember job info
    987         jpeg_job_data->jobId = jobId;
    988     }
    989 
    990     ALOGV("%s : X", __func__);
    991     return ret;
    992 }
    993 
    994 /*===========================================================================
    995  * FUNCTION   : dataProcessRoutine
    996  *
    997  * DESCRIPTION: data process routine that handles input data either from input
    998  *              Jpeg Queue to do jpeg encoding, or from input PP Queue to do
    999  *              reprocess.
   1000  *
   1001  * PARAMETERS :
   1002  *   @data    : user data ptr (QCamera3PostProcessor)
   1003  *
   1004  * RETURN     : None
   1005  *==========================================================================*/
   1006 void *QCamera3PostProcessor::dataProcessRoutine(void *data)
   1007 {
   1008     int running = 1;
   1009     int ret;
   1010     uint8_t is_active = FALSE;
   1011     uint8_t needNewSess = TRUE;
   1012     mm_camera_super_buf_t *pp_frame = NULL;
   1013     metadata_buffer_t *meta_buffer = NULL;
   1014     ALOGV("%s: E", __func__);
   1015     QCamera3PostProcessor *pme = (QCamera3PostProcessor *)data;
   1016     QCameraCmdThread *cmdThread = &pme->m_dataProcTh;
   1017     cmdThread->setName("cam_data_proc");
   1018 
   1019     do {
   1020         do {
   1021             ret = cam_sem_wait(&cmdThread->cmd_sem);
   1022             if (ret != 0 && errno != EINVAL) {
   1023                 ALOGE("%s: cam_sem_wait error (%s)",
   1024                            __func__, strerror(errno));
   1025                 return NULL;
   1026             }
   1027         } while (ret != 0);
   1028 
   1029         // we got notified about new cmd avail in cmd queue
   1030         camera_cmd_type_t cmd = cmdThread->getCmd();
   1031         switch (cmd) {
   1032         case CAMERA_CMD_TYPE_START_DATA_PROC:
   1033             ALOGD("%s: start data proc", __func__);
   1034             is_active = TRUE;
   1035             needNewSess = TRUE;
   1036 
   1037             pme->m_ongoingPPQ.init();
   1038             pme->m_inputJpegQ.init();
   1039             pme->m_inputPPQ.init();
   1040             pme->m_inputRawQ.init();
   1041             pme->m_inputMetaQ.init();
   1042             pme->m_ongoingJpegQ.init();
   1043             pme->m_jpegSettingsQ.init();
   1044 
   1045             break;
   1046         case CAMERA_CMD_TYPE_STOP_DATA_PROC:
   1047             {
   1048                 ALOGD("%s: stop data proc", __func__);
   1049                 is_active = FALSE;
   1050 
   1051                 // cancel all ongoing jpeg jobs
   1052                 qcamera_jpeg_data_t *jpeg_job =
   1053                     (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
   1054                 while (jpeg_job != NULL) {
   1055                     pme->mJpegHandle.abort_job(jpeg_job->jobId);
   1056 
   1057                     pme->releaseJpegJobData(jpeg_job);
   1058                     free(jpeg_job);
   1059 
   1060                     jpeg_job = (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
   1061                 }
   1062 
   1063                 // destroy jpeg encoding session
   1064                 if ( 0 < pme->mJpegSessionId ) {
   1065                     pme->mJpegHandle.destroy_session(pme->mJpegSessionId);
   1066                     pme->mJpegSessionId = 0;
   1067                 }
   1068 
   1069                 // free jpeg exif obj
   1070                 if (pme->m_pJpegExifObj != NULL) {
   1071                     delete pme->m_pJpegExifObj;
   1072                     pme->m_pJpegExifObj = NULL;
   1073                 }
   1074                 needNewSess = TRUE;
   1075 
   1076                 // flush ongoing postproc Queue
   1077                 pme->m_ongoingPPQ.flush();
   1078 
   1079                 // flush input jpeg Queue
   1080                 pme->m_inputJpegQ.flush();
   1081 
   1082                 // flush input Postproc Queue
   1083                 pme->m_inputPPQ.flush();
   1084 
   1085                 // flush input raw Queue
   1086                 pme->m_inputRawQ.flush();
   1087 
   1088                 pme->m_inputMetaQ.flush();
   1089 
   1090                 // signal cmd is completed
   1091                 cam_sem_post(&cmdThread->sync_sem);
   1092             }
   1093             break;
   1094         case CAMERA_CMD_TYPE_DO_NEXT_JOB:
   1095             {
   1096                 ALOGD("%s: Do next job, active is %d", __func__, is_active);
   1097                 if (is_active == TRUE) {
   1098                     // check if there is any ongoing jpeg jobs
   1099                     if (pme->m_ongoingJpegQ.isEmpty()) {
   1100                        ALOGI("%s: ongoing jpeg queue is empty so doing the jpeg job", __func__);
   1101                         // no ongoing jpeg job, we are fine to send jpeg encoding job
   1102                         qcamera_jpeg_data_t *jpeg_job =
   1103                             (qcamera_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
   1104 
   1105                         if (NULL != jpeg_job) {
   1106                             // add into ongoing jpeg job Q
   1107                             pme->m_ongoingJpegQ.enqueue((void *)jpeg_job);
   1108                             ret = pme->encodeData(jpeg_job, needNewSess);
   1109                             if (NO_ERROR != ret) {
   1110                                 // dequeue the last one
   1111                                 pme->m_ongoingJpegQ.dequeue(false);
   1112 
   1113                                 pme->releaseJpegJobData(jpeg_job);
   1114                                 free(jpeg_job);
   1115                             }
   1116                         }
   1117                     }
   1118                     ALOGD("%s: dequeuing pp frame", __func__);
   1119                     pp_frame =
   1120                         (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue();
   1121                     meta_buffer =
   1122                         (metadata_buffer_t *)pme->m_inputMetaQ.dequeue();
   1123                     if (NULL != pp_frame && NULL != meta_buffer) {
   1124                         qcamera_pp_data_t *pp_job =
   1125                             (qcamera_pp_data_t *)malloc(sizeof(qcamera_pp_data_t));
   1126                         if (pp_job != NULL) {
   1127                             memset(pp_job, 0, sizeof(qcamera_pp_data_t));
   1128                             if (pme->m_pReprocChannel != NULL) {
   1129                                 // add into ongoing PP job Q
   1130                                 pp_job->src_frame = pp_frame;
   1131                                 pp_job->metadata = meta_buffer;
   1132                                 pme->m_ongoingPPQ.enqueue((void *)pp_job);
   1133                                 ret = pme->m_pReprocChannel->doReprocessOffline(pp_frame, meta_buffer);
   1134                                 if (NO_ERROR != ret) {
   1135                                     // remove from ongoing PP job Q
   1136                                     pme->m_ongoingPPQ.dequeue(false);
   1137                                 }
   1138                             } else {
   1139                                 ALOGE("%s: Reprocess channel is NULL", __func__);
   1140                                 ret = -1;
   1141                             }
   1142                         } else {
   1143                             ALOGE("%s: no mem for qcamera_pp_data_t", __func__);
   1144                             ret = -1;
   1145                         }
   1146 
   1147                         if (0 != ret) {
   1148                             // free pp_job
   1149                             if (pp_job != NULL) {
   1150                                 free(pp_job);
   1151                             }
   1152                             // free frame
   1153                             if (pp_frame != NULL) {
   1154                                 pme->releaseSuperBuf(pp_frame);
   1155                                 free(pp_frame);
   1156                             }
   1157                         }
   1158                     }
   1159                 } else {
   1160                     // not active, simply return buf and do no op
   1161                     mm_camera_super_buf_t *super_buf;
   1162                     qcamera_jpeg_data_t *jpeg_job =
   1163                         (qcamera_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
   1164                     if (NULL != jpeg_job) {
   1165                         free(jpeg_job);
   1166                     }
   1167                     super_buf = (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue();
   1168                     if (NULL != super_buf) {
   1169                         pme->releaseSuperBuf(super_buf);
   1170                         free(super_buf);
   1171                     }
   1172                     super_buf = (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue();
   1173                     if (NULL != super_buf) {
   1174                         pme->releaseSuperBuf(super_buf);
   1175                         free(super_buf);
   1176                     }
   1177                     super_buf = (mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue();
   1178                     if (NULL != super_buf) {
   1179                         pme->releaseSuperBuf(super_buf);
   1180                         free(super_buf);
   1181                     }
   1182                 }
   1183             }
   1184             break;
   1185         case CAMERA_CMD_TYPE_EXIT:
   1186             running = 0;
   1187             break;
   1188         default:
   1189             break;
   1190         }
   1191     } while (running);
   1192     ALOGV("%s: X", __func__);
   1193     return NULL;
   1194 }
   1195 
   1196 /*===========================================================================
   1197  * FUNCTION   : QCamera3Exif
   1198  *
   1199  * DESCRIPTION: constructor of QCamera3Exif
   1200  *
   1201  * PARAMETERS : None
   1202  *
   1203  * RETURN     : None
   1204  *==========================================================================*/
   1205 QCamera3Exif::QCamera3Exif()
   1206     : m_nNumEntries(0)
   1207 {
   1208     memset(m_Entries, 0, sizeof(m_Entries));
   1209 }
   1210 
   1211 /*===========================================================================
   1212  * FUNCTION   : ~QCamera3Exif
   1213  *
   1214  * DESCRIPTION: deconstructor of QCamera3Exif. Will release internal memory ptr.
   1215  *
   1216  * PARAMETERS : None
   1217  *
   1218  * RETURN     : None
   1219  *==========================================================================*/
   1220 QCamera3Exif::~QCamera3Exif()
   1221 {
   1222     for (uint32_t i = 0; i < m_nNumEntries; i++) {
   1223         switch (m_Entries[i].tag_entry.type) {
   1224             case EXIF_BYTE:
   1225                 {
   1226                     if (m_Entries[i].tag_entry.count > 1 &&
   1227                             m_Entries[i].tag_entry.data._bytes != NULL) {
   1228                         free(m_Entries[i].tag_entry.data._bytes);
   1229                         m_Entries[i].tag_entry.data._bytes = NULL;
   1230                     }
   1231                 }
   1232                 break;
   1233             case EXIF_ASCII:
   1234                 {
   1235                     if (m_Entries[i].tag_entry.data._ascii != NULL) {
   1236                         free(m_Entries[i].tag_entry.data._ascii);
   1237                         m_Entries[i].tag_entry.data._ascii = NULL;
   1238                     }
   1239                 }
   1240                 break;
   1241             case EXIF_SHORT:
   1242                 {
   1243                     if (m_Entries[i].tag_entry.count > 1 &&
   1244                             m_Entries[i].tag_entry.data._shorts != NULL) {
   1245                         free(m_Entries[i].tag_entry.data._shorts);
   1246                         m_Entries[i].tag_entry.data._shorts = NULL;
   1247                     }
   1248                 }
   1249                 break;
   1250             case EXIF_LONG:
   1251                 {
   1252                     if (m_Entries[i].tag_entry.count > 1 &&
   1253                             m_Entries[i].tag_entry.data._longs != NULL) {
   1254                         free(m_Entries[i].tag_entry.data._longs);
   1255                         m_Entries[i].tag_entry.data._longs = NULL;
   1256                     }
   1257                 }
   1258                 break;
   1259             case EXIF_RATIONAL:
   1260                 {
   1261                     if (m_Entries[i].tag_entry.count > 1 &&
   1262                             m_Entries[i].tag_entry.data._rats != NULL) {
   1263                         free(m_Entries[i].tag_entry.data._rats);
   1264                         m_Entries[i].tag_entry.data._rats = NULL;
   1265                     }
   1266                 }
   1267                 break;
   1268             case EXIF_UNDEFINED:
   1269                 {
   1270                     if (m_Entries[i].tag_entry.data._undefined != NULL) {
   1271                         free(m_Entries[i].tag_entry.data._undefined);
   1272                         m_Entries[i].tag_entry.data._undefined = NULL;
   1273                     }
   1274                 }
   1275                 break;
   1276             case EXIF_SLONG:
   1277                 {
   1278                     if (m_Entries[i].tag_entry.count > 1 &&
   1279                             m_Entries[i].tag_entry.data._slongs != NULL) {
   1280                         free(m_Entries[i].tag_entry.data._slongs);
   1281                         m_Entries[i].tag_entry.data._slongs = NULL;
   1282                     }
   1283                 }
   1284                 break;
   1285             case EXIF_SRATIONAL:
   1286                 {
   1287                     if (m_Entries[i].tag_entry.count > 1 &&
   1288                             m_Entries[i].tag_entry.data._srats != NULL) {
   1289                         free(m_Entries[i].tag_entry.data._srats);
   1290                         m_Entries[i].tag_entry.data._srats = NULL;
   1291                     }
   1292                 }
   1293                 break;
   1294             default:
   1295                 ALOGE("%s: Error, Unknown type",__func__);
   1296                 break;
   1297         }
   1298     }
   1299 }
   1300 
   1301 /*===========================================================================
   1302  * FUNCTION   : addEntry
   1303  *
   1304  * DESCRIPTION: function to add an entry to exif data
   1305  *
   1306  * PARAMETERS :
   1307  *   @tagid   : exif tag ID
   1308  *   @type    : data type
   1309  *   @count   : number of data in uint of its type
   1310  *   @data    : input data ptr
   1311  *
   1312  * RETURN     : int32_t type of status
   1313  *              NO_ERROR  -- success
   1314  *              none-zero failure code
   1315  *==========================================================================*/
   1316 int32_t QCamera3Exif::addEntry(exif_tag_id_t tagid,
   1317                               exif_tag_type_t type,
   1318                               uint32_t count,
   1319                               void *data)
   1320 {
   1321     int32_t rc = NO_ERROR;
   1322     if(m_nNumEntries >= MAX_EXIF_TABLE_ENTRIES) {
   1323         ALOGE("%s: Number of entries exceeded limit", __func__);
   1324         return NO_MEMORY;
   1325     }
   1326 
   1327     m_Entries[m_nNumEntries].tag_id = tagid;
   1328     m_Entries[m_nNumEntries].tag_entry.type = type;
   1329     m_Entries[m_nNumEntries].tag_entry.count = count;
   1330     m_Entries[m_nNumEntries].tag_entry.copy = 1;
   1331     switch (type) {
   1332         case EXIF_BYTE:
   1333             {
   1334                 if (count > 1) {
   1335                     uint8_t *values = (uint8_t *)malloc(count);
   1336                     if (values == NULL) {
   1337                         ALOGE("%s: No memory for byte array", __func__);
   1338                         rc = NO_MEMORY;
   1339                     } else {
   1340                         memcpy(values, data, count);
   1341                         m_Entries[m_nNumEntries].tag_entry.data._bytes = values;
   1342                     }
   1343                 } else {
   1344                     m_Entries[m_nNumEntries].tag_entry.data._byte =
   1345                         *(uint8_t *)data;
   1346                 }
   1347             }
   1348             break;
   1349         case EXIF_ASCII:
   1350             {
   1351                 char *str = NULL;
   1352                 str = (char *)malloc(count + 1);
   1353                 if (str == NULL) {
   1354                     ALOGE("%s: No memory for ascii string", __func__);
   1355                     rc = NO_MEMORY;
   1356                 } else {
   1357                     memset(str, 0, count + 1);
   1358                     memcpy(str, data, count);
   1359                     m_Entries[m_nNumEntries].tag_entry.data._ascii = str;
   1360                 }
   1361             }
   1362             break;
   1363         case EXIF_SHORT:
   1364             {
   1365                 if (count > 1) {
   1366                     uint16_t *values =
   1367                         (uint16_t *)malloc(count * sizeof(uint16_t));
   1368                     if (values == NULL) {
   1369                         ALOGE("%s: No memory for short array", __func__);
   1370                         rc = NO_MEMORY;
   1371                     } else {
   1372                         memcpy(values, data, count * sizeof(uint16_t));
   1373                         m_Entries[m_nNumEntries].tag_entry.data._shorts =values;
   1374                     }
   1375                 } else {
   1376                     m_Entries[m_nNumEntries].tag_entry.data._short =
   1377                         *(uint16_t *)data;
   1378                 }
   1379             }
   1380             break;
   1381         case EXIF_LONG:
   1382             {
   1383                 if (count > 1) {
   1384                     uint32_t *values =
   1385                         (uint32_t *)malloc(count * sizeof(uint32_t));
   1386                     if (values == NULL) {
   1387                         ALOGE("%s: No memory for long array", __func__);
   1388                         rc = NO_MEMORY;
   1389                     } else {
   1390                         memcpy(values, data, count * sizeof(uint32_t));
   1391                         m_Entries[m_nNumEntries].tag_entry.data._longs = values;
   1392                     }
   1393                 } else {
   1394                     m_Entries[m_nNumEntries].tag_entry.data._long =
   1395                         *(uint32_t *)data;
   1396                 }
   1397             }
   1398             break;
   1399         case EXIF_RATIONAL:
   1400             {
   1401                 if (count > 1) {
   1402                     rat_t *values = (rat_t *)malloc(count * sizeof(rat_t));
   1403                     if (values == NULL) {
   1404                         ALOGE("%s: No memory for rational array", __func__);
   1405                         rc = NO_MEMORY;
   1406                     } else {
   1407                         memcpy(values, data, count * sizeof(rat_t));
   1408                         m_Entries[m_nNumEntries].tag_entry.data._rats = values;
   1409                     }
   1410                 } else {
   1411                     m_Entries[m_nNumEntries].tag_entry.data._rat =
   1412                         *(rat_t *)data;
   1413                 }
   1414             }
   1415             break;
   1416         case EXIF_UNDEFINED:
   1417             {
   1418                 uint8_t *values = (uint8_t *)malloc(count);
   1419                 if (values == NULL) {
   1420                     ALOGE("%s: No memory for undefined array", __func__);
   1421                     rc = NO_MEMORY;
   1422                 } else {
   1423                     memcpy(values, data, count);
   1424                     m_Entries[m_nNumEntries].tag_entry.data._undefined = values;
   1425                 }
   1426             }
   1427             break;
   1428         case EXIF_SLONG:
   1429             {
   1430                 if (count > 1) {
   1431                     int32_t *values =
   1432                         (int32_t *)malloc(count * sizeof(int32_t));
   1433                     if (values == NULL) {
   1434                         ALOGE("%s: No memory for signed long array", __func__);
   1435                         rc = NO_MEMORY;
   1436                     } else {
   1437                         memcpy(values, data, count * sizeof(int32_t));
   1438                         m_Entries[m_nNumEntries].tag_entry.data._slongs =values;
   1439                     }
   1440                 } else {
   1441                     m_Entries[m_nNumEntries].tag_entry.data._slong =
   1442                         *(int32_t *)data;
   1443                 }
   1444             }
   1445             break;
   1446         case EXIF_SRATIONAL:
   1447             {
   1448                 if (count > 1) {
   1449                     srat_t *values = (srat_t *)malloc(count * sizeof(srat_t));
   1450                     if (values == NULL) {
   1451                         ALOGE("%s: No memory for sign rational array",__func__);
   1452                         rc = NO_MEMORY;
   1453                     } else {
   1454                         memcpy(values, data, count * sizeof(srat_t));
   1455                         m_Entries[m_nNumEntries].tag_entry.data._srats = values;
   1456                     }
   1457                 } else {
   1458                     m_Entries[m_nNumEntries].tag_entry.data._srat =
   1459                         *(srat_t *)data;
   1460                 }
   1461             }
   1462             break;
   1463         default:
   1464             ALOGE("%s: Error, Unknown type",__func__);
   1465             break;
   1466     }
   1467 
   1468     // Increase number of entries
   1469     m_nNumEntries++;
   1470     return rc;
   1471 }
   1472 
   1473 }; // namespace qcamera
   1474