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