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.deinit();
    931     if (rc != 0) {
    932         ALOGE("De-init Postprocessor failed");
    933     }
    934     if (mCamera3Buffers) {
    935         delete[] mCamera3Buffers;
    936     }
    937 }
    938 
    939 int32_t QCamera3PicChannel::initialize()
    940 {
    941     int32_t rc = NO_ERROR;
    942     cam_dimension_t streamDim;
    943     cam_stream_type_t streamType;
    944     cam_format_t streamFormat;
    945     mm_camera_channel_attr_t attr;
    946 
    947     memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
    948     attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_BURST;
    949     attr.look_back = 1;
    950     attr.post_frame_skip = 1;
    951     attr.water_mark = 1;
    952     attr.max_unmatched_frames = 1;
    953 
    954     rc = init(&attr, NULL);
    955     if (rc < 0) {
    956         ALOGE("%s: init failed", __func__);
    957         return rc;
    958     }
    959 
    960     streamType = CAM_STREAM_TYPE_NON_ZSL_SNAPSHOT;
    961     streamFormat = CAM_FORMAT_YUV_420_NV21;
    962     streamDim.width = mCamera3Stream->width;
    963     streamDim.height = mCamera3Stream->height;
    964 
    965     int num_buffers = 1;
    966 
    967     rc = QCamera3Channel::addStream(streamType, streamFormat, streamDim,
    968             num_buffers);
    969 
    970     return rc;
    971 }
    972 
    973 int32_t QCamera3PicChannel::request(buffer_handle_t *buffer,
    974         uint32_t frameNumber, jpeg_settings_t* jpegSettings,
    975         mm_camera_buf_def_t *pInputBuffer,QCamera3Channel* pInputChannel)
    976 {
    977     //FIX ME: Return buffer back in case of failures below.
    978 
    979     int32_t rc = NO_ERROR;
    980     int index;
    981     mJpegSettings = jpegSettings;
    982     if(!m_bIsActive) {
    983         ALOGD("%s: First request on this channel starting stream",__func__);
    984         //Stream on for main image. YUV buffer is queued to the kernel at the end of this call.
    985         if(!pInputBuffer)
    986             rc = start();
    987         else
    988             ALOGD("%s: Current request has input buffer no need to start h/w stream", __func__);
    989     } else {
    990         mStreams[0]->bufDone(0);
    991         ALOGD("%s: Request on an existing stream",__func__);
    992     }
    993 
    994     if(rc != NO_ERROR) {
    995         ALOGE("%s: Failed to start the stream on the request",__func__);
    996         return rc;
    997     }
    998 
    999 
   1000     if(!mMemory) {
   1001         if(pInputBuffer) {
   1002             mMemory = new QCamera3GrallocMemory();
   1003             if (mMemory == NULL) {
   1004                 return NO_MEMORY;
   1005             }
   1006 
   1007             //Registering Jpeg output buffer
   1008             if (mMemory->registerBuffers(mNumBufs, mCamera3Buffers) < 0) {
   1009                 delete mMemory;
   1010                 mMemory = NULL;
   1011                 return NO_MEMORY;
   1012             }
   1013         } else {
   1014             ALOGE("%s: error, Gralloc Memory object not yet created for this stream",__func__);
   1015             return NO_MEMORY;
   1016         }
   1017     }
   1018 
   1019     index = mMemory->getMatchBufIndex((void*)buffer);
   1020     if(index < 0) {
   1021         ALOGE("%s: Could not find object among registered buffers",__func__);
   1022         return DEAD_OBJECT;
   1023     }
   1024     rc = mMemory->markFrameNumber(index, frameNumber);
   1025 
   1026     //Start the postprocessor for jpeg encoding. Pass mMemory as destination buffer
   1027     mCurrentBufIndex = index;
   1028 
   1029     m_postprocessor.start(mMemory, index, this);
   1030 
   1031     ALOGD("%s: Post-process started", __func__);
   1032     if(pInputBuffer) {
   1033         ALOGD("%s: Issue call to reprocess", __func__);
   1034         m_postprocessor.processAuxiliaryData(pInputBuffer,pInputChannel);
   1035     }
   1036     return rc;
   1037 }
   1038 
   1039 /*===========================================================================
   1040  * FUNCTION   : dataNotifyCB
   1041  *
   1042  * DESCRIPTION: Channel Level callback used for super buffer data notify.
   1043  *              This function is registered with mm-camera-interface to handle
   1044  *              data notify
   1045  *
   1046  * PARAMETERS :
   1047  *   @recvd_frame   : stream frame received
   1048  *   userdata       : user data ptr
   1049  *
   1050  * RETURN     : none
   1051  *==========================================================================*/
   1052 void QCamera3PicChannel::dataNotifyCB(mm_camera_super_buf_t *recvd_frame,
   1053                                  void *userdata)
   1054 {
   1055     ALOGV("%s: E\n", __func__);
   1056     QCamera3PicChannel *channel = (QCamera3PicChannel *)userdata;
   1057 
   1058     if (channel == NULL) {
   1059         ALOGE("%s: invalid channel pointer", __func__);
   1060         return;
   1061     }
   1062 
   1063     if(channel->m_numStreams != 1) {
   1064         ALOGE("%s: Error: Bug: This callback assumes one stream per channel",__func__);
   1065         return;
   1066     }
   1067 
   1068 
   1069     if(channel->mStreams[0] == NULL) {
   1070         ALOGE("%s: Error: Invalid Stream object",__func__);
   1071         return;
   1072     }
   1073 
   1074     channel->QCamera3PicChannel::streamCbRoutine(recvd_frame, channel->mStreams[0]);
   1075 
   1076     ALOGV("%s: X\n", __func__);
   1077     return;
   1078 }
   1079 
   1080 
   1081 int32_t QCamera3PicChannel::registerBuffers(uint32_t num_buffers,
   1082                         buffer_handle_t **buffers)
   1083 {
   1084     int rc = 0;
   1085     cam_stream_type_t streamType;
   1086     cam_format_t streamFormat;
   1087 
   1088     ALOGV("%s: E",__func__);
   1089     rc = QCamera3PicChannel::initialize();
   1090     if (rc < 0) {
   1091         ALOGE("%s: init failed", __func__);
   1092         return rc;
   1093     }
   1094 
   1095     if (mCamera3Stream->format == HAL_PIXEL_FORMAT_BLOB) {
   1096         streamType = CAM_STREAM_TYPE_NON_ZSL_SNAPSHOT;
   1097         streamFormat = CAM_FORMAT_YUV_420_NV21;
   1098     } else {
   1099         //TODO: Fail for other types of streams for now
   1100         ALOGE("%s: format is not BLOB", __func__);
   1101         return -EINVAL;
   1102     }
   1103     /* Bookkeep buffer set because they go out of scope after register call */
   1104     mNumBufs = num_buffers;
   1105     mCamera3Buffers = new buffer_handle_t*[num_buffers];
   1106     if (mCamera3Buffers == NULL) {
   1107         ALOGE("%s: Failed to allocate buffer_handle_t*", __func__);
   1108         return -ENOMEM;
   1109     }
   1110     for (size_t i = 0; i < num_buffers; i++)
   1111         mCamera3Buffers[i] = buffers[i];
   1112 
   1113     ALOGV("%s: X",__func__);
   1114     return rc;
   1115 }
   1116 
   1117 void QCamera3PicChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
   1118                             QCamera3Stream *stream)
   1119 {
   1120     //TODO
   1121     //Used only for getting YUV. Jpeg callback will be sent back from channel
   1122     //directly to HWI. Refer to func jpegEvtHandle
   1123 
   1124     //Got the yuv callback. Calling yuv callback handler in PostProc
   1125     uint8_t frameIndex;
   1126     mm_camera_super_buf_t* frame = NULL;
   1127     if(!super_frame) {
   1128          ALOGE("%s: Invalid Super buffer",__func__);
   1129          return;
   1130     }
   1131 
   1132     if(super_frame->num_bufs != 1) {
   1133          ALOGE("%s: Multiple streams are not supported",__func__);
   1134          return;
   1135     }
   1136     if(super_frame->bufs[0] == NULL ) {
   1137          ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
   1138                   __func__);
   1139          return;
   1140     }
   1141 
   1142     frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
   1143     if(frameIndex >= mNumBufs) {
   1144          ALOGE("%s: Error, Invalid index for buffer",__func__);
   1145          if(stream) {
   1146              stream->bufDone(frameIndex);
   1147          }
   1148          return;
   1149     }
   1150 
   1151     frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
   1152     if (frame == NULL) {
   1153        ALOGE("%s: Error allocating memory to save received_frame structure.",
   1154                                                                     __func__);
   1155        if(stream) {
   1156            stream->bufDone(frameIndex);
   1157        }
   1158        return;
   1159     }
   1160     *frame = *super_frame;
   1161 
   1162     m_postprocessor.processData(frame);
   1163     free(super_frame);
   1164     return;
   1165 }
   1166 
   1167 QCamera3Memory* QCamera3PicChannel::getStreamBufs(uint32_t len)
   1168 {
   1169     int rc = 0;
   1170 
   1171     if (mNumBufs == 0 || mCamera3Buffers == NULL) {
   1172         ALOGE("%s: buffers not registered yet", __func__);
   1173         return NULL;
   1174     }
   1175 
   1176     if(mMemory) {
   1177         delete mMemory;
   1178         mMemory = NULL;
   1179     }
   1180     mMemory = new QCamera3GrallocMemory();
   1181     if (mMemory == NULL) {
   1182         return NULL;
   1183     }
   1184 
   1185     //Registering Jpeg output buffer
   1186     if (mMemory->registerBuffers(mNumBufs, mCamera3Buffers) < 0) {
   1187         delete mMemory;
   1188         mMemory = NULL;
   1189         return NULL;
   1190     }
   1191 
   1192     mYuvMemory = new QCamera3HeapMemory();
   1193     if (!mYuvMemory) {
   1194         ALOGE("%s: unable to create metadata memory", __func__);
   1195         return NULL;
   1196     }
   1197 
   1198     //Queue YUV buffers in the beginning mQueueAll = true
   1199     rc = mYuvMemory->allocate(1, len, true);
   1200     if (rc < 0) {
   1201         ALOGE("%s: unable to allocate metadata memory", __func__);
   1202         delete mYuvMemory;
   1203         mYuvMemory = NULL;
   1204         return NULL;
   1205     }
   1206     return mYuvMemory;
   1207 }
   1208 
   1209 void QCamera3PicChannel::putStreamBufs()
   1210 {
   1211     mMemory->unregisterBuffers();
   1212     delete mMemory;
   1213     mMemory = NULL;
   1214 
   1215     mYuvMemory->deallocate();
   1216     delete mYuvMemory;
   1217     mYuvMemory = NULL;
   1218 }
   1219 
   1220 bool QCamera3PicChannel::isRawSnapshot()
   1221 {
   1222    return !(mJpegSettings->is_jpeg_format);
   1223 }
   1224 /*===========================================================================
   1225  * FUNCTION   : getThumbnailSize
   1226  *
   1227  * DESCRIPTION: get user set thumbnail size
   1228  *
   1229  * PARAMETERS :
   1230  *   @dim     : output of thumbnail dimension
   1231  *
   1232  * RETURN     : none
   1233  *==========================================================================*/
   1234 void QCamera3PicChannel::getThumbnailSize(cam_dimension_t &dim)
   1235 {
   1236     dim = mJpegSettings->thumbnail_size;
   1237 }
   1238 
   1239 /*===========================================================================
   1240  * FUNCTION   : getJpegQuality
   1241  *
   1242  * DESCRIPTION: get user set jpeg quality
   1243  *
   1244  * PARAMETERS : none
   1245  *
   1246  * RETURN     : jpeg quality setting
   1247  *==========================================================================*/
   1248 int QCamera3PicChannel::getJpegQuality()
   1249 {
   1250     int quality = mJpegSettings->jpeg_quality;
   1251     if (quality < 0) {
   1252         quality = 85;  //set to default quality value
   1253     }
   1254     return quality;
   1255 }
   1256 
   1257 /*===========================================================================
   1258  * FUNCTION   : getJpegRotation
   1259  *
   1260  * DESCRIPTION: get rotation information to be passed into jpeg encoding
   1261  *
   1262  * PARAMETERS : none
   1263  *
   1264  * RETURN     : rotation information
   1265  *==========================================================================*/
   1266 int QCamera3PicChannel::getJpegRotation() {
   1267     int rotation = mJpegSettings->jpeg_orientation;
   1268     if (rotation < 0) {
   1269         rotation = 0;
   1270     }
   1271     return rotation;
   1272 }
   1273 
   1274 void QCamera3PicChannel::queueMetadata(mm_camera_super_buf_t *metadata_buf)
   1275 {
   1276     m_postprocessor.processPPMetadata(metadata_buf);
   1277 }
   1278 /*===========================================================================
   1279  * FUNCTION   : getRational
   1280  *
   1281  * DESCRIPTION: compose rational struct
   1282  *
   1283  * PARAMETERS :
   1284  *   @rat     : ptr to struct to store rational info
   1285  *   @num     :num of the rational
   1286  *   @denom   : denom of the rational
   1287  *
   1288  * RETURN     : int32_t type of status
   1289  *              NO_ERROR  -- success
   1290  *              none-zero failure code
   1291  *==========================================================================*/
   1292 int32_t getRational(rat_t *rat, int num, int denom)
   1293 {
   1294     if (NULL == rat) {
   1295         ALOGE("%s: NULL rat input", __func__);
   1296         return BAD_VALUE;
   1297     }
   1298     rat->num = num;
   1299     rat->denom = denom;
   1300     return NO_ERROR;
   1301 }
   1302 
   1303 /*===========================================================================
   1304  * FUNCTION   : getRational
   1305  *
   1306  * DESCRIPTION: compose rational struct
   1307  *
   1308  * PARAMETERS :
   1309  *   @rat     : ptr to struct to store rational info
   1310  *   @num     :num of the rational
   1311  *   @denom   : denom of the rational
   1312  *
   1313  * RETURN     : int32_t type of status
   1314  *              NO_ERROR  -- success
   1315  *              none-zero failure code
   1316  *==========================================================================*/
   1317 int32_t getRationalExposureTime(rat_t *rat, double num, double denom)
   1318 {
   1319     if (NULL == rat) {
   1320         ALOGE("%s: NULL rat input", __func__);
   1321         return BAD_VALUE;
   1322     }
   1323     rat->num = num;
   1324     rat->denom = round(1.0 / denom);
   1325     return NO_ERROR;
   1326 }
   1327 
   1328 /*===========================================================================
   1329  * FUNCTION   : parseGPSCoordinate
   1330  *
   1331  * DESCRIPTION: parse GPS coordinate string
   1332  *
   1333  * PARAMETERS :
   1334  *   @coord_str : [input] coordinate string
   1335  *   @coord     : [output]  ptr to struct to store coordinate
   1336  *
   1337  * RETURN     : int32_t type of status
   1338  *              NO_ERROR  -- success
   1339  *              none-zero failure code
   1340  *==========================================================================*/
   1341 int parseGPSCoordinate(const char *coord_str, rat_t* coord)
   1342 {
   1343     if(coord == NULL) {
   1344         ALOGE("%s: error, invalid argument coord == NULL", __func__);
   1345         return BAD_VALUE;
   1346     }
   1347     float degF = atof(coord_str);
   1348     if (degF < 0) {
   1349         degF = -degF;
   1350     }
   1351     float minF = (degF - (int) degF) * 60;
   1352     float secF = (minF - (int) minF) * 60;
   1353 
   1354     getRational(&coord[0], (int)degF, 1);
   1355     getRational(&coord[1], (int)minF, 1);
   1356     getRational(&coord[2], (int)(secF * 10000), 10000);
   1357     return NO_ERROR;
   1358 }
   1359 
   1360 /*===========================================================================
   1361  * FUNCTION   : getExifDateTime
   1362  *
   1363  * DESCRIPTION: query exif date time
   1364  *
   1365  * PARAMETERS :
   1366  *   @dateTime : string to store exif date time
   1367  *   @count    : lenght of the dateTime string
   1368  *
   1369  * RETURN     : int32_t type of status
   1370  *              NO_ERROR  -- success
   1371  *              none-zero failure code
   1372  *==========================================================================*/
   1373 int32_t getExifDateTime(char *dateTime, uint32_t &count)
   1374 {
   1375     //get time and date from system
   1376     time_t rawtime;
   1377     struct tm * timeinfo;
   1378     time(&rawtime);
   1379     timeinfo = localtime (&rawtime);
   1380     //Write datetime according to EXIF Spec
   1381     //"YYYY:MM:DD HH:MM:SS" (20 chars including \0)
   1382     snprintf(dateTime, 20, "%04d:%02d:%02d %02d:%02d:%02d",
   1383              timeinfo->tm_year + 1900, timeinfo->tm_mon + 1,
   1384              timeinfo->tm_mday, timeinfo->tm_hour,
   1385              timeinfo->tm_min, timeinfo->tm_sec);
   1386     count = 20;
   1387 
   1388     return NO_ERROR;
   1389 }
   1390 
   1391 /*===========================================================================
   1392  * FUNCTION   : getExifFocalLength
   1393  *
   1394  * DESCRIPTION: get exif focal lenght
   1395  *
   1396  * PARAMETERS :
   1397  *   @focalLength : ptr to rational strcut to store focal lenght
   1398  *
   1399  * RETURN     : int32_t type of status
   1400  *              NO_ERROR  -- success
   1401  *              none-zero failure code
   1402  *==========================================================================*/
   1403 int32_t getExifFocalLength(rat_t *focalLength, float value)
   1404 {
   1405     int focalLengthValue =
   1406         (int)(value * FOCAL_LENGTH_DECIMAL_PRECISION);
   1407     return getRational(focalLength, focalLengthValue, FOCAL_LENGTH_DECIMAL_PRECISION);
   1408 }
   1409 
   1410 /*===========================================================================
   1411   * FUNCTION   : getExifExpTimeInfo
   1412   *
   1413   * DESCRIPTION: get exif exposure time information
   1414   *
   1415   * PARAMETERS :
   1416   *   @expoTimeInfo     : expousure time value
   1417   * RETURN     : nt32_t type of status
   1418   *              NO_ERROR  -- success
   1419   *              none-zero failure code
   1420   *==========================================================================*/
   1421 int32_t getExifExpTimeInfo(rat_t *expoTimeInfo, int64_t value)
   1422 {
   1423 
   1424     float cal_exposureTime;
   1425     if (value != 0)
   1426         cal_exposureTime = (double)(value / 1000000000.0);
   1427     else
   1428         cal_exposureTime = 60.00;
   1429     return getRationalExposureTime(expoTimeInfo, 1, cal_exposureTime);
   1430 }
   1431 
   1432 /*===========================================================================
   1433  * FUNCTION   : getExifGpsProcessingMethod
   1434  *
   1435  * DESCRIPTION: get GPS processing method
   1436  *
   1437  * PARAMETERS :
   1438  *   @gpsProcessingMethod : string to store GPS process method
   1439  *   @count               : lenght of the string
   1440  *
   1441  * RETURN     : int32_t type of status
   1442  *              NO_ERROR  -- success
   1443  *              none-zero failure code
   1444  *==========================================================================*/
   1445 int32_t getExifGpsProcessingMethod(char *gpsProcessingMethod,
   1446                                    uint32_t &count, char* value)
   1447 {
   1448     if(value != NULL) {
   1449         memcpy(gpsProcessingMethod, ExifAsciiPrefix, EXIF_ASCII_PREFIX_SIZE);
   1450         count = EXIF_ASCII_PREFIX_SIZE;
   1451         strncpy(gpsProcessingMethod + EXIF_ASCII_PREFIX_SIZE, value, strlen(value));
   1452         count += strlen(value);
   1453         gpsProcessingMethod[count++] = '\0'; // increase 1 for the last NULL char
   1454         return NO_ERROR;
   1455     } else {
   1456         return BAD_VALUE;
   1457     }
   1458 }
   1459 
   1460 /*===========================================================================
   1461  * FUNCTION   : getExifLatitude
   1462  *
   1463  * DESCRIPTION: get exif latitude
   1464  *
   1465  * PARAMETERS :
   1466  *   @latitude : ptr to rational struct to store latitude info
   1467  *   @ladRef   : charater to indicate latitude reference
   1468  *
   1469  * RETURN     : int32_t type of status
   1470  *              NO_ERROR  -- success
   1471  *              none-zero failure code
   1472  *==========================================================================*/
   1473 int32_t getExifLatitude(rat_t *latitude,
   1474                                            char *latRef, double value)
   1475 {
   1476     char str[30];
   1477     snprintf(str, sizeof(str), "%f", value);
   1478     if(str != NULL) {
   1479         parseGPSCoordinate(str, latitude);
   1480 
   1481         //set Latitude Ref
   1482         float latitudeValue = strtof(str, 0);
   1483         if(latitudeValue < 0.0f) {
   1484             latRef[0] = 'S';
   1485         } else {
   1486             latRef[0] = 'N';
   1487         }
   1488         latRef[1] = '\0';
   1489         return NO_ERROR;
   1490     }else{
   1491         return BAD_VALUE;
   1492     }
   1493 }
   1494 
   1495 /*===========================================================================
   1496  * FUNCTION   : getExifLongitude
   1497  *
   1498  * DESCRIPTION: get exif longitude
   1499  *
   1500  * PARAMETERS :
   1501  *   @longitude : ptr to rational struct to store longitude info
   1502  *   @lonRef    : charater to indicate longitude reference
   1503  *
   1504  * RETURN     : int32_t type of status
   1505  *              NO_ERROR  -- success
   1506  *              none-zero failure code
   1507  *==========================================================================*/
   1508 int32_t getExifLongitude(rat_t *longitude,
   1509                                             char *lonRef, double value)
   1510 {
   1511     char str[30];
   1512     snprintf(str, sizeof(str), "%f", value);
   1513     if(str != NULL) {
   1514         parseGPSCoordinate(str, longitude);
   1515 
   1516         //set Longitude Ref
   1517         float longitudeValue = strtof(str, 0);
   1518         if(longitudeValue < 0.0f) {
   1519             lonRef[0] = 'W';
   1520         } else {
   1521             lonRef[0] = 'E';
   1522         }
   1523         lonRef[1] = '\0';
   1524         return NO_ERROR;
   1525     }else{
   1526         return BAD_VALUE;
   1527     }
   1528 }
   1529 
   1530 /*===========================================================================
   1531  * FUNCTION   : getExifAltitude
   1532  *
   1533  * DESCRIPTION: get exif altitude
   1534  *
   1535  * PARAMETERS :
   1536  *   @altitude : ptr to rational struct to store altitude info
   1537  *   @altRef   : charater to indicate altitude reference
   1538  *
   1539  * RETURN     : int32_t type of status
   1540  *              NO_ERROR  -- success
   1541  *              none-zero failure code
   1542  *==========================================================================*/
   1543 int32_t getExifAltitude(rat_t *altitude,
   1544                                            char *altRef, double value)
   1545 {
   1546     char str[30];
   1547     snprintf(str, sizeof(str), "%f", value);
   1548     if(str != NULL) {
   1549         double value = atof(str);
   1550         *altRef = 0;
   1551         if(value < 0){
   1552             *altRef = 1;
   1553             value = -value;
   1554         }
   1555         return getRational(altitude, value*1000, 1000);
   1556     }else{
   1557         return BAD_VALUE;
   1558     }
   1559 }
   1560 
   1561 /*===========================================================================
   1562  * FUNCTION   : getExifGpsDateTimeStamp
   1563  *
   1564  * DESCRIPTION: get exif GPS date time stamp
   1565  *
   1566  * PARAMETERS :
   1567  *   @gpsDateStamp : GPS date time stamp string
   1568  *   @bufLen       : length of the string
   1569  *   @gpsTimeStamp : ptr to rational struct to store time stamp info
   1570  *
   1571  * RETURN     : int32_t type of status
   1572  *              NO_ERROR  -- success
   1573  *              none-zero failure code
   1574  *==========================================================================*/
   1575 int32_t getExifGpsDateTimeStamp(char *gpsDateStamp,
   1576                                            uint32_t bufLen,
   1577                                            rat_t *gpsTimeStamp, int64_t value)
   1578 {
   1579     char str[30];
   1580     snprintf(str, sizeof(str), "%lld", value);
   1581     if(str != NULL) {
   1582         time_t unixTime = (time_t)atol(str);
   1583         struct tm *UTCTimestamp = gmtime(&unixTime);
   1584 
   1585         strftime(gpsDateStamp, bufLen, "%Y:%m:%d", UTCTimestamp);
   1586 
   1587         getRational(&gpsTimeStamp[0], UTCTimestamp->tm_hour, 1);
   1588         getRational(&gpsTimeStamp[1], UTCTimestamp->tm_min, 1);
   1589         getRational(&gpsTimeStamp[2], UTCTimestamp->tm_sec, 1);
   1590 
   1591         return NO_ERROR;
   1592     } else {
   1593         return BAD_VALUE;
   1594     }
   1595 }
   1596 
   1597 int32_t getExifExposureValue(srat_t* exposure_val, int32_t exposure_comp,
   1598                              cam_rational_type_t step)
   1599 {
   1600     exposure_val->num = exposure_comp * step.numerator;
   1601     exposure_val->denom = step.denominator;
   1602     return 0;
   1603 }
   1604 /*===========================================================================
   1605  * FUNCTION   : getExifData
   1606  *
   1607  * DESCRIPTION: get exif data to be passed into jpeg encoding
   1608  *
   1609  * PARAMETERS : none
   1610  *
   1611  * RETURN     : exif data from user setting and GPS
   1612  *==========================================================================*/
   1613 QCamera3Exif *QCamera3PicChannel::getExifData()
   1614 {
   1615     QCamera3Exif *exif = new QCamera3Exif();
   1616     if (exif == NULL) {
   1617         ALOGE("%s: No memory for QCamera3Exif", __func__);
   1618         return NULL;
   1619     }
   1620 
   1621     int32_t rc = NO_ERROR;
   1622     uint32_t count = 0;
   1623 
   1624     // add exif entries
   1625     char dateTime[20];
   1626     memset(dateTime, 0, sizeof(dateTime));
   1627     count = 20;
   1628     rc = getExifDateTime(dateTime, count);
   1629     if(rc == NO_ERROR) {
   1630         exif->addEntry(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL,
   1631                        EXIF_ASCII,
   1632                        count,
   1633                        (void *)dateTime);
   1634     } else {
   1635         ALOGE("%s: getExifDateTime failed", __func__);
   1636     }
   1637 
   1638     rat_t focalLength;
   1639     rc = getExifFocalLength(&focalLength, mJpegSettings->lens_focal_length);
   1640     if (rc == NO_ERROR) {
   1641         exif->addEntry(EXIFTAGID_FOCAL_LENGTH,
   1642                        EXIF_RATIONAL,
   1643                        1,
   1644                        (void *)&(focalLength));
   1645     } else {
   1646         ALOGE("%s: getExifFocalLength failed", __func__);
   1647     }
   1648 
   1649     uint16_t isoSpeed = (uint16_t)mJpegSettings->sensor_sensitivity;
   1650     exif->addEntry(EXIFTAGID_ISO_SPEED_RATING,
   1651                    EXIF_SHORT,
   1652                    1,
   1653                    (void *)&(isoSpeed));
   1654 
   1655     rat_t sensorExpTime ;
   1656     rc = getExifExpTimeInfo(&sensorExpTime, (int64_t)mJpegSettings->sensor_exposure_time);
   1657     if (rc == NO_ERROR){
   1658         exif->addEntry(EXIFTAGID_EXPOSURE_TIME,
   1659                        EXIF_RATIONAL,
   1660                        1,
   1661                        (void *)&(sensorExpTime));
   1662     } else {
   1663         ALOGE("now addEntry for EXIFTAGID_EXPOSURE_TIME is %d", sensorExpTime);
   1664     }
   1665     if (strlen(mJpegSettings->gps_processing_method) > 0) {
   1666         char gpsProcessingMethod[EXIF_ASCII_PREFIX_SIZE + GPS_PROCESSING_METHOD_SIZE];
   1667         count = 0;
   1668         rc = getExifGpsProcessingMethod(gpsProcessingMethod, count, mJpegSettings->gps_processing_method);
   1669         if(rc == NO_ERROR) {
   1670             exif->addEntry(EXIFTAGID_GPS_PROCESSINGMETHOD,
   1671                            EXIF_ASCII,
   1672                            count,
   1673                            (void *)gpsProcessingMethod);
   1674         } else {
   1675             ALOGE("%s: getExifGpsProcessingMethod failed", __func__);
   1676         }
   1677     }
   1678 
   1679     if (mJpegSettings->gps_coordinates[0]) {
   1680         rat_t latitude[3];
   1681         char latRef[2];
   1682         rc = getExifLatitude(latitude, latRef, *(mJpegSettings->gps_coordinates[0]));
   1683         if(rc == NO_ERROR) {
   1684             exif->addEntry(EXIFTAGID_GPS_LATITUDE,
   1685                            EXIF_RATIONAL,
   1686                            3,
   1687                            (void *)latitude);
   1688             exif->addEntry(EXIFTAGID_GPS_LATITUDE_REF,
   1689                            EXIF_ASCII,
   1690                            2,
   1691                            (void *)latRef);
   1692         } else {
   1693             ALOGE("%s: getExifLatitude failed", __func__);
   1694         }
   1695     }
   1696 
   1697     if (mJpegSettings->gps_coordinates[1]) {
   1698         rat_t longitude[3];
   1699         char lonRef[2];
   1700         rc = getExifLongitude(longitude, lonRef, *(mJpegSettings->gps_coordinates[1]));
   1701         if(rc == NO_ERROR) {
   1702             exif->addEntry(EXIFTAGID_GPS_LONGITUDE,
   1703                            EXIF_RATIONAL,
   1704                            3,
   1705                            (void *)longitude);
   1706 
   1707             exif->addEntry(EXIFTAGID_GPS_LONGITUDE_REF,
   1708                            EXIF_ASCII,
   1709                            2,
   1710                            (void *)lonRef);
   1711         } else {
   1712             ALOGE("%s: getExifLongitude failed", __func__);
   1713         }
   1714     }
   1715 
   1716     if (mJpegSettings->gps_coordinates[2]) {
   1717         rat_t altitude;
   1718         char altRef;
   1719         rc = getExifAltitude(&altitude, &altRef, *(mJpegSettings->gps_coordinates[2]));
   1720         if(rc == NO_ERROR) {
   1721             exif->addEntry(EXIFTAGID_GPS_ALTITUDE,
   1722                            EXIF_RATIONAL,
   1723                            1,
   1724                            (void *)&(altitude));
   1725 
   1726             exif->addEntry(EXIFTAGID_GPS_ALTITUDE_REF,
   1727                            EXIF_BYTE,
   1728                            1,
   1729                            (void *)&altRef);
   1730         } else {
   1731             ALOGE("%s: getExifAltitude failed", __func__);
   1732         }
   1733     }
   1734 
   1735     if (mJpegSettings->gps_timestamp) {
   1736         char gpsDateStamp[20];
   1737         rat_t gpsTimeStamp[3];
   1738         rc = getExifGpsDateTimeStamp(gpsDateStamp, 20, gpsTimeStamp, *(mJpegSettings->gps_timestamp));
   1739         if(rc == NO_ERROR) {
   1740             exif->addEntry(EXIFTAGID_GPS_DATESTAMP,
   1741                            EXIF_ASCII,
   1742                            strlen(gpsDateStamp) + 1,
   1743                            (void *)gpsDateStamp);
   1744 
   1745             exif->addEntry(EXIFTAGID_GPS_TIMESTAMP,
   1746                            EXIF_RATIONAL,
   1747                            3,
   1748                            (void *)gpsTimeStamp);
   1749         } else {
   1750             ALOGE("%s: getExifGpsDataTimeStamp failed", __func__);
   1751         }
   1752     }
   1753 
   1754     srat_t exposure_val;
   1755     rc = getExifExposureValue(&exposure_val, mJpegSettings->exposure_compensation,
   1756                               mJpegSettings->exposure_comp_step);
   1757     if(rc == NO_ERROR) {
   1758         exif->addEntry(EXIFTAGID_EXPOSURE_BIAS_VALUE,
   1759                        EXIF_SRATIONAL,
   1760                        1,
   1761                        (void *)(&exposure_val));
   1762     } else {
   1763         ALOGE("%s: getExifExposureValue failed ", __func__);
   1764     }
   1765 
   1766     char value[PROPERTY_VALUE_MAX];
   1767     if (property_get("ro.product.manufacturer", value, "QCOM-AA") > 0) {
   1768         exif->addEntry(EXIFTAGID_MAKE,
   1769                        EXIF_ASCII,
   1770                        strlen(value) + 1,
   1771                        (void *)value);
   1772     } else {
   1773         ALOGE("%s: getExifMaker failed", __func__);
   1774     }
   1775 
   1776     if (property_get("ro.product.model", value, "QCAM-AA") > 0) {
   1777         exif->addEntry(EXIFTAGID_MODEL,
   1778                        EXIF_ASCII,
   1779                        strlen(value) + 1,
   1780                        (void *)value);
   1781     } else {
   1782         ALOGE("%s: getExifModel failed", __func__);
   1783     }
   1784 
   1785     return exif;
   1786 }
   1787 
   1788 int QCamera3PicChannel::kMaxBuffers = 2;
   1789 
   1790 /*===========================================================================
   1791  * FUNCTION   : QCamera3ReprocessChannel
   1792  *
   1793  * DESCRIPTION: constructor of QCamera3ReprocessChannel
   1794  *
   1795  * PARAMETERS :
   1796  *   @cam_handle : camera handle
   1797  *   @cam_ops    : ptr to camera ops table
   1798  *   @pp_mask    : post-proccess feature mask
   1799  *
   1800  * RETURN     : none
   1801  *==========================================================================*/
   1802 QCamera3ReprocessChannel::QCamera3ReprocessChannel(uint32_t cam_handle,
   1803                                                  mm_camera_ops_t *cam_ops,
   1804                                                  channel_cb_routine cb_routine,
   1805                                                  cam_padding_info_t *paddingInfo,
   1806                                                  void *userData, void *ch_hdl) :
   1807     QCamera3Channel(cam_handle, cam_ops, cb_routine, paddingInfo, userData),
   1808     picChHandle(ch_hdl),
   1809     m_pSrcChannel(NULL),
   1810     m_pMetaChannel(NULL),
   1811     m_metaFrame(NULL),
   1812     mMemory(NULL)
   1813 {
   1814     memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles));
   1815 }
   1816 
   1817 
   1818 /*===========================================================================
   1819  * FUNCTION   : QCamera3ReprocessChannel
   1820  *
   1821  * DESCRIPTION: constructor of QCamera3ReprocessChannel
   1822  *
   1823  * PARAMETERS :
   1824  *   @cam_handle : camera handle
   1825  *   @cam_ops    : ptr to camera ops table
   1826  *   @pp_mask    : post-proccess feature mask
   1827  *
   1828  * RETURN     : none
   1829  *==========================================================================*/
   1830 int32_t QCamera3ReprocessChannel::initialize()
   1831 {
   1832     int32_t rc = NO_ERROR;
   1833     mm_camera_channel_attr_t attr;
   1834 
   1835     memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
   1836     attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS;
   1837     attr.max_unmatched_frames = 1;
   1838 
   1839     rc = init(&attr, NULL);
   1840     if (rc < 0) {
   1841         ALOGE("%s: init failed", __func__);
   1842     }
   1843     return rc;
   1844 }
   1845 
   1846 
   1847 /*===========================================================================
   1848  * FUNCTION   : QCamera3ReprocessChannel
   1849  *
   1850  * DESCRIPTION: constructor of QCamera3ReprocessChannel
   1851  *
   1852  * PARAMETERS :
   1853  *   @cam_handle : camera handle
   1854  *   @cam_ops    : ptr to camera ops table
   1855  *   @pp_mask    : post-proccess feature mask
   1856  *
   1857  * RETURN     : none
   1858  *==========================================================================*/
   1859 void QCamera3ReprocessChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
   1860                                   QCamera3Stream *stream)
   1861 {
   1862     //Got the pproc data callback. Now send to jpeg encoding
   1863     uint8_t frameIndex;
   1864     mm_camera_super_buf_t* frame = NULL;
   1865     QCamera3PicChannel *obj = (QCamera3PicChannel *)picChHandle;
   1866 
   1867     if(!super_frame) {
   1868          ALOGE("%s: Invalid Super buffer",__func__);
   1869          return;
   1870     }
   1871 
   1872     if(super_frame->num_bufs != 1) {
   1873          ALOGE("%s: Multiple streams are not supported",__func__);
   1874          return;
   1875     }
   1876     if(super_frame->bufs[0] == NULL ) {
   1877          ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
   1878                   __func__);
   1879          return;
   1880     }
   1881 
   1882     frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
   1883     frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
   1884     if (frame == NULL) {
   1885        ALOGE("%s: Error allocating memory to save received_frame structure.",
   1886                                                                     __func__);
   1887        if(stream) {
   1888            stream->bufDone(frameIndex);
   1889        }
   1890        return;
   1891     }
   1892     *frame = *super_frame;
   1893     //queue back the metadata buffer
   1894     if (m_metaFrame != NULL) {
   1895        ((QCamera3MetadataChannel*)m_pMetaChannel)->bufDone(m_metaFrame);
   1896        free(m_metaFrame);
   1897        m_metaFrame = NULL;
   1898     } else {
   1899        ALOGE("%s: Meta frame was NULL", __func__);
   1900     }
   1901     obj->m_postprocessor.processPPData(frame);
   1902     return;
   1903 }
   1904 
   1905 /*===========================================================================
   1906  * FUNCTION   : QCamera3ReprocessChannel
   1907  *
   1908  * DESCRIPTION: default constructor of QCamera3ReprocessChannel
   1909  *
   1910  * PARAMETERS : none
   1911  *
   1912  * RETURN     : none
   1913  *==========================================================================*/
   1914 QCamera3ReprocessChannel::QCamera3ReprocessChannel() :
   1915     m_pSrcChannel(NULL),
   1916     m_pMetaChannel(NULL),
   1917     m_metaFrame(NULL)
   1918 {
   1919 }
   1920 
   1921 /*===========================================================================
   1922  * FUNCTION   : QCamera3ReprocessChannel
   1923  *
   1924  * DESCRIPTION: register the buffers of the reprocess channel
   1925  *
   1926  * PARAMETERS : none
   1927  *
   1928  * RETURN     : none
   1929  *==========================================================================*/
   1930 int32_t QCamera3ReprocessChannel::registerBuffers(uint32_t num_buffers, buffer_handle_t **buffers)
   1931 {
   1932    return 0;
   1933 }
   1934 
   1935 /*===========================================================================
   1936  * FUNCTION   : getStreamBufs
   1937  *
   1938  * DESCRIPTION: register the buffers of the reprocess channel
   1939  *
   1940  * PARAMETERS : none
   1941  *
   1942  * RETURN     : QCamera3Memory *
   1943  *==========================================================================*/
   1944 QCamera3Memory* QCamera3ReprocessChannel::getStreamBufs(uint32_t len)
   1945 {
   1946    int rc = 0;
   1947 
   1948     mMemory = new QCamera3HeapMemory();
   1949     if (!mMemory) {
   1950         ALOGE("%s: unable to create reproc memory", __func__);
   1951         return NULL;
   1952     }
   1953 
   1954     //Queue YUV buffers in the beginning mQueueAll = true
   1955     rc = mMemory->allocate(2, len, true);
   1956     if (rc < 0) {
   1957         ALOGE("%s: unable to allocate reproc memory", __func__);
   1958         delete mMemory;
   1959         mMemory = NULL;
   1960         return NULL;
   1961     }
   1962     return mMemory;
   1963 }
   1964 
   1965 /*===========================================================================
   1966  * FUNCTION   : getStreamBufs
   1967  *
   1968  * DESCRIPTION: register the buffers of the reprocess channel
   1969  *
   1970  * PARAMETERS : none
   1971  *
   1972  * RETURN     :
   1973  *==========================================================================*/
   1974 void QCamera3ReprocessChannel::putStreamBufs()
   1975 {
   1976     mMemory->deallocate();
   1977     delete mMemory;
   1978     mMemory = NULL;
   1979 }
   1980 
   1981 /*===========================================================================
   1982  * FUNCTION   : ~QCamera3ReprocessChannel
   1983  *
   1984  * DESCRIPTION: destructor of QCamera3ReprocessChannel
   1985  *
   1986  * PARAMETERS : none
   1987  *
   1988  * RETURN     : none
   1989  *==========================================================================*/
   1990 QCamera3ReprocessChannel::~QCamera3ReprocessChannel()
   1991 {
   1992 }
   1993 
   1994 /*===========================================================================
   1995  * FUNCTION   : getStreamBySourceHandle
   1996  *
   1997  * DESCRIPTION: find reprocess stream by its source stream handle
   1998  *
   1999  * PARAMETERS :
   2000  *   @srcHandle : source stream handle
   2001  *
   2002  * RETURN     : ptr to reprocess stream if found. NULL if not found
   2003  *==========================================================================*/
   2004 QCamera3Stream * QCamera3ReprocessChannel::getStreamBySourceHandle(uint32_t srcHandle)
   2005 {
   2006     QCamera3Stream *pStream = NULL;
   2007 
   2008     for (int i = 0; i < m_numStreams; i++) {
   2009         if (mSrcStreamHandles[i] == srcHandle) {
   2010             pStream = mStreams[i];
   2011             break;
   2012         }
   2013     }
   2014     return pStream;
   2015 }
   2016 
   2017 /*===========================================================================
   2018  * FUNCTION   : doReprocess
   2019  *
   2020  * DESCRIPTION: request to do a reprocess on the frame
   2021  *
   2022  * PARAMETERS :
   2023  *   @frame   : frame to be performed a reprocess
   2024  *
   2025  * RETURN     : int32_t type of status
   2026  *              NO_ERROR  -- success
   2027  *              none-zero failure code
   2028  *==========================================================================*/
   2029 int32_t QCamera3ReprocessChannel::doReprocess(mm_camera_super_buf_t *frame,
   2030                                               mm_camera_super_buf_t *meta_frame)
   2031 {
   2032     int32_t rc = 0;
   2033     if (m_numStreams < 1) {
   2034         ALOGE("%s: No reprocess stream is created", __func__);
   2035         return -1;
   2036     }
   2037     if (m_pSrcChannel == NULL) {
   2038         ALOGE("%s: No source channel for reprocess", __func__);
   2039         return -1;
   2040     }
   2041     m_metaFrame = meta_frame;
   2042     for (int i = 0; i < frame->num_bufs; i++) {
   2043         QCamera3Stream *pStream = getStreamBySourceHandle(frame->bufs[i]->stream_id);
   2044         if (pStream != NULL) {
   2045             cam_stream_parm_buffer_t param;
   2046             memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
   2047             param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
   2048             param.reprocess.buf_index = frame->bufs[i]->buf_idx;
   2049             param.reprocess.frame_idx = frame->bufs[i]->frame_idx;
   2050             if (meta_frame != NULL) {
   2051                param.reprocess.meta_present = 1;
   2052                param.reprocess.meta_stream_handle = m_pMetaChannel->mStreams[0]->getMyServerID();
   2053                param.reprocess.meta_buf_index = meta_frame->bufs[0]->buf_idx;
   2054             }
   2055             rc = pStream->setParameter(param);
   2056             if (rc != NO_ERROR) {
   2057                 ALOGE("%s: stream setParameter for reprocess failed", __func__);
   2058                 break;
   2059             }
   2060         }
   2061     }
   2062     return rc;
   2063 }
   2064 
   2065 /*===========================================================================
   2066  * FUNCTION   : doReprocess
   2067  *
   2068  * DESCRIPTION: request to do a reprocess on the frame
   2069  *
   2070  * PARAMETERS :
   2071  *   @buf_fd     : fd to the input buffer that needs reprocess
   2072  *   @buf_lenght : length of the input buffer
   2073  *   @ret_val    : result of reprocess.
   2074  *                 Example: Could be faceID in case of register face image.
   2075  *
   2076  * RETURN     : int32_t type of status
   2077  *              NO_ERROR  -- success
   2078  *              none-zero failure code
   2079  *==========================================================================*/
   2080 int32_t QCamera3ReprocessChannel::doReprocess(int buf_fd,
   2081                                               uint32_t buf_length,
   2082                                               int32_t &ret_val,
   2083                                               mm_camera_super_buf_t *meta_frame)
   2084 {
   2085     int32_t rc = 0;
   2086     if (m_numStreams < 1) {
   2087         ALOGE("%s: No reprocess stream is created", __func__);
   2088         return -1;
   2089     }
   2090     if (meta_frame == NULL) {
   2091         ALOGE("%s: Did not get corresponding metadata in time", __func__);
   2092         return -1;
   2093     }
   2094 
   2095     uint32_t buf_idx = 0;
   2096     for (int i = 0; i < m_numStreams; i++) {
   2097         rc = mStreams[i]->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
   2098                                  buf_idx, -1,
   2099                                  buf_fd, buf_length);
   2100 
   2101         if (rc == NO_ERROR) {
   2102             cam_stream_parm_buffer_t param;
   2103             memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
   2104             param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
   2105             param.reprocess.buf_index = buf_idx;
   2106             param.reprocess.meta_present = 1;
   2107             param.reprocess.meta_stream_handle = m_pMetaChannel->mStreams[0]->getMyServerID();
   2108             param.reprocess.meta_buf_index = meta_frame->bufs[0]->buf_idx;
   2109             rc = mStreams[i]->setParameter(param);
   2110             if (rc == NO_ERROR) {
   2111                 ret_val = param.reprocess.ret_val;
   2112             }
   2113             mStreams[i]->unmapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
   2114                                   buf_idx, -1);
   2115         }
   2116     }
   2117     return rc;
   2118 }
   2119 
   2120 /*===========================================================================
   2121  * FUNCTION   : addReprocStreamsFromSource
   2122  *
   2123  * DESCRIPTION: add reprocess streams from input source channel
   2124  *
   2125  * PARAMETERS :
   2126  *   @config         : pp feature configuration
   2127  *   @pSrcChannel    : ptr to input source channel that needs reprocess
   2128  *   @pMetaChannel   : ptr to metadata channel to get corresp. metadata
   2129  *
   2130  * RETURN     : int32_t type of status
   2131  *              NO_ERROR  -- success
   2132  *              none-zero failure code
   2133  *==========================================================================*/
   2134 int32_t QCamera3ReprocessChannel::addReprocStreamsFromSource(cam_pp_feature_config_t &config,
   2135                                                              QCamera3Channel *pSrcChannel,
   2136                                                              QCamera3Channel *pMetaChannel)
   2137 {
   2138     int32_t rc = 0;
   2139     QCamera3Stream *pSrcStream = pSrcChannel->getStreamByIndex(0);
   2140     if (pSrcStream == NULL) {
   2141        ALOGE("%s: source channel doesn't have a stream", __func__);
   2142        return BAD_VALUE;
   2143     }
   2144     cam_stream_reproc_config_t reprocess_config;
   2145     cam_dimension_t streamDim;
   2146     cam_stream_type_t streamType;
   2147     cam_format_t streamFormat;
   2148     cam_frame_len_offset_t frameOffset;
   2149     int num_buffers = 2;
   2150 
   2151     streamType = CAM_STREAM_TYPE_OFFLINE_PROC;
   2152     pSrcStream->getFormat(streamFormat);
   2153     pSrcStream->getFrameDimension(streamDim);
   2154     pSrcStream->getFrameOffset(frameOffset);
   2155 
   2156     reprocess_config.pp_type = CAM_ONLINE_REPROCESS_TYPE;
   2157     reprocess_config.online.input_stream_id = pSrcStream->getMyServerID();
   2158     reprocess_config.online.input_stream_type = pSrcStream->getMyType();
   2159     reprocess_config.pp_feature_config = config;
   2160 
   2161     mSrcStreamHandles[m_numStreams] = pSrcStream->getMyHandle();
   2162 
   2163     if (reprocess_config.pp_feature_config.feature_mask & CAM_QCOM_FEATURE_ROTATION) {
   2164         if (reprocess_config.pp_feature_config.rotation == ROTATE_90 ||
   2165             reprocess_config.pp_feature_config.rotation == ROTATE_270) {
   2166             // rotated by 90 or 270, need to switch width and height
   2167             int32_t temp = streamDim.height;
   2168             streamDim.height = streamDim.width;
   2169             streamDim.width = temp;
   2170         }
   2171     }
   2172 
   2173     QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
   2174                                                m_handle,
   2175                                                m_camOps,
   2176                                                mPaddingInfo,
   2177                                                (QCamera3Channel*)this);
   2178     if (pStream == NULL) {
   2179         ALOGE("%s: No mem for Stream", __func__);
   2180         return NO_MEMORY;
   2181     }
   2182 
   2183     rc = pStream->init(streamType, streamFormat, streamDim, &reprocess_config,
   2184                        num_buffers,QCamera3Channel::streamCbRoutine, this);
   2185 
   2186 
   2187     if (rc == 0) {
   2188         mStreams[m_numStreams] = pStream;
   2189         m_numStreams++;
   2190     } else {
   2191         ALOGE("%s: failed to create reprocess stream", __func__);
   2192         delete pStream;
   2193     }
   2194 
   2195     if (rc == NO_ERROR) {
   2196         m_pSrcChannel = pSrcChannel;
   2197         m_pMetaChannel = pMetaChannel;
   2198     }
   2199     if(m_camOps->request_super_buf(m_camHandle,m_handle,1) < 0) {
   2200         ALOGE("%s: Request for super buffer failed",__func__);
   2201     }
   2202     return rc;
   2203 }
   2204 
   2205 
   2206 }; // namespace qcamera
   2207