Home | History | Annotate | Download | only in HAL3
      1 /* Copyright (c) 2012-2015, 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 ATRACE_TAG ATRACE_TAG_CAMERA
     31 #define LOG_TAG "QCamera3Channel"
     32 //#define LOG_NDEBUG 0
     33 #include <fcntl.h>
     34 #include <stdlib.h>
     35 #include <cstdlib>
     36 #include <stdio.h>
     37 #include <string.h>
     38 #include <hardware/camera3.h>
     39 #include <system/camera_metadata.h>
     40 #include <gralloc_priv.h>
     41 #include <utils/Log.h>
     42 #include <utils/Errors.h>
     43 #include <utils/Trace.h>
     44 #include <cutils/properties.h>
     45 #include "QCamera3Channel.h"
     46 #include "QCamera3HWI.h"
     47 
     48 using namespace android;
     49 
     50 #define MIN_STREAMING_BUFFER_NUM 7+11
     51 
     52 namespace qcamera {
     53 static const char ExifAsciiPrefix[] =
     54     { 0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0 };          // "ASCII\0\0\0"
     55 static const char ExifUndefinedPrefix[] =
     56     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };   // "\0\0\0\0\0\0\0\0"
     57 
     58 #define EXIF_ASCII_PREFIX_SIZE           8   //(sizeof(ExifAsciiPrefix))
     59 #define FOCAL_LENGTH_DECIMAL_PRECISION   100
     60 
     61 #define VIDEO_FORMAT    CAM_FORMAT_YUV_420_NV12
     62 #define SNAPSHOT_FORMAT CAM_FORMAT_YUV_420_NV21
     63 #define PREVIEW_FORMAT  CAM_FORMAT_YUV_420_NV21
     64 #define DEFAULT_FORMAT  CAM_FORMAT_YUV_420_NV21
     65 #define CALLBACK_FORMAT CAM_FORMAT_YUV_420_NV21
     66 #define RAW_FORMAT      CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG
     67 
     68 /*===========================================================================
     69  * FUNCTION   : QCamera3Channel
     70  *
     71  * DESCRIPTION: constrcutor of QCamera3Channel
     72  *
     73  * PARAMETERS :
     74  *   @cam_handle : camera handle
     75  *   @cam_ops    : ptr to camera ops table
     76  *
     77  * RETURN     : none
     78  *==========================================================================*/
     79 QCamera3Channel::QCamera3Channel(uint32_t cam_handle,
     80                                mm_camera_ops_t *cam_ops,
     81                                channel_cb_routine cb_routine,
     82                                cam_padding_info_t *paddingInfo,
     83                                uint32_t postprocess_mask,
     84                                void *userData)
     85 {
     86     m_camHandle = cam_handle;
     87     m_camOps = cam_ops;
     88     m_bIsActive = false;
     89 
     90     m_handle = 0;
     91     m_numStreams = 0;
     92     memset(mStreams, 0, sizeof(mStreams));
     93     mUserData = userData;
     94 
     95     mStreamInfoBuf = NULL;
     96     mChannelCB = cb_routine;
     97     mPaddingInfo = paddingInfo;
     98 
     99     mPostProcMask = postprocess_mask;
    100 
    101     char prop[PROPERTY_VALUE_MAX];
    102     property_get("persist.camera.yuv.dump", prop, "0");
    103     mYUVDump = atoi(prop);
    104     mIsType = IS_TYPE_NONE;
    105 }
    106 
    107 /*===========================================================================
    108  * FUNCTION   : QCamera3Channel
    109  *
    110  * DESCRIPTION: default constrcutor of QCamera3Channel
    111  *
    112  * PARAMETERS : none
    113  *
    114  * RETURN     : none
    115  *==========================================================================*/
    116 QCamera3Channel::QCamera3Channel()
    117 {
    118     m_camHandle = 0;
    119     m_camOps = NULL;
    120     m_bIsActive = false;
    121 
    122     m_handle = 0;
    123     m_numStreams = 0;
    124     memset(mStreams, 0, sizeof(mStreams));
    125     mUserData = NULL;
    126 
    127     mStreamInfoBuf = NULL;
    128     mChannelCB = NULL;
    129     mPaddingInfo = NULL;
    130 
    131     mPostProcMask = 0;
    132 }
    133 
    134 /*===========================================================================
    135  * FUNCTION   : ~QCamera3Channel
    136  *
    137  * DESCRIPTION: destructor of QCamera3Channel
    138  *
    139  * PARAMETERS : none
    140  *
    141  * RETURN     : none
    142  *==========================================================================*/
    143 QCamera3Channel::~QCamera3Channel()
    144 {
    145     if (m_bIsActive)
    146         stop();
    147 
    148     for (int i = 0; i < m_numStreams; i++) {
    149         if (mStreams[i] != NULL) {
    150             delete mStreams[i];
    151             mStreams[i] = 0;
    152         }
    153     }
    154     if (m_handle) {
    155         m_camOps->delete_channel(m_camHandle, m_handle);
    156         ALOGE("%s: deleting channel %d", __func__, m_handle);
    157         m_handle = 0;
    158     }
    159     m_numStreams = 0;
    160 }
    161 
    162 /*===========================================================================
    163  * FUNCTION   : init
    164  *
    165  * DESCRIPTION: initialization of channel
    166  *
    167  * PARAMETERS :
    168  *   @attr    : channel bundle attribute setting
    169  *   @dataCB  : data notify callback
    170  *   @userData: user data ptr
    171  *
    172  * RETURN     : int32_t type of status
    173  *              NO_ERROR  -- success
    174  *              none-zero failure code
    175  *==========================================================================*/
    176 int32_t QCamera3Channel::init(mm_camera_channel_attr_t *attr,
    177                              mm_camera_buf_notify_t dataCB)
    178 {
    179     m_handle = m_camOps->add_channel(m_camHandle,
    180                                       attr,
    181                                       dataCB,
    182                                       this);
    183     if (m_handle == 0) {
    184         ALOGE("%s: Add channel failed", __func__);
    185         return UNKNOWN_ERROR;
    186     }
    187     return NO_ERROR;
    188 }
    189 
    190 /*===========================================================================
    191  * FUNCTION   : addStream
    192  *
    193  * DESCRIPTION: add a stream into channel
    194  *
    195  * PARAMETERS :
    196  *   @streamDim      : dimensions of the stream
    197  *   @streamRotation : rotation of the stream
    198  *   @minStreamBufNum: number of stream buffers needed
    199  *
    200  * RETURN     : int32_t type of status
    201  *              NO_ERROR  -- success
    202  *              none-zero failure code
    203  *==========================================================================*/
    204 int32_t QCamera3Channel::addStream(cam_stream_type_t streamType,
    205                                   cam_format_t streamFormat,
    206                                   cam_dimension_t streamDim,
    207                                   cam_rotation_t streamRotation,
    208                                   uint8_t minStreamBufNum,
    209                                   uint32_t postprocessMask,
    210                                   cam_is_type_t isType)
    211 {
    212     int32_t rc = NO_ERROR;
    213 
    214     if (m_numStreams >= 1) {
    215         ALOGE("%s: Only one stream per channel supported in v3 Hal", __func__);
    216         return BAD_VALUE;
    217     }
    218 
    219     if (m_numStreams >= MAX_STREAM_NUM_IN_BUNDLE) {
    220         ALOGE("%s: stream number (%d) exceeds max limit (%d)",
    221               __func__, m_numStreams, MAX_STREAM_NUM_IN_BUNDLE);
    222         return BAD_VALUE;
    223     }
    224     QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
    225                                                m_handle,
    226                                                m_camOps,
    227                                                mPaddingInfo,
    228                                                this);
    229     if (pStream == NULL) {
    230         ALOGE("%s: No mem for Stream", __func__);
    231         return NO_MEMORY;
    232     }
    233 
    234     rc = pStream->init(streamType, streamFormat, streamDim, streamRotation,
    235             NULL, minStreamBufNum, postprocessMask, isType, streamCbRoutine,
    236             this);
    237     if (rc == 0) {
    238         mStreams[m_numStreams] = pStream;
    239         m_numStreams++;
    240     } else {
    241         delete pStream;
    242     }
    243     return rc;
    244 }
    245 
    246 /*===========================================================================
    247  * FUNCTION   : start
    248  *
    249  * DESCRIPTION: start channel, which will start all streams belong to this channel
    250  *
    251  * PARAMETERS :
    252  *
    253  * RETURN     : int32_t type of status
    254  *              NO_ERROR  -- success
    255  *              none-zero failure code
    256  *==========================================================================*/
    257 int32_t QCamera3Channel::start()
    258 {
    259     ATRACE_CALL();
    260     int32_t rc = NO_ERROR;
    261 
    262     if (m_numStreams > 1) {
    263         ALOGE("%s: bundle not supported", __func__);
    264     } else if (m_numStreams == 0) {
    265         return NO_INIT;
    266     }
    267 
    268     if(m_bIsActive) {
    269         ALOGD("%s: Attempt to start active channel", __func__);
    270         return rc;
    271     }
    272 
    273     for (int i = 0; i < m_numStreams; i++) {
    274         if (mStreams[i] != NULL) {
    275             mStreams[i]->start();
    276         }
    277     }
    278     rc = m_camOps->start_channel(m_camHandle, m_handle);
    279 
    280     if (rc != NO_ERROR) {
    281         for (int i = 0; i < m_numStreams; i++) {
    282             if (mStreams[i] != NULL) {
    283                 mStreams[i]->stop();
    284             }
    285         }
    286     } else {
    287         m_bIsActive = true;
    288     }
    289 
    290     return rc;
    291 }
    292 
    293 /*===========================================================================
    294  * FUNCTION   : stop
    295  *
    296  * DESCRIPTION: stop a channel, which will stop all streams belong to this channel
    297  *
    298  * PARAMETERS : none
    299  *
    300  * RETURN     : int32_t type of status
    301  *              NO_ERROR  -- success
    302  *              none-zero failure code
    303  *==========================================================================*/
    304 int32_t QCamera3Channel::stop()
    305 {
    306     ATRACE_CALL();
    307     int32_t rc = NO_ERROR;
    308     if(!m_bIsActive) {
    309         ALOGE("%s: Attempt to stop inactive channel",__func__);
    310         return rc;
    311     }
    312 
    313     for (int i = 0; i < m_numStreams; i++) {
    314         if (mStreams[i] != NULL) {
    315             mStreams[i]->stop();
    316         }
    317     }
    318 
    319     rc = m_camOps->stop_channel(m_camHandle, m_handle);
    320 
    321     m_bIsActive = false;
    322     return rc;
    323 }
    324 
    325 /*===========================================================================
    326  * FUNCTION   : bufDone
    327  *
    328  * DESCRIPTION: return a stream buf back to kernel
    329  *
    330  * PARAMETERS :
    331  *   @recvd_frame  : stream buf frame to be returned
    332  *
    333  * RETURN     : int32_t type of status
    334  *              NO_ERROR  -- success
    335  *              none-zero failure code
    336  *==========================================================================*/
    337 int32_t QCamera3Channel::bufDone(mm_camera_super_buf_t *recvd_frame)
    338 {
    339     int32_t rc = NO_ERROR;
    340     for (int i = 0; i < recvd_frame->num_bufs; i++) {
    341          if (recvd_frame->bufs[i] != NULL) {
    342              for (int j = 0; j < m_numStreams; j++) {
    343                  if (mStreams[j] != NULL &&
    344                      mStreams[j]->getMyHandle() == recvd_frame->bufs[i]->stream_id) {
    345                      rc = mStreams[j]->bufDone(recvd_frame->bufs[i]->buf_idx);
    346                      break; // break loop j
    347                  }
    348              }
    349          }
    350     }
    351 
    352     return rc;
    353 }
    354 
    355 /*===========================================================================
    356  * FUNCTION   : getStreamTypeMask
    357  *
    358  * DESCRIPTION: Get bit mask of all stream types in this channel
    359  *
    360  * PARAMETERS : None
    361  *
    362  * RETURN     : Bit mask of all stream types in this channel
    363  *==========================================================================*/
    364 uint32_t QCamera3Channel::getStreamTypeMask()
    365 {
    366     uint32_t mask = 0;
    367     for (int i = 0; i < m_numStreams; i++) {
    368        mask |= (0x1 << mStreams[i]->getMyType());
    369     }
    370     return mask;
    371 }
    372 
    373 /*===========================================================================
    374  * FUNCTION   : getStreamID
    375  *
    376  * DESCRIPTION: Get StreamID of requested stream type
    377  *
    378  * PARAMETERS : streamMask
    379  *
    380  * RETURN     : Stream ID
    381  *==========================================================================*/
    382 uint32_t QCamera3Channel::getStreamID(uint32_t streamMask)
    383 {
    384     uint32_t streamID = 0;
    385     for (int i = 0; i < m_numStreams; i++) {
    386         if (streamMask == (uint32_t )(0x1 << mStreams[i]->getMyType())) {
    387             streamID = mStreams[i]->getMyServerID();
    388             break;
    389         }
    390     }
    391     return streamID;
    392 }
    393 
    394 /*===========================================================================
    395  * FUNCTION   : getStreamByHandle
    396  *
    397  * DESCRIPTION: return stream object by stream handle
    398  *
    399  * PARAMETERS :
    400  *   @streamHandle : stream handle
    401  *
    402  * RETURN     : stream object. NULL if not found
    403  *==========================================================================*/
    404 QCamera3Stream *QCamera3Channel::getStreamByHandle(uint32_t streamHandle)
    405 {
    406     for (int i = 0; i < m_numStreams; i++) {
    407         if (mStreams[i] != NULL && mStreams[i]->getMyHandle() == streamHandle) {
    408             return mStreams[i];
    409         }
    410     }
    411     return NULL;
    412 }
    413 
    414 /*===========================================================================
    415  * FUNCTION   : getStreamByIndex
    416  *
    417  * DESCRIPTION: return stream object by index
    418  *
    419  * PARAMETERS :
    420  *   @streamHandle : stream handle
    421  *
    422  * RETURN     : stream object. NULL if not found
    423  *==========================================================================*/
    424 QCamera3Stream *QCamera3Channel::getStreamByIndex(uint8_t index)
    425 {
    426     if (index < m_numStreams) {
    427         return mStreams[index];
    428     }
    429     return NULL;
    430 }
    431 
    432 /*===========================================================================
    433  * FUNCTION   : streamCbRoutine
    434  *
    435  * DESCRIPTION: callback routine for stream
    436  *
    437  * PARAMETERS :
    438  *   @streamHandle : stream handle
    439  *
    440  * RETURN     : stream object. NULL if not found
    441  *==========================================================================*/
    442 void QCamera3Channel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
    443                 QCamera3Stream *stream, void *userdata)
    444 {
    445     QCamera3Channel *channel = (QCamera3Channel *)userdata;
    446     if (channel == NULL) {
    447         ALOGE("%s: invalid channel pointer", __func__);
    448         return;
    449     }
    450     channel->streamCbRoutine(super_frame, stream);
    451 }
    452 
    453 /*===========================================================================
    454  * FUNCTION   : dumpYUV
    455  *
    456  * DESCRIPTION: function to dump the YUV data from ISP/pproc
    457  *
    458  * PARAMETERS :
    459  *   @frame   : frame to be dumped
    460  *   @dim     : dimension of the stream
    461  *   @offset  : offset of the data
    462  *   @name    : 1 if it is ISP output/pproc input, 2 if it is pproc output
    463  *
    464  * RETURN  :
    465  *==========================================================================*/
    466 void QCamera3Channel::dumpYUV(mm_camera_buf_def_t *frame, cam_dimension_t dim,
    467                               cam_frame_len_offset_t offset, uint8_t name)
    468 {
    469    char buf[64];
    470    memset(buf, 0, sizeof(buf));
    471    static int counter = 0;
    472    /* Note that the image dimension will be the unrotated stream dimension.
    473     * If you feel that the image would have been rotated during reprocess
    474     * then swap the dimensions while opening the file
    475     * */
    476    snprintf(buf, sizeof(buf), "/data/local/tmp/%d_%d_%d_%dx%d.yuv",
    477             name, counter, frame->frame_idx, dim.width, dim.height);
    478    counter++;
    479    int file_fd = open(buf, O_RDWR| O_CREAT, 0644);
    480    if (file_fd >= 0) {
    481       int written_len = write(file_fd, frame->buffer, offset.frame_len);
    482       ALOGE("%s: written number of bytes %d", __func__, written_len);
    483       close(file_fd);
    484    } else {
    485       ALOGE("%s: failed to open file to dump image", __func__);
    486    }
    487 
    488 }
    489 
    490 /*===========================================================================
    491  * FUNCTION   : QCamera3RegularChannel
    492  *
    493  * DESCRIPTION: constructor of QCamera3RegularChannel
    494  *
    495  * PARAMETERS :
    496  *   @cam_handle : camera handle
    497  *   @cam_ops    : ptr to camera ops table
    498  *   @cb_routine : callback routine to frame aggregator
    499  *   @stream     : camera3_stream_t structure
    500  *   @stream_type: Channel stream type
    501  *
    502  * RETURN     : none
    503  *==========================================================================*/
    504 QCamera3RegularChannel::QCamera3RegularChannel(uint32_t cam_handle,
    505                     mm_camera_ops_t *cam_ops,
    506                     channel_cb_routine cb_routine,
    507                     cam_padding_info_t *paddingInfo,
    508                     void *userData,
    509                     camera3_stream_t *stream,
    510                     cam_stream_type_t stream_type,
    511                     uint32_t postprocess_mask) :
    512                         QCamera3Channel(cam_handle, cam_ops, cb_routine,
    513                                 paddingInfo, postprocess_mask, userData),
    514                         mCamera3Stream(stream),
    515                         mNumBufs(0),
    516                         mStreamType(stream_type),
    517                         mRotation(ROTATE_0)
    518 {
    519 }
    520 
    521 /*===========================================================================
    522  * FUNCTION   : ~QCamera3RegularChannel
    523  *
    524  * DESCRIPTION: destructor of QCamera3RegularChannel
    525  *
    526  * PARAMETERS : none
    527  *
    528  * RETURN     : none
    529  *==========================================================================*/
    530 QCamera3RegularChannel::~QCamera3RegularChannel()
    531 {
    532 }
    533 
    534 /*===========================================================================
    535  * FUNCTION   : initialize
    536  *
    537  * DESCRIPTION: Initialize and add camera channel & stream
    538  *
    539  * PARAMETERS :
    540  *
    541  * RETURN     : int32_t type of status
    542  *              NO_ERROR  -- success
    543  *              none-zero failure code
    544  *==========================================================================*/
    545 
    546 int32_t QCamera3RawChannel::initialize(cam_is_type_t isType)
    547 {
    548     return QCamera3RegularChannel::initialize(isType);
    549 }
    550 int32_t QCamera3RegularChannel::initialize(cam_is_type_t isType)
    551 {
    552     ATRACE_CALL();
    553     int32_t rc = NO_ERROR;
    554     cam_format_t streamFormat;
    555     cam_dimension_t streamDim;
    556 
    557     if (NULL == mCamera3Stream) {
    558         ALOGE("%s: Camera stream uninitialized", __func__);
    559         return NO_INIT;
    560     }
    561 
    562     if (1 <= m_numStreams) {
    563         // Only one stream per channel supported in v3 Hal
    564         return NO_ERROR;
    565     }
    566 
    567     rc = init(NULL, NULL);
    568     if (rc < 0) {
    569         ALOGE("%s: init failed", __func__);
    570         return rc;
    571     }
    572 
    573     mNumBufs = CAM_MAX_NUM_BUFS_PER_STREAM;
    574     mIsType  = isType;
    575 
    576     if (mCamera3Stream->format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
    577         if (mStreamType ==  CAM_STREAM_TYPE_VIDEO) {
    578             streamFormat = VIDEO_FORMAT;
    579         } else if (mStreamType == CAM_STREAM_TYPE_PREVIEW) {
    580             streamFormat = PREVIEW_FORMAT;
    581         } else {
    582             //TODO: Add a new flag in libgralloc for ZSL buffers, and its size needs
    583             // to be properly aligned and padded.
    584             streamFormat = DEFAULT_FORMAT;
    585         }
    586     } else if(mCamera3Stream->format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
    587          streamFormat = CALLBACK_FORMAT;
    588     } else if (mCamera3Stream->format == HAL_PIXEL_FORMAT_RAW_OPAQUE ||
    589          mCamera3Stream->format == HAL_PIXEL_FORMAT_RAW10 ||
    590          mCamera3Stream->format == HAL_PIXEL_FORMAT_RAW16) {
    591          // Bayer pattern doesn't matter here.
    592          // All CAMIF raw format uses 10bit.
    593          streamFormat = RAW_FORMAT;
    594     } else {
    595         //TODO: Fail for other types of streams for now
    596         ALOGE("%s: format is not IMPLEMENTATION_DEFINED or flexible", __func__);
    597         return -EINVAL;
    598     }
    599 
    600     if ((mStreamType == CAM_STREAM_TYPE_VIDEO) ||
    601             (mStreamType == CAM_STREAM_TYPE_PREVIEW)) {
    602         if ((mCamera3Stream->rotation != CAMERA3_STREAM_ROTATION_0) &&
    603                 ((mPostProcMask & CAM_QCOM_FEATURE_ROTATION) == 0)) {
    604             ALOGE("%s: attempting rotation %d when rotation is disabled",
    605                     __func__,
    606                     mCamera3Stream->rotation);
    607             return -EINVAL;
    608         }
    609 
    610         switch (mCamera3Stream->rotation) {
    611         case CAMERA3_STREAM_ROTATION_0:
    612             mRotation = ROTATE_0;
    613             break;
    614         case CAMERA3_STREAM_ROTATION_90: {
    615             mRotation = ROTATE_90;
    616             break;
    617         }
    618         case CAMERA3_STREAM_ROTATION_180:
    619             mRotation = ROTATE_180;
    620             break;
    621         case CAMERA3_STREAM_ROTATION_270: {
    622             mRotation = ROTATE_270;
    623             break;
    624         }
    625         default:
    626             ALOGE("%s: Unknown rotation: %d",
    627                     __func__,
    628                     mCamera3Stream->rotation);
    629             return -EINVAL;
    630         }
    631     } else if (mCamera3Stream->rotation != CAMERA3_STREAM_ROTATION_0) {
    632         ALOGE("%s: Rotation %d is not supported by stream type %d",
    633                 __func__,
    634                 mCamera3Stream->rotation,
    635                 mStreamType);
    636         return -EINVAL;
    637     }
    638 
    639     streamDim.width = mCamera3Stream->width;
    640     streamDim.height = mCamera3Stream->height;
    641 
    642     rc = QCamera3Channel::addStream(mStreamType,
    643             streamFormat,
    644             streamDim,
    645             mRotation,
    646             mNumBufs,
    647             mPostProcMask,
    648             mIsType);
    649 
    650     return rc;
    651 }
    652 
    653 /*===========================================================================
    654 * FUNCTION   : start
    655 *
    656 * DESCRIPTION: start a regular channel
    657 *
    658 * PARAMETERS :
    659 *
    660 * RETURN     : int32_t type of status
    661 *              NO_ERROR  -- success
    662 *              none-zero failure code
    663 *==========================================================================*/
    664 int32_t QCamera3RegularChannel::start()
    665 {
    666     ATRACE_CALL();
    667     int32_t rc = NO_ERROR;
    668 
    669     if (0 < mMemory.getCnt()) {
    670         rc = QCamera3Channel::start();
    671     }
    672     return rc;
    673 }
    674 
    675 /*===========================================================================
    676  * FUNCTION   : request
    677  *
    678  * DESCRIPTION: process a request from camera service. Stream on if ncessary.
    679  *
    680  * PARAMETERS :
    681  *   @buffer  : buffer to be filled for this request
    682  *
    683  * RETURN     : 0 on a success start of capture
    684  *              -EINVAL on invalid input
    685  *              -ENODEV on serious error
    686  *==========================================================================*/
    687 int32_t QCamera3RegularChannel::request(buffer_handle_t *buffer, uint32_t frameNumber)
    688 {
    689     ATRACE_CALL();
    690     //FIX ME: Return buffer back in case of failures below.
    691 
    692     int32_t rc = NO_ERROR;
    693     int index;
    694 
    695     if (NULL == buffer) {
    696         ALOGE("%s: Invalid buffer in channel request", __func__);
    697         return BAD_VALUE;
    698     }
    699 
    700     if(!m_bIsActive) {
    701         rc = registerBuffer(buffer, mIsType);
    702         if (NO_ERROR != rc) {
    703             ALOGE("%s: On-the-fly buffer registration failed %d",
    704                     __func__, rc);
    705             return rc;
    706         }
    707 
    708         rc = start();
    709         if (NO_ERROR != rc) {
    710             return rc;
    711         }
    712     } else {
    713         CDBG("%s: Request on an existing stream",__func__);
    714     }
    715 
    716     index = mMemory.getMatchBufIndex((void*)buffer);
    717     if(index < 0) {
    718         rc = registerBuffer(buffer, mIsType);
    719         if (NO_ERROR != rc) {
    720             ALOGE("%s: On-the-fly buffer registration failed %d",
    721                     __func__, rc);
    722             return rc;
    723         }
    724 
    725         index = mMemory.getMatchBufIndex((void*)buffer);
    726         if (index < 0) {
    727             ALOGE("%s: Could not find object among registered buffers",
    728                     __func__);
    729             return DEAD_OBJECT;
    730         }
    731     }
    732 
    733     rc = mStreams[0]->bufDone(index);
    734     if(rc != NO_ERROR) {
    735         ALOGE("%s: Failed to Q new buffer to stream",__func__);
    736         return rc;
    737     }
    738 
    739     rc = mMemory.markFrameNumber(index, frameNumber);
    740     return rc;
    741 }
    742 
    743 /*===========================================================================
    744  * FUNCTION   : registerBuffer
    745  *
    746  * DESCRIPTION: register streaming buffer to the channel object
    747  *
    748  * PARAMETERS :
    749  *   @buffer     : buffer to be registered
    750  *
    751  * RETURN     : int32_t type of status
    752  *              NO_ERROR  -- success
    753  *              none-zero failure code
    754  *==========================================================================*/
    755 int32_t QCamera3RegularChannel::registerBuffer(buffer_handle_t *buffer,
    756         cam_is_type_t isType)
    757 {
    758     ATRACE_CALL();
    759     int rc = 0;
    760     mIsType = isType;
    761     cam_stream_type_t streamType;
    762 
    763     if ((uint32_t)mMemory.getCnt() > (mNumBufs - 1)) {
    764         ALOGE("%s: Trying to register more buffers than initially requested",
    765                 __func__);
    766         return BAD_VALUE;
    767     }
    768 
    769     if (0 == m_numStreams) {
    770         rc = initialize(mIsType);
    771         if (rc != NO_ERROR) {
    772             ALOGE("%s: Couldn't initialize camera stream %d",
    773                     __func__, rc);
    774             return rc;
    775         }
    776     }
    777 
    778     streamType = mStreams[0]->getMyType();
    779     rc = mMemory.registerBuffer(buffer, streamType);
    780     if (ALREADY_EXISTS == rc) {
    781         return NO_ERROR;
    782     } else if (NO_ERROR != rc) {
    783         ALOGE("%s: Buffer %p couldn't be registered %d", __func__, buffer, rc);
    784         return rc;
    785     }
    786 
    787     return rc;
    788 }
    789 
    790 void QCamera3RegularChannel::streamCbRoutine(
    791                             mm_camera_super_buf_t *super_frame,
    792                             QCamera3Stream *stream)
    793 {
    794     ATRACE_CALL();
    795     //FIXME Q Buf back in case of error?
    796     uint8_t frameIndex;
    797     buffer_handle_t *resultBuffer;
    798     int32_t resultFrameNumber;
    799     camera3_stream_buffer_t result;
    800 
    801     if (NULL == stream) {
    802         ALOGE("%s: Invalid stream", __func__);
    803         return;
    804     }
    805 
    806     if(!super_frame) {
    807          ALOGE("%s: Invalid Super buffer",__func__);
    808          return;
    809     }
    810 
    811     if(super_frame->num_bufs != 1) {
    812          ALOGE("%s: Multiple streams are not supported",__func__);
    813          return;
    814     }
    815     if(super_frame->bufs[0] == NULL ) {
    816          ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
    817                   __func__);
    818          return;
    819     }
    820 
    821     frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
    822     if(frameIndex >= mNumBufs) {
    823          ALOGE("%s: Error, Invalid index for buffer",__func__);
    824          stream->bufDone(frameIndex);
    825          return;
    826     }
    827 
    828     ////Use below data to issue framework callback
    829     resultBuffer = (buffer_handle_t *)mMemory.getBufferHandle(frameIndex);
    830     resultFrameNumber = mMemory.getFrameNumber(frameIndex);
    831 
    832     result.stream = mCamera3Stream;
    833     result.buffer = resultBuffer;
    834     result.status = CAMERA3_BUFFER_STATUS_OK;
    835     result.acquire_fence = -1;
    836     result.release_fence = -1;
    837     int32_t rc = stream->bufRelease(frameIndex);
    838     if (NO_ERROR != rc) {
    839         ALOGE("%s: Error %d releasing stream buffer %d",
    840                 __func__, rc, frameIndex);
    841     }
    842 
    843     rc = mMemory.unregisterBuffer(frameIndex);
    844     if (NO_ERROR != rc) {
    845         ALOGE("%s: Error %d unregistering stream buffer %d",
    846                 __func__, rc, frameIndex);
    847     }
    848 
    849     if (0 <= resultFrameNumber){
    850         mChannelCB(NULL, &result, (uint32_t)resultFrameNumber, mUserData);
    851     } else {
    852         ALOGE("%s: Bad frame number", __func__);
    853     }
    854 
    855     free(super_frame);
    856     return;
    857 }
    858 
    859 QCamera3Memory* QCamera3RegularChannel::getStreamBufs(uint32_t /*len*/)
    860 {
    861     return &mMemory;
    862 }
    863 
    864 void QCamera3RegularChannel::putStreamBufs()
    865 {
    866     mMemory.unregisterBuffers();
    867 }
    868 
    869 int QCamera3RegularChannel::kMaxBuffers = MAX_INFLIGHT_REQUESTS;
    870 
    871 QCamera3MetadataChannel::QCamera3MetadataChannel(uint32_t cam_handle,
    872                     mm_camera_ops_t *cam_ops,
    873                     channel_cb_routine cb_routine,
    874                     cam_padding_info_t *paddingInfo,
    875                     uint32_t postprocess_mask,
    876                     void *userData) :
    877                         QCamera3Channel(cam_handle, cam_ops,
    878                                 cb_routine, paddingInfo, postprocess_mask, userData),
    879                         mMemory(NULL)
    880 {
    881 }
    882 
    883 QCamera3MetadataChannel::~QCamera3MetadataChannel()
    884 {
    885     if (m_bIsActive)
    886         stop();
    887 
    888     if (mMemory) {
    889         mMemory->deallocate();
    890         delete mMemory;
    891         mMemory = NULL;
    892     }
    893 }
    894 
    895 int32_t QCamera3MetadataChannel::initialize(cam_is_type_t isType)
    896 {
    897     ATRACE_CALL();
    898     int32_t rc;
    899     cam_dimension_t streamDim;
    900 
    901     if (mMemory || m_numStreams > 0) {
    902         ALOGE("%s: metadata channel already initialized", __func__);
    903         return -EINVAL;
    904     }
    905 
    906     rc = init(NULL, NULL);
    907     if (rc < 0) {
    908         ALOGE("%s: init failed", __func__);
    909         return rc;
    910     }
    911     mIsType = isType;
    912     streamDim.width = sizeof(metadata_buffer_t),
    913     streamDim.height = 1;
    914     rc = QCamera3Channel::addStream(CAM_STREAM_TYPE_METADATA, CAM_FORMAT_MAX,
    915             streamDim, ROTATE_0, MIN_STREAMING_BUFFER_NUM, mPostProcMask,
    916             mIsType);
    917     if (rc < 0) {
    918         ALOGE("%s: addStream failed", __func__);
    919     }
    920     return rc;
    921 }
    922 
    923 int32_t QCamera3MetadataChannel::request(buffer_handle_t * /*buffer*/,
    924                                                 uint32_t /*frameNumber*/)
    925 {
    926     if (!m_bIsActive) {
    927         return start();
    928     }
    929     else
    930         return 0;
    931 }
    932 
    933 void QCamera3MetadataChannel::streamCbRoutine(
    934                         mm_camera_super_buf_t *super_frame,
    935                         QCamera3Stream * /*stream*/)
    936 {
    937     ATRACE_CALL();
    938     uint32_t requestNumber = 0;
    939     if (super_frame == NULL || super_frame->num_bufs != 1) {
    940         ALOGE("%s: super_frame is not valid", __func__);
    941         return;
    942     }
    943     mChannelCB(super_frame, NULL, requestNumber, mUserData);
    944 }
    945 
    946 QCamera3Memory* QCamera3MetadataChannel::getStreamBufs(uint32_t len)
    947 {
    948     int rc;
    949     if (len < sizeof(metadata_buffer_t)) {
    950         ALOGE("%s: Metadata buffer size less than structure %d vs %d",
    951                 __func__,
    952                 len,
    953                 sizeof(metadata_buffer_t));
    954         return NULL;
    955     }
    956     mMemory = new QCamera3HeapMemory();
    957     if (!mMemory) {
    958         ALOGE("%s: unable to create metadata memory", __func__);
    959         return NULL;
    960     }
    961     rc = mMemory->allocate(MIN_STREAMING_BUFFER_NUM, len, true);
    962     if (rc < 0) {
    963         ALOGE("%s: unable to allocate metadata memory", __func__);
    964         delete mMemory;
    965         mMemory = NULL;
    966         return NULL;
    967     }
    968     memset(mMemory->getPtr(0), 0, sizeof(metadata_buffer_t));
    969     return mMemory;
    970 }
    971 
    972 void QCamera3MetadataChannel::putStreamBufs()
    973 {
    974     mMemory->deallocate();
    975     delete mMemory;
    976     mMemory = NULL;
    977 }
    978 /*************************************************************************************/
    979 // RAW Channel related functions
    980 int QCamera3RawChannel::kMaxBuffers = MAX_INFLIGHT_REQUESTS;
    981 
    982 QCamera3RawChannel::QCamera3RawChannel(uint32_t cam_handle,
    983                     mm_camera_ops_t *cam_ops,
    984                     channel_cb_routine cb_routine,
    985                     cam_padding_info_t *paddingInfo,
    986                     void *userData,
    987                     camera3_stream_t *stream,
    988                     uint32_t postprocess_mask,
    989                     bool raw_16) :
    990                         QCamera3RegularChannel(cam_handle, cam_ops,
    991                                 cb_routine, paddingInfo, userData, stream,
    992                                 CAM_STREAM_TYPE_RAW, postprocess_mask),
    993                         mIsRaw16(raw_16)
    994 {
    995     char prop[PROPERTY_VALUE_MAX];
    996     property_get("persist.camera.raw.debug.dump", prop, "0");
    997     mRawDump = atoi(prop);
    998 }
    999 
   1000 QCamera3RawChannel::~QCamera3RawChannel()
   1001 {
   1002 }
   1003 
   1004 void QCamera3RawChannel::streamCbRoutine(
   1005                         mm_camera_super_buf_t *super_frame,
   1006                         QCamera3Stream * stream)
   1007 {
   1008     ATRACE_CALL();
   1009     /* Move this back down once verified */
   1010     if (mRawDump)
   1011         dumpRawSnapshot(super_frame->bufs[0]);
   1012 
   1013     if (mIsRaw16) {
   1014         if (RAW_FORMAT == CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG)
   1015             convertMipiToRaw16(super_frame->bufs[0]);
   1016         else
   1017             convertLegacyToRaw16(super_frame->bufs[0]);
   1018     }
   1019 
   1020     //Make sure cache coherence because extra processing is done
   1021     mMemory.cleanInvalidateCache(super_frame->bufs[0]->buf_idx);
   1022 
   1023     QCamera3RegularChannel::streamCbRoutine(super_frame, stream);
   1024     return;
   1025 }
   1026 
   1027 void QCamera3RawChannel::dumpRawSnapshot(mm_camera_buf_def_t *frame)
   1028 {
   1029    QCamera3Stream *stream = getStreamByIndex(0);
   1030    char buf[32];
   1031    memset(buf, 0, sizeof(buf));
   1032    cam_dimension_t dim;
   1033    memset(&dim, 0, sizeof(dim));
   1034    stream->getFrameDimension(dim);
   1035 
   1036    cam_frame_len_offset_t offset;
   1037    memset(&offset, 0, sizeof(cam_frame_len_offset_t));
   1038    stream->getFrameOffset(offset);
   1039    snprintf(buf, sizeof(buf), "/data/local/tmp/r_%d_%dx%d.raw",
   1040             frame->frame_idx, dim.width, dim.height);
   1041 
   1042    int file_fd = open(buf, O_RDWR| O_CREAT, 0644);
   1043    if (file_fd >= 0) {
   1044       int written_len = write(file_fd, frame->buffer, offset.frame_len);
   1045       ALOGE("%s: written number of bytes %d", __func__, written_len);
   1046       close(file_fd);
   1047    } else {
   1048       ALOGE("%s: failed to open file to dump image", __func__);
   1049    }
   1050 
   1051 }
   1052 
   1053 void QCamera3RawChannel::convertLegacyToRaw16(mm_camera_buf_def_t *frame)
   1054 {
   1055     // Convert image buffer from Opaque raw format to RAW16 format
   1056     // 10bit Opaque raw is stored in the format of:
   1057     // 0000 - p5 - p4 - p3 - p2 - p1 - p0
   1058     // where p0 to p5 are 6 pixels (each is 10bit)_and most significant
   1059     // 4 bits are 0s. Each 64bit word contains 6 pixels.
   1060 
   1061     QCamera3Stream *stream = getStreamByIndex(0);
   1062     cam_dimension_t dim;
   1063     memset(&dim, 0, sizeof(dim));
   1064     stream->getFrameDimension(dim);
   1065 
   1066     cam_frame_len_offset_t offset;
   1067     memset(&offset, 0, sizeof(cam_frame_len_offset_t));
   1068     stream->getFrameOffset(offset);
   1069 
   1070     uint32_t raw16_stride = (dim.width + 15) & ~15;
   1071     uint16_t* raw16_buffer = (uint16_t *)frame->buffer;
   1072 
   1073     // In-place format conversion.
   1074     // Raw16 format always occupy more memory than opaque raw10.
   1075     // Convert to Raw16 by iterating through all pixels from bottom-right
   1076     // to top-left of the image.
   1077     // One special notes:
   1078     // 1. Cross-platform raw16's stride is 16 pixels.
   1079     // 2. Opaque raw10's stride is 6 pixels, and aligned to 16 bytes.
   1080     for (int y = dim.height-1; y >= 0; y--) {
   1081         uint64_t* row_start = (uint64_t *)frame->buffer +
   1082             y * offset.mp[0].stride / 8;
   1083         for (int x = dim.width-1;  x >= 0; x--) {
   1084             uint16_t raw16_pixel = 0x3FF & (row_start[x/6] >> (10*(x%6)));
   1085             raw16_buffer[y*raw16_stride+x] = raw16_pixel;
   1086         }
   1087     }
   1088 }
   1089 
   1090 void QCamera3RawChannel::convertMipiToRaw16(mm_camera_buf_def_t *frame)
   1091 {
   1092     // Convert image buffer from mipi10 raw format to RAW16 format
   1093     // mipi10 opaque raw is stored in the format of:
   1094     // P3(1:0) P2(1:0) P1(1:0) P0(1:0) P3(9:2) P2(9:2) P1(9:2) P0(9:2)
   1095     // 4 pixels occupy 5 bytes, no padding needed
   1096 
   1097     QCamera3Stream *stream = getStreamByIndex(0);
   1098     cam_dimension_t dim;
   1099     memset(&dim, 0, sizeof(dim));
   1100     stream->getFrameDimension(dim);
   1101 
   1102     cam_frame_len_offset_t offset;
   1103     memset(&offset, 0, sizeof(cam_frame_len_offset_t));
   1104     stream->getFrameOffset(offset);
   1105 
   1106     uint32_t raw16_stride = (dim.width + 15) & ~15;
   1107     uint16_t* raw16_buffer = (uint16_t *)frame->buffer;
   1108 
   1109     // In-place format conversion.
   1110     // Raw16 format always occupy more memory than opaque raw10.
   1111     // Convert to Raw16 by iterating through all pixels from bottom-right
   1112     // to top-left of the image.
   1113     // One special notes:
   1114     // 1. Cross-platform raw16's stride is 16 pixels.
   1115     // 2. mipi raw10's stride is 4 pixels, and aligned to 16 bytes.
   1116     for (int y = dim.height-1; y >= 0; y--) {
   1117         uint8_t* row_start = (uint8_t *)frame->buffer +
   1118             y * offset.mp[0].stride;
   1119         for (int x = dim.width-1;  x >= 0; x--) {
   1120             uint8_t upper_8bit = row_start[5*(x/4)+x%4];
   1121             uint8_t lower_2bit = ((row_start[5*(x/4)+4] >> (x%4)) & 0x3);
   1122             uint16_t raw16_pixel = (((uint16_t)upper_8bit)<<2 | lower_2bit);
   1123             raw16_buffer[y*raw16_stride+x] = raw16_pixel;
   1124         }
   1125     }
   1126 
   1127 }
   1128 
   1129 
   1130 /*************************************************************************************/
   1131 // RAW Dump Channel related functions
   1132 
   1133 int QCamera3RawDumpChannel::kMaxBuffers = 3;
   1134 /*===========================================================================
   1135  * FUNCTION   : QCamera3RawDumpChannel
   1136  *
   1137  * DESCRIPTION: Constructor for RawDumpChannel
   1138  *
   1139  * PARAMETERS :
   1140  *   @cam_handle    : Handle for Camera
   1141  *   @cam_ops       : Function pointer table
   1142  *   @rawDumpSize   : Dimensions for the Raw stream
   1143  *   @paddinginfo   : Padding information for stream
   1144  *   @userData      : Cookie for parent
   1145  *   @pp mask       : PP feature mask for this stream
   1146  *
   1147  * RETURN           : NA
   1148  *==========================================================================*/
   1149 QCamera3RawDumpChannel::QCamera3RawDumpChannel(uint32_t cam_handle,
   1150                     mm_camera_ops_t *cam_ops,
   1151                     cam_dimension_t rawDumpSize,
   1152                     cam_padding_info_t *paddingInfo,
   1153                     void *userData,
   1154                     uint32_t postprocess_mask) :
   1155                         QCamera3Channel(cam_handle, cam_ops, NULL,
   1156                                 paddingInfo, postprocess_mask, userData),
   1157                         mDim(rawDumpSize),
   1158                         mMemory(NULL)
   1159 {
   1160     char prop[PROPERTY_VALUE_MAX];
   1161     property_get("persist.camera.raw.dump", prop, "0");
   1162     mRawDump = atoi(prop);
   1163 }
   1164 
   1165 /*===========================================================================
   1166  * FUNCTION   : QCamera3RawDumpChannel
   1167  *
   1168  * DESCRIPTION: Destructor for RawDumpChannel
   1169  *
   1170  * PARAMETERS :
   1171  *
   1172  * RETURN           : NA
   1173  *==========================================================================*/
   1174 
   1175 QCamera3RawDumpChannel::~QCamera3RawDumpChannel()
   1176 {
   1177 }
   1178 
   1179 /*===========================================================================
   1180  * FUNCTION   : dumpRawSnapshot
   1181  *
   1182  * DESCRIPTION: Helper function to dump Raw frames
   1183  *
   1184  * PARAMETERS :
   1185  *  @frame      : stream buf frame to be dumped
   1186  *
   1187  *  RETURN      : NA
   1188  *==========================================================================*/
   1189 void QCamera3RawDumpChannel::dumpRawSnapshot(mm_camera_buf_def_t *frame)
   1190 {
   1191     QCamera3Stream *stream = getStreamByIndex(0);
   1192     char buf[128];
   1193     struct timeval tv;
   1194     struct tm *timeinfo;
   1195 
   1196     cam_dimension_t dim;
   1197     memset(&dim, 0, sizeof(dim));
   1198     stream->getFrameDimension(dim);
   1199 
   1200     cam_frame_len_offset_t offset;
   1201     memset(&offset, 0, sizeof(cam_frame_len_offset_t));
   1202     stream->getFrameOffset(offset);
   1203 
   1204     gettimeofday(&tv, NULL);
   1205     timeinfo = localtime(&tv.tv_sec);
   1206 
   1207     memset(buf, 0, sizeof(buf));
   1208     snprintf(buf, sizeof(buf),
   1209                  "/data/%04d-%02d-%02d-%02d-%02d-%02d-%06ld_%d_%dx%d.raw",
   1210                  timeinfo->tm_year + 1900, timeinfo->tm_mon + 1,
   1211                  timeinfo->tm_mday, timeinfo->tm_hour,
   1212                  timeinfo->tm_min, timeinfo->tm_sec,tv.tv_usec,
   1213                  frame->frame_idx, dim.width, dim.height);
   1214 
   1215     int file_fd = open(buf, O_RDWR| O_CREAT, 0777);
   1216     if (file_fd >= 0) {
   1217         int written_len = write(file_fd, frame->buffer, offset.frame_len);
   1218         CDBG("%s: written number of bytes %d", __func__, written_len);
   1219         close(file_fd);
   1220     } else {
   1221         ALOGE("%s: failed to open file to dump image", __func__);
   1222     }
   1223 }
   1224 
   1225 /*===========================================================================
   1226  * FUNCTION   : streamCbRoutine
   1227  *
   1228  * DESCRIPTION: Callback routine invoked for each frame generated for
   1229  *              Rawdump channel
   1230  *
   1231  * PARAMETERS :
   1232  *   @super_frame  : stream buf frame generated
   1233  *   @stream       : Underlying Stream object cookie
   1234  *
   1235  * RETURN          : NA
   1236  *==========================================================================*/
   1237 void QCamera3RawDumpChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
   1238                                                 QCamera3Stream *stream)
   1239 {
   1240     CDBG("%s: E",__func__);
   1241     if (super_frame == NULL || super_frame->num_bufs != 1) {
   1242         ALOGE("%s: super_frame is not valid", __func__);
   1243         return;
   1244     }
   1245 
   1246     if (mRawDump)
   1247         dumpRawSnapshot(super_frame->bufs[0]);
   1248 
   1249     bufDone(super_frame);
   1250     free(super_frame);
   1251 }
   1252 
   1253 /*===========================================================================
   1254  * FUNCTION   : getStreamBufs
   1255  *
   1256  * DESCRIPTION: Callback function provided to interface to get buffers.
   1257  *
   1258  * PARAMETERS :
   1259  *   @len       : Length of each buffer to be allocated
   1260  *
   1261  * RETURN     : NULL on buffer allocation failure
   1262  *              QCamera3Memory object on sucess
   1263  *==========================================================================*/
   1264 QCamera3Memory* QCamera3RawDumpChannel::getStreamBufs(uint32_t len)
   1265 {
   1266     int rc;
   1267     mMemory = new QCamera3HeapMemory();
   1268 
   1269     if (!mMemory) {
   1270         ALOGE("%s: unable to create heap memory", __func__);
   1271         return NULL;
   1272     }
   1273     rc = mMemory->allocate(kMaxBuffers, len, true);
   1274     if (rc < 0) {
   1275         ALOGE("%s: unable to allocate heap memory", __func__);
   1276         delete mMemory;
   1277         mMemory = NULL;
   1278         return NULL;
   1279     }
   1280     return mMemory;
   1281 }
   1282 
   1283 /*===========================================================================
   1284  * FUNCTION   : putStreamBufs
   1285  *
   1286  * DESCRIPTION: Callback function provided to interface to return buffers.
   1287  *              Although no handles are actually returned, implicitl assumption
   1288  *              that interface will no longer use buffers and channel can
   1289  *              deallocated if necessary.
   1290  *
   1291  * PARAMETERS : NA
   1292  *
   1293  * RETURN     : NA
   1294  *==========================================================================*/
   1295 void QCamera3RawDumpChannel::putStreamBufs()
   1296 {
   1297     mMemory->deallocate();
   1298     delete mMemory;
   1299     mMemory = NULL;
   1300 }
   1301 
   1302 /*===========================================================================
   1303  * FUNCTION : request
   1304  *
   1305  * DESCRIPTION: Request function used as trigger
   1306  *
   1307  * PARAMETERS :
   1308  * @recvd_frame : buffer- this will be NULL since this is internal channel
   1309  * @frameNumber : Undefined again since this is internal stream
   1310  *
   1311  * RETURN     : int32_t type of status
   1312  *              NO_ERROR  -- success
   1313  *              none-zero failure code
   1314  *==========================================================================*/
   1315 int32_t QCamera3RawDumpChannel::request(buffer_handle_t * /*buffer*/,
   1316                                                 uint32_t /*frameNumber*/)
   1317 {
   1318     if (!m_bIsActive) {
   1319         return QCamera3Channel::start();
   1320     }
   1321     else
   1322         return 0;
   1323 }
   1324 
   1325 /*===========================================================================
   1326  * FUNCTION : intialize
   1327  *
   1328  * DESCRIPTION: Initializes channel params and creates underlying stream
   1329  *
   1330  * PARAMETERS : NA
   1331  *
   1332  * RETURN     : int32_t type of status
   1333  *              NO_ERROR  -- success
   1334  *              none-zero failure code
   1335  *==========================================================================*/
   1336 int32_t QCamera3RawDumpChannel::initialize(cam_is_type_t isType)
   1337 {
   1338     int32_t rc;
   1339 
   1340     rc = init(NULL, NULL);
   1341     if (rc < 0) {
   1342         ALOGE("%s: init failed", __func__);
   1343         return rc;
   1344     }
   1345     mIsType = isType;
   1346     rc = QCamera3Channel::addStream(CAM_STREAM_TYPE_RAW,
   1347             CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG, mDim, ROTATE_0, kMaxBuffers,
   1348             mPostProcMask, mIsType);
   1349     if (rc < 0) {
   1350         ALOGE("%s: addStream failed", __func__);
   1351     }
   1352     return rc;
   1353 }
   1354 /*************************************************************************************/
   1355 
   1356 /*===========================================================================
   1357  * FUNCTION   : jpegEvtHandle
   1358  *
   1359  * DESCRIPTION: Function registerd to mm-jpeg-interface to handle jpeg events.
   1360                 Construct result payload and call mChannelCb to deliver buffer
   1361                 to framework.
   1362  *
   1363  * PARAMETERS :
   1364  *   @status    : status of jpeg job
   1365  *   @client_hdl: jpeg client handle
   1366  *   @jobId     : jpeg job Id
   1367  *   @p_ouput   : ptr to jpeg output result struct
   1368  *   @userdata  : user data ptr
   1369  *
   1370  * RETURN     : none
   1371  *==========================================================================*/
   1372 void QCamera3PicChannel::jpegEvtHandle(jpeg_job_status_t status,
   1373                                               uint32_t /*client_hdl*/,
   1374                                               uint32_t jobId,
   1375                                               mm_jpeg_output_t *p_output,
   1376                                               void *userdata)
   1377 {
   1378     ATRACE_CALL();
   1379     buffer_handle_t *resultBuffer, *jpegBufferHandle;
   1380     int32_t resultFrameNumber;
   1381     int resultStatus = CAMERA3_BUFFER_STATUS_OK;
   1382     camera3_stream_buffer_t result;
   1383     camera3_jpeg_blob_t jpegHeader;
   1384     char* jpeg_eof = 0;
   1385     int maxJpegSize;
   1386     int32_t bufIdx;
   1387 
   1388     QCamera3PicChannel *obj = (QCamera3PicChannel *)userdata;
   1389     if (obj) {
   1390         //Construct payload for process_capture_result. Call mChannelCb
   1391 
   1392         qcamera_hal3_jpeg_data_t *job = obj->m_postprocessor.findJpegJobByJobId(jobId);
   1393 
   1394         if ((job == NULL) || (status == JPEG_JOB_STATUS_ERROR)) {
   1395             ALOGE("%s: Error in jobId: (%d) with status: %d", __func__, jobId, status);
   1396             resultStatus = CAMERA3_BUFFER_STATUS_ERROR;
   1397         }
   1398 
   1399         bufIdx = job->jpeg_settings->out_buf_index;
   1400         CDBG("%s: jpeg out_buf_index: %d", __func__, bufIdx);
   1401 
   1402         //Construct jpeg transient header of type camera3_jpeg_blob_t
   1403         //Append at the end of jpeg image of buf_filled_len size
   1404 
   1405         jpegHeader.jpeg_blob_id = CAMERA3_JPEG_BLOB_ID;
   1406         jpegHeader.jpeg_size = p_output->buf_filled_len;
   1407 
   1408 
   1409         char* jpeg_buf = (char *)p_output->buf_vaddr;
   1410 
   1411         // Gralloc buffer may have additional padding for 4K page size
   1412         // Follow size guidelines based on spec since framework relies
   1413         // on that to reach end of buffer and with it the header
   1414 
   1415         //Handle same as resultBuffer, but for readablity
   1416         jpegBufferHandle =
   1417             (buffer_handle_t *)obj->mMemory.getBufferHandle(bufIdx);
   1418 
   1419         maxJpegSize = ((private_handle_t*)(*jpegBufferHandle))->width;
   1420         if (maxJpegSize > obj->mMemory.getSize(bufIdx)) {
   1421             maxJpegSize = obj->mMemory.getSize(bufIdx);
   1422         }
   1423 
   1424         jpeg_eof = &jpeg_buf[maxJpegSize-sizeof(jpegHeader)];
   1425         memcpy(jpeg_eof, &jpegHeader, sizeof(jpegHeader));
   1426         obj->mMemory.cleanInvalidateCache(bufIdx);
   1427 
   1428         ////Use below data to issue framework callback
   1429         resultBuffer = (buffer_handle_t *)obj->mMemory.getBufferHandle(bufIdx);
   1430         resultFrameNumber = obj->mMemory.getFrameNumber(bufIdx);
   1431         int32_t rc = obj->mMemory.unregisterBuffer(bufIdx);
   1432         if (NO_ERROR != rc) {
   1433             ALOGE("%s: Error %d unregistering stream buffer %d",
   1434                     __func__, rc, bufIdx);
   1435         }
   1436 
   1437         result.stream = obj->mCamera3Stream;
   1438         result.buffer = resultBuffer;
   1439         result.status = resultStatus;
   1440         result.acquire_fence = -1;
   1441         result.release_fence = -1;
   1442 
   1443         // Release any snapshot buffers before calling
   1444         // the user callback. The callback can potentially
   1445         // unblock pending requests to snapshot stream.
   1446         if (NULL != job) {
   1447             int32_t snapshotIdx = -1;
   1448             mm_camera_super_buf_t* src_frame = NULL;
   1449 
   1450             if (job->src_reproc_frame)
   1451                 src_frame = job->src_reproc_frame;
   1452             else
   1453                 src_frame = job->src_frame;
   1454 
   1455             if (src_frame) {
   1456                 if (obj->mStreams[0]->getMyHandle() ==
   1457                         src_frame->bufs[0]->stream_id) {
   1458                     snapshotIdx = src_frame->bufs[0]->buf_idx;
   1459                 } else {
   1460                     ALOGE("%s: Snapshot stream id %d and source frame %d don't match!",
   1461                             __func__, obj->mStreams[0]->getMyHandle(),
   1462                             src_frame->bufs[0]->stream_id);
   1463                 }
   1464             }
   1465             if (0 <= snapshotIdx) {
   1466                 Mutex::Autolock lock(obj->mFreeBuffersLock);
   1467                 obj->mFreeBufferList.push_back(snapshotIdx);
   1468             } else {
   1469                 ALOGE("%s: Snapshot buffer not found!", __func__);
   1470             }
   1471         }
   1472 
   1473         CDBG("%s: Issue Callback", __func__);
   1474         obj->mChannelCB(NULL, &result, resultFrameNumber, obj->mUserData);
   1475 
   1476         // release internal data for jpeg job
   1477         if (job != NULL) {
   1478             if ((NULL != job->fwk_frame) || (NULL != job->fwk_src_buffer)) {
   1479                 obj->mOfflineMetaMemory.deallocate();
   1480                 obj->mOfflineMemory.unregisterBuffers();
   1481             }
   1482             obj->m_postprocessor.releaseOfflineBuffers();
   1483             obj->m_postprocessor.releaseJpegJobData(job);
   1484             free(job);
   1485         }
   1486 
   1487         return;
   1488         // }
   1489     } else {
   1490         ALOGE("%s: Null userdata in jpeg callback", __func__);
   1491     }
   1492 }
   1493 
   1494 QCamera3PicChannel::QCamera3PicChannel(uint32_t cam_handle,
   1495                     mm_camera_ops_t *cam_ops,
   1496                     channel_cb_routine cb_routine,
   1497                     cam_padding_info_t *paddingInfo,
   1498                     void *userData,
   1499                     camera3_stream_t *stream,
   1500                     uint32_t postprocess_mask,
   1501                     bool is4KVideo,
   1502                     QCamera3Channel *metadataChannel) :
   1503                         QCamera3Channel(cam_handle, cam_ops, cb_routine,
   1504                         paddingInfo, postprocess_mask, userData),
   1505                         m_postprocessor(this),
   1506                         mCamera3Stream(stream),
   1507                         mNumBufsRegistered(CAM_MAX_NUM_BUFS_PER_STREAM),
   1508                         mNumSnapshotBufs(0),
   1509                         mCurrentBufIndex(-1),
   1510                         mPostProcStarted(false),
   1511                         mInputBufferConfig(false),
   1512                         mYuvMemory(NULL),
   1513                         m_pMetaChannel(metadataChannel),
   1514                         mMetaFrame(NULL)
   1515 {
   1516     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
   1517     m_max_pic_dim = hal_obj->calcMaxJpegDim();
   1518     mYuvWidth = stream->width;
   1519     mYuvHeight = stream->height;
   1520     // Use same pixelformat for 4K video case
   1521     mStreamFormat = is4KVideo ? VIDEO_FORMAT : SNAPSHOT_FORMAT;
   1522     mStreamType = CAM_STREAM_TYPE_SNAPSHOT;
   1523     int32_t rc = m_postprocessor.init(&mMemory, jpegEvtHandle, mPostProcMask,
   1524             this);
   1525     if (rc != 0) {
   1526         ALOGE("Init Postprocessor failed");
   1527     }
   1528 }
   1529 
   1530 /*===========================================================================
   1531  * FUNCTION   : stop
   1532  *
   1533  * DESCRIPTION: stop pic channel, which will stop all streams within, including
   1534  *              the reprocessing channel in postprocessor and YUV stream.
   1535  *
   1536  * PARAMETERS : none
   1537  *
   1538  * RETURN     : int32_t type of status
   1539  *              NO_ERROR  -- success
   1540  *              none-zero failure code
   1541  *==========================================================================*/
   1542 int32_t QCamera3PicChannel::stop()
   1543 {
   1544     int32_t rc = NO_ERROR;
   1545     if(!m_bIsActive) {
   1546         ALOGE("%s: Attempt to stop inactive channel",__func__);
   1547         return rc;
   1548     }
   1549 
   1550     m_postprocessor.stop();
   1551     mPostProcStarted = false;
   1552     rc |= QCamera3Channel::stop();
   1553     return rc;
   1554 }
   1555 
   1556 QCamera3PicChannel::~QCamera3PicChannel()
   1557 {
   1558    stop();
   1559 
   1560    int32_t rc = m_postprocessor.stop();
   1561    if (rc != NO_ERROR) {
   1562        ALOGE("%s: Postprocessor stop failed", __func__);
   1563    }
   1564 
   1565    rc = m_postprocessor.deinit();
   1566    if (rc != 0) {
   1567        ALOGE("De-init Postprocessor failed");
   1568    }
   1569 
   1570    if (0 < mOfflineMetaMemory.getCnt()) {
   1571        mOfflineMetaMemory.deallocate();
   1572    }
   1573    if (0 < mOfflineMemory.getCnt()) {
   1574        mOfflineMemory.unregisterBuffers();
   1575    }
   1576 }
   1577 
   1578 int32_t QCamera3PicChannel::initialize(cam_is_type_t isType)
   1579 {
   1580     int32_t rc = NO_ERROR;
   1581     cam_dimension_t streamDim;
   1582     cam_stream_type_t streamType;
   1583     cam_format_t streamFormat;
   1584     mm_camera_channel_attr_t attr;
   1585 
   1586     if (NULL == mCamera3Stream) {
   1587         ALOGE("%s: Camera stream uninitialized", __func__);
   1588         return NO_INIT;
   1589     }
   1590 
   1591     if (1 <= m_numStreams) {
   1592         // Only one stream per channel supported in v3 Hal
   1593         return NO_ERROR;
   1594     }
   1595 
   1596     memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
   1597     attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_BURST;
   1598     attr.look_back = 1;
   1599     attr.post_frame_skip = 1;
   1600     attr.water_mark = 1;
   1601     attr.max_unmatched_frames = 1;
   1602 
   1603     rc = init(&attr, NULL);
   1604     if (rc < 0) {
   1605         ALOGE("%s: init failed", __func__);
   1606         return rc;
   1607     }
   1608     mIsType = isType;
   1609 
   1610     streamType = mStreamType;
   1611     streamFormat = mStreamFormat;
   1612     streamDim.width = mYuvWidth;
   1613     streamDim.height = mYuvHeight;
   1614 
   1615     mNumSnapshotBufs = mCamera3Stream->max_buffers;
   1616     rc = QCamera3Channel::addStream(streamType, streamFormat, streamDim,
   1617             ROTATE_0, (uint8_t)mCamera3Stream->max_buffers, mPostProcMask,
   1618             mIsType);
   1619 
   1620     Mutex::Autolock lock(mFreeBuffersLock);
   1621     mFreeBufferList.clear();
   1622     for (uint32_t i = 0; i < mCamera3Stream->max_buffers; i++) {
   1623         mFreeBufferList.push_back(i);
   1624     }
   1625 
   1626     return rc;
   1627 }
   1628 
   1629 int32_t QCamera3PicChannel::request(buffer_handle_t *buffer,
   1630         uint32_t frameNumber,
   1631         camera3_stream_buffer_t *pInputBuffer,
   1632         metadata_buffer_t *metadata)
   1633 {
   1634     ATRACE_CALL();
   1635     //FIX ME: Return buffer back in case of failures below.
   1636 
   1637     int32_t rc = NO_ERROR;
   1638     int index;
   1639     //extract rotation information
   1640 
   1641     reprocess_config_t reproc_cfg;
   1642     memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
   1643     reproc_cfg.padding = mPaddingInfo;
   1644     //to ensure a big enough buffer size set the height and width
   1645     //padding to max(height padding, width padding)
   1646     if (reproc_cfg.padding->height_padding > reproc_cfg.padding->width_padding) {
   1647        reproc_cfg.padding->width_padding = reproc_cfg.padding->height_padding;
   1648     } else {
   1649        reproc_cfg.padding->height_padding = reproc_cfg.padding->width_padding;
   1650     }
   1651     if (NULL != pInputBuffer) {
   1652         reproc_cfg.input_stream_dim.width = pInputBuffer->stream->width;
   1653         reproc_cfg.input_stream_dim.height = pInputBuffer->stream->height;
   1654     } else {
   1655         reproc_cfg.input_stream_dim.width = mYuvWidth;
   1656         reproc_cfg.input_stream_dim.height = mYuvHeight;
   1657         reproc_cfg.src_channel = this;
   1658     }
   1659     reproc_cfg.output_stream_dim.width = mCamera3Stream->width;
   1660     reproc_cfg.output_stream_dim.height = mCamera3Stream->height;
   1661     reproc_cfg.stream_type = mStreamType;
   1662     reproc_cfg.stream_format = mStreamFormat;
   1663     rc = mm_stream_calc_offset_snapshot(mStreamFormat, &reproc_cfg.input_stream_dim,
   1664             reproc_cfg.padding, &reproc_cfg.input_stream_plane_info);
   1665     if (rc != 0) {
   1666         ALOGE("%s: Snapshot stream plane info calculation failed!", __func__);
   1667         return rc;
   1668     }
   1669     if (IS_PARAM_AVAILABLE(CAM_INTF_META_JPEG_ORIENTATION, metadata)) {
   1670           int32_t *rotation = (int32_t *)POINTER_OF_PARAM(
   1671             CAM_INTF_META_JPEG_ORIENTATION, metadata);
   1672           if (*rotation == 0) {
   1673              reproc_cfg.rotation = ROTATE_0;
   1674           } else if (*rotation == 90) {
   1675              reproc_cfg.rotation = ROTATE_90;
   1676           } else if (*rotation == 180) {
   1677              reproc_cfg.rotation = ROTATE_180;
   1678           } else if (*rotation == 270) {
   1679              reproc_cfg.rotation = ROTATE_270;
   1680           }
   1681     }
   1682 
   1683     // Picture stream has already been started before any request comes in
   1684     if (!m_bIsActive) {
   1685         ALOGE("%s: Channel not started!!", __func__);
   1686         return NO_INIT;
   1687     }
   1688 
   1689     index = mMemory.getMatchBufIndex((void*)buffer);
   1690     if(index < 0) {
   1691         rc = registerBuffer(buffer, mIsType);
   1692         if (NO_ERROR != rc) {
   1693             ALOGE("%s: On-the-fly buffer registration failed %d",
   1694                     __func__, rc);
   1695             return rc;
   1696         }
   1697 
   1698         index = mMemory.getMatchBufIndex((void*)buffer);
   1699         if (index < 0) {
   1700             ALOGE("%s: Could not find object among registered buffers",__func__);
   1701             return DEAD_OBJECT;
   1702         }
   1703     }
   1704     CDBG("%s: buffer index %d, frameNumber: %u", __func__, index, frameNumber);
   1705 
   1706     rc = mMemory.markFrameNumber(index, frameNumber);
   1707 
   1708     //Start the postprocessor for jpeg encoding. Pass mMemory as destination buffer
   1709     mCurrentBufIndex = index;
   1710 
   1711     // Start postprocessor
   1712     // This component needs to be re-configured
   1713     // once we switch from input(framework) buffer
   1714     // reprocess to standard capture!
   1715     bool restartNeeded = ((!mInputBufferConfig) != (NULL != pInputBuffer));
   1716     if((!mPostProcStarted) || restartNeeded) {
   1717         m_postprocessor.start(reproc_cfg, metadata);
   1718         mPostProcStarted = true;
   1719         mInputBufferConfig = (NULL == pInputBuffer);
   1720     }
   1721 
   1722     // Queue jpeg settings
   1723     rc = queueJpegSetting(index, metadata);
   1724 
   1725     if (pInputBuffer == NULL) {
   1726         Mutex::Autolock lock(mFreeBuffersLock);
   1727         if (!mFreeBufferList.empty()) {
   1728             List<uint32_t>::iterator it = mFreeBufferList.begin();
   1729             uint32_t freeBuffer = *it;
   1730             mStreams[0]->bufDone(freeBuffer);
   1731             mFreeBufferList.erase(it);
   1732         } else {
   1733             ALOGE("%s: No snapshot buffers available!", __func__);
   1734             rc = NOT_ENOUGH_DATA;
   1735         }
   1736     } else {
   1737         if (0 < mOfflineMetaMemory.getCnt()) {
   1738             mOfflineMetaMemory.deallocate();
   1739         }
   1740         if (0 < mOfflineMemory.getCnt()) {
   1741             mOfflineMemory.unregisterBuffers();
   1742         }
   1743 
   1744         int input_index = mOfflineMemory.getMatchBufIndex((void*)pInputBuffer->buffer);
   1745         if(input_index < 0) {
   1746             rc = mOfflineMemory.registerBuffer(pInputBuffer->buffer, mStreamType);
   1747             if (NO_ERROR != rc) {
   1748                 ALOGE("%s: On-the-fly input buffer registration failed %d",
   1749                         __func__, rc);
   1750                 return rc;
   1751             }
   1752 
   1753             input_index = mOfflineMemory.getMatchBufIndex((void*)pInputBuffer->buffer);
   1754             if (input_index < 0) {
   1755                 ALOGE("%s: Could not find object among registered buffers",__func__);
   1756                 return DEAD_OBJECT;
   1757             }
   1758         }
   1759         qcamera_fwk_input_pp_data_t *src_frame = NULL;
   1760         src_frame = (qcamera_fwk_input_pp_data_t *)malloc(
   1761                 sizeof(qcamera_fwk_input_pp_data_t));
   1762         if (src_frame == NULL) {
   1763             ALOGE("%s: No memory for src frame", __func__);
   1764             return NO_MEMORY;
   1765         }
   1766         memset(src_frame, 0, sizeof(qcamera_fwk_input_pp_data_t));
   1767         src_frame->src_frame = *pInputBuffer;
   1768         rc = mOfflineMemory.getBufDef(reproc_cfg.input_stream_plane_info.plane_info,
   1769                 src_frame->input_buffer, input_index);
   1770         if (rc != 0) {
   1771             free(src_frame);
   1772             return rc;
   1773         }
   1774         if (mYUVDump) {
   1775            dumpYUV(&src_frame->input_buffer, reproc_cfg.input_stream_dim,
   1776                    reproc_cfg.input_stream_plane_info.plane_info, 1);
   1777         }
   1778         cam_dimension_t dim = {sizeof(metadata_buffer_t), 1};
   1779         cam_stream_buf_plane_info_t meta_planes;
   1780         rc = mm_stream_calc_offset_metadata(&dim, mPaddingInfo, &meta_planes);
   1781         if (rc != 0) {
   1782             ALOGE("%s: Metadata stream plane info calculation failed!", __func__);
   1783             free(src_frame);
   1784             return rc;
   1785         }
   1786 
   1787         rc = mOfflineMetaMemory.allocate(1, sizeof(metadata_buffer_t), false);
   1788         if (NO_ERROR != rc) {
   1789             ALOGE("%s: Couldn't allocate offline metadata buffer!", __func__);
   1790             free(src_frame);
   1791             return rc;
   1792         }
   1793         mm_camera_buf_def_t meta_buf;
   1794         cam_frame_len_offset_t offset = meta_planes.plane_info;
   1795         rc = mOfflineMetaMemory.getBufDef(offset, meta_buf, 0);
   1796         if (NO_ERROR != rc) {
   1797             free(src_frame);
   1798             return rc;
   1799         }
   1800         memcpy(meta_buf.buffer, metadata, sizeof(metadata_buffer_t));
   1801         src_frame->metadata_buffer = meta_buf;
   1802         src_frame->reproc_config = reproc_cfg;
   1803 
   1804         CDBG_HIGH("%s: Post-process started", __func__);
   1805         CDBG_HIGH("%s: Issue call to reprocess", __func__);
   1806 
   1807         m_postprocessor.processData(src_frame);
   1808     }
   1809     return rc;
   1810 }
   1811 
   1812 
   1813 /*===========================================================================
   1814  * FUNCTION : metadataBufDone
   1815  *
   1816  * DESCRIPTION: Buffer done method for a metadata buffer
   1817  *
   1818  * PARAMETERS :
   1819  * @recvd_frame : received metadata frame
   1820  *
   1821  * RETURN     : int32_t type of status
   1822  *              NO_ERROR  -- success
   1823  *              none-zero failure code
   1824  *==========================================================================*/
   1825 int32_t QCamera3PicChannel::metadataBufDone(mm_camera_super_buf_t *recvd_frame)
   1826 {
   1827     int32_t rc = NO_ERROR;;
   1828     if ((NULL == m_pMetaChannel) || (NULL == recvd_frame)) {
   1829         ALOGE("%s: Metadata channel or metadata buffer invalid", __func__);
   1830         return BAD_VALUE;
   1831     }
   1832 
   1833     rc = ((QCamera3MetadataChannel*)m_pMetaChannel)->bufDone(recvd_frame);
   1834 
   1835     return rc;
   1836 }
   1837 
   1838 /*===========================================================================
   1839  * FUNCTION   : dataNotifyCB
   1840  *
   1841  * DESCRIPTION: Channel Level callback used for super buffer data notify.
   1842  *              This function is registered with mm-camera-interface to handle
   1843  *              data notify
   1844  *
   1845  * PARAMETERS :
   1846  *   @recvd_frame   : stream frame received
   1847  *   userdata       : user data ptr
   1848  *
   1849  * RETURN     : none
   1850  *==========================================================================*/
   1851 void QCamera3PicChannel::dataNotifyCB(mm_camera_super_buf_t *recvd_frame,
   1852                                  void *userdata)
   1853 {
   1854     ATRACE_CALL();
   1855     CDBG("%s: E\n", __func__);
   1856     QCamera3PicChannel *channel = (QCamera3PicChannel *)userdata;
   1857 
   1858     if (channel == NULL) {
   1859         ALOGE("%s: invalid channel pointer", __func__);
   1860         return;
   1861     }
   1862 
   1863     if(channel->m_numStreams != 1) {
   1864         ALOGE("%s: Error: Bug: This callback assumes one stream per channel",__func__);
   1865         return;
   1866     }
   1867 
   1868 
   1869     if(channel->mStreams[0] == NULL) {
   1870         ALOGE("%s: Error: Invalid Stream object",__func__);
   1871         return;
   1872     }
   1873 
   1874     channel->QCamera3PicChannel::streamCbRoutine(recvd_frame, channel->mStreams[0]);
   1875 
   1876     CDBG("%s: X\n", __func__);
   1877     return;
   1878 }
   1879 
   1880 /*===========================================================================
   1881  * FUNCTION   : registerBuffer
   1882  *
   1883  * DESCRIPTION: register streaming buffer to the channel object
   1884  *
   1885  * PARAMETERS :
   1886  *   @buffer     : buffer to be registered
   1887  *
   1888  * RETURN     : int32_t type of status
   1889  *              NO_ERROR  -- success
   1890  *              none-zero failure code
   1891  *==========================================================================*/
   1892 int32_t QCamera3PicChannel::registerBuffer(buffer_handle_t *buffer, cam_is_type_t isType)
   1893 {
   1894     int rc = 0;
   1895     mIsType = isType;
   1896     if ((uint32_t)mMemory.getCnt() > (mNumBufsRegistered - 1)) {
   1897         ALOGE("%s: Trying to register more buffers than initially requested",
   1898                 __func__);
   1899         return BAD_VALUE;
   1900     }
   1901 
   1902     if (0 == m_numStreams) {
   1903         rc = initialize(mIsType);
   1904         if (rc != NO_ERROR) {
   1905             ALOGE("%s: Couldn't initialize camera stream %d",
   1906                     __func__, rc);
   1907             return rc;
   1908         }
   1909     }
   1910 
   1911     rc = mMemory.registerBuffer(buffer, mStreamType);
   1912     if (ALREADY_EXISTS == rc) {
   1913         return NO_ERROR;
   1914     } else if (NO_ERROR != rc) {
   1915         ALOGE("%s: Buffer %p couldn't be registered %d", __func__, buffer, rc);
   1916         return rc;
   1917     }
   1918 
   1919     CDBG("%s: X",__func__);
   1920 
   1921     return rc;
   1922 }
   1923 
   1924 void QCamera3PicChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
   1925                             QCamera3Stream *stream)
   1926 {
   1927     ATRACE_CALL();
   1928     //TODO
   1929     //Used only for getting YUV. Jpeg callback will be sent back from channel
   1930     //directly to HWI. Refer to func jpegEvtHandle
   1931 
   1932     //Got the yuv callback. Calling yuv callback handler in PostProc
   1933     uint8_t frameIndex;
   1934     mm_camera_super_buf_t* frame = NULL;
   1935     if(!super_frame) {
   1936          ALOGE("%s: Invalid Super buffer",__func__);
   1937          return;
   1938     }
   1939 
   1940     if(super_frame->num_bufs != 1) {
   1941          ALOGE("%s: Multiple streams are not supported",__func__);
   1942          return;
   1943     }
   1944     if(super_frame->bufs[0] == NULL ) {
   1945          ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
   1946                   __func__);
   1947          return;
   1948     }
   1949 
   1950     frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
   1951     CDBG("%s: recvd buf_idx: %u for further processing",
   1952         __func__, (uint32_t)frameIndex);
   1953     if(frameIndex >= mNumSnapshotBufs) {
   1954          ALOGE("%s: Error, Invalid index for buffer",__func__);
   1955          if(stream) {
   1956              Mutex::Autolock lock(mFreeBuffersLock);
   1957              mFreeBufferList.push_back(frameIndex);
   1958              stream->bufDone(frameIndex);
   1959          }
   1960          return;
   1961     }
   1962 
   1963     frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
   1964     if (frame == NULL) {
   1965        ALOGE("%s: Error allocating memory to save received_frame structure.",
   1966                                                                     __func__);
   1967        if(stream) {
   1968            Mutex::Autolock lock(mFreeBuffersLock);
   1969            mFreeBufferList.push_back(frameIndex);
   1970            stream->bufDone(frameIndex);
   1971        }
   1972        return;
   1973     }
   1974     *frame = *super_frame;
   1975 
   1976     if(mYUVDump) {
   1977         cam_dimension_t dim;
   1978         memset(&dim, 0, sizeof(dim));
   1979         stream->getFrameDimension(dim);
   1980         cam_frame_len_offset_t offset;
   1981         memset(&offset, 0, sizeof(cam_frame_len_offset_t));
   1982         stream->getFrameOffset(offset);
   1983         dumpYUV(frame->bufs[0], dim, offset, 1);
   1984     }
   1985 
   1986     m_postprocessor.processData(frame);
   1987     free(super_frame);
   1988     return;
   1989 }
   1990 
   1991 QCamera3Memory* QCamera3PicChannel::getStreamBufs(uint32_t len)
   1992 {
   1993     int rc = 0;
   1994 
   1995     mYuvMemory = new QCamera3HeapMemory();
   1996     if (!mYuvMemory) {
   1997         ALOGE("%s: unable to create metadata memory", __func__);
   1998         return NULL;
   1999     }
   2000 
   2001     //Queue YUV buffers in the beginning mQueueAll = true
   2002     rc = mYuvMemory->allocate(mCamera3Stream->max_buffers, len, false);
   2003     if (rc < 0) {
   2004         ALOGE("%s: unable to allocate metadata memory", __func__);
   2005         delete mYuvMemory;
   2006         mYuvMemory = NULL;
   2007         return NULL;
   2008     }
   2009     return mYuvMemory;
   2010 }
   2011 
   2012 void QCamera3PicChannel::putStreamBufs()
   2013 {
   2014     mMemory.unregisterBuffers();
   2015 
   2016     mYuvMemory->deallocate();
   2017     delete mYuvMemory;
   2018     mYuvMemory = NULL;
   2019 }
   2020 
   2021 int32_t QCamera3PicChannel::queueReprocMetadata(mm_camera_super_buf_t *metadata)
   2022 {
   2023     return m_postprocessor.processPPMetadata(metadata);
   2024 }
   2025 
   2026 int32_t QCamera3PicChannel::queueJpegSetting(int32_t index, metadata_buffer_t *metadata)
   2027 {
   2028     jpeg_settings_t *settings =
   2029             (jpeg_settings_t *)malloc(sizeof(jpeg_settings_t));
   2030 
   2031     if (!settings) {
   2032         ALOGE("%s: out of memory allocating jpeg_settings", __func__);
   2033         return -ENOMEM;
   2034     }
   2035 
   2036     memset(settings, 0, sizeof(jpeg_settings_t));
   2037 
   2038     settings->out_buf_index = index;
   2039 
   2040     settings->jpeg_orientation = 0;
   2041     if (IS_PARAM_AVAILABLE(CAM_INTF_META_JPEG_ORIENTATION, metadata)) {
   2042         int32_t *orientation = (int32_t *)POINTER_OF_PARAM(
   2043                 CAM_INTF_META_JPEG_ORIENTATION, metadata);
   2044         settings->jpeg_orientation = *orientation;
   2045     }
   2046 
   2047     settings->jpeg_quality = 85;
   2048     if (IS_PARAM_AVAILABLE(CAM_INTF_META_JPEG_QUALITY, metadata)) {
   2049         uint8_t *quality = (uint8_t *)POINTER_OF_PARAM(
   2050                 CAM_INTF_META_JPEG_QUALITY, metadata);
   2051         settings->jpeg_quality = *quality;
   2052     }
   2053 
   2054     if (IS_PARAM_AVAILABLE(CAM_INTF_META_JPEG_THUMB_QUALITY, metadata)) {
   2055         uint8_t *quality = (uint8_t *)POINTER_OF_PARAM(
   2056                 CAM_INTF_META_JPEG_THUMB_QUALITY, metadata);
   2057         settings->jpeg_thumb_quality = *quality;
   2058     }
   2059 
   2060     if (IS_PARAM_AVAILABLE(CAM_INTF_META_JPEG_THUMB_SIZE, metadata)) {
   2061         cam_dimension_t *dimension = (cam_dimension_t *)POINTER_OF_PARAM(
   2062                 CAM_INTF_META_JPEG_THUMB_SIZE, metadata);
   2063         settings->thumbnail_size = *dimension;
   2064     }
   2065 
   2066     settings->gps_timestamp_valid = 0;
   2067     if (IS_PARAM_AVAILABLE(CAM_INTF_META_JPEG_GPS_TIMESTAMP, metadata)) {
   2068         int64_t *timestamp = (int64_t *)POINTER_OF_PARAM(
   2069                 CAM_INTF_META_JPEG_GPS_TIMESTAMP, metadata);
   2070         settings->gps_timestamp = *timestamp;
   2071         settings->gps_timestamp_valid = 1;
   2072     }
   2073 
   2074     settings->gps_coordinates_valid = 0;
   2075     if (IS_PARAM_AVAILABLE(CAM_INTF_META_JPEG_GPS_COORDINATES, metadata)) {
   2076         double *coordinates = (double *)POINTER_OF_PARAM(
   2077                 CAM_INTF_META_JPEG_GPS_COORDINATES, metadata);
   2078         memcpy(settings->gps_coordinates, coordinates, 3*sizeof(double));
   2079         settings->gps_coordinates_valid = 1;
   2080     }
   2081 
   2082     if (IS_PARAM_AVAILABLE(CAM_INTF_META_JPEG_GPS_PROC_METHODS, metadata)) {
   2083         char *proc_methods = (char *)POINTER_OF_PARAM(
   2084                 CAM_INTF_META_JPEG_GPS_PROC_METHODS, metadata);
   2085         memset(settings->gps_processing_method, 0,
   2086                 sizeof(settings->gps_processing_method));
   2087         strncpy(settings->gps_processing_method, proc_methods,
   2088                 sizeof(settings->gps_processing_method));
   2089     }
   2090 
   2091     return m_postprocessor.processJpegSettingData(settings);
   2092 }
   2093 
   2094 /*===========================================================================
   2095  * FUNCTION   : getRational
   2096  *
   2097  * DESCRIPTION: compose rational struct
   2098  *
   2099  * PARAMETERS :
   2100  *   @rat     : ptr to struct to store rational info
   2101  *   @num     :num of the rational
   2102  *   @denom   : denom of the rational
   2103  *
   2104  * RETURN     : int32_t type of status
   2105  *              NO_ERROR  -- success
   2106  *              none-zero failure code
   2107  *==========================================================================*/
   2108 int32_t getRational(rat_t *rat, int num, int denom)
   2109 {
   2110     if (NULL == rat) {
   2111         ALOGE("%s: NULL rat input", __func__);
   2112         return BAD_VALUE;
   2113     }
   2114     rat->num = num;
   2115     rat->denom = denom;
   2116     return NO_ERROR;
   2117 }
   2118 
   2119 /*===========================================================================
   2120  * FUNCTION   : parseGPSCoordinate
   2121  *
   2122  * DESCRIPTION: parse GPS coordinate string
   2123  *
   2124  * PARAMETERS :
   2125  *   @coord_str : [input] coordinate string
   2126  *   @coord     : [output]  ptr to struct to store coordinate
   2127  *
   2128  * RETURN     : int32_t type of status
   2129  *              NO_ERROR  -- success
   2130  *              none-zero failure code
   2131  *==========================================================================*/
   2132 int parseGPSCoordinate(const char *coord_str, rat_t* coord)
   2133 {
   2134     if(coord == NULL) {
   2135         ALOGE("%s: error, invalid argument coord == NULL", __func__);
   2136         return BAD_VALUE;
   2137     }
   2138     float degF = atof(coord_str);
   2139     if (degF < 0) {
   2140         degF = -degF;
   2141     }
   2142     float minF = (degF - (int) degF) * 60;
   2143     float secF = (minF - (int) minF) * 60;
   2144 
   2145     getRational(&coord[0], (int)degF, 1);
   2146     getRational(&coord[1], (int)minF, 1);
   2147     getRational(&coord[2], (int)(secF * 10000), 10000);
   2148     return NO_ERROR;
   2149 }
   2150 
   2151 /*===========================================================================
   2152  * FUNCTION   : getExifDateTime
   2153  *
   2154  * DESCRIPTION: query exif date time
   2155  *
   2156  * PARAMETERS :
   2157  *   @dateTime   : string to store exif date time
   2158  *   @subsecTime : string to store exif subsec time
   2159  *   @count      : length of the dateTime string
   2160  *   @subsecCount: length of the subsecTime string
   2161  *
   2162  * RETURN     : int32_t type of status
   2163  *              NO_ERROR  -- success
   2164  *              none-zero failure code
   2165  *==========================================================================*/
   2166 int32_t getExifDateTime(char *dateTime, char *subsecTime,
   2167         uint32_t &count, uint32_t &subsecCount)
   2168 {
   2169     //get time and date from system
   2170     struct timeval tv;
   2171     struct tm *timeinfo;
   2172 
   2173     gettimeofday(&tv, NULL);
   2174     timeinfo = localtime(&tv.tv_sec);
   2175     //Write datetime according to EXIF Spec
   2176     //"YYYY:MM:DD HH:MM:SS" (20 chars including \0)
   2177     snprintf(dateTime, 20, "%04d:%02d:%02d %02d:%02d:%02d",
   2178              timeinfo->tm_year + 1900, timeinfo->tm_mon + 1,
   2179              timeinfo->tm_mday, timeinfo->tm_hour,
   2180              timeinfo->tm_min, timeinfo->tm_sec);
   2181     count = 20;
   2182 
   2183     //Write subsec according to EXIF Sepc
   2184     snprintf(subsecTime, 7, "%06ld", tv.tv_usec);
   2185     subsecCount = 7;
   2186     return NO_ERROR;
   2187 }
   2188 
   2189 /*===========================================================================
   2190  * FUNCTION   : getExifFocalLength
   2191  *
   2192  * DESCRIPTION: get exif focal lenght
   2193  *
   2194  * PARAMETERS :
   2195  *   @focalLength : ptr to rational strcut to store focal lenght
   2196  *
   2197  * RETURN     : int32_t type of status
   2198  *              NO_ERROR  -- success
   2199  *              none-zero failure code
   2200  *==========================================================================*/
   2201 int32_t getExifFocalLength(rat_t *focalLength, float value)
   2202 {
   2203     int focalLengthValue =
   2204         (int)(value * FOCAL_LENGTH_DECIMAL_PRECISION);
   2205     return getRational(focalLength, focalLengthValue, FOCAL_LENGTH_DECIMAL_PRECISION);
   2206 }
   2207 
   2208 /*===========================================================================
   2209   * FUNCTION   : getExifExpTimeInfo
   2210   *
   2211   * DESCRIPTION: get exif exposure time information
   2212   *
   2213   * PARAMETERS :
   2214   *   @expoTimeInfo     : expousure time value
   2215   * RETURN     : nt32_t type of status
   2216   *              NO_ERROR  -- success
   2217   *              none-zero failure code
   2218   *==========================================================================*/
   2219 int32_t getExifExpTimeInfo(rat_t *expoTimeInfo, int64_t value)
   2220 {
   2221 
   2222     int cal_exposureTime;
   2223     if (value != 0)
   2224         cal_exposureTime = value;
   2225     else
   2226         cal_exposureTime = 60;
   2227 
   2228     return getRational(expoTimeInfo, 1, cal_exposureTime);
   2229 }
   2230 
   2231 /*===========================================================================
   2232  * FUNCTION   : getExifGpsProcessingMethod
   2233  *
   2234  * DESCRIPTION: get GPS processing method
   2235  *
   2236  * PARAMETERS :
   2237  *   @gpsProcessingMethod : string to store GPS process method
   2238  *   @count               : lenght of the string
   2239  *
   2240  * RETURN     : int32_t type of status
   2241  *              NO_ERROR  -- success
   2242  *              none-zero failure code
   2243  *==========================================================================*/
   2244 int32_t getExifGpsProcessingMethod(char *gpsProcessingMethod,
   2245                                    uint32_t &count, char* value)
   2246 {
   2247     if(value != NULL) {
   2248         memcpy(gpsProcessingMethod, ExifAsciiPrefix, EXIF_ASCII_PREFIX_SIZE);
   2249         count = EXIF_ASCII_PREFIX_SIZE;
   2250         strncpy(gpsProcessingMethod + EXIF_ASCII_PREFIX_SIZE, value, strlen(value));
   2251         count += strlen(value);
   2252         gpsProcessingMethod[count++] = '\0'; // increase 1 for the last NULL char
   2253         return NO_ERROR;
   2254     } else {
   2255         return BAD_VALUE;
   2256     }
   2257 }
   2258 
   2259 /*===========================================================================
   2260  * FUNCTION   : getExifLatitude
   2261  *
   2262  * DESCRIPTION: get exif latitude
   2263  *
   2264  * PARAMETERS :
   2265  *   @latitude : ptr to rational struct to store latitude info
   2266  *   @ladRef   : charater to indicate latitude reference
   2267  *
   2268  * RETURN     : int32_t type of status
   2269  *              NO_ERROR  -- success
   2270  *              none-zero failure code
   2271  *==========================================================================*/
   2272 int32_t getExifLatitude(rat_t *latitude,
   2273                                            char *latRef, double value)
   2274 {
   2275     char str[30];
   2276     snprintf(str, sizeof(str), "%f", value);
   2277     if(str != NULL) {
   2278         parseGPSCoordinate(str, latitude);
   2279 
   2280         //set Latitude Ref
   2281         float latitudeValue = strtof(str, 0);
   2282         if(latitudeValue < 0.0f) {
   2283             latRef[0] = 'S';
   2284         } else {
   2285             latRef[0] = 'N';
   2286         }
   2287         latRef[1] = '\0';
   2288         return NO_ERROR;
   2289     }else{
   2290         return BAD_VALUE;
   2291     }
   2292 }
   2293 
   2294 /*===========================================================================
   2295  * FUNCTION   : getExifLongitude
   2296  *
   2297  * DESCRIPTION: get exif longitude
   2298  *
   2299  * PARAMETERS :
   2300  *   @longitude : ptr to rational struct to store longitude info
   2301  *   @lonRef    : charater to indicate longitude reference
   2302  *
   2303  * RETURN     : int32_t type of status
   2304  *              NO_ERROR  -- success
   2305  *              none-zero failure code
   2306  *==========================================================================*/
   2307 int32_t getExifLongitude(rat_t *longitude,
   2308                                             char *lonRef, double value)
   2309 {
   2310     char str[30];
   2311     snprintf(str, sizeof(str), "%f", value);
   2312     if(str != NULL) {
   2313         parseGPSCoordinate(str, longitude);
   2314 
   2315         //set Longitude Ref
   2316         float longitudeValue = strtof(str, 0);
   2317         if(longitudeValue < 0.0f) {
   2318             lonRef[0] = 'W';
   2319         } else {
   2320             lonRef[0] = 'E';
   2321         }
   2322         lonRef[1] = '\0';
   2323         return NO_ERROR;
   2324     }else{
   2325         return BAD_VALUE;
   2326     }
   2327 }
   2328 
   2329 /*===========================================================================
   2330  * FUNCTION   : getExifAltitude
   2331  *
   2332  * DESCRIPTION: get exif altitude
   2333  *
   2334  * PARAMETERS :
   2335  *   @altitude : ptr to rational struct to store altitude info
   2336  *   @altRef   : charater to indicate altitude reference
   2337  *
   2338  * RETURN     : int32_t type of status
   2339  *              NO_ERROR  -- success
   2340  *              none-zero failure code
   2341  *==========================================================================*/
   2342 int32_t getExifAltitude(rat_t *altitude,
   2343                                            char *altRef, double value)
   2344 {
   2345     char str[30];
   2346     snprintf(str, sizeof(str), "%f", value);
   2347     if(str != NULL) {
   2348         double value = atof(str);
   2349         *altRef = 0;
   2350         if(value < 0){
   2351             *altRef = 1;
   2352             value = -value;
   2353         }
   2354         return getRational(altitude, value*1000, 1000);
   2355     }else{
   2356         return BAD_VALUE;
   2357     }
   2358 }
   2359 
   2360 /*===========================================================================
   2361  * FUNCTION   : getExifGpsDateTimeStamp
   2362  *
   2363  * DESCRIPTION: get exif GPS date time stamp
   2364  *
   2365  * PARAMETERS :
   2366  *   @gpsDateStamp : GPS date time stamp string
   2367  *   @bufLen       : length of the string
   2368  *   @gpsTimeStamp : ptr to rational struct to store time stamp info
   2369  *
   2370  * RETURN     : int32_t type of status
   2371  *              NO_ERROR  -- success
   2372  *              none-zero failure code
   2373  *==========================================================================*/
   2374 int32_t getExifGpsDateTimeStamp(char *gpsDateStamp,
   2375                                            uint32_t bufLen,
   2376                                            rat_t *gpsTimeStamp, int64_t value)
   2377 {
   2378     char str[30];
   2379     snprintf(str, sizeof(str), "%lld", value);
   2380     if(str != NULL) {
   2381         time_t unixTime = (time_t)atol(str);
   2382         struct tm *UTCTimestamp = gmtime(&unixTime);
   2383 
   2384         strftime(gpsDateStamp, bufLen, "%Y:%m:%d", UTCTimestamp);
   2385 
   2386         getRational(&gpsTimeStamp[0], UTCTimestamp->tm_hour, 1);
   2387         getRational(&gpsTimeStamp[1], UTCTimestamp->tm_min, 1);
   2388         getRational(&gpsTimeStamp[2], UTCTimestamp->tm_sec, 1);
   2389 
   2390         return NO_ERROR;
   2391     } else {
   2392         return BAD_VALUE;
   2393     }
   2394 }
   2395 
   2396 int32_t getExifExposureValue(srat_t* exposure_val, int32_t exposure_comp,
   2397                              cam_rational_type_t step)
   2398 {
   2399     exposure_val->num = exposure_comp * step.numerator;
   2400     exposure_val->denom = step.denominator;
   2401     return 0;
   2402 }
   2403 /*===========================================================================
   2404  * FUNCTION   : getExifData
   2405  *
   2406  * DESCRIPTION: get exif data to be passed into jpeg encoding
   2407  *
   2408  * PARAMETERS : none
   2409  *
   2410  * RETURN     : exif data from user setting and GPS
   2411  *==========================================================================*/
   2412 QCamera3Exif *QCamera3PicChannel::getExifData(metadata_buffer_t *metadata,
   2413         jpeg_settings_t *jpeg_settings)
   2414 {
   2415     QCamera3Exif *exif = new QCamera3Exif();
   2416     if (exif == NULL) {
   2417         ALOGE("%s: No memory for QCamera3Exif", __func__);
   2418         return NULL;
   2419     }
   2420 
   2421     int32_t rc = NO_ERROR;
   2422     uint32_t count = 0;
   2423 
   2424     // add exif entries
   2425     {
   2426         char dateTime[20];
   2427         char subsecTime[7];
   2428         uint32_t subsecCount;
   2429         memset(dateTime, 0, sizeof(dateTime));
   2430         memset(subsecTime, 0, sizeof(subsecTime));
   2431         count = 20;
   2432         subsecCount = 7;
   2433         rc = getExifDateTime(dateTime, subsecTime, count, subsecCount);
   2434         if(rc == NO_ERROR) {
   2435             exif->addEntry(EXIFTAGID_DATE_TIME,
   2436                     EXIF_ASCII,
   2437                     count,
   2438                     (void *)dateTime);
   2439             exif->addEntry(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL,
   2440                     EXIF_ASCII,
   2441                     count,
   2442                     (void *)dateTime);
   2443             exif->addEntry(EXIFTAGID_EXIF_DATE_TIME_DIGITIZED,
   2444                     EXIF_ASCII,
   2445                     count,
   2446                     (void *)dateTime);
   2447             exif->addEntry(EXIFTAGID_SUBSEC_TIME,
   2448                     EXIF_ASCII,
   2449                     subsecCount,
   2450                     (void *)subsecTime);
   2451             exif->addEntry(EXIFTAGID_SUBSEC_TIME_ORIGINAL,
   2452                     EXIF_ASCII,
   2453                     subsecCount,
   2454                     (void *)subsecTime);
   2455             exif->addEntry(EXIFTAGID_SUBSEC_TIME_DIGITIZED,
   2456                     EXIF_ASCII,
   2457                     subsecCount,
   2458                     (void *)subsecTime);
   2459         } else {
   2460             ALOGE("%s: getExifDateTime failed", __func__);
   2461         }
   2462     }
   2463 
   2464     if (IS_PARAM_AVAILABLE(CAM_INTF_META_LENS_FOCAL_LENGTH, metadata)) {
   2465         float focal_length = *(float *)POINTER_OF_PARAM(
   2466                 CAM_INTF_META_LENS_FOCAL_LENGTH, metadata);
   2467         rat_t focalLength;
   2468         rc = getExifFocalLength(&focalLength, focal_length);
   2469         if (rc == NO_ERROR) {
   2470             exif->addEntry(EXIFTAGID_FOCAL_LENGTH,
   2471                     EXIF_RATIONAL,
   2472                     1,
   2473                     (void *)&(focalLength));
   2474         } else {
   2475             ALOGE("%s: getExifFocalLength failed", __func__);
   2476         }
   2477     }
   2478 
   2479     if (IS_PARAM_AVAILABLE(CAM_INTF_META_SENSOR_SENSITIVITY, metadata)) {
   2480         int16_t isoSpeed = *(int32_t *)POINTER_OF_PARAM(
   2481                 CAM_INTF_META_SENSOR_SENSITIVITY, metadata);
   2482         exif->addEntry(EXIFTAGID_ISO_SPEED_RATING,
   2483                    EXIF_SHORT,
   2484                    1,
   2485                    (void *)&(isoSpeed));
   2486     }
   2487 
   2488     if (IS_PARAM_AVAILABLE(CAM_INTF_META_SENSOR_EXPOSURE_TIME, metadata)) {
   2489         int64_t sensor_exposure_time = *(int64_t *)POINTER_OF_PARAM(
   2490                 CAM_INTF_META_SENSOR_EXPOSURE_TIME, metadata);
   2491         rat_t sensorExpTime;
   2492         rc = getExifExpTimeInfo(&sensorExpTime, sensor_exposure_time);
   2493         if (rc == NO_ERROR){
   2494             exif->addEntry(EXIFTAGID_EXPOSURE_TIME,
   2495                     EXIF_RATIONAL,
   2496                     1,
   2497                     (void *)&(sensorExpTime));
   2498         } else {
   2499             ALOGE("%s: getExifExpTimeInfo failed", __func__);
   2500         }
   2501     }
   2502 
   2503     if (strlen(jpeg_settings->gps_processing_method) > 0) {
   2504         char gpsProcessingMethod[
   2505                     EXIF_ASCII_PREFIX_SIZE + GPS_PROCESSING_METHOD_SIZE];
   2506         count = 0;
   2507         rc = getExifGpsProcessingMethod(gpsProcessingMethod,
   2508                 count, jpeg_settings->gps_processing_method);
   2509         if(rc == NO_ERROR) {
   2510             exif->addEntry(EXIFTAGID_GPS_PROCESSINGMETHOD,
   2511                     EXIF_ASCII,
   2512                     count,
   2513                     (void *)gpsProcessingMethod);
   2514         } else {
   2515             ALOGE("%s: getExifGpsProcessingMethod failed", __func__);
   2516         }
   2517     }
   2518 
   2519     if (jpeg_settings->gps_coordinates_valid) {
   2520 
   2521         //latitude
   2522         rat_t latitude[3];
   2523         char latRef[2];
   2524         rc = getExifLatitude(latitude, latRef,
   2525                 jpeg_settings->gps_coordinates[0]);
   2526         if(rc == NO_ERROR) {
   2527             exif->addEntry(EXIFTAGID_GPS_LATITUDE,
   2528                            EXIF_RATIONAL,
   2529                            3,
   2530                            (void *)latitude);
   2531             exif->addEntry(EXIFTAGID_GPS_LATITUDE_REF,
   2532                            EXIF_ASCII,
   2533                            2,
   2534                            (void *)latRef);
   2535         } else {
   2536             ALOGE("%s: getExifLatitude failed", __func__);
   2537         }
   2538 
   2539         //longitude
   2540         rat_t longitude[3];
   2541         char lonRef[2];
   2542         rc = getExifLongitude(longitude, lonRef,
   2543                 jpeg_settings->gps_coordinates[1]);
   2544         if(rc == NO_ERROR) {
   2545             exif->addEntry(EXIFTAGID_GPS_LONGITUDE,
   2546                            EXIF_RATIONAL,
   2547                            3,
   2548                            (void *)longitude);
   2549 
   2550             exif->addEntry(EXIFTAGID_GPS_LONGITUDE_REF,
   2551                            EXIF_ASCII,
   2552                            2,
   2553                            (void *)lonRef);
   2554         } else {
   2555             ALOGE("%s: getExifLongitude failed", __func__);
   2556         }
   2557 
   2558         //altitude
   2559         rat_t altitude;
   2560         char altRef;
   2561         rc = getExifAltitude(&altitude, &altRef,
   2562                 jpeg_settings->gps_coordinates[2]);
   2563         if(rc == NO_ERROR) {
   2564             exif->addEntry(EXIFTAGID_GPS_ALTITUDE,
   2565                            EXIF_RATIONAL,
   2566                            1,
   2567                            (void *)&(altitude));
   2568 
   2569             exif->addEntry(EXIFTAGID_GPS_ALTITUDE_REF,
   2570                            EXIF_BYTE,
   2571                            1,
   2572                            (void *)&altRef);
   2573         } else {
   2574             ALOGE("%s: getExifAltitude failed", __func__);
   2575         }
   2576     }
   2577 
   2578     if (jpeg_settings->gps_timestamp_valid) {
   2579 
   2580         char gpsDateStamp[20];
   2581         rat_t gpsTimeStamp[3];
   2582         rc = getExifGpsDateTimeStamp(gpsDateStamp, 20, gpsTimeStamp,
   2583                 jpeg_settings->gps_timestamp);
   2584         if(rc == NO_ERROR) {
   2585             exif->addEntry(EXIFTAGID_GPS_DATESTAMP,
   2586                            EXIF_ASCII,
   2587                            strlen(gpsDateStamp) + 1,
   2588                            (void *)gpsDateStamp);
   2589 
   2590             exif->addEntry(EXIFTAGID_GPS_TIMESTAMP,
   2591                            EXIF_RATIONAL,
   2592                            3,
   2593                            (void *)gpsTimeStamp);
   2594         } else {
   2595             ALOGE("%s: getExifGpsDataTimeStamp failed", __func__);
   2596         }
   2597     }
   2598 
   2599     if (IS_PARAM_AVAILABLE(CAM_INTF_PARM_EXPOSURE_COMPENSATION, metadata) &&
   2600             IS_PARAM_AVAILABLE(CAM_INTF_PARM_EV_STEP, metadata)) {
   2601         int32_t exposure_comp = *(int32_t *)POINTER_OF_PARAM(
   2602                 CAM_INTF_PARM_EXPOSURE_COMPENSATION, metadata);
   2603         cam_rational_type_t comp_step = *(cam_rational_type_t *)POINTER_OF_PARAM(
   2604                 CAM_INTF_PARM_EV_STEP, metadata);
   2605         srat_t exposure_val;
   2606         rc = getExifExposureValue(&exposure_val, exposure_comp, comp_step);
   2607         if(rc == NO_ERROR) {
   2608             exif->addEntry(EXIFTAGID_EXPOSURE_BIAS_VALUE,
   2609                        EXIF_SRATIONAL,
   2610                        1,
   2611                        (void *)(&exposure_val));
   2612         } else {
   2613             ALOGE("%s: getExifExposureValue failed ", __func__);
   2614         }
   2615     }
   2616 
   2617     char value[PROPERTY_VALUE_MAX];
   2618     if (property_get("ro.product.manufacturer", value, "QCOM-AA") > 0) {
   2619         exif->addEntry(EXIFTAGID_MAKE,
   2620                        EXIF_ASCII,
   2621                        strlen(value) + 1,
   2622                        (void *)value);
   2623     } else {
   2624         ALOGE("%s: getExifMaker failed", __func__);
   2625     }
   2626 
   2627     if (property_get("ro.product.model", value, "QCAM-AA") > 0) {
   2628         exif->addEntry(EXIFTAGID_MODEL,
   2629                        EXIF_ASCII,
   2630                        strlen(value) + 1,
   2631                        (void *)value);
   2632     } else {
   2633         ALOGE("%s: getExifModel failed", __func__);
   2634     }
   2635 
   2636     return exif;
   2637 }
   2638 
   2639 /* There can be MAX_INFLIGHT_REQUESTS number of requests that could get queued up. Hence
   2640  allocating same number of picture channel buffers */
   2641 int QCamera3PicChannel::kMaxBuffers = MAX_INFLIGHT_REQUESTS;
   2642 
   2643 void QCamera3PicChannel::overrideYuvSize(uint32_t width, uint32_t height)
   2644 {
   2645    mYuvWidth = width;
   2646    mYuvHeight = height;
   2647 }
   2648 
   2649 /*===========================================================================
   2650  * FUNCTION   : QCamera3ReprocessChannel
   2651  *
   2652  * DESCRIPTION: constructor of QCamera3ReprocessChannel
   2653  *
   2654  * PARAMETERS :
   2655  *   @cam_handle : camera handle
   2656  *   @cam_ops    : ptr to camera ops table
   2657  *   @pp_mask    : post-proccess feature mask
   2658  *
   2659  * RETURN     : none
   2660  *==========================================================================*/
   2661 QCamera3ReprocessChannel::QCamera3ReprocessChannel(uint32_t cam_handle,
   2662                                                  mm_camera_ops_t *cam_ops,
   2663                                                  channel_cb_routine cb_routine,
   2664                                                  cam_padding_info_t *paddingInfo,
   2665                                                  uint32_t postprocess_mask,
   2666                                                  void *userData, void *ch_hdl) :
   2667     QCamera3Channel(cam_handle, cam_ops, cb_routine, paddingInfo, postprocess_mask,
   2668                     userData),
   2669     picChHandle(ch_hdl),
   2670     mOfflineBuffersIndex(-1),
   2671     m_pSrcChannel(NULL),
   2672     m_pMetaChannel(NULL),
   2673     mMemory(NULL)
   2674 {
   2675     memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles));
   2676     mOfflineMetaIndex = MAX_INFLIGHT_REQUESTS -1;
   2677 }
   2678 
   2679 
   2680 /*===========================================================================
   2681  * FUNCTION   : QCamera3ReprocessChannel
   2682  *
   2683  * DESCRIPTION: constructor of QCamera3ReprocessChannel
   2684  *
   2685  * PARAMETERS :
   2686  *   @cam_handle : camera handle
   2687  *   @cam_ops    : ptr to camera ops table
   2688  *   @pp_mask    : post-proccess feature mask
   2689  *
   2690  * RETURN     : none
   2691  *==========================================================================*/
   2692 int32_t QCamera3ReprocessChannel::initialize(cam_is_type_t isType)
   2693 {
   2694     int32_t rc = NO_ERROR;
   2695     mm_camera_channel_attr_t attr;
   2696 
   2697     memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
   2698     attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS;
   2699     attr.max_unmatched_frames = 1;
   2700 
   2701     rc = init(&attr, NULL);
   2702     if (rc < 0) {
   2703         ALOGE("%s: init failed", __func__);
   2704     }
   2705     mIsType = isType;
   2706     return rc;
   2707 }
   2708 
   2709 
   2710 /*===========================================================================
   2711  * FUNCTION   : QCamera3ReprocessChannel
   2712  *
   2713  * DESCRIPTION: constructor of QCamera3ReprocessChannel
   2714  *
   2715  * PARAMETERS :
   2716  *   @cam_handle : camera handle
   2717  *   @cam_ops    : ptr to camera ops table
   2718  *   @pp_mask    : post-proccess feature mask
   2719  *
   2720  * RETURN     : none
   2721  *==========================================================================*/
   2722 void QCamera3ReprocessChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
   2723                                   QCamera3Stream *stream)
   2724 {
   2725     //Got the pproc data callback. Now send to jpeg encoding
   2726     uint8_t frameIndex;
   2727     mm_camera_super_buf_t* frame = NULL;
   2728     QCamera3PicChannel *obj = (QCamera3PicChannel *)picChHandle;
   2729 
   2730     if(!super_frame) {
   2731          ALOGE("%s: Invalid Super buffer",__func__);
   2732          return;
   2733     }
   2734 
   2735     if(super_frame->num_bufs != 1) {
   2736          ALOGE("%s: Multiple streams are not supported",__func__);
   2737          return;
   2738     }
   2739     if(super_frame->bufs[0] == NULL ) {
   2740          ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
   2741                   __func__);
   2742          return;
   2743     }
   2744 
   2745     frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
   2746     frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
   2747     if (frame == NULL) {
   2748        ALOGE("%s: Error allocating memory to save received_frame structure.",
   2749                                                                     __func__);
   2750        if(stream) {
   2751            stream->bufDone(frameIndex);
   2752        }
   2753        return;
   2754     }
   2755     CDBG("%s: bufIndex: %u recvd from post proc",
   2756         __func__, (uint32_t)frameIndex);
   2757     *frame = *super_frame;
   2758     if(mYUVDump) {
   2759         cam_dimension_t dim;
   2760         memset(&dim, 0, sizeof(dim));
   2761         stream->getFrameDimension(dim);
   2762         cam_frame_len_offset_t offset;
   2763         memset(&offset, 0, sizeof(cam_frame_len_offset_t));
   2764         stream->getFrameOffset(offset);
   2765         dumpYUV(frame->bufs[0], dim, offset, 2);
   2766     }
   2767     obj->m_postprocessor.processPPData(frame);
   2768     free(super_frame);
   2769     return;
   2770 }
   2771 
   2772 /*===========================================================================
   2773  * FUNCTION   : QCamera3ReprocessChannel
   2774  *
   2775  * DESCRIPTION: default constructor of QCamera3ReprocessChannel
   2776  *
   2777  * PARAMETERS : none
   2778  *
   2779  * RETURN     : none
   2780  *==========================================================================*/
   2781 QCamera3ReprocessChannel::QCamera3ReprocessChannel() :
   2782     m_pSrcChannel(NULL),
   2783     m_pMetaChannel(NULL)
   2784 {
   2785 }
   2786 
   2787 /*===========================================================================
   2788  * FUNCTION   : getStreamBufs
   2789  *
   2790  * DESCRIPTION: register the buffers of the reprocess channel
   2791  *
   2792  * PARAMETERS : none
   2793  *
   2794  * RETURN     : QCamera3Memory *
   2795  *==========================================================================*/
   2796 QCamera3Memory* QCamera3ReprocessChannel::getStreamBufs(uint32_t len)
   2797 {
   2798    int rc = 0;
   2799 
   2800     mMemory = new QCamera3HeapMemory();
   2801     if (!mMemory) {
   2802         ALOGE("%s: unable to create reproc memory", __func__);
   2803         return NULL;
   2804     }
   2805 
   2806     //Queue YUV buffers in the beginning mQueueAll = true
   2807     /* There can be MAX_INFLIGHT_REQUESTS number of requests that could get queued up.
   2808      * Hence allocating same number of reprocess channel's output buffers */
   2809     rc = mMemory->allocate(MAX_INFLIGHT_REQUESTS, len, true);
   2810     if (rc < 0) {
   2811         ALOGE("%s: unable to allocate reproc memory", __func__);
   2812         delete mMemory;
   2813         mMemory = NULL;
   2814         return NULL;
   2815     }
   2816     return mMemory;
   2817 }
   2818 
   2819 /*===========================================================================
   2820  * FUNCTION   : getStreamBufs
   2821  *
   2822  * DESCRIPTION: register the buffers of the reprocess channel
   2823  *
   2824  * PARAMETERS : none
   2825  *
   2826  * RETURN     :
   2827  *==========================================================================*/
   2828 void QCamera3ReprocessChannel::putStreamBufs()
   2829 {
   2830     mMemory->deallocate();
   2831     delete mMemory;
   2832     mMemory = NULL;
   2833 }
   2834 
   2835 /*===========================================================================
   2836  * FUNCTION   : ~QCamera3ReprocessChannel
   2837  *
   2838  * DESCRIPTION: destructor of QCamera3ReprocessChannel
   2839  *
   2840  * PARAMETERS : none
   2841  *
   2842  * RETURN     : none
   2843  *==========================================================================*/
   2844 QCamera3ReprocessChannel::~QCamera3ReprocessChannel()
   2845 {
   2846 }
   2847 
   2848 /*===========================================================================
   2849  * FUNCTION   : getStreamBySrcHandle
   2850  *
   2851  * DESCRIPTION: find reprocess stream by its source stream handle
   2852  *
   2853  * PARAMETERS :
   2854  *   @srcHandle : source stream handle
   2855  *
   2856  * RETURN     : ptr to reprocess stream if found. NULL if not found
   2857  *==========================================================================*/
   2858 QCamera3Stream * QCamera3ReprocessChannel::getStreamBySrcHandle(uint32_t srcHandle)
   2859 {
   2860     QCamera3Stream *pStream = NULL;
   2861 
   2862     for (int i = 0; i < m_numStreams; i++) {
   2863         if (mSrcStreamHandles[i] == srcHandle) {
   2864             pStream = mStreams[i];
   2865             break;
   2866         }
   2867     }
   2868     return pStream;
   2869 }
   2870 
   2871 /*===========================================================================
   2872  * FUNCTION   : getSrcStreamBySrcHandle
   2873  *
   2874  * DESCRIPTION: find source stream by source stream handle
   2875  *
   2876  * PARAMETERS :
   2877  *   @srcHandle : source stream handle
   2878  *
   2879  * RETURN     : ptr to reprocess stream if found. NULL if not found
   2880  *==========================================================================*/
   2881 QCamera3Stream * QCamera3ReprocessChannel::getSrcStreamBySrcHandle(uint32_t srcHandle)
   2882 {
   2883     QCamera3Stream *pStream = NULL;
   2884 
   2885     if (NULL == m_pSrcChannel) {
   2886         return NULL;
   2887     }
   2888 
   2889     for (int i = 0; i < m_numStreams; i++) {
   2890         if (mSrcStreamHandles[i] == srcHandle) {
   2891             pStream = m_pSrcChannel->getStreamByIndex(i);
   2892             break;
   2893         }
   2894     }
   2895     return pStream;
   2896 }
   2897 
   2898 /*===========================================================================
   2899  * FUNCTION   : stop
   2900  *
   2901  * DESCRIPTION: stop channel
   2902  *
   2903  * PARAMETERS : none
   2904  *
   2905  * RETURN     : int32_t type of status
   2906  *              NO_ERROR  -- success
   2907  *              none-zero failure code
   2908  *==========================================================================*/
   2909 int32_t QCamera3ReprocessChannel::stop()
   2910 {
   2911     unmapOfflineBuffers(true);
   2912 
   2913     return QCamera3Channel::stop();
   2914 }
   2915 
   2916 /*===========================================================================
   2917  * FUNCTION   : unmapOfflineBuffers
   2918  *
   2919  * DESCRIPTION: Unmaps offline buffers
   2920  *
   2921  * PARAMETERS : none
   2922  *
   2923  * RETURN     : int32_t type of status
   2924  *              NO_ERROR  -- success
   2925  *              none-zero failure code
   2926  *==========================================================================*/
   2927 int32_t QCamera3ReprocessChannel::unmapOfflineBuffers(bool all)
   2928 {
   2929     int rc = NO_ERROR;
   2930     if (!mOfflineBuffers.empty()) {
   2931         QCamera3Stream *stream = NULL;
   2932         List<OfflineBuffer>::iterator it = mOfflineBuffers.begin();
   2933         for (; it != mOfflineBuffers.end(); it++) {
   2934            stream = (*it).stream;
   2935            if (NULL != stream) {
   2936                rc = stream->unmapBuf((*it).type,
   2937                                      (*it).index,
   2938                                         -1);
   2939                if (NO_ERROR != rc) {
   2940                    ALOGE("%s: Error during offline buffer unmap %d",
   2941                          __func__, rc);
   2942                }
   2943                CDBG("%s: Unmapped buffer with index %d", __func__, (*it).index);
   2944            }
   2945            if (!all) {
   2946                mOfflineBuffers.erase(it);
   2947                break;
   2948            }
   2949         }
   2950         if (all) {
   2951            mOfflineBuffers.clear();
   2952         }
   2953     }
   2954 
   2955     if (!mOfflineMetaBuffers.empty()) {
   2956         QCamera3Stream *stream = NULL;
   2957         List<OfflineBuffer>::iterator it = mOfflineMetaBuffers.begin();
   2958         for (; it != mOfflineMetaBuffers.end(); it++) {
   2959            stream = (*it).stream;
   2960            if (NULL != stream) {
   2961                rc = stream->unmapBuf((*it).type,
   2962                                      (*it).index,
   2963                                         -1);
   2964                if (NO_ERROR != rc) {
   2965                    ALOGE("%s: Error during offline buffer unmap %d",
   2966                          __func__, rc);
   2967                }
   2968                CDBG("%s: Unmapped meta buffer with index %d", __func__, (*it).index);
   2969            }
   2970            if (!all) {
   2971                mOfflineMetaBuffers.erase(it);
   2972                break;
   2973            }
   2974         }
   2975         if (all) {
   2976            mOfflineMetaBuffers.clear();
   2977         }
   2978     }
   2979     return rc;
   2980 }
   2981 
   2982 
   2983 /*===========================================================================
   2984  * FUNCTION   : extractFrameAndRotation
   2985  *
   2986  * DESCRIPTION: Extract output rotation and frame data if present
   2987  *
   2988  * PARAMETERS :
   2989  *   @frame     : input frame from source stream
   2990  *   meta_buffer: metadata buffer
   2991  *   @metadata  : corresponding metadata
   2992  *   @fwk_frame :
   2993  *
   2994  * RETURN     : int32_t type of status
   2995  *              NO_ERROR  -- success
   2996  *              none-zero failure code
   2997  *==========================================================================*/
   2998 int32_t QCamera3ReprocessChannel::extractFrameCropAndRotation(mm_camera_super_buf_t *frame,
   2999         mm_camera_buf_def_t *meta_buffer, jpeg_settings_t *jpeg_settings,
   3000         qcamera_fwk_input_pp_data_t &fwk_frame)
   3001 {
   3002     if ((NULL == meta_buffer) || (NULL == frame) || (NULL == jpeg_settings)) {
   3003         return BAD_VALUE;
   3004     }
   3005 
   3006     metadata_buffer_t *meta = (metadata_buffer_t *)meta_buffer->buffer;
   3007     if (NULL == meta) {
   3008         return BAD_VALUE;
   3009     }
   3010 
   3011     for (int i = 0; i < frame->num_bufs; i++) {
   3012         QCamera3Stream *pStream = getStreamBySrcHandle(frame->bufs[i]->stream_id);
   3013         QCamera3Stream *pSrcStream = getSrcStreamBySrcHandle(frame->bufs[i]->stream_id);
   3014 
   3015         if (pStream != NULL && pSrcStream != NULL) {
   3016             // Find rotation info for reprocess stream
   3017             if (jpeg_settings->jpeg_orientation == 0) {
   3018                fwk_frame.reproc_config.rotation = ROTATE_0;
   3019             } else if (jpeg_settings->jpeg_orientation == 90) {
   3020                fwk_frame.reproc_config.rotation = ROTATE_90;
   3021             } else if (jpeg_settings->jpeg_orientation == 180) {
   3022                fwk_frame.reproc_config.rotation = ROTATE_180;
   3023             } else if (jpeg_settings->jpeg_orientation == 270) {
   3024                fwk_frame.reproc_config.rotation = ROTATE_270;
   3025             }
   3026 
   3027             // Find crop info for reprocess stream
   3028             cam_crop_data_t *crop_data = (cam_crop_data_t *)
   3029                 POINTER_OF_PARAM(CAM_INTF_META_CROP_DATA, meta);
   3030             if (NULL != crop_data) {
   3031                 for (int j = 0; j < crop_data->num_of_streams; j++) {
   3032                     if (crop_data->crop_info[j].stream_id ==
   3033                         pSrcStream->getMyServerID()) {
   3034                         fwk_frame.reproc_config.output_crop =
   3035                             crop_data->crop_info[0].crop;
   3036                         CDBG("%s: Found offline reprocess crop %dx%d %dx%d",
   3037                               __func__,
   3038                               crop_data->crop_info[0].crop.left,
   3039                               crop_data->crop_info[0].crop.top,
   3040                               crop_data->crop_info[0].crop.width,
   3041                               crop_data->crop_info[0].crop.height);
   3042                      }
   3043                 }
   3044             }
   3045             fwk_frame.input_buffer = *frame->bufs[i];
   3046             fwk_frame.metadata_buffer = *meta_buffer;
   3047             break;
   3048         } else {
   3049             ALOGE("%s: Source/Re-process streams are invalid", __func__);
   3050             return BAD_VALUE;
   3051         }
   3052     }
   3053 
   3054     return NO_ERROR;
   3055 }
   3056 
   3057 /*===========================================================================
   3058  * FUNCTION   : extractCrop
   3059  *
   3060  * DESCRIPTION: Extract framework output crop if present
   3061  *
   3062  * PARAMETERS :
   3063  *   @frame     : input frame for reprocessing
   3064  *
   3065  * RETURN     : int32_t type of status
   3066  *              NO_ERROR  -- success
   3067  *              none-zero failure code
   3068  *==========================================================================*/
   3069 int32_t QCamera3ReprocessChannel::extractCrop(qcamera_fwk_input_pp_data_t *frame)
   3070 {
   3071     if (NULL == frame) {
   3072         ALOGE("%s: Incorrect input frame", __func__);
   3073         return BAD_VALUE;
   3074     }
   3075 
   3076     if (NULL == frame->metadata_buffer.buffer) {
   3077         ALOGE("%s: No metadata available", __func__);
   3078         return BAD_VALUE;
   3079     }
   3080 
   3081     // Find crop info for reprocess stream
   3082     metadata_buffer_t *meta = (metadata_buffer_t *) frame->metadata_buffer.buffer;
   3083     if (IS_META_AVAILABLE(CAM_INTF_META_CROP_DATA, meta)) {
   3084         cam_crop_data_t *crop_data = (cam_crop_data_t *)
   3085                 POINTER_OF_PARAM(CAM_INTF_META_CROP_DATA, meta);
   3086         if (1 == crop_data->num_of_streams) {
   3087             frame->reproc_config.output_crop = crop_data->crop_info[0].crop;
   3088             CDBG("%s: Found offline reprocess crop %dx%d %dx%d", __func__,
   3089                     crop_data->crop_info[0].crop.left,
   3090                     crop_data->crop_info[0].crop.top,
   3091                     crop_data->crop_info[0].crop.width,
   3092                     crop_data->crop_info[0].crop.height);
   3093         } else {
   3094             ALOGE("%s: Incorrect number of offline crop data entries %d",
   3095                     __func__,
   3096                     crop_data->num_of_streams);
   3097             return BAD_VALUE;
   3098         }
   3099     } else {
   3100         CDBG_HIGH("%s: Crop data not present", __func__);
   3101     }
   3102 
   3103     return NO_ERROR;
   3104 }
   3105 
   3106 /*===========================================================================
   3107  * FUNCTION   : doReprocessOffline
   3108  *
   3109  * DESCRIPTION: request to do a reprocess on the frame
   3110  *
   3111  * PARAMETERS :
   3112  *   @frame     : input frame for reprocessing
   3113  *
   3114  * RETURN     : int32_t type of status
   3115  *              NO_ERROR  -- success
   3116  *              none-zero failure code
   3117  *==========================================================================*/
   3118  int32_t QCamera3ReprocessChannel::doReprocessOffline(qcamera_fwk_input_pp_data_t *frame)
   3119 {
   3120     int32_t rc = 0;
   3121     OfflineBuffer mappedBuffer;
   3122 
   3123     if (m_numStreams < 1) {
   3124         ALOGE("%s: No reprocess stream is created", __func__);
   3125         return -1;
   3126     }
   3127 
   3128     if (NULL == frame) {
   3129         ALOGE("%s: Incorrect input frame", __func__);
   3130         return BAD_VALUE;
   3131     }
   3132 
   3133     if (NULL == frame->metadata_buffer.buffer) {
   3134         ALOGE("%s: No metadata available", __func__);
   3135         return BAD_VALUE;
   3136     }
   3137 
   3138     if (NULL == frame->input_buffer.buffer) {
   3139         ALOGE("%s: No input buffer available", __func__);
   3140         return BAD_VALUE;
   3141     }
   3142 
   3143     if ((0 == m_numStreams) || (NULL == mStreams[0])) {
   3144         ALOGE("%s: Reprocess stream not initialized!", __func__);
   3145         return NO_INIT;
   3146     }
   3147 
   3148     QCamera3Stream *pStream = mStreams[0];
   3149     int32_t max_idx = MAX_INFLIGHT_REQUESTS-1;
   3150     //loop back the indices if max burst count reached
   3151     if (mOfflineBuffersIndex == max_idx) {
   3152        mOfflineBuffersIndex = -1;
   3153     }
   3154     uint32_t buf_idx = mOfflineBuffersIndex + 1;
   3155 
   3156     rc = pStream->mapBuf(
   3157             CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
   3158             buf_idx, -1,
   3159             frame->input_buffer.fd, frame->input_buffer.frame_len);
   3160     if (NO_ERROR == rc) {
   3161         mappedBuffer.index = buf_idx;
   3162         mappedBuffer.stream = pStream;
   3163         mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF;
   3164         mOfflineBuffers.push_back(mappedBuffer);
   3165         mOfflineBuffersIndex = buf_idx;
   3166         CDBG("%s: Mapped buffer with index %d", __func__, mOfflineBuffersIndex);
   3167     }
   3168 
   3169     max_idx = MAX_INFLIGHT_REQUESTS*2 - 1;
   3170     //loop back the indices if max burst count reached
   3171     if (mOfflineMetaIndex == max_idx) {
   3172        mOfflineMetaIndex = MAX_INFLIGHT_REQUESTS-1;
   3173     }
   3174     uint32_t meta_buf_idx = mOfflineMetaIndex + 1;
   3175 
   3176     rc |= pStream->mapBuf(
   3177             CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF,
   3178             meta_buf_idx, -1,
   3179             frame->metadata_buffer.fd, frame->metadata_buffer.frame_len);
   3180     if (NO_ERROR == rc) {
   3181         mappedBuffer.index = meta_buf_idx;
   3182         mappedBuffer.stream = pStream;
   3183         mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF;
   3184         mOfflineMetaBuffers.push_back(mappedBuffer);
   3185         mOfflineMetaIndex = meta_buf_idx;
   3186         CDBG("%s: Mapped meta buffer with index %d", __func__, mOfflineMetaIndex);
   3187     }
   3188 
   3189     if (rc == NO_ERROR) {
   3190         cam_stream_parm_buffer_t param;
   3191         memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
   3192         param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
   3193         param.reprocess.buf_index = buf_idx;
   3194         param.reprocess.frame_idx = frame->input_buffer.frame_idx;
   3195         param.reprocess.meta_present = 1;
   3196         param.reprocess.meta_buf_index = meta_buf_idx;
   3197         param.reprocess.frame_pp_config.rotation = frame->reproc_config.rotation;
   3198         param.reprocess.frame_pp_config.crop.input_crop = frame->reproc_config.output_crop;
   3199         param.reprocess.frame_pp_config.crop.crop_enabled = 1;
   3200         rc = pStream->setParameter(param);
   3201         if (rc != NO_ERROR) {
   3202             ALOGE("%s: stream setParameter for reprocess failed", __func__);
   3203         }
   3204     } else {
   3205         ALOGE("%s: Input buffer memory map failed: %d", __func__, rc);
   3206     }
   3207 
   3208     return rc;
   3209 }
   3210 
   3211 /*===========================================================================
   3212  * FUNCTION   : doReprocess
   3213  *
   3214  * DESCRIPTION: request to do a reprocess on the frame
   3215  *
   3216  * PARAMETERS :
   3217  *   @buf_fd     : fd to the input buffer that needs reprocess
   3218  *   @buf_lenght : length of the input buffer
   3219  *   @ret_val    : result of reprocess.
   3220  *                 Example: Could be faceID in case of register face image.
   3221  *
   3222  * RETURN     : int32_t type of status
   3223  *              NO_ERROR  -- success
   3224  *              none-zero failure code
   3225  *==========================================================================*/
   3226 int32_t QCamera3ReprocessChannel::doReprocess(int buf_fd,
   3227                                               uint32_t buf_length,
   3228                                               int32_t &ret_val,
   3229                                               mm_camera_super_buf_t *meta_frame)
   3230 {
   3231     int32_t rc = 0;
   3232     if (m_numStreams < 1) {
   3233         ALOGE("%s: No reprocess stream is created", __func__);
   3234         return -1;
   3235     }
   3236     if (meta_frame == NULL) {
   3237         ALOGE("%s: Did not get corresponding metadata in time", __func__);
   3238         return -1;
   3239     }
   3240 
   3241     uint32_t buf_idx = 0;
   3242     for (int i = 0; i < m_numStreams; i++) {
   3243         rc = mStreams[i]->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
   3244                                  buf_idx, -1,
   3245                                  buf_fd, buf_length);
   3246 
   3247         if (rc == NO_ERROR) {
   3248             cam_stream_parm_buffer_t param;
   3249             memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
   3250             param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
   3251             param.reprocess.buf_index = buf_idx;
   3252             param.reprocess.meta_present = 1;
   3253             param.reprocess.meta_stream_handle = m_pMetaChannel->mStreams[0]->getMyServerID();
   3254             param.reprocess.meta_buf_index = meta_frame->bufs[0]->buf_idx;
   3255             rc = mStreams[i]->setParameter(param);
   3256             if (rc == NO_ERROR) {
   3257                 ret_val = param.reprocess.ret_val;
   3258             }
   3259             mStreams[i]->unmapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
   3260                                   buf_idx, -1);
   3261         }
   3262     }
   3263     return rc;
   3264 }
   3265 
   3266 /*===========================================================================
   3267  * FUNCTION   : addReprocStreamsFromSource
   3268  *
   3269  * DESCRIPTION: add reprocess streams from input source channel
   3270  *
   3271  * PARAMETERS :
   3272  *   @config         : pp feature configuration
   3273  *   @src_config     : source reprocess configuration
   3274  *   @pMetaChannel   : ptr to metadata channel to get corresp. metadata
   3275  *   @offline        : configure for offline reprocessing
   3276  *
   3277  * RETURN     : int32_t type of status
   3278  *              NO_ERROR  -- success
   3279  *              none-zero failure code
   3280  *==========================================================================*/
   3281 int32_t QCamera3ReprocessChannel::addReprocStreamsFromSource(cam_pp_feature_config_t &pp_config,
   3282         const reprocess_config_t &src_config , cam_is_type_t is_type,
   3283         QCamera3Channel *pMetaChannel)
   3284 {
   3285     int32_t rc = 0;
   3286     cam_stream_reproc_config_t reprocess_config;
   3287     cam_stream_type_t streamType;
   3288 
   3289     /* There can be MAX_INFLIGHT_REQUESTS number of requests that could get queued up.
   3290      * Hence allocating same number of reprocess channel's output buffers */
   3291     int num_buffers = MAX_INFLIGHT_REQUESTS;
   3292     cam_dimension_t streamDim = src_config.output_stream_dim;
   3293 
   3294     if (NULL != src_config.src_channel) {
   3295         QCamera3Stream *pSrcStream = src_config.src_channel->getStreamByIndex(0);
   3296         if (pSrcStream == NULL) {
   3297            ALOGE("%s: source channel doesn't have a stream", __func__);
   3298            return BAD_VALUE;
   3299         }
   3300         mSrcStreamHandles[m_numStreams] = pSrcStream->getMyHandle();
   3301     }
   3302 
   3303     streamType = CAM_STREAM_TYPE_OFFLINE_PROC;
   3304     reprocess_config.pp_type = CAM_OFFLINE_REPROCESS_TYPE;
   3305 
   3306     reprocess_config.offline.input_fmt = src_config.stream_format;
   3307     reprocess_config.offline.input_dim = src_config.input_stream_dim;
   3308     reprocess_config.offline.input_buf_planes.plane_info =
   3309             src_config.input_stream_plane_info.plane_info;
   3310     reprocess_config.offline.num_of_bufs = num_buffers;
   3311     reprocess_config.offline.input_type = src_config.stream_type;
   3312 
   3313     reprocess_config.pp_feature_config = pp_config;
   3314     QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
   3315             m_handle,
   3316             m_camOps,
   3317             mPaddingInfo,
   3318             (QCamera3Channel*)this);
   3319     if (pStream == NULL) {
   3320         ALOGE("%s: No mem for Stream", __func__);
   3321         return NO_MEMORY;
   3322     }
   3323 
   3324     rc = pStream->init(streamType, src_config.stream_format,
   3325             streamDim, ROTATE_0, &reprocess_config,
   3326             num_buffers,
   3327             reprocess_config.pp_feature_config.feature_mask,
   3328             is_type,
   3329             QCamera3Channel::streamCbRoutine, this);
   3330 
   3331     if (rc == 0) {
   3332         mStreams[m_numStreams] = pStream;
   3333         m_numStreams++;
   3334     } else {
   3335         ALOGE("%s: failed to create reprocess stream", __func__);
   3336         delete pStream;
   3337     }
   3338 
   3339     if (rc == NO_ERROR) {
   3340         m_pSrcChannel = src_config.src_channel;
   3341         m_pMetaChannel = pMetaChannel;
   3342     }
   3343     if(m_camOps->request_super_buf(m_camHandle,m_handle,1,0) < 0) {
   3344         ALOGE("%s: Request for super buffer failed",__func__);
   3345     }
   3346     return rc;
   3347 }
   3348 
   3349 cam_dimension_t QCamera3SupportChannel::kDim = {640, 480};
   3350 
   3351 QCamera3SupportChannel::QCamera3SupportChannel(uint32_t cam_handle,
   3352                     mm_camera_ops_t *cam_ops,
   3353                     cam_padding_info_t *paddingInfo,
   3354                     uint32_t postprocess_mask,
   3355                     void *userData) :
   3356                         QCamera3Channel(cam_handle, cam_ops,
   3357                                 NULL, paddingInfo, postprocess_mask, userData),
   3358                         mMemory(NULL)
   3359 {
   3360 }
   3361 
   3362 QCamera3SupportChannel::~QCamera3SupportChannel()
   3363 {
   3364     if (m_bIsActive)
   3365         stop();
   3366 
   3367     if (mMemory) {
   3368         mMemory->deallocate();
   3369         delete mMemory;
   3370         mMemory = NULL;
   3371     }
   3372 }
   3373 
   3374 int32_t QCamera3SupportChannel::initialize(cam_is_type_t isType)
   3375 {
   3376     int32_t rc;
   3377 
   3378     if (mMemory || m_numStreams > 0) {
   3379         ALOGE("%s: metadata channel already initialized", __func__);
   3380         return -EINVAL;
   3381     }
   3382 
   3383     rc = init(NULL, NULL);
   3384     if (rc < 0) {
   3385         ALOGE("%s: init failed", __func__);
   3386         return rc;
   3387     }
   3388     mIsType = isType;
   3389     // Hardcode to VGA size for now
   3390     rc = QCamera3Channel::addStream(CAM_STREAM_TYPE_CALLBACK,
   3391             CAM_FORMAT_YUV_420_NV21, kDim, ROTATE_0, MIN_STREAMING_BUFFER_NUM,
   3392             mPostProcMask, mIsType);
   3393     if (rc < 0) {
   3394         ALOGE("%s: addStream failed", __func__);
   3395     }
   3396     return rc;
   3397 }
   3398 
   3399 int32_t QCamera3SupportChannel::request(buffer_handle_t * /*buffer*/,
   3400                                                 uint32_t /*frameNumber*/)
   3401 {
   3402     return NO_ERROR;
   3403 }
   3404 
   3405 void QCamera3SupportChannel::streamCbRoutine(
   3406                         mm_camera_super_buf_t *super_frame,
   3407                         QCamera3Stream * /*stream*/)
   3408 {
   3409     if (super_frame == NULL || super_frame->num_bufs != 1) {
   3410         ALOGE("%s: super_frame is not valid", __func__);
   3411         return;
   3412     }
   3413     bufDone(super_frame);
   3414     free(super_frame);
   3415 }
   3416 
   3417 QCamera3Memory* QCamera3SupportChannel::getStreamBufs(uint32_t len)
   3418 {
   3419     int rc;
   3420 
   3421     mMemory = new QCamera3HeapMemory();
   3422     if (!mMemory) {
   3423         ALOGE("%s: unable to create heap memory", __func__);
   3424         return NULL;
   3425     }
   3426     rc = mMemory->allocate(MIN_STREAMING_BUFFER_NUM, len, true);
   3427     if (rc < 0) {
   3428         ALOGE("%s: unable to allocate heap memory", __func__);
   3429         delete mMemory;
   3430         mMemory = NULL;
   3431         return NULL;
   3432     }
   3433     return mMemory;
   3434 }
   3435 
   3436 void QCamera3SupportChannel::putStreamBufs()
   3437 {
   3438     mMemory->deallocate();
   3439     delete mMemory;
   3440     mMemory = NULL;
   3441 }
   3442 
   3443 }; // namespace qcamera
   3444