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