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