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 = -1;
    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     mm_camera_buf_def_t *meta_frame = NULL;
    765     for (uint32_t i = 0; i < frame->num_bufs; i++) {
    766         // look through input superbuf
    767         if (frame->bufs[i]->stream_type == CAM_STREAM_TYPE_METADATA) {
    768             meta_frame = frame->bufs[i];
    769             break;
    770         }
    771     }
    772     if (meta_frame != NULL) {
    773         //Function to upadte metadata for frame based parameter
    774         m_parent->updateMetadata((metadata_buffer_t *)meta_frame->buffer);
    775     }
    776 
    777     if (m_parent->needReprocess()) {
    778         if ((!m_parent->isLongshotEnabled() &&
    779              !m_parent->m_stateMachine.isNonZSLCaptureRunning()) ||
    780             (m_parent->isLongshotEnabled() &&
    781              m_parent->isCaptureShutterEnabled())) {
    782             //play shutter sound
    783             m_parent->playShutter();
    784         }
    785 
    786         ATRACE_INT("Camera:Reprocess", 1);
    787         CDBG_HIGH("%s: need reprocess", __func__);
    788 
    789         // enqueu to post proc input queue
    790         qcamera_pp_request_t *pp_request_job =
    791                 (qcamera_pp_request_t *)malloc(sizeof(qcamera_pp_request_t));
    792         if (pp_request_job == NULL) {
    793             ALOGE("%s: No memory for pproc job", __func__);
    794             return NO_MEMORY;
    795         }
    796         memset(pp_request_job, 0, sizeof(qcamera_pp_request_t));
    797         pp_request_job->src_frame = frame;
    798         pp_request_job->src_reproc_frame = frame;
    799         pp_request_job->reprocCount = 0;
    800         if (m_inputPPQ.enqueue((void *)pp_request_job)) {
    801             //avoid sending frame for reprocessing if o/p buffer is not queued to CPP.
    802             triggerEvent = validatePostProcess(frame);
    803         }else {
    804             CDBG_HIGH("%s : Input PP Q is not active!!!", __func__);
    805             releaseSuperBuf(frame);
    806             free(frame);
    807             free(pp_request_job);
    808             frame = NULL;
    809             pp_request_job = NULL;
    810             return NO_ERROR;
    811         }
    812         if (m_parent->mParameters.isAdvCamFeaturesEnabled()
    813                 && (meta_frame != NULL)) {
    814             m_InputMetadata.add(meta_frame);
    815         }
    816     } else if (m_parent->mParameters.isNV16PictureFormat() ||
    817         m_parent->mParameters.isNV21PictureFormat()) {
    818         //check if raw frame information is needed.
    819         if(m_parent->mParameters.isYUVFrameInfoNeeded())
    820             setYUVFrameInfo(frame);
    821 
    822         processRawData(frame);
    823     } else {
    824         //play shutter sound
    825         if(!m_parent->m_stateMachine.isNonZSLCaptureRunning() &&
    826            !m_parent->mLongshotEnabled)
    827            m_parent->playShutter();
    828 
    829         CDBG_HIGH("%s: no need offline reprocess, sending to jpeg encoding", __func__);
    830         qcamera_jpeg_data_t *jpeg_job =
    831             (qcamera_jpeg_data_t *)malloc(sizeof(qcamera_jpeg_data_t));
    832         if (jpeg_job == NULL) {
    833             ALOGE("%s: No memory for jpeg job", __func__);
    834             return NO_MEMORY;
    835         }
    836 
    837         memset(jpeg_job, 0, sizeof(qcamera_jpeg_data_t));
    838         jpeg_job->src_frame = frame;
    839 
    840         if (meta_frame != NULL) {
    841             // fill in meta data frame ptr
    842             jpeg_job->metadata = (metadata_buffer_t *)meta_frame->buffer;
    843         }
    844 
    845         // enqueu to jpeg input queue
    846         if (!m_inputJpegQ.enqueue((void *)jpeg_job)) {
    847             CDBG_HIGH("%s : Input Jpeg Q is not active!!!", __func__);
    848             releaseJpegJobData(jpeg_job);
    849             free(jpeg_job);
    850             jpeg_job = NULL;
    851             return NO_ERROR;
    852         }
    853     }
    854 
    855     if (triggerEvent){
    856         m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
    857     }
    858 
    859     return NO_ERROR;
    860 }
    861 
    862 /*===========================================================================
    863  * FUNCTION   : processRawData
    864  *
    865  * DESCRIPTION: enqueue raw data into dataProc thread
    866  *
    867  * PARAMETERS :
    868  *   @frame   : process frame received from mm-camera-interface
    869  *
    870  * RETURN     : int32_t type of status
    871  *              NO_ERROR  -- success
    872  *              none-zero failure code
    873  *==========================================================================*/
    874 int32_t QCameraPostProcessor::processRawData(mm_camera_super_buf_t *frame)
    875 {
    876     if (m_bInited == FALSE) {
    877         ALOGE("%s: postproc not initialized yet", __func__);
    878         return UNKNOWN_ERROR;
    879     }
    880 
    881     // enqueu to raw input queue
    882     if (m_inputRawQ.enqueue((void *)frame)) {
    883         m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
    884     } else {
    885         CDBG_HIGH("%s : m_inputRawQ is not active!!!", __func__);
    886         releaseSuperBuf(frame);
    887         free(frame);
    888         frame = NULL;
    889     }
    890     return NO_ERROR;
    891 }
    892 
    893 /*===========================================================================
    894  * FUNCTION   : processJpegEvt
    895  *
    896  * DESCRIPTION: process jpeg event from mm-jpeg-interface.
    897  *
    898  * PARAMETERS :
    899  *   @evt     : payload of jpeg event, including information about jpeg encoding
    900  *              status, jpeg size and so on.
    901  *
    902  * RETURN     : int32_t type of status
    903  *              NO_ERROR  -- success
    904  *              none-zero failure code
    905  *
    906  * NOTE       : This event will also trigger DataProc thread to move to next job
    907  *              processing (i.e., send a new jpeg encoding job to mm-jpeg-interface
    908  *              if there is any pending job in jpeg input queue)
    909  *==========================================================================*/
    910 int32_t QCameraPostProcessor::processJpegEvt(qcamera_jpeg_evt_payload_t *evt)
    911 {
    912     if (m_bInited == FALSE) {
    913         ALOGE("%s: postproc not initialized yet", __func__);
    914         return UNKNOWN_ERROR;
    915     }
    916 
    917     int32_t rc = NO_ERROR;
    918     camera_memory_t *jpeg_mem = NULL;
    919     omx_jpeg_ouput_buf_t *jpeg_out = NULL;
    920 
    921     if (mUseSaveProc && m_parent->isLongshotEnabled()) {
    922         qcamera_jpeg_evt_payload_t *saveData = ( qcamera_jpeg_evt_payload_t * ) malloc(sizeof(qcamera_jpeg_evt_payload_t));
    923         if ( NULL == saveData ) {
    924             ALOGE("%s: Can not allocate save data message!", __func__);
    925             return NO_MEMORY;
    926         }
    927         *saveData = *evt;
    928         if (m_inputSaveQ.enqueue((void *) saveData)) {
    929             m_saveProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
    930         } else {
    931             CDBG("%s : m_inputSaveQ PP Q is not active!!!", __func__);
    932             free(saveData);
    933             saveData = NULL;
    934             return rc;
    935         }
    936     } else {
    937         // Release jpeg job data
    938         m_ongoingJpegQ.flushNodes(matchJobId, (void*)&evt->jobId);
    939 
    940         if (m_inputPPQ.getCurrentSize() > 0) {
    941             m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
    942         }
    943         CDBG_HIGH("[KPI Perf] %s : jpeg job %d", __func__, evt->jobId);
    944 
    945         if ((false == m_parent->m_bIntJpegEvtPending) &&
    946              (m_parent->mDataCb == NULL ||
    947               m_parent->msgTypeEnabledWithLock(CAMERA_MSG_COMPRESSED_IMAGE) == 0 )) {
    948             CDBG_HIGH("%s: No dataCB or CAMERA_MSG_COMPRESSED_IMAGE not enabled",
    949                   __func__);
    950             rc = NO_ERROR;
    951             goto end;
    952         }
    953 
    954         if(evt->status == JPEG_JOB_STATUS_ERROR) {
    955             ALOGE("%s: Error event handled from jpeg, status = %d",
    956                   __func__, evt->status);
    957             rc = FAILED_TRANSACTION;
    958             goto end;
    959         }
    960 
    961         m_parent->dumpJpegToFile(evt->out_data.buf_vaddr,
    962                                   evt->out_data.buf_filled_len,
    963                                   evt->jobId);
    964         CDBG_HIGH("%s: Dump jpeg_size=%d", __func__, evt->out_data.buf_filled_len);
    965 
    966         if(true == m_parent->m_bIntJpegEvtPending) {
    967             //Sending JPEG snapshot taken notification to HAL
    968             pthread_mutex_lock(&m_parent->m_int_lock);
    969             pthread_cond_signal(&m_parent->m_int_cond);
    970             pthread_mutex_unlock(&m_parent->m_int_lock);
    971             m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
    972             return rc;
    973         }
    974 
    975         if (!mJpegMemOpt) {
    976             // alloc jpeg memory to pass to upper layer
    977             jpeg_mem = m_parent->mGetMemory(-1, evt->out_data.buf_filled_len,
    978                 1, m_parent->mCallbackCookie);
    979             if (NULL == jpeg_mem) {
    980                 rc = NO_MEMORY;
    981                 ALOGE("%s : getMemory for jpeg, ret = NO_MEMORY", __func__);
    982                 goto end;
    983             }
    984             memcpy(jpeg_mem->data, evt->out_data.buf_vaddr, evt->out_data.buf_filled_len);
    985         } else {
    986             jpeg_out  = (omx_jpeg_ouput_buf_t*) evt->out_data.buf_vaddr;
    987             jpeg_mem = (camera_memory_t *)jpeg_out->mem_hdl;
    988         }
    989 
    990         CDBG_HIGH("%s : Calling upperlayer callback to store JPEG image", __func__);
    991         qcamera_release_data_t release_data;
    992         memset(&release_data, 0, sizeof(qcamera_release_data_t));
    993         release_data.data = jpeg_mem;
    994         CDBG_HIGH("[KPI Perf] %s: PROFILE_JPEG_CB ",__func__);
    995         rc = sendDataNotify(CAMERA_MSG_COMPRESSED_IMAGE,
    996                             jpeg_mem,
    997                             0,
    998                             NULL,
    999                             &release_data);
   1000         m_parent->setOutputImageCount(m_parent->getOutputImageCount() + 1);
   1001 
   1002 end:
   1003         if (rc != NO_ERROR) {
   1004             // send error msg to upper layer
   1005             sendEvtNotify(CAMERA_MSG_ERROR,
   1006                           UNKNOWN_ERROR,
   1007                           0);
   1008 
   1009             if (NULL != jpeg_mem) {
   1010                 jpeg_mem->release(jpeg_mem);
   1011                 jpeg_mem = NULL;
   1012             }
   1013         }
   1014 
   1015         /* check whether to send callback for depth map */
   1016         if (m_parent->mParameters.isUbiRefocus() &&
   1017                 (m_parent->getOutputImageCount() + 1 ==
   1018                         m_parent->mParameters.getRefocusOutputCount())) {
   1019             m_parent->setOutputImageCount(m_parent->getOutputImageCount() + 1);
   1020 
   1021             jpeg_mem = m_DataMem;
   1022             release_data.data = jpeg_mem;
   1023             m_DataMem = NULL;
   1024             CDBG_HIGH("[KPI Perf] %s: send jpeg callback for depthmap ",__func__);
   1025             rc = sendDataNotify(CAMERA_MSG_COMPRESSED_IMAGE,
   1026                 jpeg_mem,
   1027                 0,
   1028                 NULL,
   1029                 &release_data);
   1030             if (rc != NO_ERROR) {
   1031                 // send error msg to upper layer
   1032                 sendEvtNotify(CAMERA_MSG_ERROR,
   1033                         UNKNOWN_ERROR,
   1034                         0);
   1035                 if (NULL != jpeg_mem) {
   1036                     jpeg_mem->release(jpeg_mem);
   1037                     jpeg_mem = NULL;
   1038                 }
   1039             }
   1040         }
   1041     }
   1042 
   1043     // wait up data proc thread to do next job,
   1044     // if previous request is blocked due to ongoing jpeg job
   1045     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
   1046 
   1047     return rc;
   1048 }
   1049 
   1050 /*===========================================================================
   1051  * FUNCTION   : processPPData
   1052  *
   1053  * DESCRIPTION: process received frame after reprocess.
   1054  *
   1055  * PARAMETERS :
   1056  *   @frame   : received frame from reprocess channel.
   1057  *
   1058  * RETURN     : int32_t type of status
   1059  *              NO_ERROR  -- success
   1060  *              none-zero failure code
   1061  *
   1062  * NOTE       : The frame after reprocess need to send to jpeg encoding.
   1063  *==========================================================================*/
   1064 int32_t QCameraPostProcessor::processPPData(mm_camera_super_buf_t *frame)
   1065 {
   1066     bool triggerEvent = TRUE;
   1067 
   1068     bool needSuperBufMatch = m_parent->mParameters.generateThumbFromMain();
   1069     if (m_bInited == FALSE) {
   1070         ALOGE("%s: postproc not initialized yet", __func__);
   1071         return UNKNOWN_ERROR;
   1072     }
   1073 
   1074     qcamera_pp_data_t *job = (qcamera_pp_data_t *)m_ongoingPPQ.dequeue();
   1075     if (NULL == job) {
   1076         ALOGE("%s: Cannot find reprocess job", __func__);
   1077         return BAD_VALUE;
   1078     }
   1079 
   1080     if (!needSuperBufMatch && (job->src_frame == NULL
   1081             || job->src_reproc_frame == NULL) ) {
   1082         ALOGE("%s: Invalid reprocess job", __func__);
   1083         return BAD_VALUE;
   1084     }
   1085 
   1086     if (!needSuperBufMatch && (m_parent->mParameters.isNV16PictureFormat() ||
   1087         m_parent->mParameters.isNV21PictureFormat())) {
   1088         releaseOngoingPPData(job, this);
   1089         free(job);
   1090 
   1091         if(m_parent->mParameters.isYUVFrameInfoNeeded())
   1092             setYUVFrameInfo(frame);
   1093         return processRawData(frame);
   1094     }
   1095     if (m_parent->isLongshotEnabled() &&
   1096             !m_parent->isCaptureShutterEnabled()) {
   1097         // play shutter sound for longshot
   1098         // after reprocess is done
   1099         // TODO: Move this after CAC done event
   1100         m_parent->playShutter();
   1101     }
   1102 
   1103     int8_t mCurReprocCount = job->reprocCount;
   1104     if ( mCurReprocCount > 1 ) {
   1105         //In case of pp 2nd pass, we can release input of 2nd pass
   1106         releaseSuperBuf(job->src_frame);
   1107         free(job->src_frame);
   1108         job->src_frame = NULL;
   1109     }
   1110 
   1111     CDBG("%s: mCurReprocCount = %d mTotalNumReproc = %d",
   1112             __func__, mCurReprocCount, mTotalNumReproc);
   1113     if (mCurReprocCount < mTotalNumReproc) {
   1114         //More pp pass needed. Push frame back to pp queue.
   1115         qcamera_pp_request_t *pp_request_job =
   1116                 (qcamera_pp_request_t *)malloc(sizeof(qcamera_pp_request_t));
   1117         if (pp_request_job == NULL) {
   1118             ALOGE("%s: No memory for pproc job", __func__);
   1119             return NO_MEMORY;
   1120         }
   1121         memset(pp_request_job, 0, sizeof(qcamera_pp_request_t));
   1122         pp_request_job->src_frame = frame;
   1123         pp_request_job->src_reproc_frame = job->src_reproc_frame;
   1124         pp_request_job->reprocCount = mCurReprocCount;
   1125         // enqueu to post proc input queue
   1126         if (m_inputPPQ.enqueue((void *)pp_request_job)) {
   1127             triggerEvent = validatePostProcess(frame);
   1128         } else {
   1129             CDBG_HIGH("%s : m_input PP Q is not active!!!", __func__);
   1130             releasePPInputData(pp_request_job,this);
   1131             free(pp_request_job);
   1132             pp_request_job = NULL;
   1133             triggerEvent = FALSE;
   1134         }
   1135     } else {
   1136         //Done with post processing. Send frame to Jpeg
   1137         qcamera_jpeg_data_t *jpeg_job =
   1138                 (qcamera_jpeg_data_t *)malloc(sizeof(qcamera_jpeg_data_t));
   1139         if (jpeg_job == NULL) {
   1140             ALOGE("%s: No memory for jpeg job", __func__);
   1141             return NO_MEMORY;
   1142         }
   1143 
   1144         memset(jpeg_job, 0, sizeof(qcamera_jpeg_data_t));
   1145         jpeg_job->src_frame = frame;
   1146         jpeg_job->src_reproc_frame = job ? job->src_reproc_frame : NULL;
   1147         jpeg_job->src_reproc_bufs = job ? job->src_reproc_bufs : NULL;
   1148         jpeg_job->reproc_frame_release = job ? job->reproc_frame_release : false;
   1149 
   1150         // find meta data frame
   1151         mm_camera_buf_def_t *meta_frame = NULL;
   1152         if (m_parent->mParameters.isAdvCamFeaturesEnabled()) {
   1153             size_t meta_idx = m_parent->mParameters.getExifBufIndex(m_PPindex);
   1154             if (m_InputMetadata.size() >= (meta_idx + 1)) {
   1155                 meta_frame = m_InputMetadata.itemAt(meta_idx);
   1156             } else {
   1157                 ALOGE("%s: Input metadata vector contains %d entries, index required %d",
   1158                         __func__, m_InputMetadata.size(), meta_idx);
   1159             }
   1160             m_PPindex++;
   1161         } else {
   1162             for (uint32_t i = 0; job && job->src_reproc_frame &&
   1163                     (i < job->src_reproc_frame->num_bufs); i++) {
   1164                 // look through input superbuf
   1165                 if (job->src_reproc_frame->bufs[i]->stream_type == CAM_STREAM_TYPE_METADATA) {
   1166                     meta_frame = job->src_reproc_frame->bufs[i];
   1167                     break;
   1168                 }
   1169             }
   1170 
   1171             if (meta_frame == NULL) {
   1172                 // look through reprocess superbuf
   1173                 for (uint32_t i = 0; i < frame->num_bufs; i++) {
   1174                     if (frame->bufs[i]->stream_type == CAM_STREAM_TYPE_METADATA) {
   1175                         meta_frame = frame->bufs[i];
   1176                         break;
   1177                     }
   1178                 }
   1179             }
   1180         }
   1181         if (meta_frame != NULL) {
   1182             // fill in meta data frame ptr
   1183             jpeg_job->metadata = (metadata_buffer_t *)meta_frame->buffer;
   1184         }
   1185 
   1186         // enqueu reprocessed frame to jpeg input queue
   1187         if (m_inputJpegQ.enqueue((void *)jpeg_job)) {
   1188             if (m_parent->isLongshotEnabled()) {
   1189                 triggerEvent = validatePostProcess(frame);
   1190             }
   1191         } else {
   1192             CDBG_HIGH("%s : Input Jpeg Q is not active!!!", __func__);
   1193             releaseJpegJobData(jpeg_job);
   1194             free(jpeg_job);
   1195             jpeg_job = NULL;
   1196             triggerEvent = FALSE;
   1197         }
   1198     }
   1199 
   1200     // free pp job buf
   1201     if (job) {
   1202         free(job);
   1203     }
   1204 
   1205     ALOGD("%s: %d] ", __func__, __LINE__);
   1206     // wait up data proc thread
   1207 
   1208     if (triggerEvent) {
   1209         m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
   1210     }
   1211 
   1212     return NO_ERROR;
   1213 }
   1214 
   1215 /*===========================================================================
   1216  * FUNCTION   : findJpegJobByJobId
   1217  *
   1218  * DESCRIPTION: find a jpeg job from ongoing Jpeg queue by its job ID
   1219  *
   1220  * PARAMETERS :
   1221  *   @jobId   : job Id of the job
   1222  *
   1223  * RETURN     : ptr to a jpeg job struct. NULL if not found.
   1224  *
   1225  * NOTE       : Currently only one job is sending to mm-jpeg-interface for jpeg
   1226  *              encoding. Therefore simply dequeue from the ongoing Jpeg Queue
   1227  *              will serve the purpose to find the jpeg job.
   1228  *==========================================================================*/
   1229 qcamera_jpeg_data_t *QCameraPostProcessor::findJpegJobByJobId(uint32_t jobId)
   1230 {
   1231     qcamera_jpeg_data_t * job = NULL;
   1232     if (jobId == 0) {
   1233         ALOGE("%s: not a valid jpeg jobId", __func__);
   1234         return NULL;
   1235     }
   1236 
   1237     // currely only one jpeg job ongoing, so simply dequeue the head
   1238     job = (qcamera_jpeg_data_t *)m_ongoingJpegQ.dequeue();
   1239     return job;
   1240 }
   1241 
   1242 /*===========================================================================
   1243  * FUNCTION   : releasePPInputData
   1244  *
   1245  * DESCRIPTION: callback function to release post process input data node
   1246  *
   1247  * PARAMETERS :
   1248  *   @data      : ptr to post process input data
   1249  *   @user_data : user data ptr (QCameraReprocessor)
   1250  *
   1251  * RETURN     : None
   1252  *==========================================================================*/
   1253 void QCameraPostProcessor::releasePPInputData(void *data, void *user_data)
   1254 {
   1255     QCameraPostProcessor *pme = (QCameraPostProcessor *)user_data;
   1256     if (NULL != pme) {
   1257         qcamera_pp_request_t *pp_job = (qcamera_pp_request_t *)data;
   1258         if (NULL != pp_job->src_frame) {
   1259             pme->releaseSuperBuf(pp_job->src_frame);
   1260             if (pp_job->src_frame == pp_job->src_reproc_frame)
   1261                 pp_job->src_reproc_frame = NULL;
   1262             free(pp_job->src_frame);
   1263             pp_job->src_frame = NULL;
   1264         }
   1265         if (NULL != pp_job->src_reproc_frame) {
   1266             pme->releaseSuperBuf(pp_job->src_reproc_frame);
   1267             free(pp_job->src_reproc_frame);
   1268             pp_job->src_reproc_frame = NULL;
   1269         }
   1270         pp_job->reprocCount = 0;
   1271     }
   1272 }
   1273 
   1274 /*===========================================================================
   1275  * FUNCTION   : releaseJpegData
   1276  *
   1277  * DESCRIPTION: callback function to release jpeg job node
   1278  *
   1279  * PARAMETERS :
   1280  *   @data      : ptr to ongoing jpeg job data
   1281  *   @user_data : user data ptr (QCameraReprocessor)
   1282  *
   1283  * RETURN     : None
   1284  *==========================================================================*/
   1285 void QCameraPostProcessor::releaseJpegData(void *data, void *user_data)
   1286 {
   1287     QCameraPostProcessor *pme = (QCameraPostProcessor *)user_data;
   1288     if (NULL != pme) {
   1289         pme->releaseJpegJobData((qcamera_jpeg_data_t *)data);
   1290         CDBG_HIGH("%s : Rleased job ID %u", __func__,
   1291             ((qcamera_jpeg_data_t *)data)->jobId);
   1292     }
   1293 }
   1294 
   1295 /*===========================================================================
   1296  * FUNCTION   : releaseOngoingPPData
   1297  *
   1298  * DESCRIPTION: callback function to release ongoing postprocess job node
   1299  *
   1300  * PARAMETERS :
   1301  *   @data      : ptr to onging postprocess job
   1302  *   @user_data : user data ptr (QCameraReprocessor)
   1303  *
   1304  * RETURN     : None
   1305  *==========================================================================*/
   1306 void QCameraPostProcessor::releaseOngoingPPData(void *data, void *user_data)
   1307 {
   1308     QCameraPostProcessor *pme = (QCameraPostProcessor *)user_data;
   1309     if (NULL != pme) {
   1310         qcamera_pp_data_t *pp_job = (qcamera_pp_data_t *)data;
   1311         if (NULL != pp_job->src_frame) {
   1312             if (!pp_job->reproc_frame_release) {
   1313                 pme->releaseSuperBuf(pp_job->src_frame);
   1314             }
   1315             if (pp_job->src_frame == pp_job->src_reproc_frame)
   1316                 pp_job->src_reproc_frame = NULL;
   1317 
   1318             free(pp_job->src_frame);
   1319             pp_job->src_frame = NULL;
   1320         }
   1321         if (NULL != pp_job->src_reproc_frame) {
   1322             pme->releaseSuperBuf(pp_job->src_reproc_frame);
   1323             free(pp_job->src_reproc_frame);
   1324             pp_job->src_reproc_frame = NULL;
   1325         }
   1326         pp_job->reprocCount = 0;
   1327     }
   1328 }
   1329 
   1330 /*===========================================================================
   1331  * FUNCTION   : releaseNotifyData
   1332  *
   1333  * DESCRIPTION: function to release internal resources in notify data struct
   1334  *
   1335  * PARAMETERS :
   1336  *   @user_data  : ptr user data
   1337  *   @cookie     : callback cookie
   1338  *   @cb_status  : callback status
   1339  *
   1340  * RETURN     : None
   1341  *
   1342  * NOTE       : deallocate jpeg heap memory if it's not NULL
   1343  *==========================================================================*/
   1344 void QCameraPostProcessor::releaseNotifyData(void *user_data,
   1345                                              void *cookie,
   1346                                              int32_t cb_status)
   1347 {
   1348     qcamera_data_argm_t *app_cb = ( qcamera_data_argm_t * ) user_data;
   1349     QCameraPostProcessor *postProc = ( QCameraPostProcessor * ) cookie;
   1350     if ( ( NULL != app_cb ) && ( NULL != postProc ) ) {
   1351 
   1352         if ( postProc->mUseSaveProc &&
   1353              app_cb->release_data.unlinkFile &&
   1354              ( NO_ERROR != cb_status ) ) {
   1355 
   1356             String8 unlinkPath((const char *) app_cb->release_data.data->data,
   1357                                 app_cb->release_data.data->size);
   1358             int rc = unlink(unlinkPath.string());
   1359             CDBG_HIGH("%s : Unlinking stored file rc = %d",
   1360                   __func__,
   1361                   rc);
   1362         }
   1363 
   1364         if (app_cb && NULL != app_cb->release_data.data) {
   1365             app_cb->release_data.data->release(app_cb->release_data.data);
   1366             app_cb->release_data.data = NULL;
   1367         }
   1368         if (app_cb && NULL != app_cb->release_data.frame) {
   1369             postProc->releaseSuperBuf(app_cb->release_data.frame);
   1370             free(app_cb->release_data.frame);
   1371             app_cb->release_data.frame = NULL;
   1372         }
   1373         if (app_cb && NULL != app_cb->release_data.streamBufs) {
   1374             app_cb->release_data.streamBufs->deallocate();
   1375             delete app_cb->release_data.streamBufs;
   1376             app_cb->release_data.streamBufs = NULL;
   1377         }
   1378         free(app_cb);
   1379     }
   1380 }
   1381 
   1382 /*===========================================================================
   1383  * FUNCTION   : releaseSuperBuf
   1384  *
   1385  * DESCRIPTION: function to release a superbuf frame by returning back to kernel
   1386  *
   1387  * PARAMETERS :
   1388  *   @super_buf : ptr to the superbuf frame
   1389  *
   1390  * RETURN     : None
   1391  *==========================================================================*/
   1392 void QCameraPostProcessor::releaseSuperBuf(mm_camera_super_buf_t *super_buf)
   1393 {
   1394     QCameraChannel *pChannel = NULL;
   1395 
   1396     if (NULL != super_buf) {
   1397         pChannel = m_parent->getChannelByHandle(super_buf->ch_id);
   1398 
   1399         if ( NULL == pChannel ) {
   1400             for (int8_t i = 0; i < mTotalNumReproc; i++) {
   1401                 if ((mPPChannels[i] != NULL) &&
   1402                         (mPPChannels[i]->getMyHandle() == super_buf->ch_id)) {
   1403                     pChannel = mPPChannels[i];
   1404                     break;
   1405                 }
   1406             }
   1407         }
   1408 
   1409         if (pChannel != NULL) {
   1410             pChannel->bufDone(super_buf);
   1411         } else {
   1412             ALOGE(" %s : Channel id %d not found!!",
   1413                   __func__,
   1414                   super_buf->ch_id);
   1415         }
   1416     }
   1417 }
   1418 
   1419 /*===========================================================================
   1420  * FUNCTION   : releaseJpegJobData
   1421  *
   1422  * DESCRIPTION: function to release internal resources in jpeg job struct
   1423  *
   1424  * PARAMETERS :
   1425  *   @job     : ptr to jpeg job struct
   1426  *
   1427  * RETURN     : None
   1428  *
   1429  * NOTE       : original source frame need to be queued back to kernel for
   1430  *              future use. Output buf of jpeg job need to be released since
   1431  *              it's allocated for each job. Exif object need to be deleted.
   1432  *==========================================================================*/
   1433 void QCameraPostProcessor::releaseJpegJobData(qcamera_jpeg_data_t *job)
   1434 {
   1435     CDBG("%s: E", __func__);
   1436     if (NULL != job) {
   1437         if (NULL != job->src_reproc_frame) {
   1438             if (!job->reproc_frame_release) {
   1439                 releaseSuperBuf(job->src_reproc_frame);
   1440             }
   1441             free(job->src_reproc_frame);
   1442             job->src_reproc_frame = NULL;
   1443         }
   1444 
   1445         if (NULL != job->src_frame) {
   1446             releaseSuperBuf(job->src_frame);
   1447             free(job->src_frame);
   1448             job->src_frame = NULL;
   1449         }
   1450 
   1451         if (NULL != job->pJpegExifObj) {
   1452             delete job->pJpegExifObj;
   1453             job->pJpegExifObj = NULL;
   1454         }
   1455 
   1456         if (NULL != job->src_reproc_bufs) {
   1457             delete [] job->src_reproc_bufs;
   1458         }
   1459 
   1460     }
   1461     CDBG("%s: X", __func__);
   1462 }
   1463 
   1464 /*===========================================================================
   1465  * FUNCTION   : releaseSaveJobData
   1466  *
   1467  * DESCRIPTION: function to release internal resources in store jobs
   1468  *
   1469  * PARAMETERS :
   1470  *   @job     : ptr to save job struct
   1471  *
   1472  * RETURN     : None
   1473  *
   1474  *==========================================================================*/
   1475 void QCameraPostProcessor::releaseSaveJobData(void *data, void *user_data)
   1476 {
   1477     CDBG("%s: E", __func__);
   1478 
   1479     QCameraPostProcessor *pme = (QCameraPostProcessor *) user_data;
   1480     if (NULL == pme) {
   1481         ALOGE("%s: Invalid postproc handle", __func__);
   1482         return;
   1483     }
   1484 
   1485     qcamera_jpeg_evt_payload_t *job_data = (qcamera_jpeg_evt_payload_t *) data;
   1486     if (job_data == NULL) {
   1487         ALOGE("%s: Invalid jpeg event data", __func__);
   1488         return;
   1489     }
   1490 
   1491     // find job by jobId
   1492     qcamera_jpeg_data_t *job = pme->findJpegJobByJobId(job_data->jobId);
   1493 
   1494     if (NULL != job) {
   1495         pme->releaseJpegJobData(job);
   1496         free(job);
   1497     } else {
   1498         ALOGE("%s : Invalid jpeg job", __func__);
   1499     }
   1500 
   1501     CDBG("%s: X", __func__);
   1502 }
   1503 
   1504 /*===========================================================================
   1505  * FUNCTION   : releaseRawData
   1506  *
   1507  * DESCRIPTION: function to release internal resources in store jobs
   1508  *
   1509  * PARAMETERS :
   1510  *   @job     : ptr to save job struct
   1511  *
   1512  * RETURN     : None
   1513  *
   1514  *==========================================================================*/
   1515 void QCameraPostProcessor::releaseRawData(void *data, void *user_data)
   1516 {
   1517     CDBG("%s: E", __func__);
   1518 
   1519     QCameraPostProcessor *pme = (QCameraPostProcessor *) user_data;
   1520     if (NULL == pme) {
   1521         ALOGE("%s: Invalid postproc handle", __func__);
   1522         return;
   1523     }
   1524     mm_camera_super_buf_t *super_buf = (mm_camera_super_buf_t *) data;
   1525     pme->releaseSuperBuf(super_buf);
   1526 
   1527     CDBG("%s: X", __func__);
   1528 }
   1529 
   1530 
   1531 /*===========================================================================
   1532  * FUNCTION   : getColorfmtFromImgFmt
   1533  *
   1534  * DESCRIPTION: function to return jpeg color format based on its image format
   1535  *
   1536  * PARAMETERS :
   1537  *   @img_fmt : image format
   1538  *
   1539  * RETURN     : jpeg color format that can be understandable by omx lib
   1540  *==========================================================================*/
   1541 mm_jpeg_color_format QCameraPostProcessor::getColorfmtFromImgFmt(cam_format_t img_fmt)
   1542 {
   1543     switch (img_fmt) {
   1544     case CAM_FORMAT_YUV_420_NV21:
   1545         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
   1546     case CAM_FORMAT_YUV_420_NV21_ADRENO:
   1547         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
   1548     case CAM_FORMAT_YUV_420_NV12:
   1549         return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2;
   1550     case CAM_FORMAT_YUV_420_YV12:
   1551         return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2;
   1552     case CAM_FORMAT_YUV_422_NV61:
   1553         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V1;
   1554     case CAM_FORMAT_YUV_422_NV16:
   1555         return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V1;
   1556     default:
   1557         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
   1558     }
   1559 }
   1560 
   1561 /*===========================================================================
   1562  * FUNCTION   : getJpegImgTypeFromImgFmt
   1563  *
   1564  * DESCRIPTION: function to return jpeg encode image type based on its image format
   1565  *
   1566  * PARAMETERS :
   1567  *   @img_fmt : image format
   1568  *
   1569  * RETURN     : return jpeg source image format (YUV or Bitstream)
   1570  *==========================================================================*/
   1571 mm_jpeg_format_t QCameraPostProcessor::getJpegImgTypeFromImgFmt(cam_format_t img_fmt)
   1572 {
   1573     switch (img_fmt) {
   1574     case CAM_FORMAT_YUV_420_NV21:
   1575     case CAM_FORMAT_YUV_420_NV21_ADRENO:
   1576     case CAM_FORMAT_YUV_420_NV12:
   1577     case CAM_FORMAT_YUV_420_YV12:
   1578     case CAM_FORMAT_YUV_422_NV61:
   1579     case CAM_FORMAT_YUV_422_NV16:
   1580         return MM_JPEG_FMT_YUV;
   1581     default:
   1582         return MM_JPEG_FMT_YUV;
   1583     }
   1584 }
   1585 
   1586 /*===========================================================================
   1587  * FUNCTION   : queryStreams
   1588  *
   1589  * DESCRIPTION: utility method for retrieving main, thumbnail and reprocess
   1590  *              streams and frame from bundled super buffer
   1591  *
   1592  * PARAMETERS :
   1593  *   @main    : ptr to main stream if present
   1594  *   @thumb   : ptr to thumbnail stream if present
   1595  *   @reproc  : ptr to reprocess stream if present
   1596  *   @main_image : ptr to main image if present
   1597  *   @thumb_image: ptr to thumbnail image if present
   1598  *   @frame   : bundled super buffer
   1599  *   @reproc_frame : bundled source frame buffer
   1600  *
   1601  * RETURN     : int32_t type of status
   1602  *              NO_ERROR  -- success
   1603  *              none-zero failure code
   1604  *==========================================================================*/
   1605 int32_t QCameraPostProcessor::queryStreams(QCameraStream **main,
   1606         QCameraStream **thumb,
   1607         QCameraStream **reproc,
   1608         mm_camera_buf_def_t **main_image,
   1609         mm_camera_buf_def_t **thumb_image,
   1610         mm_camera_super_buf_t *frame,
   1611         mm_camera_super_buf_t *reproc_frame)
   1612 {
   1613     if (NULL == frame) {
   1614         return NO_INIT;
   1615     }
   1616 
   1617     QCameraChannel *pChannel = m_parent->getChannelByHandle(frame->ch_id);
   1618     // check reprocess channel if not found
   1619     if (pChannel == NULL) {
   1620         for (int8_t i = 0; i < mTotalNumReproc; i++) {
   1621             if ((mPPChannels[i] != NULL) &&
   1622                     (mPPChannels[i]->getMyHandle() == frame->ch_id)) {
   1623                 pChannel = mPPChannels[i];
   1624                 break;
   1625             }
   1626         }
   1627     }
   1628     if (pChannel == NULL) {
   1629         ALOGD("%s: No corresponding channel (ch_id = %d) exist, return here",
   1630               __func__, frame->ch_id);
   1631         return BAD_VALUE;
   1632     }
   1633 
   1634     // Use snapshot stream to create thumbnail if snapshot and preview
   1635     // flip settings doesn't match in ZSL mode.
   1636     bool thumb_stream_needed = ((!m_parent->isZSLMode() ||
   1637         (m_parent->mParameters.getFlipMode(CAM_STREAM_TYPE_SNAPSHOT) ==
   1638          m_parent->mParameters.getFlipMode(CAM_STREAM_TYPE_PREVIEW))) &&
   1639         !m_parent->mParameters.generateThumbFromMain());
   1640 
   1641     *main = *thumb = *reproc = NULL;
   1642     *main_image = *thumb_image = NULL;
   1643     // find snapshot frame and thumnail frame
   1644     for (uint32_t i = 0; i < frame->num_bufs; i++) {
   1645         QCameraStream *pStream =
   1646                 pChannel->getStreamByHandle(frame->bufs[i]->stream_id);
   1647         if (pStream != NULL) {
   1648             if (pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
   1649                     pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
   1650                     (m_parent->mParameters.getofflineRAW() &&
   1651                             pStream->isOrignalTypeOf(CAM_STREAM_TYPE_RAW))) {
   1652                 *main= pStream;
   1653                 *main_image = frame->bufs[i];
   1654             } else if (thumb_stream_needed &&
   1655                        (pStream->isTypeOf(CAM_STREAM_TYPE_PREVIEW) ||
   1656                         pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) ||
   1657                         pStream->isOrignalTypeOf(CAM_STREAM_TYPE_PREVIEW) ||
   1658                         pStream->isOrignalTypeOf(CAM_STREAM_TYPE_POSTVIEW))) {
   1659                 *thumb = pStream;
   1660                 *thumb_image = frame->bufs[i];
   1661             }
   1662             if (pStream->isTypeOf(CAM_STREAM_TYPE_OFFLINE_PROC) ) {
   1663                 *reproc = pStream;
   1664             }
   1665         }
   1666     }
   1667 
   1668     if (thumb_stream_needed && *thumb_image == NULL && reproc_frame != NULL) {
   1669         QCameraChannel *pSrcReprocChannel = NULL;
   1670         pSrcReprocChannel = m_parent->getChannelByHandle(reproc_frame->ch_id);
   1671         if (pSrcReprocChannel != NULL) {
   1672             // find thumbnail frame
   1673             for (uint32_t i = 0; i < reproc_frame->num_bufs; i++) {
   1674                 QCameraStream *pStream =
   1675                         pSrcReprocChannel->getStreamByHandle(
   1676                                 reproc_frame->bufs[i]->stream_id);
   1677                 if (pStream != NULL) {
   1678                     if (pStream->isTypeOf(CAM_STREAM_TYPE_PREVIEW) ||
   1679                         pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW)) {
   1680                         *thumb = pStream;
   1681                         *thumb_image = reproc_frame->bufs[i];
   1682                     }
   1683                 }
   1684             }
   1685         }
   1686     }
   1687 
   1688     return NO_ERROR;
   1689 }
   1690 
   1691 /*===========================================================================
   1692 * FUNCTION   : syncStreamParams
   1693 *
   1694 * DESCRIPTION: Query the runtime parameters of all streams included
   1695 *              in the main and reprocessed frames
   1696 *
   1697 * PARAMETERS :
   1698 *   @frame : Main image super buffer
   1699 *   @reproc_frame : Image supper buffer that got processed
   1700 *
   1701 * RETURN     : int32_t type of status
   1702 *              NO_ERROR  -- success
   1703 *              none-zero failure code
   1704 *==========================================================================*/
   1705 int32_t QCameraPostProcessor::syncStreamParams(mm_camera_super_buf_t *frame,
   1706         mm_camera_super_buf_t *reproc_frame)
   1707 {
   1708     QCameraStream *reproc_stream = NULL;
   1709     QCameraStream *main_stream = NULL;
   1710     QCameraStream *thumb_stream = NULL;
   1711     mm_camera_buf_def_t *main_frame = NULL;
   1712     mm_camera_buf_def_t *thumb_frame = NULL;
   1713     int32_t ret = NO_ERROR;
   1714 
   1715     ret = queryStreams(&main_stream,
   1716             &thumb_stream,
   1717             &reproc_stream,
   1718             &main_frame,
   1719             &thumb_frame,
   1720             frame,
   1721             reproc_frame);
   1722     if (NO_ERROR != ret) {
   1723         ALOGE("%s : Camera streams query from input frames failed %d",
   1724                 __func__,
   1725                 ret);
   1726         return ret;
   1727     }
   1728 
   1729     if (NULL != main_stream) {
   1730         ret = main_stream->syncRuntimeParams();
   1731         if (NO_ERROR != ret) {
   1732             ALOGE("%s : Syncing of main stream runtime parameters failed %d",
   1733                     __func__,
   1734                     ret);
   1735             return ret;
   1736         }
   1737     }
   1738 
   1739     if (NULL != thumb_stream) {
   1740         ret = thumb_stream->syncRuntimeParams();
   1741         if (NO_ERROR != ret) {
   1742             ALOGE("%s : Syncing of thumb stream runtime parameters failed %d",
   1743                     __func__,
   1744                     ret);
   1745             return ret;
   1746         }
   1747     }
   1748 
   1749     if ((NULL != reproc_stream) && (reproc_stream != main_stream)) {
   1750         ret = reproc_stream->syncRuntimeParams();
   1751         if (NO_ERROR != ret) {
   1752             ALOGE("%s : Syncing of reproc stream runtime parameters failed %d",
   1753                     __func__,
   1754                     ret);
   1755             return ret;
   1756         }
   1757     }
   1758 
   1759     return ret;
   1760 }
   1761 
   1762 /*===========================================================================
   1763  * FUNCTION   : encodeData
   1764  *
   1765  * DESCRIPTION: function to prepare encoding job information and send to
   1766  *              mm-jpeg-interface to do the encoding job
   1767  *
   1768  * PARAMETERS :
   1769  *   @jpeg_job_data : ptr to a struct saving job related information
   1770  *   @needNewSess   : flag to indicate if a new jpeg encoding session need
   1771  *                    to be created. After creation, this flag will be toggled
   1772  *
   1773  * RETURN     : int32_t type of status
   1774  *              NO_ERROR  -- success
   1775  *              none-zero failure code
   1776  *==========================================================================*/
   1777 int32_t QCameraPostProcessor::encodeData(qcamera_jpeg_data_t *jpeg_job_data,
   1778                                          uint8_t &needNewSess)
   1779 {
   1780     CDBG("%s : E", __func__);
   1781     int32_t ret = NO_ERROR;
   1782     mm_jpeg_job_t jpg_job;
   1783     uint32_t jobId = 0;
   1784     QCameraStream *reproc_stream = NULL;
   1785     QCameraStream *main_stream = NULL;
   1786     mm_camera_buf_def_t *main_frame = NULL;
   1787     QCameraStream *thumb_stream = NULL;
   1788     mm_camera_buf_def_t *thumb_frame = NULL;
   1789     mm_camera_super_buf_t *recvd_frame = jpeg_job_data->src_frame;
   1790     cam_rect_t crop;
   1791     cam_stream_parm_buffer_t param;
   1792     cam_stream_img_prop_t imgProp;
   1793 
   1794     // find channel
   1795     QCameraChannel *pChannel = m_parent->getChannelByHandle(recvd_frame->ch_id);
   1796     // check reprocess channel if not found
   1797     if (pChannel == NULL) {
   1798         for (int8_t i = 0; i < mTotalNumReproc; i++) {
   1799             if ((mPPChannels[i] != NULL) &&
   1800                     (mPPChannels[i]->getMyHandle() == recvd_frame->ch_id)) {
   1801                 pChannel = mPPChannels[i];
   1802                 break;
   1803             }
   1804         }
   1805     }
   1806 
   1807     if (pChannel == NULL) {
   1808         ALOGE("%s:%d] No corresponding channel (ch_id = %d) exist, return here",
   1809               __func__, __LINE__, recvd_frame->ch_id);
   1810         return BAD_VALUE;
   1811     }
   1812 
   1813     const uint32_t jpeg_rotation = m_parent->mParameters.getJpegRotation();
   1814 
   1815     ret = queryStreams(&main_stream,
   1816             &thumb_stream,
   1817             &reproc_stream,
   1818             &main_frame,
   1819             &thumb_frame,
   1820             recvd_frame,
   1821             jpeg_job_data->src_reproc_frame);
   1822     if (NO_ERROR != ret) {
   1823         return ret;
   1824     }
   1825 
   1826     if(NULL == main_frame){
   1827        ALOGE("%s : Main frame is NULL", __func__);
   1828        return BAD_VALUE;
   1829     }
   1830 
   1831     if(NULL == thumb_frame){
   1832        CDBG("%s : Thumbnail frame does not exist", __func__);
   1833     }
   1834 
   1835     QCameraMemory *memObj = (QCameraMemory *)main_frame->mem_info;
   1836     if (NULL == memObj) {
   1837         ALOGE("%s : Memeory Obj of main frame is NULL", __func__);
   1838         return NO_MEMORY;
   1839     }
   1840 
   1841     // dump snapshot frame if enabled
   1842     m_parent->dumpFrameToFile(main_stream, main_frame, QCAMERA_DUMP_FRM_SNAPSHOT);
   1843 
   1844     // send upperlayer callback for raw image
   1845     camera_memory_t *mem = memObj->getMemory(main_frame->buf_idx, false);
   1846     if (NULL != m_parent->mDataCb &&
   1847         m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE) > 0) {
   1848         qcamera_callback_argm_t cbArg;
   1849         memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
   1850         cbArg.cb_type = QCAMERA_DATA_CALLBACK;
   1851         cbArg.msg_type = CAMERA_MSG_RAW_IMAGE;
   1852         cbArg.data = mem;
   1853         cbArg.index = 1;
   1854         m_parent->m_cbNotifier.notifyCallback(cbArg);
   1855     }
   1856     if (NULL != m_parent->mNotifyCb &&
   1857         m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE_NOTIFY) > 0) {
   1858         qcamera_callback_argm_t cbArg;
   1859         memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
   1860         cbArg.cb_type = QCAMERA_NOTIFY_CALLBACK;
   1861         cbArg.msg_type = CAMERA_MSG_RAW_IMAGE_NOTIFY;
   1862         cbArg.ext1 = 0;
   1863         cbArg.ext2 = 0;
   1864         m_parent->m_cbNotifier.notifyCallback(cbArg);
   1865     }
   1866 
   1867     if (mJpegClientHandle <= 0) {
   1868         ALOGE("%s: Error: bug here, mJpegClientHandle is 0", __func__);
   1869         return UNKNOWN_ERROR;
   1870     }
   1871 
   1872     if (needNewSess) {
   1873         // create jpeg encoding session
   1874         mm_jpeg_encode_params_t encodeParam;
   1875         memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t));
   1876         ret = getJpegEncodingConfig(encodeParam, main_stream, thumb_stream);
   1877         if (ret != NO_ERROR) {
   1878             ALOGE("%s: error getting encoding config", __func__);
   1879             return ret;
   1880         }
   1881         CDBG_HIGH("[KPI Perf] %s : call jpeg create_session", __func__);
   1882         ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId);
   1883         if (ret != NO_ERROR) {
   1884             ALOGE("%s: error creating a new jpeg encoding session", __func__);
   1885             return ret;
   1886         }
   1887         needNewSess = FALSE;
   1888     }
   1889     // Fill in new job
   1890     memset(&jpg_job, 0, sizeof(mm_jpeg_job_t));
   1891     jpg_job.job_type = JPEG_JOB_TYPE_ENCODE;
   1892     jpg_job.encode_job.session_id = mJpegSessionId;
   1893     jpg_job.encode_job.src_index = (int32_t)main_frame->buf_idx;
   1894     jpg_job.encode_job.dst_index = 0;
   1895 
   1896     if (mJpegMemOpt) {
   1897         jpg_job.encode_job.dst_index = jpg_job.encode_job.src_index;
   1898     } else if (mUseJpegBurst) {
   1899         jpg_job.encode_job.dst_index = -1;
   1900     }
   1901 
   1902     cam_dimension_t src_dim;
   1903     memset(&src_dim, 0, sizeof(cam_dimension_t));
   1904     main_stream->getFrameDimension(src_dim);
   1905 
   1906     bool hdr_output_crop = m_parent->mParameters.isHDROutputCropEnabled();
   1907     bool img_feature_enabled =
   1908             m_parent->mParameters.isUbiFocusEnabled() ||
   1909             m_parent->mParameters.isUbiRefocus() ||
   1910             m_parent->mParameters.isChromaFlashEnabled() ||
   1911             m_parent->mParameters.isOptiZoomEnabled() ||
   1912             m_parent->mParameters.isStillMoreEnabled();
   1913 
   1914     CDBG_HIGH("%s:%d] Crop needed %d", __func__, __LINE__, img_feature_enabled);
   1915     crop.left = 0;
   1916     crop.top = 0;
   1917     crop.height = src_dim.height;
   1918     crop.width = src_dim.width;
   1919 
   1920     param = main_stream->getOutputCrop();
   1921     for (int i = 0; i < param.outputCrop.num_of_streams; i++) {
   1922        if (param.outputCrop.crop_info[i].stream_id
   1923            == main_stream->getMyServerID()) {
   1924                crop = param.outputCrop.crop_info[i].crop;
   1925                main_stream->setCropInfo(crop);
   1926        }
   1927     }
   1928     if (img_feature_enabled) {
   1929         memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
   1930 
   1931         param = main_stream->getImgProp();
   1932         imgProp = param.imgProp;
   1933         main_stream->setCropInfo(imgProp.crop);
   1934         crop = imgProp.crop;
   1935         thumb_stream = NULL; /* use thumbnail from main image */
   1936 
   1937         if ((reproc_stream != NULL) && (m_DataMem == NULL) &&
   1938                 m_parent->mParameters.isUbiRefocus()) {
   1939 
   1940             QCameraHeapMemory* miscBufHandler = reproc_stream->getMiscBuf();
   1941             cam_misc_buf_t* refocusResult =
   1942                     reinterpret_cast<cam_misc_buf_t *>(miscBufHandler->getPtr(0));
   1943             uint32_t resultSize = refocusResult->header_size +
   1944                     refocusResult->width * refocusResult->height;
   1945             camera_memory_t *dataMem = m_parent->mGetMemory(-1, resultSize,
   1946                     1, m_parent->mCallbackCookie);
   1947 
   1948             CDBG_HIGH("%s:%d] Refocus result header %u dims %dx%d", __func__, __LINE__,
   1949                     resultSize, refocusResult->width, refocusResult->height);
   1950 
   1951             if (dataMem && dataMem->data) {
   1952                 memcpy(dataMem->data, refocusResult->data, resultSize);
   1953                 //save mem pointer for depth map
   1954                 m_DataMem = dataMem;
   1955             }
   1956         }
   1957     } else if ((reproc_stream != NULL) && (m_parent->mParameters.isTruePortraitEnabled())) {
   1958 
   1959         QCameraHeapMemory* miscBufHandler = reproc_stream->getMiscBuf();
   1960         cam_misc_buf_t* tpResult =
   1961                 reinterpret_cast<cam_misc_buf_t *>(miscBufHandler->getPtr(0));
   1962         uint32_t tpMetaSize = tpResult->header_size + tpResult->width * tpResult->height;
   1963 
   1964         CDBG_HIGH("%s:%d] True portrait result header %d% dims dx%d", __func__, __LINE__,
   1965                 tpMetaSize, tpResult->width, tpResult->height);
   1966 
   1967         CAM_DUMP_TO_FILE(QCAMERA_DUMP_FRM_LOCATION"tp", "bm", -1, "y",
   1968                 &tpResult->data, tpMetaSize);
   1969     }
   1970 
   1971     cam_dimension_t dst_dim;
   1972 
   1973     if (hdr_output_crop && crop.height) {
   1974         dst_dim.height = crop.height;
   1975     } else {
   1976         dst_dim.height = src_dim.height;
   1977     }
   1978     if (hdr_output_crop && crop.width) {
   1979         dst_dim.width = crop.width;
   1980     } else {
   1981         dst_dim.width = src_dim.width;
   1982     }
   1983 
   1984     // main dim
   1985     jpg_job.encode_job.main_dim.src_dim = src_dim;
   1986     jpg_job.encode_job.main_dim.dst_dim = dst_dim;
   1987     jpg_job.encode_job.main_dim.crop = crop;
   1988 
   1989     // get 3a sw version info
   1990     cam_q3a_version_t sw_version =
   1991         m_parent->getCamHalCapabilities()->q3a_version;
   1992 
   1993     // get exif data
   1994     QCameraExif *pJpegExifObj = m_parent->getExifData();
   1995     jpeg_job_data->pJpegExifObj = pJpegExifObj;
   1996     if (pJpegExifObj != NULL) {
   1997         jpg_job.encode_job.exif_info.exif_data = pJpegExifObj->getEntries();
   1998         jpg_job.encode_job.exif_info.numOfEntries =
   1999             pJpegExifObj->getNumOfEntries();
   2000         jpg_job.encode_job.exif_info.debug_data.sw_3a_version[0] =
   2001             sw_version.major_version;
   2002         jpg_job.encode_job.exif_info.debug_data.sw_3a_version[1] =
   2003             sw_version.minor_version;
   2004         jpg_job.encode_job.exif_info.debug_data.sw_3a_version[2] =
   2005             sw_version.patch_version;
   2006         jpg_job.encode_job.exif_info.debug_data.sw_3a_version[3] =
   2007             sw_version.new_feature_des;
   2008     }
   2009 
   2010     // set rotation only when no online rotation or offline pp rotation is done before
   2011     if (!m_parent->needRotationReprocess()) {
   2012         jpg_job.encode_job.rotation = jpeg_rotation;
   2013     }
   2014     CDBG_HIGH("%s: jpeg rotation is set to %d", __func__, jpg_job.encode_job.rotation);
   2015 
   2016     // thumbnail dim
   2017     if (m_bThumbnailNeeded == TRUE) {
   2018         m_parent->getThumbnailSize(jpg_job.encode_job.thumb_dim.dst_dim);
   2019 
   2020         if (thumb_stream == NULL) {
   2021             // need jpeg thumbnail, but no postview/preview stream exists
   2022             // we use the main stream/frame to encode thumbnail
   2023             thumb_stream = main_stream;
   2024             thumb_frame = main_frame;
   2025             if (m_parent->needRotationReprocess() &&
   2026                 ((90 == jpeg_rotation) || (270 == jpeg_rotation))) {
   2027                 // swap thumbnail dimensions
   2028                 cam_dimension_t tmp_dim = jpg_job.encode_job.thumb_dim.dst_dim;
   2029                 jpg_job.encode_job.thumb_dim.dst_dim.width = tmp_dim.height;
   2030                 jpg_job.encode_job.thumb_dim.dst_dim.height = tmp_dim.width;
   2031             }
   2032         }
   2033 
   2034         memset(&src_dim, 0, sizeof(cam_dimension_t));
   2035         thumb_stream->getFrameDimension(src_dim);
   2036         jpg_job.encode_job.thumb_dim.src_dim = src_dim;
   2037 
   2038         // crop is the same if frame is the same
   2039         if (thumb_frame != main_frame) {
   2040             crop.left = 0;
   2041             crop.top = 0;
   2042             crop.height = src_dim.height;
   2043             crop.width = src_dim.width;
   2044 
   2045             param = thumb_stream->getOutputCrop();
   2046             for (int i = 0; i < param.outputCrop.num_of_streams; i++) {
   2047                if (param.outputCrop.crop_info[i].stream_id
   2048                    == thumb_stream->getMyServerID()) {
   2049                        crop = param.outputCrop.crop_info[i].crop;
   2050                        thumb_stream->setCropInfo(crop);
   2051                }
   2052            }
   2053         }
   2054 
   2055 
   2056         jpg_job.encode_job.thumb_dim.crop = crop;
   2057         if (thumb_frame != NULL) {
   2058             jpg_job.encode_job.thumb_index = thumb_frame->buf_idx;
   2059         }
   2060         CDBG_HIGH("%s, thumbnail src w/h (%dx%d), dst w/h (%dx%d)", __func__,
   2061             jpg_job.encode_job.thumb_dim.src_dim.width,
   2062             jpg_job.encode_job.thumb_dim.src_dim.height,
   2063             jpg_job.encode_job.thumb_dim.dst_dim.width,
   2064             jpg_job.encode_job.thumb_dim.dst_dim.height);
   2065     }
   2066 
   2067     if (thumb_frame != NULL) {
   2068         // dump thumbnail frame if enabled
   2069         m_parent->dumpFrameToFile(thumb_stream, thumb_frame, QCAMERA_DUMP_FRM_THUMBNAIL);
   2070     }
   2071 
   2072     if (jpeg_job_data->metadata != NULL) {
   2073         // fill in meta data frame ptr
   2074         jpg_job.encode_job.p_metadata = jpeg_job_data->metadata;
   2075     }
   2076 
   2077     jpg_job.encode_job.hal_version = CAM_HAL_V1;
   2078     m_parent->mExifParams.sensor_params.sens_type = m_parent->getSensorType();
   2079     jpg_job.encode_job.cam_exif_params = m_parent->mExifParams;
   2080     jpg_job.encode_job.mobicat_mask = m_parent->mParameters.getMobicatMask();
   2081 
   2082 
   2083     if (NULL != jpg_job.encode_job.p_metadata && (jpg_job.encode_job.mobicat_mask > 0)) {
   2084 
   2085        /* Save a copy of mobicat params */
   2086        jpg_job.encode_job.p_metadata->is_mobicat_aec_params_valid =
   2087             jpg_job.encode_job.cam_exif_params.cam_3a_params_valid;
   2088 
   2089        if (jpg_job.encode_job.cam_exif_params.cam_3a_params_valid) {
   2090             jpg_job.encode_job.p_metadata->mobicat_aec_params =
   2091                 jpg_job.encode_job.cam_exif_params.cam_3a_params;
   2092        }
   2093 
   2094        /* Save a copy of 3A debug params */
   2095         jpg_job.encode_job.p_metadata->is_statsdebug_ae_params_valid =
   2096             jpg_job.encode_job.cam_exif_params.ae_debug_params_valid;
   2097         jpg_job.encode_job.p_metadata->is_statsdebug_awb_params_valid =
   2098             jpg_job.encode_job.cam_exif_params.awb_debug_params_valid;
   2099         jpg_job.encode_job.p_metadata->is_statsdebug_af_params_valid =
   2100             jpg_job.encode_job.cam_exif_params.af_debug_params_valid;
   2101         jpg_job.encode_job.p_metadata->is_statsdebug_asd_params_valid =
   2102             jpg_job.encode_job.cam_exif_params.asd_debug_params_valid;
   2103         jpg_job.encode_job.p_metadata->is_statsdebug_stats_params_valid =
   2104             jpg_job.encode_job.cam_exif_params.stats_debug_params_valid;
   2105 
   2106         if (jpg_job.encode_job.cam_exif_params.ae_debug_params_valid) {
   2107             jpg_job.encode_job.p_metadata->statsdebug_ae_data =
   2108                 jpg_job.encode_job.cam_exif_params.ae_debug_params;
   2109         }
   2110         if (jpg_job.encode_job.cam_exif_params.awb_debug_params_valid) {
   2111             jpg_job.encode_job.p_metadata->statsdebug_awb_data =
   2112                 jpg_job.encode_job.cam_exif_params.awb_debug_params;
   2113         }
   2114         if (jpg_job.encode_job.cam_exif_params.af_debug_params_valid) {
   2115             jpg_job.encode_job.p_metadata->statsdebug_af_data =
   2116                 jpg_job.encode_job.cam_exif_params.af_debug_params;
   2117         }
   2118         if (jpg_job.encode_job.cam_exif_params.asd_debug_params_valid) {
   2119             jpg_job.encode_job.p_metadata->statsdebug_asd_data =
   2120                 jpg_job.encode_job.cam_exif_params.asd_debug_params;
   2121         }
   2122         if (jpg_job.encode_job.cam_exif_params.stats_debug_params_valid) {
   2123             jpg_job.encode_job.p_metadata->statsdebug_stats_buffer_data =
   2124                 jpg_job.encode_job.cam_exif_params.stats_debug_params;
   2125         }
   2126     }
   2127 
   2128     /* Init the QTable */
   2129     for (int i = 0; i < QTABLE_MAX; i++) {
   2130         jpg_job.encode_job.qtable_set[i] = 0;
   2131     }
   2132 
   2133     CDBG_HIGH("[KPI Perf] %s : PROFILE_JPEG_JOB_START", __func__);
   2134     ret = mJpegHandle.start_job(&jpg_job, &jobId);
   2135     if (ret == NO_ERROR) {
   2136         // remember job info
   2137         jpeg_job_data->jobId = jobId;
   2138     }
   2139 
   2140     return ret;
   2141 }
   2142 
   2143 /*===========================================================================
   2144  * FUNCTION   : processRawImageImpl
   2145  *
   2146  * DESCRIPTION: function to send raw image to upper layer
   2147  *
   2148  * PARAMETERS :
   2149  *   @recvd_frame   : frame to be encoded
   2150  *
   2151  * RETURN     : int32_t type of status
   2152  *              NO_ERROR  -- success
   2153  *              none-zero failure code
   2154  *==========================================================================*/
   2155 int32_t QCameraPostProcessor::processRawImageImpl(mm_camera_super_buf_t *recvd_frame)
   2156 {
   2157     int32_t rc = NO_ERROR;
   2158 
   2159     QCameraChannel *pChannel = m_parent->getChannelByHandle(recvd_frame->ch_id);
   2160     QCameraStream *pStream = NULL;
   2161     mm_camera_buf_def_t *frame = NULL;
   2162     // check reprocess channel if not found
   2163     if (pChannel == NULL) {
   2164         for (int8_t i = 0; i < mTotalNumReproc; i++) {
   2165             if ((mPPChannels[i] != NULL) &&
   2166                     (mPPChannels[i]->getMyHandle() == recvd_frame->ch_id)) {
   2167                 pChannel = mPPChannels[i];
   2168                 break;
   2169             }
   2170         }
   2171     }
   2172     if (pChannel == NULL) {
   2173         ALOGE("%s:%d] No corresponding channel (ch_id = %d) exist, return here",
   2174               __func__, __LINE__, recvd_frame->ch_id);
   2175         return BAD_VALUE;
   2176     }
   2177 
   2178     // find snapshot frame
   2179     for (uint32_t i = 0; i < recvd_frame->num_bufs; i++) {
   2180         QCameraStream *pCurStream =
   2181             pChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id);
   2182         if (pCurStream != NULL) {
   2183             if (pCurStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
   2184                 pCurStream->isTypeOf(CAM_STREAM_TYPE_RAW) ||
   2185                 pCurStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
   2186                 pCurStream->isOrignalTypeOf(CAM_STREAM_TYPE_RAW)) {
   2187                 pStream = pCurStream;
   2188                 frame = recvd_frame->bufs[i];
   2189                 break;
   2190             }
   2191         }
   2192     }
   2193 
   2194     if ( NULL == frame ) {
   2195         ALOGE("%s: No valid raw buffer", __func__);
   2196         return BAD_VALUE;
   2197     }
   2198 
   2199     QCameraMemory *rawMemObj = (QCameraMemory *)frame->mem_info;
   2200     bool zslChannelUsed = m_parent->isZSLMode() &&
   2201             ( pChannel != mPPChannels[0] );
   2202     camera_memory_t *raw_mem = NULL;
   2203 
   2204     if (rawMemObj != NULL) {
   2205         if (zslChannelUsed) {
   2206             raw_mem = rawMemObj->getMemory(frame->buf_idx, false);
   2207         } else {
   2208             raw_mem = m_parent->mGetMemory(-1,
   2209                                            frame->frame_len,
   2210                                            1,
   2211                                            m_parent->mCallbackCookie);
   2212             if (NULL == raw_mem) {
   2213                 ALOGE("%s : Not enough memory for RAW cb ", __func__);
   2214                 return NO_MEMORY;
   2215             }
   2216             memcpy(raw_mem->data, frame->buffer, frame->frame_len);
   2217         }
   2218     }
   2219 
   2220     if (NULL != rawMemObj && NULL != raw_mem) {
   2221         // dump frame into file
   2222         if (frame->stream_type == CAM_STREAM_TYPE_SNAPSHOT ||
   2223             pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT)) {
   2224             // for YUV422 NV16 case
   2225             m_parent->dumpFrameToFile(pStream, frame, QCAMERA_DUMP_FRM_SNAPSHOT);
   2226         } else {
   2227             //Received RAW snapshot taken notification
   2228             m_parent->dumpFrameToFile(pStream, frame, QCAMERA_DUMP_FRM_RAW);
   2229 
   2230             if(true == m_parent->m_bIntRawEvtPending) {
   2231               //Sending RAW snapshot taken notification to HAL
   2232               memset(&m_dst_dim, 0, sizeof(m_dst_dim));
   2233               pStream->getFrameDimension(m_dst_dim);
   2234               pthread_mutex_lock(&m_parent->m_int_lock);
   2235               pthread_cond_signal(&m_parent->m_int_cond);
   2236               pthread_mutex_unlock(&m_parent->m_int_lock);
   2237               raw_mem->release(raw_mem);
   2238               return rc;
   2239             }
   2240         }
   2241 
   2242         // send data callback / notify for RAW_IMAGE
   2243         if (NULL != m_parent->mDataCb &&
   2244             m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE) > 0) {
   2245             qcamera_callback_argm_t cbArg;
   2246             memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
   2247             cbArg.cb_type = QCAMERA_DATA_CALLBACK;
   2248             cbArg.msg_type = CAMERA_MSG_RAW_IMAGE;
   2249             cbArg.data = raw_mem;
   2250             cbArg.index = 0;
   2251             m_parent->m_cbNotifier.notifyCallback(cbArg);
   2252         }
   2253         if (NULL != m_parent->mNotifyCb &&
   2254             m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE_NOTIFY) > 0) {
   2255             qcamera_callback_argm_t cbArg;
   2256             memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
   2257             cbArg.cb_type = QCAMERA_NOTIFY_CALLBACK;
   2258             cbArg.msg_type = CAMERA_MSG_RAW_IMAGE_NOTIFY;
   2259             cbArg.ext1 = 0;
   2260             cbArg.ext2 = 0;
   2261             m_parent->m_cbNotifier.notifyCallback(cbArg);
   2262         }
   2263 
   2264         if ((m_parent->mDataCb != NULL) &&
   2265             m_parent->msgTypeEnabledWithLock(CAMERA_MSG_COMPRESSED_IMAGE) > 0) {
   2266             qcamera_release_data_t release_data;
   2267             memset(&release_data, 0, sizeof(qcamera_release_data_t));
   2268             if ( zslChannelUsed ) {
   2269                 release_data.frame = recvd_frame;
   2270             } else {
   2271                 release_data.data = raw_mem;
   2272             }
   2273             rc = sendDataNotify(CAMERA_MSG_COMPRESSED_IMAGE,
   2274                                 raw_mem,
   2275                                 0,
   2276                                 NULL,
   2277                                 &release_data);
   2278         } else {
   2279             raw_mem->release(raw_mem);
   2280         }
   2281     } else {
   2282         ALOGE("%s: Cannot get raw mem", __func__);
   2283         rc = UNKNOWN_ERROR;
   2284     }
   2285 
   2286     return rc;
   2287 }
   2288 
   2289 /*===========================================================================
   2290  * FUNCTION   : dataSaveRoutine
   2291  *
   2292  * DESCRIPTION: data saving routine
   2293  *
   2294  * PARAMETERS :
   2295  *   @data    : user data ptr (QCameraPostProcessor)
   2296  *
   2297  * RETURN     : None
   2298  *==========================================================================*/
   2299 void *QCameraPostProcessor::dataSaveRoutine(void *data)
   2300 {
   2301     int running = 1;
   2302     int ret;
   2303     uint8_t is_active = FALSE;
   2304     QCameraPostProcessor *pme = (QCameraPostProcessor *)data;
   2305     QCameraCmdThread *cmdThread = &pme->m_saveProcTh;
   2306     cmdThread->setName("CAM_JpegSave");
   2307     char saveName[PROPERTY_VALUE_MAX];
   2308 
   2309     CDBG_HIGH("%s: E", __func__);
   2310     do {
   2311         do {
   2312             ret = cam_sem_wait(&cmdThread->cmd_sem);
   2313             if (ret != 0 && errno != EINVAL) {
   2314                 ALOGE("%s: cam_sem_wait error (%s)",
   2315                            __func__, strerror(errno));
   2316                 return NULL;
   2317             }
   2318         } while (ret != 0);
   2319 
   2320         // we got notified about new cmd avail in cmd queue
   2321         camera_cmd_type_t cmd = cmdThread->getCmd();
   2322         switch (cmd) {
   2323         case CAMERA_CMD_TYPE_START_DATA_PROC:
   2324             CDBG_HIGH("%s: start data proc", __func__);
   2325             is_active = TRUE;
   2326             pme->m_inputSaveQ.init();
   2327             break;
   2328         case CAMERA_CMD_TYPE_STOP_DATA_PROC:
   2329             {
   2330                 CDBG_HIGH("%s: stop data proc", __func__);
   2331                 is_active = FALSE;
   2332 
   2333                 // flush input save Queue
   2334                 pme->m_inputSaveQ.flush();
   2335 
   2336                 // signal cmd is completed
   2337                 cam_sem_post(&cmdThread->sync_sem);
   2338             }
   2339             break;
   2340         case CAMERA_CMD_TYPE_DO_NEXT_JOB:
   2341             {
   2342                 CDBG_HIGH("%s: Do next job, active is %d", __func__, is_active);
   2343 
   2344                 qcamera_jpeg_evt_payload_t *job_data = (qcamera_jpeg_evt_payload_t *) pme->m_inputSaveQ.dequeue();
   2345                 if (job_data == NULL) {
   2346                     ALOGE("%s: Invalid jpeg event data", __func__);
   2347                     continue;
   2348                 }
   2349 
   2350                 pme->m_ongoingJpegQ.flushNodes(matchJobId, (void*)&job_data->jobId);
   2351 
   2352                 CDBG_HIGH("[KPI Perf] %s : jpeg job %d", __func__, job_data->jobId);
   2353 
   2354                 if (is_active == TRUE) {
   2355                     memset(saveName, '\0', sizeof(saveName));
   2356                     snprintf(saveName,
   2357                              sizeof(saveName),
   2358                              QCameraPostProcessor::STORE_LOCATION,
   2359                              pme->mSaveFrmCnt);
   2360 
   2361                     int file_fd = open(saveName, O_RDWR | O_CREAT, 0655);
   2362                     if (file_fd >= 0) {
   2363                         ssize_t written_len = write(file_fd, job_data->out_data.buf_vaddr,
   2364                                 job_data->out_data.buf_filled_len);
   2365                         if ((ssize_t)job_data->out_data.buf_filled_len != written_len) {
   2366                             ALOGE("%s: Failed save complete data %d bytes "
   2367                                   "written instead of %d bytes!",
   2368                                   __func__, written_len,
   2369                                   job_data->out_data.buf_filled_len);
   2370                         } else {
   2371                             CDBG_HIGH("%s: written number of bytes %d\n",
   2372                                 __func__, written_len);
   2373                         }
   2374 
   2375                         close(file_fd);
   2376                     } else {
   2377                         ALOGE("%s: fail t open file for saving", __func__);
   2378                     }
   2379                     pme->mSaveFrmCnt++;
   2380 
   2381                     camera_memory_t* jpeg_mem = pme->m_parent->mGetMemory(-1,
   2382                                                          strlen(saveName),
   2383                                                          1,
   2384                                                          pme->m_parent->mCallbackCookie);
   2385                     if (NULL == jpeg_mem) {
   2386                         ret = NO_MEMORY;
   2387                         ALOGE("%s : getMemory for jpeg, ret = NO_MEMORY", __func__);
   2388                         goto end;
   2389                     }
   2390                     memcpy(jpeg_mem->data, saveName, strlen(saveName));
   2391 
   2392                     CDBG_HIGH("%s : Calling upperlayer callback to store JPEG image", __func__);
   2393                     qcamera_release_data_t release_data;
   2394                     memset(&release_data, 0, sizeof(qcamera_release_data_t));
   2395                     release_data.data = jpeg_mem;
   2396                     release_data.unlinkFile = true;
   2397                     CDBG_HIGH("[KPI Perf] %s: PROFILE_JPEG_CB ",__func__);
   2398                     ret = pme->sendDataNotify(CAMERA_MSG_COMPRESSED_IMAGE,
   2399                                         jpeg_mem,
   2400                                         0,
   2401                                         NULL,
   2402                                         &release_data);
   2403                 }
   2404 
   2405 end:
   2406                 free(job_data);
   2407             }
   2408             break;
   2409         case CAMERA_CMD_TYPE_EXIT:
   2410             CDBG_HIGH("%s : save thread exit", __func__);
   2411             running = 0;
   2412             break;
   2413         default:
   2414             break;
   2415         }
   2416     } while (running);
   2417     CDBG_HIGH("%s: X", __func__);
   2418     return NULL;
   2419 }
   2420 
   2421 /*===========================================================================
   2422  * FUNCTION   : dataProcessRoutine
   2423  *
   2424  * DESCRIPTION: data process routine that handles input data either from input
   2425  *              Jpeg Queue to do jpeg encoding, or from input PP Queue to do
   2426  *              reprocess.
   2427  *
   2428  * PARAMETERS :
   2429  *   @data    : user data ptr (QCameraPostProcessor)
   2430  *
   2431  * RETURN     : None
   2432  *==========================================================================*/
   2433 void *QCameraPostProcessor::dataProcessRoutine(void *data)
   2434 {
   2435     int running = 1;
   2436     int ret;
   2437     uint8_t is_active = FALSE;
   2438     QCameraPostProcessor *pme = (QCameraPostProcessor *)data;
   2439     QCameraCmdThread *cmdThread = &pme->m_dataProcTh;
   2440     cmdThread->setName("CAM_JpegProc");
   2441 
   2442     CDBG_HIGH("%s: E", __func__);
   2443     do {
   2444         do {
   2445             ret = cam_sem_wait(&cmdThread->cmd_sem);
   2446             if (ret != 0 && errno != EINVAL) {
   2447                 ALOGE("%s: cam_sem_wait error (%s)",
   2448                            __func__, strerror(errno));
   2449                 return NULL;
   2450             }
   2451         } while (ret != 0);
   2452 
   2453         // we got notified about new cmd avail in cmd queue
   2454         camera_cmd_type_t cmd = cmdThread->getCmd();
   2455         switch (cmd) {
   2456         case CAMERA_CMD_TYPE_START_DATA_PROC:
   2457             CDBG_HIGH("%s: start data proc", __func__);
   2458             is_active = TRUE;
   2459 
   2460             pme->m_ongoingPPQ.init();
   2461             pme->m_inputJpegQ.init();
   2462             pme->m_inputPPQ.init();
   2463             pme->m_inputRawQ.init();
   2464 
   2465             pme->m_saveProcTh.sendCmd(CAMERA_CMD_TYPE_START_DATA_PROC,
   2466                                       FALSE,
   2467                                       FALSE);
   2468 
   2469             // signal cmd is completed
   2470             cam_sem_post(&cmdThread->sync_sem);
   2471 
   2472             break;
   2473         case CAMERA_CMD_TYPE_STOP_DATA_PROC:
   2474             {
   2475                 CDBG_HIGH("%s: stop data proc", __func__);
   2476                 is_active = FALSE;
   2477 
   2478                 pme->m_saveProcTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC,
   2479                                            TRUE,
   2480                                            TRUE);
   2481                 // cancel all ongoing jpeg jobs
   2482                 qcamera_jpeg_data_t *jpeg_job =
   2483                     (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
   2484                 while (jpeg_job != NULL) {
   2485                     pme->mJpegHandle.abort_job(jpeg_job->jobId);
   2486 
   2487                     pme->releaseJpegJobData(jpeg_job);
   2488                     free(jpeg_job);
   2489 
   2490                     jpeg_job = (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
   2491                 }
   2492 
   2493                 // destroy jpeg encoding session
   2494                 if ( 0 < pme->mJpegSessionId ) {
   2495                     pme->mJpegHandle.destroy_session(pme->mJpegSessionId);
   2496                     pme->mJpegSessionId = 0;
   2497                 }
   2498 
   2499                 // free jpeg out buf and exif obj
   2500                 FREE_JPEG_OUTPUT_BUFFER(pme->m_pJpegOutputMem,
   2501                     pme->m_JpegOutputMemCount);
   2502 
   2503                 if (pme->m_pJpegExifObj != NULL) {
   2504                     delete pme->m_pJpegExifObj;
   2505                     pme->m_pJpegExifObj = NULL;
   2506                 }
   2507 
   2508                 // flush ongoing postproc Queue
   2509                 pme->m_ongoingPPQ.flush();
   2510 
   2511                 // flush input jpeg Queue
   2512                 pme->m_inputJpegQ.flush();
   2513 
   2514                 // flush input Postproc Queue
   2515                 pme->m_inputPPQ.flush();
   2516 
   2517                 // flush input raw Queue
   2518                 pme->m_inputRawQ.flush();
   2519 
   2520                 // signal cmd is completed
   2521                 cam_sem_post(&cmdThread->sync_sem);
   2522 
   2523                 pme->mNewJpegSessionNeeded = true;
   2524             }
   2525             break;
   2526         case CAMERA_CMD_TYPE_DO_NEXT_JOB:
   2527             {
   2528                 CDBG_HIGH("%s: Do next job, active is %d", __func__, is_active);
   2529                 if (is_active == TRUE) {
   2530                     qcamera_jpeg_data_t *jpeg_job =
   2531                         (qcamera_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
   2532 
   2533                     if (NULL != jpeg_job) {
   2534                         // To avoid any race conditions,
   2535                         // sync any stream specific parameters here.
   2536                         pme->syncStreamParams(jpeg_job->src_frame, NULL);
   2537 
   2538                         // add into ongoing jpeg job Q
   2539                         if (pme->m_ongoingJpegQ.enqueue((void *)jpeg_job)) {
   2540                             ret = pme->encodeData(jpeg_job,
   2541                                       pme->mNewJpegSessionNeeded);
   2542                             if (NO_ERROR != ret) {
   2543                                 // dequeue the last one
   2544                                 pme->m_ongoingJpegQ.dequeue(false);
   2545                                 pme->releaseJpegJobData(jpeg_job);
   2546                                 free(jpeg_job);
   2547                                 jpeg_job = NULL;
   2548                                 pme->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
   2549                             }
   2550                         } else {
   2551                             CDBG_HIGH("%s : m_ongoingJpegQ is not active!!!", __func__);
   2552                             pme->releaseJpegJobData(jpeg_job);
   2553                             free(jpeg_job);
   2554                             jpeg_job = NULL;
   2555                         }
   2556                     }
   2557 
   2558 
   2559                     // process raw data if any
   2560                     mm_camera_super_buf_t *super_buf =
   2561                         (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue();
   2562 
   2563                     if (NULL != super_buf) {
   2564                         //play shutter sound
   2565                         pme->m_parent->playShutter();
   2566                         ret = pme->processRawImageImpl(super_buf);
   2567                         if (NO_ERROR != ret) {
   2568                             pme->releaseSuperBuf(super_buf);
   2569                             free(super_buf);
   2570                             pme->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
   2571                         }
   2572                     }
   2573 
   2574                     ret = pme->doReprocess();
   2575                     if (NO_ERROR != ret) {
   2576                         pme->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
   2577                     } else {
   2578                         ret = pme->stopCapture();
   2579                     }
   2580 
   2581                 } else {
   2582                     // not active, simply return buf and do no op
   2583                     qcamera_jpeg_data_t *jpeg_data =
   2584                         (qcamera_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
   2585                     if (NULL != jpeg_data) {
   2586                         pme->releaseJpegJobData(jpeg_data);
   2587                         free(jpeg_data);
   2588                     }
   2589                     mm_camera_super_buf_t *super_buf =
   2590                         (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue();
   2591                     if (NULL != super_buf) {
   2592                         pme->releaseSuperBuf(super_buf);
   2593                         free(super_buf);
   2594                     }
   2595 
   2596                     // flush input Postproc Queue
   2597                     pme->m_inputPPQ.flush();
   2598                 }
   2599             }
   2600             break;
   2601         case CAMERA_CMD_TYPE_EXIT:
   2602             running = 0;
   2603             break;
   2604         default:
   2605             break;
   2606         }
   2607     } while (running);
   2608     CDBG_HIGH("%s: X", __func__);
   2609     return NULL;
   2610 }
   2611 
   2612 /*===========================================================================
   2613  * FUNCTION   : doReprocess
   2614  *
   2615  * DESCRIPTION: Trigger channel reprocessing
   2616  *
   2617  * PARAMETERS :None
   2618  *
   2619  * RETURN     : int32_t type of status
   2620  *                    NO_ERROR  -- success
   2621  *                    none-zero failure code
   2622  *==========================================================================*/
   2623 int32_t QCameraPostProcessor::doReprocess()
   2624 {
   2625     int32_t ret = NO_ERROR;
   2626     QCameraChannel *m_pSrcChannel;
   2627     QCameraStream *pMetaStream = NULL;
   2628     uint8_t meta_buf_index = 0;
   2629     mm_camera_buf_def_t *meta_buf = NULL;
   2630     bool found_meta = FALSE;
   2631 
   2632     qcamera_pp_request_t *ppreq_job = (qcamera_pp_request_t *)m_inputPPQ.peek();
   2633     if ((ppreq_job == NULL) || (ppreq_job->src_frame == NULL)) {
   2634         return ret;
   2635     }
   2636 
   2637     if (!validatePostProcess(ppreq_job->src_frame)) {
   2638         return ret;
   2639     }
   2640 
   2641     ppreq_job = (qcamera_pp_request_t *)m_inputPPQ.dequeue();
   2642     if (ppreq_job == NULL || ppreq_job->src_frame == NULL ||
   2643             ppreq_job->src_reproc_frame == NULL) {
   2644         return ret;
   2645     }
   2646 
   2647     mm_camera_super_buf_t *src_frame = ppreq_job->src_frame;
   2648     mm_camera_super_buf_t *src_reproc_frame = ppreq_job->src_reproc_frame;
   2649     int8_t mCurReprocCount = ppreq_job->reprocCount;
   2650 
   2651     CDBG("%s: frame = %p src_frame = %p mCurReprocCount = %d",__func__,
   2652             src_frame,src_reproc_frame,mCurReprocCount);
   2653 
   2654     // find meta data stream and index of meta data frame in the superbuf
   2655     for (int8_t j = 0; j < mTotalNumReproc; j++) {
   2656         uint32_t i;
   2657         m_pSrcChannel = mPPChannels[j]->getSrcChannel();
   2658         if (m_pSrcChannel == NULL)
   2659             continue;
   2660         for (i = 0; i < src_reproc_frame->num_bufs; i++) {
   2661             QCameraStream *pStream =
   2662                     m_pSrcChannel->getStreamByHandle(src_reproc_frame->bufs[i]->stream_id);
   2663             if (pStream != NULL && pStream->isTypeOf(CAM_STREAM_TYPE_METADATA)) {
   2664                 meta_buf_index = (uint8_t) src_reproc_frame->bufs[i]->buf_idx;
   2665                 pMetaStream = pStream;
   2666                 meta_buf = src_reproc_frame->bufs[i];
   2667                 break;
   2668             }
   2669         }
   2670         if (i < src_reproc_frame->num_bufs) {
   2671             CDBG(" %s: Found Meta data info for reprocessing index = %d", __func__,
   2672                     (int)meta_buf_index);
   2673             break;
   2674         }
   2675     }
   2676 
   2677     qcamera_pp_data_t *pp_job =
   2678             (qcamera_pp_data_t *)malloc(sizeof(qcamera_pp_data_t));
   2679     if (pp_job != NULL) {
   2680         syncStreamParams(src_frame, src_reproc_frame);
   2681         memset(pp_job, 0, sizeof(qcamera_pp_data_t));
   2682         if (mPPChannels[mCurReprocCount] != NULL) {
   2683             // add into ongoing PP job Q
   2684             pp_job->src_frame = src_frame;
   2685             pp_job->src_reproc_frame = src_reproc_frame;
   2686             pp_job->reprocCount = (int8_t) (mCurReprocCount + 1);
   2687 
   2688             if (m_parent->isRegularCapture()) {
   2689                 if ((NULL != pp_job->src_frame) &&
   2690                     (0 < pp_job->src_frame->num_bufs)) {
   2691                     mm_camera_buf_def_t *bufs = NULL;
   2692                     uint32_t num_bufs = pp_job->src_frame->num_bufs;
   2693                     bufs = new mm_camera_buf_def_t[num_bufs];
   2694                     if (NULL == bufs) {
   2695                         ALOGE("%s:Unable to allocate cached buffers",
   2696                             __func__);
   2697                         return NO_MEMORY;
   2698                     }
   2699 
   2700                     for (uint32_t i = 0; i < num_bufs; i++) {
   2701                         bufs[i] = *pp_job->src_frame->bufs[i];
   2702                         pp_job->src_frame->bufs[i] = &bufs[i];
   2703                     }
   2704                     pp_job->src_reproc_bufs = bufs;
   2705                 }
   2706 
   2707                 m_bufCountPPQ++;
   2708 
   2709                 // Don't release source frame after encoding
   2710                 // at this point the source channel will not exist.
   2711                 pp_job->reproc_frame_release = true;
   2712                 if (m_ongoingPPQ.enqueue((void *)pp_job)) {
   2713                     ret = mPPChannels[mCurReprocCount]->doReprocessOffline(pp_job->src_frame,
   2714                             meta_buf);
   2715                 } else {
   2716                     CDBG_HIGH("%s : m_ongoingJpegQ is not active!!!", __func__);
   2717                     releaseOngoingPPData(pp_job, this);
   2718                     free(pp_job);
   2719                     pp_job = NULL;
   2720                 }
   2721             } else {
   2722 
   2723                 m_bufCountPPQ++;
   2724                 if (!m_ongoingPPQ.enqueue((void *)pp_job)) {
   2725                     CDBG_HIGH("%s : m_ongoingJpegQ is not active!!!", __func__);
   2726                     releaseOngoingPPData(pp_job, this);
   2727                     free(pp_job);
   2728                     pp_job = NULL;
   2729                     goto end;
   2730                 }
   2731 
   2732                 int32_t numRequiredPPQBufsForSingleOutput = (int32_t)
   2733                         m_parent->mParameters.getNumberInBufsForSingleShot();
   2734 
   2735                 if (m_bufCountPPQ % numRequiredPPQBufsForSingleOutput == 0) {
   2736                     int32_t extra_pp_job_count =
   2737                             m_parent->mParameters.getNumberOutBufsForSingleShot() -
   2738                             m_parent->mParameters.getNumberInBufsForSingleShot();
   2739 
   2740                     for (int32_t i = 0; i < extra_pp_job_count; i++) {
   2741                         qcamera_pp_data_t *extra_pp_job =
   2742                                 (qcamera_pp_data_t *)calloc(1, sizeof(qcamera_pp_data_t));
   2743                         if (!extra_pp_job) {
   2744                             ALOGE("%s: no mem for qcamera_pp_data_t", __func__);
   2745                             ret = NO_MEMORY;
   2746                             break;
   2747                         }
   2748                         extra_pp_job->reprocCount = pp_job->reprocCount;
   2749                         if (!m_ongoingPPQ.enqueue((void *)extra_pp_job)) {
   2750                             CDBG_HIGH("%s : m_ongoingJpegQ is not active!!!", __func__);
   2751                             releaseOngoingPPData(extra_pp_job, this);
   2752                             free(extra_pp_job);
   2753                             extra_pp_job = NULL;
   2754                             goto end;
   2755                         }
   2756                     }
   2757                 }
   2758 
   2759                 ret = mPPChannels[mCurReprocCount]->doReprocess(pp_job->src_frame,
   2760                         m_parent->mParameters, pMetaStream, meta_buf_index);
   2761             }
   2762         } else {
   2763             ALOGE("%s: Reprocess channel is NULL", __func__);
   2764             if (pp_job != NULL) {
   2765                 free(pp_job);
   2766                 pp_job = NULL;
   2767             }
   2768             releasePPInputData(ppreq_job, this);
   2769             ret = UNKNOWN_ERROR;
   2770         }
   2771     } else {
   2772         ALOGE("%s: no mem for qcamera_pp_data_t", __func__);
   2773         ret = NO_MEMORY;
   2774     }
   2775 
   2776 end:
   2777     free(ppreq_job);
   2778     ppreq_job = NULL;
   2779     return ret;
   2780 }
   2781 
   2782 /*===========================================================================
   2783  * FUNCTION   : getReprocChannel
   2784  *
   2785  * DESCRIPTION:  Returns reprocessing channel handle
   2786  *
   2787  * PARAMETERS : index for reprocessing array
   2788  *
   2789  * RETURN     : QCameraReprocessChannel * type of pointer
   2790                        NULL if no reprocessing channel
   2791  *==========================================================================*/
   2792 QCameraReprocessChannel * QCameraPostProcessor::getReprocChannel(uint8_t index)
   2793 {
   2794     if (index >= mTotalNumReproc) {
   2795         ALOGE("%s: Invalid index value",__func__);
   2796         return NULL;
   2797     }
   2798     return mPPChannels[index];
   2799 }
   2800 
   2801 /*===========================================================================
   2802  * FUNCTION   : stopCapture
   2803  *
   2804  * DESCRIPTION: Trigger image capture stop
   2805  *
   2806  * PARAMETERS :
   2807  * None
   2808  *
   2809  * RETURN     : int32_t type of status
   2810  *              NO_ERROR  -- success
   2811  *              none-zero failure code
   2812  *==========================================================================*/
   2813 int32_t QCameraPostProcessor::stopCapture()
   2814 {
   2815      int rc = NO_ERROR;
   2816 
   2817      if (m_parent->isRegularCapture()) {
   2818         rc = m_parent->processAPI(
   2819                         QCAMERA_SM_EVT_STOP_CAPTURE_CHANNEL,
   2820                         NULL);
   2821      }
   2822 
   2823      return rc;
   2824 }
   2825 
   2826 /*===========================================================================
   2827  * FUNCTION   : getJpegPaddingReq
   2828  *
   2829  * DESCRIPTION: function to add an entry to exif data
   2830  *
   2831  * PARAMETERS :
   2832  *   @padding_info : jpeg specific padding requirement
   2833  *
   2834  * RETURN     : int32_t type of status
   2835  *              NO_ERROR  -- success
   2836  *              none-zero failure code
   2837  *==========================================================================*/
   2838 int32_t QCameraPostProcessor::getJpegPaddingReq(cam_padding_info_t &padding_info)
   2839 {
   2840     // TODO: hardcode for now, needs to query from mm-jpeg-interface
   2841     padding_info.width_padding  = CAM_PAD_NONE;
   2842     padding_info.height_padding  = CAM_PAD_TO_16;
   2843     padding_info.plane_padding  = CAM_PAD_TO_WORD;
   2844     return NO_ERROR;
   2845 }
   2846 
   2847 /*===========================================================================
   2848  * FUNCTION   : setYUVFrameInfo
   2849  *
   2850  * DESCRIPTION: set Raw YUV frame data info for up-layer
   2851  *
   2852  * PARAMETERS :
   2853  *   @frame   : process frame received from mm-camera-interface
   2854  *
   2855  * RETURN     : int32_t type of status
   2856  *              NO_ERROR  -- success
   2857  *              none-zero failure code
   2858  *
   2859  * NOTE       : currently we return frame len, y offset, cbcr offset and frame format
   2860  *==========================================================================*/
   2861 int32_t QCameraPostProcessor::setYUVFrameInfo(mm_camera_super_buf_t *recvd_frame)
   2862 {
   2863     QCameraChannel *pChannel = m_parent->getChannelByHandle(recvd_frame->ch_id);
   2864     // check reprocess channel if not found
   2865     if (pChannel == NULL) {
   2866         for (int8_t i = 0; i < mTotalNumReproc; i++) {
   2867             if ((mPPChannels[i] != NULL) &&
   2868                     (mPPChannels[i]->getMyHandle() == recvd_frame->ch_id)) {
   2869                 pChannel = mPPChannels[i];
   2870                 break;
   2871             }
   2872         }
   2873     }
   2874 
   2875     if (pChannel == NULL) {
   2876         ALOGE("%s:%d] No corresponding channel (ch_id = %d) exist, return here",
   2877               __func__, __LINE__, recvd_frame->ch_id);
   2878         return BAD_VALUE;
   2879     }
   2880 
   2881     // find snapshot frame
   2882     for (uint32_t i = 0; i < recvd_frame->num_bufs; i++) {
   2883         QCameraStream *pStream =
   2884             pChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id);
   2885         if (pStream != NULL) {
   2886             if (pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
   2887                 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT)) {
   2888                 //get the main frame, use stream info
   2889                 cam_frame_len_offset_t frame_offset;
   2890                 cam_dimension_t frame_dim;
   2891                 cam_format_t frame_fmt;
   2892                 const char *fmt_string;
   2893                 pStream->getFrameDimension(frame_dim);
   2894                 pStream->getFrameOffset(frame_offset);
   2895                 pStream->getFormat(frame_fmt);
   2896                 fmt_string = m_parent->mParameters.getFrameFmtString(frame_fmt);
   2897 
   2898                 int cbcr_offset = (int32_t)frame_offset.mp[0].len -
   2899                         frame_dim.width * frame_dim.height;
   2900                 m_parent->mParameters.set("snapshot-framelen", (int)frame_offset.frame_len);
   2901                 m_parent->mParameters.set("snapshot-yoff", (int)frame_offset.mp[0].offset);
   2902                 m_parent->mParameters.set("snapshot-cbcroff", cbcr_offset);
   2903                 if (fmt_string != NULL) {
   2904                     m_parent->mParameters.set("snapshot-format", fmt_string);
   2905                 } else {
   2906                     m_parent->mParameters.set("snapshot-format", "");
   2907                 }
   2908 
   2909                 CDBG_HIGH("%s: frame width=%d, height=%d, yoff=%d, cbcroff=%d, fmt_string=%s", __func__,
   2910                         frame_dim.width, frame_dim.height, frame_offset.mp[0].offset, cbcr_offset, fmt_string);
   2911                 return NO_ERROR;
   2912             }
   2913         }
   2914     }
   2915 
   2916     return BAD_VALUE;
   2917 }
   2918 
   2919 bool QCameraPostProcessor::matchJobId(void *data, void *, void *match_data)
   2920 {
   2921   qcamera_jpeg_data_t * job = (qcamera_jpeg_data_t *) data;
   2922   uint32_t job_id = *((uint32_t *) match_data);
   2923   return job->jobId == job_id;
   2924 }
   2925 
   2926 /*===========================================================================
   2927  * FUNCTION   : getJpegMemory
   2928  *
   2929  * DESCRIPTION: buffer allocation function
   2930  *   to pass to jpeg interface
   2931  *
   2932  * PARAMETERS :
   2933  *   @out_buf : buffer descriptor struct
   2934  *
   2935  * RETURN     : int32_t type of status
   2936  *              NO_ERROR  -- success
   2937  *              none-zero failure code
   2938  *==========================================================================*/
   2939 int QCameraPostProcessor::getJpegMemory(omx_jpeg_ouput_buf_t *out_buf)
   2940 {
   2941     CDBG_HIGH("%s: Allocating jpeg out buffer of size: %d", __func__, out_buf->size);
   2942     QCameraPostProcessor *procInst = (QCameraPostProcessor *) out_buf->handle;
   2943     camera_memory_t *cam_mem = procInst->m_parent->mGetMemory(out_buf->fd, out_buf->size, 1U,
   2944             procInst->m_parent->mCallbackCookie);
   2945     out_buf->mem_hdl = cam_mem;
   2946     out_buf->vaddr = cam_mem->data;
   2947 
   2948     return 0;
   2949 }
   2950 
   2951 /*===========================================================================
   2952  * FUNCTION   : QCameraExif
   2953  *
   2954  * DESCRIPTION: constructor of QCameraExif
   2955  *
   2956  * PARAMETERS : None
   2957  *
   2958  * RETURN     : None
   2959  *==========================================================================*/
   2960 QCameraExif::QCameraExif()
   2961     : m_nNumEntries(0)
   2962 {
   2963     memset(m_Entries, 0, sizeof(m_Entries));
   2964 }
   2965 
   2966 /*===========================================================================
   2967  * FUNCTION   : ~QCameraExif
   2968  *
   2969  * DESCRIPTION: deconstructor of QCameraExif. Will release internal memory ptr.
   2970  *
   2971  * PARAMETERS : None
   2972  *
   2973  * RETURN     : None
   2974  *==========================================================================*/
   2975 QCameraExif::~QCameraExif()
   2976 {
   2977     for (uint32_t i = 0; i < m_nNumEntries; i++) {
   2978         switch (m_Entries[i].tag_entry.type) {
   2979         case EXIF_BYTE:
   2980             {
   2981                 if (m_Entries[i].tag_entry.count > 1 &&
   2982                     m_Entries[i].tag_entry.data._bytes != NULL) {
   2983                     free(m_Entries[i].tag_entry.data._bytes);
   2984                     m_Entries[i].tag_entry.data._bytes = NULL;
   2985                 }
   2986             }
   2987             break;
   2988         case EXIF_ASCII:
   2989             {
   2990                 if (m_Entries[i].tag_entry.data._ascii != NULL) {
   2991                     free(m_Entries[i].tag_entry.data._ascii);
   2992                     m_Entries[i].tag_entry.data._ascii = NULL;
   2993                 }
   2994             }
   2995             break;
   2996         case EXIF_SHORT:
   2997             {
   2998                 if (m_Entries[i].tag_entry.count > 1 &&
   2999                     m_Entries[i].tag_entry.data._shorts != NULL) {
   3000                     free(m_Entries[i].tag_entry.data._shorts);
   3001                     m_Entries[i].tag_entry.data._shorts = NULL;
   3002                 }
   3003             }
   3004             break;
   3005         case EXIF_LONG:
   3006             {
   3007                 if (m_Entries[i].tag_entry.count > 1 &&
   3008                     m_Entries[i].tag_entry.data._longs != NULL) {
   3009                     free(m_Entries[i].tag_entry.data._longs);
   3010                     m_Entries[i].tag_entry.data._longs = NULL;
   3011                 }
   3012             }
   3013             break;
   3014         case EXIF_RATIONAL:
   3015             {
   3016                 if (m_Entries[i].tag_entry.count > 1 &&
   3017                     m_Entries[i].tag_entry.data._rats != NULL) {
   3018                     free(m_Entries[i].tag_entry.data._rats);
   3019                     m_Entries[i].tag_entry.data._rats = NULL;
   3020                 }
   3021             }
   3022             break;
   3023         case EXIF_UNDEFINED:
   3024             {
   3025                 if (m_Entries[i].tag_entry.data._undefined != NULL) {
   3026                     free(m_Entries[i].tag_entry.data._undefined);
   3027                     m_Entries[i].tag_entry.data._undefined = NULL;
   3028                 }
   3029             }
   3030             break;
   3031         case EXIF_SLONG:
   3032             {
   3033                 if (m_Entries[i].tag_entry.count > 1 &&
   3034                     m_Entries[i].tag_entry.data._slongs != NULL) {
   3035                     free(m_Entries[i].tag_entry.data._slongs);
   3036                     m_Entries[i].tag_entry.data._slongs = NULL;
   3037                 }
   3038             }
   3039             break;
   3040         case EXIF_SRATIONAL:
   3041             {
   3042                 if (m_Entries[i].tag_entry.count > 1 &&
   3043                     m_Entries[i].tag_entry.data._srats != NULL) {
   3044                     free(m_Entries[i].tag_entry.data._srats);
   3045                     m_Entries[i].tag_entry.data._srats = NULL;
   3046                 }
   3047             }
   3048             break;
   3049         }
   3050     }
   3051 }
   3052 
   3053 /*===========================================================================
   3054  * FUNCTION   : addEntry
   3055  *
   3056  * DESCRIPTION: function to add an entry to exif data
   3057  *
   3058  * PARAMETERS :
   3059  *   @tagid   : exif tag ID
   3060  *   @type    : data type
   3061  *   @count   : number of data in uint of its type
   3062  *   @data    : input data ptr
   3063  *
   3064  * RETURN     : int32_t type of status
   3065  *              NO_ERROR  -- success
   3066  *              none-zero failure code
   3067  *==========================================================================*/
   3068 int32_t QCameraExif::addEntry(exif_tag_id_t tagid,
   3069                               exif_tag_type_t type,
   3070                               uint32_t count,
   3071                               void *data)
   3072 {
   3073     int32_t rc = NO_ERROR;
   3074     if(m_nNumEntries >= MAX_EXIF_TABLE_ENTRIES) {
   3075         ALOGE("%s: Number of entries exceeded limit", __func__);
   3076         return NO_MEMORY;
   3077     }
   3078 
   3079     m_Entries[m_nNumEntries].tag_id = tagid;
   3080     m_Entries[m_nNumEntries].tag_entry.type = type;
   3081     m_Entries[m_nNumEntries].tag_entry.count = count;
   3082     m_Entries[m_nNumEntries].tag_entry.copy = 1;
   3083     switch (type) {
   3084     case EXIF_BYTE:
   3085         {
   3086             if (count > 1) {
   3087                 uint8_t *values = (uint8_t *)malloc(count);
   3088                 if (values == NULL) {
   3089                     ALOGE("%s: No memory for byte array", __func__);
   3090                     rc = NO_MEMORY;
   3091                 } else {
   3092                     memcpy(values, data, count);
   3093                     m_Entries[m_nNumEntries].tag_entry.data._bytes = values;
   3094                 }
   3095             } else {
   3096                 m_Entries[m_nNumEntries].tag_entry.data._byte = *(uint8_t *)data;
   3097             }
   3098         }
   3099         break;
   3100     case EXIF_ASCII:
   3101         {
   3102             char *str = NULL;
   3103             str = (char *)malloc(count + 1);
   3104             if (str == NULL) {
   3105                 ALOGE("%s: No memory for ascii string", __func__);
   3106                 rc = NO_MEMORY;
   3107             } else {
   3108                 memset(str, 0, count + 1);
   3109                 memcpy(str, data, count);
   3110                 m_Entries[m_nNumEntries].tag_entry.data._ascii = str;
   3111             }
   3112         }
   3113         break;
   3114     case EXIF_SHORT:
   3115         {
   3116             if (count > 1) {
   3117                 uint16_t *values = (uint16_t *)malloc(count * sizeof(uint16_t));
   3118                 if (values == NULL) {
   3119                     ALOGE("%s: No memory for short array", __func__);
   3120                     rc = NO_MEMORY;
   3121                 } else {
   3122                     memcpy(values, data, count * sizeof(uint16_t));
   3123                     m_Entries[m_nNumEntries].tag_entry.data._shorts = values;
   3124                 }
   3125             } else {
   3126                 m_Entries[m_nNumEntries].tag_entry.data._short = *(uint16_t *)data;
   3127             }
   3128         }
   3129         break;
   3130     case EXIF_LONG:
   3131         {
   3132             if (count > 1) {
   3133                 uint32_t *values = (uint32_t *)malloc(count * sizeof(uint32_t));
   3134                 if (values == NULL) {
   3135                     ALOGE("%s: No memory for long array", __func__);
   3136                     rc = NO_MEMORY;
   3137                 } else {
   3138                     memcpy(values, data, count * sizeof(uint32_t));
   3139                     m_Entries[m_nNumEntries].tag_entry.data._longs = values;
   3140                 }
   3141             } else {
   3142                 m_Entries[m_nNumEntries].tag_entry.data._long = *(uint32_t *)data;
   3143             }
   3144         }
   3145         break;
   3146     case EXIF_RATIONAL:
   3147         {
   3148             if (count > 1) {
   3149                 rat_t *values = (rat_t *)malloc(count * sizeof(rat_t));
   3150                 if (values == NULL) {
   3151                     ALOGE("%s: No memory for rational array", __func__);
   3152                     rc = NO_MEMORY;
   3153                 } else {
   3154                     memcpy(values, data, count * sizeof(rat_t));
   3155                     m_Entries[m_nNumEntries].tag_entry.data._rats = values;
   3156                 }
   3157             } else {
   3158                 m_Entries[m_nNumEntries].tag_entry.data._rat = *(rat_t *)data;
   3159             }
   3160         }
   3161         break;
   3162     case EXIF_UNDEFINED:
   3163         {
   3164             uint8_t *values = (uint8_t *)malloc(count);
   3165             if (values == NULL) {
   3166                 ALOGE("%s: No memory for undefined array", __func__);
   3167                 rc = NO_MEMORY;
   3168             } else {
   3169                 memcpy(values, data, count);
   3170                 m_Entries[m_nNumEntries].tag_entry.data._undefined = values;
   3171             }
   3172         }
   3173         break;
   3174     case EXIF_SLONG:
   3175         {
   3176             if (count > 1) {
   3177                 int32_t *values = (int32_t *)malloc(count * sizeof(int32_t));
   3178                 if (values == NULL) {
   3179                     ALOGE("%s: No memory for signed long array", __func__);
   3180                     rc = NO_MEMORY;
   3181                 } else {
   3182                     memcpy(values, data, count * sizeof(int32_t));
   3183                     m_Entries[m_nNumEntries].tag_entry.data._slongs = values;
   3184                 }
   3185             } else {
   3186                 m_Entries[m_nNumEntries].tag_entry.data._slong = *(int32_t *)data;
   3187             }
   3188         }
   3189         break;
   3190     case EXIF_SRATIONAL:
   3191         {
   3192             if (count > 1) {
   3193                 srat_t *values = (srat_t *)malloc(count * sizeof(srat_t));
   3194                 if (values == NULL) {
   3195                     ALOGE("%s: No memory for signed rational array", __func__);
   3196                     rc = NO_MEMORY;
   3197                 } else {
   3198                     memcpy(values, data, count * sizeof(srat_t));
   3199                     m_Entries[m_nNumEntries].tag_entry.data._srats = values;
   3200                 }
   3201             } else {
   3202                 m_Entries[m_nNumEntries].tag_entry.data._srat = *(srat_t *)data;
   3203             }
   3204         }
   3205         break;
   3206     }
   3207 
   3208     // Increase number of entries
   3209     m_nNumEntries++;
   3210     return rc;
   3211 }
   3212 
   3213 }; // namespace qcamera
   3214