Home | History | Annotate | Download | only in HAL3
      1 /* Copyright (c) 2012-2014, 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 #include <fcntl.h>
     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 
     53 #define EXIF_ASCII_PREFIX_SIZE           8   //(sizeof(ExifAsciiPrefix))
     54 #define FOCAL_LENGTH_DECIMAL_PRECISION   1000
     55 
     56 /*===========================================================================
     57  * FUNCTION   : QCamera3Channel
     58  *
     59  * DESCRIPTION: constrcutor of QCamera3Channel
     60  *
     61  * PARAMETERS :
     62  *   @cam_handle : camera handle
     63  *   @cam_ops    : ptr to camera ops table
     64  *
     65  * RETURN     : none
     66  *==========================================================================*/
     67 QCamera3Channel::QCamera3Channel(uint32_t cam_handle,
     68                                mm_camera_ops_t *cam_ops,
     69                                channel_cb_routine cb_routine,
     70                                cam_padding_info_t *paddingInfo,
     71                                void *userData)
     72 {
     73     m_camHandle = cam_handle;
     74     m_camOps = cam_ops;
     75     m_bIsActive = false;
     76 
     77     m_handle = 0;
     78     m_numStreams = 0;
     79     memset(mStreams, 0, sizeof(mStreams));
     80     mUserData = userData;
     81 
     82     mStreamInfoBuf = NULL;
     83     mChannelCB = cb_routine;
     84     mPaddingInfo = paddingInfo;
     85 }
     86 
     87 /*===========================================================================
     88  * FUNCTION   : QCamera3Channel
     89  *
     90  * DESCRIPTION: default constrcutor of QCamera3Channel
     91  *
     92  * PARAMETERS : none
     93  *
     94  * RETURN     : none
     95  *==========================================================================*/
     96 QCamera3Channel::QCamera3Channel()
     97 {
     98     m_camHandle = 0;
     99     m_camOps = NULL;
    100     m_bIsActive = false;
    101 
    102     m_handle = 0;
    103     m_numStreams = 0;
    104     memset(mStreams, 0, sizeof(mStreams));
    105     mUserData = NULL;
    106 
    107     mStreamInfoBuf = NULL;
    108     mChannelCB = NULL;
    109     mPaddingInfo = NULL;
    110 }
    111 
    112 /*===========================================================================
    113  * FUNCTION   : ~QCamera3Channel
    114  *
    115  * DESCRIPTION: destructor of QCamera3Channel
    116  *
    117  * PARAMETERS : none
    118  *
    119  * RETURN     : none
    120  *==========================================================================*/
    121 QCamera3Channel::~QCamera3Channel()
    122 {
    123     if (m_bIsActive)
    124         stop();
    125 
    126     for (int i = 0; i < m_numStreams; i++) {
    127         if (mStreams[i] != NULL) {
    128             delete mStreams[i];
    129             mStreams[i] = 0;
    130         }
    131     }
    132     if (m_handle) {
    133         m_camOps->delete_channel(m_camHandle, m_handle);
    134         ALOGE("%s: deleting channel %d", __func__, m_handle);
    135         m_handle = 0;
    136     }
    137     m_numStreams = 0;
    138 }
    139 
    140 /*===========================================================================
    141  * FUNCTION   : init
    142  *
    143  * DESCRIPTION: initialization of channel
    144  *
    145  * PARAMETERS :
    146  *   @attr    : channel bundle attribute setting
    147  *   @dataCB  : data notify callback
    148  *   @userData: user data ptr
    149  *
    150  * RETURN     : int32_t type of status
    151  *              NO_ERROR  -- success
    152  *              none-zero failure code
    153  *==========================================================================*/
    154 int32_t QCamera3Channel::init(mm_camera_channel_attr_t *attr,
    155                              mm_camera_buf_notify_t dataCB)
    156 {
    157     m_handle = m_camOps->add_channel(m_camHandle,
    158                                       attr,
    159                                       dataCB,
    160                                       this);
    161     if (m_handle == 0) {
    162         ALOGE("%s: Add channel failed", __func__);
    163         return UNKNOWN_ERROR;
    164     }
    165     return NO_ERROR;
    166 }
    167 
    168 /*===========================================================================
    169  * FUNCTION   : addStream
    170  *
    171  * DESCRIPTION: add a stream into channel
    172  *
    173  * PARAMETERS :
    174  *   @allocator      : stream related buffer allocator
    175  *   @streamInfoBuf  : ptr to buf that constains stream info
    176  *   @minStreamBufNum: number of stream buffers needed
    177  *   @paddingInfo    : padding information
    178  *   @stream_cb      : stream data notify callback
    179  *   @userdata       : user data ptr
    180  *
    181  * RETURN     : int32_t type of status
    182  *              NO_ERROR  -- success
    183  *              none-zero failure code
    184  *==========================================================================*/
    185 int32_t QCamera3Channel::addStream(cam_stream_type_t streamType,
    186                                   cam_format_t streamFormat,
    187                                   cam_dimension_t streamDim,
    188                                   uint8_t minStreamBufNum)
    189 {
    190     int32_t rc = NO_ERROR;
    191 
    192     if (m_numStreams >= 1) {
    193         ALOGE("%s: Only one stream per channel supported in v3 Hal", __func__);
    194         return BAD_VALUE;
    195     }
    196 
    197     if (m_numStreams >= MAX_STREAM_NUM_IN_BUNDLE) {
    198         ALOGE("%s: stream number (%d) exceeds max limit (%d)",
    199               __func__, m_numStreams, MAX_STREAM_NUM_IN_BUNDLE);
    200         return BAD_VALUE;
    201     }
    202     QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
    203                                                m_handle,
    204                                                m_camOps,
    205                                                mPaddingInfo,
    206                                                this);
    207     if (pStream == NULL) {
    208         ALOGE("%s: No mem for Stream", __func__);
    209         return NO_MEMORY;
    210     }
    211 
    212     rc = pStream->init(streamType, streamFormat, streamDim, NULL, minStreamBufNum,
    213                                                     streamCbRoutine, this);
    214     if (rc == 0) {
    215         mStreams[m_numStreams] = pStream;
    216         m_numStreams++;
    217     } else {
    218         delete pStream;
    219     }
    220     return rc;
    221 }
    222 
    223 /*===========================================================================
    224  * FUNCTION   : start
    225  *
    226  * DESCRIPTION: start channel, which will start all streams belong to this channel
    227  *
    228  * PARAMETERS :
    229  *
    230  * RETURN     : int32_t type of status
    231  *              NO_ERROR  -- success
    232  *              none-zero failure code
    233  *==========================================================================*/
    234 int32_t QCamera3Channel::start()
    235 {
    236     int32_t rc = NO_ERROR;
    237 
    238     if (m_numStreams > 1) {
    239         ALOGE("%s: bundle not supported", __func__);
    240     } else if (m_numStreams == 0) {
    241         return NO_INIT;
    242     }
    243 
    244     if(m_bIsActive) {
    245         ALOGD("%s: Attempt to start active channel", __func__);
    246         return rc;
    247     }
    248 
    249     for (int i = 0; i < m_numStreams; i++) {
    250         if (mStreams[i] != NULL) {
    251             mStreams[i]->start();
    252         }
    253     }
    254     rc = m_camOps->start_channel(m_camHandle, m_handle);
    255 
    256     if (rc != NO_ERROR) {
    257         for (int i = 0; i < m_numStreams; i++) {
    258             if (mStreams[i] != NULL) {
    259                 mStreams[i]->stop();
    260             }
    261         }
    262     } else {
    263         m_bIsActive = true;
    264     }
    265 
    266     return rc;
    267 }
    268 
    269 /*===========================================================================
    270  * FUNCTION   : stop
    271  *
    272  * DESCRIPTION: stop a channel, which will stop all streams belong to this channel
    273  *
    274  * PARAMETERS : none
    275  *
    276  * RETURN     : int32_t type of status
    277  *              NO_ERROR  -- success
    278  *              none-zero failure code
    279  *==========================================================================*/
    280 int32_t QCamera3Channel::stop()
    281 {
    282     int32_t rc = NO_ERROR;
    283     if(!m_bIsActive) {
    284         ALOGE("%s: Attempt to stop inactive channel",__func__);
    285         return rc;
    286     }
    287 
    288     for (int i = 0; i < m_numStreams; i++) {
    289         if (mStreams[i] != NULL) {
    290             mStreams[i]->stop();
    291         }
    292     }
    293 
    294     rc = m_camOps->stop_channel(m_camHandle, m_handle);
    295 
    296     m_bIsActive = false;
    297     return rc;
    298 }
    299 
    300 /*===========================================================================
    301  * FUNCTION   : bufDone
    302  *
    303  * DESCRIPTION: return a stream buf back to kernel
    304  *
    305  * PARAMETERS :
    306  *   @recvd_frame  : stream buf frame to be returned
    307  *
    308  * RETURN     : int32_t type of status
    309  *              NO_ERROR  -- success
    310  *              none-zero failure code
    311  *==========================================================================*/
    312 int32_t QCamera3Channel::bufDone(mm_camera_super_buf_t *recvd_frame)
    313 {
    314     int32_t rc = NO_ERROR;
    315     for (int i = 0; i < recvd_frame->num_bufs; i++) {
    316          if (recvd_frame->bufs[i] != NULL) {
    317              for (int j = 0; j < m_numStreams; j++) {
    318                  if (mStreams[j] != NULL &&
    319                      mStreams[j]->getMyHandle() == recvd_frame->bufs[i]->stream_id) {
    320                      rc = mStreams[j]->bufDone(recvd_frame->bufs[i]->buf_idx);
    321                      break; // break loop j
    322                  }
    323              }
    324          }
    325     }
    326 
    327     return rc;
    328 }
    329 
    330 /*===========================================================================
    331  * FUNCTION   : getStreamTypeMask
    332  *
    333  * DESCRIPTION: Get bit mask of all stream types in this channel
    334  *
    335  * PARAMETERS : None
    336  *
    337  * RETURN     : Bit mask of all stream types in this channel
    338  *==========================================================================*/
    339 uint32_t QCamera3Channel::getStreamTypeMask()
    340 {
    341     uint32_t mask = 0;
    342     for (int i = 0; i < m_numStreams; i++) {
    343        mask |= (0x1 << mStreams[i]->getMyType());
    344     }
    345     return mask;
    346 }
    347 
    348 /*===========================================================================
    349  * FUNCTION   : getStreamID
    350  *
    351  * DESCRIPTION: Get StreamID of requested stream type
    352  *
    353  * PARAMETERS : streamMask
    354  *
    355  * RETURN     : Stream ID
    356  *==========================================================================*/
    357 uint32_t QCamera3Channel::getStreamID(uint32_t streamMask)
    358 {
    359     uint32_t streamID = 0;
    360     for (int i = 0; i < m_numStreams; i++) {
    361         if (streamMask == (uint32_t )(0x1 << mStreams[i]->getMyType())) {
    362             streamID = mStreams[i]->getMyServerID();
    363             break;
    364         }
    365     }
    366     return streamID;
    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  *   @stream_type: Channel stream type
    439  *
    440  * RETURN     : none
    441  *==========================================================================*/
    442 QCamera3RegularChannel::QCamera3RegularChannel(uint32_t cam_handle,
    443                     mm_camera_ops_t *cam_ops,
    444                     channel_cb_routine cb_routine,
    445                     cam_padding_info_t *paddingInfo,
    446                     void *userData,
    447                     camera3_stream_t *stream,
    448                     cam_stream_type_t stream_type) :
    449                         QCamera3Channel(cam_handle, cam_ops, cb_routine,
    450                                                 paddingInfo, userData),
    451                         mCamera3Stream(stream),
    452                         mNumBufs(0),
    453                         mStreamType(stream_type)
    454 {
    455 }
    456 
    457 /*===========================================================================
    458  * FUNCTION   : ~QCamera3RegularChannel
    459  *
    460  * DESCRIPTION: destructor of QCamera3RegularChannel
    461  *
    462  * PARAMETERS : none
    463  *
    464  * RETURN     : none
    465  *==========================================================================*/
    466 QCamera3RegularChannel::~QCamera3RegularChannel()
    467 {
    468     mMemory.unregisterBuffers();
    469 }
    470 
    471 /*===========================================================================
    472  * FUNCTION   : initialize
    473  *
    474  * DESCRIPTION: Initialize and add camera channel & stream
    475  *
    476  * PARAMETERS :
    477  *
    478  * RETURN     : int32_t type of status
    479  *              NO_ERROR  -- success
    480  *              none-zero failure code
    481  *==========================================================================*/
    482 
    483 int32_t QCamera3RegularChannel::initialize()
    484 {
    485     int32_t rc = NO_ERROR;
    486     cam_format_t streamFormat;
    487     cam_dimension_t streamDim;
    488 
    489     if (NULL == mCamera3Stream) {
    490         ALOGE("%s: Camera stream uninitialized", __func__);
    491         return NO_INIT;
    492     }
    493 
    494     if (1 <= m_numStreams) {
    495         // Only one stream per channel supported in v3 Hal
    496         return NO_ERROR;
    497     }
    498 
    499     rc = init(NULL, NULL);
    500     if (rc < 0) {
    501         ALOGE("%s: init failed", __func__);
    502         return rc;
    503     }
    504 
    505     mNumBufs = CAM_MAX_NUM_BUFS_PER_STREAM;
    506 
    507     if (mCamera3Stream->format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
    508         if (mStreamType ==  CAM_STREAM_TYPE_VIDEO) {
    509             streamFormat = CAM_FORMAT_YUV_420_NV12;
    510         } else if (mStreamType == CAM_STREAM_TYPE_PREVIEW) {
    511             streamFormat = CAM_FORMAT_YUV_420_NV21;
    512         } else {
    513             //TODO: Add a new flag in libgralloc for ZSL buffers, and its size needs
    514             // to be properly aligned and padded.
    515             streamFormat = CAM_FORMAT_YUV_420_NV21;
    516         }
    517     } else if(mCamera3Stream->format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
    518          streamFormat = CAM_FORMAT_YUV_420_NV21;
    519     } else if (mCamera3Stream->format == HAL_PIXEL_FORMAT_RAW_OPAQUE ||
    520             mCamera3Stream->format == HAL_PIXEL_FORMAT_RAW16) {
    521         // Bayer pattern doesn't matter here.
    522         // All CAMIF raw format uses 10bit.
    523         streamFormat = CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GBRG;
    524     } else {
    525 
    526         //TODO: Fail for other types of streams for now
    527         ALOGE("%s: format is not IMPLEMENTATION_DEFINED or flexible", __func__);
    528         return -EINVAL;
    529     }
    530 
    531     streamDim.width = mCamera3Stream->width;
    532     streamDim.height = mCamera3Stream->height;
    533 
    534     rc = QCamera3Channel::addStream(mStreamType,
    535             streamFormat,
    536             streamDim,
    537             mNumBufs);
    538 
    539     return rc;
    540 }
    541 
    542 /*===========================================================================
    543  * FUNCTION   : start
    544  *
    545  * DESCRIPTION: start a regular channel
    546  *
    547  * PARAMETERS :
    548  *
    549  * RETURN     : int32_t type of status
    550  *              NO_ERROR  -- success
    551  *              none-zero failure code
    552  *==========================================================================*/
    553 int32_t QCamera3RegularChannel::start()
    554 {
    555     int32_t rc = NO_ERROR;
    556 
    557     if (0 < mMemory.getCnt()) {
    558         rc = QCamera3Channel::start();
    559     }
    560 
    561     return rc;
    562 }
    563 /*===========================================================================
    564  * FUNCTION   : getInternalFormatBuffer
    565  *
    566  * DESCRIPTION: return buffer in the internal format structure
    567  *
    568  * PARAMETERS :
    569  *   @streamHandle : buffer handle
    570  *
    571  * RETURN     : stream object. NULL if not found
    572  *==========================================================================*/
    573 mm_camera_buf_def_t* QCamera3RegularChannel::getInternalFormatBuffer(
    574                                             buffer_handle_t * buffer)
    575 {
    576     int32_t index;
    577     if(buffer == NULL)
    578         return NULL;
    579     index = mMemory.getMatchBufIndex((void*)buffer);
    580     if(index < 0) {
    581         ALOGE("%s: Could not find object among registered buffers",__func__);
    582         return NULL;
    583     }
    584     return mStreams[0]->getInternalFormatBuffer(index);
    585 }
    586 
    587 /*===========================================================================
    588  * FUNCTION   : request
    589  *
    590  * DESCRIPTION: process a request from camera service. Stream on if ncessary.
    591  *
    592  * PARAMETERS :
    593  *   @buffer  : buffer to be filled for this request
    594  *
    595  * RETURN     : 0 on a success start of capture
    596  *              -EINVAL on invalid input
    597  *              -ENODEV on serious error
    598  *==========================================================================*/
    599 int32_t QCamera3RegularChannel::request(buffer_handle_t *buffer, uint32_t frameNumber)
    600 {
    601     //FIX ME: Return buffer back in case of failures below.
    602 
    603     int32_t rc = NO_ERROR;
    604     int index;
    605 
    606     if (NULL == buffer) {
    607         ALOGE("%s: Invalid buffer in channel request", __func__);
    608         return BAD_VALUE;
    609     }
    610 
    611     if(!m_bIsActive) {
    612         rc = registerBuffer(buffer);
    613         if (NO_ERROR != rc) {
    614             ALOGE("%s: On-the-fly buffer registration failed %d",
    615                     __func__, rc);
    616             return rc;
    617         }
    618 
    619         rc = start();
    620         if (NO_ERROR != rc) {
    621             return rc;
    622         }
    623     } else {
    624         ALOGV("%s: Request on an existing stream",__func__);
    625     }
    626 
    627     index = mMemory.getMatchBufIndex((void*)buffer);
    628     if(index < 0) {
    629         rc = registerBuffer(buffer);
    630         if (NO_ERROR != rc) {
    631             ALOGE("%s: On-the-fly buffer registration failed %d",
    632                     __func__, rc);
    633             return rc;
    634         }
    635 
    636         index = mMemory.getMatchBufIndex((void*)buffer);
    637         if (index < 0) {
    638             ALOGE("%s: Could not find object among registered buffers",
    639                     __func__);
    640             return DEAD_OBJECT;
    641         }
    642     }
    643 
    644     rc = mStreams[0]->bufDone(index);
    645     if(rc != NO_ERROR) {
    646         ALOGE("%s: Failed to Q new buffer to stream",__func__);
    647         return rc;
    648     }
    649 
    650     rc = mMemory.markFrameNumber(index, frameNumber);
    651     return rc;
    652 }
    653 
    654 /*===========================================================================
    655  * FUNCTION   : registerBuffer
    656  *
    657  * DESCRIPTION: register streaming buffer to the channel object
    658  *
    659  * PARAMETERS :
    660  *   @buffer     : buffer to be registered
    661  *
    662  * RETURN     : int32_t type of status
    663  *              NO_ERROR  -- success
    664  *              none-zero failure code
    665  *==========================================================================*/
    666 int32_t QCamera3RegularChannel::registerBuffer(buffer_handle_t *buffer)
    667 {
    668     int rc = 0;
    669 
    670     if ((uint32_t)mMemory.getCnt() > (mNumBufs - 1)) {
    671         ALOGE("%s: Trying to register more buffers than initially requested",
    672                 __func__);
    673         return BAD_VALUE;
    674     }
    675 
    676     if (0 == m_numStreams) {
    677         rc = initialize();
    678         if (rc != NO_ERROR) {
    679             ALOGE("%s: Couldn't initialize camera stream %d",
    680                     __func__, rc);
    681             return rc;
    682         }
    683     }
    684 
    685     rc = mMemory.registerBuffer(buffer);
    686     if (ALREADY_EXISTS == rc) {
    687         return NO_ERROR;
    688     } else if (NO_ERROR != rc) {
    689         ALOGE("%s: Buffer %p couldn't be registered %d", __func__, buffer, rc);
    690         return rc;
    691     }
    692 
    693     return rc;
    694 }
    695 
    696 void QCamera3RegularChannel::streamCbRoutine(
    697                             mm_camera_super_buf_t *super_frame,
    698                             QCamera3Stream *stream)
    699 {
    700     //FIXME Q Buf back in case of error?
    701     uint8_t frameIndex;
    702     buffer_handle_t *resultBuffer;
    703     int32_t resultFrameNumber;
    704     camera3_stream_buffer_t result;
    705 
    706     if(!super_frame) {
    707          ALOGE("%s: Invalid Super buffer",__func__);
    708          return;
    709     }
    710 
    711     if(super_frame->num_bufs != 1) {
    712          ALOGE("%s: Multiple streams are not supported",__func__);
    713          return;
    714     }
    715     if(super_frame->bufs[0] == NULL ) {
    716          ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
    717                   __func__);
    718          return;
    719     }
    720 
    721     frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
    722     if(frameIndex >= mNumBufs) {
    723          ALOGE("%s: Error, Invalid index for buffer",__func__);
    724          if(stream) {
    725              stream->bufDone(frameIndex);
    726          }
    727          return;
    728     }
    729 
    730     ////Use below data to issue framework callback
    731     resultBuffer = (buffer_handle_t *)mMemory.getBufferHandle(frameIndex);
    732     resultFrameNumber = mMemory.getFrameNumber(frameIndex);
    733 
    734     result.stream = mCamera3Stream;
    735     result.buffer = resultBuffer;
    736     result.status = CAMERA3_BUFFER_STATUS_OK;
    737     result.acquire_fence = -1;
    738     result.release_fence = -1;
    739 
    740     mChannelCB(NULL, &result, resultFrameNumber, mUserData);
    741     free(super_frame);
    742     return;
    743 }
    744 
    745 QCamera3Memory* QCamera3RegularChannel::getStreamBufs(uint32_t /*len*/)
    746 {
    747     return &mMemory;
    748 }
    749 
    750 int QCamera3RegularChannel::kMaxBuffers = 7;
    751 
    752 QCamera3MetadataChannel::QCamera3MetadataChannel(uint32_t cam_handle,
    753                     mm_camera_ops_t *cam_ops,
    754                     channel_cb_routine cb_routine,
    755                     cam_padding_info_t *paddingInfo,
    756                     void *userData) :
    757                         QCamera3Channel(cam_handle, cam_ops,
    758                                 cb_routine, paddingInfo, userData),
    759                         mMemory(NULL)
    760 {
    761 }
    762 
    763 QCamera3MetadataChannel::~QCamera3MetadataChannel()
    764 {
    765     if (m_bIsActive)
    766         stop();
    767 
    768     if (mMemory) {
    769         mMemory->deallocate();
    770         delete mMemory;
    771         mMemory = NULL;
    772     }
    773 }
    774 
    775 int32_t QCamera3MetadataChannel::initialize()
    776 {
    777     int32_t rc;
    778     cam_dimension_t streamDim;
    779 
    780     if (mMemory || m_numStreams > 0) {
    781         ALOGE("%s: metadata channel already initialized", __func__);
    782         return -EINVAL;
    783     }
    784 
    785     rc = init(NULL, NULL);
    786     if (rc < 0) {
    787         ALOGE("%s: init failed", __func__);
    788         return rc;
    789     }
    790 
    791     streamDim.width = sizeof(metadata_buffer_t),
    792     streamDim.height = 1;
    793     rc = QCamera3Channel::addStream(CAM_STREAM_TYPE_METADATA, CAM_FORMAT_MAX,
    794         streamDim, MIN_STREAMING_BUFFER_NUM);
    795     if (rc < 0) {
    796         ALOGE("%s: addStream failed", __func__);
    797     }
    798     return rc;
    799 }
    800 
    801 int32_t QCamera3MetadataChannel::request(buffer_handle_t * /*buffer*/,
    802                                                 uint32_t /*frameNumber*/)
    803 {
    804     if (!m_bIsActive) {
    805         return start();
    806     }
    807     else
    808         return 0;
    809 }
    810 
    811 void QCamera3MetadataChannel::streamCbRoutine(
    812                         mm_camera_super_buf_t *super_frame,
    813                         QCamera3Stream * /*stream*/)
    814 {
    815     uint32_t requestNumber = 0;
    816     if (super_frame == NULL || super_frame->num_bufs != 1) {
    817         ALOGE("%s: super_frame is not valid", __func__);
    818         return;
    819     }
    820     mChannelCB(super_frame, NULL, requestNumber, mUserData);
    821 }
    822 
    823 QCamera3Memory* QCamera3MetadataChannel::getStreamBufs(uint32_t len)
    824 {
    825     int rc;
    826     if (len < sizeof(metadata_buffer_t)) {
    827         ALOGE("%s: size doesn't match %d vs %d", __func__,
    828                 len, sizeof(metadata_buffer_t));
    829         return NULL;
    830     }
    831     mMemory = new QCamera3HeapMemory();
    832     if (!mMemory) {
    833         ALOGE("%s: unable to create metadata memory", __func__);
    834         return NULL;
    835     }
    836     rc = mMemory->allocate(MIN_STREAMING_BUFFER_NUM, len, true);
    837     if (rc < 0) {
    838         ALOGE("%s: unable to allocate metadata memory", __func__);
    839         delete mMemory;
    840         mMemory = NULL;
    841         return NULL;
    842     }
    843     memset(mMemory->getPtr(0), 0, sizeof(metadata_buffer_t));
    844     return mMemory;
    845 }
    846 
    847 void QCamera3MetadataChannel::putStreamBufs()
    848 {
    849     mMemory->deallocate();
    850     delete mMemory;
    851     mMemory = NULL;
    852 }
    853 /*************************************************************************************/
    854 // RAW Channel related functions
    855 int QCamera3RawChannel::kMaxBuffers = 7;
    856 
    857 QCamera3RawChannel::QCamera3RawChannel(uint32_t cam_handle,
    858                     mm_camera_ops_t *cam_ops,
    859                     channel_cb_routine cb_routine,
    860                     cam_padding_info_t *paddingInfo,
    861                     void *userData,
    862                     camera3_stream_t *stream,
    863                     bool raw_16) :
    864                         QCamera3RegularChannel(cam_handle, cam_ops,
    865                                 cb_routine, paddingInfo, userData, stream,
    866                                 CAM_STREAM_TYPE_RAW),
    867                         mIsRaw16(raw_16)
    868 {
    869     char prop[PROPERTY_VALUE_MAX];
    870     property_get("persist.camera.raw.dump", prop, "0");
    871     mRawDump = atoi(prop);
    872 }
    873 
    874 QCamera3RawChannel::~QCamera3RawChannel()
    875 {
    876 }
    877 
    878 void QCamera3RawChannel::streamCbRoutine(
    879                         mm_camera_super_buf_t *super_frame,
    880                         QCamera3Stream * stream)
    881 {
    882     /* Move this back down once verified */
    883     if (mRawDump)
    884         dumpRawSnapshot(super_frame->bufs[0]);
    885 
    886     if (mIsRaw16)
    887         convertToRaw16(super_frame->bufs[0]);
    888 
    889     //Make sure cache coherence because extra processing is done
    890     mMemory.cleanInvalidateCache(super_frame->bufs[0]->buf_idx);
    891 
    892     QCamera3RegularChannel::streamCbRoutine(super_frame, stream);
    893     return;
    894 }
    895 
    896 void QCamera3RawChannel::dumpRawSnapshot(mm_camera_buf_def_t *frame)
    897 {
    898    QCamera3Stream *stream = getStreamByIndex(0);
    899    char buf[32];
    900    memset(buf, 0, sizeof(buf));
    901    cam_dimension_t dim;
    902    memset(&dim, 0, sizeof(dim));
    903    stream->getFrameDimension(dim);
    904 
    905    cam_frame_len_offset_t offset;
    906    memset(&offset, 0, sizeof(cam_frame_len_offset_t));
    907    stream->getFrameOffset(offset);
    908    snprintf(buf, sizeof(buf), "/data/r_%d_%dx%d.raw",
    909             frame->frame_idx, dim.width, dim.height);
    910 
    911    int file_fd = open(buf, O_RDWR| O_CREAT, 0777);
    912    if (file_fd >= 0) {
    913       int written_len = write(file_fd, frame->buffer, offset.frame_len);
    914       ALOGE("%s: written number of bytes %d", __func__, written_len);
    915       close(file_fd);
    916    } else {
    917       ALOGE("%s: failed to open file to dump image", __func__);
    918    }
    919 
    920 }
    921 
    922 void QCamera3RawChannel::convertToRaw16(mm_camera_buf_def_t *frame)
    923 {
    924     // Convert image buffer from Opaque raw format to RAW16 format
    925     // 10bit Opaque raw is stored in the format of:
    926     // 0000 - p5 - p4 - p3 - p2 - p1 - p0
    927     // where p0 to p5 are 6 pixels (each is 10bit)_and most significant
    928     // 4 bits are 0s. Each 64bit word contains 6 pixels.
    929 
    930     QCamera3Stream *stream = getStreamByIndex(0);
    931     cam_dimension_t dim;
    932     memset(&dim, 0, sizeof(dim));
    933     stream->getFrameDimension(dim);
    934 
    935     cam_frame_len_offset_t offset;
    936     memset(&offset, 0, sizeof(cam_frame_len_offset_t));
    937     stream->getFrameOffset(offset);
    938 
    939     uint32_t raw16_stride = (dim.width + 15) & ~15;
    940     uint16_t* raw16_buffer = (uint16_t *)frame->buffer;
    941 
    942     // In-place format conversion.
    943     // Raw16 format always occupy more memory than opaque raw10.
    944     // Convert to Raw16 by iterating through all pixels from bottom-right
    945     // to top-left of the image.
    946     // One special notes:
    947     // 1. Cross-platform raw16's stride is 16 pixels.
    948     // 2. Opaque raw10's stride is 6 pixels, and aligned to 16 bytes.
    949     for (int y = dim.height-1; y >= 0; y--) {
    950         uint64_t* row_start = (uint64_t *)frame->buffer +
    951             y * offset.mp[0].stride / 8;
    952         for (int x = dim.width-1;  x >= 0; x--) {
    953             uint16_t raw16_pixel = 0x3FF & (row_start[x/6] >> (10*(x%6)));
    954             raw16_buffer[y*raw16_stride+x] = raw16_pixel;
    955         }
    956     }
    957 }
    958 
    959 /*************************************************************************************/
    960 
    961 /*===========================================================================
    962  * FUNCTION   : jpegEvtHandle
    963  *
    964  * DESCRIPTION: Function registerd to mm-jpeg-interface to handle jpeg events.
    965                 Construct result payload and call mChannelCb to deliver buffer
    966                 to framework.
    967  *
    968  * PARAMETERS :
    969  *   @status    : status of jpeg job
    970  *   @client_hdl: jpeg client handle
    971  *   @jobId     : jpeg job Id
    972  *   @p_ouput   : ptr to jpeg output result struct
    973  *   @userdata  : user data ptr
    974  *
    975  * RETURN     : none
    976  *==========================================================================*/
    977 void QCamera3PicChannel::jpegEvtHandle(jpeg_job_status_t status,
    978                                               uint32_t /*client_hdl*/,
    979                                               uint32_t jobId,
    980                                               mm_jpeg_output_t *p_output,
    981                                               void *userdata)
    982 {
    983     buffer_handle_t *resultBuffer, *jpegBufferHandle;
    984     int32_t resultFrameNumber;
    985     int resultStatus = CAMERA3_BUFFER_STATUS_OK;
    986     camera3_stream_buffer_t result;
    987     camera3_jpeg_blob_t jpegHeader;
    988     char* jpeg_eof = 0;
    989     int maxJpegSize;
    990     QCamera3PicChannel *obj = (QCamera3PicChannel *)userdata;
    991     if (obj) {
    992 
    993         //Release any cached metabuffer information
    994         if (obj->mMetaFrame != NULL && obj->m_pMetaChannel != NULL) {
    995             ((QCamera3MetadataChannel*)(obj->m_pMetaChannel))->bufDone(obj->mMetaFrame);
    996             obj->mMetaFrame = NULL;
    997             obj->m_pMetaChannel = NULL;
    998         } else {
    999             ALOGE("%s: Meta frame was NULL", __func__);
   1000         }
   1001         //Construct payload for process_capture_result. Call mChannelCb
   1002 
   1003         qcamera_jpeg_data_t *job = obj->m_postprocessor.findJpegJobByJobId(jobId);
   1004 
   1005         if ((job == NULL) || (status == JPEG_JOB_STATUS_ERROR)) {
   1006             ALOGE("%s: Error in jobId: (%d) with status: %d", __func__, jobId, status);
   1007             resultStatus = CAMERA3_BUFFER_STATUS_ERROR;
   1008         }
   1009 
   1010         //Construct jpeg transient header of type camera3_jpeg_blob_t
   1011         //Append at the end of jpeg image of buf_filled_len size
   1012 
   1013         jpegHeader.jpeg_blob_id = CAMERA3_JPEG_BLOB_ID;
   1014         jpegHeader.jpeg_size = p_output->buf_filled_len;
   1015 
   1016 
   1017         char* jpeg_buf = (char *)p_output->buf_vaddr;
   1018 
   1019         // Gralloc buffer may have additional padding for 4K page size
   1020         // Follow size guidelines based on spec since framework relies
   1021         // on that to reach end of buffer and with it the header
   1022 
   1023         //Handle same as resultBuffer, but for readablity
   1024         jpegBufferHandle =
   1025             (buffer_handle_t *)obj->mMemory.getBufferHandle(obj->mCurrentBufIndex);
   1026 
   1027         maxJpegSize = ((private_handle_t*)(*jpegBufferHandle))->width;
   1028         if (maxJpegSize > obj->mMemory.getSize(obj->mCurrentBufIndex)) {
   1029             maxJpegSize = obj->mMemory.getSize(obj->mCurrentBufIndex);
   1030         }
   1031 
   1032         jpeg_eof = &jpeg_buf[maxJpegSize-sizeof(jpegHeader)];
   1033         memcpy(jpeg_eof, &jpegHeader, sizeof(jpegHeader));
   1034         obj->mMemory.cleanInvalidateCache(obj->mCurrentBufIndex);
   1035 
   1036         ////Use below data to issue framework callback
   1037         resultBuffer = (buffer_handle_t *)obj->mMemory.getBufferHandle(obj->mCurrentBufIndex);
   1038         resultFrameNumber = obj->mMemory.getFrameNumber(obj->mCurrentBufIndex);
   1039 
   1040         result.stream = obj->mCamera3Stream;
   1041         result.buffer = resultBuffer;
   1042         result.status = resultStatus;
   1043         result.acquire_fence = -1;
   1044         result.release_fence = -1;
   1045 
   1046         ALOGV("%s: Issue Callback", __func__);
   1047         obj->mChannelCB(NULL, &result, resultFrameNumber, obj->mUserData);
   1048 
   1049         // release internal data for jpeg job
   1050         if (job != NULL) {
   1051             obj->m_postprocessor.releaseJpegJobData(job);
   1052             free(job);
   1053         }
   1054         return;
   1055         // }
   1056     } else {
   1057         ALOGE("%s: Null userdata in jpeg callback", __func__);
   1058     }
   1059 }
   1060 
   1061 QCamera3PicChannel::QCamera3PicChannel(uint32_t cam_handle,
   1062                     mm_camera_ops_t *cam_ops,
   1063                     channel_cb_routine cb_routine,
   1064                     cam_padding_info_t *paddingInfo,
   1065                     void *userData,
   1066                     camera3_stream_t *stream) :
   1067                         QCamera3Channel(cam_handle, cam_ops, cb_routine,
   1068                         paddingInfo, userData),
   1069                         m_postprocessor(this),
   1070                         mCamera3Stream(stream),
   1071                         mNumBufs(0),
   1072                         mCurrentBufIndex(-1),
   1073                         mYuvMemory(NULL),
   1074                         mMetaFrame(NULL)
   1075 {
   1076     mYuvWidth = stream->width;
   1077     mYuvHeight = stream->height;
   1078     int32_t rc = m_postprocessor.init(&mMemory, jpegEvtHandle, this);
   1079     if (rc != 0) {
   1080         ALOGE("Init Postprocessor failed");
   1081     }
   1082 }
   1083 
   1084 /*===========================================================================
   1085  * FUNCTION   : stop
   1086  *
   1087  * DESCRIPTION: stop pic channel, which will stop all streams within, including
   1088  *              the reprocessing channel in postprocessor and YUV stream.
   1089  *
   1090  * PARAMETERS : none
   1091  *
   1092  * RETURN     : int32_t type of status
   1093  *              NO_ERROR  -- success
   1094  *              none-zero failure code
   1095  *==========================================================================*/
   1096 int32_t QCamera3PicChannel::stop()
   1097 {
   1098     int32_t rc = NO_ERROR;
   1099     if(!m_bIsActive) {
   1100         ALOGE("%s: Attempt to stop inactive channel",__func__);
   1101         return rc;
   1102     }
   1103 
   1104     m_postprocessor.stop();
   1105 
   1106     rc |= QCamera3Channel::stop();
   1107     return rc;
   1108 }
   1109 
   1110 QCamera3PicChannel::~QCamera3PicChannel()
   1111 {
   1112    stop();
   1113 
   1114    int32_t rc = m_postprocessor.deinit();
   1115    if (rc != 0) {
   1116        ALOGE("De-init Postprocessor failed");
   1117    }
   1118 }
   1119 
   1120 int32_t QCamera3PicChannel::initialize()
   1121 {
   1122     int32_t rc = NO_ERROR;
   1123     cam_dimension_t streamDim;
   1124     cam_stream_type_t streamType;
   1125     cam_format_t streamFormat;
   1126     mm_camera_channel_attr_t attr;
   1127 
   1128     if (NULL == mCamera3Stream) {
   1129         ALOGE("%s: Camera stream uninitialized", __func__);
   1130         return NO_INIT;
   1131     }
   1132 
   1133     if (1 <= m_numStreams) {
   1134         // Only one stream per channel supported in v3 Hal
   1135         return NO_ERROR;
   1136     }
   1137 
   1138     memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
   1139     attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_BURST;
   1140     attr.look_back = 1;
   1141     attr.post_frame_skip = 1;
   1142     attr.water_mark = 1;
   1143     attr.max_unmatched_frames = 1;
   1144 
   1145     rc = init(&attr, NULL);
   1146     if (rc < 0) {
   1147         ALOGE("%s: init failed", __func__);
   1148         return rc;
   1149     }
   1150 
   1151     streamType = CAM_STREAM_TYPE_NON_ZSL_SNAPSHOT;
   1152     streamFormat = CAM_FORMAT_YUV_420_NV21;
   1153     streamDim.width = mYuvWidth;
   1154     streamDim.height = mYuvHeight;
   1155 
   1156     int num_buffers = 1;
   1157     mNumBufs = CAM_MAX_NUM_BUFS_PER_STREAM;
   1158     rc = QCamera3Channel::addStream(streamType, streamFormat, streamDim,
   1159             num_buffers);
   1160 
   1161     return rc;
   1162 }
   1163 
   1164 int32_t QCamera3PicChannel::request(buffer_handle_t *buffer,
   1165         uint32_t frameNumber,
   1166         mm_camera_buf_def_t *pInputBuffer,
   1167         metadata_buffer_t *metadata)
   1168 {
   1169     //FIX ME: Return buffer back in case of failures below.
   1170 
   1171     int32_t rc = NO_ERROR;
   1172     int index;
   1173     // Picture stream has already been started before any request comes in
   1174     if (!m_bIsActive) {
   1175         ALOGE("%s: Channel not started!!", __func__);
   1176         return NO_INIT;
   1177     }
   1178 
   1179     index = mMemory.getMatchBufIndex((void*)buffer);
   1180     if(index < 0) {
   1181         rc = registerBuffer(buffer);
   1182         if (NO_ERROR != rc) {
   1183             ALOGE("%s: On-the-fly buffer registration failed %d",
   1184                     __func__, rc);
   1185             return rc;
   1186         }
   1187 
   1188         index = mMemory.getMatchBufIndex((void*)buffer);
   1189         if (index < 0) {
   1190             ALOGE("%s: Could not find object among registered buffers",__func__);
   1191             return DEAD_OBJECT;
   1192         }
   1193     }
   1194     rc = mMemory.markFrameNumber(index, frameNumber);
   1195 
   1196     //Start the postprocessor for jpeg encoding. Pass mMemory as destination buffer
   1197     mCurrentBufIndex = index;
   1198 
   1199     // Start postprocessor
   1200     m_postprocessor.start(this, metadata);
   1201 
   1202     // Queue jpeg settings
   1203     rc = queueJpegSetting(index, metadata);
   1204 
   1205     if (pInputBuffer == NULL)
   1206         mStreams[0]->bufDone(0);
   1207     else {
   1208         mm_camera_super_buf_t *src_frame = NULL;
   1209         src_frame = (mm_camera_super_buf_t *)malloc(
   1210                 sizeof(mm_camera_super_buf_t));
   1211         if (src_frame == NULL) {
   1212             ALOGE("%s: No memory for src frame", __func__);
   1213             return NO_MEMORY;
   1214         }
   1215         memset(src_frame, 0, sizeof(mm_camera_super_buf_t));
   1216         src_frame->num_bufs = 1;
   1217         src_frame->bufs[0] = pInputBuffer;
   1218 
   1219         ALOGD("%s: Post-process started", __func__);
   1220         ALOGD("%s: Issue call to reprocess", __func__);
   1221 
   1222         m_postprocessor.processPPMetadata(metadata);
   1223         m_postprocessor.processData(src_frame);
   1224     }
   1225     return rc;
   1226 }
   1227 
   1228 /*===========================================================================
   1229  * FUNCTION   : dataNotifyCB
   1230  *
   1231  * DESCRIPTION: Channel Level callback used for super buffer data notify.
   1232  *              This function is registered with mm-camera-interface to handle
   1233  *              data notify
   1234  *
   1235  * PARAMETERS :
   1236  *   @recvd_frame   : stream frame received
   1237  *   userdata       : user data ptr
   1238  *
   1239  * RETURN     : none
   1240  *==========================================================================*/
   1241 void QCamera3PicChannel::dataNotifyCB(mm_camera_super_buf_t *recvd_frame,
   1242                                  void *userdata)
   1243 {
   1244     ALOGV("%s: E\n", __func__);
   1245     QCamera3PicChannel *channel = (QCamera3PicChannel *)userdata;
   1246 
   1247     if (channel == NULL) {
   1248         ALOGE("%s: invalid channel pointer", __func__);
   1249         return;
   1250     }
   1251 
   1252     if(channel->m_numStreams != 1) {
   1253         ALOGE("%s: Error: Bug: This callback assumes one stream per channel",__func__);
   1254         return;
   1255     }
   1256 
   1257 
   1258     if(channel->mStreams[0] == NULL) {
   1259         ALOGE("%s: Error: Invalid Stream object",__func__);
   1260         return;
   1261     }
   1262 
   1263     channel->QCamera3PicChannel::streamCbRoutine(recvd_frame, channel->mStreams[0]);
   1264 
   1265     ALOGV("%s: X\n", __func__);
   1266     return;
   1267 }
   1268 
   1269 /*===========================================================================
   1270  * FUNCTION   : registerBuffer
   1271  *
   1272  * DESCRIPTION: register streaming buffer to the channel object
   1273  *
   1274  * PARAMETERS :
   1275  *   @buffer     : buffer to be registered
   1276  *
   1277  * RETURN     : int32_t type of status
   1278  *              NO_ERROR  -- success
   1279  *              none-zero failure code
   1280  *==========================================================================*/
   1281 int32_t QCamera3PicChannel::registerBuffer(buffer_handle_t *buffer)
   1282 {
   1283     int rc = 0;
   1284 
   1285     if ((uint32_t)mMemory.getCnt() > (mNumBufs - 1)) {
   1286         ALOGE("%s: Trying to register more buffers than initially requested",
   1287                 __func__);
   1288         return BAD_VALUE;
   1289     }
   1290 
   1291     if (0 == m_numStreams) {
   1292         rc = initialize();
   1293         if (rc != NO_ERROR) {
   1294             ALOGE("%s: Couldn't initialize camera stream %d",
   1295                     __func__, rc);
   1296             return rc;
   1297         }
   1298     }
   1299     rc = mMemory.registerBuffer(buffer);
   1300     if (ALREADY_EXISTS == rc) {
   1301         return NO_ERROR;
   1302     } else if (NO_ERROR != rc) {
   1303         ALOGE("%s: Buffer %p couldn't be registered %d", __func__, buffer, rc);
   1304         return rc;
   1305     }
   1306 
   1307     return rc;
   1308 }
   1309 
   1310 void QCamera3PicChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
   1311                             QCamera3Stream *stream)
   1312 {
   1313     //TODO
   1314     //Used only for getting YUV. Jpeg callback will be sent back from channel
   1315     //directly to HWI. Refer to func jpegEvtHandle
   1316 
   1317     //Got the yuv callback. Calling yuv callback handler in PostProc
   1318     uint8_t frameIndex;
   1319     mm_camera_super_buf_t* frame = NULL;
   1320     if(!super_frame) {
   1321          ALOGE("%s: Invalid Super buffer",__func__);
   1322          return;
   1323     }
   1324 
   1325     if(super_frame->num_bufs != 1) {
   1326          ALOGE("%s: Multiple streams are not supported",__func__);
   1327          return;
   1328     }
   1329     if(super_frame->bufs[0] == NULL ) {
   1330          ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
   1331                   __func__);
   1332          return;
   1333     }
   1334 
   1335     frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
   1336     if(frameIndex >= mNumBufs) {
   1337          ALOGE("%s: Error, Invalid index for buffer",__func__);
   1338          if(stream) {
   1339              stream->bufDone(frameIndex);
   1340          }
   1341          return;
   1342     }
   1343 
   1344     frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
   1345     if (frame == NULL) {
   1346        ALOGE("%s: Error allocating memory to save received_frame structure.",
   1347                                                                     __func__);
   1348        if(stream) {
   1349            stream->bufDone(frameIndex);
   1350        }
   1351        return;
   1352     }
   1353     *frame = *super_frame;
   1354     m_postprocessor.processData(frame);
   1355     free(super_frame);
   1356     return;
   1357 }
   1358 
   1359 QCamera3Memory* QCamera3PicChannel::getStreamBufs(uint32_t len)
   1360 {
   1361     int rc = 0;
   1362 
   1363     mYuvMemory = new QCamera3HeapMemory();
   1364     if (!mYuvMemory) {
   1365         ALOGE("%s: unable to create metadata memory", __func__);
   1366         return NULL;
   1367     }
   1368 
   1369     //Queue YUV buffers in the beginning mQueueAll = true
   1370     rc = mYuvMemory->allocate(1, len, false);
   1371     if (rc < 0) {
   1372         ALOGE("%s: unable to allocate metadata memory", __func__);
   1373         delete mYuvMemory;
   1374         mYuvMemory = NULL;
   1375         return NULL;
   1376     }
   1377     return mYuvMemory;
   1378 }
   1379 
   1380 void QCamera3PicChannel::putStreamBufs()
   1381 {
   1382     mMemory.unregisterBuffers();
   1383 
   1384     mYuvMemory->deallocate();
   1385     delete mYuvMemory;
   1386     mYuvMemory = NULL;
   1387 }
   1388 
   1389 int32_t QCamera3PicChannel::queueReprocMetadata(metadata_buffer_t *metadata)
   1390 {
   1391     return m_postprocessor.processPPMetadata(metadata);
   1392 }
   1393 
   1394 int32_t QCamera3PicChannel::queueJpegSetting(int32_t index, metadata_buffer_t *metadata)
   1395 {
   1396     jpeg_settings_t *settings =
   1397             (jpeg_settings_t *)malloc(sizeof(jpeg_settings_t));
   1398 
   1399     if (!settings) {
   1400         ALOGE("%s: out of memory allocating jpeg_settings", __func__);
   1401         return -ENOMEM;
   1402     }
   1403 
   1404     memset(settings, 0, sizeof(jpeg_settings_t));
   1405 
   1406     settings->out_buf_index = index;
   1407 
   1408     settings->jpeg_orientation = 0;
   1409     if (IS_PARM_VALID(CAM_INTF_META_JPEG_ORIENTATION, metadata)) {
   1410         int32_t *orientation = (int32_t *)POINTER_OF(
   1411                 CAM_INTF_META_JPEG_ORIENTATION, metadata);
   1412         settings->jpeg_orientation = *orientation;
   1413     }
   1414 
   1415     settings->jpeg_quality = 85;
   1416     if (IS_PARM_VALID(CAM_INTF_META_JPEG_QUALITY, metadata)) {
   1417         uint8_t *quality = (uint8_t *)POINTER_OF(
   1418                 CAM_INTF_META_JPEG_QUALITY, metadata);
   1419         settings->jpeg_quality = *quality;
   1420     }
   1421 
   1422     if (IS_PARM_VALID(CAM_INTF_META_JPEG_THUMB_QUALITY, metadata)) {
   1423         uint8_t *quality = (uint8_t *)POINTER_OF(
   1424                 CAM_INTF_META_JPEG_THUMB_QUALITY, metadata);
   1425         settings->jpeg_thumb_quality = *quality;
   1426     }
   1427 
   1428     if (IS_PARM_VALID(CAM_INTF_META_JPEG_THUMB_SIZE, metadata)) {
   1429         cam_dimension_t *dimension = (cam_dimension_t *)POINTER_OF(
   1430                 CAM_INTF_META_JPEG_THUMB_SIZE, metadata);
   1431         settings->thumbnail_size = *dimension;
   1432     }
   1433 
   1434     settings->gps_timestamp_valid = 0;
   1435     if (IS_PARM_VALID(CAM_INTF_META_JPEG_GPS_TIMESTAMP, metadata)) {
   1436         int64_t *timestamp = (int64_t *)POINTER_OF(
   1437                 CAM_INTF_META_JPEG_GPS_TIMESTAMP, metadata);
   1438         settings->gps_timestamp = *timestamp;
   1439         settings->gps_timestamp_valid = 1;
   1440     }
   1441 
   1442     settings->gps_coordinates_valid = 0;
   1443     if (IS_PARM_VALID(CAM_INTF_META_JPEG_GPS_COORDINATES, metadata)) {
   1444         double *coordinates = (double *)POINTER_OF(
   1445                 CAM_INTF_META_JPEG_GPS_COORDINATES, metadata);
   1446         memcpy(settings->gps_coordinates, coordinates, 3*sizeof(double));
   1447         settings->gps_coordinates_valid = 1;
   1448     }
   1449 
   1450     if (IS_PARM_VALID(CAM_INTF_META_JPEG_GPS_PROC_METHODS, metadata)) {
   1451         char *proc_methods = (char *)POINTER_OF(
   1452                 CAM_INTF_META_JPEG_GPS_PROC_METHODS, metadata);
   1453         memset(settings->gps_processing_method, 0,
   1454                 sizeof(settings->gps_processing_method));
   1455         strncpy(settings->gps_processing_method, proc_methods,
   1456                 sizeof(settings->gps_processing_method));
   1457     }
   1458 
   1459     return m_postprocessor.processJpegSettingData(settings);
   1460 }
   1461 
   1462 /*===========================================================================
   1463  * FUNCTION   : getRational
   1464  *
   1465  * DESCRIPTION: compose rational struct
   1466  *
   1467  * PARAMETERS :
   1468  *   @rat     : ptr to struct to store rational info
   1469  *   @num     :num of the rational
   1470  *   @denom   : denom of the rational
   1471  *
   1472  * RETURN     : int32_t type of status
   1473  *              NO_ERROR  -- success
   1474  *              none-zero failure code
   1475  *==========================================================================*/
   1476 int32_t getRational(rat_t *rat, int num, int denom)
   1477 {
   1478     if (NULL == rat) {
   1479         ALOGE("%s: NULL rat input", __func__);
   1480         return BAD_VALUE;
   1481     }
   1482     rat->num = num;
   1483     rat->denom = denom;
   1484     return NO_ERROR;
   1485 }
   1486 
   1487 /*===========================================================================
   1488  * FUNCTION   : parseGPSCoordinate
   1489  *
   1490  * DESCRIPTION: parse GPS coordinate string
   1491  *
   1492  * PARAMETERS :
   1493  *   @coord_str : [input] coordinate string
   1494  *   @coord     : [output]  ptr to struct to store coordinate
   1495  *
   1496  * RETURN     : int32_t type of status
   1497  *              NO_ERROR  -- success
   1498  *              none-zero failure code
   1499  *==========================================================================*/
   1500 int parseGPSCoordinate(const char *coord_str, rat_t* coord)
   1501 {
   1502     if(coord == NULL) {
   1503         ALOGE("%s: error, invalid argument coord == NULL", __func__);
   1504         return BAD_VALUE;
   1505     }
   1506     float degF = atof(coord_str);
   1507     if (degF < 0) {
   1508         degF = -degF;
   1509     }
   1510     float minF = (degF - (int) degF) * 60;
   1511     float secF = (minF - (int) minF) * 60;
   1512 
   1513     getRational(&coord[0], (int)degF, 1);
   1514     getRational(&coord[1], (int)minF, 1);
   1515     getRational(&coord[2], (int)(secF * 10000), 10000);
   1516     return NO_ERROR;
   1517 }
   1518 
   1519 /*===========================================================================
   1520  * FUNCTION   : getExifDateTime
   1521  *
   1522  * DESCRIPTION: query exif date time
   1523  *
   1524  * PARAMETERS :
   1525  *   @dateTime   : string to store exif date time
   1526  *   @subsecTime : string to store exif subsec time
   1527  *   @count      : length of the dateTime string
   1528  *   @subsecCount: length of the subsecTime string
   1529  *
   1530  * RETURN     : int32_t type of status
   1531  *              NO_ERROR  -- success
   1532  *              none-zero failure code
   1533  *==========================================================================*/
   1534 int32_t getExifDateTime(char *dateTime, char *subsecTime,
   1535         uint32_t &count, uint32_t &subsecCount)
   1536 {
   1537     //get time and date from system
   1538     struct timeval tv;
   1539     struct tm *timeinfo;
   1540 
   1541     gettimeofday(&tv, NULL);
   1542     timeinfo = localtime(&tv.tv_sec);
   1543     //Write datetime according to EXIF Spec
   1544     //"YYYY:MM:DD HH:MM:SS" (20 chars including \0)
   1545     snprintf(dateTime, 20, "%04d:%02d:%02d %02d:%02d:%02d",
   1546              timeinfo->tm_year + 1900, timeinfo->tm_mon + 1,
   1547              timeinfo->tm_mday, timeinfo->tm_hour,
   1548              timeinfo->tm_min, timeinfo->tm_sec);
   1549     count = 20;
   1550 
   1551     //Write subsec according to EXIF Sepc
   1552     snprintf(subsecTime, 7, "%06ld", tv.tv_usec);
   1553     subsecCount = 7;
   1554     return NO_ERROR;
   1555 }
   1556 
   1557 /*===========================================================================
   1558  * FUNCTION   : getExifFocalLength
   1559  *
   1560  * DESCRIPTION: get exif focal lenght
   1561  *
   1562  * PARAMETERS :
   1563  *   @focalLength : ptr to rational strcut to store focal lenght
   1564  *
   1565  * RETURN     : int32_t type of status
   1566  *              NO_ERROR  -- success
   1567  *              none-zero failure code
   1568  *==========================================================================*/
   1569 int32_t getExifFocalLength(rat_t *focalLength, float value)
   1570 {
   1571     int focalLengthValue =
   1572         (int)(value * FOCAL_LENGTH_DECIMAL_PRECISION);
   1573     return getRational(focalLength, focalLengthValue, FOCAL_LENGTH_DECIMAL_PRECISION);
   1574 }
   1575 
   1576 /*===========================================================================
   1577   * FUNCTION   : getExifExpTimeInfo
   1578   *
   1579   * DESCRIPTION: get exif exposure time information
   1580   *
   1581   * PARAMETERS :
   1582   *   @expoTimeInfo     : expousure time value
   1583   * RETURN     : nt32_t type of status
   1584   *              NO_ERROR  -- success
   1585   *              none-zero failure code
   1586   *==========================================================================*/
   1587 int32_t getExifExpTimeInfo(rat_t *expoTimeInfo, int64_t value)
   1588 {
   1589 
   1590     int cal_exposureTime;
   1591     if (value != 0)
   1592         cal_exposureTime = value;
   1593     else
   1594         cal_exposureTime = 60;
   1595 
   1596     return getRational(expoTimeInfo, 1, cal_exposureTime);
   1597 }
   1598 
   1599 /*===========================================================================
   1600  * FUNCTION   : getExifGpsProcessingMethod
   1601  *
   1602  * DESCRIPTION: get GPS processing method
   1603  *
   1604  * PARAMETERS :
   1605  *   @gpsProcessingMethod : string to store GPS process method
   1606  *   @count               : lenght of the string
   1607  *
   1608  * RETURN     : int32_t type of status
   1609  *              NO_ERROR  -- success
   1610  *              none-zero failure code
   1611  *==========================================================================*/
   1612 int32_t getExifGpsProcessingMethod(char *gpsProcessingMethod,
   1613                                    uint32_t &count, char* value)
   1614 {
   1615     if(value != NULL) {
   1616         memcpy(gpsProcessingMethod, ExifAsciiPrefix, EXIF_ASCII_PREFIX_SIZE);
   1617         count = EXIF_ASCII_PREFIX_SIZE;
   1618         strncpy(gpsProcessingMethod + EXIF_ASCII_PREFIX_SIZE, value, strlen(value));
   1619         count += strlen(value);
   1620         gpsProcessingMethod[count++] = '\0'; // increase 1 for the last NULL char
   1621         return NO_ERROR;
   1622     } else {
   1623         return BAD_VALUE;
   1624     }
   1625 }
   1626 
   1627 /*===========================================================================
   1628  * FUNCTION   : getExifLatitude
   1629  *
   1630  * DESCRIPTION: get exif latitude
   1631  *
   1632  * PARAMETERS :
   1633  *   @latitude : ptr to rational struct to store latitude info
   1634  *   @ladRef   : charater to indicate latitude reference
   1635  *
   1636  * RETURN     : int32_t type of status
   1637  *              NO_ERROR  -- success
   1638  *              none-zero failure code
   1639  *==========================================================================*/
   1640 int32_t getExifLatitude(rat_t *latitude,
   1641                                            char *latRef, double value)
   1642 {
   1643     char str[30];
   1644     snprintf(str, sizeof(str), "%f", value);
   1645     if(str != NULL) {
   1646         parseGPSCoordinate(str, latitude);
   1647 
   1648         //set Latitude Ref
   1649         float latitudeValue = strtof(str, 0);
   1650         if(latitudeValue < 0.0f) {
   1651             latRef[0] = 'S';
   1652         } else {
   1653             latRef[0] = 'N';
   1654         }
   1655         latRef[1] = '\0';
   1656         return NO_ERROR;
   1657     }else{
   1658         return BAD_VALUE;
   1659     }
   1660 }
   1661 
   1662 /*===========================================================================
   1663  * FUNCTION   : getExifLongitude
   1664  *
   1665  * DESCRIPTION: get exif longitude
   1666  *
   1667  * PARAMETERS :
   1668  *   @longitude : ptr to rational struct to store longitude info
   1669  *   @lonRef    : charater to indicate longitude reference
   1670  *
   1671  * RETURN     : int32_t type of status
   1672  *              NO_ERROR  -- success
   1673  *              none-zero failure code
   1674  *==========================================================================*/
   1675 int32_t getExifLongitude(rat_t *longitude,
   1676                                             char *lonRef, double value)
   1677 {
   1678     char str[30];
   1679     snprintf(str, sizeof(str), "%f", value);
   1680     if(str != NULL) {
   1681         parseGPSCoordinate(str, longitude);
   1682 
   1683         //set Longitude Ref
   1684         float longitudeValue = strtof(str, 0);
   1685         if(longitudeValue < 0.0f) {
   1686             lonRef[0] = 'W';
   1687         } else {
   1688             lonRef[0] = 'E';
   1689         }
   1690         lonRef[1] = '\0';
   1691         return NO_ERROR;
   1692     }else{
   1693         return BAD_VALUE;
   1694     }
   1695 }
   1696 
   1697 /*===========================================================================
   1698  * FUNCTION   : getExifAltitude
   1699  *
   1700  * DESCRIPTION: get exif altitude
   1701  *
   1702  * PARAMETERS :
   1703  *   @altitude : ptr to rational struct to store altitude info
   1704  *   @altRef   : charater to indicate altitude reference
   1705  *
   1706  * RETURN     : int32_t type of status
   1707  *              NO_ERROR  -- success
   1708  *              none-zero failure code
   1709  *==========================================================================*/
   1710 int32_t getExifAltitude(rat_t *altitude,
   1711                                            char *altRef, double value)
   1712 {
   1713     char str[30];
   1714     snprintf(str, sizeof(str), "%f", value);
   1715     if(str != NULL) {
   1716         double value = atof(str);
   1717         *altRef = 0;
   1718         if(value < 0){
   1719             *altRef = 1;
   1720             value = -value;
   1721         }
   1722         return getRational(altitude, value*1000, 1000);
   1723     }else{
   1724         return BAD_VALUE;
   1725     }
   1726 }
   1727 
   1728 /*===========================================================================
   1729  * FUNCTION   : getExifGpsDateTimeStamp
   1730  *
   1731  * DESCRIPTION: get exif GPS date time stamp
   1732  *
   1733  * PARAMETERS :
   1734  *   @gpsDateStamp : GPS date time stamp string
   1735  *   @bufLen       : length of the string
   1736  *   @gpsTimeStamp : ptr to rational struct to store time stamp info
   1737  *
   1738  * RETURN     : int32_t type of status
   1739  *              NO_ERROR  -- success
   1740  *              none-zero failure code
   1741  *==========================================================================*/
   1742 int32_t getExifGpsDateTimeStamp(char *gpsDateStamp,
   1743                                            uint32_t bufLen,
   1744                                            rat_t *gpsTimeStamp, int64_t value)
   1745 {
   1746     char str[30];
   1747     snprintf(str, sizeof(str), "%lld", value);
   1748     if(str != NULL) {
   1749         time_t unixTime = (time_t)atol(str);
   1750         struct tm *UTCTimestamp = gmtime(&unixTime);
   1751 
   1752         strftime(gpsDateStamp, bufLen, "%Y:%m:%d", UTCTimestamp);
   1753 
   1754         getRational(&gpsTimeStamp[0], UTCTimestamp->tm_hour, 1);
   1755         getRational(&gpsTimeStamp[1], UTCTimestamp->tm_min, 1);
   1756         getRational(&gpsTimeStamp[2], UTCTimestamp->tm_sec, 1);
   1757 
   1758         return NO_ERROR;
   1759     } else {
   1760         return BAD_VALUE;
   1761     }
   1762 }
   1763 
   1764 int32_t getExifExposureValue(srat_t* exposure_val, int32_t exposure_comp,
   1765                              cam_rational_type_t step)
   1766 {
   1767     exposure_val->num = exposure_comp * step.numerator;
   1768     exposure_val->denom = step.denominator;
   1769     return 0;
   1770 }
   1771 /*===========================================================================
   1772  * FUNCTION   : getExifData
   1773  *
   1774  * DESCRIPTION: get exif data to be passed into jpeg encoding
   1775  *
   1776  * PARAMETERS : none
   1777  *
   1778  * RETURN     : exif data from user setting and GPS
   1779  *==========================================================================*/
   1780 QCamera3Exif *QCamera3PicChannel::getExifData(metadata_buffer_t *metadata,
   1781         jpeg_settings_t *jpeg_settings)
   1782 {
   1783     QCamera3Exif *exif = new QCamera3Exif();
   1784     if (exif == NULL) {
   1785         ALOGE("%s: No memory for QCamera3Exif", __func__);
   1786         return NULL;
   1787     }
   1788 
   1789     int32_t rc = NO_ERROR;
   1790     uint32_t count = 0;
   1791 
   1792     // add exif entries
   1793     {
   1794         char dateTime[20];
   1795         char subsecTime[7];
   1796         uint32_t subsecCount;
   1797         memset(dateTime, 0, sizeof(dateTime));
   1798         memset(subsecTime, 0, sizeof(subsecTime));
   1799         count = 20;
   1800         subsecCount = 7;
   1801         rc = getExifDateTime(dateTime, subsecTime, count, subsecCount);
   1802         if(rc == NO_ERROR) {
   1803             exif->addEntry(EXIFTAGID_DATE_TIME,
   1804                     EXIF_ASCII,
   1805                     count,
   1806                     (void *)dateTime);
   1807             exif->addEntry(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL,
   1808                     EXIF_ASCII,
   1809                     count,
   1810                     (void *)dateTime);
   1811             exif->addEntry(EXIFTAGID_EXIF_DATE_TIME_DIGITIZED,
   1812                     EXIF_ASCII,
   1813                     count,
   1814                     (void *)dateTime);
   1815             exif->addEntry(EXIFTAGID_SUBSEC_TIME,
   1816                     EXIF_ASCII,
   1817                     subsecCount,
   1818                     (void *)subsecTime);
   1819             exif->addEntry(EXIFTAGID_SUBSEC_TIME_ORIGINAL,
   1820                     EXIF_ASCII,
   1821                     subsecCount,
   1822                     (void *)subsecTime);
   1823             exif->addEntry(EXIFTAGID_SUBSEC_TIME_DIGITIZED,
   1824                     EXIF_ASCII,
   1825                     subsecCount,
   1826                     (void *)subsecTime);
   1827         } else {
   1828             ALOGE("%s: getExifDateTime failed", __func__);
   1829         }
   1830     }
   1831 
   1832     if (IS_PARM_VALID(CAM_INTF_META_LENS_FOCAL_LENGTH, metadata)) {
   1833         float focal_length = *(float *)POINTER_OF(
   1834                 CAM_INTF_META_LENS_FOCAL_LENGTH, metadata);
   1835         rat_t focalLength;
   1836         rc = getExifFocalLength(&focalLength, focal_length);
   1837         if (rc == NO_ERROR) {
   1838             exif->addEntry(EXIFTAGID_FOCAL_LENGTH,
   1839                     EXIF_RATIONAL,
   1840                     1,
   1841                     (void *)&(focalLength));
   1842         } else {
   1843             ALOGE("%s: getExifFocalLength failed", __func__);
   1844         }
   1845     }
   1846 
   1847     if (IS_PARM_VALID(CAM_INTF_META_SENSOR_SENSITIVITY, metadata)) {
   1848         int16_t isoSpeed = *(int32_t *)POINTER_OF(
   1849                 CAM_INTF_META_SENSOR_SENSITIVITY, metadata);
   1850         exif->addEntry(EXIFTAGID_ISO_SPEED_RATING,
   1851                    EXIF_SHORT,
   1852                    1,
   1853                    (void *)&(isoSpeed));
   1854     }
   1855 
   1856     if (IS_PARM_VALID(CAM_INTF_META_SENSOR_EXPOSURE_TIME, metadata)) {
   1857         int64_t sensor_exposure_time = *(int64_t *)POINTER_OF(
   1858                 CAM_INTF_META_SENSOR_EXPOSURE_TIME, metadata);
   1859         rat_t sensorExpTime;
   1860         rc = getExifExpTimeInfo(&sensorExpTime, sensor_exposure_time);
   1861         if (rc == NO_ERROR){
   1862             exif->addEntry(EXIFTAGID_EXPOSURE_TIME,
   1863                     EXIF_RATIONAL,
   1864                     1,
   1865                     (void *)&(sensorExpTime));
   1866         } else {
   1867             ALOGE("%s: getExifExpTimeInfo failed", __func__);
   1868         }
   1869     }
   1870 
   1871     if (strlen(jpeg_settings->gps_processing_method) > 0) {
   1872         char gpsProcessingMethod[
   1873                     EXIF_ASCII_PREFIX_SIZE + GPS_PROCESSING_METHOD_SIZE];
   1874         count = 0;
   1875         rc = getExifGpsProcessingMethod(gpsProcessingMethod,
   1876                 count, jpeg_settings->gps_processing_method);
   1877         if(rc == NO_ERROR) {
   1878             exif->addEntry(EXIFTAGID_GPS_PROCESSINGMETHOD,
   1879                     EXIF_ASCII,
   1880                     count,
   1881                     (void *)gpsProcessingMethod);
   1882         } else {
   1883             ALOGE("%s: getExifGpsProcessingMethod failed", __func__);
   1884         }
   1885     }
   1886 
   1887     if (jpeg_settings->gps_coordinates_valid) {
   1888 
   1889         //latitude
   1890         rat_t latitude[3];
   1891         char latRef[2];
   1892         rc = getExifLatitude(latitude, latRef,
   1893                 jpeg_settings->gps_coordinates[0]);
   1894         if(rc == NO_ERROR) {
   1895             exif->addEntry(EXIFTAGID_GPS_LATITUDE,
   1896                            EXIF_RATIONAL,
   1897                            3,
   1898                            (void *)latitude);
   1899             exif->addEntry(EXIFTAGID_GPS_LATITUDE_REF,
   1900                            EXIF_ASCII,
   1901                            2,
   1902                            (void *)latRef);
   1903         } else {
   1904             ALOGE("%s: getExifLatitude failed", __func__);
   1905         }
   1906 
   1907         //longitude
   1908         rat_t longitude[3];
   1909         char lonRef[2];
   1910         rc = getExifLongitude(longitude, lonRef,
   1911                 jpeg_settings->gps_coordinates[1]);
   1912         if(rc == NO_ERROR) {
   1913             exif->addEntry(EXIFTAGID_GPS_LONGITUDE,
   1914                            EXIF_RATIONAL,
   1915                            3,
   1916                            (void *)longitude);
   1917 
   1918             exif->addEntry(EXIFTAGID_GPS_LONGITUDE_REF,
   1919                            EXIF_ASCII,
   1920                            2,
   1921                            (void *)lonRef);
   1922         } else {
   1923             ALOGE("%s: getExifLongitude failed", __func__);
   1924         }
   1925 
   1926         //altitude
   1927         rat_t altitude;
   1928         char altRef;
   1929         rc = getExifAltitude(&altitude, &altRef,
   1930                 jpeg_settings->gps_coordinates[2]);
   1931         if(rc == NO_ERROR) {
   1932             exif->addEntry(EXIFTAGID_GPS_ALTITUDE,
   1933                            EXIF_RATIONAL,
   1934                            1,
   1935                            (void *)&(altitude));
   1936 
   1937             exif->addEntry(EXIFTAGID_GPS_ALTITUDE_REF,
   1938                            EXIF_BYTE,
   1939                            1,
   1940                            (void *)&altRef);
   1941         } else {
   1942             ALOGE("%s: getExifAltitude failed", __func__);
   1943         }
   1944     }
   1945 
   1946     if (jpeg_settings->gps_timestamp_valid) {
   1947 
   1948         char gpsDateStamp[20];
   1949         rat_t gpsTimeStamp[3];
   1950         rc = getExifGpsDateTimeStamp(gpsDateStamp, 20, gpsTimeStamp,
   1951                 jpeg_settings->gps_timestamp);
   1952         if(rc == NO_ERROR) {
   1953             exif->addEntry(EXIFTAGID_GPS_DATESTAMP,
   1954                            EXIF_ASCII,
   1955                            strlen(gpsDateStamp) + 1,
   1956                            (void *)gpsDateStamp);
   1957 
   1958             exif->addEntry(EXIFTAGID_GPS_TIMESTAMP,
   1959                            EXIF_RATIONAL,
   1960                            3,
   1961                            (void *)gpsTimeStamp);
   1962         } else {
   1963             ALOGE("%s: getExifGpsDataTimeStamp failed", __func__);
   1964         }
   1965     }
   1966 
   1967     if (IS_PARM_VALID(CAM_INTF_PARM_EV, metadata) &&
   1968             IS_PARM_VALID(CAM_INTF_PARM_EV_STEP, metadata)) {
   1969         int32_t exposure_comp = *(int32_t *)POINTER_OF(
   1970                 CAM_INTF_PARM_EV, metadata);
   1971         cam_rational_type_t comp_step = *(cam_rational_type_t *)POINTER_OF(
   1972                 CAM_INTF_PARM_EV_STEP, metadata);
   1973         srat_t exposure_val;
   1974         rc = getExifExposureValue(&exposure_val, exposure_comp, comp_step);
   1975         if(rc == NO_ERROR) {
   1976             exif->addEntry(EXIFTAGID_EXPOSURE_BIAS_VALUE,
   1977                        EXIF_SRATIONAL,
   1978                        1,
   1979                        (void *)(&exposure_val));
   1980         } else {
   1981             ALOGE("%s: getExifExposureValue failed ", __func__);
   1982         }
   1983     }
   1984 
   1985     char value[PROPERTY_VALUE_MAX];
   1986     if (property_get("ro.product.manufacturer", value, "QCOM-AA") > 0) {
   1987         exif->addEntry(EXIFTAGID_MAKE,
   1988                        EXIF_ASCII,
   1989                        strlen(value) + 1,
   1990                        (void *)value);
   1991     } else {
   1992         ALOGE("%s: getExifMaker failed", __func__);
   1993     }
   1994 
   1995     if (property_get("ro.product.model", value, "QCAM-AA") > 0) {
   1996         exif->addEntry(EXIFTAGID_MODEL,
   1997                        EXIF_ASCII,
   1998                        strlen(value) + 1,
   1999                        (void *)value);
   2000     } else {
   2001         ALOGE("%s: getExifModel failed", __func__);
   2002     }
   2003 
   2004     return exif;
   2005 }
   2006 
   2007 void QCamera3PicChannel::overrideYuvSize(uint32_t width, uint32_t height)
   2008 {
   2009    mYuvWidth = width;
   2010    mYuvHeight = height;
   2011 }
   2012 
   2013 int QCamera3PicChannel::kMaxBuffers = 1;
   2014 
   2015 /*===========================================================================
   2016  * FUNCTION   : QCamera3ReprocessChannel
   2017  *
   2018  * DESCRIPTION: constructor of QCamera3ReprocessChannel
   2019  *
   2020  * PARAMETERS :
   2021  *   @cam_handle : camera handle
   2022  *   @cam_ops    : ptr to camera ops table
   2023  *   @pp_mask    : post-proccess feature mask
   2024  *
   2025  * RETURN     : none
   2026  *==========================================================================*/
   2027 QCamera3ReprocessChannel::QCamera3ReprocessChannel(uint32_t cam_handle,
   2028                                                  mm_camera_ops_t *cam_ops,
   2029                                                  channel_cb_routine cb_routine,
   2030                                                  cam_padding_info_t *paddingInfo,
   2031                                                  void *userData, void *ch_hdl) :
   2032     QCamera3Channel(cam_handle, cam_ops, cb_routine, paddingInfo, userData),
   2033     picChHandle(ch_hdl),
   2034     m_pSrcChannel(NULL),
   2035     m_pMetaChannel(NULL),
   2036     mMemory(NULL)
   2037 {
   2038     memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles));
   2039 }
   2040 
   2041 
   2042 /*===========================================================================
   2043  * FUNCTION   : QCamera3ReprocessChannel
   2044  *
   2045  * DESCRIPTION: constructor of QCamera3ReprocessChannel
   2046  *
   2047  * PARAMETERS :
   2048  *   @cam_handle : camera handle
   2049  *   @cam_ops    : ptr to camera ops table
   2050  *   @pp_mask    : post-proccess feature mask
   2051  *
   2052  * RETURN     : none
   2053  *==========================================================================*/
   2054 int32_t QCamera3ReprocessChannel::initialize()
   2055 {
   2056     int32_t rc = NO_ERROR;
   2057     mm_camera_channel_attr_t attr;
   2058 
   2059     memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
   2060     attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS;
   2061     attr.max_unmatched_frames = 1;
   2062 
   2063     rc = init(&attr, NULL);
   2064     if (rc < 0) {
   2065         ALOGE("%s: init failed", __func__);
   2066     }
   2067     return rc;
   2068 }
   2069 
   2070 
   2071 /*===========================================================================
   2072  * FUNCTION   : QCamera3ReprocessChannel
   2073  *
   2074  * DESCRIPTION: constructor of QCamera3ReprocessChannel
   2075  *
   2076  * PARAMETERS :
   2077  *   @cam_handle : camera handle
   2078  *   @cam_ops    : ptr to camera ops table
   2079  *   @pp_mask    : post-proccess feature mask
   2080  *
   2081  * RETURN     : none
   2082  *==========================================================================*/
   2083 void QCamera3ReprocessChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
   2084                                   QCamera3Stream *stream)
   2085 {
   2086     //Got the pproc data callback. Now send to jpeg encoding
   2087     uint8_t frameIndex;
   2088     mm_camera_super_buf_t* frame = NULL;
   2089     QCamera3PicChannel *obj = (QCamera3PicChannel *)picChHandle;
   2090 
   2091     if(!super_frame) {
   2092          ALOGE("%s: Invalid Super buffer",__func__);
   2093          return;
   2094     }
   2095 
   2096     if(super_frame->num_bufs != 1) {
   2097          ALOGE("%s: Multiple streams are not supported",__func__);
   2098          return;
   2099     }
   2100     if(super_frame->bufs[0] == NULL ) {
   2101          ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
   2102                   __func__);
   2103          return;
   2104     }
   2105 
   2106     frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
   2107     frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
   2108     if (frame == NULL) {
   2109        ALOGE("%s: Error allocating memory to save received_frame structure.",
   2110                                                                     __func__);
   2111        if(stream) {
   2112            stream->bufDone(frameIndex);
   2113        }
   2114        return;
   2115     }
   2116     *frame = *super_frame;
   2117     obj->m_postprocessor.processPPData(frame);
   2118     free(super_frame);
   2119     return;
   2120 }
   2121 
   2122 /*===========================================================================
   2123  * FUNCTION   : QCamera3ReprocessChannel
   2124  *
   2125  * DESCRIPTION: default constructor of QCamera3ReprocessChannel
   2126  *
   2127  * PARAMETERS : none
   2128  *
   2129  * RETURN     : none
   2130  *==========================================================================*/
   2131 QCamera3ReprocessChannel::QCamera3ReprocessChannel() :
   2132     m_pSrcChannel(NULL),
   2133     m_pMetaChannel(NULL)
   2134 {
   2135 }
   2136 
   2137 /*===========================================================================
   2138  * FUNCTION   : getStreamBufs
   2139  *
   2140  * DESCRIPTION: register the buffers of the reprocess channel
   2141  *
   2142  * PARAMETERS : none
   2143  *
   2144  * RETURN     : QCamera3Memory *
   2145  *==========================================================================*/
   2146 QCamera3Memory* QCamera3ReprocessChannel::getStreamBufs(uint32_t len)
   2147 {
   2148    int rc = 0;
   2149 
   2150     mMemory = new QCamera3HeapMemory();
   2151     if (!mMemory) {
   2152         ALOGE("%s: unable to create reproc memory", __func__);
   2153         return NULL;
   2154     }
   2155 
   2156     //Queue YUV buffers in the beginning mQueueAll = true
   2157     rc = mMemory->allocate(2, len, true);
   2158     if (rc < 0) {
   2159         ALOGE("%s: unable to allocate reproc memory", __func__);
   2160         delete mMemory;
   2161         mMemory = NULL;
   2162         return NULL;
   2163     }
   2164     return mMemory;
   2165 }
   2166 
   2167 /*===========================================================================
   2168  * FUNCTION   : getStreamBufs
   2169  *
   2170  * DESCRIPTION: register the buffers of the reprocess channel
   2171  *
   2172  * PARAMETERS : none
   2173  *
   2174  * RETURN     :
   2175  *==========================================================================*/
   2176 void QCamera3ReprocessChannel::putStreamBufs()
   2177 {
   2178     mMemory->deallocate();
   2179     delete mMemory;
   2180     mMemory = NULL;
   2181 }
   2182 
   2183 /*===========================================================================
   2184  * FUNCTION   : ~QCamera3ReprocessChannel
   2185  *
   2186  * DESCRIPTION: destructor of QCamera3ReprocessChannel
   2187  *
   2188  * PARAMETERS : none
   2189  *
   2190  * RETURN     : none
   2191  *==========================================================================*/
   2192 QCamera3ReprocessChannel::~QCamera3ReprocessChannel()
   2193 {
   2194 }
   2195 
   2196 /*===========================================================================
   2197  * FUNCTION   : getStreamBySrcHandle
   2198  *
   2199  * DESCRIPTION: find reprocess stream by its source stream handle
   2200  *
   2201  * PARAMETERS :
   2202  *   @srcHandle : source stream handle
   2203  *
   2204  * RETURN     : ptr to reprocess stream if found. NULL if not found
   2205  *==========================================================================*/
   2206 QCamera3Stream * QCamera3ReprocessChannel::getStreamBySrcHandle(uint32_t srcHandle)
   2207 {
   2208     QCamera3Stream *pStream = NULL;
   2209 
   2210     for (int i = 0; i < m_numStreams; i++) {
   2211         if (mSrcStreamHandles[i] == srcHandle) {
   2212             pStream = mStreams[i];
   2213             break;
   2214         }
   2215     }
   2216     return pStream;
   2217 }
   2218 
   2219 /*===========================================================================
   2220  * FUNCTION   : getSrcStreamBySrcHandle
   2221  *
   2222  * DESCRIPTION: find source stream by source stream handle
   2223  *
   2224  * PARAMETERS :
   2225  *   @srcHandle : source stream handle
   2226  *
   2227  * RETURN     : ptr to reprocess stream if found. NULL if not found
   2228  *==========================================================================*/
   2229 QCamera3Stream * QCamera3ReprocessChannel::getSrcStreamBySrcHandle(uint32_t srcHandle)
   2230 {
   2231     QCamera3Stream *pStream = NULL;
   2232 
   2233     for (int i = 0; i < m_numStreams; i++) {
   2234         if (mSrcStreamHandles[i] == srcHandle) {
   2235             pStream = m_pSrcChannel->getStreamByIndex(i);
   2236             break;
   2237         }
   2238     }
   2239     return pStream;
   2240 }
   2241 
   2242 /*===========================================================================
   2243  * FUNCTION   : metadataBufDone
   2244  *
   2245  * DESCRIPTION: buf done method for a metadata buffer
   2246  *
   2247  * PARAMETERS :
   2248  *   @recvd_frame : received metadata frame
   2249  *
   2250  * RETURN     :
   2251  *==========================================================================*/
   2252 int32_t QCamera3ReprocessChannel::metadataBufDone(mm_camera_super_buf_t *recvd_frame)
   2253 {
   2254    int32_t rc;
   2255    rc = ((QCamera3MetadataChannel*)m_pMetaChannel)->bufDone(recvd_frame);
   2256    free(recvd_frame);
   2257    recvd_frame = NULL;
   2258    return rc;
   2259 }
   2260 
   2261 /*===========================================================================
   2262  * FUNCTION   : doReprocess
   2263  *
   2264  * DESCRIPTION: request to do a reprocess on the frame
   2265  *
   2266  * PARAMETERS :
   2267  *   @frame   : frame to be performed a reprocess
   2268  *
   2269  * RETURN     : int32_t type of status
   2270  *              NO_ERROR  -- success
   2271  *              none-zero failure code
   2272  *==========================================================================*/
   2273 int32_t QCamera3ReprocessChannel::doReprocess(mm_camera_super_buf_t *frame,
   2274                                               mm_camera_super_buf_t *meta_frame)
   2275 {
   2276     int32_t rc = 0;
   2277     if (m_numStreams < 1) {
   2278         ALOGE("%s: No reprocess stream is created", __func__);
   2279         return -1;
   2280     }
   2281     if (m_pSrcChannel == NULL) {
   2282         ALOGE("%s: No source channel for reprocess", __func__);
   2283         return -1;
   2284     }
   2285     for (int i = 0; i < frame->num_bufs; i++) {
   2286         QCamera3Stream *pStream = getStreamBySrcHandle(frame->bufs[i]->stream_id);
   2287         if (pStream != NULL) {
   2288             cam_stream_parm_buffer_t param;
   2289             memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
   2290             param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
   2291             param.reprocess.buf_index = frame->bufs[i]->buf_idx;
   2292             if (meta_frame != NULL) {
   2293                param.reprocess.meta_present = 1;
   2294                param.reprocess.meta_stream_handle = m_pMetaChannel->mStreams[0]->getMyServerID();
   2295                param.reprocess.meta_buf_index = meta_frame->bufs[0]->buf_idx;
   2296             }
   2297             rc = pStream->setParameter(param);
   2298             if (rc != NO_ERROR) {
   2299                 ALOGE("%s: stream setParameter for reprocess failed", __func__);
   2300                 break;
   2301             }
   2302         }
   2303     }
   2304     return rc;
   2305 }
   2306 
   2307 int32_t QCamera3ReprocessChannel::doReprocessOffline(mm_camera_super_buf_t *frame,
   2308         metadata_buffer_t *metadata)
   2309 {
   2310     int32_t rc = 0;
   2311     OfflineBuffer mappedBuffer;
   2312     if (m_numStreams < 1) {
   2313         ALOGE("%s: No reprocess stream is created", __func__);
   2314         return -1;
   2315     }
   2316     if (m_pSrcChannel == NULL) {
   2317         ALOGE("%s: No source channel for reprocess", __func__);
   2318         return -1;
   2319     }
   2320 
   2321     uint32_t buf_idx = 0;
   2322     for (int i = 0; i < frame->num_bufs; i++) {
   2323         QCamera3Stream *pStream = getStreamBySrcHandle(frame->bufs[i]->stream_id);
   2324         QCamera3Stream *pSrcStream = getSrcStreamBySrcHandle(frame->bufs[i]->stream_id);
   2325         if (pStream != NULL && pSrcStream != NULL) {
   2326 
   2327             rc = mStreams[i]->mapBuf(
   2328                     CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
   2329                     buf_idx, -1,
   2330                     frame->bufs[i]->fd, frame->bufs[i]->frame_len);
   2331 
   2332             if (rc == NO_ERROR) {
   2333                 memset(&mappedBuffer, 0, sizeof(OfflineBuffer));
   2334                 mappedBuffer.index = buf_idx;
   2335                 mappedBuffer.stream = pStream;
   2336                 mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF;
   2337                 mOfflineBuffers.push_back(mappedBuffer);
   2338 
   2339                 cam_stream_parm_buffer_t param;
   2340                 memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
   2341                 param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
   2342                 param.reprocess.buf_index = buf_idx;
   2343 
   2344                 param.reprocess.meta_present = 1;
   2345                 char* private_data = (char *)POINTER_OF(
   2346                         CAM_INTF_META_PRIVATE_DATA, metadata);
   2347                 memcpy(param.reprocess.private_data, private_data,
   2348                         MAX_METADATA_PAYLOAD_SIZE);
   2349 
   2350                 // Find crop info for reprocess stream
   2351                 cam_crop_data_t *crop_data = (cam_crop_data_t *)
   2352                         POINTER_OF(CAM_INTF_META_CROP_DATA, metadata);
   2353                 for (int j = 0; j < crop_data->num_of_streams; j++) {
   2354                     if (crop_data->crop_info[j].stream_id ==
   2355                            pSrcStream->getMyServerID()) {
   2356                         param.reprocess.crop_rect  =
   2357                                 crop_data->crop_info[j].crop;
   2358                         break;
   2359                     }
   2360                 }
   2361                 rc = pStream->setParameter(param);
   2362                 if (rc != NO_ERROR) {
   2363                     ALOGE("%s: stream setParameter for reprocess failed", __func__);
   2364                     break;
   2365                 }
   2366             }
   2367         }
   2368     }
   2369     return rc;
   2370 }
   2371 
   2372 /*===========================================================================
   2373 * FUNCTION : stop
   2374 *
   2375 * DESCRIPTION: Unmap offline buffers and stop channel
   2376 *
   2377 * PARAMETERS : none
   2378 *
   2379 * RETURN : int32_t type of status
   2380 * NO_ERROR -- success
   2381 * none-zero failure code
   2382 *==========================================================================*/
   2383 int32_t QCamera3ReprocessChannel::stop()
   2384 {
   2385     if (!mOfflineBuffers.empty()) {
   2386         QCamera3Stream *stream = NULL;
   2387         List<OfflineBuffer>::iterator it = mOfflineBuffers.begin();
   2388         int error = NO_ERROR;
   2389         for( ; it != mOfflineBuffers.end(); it++) {
   2390             stream = (*it).stream;
   2391             if (NULL != stream) {
   2392                 error = stream->unmapBuf((*it).type,
   2393                         (*it).index,
   2394                         -1);
   2395                 if (NO_ERROR != error) {
   2396                     ALOGE("%s: Error during offline buffer unmap %d",
   2397                             __func__, error);
   2398                 }
   2399             }
   2400         }
   2401         mOfflineBuffers.clear();
   2402     }
   2403 
   2404     return QCamera3Channel::stop();
   2405 }
   2406 
   2407 /*===========================================================================
   2408  * FUNCTION   : doReprocess
   2409  *
   2410  * DESCRIPTION: request to do a reprocess on the frame
   2411  *
   2412  * PARAMETERS :
   2413  *   @buf_fd     : fd to the input buffer that needs reprocess
   2414  *   @buf_lenght : length of the input buffer
   2415  *   @ret_val    : result of reprocess.
   2416  *                 Example: Could be faceID in case of register face image.
   2417  *
   2418  * RETURN     : int32_t type of status
   2419  *              NO_ERROR  -- success
   2420  *              none-zero failure code
   2421  *==========================================================================*/
   2422 int32_t QCamera3ReprocessChannel::doReprocess(int buf_fd,
   2423                                               uint32_t buf_length,
   2424                                               int32_t &ret_val,
   2425                                               mm_camera_super_buf_t *meta_frame)
   2426 {
   2427     int32_t rc = 0;
   2428     if (m_numStreams < 1) {
   2429         ALOGE("%s: No reprocess stream is created", __func__);
   2430         return -1;
   2431     }
   2432     if (meta_frame == NULL) {
   2433         ALOGE("%s: Did not get corresponding metadata in time", __func__);
   2434         return -1;
   2435     }
   2436 
   2437     uint32_t buf_idx = 0;
   2438     for (int i = 0; i < m_numStreams; i++) {
   2439         rc = mStreams[i]->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
   2440                                  buf_idx, -1,
   2441                                  buf_fd, buf_length);
   2442 
   2443         if (rc == NO_ERROR) {
   2444             cam_stream_parm_buffer_t param;
   2445             memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
   2446             param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
   2447             param.reprocess.buf_index = buf_idx;
   2448             param.reprocess.meta_present = 1;
   2449             param.reprocess.meta_stream_handle = m_pMetaChannel->mStreams[0]->getMyServerID();
   2450             param.reprocess.meta_buf_index = meta_frame->bufs[0]->buf_idx;
   2451             rc = mStreams[i]->setParameter(param);
   2452             if (rc == NO_ERROR) {
   2453                 ret_val = param.reprocess.ret_val;
   2454             }
   2455             mStreams[i]->unmapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
   2456                                   buf_idx, -1);
   2457         }
   2458     }
   2459     return rc;
   2460 }
   2461 
   2462 /*===========================================================================
   2463  * FUNCTION   : addReprocStreamsFromSource
   2464  *
   2465  * DESCRIPTION: add reprocess streams from input source channel
   2466  *
   2467  * PARAMETERS :
   2468  *   @config         : pp feature configuration
   2469  *   @pSrcChannel    : ptr to input source channel that needs reprocess
   2470  *   @pMetaChannel   : ptr to metadata channel to get corresp. metadata
   2471  *   @offline        : configure for offline reprocessing
   2472  *
   2473  * RETURN     : int32_t type of status
   2474  *              NO_ERROR  -- success
   2475  *              none-zero failure code
   2476  *==========================================================================*/
   2477 int32_t QCamera3ReprocessChannel::addReprocStreamsFromSource(cam_pp_feature_config_t &pp_config,
   2478                                                              QCamera3Channel *pSrcChannel,
   2479                                                              QCamera3Channel *pMetaChannel)
   2480 {
   2481     int32_t rc = 0;
   2482     QCamera3Stream *pSrcStream = pSrcChannel->getStreamByIndex(0);
   2483     if (pSrcStream == NULL) {
   2484        ALOGE("%s: source channel doesn't have a stream", __func__);
   2485        return BAD_VALUE;
   2486     }
   2487     cam_stream_reproc_config_t reprocess_config;
   2488     cam_dimension_t streamDim;
   2489     cam_stream_type_t streamType;
   2490     cam_format_t streamFormat;
   2491     cam_frame_len_offset_t frameOffset;
   2492     int num_buffers = 2;
   2493 
   2494     streamType = CAM_STREAM_TYPE_OFFLINE_PROC;
   2495     pSrcStream->getFormat(streamFormat);
   2496     pSrcStream->getFrameDimension(streamDim);
   2497     pSrcStream->getFrameOffset(frameOffset);
   2498     reprocess_config.pp_type = CAM_OFFLINE_REPROCESS_TYPE;
   2499 
   2500     reprocess_config.offline.input_fmt = streamFormat;
   2501     reprocess_config.offline.input_dim = streamDim;
   2502     reprocess_config.offline.input_buf_planes.plane_info = frameOffset;
   2503     reprocess_config.offline.num_of_bufs = num_buffers;
   2504     reprocess_config.offline.input_stream_type = pSrcStream->getMyType();
   2505 
   2506 
   2507     reprocess_config.pp_feature_config = pp_config;
   2508     mSrcStreamHandles[m_numStreams] = pSrcStream->getMyHandle();
   2509 
   2510     // pp feature config
   2511     if (pp_config.feature_mask & CAM_QCOM_FEATURE_ROTATION) {
   2512         if (pp_config.rotation == ROTATE_90 ||
   2513             pp_config.rotation == ROTATE_270) {
   2514             // rotated by 90 or 270, need to switch width and height
   2515             int32_t temp = streamDim.height;
   2516             streamDim.height = streamDim.width;
   2517             streamDim.width = temp;
   2518         }
   2519     }
   2520 
   2521     QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
   2522                                                m_handle,
   2523                                                m_camOps,
   2524                                                mPaddingInfo,
   2525                                                (QCamera3Channel*)this);
   2526     if (pStream == NULL) {
   2527         ALOGE("%s: No mem for Stream", __func__);
   2528         return NO_MEMORY;
   2529     }
   2530 
   2531     rc = pStream->init(streamType, streamFormat, streamDim, &reprocess_config,
   2532                        num_buffers,QCamera3Channel::streamCbRoutine, this);
   2533 
   2534 
   2535     if (rc == 0) {
   2536         mStreams[m_numStreams] = pStream;
   2537         m_numStreams++;
   2538     } else {
   2539         ALOGE("%s: failed to create reprocess stream", __func__);
   2540         delete pStream;
   2541     }
   2542 
   2543     if (rc == NO_ERROR) {
   2544         m_pSrcChannel = pSrcChannel;
   2545         m_pMetaChannel = pMetaChannel;
   2546     }
   2547     if(m_camOps->request_super_buf(m_camHandle,m_handle,1) < 0) {
   2548         ALOGE("%s: Request for super buffer failed",__func__);
   2549     }
   2550     return rc;
   2551 }
   2552 
   2553 cam_dimension_t QCamera3SupportChannel::kDim = {640, 480};
   2554 
   2555 QCamera3SupportChannel::QCamera3SupportChannel(uint32_t cam_handle,
   2556                     mm_camera_ops_t *cam_ops,
   2557                     cam_padding_info_t *paddingInfo,
   2558                     void *userData) :
   2559                         QCamera3Channel(cam_handle, cam_ops,
   2560                                 NULL, paddingInfo, userData),
   2561                         mMemory(NULL)
   2562 {
   2563 }
   2564 
   2565 QCamera3SupportChannel::~QCamera3SupportChannel()
   2566 {
   2567     if (m_bIsActive)
   2568         stop();
   2569 
   2570     if (mMemory) {
   2571         mMemory->deallocate();
   2572         delete mMemory;
   2573         mMemory = NULL;
   2574     }
   2575 }
   2576 
   2577 int32_t QCamera3SupportChannel::initialize()
   2578 {
   2579     int32_t rc;
   2580 
   2581     if (mMemory || m_numStreams > 0) {
   2582         ALOGE("%s: Support channel already initialized", __func__);
   2583         return -EINVAL;
   2584     }
   2585 
   2586     rc = init(NULL, NULL);
   2587     if (rc < 0) {
   2588         ALOGE("%s: init failed", __func__);
   2589         return rc;
   2590     }
   2591 
   2592     // Hardcode to VGA size for now
   2593     rc = QCamera3Channel::addStream(CAM_STREAM_TYPE_CALLBACK,
   2594         CAM_FORMAT_YUV_420_NV21, kDim, MIN_STREAMING_BUFFER_NUM);
   2595     if (rc < 0) {
   2596         ALOGE("%s: addStream failed", __func__);
   2597     }
   2598     return rc;
   2599 }
   2600 
   2601 int32_t QCamera3SupportChannel::request(buffer_handle_t * /*buffer*/,
   2602                                                 uint32_t /*frameNumber*/)
   2603 {
   2604     return NO_ERROR;
   2605 }
   2606 
   2607 void QCamera3SupportChannel::streamCbRoutine(
   2608                         mm_camera_super_buf_t *super_frame,
   2609                         QCamera3Stream * /*stream*/)
   2610 {
   2611     if (super_frame == NULL || super_frame->num_bufs != 1) {
   2612         ALOGE("%s: super_frame is not valid", __func__);
   2613         return;
   2614     }
   2615     bufDone(super_frame);
   2616     free(super_frame);
   2617 }
   2618 
   2619 QCamera3Memory* QCamera3SupportChannel::getStreamBufs(uint32_t len)
   2620 {
   2621     int rc;
   2622 
   2623     mMemory = new QCamera3HeapMemory();
   2624     if (!mMemory) {
   2625         ALOGE("%s: unable to create heap memory", __func__);
   2626         return NULL;
   2627     }
   2628     rc = mMemory->allocate(MIN_STREAMING_BUFFER_NUM, len, true);
   2629     if (rc < 0) {
   2630         ALOGE("%s: unable to allocate heap memory", __func__);
   2631         delete mMemory;
   2632         mMemory = NULL;
   2633         return NULL;
   2634     }
   2635     return mMemory;
   2636 }
   2637 
   2638 void QCamera3SupportChannel::putStreamBufs()
   2639 {
   2640     mMemory->deallocate();
   2641     delete mMemory;
   2642     mMemory = NULL;
   2643 }
   2644 
   2645 }; // namespace qcamera
   2646