Home | History | Annotate | Download | only in HAL3
      1 /* Copyright (c) 2012-2013, The Linux Foundataion. All rights reserved.
      2 *
      3 * Redistribution and use in source and binary forms, with or without
      4 * modification, are permitted provided that the following conditions are
      5 * met:
      6 *     * Redistributions of source code must retain the above copyright
      7 *       notice, this list of conditions and the following disclaimer.
      8 *     * Redistributions in binary form must reproduce the above
      9 *       copyright notice, this list of conditions and the following
     10 *       disclaimer in the documentation and/or other materials provided
     11 *       with the distribution.
     12 *     * Neither the name of The Linux Foundation nor the names of its
     13 *       contributors may be used to endorse or promote products derived
     14 *       from this software without specific prior written permission.
     15 *
     16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 *
     28 */
     29 
     30 #define LOG_TAG "QCamera3Channel"
     31 
     32 #include <stdlib.h>
     33 #include <cstdlib>
     34 #include <cutils/properties.h>
     35 #include <stdio.h>
     36 #include <string.h>
     37 #include <hardware/camera3.h>
     38 #include <math.h>
     39 #include <system/camera_metadata.h>
     40 #include <gralloc_priv.h>
     41 #include <utils/Log.h>
     42 #include <utils/Errors.h>
     43 #include <cutils/properties.h>
     44 #include "QCamera3Channel.h"
     45 
     46 using namespace android;
     47 
     48 #define MIN_STREAMING_BUFFER_NUM 7
     49 
     50 namespace qcamera {
     51 static const char ExifAsciiPrefix[] =
     52     { 0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0 };          // "ASCII\0\0\0"
     53 static const char ExifUndefinedPrefix[] =
     54     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };   // "\0\0\0\0\0\0\0\0"
     55 
     56 #define GPS_PROCESSING_METHOD_SIZE       101
     57 #define EXIF_ASCII_PREFIX_SIZE           8   //(sizeof(ExifAsciiPrefix))
     58 #define FOCAL_LENGTH_DECIMAL_PRECISION   100
     59 
     60 /*===========================================================================
     61  * FUNCTION   : QCamera3Channel
     62  *
     63  * DESCRIPTION: constrcutor of QCamera3Channel
     64  *
     65  * PARAMETERS :
     66  *   @cam_handle : camera handle
     67  *   @cam_ops    : ptr to camera ops table
     68  *
     69  * RETURN     : none
     70  *==========================================================================*/
     71 QCamera3Channel::QCamera3Channel(uint32_t cam_handle,
     72                                mm_camera_ops_t *cam_ops,
     73                                channel_cb_routine cb_routine,
     74                                cam_padding_info_t *paddingInfo,
     75                                void *userData)
     76 {
     77     m_camHandle = cam_handle;
     78     m_camOps = cam_ops;
     79     m_bIsActive = false;
     80 
     81     m_handle = 0;
     82     m_numStreams = 0;
     83     memset(mStreams, 0, sizeof(mStreams));
     84     mUserData = userData;
     85 
     86     mStreamInfoBuf = NULL;
     87     mChannelCB = cb_routine;
     88     mPaddingInfo = paddingInfo;
     89 }
     90 
     91 /*===========================================================================
     92  * FUNCTION   : QCamera3Channel
     93  *
     94  * DESCRIPTION: default constrcutor of QCamera3Channel
     95  *
     96  * PARAMETERS : none
     97  *
     98  * RETURN     : none
     99  *==========================================================================*/
    100 QCamera3Channel::QCamera3Channel()
    101 {
    102     m_camHandle = 0;
    103     m_camOps = NULL;
    104     m_bIsActive = false;
    105 
    106     m_handle = 0;
    107     m_numStreams = 0;
    108     memset(mStreams, 0, sizeof(mStreams));
    109     mUserData = NULL;
    110 
    111     mStreamInfoBuf = NULL;
    112     mChannelCB = NULL;
    113     mPaddingInfo = NULL;
    114 }
    115 
    116 /*===========================================================================
    117  * FUNCTION   : ~QCamera3Channel
    118  *
    119  * DESCRIPTION: destructor of QCamera3Channel
    120  *
    121  * PARAMETERS : none
    122  *
    123  * RETURN     : none
    124  *==========================================================================*/
    125 QCamera3Channel::~QCamera3Channel()
    126 {
    127     if (m_bIsActive)
    128         stop();
    129 
    130     for (int i = 0; i < m_numStreams; i++) {
    131         if (mStreams[i] != NULL) {
    132             delete mStreams[i];
    133             mStreams[i] = 0;
    134         }
    135     }
    136     if (m_handle) {
    137         m_camOps->delete_channel(m_camHandle, m_handle);
    138         ALOGE("%s: deleting channel %d", __func__, m_handle);
    139         m_handle = 0;
    140     }
    141     m_numStreams = 0;
    142 }
    143 
    144 /*===========================================================================
    145  * FUNCTION   : init
    146  *
    147  * DESCRIPTION: initialization of channel
    148  *
    149  * PARAMETERS :
    150  *   @attr    : channel bundle attribute setting
    151  *   @dataCB  : data notify callback
    152  *   @userData: user data ptr
    153  *
    154  * RETURN     : int32_t type of status
    155  *              NO_ERROR  -- success
    156  *              none-zero failure code
    157  *==========================================================================*/
    158 int32_t QCamera3Channel::init(mm_camera_channel_attr_t *attr,
    159                              mm_camera_buf_notify_t dataCB)
    160 {
    161     m_handle = m_camOps->add_channel(m_camHandle,
    162                                       attr,
    163                                       dataCB,
    164                                       this);
    165     if (m_handle == 0) {
    166         ALOGE("%s: Add channel failed", __func__);
    167         return UNKNOWN_ERROR;
    168     }
    169     return NO_ERROR;
    170 }
    171 
    172 /*===========================================================================
    173  * FUNCTION   : addStream
    174  *
    175  * DESCRIPTION: add a stream into channel
    176  *
    177  * PARAMETERS :
    178  *   @allocator      : stream related buffer allocator
    179  *   @streamInfoBuf  : ptr to buf that constains stream info
    180  *   @minStreamBufNum: number of stream buffers needed
    181  *   @paddingInfo    : padding information
    182  *   @stream_cb      : stream data notify callback
    183  *   @userdata       : user data ptr
    184  *
    185  * RETURN     : int32_t type of status
    186  *              NO_ERROR  -- success
    187  *              none-zero failure code
    188  *==========================================================================*/
    189 int32_t QCamera3Channel::addStream(cam_stream_type_t streamType,
    190                                   cam_format_t streamFormat,
    191                                   cam_dimension_t streamDim,
    192                                   uint8_t minStreamBufNum)
    193 {
    194     int32_t rc = NO_ERROR;
    195 
    196     if (m_numStreams >= 1) {
    197         ALOGE("%s: Only one stream per channel supported in v3 Hal", __func__);
    198         return BAD_VALUE;
    199     }
    200 
    201     if (m_numStreams >= MAX_STREAM_NUM_IN_BUNDLE) {
    202         ALOGE("%s: stream number (%d) exceeds max limit (%d)",
    203               __func__, m_numStreams, MAX_STREAM_NUM_IN_BUNDLE);
    204         return BAD_VALUE;
    205     }
    206     QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
    207                                                m_handle,
    208                                                m_camOps,
    209                                                mPaddingInfo,
    210                                                this);
    211     if (pStream == NULL) {
    212         ALOGE("%s: No mem for Stream", __func__);
    213         return NO_MEMORY;
    214     }
    215 
    216     rc = pStream->init(streamType, streamFormat, streamDim, NULL, minStreamBufNum,
    217                                                     streamCbRoutine, this);
    218     if (rc == 0) {
    219         mStreams[m_numStreams] = pStream;
    220         m_numStreams++;
    221     } else {
    222         delete pStream;
    223     }
    224     return rc;
    225 }
    226 
    227 /*===========================================================================
    228  * FUNCTION   : start
    229  *
    230  * DESCRIPTION: start channel, which will start all streams belong to this channel
    231  *
    232  * PARAMETERS :
    233  *
    234  * RETURN     : int32_t type of status
    235  *              NO_ERROR  -- success
    236  *              none-zero failure code
    237  *==========================================================================*/
    238 int32_t QCamera3Channel::start()
    239 {
    240     int32_t rc = NO_ERROR;
    241 
    242     if (m_numStreams > 1) {
    243         ALOGE("%s: bundle not supported", __func__);
    244     }
    245 
    246     for (int i = 0; i < m_numStreams; i++) {
    247         if (mStreams[i] != NULL) {
    248             mStreams[i]->start();
    249         }
    250     }
    251     rc = m_camOps->start_channel(m_camHandle, m_handle);
    252 
    253     if (rc != NO_ERROR) {
    254         for (int i = 0; i < m_numStreams; i++) {
    255             if (mStreams[i] != NULL) {
    256                 mStreams[i]->stop();
    257             }
    258         }
    259     } else {
    260         m_bIsActive = true;
    261     }
    262 
    263     return rc;
    264 }
    265 
    266 /*===========================================================================
    267  * FUNCTION   : stop
    268  *
    269  * DESCRIPTION: stop a channel, which will stop all streams belong to this channel
    270  *
    271  * PARAMETERS : none
    272  *
    273  * RETURN     : int32_t type of status
    274  *              NO_ERROR  -- success
    275  *              none-zero failure code
    276  *==========================================================================*/
    277 int32_t QCamera3Channel::stop()
    278 {
    279     int32_t rc = NO_ERROR;
    280     if(!m_bIsActive) {
    281         ALOGE("%s: Attempt to stop inactive channel",__func__);
    282         return rc;
    283     }
    284 
    285     rc = m_camOps->stop_channel(m_camHandle, m_handle);
    286 
    287     for (int i = 0; i < m_numStreams; i++) {
    288         if (mStreams[i] != NULL) {
    289             mStreams[i]->stop();
    290         }
    291     }
    292 
    293     m_bIsActive = false;
    294     return rc;
    295 }
    296 
    297 /*===========================================================================
    298  * FUNCTION   : bufDone
    299  *
    300  * DESCRIPTION: return a stream buf back to kernel
    301  *
    302  * PARAMETERS :
    303  *   @recvd_frame  : stream buf frame to be returned
    304  *
    305  * RETURN     : int32_t type of status
    306  *              NO_ERROR  -- success
    307  *              none-zero failure code
    308  *==========================================================================*/
    309 int32_t QCamera3Channel::bufDone(mm_camera_super_buf_t *recvd_frame)
    310 {
    311     int32_t rc = NO_ERROR;
    312     for (int i = 0; i < recvd_frame->num_bufs; i++) {
    313          if (recvd_frame->bufs[i] != NULL) {
    314              for (int j = 0; j < m_numStreams; j++) {
    315                  if (mStreams[j] != NULL &&
    316                      mStreams[j]->getMyHandle() == recvd_frame->bufs[i]->stream_id) {
    317                      rc = mStreams[j]->bufDone(recvd_frame->bufs[i]->buf_idx);
    318                      break; // break loop j
    319                  }
    320              }
    321          }
    322     }
    323 
    324     return rc;
    325 }
    326 
    327 /*===========================================================================
    328  * FUNCTION   : getStreamTypeMask
    329  *
    330  * DESCRIPTION: Get bit mask of all stream types in this channel
    331  *
    332  * PARAMETERS : None
    333  *
    334  * RETURN     : Bit mask of all stream types in this channel
    335  *==========================================================================*/
    336 uint32_t QCamera3Channel::getStreamTypeMask()
    337 {
    338     uint32_t mask = 0;
    339     for (int i = 0; i < m_numStreams; i++) {
    340        mask |= (0x1 << mStreams[i]->getMyType());
    341     }
    342     return mask;
    343 }
    344 
    345 /*===========================================================================
    346  * FUNCTION   : getInternalFormatBuffer
    347  *
    348  * DESCRIPTION: return buffer in the internal format structure
    349  *
    350  * PARAMETERS :
    351  *   @streamHandle : buffer handle
    352  *
    353  * RETURN     : stream object. NULL if not found
    354  *==========================================================================*/
    355 mm_camera_buf_def_t* QCamera3RegularChannel::getInternalFormatBuffer(
    356                                             buffer_handle_t * buffer)
    357 {
    358     int32_t index;
    359     if(buffer == NULL)
    360         return NULL;
    361     index = mMemory->getMatchBufIndex((void*)buffer);
    362     if(index < 0) {
    363         ALOGE("%s: Could not find object among registered buffers",__func__);
    364         return NULL;
    365     }
    366     return mStreams[0]->getInternalFormatBuffer(index);
    367 }
    368 
    369 /*===========================================================================
    370  * FUNCTION   : getStreamByHandle
    371  *
    372  * DESCRIPTION: return stream object by stream handle
    373  *
    374  * PARAMETERS :
    375  *   @streamHandle : stream handle
    376  *
    377  * RETURN     : stream object. NULL if not found
    378  *==========================================================================*/
    379 QCamera3Stream *QCamera3Channel::getStreamByHandle(uint32_t streamHandle)
    380 {
    381     for (int i = 0; i < m_numStreams; i++) {
    382         if (mStreams[i] != NULL && mStreams[i]->getMyHandle() == streamHandle) {
    383             return mStreams[i];
    384         }
    385     }
    386     return NULL;
    387 }
    388 
    389 /*===========================================================================
    390  * FUNCTION   : getStreamByIndex
    391  *
    392  * DESCRIPTION: return stream object by index
    393  *
    394  * PARAMETERS :
    395  *   @streamHandle : stream handle
    396  *
    397  * RETURN     : stream object. NULL if not found
    398  *==========================================================================*/
    399 QCamera3Stream *QCamera3Channel::getStreamByIndex(uint8_t index)
    400 {
    401     if (index < m_numStreams) {
    402         return mStreams[index];
    403     }
    404     return NULL;
    405 }
    406 
    407 /*===========================================================================
    408  * FUNCTION   : streamCbRoutine
    409  *
    410  * DESCRIPTION: callback routine for stream
    411  *
    412  * PARAMETERS :
    413  *   @streamHandle : stream handle
    414  *
    415  * RETURN     : stream object. NULL if not found
    416  *==========================================================================*/
    417 void QCamera3Channel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
    418                 QCamera3Stream *stream, void *userdata)
    419 {
    420     QCamera3Channel *channel = (QCamera3Channel *)userdata;
    421     if (channel == NULL) {
    422         ALOGE("%s: invalid channel pointer", __func__);
    423         return;
    424     }
    425     channel->streamCbRoutine(super_frame, stream);
    426 }
    427 
    428 /*===========================================================================
    429  * FUNCTION   : QCamera3RegularChannel
    430  *
    431  * DESCRIPTION: constrcutor of QCamera3RegularChannel
    432  *
    433  * PARAMETERS :
    434  *   @cam_handle : camera handle
    435  *   @cam_ops    : ptr to camera ops table
    436  *   @cb_routine : callback routine to frame aggregator
    437  *   @stream     : camera3_stream_t structure
    438  *
    439  * RETURN     : none
    440  *==========================================================================*/
    441 QCamera3RegularChannel::QCamera3RegularChannel(uint32_t cam_handle,
    442                     mm_camera_ops_t *cam_ops,
    443                     channel_cb_routine cb_routine,
    444                     cam_padding_info_t *paddingInfo,
    445                     void *userData,
    446                     camera3_stream_t *stream) :
    447                         QCamera3Channel(cam_handle, cam_ops, cb_routine,
    448                                                 paddingInfo, userData),
    449                         mCamera3Stream(stream),
    450                         mNumBufs(0),
    451                         mCamera3Buffers(NULL),
    452                         mMemory(NULL),
    453                         mWidth(stream->width),
    454                         mHeight(stream->height)
    455 {
    456 }
    457 
    458 /*===========================================================================
    459  * FUNCTION   : QCamera3RegularChannel
    460  *
    461  * DESCRIPTION: constrcutor of QCamera3RegularChannel
    462  *
    463  * PARAMETERS :
    464  *   @cam_handle : camera handle
    465  *   @cam_ops    : ptr to camera ops table
    466  *   @cb_routine : callback routine to frame aggregator
    467  *   @stream     : camera3_stream_t structure
    468  *
    469  * RETURN     : none
    470  *==========================================================================*/
    471 QCamera3RegularChannel::QCamera3RegularChannel(uint32_t cam_handle,
    472                     mm_camera_ops_t *cam_ops,
    473                     channel_cb_routine cb_routine,
    474                     cam_padding_info_t *paddingInfo,
    475                     void *userData,
    476                     camera3_stream_t *stream,
    477                     uint32_t width, uint32_t height) :
    478                         QCamera3Channel(cam_handle, cam_ops, cb_routine,
    479                                                 paddingInfo, userData),
    480                         mCamera3Stream(stream),
    481                         mNumBufs(0),
    482                         mCamera3Buffers(NULL),
    483                         mMemory(NULL),
    484                         mWidth(width),
    485                         mHeight(height)
    486 {
    487 }
    488 
    489 /*===========================================================================
    490  * FUNCTION   : ~QCamera3RegularChannel
    491  *
    492  * DESCRIPTION: destructor of QCamera3RegularChannel
    493  *
    494  * PARAMETERS : none
    495  *
    496  * RETURN     : none
    497  *==========================================================================*/
    498 QCamera3RegularChannel::~QCamera3RegularChannel()
    499 {
    500     if (mCamera3Buffers) {
    501         delete[] mCamera3Buffers;
    502     }
    503 }
    504 
    505 int32_t QCamera3RegularChannel::initialize()
    506 {
    507   //TO DO
    508   return 0;
    509 }
    510 
    511 /*===========================================================================
    512  * FUNCTION   : request
    513  *
    514  * DESCRIPTION: process a request from camera service. Stream on if ncessary.
    515  *
    516  * PARAMETERS :
    517  *   @buffer  : buffer to be filled for this request
    518  *
    519  * RETURN     : 0 on a success start of capture
    520  *              -EINVAL on invalid input
    521  *              -ENODEV on serious error
    522  *==========================================================================*/
    523 int32_t QCamera3RegularChannel::request(buffer_handle_t *buffer, uint32_t frameNumber)
    524 {
    525     //FIX ME: Return buffer back in case of failures below.
    526 
    527     int32_t rc = NO_ERROR;
    528     int index;
    529     if(!m_bIsActive) {
    530         ALOGD("%s: First request on this channel starting stream",__func__);
    531         start();
    532         if(rc != NO_ERROR) {
    533             ALOGE("%s: Failed to start the stream on the request",__func__);
    534             return rc;
    535         }
    536     } else {
    537         ALOGV("%s: Request on an existing stream",__func__);
    538     }
    539 
    540     if(!mMemory) {
    541         ALOGE("%s: error, Gralloc Memory object not yet created for this stream",__func__);
    542         return NO_MEMORY;
    543     }
    544 
    545     index = mMemory->getMatchBufIndex((void*)buffer);
    546     if(index < 0) {
    547         ALOGE("%s: Could not find object among registered buffers",__func__);
    548         return DEAD_OBJECT;
    549     }
    550 
    551     rc = mStreams[0]->bufDone(index);
    552     if(rc != NO_ERROR) {
    553         ALOGE("%s: Failed to Q new buffer to stream",__func__);
    554         return rc;
    555     }
    556 
    557     rc = mMemory->markFrameNumber(index, frameNumber);
    558     return rc;
    559 }
    560 
    561 /*===========================================================================
    562  * FUNCTION   : registerBuffers
    563  *
    564  * DESCRIPTION: register streaming buffers to the channel object
    565  *
    566  * PARAMETERS :
    567  *   @num_buffers : number of buffers to be registered
    568  *   @buffers     : buffer to be registered
    569  *
    570  * RETURN     : 0 on a success start of capture
    571  *              -EINVAL on invalid input
    572  *              -ENOMEM on failure to register the buffer
    573  *              -ENODEV on serious error
    574  *==========================================================================*/
    575 int32_t QCamera3RegularChannel::registerBuffers(uint32_t num_buffers, buffer_handle_t **buffers)
    576 {
    577     int rc = 0;
    578     struct private_handle_t *priv_handle = (struct private_handle_t *)(*buffers[0]);
    579     cam_stream_type_t streamType;
    580     cam_format_t streamFormat;
    581     cam_dimension_t streamDim;
    582 
    583     rc = init(NULL, NULL);
    584     if (rc < 0) {
    585         ALOGE("%s: init failed", __func__);
    586         return rc;
    587     }
    588 
    589     if (mCamera3Stream->format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
    590         if (priv_handle->flags & private_handle_t::PRIV_FLAGS_VIDEO_ENCODER) {
    591             streamType = CAM_STREAM_TYPE_VIDEO;
    592             streamFormat = CAM_FORMAT_YUV_420_NV12;
    593         } else if (priv_handle->flags & private_handle_t::PRIV_FLAGS_HW_TEXTURE) {
    594             streamType = CAM_STREAM_TYPE_PREVIEW;
    595             streamFormat = CAM_FORMAT_YUV_420_NV21;
    596         } else {
    597             //TODO: Add a new flag in libgralloc for ZSL buffers, and its size needs
    598             // to be properly aligned and padded.
    599             ALOGE("%s: priv_handle->flags 0x%x not supported",
    600                     __func__, priv_handle->flags);
    601             streamType = CAM_STREAM_TYPE_SNAPSHOT;
    602             streamFormat = CAM_FORMAT_YUV_420_NV21;
    603         }
    604     } else if(mCamera3Stream->format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
    605          streamType = CAM_STREAM_TYPE_CALLBACK;
    606          streamFormat = CAM_FORMAT_YUV_420_NV21;
    607     } else {
    608         //TODO: Fail for other types of streams for now
    609         ALOGE("%s: format is not IMPLEMENTATION_DEFINED or flexible", __func__);
    610         return -EINVAL;
    611     }
    612 
    613     /* Bookkeep buffer set because they go out of scope after register call */
    614     mNumBufs = num_buffers;
    615     mCamera3Buffers = new buffer_handle_t*[num_buffers];
    616     if (mCamera3Buffers == NULL) {
    617         ALOGE("%s: Failed to allocate buffer_handle_t*", __func__);
    618         return -ENOMEM;
    619     }
    620     for (size_t i = 0; i < num_buffers; i++)
    621         mCamera3Buffers[i] = buffers[i];
    622 
    623     streamDim.width = mWidth;
    624     streamDim.height = mHeight;
    625 
    626     rc = QCamera3Channel::addStream(streamType, streamFormat, streamDim,
    627         num_buffers);
    628     return rc;
    629 }
    630 
    631 void QCamera3RegularChannel::streamCbRoutine(
    632                             mm_camera_super_buf_t *super_frame,
    633                             QCamera3Stream *stream)
    634 {
    635     //FIXME Q Buf back in case of error?
    636     uint8_t frameIndex;
    637     buffer_handle_t *resultBuffer;
    638     int32_t resultFrameNumber;
    639     camera3_stream_buffer_t result;
    640 
    641     if(!super_frame) {
    642          ALOGE("%s: Invalid Super buffer",__func__);
    643          return;
    644     }
    645 
    646     if(super_frame->num_bufs != 1) {
    647          ALOGE("%s: Multiple streams are not supported",__func__);
    648          return;
    649     }
    650     if(super_frame->bufs[0] == NULL ) {
    651          ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
    652                   __func__);
    653          return;
    654     }
    655 
    656     frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
    657     if(frameIndex >= mNumBufs) {
    658          ALOGE("%s: Error, Invalid index for buffer",__func__);
    659          if(stream) {
    660              stream->bufDone(frameIndex);
    661          }
    662          return;
    663     }
    664 
    665     ////Use below data to issue framework callback
    666     resultBuffer = mCamera3Buffers[frameIndex];
    667     resultFrameNumber = mMemory->getFrameNumber(frameIndex);
    668 
    669     result.stream = mCamera3Stream;
    670     result.buffer = resultBuffer;
    671     result.status = CAMERA3_BUFFER_STATUS_OK;
    672     result.acquire_fence = -1;
    673     result.release_fence = -1;
    674 
    675     mChannelCB(NULL, &result, resultFrameNumber, mUserData);
    676     free(super_frame);
    677     return;
    678 }
    679 
    680 QCamera3Memory* QCamera3RegularChannel::getStreamBufs(uint32_t /*len*/)
    681 {
    682     if (mNumBufs == 0 || mCamera3Buffers == NULL) {
    683         ALOGE("%s: buffers not registered yet", __func__);
    684         return NULL;
    685     }
    686 
    687     mMemory = new QCamera3GrallocMemory();
    688     if (mMemory == NULL) {
    689         return NULL;
    690     }
    691 
    692     if (mMemory->registerBuffers(mNumBufs, mCamera3Buffers) < 0) {
    693         delete mMemory;
    694         mMemory = NULL;
    695         return NULL;
    696     }
    697     return mMemory;
    698 }
    699 
    700 void QCamera3RegularChannel::putStreamBufs()
    701 {
    702     mMemory->unregisterBuffers();
    703     delete mMemory;
    704     mMemory = NULL;
    705 }
    706 
    707 int QCamera3RegularChannel::kMaxBuffers = 7;
    708 
    709 QCamera3MetadataChannel::QCamera3MetadataChannel(uint32_t cam_handle,
    710                     mm_camera_ops_t *cam_ops,
    711                     channel_cb_routine cb_routine,
    712                     cam_padding_info_t *paddingInfo,
    713                     void *userData) :
    714                         QCamera3Channel(cam_handle, cam_ops,
    715                                 cb_routine, paddingInfo, userData),
    716                         mMemory(NULL)
    717 {
    718 }
    719 
    720 QCamera3MetadataChannel::~QCamera3MetadataChannel()
    721 {
    722     if (m_bIsActive)
    723         stop();
    724 
    725     if (mMemory) {
    726         mMemory->deallocate();
    727         delete mMemory;
    728         mMemory = NULL;
    729     }
    730 }
    731 
    732 int32_t QCamera3MetadataChannel::initialize()
    733 {
    734     int32_t rc;
    735     cam_dimension_t streamDim;
    736 
    737     if (mMemory || m_numStreams > 0) {
    738         ALOGE("%s: metadata channel already initialized", __func__);
    739         return -EINVAL;
    740     }
    741 
    742     rc = init(NULL, NULL);
    743     if (rc < 0) {
    744         ALOGE("%s: init failed", __func__);
    745         return rc;
    746     }
    747 
    748     streamDim.width = sizeof(metadata_buffer_t),
    749     streamDim.height = 1;
    750     rc = QCamera3Channel::addStream(CAM_STREAM_TYPE_METADATA, CAM_FORMAT_MAX,
    751         streamDim, MIN_STREAMING_BUFFER_NUM);
    752     if (rc < 0) {
    753         ALOGE("%s: addStream failed", __func__);
    754     }
    755     return rc;
    756 }
    757 
    758 int32_t QCamera3MetadataChannel::request(buffer_handle_t * /*buffer*/,
    759                                                 uint32_t /*frameNumber*/)
    760 {
    761     if (!m_bIsActive) {
    762         return start();
    763     }
    764     else
    765         return 0;
    766 }
    767 
    768 int32_t QCamera3MetadataChannel::registerBuffers(uint32_t /*num_buffers*/,
    769                                         buffer_handle_t ** /*buffers*/)
    770 {
    771     // no registerBuffers are supported for metadata channel
    772     return -EINVAL;
    773 }
    774 
    775 void QCamera3MetadataChannel::streamCbRoutine(
    776                         mm_camera_super_buf_t *super_frame,
    777                         QCamera3Stream *stream)
    778 {
    779     uint32_t requestNumber = 0;
    780     if (super_frame == NULL || super_frame->num_bufs != 1) {
    781         ALOGE("%s: super_frame is not valid", __func__);
    782         return;
    783     }
    784     mChannelCB(super_frame, NULL, requestNumber, mUserData);
    785 }
    786 
    787 QCamera3Memory* QCamera3MetadataChannel::getStreamBufs(uint32_t len)
    788 {
    789     int rc;
    790     if (len < sizeof(metadata_buffer_t)) {
    791         ALOGE("%s: size doesn't match %d vs %d", __func__,
    792                 len, sizeof(metadata_buffer_t));
    793         return NULL;
    794     }
    795     mMemory = new QCamera3HeapMemory();
    796     if (!mMemory) {
    797         ALOGE("%s: unable to create metadata memory", __func__);
    798         return NULL;
    799     }
    800     rc = mMemory->allocate(MIN_STREAMING_BUFFER_NUM, len, true);
    801     if (rc < 0) {
    802         ALOGE("%s: unable to allocate metadata memory", __func__);
    803         delete mMemory;
    804         mMemory = NULL;
    805         return NULL;
    806     }
    807     memset(mMemory->getPtr(0), 0, sizeof(metadata_buffer_t));
    808     return mMemory;
    809 }
    810 
    811 void QCamera3MetadataChannel::putStreamBufs()
    812 {
    813     mMemory->deallocate();
    814     delete mMemory;
    815     mMemory = NULL;
    816 }
    817 
    818 /*===========================================================================
    819  * FUNCTION   : jpegEvtHandle
    820  *
    821  * DESCRIPTION: Function registerd to mm-jpeg-interface to handle jpeg events.
    822                 Construct result payload and call mChannelCb to deliver buffer
    823                 to framework.
    824  *
    825  * PARAMETERS :
    826  *   @status    : status of jpeg job
    827  *   @client_hdl: jpeg client handle
    828  *   @jobId     : jpeg job Id
    829  *   @p_ouput   : ptr to jpeg output result struct
    830  *   @userdata  : user data ptr
    831  *
    832  * RETURN     : none
    833  *==========================================================================*/
    834 void QCamera3PicChannel::jpegEvtHandle(jpeg_job_status_t status,
    835                                               uint32_t /*client_hdl*/,
    836                                               uint32_t jobId,
    837                                               mm_jpeg_output_t *p_output,
    838                                               void *userdata)
    839 {
    840     buffer_handle_t *resultBuffer;
    841     int32_t resultFrameNumber;
    842     int resultStatus = CAMERA3_BUFFER_STATUS_OK;
    843     camera3_stream_buffer_t result;
    844     camera3_jpeg_blob_t jpegHeader;
    845     char* jpeg_eof = 0;
    846     int maxJpegSize;
    847     QCamera3PicChannel *obj = (QCamera3PicChannel *)userdata;
    848     if (obj) {
    849         //Construct payload for process_capture_result. Call mChannelCb
    850 
    851         qcamera_jpeg_data_t *job = obj->m_postprocessor.findJpegJobByJobId(jobId);
    852 
    853         if ((job == NULL) || (status == JPEG_JOB_STATUS_ERROR)) {
    854             ALOGE("%s: Error in jobId: (%d) with status: %d", __func__, jobId, status);
    855             resultStatus = CAMERA3_BUFFER_STATUS_ERROR;
    856         }
    857 
    858         //Construct jpeg transient header of type camera3_jpeg_blob_t
    859         //Append at the end of jpeg image of buf_filled_len size
    860 
    861         jpegHeader.jpeg_blob_id = CAMERA3_JPEG_BLOB_ID;
    862         jpegHeader.jpeg_size = p_output->buf_filled_len;
    863 
    864 
    865         char* jpeg_buf = (char *)p_output->buf_vaddr;
    866 
    867         if(obj->mJpegSettings->max_jpeg_size <= 0 ||
    868                 obj->mJpegSettings->max_jpeg_size > obj->mMemory->getSize(obj->mCurrentBufIndex)){
    869             ALOGE("%s:Max Jpeg size :%d is out of valid range setting to size of buffer",
    870                     __func__, obj->mJpegSettings->max_jpeg_size);
    871             maxJpegSize =  obj->mMemory->getSize(obj->mCurrentBufIndex);
    872         } else {
    873             maxJpegSize = obj->mJpegSettings->max_jpeg_size;
    874             ALOGE("%s: Setting max jpeg size to %d",__func__, maxJpegSize);
    875         }
    876         jpeg_eof = &jpeg_buf[maxJpegSize-sizeof(jpegHeader)];
    877         memcpy(jpeg_eof, &jpegHeader, sizeof(jpegHeader));
    878         obj->mMemory->cleanInvalidateCache(obj->mCurrentBufIndex);
    879 
    880         ////Use below data to issue framework callback
    881         resultBuffer = obj->mCamera3Buffers[obj->mCurrentBufIndex];
    882         resultFrameNumber = obj->mMemory->getFrameNumber(obj->mCurrentBufIndex);
    883 
    884         result.stream = obj->mCamera3Stream;
    885         result.buffer = resultBuffer;
    886         result.status = resultStatus;
    887         result.acquire_fence = -1;
    888         result.release_fence = -1;
    889 
    890         ALOGV("%s: Issue Callback", __func__);
    891         obj->mChannelCB(NULL, &result, resultFrameNumber, obj->mUserData);
    892 
    893         // release internal data for jpeg job
    894         if (job != NULL) {
    895             obj->m_postprocessor.releaseJpegJobData(job);
    896             free(job);
    897         }
    898         return;
    899         // }
    900     } else {
    901         ALOGE("%s: Null userdata in jpeg callback", __func__);
    902     }
    903 }
    904 
    905 QCamera3PicChannel::QCamera3PicChannel(uint32_t cam_handle,
    906                     mm_camera_ops_t *cam_ops,
    907                     channel_cb_routine cb_routine,
    908                     cam_padding_info_t *paddingInfo,
    909                     void *userData,
    910                     camera3_stream_t *stream) :
    911                         QCamera3Channel(cam_handle, cam_ops, cb_routine,
    912                         paddingInfo, userData),
    913                         m_postprocessor(this),
    914                         mCamera3Stream(stream),
    915                         mNumBufs(0),
    916                         mCamera3Buffers(NULL),
    917                         mJpegSettings(NULL),
    918                         mCurrentBufIndex(-1),
    919                         mMemory(NULL),
    920                         mYuvMemory(NULL)
    921 {
    922     int32_t rc = m_postprocessor.init(jpegEvtHandle, this);
    923     if (rc != 0) {
    924         ALOGE("Init Postprocessor failed");
    925     }
    926 }
    927 
    928 QCamera3PicChannel::~QCamera3PicChannel()
    929 {
    930     int32_t rc = m_postprocessor.stop();
    931     if (rc != NO_ERROR) {
    932         ALOGE("%s: Postprocessor stop failed", __func__);
    933     }
    934     rc = m_postprocessor.deinit();
    935     if (rc != 0) {
    936         ALOGE("De-init Postprocessor failed");
    937     }
    938     if (mCamera3Buffers) {
    939         delete[] mCamera3Buffers;
    940     }
    941 }
    942 
    943 int32_t QCamera3PicChannel::initialize()
    944 {
    945     int32_t rc = NO_ERROR;
    946     cam_dimension_t streamDim;
    947     cam_stream_type_t streamType;
    948     cam_format_t streamFormat;
    949     mm_camera_channel_attr_t attr;
    950 
    951     memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
    952     attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_BURST;
    953     attr.look_back = 1;
    954     attr.post_frame_skip = 1;
    955     attr.water_mark = 1;
    956     attr.max_unmatched_frames = 1;
    957 
    958     rc = init(&attr, NULL);
    959     if (rc < 0) {
    960         ALOGE("%s: init failed", __func__);
    961         return rc;
    962     }
    963 
    964     streamType = CAM_STREAM_TYPE_NON_ZSL_SNAPSHOT;
    965     streamFormat = CAM_FORMAT_YUV_420_NV21;
    966     streamDim.width = mCamera3Stream->width;
    967     streamDim.height = mCamera3Stream->height;
    968 
    969     int num_buffers = 1;
    970 
    971     rc = QCamera3Channel::addStream(streamType, streamFormat, streamDim,
    972             num_buffers);
    973 
    974     return rc;
    975 }
    976 
    977 int32_t QCamera3PicChannel::request(buffer_handle_t *buffer,
    978         uint32_t frameNumber, jpeg_settings_t* jpegSettings,
    979         mm_camera_buf_def_t *pInputBuffer,QCamera3Channel* pInputChannel)
    980 {
    981     //FIX ME: Return buffer back in case of failures below.
    982 
    983     int32_t rc = NO_ERROR;
    984     int index;
    985     mJpegSettings = jpegSettings;
    986     if(!m_bIsActive) {
    987         ALOGD("%s: First request on this channel starting stream",__func__);
    988         //Stream on for main image. YUV buffer is queued to the kernel at the end of this call.
    989         if(!pInputBuffer)
    990             rc = start();
    991         else
    992             ALOGD("%s: Current request has input buffer no need to start h/w stream", __func__);
    993     } else {
    994         mStreams[0]->bufDone(0);
    995         ALOGD("%s: Request on an existing stream",__func__);
    996     }
    997 
    998     if(rc != NO_ERROR) {
    999         ALOGE("%s: Failed to start the stream on the request",__func__);
   1000         return rc;
   1001     }
   1002 
   1003 
   1004     if(!mMemory) {
   1005         if(pInputBuffer) {
   1006             mMemory = new QCamera3GrallocMemory();
   1007             if (mMemory == NULL) {
   1008                 return NO_MEMORY;
   1009             }
   1010 
   1011             //Registering Jpeg output buffer
   1012             if (mMemory->registerBuffers(mNumBufs, mCamera3Buffers) < 0) {
   1013                 delete mMemory;
   1014                 mMemory = NULL;
   1015                 return NO_MEMORY;
   1016             }
   1017         } else {
   1018             ALOGE("%s: error, Gralloc Memory object not yet created for this stream",__func__);
   1019             return NO_MEMORY;
   1020         }
   1021     }
   1022 
   1023     index = mMemory->getMatchBufIndex((void*)buffer);
   1024     if(index < 0) {
   1025         ALOGE("%s: Could not find object among registered buffers",__func__);
   1026         return DEAD_OBJECT;
   1027     }
   1028     rc = mMemory->markFrameNumber(index, frameNumber);
   1029 
   1030     //Start the postprocessor for jpeg encoding. Pass mMemory as destination buffer
   1031     mCurrentBufIndex = index;
   1032 
   1033     m_postprocessor.start(mMemory, index, this);
   1034 
   1035     ALOGD("%s: Post-process started", __func__);
   1036     if(pInputBuffer) {
   1037         ALOGD("%s: Issue call to reprocess", __func__);
   1038         m_postprocessor.processAuxiliaryData(pInputBuffer,pInputChannel);
   1039     }
   1040     return rc;
   1041 }
   1042 
   1043 /*===========================================================================
   1044  * FUNCTION   : dataNotifyCB
   1045  *
   1046  * DESCRIPTION: Channel Level callback used for super buffer data notify.
   1047  *              This function is registered with mm-camera-interface to handle
   1048  *              data notify
   1049  *
   1050  * PARAMETERS :
   1051  *   @recvd_frame   : stream frame received
   1052  *   userdata       : user data ptr
   1053  *
   1054  * RETURN     : none
   1055  *==========================================================================*/
   1056 void QCamera3PicChannel::dataNotifyCB(mm_camera_super_buf_t *recvd_frame,
   1057                                  void *userdata)
   1058 {
   1059     ALOGV("%s: E\n", __func__);
   1060     QCamera3PicChannel *channel = (QCamera3PicChannel *)userdata;
   1061 
   1062     if (channel == NULL) {
   1063         ALOGE("%s: invalid channel pointer", __func__);
   1064         return;
   1065     }
   1066 
   1067     if(channel->m_numStreams != 1) {
   1068         ALOGE("%s: Error: Bug: This callback assumes one stream per channel",__func__);
   1069         return;
   1070     }
   1071 
   1072 
   1073     if(channel->mStreams[0] == NULL) {
   1074         ALOGE("%s: Error: Invalid Stream object",__func__);
   1075         return;
   1076     }
   1077 
   1078     channel->QCamera3PicChannel::streamCbRoutine(recvd_frame, channel->mStreams[0]);
   1079 
   1080     ALOGV("%s: X\n", __func__);
   1081     return;
   1082 }
   1083 
   1084 
   1085 int32_t QCamera3PicChannel::registerBuffers(uint32_t num_buffers,
   1086                         buffer_handle_t **buffers)
   1087 {
   1088     int rc = 0;
   1089     cam_stream_type_t streamType;
   1090     cam_format_t streamFormat;
   1091 
   1092     ALOGV("%s: E",__func__);
   1093     rc = QCamera3PicChannel::initialize();
   1094     if (rc < 0) {
   1095         ALOGE("%s: init failed", __func__);
   1096         return rc;
   1097     }
   1098 
   1099     if (mCamera3Stream->format == HAL_PIXEL_FORMAT_BLOB) {
   1100         streamType = CAM_STREAM_TYPE_NON_ZSL_SNAPSHOT;
   1101         streamFormat = CAM_FORMAT_YUV_420_NV21;
   1102     } else {
   1103         //TODO: Fail for other types of streams for now
   1104         ALOGE("%s: format is not BLOB", __func__);
   1105         return -EINVAL;
   1106     }
   1107     /* Bookkeep buffer set because they go out of scope after register call */
   1108     mNumBufs = num_buffers;
   1109     mCamera3Buffers = new buffer_handle_t*[num_buffers];
   1110     if (mCamera3Buffers == NULL) {
   1111         ALOGE("%s: Failed to allocate buffer_handle_t*", __func__);
   1112         return -ENOMEM;
   1113     }
   1114     for (size_t i = 0; i < num_buffers; i++)
   1115         mCamera3Buffers[i] = buffers[i];
   1116 
   1117     ALOGV("%s: X",__func__);
   1118     return rc;
   1119 }
   1120 
   1121 void QCamera3PicChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
   1122                             QCamera3Stream *stream)
   1123 {
   1124     //TODO
   1125     //Used only for getting YUV. Jpeg callback will be sent back from channel
   1126     //directly to HWI. Refer to func jpegEvtHandle
   1127 
   1128     //Got the yuv callback. Calling yuv callback handler in PostProc
   1129     uint8_t frameIndex;
   1130     mm_camera_super_buf_t* frame = NULL;
   1131     if(!super_frame) {
   1132          ALOGE("%s: Invalid Super buffer",__func__);
   1133          return;
   1134     }
   1135 
   1136     if(super_frame->num_bufs != 1) {
   1137          ALOGE("%s: Multiple streams are not supported",__func__);
   1138          return;
   1139     }
   1140     if(super_frame->bufs[0] == NULL ) {
   1141          ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
   1142                   __func__);
   1143          return;
   1144     }
   1145 
   1146     frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
   1147     if(frameIndex >= mNumBufs) {
   1148          ALOGE("%s: Error, Invalid index for buffer",__func__);
   1149          if(stream) {
   1150              stream->bufDone(frameIndex);
   1151          }
   1152          return;
   1153     }
   1154 
   1155     frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
   1156     if (frame == NULL) {
   1157        ALOGE("%s: Error allocating memory to save received_frame structure.",
   1158                                                                     __func__);
   1159        if(stream) {
   1160            stream->bufDone(frameIndex);
   1161        }
   1162        return;
   1163     }
   1164     *frame = *super_frame;
   1165 
   1166     m_postprocessor.processData(frame);
   1167     free(super_frame);
   1168     return;
   1169 }
   1170 
   1171 QCamera3Memory* QCamera3PicChannel::getStreamBufs(uint32_t len)
   1172 {
   1173     int rc = 0;
   1174 
   1175     if (mNumBufs == 0 || mCamera3Buffers == NULL) {
   1176         ALOGE("%s: buffers not registered yet", __func__);
   1177         return NULL;
   1178     }
   1179 
   1180     if(mMemory) {
   1181         delete mMemory;
   1182         mMemory = NULL;
   1183     }
   1184     mMemory = new QCamera3GrallocMemory();
   1185     if (mMemory == NULL) {
   1186         return NULL;
   1187     }
   1188 
   1189     //Registering Jpeg output buffer
   1190     if (mMemory->registerBuffers(mNumBufs, mCamera3Buffers) < 0) {
   1191         delete mMemory;
   1192         mMemory = NULL;
   1193         return NULL;
   1194     }
   1195 
   1196     mYuvMemory = new QCamera3HeapMemory();
   1197     if (!mYuvMemory) {
   1198         ALOGE("%s: unable to create metadata memory", __func__);
   1199         return NULL;
   1200     }
   1201 
   1202     //Queue YUV buffers in the beginning mQueueAll = true
   1203     rc = mYuvMemory->allocate(1, len, true);
   1204     if (rc < 0) {
   1205         ALOGE("%s: unable to allocate metadata memory", __func__);
   1206         delete mYuvMemory;
   1207         mYuvMemory = NULL;
   1208         return NULL;
   1209     }
   1210     return mYuvMemory;
   1211 }
   1212 
   1213 void QCamera3PicChannel::putStreamBufs()
   1214 {
   1215     mMemory->unregisterBuffers();
   1216     delete mMemory;
   1217     mMemory = NULL;
   1218 
   1219     mYuvMemory->deallocate();
   1220     delete mYuvMemory;
   1221     mYuvMemory = NULL;
   1222 }
   1223 
   1224 bool QCamera3PicChannel::isRawSnapshot()
   1225 {
   1226    return !(mJpegSettings->is_jpeg_format);
   1227 }
   1228 /*===========================================================================
   1229  * FUNCTION   : getThumbnailSize
   1230  *
   1231  * DESCRIPTION: get user set thumbnail size
   1232  *
   1233  * PARAMETERS :
   1234  *   @dim     : output of thumbnail dimension
   1235  *
   1236  * RETURN     : none
   1237  *==========================================================================*/
   1238 void QCamera3PicChannel::getThumbnailSize(cam_dimension_t &dim)
   1239 {
   1240     dim = mJpegSettings->thumbnail_size;
   1241 }
   1242 
   1243 /*===========================================================================
   1244  * FUNCTION   : getJpegQuality
   1245  *
   1246  * DESCRIPTION: get user set jpeg quality
   1247  *
   1248  * PARAMETERS : none
   1249  *
   1250  * RETURN     : jpeg quality setting
   1251  *==========================================================================*/
   1252 int QCamera3PicChannel::getJpegQuality()
   1253 {
   1254     int quality = mJpegSettings->jpeg_quality;
   1255     if (quality < 0) {
   1256         quality = 85;  //set to default quality value
   1257     }
   1258     return quality;
   1259 }
   1260 
   1261 /*===========================================================================
   1262  * FUNCTION   : getJpegRotation
   1263  *
   1264  * DESCRIPTION: get rotation information to be passed into jpeg encoding
   1265  *
   1266  * PARAMETERS : none
   1267  *
   1268  * RETURN     : rotation information
   1269  *==========================================================================*/
   1270 int QCamera3PicChannel::getJpegRotation() {
   1271     int rotation = mJpegSettings->jpeg_orientation;
   1272     if (rotation < 0) {
   1273         rotation = 0;
   1274     }
   1275     return rotation;
   1276 }
   1277 
   1278 void QCamera3PicChannel::queueMetadata(mm_camera_super_buf_t *metadata_buf)
   1279 {
   1280     m_postprocessor.processPPMetadata(metadata_buf);
   1281 }
   1282 /*===========================================================================
   1283  * FUNCTION   : getRational
   1284  *
   1285  * DESCRIPTION: compose rational struct
   1286  *
   1287  * PARAMETERS :
   1288  *   @rat     : ptr to struct to store rational info
   1289  *   @num     :num of the rational
   1290  *   @denom   : denom of the rational
   1291  *
   1292  * RETURN     : int32_t type of status
   1293  *              NO_ERROR  -- success
   1294  *              none-zero failure code
   1295  *==========================================================================*/
   1296 int32_t getRational(rat_t *rat, int num, int denom)
   1297 {
   1298     if (NULL == rat) {
   1299         ALOGE("%s: NULL rat input", __func__);
   1300         return BAD_VALUE;
   1301     }
   1302     rat->num = num;
   1303     rat->denom = denom;
   1304     return NO_ERROR;
   1305 }
   1306 
   1307 /*===========================================================================
   1308  * FUNCTION   : getRational
   1309  *
   1310  * DESCRIPTION: compose rational struct
   1311  *
   1312  * PARAMETERS :
   1313  *   @rat     : ptr to struct to store rational info
   1314  *   @num     :num of the rational
   1315  *   @denom   : denom of the rational
   1316  *
   1317  * RETURN     : int32_t type of status
   1318  *              NO_ERROR  -- success
   1319  *              none-zero failure code
   1320  *==========================================================================*/
   1321 int32_t getRationalExposureTime(rat_t *rat, double num, double denom)
   1322 {
   1323     if (NULL == rat) {
   1324         ALOGE("%s: NULL rat input", __func__);
   1325         return BAD_VALUE;
   1326     }
   1327     rat->num = num;
   1328     rat->denom = round(1.0 / denom);
   1329     return NO_ERROR;
   1330 }
   1331 
   1332 /*===========================================================================
   1333  * FUNCTION   : parseGPSCoordinate
   1334  *
   1335  * DESCRIPTION: parse GPS coordinate string
   1336  *
   1337  * PARAMETERS :
   1338  *   @coord_str : [input] coordinate string
   1339  *   @coord     : [output]  ptr to struct to store coordinate
   1340  *
   1341  * RETURN     : int32_t type of status
   1342  *              NO_ERROR  -- success
   1343  *              none-zero failure code
   1344  *==========================================================================*/
   1345 int parseGPSCoordinate(const char *coord_str, rat_t* coord)
   1346 {
   1347     if(coord == NULL) {
   1348         ALOGE("%s: error, invalid argument coord == NULL", __func__);
   1349         return BAD_VALUE;
   1350     }
   1351     float degF = atof(coord_str);
   1352     if (degF < 0) {
   1353         degF = -degF;
   1354     }
   1355     float minF = (degF - (int) degF) * 60;
   1356     float secF = (minF - (int) minF) * 60;
   1357 
   1358     getRational(&coord[0], (int)degF, 1);
   1359     getRational(&coord[1], (int)minF, 1);
   1360     getRational(&coord[2], (int)(secF * 10000), 10000);
   1361     return NO_ERROR;
   1362 }
   1363 
   1364 /*===========================================================================
   1365  * FUNCTION   : getExifDateTime
   1366  *
   1367  * DESCRIPTION: query exif date time
   1368  *
   1369  * PARAMETERS :
   1370  *   @dateTime : string to store exif date time
   1371  *   @count    : lenght of the dateTime string
   1372  *
   1373  * RETURN     : int32_t type of status
   1374  *              NO_ERROR  -- success
   1375  *              none-zero failure code
   1376  *==========================================================================*/
   1377 int32_t getExifDateTime(char *dateTime, uint32_t &count)
   1378 {
   1379     //get time and date from system
   1380     time_t rawtime;
   1381     struct tm * timeinfo;
   1382     time(&rawtime);
   1383     timeinfo = localtime (&rawtime);
   1384     //Write datetime according to EXIF Spec
   1385     //"YYYY:MM:DD HH:MM:SS" (20 chars including \0)
   1386     snprintf(dateTime, 20, "%04d:%02d:%02d %02d:%02d:%02d",
   1387              timeinfo->tm_year + 1900, timeinfo->tm_mon + 1,
   1388              timeinfo->tm_mday, timeinfo->tm_hour,
   1389              timeinfo->tm_min, timeinfo->tm_sec);
   1390     count = 20;
   1391 
   1392     return NO_ERROR;
   1393 }
   1394 
   1395 /*===========================================================================
   1396  * FUNCTION   : getExifFocalLength
   1397  *
   1398  * DESCRIPTION: get exif focal lenght
   1399  *
   1400  * PARAMETERS :
   1401  *   @focalLength : ptr to rational strcut to store focal lenght
   1402  *
   1403  * RETURN     : int32_t type of status
   1404  *              NO_ERROR  -- success
   1405  *              none-zero failure code
   1406  *==========================================================================*/
   1407 int32_t getExifFocalLength(rat_t *focalLength, float value)
   1408 {
   1409     int focalLengthValue =
   1410         (int)(value * FOCAL_LENGTH_DECIMAL_PRECISION);
   1411     return getRational(focalLength, focalLengthValue, FOCAL_LENGTH_DECIMAL_PRECISION);
   1412 }
   1413 
   1414 /*===========================================================================
   1415   * FUNCTION   : getExifExpTimeInfo
   1416   *
   1417   * DESCRIPTION: get exif exposure time information
   1418   *
   1419   * PARAMETERS :
   1420   *   @expoTimeInfo     : expousure time value
   1421   * RETURN     : nt32_t type of status
   1422   *              NO_ERROR  -- success
   1423   *              none-zero failure code
   1424   *==========================================================================*/
   1425 int32_t getExifExpTimeInfo(rat_t *expoTimeInfo, int64_t value)
   1426 {
   1427 
   1428     float cal_exposureTime;
   1429     if (value != 0)
   1430         cal_exposureTime = (double)(value / 1000000000.0);
   1431     else
   1432         cal_exposureTime = 60.00;
   1433     return getRationalExposureTime(expoTimeInfo, 1, cal_exposureTime);
   1434 }
   1435 
   1436 /*===========================================================================
   1437  * FUNCTION   : getExifGpsProcessingMethod
   1438  *
   1439  * DESCRIPTION: get GPS processing method
   1440  *
   1441  * PARAMETERS :
   1442  *   @gpsProcessingMethod : string to store GPS process method
   1443  *   @count               : lenght of the string
   1444  *
   1445  * RETURN     : int32_t type of status
   1446  *              NO_ERROR  -- success
   1447  *              none-zero failure code
   1448  *==========================================================================*/
   1449 int32_t getExifGpsProcessingMethod(char *gpsProcessingMethod,
   1450                                    uint32_t &count, char* value)
   1451 {
   1452     if(value != NULL) {
   1453         memcpy(gpsProcessingMethod, ExifAsciiPrefix, EXIF_ASCII_PREFIX_SIZE);
   1454         count = EXIF_ASCII_PREFIX_SIZE;
   1455         strncpy(gpsProcessingMethod + EXIF_ASCII_PREFIX_SIZE, value, strlen(value));
   1456         count += strlen(value);
   1457         gpsProcessingMethod[count++] = '\0'; // increase 1 for the last NULL char
   1458         return NO_ERROR;
   1459     } else {
   1460         return BAD_VALUE;
   1461     }
   1462 }
   1463 
   1464 /*===========================================================================
   1465  * FUNCTION   : getExifLatitude
   1466  *
   1467  * DESCRIPTION: get exif latitude
   1468  *
   1469  * PARAMETERS :
   1470  *   @latitude : ptr to rational struct to store latitude info
   1471  *   @ladRef   : charater to indicate latitude reference
   1472  *
   1473  * RETURN     : int32_t type of status
   1474  *              NO_ERROR  -- success
   1475  *              none-zero failure code
   1476  *==========================================================================*/
   1477 int32_t getExifLatitude(rat_t *latitude,
   1478                                            char *latRef, double value)
   1479 {
   1480     char str[30];
   1481     snprintf(str, sizeof(str), "%f", value);
   1482     if(str != NULL) {
   1483         parseGPSCoordinate(str, latitude);
   1484 
   1485         //set Latitude Ref
   1486         float latitudeValue = strtof(str, 0);
   1487         if(latitudeValue < 0.0f) {
   1488             latRef[0] = 'S';
   1489         } else {
   1490             latRef[0] = 'N';
   1491         }
   1492         latRef[1] = '\0';
   1493         return NO_ERROR;
   1494     }else{
   1495         return BAD_VALUE;
   1496     }
   1497 }
   1498 
   1499 /*===========================================================================
   1500  * FUNCTION   : getExifLongitude
   1501  *
   1502  * DESCRIPTION: get exif longitude
   1503  *
   1504  * PARAMETERS :
   1505  *   @longitude : ptr to rational struct to store longitude info
   1506  *   @lonRef    : charater to indicate longitude reference
   1507  *
   1508  * RETURN     : int32_t type of status
   1509  *              NO_ERROR  -- success
   1510  *              none-zero failure code
   1511  *==========================================================================*/
   1512 int32_t getExifLongitude(rat_t *longitude,
   1513                                             char *lonRef, double value)
   1514 {
   1515     char str[30];
   1516     snprintf(str, sizeof(str), "%f", value);
   1517     if(str != NULL) {
   1518         parseGPSCoordinate(str, longitude);
   1519 
   1520         //set Longitude Ref
   1521         float longitudeValue = strtof(str, 0);
   1522         if(longitudeValue < 0.0f) {
   1523             lonRef[0] = 'W';
   1524         } else {
   1525             lonRef[0] = 'E';
   1526         }
   1527         lonRef[1] = '\0';
   1528         return NO_ERROR;
   1529     }else{
   1530         return BAD_VALUE;
   1531     }
   1532 }
   1533 
   1534 /*===========================================================================
   1535  * FUNCTION   : getExifAltitude
   1536  *
   1537  * DESCRIPTION: get exif altitude
   1538  *
   1539  * PARAMETERS :
   1540  *   @altitude : ptr to rational struct to store altitude info
   1541  *   @altRef   : charater to indicate altitude reference
   1542  *
   1543  * RETURN     : int32_t type of status
   1544  *              NO_ERROR  -- success
   1545  *              none-zero failure code
   1546  *==========================================================================*/
   1547 int32_t getExifAltitude(rat_t *altitude,
   1548                                            char *altRef, double value)
   1549 {
   1550     char str[30];
   1551     snprintf(str, sizeof(str), "%f", value);
   1552     if(str != NULL) {
   1553         double value = atof(str);
   1554         *altRef = 0;
   1555         if(value < 0){
   1556             *altRef = 1;
   1557             value = -value;
   1558         }
   1559         return getRational(altitude, value*1000, 1000);
   1560     }else{
   1561         return BAD_VALUE;
   1562     }
   1563 }
   1564 
   1565 /*===========================================================================
   1566  * FUNCTION   : getExifGpsDateTimeStamp
   1567  *
   1568  * DESCRIPTION: get exif GPS date time stamp
   1569  *
   1570  * PARAMETERS :
   1571  *   @gpsDateStamp : GPS date time stamp string
   1572  *   @bufLen       : length of the string
   1573  *   @gpsTimeStamp : ptr to rational struct to store time stamp info
   1574  *
   1575  * RETURN     : int32_t type of status
   1576  *              NO_ERROR  -- success
   1577  *              none-zero failure code
   1578  *==========================================================================*/
   1579 int32_t getExifGpsDateTimeStamp(char *gpsDateStamp,
   1580                                            uint32_t bufLen,
   1581                                            rat_t *gpsTimeStamp, int64_t value)
   1582 {
   1583     char str[30];
   1584     snprintf(str, sizeof(str), "%lld", value);
   1585     if(str != NULL) {
   1586         time_t unixTime = (time_t)atol(str);
   1587         struct tm *UTCTimestamp = gmtime(&unixTime);
   1588 
   1589         strftime(gpsDateStamp, bufLen, "%Y:%m:%d", UTCTimestamp);
   1590 
   1591         getRational(&gpsTimeStamp[0], UTCTimestamp->tm_hour, 1);
   1592         getRational(&gpsTimeStamp[1], UTCTimestamp->tm_min, 1);
   1593         getRational(&gpsTimeStamp[2], UTCTimestamp->tm_sec, 1);
   1594 
   1595         return NO_ERROR;
   1596     } else {
   1597         return BAD_VALUE;
   1598     }
   1599 }
   1600 
   1601 int32_t getExifExposureValue(srat_t* exposure_val, int32_t exposure_comp,
   1602                              cam_rational_type_t step)
   1603 {
   1604     exposure_val->num = exposure_comp * step.numerator;
   1605     exposure_val->denom = step.denominator;
   1606     return 0;
   1607 }
   1608 /*===========================================================================
   1609  * FUNCTION   : getExifData
   1610  *
   1611  * DESCRIPTION: get exif data to be passed into jpeg encoding
   1612  *
   1613  * PARAMETERS : none
   1614  *
   1615  * RETURN     : exif data from user setting and GPS
   1616  *==========================================================================*/
   1617 QCamera3Exif *QCamera3PicChannel::getExifData()
   1618 {
   1619     QCamera3Exif *exif = new QCamera3Exif();
   1620     if (exif == NULL) {
   1621         ALOGE("%s: No memory for QCamera3Exif", __func__);
   1622         return NULL;
   1623     }
   1624 
   1625     int32_t rc = NO_ERROR;
   1626     uint32_t count = 0;
   1627 
   1628     // add exif entries
   1629     char dateTime[20];
   1630     memset(dateTime, 0, sizeof(dateTime));
   1631     count = 20;
   1632     rc = getExifDateTime(dateTime, count);
   1633     if(rc == NO_ERROR) {
   1634         exif->addEntry(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL,
   1635                        EXIF_ASCII,
   1636                        count,
   1637                        (void *)dateTime);
   1638         exif->addEntry(EXIFTAGID_EXIF_DATE_TIME_DIGITIZED,
   1639                        EXIF_ASCII,
   1640                        count,
   1641                        (void *)dateTime);
   1642     } else {
   1643         ALOGE("%s: getExifDateTime failed", __func__);
   1644     }
   1645 
   1646     rat_t focalLength;
   1647     rc = getExifFocalLength(&focalLength, mJpegSettings->lens_focal_length);
   1648     if (rc == NO_ERROR) {
   1649         exif->addEntry(EXIFTAGID_FOCAL_LENGTH,
   1650                        EXIF_RATIONAL,
   1651                        1,
   1652                        (void *)&(focalLength));
   1653     } else {
   1654         ALOGE("%s: getExifFocalLength failed", __func__);
   1655     }
   1656 
   1657     uint16_t isoSpeed = (uint16_t)mJpegSettings->sensor_sensitivity;
   1658     if(isoSpeed == 0) {
   1659         isoSpeed = (uint16_t)(mJpegSettings->lens_focal_length + 0.5)*100;
   1660     }
   1661 
   1662     exif->addEntry(EXIFTAGID_ISO_SPEED_RATING,
   1663                    EXIF_SHORT,
   1664                    1,
   1665                    (void *)&(isoSpeed));
   1666 
   1667     rat_t sensorExpTime, temp;
   1668     rc = getExifExpTimeInfo(&sensorExpTime, (int64_t)mJpegSettings->sensor_exposure_time);
   1669     if(sensorExpTime.denom <= 0) {// avoid zero-divide problem
   1670         sensorExpTime.denom  = 0.01668; // expoure time will be 1/60 s
   1671         uint16_t temp2 = (uint16_t)(sensorExpTime.denom <= 0 * 100000);
   1672         temp2 = (uint16_t)(100000 / temp2);
   1673         temp.num = 1;
   1674         temp.denom = temp2;
   1675         memcpy(&sensorExpTime, &temp, sizeof(sensorExpTime));
   1676     }
   1677     exif->addEntry(EXIFTAGID_EXPOSURE_TIME,
   1678                     EXIF_LONG,
   1679                     1,
   1680                     (void *) &(sensorExpTime.denom));
   1681 
   1682     if (strlen(mJpegSettings->gps_processing_method) > 0) {
   1683         char gpsProcessingMethod[EXIF_ASCII_PREFIX_SIZE + GPS_PROCESSING_METHOD_SIZE];
   1684         count = 0;
   1685         rc = getExifGpsProcessingMethod(gpsProcessingMethod, count, mJpegSettings->gps_processing_method);
   1686         if(rc == NO_ERROR) {
   1687             exif->addEntry(EXIFTAGID_GPS_PROCESSINGMETHOD,
   1688                            EXIF_ASCII,
   1689                            count,
   1690                            (void *)gpsProcessingMethod);
   1691         } else {
   1692             ALOGE("%s: getExifGpsProcessingMethod failed", __func__);
   1693         }
   1694     }
   1695 
   1696     if (mJpegSettings->gps_coordinates[0]) {
   1697         rat_t latitude[3];
   1698         char latRef[2];
   1699         rc = getExifLatitude(latitude, latRef, *(mJpegSettings->gps_coordinates[0]));
   1700         if(rc == NO_ERROR) {
   1701             exif->addEntry(EXIFTAGID_GPS_LATITUDE,
   1702                            EXIF_RATIONAL,
   1703                            3,
   1704                            (void *)latitude);
   1705             exif->addEntry(EXIFTAGID_GPS_LATITUDE_REF,
   1706                            EXIF_ASCII,
   1707                            2,
   1708                            (void *)latRef);
   1709         } else {
   1710             ALOGE("%s: getExifLatitude failed", __func__);
   1711         }
   1712     }
   1713 
   1714     if (mJpegSettings->gps_coordinates[1]) {
   1715         rat_t longitude[3];
   1716         char lonRef[2];
   1717         rc = getExifLongitude(longitude, lonRef, *(mJpegSettings->gps_coordinates[1]));
   1718         if(rc == NO_ERROR) {
   1719             exif->addEntry(EXIFTAGID_GPS_LONGITUDE,
   1720                            EXIF_RATIONAL,
   1721                            3,
   1722                            (void *)longitude);
   1723 
   1724             exif->addEntry(EXIFTAGID_GPS_LONGITUDE_REF,
   1725                            EXIF_ASCII,
   1726                            2,
   1727                            (void *)lonRef);
   1728         } else {
   1729             ALOGE("%s: getExifLongitude failed", __func__);
   1730         }
   1731     }
   1732 
   1733     if (mJpegSettings->gps_coordinates[2]) {
   1734         rat_t altitude;
   1735         char altRef;
   1736         rc = getExifAltitude(&altitude, &altRef, *(mJpegSettings->gps_coordinates[2]));
   1737         if(rc == NO_ERROR) {
   1738             exif->addEntry(EXIFTAGID_GPS_ALTITUDE,
   1739                            EXIF_RATIONAL,
   1740                            1,
   1741                            (void *)&(altitude));
   1742 
   1743             exif->addEntry(EXIFTAGID_GPS_ALTITUDE_REF,
   1744                            EXIF_BYTE,
   1745                            1,
   1746                            (void *)&altRef);
   1747         } else {
   1748             ALOGE("%s: getExifAltitude failed", __func__);
   1749         }
   1750     }
   1751 
   1752     if (mJpegSettings->gps_timestamp) {
   1753         char gpsDateStamp[20];
   1754         rat_t gpsTimeStamp[3];
   1755         rc = getExifGpsDateTimeStamp(gpsDateStamp, 20, gpsTimeStamp, *(mJpegSettings->gps_timestamp));
   1756         if(rc == NO_ERROR) {
   1757             exif->addEntry(EXIFTAGID_GPS_DATESTAMP,
   1758                            EXIF_ASCII,
   1759                            strlen(gpsDateStamp) + 1,
   1760                            (void *)gpsDateStamp);
   1761 
   1762             exif->addEntry(EXIFTAGID_GPS_TIMESTAMP,
   1763                            EXIF_RATIONAL,
   1764                            3,
   1765                            (void *)gpsTimeStamp);
   1766         } else {
   1767             ALOGE("%s: getExifGpsDataTimeStamp failed", __func__);
   1768         }
   1769     }
   1770 
   1771     srat_t exposure_val;
   1772     rc = getExifExposureValue(&exposure_val, mJpegSettings->exposure_compensation,
   1773                               mJpegSettings->exposure_comp_step);
   1774     if(rc == NO_ERROR) {
   1775         exif->addEntry(EXIFTAGID_EXPOSURE_BIAS_VALUE,
   1776                        EXIF_SRATIONAL,
   1777                        1,
   1778                        (void *)(&exposure_val));
   1779     } else {
   1780         ALOGE("%s: getExifExposureValue failed ", __func__);
   1781     }
   1782 
   1783     char value[PROPERTY_VALUE_MAX];
   1784     if (property_get("ro.product.manufacturer", value, "QCOM-AA") > 0) {
   1785         exif->addEntry(EXIFTAGID_MAKE,
   1786                        EXIF_ASCII,
   1787                        strlen(value) + 1,
   1788                        (void *)value);
   1789     } else {
   1790         ALOGE("%s: getExifMaker failed", __func__);
   1791     }
   1792 
   1793     if (property_get("ro.product.model", value, "QCAM-AA") > 0) {
   1794         exif->addEntry(EXIFTAGID_MODEL,
   1795                        EXIF_ASCII,
   1796                        strlen(value) + 1,
   1797                        (void *)value);
   1798     } else {
   1799         ALOGE("%s: getExifModel failed", __func__);
   1800     }
   1801 
   1802     float f_number = 0.0f;
   1803     f_number = mJpegSettings->f_number;
   1804     rat_t aperture;
   1805     getRational(&aperture, (uint32_t)f_number*F_NUMBER_DECIMAL_PRECISION, (uint32_t)F_NUMBER_DECIMAL_PRECISION);
   1806     exif->addEntry(EXIFTAGID_APERTURE,
   1807                        EXIF_RATIONAL,
   1808                        1,
   1809                        (void *)&(aperture));
   1810 
   1811     exif->addEntry(EXIFTAGID_F_NUMBER,
   1812                        EXIF_RATIONAL,
   1813                        1,
   1814                        (void *)&(aperture));
   1815 
   1816     uint16_t flash = mJpegSettings->flash;
   1817     exif->addEntry(EXIFTAGID_FLASH,
   1818                    EXIF_SHORT, 1,
   1819                    (void *)&(flash));
   1820 
   1821     int wb;
   1822     short val_short;
   1823     wb = mJpegSettings->wb;
   1824     if(wb == CAM_WB_MODE_AUTO)
   1825         val_short = 0;
   1826     else
   1827         val_short = 1;
   1828 
   1829     exif->addEntry(EXIFTAGID_WHITE_BALANCE,
   1830                        EXIF_SHORT,
   1831                        1,
   1832                        (void *)&(wb));
   1833 
   1834     struct timeval tv;
   1835     char subsecTime[7];
   1836     gettimeofday(&tv, NULL);
   1837     snprintf(subsecTime, 7, "%06ld", tv.tv_usec);
   1838 
   1839     exif->addEntry(EXIFTAGID_SUBSEC_TIME,
   1840                    EXIF_ASCII, 7,
   1841                    (void *)subsecTime);
   1842 
   1843     exif->addEntry(EXIFTAGID_SUBSEC_TIME_ORIGINAL,
   1844                    EXIF_ASCII, 7,
   1845                    (void *)subsecTime);
   1846 
   1847     exif->addEntry(EXIFTAGID_SUBSEC_TIME_DIGITIZED,
   1848                    EXIF_ASCII, 7,
   1849                    (void *)subsecTime);
   1850 
   1851     return exif;
   1852 }
   1853 
   1854 int QCamera3PicChannel::kMaxBuffers = 2;
   1855 
   1856 /*===========================================================================
   1857  * FUNCTION   : QCamera3ReprocessChannel
   1858  *
   1859  * DESCRIPTION: constructor of QCamera3ReprocessChannel
   1860  *
   1861  * PARAMETERS :
   1862  *   @cam_handle : camera handle
   1863  *   @cam_ops    : ptr to camera ops table
   1864  *   @pp_mask    : post-proccess feature mask
   1865  *
   1866  * RETURN     : none
   1867  *==========================================================================*/
   1868 QCamera3ReprocessChannel::QCamera3ReprocessChannel(uint32_t cam_handle,
   1869                                                  mm_camera_ops_t *cam_ops,
   1870                                                  channel_cb_routine cb_routine,
   1871                                                  cam_padding_info_t *paddingInfo,
   1872                                                  void *userData, void *ch_hdl) :
   1873     QCamera3Channel(cam_handle, cam_ops, cb_routine, paddingInfo, userData),
   1874     picChHandle(ch_hdl),
   1875     m_pSrcChannel(NULL),
   1876     m_pMetaChannel(NULL),
   1877     m_metaFrame(NULL),
   1878     mMemory(NULL)
   1879 {
   1880     memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles));
   1881 }
   1882 
   1883 
   1884 /*===========================================================================
   1885  * FUNCTION   : QCamera3ReprocessChannel
   1886  *
   1887  * DESCRIPTION: constructor of QCamera3ReprocessChannel
   1888  *
   1889  * PARAMETERS :
   1890  *   @cam_handle : camera handle
   1891  *   @cam_ops    : ptr to camera ops table
   1892  *   @pp_mask    : post-proccess feature mask
   1893  *
   1894  * RETURN     : none
   1895  *==========================================================================*/
   1896 int32_t QCamera3ReprocessChannel::initialize()
   1897 {
   1898     int32_t rc = NO_ERROR;
   1899     mm_camera_channel_attr_t attr;
   1900 
   1901     memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
   1902     attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS;
   1903     attr.max_unmatched_frames = 1;
   1904 
   1905     rc = init(&attr, NULL);
   1906     if (rc < 0) {
   1907         ALOGE("%s: init failed", __func__);
   1908     }
   1909     return rc;
   1910 }
   1911 
   1912 
   1913 /*===========================================================================
   1914  * FUNCTION   : QCamera3ReprocessChannel
   1915  *
   1916  * DESCRIPTION: constructor of QCamera3ReprocessChannel
   1917  *
   1918  * PARAMETERS :
   1919  *   @cam_handle : camera handle
   1920  *   @cam_ops    : ptr to camera ops table
   1921  *   @pp_mask    : post-proccess feature mask
   1922  *
   1923  * RETURN     : none
   1924  *==========================================================================*/
   1925 void QCamera3ReprocessChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
   1926                                   QCamera3Stream *stream)
   1927 {
   1928     //Got the pproc data callback. Now send to jpeg encoding
   1929     uint8_t frameIndex;
   1930     mm_camera_super_buf_t* frame = NULL;
   1931     QCamera3PicChannel *obj = (QCamera3PicChannel *)picChHandle;
   1932 
   1933     if(!super_frame) {
   1934          ALOGE("%s: Invalid Super buffer",__func__);
   1935          return;
   1936     }
   1937 
   1938     if(super_frame->num_bufs != 1) {
   1939          ALOGE("%s: Multiple streams are not supported",__func__);
   1940          return;
   1941     }
   1942     if(super_frame->bufs[0] == NULL ) {
   1943          ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
   1944                   __func__);
   1945          return;
   1946     }
   1947 
   1948     frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
   1949     frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
   1950     if (frame == NULL) {
   1951        ALOGE("%s: Error allocating memory to save received_frame structure.",
   1952                                                                     __func__);
   1953        if(stream) {
   1954            stream->bufDone(frameIndex);
   1955        }
   1956        return;
   1957     }
   1958     *frame = *super_frame;
   1959     //queue back the metadata buffer
   1960     if (m_metaFrame != NULL) {
   1961        ((QCamera3MetadataChannel*)m_pMetaChannel)->bufDone(m_metaFrame);
   1962        free(m_metaFrame);
   1963        m_metaFrame = NULL;
   1964     } else {
   1965        ALOGE("%s: Meta frame was NULL", __func__);
   1966     }
   1967     obj->m_postprocessor.processPPData(frame);
   1968     return;
   1969 }
   1970 
   1971 /*===========================================================================
   1972  * FUNCTION   : QCamera3ReprocessChannel
   1973  *
   1974  * DESCRIPTION: default constructor of QCamera3ReprocessChannel
   1975  *
   1976  * PARAMETERS : none
   1977  *
   1978  * RETURN     : none
   1979  *==========================================================================*/
   1980 QCamera3ReprocessChannel::QCamera3ReprocessChannel() :
   1981     m_pSrcChannel(NULL),
   1982     m_pMetaChannel(NULL),
   1983     m_metaFrame(NULL)
   1984 {
   1985 }
   1986 
   1987 /*===========================================================================
   1988  * FUNCTION   : QCamera3ReprocessChannel
   1989  *
   1990  * DESCRIPTION: register the buffers of the reprocess channel
   1991  *
   1992  * PARAMETERS : none
   1993  *
   1994  * RETURN     : none
   1995  *==========================================================================*/
   1996 int32_t QCamera3ReprocessChannel::registerBuffers(uint32_t num_buffers, buffer_handle_t **buffers)
   1997 {
   1998    return 0;
   1999 }
   2000 
   2001 /*===========================================================================
   2002  * FUNCTION   : getStreamBufs
   2003  *
   2004  * DESCRIPTION: register the buffers of the reprocess channel
   2005  *
   2006  * PARAMETERS : none
   2007  *
   2008  * RETURN     : QCamera3Memory *
   2009  *==========================================================================*/
   2010 QCamera3Memory* QCamera3ReprocessChannel::getStreamBufs(uint32_t len)
   2011 {
   2012    int rc = 0;
   2013 
   2014     mMemory = new QCamera3HeapMemory();
   2015     if (!mMemory) {
   2016         ALOGE("%s: unable to create reproc memory", __func__);
   2017         return NULL;
   2018     }
   2019 
   2020     //Queue YUV buffers in the beginning mQueueAll = true
   2021     rc = mMemory->allocate(2, len, true);
   2022     if (rc < 0) {
   2023         ALOGE("%s: unable to allocate reproc memory", __func__);
   2024         delete mMemory;
   2025         mMemory = NULL;
   2026         return NULL;
   2027     }
   2028     return mMemory;
   2029 }
   2030 
   2031 /*===========================================================================
   2032  * FUNCTION   : getStreamBufs
   2033  *
   2034  * DESCRIPTION: register the buffers of the reprocess channel
   2035  *
   2036  * PARAMETERS : none
   2037  *
   2038  * RETURN     :
   2039  *==========================================================================*/
   2040 void QCamera3ReprocessChannel::putStreamBufs()
   2041 {
   2042     mMemory->deallocate();
   2043     delete mMemory;
   2044     mMemory = NULL;
   2045 }
   2046 
   2047 /*===========================================================================
   2048  * FUNCTION   : ~QCamera3ReprocessChannel
   2049  *
   2050  * DESCRIPTION: destructor of QCamera3ReprocessChannel
   2051  *
   2052  * PARAMETERS : none
   2053  *
   2054  * RETURN     : none
   2055  *==========================================================================*/
   2056 QCamera3ReprocessChannel::~QCamera3ReprocessChannel()
   2057 {
   2058 }
   2059 
   2060 /*===========================================================================
   2061  * FUNCTION   : getStreamBySourceHandle
   2062  *
   2063  * DESCRIPTION: find reprocess stream by its source stream handle
   2064  *
   2065  * PARAMETERS :
   2066  *   @srcHandle : source stream handle
   2067  *
   2068  * RETURN     : ptr to reprocess stream if found. NULL if not found
   2069  *==========================================================================*/
   2070 QCamera3Stream * QCamera3ReprocessChannel::getStreamBySourceHandle(uint32_t srcHandle)
   2071 {
   2072     QCamera3Stream *pStream = NULL;
   2073 
   2074     for (int i = 0; i < m_numStreams; i++) {
   2075         if (mSrcStreamHandles[i] == srcHandle) {
   2076             pStream = mStreams[i];
   2077             break;
   2078         }
   2079     }
   2080     return pStream;
   2081 }
   2082 
   2083 /*===========================================================================
   2084  * FUNCTION   : doReprocess
   2085  *
   2086  * DESCRIPTION: request to do a reprocess on the frame
   2087  *
   2088  * PARAMETERS :
   2089  *   @frame   : frame to be performed a reprocess
   2090  *
   2091  * RETURN     : int32_t type of status
   2092  *              NO_ERROR  -- success
   2093  *              none-zero failure code
   2094  *==========================================================================*/
   2095 int32_t QCamera3ReprocessChannel::doReprocess(mm_camera_super_buf_t *frame,
   2096                                               mm_camera_super_buf_t *meta_frame)
   2097 {
   2098     int32_t rc = 0;
   2099     if (m_numStreams < 1) {
   2100         ALOGE("%s: No reprocess stream is created", __func__);
   2101         return -1;
   2102     }
   2103     if (m_pSrcChannel == NULL) {
   2104         ALOGE("%s: No source channel for reprocess", __func__);
   2105         return -1;
   2106     }
   2107     m_metaFrame = meta_frame;
   2108     for (int i = 0; i < frame->num_bufs; i++) {
   2109         QCamera3Stream *pStream = getStreamBySourceHandle(frame->bufs[i]->stream_id);
   2110         if (pStream != NULL) {
   2111             cam_stream_parm_buffer_t param;
   2112             memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
   2113             param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
   2114             param.reprocess.buf_index = frame->bufs[i]->buf_idx;
   2115             param.reprocess.frame_idx = frame->bufs[i]->frame_idx;
   2116             if (meta_frame != NULL) {
   2117                param.reprocess.meta_present = 1;
   2118                param.reprocess.meta_stream_handle = m_pMetaChannel->mStreams[0]->getMyServerID();
   2119                param.reprocess.meta_buf_index = meta_frame->bufs[0]->buf_idx;
   2120             }
   2121             rc = pStream->setParameter(param);
   2122             if (rc != NO_ERROR) {
   2123                 ALOGE("%s: stream setParameter for reprocess failed", __func__);
   2124                 break;
   2125             }
   2126         }
   2127     }
   2128     return rc;
   2129 }
   2130 
   2131 /*===========================================================================
   2132  * FUNCTION   : doReprocess
   2133  *
   2134  * DESCRIPTION: request to do a reprocess on the frame
   2135  *
   2136  * PARAMETERS :
   2137  *   @buf_fd     : fd to the input buffer that needs reprocess
   2138  *   @buf_lenght : length of the input buffer
   2139  *   @ret_val    : result of reprocess.
   2140  *                 Example: Could be faceID in case of register face image.
   2141  *
   2142  * RETURN     : int32_t type of status
   2143  *              NO_ERROR  -- success
   2144  *              none-zero failure code
   2145  *==========================================================================*/
   2146 int32_t QCamera3ReprocessChannel::doReprocess(int buf_fd,
   2147                                               uint32_t buf_length,
   2148                                               int32_t &ret_val,
   2149                                               mm_camera_super_buf_t *meta_frame)
   2150 {
   2151     int32_t rc = 0;
   2152     if (m_numStreams < 1) {
   2153         ALOGE("%s: No reprocess stream is created", __func__);
   2154         return -1;
   2155     }
   2156     if (meta_frame == NULL) {
   2157         ALOGE("%s: Did not get corresponding metadata in time", __func__);
   2158         return -1;
   2159     }
   2160 
   2161     uint32_t buf_idx = 0;
   2162     for (int i = 0; i < m_numStreams; i++) {
   2163         rc = mStreams[i]->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
   2164                                  buf_idx, -1,
   2165                                  buf_fd, buf_length);
   2166 
   2167         if (rc == NO_ERROR) {
   2168             cam_stream_parm_buffer_t param;
   2169             memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
   2170             param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
   2171             param.reprocess.buf_index = buf_idx;
   2172             param.reprocess.meta_present = 1;
   2173             param.reprocess.meta_stream_handle = m_pMetaChannel->mStreams[0]->getMyServerID();
   2174             param.reprocess.meta_buf_index = meta_frame->bufs[0]->buf_idx;
   2175             rc = mStreams[i]->setParameter(param);
   2176             if (rc == NO_ERROR) {
   2177                 ret_val = param.reprocess.ret_val;
   2178             }
   2179             mStreams[i]->unmapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
   2180                                   buf_idx, -1);
   2181         }
   2182     }
   2183     return rc;
   2184 }
   2185 
   2186 /*===========================================================================
   2187  * FUNCTION   : addReprocStreamsFromSource
   2188  *
   2189  * DESCRIPTION: add reprocess streams from input source channel
   2190  *
   2191  * PARAMETERS :
   2192  *   @config         : pp feature configuration
   2193  *   @pSrcChannel    : ptr to input source channel that needs reprocess
   2194  *   @pMetaChannel   : ptr to metadata channel to get corresp. metadata
   2195  *
   2196  * RETURN     : int32_t type of status
   2197  *              NO_ERROR  -- success
   2198  *              none-zero failure code
   2199  *==========================================================================*/
   2200 int32_t QCamera3ReprocessChannel::addReprocStreamsFromSource(cam_pp_feature_config_t &config,
   2201                                                              QCamera3Channel *pSrcChannel,
   2202                                                              QCamera3Channel *pMetaChannel)
   2203 {
   2204     int32_t rc = 0;
   2205     QCamera3Stream *pSrcStream = pSrcChannel->getStreamByIndex(0);
   2206     if (pSrcStream == NULL) {
   2207        ALOGE("%s: source channel doesn't have a stream", __func__);
   2208        return BAD_VALUE;
   2209     }
   2210     cam_stream_reproc_config_t reprocess_config;
   2211     cam_dimension_t streamDim;
   2212     cam_stream_type_t streamType;
   2213     cam_format_t streamFormat;
   2214     cam_frame_len_offset_t frameOffset;
   2215     int num_buffers = 2;
   2216 
   2217     streamType = CAM_STREAM_TYPE_OFFLINE_PROC;
   2218     pSrcStream->getFormat(streamFormat);
   2219     pSrcStream->getFrameDimension(streamDim);
   2220     pSrcStream->getFrameOffset(frameOffset);
   2221 
   2222     reprocess_config.pp_type = CAM_ONLINE_REPROCESS_TYPE;
   2223     reprocess_config.online.input_stream_id = pSrcStream->getMyServerID();
   2224     reprocess_config.online.input_stream_type = pSrcStream->getMyType();
   2225     reprocess_config.pp_feature_config = config;
   2226 
   2227     mSrcStreamHandles[m_numStreams] = pSrcStream->getMyHandle();
   2228 
   2229     if (reprocess_config.pp_feature_config.feature_mask & CAM_QCOM_FEATURE_ROTATION) {
   2230         if (reprocess_config.pp_feature_config.rotation == ROTATE_90 ||
   2231             reprocess_config.pp_feature_config.rotation == ROTATE_270) {
   2232             // rotated by 90 or 270, need to switch width and height
   2233             int32_t temp = streamDim.height;
   2234             streamDim.height = streamDim.width;
   2235             streamDim.width = temp;
   2236         }
   2237     }
   2238 
   2239     QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
   2240                                                m_handle,
   2241                                                m_camOps,
   2242                                                mPaddingInfo,
   2243                                                (QCamera3Channel*)this);
   2244     if (pStream == NULL) {
   2245         ALOGE("%s: No mem for Stream", __func__);
   2246         return NO_MEMORY;
   2247     }
   2248 
   2249     rc = pStream->init(streamType, streamFormat, streamDim, &reprocess_config,
   2250                        num_buffers,QCamera3Channel::streamCbRoutine, this);
   2251 
   2252 
   2253     if (rc == 0) {
   2254         mStreams[m_numStreams] = pStream;
   2255         m_numStreams++;
   2256     } else {
   2257         ALOGE("%s: failed to create reprocess stream", __func__);
   2258         delete pStream;
   2259     }
   2260 
   2261     if (rc == NO_ERROR) {
   2262         m_pSrcChannel = pSrcChannel;
   2263         m_pMetaChannel = pMetaChannel;
   2264     }
   2265     if(m_camOps->request_super_buf(m_camHandle,m_handle,1) < 0) {
   2266         ALOGE("%s: Request for super buffer failed",__func__);
   2267     }
   2268     return rc;
   2269 }
   2270 
   2271 
   2272 }; // namespace qcamera
   2273