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