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