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