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