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