Home | History | Annotate | Download | only in HAL
      1 /* Copyright (c) 2012-2014, The Linux Foundataion. All rights reserved.
      2 *
      3 * Redistribution and use in source and binary forms, with or without
      4 * modification, are permitted provided that the following conditions are
      5 * met:
      6 *     * Redistributions of source code must retain the above copyright
      7 *       notice, this list of conditions and the following disclaimer.
      8 *     * Redistributions in binary form must reproduce the above
      9 *       copyright notice, this list of conditions and the following
     10 *       disclaimer in the documentation and/or other materials provided
     11 *       with the distribution.
     12 *     * Neither the name of The Linux Foundation nor the names of its
     13 *       contributors may be used to endorse or promote products derived
     14 *       from this software without specific prior written permission.
     15 *
     16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 *
     28 */
     29 
     30 #define LOG_TAG "QCameraPostProc"
     31 
     32 #include <fcntl.h>
     33 #include <stdlib.h>
     34 #include <utils/Errors.h>
     35 
     36 #include "QCamera2HWI.h"
     37 #include "QCameraPostProc.h"
     38 
     39 namespace qcamera {
     40 
     41 const char *QCameraPostProcessor::STORE_LOCATION = "/sdcard/img_%d.jpg";
     42 
     43 #define FREE_JPEG_OUTPUT_BUFFER(ptr,cnt)     \
     44     int jpeg_bufs; \
     45     for (jpeg_bufs = 0; jpeg_bufs < (int)cnt; jpeg_bufs++)  { \
     46       if (ptr[jpeg_bufs] != NULL) { \
     47           free(ptr[jpeg_bufs]); \
     48           ptr[jpeg_bufs] = NULL; \
     49       } \
     50     }
     51 
     52 /*===========================================================================
     53  * FUNCTION   : QCameraPostProcessor
     54  *
     55  * DESCRIPTION: constructor of QCameraPostProcessor.
     56  *
     57  * PARAMETERS :
     58  *   @cam_ctrl : ptr to HWI object
     59  *
     60  * RETURN     : None
     61  *==========================================================================*/
     62 QCameraPostProcessor::QCameraPostProcessor(QCamera2HardwareInterface *cam_ctrl)
     63     : m_parent(cam_ctrl),
     64       mJpegCB(NULL),
     65       mJpegUserData(NULL),
     66       mJpegClientHandle(0),
     67       mJpegSessionId(0),
     68       m_pJpegExifObj(NULL),
     69       m_bThumbnailNeeded(TRUE),
     70       m_pReprocChannel(NULL),
     71       m_bInited(FALSE),
     72       m_inputPPQ(releasePPInputData, this),
     73       m_ongoingPPQ(releaseOngoingPPData, this),
     74       m_inputJpegQ(releaseJpegData, this),
     75       m_ongoingJpegQ(releaseJpegData, this),
     76       m_inputRawQ(releaseRawData, this),
     77       mSaveFrmCnt(0),
     78       mUseSaveProc(false),
     79       mUseJpegBurst(false),
     80       mJpegMemOpt(true),
     81       m_JpegOutputMemCount(0),
     82       mNewJpegSessionNeeded(true)
     83 {
     84     memset(&mJpegHandle, 0, sizeof(mJpegHandle));
     85     memset(&m_pJpegOutputMem, 0, sizeof(m_pJpegOutputMem));
     86 }
     87 
     88 /*===========================================================================
     89  * FUNCTION   : ~QCameraPostProcessor
     90  *
     91  * DESCRIPTION: deconstructor of QCameraPostProcessor.
     92  *
     93  * PARAMETERS : None
     94  *
     95  * RETURN     : None
     96  *==========================================================================*/
     97 QCameraPostProcessor::~QCameraPostProcessor()
     98 {
     99     FREE_JPEG_OUTPUT_BUFFER(m_pJpegOutputMem,m_JpegOutputMemCount);
    100     if (m_pJpegExifObj != NULL) {
    101         delete m_pJpegExifObj;
    102         m_pJpegExifObj = NULL;
    103     }
    104     if (m_pReprocChannel != NULL) {
    105         m_pReprocChannel->stop();
    106         delete m_pReprocChannel;
    107         m_pReprocChannel = NULL;
    108     }
    109 }
    110 
    111 /*===========================================================================
    112  * FUNCTION   : init
    113  *
    114  * DESCRIPTION: initialization of postprocessor
    115  *
    116  * PARAMETERS :
    117  *   @jpeg_cb      : callback to handle jpeg event from mm-camera-interface
    118  *   @user_data    : user data ptr for jpeg callback
    119  *
    120  * RETURN     : int32_t type of status
    121  *              NO_ERROR  -- success
    122  *              none-zero failure code
    123  *==========================================================================*/
    124 int32_t QCameraPostProcessor::init(jpeg_encode_callback_t jpeg_cb, void *user_data)
    125 {
    126     mJpegCB = jpeg_cb;
    127     mJpegUserData = user_data;
    128     mm_dimension max_size;
    129 
    130     //set max pic size
    131     memset(&max_size, 0, sizeof(mm_dimension));
    132     max_size.w = m_parent->m_max_pic_width;
    133     max_size.h = m_parent->m_max_pic_height;
    134 
    135     mJpegClientHandle = jpeg_open(&mJpegHandle, max_size);
    136     if(!mJpegClientHandle) {
    137         ALOGE("%s : jpeg_open did not work", __func__);
    138         return UNKNOWN_ERROR;
    139     }
    140 
    141     m_dataProcTh.launch(dataProcessRoutine, this);
    142     m_saveProcTh.launch(dataSaveRoutine, this);
    143 
    144     m_bInited = TRUE;
    145     return NO_ERROR;
    146 }
    147 
    148 /*===========================================================================
    149  * FUNCTION   : deinit
    150  *
    151  * DESCRIPTION: de-initialization of postprocessor
    152  *
    153  * PARAMETERS : None
    154  *
    155  * RETURN     : int32_t type of status
    156  *              NO_ERROR  -- success
    157  *              none-zero failure code
    158  *==========================================================================*/
    159 int32_t QCameraPostProcessor::deinit()
    160 {
    161     if (m_bInited == TRUE) {
    162         m_dataProcTh.exit();
    163         m_saveProcTh.exit();
    164 
    165         if(mJpegClientHandle > 0) {
    166             int rc = mJpegHandle.close(mJpegClientHandle);
    167             CDBG_HIGH("%s: Jpeg closed, rc = %d, mJpegClientHandle = %x",
    168                   __func__, rc, mJpegClientHandle);
    169             mJpegClientHandle = 0;
    170             memset(&mJpegHandle, 0, sizeof(mJpegHandle));
    171         }
    172         m_bInited = FALSE;
    173     }
    174     return NO_ERROR;
    175 }
    176 
    177 /*===========================================================================
    178  * FUNCTION   : start
    179  *
    180  * DESCRIPTION: start postprocessor. Data process thread and data notify thread
    181  *              will be launched.
    182  *
    183  * PARAMETERS :
    184  *   @pSrcChannel : source channel obj ptr that possibly needs reprocess
    185  *
    186  * RETURN     : int32_t type of status
    187  *              NO_ERROR  -- success
    188  *              none-zero failure code
    189  *
    190  * NOTE       : if any reprocess is needed, a reprocess channel/stream
    191  *              will be started.
    192  *==========================================================================*/
    193 int32_t QCameraPostProcessor::start(QCameraChannel *pSrcChannel)
    194 {
    195     char prop[PROPERTY_VALUE_MAX];
    196     int32_t rc = NO_ERROR;
    197     if (m_bInited == FALSE) {
    198         ALOGE("%s: postproc not initialized yet", __func__);
    199         return UNKNOWN_ERROR;
    200     }
    201 
    202     if (m_parent->needReprocess()) {
    203         if (m_pReprocChannel != NULL) {
    204             delete m_pReprocChannel;
    205             m_pReprocChannel = NULL;
    206         }
    207         // if reprocess is needed, start reprocess channel
    208         m_pReprocChannel = m_parent->addReprocChannel(pSrcChannel);
    209         if (m_pReprocChannel == NULL) {
    210             ALOGE("%s: cannot add reprocess channel", __func__);
    211             return UNKNOWN_ERROR;
    212         }
    213 
    214         rc = m_pReprocChannel->start();
    215         if (rc != 0) {
    216             ALOGE("%s: cannot start reprocess channel", __func__);
    217             delete m_pReprocChannel;
    218             m_pReprocChannel = NULL;
    219             return rc;
    220         }
    221     }
    222 
    223     property_get("persist.camera.longshot.save", prop, "0");
    224     mUseSaveProc = atoi(prop) > 0 ? true : false;
    225 
    226     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_START_DATA_PROC, TRUE, FALSE);
    227     m_parent->m_cbNotifier.startSnapshots();
    228 
    229     // Create Jpeg session
    230     if ( !m_parent->mParameters.getRecordingHintValue() &&
    231             !m_parent->isLongshotEnabled() &&
    232             !m_parent->isZSLMode()) {
    233 
    234         QCameraChannel *pChannel = NULL;
    235         pChannel = m_parent->needReprocess() ? m_pReprocChannel : pSrcChannel;
    236         QCameraStream *pSnapshotStream = NULL;
    237         QCameraStream *pThumbStream = NULL;
    238 
    239         for (int i = 0; i < pChannel->getNumOfStreams(); ++i) {
    240             QCameraStream *pStream = pChannel->getStreamByIndex(i);
    241 
    242             if ( NULL == pStream ) {
    243                 break;
    244             }
    245 
    246             if (pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
    247                     pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT)) {
    248                 pSnapshotStream = pStream;
    249             }
    250 
    251             if (pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) ||
    252                     pStream->isOrignalTypeOf(CAM_STREAM_TYPE_POSTVIEW)) {
    253                 pThumbStream = pStream;
    254             }
    255         }
    256 
    257         // If thumbnail is not part of the reprocess channel, then
    258         // try to get it from the source channel
    259         if ((NULL == pThumbStream) && (pChannel == m_pReprocChannel)) {
    260             for (int i = 0; i < pSrcChannel->getNumOfStreams(); ++i) {
    261                 QCameraStream *pStream = pSrcChannel->getStreamByIndex(i);
    262 
    263                 if ( NULL == pStream ) {
    264                     break;
    265                 }
    266 
    267                 if (pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) ||
    268                     pStream->isOrignalTypeOf(CAM_STREAM_TYPE_POSTVIEW)) {
    269                     pThumbStream = pStream;
    270                 }
    271             }
    272         }
    273 
    274         if (m_parent->mParameters.generateThumbFromMain()) {
    275             pThumbStream = NULL;
    276         }
    277 
    278         if ( NULL != pSnapshotStream ) {
    279             mm_jpeg_encode_params_t encodeParam;
    280             memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t));
    281             getJpegEncodingConfig(encodeParam, pSnapshotStream, pThumbStream);
    282             CDBG_HIGH("[KPI Perf] %s : call jpeg create_session", __func__);
    283 
    284             rc = mJpegHandle.create_session(mJpegClientHandle,
    285                     &encodeParam,
    286                     &mJpegSessionId);
    287             if (rc != NO_ERROR) {
    288                 ALOGE("%s: error creating a new jpeg encoding session", __func__);
    289                 return rc;
    290             }
    291             mNewJpegSessionNeeded = false;
    292         }
    293     }
    294 
    295     return rc;
    296 }
    297 
    298 /*===========================================================================
    299  * FUNCTION   : stop
    300  *
    301  * DESCRIPTION: stop postprocessor. Data process and notify thread will be stopped.
    302  *
    303  * PARAMETERS : None
    304  *
    305  * RETURN     : int32_t type of status
    306  *              NO_ERROR  -- success
    307  *              none-zero failure code
    308  *
    309  * NOTE       : reprocess channel will be stopped and deleted if there is any
    310  *==========================================================================*/
    311 int32_t QCameraPostProcessor::stop()
    312 {
    313     if (m_bInited == TRUE) {
    314         m_parent->m_cbNotifier.stopSnapshots();
    315         // dataProc Thread need to process "stop" as sync call because abort jpeg job should be a sync call
    316         m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC, TRUE, TRUE);
    317     }
    318 
    319     return NO_ERROR;
    320 }
    321 
    322 /*===========================================================================
    323  * FUNCTION   : getJpegEncodingConfig
    324  *
    325  * DESCRIPTION: function to prepare encoding job information
    326  *
    327  * PARAMETERS :
    328  *   @encode_parm   : param to be filled with encoding configuration
    329  *
    330  * RETURN     : int32_t type of status
    331  *              NO_ERROR  -- success
    332  *              none-zero failure code
    333  *==========================================================================*/
    334 int32_t QCameraPostProcessor::getJpegEncodingConfig(mm_jpeg_encode_params_t& encode_parm,
    335                                                     QCameraStream *main_stream,
    336                                                     QCameraStream *thumb_stream)
    337 {
    338     CDBG("%s : E", __func__);
    339     int32_t ret = NO_ERROR;
    340     uint32_t out_size;
    341 
    342     char prop[PROPERTY_VALUE_MAX];
    343     property_get("persist.camera.jpeg_burst", prop, "0");
    344     mUseJpegBurst = (atoi(prop) > 0) && !mUseSaveProc;
    345     encode_parm.burst_mode = mUseJpegBurst;
    346 
    347     cam_rect_t crop;
    348     memset(&crop, 0, sizeof(cam_rect_t));
    349     main_stream->getCropInfo(crop);
    350 
    351     cam_dimension_t src_dim, dst_dim;
    352     memset(&src_dim, 0, sizeof(cam_dimension_t));
    353     memset(&dst_dim, 0, sizeof(cam_dimension_t));
    354     main_stream->getFrameDimension(src_dim);
    355 
    356     bool hdr_output_crop = m_parent->mParameters.isHDROutputCropEnabled();
    357     if (hdr_output_crop && crop.height) {
    358         dst_dim.height = crop.height;
    359     } else {
    360         dst_dim.height = src_dim.height;
    361     }
    362     if (hdr_output_crop && crop.width) {
    363         dst_dim.width = crop.width;
    364     } else {
    365         dst_dim.width = src_dim.width;
    366     }
    367 
    368     // set rotation only when no online rotation or offline pp rotation is done before
    369     if (!m_parent->needRotationReprocess()) {
    370         encode_parm.rotation = m_parent->getJpegRotation();
    371     }
    372 
    373     encode_parm.main_dim.src_dim = src_dim;
    374     encode_parm.main_dim.dst_dim = dst_dim;
    375 
    376     encode_parm.jpeg_cb = mJpegCB;
    377     encode_parm.userdata = mJpegUserData;
    378 
    379     m_bThumbnailNeeded = TRUE; // need encode thumbnail by default
    380     cam_dimension_t thumbnailSize;
    381     memset(&thumbnailSize, 0, sizeof(cam_dimension_t));
    382     m_parent->getThumbnailSize(thumbnailSize);
    383     if (thumbnailSize.width == 0 || thumbnailSize.height == 0) {
    384         // (0,0) means no thumbnail
    385         m_bThumbnailNeeded = FALSE;
    386     }
    387     encode_parm.encode_thumbnail = m_bThumbnailNeeded;
    388 
    389     // get color format
    390     cam_format_t img_fmt = CAM_FORMAT_YUV_420_NV12;
    391     main_stream->getFormat(img_fmt);
    392     encode_parm.color_format = getColorfmtFromImgFmt(img_fmt);
    393 
    394     // get jpeg quality
    395     encode_parm.quality = m_parent->getJpegQuality();
    396     if (encode_parm.quality <= 0) {
    397         encode_parm.quality = 85;
    398     }
    399     cam_frame_len_offset_t main_offset;
    400     memset(&main_offset, 0, sizeof(cam_frame_len_offset_t));
    401     main_stream->getFrameOffset(main_offset);
    402 
    403     // src buf config
    404     QCameraMemory *pStreamMem = main_stream->getStreamBufs();
    405     if (pStreamMem == NULL) {
    406         ALOGE("%s: cannot get stream bufs from main stream", __func__);
    407         ret = BAD_VALUE;
    408         goto on_error;
    409     }
    410     encode_parm.num_src_bufs = pStreamMem->getCnt();
    411     for (uint32_t i = 0; i < encode_parm.num_src_bufs; i++) {
    412         camera_memory_t *stream_mem = pStreamMem->getMemory(i, false);
    413         if (stream_mem != NULL) {
    414             encode_parm.src_main_buf[i].index = i;
    415             encode_parm.src_main_buf[i].buf_size = stream_mem->size;
    416             encode_parm.src_main_buf[i].buf_vaddr = (uint8_t *)stream_mem->data;
    417             encode_parm.src_main_buf[i].fd = pStreamMem->getFd(i);
    418             encode_parm.src_main_buf[i].format = MM_JPEG_FMT_YUV;
    419             encode_parm.src_main_buf[i].offset = main_offset;
    420         }
    421     }
    422 
    423     if (m_bThumbnailNeeded == TRUE) {
    424         bool need_thumb_rotate = true;
    425         int jpeg_rotation = m_parent->getJpegRotation();
    426         m_parent->getThumbnailSize(encode_parm.thumb_dim.dst_dim);
    427 
    428         if (thumb_stream == NULL) {
    429             thumb_stream = main_stream;
    430             need_thumb_rotate = false;
    431         }
    432         pStreamMem = thumb_stream->getStreamBufs();
    433         if (pStreamMem == NULL) {
    434             ALOGE("%s: cannot get stream bufs from thumb stream", __func__);
    435             ret = BAD_VALUE;
    436             goto on_error;
    437         }
    438         cam_frame_len_offset_t thumb_offset;
    439         memset(&thumb_offset, 0, sizeof(cam_frame_len_offset_t));
    440         thumb_stream->getFrameOffset(thumb_offset);
    441         encode_parm.num_tmb_bufs =  pStreamMem->getCnt();
    442         for (int i = 0; i < pStreamMem->getCnt(); i++) {
    443             camera_memory_t *stream_mem = pStreamMem->getMemory(i, false);
    444             if (stream_mem != NULL) {
    445                 encode_parm.src_thumb_buf[i].index = i;
    446                 encode_parm.src_thumb_buf[i].buf_size = stream_mem->size;
    447                 encode_parm.src_thumb_buf[i].buf_vaddr = (uint8_t *)stream_mem->data;
    448                 encode_parm.src_thumb_buf[i].fd = pStreamMem->getFd(i);
    449                 encode_parm.src_thumb_buf[i].format = MM_JPEG_FMT_YUV;
    450                 encode_parm.src_thumb_buf[i].offset = thumb_offset;
    451             }
    452         }
    453         cam_format_t img_fmt_thumb = CAM_FORMAT_YUV_420_NV12;
    454         thumb_stream->getFormat(img_fmt_thumb);
    455         encode_parm.thumb_color_format = getColorfmtFromImgFmt(img_fmt_thumb);
    456 
    457         // crop is the same if frame is the same
    458         if (thumb_stream != main_stream) {
    459             memset(&crop, 0, sizeof(cam_rect_t));
    460             thumb_stream->getCropInfo(crop);
    461         }
    462 
    463         memset(&src_dim, 0, sizeof(cam_dimension_t));
    464         thumb_stream->getFrameDimension(src_dim);
    465         encode_parm.thumb_dim.src_dim = src_dim;
    466 
    467         if (!m_parent->needRotationReprocess() || need_thumb_rotate) {
    468             encode_parm.thumb_rotation = jpeg_rotation;
    469         } else if ((90 == jpeg_rotation) || (270 == jpeg_rotation)) {
    470             // swap thumbnail dimensions
    471             cam_dimension_t tmp_dim = encode_parm.thumb_dim.dst_dim;
    472             encode_parm.thumb_dim.dst_dim.width = tmp_dim.height;
    473             encode_parm.thumb_dim.dst_dim.height = tmp_dim.width;
    474         }
    475         encode_parm.thumb_dim.crop = crop;
    476     }
    477 
    478     encode_parm.num_dst_bufs = 1;
    479     if (mUseJpegBurst) {
    480         encode_parm.num_dst_bufs = MAX_JPEG_BURST;
    481     }
    482     encode_parm.get_memory = NULL;
    483     out_size = main_offset.frame_len;
    484     if (mJpegMemOpt) {
    485         encode_parm.get_memory = getJpegMemory;
    486         out_size = sizeof(omx_jpeg_ouput_buf_t);
    487         encode_parm.num_dst_bufs = encode_parm.num_src_bufs;
    488     }
    489     m_JpegOutputMemCount = encode_parm.num_dst_bufs;
    490     for (int i = 0; i < (int)m_JpegOutputMemCount; i++) {
    491         if (m_pJpegOutputMem[i] != NULL)
    492           free(m_pJpegOutputMem[i]);
    493         omx_jpeg_ouput_buf_t omx_out_buf;
    494         omx_out_buf.handle = this;
    495         // allocate output buf for jpeg encoding
    496         m_pJpegOutputMem[i] = malloc(out_size);
    497 
    498         if (NULL == m_pJpegOutputMem[i]) {
    499           ret = NO_MEMORY;
    500           ALOGE("%s : initHeapMem for jpeg, ret = NO_MEMORY", __func__);
    501           goto on_error;
    502         }
    503 
    504         if (mJpegMemOpt) {
    505             memcpy(m_pJpegOutputMem[i], &omx_out_buf, sizeof(omx_out_buf));
    506         }
    507 
    508 
    509         encode_parm.dest_buf[i].index = i;
    510         encode_parm.dest_buf[i].buf_size = main_offset.frame_len;
    511         encode_parm.dest_buf[i].buf_vaddr = (uint8_t *)m_pJpegOutputMem[i];
    512         encode_parm.dest_buf[i].fd = 0;
    513         encode_parm.dest_buf[i].format = MM_JPEG_FMT_YUV;
    514         encode_parm.dest_buf[i].offset = main_offset;
    515     }
    516 
    517 
    518     CDBG("%s : X", __func__);
    519     return NO_ERROR;
    520 
    521 on_error:
    522     FREE_JPEG_OUTPUT_BUFFER(m_pJpegOutputMem, m_JpegOutputMemCount);
    523 
    524     CDBG("%s : X with error %d", __func__, ret);
    525     return ret;
    526 }
    527 
    528 /*===========================================================================
    529  * FUNCTION   : sendEvtNotify
    530  *
    531  * DESCRIPTION: send event notify through notify callback registered by upper layer
    532  *
    533  * PARAMETERS :
    534  *   @msg_type: msg type of notify
    535  *   @ext1    : extension
    536  *   @ext2    : extension
    537  *
    538  * RETURN     : int32_t type of status
    539  *              NO_ERROR  -- success
    540  *              none-zero failure code
    541  *==========================================================================*/
    542 int32_t QCameraPostProcessor::sendEvtNotify(int32_t msg_type,
    543                                             int32_t ext1,
    544                                             int32_t ext2)
    545 {
    546     return m_parent->sendEvtNotify(msg_type, ext1, ext2);
    547 }
    548 
    549 /*===========================================================================
    550  * FUNCTION   : sendDataNotify
    551  *
    552  * DESCRIPTION: enqueue data into dataNotify thread
    553  *
    554  * PARAMETERS :
    555  *   @msg_type: data callback msg type
    556  *   @data    : ptr to data memory struct
    557  *   @index   : index to data buffer
    558  *   @metadata: ptr to meta data buffer if there is any
    559  *   @release_data : ptr to struct indicating if data need to be released
    560  *                   after notify
    561  *
    562  * RETURN     : int32_t type of status
    563  *              NO_ERROR  -- success
    564  *              none-zero failure code
    565  *==========================================================================*/
    566 int32_t QCameraPostProcessor::sendDataNotify(int32_t msg_type,
    567                                              camera_memory_t *data,
    568                                              uint8_t index,
    569                                              camera_frame_metadata_t *metadata,
    570                                              qcamera_release_data_t *release_data)
    571 {
    572     qcamera_data_argm_t *data_cb = (qcamera_data_argm_t *)malloc(sizeof(qcamera_data_argm_t));
    573     if (NULL == data_cb) {
    574         ALOGE("%s: no mem for acamera_data_argm_t", __func__);
    575         return NO_MEMORY;
    576     }
    577     memset(data_cb, 0, sizeof(qcamera_data_argm_t));
    578     data_cb->msg_type = msg_type;
    579     data_cb->data = data;
    580     data_cb->index = index;
    581     data_cb->metadata = metadata;
    582     if (release_data != NULL) {
    583         data_cb->release_data = *release_data;
    584     }
    585 
    586     qcamera_callback_argm_t cbArg;
    587     memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
    588     cbArg.cb_type = QCAMERA_DATA_SNAPSHOT_CALLBACK;
    589     cbArg.msg_type = msg_type;
    590     cbArg.data = data;
    591     cbArg.metadata = metadata;
    592     cbArg.user_data = data_cb;
    593     cbArg.cookie = this;
    594     cbArg.release_cb = releaseNotifyData;
    595     int rc = m_parent->m_cbNotifier.notifyCallback(cbArg);
    596     if ( NO_ERROR != rc ) {
    597         ALOGE("%s: Error enqueuing jpeg data into notify queue", __func__);
    598         releaseNotifyData(data_cb, this, UNKNOWN_ERROR);
    599         return UNKNOWN_ERROR;
    600     }
    601 
    602     return rc;
    603 }
    604 
    605 /*===========================================================================
    606  * FUNCTION   : processData
    607  *
    608  * DESCRIPTION: enqueue data into dataProc thread
    609  *
    610  * PARAMETERS :
    611  *   @frame   : process frame received from mm-camera-interface
    612  *
    613  * RETURN     : int32_t type of status
    614  *              NO_ERROR  -- success
    615  *              none-zero failure code
    616  *
    617  * NOTE       : depends on if offline reprocess is needed, received frame will
    618  *              be sent to either input queue of postprocess or jpeg encoding
    619  *==========================================================================*/
    620 int32_t QCameraPostProcessor::processData(mm_camera_super_buf_t *frame)
    621 {
    622     if (m_bInited == FALSE) {
    623         ALOGE("%s: postproc not initialized yet", __func__);
    624         return UNKNOWN_ERROR;
    625     }
    626 
    627     if (m_parent->needReprocess()) {
    628         if ((!m_parent->isLongshotEnabled() &&
    629              !m_parent->m_stateMachine.isNonZSLCaptureRunning()) ||
    630             (m_parent->isLongshotEnabled() &&
    631              m_parent->isCaptureShutterEnabled())) {
    632             //play shutter sound
    633             m_parent->playShutter();
    634         }
    635 
    636         CDBG_HIGH("%s: need reprocess", __func__);
    637         // enqueu to post proc input queue
    638         m_inputPPQ.enqueue((void *)frame);
    639     } else if (m_parent->mParameters.isNV16PictureFormat() ||
    640         m_parent->mParameters.isNV21PictureFormat()) {
    641         //check if raw frame information is needed.
    642         if(m_parent->mParameters.isYUVFrameInfoNeeded())
    643             setYUVFrameInfo(frame);
    644 
    645         processRawData(frame);
    646     } else {
    647         //play shutter sound
    648         if(!m_parent->m_stateMachine.isNonZSLCaptureRunning() &&
    649            !m_parent->mLongshotEnabled)
    650            m_parent->playShutter();
    651 
    652         CDBG_HIGH("%s: no need offline reprocess, sending to jpeg encoding", __func__);
    653         qcamera_jpeg_data_t *jpeg_job =
    654             (qcamera_jpeg_data_t *)malloc(sizeof(qcamera_jpeg_data_t));
    655         if (jpeg_job == NULL) {
    656             ALOGE("%s: No memory for jpeg job", __func__);
    657             return NO_MEMORY;
    658         }
    659 
    660         memset(jpeg_job, 0, sizeof(qcamera_jpeg_data_t));
    661         jpeg_job->src_frame = frame;
    662 
    663         // find meta data frame
    664         mm_camera_buf_def_t *meta_frame = NULL;
    665         for (int i = 0; i < frame->num_bufs; i++) {
    666             // look through input superbuf
    667             if (frame->bufs[i]->stream_type == CAM_STREAM_TYPE_METADATA) {
    668                 meta_frame = frame->bufs[i];
    669                 break;
    670             }
    671         }
    672 
    673         if (meta_frame != NULL) {
    674             // fill in meta data frame ptr
    675             jpeg_job->metadata = (metadata_buffer_t *)meta_frame->buffer;
    676         }
    677 
    678         // enqueu to jpeg input queue
    679         m_inputJpegQ.enqueue((void *)jpeg_job);
    680     }
    681     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
    682 
    683     return NO_ERROR;
    684 }
    685 
    686 /*===========================================================================
    687  * FUNCTION   : processRawData
    688  *
    689  * DESCRIPTION: enqueue raw data into dataProc thread
    690  *
    691  * PARAMETERS :
    692  *   @frame   : process frame received from mm-camera-interface
    693  *
    694  * RETURN     : int32_t type of status
    695  *              NO_ERROR  -- success
    696  *              none-zero failure code
    697  *==========================================================================*/
    698 int32_t QCameraPostProcessor::processRawData(mm_camera_super_buf_t *frame)
    699 {
    700     if (m_bInited == FALSE) {
    701         ALOGE("%s: postproc not initialized yet", __func__);
    702         return UNKNOWN_ERROR;
    703     }
    704 
    705     // enqueu to raw input queue
    706     m_inputRawQ.enqueue((void *)frame);
    707     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
    708     return NO_ERROR;
    709 }
    710 
    711 /*===========================================================================
    712  * FUNCTION   : processJpegEvt
    713  *
    714  * DESCRIPTION: process jpeg event from mm-jpeg-interface.
    715  *
    716  * PARAMETERS :
    717  *   @evt     : payload of jpeg event, including information about jpeg encoding
    718  *              status, jpeg size and so on.
    719  *
    720  * RETURN     : int32_t type of status
    721  *              NO_ERROR  -- success
    722  *              none-zero failure code
    723  *
    724  * NOTE       : This event will also trigger DataProc thread to move to next job
    725  *              processing (i.e., send a new jpeg encoding job to mm-jpeg-interface
    726  *              if there is any pending job in jpeg input queue)
    727  *==========================================================================*/
    728 int32_t QCameraPostProcessor::processJpegEvt(qcamera_jpeg_evt_payload_t *evt)
    729 {
    730     if (m_bInited == FALSE) {
    731         ALOGE("%s: postproc not initialized yet", __func__);
    732         return UNKNOWN_ERROR;
    733     }
    734 
    735     int32_t rc = NO_ERROR;
    736     camera_memory_t *jpeg_mem = NULL;
    737     omx_jpeg_ouput_buf_t *jpeg_out = NULL;
    738 
    739     if (mUseSaveProc && m_parent->isLongshotEnabled()) {
    740         qcamera_jpeg_evt_payload_t *saveData = ( qcamera_jpeg_evt_payload_t * ) malloc(sizeof(qcamera_jpeg_evt_payload_t));
    741         if ( NULL == saveData ) {
    742             ALOGE("%s: Can not allocate save data message!", __func__);
    743             return NO_MEMORY;
    744         }
    745         *saveData = *evt;
    746         m_inputSaveQ.enqueue((void *) saveData);
    747         m_saveProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
    748     } else {
    749         // Release jpeg job data
    750         m_ongoingJpegQ.flushNodes(matchJobId, (void*)&evt->jobId);
    751 
    752         CDBG_HIGH("[KPI Perf] %s : jpeg job %d", __func__, evt->jobId);
    753 
    754         if (m_parent->mDataCb == NULL ||
    755             m_parent->msgTypeEnabledWithLock(CAMERA_MSG_COMPRESSED_IMAGE) == 0 ) {
    756             CDBG_HIGH("%s: No dataCB or CAMERA_MSG_COMPRESSED_IMAGE not enabled",
    757                   __func__);
    758             rc = NO_ERROR;
    759             goto end;
    760         }
    761 
    762         if(evt->status == JPEG_JOB_STATUS_ERROR) {
    763             ALOGE("%s: Error event handled from jpeg, status = %d",
    764                   __func__, evt->status);
    765             rc = FAILED_TRANSACTION;
    766             goto end;
    767         }
    768 
    769         m_parent->dumpJpegToFile(evt->out_data.buf_vaddr,
    770                                   evt->out_data.buf_filled_len,
    771                                   evt->jobId);
    772         CDBG_HIGH("%s: Dump jpeg_size=%d", __func__, evt->out_data.buf_filled_len);
    773 
    774         /* check if the all the captures are done */
    775         if (m_parent->mParameters.isUbiRefocus() &&
    776             (m_parent->getOutputImageCount() <
    777             m_parent->mParameters.UfOutputCount())) {
    778             jpeg_out  = (omx_jpeg_ouput_buf_t*) evt->out_data.buf_vaddr;
    779             jpeg_mem = (camera_memory_t *)jpeg_out->mem_hdl;
    780             if (NULL != jpeg_mem) {
    781                 jpeg_mem->release(jpeg_mem);
    782                 jpeg_mem = NULL;
    783             }
    784             goto end;
    785         }
    786 
    787         if (!mJpegMemOpt) {
    788             // alloc jpeg memory to pass to upper layer
    789             jpeg_mem = m_parent->mGetMemory(-1, evt->out_data.buf_filled_len,
    790                 1, m_parent->mCallbackCookie);
    791             if (NULL == jpeg_mem) {
    792                 rc = NO_MEMORY;
    793                 ALOGE("%s : getMemory for jpeg, ret = NO_MEMORY", __func__);
    794                 goto end;
    795             }
    796             memcpy(jpeg_mem->data, evt->out_data.buf_vaddr, evt->out_data.buf_filled_len);
    797         } else {
    798             jpeg_out  = (omx_jpeg_ouput_buf_t*) evt->out_data.buf_vaddr;
    799             jpeg_mem = (camera_memory_t *)jpeg_out->mem_hdl;
    800         }
    801 
    802         CDBG_HIGH("%s : Calling upperlayer callback to store JPEG image", __func__);
    803         qcamera_release_data_t release_data;
    804         memset(&release_data, 0, sizeof(qcamera_release_data_t));
    805         release_data.data = jpeg_mem;
    806         CDBG_HIGH("[KPI Perf] %s: PROFILE_JPEG_CB ",__func__);
    807         rc = sendDataNotify(CAMERA_MSG_COMPRESSED_IMAGE,
    808                             jpeg_mem,
    809                             0,
    810                             NULL,
    811                             &release_data);
    812 
    813 end:
    814         if (rc != NO_ERROR) {
    815             // send error msg to upper layer
    816             sendEvtNotify(CAMERA_MSG_ERROR,
    817                           UNKNOWN_ERROR,
    818                           0);
    819 
    820             if (NULL != jpeg_mem) {
    821                 jpeg_mem->release(jpeg_mem);
    822                 jpeg_mem = NULL;
    823             }
    824         }
    825     }
    826 
    827     // wait up data proc thread to do next job,
    828     // if previous request is blocked due to ongoing jpeg job
    829     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
    830 
    831     return rc;
    832 }
    833 
    834 /*===========================================================================
    835  * FUNCTION   : processPPData
    836  *
    837  * DESCRIPTION: process received frame after reprocess.
    838  *
    839  * PARAMETERS :
    840  *   @frame   : received frame from reprocess channel.
    841  *
    842  * RETURN     : int32_t type of status
    843  *              NO_ERROR  -- success
    844  *              none-zero failure code
    845  *
    846  * NOTE       : The frame after reprocess need to send to jpeg encoding.
    847  *==========================================================================*/
    848 int32_t QCameraPostProcessor::processPPData(mm_camera_super_buf_t *frame)
    849 {
    850     bool needSuperBufMatch = m_parent->mParameters.generateThumbFromMain();
    851     if (m_bInited == FALSE) {
    852         ALOGE("%s: postproc not initialized yet", __func__);
    853         return UNKNOWN_ERROR;
    854     }
    855 
    856     qcamera_pp_data_t *job = (qcamera_pp_data_t *)m_ongoingPPQ.dequeue();
    857 
    858     if (!needSuperBufMatch && (job == NULL || job->src_frame == NULL) ) {
    859         ALOGE("%s: Cannot find reprocess job", __func__);
    860         return BAD_VALUE;
    861     }
    862 
    863     if (!needSuperBufMatch && (m_parent->mParameters.isNV16PictureFormat() ||
    864         m_parent->mParameters.isNV21PictureFormat())) {
    865         releaseSuperBuf(job->src_frame);
    866         free(job->src_frame);
    867         free(job);
    868 
    869         if(m_parent->mParameters.isYUVFrameInfoNeeded())
    870             setYUVFrameInfo(frame);
    871         return processRawData(frame);
    872     }
    873 
    874     if (m_parent->isLongshotEnabled() &&
    875             !m_parent->isCaptureShutterEnabled()) {
    876         // play shutter sound for longshot
    877         // after reprocess is done
    878         // TODO: Move this after CAC done event
    879         m_parent->playShutter();
    880     }
    881 
    882     qcamera_jpeg_data_t *jpeg_job =
    883         (qcamera_jpeg_data_t *)malloc(sizeof(qcamera_jpeg_data_t));
    884     if (jpeg_job == NULL) {
    885         ALOGE("%s: No memory for jpeg job", __func__);
    886         return NO_MEMORY;
    887     }
    888 
    889     memset(jpeg_job, 0, sizeof(qcamera_jpeg_data_t));
    890     jpeg_job->src_frame = frame;
    891     jpeg_job->src_reproc_frame = job ? job->src_frame : NULL;
    892     jpeg_job->src_reproc_bufs = job ? job->src_reproc_bufs : NULL;
    893     jpeg_job->reproc_frame_release = job ? job->reproc_frame_release : false;
    894 
    895     // find meta data frame
    896     mm_camera_buf_def_t *meta_frame = NULL;
    897     for (int i = 0; job && (i < job->src_frame->num_bufs); i++) {
    898         // look through input superbuf
    899         if (job->src_frame->bufs[i]->stream_type == CAM_STREAM_TYPE_METADATA) {
    900             meta_frame = job->src_frame->bufs[i];
    901             break;
    902         }
    903     }
    904 
    905     if (meta_frame == NULL) {
    906         // look through reprocess superbuf
    907         for (int i = 0; i < frame->num_bufs; i++) {
    908             if (frame->bufs[i]->stream_type == CAM_STREAM_TYPE_METADATA) {
    909                 meta_frame = frame->bufs[i];
    910                 break;
    911             }
    912         }
    913     }
    914 
    915     if (meta_frame != NULL) {
    916         // fill in meta data frame ptr
    917         jpeg_job->metadata = (metadata_buffer_t *)meta_frame->buffer;
    918     }
    919 
    920     // free pp job buf
    921     if (job) {
    922         free(job);
    923     }
    924 
    925     // enqueu reprocessed frame to jpeg input queue
    926     m_inputJpegQ.enqueue((void *)jpeg_job);
    927 
    928     ALOGD("%s: %d] ", __func__, __LINE__);
    929     // wait up data proc thread
    930     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
    931 
    932     return NO_ERROR;
    933 }
    934 
    935 /*===========================================================================
    936  * FUNCTION   : findJpegJobByJobId
    937  *
    938  * DESCRIPTION: find a jpeg job from ongoing Jpeg queue by its job ID
    939  *
    940  * PARAMETERS :
    941  *   @jobId   : job Id of the job
    942  *
    943  * RETURN     : ptr to a jpeg job struct. NULL if not found.
    944  *
    945  * NOTE       : Currently only one job is sending to mm-jpeg-interface for jpeg
    946  *              encoding. Therefore simply dequeue from the ongoing Jpeg Queue
    947  *              will serve the purpose to find the jpeg job.
    948  *==========================================================================*/
    949 qcamera_jpeg_data_t *QCameraPostProcessor::findJpegJobByJobId(uint32_t jobId)
    950 {
    951     qcamera_jpeg_data_t * job = NULL;
    952     if (jobId == 0) {
    953         ALOGE("%s: not a valid jpeg jobId", __func__);
    954         return NULL;
    955     }
    956 
    957     // currely only one jpeg job ongoing, so simply dequeue the head
    958     job = (qcamera_jpeg_data_t *)m_ongoingJpegQ.dequeue();
    959     return job;
    960 }
    961 
    962 /*===========================================================================
    963  * FUNCTION   : releasePPInputData
    964  *
    965  * DESCRIPTION: callback function to release post process input data node
    966  *
    967  * PARAMETERS :
    968  *   @data      : ptr to post process input data
    969  *   @user_data : user data ptr (QCameraReprocessor)
    970  *
    971  * RETURN     : None
    972  *==========================================================================*/
    973 void QCameraPostProcessor::releasePPInputData(void *data, void *user_data)
    974 {
    975     QCameraPostProcessor *pme = (QCameraPostProcessor *)user_data;
    976     if (NULL != pme) {
    977         pme->releaseSuperBuf((mm_camera_super_buf_t *)data);
    978     }
    979 }
    980 
    981 /*===========================================================================
    982  * FUNCTION   : releaseJpegData
    983  *
    984  * DESCRIPTION: callback function to release jpeg job node
    985  *
    986  * PARAMETERS :
    987  *   @data      : ptr to ongoing jpeg job data
    988  *   @user_data : user data ptr (QCameraReprocessor)
    989  *
    990  * RETURN     : None
    991  *==========================================================================*/
    992 void QCameraPostProcessor::releaseJpegData(void *data, void *user_data)
    993 {
    994     QCameraPostProcessor *pme = (QCameraPostProcessor *)user_data;
    995     if (NULL != pme) {
    996         pme->releaseJpegJobData((qcamera_jpeg_data_t *)data);
    997         CDBG_HIGH("%s : Rleased job ID %u", __func__,
    998             ((qcamera_jpeg_data_t *)data)->jobId);
    999     }
   1000 }
   1001 
   1002 /*===========================================================================
   1003  * FUNCTION   : releaseOngoingPPData
   1004  *
   1005  * DESCRIPTION: callback function to release ongoing postprocess job node
   1006  *
   1007  * PARAMETERS :
   1008  *   @data      : ptr to onging postprocess job
   1009  *   @user_data : user data ptr (QCameraReprocessor)
   1010  *
   1011  * RETURN     : None
   1012  *==========================================================================*/
   1013 void QCameraPostProcessor::releaseOngoingPPData(void *data, void *user_data)
   1014 {
   1015     QCameraPostProcessor *pme = (QCameraPostProcessor *)user_data;
   1016     if (NULL != pme) {
   1017         qcamera_pp_data_t *pp_job = (qcamera_pp_data_t *)data;
   1018         if (NULL != pp_job->src_frame) {
   1019             if (!pp_job->reproc_frame_release) {
   1020                 pme->releaseSuperBuf(pp_job->src_frame);
   1021             }
   1022             free(pp_job->src_frame);
   1023             pp_job->src_frame = NULL;
   1024         }
   1025     }
   1026 }
   1027 
   1028 /*===========================================================================
   1029  * FUNCTION   : releaseNotifyData
   1030  *
   1031  * DESCRIPTION: function to release internal resources in notify data struct
   1032  *
   1033  * PARAMETERS :
   1034  *   @user_data  : ptr user data
   1035  *   @cookie     : callback cookie
   1036  *   @cb_status  : callback status
   1037  *
   1038  * RETURN     : None
   1039  *
   1040  * NOTE       : deallocate jpeg heap memory if it's not NULL
   1041  *==========================================================================*/
   1042 void QCameraPostProcessor::releaseNotifyData(void *user_data,
   1043                                              void *cookie,
   1044                                              int32_t cb_status)
   1045 {
   1046     qcamera_data_argm_t *app_cb = ( qcamera_data_argm_t * ) user_data;
   1047     QCameraPostProcessor *postProc = ( QCameraPostProcessor * ) cookie;
   1048     if ( ( NULL != app_cb ) && ( NULL != postProc ) ) {
   1049 
   1050         if ( postProc->mUseSaveProc &&
   1051              app_cb->release_data.unlinkFile &&
   1052              ( NO_ERROR != cb_status ) ) {
   1053 
   1054             String8 unlinkPath((const char *) app_cb->release_data.data->data,
   1055                                 app_cb->release_data.data->size);
   1056             int rc = unlink(unlinkPath.string());
   1057             CDBG_HIGH("%s : Unlinking stored file rc = %d",
   1058                   __func__,
   1059                   rc);
   1060         }
   1061 
   1062         if (app_cb && NULL != app_cb->release_data.data) {
   1063             app_cb->release_data.data->release(app_cb->release_data.data);
   1064             app_cb->release_data.data = NULL;
   1065         }
   1066         if (app_cb && NULL != app_cb->release_data.frame) {
   1067             postProc->releaseSuperBuf(app_cb->release_data.frame);
   1068             free(app_cb->release_data.frame);
   1069             app_cb->release_data.frame = NULL;
   1070         }
   1071         if (app_cb && NULL != app_cb->release_data.streamBufs) {
   1072             app_cb->release_data.streamBufs->deallocate();
   1073             delete app_cb->release_data.streamBufs;
   1074             app_cb->release_data.streamBufs = NULL;
   1075         }
   1076         free(app_cb);
   1077     }
   1078 }
   1079 
   1080 /*===========================================================================
   1081  * FUNCTION   : releaseSuperBuf
   1082  *
   1083  * DESCRIPTION: function to release a superbuf frame by returning back to kernel
   1084  *
   1085  * PARAMETERS :
   1086  *   @super_buf : ptr to the superbuf frame
   1087  *
   1088  * RETURN     : None
   1089  *==========================================================================*/
   1090 void QCameraPostProcessor::releaseSuperBuf(mm_camera_super_buf_t *super_buf)
   1091 {
   1092     QCameraChannel *pChannel = NULL;
   1093 
   1094     if (NULL != super_buf) {
   1095         pChannel = m_parent->getChannelByHandle(super_buf->ch_id);
   1096 
   1097         if ( NULL == pChannel ) {
   1098             if (m_pReprocChannel != NULL &&
   1099                 m_pReprocChannel->getMyHandle() == super_buf->ch_id) {
   1100                 pChannel = m_pReprocChannel;
   1101             }
   1102         }
   1103 
   1104         if (pChannel != NULL) {
   1105             pChannel->bufDone(super_buf);
   1106         } else {
   1107             ALOGE(" %s : Channel id %d not found!!",
   1108                   __func__,
   1109                   super_buf->ch_id);
   1110         }
   1111     }
   1112 }
   1113 
   1114 /*===========================================================================
   1115  * FUNCTION   : releaseJpegJobData
   1116  *
   1117  * DESCRIPTION: function to release internal resources in jpeg job struct
   1118  *
   1119  * PARAMETERS :
   1120  *   @job     : ptr to jpeg job struct
   1121  *
   1122  * RETURN     : None
   1123  *
   1124  * NOTE       : original source frame need to be queued back to kernel for
   1125  *              future use. Output buf of jpeg job need to be released since
   1126  *              it's allocated for each job. Exif object need to be deleted.
   1127  *==========================================================================*/
   1128 void QCameraPostProcessor::releaseJpegJobData(qcamera_jpeg_data_t *job)
   1129 {
   1130     CDBG("%s: E", __func__);
   1131     if (NULL != job) {
   1132         if (NULL != job->src_reproc_frame) {
   1133             if (!job->reproc_frame_release) {
   1134                 releaseSuperBuf(job->src_reproc_frame);
   1135             }
   1136             free(job->src_reproc_frame);
   1137             job->src_reproc_frame = NULL;
   1138         }
   1139 
   1140         if (NULL != job->src_frame) {
   1141             releaseSuperBuf(job->src_frame);
   1142             free(job->src_frame);
   1143             job->src_frame = NULL;
   1144         }
   1145 
   1146         if (NULL != job->pJpegExifObj) {
   1147             delete job->pJpegExifObj;
   1148             job->pJpegExifObj = NULL;
   1149         }
   1150 
   1151         if (NULL != job->src_reproc_bufs) {
   1152             delete [] job->src_reproc_bufs;
   1153         }
   1154 
   1155     }
   1156     CDBG("%s: X", __func__);
   1157 }
   1158 
   1159 /*===========================================================================
   1160  * FUNCTION   : releaseSaveJobData
   1161  *
   1162  * DESCRIPTION: function to release internal resources in store jobs
   1163  *
   1164  * PARAMETERS :
   1165  *   @job     : ptr to save job struct
   1166  *
   1167  * RETURN     : None
   1168  *
   1169  *==========================================================================*/
   1170 void QCameraPostProcessor::releaseSaveJobData(void *data, void *user_data)
   1171 {
   1172     CDBG("%s: E", __func__);
   1173 
   1174     QCameraPostProcessor *pme = (QCameraPostProcessor *) user_data;
   1175     if (NULL == pme) {
   1176         ALOGE("%s: Invalid postproc handle", __func__);
   1177         return;
   1178     }
   1179 
   1180     qcamera_jpeg_evt_payload_t *job_data = (qcamera_jpeg_evt_payload_t *) data;
   1181     if (job_data == NULL) {
   1182         ALOGE("%s: Invalid jpeg event data", __func__);
   1183         return;
   1184     }
   1185 
   1186     // find job by jobId
   1187     qcamera_jpeg_data_t *job = pme->findJpegJobByJobId(job_data->jobId);
   1188 
   1189     if (NULL != job) {
   1190         pme->releaseJpegJobData(job);
   1191         free(job);
   1192     } else {
   1193         ALOGE("%s : Invalid jpeg job", __func__);
   1194     }
   1195 
   1196     CDBG("%s: X", __func__);
   1197 }
   1198 
   1199 /*===========================================================================
   1200  * FUNCTION   : releaseRawData
   1201  *
   1202  * DESCRIPTION: function to release internal resources in store jobs
   1203  *
   1204  * PARAMETERS :
   1205  *   @job     : ptr to save job struct
   1206  *
   1207  * RETURN     : None
   1208  *
   1209  *==========================================================================*/
   1210 void QCameraPostProcessor::releaseRawData(void *data, void *user_data)
   1211 {
   1212     CDBG("%s: E", __func__);
   1213 
   1214     QCameraPostProcessor *pme = (QCameraPostProcessor *) user_data;
   1215     if (NULL == pme) {
   1216         ALOGE("%s: Invalid postproc handle", __func__);
   1217         return;
   1218     }
   1219     mm_camera_super_buf_t *super_buf = (mm_camera_super_buf_t *) data;
   1220     pme->releaseSuperBuf(super_buf);
   1221 
   1222     CDBG("%s: X", __func__);
   1223 }
   1224 
   1225 
   1226 /*===========================================================================
   1227  * FUNCTION   : getColorfmtFromImgFmt
   1228  *
   1229  * DESCRIPTION: function to return jpeg color format based on its image format
   1230  *
   1231  * PARAMETERS :
   1232  *   @img_fmt : image format
   1233  *
   1234  * RETURN     : jpeg color format that can be understandable by omx lib
   1235  *==========================================================================*/
   1236 mm_jpeg_color_format QCameraPostProcessor::getColorfmtFromImgFmt(cam_format_t img_fmt)
   1237 {
   1238     switch (img_fmt) {
   1239     case CAM_FORMAT_YUV_420_NV21:
   1240         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
   1241     case CAM_FORMAT_YUV_420_NV21_ADRENO:
   1242         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
   1243     case CAM_FORMAT_YUV_420_NV12:
   1244         return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2;
   1245     case CAM_FORMAT_YUV_420_YV12:
   1246         return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2;
   1247     case CAM_FORMAT_YUV_422_NV61:
   1248         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V1;
   1249     case CAM_FORMAT_YUV_422_NV16:
   1250         return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V1;
   1251     default:
   1252         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
   1253     }
   1254 }
   1255 
   1256 /*===========================================================================
   1257  * FUNCTION   : getJpegImgTypeFromImgFmt
   1258  *
   1259  * DESCRIPTION: function to return jpeg encode image type based on its image format
   1260  *
   1261  * PARAMETERS :
   1262  *   @img_fmt : image format
   1263  *
   1264  * RETURN     : return jpeg source image format (YUV or Bitstream)
   1265  *==========================================================================*/
   1266 mm_jpeg_format_t QCameraPostProcessor::getJpegImgTypeFromImgFmt(cam_format_t img_fmt)
   1267 {
   1268     switch (img_fmt) {
   1269     case CAM_FORMAT_YUV_420_NV21:
   1270     case CAM_FORMAT_YUV_420_NV21_ADRENO:
   1271     case CAM_FORMAT_YUV_420_NV12:
   1272     case CAM_FORMAT_YUV_420_YV12:
   1273     case CAM_FORMAT_YUV_422_NV61:
   1274     case CAM_FORMAT_YUV_422_NV16:
   1275         return MM_JPEG_FMT_YUV;
   1276     default:
   1277         return MM_JPEG_FMT_YUV;
   1278     }
   1279 }
   1280 
   1281 /*===========================================================================
   1282  * FUNCTION   : queryStreams
   1283  *
   1284  * DESCRIPTION: utility method for retrieving main, thumbnail and reprocess
   1285  *              streams and frame from bundled super buffer
   1286  *
   1287  * PARAMETERS :
   1288  *   @main    : ptr to main stream if present
   1289  *   @thumb   : ptr to thumbnail stream if present
   1290  *   @reproc  : ptr to reprocess stream if present
   1291  *   @main_image : ptr to main image if present
   1292  *   @thumb_image: ptr to thumbnail image if present
   1293  *   @frame   : bundled super buffer
   1294  *   @reproc_frame : bundled source frame buffer
   1295  *
   1296  * RETURN     : int32_t type of status
   1297  *              NO_ERROR  -- success
   1298  *              none-zero failure code
   1299  *==========================================================================*/
   1300 int32_t QCameraPostProcessor::queryStreams(QCameraStream **main,
   1301         QCameraStream **thumb,
   1302         QCameraStream **reproc,
   1303         mm_camera_buf_def_t **main_image,
   1304         mm_camera_buf_def_t **thumb_image,
   1305         mm_camera_super_buf_t *frame,
   1306         mm_camera_super_buf_t *reproc_frame)
   1307 {
   1308     if (NULL == frame) {
   1309         return NO_INIT;
   1310     }
   1311 
   1312     QCameraChannel *pChannel = m_parent->getChannelByHandle(frame->ch_id);
   1313     // check reprocess channel if not found
   1314     if (pChannel == NULL) {
   1315         if (m_pReprocChannel != NULL &&
   1316             m_pReprocChannel->getMyHandle() == frame->ch_id) {
   1317             pChannel = m_pReprocChannel;
   1318         }
   1319     }
   1320     if (pChannel == NULL) {
   1321         ALOGD("%s: No corresponding channel (ch_id = %d) exist, return here",
   1322               __func__, frame->ch_id);
   1323         return BAD_VALUE;
   1324     }
   1325 
   1326     // Use snapshot stream to create thumbnail if snapshot and preview
   1327     // flip settings doesn't match in ZSL mode.
   1328     bool thumb_stream_needed = !m_parent->isZSLMode() ||
   1329         (m_parent->mParameters.getFlipMode(CAM_STREAM_TYPE_SNAPSHOT) ==
   1330          m_parent->mParameters.getFlipMode(CAM_STREAM_TYPE_PREVIEW));
   1331 
   1332     *main = *thumb = *reproc = NULL;
   1333     *main_image = *thumb_image = NULL;
   1334     // find snapshot frame and thumnail frame
   1335     for (int i = 0; i < frame->num_bufs; i++) {
   1336         QCameraStream *pStream =
   1337                 pChannel->getStreamByHandle(frame->bufs[i]->stream_id);
   1338         if (pStream != NULL) {
   1339             if (pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
   1340                 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT)) {
   1341                 *main= pStream;
   1342                 *main_image = frame->bufs[i];
   1343             } else if (thumb_stream_needed &&
   1344                        (pStream->isTypeOf(CAM_STREAM_TYPE_PREVIEW) ||
   1345                         pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) ||
   1346                         pStream->isOrignalTypeOf(CAM_STREAM_TYPE_PREVIEW) ||
   1347                         pStream->isOrignalTypeOf(CAM_STREAM_TYPE_POSTVIEW))) {
   1348                 *thumb = pStream;
   1349                 *thumb_image = frame->bufs[i];
   1350             }
   1351             if (pStream->isTypeOf(CAM_STREAM_TYPE_OFFLINE_PROC) ) {
   1352                 *reproc = pStream;
   1353             }
   1354         }
   1355     }
   1356 
   1357     if (thumb_stream_needed && *thumb_image == NULL && reproc_frame != NULL) {
   1358         QCameraChannel *pSrcReprocChannel = NULL;
   1359         pSrcReprocChannel = m_parent->getChannelByHandle(reproc_frame->ch_id);
   1360         if (pSrcReprocChannel != NULL) {
   1361             // find thumbnail frame
   1362             for (int i = 0; i < reproc_frame->num_bufs; i++) {
   1363                 QCameraStream *pStream =
   1364                         pSrcReprocChannel->getStreamByHandle(
   1365                                 reproc_frame->bufs[i]->stream_id);
   1366                 if (pStream != NULL) {
   1367                     if (pStream->isTypeOf(CAM_STREAM_TYPE_PREVIEW) ||
   1368                         pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW)) {
   1369                         *thumb = pStream;
   1370                         *thumb_image = reproc_frame->bufs[i];
   1371                     }
   1372                 }
   1373             }
   1374         }
   1375     }
   1376 
   1377     if (m_parent->mParameters.generateThumbFromMain()) {
   1378         *thumb = NULL;
   1379         *thumb_image = NULL;
   1380     }
   1381 
   1382     return NO_ERROR;
   1383 }
   1384 
   1385 /*===========================================================================
   1386 * FUNCTION   : syncStreamParams
   1387 *
   1388 * DESCRIPTION: Query the runtime parameters of all streams included
   1389 *              in the main and reprocessed frames
   1390 *
   1391 * PARAMETERS :
   1392 *   @frame : Main image super buffer
   1393 *   @reproc_frame : Image supper buffer that got processed
   1394 *
   1395 * RETURN     : int32_t type of status
   1396 *              NO_ERROR  -- success
   1397 *              none-zero failure code
   1398 *==========================================================================*/
   1399 int32_t QCameraPostProcessor::syncStreamParams(mm_camera_super_buf_t *frame,
   1400         mm_camera_super_buf_t *reproc_frame)
   1401 {
   1402     QCameraStream *reproc_stream = NULL;
   1403     QCameraStream *main_stream = NULL;
   1404     QCameraStream *thumb_stream = NULL;
   1405     mm_camera_buf_def_t *main_frame = NULL;
   1406     mm_camera_buf_def_t *thumb_frame = NULL;
   1407     int32_t ret = NO_ERROR;
   1408 
   1409     ret = queryStreams(&main_stream,
   1410             &thumb_stream,
   1411             &reproc_stream,
   1412             &main_frame,
   1413             &thumb_frame,
   1414             frame,
   1415             reproc_frame);
   1416     if (NO_ERROR != ret) {
   1417         ALOGE("%s : Camera streams query from input frames failed %d",
   1418                 __func__,
   1419                 ret);
   1420         return ret;
   1421     }
   1422 
   1423     if (NULL != main_stream) {
   1424         ret = main_stream->syncRuntimeParams();
   1425         if (NO_ERROR != ret) {
   1426             ALOGE("%s : Syncing of main stream runtime parameters failed %d",
   1427                     __func__,
   1428                     ret);
   1429             return ret;
   1430         }
   1431     }
   1432 
   1433     if (NULL != thumb_stream) {
   1434         ret = thumb_stream->syncRuntimeParams();
   1435         if (NO_ERROR != ret) {
   1436             ALOGE("%s : Syncing of thumb stream runtime parameters failed %d",
   1437                     __func__,
   1438                     ret);
   1439             return ret;
   1440         }
   1441     }
   1442 
   1443     if ((NULL != reproc_stream) && (reproc_stream != main_stream)) {
   1444         ret = reproc_stream->syncRuntimeParams();
   1445         if (NO_ERROR != ret) {
   1446             ALOGE("%s : Syncing of reproc stream runtime parameters failed %d",
   1447                     __func__,
   1448                     ret);
   1449             return ret;
   1450         }
   1451     }
   1452 
   1453     return ret;
   1454 }
   1455 
   1456 /*===========================================================================
   1457  * FUNCTION   : encodeData
   1458  *
   1459  * DESCRIPTION: function to prepare encoding job information and send to
   1460  *              mm-jpeg-interface to do the encoding job
   1461  *
   1462  * PARAMETERS :
   1463  *   @jpeg_job_data : ptr to a struct saving job related information
   1464  *   @needNewSess   : flag to indicate if a new jpeg encoding session need
   1465  *                    to be created. After creation, this flag will be toggled
   1466  *
   1467  * RETURN     : int32_t type of status
   1468  *              NO_ERROR  -- success
   1469  *              none-zero failure code
   1470  *==========================================================================*/
   1471 int32_t QCameraPostProcessor::encodeData(qcamera_jpeg_data_t *jpeg_job_data,
   1472                                          uint8_t &needNewSess)
   1473 {
   1474     CDBG("%s : E", __func__);
   1475     int32_t ret = NO_ERROR;
   1476     mm_jpeg_job_t jpg_job;
   1477     uint32_t jobId = 0;
   1478     QCameraStream *reproc_stream = NULL;
   1479     QCameraStream *main_stream = NULL;
   1480     mm_camera_buf_def_t *main_frame = NULL;
   1481     QCameraStream *thumb_stream = NULL;
   1482     mm_camera_buf_def_t *thumb_frame = NULL;
   1483     mm_camera_super_buf_t *recvd_frame = jpeg_job_data->src_frame;
   1484     cam_rect_t crop;
   1485     cam_stream_parm_buffer_t param;
   1486     cam_stream_img_prop_t imgProp;
   1487 
   1488     // find channel
   1489     QCameraChannel *pChannel = m_parent->getChannelByHandle(recvd_frame->ch_id);
   1490     // check reprocess channel if not found
   1491     if (pChannel == NULL) {
   1492         if (m_pReprocChannel != NULL &&
   1493             m_pReprocChannel->getMyHandle() == recvd_frame->ch_id) {
   1494             pChannel = m_pReprocChannel;
   1495         }
   1496     }
   1497 
   1498     if (pChannel == NULL) {
   1499         ALOGE("%s:%d] No corresponding channel (ch_id = %d) exist, return here",
   1500               __func__, __LINE__, recvd_frame->ch_id);
   1501         return BAD_VALUE;
   1502     }
   1503 
   1504     const int jpeg_rotation = m_parent->getJpegRotation();
   1505 
   1506     ret = queryStreams(&main_stream,
   1507             &thumb_stream,
   1508             &reproc_stream,
   1509             &main_frame,
   1510             &thumb_frame,
   1511             recvd_frame,
   1512             jpeg_job_data->src_reproc_frame);
   1513     if (NO_ERROR != ret) {
   1514         return ret;
   1515     }
   1516 
   1517     if(NULL == main_frame){
   1518        ALOGE("%s : Main frame is NULL", __func__);
   1519        return BAD_VALUE;
   1520     }
   1521 
   1522     if(NULL == thumb_frame){
   1523        CDBG("%s : Thumbnail frame does not exist", __func__);
   1524     }
   1525 
   1526     QCameraMemory *memObj = (QCameraMemory *)main_frame->mem_info;
   1527     if (NULL == memObj) {
   1528         ALOGE("%s : Memeory Obj of main frame is NULL", __func__);
   1529         return NO_MEMORY;
   1530     }
   1531 
   1532     // dump snapshot frame if enabled
   1533     m_parent->dumpFrameToFile(main_stream, main_frame, QCAMERA_DUMP_FRM_SNAPSHOT);
   1534 
   1535     // send upperlayer callback for raw image
   1536     camera_memory_t *mem = memObj->getMemory(main_frame->buf_idx, false);
   1537     if (NULL != m_parent->mDataCb &&
   1538         m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE) > 0) {
   1539         qcamera_callback_argm_t cbArg;
   1540         memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
   1541         cbArg.cb_type = QCAMERA_DATA_CALLBACK;
   1542         cbArg.msg_type = CAMERA_MSG_RAW_IMAGE;
   1543         cbArg.data = mem;
   1544         cbArg.index = 1;
   1545         m_parent->m_cbNotifier.notifyCallback(cbArg);
   1546     }
   1547     if (NULL != m_parent->mNotifyCb &&
   1548         m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE_NOTIFY) > 0) {
   1549         qcamera_callback_argm_t cbArg;
   1550         memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
   1551         cbArg.cb_type = QCAMERA_NOTIFY_CALLBACK;
   1552         cbArg.msg_type = CAMERA_MSG_RAW_IMAGE_NOTIFY;
   1553         cbArg.ext1 = 0;
   1554         cbArg.ext2 = 0;
   1555         m_parent->m_cbNotifier.notifyCallback(cbArg);
   1556     }
   1557 
   1558     if (thumb_frame != NULL) {
   1559         // dump thumbnail frame if enabled
   1560         m_parent->dumpFrameToFile(thumb_stream, thumb_frame, QCAMERA_DUMP_FRM_THUMBNAIL);
   1561     }
   1562 
   1563     if (mJpegClientHandle <= 0) {
   1564         ALOGE("%s: Error: bug here, mJpegClientHandle is 0", __func__);
   1565         return UNKNOWN_ERROR;
   1566     }
   1567 
   1568     if (needNewSess) {
   1569         // create jpeg encoding session
   1570         mm_jpeg_encode_params_t encodeParam;
   1571         memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t));
   1572         getJpegEncodingConfig(encodeParam, main_stream, thumb_stream);
   1573         CDBG_HIGH("[KPI Perf] %s : call jpeg create_session", __func__);
   1574         ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId);
   1575         if (ret != NO_ERROR) {
   1576             ALOGE("%s: error creating a new jpeg encoding session", __func__);
   1577             return ret;
   1578         }
   1579         needNewSess = FALSE;
   1580     }
   1581     // Fill in new job
   1582     memset(&jpg_job, 0, sizeof(mm_jpeg_job_t));
   1583     jpg_job.job_type = JPEG_JOB_TYPE_ENCODE;
   1584     jpg_job.encode_job.session_id = mJpegSessionId;
   1585     jpg_job.encode_job.src_index = main_frame->buf_idx;
   1586     jpg_job.encode_job.dst_index = 0;
   1587 
   1588     if (mJpegMemOpt) {
   1589         jpg_job.encode_job.dst_index = jpg_job.encode_job.src_index;
   1590     } else if (mUseJpegBurst) {
   1591         jpg_job.encode_job.dst_index = -1;
   1592     }
   1593 
   1594     cam_dimension_t src_dim;
   1595     memset(&src_dim, 0, sizeof(cam_dimension_t));
   1596     main_stream->getFrameDimension(src_dim);
   1597 
   1598     bool hdr_output_crop = m_parent->mParameters.isHDROutputCropEnabled();
   1599     bool img_feature_enabled =
   1600       m_parent->mParameters.isUbiFocusEnabled() ||
   1601       m_parent->mParameters.isChromaFlashEnabled() ||
   1602       m_parent->mParameters.isOptiZoomEnabled();
   1603 
   1604     CDBG_HIGH("%s:%d] Crop needed %d", __func__, __LINE__, img_feature_enabled);
   1605     crop.left = 0;
   1606     crop.top = 0;
   1607     crop.height = src_dim.height;
   1608     crop.width = src_dim.width;
   1609 
   1610     param = main_stream->getOutputCrop();
   1611     for (int i = 0; i < param.outputCrop.num_of_streams; i++) {
   1612        if (param.outputCrop.crop_info[i].stream_id
   1613            == main_stream->getMyServerID()) {
   1614                crop = param.outputCrop.crop_info[i].crop;
   1615                main_stream->setCropInfo(crop);
   1616        }
   1617     }
   1618     if (img_feature_enabled) {
   1619         memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
   1620 
   1621         param = main_stream->getImgProp();
   1622         imgProp = param.imgProp;
   1623         main_stream->setCropInfo(imgProp.crop);
   1624         crop = imgProp.crop;
   1625         thumb_stream = NULL; /* use thumbnail from main image */
   1626         if (imgProp.is_raw_image) {
   1627            camera_memory_t *mem = memObj->getMemory(
   1628                main_frame->buf_idx, false);
   1629            ALOGE("%s:%d] Process raw image %p %d", __func__, __LINE__,
   1630                mem, imgProp.size);
   1631            /* dump image */
   1632            if (mem && mem->data) {
   1633                CAM_DUMP_TO_FILE("/data/local/ubifocus", "DepthMapImage",
   1634                                 -1, "y",
   1635                                 (uint8_t *)mem->data,
   1636                                 imgProp.size);
   1637            }
   1638            return NO_ERROR;
   1639         }
   1640     }
   1641 
   1642     cam_dimension_t dst_dim;
   1643 
   1644     if (hdr_output_crop && crop.height) {
   1645         dst_dim.height = crop.height;
   1646     } else {
   1647         dst_dim.height = src_dim.height;
   1648     }
   1649     if (hdr_output_crop && crop.width) {
   1650         dst_dim.width = crop.width;
   1651     } else {
   1652         dst_dim.width = src_dim.width;
   1653     }
   1654 
   1655     // main dim
   1656     jpg_job.encode_job.main_dim.src_dim = src_dim;
   1657     jpg_job.encode_job.main_dim.dst_dim = dst_dim;
   1658     jpg_job.encode_job.main_dim.crop = crop;
   1659 
   1660     // get exif data
   1661     QCameraExif *pJpegExifObj = m_parent->getExifData();
   1662     jpeg_job_data->pJpegExifObj = pJpegExifObj;
   1663     if (pJpegExifObj != NULL) {
   1664         jpg_job.encode_job.exif_info.exif_data = pJpegExifObj->getEntries();
   1665         jpg_job.encode_job.exif_info.numOfEntries =
   1666             pJpegExifObj->getNumOfEntries();
   1667     }
   1668 
   1669     // set rotation only when no online rotation or offline pp rotation is done before
   1670     if (!m_parent->needRotationReprocess()) {
   1671         jpg_job.encode_job.rotation = jpeg_rotation;
   1672     }
   1673     CDBG_HIGH("%s: jpeg rotation is set to %d", __func__, jpg_job.encode_job.rotation);
   1674 
   1675     // thumbnail dim
   1676     if (m_bThumbnailNeeded == TRUE) {
   1677         m_parent->getThumbnailSize(jpg_job.encode_job.thumb_dim.dst_dim);
   1678 
   1679         if (thumb_stream == NULL) {
   1680             // need jpeg thumbnail, but no postview/preview stream exists
   1681             // we use the main stream/frame to encode thumbnail
   1682             thumb_stream = main_stream;
   1683             thumb_frame = main_frame;
   1684             if (m_parent->needRotationReprocess() &&
   1685                 ((90 == jpeg_rotation) || (270 == jpeg_rotation))) {
   1686                 // swap thumbnail dimensions
   1687                 cam_dimension_t tmp_dim = jpg_job.encode_job.thumb_dim.dst_dim;
   1688                 jpg_job.encode_job.thumb_dim.dst_dim.width = tmp_dim.height;
   1689                 jpg_job.encode_job.thumb_dim.dst_dim.height = tmp_dim.width;
   1690             }
   1691         }
   1692 
   1693         memset(&src_dim, 0, sizeof(cam_dimension_t));
   1694         thumb_stream->getFrameDimension(src_dim);
   1695         jpg_job.encode_job.thumb_dim.src_dim = src_dim;
   1696 
   1697         // crop is the same if frame is the same
   1698         if (thumb_frame != main_frame) {
   1699             crop.left = 0;
   1700             crop.top = 0;
   1701             crop.height = src_dim.height;
   1702             crop.width = src_dim.width;
   1703 
   1704             param = thumb_stream->getOutputCrop();
   1705             for (int i = 0; i < param.outputCrop.num_of_streams; i++) {
   1706                if (param.outputCrop.crop_info[i].stream_id
   1707                    == thumb_stream->getMyServerID()) {
   1708                        crop = param.outputCrop.crop_info[i].crop;
   1709                        thumb_stream->setCropInfo(crop);
   1710                }
   1711            }
   1712         }
   1713 
   1714         jpg_job.encode_job.thumb_dim.crop = crop;
   1715         jpg_job.encode_job.thumb_index = thumb_frame->buf_idx;
   1716         CDBG_HIGH("%s, thumbnail src w/h (%dx%d), dst w/h (%dx%d)", __func__,
   1717             jpg_job.encode_job.thumb_dim.src_dim.width,
   1718             jpg_job.encode_job.thumb_dim.src_dim.height,
   1719             jpg_job.encode_job.thumb_dim.dst_dim.width,
   1720             jpg_job.encode_job.thumb_dim.dst_dim.height);
   1721     }
   1722 
   1723     if (jpeg_job_data->metadata != NULL) {
   1724         // fill in meta data frame ptr
   1725         jpg_job.encode_job.p_metadata = jpeg_job_data->metadata;
   1726     }
   1727 
   1728     jpg_job.encode_job.hal_version = CAM_HAL_V1;
   1729     jpg_job.encode_job.cam_exif_params = m_parent->mExifParams;
   1730 
   1731     /* Init the QTable */
   1732     for (int i = 0; i < QTABLE_MAX; i++) {
   1733         jpg_job.encode_job.qtable_set[i] = 0;
   1734     }
   1735 
   1736     CDBG_HIGH("[KPI Perf] %s : PROFILE_JPEG_JOB_START", __func__);
   1737     ret = mJpegHandle.start_job(&jpg_job, &jobId);
   1738     if (ret == NO_ERROR) {
   1739         // remember job info
   1740         jpeg_job_data->jobId = jobId;
   1741     }
   1742 
   1743     return ret;
   1744 }
   1745 
   1746 /*===========================================================================
   1747  * FUNCTION   : processRawImageImpl
   1748  *
   1749  * DESCRIPTION: function to send raw image to upper layer
   1750  *
   1751  * PARAMETERS :
   1752  *   @recvd_frame   : frame to be encoded
   1753  *
   1754  * RETURN     : int32_t type of status
   1755  *              NO_ERROR  -- success
   1756  *              none-zero failure code
   1757  *==========================================================================*/
   1758 int32_t QCameraPostProcessor::processRawImageImpl(mm_camera_super_buf_t *recvd_frame)
   1759 {
   1760     int32_t rc = NO_ERROR;
   1761 
   1762     QCameraChannel *pChannel = m_parent->getChannelByHandle(recvd_frame->ch_id);
   1763     QCameraStream *pStream = NULL;
   1764     mm_camera_buf_def_t *frame = NULL;
   1765     // check reprocess channel if not found
   1766     if (pChannel == NULL) {
   1767         if (m_pReprocChannel != NULL &&
   1768             m_pReprocChannel->getMyHandle() == recvd_frame->ch_id) {
   1769             pChannel = m_pReprocChannel;
   1770         }
   1771     }
   1772     if (pChannel == NULL) {
   1773         ALOGE("%s:%d] No corresponding channel (ch_id = %d) exist, return here",
   1774               __func__, __LINE__, recvd_frame->ch_id);
   1775         return BAD_VALUE;
   1776     }
   1777 
   1778     // find snapshot frame
   1779     for (int i = 0; i < recvd_frame->num_bufs; i++) {
   1780         QCameraStream *pCurStream =
   1781             pChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id);
   1782         if (pCurStream != NULL) {
   1783             if (pCurStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
   1784                 pCurStream->isTypeOf(CAM_STREAM_TYPE_RAW) ||
   1785                 pCurStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
   1786                 pCurStream->isOrignalTypeOf(CAM_STREAM_TYPE_RAW)) {
   1787                 pStream = pCurStream;
   1788                 frame = recvd_frame->bufs[i];
   1789                 break;
   1790             }
   1791         }
   1792     }
   1793 
   1794     if ( NULL == frame ) {
   1795         ALOGE("%s: No valid raw buffer", __func__);
   1796         return BAD_VALUE;
   1797     }
   1798 
   1799     QCameraMemory *rawMemObj = (QCameraMemory *)frame->mem_info;
   1800     bool zslChannelUsed = m_parent->isZSLMode() &&
   1801             ( pChannel != m_pReprocChannel );
   1802     camera_memory_t *raw_mem = NULL;
   1803 
   1804     if (rawMemObj != NULL) {
   1805         if (zslChannelUsed) {
   1806             raw_mem = rawMemObj->getMemory(frame->buf_idx, false);
   1807         } else {
   1808             raw_mem = m_parent->mGetMemory(-1,
   1809                                            frame->frame_len,
   1810                                            1,
   1811                                            m_parent->mCallbackCookie);
   1812             if (NULL == raw_mem) {
   1813                 ALOGE("%s : Not enough memory for RAW cb ", __func__);
   1814                 return NO_MEMORY;
   1815             }
   1816             memcpy(raw_mem->data, frame->buffer, frame->frame_len);
   1817         }
   1818     }
   1819 
   1820     if (NULL != rawMemObj && NULL != raw_mem) {
   1821         // dump frame into file
   1822         if (frame->stream_type == CAM_STREAM_TYPE_SNAPSHOT ||
   1823             pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT)) {
   1824             // for YUV422 NV16 case
   1825             m_parent->dumpFrameToFile(pStream, frame, QCAMERA_DUMP_FRM_SNAPSHOT);
   1826         } else {
   1827             m_parent->dumpFrameToFile(pStream, frame, QCAMERA_DUMP_FRM_RAW);
   1828         }
   1829 
   1830         // send data callback / notify for RAW_IMAGE
   1831         if (NULL != m_parent->mDataCb &&
   1832             m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE) > 0) {
   1833             qcamera_callback_argm_t cbArg;
   1834             memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
   1835             cbArg.cb_type = QCAMERA_DATA_CALLBACK;
   1836             cbArg.msg_type = CAMERA_MSG_RAW_IMAGE;
   1837             cbArg.data = raw_mem;
   1838             cbArg.index = 0;
   1839             m_parent->m_cbNotifier.notifyCallback(cbArg);
   1840         }
   1841         if (NULL != m_parent->mNotifyCb &&
   1842             m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE_NOTIFY) > 0) {
   1843             qcamera_callback_argm_t cbArg;
   1844             memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
   1845             cbArg.cb_type = QCAMERA_NOTIFY_CALLBACK;
   1846             cbArg.msg_type = CAMERA_MSG_RAW_IMAGE_NOTIFY;
   1847             cbArg.ext1 = 0;
   1848             cbArg.ext2 = 0;
   1849             m_parent->m_cbNotifier.notifyCallback(cbArg);
   1850         }
   1851 
   1852         if ((m_parent->mDataCb != NULL) &&
   1853             m_parent->msgTypeEnabledWithLock(CAMERA_MSG_COMPRESSED_IMAGE) > 0) {
   1854             qcamera_release_data_t release_data;
   1855             memset(&release_data, 0, sizeof(qcamera_release_data_t));
   1856             if ( zslChannelUsed ) {
   1857                 release_data.frame = recvd_frame;
   1858             } else {
   1859                 release_data.data = raw_mem;
   1860             }
   1861             rc = sendDataNotify(CAMERA_MSG_COMPRESSED_IMAGE,
   1862                                 raw_mem,
   1863                                 0,
   1864                                 NULL,
   1865                                 &release_data);
   1866         } else {
   1867             raw_mem->release(raw_mem);
   1868         }
   1869     } else {
   1870         ALOGE("%s: Cannot get raw mem", __func__);
   1871         rc = UNKNOWN_ERROR;
   1872     }
   1873 
   1874     return rc;
   1875 }
   1876 
   1877 /*===========================================================================
   1878  * FUNCTION   : dataSaveRoutine
   1879  *
   1880  * DESCRIPTION: data saving routine
   1881  *
   1882  * PARAMETERS :
   1883  *   @data    : user data ptr (QCameraPostProcessor)
   1884  *
   1885  * RETURN     : None
   1886  *==========================================================================*/
   1887 void *QCameraPostProcessor::dataSaveRoutine(void *data)
   1888 {
   1889     int running = 1;
   1890     int ret;
   1891     uint8_t is_active = FALSE;
   1892     QCameraPostProcessor *pme = (QCameraPostProcessor *)data;
   1893     QCameraCmdThread *cmdThread = &pme->m_saveProcTh;
   1894     char saveName[PROPERTY_VALUE_MAX];
   1895 
   1896     CDBG_HIGH("%s: E", __func__);
   1897     do {
   1898         do {
   1899             ret = cam_sem_wait(&cmdThread->cmd_sem);
   1900             if (ret != 0 && errno != EINVAL) {
   1901                 ALOGE("%s: cam_sem_wait error (%s)",
   1902                            __func__, strerror(errno));
   1903                 return NULL;
   1904             }
   1905         } while (ret != 0);
   1906 
   1907         // we got notified about new cmd avail in cmd queue
   1908         camera_cmd_type_t cmd = cmdThread->getCmd();
   1909         switch (cmd) {
   1910         case CAMERA_CMD_TYPE_START_DATA_PROC:
   1911             CDBG_HIGH("%s: start data proc", __func__);
   1912             is_active = TRUE;
   1913             pme->m_inputSaveQ.init();
   1914             break;
   1915         case CAMERA_CMD_TYPE_STOP_DATA_PROC:
   1916             {
   1917                 CDBG_HIGH("%s: stop data proc", __func__);
   1918                 is_active = FALSE;
   1919 
   1920                 // flush input save Queue
   1921                 pme->m_inputSaveQ.flush();
   1922 
   1923                 // signal cmd is completed
   1924                 cam_sem_post(&cmdThread->sync_sem);
   1925             }
   1926             break;
   1927         case CAMERA_CMD_TYPE_DO_NEXT_JOB:
   1928             {
   1929                 CDBG_HIGH("%s: Do next job, active is %d", __func__, is_active);
   1930 
   1931                 qcamera_jpeg_evt_payload_t *job_data = (qcamera_jpeg_evt_payload_t *) pme->m_inputSaveQ.dequeue();
   1932                 if (job_data == NULL) {
   1933                     ALOGE("%s: Invalid jpeg event data", __func__);
   1934                     continue;
   1935                 }
   1936 
   1937                 pme->m_ongoingJpegQ.flushNodes(matchJobId, (void*)&job_data->jobId);
   1938 
   1939                 CDBG_HIGH("[KPI Perf] %s : jpeg job %d", __func__, job_data->jobId);
   1940 
   1941                 if (is_active == TRUE) {
   1942                     memset(saveName, '\0', sizeof(saveName));
   1943                     snprintf(saveName,
   1944                              sizeof(saveName),
   1945                              QCameraPostProcessor::STORE_LOCATION,
   1946                              pme->mSaveFrmCnt);
   1947 
   1948                     int file_fd = open(saveName, O_RDWR | O_CREAT, 0655);
   1949                     if (file_fd > 0) {
   1950                         size_t written_len = write(file_fd,
   1951                                                 job_data->out_data.buf_vaddr,
   1952                                                 job_data->out_data.buf_filled_len);
   1953                         if ( job_data->out_data.buf_filled_len != written_len ) {
   1954                             ALOGE("%s: Failed save complete data %d bytes written instead of %d bytes!",
   1955                                   __func__,
   1956                                   written_len,
   1957                                   job_data->out_data.buf_filled_len);
   1958                         } else {
   1959                             CDBG_HIGH("%s: written number of bytes %d\n", __func__, written_len);
   1960                         }
   1961 
   1962                         close(file_fd);
   1963                     } else {
   1964                         ALOGE("%s: fail t open file for saving", __func__);
   1965                     }
   1966                     pme->mSaveFrmCnt++;
   1967 
   1968                     camera_memory_t* jpeg_mem = pme->m_parent->mGetMemory(-1,
   1969                                                          strlen(saveName),
   1970                                                          1,
   1971                                                          pme->m_parent->mCallbackCookie);
   1972                     if (NULL == jpeg_mem) {
   1973                         ret = NO_MEMORY;
   1974                         ALOGE("%s : getMemory for jpeg, ret = NO_MEMORY", __func__);
   1975                         goto end;
   1976                     }
   1977                     memcpy(jpeg_mem->data, saveName, strlen(saveName));
   1978 
   1979                     CDBG_HIGH("%s : Calling upperlayer callback to store JPEG image", __func__);
   1980                     qcamera_release_data_t release_data;
   1981                     memset(&release_data, 0, sizeof(qcamera_release_data_t));
   1982                     release_data.data = jpeg_mem;
   1983                     release_data.unlinkFile = true;
   1984                     CDBG_HIGH("[KPI Perf] %s: PROFILE_JPEG_CB ",__func__);
   1985                     ret = pme->sendDataNotify(CAMERA_MSG_COMPRESSED_IMAGE,
   1986                                         jpeg_mem,
   1987                                         0,
   1988                                         NULL,
   1989                                         &release_data);
   1990                 }
   1991 
   1992 end:
   1993                 free(job_data);
   1994             }
   1995             break;
   1996         case CAMERA_CMD_TYPE_EXIT:
   1997             CDBG_HIGH("%s : save thread exit", __func__);
   1998             running = 0;
   1999             break;
   2000         default:
   2001             break;
   2002         }
   2003     } while (running);
   2004     CDBG_HIGH("%s: X", __func__);
   2005     return NULL;
   2006 }
   2007 
   2008 /*===========================================================================
   2009  * FUNCTION   : dataProcessRoutine
   2010  *
   2011  * DESCRIPTION: data process routine that handles input data either from input
   2012  *              Jpeg Queue to do jpeg encoding, or from input PP Queue to do
   2013  *              reprocess.
   2014  *
   2015  * PARAMETERS :
   2016  *   @data    : user data ptr (QCameraPostProcessor)
   2017  *
   2018  * RETURN     : None
   2019  *==========================================================================*/
   2020 void *QCameraPostProcessor::dataProcessRoutine(void *data)
   2021 {
   2022     int running = 1;
   2023     int ret;
   2024     uint8_t is_active = FALSE;
   2025     QCameraPostProcessor *pme = (QCameraPostProcessor *)data;
   2026     QCameraCmdThread *cmdThread = &pme->m_dataProcTh;
   2027 
   2028     CDBG_HIGH("%s: E", __func__);
   2029     do {
   2030         do {
   2031             ret = cam_sem_wait(&cmdThread->cmd_sem);
   2032             if (ret != 0 && errno != EINVAL) {
   2033                 ALOGE("%s: cam_sem_wait error (%s)",
   2034                            __func__, strerror(errno));
   2035                 return NULL;
   2036             }
   2037         } while (ret != 0);
   2038 
   2039         // we got notified about new cmd avail in cmd queue
   2040         camera_cmd_type_t cmd = cmdThread->getCmd();
   2041         switch (cmd) {
   2042         case CAMERA_CMD_TYPE_START_DATA_PROC:
   2043             CDBG_HIGH("%s: start data proc", __func__);
   2044             is_active = TRUE;
   2045 
   2046             pme->m_ongoingPPQ.init();
   2047             pme->m_inputJpegQ.init();
   2048             pme->m_inputPPQ.init();
   2049             pme->m_inputRawQ.init();
   2050 
   2051             pme->m_saveProcTh.sendCmd(CAMERA_CMD_TYPE_START_DATA_PROC,
   2052                                       FALSE,
   2053                                       FALSE);
   2054 
   2055             // signal cmd is completed
   2056             cam_sem_post(&cmdThread->sync_sem);
   2057 
   2058             break;
   2059         case CAMERA_CMD_TYPE_STOP_DATA_PROC:
   2060             {
   2061                 CDBG_HIGH("%s: stop data proc", __func__);
   2062                 is_active = FALSE;
   2063 
   2064                 pme->m_saveProcTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC,
   2065                                            TRUE,
   2066                                            TRUE);
   2067                 // cancel all ongoing jpeg jobs
   2068                 qcamera_jpeg_data_t *jpeg_job =
   2069                     (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
   2070                 while (jpeg_job != NULL) {
   2071                     pme->mJpegHandle.abort_job(jpeg_job->jobId);
   2072 
   2073                     pme->releaseJpegJobData(jpeg_job);
   2074                     free(jpeg_job);
   2075 
   2076                     jpeg_job = (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
   2077                 }
   2078 
   2079                 // destroy jpeg encoding session
   2080                 if ( 0 < pme->mJpegSessionId ) {
   2081                     pme->mJpegHandle.destroy_session(pme->mJpegSessionId);
   2082                     pme->mJpegSessionId = 0;
   2083                 }
   2084 
   2085                 // free jpeg out buf and exif obj
   2086                 FREE_JPEG_OUTPUT_BUFFER(pme->m_pJpegOutputMem,
   2087                     pme->m_JpegOutputMemCount);
   2088 
   2089                 if (pme->m_pJpegExifObj != NULL) {
   2090                     delete pme->m_pJpegExifObj;
   2091                     pme->m_pJpegExifObj = NULL;
   2092                 }
   2093 
   2094                 // stop reproc channel if exists
   2095                 if (pme->m_pReprocChannel != NULL) {
   2096                     pme->m_pReprocChannel->stop();
   2097                     delete pme->m_pReprocChannel;
   2098                     pme->m_pReprocChannel = NULL;
   2099                 }
   2100 
   2101                 // flush ongoing postproc Queue
   2102                 pme->m_ongoingPPQ.flush();
   2103 
   2104                 // flush input jpeg Queue
   2105                 pme->m_inputJpegQ.flush();
   2106 
   2107                 // flush input Postproc Queue
   2108                 pme->m_inputPPQ.flush();
   2109 
   2110                 // flush input raw Queue
   2111                 pme->m_inputRawQ.flush();
   2112 
   2113                 // signal cmd is completed
   2114                 cam_sem_post(&cmdThread->sync_sem);
   2115 
   2116                 pme->mNewJpegSessionNeeded = true;
   2117             }
   2118             break;
   2119         case CAMERA_CMD_TYPE_DO_NEXT_JOB:
   2120             {
   2121                 CDBG_HIGH("%s: Do next job, active is %d", __func__, is_active);
   2122                 if (is_active == TRUE) {
   2123                     qcamera_jpeg_data_t *jpeg_job =
   2124                         (qcamera_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
   2125 
   2126                     if (NULL != jpeg_job) {
   2127                         // To avoid any race conditions,
   2128                         // sync any stream specific parameters here.
   2129                         pme->syncStreamParams(jpeg_job->src_frame, NULL);
   2130 
   2131                         // add into ongoing jpeg job Q
   2132                         pme->m_ongoingJpegQ.enqueue((void *)jpeg_job);
   2133                         ret = pme->encodeData(jpeg_job,
   2134                                   pme->mNewJpegSessionNeeded);
   2135                         if (NO_ERROR != ret) {
   2136                             // dequeue the last one
   2137                             pme->m_ongoingJpegQ.dequeue(false);
   2138                             pme->releaseJpegJobData(jpeg_job);
   2139                             free(jpeg_job);
   2140                             pme->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
   2141                         }
   2142                     }
   2143 
   2144 
   2145                     // process raw data if any
   2146                     mm_camera_super_buf_t *super_buf =
   2147                         (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue();
   2148 
   2149                     if (NULL != super_buf) {
   2150                         //play shutter sound
   2151                         pme->m_parent->playShutter();
   2152                         ret = pme->processRawImageImpl(super_buf);
   2153                         if (NO_ERROR != ret) {
   2154                             pme->releaseSuperBuf(super_buf);
   2155                             free(super_buf);
   2156                             pme->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
   2157                         }
   2158                     }
   2159 
   2160                     mm_camera_super_buf_t *pp_frame =
   2161                         (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue();
   2162                     if (NULL != pp_frame) {
   2163                         qcamera_pp_data_t *pp_job =
   2164                             (qcamera_pp_data_t *)malloc(sizeof(qcamera_pp_data_t));
   2165                         if (pp_job != NULL) {
   2166                             pme->syncStreamParams(pp_frame, NULL);
   2167                             memset(pp_job, 0, sizeof(qcamera_pp_data_t));
   2168                             if (pme->m_pReprocChannel != NULL) {
   2169                                 // add into ongoing PP job Q
   2170                                 pp_job->src_frame = pp_frame;
   2171                                 ret = pme->reprocess(pp_job);
   2172                                 if (NO_ERROR == ret) {
   2173                                     pme->stopCapture();
   2174                                 }
   2175                             } else {
   2176                                 ALOGE("%s: Reprocess channel is NULL", __func__);
   2177                                 ret = -1;
   2178                             }
   2179                         } else {
   2180                             ALOGE("%s: no mem for qcamera_pp_data_t", __func__);
   2181                             ret = -1;
   2182                         }
   2183 
   2184                         if (0 != ret) {
   2185                             // free pp_job
   2186                             if (pp_job != NULL) {
   2187                                 free(pp_job);
   2188                             }
   2189                             // free frame
   2190                             if (pp_frame != NULL) {
   2191                                 pme->releaseSuperBuf(pp_frame);
   2192                                 free(pp_frame);
   2193                             }
   2194                             // send error notify
   2195                             pme->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
   2196                         }
   2197                     }
   2198                 } else {
   2199                     // not active, simply return buf and do no op
   2200                     qcamera_jpeg_data_t *jpeg_data =
   2201                         (qcamera_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
   2202                     if (NULL != jpeg_data) {
   2203                         pme->releaseJpegJobData(jpeg_data);
   2204                         free(jpeg_data);
   2205                     }
   2206                     mm_camera_super_buf_t *super_buf =
   2207                         (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue();
   2208                     if (NULL != super_buf) {
   2209                         pme->releaseSuperBuf(super_buf);
   2210                         free(super_buf);
   2211                     }
   2212                     super_buf = (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue();
   2213                     if (NULL != super_buf) {
   2214                         pme->releaseSuperBuf(super_buf);
   2215                         free(super_buf);
   2216                     }
   2217                 }
   2218             }
   2219             break;
   2220         case CAMERA_CMD_TYPE_EXIT:
   2221             running = 0;
   2222             break;
   2223         default:
   2224             break;
   2225         }
   2226     } while (running);
   2227     CDBG_HIGH("%s: X", __func__);
   2228     return NULL;
   2229 }
   2230 
   2231 /*===========================================================================
   2232  * FUNCTION   : reprocess
   2233  *
   2234  * DESCRIPTION: Trigger reprocessing
   2235  *
   2236  * PARAMETERS :
   2237  *   @pp_job  : Postproc job
   2238  *
   2239  * RETURN     : int32_t type of status
   2240  *              NO_ERROR  -- success
   2241  *              none-zero failure code
   2242  *==========================================================================*/
   2243 int32_t QCameraPostProcessor::reprocess(qcamera_pp_data_t *pp_job)
   2244 {
   2245     int rc = NO_ERROR;
   2246 
   2247     if (NULL == pp_job) {
   2248         return BAD_VALUE;
   2249     }
   2250 
   2251     if (m_parent->isRegularCapture()) {
   2252        if ((NULL != pp_job->src_frame) &&
   2253            (0 < pp_job->src_frame->num_bufs)) {
   2254            mm_camera_buf_def_t *bufs = NULL;
   2255            uint8_t num_bufs = -1;
   2256            num_bufs = pp_job->src_frame->num_bufs;
   2257            bufs = new mm_camera_buf_def_t[num_bufs];
   2258            if (NULL == bufs) {
   2259                ALOGE("%s:Unable to allocate cached buffers",
   2260                      __func__);
   2261                return NO_MEMORY;
   2262            }
   2263 
   2264            for (int i = 0; i < num_bufs; i++) {
   2265                bufs[i] = *pp_job->src_frame->bufs[i];
   2266                pp_job->src_frame->bufs[i] = &bufs[i];
   2267            }
   2268            pp_job->src_reproc_bufs = bufs;
   2269        }
   2270 
   2271        // Don't release source frame after encoding
   2272        // at this point the source channel will not exist.
   2273        pp_job->reproc_frame_release = true;
   2274        m_ongoingPPQ.enqueue((void *)pp_job);
   2275        rc = m_pReprocChannel->doReprocessOffline(pp_job->src_frame);
   2276     } else {
   2277         m_ongoingPPQ.enqueue((void *)pp_job);
   2278         rc = m_pReprocChannel->doReprocess(pp_job->src_frame);
   2279     }
   2280 
   2281     if (NO_ERROR != rc) {
   2282         // remove from ongoing PP job Q
   2283         m_ongoingPPQ.dequeue(false);
   2284     }
   2285 
   2286     return rc;
   2287 }
   2288 
   2289 /*===========================================================================
   2290  * FUNCTION   : stopCapture
   2291  *
   2292  * DESCRIPTION: Trigger image capture stop
   2293  *
   2294  * PARAMETERS :
   2295  * None
   2296  *
   2297  * RETURN     : int32_t type of status
   2298  *              NO_ERROR  -- success
   2299  *              none-zero failure code
   2300  *==========================================================================*/
   2301 int32_t QCameraPostProcessor::stopCapture()
   2302 {
   2303      int rc = NO_ERROR;
   2304 
   2305      if (m_parent->isRegularCapture()) {
   2306         rc = m_parent->processAPI(
   2307                         QCAMERA_SM_EVT_STOP_CAPTURE_CHANNEL,
   2308                         NULL);
   2309      }
   2310 
   2311      return rc;
   2312 }
   2313 
   2314 /*===========================================================================
   2315  * FUNCTION   : getJpegPaddingReq
   2316  *
   2317  * DESCRIPTION: function to add an entry to exif data
   2318  *
   2319  * PARAMETERS :
   2320  *   @padding_info : jpeg specific padding requirement
   2321  *
   2322  * RETURN     : int32_t type of status
   2323  *              NO_ERROR  -- success
   2324  *              none-zero failure code
   2325  *==========================================================================*/
   2326 int32_t QCameraPostProcessor::getJpegPaddingReq(cam_padding_info_t &padding_info)
   2327 {
   2328     // TODO: hardcode for now, needs to query from mm-jpeg-interface
   2329     padding_info.width_padding  = CAM_PAD_NONE;
   2330     padding_info.height_padding  = CAM_PAD_TO_16;
   2331     padding_info.plane_padding  = CAM_PAD_TO_WORD;
   2332     return NO_ERROR;
   2333 }
   2334 
   2335 /*===========================================================================
   2336  * FUNCTION   : setYUVFrameInfo
   2337  *
   2338  * DESCRIPTION: set Raw YUV frame data info for up-layer
   2339  *
   2340  * PARAMETERS :
   2341  *   @frame   : process frame received from mm-camera-interface
   2342  *
   2343  * RETURN     : int32_t type of status
   2344  *              NO_ERROR  -- success
   2345  *              none-zero failure code
   2346  *
   2347  * NOTE       : currently we return frame len, y offset, cbcr offset and frame format
   2348  *==========================================================================*/
   2349 int32_t QCameraPostProcessor::setYUVFrameInfo(mm_camera_super_buf_t *recvd_frame)
   2350 {
   2351     QCameraChannel *pChannel = m_parent->getChannelByHandle(recvd_frame->ch_id);
   2352     // check reprocess channel if not found
   2353     if (pChannel == NULL) {
   2354         if (m_pReprocChannel != NULL &&
   2355             m_pReprocChannel->getMyHandle() == recvd_frame->ch_id) {
   2356             pChannel = m_pReprocChannel;
   2357         }
   2358     }
   2359 
   2360     if (pChannel == NULL) {
   2361         ALOGE("%s:%d] No corresponding channel (ch_id = %d) exist, return here",
   2362               __func__, __LINE__, recvd_frame->ch_id);
   2363         return BAD_VALUE;
   2364     }
   2365 
   2366     // find snapshot frame
   2367     for (int i = 0; i < recvd_frame->num_bufs; i++) {
   2368         QCameraStream *pStream =
   2369             pChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id);
   2370         if (pStream != NULL) {
   2371             if (pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
   2372                 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT)) {
   2373                 //get the main frame, use stream info
   2374                 cam_frame_len_offset_t frame_offset;
   2375                 cam_dimension_t frame_dim;
   2376                 cam_format_t frame_fmt;
   2377                 const char *fmt_string;
   2378                 pStream->getFrameDimension(frame_dim);
   2379                 pStream->getFrameOffset(frame_offset);
   2380                 pStream->getFormat(frame_fmt);
   2381                 fmt_string = m_parent->mParameters.getFrameFmtString(frame_fmt);
   2382 
   2383                 int cbcr_offset = frame_offset.mp[0].len - frame_dim.width * frame_dim.height;
   2384                 m_parent->mParameters.set("snapshot-framelen", frame_offset.frame_len);
   2385                 m_parent->mParameters.set("snapshot-yoff", frame_offset.mp[0].offset);
   2386                 m_parent->mParameters.set("snapshot-cbcroff", cbcr_offset);
   2387                 if(fmt_string != NULL){
   2388                     m_parent->mParameters.set("snapshot-format", fmt_string);
   2389                 }else{
   2390                     m_parent->mParameters.set("snapshot-format", "");
   2391                 }
   2392 
   2393                 CDBG_HIGH("%s: frame width=%d, height=%d, yoff=%d, cbcroff=%d, fmt_string=%s", __func__,
   2394                         frame_dim.width, frame_dim.height, frame_offset.mp[0].offset, cbcr_offset, fmt_string);
   2395                 return NO_ERROR;
   2396             }
   2397         }
   2398     }
   2399 
   2400     return BAD_VALUE;
   2401 }
   2402 
   2403 bool QCameraPostProcessor::matchJobId(void *data, void *, void *match_data)
   2404 {
   2405   qcamera_jpeg_data_t * job = (qcamera_jpeg_data_t *) data;
   2406   uint32_t job_id = *((uint32_t *) match_data);
   2407   return job->jobId == job_id;
   2408 }
   2409 
   2410 /*===========================================================================
   2411  * FUNCTION   : getJpegMemory
   2412  *
   2413  * DESCRIPTION: buffer allocation function
   2414  *   to pass to jpeg interface
   2415  *
   2416  * PARAMETERS :
   2417  *   @out_buf : buffer descriptor struct
   2418  *
   2419  * RETURN     : int32_t type of status
   2420  *              NO_ERROR  -- success
   2421  *              none-zero failure code
   2422  *==========================================================================*/
   2423 int QCameraPostProcessor::getJpegMemory(omx_jpeg_ouput_buf_t *out_buf)
   2424 {
   2425     CDBG_HIGH("%s: Allocating jpeg out buffer of size: %d", __func__, out_buf->size);
   2426     QCameraPostProcessor *procInst = (QCameraPostProcessor *) out_buf->handle;
   2427     camera_memory_t *cam_mem = procInst->m_parent->mGetMemory(-1, out_buf->size,
   2428         1, procInst->m_parent->mCallbackCookie);
   2429     out_buf->mem_hdl = cam_mem;
   2430     out_buf->vaddr = cam_mem->data;
   2431 
   2432     return 0;
   2433 }
   2434 
   2435 /*===========================================================================
   2436  * FUNCTION   : QCameraExif
   2437  *
   2438  * DESCRIPTION: constructor of QCameraExif
   2439  *
   2440  * PARAMETERS : None
   2441  *
   2442  * RETURN     : None
   2443  *==========================================================================*/
   2444 QCameraExif::QCameraExif()
   2445     : m_nNumEntries(0)
   2446 {
   2447     memset(m_Entries, 0, sizeof(m_Entries));
   2448 }
   2449 
   2450 /*===========================================================================
   2451  * FUNCTION   : ~QCameraExif
   2452  *
   2453  * DESCRIPTION: deconstructor of QCameraExif. Will release internal memory ptr.
   2454  *
   2455  * PARAMETERS : None
   2456  *
   2457  * RETURN     : None
   2458  *==========================================================================*/
   2459 QCameraExif::~QCameraExif()
   2460 {
   2461     for (uint32_t i = 0; i < m_nNumEntries; i++) {
   2462         switch (m_Entries[i].tag_entry.type) {
   2463         case EXIF_BYTE:
   2464             {
   2465                 if (m_Entries[i].tag_entry.count > 1 &&
   2466                     m_Entries[i].tag_entry.data._bytes != NULL) {
   2467                     free(m_Entries[i].tag_entry.data._bytes);
   2468                     m_Entries[i].tag_entry.data._bytes = NULL;
   2469                 }
   2470             }
   2471             break;
   2472         case EXIF_ASCII:
   2473             {
   2474                 if (m_Entries[i].tag_entry.data._ascii != NULL) {
   2475                     free(m_Entries[i].tag_entry.data._ascii);
   2476                     m_Entries[i].tag_entry.data._ascii = NULL;
   2477                 }
   2478             }
   2479             break;
   2480         case EXIF_SHORT:
   2481             {
   2482                 if (m_Entries[i].tag_entry.count > 1 &&
   2483                     m_Entries[i].tag_entry.data._shorts != NULL) {
   2484                     free(m_Entries[i].tag_entry.data._shorts);
   2485                     m_Entries[i].tag_entry.data._shorts = NULL;
   2486                 }
   2487             }
   2488             break;
   2489         case EXIF_LONG:
   2490             {
   2491                 if (m_Entries[i].tag_entry.count > 1 &&
   2492                     m_Entries[i].tag_entry.data._longs != NULL) {
   2493                     free(m_Entries[i].tag_entry.data._longs);
   2494                     m_Entries[i].tag_entry.data._longs = NULL;
   2495                 }
   2496             }
   2497             break;
   2498         case EXIF_RATIONAL:
   2499             {
   2500                 if (m_Entries[i].tag_entry.count > 1 &&
   2501                     m_Entries[i].tag_entry.data._rats != NULL) {
   2502                     free(m_Entries[i].tag_entry.data._rats);
   2503                     m_Entries[i].tag_entry.data._rats = NULL;
   2504                 }
   2505             }
   2506             break;
   2507         case EXIF_UNDEFINED:
   2508             {
   2509                 if (m_Entries[i].tag_entry.data._undefined != NULL) {
   2510                     free(m_Entries[i].tag_entry.data._undefined);
   2511                     m_Entries[i].tag_entry.data._undefined = NULL;
   2512                 }
   2513             }
   2514             break;
   2515         case EXIF_SLONG:
   2516             {
   2517                 if (m_Entries[i].tag_entry.count > 1 &&
   2518                     m_Entries[i].tag_entry.data._slongs != NULL) {
   2519                     free(m_Entries[i].tag_entry.data._slongs);
   2520                     m_Entries[i].tag_entry.data._slongs = NULL;
   2521                 }
   2522             }
   2523             break;
   2524         case EXIF_SRATIONAL:
   2525             {
   2526                 if (m_Entries[i].tag_entry.count > 1 &&
   2527                     m_Entries[i].tag_entry.data._srats != NULL) {
   2528                     free(m_Entries[i].tag_entry.data._srats);
   2529                     m_Entries[i].tag_entry.data._srats = NULL;
   2530                 }
   2531             }
   2532             break;
   2533         }
   2534     }
   2535 }
   2536 
   2537 /*===========================================================================
   2538  * FUNCTION   : addEntry
   2539  *
   2540  * DESCRIPTION: function to add an entry to exif data
   2541  *
   2542  * PARAMETERS :
   2543  *   @tagid   : exif tag ID
   2544  *   @type    : data type
   2545  *   @count   : number of data in uint of its type
   2546  *   @data    : input data ptr
   2547  *
   2548  * RETURN     : int32_t type of status
   2549  *              NO_ERROR  -- success
   2550  *              none-zero failure code
   2551  *==========================================================================*/
   2552 int32_t QCameraExif::addEntry(exif_tag_id_t tagid,
   2553                               exif_tag_type_t type,
   2554                               uint32_t count,
   2555                               void *data)
   2556 {
   2557     int32_t rc = NO_ERROR;
   2558     if(m_nNumEntries >= MAX_EXIF_TABLE_ENTRIES) {
   2559         ALOGE("%s: Number of entries exceeded limit", __func__);
   2560         return NO_MEMORY;
   2561     }
   2562 
   2563     m_Entries[m_nNumEntries].tag_id = tagid;
   2564     m_Entries[m_nNumEntries].tag_entry.type = type;
   2565     m_Entries[m_nNumEntries].tag_entry.count = count;
   2566     m_Entries[m_nNumEntries].tag_entry.copy = 1;
   2567     switch (type) {
   2568     case EXIF_BYTE:
   2569         {
   2570             if (count > 1) {
   2571                 uint8_t *values = (uint8_t *)malloc(count);
   2572                 if (values == NULL) {
   2573                     ALOGE("%s: No memory for byte array", __func__);
   2574                     rc = NO_MEMORY;
   2575                 } else {
   2576                     memcpy(values, data, count);
   2577                     m_Entries[m_nNumEntries].tag_entry.data._bytes = values;
   2578                 }
   2579             } else {
   2580                 m_Entries[m_nNumEntries].tag_entry.data._byte = *(uint8_t *)data;
   2581             }
   2582         }
   2583         break;
   2584     case EXIF_ASCII:
   2585         {
   2586             char *str = NULL;
   2587             str = (char *)malloc(count + 1);
   2588             if (str == NULL) {
   2589                 ALOGE("%s: No memory for ascii string", __func__);
   2590                 rc = NO_MEMORY;
   2591             } else {
   2592                 memset(str, 0, count + 1);
   2593                 memcpy(str, data, count);
   2594                 m_Entries[m_nNumEntries].tag_entry.data._ascii = str;
   2595             }
   2596         }
   2597         break;
   2598     case EXIF_SHORT:
   2599         {
   2600             if (count > 1) {
   2601                 uint16_t *values = (uint16_t *)malloc(count * sizeof(uint16_t));
   2602                 if (values == NULL) {
   2603                     ALOGE("%s: No memory for short array", __func__);
   2604                     rc = NO_MEMORY;
   2605                 } else {
   2606                     memcpy(values, data, count * sizeof(uint16_t));
   2607                     m_Entries[m_nNumEntries].tag_entry.data._shorts = values;
   2608                 }
   2609             } else {
   2610                 m_Entries[m_nNumEntries].tag_entry.data._short = *(uint16_t *)data;
   2611             }
   2612         }
   2613         break;
   2614     case EXIF_LONG:
   2615         {
   2616             if (count > 1) {
   2617                 uint32_t *values = (uint32_t *)malloc(count * sizeof(uint32_t));
   2618                 if (values == NULL) {
   2619                     ALOGE("%s: No memory for long array", __func__);
   2620                     rc = NO_MEMORY;
   2621                 } else {
   2622                     memcpy(values, data, count * sizeof(uint32_t));
   2623                     m_Entries[m_nNumEntries].tag_entry.data._longs = values;
   2624                 }
   2625             } else {
   2626                 m_Entries[m_nNumEntries].tag_entry.data._long = *(uint32_t *)data;
   2627             }
   2628         }
   2629         break;
   2630     case EXIF_RATIONAL:
   2631         {
   2632             if (count > 1) {
   2633                 rat_t *values = (rat_t *)malloc(count * sizeof(rat_t));
   2634                 if (values == NULL) {
   2635                     ALOGE("%s: No memory for rational array", __func__);
   2636                     rc = NO_MEMORY;
   2637                 } else {
   2638                     memcpy(values, data, count * sizeof(rat_t));
   2639                     m_Entries[m_nNumEntries].tag_entry.data._rats = values;
   2640                 }
   2641             } else {
   2642                 m_Entries[m_nNumEntries].tag_entry.data._rat = *(rat_t *)data;
   2643             }
   2644         }
   2645         break;
   2646     case EXIF_UNDEFINED:
   2647         {
   2648             uint8_t *values = (uint8_t *)malloc(count);
   2649             if (values == NULL) {
   2650                 ALOGE("%s: No memory for undefined array", __func__);
   2651                 rc = NO_MEMORY;
   2652             } else {
   2653                 memcpy(values, data, count);
   2654                 m_Entries[m_nNumEntries].tag_entry.data._undefined = values;
   2655             }
   2656         }
   2657         break;
   2658     case EXIF_SLONG:
   2659         {
   2660             if (count > 1) {
   2661                 int32_t *values = (int32_t *)malloc(count * sizeof(int32_t));
   2662                 if (values == NULL) {
   2663                     ALOGE("%s: No memory for signed long array", __func__);
   2664                     rc = NO_MEMORY;
   2665                 } else {
   2666                     memcpy(values, data, count * sizeof(int32_t));
   2667                     m_Entries[m_nNumEntries].tag_entry.data._slongs = values;
   2668                 }
   2669             } else {
   2670                 m_Entries[m_nNumEntries].tag_entry.data._slong = *(int32_t *)data;
   2671             }
   2672         }
   2673         break;
   2674     case EXIF_SRATIONAL:
   2675         {
   2676             if (count > 1) {
   2677                 srat_t *values = (srat_t *)malloc(count * sizeof(srat_t));
   2678                 if (values == NULL) {
   2679                     ALOGE("%s: No memory for signed rational array", __func__);
   2680                     rc = NO_MEMORY;
   2681                 } else {
   2682                     memcpy(values, data, count * sizeof(srat_t));
   2683                     m_Entries[m_nNumEntries].tag_entry.data._srats = values;
   2684                 }
   2685             } else {
   2686                 m_Entries[m_nNumEntries].tag_entry.data._srat = *(srat_t *)data;
   2687             }
   2688         }
   2689         break;
   2690     }
   2691 
   2692     // Increase number of entries
   2693     m_nNumEntries++;
   2694     return rc;
   2695 }
   2696 
   2697 }; // namespace qcamera
   2698