Home | History | Annotate | Download | only in HAL3
      1 /* Copyright (c) 2012-2015, The Linux Foundataion. All rights reserved.
      2 *
      3 * Redistribution and use in source and binary forms, with or without
      4 * modification, are permitted provided that the following conditions are
      5 * met:
      6 *     * Redistributions of source code must retain the above copyright
      7 *       notice, this list of conditions and the following disclaimer.
      8 *     * Redistributions in binary form must reproduce the above
      9 *       copyright notice, this list of conditions and the following
     10 *       disclaimer in the documentation and/or other materials provided
     11 *       with the distribution.
     12 *     * Neither the name of The Linux Foundation nor the names of its
     13 *       contributors may be used to endorse or promote products derived
     14 *       from this software without specific prior written permission.
     15 *
     16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 *
     28 */
     29 #define ATRACE_TAG ATRACE_TAG_CAMERA
     30 
     31 #define LOG_TAG "QCamera3PostProc"
     32 //#define LOG_NDEBUG 0
     33 
     34 #include <stdlib.h>
     35 #include <utils/Errors.h>
     36 #include <utils/Trace.h>
     37 #include <cutils/properties.h>
     38 
     39 #include "QCamera3PostProc.h"
     40 #include "QCamera3HWI.h"
     41 #include "QCamera3Channel.h"
     42 #include "QCamera3Stream.h"
     43 
     44 namespace qcamera {
     45 
     46 static const char ExifAsciiPrefix[] =
     47     { 0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0 };          // "ASCII\0\0\0"
     48 static const char ExifUndefinedPrefix[] =
     49     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };   // "\0\0\0\0\0\0\0\0"
     50 
     51 #define EXIF_ASCII_PREFIX_SIZE           8   //(sizeof(ExifAsciiPrefix))
     52 #define FOCAL_LENGTH_DECIMAL_PRECISION   100
     53 
     54 /*===========================================================================
     55  * FUNCTION   : QCamera3PostProcessor
     56  *
     57  * DESCRIPTION: constructor of QCamera3PostProcessor.
     58  *
     59  * PARAMETERS :
     60  *   @cam_ctrl : ptr to HWI object
     61  *
     62  * RETURN     : None
     63  *==========================================================================*/
     64 QCamera3PostProcessor::QCamera3PostProcessor(QCamera3ProcessingChannel* ch_ctrl)
     65     : m_parent(ch_ctrl),
     66       mJpegCB(NULL),
     67       mJpegUserData(NULL),
     68       mJpegClientHandle(0),
     69       mJpegSessionId(0),
     70       m_bThumbnailNeeded(TRUE),
     71       m_pReprocChannel(NULL),
     72       m_inputPPQ(releasePPInputData, this),
     73       m_inputFWKPPQ(NULL, this),
     74       m_ongoingPPQ(releaseOngoingPPData, this),
     75       m_inputJpegQ(releaseJpegData, this),
     76       m_ongoingJpegQ(releaseJpegData, this),
     77       m_inputRawQ(releasePPInputData, this),
     78       m_inputMetaQ(releaseMetadata, this),
     79       m_jpegSettingsQ(NULL, this)
     80 {
     81     memset(&mJpegHandle, 0, sizeof(mJpegHandle));
     82     pthread_mutex_init(&mReprocJobLock, NULL);
     83 }
     84 
     85 /*===========================================================================
     86  * FUNCTION   : ~QCamera3PostProcessor
     87  *
     88  * DESCRIPTION: deconstructor of QCamera3PostProcessor.
     89  *
     90  * PARAMETERS : None
     91  *
     92  * RETURN     : None
     93  *==========================================================================*/
     94 QCamera3PostProcessor::~QCamera3PostProcessor()
     95 {
     96     pthread_mutex_destroy(&mReprocJobLock);
     97 }
     98 
     99 /*===========================================================================
    100  * FUNCTION   : init
    101  *
    102  * DESCRIPTION: initialization of postprocessor
    103  *
    104  * PARAMETERS :
    105  *   @memory              : output buffer memory
    106  *   @postprocess_mask    : postprocess mask for the buffer
    107  *
    108  * RETURN     : int32_t type of status
    109  *              NO_ERROR  -- success
    110  *              none-zero failure code
    111  *==========================================================================*/
    112 int32_t QCamera3PostProcessor::init(QCamera3Memory *memory,
    113         uint32_t postprocess_mask)
    114 {
    115     ATRACE_CALL();
    116     mOutputMem = memory;
    117     mPostProcMask = postprocess_mask;
    118     m_dataProcTh.launch(dataProcessRoutine, this);
    119 
    120     return NO_ERROR;
    121 }
    122 
    123 /*===========================================================================
    124  * FUNCTION   : deinit
    125  *
    126  * DESCRIPTION: de-initialization of postprocessor
    127  *
    128  * PARAMETERS : None
    129  *
    130  * RETURN     : int32_t type of status
    131  *              NO_ERROR  -- success
    132  *              none-zero failure code
    133  *==========================================================================*/
    134 int32_t QCamera3PostProcessor::deinit()
    135 {
    136     int rc = NO_ERROR;
    137     m_dataProcTh.exit();
    138 
    139     if (m_pReprocChannel != NULL) {
    140         m_pReprocChannel->stop();
    141         delete m_pReprocChannel;
    142         m_pReprocChannel = NULL;
    143     }
    144 
    145     if(mJpegClientHandle > 0) {
    146         rc = mJpegHandle.close(mJpegClientHandle);
    147         CDBG_HIGH("%s: Jpeg closed, rc = %d, mJpegClientHandle = %x",
    148               __func__, rc, mJpegClientHandle);
    149         mJpegClientHandle = 0;
    150         memset(&mJpegHandle, 0, sizeof(mJpegHandle));
    151     }
    152 
    153     mOutputMem = NULL;
    154     return rc;
    155 }
    156 
    157 /*===========================================================================
    158  * FUNCTION   : initJpeg
    159  *
    160  * DESCRIPTION: initialization of jpeg through postprocessor
    161  *
    162  * PARAMETERS :
    163  *   @jpeg_cb      : callback to handle jpeg event from mm-camera-interface
    164  *   @max_pic_dim  : max picture dimensions
    165  *   @user_data    : user data ptr for jpeg callback
    166  *
    167  * RETURN     : int32_t type of status
    168  *              NO_ERROR  -- success
    169  *              none-zero failure code
    170  *==========================================================================*/
    171 int32_t QCamera3PostProcessor::initJpeg(jpeg_encode_callback_t jpeg_cb,
    172         cam_dimension_t* max_pic_dim,
    173         void *user_data)
    174 {
    175     ATRACE_CALL();
    176     mJpegCB = jpeg_cb;
    177     mJpegUserData = user_data;
    178     mm_dimension max_size;
    179 
    180     if ((0 > max_pic_dim->width) || (0 > max_pic_dim->height)) {
    181         ALOGE("%s : Negative dimension %dx%d", __func__,
    182                 max_pic_dim->width, max_pic_dim->height);
    183         return BAD_VALUE;
    184     }
    185 
    186     //set max pic size
    187     memset(&max_size, 0, sizeof(mm_dimension));
    188     max_size.w =  max_pic_dim->width;
    189     max_size.h =  max_pic_dim->height;
    190 
    191     mJpegClientHandle = jpeg_open(&mJpegHandle,max_size);
    192     if(!mJpegClientHandle) {
    193         ALOGE("%s : jpeg_open did not work", __func__);
    194         return UNKNOWN_ERROR;
    195     }
    196     return NO_ERROR;
    197 }
    198 
    199 /*===========================================================================
    200  * FUNCTION   : start
    201  *
    202  * DESCRIPTION: start postprocessor. Data process thread and data notify thread
    203  *              will be launched.
    204  *
    205  * PARAMETERS :
    206  *   @config        : reprocess configuration
    207  *   @metadata      : metadata for the reprocessing
    208  *
    209  * RETURN     : int32_t type of status
    210  *              NO_ERROR  -- success
    211  *              none-zero failure code
    212  *
    213  * NOTE       : if any reprocess is needed, a reprocess channel/stream
    214  *              will be started.
    215  *==========================================================================*/
    216 int32_t QCamera3PostProcessor::start(const reprocess_config_t &config)
    217 {
    218     int32_t rc = NO_ERROR;
    219     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
    220 
    221     if (hal_obj->needReprocess(mPostProcMask) || config.src_channel != m_parent) {
    222         if (m_pReprocChannel != NULL) {
    223             m_pReprocChannel->stop();
    224             delete m_pReprocChannel;
    225             m_pReprocChannel = NULL;
    226         }
    227 
    228         // if reprocess is needed, start reprocess channel
    229         CDBG("%s: Setting input channel as pInputChannel", __func__);
    230         m_pReprocChannel = hal_obj->addOfflineReprocChannel(config, m_parent);
    231         if (m_pReprocChannel == NULL) {
    232             ALOGE("%s: cannot add reprocess channel", __func__);
    233             return UNKNOWN_ERROR;
    234         }
    235         /*start the reprocess channel only if buffers are already allocated, thus
    236           only start it in an intermediate reprocess type, defer it for others*/
    237         if (config.reprocess_type == REPROCESS_TYPE_JPEG) {
    238             rc = m_pReprocChannel->start();
    239             if (rc != 0) {
    240                 ALOGE("%s: cannot start reprocess channel", __func__);
    241                 delete m_pReprocChannel;
    242                 m_pReprocChannel = NULL;
    243                 return rc;
    244             }
    245         }
    246     }
    247     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_START_DATA_PROC, FALSE, FALSE);
    248 
    249     return rc;
    250 }
    251 
    252 /*===========================================================================
    253  * FUNCTION   : stop
    254  *
    255  * DESCRIPTION: stop postprocessor. Data process and notify thread will be stopped.
    256  *
    257  * PARAMETERS : None
    258  *
    259  * RETURN     : int32_t type of status
    260  *              NO_ERROR  -- success
    261  *              none-zero failure code
    262  *
    263  * NOTE       : reprocess channel will be stopped and deleted if there is any
    264  *==========================================================================*/
    265 int32_t QCamera3PostProcessor::stop()
    266 {
    267     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC, TRUE, TRUE);
    268 
    269     if (m_pReprocChannel != NULL) {
    270         m_pReprocChannel->stop();
    271         delete m_pReprocChannel;
    272         m_pReprocChannel = NULL;
    273     }
    274 
    275     return NO_ERROR;
    276 }
    277 
    278 /*===========================================================================
    279  * FUNCTION   : getFWKJpegEncodeConfig
    280  *
    281  * DESCRIPTION: function to prepare encoding job information
    282  *
    283  * PARAMETERS :
    284  *   @encode_parm   : param to be filled with encoding configuration
    285  *   @frame         : framework input buffer
    286  *   @jpeg_settings : jpeg settings to be applied for encoding
    287  *
    288  * RETURN     : int32_t type of status
    289  *              NO_ERROR  -- success
    290  *              none-zero failure code
    291  *==========================================================================*/
    292 int32_t QCamera3PostProcessor::getFWKJpegEncodeConfig(
    293         mm_jpeg_encode_params_t& encode_parm,
    294         qcamera_fwk_input_pp_data_t *frame,
    295         jpeg_settings_t *jpeg_settings)
    296 {
    297     CDBG("%s : E", __func__);
    298     int32_t ret = NO_ERROR;
    299 
    300     if ((NULL == frame) || (NULL == jpeg_settings)) {
    301         return BAD_VALUE;
    302     }
    303 
    304     ssize_t bufSize = mOutputMem->getSize(jpeg_settings->out_buf_index);
    305     if (BAD_INDEX == bufSize) {
    306         ALOGE("%s: cannot retrieve buffer size for buffer %u", __func__,
    307                 jpeg_settings->out_buf_index);
    308         return BAD_VALUE;
    309     }
    310 
    311     encode_parm.jpeg_cb = mJpegCB;
    312     encode_parm.userdata = mJpegUserData;
    313 
    314     if (jpeg_settings->thumbnail_size.width > 0 &&
    315             jpeg_settings->thumbnail_size.height > 0)
    316         m_bThumbnailNeeded = TRUE;
    317     else
    318         m_bThumbnailNeeded = FALSE;
    319     encode_parm.encode_thumbnail = m_bThumbnailNeeded;
    320 
    321     // get color format
    322     cam_format_t img_fmt = frame->reproc_config.stream_format;
    323     encode_parm.color_format = getColorfmtFromImgFmt(img_fmt);
    324 
    325     // get jpeg quality
    326     encode_parm.quality = jpeg_settings->jpeg_quality;
    327     if (encode_parm.quality <= 0) {
    328         encode_parm.quality = 85;
    329     }
    330 
    331     // get jpeg thumbnail quality
    332     encode_parm.thumb_quality = jpeg_settings->jpeg_thumb_quality;
    333 
    334     cam_frame_len_offset_t main_offset =
    335             frame->reproc_config.input_stream_plane_info.plane_info;
    336 
    337     encode_parm.num_src_bufs = 1;
    338     encode_parm.src_main_buf[0].index = 0;
    339     encode_parm.src_main_buf[0].buf_size = frame->input_buffer.frame_len;
    340     encode_parm.src_main_buf[0].buf_vaddr = (uint8_t *) frame->input_buffer.buffer;
    341     encode_parm.src_main_buf[0].fd = frame->input_buffer.fd;
    342     encode_parm.src_main_buf[0].format = MM_JPEG_FMT_YUV;
    343     encode_parm.src_main_buf[0].offset = main_offset;
    344 
    345     //Pass input thumbnail buffer info to encoder.
    346     //Note: Use main buffer to encode thumbnail
    347     if (m_bThumbnailNeeded == TRUE) {
    348         encode_parm.num_tmb_bufs = 1;
    349         encode_parm.src_thumb_buf[0] = encode_parm.src_main_buf[0];
    350     }
    351 
    352     //Pass output jpeg buffer info to encoder.
    353     //mOutputMem is allocated by framework.
    354     encode_parm.num_dst_bufs = 1;
    355     encode_parm.dest_buf[0].index = 0;
    356     encode_parm.dest_buf[0].buf_size = (size_t)bufSize;
    357     encode_parm.dest_buf[0].buf_vaddr = (uint8_t *)mOutputMem->getPtr(
    358             jpeg_settings->out_buf_index);
    359     encode_parm.dest_buf[0].fd = mOutputMem->getFd(
    360             jpeg_settings->out_buf_index);
    361     encode_parm.dest_buf[0].format = MM_JPEG_FMT_YUV;
    362     encode_parm.dest_buf[0].offset = main_offset;
    363 
    364     CDBG("%s : X", __func__);
    365     return NO_ERROR;
    366 
    367 on_error:
    368     CDBG("%s : X with error %d", __func__, ret);
    369     return ret;
    370 }
    371 
    372 /*===========================================================================
    373  * FUNCTION   : getJpegEncodeConfig
    374  *
    375  * DESCRIPTION: function to prepare encoding job information
    376  *
    377  * PARAMETERS :
    378  *   @encode_parm   : param to be filled with encoding configuration
    379  *   #main_stream   : stream object where the input buffer comes from
    380  *   @jpeg_settings : jpeg settings to be applied for encoding
    381  *
    382  * RETURN     : int32_t type of status
    383  *              NO_ERROR  -- success
    384  *              none-zero failure code
    385  *==========================================================================*/
    386 int32_t QCamera3PostProcessor::getJpegEncodeConfig(
    387                 mm_jpeg_encode_params_t& encode_parm,
    388                 QCamera3Stream *main_stream,
    389                 jpeg_settings_t *jpeg_settings)
    390 {
    391     CDBG("%s : E", __func__);
    392     int32_t ret = NO_ERROR;
    393     ssize_t bufSize = 0;
    394 
    395     encode_parm.jpeg_cb = mJpegCB;
    396     encode_parm.userdata = mJpegUserData;
    397 
    398     if (jpeg_settings->thumbnail_size.width > 0 &&
    399             jpeg_settings->thumbnail_size.height > 0)
    400         m_bThumbnailNeeded = TRUE;
    401     else
    402         m_bThumbnailNeeded = FALSE;
    403     encode_parm.encode_thumbnail = m_bThumbnailNeeded;
    404 
    405     // get color format
    406     cam_format_t img_fmt = CAM_FORMAT_YUV_420_NV12;  //default value
    407     main_stream->getFormat(img_fmt);
    408     encode_parm.color_format = getColorfmtFromImgFmt(img_fmt);
    409 
    410     // get jpeg quality
    411     encode_parm.quality = jpeg_settings->jpeg_quality;
    412     if (encode_parm.quality <= 0) {
    413         encode_parm.quality = 85;
    414     }
    415 
    416     // get jpeg thumbnail quality
    417     encode_parm.thumb_quality = jpeg_settings->jpeg_thumb_quality;
    418 
    419     cam_frame_len_offset_t main_offset;
    420     memset(&main_offset, 0, sizeof(cam_frame_len_offset_t));
    421     main_stream->getFrameOffset(main_offset);
    422 
    423     // src buf config
    424     //Pass input main image buffer info to encoder.
    425     QCamera3Memory *pStreamMem = main_stream->getStreamBufs();
    426     if (pStreamMem == NULL) {
    427         ALOGE("%s: cannot get stream bufs from main stream", __func__);
    428         ret = BAD_VALUE;
    429         goto on_error;
    430     }
    431     encode_parm.num_src_bufs = MIN(pStreamMem->getCnt(), MM_JPEG_MAX_BUF);
    432     for (uint32_t i = 0; i < encode_parm.num_src_bufs; i++) {
    433         if (pStreamMem != NULL) {
    434             encode_parm.src_main_buf[i].index = i;
    435             bufSize = pStreamMem->getSize(i);
    436             if (BAD_INDEX == bufSize) {
    437             ALOGE("%s: cannot retrieve buffer size for buffer %u", __func__, i);
    438                 ret = BAD_VALUE;
    439                 goto on_error;
    440             }
    441             encode_parm.src_main_buf[i].buf_size = (size_t)bufSize;
    442             encode_parm.src_main_buf[i].buf_vaddr = (uint8_t *)pStreamMem->getPtr(i);
    443             encode_parm.src_main_buf[i].fd = pStreamMem->getFd(i);
    444             encode_parm.src_main_buf[i].format = MM_JPEG_FMT_YUV;
    445             encode_parm.src_main_buf[i].offset = main_offset;
    446         }
    447     }
    448 
    449     //Pass input thumbnail buffer info to encoder.
    450     //Note: Use main buffer to encode thumbnail
    451     if (m_bThumbnailNeeded == TRUE) {
    452         pStreamMem = main_stream->getStreamBufs();
    453         if (pStreamMem == NULL) {
    454             ALOGE("%s: cannot get stream bufs from thumb stream", __func__);
    455             ret = BAD_VALUE;
    456             goto on_error;
    457         }
    458         cam_frame_len_offset_t thumb_offset;
    459         memset(&thumb_offset, 0, sizeof(cam_frame_len_offset_t));
    460         main_stream->getFrameOffset(thumb_offset);
    461         encode_parm.num_tmb_bufs = MIN(pStreamMem->getCnt(), MM_JPEG_MAX_BUF);
    462         for (uint32_t i = 0; i < encode_parm.num_tmb_bufs; i++) {
    463             if (pStreamMem != NULL) {
    464                 encode_parm.src_thumb_buf[i].index = i;
    465                 bufSize = pStreamMem->getSize(i);
    466                 if (BAD_INDEX == bufSize) {
    467                     ALOGE("%s: cannot retrieve buffer size for buffer %u", __func__, i);
    468                     ret = BAD_VALUE;
    469                     goto on_error;
    470                 }
    471                 encode_parm.src_thumb_buf[i].buf_size = (uint32_t)bufSize;
    472                 encode_parm.src_thumb_buf[i].buf_vaddr = (uint8_t *)pStreamMem->getPtr(i);
    473                 encode_parm.src_thumb_buf[i].fd = pStreamMem->getFd(i);
    474                 encode_parm.src_thumb_buf[i].format = MM_JPEG_FMT_YUV;
    475                 encode_parm.src_thumb_buf[i].offset = thumb_offset;
    476             }
    477         }
    478     }
    479 
    480     //Pass output jpeg buffer info to encoder.
    481     //mJpegMem is allocated by framework.
    482     bufSize = mOutputMem->getSize(jpeg_settings->out_buf_index);
    483     if (BAD_INDEX == bufSize) {
    484         ALOGE("%s: cannot retrieve buffer size for buffer %u", __func__,
    485                 jpeg_settings->out_buf_index);
    486         ret = BAD_VALUE;
    487         goto on_error;
    488     }
    489     encode_parm.num_dst_bufs = 1;
    490     encode_parm.dest_buf[0].index = 0;
    491     encode_parm.dest_buf[0].buf_size = (size_t)bufSize;
    492     encode_parm.dest_buf[0].buf_vaddr = (uint8_t *)mOutputMem->getPtr(
    493             jpeg_settings->out_buf_index);
    494     encode_parm.dest_buf[0].fd = mOutputMem->getFd(
    495             jpeg_settings->out_buf_index);
    496     encode_parm.dest_buf[0].format = MM_JPEG_FMT_YUV;
    497     encode_parm.dest_buf[0].offset = main_offset;
    498 
    499     CDBG("%s : X", __func__);
    500     return NO_ERROR;
    501 
    502 on_error:
    503     CDBG("%s : X with error %d", __func__, ret);
    504     return ret;
    505 }
    506 
    507 /*===========================================================================
    508  * FUNCTION   : processData
    509  *
    510  * DESCRIPTION: enqueue data into dataProc thread
    511  *
    512  * PARAMETERS :
    513  *   @frame   : process frame
    514  *
    515  * RETURN     : int32_t type of status
    516  *              NO_ERROR  -- success
    517  *              none-zero failure code
    518  *
    519  * NOTE       : depends on if offline reprocess is needed, received frame will
    520  *              be sent to either input queue of postprocess or jpeg encoding
    521  *==========================================================================*/
    522 int32_t QCamera3PostProcessor::processData(mm_camera_super_buf_t *frame)
    523 {
    524     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
    525     pthread_mutex_lock(&mReprocJobLock);
    526     // enqueue to post proc input queue
    527     m_inputPPQ.enqueue((void *)frame);
    528     if (!(m_inputMetaQ.isEmpty())) {
    529        CDBG("%s: meta queue is not empty, do next job", __func__);
    530        m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
    531     }
    532     pthread_mutex_unlock(&mReprocJobLock);
    533 
    534     return NO_ERROR;
    535 }
    536 
    537 /*===========================================================================
    538  * FUNCTION   : processData
    539  *
    540  * DESCRIPTION: enqueue data into dataProc thread
    541  *
    542  * PARAMETERS :
    543  *   @frame   : process frame
    544  *
    545  * RETURN     : int32_t type of status
    546  *              NO_ERROR  -- success
    547  *              none-zero failure code
    548  *
    549  * NOTE       : depends on if offline reprocess is needed, received frame will
    550  *              be sent to either input queue of postprocess or jpeg encoding
    551  *==========================================================================*/
    552 int32_t QCamera3PostProcessor::processData(qcamera_fwk_input_pp_data_t *frame)
    553 {
    554     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
    555     if (hal_obj->needReprocess(mPostProcMask) ||
    556             frame->reproc_config.src_channel != m_parent) {
    557         pthread_mutex_lock(&mReprocJobLock);
    558         // enqueu to post proc input queue
    559         m_inputFWKPPQ.enqueue((void *)frame);
    560         m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
    561         pthread_mutex_unlock(&mReprocJobLock);
    562     } else {
    563         jpeg_settings_t *jpeg_settings = (jpeg_settings_t *)m_jpegSettingsQ.dequeue();
    564 
    565         if (jpeg_settings == NULL) {
    566             ALOGE("%s: Cannot find jpeg settings", __func__);
    567             return BAD_VALUE;
    568         }
    569 
    570         CDBG_HIGH("%s: no need offline reprocess, sending to jpeg encoding", __func__);
    571         qcamera_hal3_jpeg_data_t *jpeg_job =
    572             (qcamera_hal3_jpeg_data_t *)malloc(sizeof(qcamera_hal3_jpeg_data_t));
    573         if (jpeg_job == NULL) {
    574             ALOGE("%s: No memory for jpeg job", __func__);
    575             return NO_MEMORY;
    576         }
    577 
    578         memset(jpeg_job, 0, sizeof(qcamera_hal3_jpeg_data_t));
    579         jpeg_job->fwk_frame = frame;
    580         jpeg_job->jpeg_settings = jpeg_settings;
    581         jpeg_job->metadata =
    582                 (metadata_buffer_t *) frame->metadata_buffer.buffer;
    583 
    584         // enqueu to jpeg input queue
    585         m_inputJpegQ.enqueue((void *)jpeg_job);
    586         m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
    587     }
    588 
    589     return NO_ERROR;
    590 }
    591 
    592 /*===========================================================================
    593  * FUNCTION   : processPPMetadata
    594  *
    595  * DESCRIPTION: enqueue data into dataProc thread
    596  *
    597  * PARAMETERS :
    598  *   @frame   : process metadata frame received from pic channel
    599  *
    600  * RETURN     : int32_t type of status
    601  *              NO_ERROR  -- success
    602  *              none-zero failure code
    603  *
    604  *==========================================================================*/
    605 int32_t QCamera3PostProcessor::processPPMetadata(mm_camera_super_buf_t *reproc_meta)
    606 {
    607    pthread_mutex_lock(&mReprocJobLock);
    608     // enqueue to metadata input queue
    609     m_inputMetaQ.enqueue((void *)reproc_meta);
    610     if (!(m_inputPPQ.isEmpty())) {
    611        CDBG("%s: pp queue is not empty, do next job", __func__);
    612        m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
    613     } else {
    614        CDBG("%s: pp queue is empty, not calling do next job", __func__);
    615     }
    616     pthread_mutex_unlock(&mReprocJobLock);
    617     return NO_ERROR;
    618 }
    619 
    620 /*===========================================================================
    621  * FUNCTION   : processJpegSettingData
    622  *
    623  * DESCRIPTION: enqueue jpegSetting into dataProc thread
    624  *
    625  * PARAMETERS :
    626  *   @jpeg_settings : jpeg settings data received from pic channel
    627  *
    628  * RETURN     : int32_t type of status
    629  *              NO_ERROR  -- success
    630  *              none-zero failure code
    631  *
    632  *==========================================================================*/
    633 int32_t QCamera3PostProcessor::processJpegSettingData(
    634         jpeg_settings_t *jpeg_settings)
    635 {
    636     if (!jpeg_settings) {
    637         ALOGE("%s: invalid jpeg settings pointer", __func__);
    638         return -EINVAL;
    639     }
    640     return m_jpegSettingsQ.enqueue((void *)jpeg_settings);
    641 }
    642 
    643 /*===========================================================================
    644  * FUNCTION   : processRawData
    645  *
    646  * DESCRIPTION: enqueue raw data into dataProc thread
    647  *
    648  * PARAMETERS :
    649  *   @frame   : process frame received from mm-camera-interface
    650  *
    651  * RETURN     : int32_t type of status
    652  *              NO_ERROR  -- success
    653  *              none-zero failure code
    654  *==========================================================================*/
    655 int32_t QCamera3PostProcessor::processRawData(mm_camera_super_buf_t *frame)
    656 {
    657     // enqueu to raw input queue
    658     m_inputRawQ.enqueue((void *)frame);
    659     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
    660     return NO_ERROR;
    661 }
    662 
    663 /*===========================================================================
    664  * FUNCTION   : processPPData
    665  *
    666  * DESCRIPTION: process received frame after reprocess.
    667  *
    668  * PARAMETERS :
    669  *   @frame   : received frame from reprocess channel.
    670  *
    671  * RETURN     : int32_t type of status
    672  *              NO_ERROR  -- success
    673  *              none-zero failure code
    674  *
    675  * NOTE       : The frame after reprocess need to send to jpeg encoding.
    676  *==========================================================================*/
    677 int32_t QCamera3PostProcessor::processPPData(mm_camera_super_buf_t *frame)
    678 {
    679     qcamera_hal3_pp_data_t *job = (qcamera_hal3_pp_data_t *)m_ongoingPPQ.dequeue();
    680 
    681     if (job == NULL || ((NULL == job->src_frame) && (NULL == job->fwk_src_frame))) {
    682         ALOGE("%s: Cannot find reprocess job", __func__);
    683         return BAD_VALUE;
    684     }
    685     if (job->jpeg_settings == NULL) {
    686         ALOGE("%s: Cannot find jpeg settings", __func__);
    687         return BAD_VALUE;
    688     }
    689 
    690     qcamera_hal3_jpeg_data_t *jpeg_job =
    691         (qcamera_hal3_jpeg_data_t *)malloc(sizeof(qcamera_hal3_jpeg_data_t));
    692     if (jpeg_job == NULL) {
    693         ALOGE("%s: No memory for jpeg job", __func__);
    694         return NO_MEMORY;
    695     }
    696 
    697     memset(jpeg_job, 0, sizeof(qcamera_hal3_jpeg_data_t));
    698     jpeg_job->src_frame = frame;
    699     if(frame != job->src_frame)
    700         jpeg_job->src_reproc_frame = job->src_frame;
    701     if (NULL == job->fwk_src_frame) {
    702         jpeg_job->metadata = job->metadata;
    703     } else {
    704         jpeg_job->metadata =
    705                 (metadata_buffer_t *) job->fwk_src_frame->metadata_buffer.buffer;
    706         jpeg_job->fwk_src_buffer = job->fwk_src_frame;
    707     }
    708     jpeg_job->src_metadata = job->src_metadata;
    709     jpeg_job->jpeg_settings = job->jpeg_settings;
    710 
    711     // free pp job buf
    712     free(job);
    713 
    714     // enqueu reprocessed frame to jpeg input queue
    715     m_inputJpegQ.enqueue((void *)jpeg_job);
    716 
    717     // wait up data proc thread
    718     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
    719 
    720     return NO_ERROR;
    721 }
    722 
    723 /*===========================================================================
    724  * FUNCTION   : findJpegJobByJobId
    725  *
    726  * DESCRIPTION: find a jpeg job from ongoing Jpeg queue by its job ID
    727  *
    728  * PARAMETERS :
    729  *   @jobId   : job Id of the job
    730  *
    731  * RETURN     : ptr to a jpeg job struct. NULL if not found.
    732  *
    733  * NOTE       : Currently only one job is sending to mm-jpeg-interface for jpeg
    734  *              encoding. Therefore simply dequeue from the ongoing Jpeg Queue
    735  *              will serve the purpose to find the jpeg job.
    736  *==========================================================================*/
    737 qcamera_hal3_jpeg_data_t *QCamera3PostProcessor::findJpegJobByJobId(uint32_t jobId)
    738 {
    739     qcamera_hal3_jpeg_data_t * job = NULL;
    740     if (jobId == 0) {
    741         ALOGE("%s: not a valid jpeg jobId", __func__);
    742         return NULL;
    743     }
    744 
    745     // currely only one jpeg job ongoing, so simply dequeue the head
    746     job = (qcamera_hal3_jpeg_data_t *)m_ongoingJpegQ.dequeue();
    747     return job;
    748 }
    749 
    750 /*===========================================================================
    751  * FUNCTION   : releasePPInputData
    752  *
    753  * DESCRIPTION: callback function to release post process input data node
    754  *
    755  * PARAMETERS :
    756  *   @data      : ptr to post process input data
    757  *   @user_data : user data ptr (QCamera3Reprocessor)
    758  *
    759  * RETURN     : None
    760  *==========================================================================*/
    761 void QCamera3PostProcessor::releasePPInputData(void *data, void *user_data)
    762 {
    763     QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
    764     if (NULL != pme) {
    765         pme->releaseSuperBuf((mm_camera_super_buf_t *)data);
    766     }
    767 }
    768 
    769 /*===========================================================================
    770  * FUNCTION   : releaseMetaData
    771  *
    772  * DESCRIPTION: callback function to release metadata camera buffer
    773  *
    774  * PARAMETERS :
    775  *   @data      : ptr to post process input data
    776  *   @user_data : user data ptr (QCamera3Reprocessor)
    777  *
    778  * RETURN     : None
    779  *==========================================================================*/
    780 void QCamera3PostProcessor::releaseMetadata(void *data, void *user_data)
    781 {
    782     QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
    783     if (NULL != pme) {
    784         pme->m_parent->metadataBufDone((mm_camera_super_buf_t *)data);
    785     }
    786 }
    787 
    788 /*===========================================================================
    789  * FUNCTION   : releaseJpegData
    790  *
    791  * DESCRIPTION: callback function to release jpeg job node
    792  *
    793  * PARAMETERS :
    794  *   @data      : ptr to ongoing jpeg job data
    795  *   @user_data : user data ptr (QCamera3Reprocessor)
    796  *
    797  * RETURN     : None
    798  *==========================================================================*/
    799 void QCamera3PostProcessor::releaseJpegData(void *data, void *user_data)
    800 {
    801     QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
    802     if (NULL != pme) {
    803         pme->releaseJpegJobData((qcamera_hal3_jpeg_data_t *)data);
    804     }
    805 }
    806 
    807 /*===========================================================================
    808  * FUNCTION   : releaseOngoingPPData
    809  *
    810  * DESCRIPTION: callback function to release ongoing postprocess job node
    811  *
    812  * PARAMETERS :
    813  *   @data      : ptr to onging postprocess job
    814  *   @user_data : user data ptr (QCamera3Reprocessor)
    815  *
    816  * RETURN     : None
    817  *==========================================================================*/
    818 void QCamera3PostProcessor::releaseOngoingPPData(void *data, void *user_data)
    819 {
    820     QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
    821     if (NULL != pme) {
    822         qcamera_hal3_pp_data_t *pp_job = (qcamera_hal3_pp_data_t *)data;
    823         if (NULL != pp_job->src_frame) {
    824             pme->releaseSuperBuf(pp_job->src_frame);
    825             free(pp_job->src_frame);
    826             if (NULL != pp_job->src_metadata) {
    827                 pme->m_parent->metadataBufDone(pp_job->src_metadata);
    828                 free(pp_job->src_metadata);
    829             }
    830             pp_job->src_frame = NULL;
    831             pp_job->metadata = NULL;
    832         }
    833 
    834         if (NULL != pp_job->fwk_src_frame) {
    835             free(pp_job->fwk_src_frame);
    836             pp_job->fwk_src_frame = NULL;
    837         }
    838     }
    839 }
    840 
    841 /*===========================================================================
    842  * FUNCTION   : releaseSuperBuf
    843  *
    844  * DESCRIPTION: function to release a superbuf frame by returning back to kernel
    845  *
    846  * PARAMETERS :
    847  *   @super_buf : ptr to the superbuf frame
    848  *
    849  * RETURN     : None
    850  *==========================================================================*/
    851 void QCamera3PostProcessor::releaseSuperBuf(mm_camera_super_buf_t *super_buf)
    852 {
    853     if (NULL != super_buf) {
    854         if (m_parent != NULL) {
    855             m_parent->bufDone(super_buf);
    856         }
    857     }
    858 }
    859 
    860 /*===========================================================================
    861  * FUNCTION   : releaseOfflineBuffers
    862  *
    863  * DESCRIPTION: function to release/unmap offline buffers if any
    864  *
    865  * PARAMETERS : None
    866  *
    867  * RETURN     : int32_t type of status
    868  *              NO_ERROR  -- success
    869  *              none-zero failure code
    870  *==========================================================================*/
    871 int32_t QCamera3PostProcessor::releaseOfflineBuffers()
    872 {
    873     int32_t rc = NO_ERROR;
    874 
    875     if(NULL != m_pReprocChannel) {
    876         rc = m_pReprocChannel->unmapOfflineBuffers(false);
    877     }
    878 
    879     return rc;
    880 }
    881 
    882 /*===========================================================================
    883  * FUNCTION   : releaseJpegJobData
    884  *
    885  * DESCRIPTION: function to release internal resources in jpeg job struct
    886  *
    887  * PARAMETERS :
    888  *   @job     : ptr to jpeg job struct
    889  *
    890  * RETURN     : None
    891  *
    892  * NOTE       : original source frame need to be queued back to kernel for
    893  *              future use. Output buf of jpeg job need to be released since
    894  *              it's allocated for each job. Exif object need to be deleted.
    895  *==========================================================================*/
    896 void QCamera3PostProcessor::releaseJpegJobData(qcamera_hal3_jpeg_data_t *job)
    897 {
    898     ATRACE_CALL();
    899     int32_t rc = NO_ERROR;
    900     CDBG("%s: E", __func__);
    901     if (NULL != job) {
    902         if (NULL != job->src_reproc_frame) {
    903             free(job->src_reproc_frame);
    904             job->src_reproc_frame = NULL;
    905         }
    906 
    907         if (NULL != job->src_frame) {
    908             if (NULL != m_pReprocChannel) {
    909                 rc = m_pReprocChannel->bufDone(job->src_frame);
    910                 if (NO_ERROR != rc)
    911                     ALOGE("%s: bufDone error: %d", __func__, rc);
    912             }
    913             free(job->src_frame);
    914             job->src_frame = NULL;
    915         }
    916 
    917         if (NULL != job->fwk_src_buffer) {
    918             free(job->fwk_src_buffer);
    919             job->fwk_src_buffer = NULL;
    920         } else if (NULL != job->src_metadata) {
    921             m_parent->metadataBufDone(job->src_metadata);
    922             free(job->src_metadata);
    923             job->src_metadata = NULL;
    924         }
    925 
    926         if (NULL != job->fwk_frame) {
    927             free(job->fwk_frame);
    928             job->fwk_frame = NULL;
    929         }
    930 
    931         if (NULL != job->pJpegExifObj) {
    932             delete job->pJpegExifObj;
    933             job->pJpegExifObj = NULL;
    934         }
    935 
    936         if (NULL != job->jpeg_settings) {
    937             free(job->jpeg_settings);
    938             job->jpeg_settings = NULL;
    939         }
    940     }
    941     /* Additional trigger to process any pending jobs in the input queue */
    942     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
    943     CDBG("%s: X", __func__);
    944 }
    945 
    946 /*===========================================================================
    947  * FUNCTION   : getColorfmtFromImgFmt
    948  *
    949  * DESCRIPTION: function to return jpeg color format based on its image format
    950  *
    951  * PARAMETERS :
    952  *   @img_fmt : image format
    953  *
    954  * RETURN     : jpeg color format that can be understandable by omx lib
    955  *==========================================================================*/
    956 mm_jpeg_color_format QCamera3PostProcessor::getColorfmtFromImgFmt(cam_format_t img_fmt)
    957 {
    958     switch (img_fmt) {
    959     case CAM_FORMAT_YUV_420_NV21:
    960         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
    961     case CAM_FORMAT_YUV_420_NV21_ADRENO:
    962         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
    963     case CAM_FORMAT_YUV_420_NV12:
    964         return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2;
    965     case CAM_FORMAT_YUV_420_YV12:
    966         return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2;
    967     case CAM_FORMAT_YUV_422_NV61:
    968         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V1;
    969     case CAM_FORMAT_YUV_422_NV16:
    970         return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V1;
    971     default:
    972         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
    973     }
    974 }
    975 
    976 /*===========================================================================
    977  * FUNCTION   : getJpegImgTypeFromImgFmt
    978  *
    979  * DESCRIPTION: function to return jpeg encode image type based on its image format
    980  *
    981  * PARAMETERS :
    982  *   @img_fmt : image format
    983  *
    984  * RETURN     : return jpeg source image format (YUV or Bitstream)
    985  *==========================================================================*/
    986 mm_jpeg_format_t QCamera3PostProcessor::getJpegImgTypeFromImgFmt(cam_format_t img_fmt)
    987 {
    988     switch (img_fmt) {
    989     case CAM_FORMAT_YUV_420_NV21:
    990     case CAM_FORMAT_YUV_420_NV21_ADRENO:
    991     case CAM_FORMAT_YUV_420_NV12:
    992     case CAM_FORMAT_YUV_420_YV12:
    993     case CAM_FORMAT_YUV_422_NV61:
    994     case CAM_FORMAT_YUV_422_NV16:
    995         return MM_JPEG_FMT_YUV;
    996     default:
    997         return MM_JPEG_FMT_YUV;
    998     }
    999 }
   1000 
   1001 /*===========================================================================
   1002  * FUNCTION   : encodeFWKData
   1003  *
   1004  * DESCRIPTION: function to prepare encoding job information and send to
   1005  *              mm-jpeg-interface to do the encoding job
   1006  *
   1007  * PARAMETERS :
   1008  *   @jpeg_job_data : ptr to a struct saving job related information
   1009  *   @needNewSess   : flag to indicate if a new jpeg encoding session need
   1010  *                    to be created. After creation, this flag will be toggled
   1011  *
   1012  * RETURN     : int32_t type of status
   1013  *              NO_ERROR  -- success
   1014  *              none-zero failure code
   1015  *==========================================================================*/
   1016 int32_t QCamera3PostProcessor::encodeFWKData(qcamera_hal3_jpeg_data_t *jpeg_job_data,
   1017         uint8_t &needNewSess)
   1018 {
   1019     CDBG("%s : E", __func__);
   1020     int32_t ret = NO_ERROR;
   1021     mm_jpeg_job_t jpg_job;
   1022     uint32_t jobId = 0;
   1023     qcamera_fwk_input_pp_data_t *recvd_frame = NULL;
   1024     metadata_buffer_t *metadata = NULL;
   1025     jpeg_settings_t *jpeg_settings = NULL;
   1026     QCamera3HardwareInterface* hal_obj = NULL;
   1027     bool needJpegRotation = false;
   1028 
   1029     if (NULL == jpeg_job_data) {
   1030         ALOGE("%s: Invalid jpeg job", __func__);
   1031         return BAD_VALUE;
   1032     }
   1033 
   1034     recvd_frame = jpeg_job_data->fwk_frame;
   1035     if (NULL == recvd_frame) {
   1036         ALOGE("%s: Invalid input buffer", __func__);
   1037         return BAD_VALUE;
   1038     }
   1039 
   1040     metadata = jpeg_job_data->metadata;
   1041     if (NULL == metadata) {
   1042         ALOGE("%s: Invalid metadata buffer", __func__);
   1043         return BAD_VALUE;
   1044     }
   1045 
   1046     jpeg_settings = jpeg_job_data->jpeg_settings;
   1047     if (NULL == jpeg_settings) {
   1048         ALOGE("%s: Invalid jpeg settings buffer", __func__);
   1049         return BAD_VALUE;
   1050     }
   1051 
   1052     if ((NULL != jpeg_job_data->src_frame) && (NULL != jpeg_job_data->src_frame)) {
   1053         ALOGE("%s: Unsupported case both framework and camera source buffers are invalid!",
   1054                 __func__);
   1055         return BAD_VALUE;
   1056     }
   1057 
   1058     hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
   1059 
   1060     if (mJpegClientHandle <= 0) {
   1061         ALOGE("%s: Error: bug here, mJpegClientHandle is 0", __func__);
   1062         return UNKNOWN_ERROR;
   1063     }
   1064 
   1065     cam_dimension_t src_dim;
   1066     memset(&src_dim, 0, sizeof(cam_dimension_t));
   1067     src_dim.width = recvd_frame->reproc_config.input_stream_dim.width;
   1068     src_dim.height = recvd_frame->reproc_config.input_stream_dim.height;
   1069 
   1070     cam_dimension_t dst_dim;
   1071     memset(&dst_dim, 0, sizeof(cam_dimension_t));
   1072     dst_dim.width = recvd_frame->reproc_config.output_stream_dim.width;
   1073     dst_dim.height = recvd_frame->reproc_config.output_stream_dim.height;
   1074 
   1075     CDBG_HIGH("%s: Need new session?:%d",__func__, needNewSess);
   1076     if (needNewSess) {
   1077         //creating a new session, so we must destroy the old one
   1078         if ( 0 < mJpegSessionId ) {
   1079             ret = mJpegHandle.destroy_session(mJpegSessionId);
   1080             if (ret != NO_ERROR) {
   1081                 ALOGE("%s: Error destroying an old jpeg encoding session, id = %d",
   1082                       __func__, mJpegSessionId);
   1083                 return ret;
   1084             }
   1085             mJpegSessionId = 0;
   1086         }
   1087         // create jpeg encoding session
   1088         mm_jpeg_encode_params_t encodeParam;
   1089         memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t));
   1090         encodeParam.main_dim.src_dim = src_dim;
   1091         encodeParam.main_dim.dst_dim = dst_dim;
   1092         encodeParam.thumb_dim.src_dim = src_dim;
   1093         encodeParam.thumb_dim.dst_dim = jpeg_settings->thumbnail_size;
   1094 
   1095         getFWKJpegEncodeConfig(encodeParam, recvd_frame, jpeg_settings);
   1096         CDBG_HIGH("%s: #src bufs:%d # tmb bufs:%d #dst_bufs:%d", __func__,
   1097                      encodeParam.num_src_bufs,encodeParam.num_tmb_bufs,encodeParam.num_dst_bufs);
   1098 
   1099         ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId);
   1100         if (ret != NO_ERROR) {
   1101             ALOGE("%s: Error creating a new jpeg encoding session, ret = %d", __func__, ret);
   1102             return ret;
   1103         }
   1104         needNewSess = FALSE;
   1105     }
   1106 
   1107     // Fill in new job
   1108     memset(&jpg_job, 0, sizeof(mm_jpeg_job_t));
   1109     jpg_job.job_type = JPEG_JOB_TYPE_ENCODE;
   1110     jpg_job.encode_job.session_id = mJpegSessionId;
   1111     jpg_job.encode_job.src_index = 0;
   1112     jpg_job.encode_job.dst_index = 0;
   1113 
   1114     cam_rect_t crop;
   1115     memset(&crop, 0, sizeof(cam_rect_t));
   1116     //TBD_later - Zoom event removed in stream
   1117     //main_stream->getCropInfo(crop);
   1118 
   1119     // Set main dim job parameters and handle rotation
   1120     needJpegRotation = hal_obj->needJpegRotation();
   1121     if (!needJpegRotation && (jpeg_settings->jpeg_orientation == 90 ||
   1122             jpeg_settings->jpeg_orientation == 270)) {
   1123 
   1124         jpg_job.encode_job.main_dim.src_dim.width = src_dim.height;
   1125         jpg_job.encode_job.main_dim.src_dim.height = src_dim.width;
   1126 
   1127         jpg_job.encode_job.main_dim.dst_dim.width = dst_dim.height;
   1128         jpg_job.encode_job.main_dim.dst_dim.height = dst_dim.width;
   1129 
   1130         jpg_job.encode_job.main_dim.crop.width = crop.height;
   1131         jpg_job.encode_job.main_dim.crop.height = crop.width;
   1132         jpg_job.encode_job.main_dim.crop.left = crop.top;
   1133         jpg_job.encode_job.main_dim.crop.top = crop.left;
   1134     } else {
   1135         jpg_job.encode_job.main_dim.src_dim = src_dim;
   1136         jpg_job.encode_job.main_dim.dst_dim = dst_dim;
   1137         jpg_job.encode_job.main_dim.crop = crop;
   1138     }
   1139 
   1140     // get exif data
   1141     QCamera3Exif *pJpegExifObj = getExifData(metadata, jpeg_settings);
   1142     jpeg_job_data->pJpegExifObj = pJpegExifObj;
   1143     if (pJpegExifObj != NULL) {
   1144         jpg_job.encode_job.exif_info.exif_data = pJpegExifObj->getEntries();
   1145         jpg_job.encode_job.exif_info.numOfEntries =
   1146             pJpegExifObj->getNumOfEntries();
   1147     }
   1148 
   1149     // thumbnail dim
   1150     CDBG_HIGH("%s: Thumbnail needed:%d",__func__, m_bThumbnailNeeded);
   1151     if (m_bThumbnailNeeded == TRUE) {
   1152         memset(&crop, 0, sizeof(cam_rect_t));
   1153         jpg_job.encode_job.thumb_dim.dst_dim =
   1154                 jpeg_settings->thumbnail_size;
   1155 
   1156         if (needJpegRotation) {
   1157             jpg_job.encode_job.rotation = (uint32_t)jpeg_settings->jpeg_orientation;
   1158             CDBG_HIGH("%s: jpeg rotation is set to %u", __func__, jpg_job.encode_job.rotation);
   1159         } else if (jpeg_settings->jpeg_orientation  == 90 ||
   1160                 jpeg_settings->jpeg_orientation == 270) {
   1161             //swap the thumbnail destination width and height if it has
   1162             //already been rotated
   1163             int temp = jpg_job.encode_job.thumb_dim.dst_dim.width;
   1164             jpg_job.encode_job.thumb_dim.dst_dim.width =
   1165                     jpg_job.encode_job.thumb_dim.dst_dim.height;
   1166             jpg_job.encode_job.thumb_dim.dst_dim.height = temp;
   1167         }
   1168         jpg_job.encode_job.thumb_dim.src_dim = src_dim;
   1169         jpg_job.encode_job.thumb_dim.crop = crop;
   1170         jpg_job.encode_job.thumb_index = 0;
   1171     }
   1172 
   1173     if (metadata != NULL) {
   1174        //Fill in the metadata passed as parameter
   1175        jpg_job.encode_job.p_metadata = metadata;
   1176     } else {
   1177        ALOGE("%s: Metadata is null", __func__);
   1178     }
   1179 
   1180     jpg_job.encode_job.hal_version = CAM_HAL_V3;
   1181 
   1182     //Start jpeg encoding
   1183     ret = mJpegHandle.start_job(&jpg_job, &jobId);
   1184     if (ret == NO_ERROR) {
   1185         // remember job info
   1186         jpeg_job_data->jobId = jobId;
   1187     }
   1188 
   1189     CDBG("%s : X", __func__);
   1190     return ret;
   1191 }
   1192 
   1193 /*===========================================================================
   1194  * FUNCTION   : encodeData
   1195  *
   1196  * DESCRIPTION: function to prepare encoding job information and send to
   1197  *              mm-jpeg-interface to do the encoding job
   1198  *
   1199  * PARAMETERS :
   1200  *   @jpeg_job_data : ptr to a struct saving job related information
   1201  *   @needNewSess   : flag to indicate if a new jpeg encoding session need
   1202  *                    to be created. After creation, this flag will be toggled
   1203  *
   1204  * RETURN     : int32_t type of status
   1205  *              NO_ERROR  -- success
   1206  *              none-zero failure code
   1207  *==========================================================================*/
   1208 int32_t QCamera3PostProcessor::encodeData(qcamera_hal3_jpeg_data_t *jpeg_job_data,
   1209                           uint8_t &needNewSess)
   1210 {
   1211     ATRACE_CALL();
   1212     CDBG("%s : E", __func__);
   1213     int32_t ret = NO_ERROR;
   1214     mm_jpeg_job_t jpg_job;
   1215     uint32_t jobId = 0;
   1216     QCamera3Stream *main_stream = NULL;
   1217     mm_camera_buf_def_t *main_frame = NULL;
   1218     QCamera3Channel *srcChannel = NULL;
   1219     mm_camera_super_buf_t *recvd_frame = NULL;
   1220     metadata_buffer_t *metadata = NULL;
   1221     jpeg_settings_t *jpeg_settings = NULL;
   1222     QCamera3HardwareInterface* hal_obj = NULL;
   1223     if (m_parent != NULL) {
   1224        hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
   1225     } else {
   1226        ALOGE("%s: m_parent is NULL, Error",__func__);
   1227        return BAD_VALUE;
   1228     }
   1229     bool needJpegRotation = false;
   1230 
   1231     recvd_frame = jpeg_job_data->src_frame;
   1232     metadata = jpeg_job_data->metadata;
   1233     jpeg_settings = jpeg_job_data->jpeg_settings;
   1234 
   1235     CDBG("%s: encoding bufIndex: %u", __func__,
   1236         jpeg_job_data->src_frame->bufs[0]->buf_idx);
   1237 
   1238     QCamera3Channel *pChannel = NULL;
   1239     // first check picture channel
   1240     if (m_parent->getMyHandle() == recvd_frame->ch_id) {
   1241         pChannel = m_parent;
   1242     }
   1243     // check reprocess channel if not found
   1244     if (pChannel == NULL) {
   1245         if (m_pReprocChannel != NULL &&
   1246             m_pReprocChannel->getMyHandle() == recvd_frame->ch_id) {
   1247             pChannel = m_pReprocChannel;
   1248         }
   1249     }
   1250 
   1251     srcChannel = pChannel;
   1252 
   1253     if (srcChannel == NULL) {
   1254         ALOGE("%s: No corresponding channel (ch_id = %d) exist, return here",
   1255               __func__, recvd_frame->ch_id);
   1256         return BAD_VALUE;
   1257     }
   1258 
   1259     // find snapshot frame and thumnail frame
   1260     //Note: In this version we will receive only snapshot frame.
   1261     for (uint32_t i = 0; i < recvd_frame->num_bufs; i++) {
   1262         QCamera3Stream *srcStream =
   1263             srcChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id);
   1264         if (srcStream != NULL) {
   1265             switch (srcStream->getMyType()) {
   1266             case CAM_STREAM_TYPE_SNAPSHOT:
   1267             case CAM_STREAM_TYPE_OFFLINE_PROC:
   1268                 main_stream = srcStream;
   1269                 main_frame = recvd_frame->bufs[i];
   1270                 break;
   1271             default:
   1272                 break;
   1273             }
   1274         }
   1275     }
   1276 
   1277     if(NULL == main_frame){
   1278        ALOGE("%s : Main frame is NULL", __func__);
   1279        return BAD_VALUE;
   1280     }
   1281 
   1282     QCamera3Memory *memObj = (QCamera3Memory *)main_frame->mem_info;
   1283     if (NULL == memObj) {
   1284         ALOGE("%s : Memeory Obj of main frame is NULL", __func__);
   1285         return NO_MEMORY;
   1286     }
   1287 
   1288     // clean and invalidate cache ops through mem obj of the frame
   1289     memObj->cleanInvalidateCache(main_frame->buf_idx);
   1290 
   1291     if (mJpegClientHandle <= 0) {
   1292         ALOGE("%s: Error: bug here, mJpegClientHandle is 0", __func__);
   1293         return UNKNOWN_ERROR;
   1294     }
   1295     cam_dimension_t src_dim;
   1296     memset(&src_dim, 0, sizeof(cam_dimension_t));
   1297     main_stream->getFrameDimension(src_dim);
   1298 
   1299     cam_dimension_t dst_dim;
   1300     memset(&dst_dim, 0, sizeof(cam_dimension_t));
   1301     if (srcChannel->getStreamByIndex(0)) {
   1302        srcChannel->getStreamByIndex(0)->getFrameDimension(dst_dim);
   1303     }
   1304 
   1305     needJpegRotation = hal_obj->needJpegRotation();
   1306     CDBG_HIGH("%s: Need new session?:%d",__func__, needNewSess);
   1307     if (needNewSess) {
   1308         //creating a new session, so we must destroy the old one
   1309         if ( 0 < mJpegSessionId ) {
   1310             ret = mJpegHandle.destroy_session(mJpegSessionId);
   1311             if (ret != NO_ERROR) {
   1312                 ALOGE("%s: Error destroying an old jpeg encoding session, id = %d",
   1313                       __func__, mJpegSessionId);
   1314                 return ret;
   1315             }
   1316             mJpegSessionId = 0;
   1317         }
   1318         // create jpeg encoding session
   1319         mm_jpeg_encode_params_t encodeParam;
   1320         memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t));
   1321         getJpegEncodeConfig(encodeParam, main_stream, jpeg_settings);
   1322         CDBG_HIGH("%s: #src bufs:%d # tmb bufs:%d #dst_bufs:%d", __func__,
   1323                      encodeParam.num_src_bufs,encodeParam.num_tmb_bufs,encodeParam.num_dst_bufs);
   1324         if (!needJpegRotation &&
   1325             (jpeg_settings->jpeg_orientation == 90 ||
   1326             jpeg_settings->jpeg_orientation == 270)) {
   1327            //swap src width and height, stride and scanline due to rotation
   1328            encodeParam.main_dim.src_dim.width = src_dim.height;
   1329            encodeParam.main_dim.src_dim.height = src_dim.width;
   1330            encodeParam.thumb_dim.src_dim.width = src_dim.height;
   1331            encodeParam.thumb_dim.src_dim.height = src_dim.width;
   1332 
   1333            int32_t temp = encodeParam.src_main_buf[0].offset.mp[0].stride;
   1334            encodeParam.src_main_buf[0].offset.mp[0].stride =
   1335               encodeParam.src_main_buf[0].offset.mp[0].scanline;
   1336            encodeParam.src_main_buf[0].offset.mp[0].scanline = temp;
   1337 
   1338            temp = encodeParam.src_thumb_buf[0].offset.mp[0].stride;
   1339            encodeParam.src_thumb_buf[0].offset.mp[0].stride =
   1340               encodeParam.src_thumb_buf[0].offset.mp[0].scanline;
   1341            encodeParam.src_thumb_buf[0].offset.mp[0].scanline = temp;
   1342         } else {
   1343            encodeParam.main_dim.src_dim  = src_dim;
   1344            encodeParam.thumb_dim.src_dim = src_dim;
   1345         }
   1346         encodeParam.main_dim.dst_dim = dst_dim;
   1347         encodeParam.thumb_dim.dst_dim = jpeg_settings->thumbnail_size;
   1348         if (needJpegRotation) {
   1349            encodeParam.rotation = (uint32_t)jpeg_settings->jpeg_orientation;
   1350         }
   1351 
   1352         ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId);
   1353         if (ret != NO_ERROR) {
   1354             ALOGE("%s: Error creating a new jpeg encoding session, ret = %d", __func__, ret);
   1355             return ret;
   1356         }
   1357         needNewSess = FALSE;
   1358     }
   1359 
   1360     // Fill in new job
   1361     memset(&jpg_job, 0, sizeof(mm_jpeg_job_t));
   1362     jpg_job.job_type = JPEG_JOB_TYPE_ENCODE;
   1363     jpg_job.encode_job.session_id = mJpegSessionId;
   1364     jpg_job.encode_job.src_index = (int32_t)main_frame->buf_idx;
   1365     jpg_job.encode_job.dst_index = 0;
   1366 
   1367     if (needJpegRotation) {
   1368         jpg_job.encode_job.rotation = (uint32_t)jpeg_settings->jpeg_orientation;
   1369         CDBG("%s: %d: jpeg rotation is set to %d", __func__, __LINE__,
   1370                 jpg_job.encode_job.rotation);
   1371     }
   1372 
   1373     cam_rect_t crop;
   1374     memset(&crop, 0, sizeof(cam_rect_t));
   1375     //TBD_later - Zoom event removed in stream
   1376     //main_stream->getCropInfo(crop);
   1377 
   1378     // Set main dim job parameters and handle rotation
   1379     if (!needJpegRotation && (jpeg_settings->jpeg_orientation == 90 ||
   1380             jpeg_settings->jpeg_orientation == 270)) {
   1381 
   1382         jpg_job.encode_job.main_dim.src_dim.width = src_dim.height;
   1383         jpg_job.encode_job.main_dim.src_dim.height = src_dim.width;
   1384 
   1385         jpg_job.encode_job.main_dim.dst_dim.width = dst_dim.height;
   1386         jpg_job.encode_job.main_dim.dst_dim.height = dst_dim.width;
   1387 
   1388         jpg_job.encode_job.main_dim.crop.width = crop.height;
   1389         jpg_job.encode_job.main_dim.crop.height = crop.width;
   1390         jpg_job.encode_job.main_dim.crop.left = crop.top;
   1391         jpg_job.encode_job.main_dim.crop.top = crop.left;
   1392     } else {
   1393         jpg_job.encode_job.main_dim.src_dim = src_dim;
   1394         jpg_job.encode_job.main_dim.dst_dim = dst_dim;
   1395         jpg_job.encode_job.main_dim.crop = crop;
   1396     }
   1397 
   1398 
   1399     // get exif data
   1400     QCamera3Exif *pJpegExifObj = getExifData(metadata, jpeg_settings);
   1401     jpeg_job_data->pJpegExifObj = pJpegExifObj;
   1402     if (pJpegExifObj != NULL) {
   1403         jpg_job.encode_job.exif_info.exif_data = pJpegExifObj->getEntries();
   1404         jpg_job.encode_job.exif_info.numOfEntries =
   1405             pJpegExifObj->getNumOfEntries();
   1406     }
   1407 
   1408     // thumbnail dim
   1409     CDBG_HIGH("%s: Thumbnail needed:%d",__func__, m_bThumbnailNeeded);
   1410     if (m_bThumbnailNeeded == TRUE) {
   1411         memset(&crop, 0, sizeof(cam_rect_t));
   1412         jpg_job.encode_job.thumb_dim.dst_dim =
   1413                 jpeg_settings->thumbnail_size;
   1414 
   1415       if (!needJpegRotation &&
   1416           (jpeg_settings->jpeg_orientation  == 90 ||
   1417            jpeg_settings->jpeg_orientation == 270)) {
   1418             //swap the thumbnail destination width and height if it has
   1419             //already been rotated
   1420             int temp = jpg_job.encode_job.thumb_dim.dst_dim.width;
   1421             jpg_job.encode_job.thumb_dim.dst_dim.width =
   1422                     jpg_job.encode_job.thumb_dim.dst_dim.height;
   1423             jpg_job.encode_job.thumb_dim.dst_dim.height = temp;
   1424 
   1425             jpg_job.encode_job.thumb_dim.src_dim.width = src_dim.height;
   1426             jpg_job.encode_job.thumb_dim.src_dim.height = src_dim.width;
   1427         } else {
   1428            jpg_job.encode_job.thumb_dim.src_dim = src_dim;
   1429         }
   1430         jpg_job.encode_job.thumb_dim.crop = crop;
   1431         jpg_job.encode_job.thumb_index = main_frame->buf_idx;
   1432     }
   1433 
   1434     jpg_job.encode_job.cam_exif_params = hal_obj->get3AExifParams();
   1435     jpg_job.encode_job.mobicat_mask = hal_obj->getMobicatMask();
   1436     if (metadata != NULL) {
   1437        //Fill in the metadata passed as parameter
   1438        jpg_job.encode_job.p_metadata = metadata;
   1439 
   1440        jpg_job.encode_job.p_metadata->is_mobicat_aec_params_valid =
   1441                 jpg_job.encode_job.cam_exif_params.cam_3a_params_valid;
   1442 
   1443        if (jpg_job.encode_job.cam_exif_params.cam_3a_params_valid) {
   1444             jpg_job.encode_job.p_metadata->mobicat_aec_params =
   1445                 jpg_job.encode_job.cam_exif_params.cam_3a_params;
   1446        }
   1447 
   1448        /* Save a copy of 3A debug params */
   1449         jpg_job.encode_job.p_metadata->is_statsdebug_ae_params_valid =
   1450                 jpg_job.encode_job.cam_exif_params.ae_debug_params_valid;
   1451         jpg_job.encode_job.p_metadata->is_statsdebug_awb_params_valid =
   1452                 jpg_job.encode_job.cam_exif_params.awb_debug_params_valid;
   1453         jpg_job.encode_job.p_metadata->is_statsdebug_af_params_valid =
   1454                 jpg_job.encode_job.cam_exif_params.af_debug_params_valid;
   1455         jpg_job.encode_job.p_metadata->is_statsdebug_asd_params_valid =
   1456                 jpg_job.encode_job.cam_exif_params.asd_debug_params_valid;
   1457         jpg_job.encode_job.p_metadata->is_statsdebug_stats_params_valid =
   1458                 jpg_job.encode_job.cam_exif_params.stats_debug_params_valid;
   1459 
   1460         if (jpg_job.encode_job.cam_exif_params.ae_debug_params_valid) {
   1461             jpg_job.encode_job.p_metadata->statsdebug_ae_data =
   1462                     jpg_job.encode_job.cam_exif_params.ae_debug_params;
   1463         }
   1464         if (jpg_job.encode_job.cam_exif_params.awb_debug_params_valid) {
   1465             jpg_job.encode_job.p_metadata->statsdebug_awb_data =
   1466                     jpg_job.encode_job.cam_exif_params.awb_debug_params;
   1467         }
   1468         if (jpg_job.encode_job.cam_exif_params.af_debug_params_valid) {
   1469             jpg_job.encode_job.p_metadata->statsdebug_af_data =
   1470                     jpg_job.encode_job.cam_exif_params.af_debug_params;
   1471         }
   1472         if (jpg_job.encode_job.cam_exif_params.asd_debug_params_valid) {
   1473             jpg_job.encode_job.p_metadata->statsdebug_asd_data =
   1474                     jpg_job.encode_job.cam_exif_params.asd_debug_params;
   1475         }
   1476         if (jpg_job.encode_job.cam_exif_params.stats_debug_params_valid) {
   1477             jpg_job.encode_job.p_metadata->statsdebug_stats_buffer_data =
   1478                     jpg_job.encode_job.cam_exif_params.stats_debug_params;
   1479         }
   1480     } else {
   1481        ALOGE("%s: Metadata is null", __func__);
   1482     }
   1483 
   1484     jpg_job.encode_job.hal_version = CAM_HAL_V3;
   1485 
   1486     //Start jpeg encoding
   1487     ret = mJpegHandle.start_job(&jpg_job, &jobId);
   1488     if (ret == NO_ERROR) {
   1489         // remember job info
   1490         jpeg_job_data->jobId = jobId;
   1491     }
   1492 
   1493     CDBG("%s : X", __func__);
   1494     return ret;
   1495 }
   1496 
   1497 /*===========================================================================
   1498  * FUNCTION   : dataProcessRoutine
   1499  *
   1500  * DESCRIPTION: data process routine that handles input data either from input
   1501  *              Jpeg Queue to do jpeg encoding, or from input PP Queue to do
   1502  *              reprocess.
   1503  *
   1504  * PARAMETERS :
   1505  *   @data    : user data ptr (QCamera3PostProcessor)
   1506  *
   1507  * RETURN     : None
   1508  *==========================================================================*/
   1509 void *QCamera3PostProcessor::dataProcessRoutine(void *data)
   1510 {
   1511     int running = 1;
   1512     int ret;
   1513     uint8_t is_active = FALSE;
   1514     uint8_t needNewSess = TRUE;
   1515     mm_camera_super_buf_t *meta_buffer = NULL;
   1516     CDBG("%s: E", __func__);
   1517     QCamera3PostProcessor *pme = (QCamera3PostProcessor *)data;
   1518     QCameraCmdThread *cmdThread = &pme->m_dataProcTh;
   1519     cmdThread->setName("cam_data_proc");
   1520 
   1521     do {
   1522         do {
   1523             ret = cam_sem_wait(&cmdThread->cmd_sem);
   1524             if (ret != 0 && errno != EINVAL) {
   1525                 ALOGE("%s: cam_sem_wait error (%s)",
   1526                            __func__, strerror(errno));
   1527                 return NULL;
   1528             }
   1529         } while (ret != 0);
   1530 
   1531         // we got notified about new cmd avail in cmd queue
   1532         camera_cmd_type_t cmd = cmdThread->getCmd();
   1533         switch (cmd) {
   1534         case CAMERA_CMD_TYPE_START_DATA_PROC:
   1535             CDBG_HIGH("%s: start data proc", __func__);
   1536             is_active = TRUE;
   1537             needNewSess = TRUE;
   1538 
   1539             pme->m_ongoingPPQ.init();
   1540             pme->m_inputJpegQ.init();
   1541             pme->m_inputPPQ.init();
   1542             pme->m_inputFWKPPQ.init();
   1543             pme->m_inputRawQ.init();
   1544             pme->m_inputMetaQ.init();
   1545 
   1546             break;
   1547         case CAMERA_CMD_TYPE_STOP_DATA_PROC:
   1548             {
   1549                 CDBG_HIGH("%s: stop data proc", __func__);
   1550                 is_active = FALSE;
   1551 
   1552                 // cancel all ongoing jpeg jobs
   1553                 qcamera_hal3_jpeg_data_t *jpeg_job =
   1554                     (qcamera_hal3_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
   1555                 while (jpeg_job != NULL) {
   1556                     pme->mJpegHandle.abort_job(jpeg_job->jobId);
   1557 
   1558                     pme->releaseJpegJobData(jpeg_job);
   1559                     free(jpeg_job);
   1560 
   1561                     jpeg_job = (qcamera_hal3_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
   1562                 }
   1563 
   1564                 // destroy jpeg encoding session
   1565                 if ( 0 < pme->mJpegSessionId ) {
   1566                     pme->mJpegHandle.destroy_session(pme->mJpegSessionId);
   1567                     pme->mJpegSessionId = 0;
   1568                 }
   1569 
   1570                 needNewSess = TRUE;
   1571 
   1572                 // flush ongoing postproc Queue
   1573                 pme->m_ongoingPPQ.flush();
   1574 
   1575                 // flush input jpeg Queue
   1576                 pme->m_inputJpegQ.flush();
   1577 
   1578                 // flush input Postproc Queue
   1579                 pme->m_inputPPQ.flush();
   1580 
   1581                 // flush framework input Postproc Queue
   1582                 pme->m_inputFWKPPQ.flush();
   1583 
   1584                 // flush input raw Queue
   1585                 pme->m_inputRawQ.flush();
   1586 
   1587                 pme->m_inputMetaQ.flush();
   1588 
   1589                 // signal cmd is completed
   1590                 cam_sem_post(&cmdThread->sync_sem);
   1591             }
   1592             break;
   1593         case CAMERA_CMD_TYPE_DO_NEXT_JOB:
   1594             {
   1595                 CDBG_HIGH("%s: Do next job, active is %d", __func__, is_active);
   1596                 /* needNewSess is set to TRUE as postproc is not re-STARTed
   1597                  * anymore for every captureRequest */
   1598                 needNewSess = TRUE;
   1599                 if (is_active == TRUE) {
   1600                     // check if there is any ongoing jpeg jobs
   1601                     if (pme->m_ongoingJpegQ.isEmpty()) {
   1602                        CDBG("%s: ongoing jpeg queue is empty so doing the jpeg job", __func__);
   1603                         // no ongoing jpeg job, we are fine to send jpeg encoding job
   1604                         qcamera_hal3_jpeg_data_t *jpeg_job =
   1605                             (qcamera_hal3_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
   1606 
   1607                         if (NULL != jpeg_job) {
   1608                             // add into ongoing jpeg job Q
   1609                             pme->m_ongoingJpegQ.enqueue((void *)jpeg_job);
   1610 
   1611                             if (jpeg_job->fwk_frame) {
   1612                                 ret = pme->encodeFWKData(jpeg_job, needNewSess);
   1613                             } else {
   1614                                 ret = pme->encodeData(jpeg_job, needNewSess);
   1615                             }
   1616                             if (NO_ERROR != ret) {
   1617                                 // dequeue the last one
   1618                                 pme->m_ongoingJpegQ.dequeue(false);
   1619 
   1620                                 pme->releaseJpegJobData(jpeg_job);
   1621                                 free(jpeg_job);
   1622                             }
   1623                         }
   1624                     }
   1625 
   1626                     // check if there are any framework pp jobs
   1627                     if (!pme->m_inputFWKPPQ.isEmpty()) {
   1628                         qcamera_fwk_input_pp_data_t *fwk_frame =
   1629                                 (qcamera_fwk_input_pp_data_t *) pme->m_inputFWKPPQ.dequeue();
   1630                         if (NULL != fwk_frame) {
   1631                             qcamera_hal3_pp_data_t *pp_job =
   1632                                     (qcamera_hal3_pp_data_t *)malloc(sizeof(qcamera_hal3_pp_data_t));
   1633                             jpeg_settings_t *jpeg_settings =
   1634                                     (jpeg_settings_t *)pme->m_jpegSettingsQ.dequeue();
   1635                             if (pp_job != NULL) {
   1636                                 memset(pp_job, 0, sizeof(qcamera_hal3_pp_data_t));
   1637                                 pp_job->jpeg_settings = jpeg_settings;
   1638                                 if (pme->m_pReprocChannel != NULL) {
   1639                                     if (NO_ERROR != pme->m_pReprocChannel->extractCrop(fwk_frame)) {
   1640                                         ALOGE("%s: Failed to extract output crop", __func__);
   1641                                     }
   1642                                     // add into ongoing PP job Q
   1643                                     pp_job->fwk_src_frame = fwk_frame;
   1644                                     pme->m_ongoingPPQ.enqueue((void *)pp_job);
   1645                                     ret = pme->m_pReprocChannel->doReprocessOffline(fwk_frame);
   1646                                     if (NO_ERROR != ret) {
   1647                                         // remove from ongoing PP job Q
   1648                                         pme->m_ongoingPPQ.dequeue(false);
   1649                                     }
   1650                                 } else {
   1651                                     ALOGE("%s: Reprocess channel is NULL", __func__);
   1652                                     ret = -1;
   1653                                 }
   1654                             } else {
   1655                                 ALOGE("%s: no mem for qcamera_hal3_pp_data_t", __func__);
   1656                                 ret = -1;
   1657                             }
   1658 
   1659                             if (0 != ret) {
   1660                                 // free pp_job
   1661                                 if (pp_job != NULL) {
   1662                                     free(pp_job);
   1663                                 }
   1664                                 // free frame
   1665                                 if (fwk_frame != NULL) {
   1666                                     free(fwk_frame);
   1667                                 }
   1668                             }
   1669                         }
   1670                     }
   1671 
   1672                     CDBG_HIGH("%s: dequeuing pp frame", __func__);
   1673                     pthread_mutex_lock(&pme->mReprocJobLock);
   1674                     if(!pme->m_inputPPQ.isEmpty() && !pme->m_inputMetaQ.isEmpty()) {
   1675                         mm_camera_super_buf_t *pp_frame =
   1676                             (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue();
   1677                         meta_buffer =
   1678                             (mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue();
   1679                         jpeg_settings_t *jpeg_settings =
   1680                            (jpeg_settings_t *)pme->m_jpegSettingsQ.dequeue();
   1681                         pthread_mutex_unlock(&pme->mReprocJobLock);
   1682                         qcamera_hal3_pp_data_t *pp_job =
   1683                             (qcamera_hal3_pp_data_t *)malloc(sizeof(qcamera_hal3_pp_data_t));
   1684                         if (pp_job == NULL) {
   1685                             ALOGE("%s: no mem for qcamera_hal3_pp_data_t",
   1686                                     __func__);
   1687                             ret = -1;
   1688                         } else if (meta_buffer == NULL) {
   1689                             ALOGE("%s: no mem for mm_camera_super_buf_t",
   1690                                     __func__);
   1691                             ret = -1;
   1692                         } else {
   1693                             memset(pp_job, 0, sizeof(qcamera_hal3_pp_data_t));
   1694                             pp_job->src_frame = pp_frame;
   1695                             pp_job->src_metadata = meta_buffer;
   1696                             if (meta_buffer->bufs[0] != NULL) {
   1697                                 pp_job->metadata = (metadata_buffer_t *)
   1698                                         meta_buffer->bufs[0]->buffer;
   1699                             }
   1700                             pp_job->jpeg_settings = jpeg_settings;
   1701                             pme->m_ongoingPPQ.enqueue((void *)pp_job);
   1702                             if (pme->m_pReprocChannel != NULL) {
   1703                                 mm_camera_buf_def_t *meta_buffer_arg = NULL;
   1704                                 meta_buffer_arg = meta_buffer->bufs[0];
   1705                                 qcamera_fwk_input_pp_data_t fwk_frame;
   1706                                 memset(&fwk_frame, 0, sizeof(qcamera_fwk_input_pp_data_t));
   1707                                 ret = pme->m_pReprocChannel->extractFrameCropAndRotation(
   1708                                         pp_frame, meta_buffer_arg,
   1709                                         pp_job->jpeg_settings,
   1710                                         fwk_frame);
   1711                                 if (NO_ERROR == ret) {
   1712                                     // add into ongoing PP job Q
   1713                                     ret = pme->m_pReprocChannel->doReprocessOffline(
   1714                                             &fwk_frame);
   1715                                     if (NO_ERROR != ret) {
   1716                                         // remove from ongoing PP job Q
   1717                                         pme->m_ongoingPPQ.dequeue(false);
   1718                                     }
   1719                                 }
   1720                             } else {
   1721                                 CDBG_HIGH("%s: No reprocess. Calling processPPData directly",
   1722                                     __func__);
   1723                                 ret = pme->processPPData(pp_frame);
   1724                             }
   1725                         }
   1726 
   1727                         if (0 != ret) {
   1728                             // free pp_job
   1729                             if (pp_job != NULL) {
   1730                                 free(pp_job);
   1731                             }
   1732                             // free frame
   1733                             if (pp_frame != NULL) {
   1734                                 pme->releaseSuperBuf(pp_frame);
   1735                                 free(pp_frame);
   1736                             }
   1737                             //free metadata
   1738                             if (NULL != meta_buffer) {
   1739                                 pme->m_parent->metadataBufDone(meta_buffer);
   1740                                 free(meta_buffer);
   1741                             }
   1742                         }
   1743                     } else {
   1744                         pthread_mutex_unlock(&pme->mReprocJobLock);
   1745                     }
   1746                 } else {
   1747                     // not active, simply return buf and do no op
   1748                     qcamera_hal3_jpeg_data_t *jpeg_job =
   1749                         (qcamera_hal3_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
   1750                     if (NULL != jpeg_job) {
   1751                         free(jpeg_job);
   1752                     }
   1753                     mm_camera_super_buf_t *super_buf;
   1754                     super_buf = (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue();
   1755                     if (NULL != super_buf) {
   1756                         pme->releaseSuperBuf(super_buf);
   1757                         free(super_buf);
   1758                     }
   1759                     super_buf = (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue();
   1760                     if (NULL != super_buf) {
   1761                         pme->releaseSuperBuf(super_buf);
   1762                         free(super_buf);
   1763                     }
   1764                     mm_camera_super_buf_t *metadata = (mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue();
   1765                     if (metadata != NULL) {
   1766                         pme->m_parent->metadataBufDone(metadata);
   1767                         free(metadata);
   1768                     }
   1769                     qcamera_fwk_input_pp_data_t *fwk_frame =
   1770                             (qcamera_fwk_input_pp_data_t *) pme->m_inputFWKPPQ.dequeue();
   1771                     if (NULL != fwk_frame) {
   1772                         free(fwk_frame);
   1773                     }
   1774                 }
   1775             }
   1776             break;
   1777         case CAMERA_CMD_TYPE_EXIT:
   1778             running = 0;
   1779             break;
   1780         default:
   1781             break;
   1782         }
   1783     } while (running);
   1784     CDBG("%s: X", __func__);
   1785     return NULL;
   1786 }
   1787 
   1788 /* EXIF related helper methods */
   1789 
   1790 /*===========================================================================
   1791  * FUNCTION   : getRational
   1792  *
   1793  * DESCRIPTION: compose rational struct
   1794  *
   1795  * PARAMETERS :
   1796  *   @rat     : ptr to struct to store rational info
   1797  *   @num     :num of the rational
   1798  *   @denom   : denom of the rational
   1799  *
   1800  * RETURN     : int32_t type of status
   1801  *              NO_ERROR  -- success
   1802  *              none-zero failure code
   1803  *==========================================================================*/
   1804 int32_t getRational(rat_t *rat, int num, int denom)
   1805 {
   1806     if ((0 > num) || (0 > denom)) {
   1807         ALOGE("%s: Negative values", __func__);
   1808         return BAD_VALUE;
   1809     }
   1810     if (NULL == rat) {
   1811         ALOGE("%s: NULL rat input", __func__);
   1812         return BAD_VALUE;
   1813     }
   1814     rat->num = (uint32_t)num;
   1815     rat->denom = (uint32_t)denom;
   1816     return NO_ERROR;
   1817 }
   1818 
   1819 /*===========================================================================
   1820  * FUNCTION   : parseGPSCoordinate
   1821  *
   1822  * DESCRIPTION: parse GPS coordinate string
   1823  *
   1824  * PARAMETERS :
   1825  *   @coord_str : [input] coordinate string
   1826  *   @coord     : [output]  ptr to struct to store coordinate
   1827  *
   1828  * RETURN     : int32_t type of status
   1829  *              NO_ERROR  -- success
   1830  *              none-zero failure code
   1831  *==========================================================================*/
   1832 int parseGPSCoordinate(const char *coord_str, rat_t* coord)
   1833 {
   1834     if(coord == NULL) {
   1835         ALOGE("%s: error, invalid argument coord == NULL", __func__);
   1836         return BAD_VALUE;
   1837     }
   1838     double degF = atof(coord_str);
   1839     if (degF < 0) {
   1840         degF = -degF;
   1841     }
   1842     double minF = (degF - (int) degF) * 60;
   1843     double secF = (minF - (int) minF) * 60;
   1844 
   1845     getRational(&coord[0], (int)degF, 1);
   1846     getRational(&coord[1], (int)minF, 1);
   1847     getRational(&coord[2], (int)(secF * 10000), 10000);
   1848     return NO_ERROR;
   1849 }
   1850 
   1851 /*===========================================================================
   1852  * FUNCTION   : getExifDateTime
   1853  *
   1854  * DESCRIPTION: query exif date time
   1855  *
   1856  * PARAMETERS :
   1857  *   @dateTime   : string to store exif date time
   1858  *   @subsecTime : string to store exif subsec time
   1859  *
   1860  * RETURN     : int32_t type of status
   1861  *              NO_ERROR  -- success
   1862  *              none-zero failure code
   1863  *==========================================================================*/
   1864 int32_t getExifDateTime(String8 &dateTime, String8 &subsecTime)
   1865 {
   1866     int32_t ret = NO_ERROR;
   1867 
   1868     //get time and date from system
   1869     struct timeval tv;
   1870     struct tm timeinfo_data;
   1871 
   1872     int res = gettimeofday(&tv, NULL);
   1873     if (0 == res) {
   1874         struct tm *timeinfo = localtime_r(&tv.tv_sec, &timeinfo_data);
   1875         if (NULL != timeinfo) {
   1876             //Write datetime according to EXIF Spec
   1877             //"YYYY:MM:DD HH:MM:SS" (20 chars including \0)
   1878             dateTime = String8::format("%04d:%02d:%02d %02d:%02d:%02d",
   1879                     timeinfo->tm_year + 1900, timeinfo->tm_mon + 1,
   1880                     timeinfo->tm_mday, timeinfo->tm_hour,
   1881                     timeinfo->tm_min, timeinfo->tm_sec);
   1882             //Write subsec according to EXIF Sepc
   1883             subsecTime = String8::format("%06ld", tv.tv_usec);
   1884         } else {
   1885             ALOGE("%s: localtime_r() error", __func__);
   1886             ret = UNKNOWN_ERROR;
   1887         }
   1888     } else if (-1 == res) {
   1889         ALOGE("%s: gettimeofday() error: %s", __func__, strerror(errno));
   1890         ret = UNKNOWN_ERROR;
   1891     } else {
   1892         ALOGE("%s: gettimeofday() unexpected return code: %d", __func__, res);
   1893         ret = UNKNOWN_ERROR;
   1894     }
   1895 
   1896     return ret;
   1897 }
   1898 
   1899 /*===========================================================================
   1900  * FUNCTION   : getExifFocalLength
   1901  *
   1902  * DESCRIPTION: get exif focal length
   1903  *
   1904  * PARAMETERS :
   1905  *   @focalLength : ptr to rational struct to store focal length
   1906  *   @value       : focal length value
   1907  *
   1908  * RETURN     : int32_t type of status
   1909  *              NO_ERROR  -- success
   1910  *              none-zero failure code
   1911  *==========================================================================*/
   1912 int32_t getExifFocalLength(rat_t *focalLength, float value)
   1913 {
   1914     int focalLengthValue =
   1915         (int)(value * FOCAL_LENGTH_DECIMAL_PRECISION);
   1916     return getRational(focalLength, focalLengthValue, FOCAL_LENGTH_DECIMAL_PRECISION);
   1917 }
   1918 
   1919 /*===========================================================================
   1920   * FUNCTION   : getExifExpTimeInfo
   1921   *
   1922   * DESCRIPTION: get exif exposure time information
   1923   *
   1924   * PARAMETERS :
   1925   *   @expoTimeInfo     : rational exposure time value
   1926   *   @value            : exposure time value
   1927   * RETURN     : nt32_t type of status
   1928   *              NO_ERROR  -- success
   1929   *              none-zero failure code
   1930   *==========================================================================*/
   1931 int32_t getExifExpTimeInfo(rat_t *expoTimeInfo, int64_t value)
   1932 {
   1933 
   1934     int64_t cal_exposureTime;
   1935     if (value != 0)
   1936         cal_exposureTime = value;
   1937     else
   1938         cal_exposureTime = 60;
   1939 
   1940     return getRational(expoTimeInfo, 1, (int)cal_exposureTime);
   1941 }
   1942 
   1943 /*===========================================================================
   1944  * FUNCTION   : getExifGpsProcessingMethod
   1945  *
   1946  * DESCRIPTION: get GPS processing method
   1947  *
   1948  * PARAMETERS :
   1949  *   @gpsProcessingMethod : string to store GPS process method
   1950  *   @count               : length of the string
   1951  *   @value               : the value of the processing method
   1952  *
   1953  * RETURN     : int32_t type of status
   1954  *              NO_ERROR  -- success
   1955  *              none-zero failure code
   1956  *==========================================================================*/
   1957 int32_t getExifGpsProcessingMethod(char *gpsProcessingMethod,
   1958         uint32_t &count, char* value)
   1959 {
   1960     if(value != NULL) {
   1961         memcpy(gpsProcessingMethod, ExifAsciiPrefix, EXIF_ASCII_PREFIX_SIZE);
   1962         count = EXIF_ASCII_PREFIX_SIZE;
   1963         strlcpy(gpsProcessingMethod + EXIF_ASCII_PREFIX_SIZE,
   1964                 value,
   1965                 strlen(value)+1);
   1966         count += (uint32_t)strlen(value);
   1967         gpsProcessingMethod[count++] = '\0'; // increase 1 for the last NULL char
   1968         return NO_ERROR;
   1969     } else {
   1970         return BAD_VALUE;
   1971     }
   1972 }
   1973 
   1974 /*===========================================================================
   1975  * FUNCTION   : getExifLatitude
   1976  *
   1977  * DESCRIPTION: get exif latitude
   1978  *
   1979  * PARAMETERS :
   1980  *   @latitude : ptr to rational struct to store latitude info
   1981  *   @ladRef   : charater to indicate latitude reference
   1982  *   @value    : value of the latitude
   1983  *
   1984  * RETURN     : int32_t type of status
   1985  *              NO_ERROR  -- success
   1986  *              none-zero failure code
   1987  *==========================================================================*/
   1988 int32_t getExifLatitude(rat_t *latitude, char *latRef, double value)
   1989 {
   1990     char str[30];
   1991     snprintf(str, sizeof(str), "%f", value);
   1992     if(str != NULL) {
   1993         parseGPSCoordinate(str, latitude);
   1994 
   1995         //set Latitude Ref
   1996         float latitudeValue = strtof(str, 0);
   1997         if(latitudeValue < 0.0f) {
   1998             latRef[0] = 'S';
   1999         } else {
   2000             latRef[0] = 'N';
   2001         }
   2002         latRef[1] = '\0';
   2003         return NO_ERROR;
   2004     }else{
   2005         return BAD_VALUE;
   2006     }
   2007 }
   2008 
   2009 /*===========================================================================
   2010  * FUNCTION   : getExifLongitude
   2011  *
   2012  * DESCRIPTION: get exif longitude
   2013  *
   2014  * PARAMETERS :
   2015  *   @longitude : ptr to rational struct to store longitude info
   2016  *   @lonRef    : charater to indicate longitude reference
   2017  *   @value     : value of the longitude
   2018  *
   2019  * RETURN     : int32_t type of status
   2020  *              NO_ERROR  -- success
   2021  *              none-zero failure code
   2022  *==========================================================================*/
   2023 int32_t getExifLongitude(rat_t *longitude, char *lonRef, double value)
   2024 {
   2025     char str[30];
   2026     snprintf(str, sizeof(str), "%f", value);
   2027     if(str != NULL) {
   2028         parseGPSCoordinate(str, longitude);
   2029 
   2030         //set Longitude Ref
   2031         float longitudeValue = strtof(str, 0);
   2032         if(longitudeValue < 0.0f) {
   2033             lonRef[0] = 'W';
   2034         } else {
   2035             lonRef[0] = 'E';
   2036         }
   2037         lonRef[1] = '\0';
   2038         return NO_ERROR;
   2039     }else{
   2040         return BAD_VALUE;
   2041     }
   2042 }
   2043 
   2044 /*===========================================================================
   2045  * FUNCTION   : getExifAltitude
   2046  *
   2047  * DESCRIPTION: get exif altitude
   2048  *
   2049  * PARAMETERS :
   2050  *   @altitude : ptr to rational struct to store altitude info
   2051  *   @altRef   : charater to indicate altitude reference
   2052  *   @argValue : altitude value
   2053  *
   2054  * RETURN     : int32_t type of status
   2055  *              NO_ERROR  -- success
   2056  *              none-zero failure code
   2057  *==========================================================================*/
   2058 int32_t getExifAltitude(rat_t *altitude, char *altRef, double argValue)
   2059 {
   2060     char str[30];
   2061     snprintf(str, sizeof(str), "%f", argValue);
   2062     if (str != NULL) {
   2063         double value = atof(str);
   2064         *altRef = 0;
   2065         if(value < 0){
   2066             *altRef = 1;
   2067             value = -value;
   2068         }
   2069         return getRational(altitude, (int)(value * 1000), 1000);
   2070     } else {
   2071         return BAD_VALUE;
   2072     }
   2073 }
   2074 
   2075 /*===========================================================================
   2076  * FUNCTION   : getExifGpsDateTimeStamp
   2077  *
   2078  * DESCRIPTION: get exif GPS date time stamp
   2079  *
   2080  * PARAMETERS :
   2081  *   @gpsDateStamp : GPS date time stamp string
   2082  *   @bufLen       : length of the string
   2083  *   @gpsTimeStamp : ptr to rational struct to store time stamp info
   2084  *
   2085  * RETURN     : int32_t type of status
   2086  *              NO_ERROR  -- success
   2087  *              none-zero failure code
   2088  *==========================================================================*/
   2089 int32_t getExifGpsDateTimeStamp(char *gpsDateStamp, uint32_t bufLen,
   2090         rat_t *gpsTimeStamp, int64_t value)
   2091 {
   2092     char str[30];
   2093     snprintf(str, sizeof(str), "%lld", (long long int)value);
   2094     if(str != NULL) {
   2095         time_t unixTime = (time_t)atol(str);
   2096         struct tm *UTCTimestamp = gmtime(&unixTime);
   2097         if (UTCTimestamp != NULL && gpsDateStamp != NULL
   2098                 && gpsTimeStamp != NULL) {
   2099             strftime(gpsDateStamp, bufLen, "%Y:%m:%d", UTCTimestamp);
   2100 
   2101             getRational(&gpsTimeStamp[0], UTCTimestamp->tm_hour, 1);
   2102             getRational(&gpsTimeStamp[1], UTCTimestamp->tm_min, 1);
   2103             getRational(&gpsTimeStamp[2], UTCTimestamp->tm_sec, 1);
   2104             return NO_ERROR;
   2105         } else {
   2106             ALOGE("%s: Could not get the timestamp", __func__);
   2107             return BAD_VALUE;
   2108         }
   2109     } else {
   2110         return BAD_VALUE;
   2111     }
   2112 }
   2113 
   2114 /*===========================================================================
   2115  * FUNCTION   : getExifExposureValue
   2116  *
   2117  * DESCRIPTION: get exif GPS date time stamp
   2118  *
   2119  * PARAMETERS :
   2120  *   @exposure_val        : rational exposure value
   2121  *   @exposure_comp       : exposure compensation
   2122  *   @step                : exposure step
   2123  *
   2124  * RETURN     : int32_t type of status
   2125  *              NO_ERROR  -- success
   2126  *              none-zero failure code
   2127  *==========================================================================*/
   2128 int32_t getExifExposureValue(srat_t* exposure_val, int32_t exposure_comp,
   2129         cam_rational_type_t step)
   2130 {
   2131     exposure_val->num = exposure_comp * step.numerator;
   2132     exposure_val->denom = step.denominator;
   2133     return 0;
   2134 }
   2135 
   2136 /*===========================================================================
   2137  * FUNCTION   : getExifData
   2138  *
   2139  * DESCRIPTION: get exif data to be passed into jpeg encoding
   2140  *
   2141  * PARAMETERS : none
   2142  *
   2143  * RETURN     : exif data from user setting and GPS
   2144  *==========================================================================*/
   2145 QCamera3Exif *QCamera3PostProcessor::getExifData(metadata_buffer_t *metadata,
   2146         jpeg_settings_t *jpeg_settings)
   2147 {
   2148     QCamera3Exif *exif = new QCamera3Exif();
   2149     if (exif == NULL) {
   2150         ALOGE("%s: No memory for QCamera3Exif", __func__);
   2151         return NULL;
   2152     }
   2153 
   2154     int32_t rc = NO_ERROR;
   2155     uint32_t count = 0;
   2156 
   2157     // add exif entries
   2158     String8 dateTime;
   2159     String8 subsecTime;
   2160     rc = getExifDateTime(dateTime, subsecTime);
   2161     if (rc == NO_ERROR) {
   2162         exif->addEntry(EXIFTAGID_DATE_TIME, EXIF_ASCII,
   2163                 (uint32_t)(dateTime.length() + 1), (void *)dateTime.string());
   2164         exif->addEntry(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL, EXIF_ASCII,
   2165                 (uint32_t)(dateTime.length() + 1), (void *)dateTime.string());
   2166         exif->addEntry(EXIFTAGID_EXIF_DATE_TIME_DIGITIZED, EXIF_ASCII,
   2167                 (uint32_t)(dateTime.length() + 1), (void *)dateTime.string());
   2168         exif->addEntry(EXIFTAGID_SUBSEC_TIME, EXIF_ASCII,
   2169                 (uint32_t)(subsecTime.length() + 1), (void *)subsecTime.string());
   2170         exif->addEntry(EXIFTAGID_SUBSEC_TIME_ORIGINAL, EXIF_ASCII,
   2171                 (uint32_t)(subsecTime.length() + 1), (void *)subsecTime.string());
   2172         exif->addEntry(EXIFTAGID_SUBSEC_TIME_DIGITIZED, EXIF_ASCII,
   2173                 (uint32_t)(subsecTime.length() + 1), (void *)subsecTime.string());
   2174     } else {
   2175         ALOGE("%s: getExifDateTime failed", __func__);
   2176     }
   2177 
   2178 
   2179     if (metadata != NULL) {
   2180         IF_META_AVAILABLE(float, focal_length, CAM_INTF_META_LENS_FOCAL_LENGTH, metadata) {
   2181             rat_t focalLength;
   2182             rc = getExifFocalLength(&focalLength, *focal_length);
   2183             if (rc == NO_ERROR) {
   2184                 exif->addEntry(EXIFTAGID_FOCAL_LENGTH,
   2185                         EXIF_RATIONAL,
   2186                         1,
   2187                         (void *)&(focalLength));
   2188             } else {
   2189                 ALOGE("%s: getExifFocalLength failed", __func__);
   2190             }
   2191         }
   2192 
   2193         IF_META_AVAILABLE(int32_t, isoSpeed, CAM_INTF_META_SENSOR_SENSITIVITY, metadata) {
   2194             int16_t fwk_isoSpeed = (int16_t) *isoSpeed;
   2195             exif->addEntry(EXIFTAGID_ISO_SPEED_RATING, EXIF_SHORT, 1, (void *) &(fwk_isoSpeed));
   2196         }
   2197 
   2198 
   2199         IF_META_AVAILABLE(int64_t, sensor_exposure_time,
   2200                 CAM_INTF_META_SENSOR_EXPOSURE_TIME, metadata) {
   2201             rat_t sensorExpTime;
   2202             rc = getExifExpTimeInfo(&sensorExpTime, *sensor_exposure_time);
   2203             if (rc == NO_ERROR){
   2204                 exif->addEntry(EXIFTAGID_EXPOSURE_TIME,
   2205                         EXIF_RATIONAL,
   2206                         1,
   2207                         (void *)&(sensorExpTime));
   2208             } else {
   2209                 ALOGE("%s: getExifExpTimeInfo failed", __func__);
   2210             }
   2211         }
   2212 
   2213         char* jpeg_gps_processing_method = jpeg_settings->gps_processing_method;
   2214         if (strlen(jpeg_gps_processing_method) > 0) {
   2215             char gpsProcessingMethod[EXIF_ASCII_PREFIX_SIZE +
   2216                     GPS_PROCESSING_METHOD_SIZE];
   2217             count = 0;
   2218             rc = getExifGpsProcessingMethod(gpsProcessingMethod,
   2219                     count,
   2220                     jpeg_gps_processing_method);
   2221             if(rc == NO_ERROR) {
   2222                 exif->addEntry(EXIFTAGID_GPS_PROCESSINGMETHOD,
   2223                         EXIF_ASCII,
   2224                         count,
   2225                         (void *)gpsProcessingMethod);
   2226             } else {
   2227                 ALOGE("%s: getExifGpsProcessingMethod failed", __func__);
   2228             }
   2229         }
   2230 
   2231         if (jpeg_settings->gps_coordinates_valid) {
   2232 
   2233             //latitude
   2234             rat_t latitude[3];
   2235             char latRef[2];
   2236             rc = getExifLatitude(latitude, latRef,
   2237                     jpeg_settings->gps_coordinates[0]);
   2238             if(rc == NO_ERROR) {
   2239                 exif->addEntry(EXIFTAGID_GPS_LATITUDE,
   2240                         EXIF_RATIONAL,
   2241                         3,
   2242                         (void *)latitude);
   2243                 exif->addEntry(EXIFTAGID_GPS_LATITUDE_REF,
   2244                         EXIF_ASCII,
   2245                         2,
   2246                         (void *)latRef);
   2247             } else {
   2248                 ALOGE("%s: getExifLatitude failed", __func__);
   2249             }
   2250 
   2251             //longitude
   2252             rat_t longitude[3];
   2253             char lonRef[2];
   2254             rc = getExifLongitude(longitude, lonRef,
   2255                     jpeg_settings->gps_coordinates[1]);
   2256             if(rc == NO_ERROR) {
   2257                 exif->addEntry(EXIFTAGID_GPS_LONGITUDE,
   2258                         EXIF_RATIONAL,
   2259                         3,
   2260                         (void *)longitude);
   2261 
   2262                 exif->addEntry(EXIFTAGID_GPS_LONGITUDE_REF,
   2263                         EXIF_ASCII,
   2264                         2,
   2265                         (void *)lonRef);
   2266             } else {
   2267                 ALOGE("%s: getExifLongitude failed", __func__);
   2268             }
   2269 
   2270             //altitude
   2271             rat_t altitude;
   2272             char altRef;
   2273             rc = getExifAltitude(&altitude, &altRef,
   2274                     jpeg_settings->gps_coordinates[2]);
   2275             if(rc == NO_ERROR) {
   2276                 exif->addEntry(EXIFTAGID_GPS_ALTITUDE,
   2277                         EXIF_RATIONAL,
   2278                         1,
   2279                         (void *)&(altitude));
   2280 
   2281                 exif->addEntry(EXIFTAGID_GPS_ALTITUDE_REF,
   2282                         EXIF_BYTE,
   2283                         1,
   2284                         (void *)&altRef);
   2285             } else {
   2286                 ALOGE("%s: getExifAltitude failed", __func__);
   2287             }
   2288         }
   2289 
   2290         if (jpeg_settings->gps_timestamp_valid) {
   2291 
   2292             char gpsDateStamp[20];
   2293             rat_t gpsTimeStamp[3];
   2294             rc = getExifGpsDateTimeStamp(gpsDateStamp, 20, gpsTimeStamp,
   2295                     jpeg_settings->gps_timestamp);
   2296             if(rc == NO_ERROR) {
   2297                 exif->addEntry(EXIFTAGID_GPS_DATESTAMP, EXIF_ASCII,
   2298                         (uint32_t)(strlen(gpsDateStamp) + 1),
   2299                         (void *)gpsDateStamp);
   2300 
   2301                 exif->addEntry(EXIFTAGID_GPS_TIMESTAMP,
   2302                         EXIF_RATIONAL,
   2303                         3,
   2304                         (void *)gpsTimeStamp);
   2305             } else {
   2306                 ALOGE("%s: getExifGpsDataTimeStamp failed", __func__);
   2307             }
   2308         }
   2309 
   2310         IF_META_AVAILABLE(int32_t, exposure_comp, CAM_INTF_PARM_EXPOSURE_COMPENSATION, metadata) {
   2311             IF_META_AVAILABLE(cam_rational_type_t, comp_step, CAM_INTF_PARM_EV_STEP, metadata) {
   2312                 srat_t exposure_val;
   2313                 rc = getExifExposureValue(&exposure_val, *exposure_comp, *comp_step);
   2314                 if(rc == NO_ERROR) {
   2315                     exif->addEntry(EXIFTAGID_EXPOSURE_BIAS_VALUE,
   2316                             EXIF_SRATIONAL,
   2317                             1,
   2318                             (void *)(&exposure_val));
   2319                 } else {
   2320                     ALOGE("%s: getExifExposureValue failed ", __func__);
   2321                 }
   2322             }
   2323         }
   2324     } else {
   2325         ALOGE("%s: no metadata provided ", __func__);
   2326     }
   2327 
   2328     char value[PROPERTY_VALUE_MAX];
   2329     if (property_get("ro.product.manufacturer", value, "QCOM-AA") > 0) {
   2330         exif->addEntry(EXIFTAGID_MAKE, EXIF_ASCII,
   2331                 (uint32_t)(strlen(value) + 1), (void *)value);
   2332     } else {
   2333         ALOGE("%s: getExifMaker failed", __func__);
   2334     }
   2335 
   2336     if (property_get("ro.product.model", value, "QCAM-AA") > 0) {
   2337         exif->addEntry(EXIFTAGID_MODEL, EXIF_ASCII,
   2338                 (uint32_t)(strlen(value) + 1), (void *)value);
   2339     } else {
   2340         ALOGE("%s: getExifModel failed", __func__);
   2341     }
   2342 
   2343     if (property_get("ro.build.description", value, "QCAM-AA") > 0) {
   2344         exif->addEntry(EXIFTAGID_SOFTWARE, EXIF_ASCII,
   2345                 (uint32_t)(strlen(value) + 1), (void *)value);
   2346     } else {
   2347         ALOGE("%s: getExifSoftware failed", __func__);
   2348     }
   2349 
   2350     return exif;
   2351 }
   2352 
   2353 /*===========================================================================
   2354  * FUNCTION   : QCamera3Exif
   2355  *
   2356  * DESCRIPTION: constructor of QCamera3Exif
   2357  *
   2358  * PARAMETERS : None
   2359  *
   2360  * RETURN     : None
   2361  *==========================================================================*/
   2362 QCamera3Exif::QCamera3Exif()
   2363     : m_nNumEntries(0)
   2364 {
   2365     memset(m_Entries, 0, sizeof(m_Entries));
   2366 }
   2367 
   2368 /*===========================================================================
   2369  * FUNCTION   : ~QCamera3Exif
   2370  *
   2371  * DESCRIPTION: deconstructor of QCamera3Exif. Will release internal memory ptr.
   2372  *
   2373  * PARAMETERS : None
   2374  *
   2375  * RETURN     : None
   2376  *==========================================================================*/
   2377 QCamera3Exif::~QCamera3Exif()
   2378 {
   2379     for (uint32_t i = 0; i < m_nNumEntries; i++) {
   2380         switch (m_Entries[i].tag_entry.type) {
   2381             case EXIF_BYTE:
   2382                 {
   2383                     if (m_Entries[i].tag_entry.count > 1 &&
   2384                             m_Entries[i].tag_entry.data._bytes != NULL) {
   2385                         free(m_Entries[i].tag_entry.data._bytes);
   2386                         m_Entries[i].tag_entry.data._bytes = NULL;
   2387                     }
   2388                 }
   2389                 break;
   2390             case EXIF_ASCII:
   2391                 {
   2392                     if (m_Entries[i].tag_entry.data._ascii != NULL) {
   2393                         free(m_Entries[i].tag_entry.data._ascii);
   2394                         m_Entries[i].tag_entry.data._ascii = NULL;
   2395                     }
   2396                 }
   2397                 break;
   2398             case EXIF_SHORT:
   2399                 {
   2400                     if (m_Entries[i].tag_entry.count > 1 &&
   2401                             m_Entries[i].tag_entry.data._shorts != NULL) {
   2402                         free(m_Entries[i].tag_entry.data._shorts);
   2403                         m_Entries[i].tag_entry.data._shorts = NULL;
   2404                     }
   2405                 }
   2406                 break;
   2407             case EXIF_LONG:
   2408                 {
   2409                     if (m_Entries[i].tag_entry.count > 1 &&
   2410                             m_Entries[i].tag_entry.data._longs != NULL) {
   2411                         free(m_Entries[i].tag_entry.data._longs);
   2412                         m_Entries[i].tag_entry.data._longs = NULL;
   2413                     }
   2414                 }
   2415                 break;
   2416             case EXIF_RATIONAL:
   2417                 {
   2418                     if (m_Entries[i].tag_entry.count > 1 &&
   2419                             m_Entries[i].tag_entry.data._rats != NULL) {
   2420                         free(m_Entries[i].tag_entry.data._rats);
   2421                         m_Entries[i].tag_entry.data._rats = NULL;
   2422                     }
   2423                 }
   2424                 break;
   2425             case EXIF_UNDEFINED:
   2426                 {
   2427                     if (m_Entries[i].tag_entry.data._undefined != NULL) {
   2428                         free(m_Entries[i].tag_entry.data._undefined);
   2429                         m_Entries[i].tag_entry.data._undefined = NULL;
   2430                     }
   2431                 }
   2432                 break;
   2433             case EXIF_SLONG:
   2434                 {
   2435                     if (m_Entries[i].tag_entry.count > 1 &&
   2436                             m_Entries[i].tag_entry.data._slongs != NULL) {
   2437                         free(m_Entries[i].tag_entry.data._slongs);
   2438                         m_Entries[i].tag_entry.data._slongs = NULL;
   2439                     }
   2440                 }
   2441                 break;
   2442             case EXIF_SRATIONAL:
   2443                 {
   2444                     if (m_Entries[i].tag_entry.count > 1 &&
   2445                             m_Entries[i].tag_entry.data._srats != NULL) {
   2446                         free(m_Entries[i].tag_entry.data._srats);
   2447                         m_Entries[i].tag_entry.data._srats = NULL;
   2448                     }
   2449                 }
   2450                 break;
   2451             default:
   2452                 ALOGE("%s: Error, Unknown type",__func__);
   2453                 break;
   2454         }
   2455     }
   2456 }
   2457 
   2458 /*===========================================================================
   2459  * FUNCTION   : addEntry
   2460  *
   2461  * DESCRIPTION: function to add an entry to exif data
   2462  *
   2463  * PARAMETERS :
   2464  *   @tagid   : exif tag ID
   2465  *   @type    : data type
   2466  *   @count   : number of data in uint of its type
   2467  *   @data    : input data ptr
   2468  *
   2469  * RETURN     : int32_t type of status
   2470  *              NO_ERROR  -- success
   2471  *              none-zero failure code
   2472  *==========================================================================*/
   2473 int32_t QCamera3Exif::addEntry(exif_tag_id_t tagid,
   2474                               exif_tag_type_t type,
   2475                               uint32_t count,
   2476                               void *data)
   2477 {
   2478     int32_t rc = NO_ERROR;
   2479     if(m_nNumEntries >= MAX_HAL3_EXIF_TABLE_ENTRIES) {
   2480         ALOGE("%s: Number of entries exceeded limit", __func__);
   2481         return NO_MEMORY;
   2482     }
   2483 
   2484     m_Entries[m_nNumEntries].tag_id = tagid;
   2485     m_Entries[m_nNumEntries].tag_entry.type = type;
   2486     m_Entries[m_nNumEntries].tag_entry.count = count;
   2487     m_Entries[m_nNumEntries].tag_entry.copy = 1;
   2488     switch (type) {
   2489         case EXIF_BYTE:
   2490             {
   2491                 if (count > 1) {
   2492                     uint8_t *values = (uint8_t *)malloc(count);
   2493                     if (values == NULL) {
   2494                         ALOGE("%s: No memory for byte array", __func__);
   2495                         rc = NO_MEMORY;
   2496                     } else {
   2497                         memcpy(values, data, count);
   2498                         m_Entries[m_nNumEntries].tag_entry.data._bytes = values;
   2499                     }
   2500                 } else {
   2501                     m_Entries[m_nNumEntries].tag_entry.data._byte =
   2502                         *(uint8_t *)data;
   2503                 }
   2504             }
   2505             break;
   2506         case EXIF_ASCII:
   2507             {
   2508                 char *str = NULL;
   2509                 str = (char *)malloc(count + 1);
   2510                 if (str == NULL) {
   2511                     ALOGE("%s: No memory for ascii string", __func__);
   2512                     rc = NO_MEMORY;
   2513                 } else {
   2514                     memset(str, 0, count + 1);
   2515                     memcpy(str, data, count);
   2516                     m_Entries[m_nNumEntries].tag_entry.data._ascii = str;
   2517                 }
   2518             }
   2519             break;
   2520         case EXIF_SHORT:
   2521             {
   2522                 if (count > 1) {
   2523                     uint16_t *values =
   2524                         (uint16_t *)malloc(count * sizeof(uint16_t));
   2525                     if (values == NULL) {
   2526                         ALOGE("%s: No memory for short array", __func__);
   2527                         rc = NO_MEMORY;
   2528                     } else {
   2529                         memcpy(values, data, count * sizeof(uint16_t));
   2530                         m_Entries[m_nNumEntries].tag_entry.data._shorts =values;
   2531                     }
   2532                 } else {
   2533                     m_Entries[m_nNumEntries].tag_entry.data._short =
   2534                         *(uint16_t *)data;
   2535                 }
   2536             }
   2537             break;
   2538         case EXIF_LONG:
   2539             {
   2540                 if (count > 1) {
   2541                     uint32_t *values =
   2542                         (uint32_t *)malloc(count * sizeof(uint32_t));
   2543                     if (values == NULL) {
   2544                         ALOGE("%s: No memory for long array", __func__);
   2545                         rc = NO_MEMORY;
   2546                     } else {
   2547                         memcpy(values, data, count * sizeof(uint32_t));
   2548                         m_Entries[m_nNumEntries].tag_entry.data._longs = values;
   2549                     }
   2550                 } else {
   2551                     m_Entries[m_nNumEntries].tag_entry.data._long =
   2552                         *(uint32_t *)data;
   2553                 }
   2554             }
   2555             break;
   2556         case EXIF_RATIONAL:
   2557             {
   2558                 if (count > 1) {
   2559                     rat_t *values = (rat_t *)malloc(count * sizeof(rat_t));
   2560                     if (values == NULL) {
   2561                         ALOGE("%s: No memory for rational array", __func__);
   2562                         rc = NO_MEMORY;
   2563                     } else {
   2564                         memcpy(values, data, count * sizeof(rat_t));
   2565                         m_Entries[m_nNumEntries].tag_entry.data._rats = values;
   2566                     }
   2567                 } else {
   2568                     m_Entries[m_nNumEntries].tag_entry.data._rat =
   2569                         *(rat_t *)data;
   2570                 }
   2571             }
   2572             break;
   2573         case EXIF_UNDEFINED:
   2574             {
   2575                 uint8_t *values = (uint8_t *)malloc(count);
   2576                 if (values == NULL) {
   2577                     ALOGE("%s: No memory for undefined array", __func__);
   2578                     rc = NO_MEMORY;
   2579                 } else {
   2580                     memcpy(values, data, count);
   2581                     m_Entries[m_nNumEntries].tag_entry.data._undefined = values;
   2582                 }
   2583             }
   2584             break;
   2585         case EXIF_SLONG:
   2586             {
   2587                 if (count > 1) {
   2588                     int32_t *values =
   2589                         (int32_t *)malloc(count * sizeof(int32_t));
   2590                     if (values == NULL) {
   2591                         ALOGE("%s: No memory for signed long array", __func__);
   2592                         rc = NO_MEMORY;
   2593                     } else {
   2594                         memcpy(values, data, count * sizeof(int32_t));
   2595                         m_Entries[m_nNumEntries].tag_entry.data._slongs =values;
   2596                     }
   2597                 } else {
   2598                     m_Entries[m_nNumEntries].tag_entry.data._slong =
   2599                         *(int32_t *)data;
   2600                 }
   2601             }
   2602             break;
   2603         case EXIF_SRATIONAL:
   2604             {
   2605                 if (count > 1) {
   2606                     srat_t *values = (srat_t *)malloc(count * sizeof(srat_t));
   2607                     if (values == NULL) {
   2608                         ALOGE("%s: No memory for sign rational array",__func__);
   2609                         rc = NO_MEMORY;
   2610                     } else {
   2611                         memcpy(values, data, count * sizeof(srat_t));
   2612                         m_Entries[m_nNumEntries].tag_entry.data._srats = values;
   2613                     }
   2614                 } else {
   2615                     m_Entries[m_nNumEntries].tag_entry.data._srat =
   2616                         *(srat_t *)data;
   2617                 }
   2618             }
   2619             break;
   2620         default:
   2621             ALOGE("%s: Error, Unknown type",__func__);
   2622             break;
   2623     }
   2624 
   2625     // Increase number of entries
   2626     m_nNumEntries++;
   2627     return rc;
   2628 }
   2629 
   2630 }; // namespace qcamera
   2631