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