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