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