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