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