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         uint8_t first_quintuple[5];
   1978         memcpy(first_quintuple, raw16_buffer, sizeof(first_quintuple));
   1979 
   1980         // Some raw processing may be needed prior to conversion.
   1981         static bool raw_proc_lib_load_attempted = false;
   1982         static void *raw_proc_lib = NULL;
   1983         static void *raw_proc_fn = NULL;
   1984         if (! raw_proc_lib && ! raw_proc_lib_load_attempted) {
   1985             raw_proc_lib_load_attempted = true;
   1986             raw_proc_lib = dlopen("libgoog_rownr.so", RTLD_NOW);
   1987             if (raw_proc_lib) {
   1988                 *(void **)&raw_proc_fn = dlsym(raw_proc_lib, "rownr_process_bayer10");
   1989             }
   1990         }
   1991         if (raw_proc_fn) {
   1992             int (*raw_proc)(unsigned char*,int,int,int,int) =
   1993                       (int (*)(unsigned char*,int,int,int,int))(raw_proc_fn);
   1994             raw_proc((unsigned char*)(frame->buffer), 0, dim.width, dim.height,
   1995                        offset.mp[0].stride_in_bytes);
   1996         }
   1997 
   1998         // In-place format conversion.
   1999         // Raw16 format always occupy more memory than opaque raw10.
   2000         // Convert to Raw16 by iterating through all pixels from bottom-right
   2001         // to top-left of the image.
   2002         // One special notes:
   2003         // 1. Cross-platform raw16's stride is 16 pixels.
   2004         // 2. mipi raw10's stride is 4 pixels, and aligned to 16 bytes.
   2005         for (int32_t ys = dim.height - 1; ys >= 0; ys--) {
   2006             uint32_t y = (uint32_t)ys;
   2007             uint8_t* row_start = (uint8_t *)frame->buffer +
   2008                     y * (uint32_t)offset.mp[0].stride_in_bytes;
   2009             for (int32_t xs = dim.width - 1; xs >= 0; xs--) {
   2010                 uint32_t x = (uint32_t)xs;
   2011                 uint8_t upper_8bit = row_start[5*(x/4)+x%4];
   2012                 uint8_t lower_2bit = ((row_start[5*(x/4)+4] >> ((x%4) << 1)) & 0x3);
   2013                 uint16_t raw16_pixel =
   2014                         (uint16_t)(((uint16_t)upper_8bit)<<2 |
   2015                         (uint16_t)lower_2bit);
   2016                 raw16_buffer[y*raw16_stride+x] = raw16_pixel;
   2017             }
   2018         }
   2019 
   2020         // Re-convert the first 2 pixels of the buffer because the loop above messes
   2021         // them up by reading the first quintuple while modifying it.
   2022         raw16_buffer[0] = ((uint16_t)first_quintuple[0]<<2) | (first_quintuple[4] & 0x3);
   2023         raw16_buffer[1] = ((uint16_t)first_quintuple[1]<<2) | ((first_quintuple[4] >> 2) & 0x3);
   2024 
   2025     } else {
   2026         ALOGE("%s: Could not find stream", __func__);
   2027     }
   2028 
   2029 }
   2030 
   2031 /*===========================================================================
   2032  * FUNCTION   : getReprocessType
   2033  *
   2034  * DESCRIPTION: get the type of reprocess output supported by this channel
   2035  *
   2036  * PARAMETERS : NONE
   2037  *
   2038  * RETURN     : reprocess_type_t : type of reprocess
   2039  *==========================================================================*/
   2040 reprocess_type_t QCamera3RawChannel::getReprocessType()
   2041 {
   2042     return REPROCESS_TYPE_RAW;
   2043 }
   2044 
   2045 
   2046 /*************************************************************************************/
   2047 // RAW Dump Channel related functions
   2048 
   2049 /*===========================================================================
   2050  * FUNCTION   : QCamera3RawDumpChannel
   2051  *
   2052  * DESCRIPTION: Constructor for RawDumpChannel
   2053  *
   2054  * PARAMETERS :
   2055  *   @cam_handle    : Handle for Camera
   2056  *   @cam_ops       : Function pointer table
   2057  *   @rawDumpSize   : Dimensions for the Raw stream
   2058  *   @paddinginfo   : Padding information for stream
   2059  *   @userData      : Cookie for parent
   2060  *   @pp mask       : PP feature mask for this stream
   2061  *   @numBuffers    : number of max dequeued buffers
   2062  *
   2063  * RETURN           : NA
   2064  *==========================================================================*/
   2065 QCamera3RawDumpChannel::QCamera3RawDumpChannel(uint32_t cam_handle,
   2066                     uint32_t channel_handle,
   2067                     mm_camera_ops_t *cam_ops,
   2068                     cam_dimension_t rawDumpSize,
   2069                     cam_padding_info_t *paddingInfo,
   2070                     void *userData,
   2071                     uint32_t postprocess_mask, uint32_t numBuffers) :
   2072                         QCamera3Channel(cam_handle, channel_handle, cam_ops, NULL,
   2073                                 paddingInfo, postprocess_mask,
   2074                                 userData, numBuffers),
   2075                         mDim(rawDumpSize),
   2076                         mMemory(NULL)
   2077 {
   2078     char prop[PROPERTY_VALUE_MAX];
   2079     property_get("persist.camera.raw.dump", prop, "0");
   2080     mRawDump = atoi(prop);
   2081 }
   2082 
   2083 /*===========================================================================
   2084  * FUNCTION   : QCamera3RawDumpChannel
   2085  *
   2086  * DESCRIPTION: Destructor for RawDumpChannel
   2087  *
   2088  * PARAMETERS :
   2089  *
   2090  * RETURN           : NA
   2091  *==========================================================================*/
   2092 
   2093 QCamera3RawDumpChannel::~QCamera3RawDumpChannel()
   2094 {
   2095 }
   2096 
   2097 /*===========================================================================
   2098  * FUNCTION   : dumpRawSnapshot
   2099  *
   2100  * DESCRIPTION: Helper function to dump Raw frames
   2101  *
   2102  * PARAMETERS :
   2103  *  @frame      : stream buf frame to be dumped
   2104  *
   2105  *  RETURN      : NA
   2106  *==========================================================================*/
   2107 void QCamera3RawDumpChannel::dumpRawSnapshot(mm_camera_buf_def_t *frame)
   2108 {
   2109     QCamera3Stream *stream = getStreamByIndex(0);
   2110     if (stream != NULL) {
   2111         char buf[FILENAME_MAX];
   2112         struct timeval tv;
   2113         struct tm timeinfo_data;
   2114         struct tm *timeinfo;
   2115 
   2116         cam_dimension_t dim;
   2117         memset(&dim, 0, sizeof(dim));
   2118         stream->getFrameDimension(dim);
   2119 
   2120         cam_frame_len_offset_t offset;
   2121         memset(&offset, 0, sizeof(cam_frame_len_offset_t));
   2122         stream->getFrameOffset(offset);
   2123 
   2124         gettimeofday(&tv, NULL);
   2125         timeinfo = localtime_r(&tv.tv_sec, &timeinfo_data);
   2126 
   2127         if (NULL != timeinfo) {
   2128             memset(buf, 0, sizeof(buf));
   2129             snprintf(buf, sizeof(buf),
   2130                     QCAMERA_DUMP_FRM_LOCATION
   2131                     "%04d-%02d-%02d-%02d-%02d-%02d-%06ld_%d_%dx%d.raw",
   2132                     timeinfo->tm_year + 1900, timeinfo->tm_mon + 1,
   2133                     timeinfo->tm_mday, timeinfo->tm_hour,
   2134                     timeinfo->tm_min, timeinfo->tm_sec,tv.tv_usec,
   2135                     frame->frame_idx, dim.width, dim.height);
   2136 
   2137             int file_fd = open(buf, O_RDWR| O_CREAT, 0777);
   2138             if (file_fd >= 0) {
   2139                 ssize_t written_len =
   2140                         write(file_fd, frame->buffer, offset.frame_len);
   2141                 CDBG("%s: written number of bytes %zd", __func__, written_len);
   2142                 close(file_fd);
   2143             } else {
   2144                 ALOGE("%s: failed to open file to dump image", __func__);
   2145             }
   2146         } else {
   2147             ALOGE("%s: localtime_r() error", __func__);
   2148         }
   2149     } else {
   2150         ALOGE("%s: Could not find stream", __func__);
   2151     }
   2152 
   2153 }
   2154 
   2155 /*===========================================================================
   2156  * FUNCTION   : streamCbRoutine
   2157  *
   2158  * DESCRIPTION: Callback routine invoked for each frame generated for
   2159  *              Rawdump channel
   2160  *
   2161  * PARAMETERS :
   2162  *   @super_frame  : stream buf frame generated
   2163  *   @stream       : Underlying Stream object cookie
   2164  *
   2165  * RETURN          : NA
   2166  *==========================================================================*/
   2167 void QCamera3RawDumpChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
   2168                                                 QCamera3Stream *stream)
   2169 {
   2170     CDBG("%s: E",__func__);
   2171     if (super_frame == NULL || super_frame->num_bufs != 1) {
   2172         ALOGE("%s: super_frame is not valid", __func__);
   2173         return;
   2174     }
   2175 
   2176     if (mRawDump)
   2177         dumpRawSnapshot(super_frame->bufs[0]);
   2178 
   2179     bufDone(super_frame);
   2180     free(super_frame);
   2181 }
   2182 
   2183 /*===========================================================================
   2184  * FUNCTION   : getStreamBufs
   2185  *
   2186  * DESCRIPTION: Callback function provided to interface to get buffers.
   2187  *
   2188  * PARAMETERS :
   2189  *   @len       : Length of each buffer to be allocated
   2190  *
   2191  * RETURN     : NULL on buffer allocation failure
   2192  *              QCamera3StreamMem object on sucess
   2193  *==========================================================================*/
   2194 QCamera3StreamMem* QCamera3RawDumpChannel::getStreamBufs(uint32_t len)
   2195 {
   2196     int rc;
   2197     mMemory = new QCamera3StreamMem(mNumBuffers);
   2198 
   2199     if (!mMemory) {
   2200         ALOGE("%s: unable to create heap memory", __func__);
   2201         return NULL;
   2202     }
   2203     rc = mMemory->allocateAll((size_t)len);
   2204     if (rc < 0) {
   2205         ALOGE("%s: unable to allocate heap memory", __func__);
   2206         delete mMemory;
   2207         mMemory = NULL;
   2208         return NULL;
   2209     }
   2210     return mMemory;
   2211 }
   2212 
   2213 /*===========================================================================
   2214  * FUNCTION   : putStreamBufs
   2215  *
   2216  * DESCRIPTION: Callback function provided to interface to return buffers.
   2217  *              Although no handles are actually returned, implicitl assumption
   2218  *              that interface will no longer use buffers and channel can
   2219  *              deallocated if necessary.
   2220  *
   2221  * PARAMETERS : NA
   2222  *
   2223  * RETURN     : NA
   2224  *==========================================================================*/
   2225 void QCamera3RawDumpChannel::putStreamBufs()
   2226 {
   2227     mMemory->deallocate();
   2228     delete mMemory;
   2229     mMemory = NULL;
   2230 }
   2231 
   2232 /*===========================================================================
   2233  * FUNCTION : request
   2234  *
   2235  * DESCRIPTION: Request function used as trigger
   2236  *
   2237  * PARAMETERS :
   2238  * @recvd_frame : buffer- this will be NULL since this is internal channel
   2239  * @frameNumber : Undefined again since this is internal stream
   2240  *
   2241  * RETURN     : int32_t type of status
   2242  *              NO_ERROR  -- success
   2243  *              none-zero failure code
   2244  *==========================================================================*/
   2245 int32_t QCamera3RawDumpChannel::request(buffer_handle_t * /*buffer*/,
   2246                                                 uint32_t /*frameNumber*/)
   2247 {
   2248     if (!m_bIsActive) {
   2249         return QCamera3Channel::start();
   2250     }
   2251     else
   2252         return 0;
   2253 }
   2254 
   2255 /*===========================================================================
   2256  * FUNCTION : intialize
   2257  *
   2258  * DESCRIPTION: Initializes channel params and creates underlying stream
   2259  *
   2260  * PARAMETERS :
   2261  *    @isType : type of image stabilization required on this stream
   2262  *
   2263  * RETURN     : int32_t type of status
   2264  *              NO_ERROR  -- success
   2265  *              none-zero failure code
   2266  *==========================================================================*/
   2267 int32_t QCamera3RawDumpChannel::initialize(cam_is_type_t isType)
   2268 {
   2269     int32_t rc;
   2270 
   2271     mIsType = isType;
   2272     rc = QCamera3Channel::addStream(CAM_STREAM_TYPE_RAW,
   2273         CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG, mDim, ROTATE_0, (uint8_t)mNumBuffers,
   2274         mPostProcMask, mIsType);
   2275     if (rc < 0) {
   2276         ALOGE("%s: addStream failed", __func__);
   2277     }
   2278     return rc;
   2279 }
   2280 /*************************************************************************************/
   2281 
   2282 /* QCamera3YUVChannel methods */
   2283 
   2284 /*===========================================================================
   2285  * FUNCTION   : QCamera3YUVChannel
   2286  *
   2287  * DESCRIPTION: constructor of QCamera3YUVChannel
   2288  *
   2289  * PARAMETERS :
   2290  *   @cam_handle : camera handle
   2291  *   @cam_ops    : ptr to camera ops table
   2292  *   @cb_routine : callback routine to frame aggregator
   2293  *   @paddingInfo : padding information for the stream
   2294  *   @stream     : camera3_stream_t structure
   2295  *   @stream_type: Channel stream type
   2296  *   @postprocess_mask: the postprocess mask for streams of this channel
   2297  *   @metadataChannel: handle to the metadataChannel
   2298  * RETURN     : none
   2299  *==========================================================================*/
   2300 QCamera3YUVChannel::QCamera3YUVChannel(uint32_t cam_handle,
   2301         uint32_t channel_handle,
   2302         mm_camera_ops_t *cam_ops,
   2303         channel_cb_routine cb_routine,
   2304         cam_padding_info_t *paddingInfo,
   2305         void *userData,
   2306         camera3_stream_t *stream,
   2307         cam_stream_type_t stream_type,
   2308         uint32_t postprocess_mask,
   2309         QCamera3Channel *metadataChannel) :
   2310             QCamera3ProcessingChannel(cam_handle, channel_handle, cam_ops,
   2311                     cb_routine, paddingInfo, userData, stream, stream_type,
   2312                     postprocess_mask, metadataChannel)
   2313 {
   2314 
   2315     mBypass = (postprocess_mask == CAM_QCOM_FEATURE_NONE);
   2316     mFrameLen = 0;
   2317     mEdgeMode.edge_mode = CAM_EDGE_MODE_OFF;
   2318     mEdgeMode.sharpness = 0;
   2319     mNoiseRedMode = CAM_NOISE_REDUCTION_MODE_OFF;
   2320     memset(&mCropRegion, 0, sizeof(mCropRegion));
   2321 }
   2322 
   2323 /*===========================================================================
   2324  * FUNCTION   : ~QCamera3YUVChannel
   2325  *
   2326  * DESCRIPTION: destructor of QCamera3YUVChannel
   2327  *
   2328  * PARAMETERS : none
   2329  *
   2330  *
   2331  * RETURN     : none
   2332  *==========================================================================*/
   2333 QCamera3YUVChannel::~QCamera3YUVChannel()
   2334 {
   2335    // Deallocation of heap buffers allocated in mMemory is freed
   2336    // automatically by its destructor
   2337 }
   2338 
   2339 /*===========================================================================
   2340  * FUNCTION   : initialize
   2341  *
   2342  * DESCRIPTION: Initialize and add camera channel & stream
   2343  *
   2344  * PARAMETERS :
   2345  * @isType    : the image stabilization type
   2346  *
   2347  * RETURN     : int32_t type of status
   2348  *              NO_ERROR  -- success
   2349  *              none-zero failure code
   2350  *==========================================================================*/
   2351 int32_t QCamera3YUVChannel::initialize(cam_is_type_t isType)
   2352 {
   2353     ATRACE_CALL();
   2354     int32_t rc = NO_ERROR;
   2355     cam_dimension_t streamDim;
   2356 
   2357     if (NULL == mCamera3Stream) {
   2358         ALOGE("%s: Camera stream uninitialized", __func__);
   2359         return NO_INIT;
   2360     }
   2361 
   2362     if (1 <= m_numStreams) {
   2363         // Only one stream per channel supported in v3 Hal
   2364         return NO_ERROR;
   2365     }
   2366 
   2367     mIsType  = isType;
   2368     mStreamFormat = CALLBACK_FORMAT;
   2369     streamDim.width = mCamera3Stream->width;
   2370     streamDim.height = mCamera3Stream->height;
   2371 
   2372     rc = QCamera3Channel::addStream(mStreamType,
   2373             mStreamFormat,
   2374             streamDim,
   2375             ROTATE_0,
   2376             mNumBufs,
   2377             mPostProcMask,
   2378             mIsType);
   2379     if (rc < 0) {
   2380         ALOGE("%s: addStream failed", __func__);
   2381         return rc;
   2382     }
   2383 
   2384     cam_stream_buf_plane_info_t buf_planes;
   2385     cam_padding_info_t paddingInfo = *mPaddingInfo;
   2386 
   2387     memset(&buf_planes, 0, sizeof(buf_planes));
   2388     //to ensure a big enough buffer size set the height and width
   2389     //padding to max(height padding, width padding)
   2390     paddingInfo.width_padding = MAX(paddingInfo.width_padding, paddingInfo.height_padding);
   2391     paddingInfo.height_padding = paddingInfo.width_padding;
   2392 
   2393     rc = mm_stream_calc_offset_snapshot(mStreamFormat, &streamDim, &paddingInfo,
   2394             &buf_planes);
   2395     if (rc < 0) {
   2396         ALOGE("%s: mm_stream_calc_offset_preview failed", __func__);
   2397         return rc;
   2398     }
   2399 
   2400     mFrameLen = buf_planes.plane_info.frame_len;
   2401 
   2402     if (NO_ERROR != rc) {
   2403         ALOGE("%s: Initialize failed, rc = %d", __func__, rc);
   2404         return rc;
   2405     }
   2406 
   2407     /* initialize offline meta memory for input reprocess */
   2408     rc = QCamera3ProcessingChannel::initialize(isType);
   2409     if (NO_ERROR != rc) {
   2410         ALOGE("%s: Processing Channel initialize failed, rc = %d",
   2411                 __func__, rc);
   2412     }
   2413 
   2414     return rc;
   2415 }
   2416 
   2417 /*===========================================================================
   2418  * FUNCTION   : request
   2419  *
   2420  * DESCRIPTION: entry function for a request on a YUV stream. This function
   2421  *              has the logic to service a request based on its type
   2422  *
   2423  * PARAMETERS :
   2424  * @buffer          : pointer to the output buffer
   2425  * @frameNumber     : frame number of the request
   2426  * @pInputBuffer    : pointer to input buffer if an input request
   2427  * @metadata        : parameters associated with the request
   2428  *
   2429  * RETURN     : 0 on a success start of capture
   2430  *              -EINVAL on invalid input
   2431  *              -ENODEV on serious error
   2432  *==========================================================================*/
   2433 int32_t QCamera3YUVChannel::request(buffer_handle_t *buffer,
   2434         uint32_t frameNumber,
   2435         camera3_stream_buffer_t* pInputBuffer,
   2436         metadata_buffer_t* metadata, bool &needMetadata)
   2437 {
   2438     int32_t rc = NO_ERROR;
   2439     int index;
   2440     Mutex::Autolock lock(mOfflinePpLock);
   2441 
   2442     CDBG("%s: pInputBuffer is %p", __func__, pInputBuffer);
   2443     CDBG("%s, frame number %d", __func__, frameNumber);
   2444     if (NULL == buffer || NULL == metadata) {
   2445         ALOGE("%s: Invalid buffer/metadata in channel request", __func__);
   2446         return BAD_VALUE;
   2447     }
   2448 
   2449     PpInfo ppInfo;
   2450     memset(&ppInfo, 0, sizeof(ppInfo));
   2451     ppInfo.frameNumber = frameNumber;
   2452     ppInfo.offlinePpFlag = false;
   2453     if (mBypass && !pInputBuffer ) {
   2454         ppInfo.offlinePpFlag = needsFramePostprocessing(metadata);
   2455         ppInfo.output = buffer;
   2456         mOfflinePpInfoList.push_back(ppInfo);
   2457     }
   2458 
   2459     CDBG("%s: offlinePpFlag is %d", __func__, ppInfo.offlinePpFlag);
   2460     needMetadata = ppInfo.offlinePpFlag;
   2461     if (!ppInfo.offlinePpFlag) {
   2462         // regular request
   2463         return QCamera3ProcessingChannel::request(buffer, frameNumber,
   2464                 pInputBuffer, metadata);
   2465     } else {
   2466         if(!m_bIsActive) {
   2467             rc = start();
   2468             if (NO_ERROR != rc)
   2469                 return rc;
   2470         } else {
   2471             CDBG("%s: Request on an existing stream",__func__);
   2472         }
   2473 
   2474         //we need to send this frame through the CPP
   2475         //Allocate heap memory, then buf done on the buffer
   2476         uint32_t bufIdx;
   2477         if (mFreeHeapBufferList.empty()) {
   2478             rc = mMemory.allocateOne(mFrameLen);
   2479             if (rc < 0) {
   2480                 ALOGE("%s: Failed allocating heap buffer. Fatal", __func__);
   2481                 return BAD_VALUE;
   2482             } else {
   2483                 bufIdx = (uint32_t)rc;
   2484             }
   2485         } else {
   2486             bufIdx = *(mFreeHeapBufferList.begin());
   2487             mFreeHeapBufferList.erase(mFreeHeapBufferList.begin());
   2488         }
   2489 
   2490         /* Configure and start postproc if necessary */
   2491         reprocess_config_t reproc_cfg;
   2492         cam_dimension_t dim;
   2493         memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
   2494         memset(&dim, 0, sizeof(dim));
   2495         mStreams[0]->getFrameDimension(dim);
   2496         setReprocConfig(reproc_cfg, NULL, metadata, mStreamFormat, dim);
   2497 
   2498         // Start postprocessor without input buffer
   2499         startPostProc(reproc_cfg);
   2500 
   2501         CDBG("%s: erasing %d", __func__, bufIdx);
   2502 
   2503         mMemory.markFrameNumber(bufIdx, frameNumber);
   2504         mStreams[0]->bufDone(bufIdx);
   2505 
   2506     }
   2507     return rc;
   2508 }
   2509 
   2510 /*===========================================================================
   2511  * FUNCTION   : streamCbRoutine
   2512  *
   2513  * DESCRIPTION:
   2514  *
   2515  * PARAMETERS :
   2516  * @super_frame : the super frame with filled buffer
   2517  * @stream      : stream on which the buffer was requested and filled
   2518  *
   2519  * RETURN     : none
   2520  *==========================================================================*/
   2521 void QCamera3YUVChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
   2522         QCamera3Stream *stream)
   2523 {
   2524     ATRACE_CALL();
   2525     uint8_t frameIndex;
   2526     int32_t resultFrameNumber;
   2527 
   2528     if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
   2529         ALOGE("%s: Error with the stream callback", __func__);
   2530         return;
   2531     }
   2532 
   2533     frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
   2534     if(frameIndex >= mNumBufs) {
   2535          ALOGE("%s: Error, Invalid index for buffer",__func__);
   2536          stream->bufDone(frameIndex);
   2537          return;
   2538     }
   2539 
   2540     if (mBypass) {
   2541         List<PpInfo>::iterator ppInfo;
   2542 
   2543         Mutex::Autolock lock(mOfflinePpLock);
   2544         resultFrameNumber = mMemory.getFrameNumber(frameIndex);
   2545         for (ppInfo = mOfflinePpInfoList.begin();
   2546                 ppInfo != mOfflinePpInfoList.end(); ppInfo++) {
   2547             if (ppInfo->frameNumber == (uint32_t)resultFrameNumber) {
   2548                 break;
   2549             }
   2550         }
   2551         CDBG("%s, frame index %d, frame number %d", __func__, frameIndex, resultFrameNumber);
   2552         //check the reprocessing required flag against the frame number
   2553         if (ppInfo == mOfflinePpInfoList.end()) {
   2554             ALOGE("%s: Error, request for frame number is a reprocess.", __func__);
   2555             stream->bufDone(frameIndex);
   2556             return;
   2557         }
   2558 
   2559         if (ppInfo->offlinePpFlag) {
   2560             mm_camera_super_buf_t *frame =
   2561                     (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
   2562             if (frame == NULL) {
   2563                 ALOGE("%s: Error allocating memory to save received_frame structure.",
   2564                         __func__);
   2565                 if(stream) {
   2566                     stream->bufDone(frameIndex);
   2567                 }
   2568                 return;
   2569             }
   2570 
   2571             *frame = *super_frame;
   2572             m_postprocessor.processData(frame, ppInfo->output, resultFrameNumber);
   2573             free(super_frame);
   2574             return;
   2575         } else {
   2576             if (ppInfo != mOfflinePpInfoList.begin()) {
   2577                 // There is pending reprocess buffer, cache current buffer
   2578                 if (ppInfo->callback_buffer != NULL) {
   2579                     ALOGE("%s: Fatal: cached callback_buffer is already present",
   2580                         __func__);
   2581 
   2582                 }
   2583                 ppInfo->callback_buffer = super_frame;
   2584                 return;
   2585             } else {
   2586                 mOfflinePpInfoList.erase(ppInfo);
   2587             }
   2588         }
   2589     }
   2590 
   2591     QCamera3ProcessingChannel::streamCbRoutine(super_frame, stream);
   2592     return;
   2593 }
   2594 
   2595 /*===========================================================================
   2596  * FUNCTION   : reprocessCbRoutine
   2597  *
   2598  * DESCRIPTION: callback function for the reprocessed frame. This frame now
   2599  *              should be returned to the framework. This same callback is
   2600  *              used during input reprocessing or offline postprocessing
   2601  *
   2602  * PARAMETERS :
   2603  * @resultBuffer      : buffer containing the reprocessed data
   2604  * @resultFrameNumber : frame number on which the buffer was requested
   2605  *
   2606  * RETURN     : NONE
   2607  *
   2608  *==========================================================================*/
   2609 void QCamera3YUVChannel::reprocessCbRoutine(buffer_handle_t *resultBuffer,
   2610         uint32_t resultFrameNumber)
   2611 {
   2612     CDBG("%s E: frame number %d", __func__, resultFrameNumber);
   2613     Vector<mm_camera_super_buf_t *> pendingCbs;
   2614 
   2615     /* release the input buffer and input metadata buffer if used */
   2616     if (0 > mMemory.getHeapBufferIndex(resultFrameNumber)) {
   2617         /* mOfflineMemory and mOfflineMetaMemory used only for input reprocessing */
   2618         int32_t rc = releaseOfflineMemory(resultFrameNumber);
   2619         if (NO_ERROR != rc) {
   2620             ALOGE("%s: Error releasing offline memory rc = %d", __func__, rc);
   2621         }
   2622         /* Since reprocessing is done, send the callback to release the input buffer */
   2623         if (mChannelCB) {
   2624             mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData);
   2625         }
   2626     }
   2627 
   2628     if (mBypass) {
   2629         int32_t rc = handleOfflinePpCallback(resultFrameNumber, pendingCbs);
   2630         if (rc != NO_ERROR) {
   2631             return;
   2632         }
   2633     }
   2634 
   2635     issueChannelCb(resultBuffer, resultFrameNumber);
   2636 
   2637     // Call all pending callbacks to return buffers
   2638     for (size_t i = 0; i < pendingCbs.size(); i++) {
   2639         QCamera3ProcessingChannel::streamCbRoutine(
   2640                 pendingCbs[i], mStreams[0]);
   2641     }
   2642 
   2643 }
   2644 
   2645 /*===========================================================================
   2646  * FUNCTION   : needsFramePostprocessing
   2647  *
   2648  * DESCRIPTION:
   2649  *
   2650  * PARAMETERS :
   2651  *
   2652  * RETURN     :
   2653  *  TRUE if frame needs to be postprocessed
   2654  *  FALSE is frame does not need to be postprocessed
   2655  *
   2656  *==========================================================================*/
   2657 bool QCamera3YUVChannel::needsFramePostprocessing(metadata_buffer_t *meta)
   2658 {
   2659     bool ppNeeded = false;
   2660 
   2661     //sharpness
   2662     IF_META_AVAILABLE(cam_edge_application_t, edgeMode,
   2663             CAM_INTF_META_EDGE_MODE, meta) {
   2664         mEdgeMode = *edgeMode;
   2665     }
   2666 
   2667     //wnr
   2668     IF_META_AVAILABLE(uint32_t, noiseRedMode,
   2669             CAM_INTF_META_NOISE_REDUCTION_MODE, meta) {
   2670         mNoiseRedMode = *noiseRedMode;
   2671     }
   2672 
   2673     //crop region
   2674     IF_META_AVAILABLE(cam_crop_region_t, scalerCropRegion,
   2675             CAM_INTF_META_SCALER_CROP_REGION, meta) {
   2676         mCropRegion = *scalerCropRegion;
   2677     }
   2678 
   2679     if ((CAM_EDGE_MODE_OFF != mEdgeMode.edge_mode) &&
   2680             (CAM_EDGE_MODE_ZERO_SHUTTER_LAG != mEdgeMode.edge_mode)) {
   2681         ppNeeded = true;
   2682     }
   2683     if ((CAM_NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG != mNoiseRedMode) &&
   2684             (CAM_NOISE_REDUCTION_MODE_OFF != mNoiseRedMode) &&
   2685             (CAM_NOISE_REDUCTION_MODE_MINIMAL != mNoiseRedMode)) {
   2686         ppNeeded = true;
   2687     }
   2688     if ((mCropRegion.width < (int32_t)mCamera3Stream->width) ||
   2689             (mCropRegion.height < (int32_t)mCamera3Stream->height)) {
   2690         ppNeeded = true;
   2691     }
   2692 
   2693     return ppNeeded;
   2694 }
   2695 
   2696 /*===========================================================================
   2697  * FUNCTION   : handleOfflinePpCallback
   2698  *
   2699  * DESCRIPTION: callback function for the reprocessed frame from offline
   2700  *              postprocessing.
   2701  *
   2702  * PARAMETERS :
   2703  * @resultFrameNumber : frame number on which the buffer was requested
   2704  * @pendingCbs        : pending buffers to be returned first
   2705  *
   2706  * RETURN     : int32_t type of status
   2707  *              NO_ERROR  -- success
   2708  *              none-zero failure code
   2709  *==========================================================================*/
   2710 int32_t QCamera3YUVChannel::handleOfflinePpCallback(uint32_t resultFrameNumber,
   2711             Vector<mm_camera_super_buf_t *>& pendingCbs)
   2712 {
   2713     Mutex::Autolock lock(mOfflinePpLock);
   2714     List<PpInfo>::iterator ppInfo;
   2715 
   2716     for (ppInfo = mOfflinePpInfoList.begin();
   2717             ppInfo != mOfflinePpInfoList.end(); ppInfo++) {
   2718         if (ppInfo->frameNumber == resultFrameNumber) {
   2719             break;
   2720         }
   2721     }
   2722 
   2723     if (ppInfo == mOfflinePpInfoList.end()) {
   2724         ALOGI("%s: Request of frame number %d is reprocessing",
   2725                 __func__, resultFrameNumber);
   2726         return NO_ERROR;
   2727     } else if (ppInfo != mOfflinePpInfoList.begin()) {
   2728         ALOGE("%s: callback for frame number %d should be head of list",
   2729                 __func__, resultFrameNumber);
   2730         return BAD_VALUE;
   2731     }
   2732 
   2733     if (ppInfo->offlinePpFlag) {
   2734         // Need to get the input buffer frame index from the
   2735         // mMemory object and add that to the free heap buffers list.
   2736         int32_t bufferIndex =
   2737                 mMemory.getHeapBufferIndex(resultFrameNumber);
   2738         if (bufferIndex < 0) {
   2739             ALOGE("%s: Fatal %d: no buffer index for frame number %d",
   2740                     __func__, bufferIndex, resultFrameNumber);
   2741             return BAD_VALUE;
   2742         }
   2743         mFreeHeapBufferList.push_back(bufferIndex);
   2744         ppInfo = mOfflinePpInfoList.erase(ppInfo);
   2745 
   2746         // Return pending buffer callbacks
   2747         while (ppInfo != mOfflinePpInfoList.end() &&
   2748                 !ppInfo->offlinePpFlag && ppInfo->callback_buffer) {
   2749 
   2750             // Call stream callbacks for cached buffers
   2751             pendingCbs.push_back(ppInfo->callback_buffer);
   2752 
   2753             ppInfo = mOfflinePpInfoList.erase(ppInfo);
   2754         }
   2755 
   2756     } else {
   2757         ALOGE("%s: Fatal: request of frame number %d doesn't need"
   2758                 " offline postprocessing. However there is"
   2759                 " reprocessing callback.", __func__,
   2760                 resultFrameNumber);
   2761         return BAD_VALUE;
   2762     }
   2763 
   2764     return NO_ERROR;
   2765 }
   2766 
   2767 /*===========================================================================
   2768  * FUNCTION   : getReprocessType
   2769  *
   2770  * DESCRIPTION: get the type of reprocess output supported by this channel
   2771  *
   2772  * PARAMETERS : NONE
   2773  *
   2774  * RETURN     : reprocess_type_t : type of reprocess
   2775  *==========================================================================*/
   2776 reprocess_type_t QCamera3YUVChannel::getReprocessType()
   2777 {
   2778     return REPROCESS_TYPE_YUV;
   2779 }
   2780 
   2781 /* QCamera3PicChannel methods */
   2782 
   2783 /*===========================================================================
   2784  * FUNCTION   : jpegEvtHandle
   2785  *
   2786  * DESCRIPTION: Function registerd to mm-jpeg-interface to handle jpeg events.
   2787                 Construct result payload and call mChannelCb to deliver buffer
   2788                 to framework.
   2789  *
   2790  * PARAMETERS :
   2791  *   @status    : status of jpeg job
   2792  *   @client_hdl: jpeg client handle
   2793  *   @jobId     : jpeg job Id
   2794  *   @p_ouput   : ptr to jpeg output result struct
   2795  *   @userdata  : user data ptr
   2796  *
   2797  * RETURN     : none
   2798  *==========================================================================*/
   2799 void QCamera3PicChannel::jpegEvtHandle(jpeg_job_status_t status,
   2800                                               uint32_t /*client_hdl*/,
   2801                                               uint32_t jobId,
   2802                                               mm_jpeg_output_t *p_output,
   2803                                               void *userdata)
   2804 {
   2805     ATRACE_CALL();
   2806     buffer_handle_t *resultBuffer = NULL;
   2807     buffer_handle_t *jpegBufferHandle = NULL;
   2808     int resultStatus = CAMERA3_BUFFER_STATUS_OK;
   2809     camera3_stream_buffer_t result;
   2810     camera3_jpeg_blob_t jpegHeader;
   2811 
   2812     QCamera3PicChannel *obj = (QCamera3PicChannel *)userdata;
   2813     if (obj) {
   2814         //Construct payload for process_capture_result. Call mChannelCb
   2815 
   2816         qcamera_hal3_jpeg_data_t *job = obj->m_postprocessor.findJpegJobByJobId(jobId);
   2817 
   2818         if ((job == NULL) || (status == JPEG_JOB_STATUS_ERROR)) {
   2819             ALOGE("%s: Error in jobId: (%d) with status: %d", __func__, jobId, status);
   2820             resultStatus = CAMERA3_BUFFER_STATUS_ERROR;
   2821         }
   2822 
   2823         if (NULL != job) {
   2824             uint32_t bufIdx = (uint32_t)job->jpeg_settings->out_buf_index;
   2825             CDBG("%s: jpeg out_buf_index: %d", __func__, bufIdx);
   2826 
   2827             //Construct jpeg transient header of type camera3_jpeg_blob_t
   2828             //Append at the end of jpeg image of buf_filled_len size
   2829 
   2830             jpegHeader.jpeg_blob_id = CAMERA3_JPEG_BLOB_ID;
   2831             if (JPEG_JOB_STATUS_DONE == status) {
   2832                 jpegHeader.jpeg_size = (uint32_t)p_output->buf_filled_len;
   2833                 char* jpeg_buf = (char *)p_output->buf_vaddr;
   2834 
   2835                 ssize_t maxJpegSize = -1;
   2836 
   2837                 // Gralloc buffer may have additional padding for 4K page size
   2838                 // Follow size guidelines based on spec since framework relies
   2839                 // on that to reach end of buffer and with it the header
   2840 
   2841                 //Handle same as resultBuffer, but for readablity
   2842                 jpegBufferHandle =
   2843                         (buffer_handle_t *)obj->mMemory.getBufferHandle(bufIdx);
   2844 
   2845                 if (NULL != jpegBufferHandle) {
   2846                     maxJpegSize = ((private_handle_t*)(*jpegBufferHandle))->width;
   2847                     if (maxJpegSize > obj->mMemory.getSize(bufIdx)) {
   2848                         maxJpegSize = obj->mMemory.getSize(bufIdx);
   2849                     }
   2850 
   2851                     size_t jpeg_eof_offset =
   2852                             (size_t)(maxJpegSize - (ssize_t)sizeof(jpegHeader));
   2853                     char *jpeg_eof = &jpeg_buf[jpeg_eof_offset];
   2854                     memcpy(jpeg_eof, &jpegHeader, sizeof(jpegHeader));
   2855                     obj->mMemory.cleanInvalidateCache(bufIdx);
   2856                 } else {
   2857                     ALOGE("%s: JPEG buffer not found and index: %d",
   2858                             __func__,
   2859                             bufIdx);
   2860                     resultStatus = CAMERA3_BUFFER_STATUS_ERROR;
   2861                 }
   2862             }
   2863 
   2864             ////Use below data to issue framework callback
   2865             resultBuffer =
   2866                     (buffer_handle_t *)obj->mMemory.getBufferHandle(bufIdx);
   2867             int32_t resultFrameNumber = obj->mMemory.getFrameNumber(bufIdx);
   2868             int32_t rc = obj->mMemory.unregisterBuffer(bufIdx);
   2869             if (NO_ERROR != rc) {
   2870                 ALOGE("%s: Error %d unregistering stream buffer %d",
   2871                     __func__, rc, bufIdx);
   2872             }
   2873 
   2874             result.stream = obj->mCamera3Stream;
   2875             result.buffer = resultBuffer;
   2876             result.status = resultStatus;
   2877             result.acquire_fence = -1;
   2878             result.release_fence = -1;
   2879 
   2880             // Release any snapshot buffers before calling
   2881             // the user callback. The callback can potentially
   2882             // unblock pending requests to snapshot stream.
   2883             int32_t snapshotIdx = -1;
   2884             mm_camera_super_buf_t* src_frame = NULL;
   2885 
   2886             if (job->src_reproc_frame)
   2887                 src_frame = job->src_reproc_frame;
   2888             else
   2889                 src_frame = job->src_frame;
   2890 
   2891             if (src_frame) {
   2892                 if (obj->mStreams[0]->getMyHandle() ==
   2893                         src_frame->bufs[0]->stream_id) {
   2894                     snapshotIdx = (int32_t)src_frame->bufs[0]->buf_idx;
   2895 
   2896                     if (0 <= snapshotIdx) {
   2897                         Mutex::Autolock lock(obj->mFreeBuffersLock);
   2898                         obj->mFreeBufferList.push_back((uint32_t)snapshotIdx);
   2899                     }
   2900                 }
   2901             }
   2902 
   2903             CDBG("%s: Issue Callback", __func__);
   2904             if (obj->mChannelCB) {
   2905                 obj->mChannelCB(NULL,
   2906                         &result,
   2907                         (uint32_t)resultFrameNumber,
   2908                         false,
   2909                         obj->mUserData);
   2910             }
   2911 
   2912             // release internal data for jpeg job
   2913             if ((NULL != job->fwk_frame) || (NULL != job->fwk_src_buffer)) {
   2914                 /* unregister offline input buffer */
   2915                 int32_t inputBufIndex =
   2916                         obj->mOfflineMemory.getGrallocBufferIndex((uint32_t)resultFrameNumber);
   2917                 if (0 <= inputBufIndex) {
   2918                     rc = obj->mOfflineMemory.unregisterBuffer(inputBufIndex);
   2919                 } else {
   2920                     ALOGE("%s: could not find the input buf index, frame number %d",
   2921                             __func__, resultFrameNumber);
   2922                 }
   2923                 if (NO_ERROR != rc) {
   2924                     ALOGE("%s: Error %d unregistering input buffer %d",
   2925                             __func__, rc, bufIdx);
   2926                 }
   2927 
   2928                 /* unregister offline meta buffer */
   2929                 int32_t metaBufIndex =
   2930                         obj->mOfflineMetaMemory.getHeapBufferIndex((uint32_t)resultFrameNumber);
   2931                 if (0 <= metaBufIndex) {
   2932                     Mutex::Autolock lock(obj->mFreeOfflineMetaBuffersLock);
   2933                     obj->mFreeOfflineMetaBuffersList.push_back((uint32_t)metaBufIndex);
   2934                 } else {
   2935                     ALOGE("%s: could not find the input meta buf index, frame number %d",
   2936                             __func__, resultFrameNumber);
   2937                 }
   2938             }
   2939             obj->m_postprocessor.releaseOfflineBuffers();
   2940             obj->m_postprocessor.releaseJpegJobData(job);
   2941             free(job);
   2942         }
   2943 
   2944         return;
   2945         // }
   2946     } else {
   2947         ALOGE("%s: Null userdata in jpeg callback", __func__);
   2948     }
   2949 }
   2950 
   2951 QCamera3PicChannel::QCamera3PicChannel(uint32_t cam_handle,
   2952                     uint32_t channel_handle,
   2953                     mm_camera_ops_t *cam_ops,
   2954                     channel_cb_routine cb_routine,
   2955                     cam_padding_info_t *paddingInfo,
   2956                     void *userData,
   2957                     camera3_stream_t *stream,
   2958                     uint32_t postprocess_mask,
   2959                     bool is4KVideo,
   2960                     bool isInputStreamConfigured,
   2961                     QCamera3Channel *metadataChannel,
   2962                     uint32_t numBuffers) :
   2963                         QCamera3ProcessingChannel(cam_handle, channel_handle,
   2964                                 cam_ops, cb_routine, paddingInfo, userData,
   2965                                 stream, CAM_STREAM_TYPE_SNAPSHOT,
   2966                                 postprocess_mask, metadataChannel, numBuffers),
   2967                         mNumSnapshotBufs(0),
   2968                         mInputBufferHint(isInputStreamConfigured),
   2969                         mYuvMemory(NULL),
   2970                         mFrameLen(0)
   2971 {
   2972     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
   2973     m_max_pic_dim = hal_obj->calcMaxJpegDim();
   2974     mYuvWidth = stream->width;
   2975     mYuvHeight = stream->height;
   2976     mStreamType = CAM_STREAM_TYPE_SNAPSHOT;
   2977     // Use same pixelformat for 4K video case
   2978     mStreamFormat = is4KVideo ? VIDEO_FORMAT : SNAPSHOT_FORMAT;
   2979     int32_t rc = m_postprocessor.initJpeg(jpegEvtHandle, &m_max_pic_dim, this);
   2980     if (rc != 0) {
   2981         ALOGE("Init Postprocessor failed");
   2982     }
   2983 }
   2984 
   2985 QCamera3PicChannel::~QCamera3PicChannel()
   2986 {
   2987 }
   2988 
   2989 int32_t QCamera3PicChannel::initialize(cam_is_type_t isType)
   2990 {
   2991     int32_t rc = NO_ERROR;
   2992     cam_dimension_t streamDim;
   2993     cam_stream_type_t streamType;
   2994     cam_format_t streamFormat;
   2995     mm_camera_channel_attr_t attr;
   2996 
   2997     if (NULL == mCamera3Stream) {
   2998         ALOGE("%s: Camera stream uninitialized", __func__);
   2999         return NO_INIT;
   3000     }
   3001 
   3002     if (1 <= m_numStreams) {
   3003         // Only one stream per channel supported in v3 Hal
   3004         return NO_ERROR;
   3005     }
   3006 
   3007     mIsType = isType;
   3008     streamType = mStreamType;
   3009     streamFormat = mStreamFormat;
   3010     streamDim.width = (int32_t)mYuvWidth;
   3011     streamDim.height = (int32_t)mYuvHeight;
   3012 
   3013     mNumSnapshotBufs = mCamera3Stream->max_buffers;
   3014     rc = QCamera3Channel::addStream(streamType, streamFormat, streamDim,
   3015             ROTATE_0, (uint8_t)mCamera3Stream->max_buffers, mPostProcMask,
   3016             mIsType);
   3017 
   3018     if (NO_ERROR != rc) {
   3019         ALOGE("%s: Initialize failed, rc = %d", __func__, rc);
   3020         return rc;
   3021     }
   3022 
   3023     /* initialize offline meta memory for input reprocess */
   3024     rc = QCamera3ProcessingChannel::initialize(isType);
   3025     if (NO_ERROR != rc) {
   3026         ALOGE("%s: Processing Channel initialize failed, rc = %d",
   3027                 __func__, rc);
   3028     }
   3029 
   3030     return rc;
   3031 }
   3032 
   3033 /*===========================================================================
   3034  * FUNCTION   : request
   3035  *
   3036  * DESCRIPTION: handle the request - either with an input buffer or a direct
   3037  *              output request
   3038  *
   3039  * PARAMETERS :
   3040  * @buffer       : pointer to the output buffer
   3041  * @frameNumber  : frame number of the request
   3042  * @pInputBuffer : pointer to input buffer if an input request
   3043  * @metadata     : parameters associated with the request
   3044  *
   3045  * RETURN     : 0 on a success start of capture
   3046  *              -EINVAL on invalid input
   3047  *              -ENODEV on serious error
   3048  *==========================================================================*/
   3049 int32_t QCamera3PicChannel::request(buffer_handle_t *buffer,
   3050         uint32_t frameNumber,
   3051         camera3_stream_buffer_t *pInputBuffer,
   3052         metadata_buffer_t *metadata)
   3053 {
   3054     ATRACE_CALL();
   3055     //FIX ME: Return buffer back in case of failures below.
   3056 
   3057     int32_t rc = NO_ERROR;
   3058 
   3059     reprocess_config_t reproc_cfg;
   3060     cam_dimension_t dim;
   3061     memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
   3062     //make sure to set the correct input stream dim in case of YUV size override
   3063     //and recalculate the plane info
   3064     dim.width = (int32_t)mYuvWidth;
   3065     dim.height = (int32_t)mYuvHeight;
   3066     setReprocConfig(reproc_cfg, pInputBuffer, metadata, mStreamFormat, dim);
   3067 
   3068     // Picture stream has already been started before any request comes in
   3069     if (!m_bIsActive) {
   3070         ALOGE("%s: Channel not started!!", __func__);
   3071         return NO_INIT;
   3072     }
   3073 
   3074     int index = mMemory.getMatchBufIndex((void*)buffer);
   3075 
   3076     if(index < 0) {
   3077         rc = registerBuffer(buffer, mIsType);
   3078         if (NO_ERROR != rc) {
   3079             ALOGE("%s: On-the-fly buffer registration failed %d",
   3080                     __func__, rc);
   3081             return rc;
   3082         }
   3083 
   3084         index = mMemory.getMatchBufIndex((void*)buffer);
   3085         if (index < 0) {
   3086             ALOGE("%s: Could not find object among registered buffers",__func__);
   3087             return DEAD_OBJECT;
   3088         }
   3089     }
   3090     CDBG("%s: buffer index %d, frameNumber: %u", __func__, index, frameNumber);
   3091 
   3092     rc = mMemory.markFrameNumber((uint32_t)index, frameNumber);
   3093 
   3094     // Start postprocessor
   3095     startPostProc(reproc_cfg);
   3096 
   3097     // Queue jpeg settings
   3098     rc = queueJpegSetting((uint32_t)index, metadata);
   3099 
   3100     if (pInputBuffer == NULL) {
   3101         Mutex::Autolock lock(mFreeBuffersLock);
   3102         uint32_t bufIdx;
   3103         if (mFreeBufferList.empty()) {
   3104             rc = mYuvMemory->allocateOne(mFrameLen);
   3105             if (rc < 0) {
   3106                 ALOGE("%s: Failed to allocate heap buffer. Fatal", __func__);
   3107                 return rc;
   3108             } else {
   3109                 bufIdx = (uint32_t)rc;
   3110             }
   3111         } else {
   3112             List<uint32_t>::iterator it = mFreeBufferList.begin();
   3113             bufIdx = *it;
   3114             mFreeBufferList.erase(it);
   3115         }
   3116         mYuvMemory->markFrameNumber(bufIdx, frameNumber);
   3117         mStreams[0]->bufDone(bufIdx);
   3118     } else {
   3119         qcamera_fwk_input_pp_data_t *src_frame = NULL;
   3120         src_frame = (qcamera_fwk_input_pp_data_t *)calloc(1,
   3121                 sizeof(qcamera_fwk_input_pp_data_t));
   3122         if (src_frame == NULL) {
   3123             ALOGE("%s: No memory for src frame", __func__);
   3124             return NO_MEMORY;
   3125         }
   3126         rc = setFwkInputPPData(src_frame, pInputBuffer, &reproc_cfg, metadata,
   3127                 NULL /*fwk output buffer*/, frameNumber);
   3128         if (NO_ERROR != rc) {
   3129             ALOGE("%s: Error %d while setting framework input PP data", __func__, rc);
   3130             free(src_frame);
   3131             return rc;
   3132         }
   3133         CDBG_HIGH("%s: Post-process started", __func__);
   3134         CDBG_HIGH("%s: Issue call to reprocess", __func__);
   3135         m_postprocessor.processData(src_frame);
   3136     }
   3137     return rc;
   3138 }
   3139 
   3140 
   3141 /*===========================================================================
   3142  * FUNCTION   : dataNotifyCB
   3143  *
   3144  * DESCRIPTION: Channel Level callback used for super buffer data notify.
   3145  *              This function is registered with mm-camera-interface to handle
   3146  *              data notify
   3147  *
   3148  * PARAMETERS :
   3149  *   @recvd_frame   : stream frame received
   3150  *   userdata       : user data ptr
   3151  *
   3152  * RETURN     : none
   3153  *==========================================================================*/
   3154 void QCamera3PicChannel::dataNotifyCB(mm_camera_super_buf_t *recvd_frame,
   3155                                  void *userdata)
   3156 {
   3157     ATRACE_CALL();
   3158     CDBG("%s: E\n", __func__);
   3159     QCamera3PicChannel *channel = (QCamera3PicChannel *)userdata;
   3160 
   3161     if (channel == NULL) {
   3162         ALOGE("%s: invalid channel pointer", __func__);
   3163         return;
   3164     }
   3165 
   3166     if(channel->m_numStreams != 1) {
   3167         ALOGE("%s: Error: Bug: This callback assumes one stream per channel",__func__);
   3168         return;
   3169     }
   3170 
   3171 
   3172     if(channel->mStreams[0] == NULL) {
   3173         ALOGE("%s: Error: Invalid Stream object",__func__);
   3174         return;
   3175     }
   3176 
   3177     channel->QCamera3PicChannel::streamCbRoutine(recvd_frame, channel->mStreams[0]);
   3178 
   3179     CDBG("%s: X\n", __func__);
   3180     return;
   3181 }
   3182 
   3183 /*===========================================================================
   3184  * FUNCTION   : streamCbRoutine
   3185  *
   3186  * DESCRIPTION:
   3187  *
   3188  * PARAMETERS :
   3189  * @super_frame : the super frame with filled buffer
   3190  * @stream      : stream on which the buffer was requested and filled
   3191  *
   3192  * RETURN     : none
   3193  *==========================================================================*/
   3194 void QCamera3PicChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
   3195                             QCamera3Stream *stream)
   3196 {
   3197     ATRACE_CALL();
   3198     //TODO
   3199     //Used only for getting YUV. Jpeg callback will be sent back from channel
   3200     //directly to HWI. Refer to func jpegEvtHandle
   3201 
   3202     //Got the yuv callback. Calling yuv callback handler in PostProc
   3203     uint8_t frameIndex;
   3204     mm_camera_super_buf_t* frame = NULL;
   3205 
   3206     if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
   3207         ALOGE("%s: Error with the stream callback", __func__);
   3208         return;
   3209     }
   3210 
   3211     frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
   3212     CDBG("%s: recvd buf_idx: %u for further processing",
   3213         __func__, (uint32_t)frameIndex);
   3214     if(frameIndex >= mNumSnapshotBufs) {
   3215          ALOGE("%s: Error, Invalid index for buffer",__func__);
   3216          if(stream) {
   3217              Mutex::Autolock lock(mFreeBuffersLock);
   3218              mFreeBufferList.push_back(frameIndex);
   3219              stream->bufDone(frameIndex);
   3220          }
   3221          return;
   3222     }
   3223 
   3224     frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
   3225     if (frame == NULL) {
   3226        ALOGE("%s: Error allocating memory to save received_frame structure.",
   3227                                                                     __func__);
   3228        if(stream) {
   3229            Mutex::Autolock lock(mFreeBuffersLock);
   3230            mFreeBufferList.push_back(frameIndex);
   3231            stream->bufDone(frameIndex);
   3232        }
   3233        return;
   3234     }
   3235     *frame = *super_frame;
   3236 
   3237     if (mYUVDump) {
   3238         cam_dimension_t dim;
   3239         memset(&dim, 0, sizeof(dim));
   3240         stream->getFrameDimension(dim);
   3241         cam_frame_len_offset_t offset;
   3242         memset(&offset, 0, sizeof(cam_frame_len_offset_t));
   3243         stream->getFrameOffset(offset);
   3244         dumpYUV(frame->bufs[0], dim, offset, 1);
   3245     }
   3246 
   3247     m_postprocessor.processData(frame);
   3248     free(super_frame);
   3249     return;
   3250 }
   3251 
   3252 QCamera3StreamMem* QCamera3PicChannel::getStreamBufs(uint32_t len)
   3253 {
   3254     int rc = 0;
   3255 
   3256     mYuvMemory = new QCamera3StreamMem(mCamera3Stream->max_buffers, false);
   3257     if (!mYuvMemory) {
   3258         ALOGE("%s: unable to create metadata memory", __func__);
   3259         return NULL;
   3260     }
   3261     mFrameLen = len;
   3262 
   3263     return mYuvMemory;
   3264 }
   3265 
   3266 void QCamera3PicChannel::putStreamBufs()
   3267 {
   3268     QCamera3ProcessingChannel::putStreamBufs();
   3269 
   3270     mYuvMemory->deallocate();
   3271     delete mYuvMemory;
   3272     mYuvMemory = NULL;
   3273     mFreeBufferList.clear();
   3274 }
   3275 
   3276 int32_t QCamera3PicChannel::queueJpegSetting(uint32_t index, metadata_buffer_t *metadata)
   3277 {
   3278     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
   3279     jpeg_settings_t *settings =
   3280             (jpeg_settings_t *)malloc(sizeof(jpeg_settings_t));
   3281 
   3282     if (!settings) {
   3283         ALOGE("%s: out of memory allocating jpeg_settings", __func__);
   3284         return -ENOMEM;
   3285     }
   3286 
   3287     memset(settings, 0, sizeof(jpeg_settings_t));
   3288 
   3289     settings->out_buf_index = index;
   3290 
   3291     settings->jpeg_orientation = 0;
   3292     IF_META_AVAILABLE(int32_t, orientation, CAM_INTF_META_JPEG_ORIENTATION, metadata) {
   3293         settings->jpeg_orientation = *orientation;
   3294     }
   3295 
   3296     settings->jpeg_quality = 85;
   3297     IF_META_AVAILABLE(uint32_t, quality1, CAM_INTF_META_JPEG_QUALITY, metadata) {
   3298         settings->jpeg_quality = (uint8_t) *quality1;
   3299     }
   3300 
   3301     IF_META_AVAILABLE(uint32_t, quality2, CAM_INTF_META_JPEG_THUMB_QUALITY, metadata) {
   3302         settings->jpeg_thumb_quality = (uint8_t) *quality2;
   3303     }
   3304 
   3305     IF_META_AVAILABLE(cam_dimension_t, dimension, CAM_INTF_META_JPEG_THUMB_SIZE, metadata) {
   3306         settings->thumbnail_size = *dimension;
   3307     }
   3308 
   3309     settings->gps_timestamp_valid = 0;
   3310     IF_META_AVAILABLE(int64_t, timestamp, CAM_INTF_META_JPEG_GPS_TIMESTAMP, metadata) {
   3311         settings->gps_timestamp = *timestamp;
   3312         settings->gps_timestamp_valid = 1;
   3313     }
   3314 
   3315     settings->gps_coordinates_valid = 0;
   3316     IF_META_AVAILABLE(double, coordinates, CAM_INTF_META_JPEG_GPS_COORDINATES, metadata) {
   3317         memcpy(settings->gps_coordinates, coordinates, 3*sizeof(double));
   3318         settings->gps_coordinates_valid = 1;
   3319     }
   3320 
   3321     IF_META_AVAILABLE(uint8_t, proc_methods, CAM_INTF_META_JPEG_GPS_PROC_METHODS, metadata) {
   3322         memset(settings->gps_processing_method, 0,
   3323                 sizeof(settings->gps_processing_method));
   3324         strlcpy(settings->gps_processing_method, (const char *)proc_methods,
   3325                 sizeof(settings->gps_processing_method));
   3326     }
   3327 
   3328     // Image description
   3329     const char *eepromVersion = hal_obj->getEepromVersionInfo();
   3330     const uint32_t *ldafCalib = hal_obj->getLdafCalib();
   3331     if ((eepromVersion && strlen(eepromVersion)) ||
   3332             ldafCalib) {
   3333         int len = 0;
   3334         settings->image_desc_valid = true;
   3335         if (eepromVersion && strlen(eepromVersion)) {
   3336             len = snprintf(settings->image_desc, sizeof(settings->image_desc),
   3337                     "M:%s ", eepromVersion);
   3338         }
   3339         if (ldafCalib) {
   3340             snprintf(settings->image_desc + len,
   3341                     sizeof(settings->image_desc) - len, "L:%u-%u",
   3342                     ldafCalib[0], ldafCalib[1]);
   3343         }
   3344     }
   3345 
   3346     return m_postprocessor.processJpegSettingData(settings);
   3347 }
   3348 
   3349 /*===========================================================================
   3350  * FUNCTION   : overrideYuvSize
   3351  *
   3352  * DESCRIPTION: constructor of QCamera3ReprocessChannel
   3353  *
   3354  * PARAMETERS :
   3355  *   @width     : new width
   3356  *   @height    : new height
   3357  *
   3358  * RETURN     : none
   3359  *==========================================================================*/
   3360 void QCamera3PicChannel::overrideYuvSize(uint32_t width, uint32_t height)
   3361 {
   3362    mYuvWidth = width;
   3363    mYuvHeight = height;
   3364 }
   3365 
   3366 /*===========================================================================
   3367  * FUNCTION   : getReprocessType
   3368  *
   3369  * DESCRIPTION: get the type of reprocess output supported by this channel
   3370  *
   3371  * PARAMETERS : NONE
   3372  *
   3373  * RETURN     : reprocess_type_t : type of reprocess
   3374  *==========================================================================*/
   3375 reprocess_type_t QCamera3PicChannel::getReprocessType()
   3376 {
   3377     /* a picture channel could either use the postprocessor for reprocess+jpeg
   3378        or only for reprocess */
   3379     reprocess_type_t expectedReprocess;
   3380     if (mPostProcMask == CAM_QCOM_FEATURE_NONE || mInputBufferHint) {
   3381         expectedReprocess = REPROCESS_TYPE_JPEG;
   3382     } else {
   3383         expectedReprocess = REPROCESS_TYPE_NONE;
   3384     }
   3385     CDBG_HIGH("%s: expectedReprocess from Pic Channel is %d", __func__, expectedReprocess);
   3386     return expectedReprocess;
   3387 }
   3388 
   3389 /* Reprocess Channel methods */
   3390 
   3391 /*===========================================================================
   3392  * FUNCTION   : QCamera3ReprocessChannel
   3393  *
   3394  * DESCRIPTION: constructor of QCamera3ReprocessChannel
   3395  *
   3396  * PARAMETERS :
   3397  *   @cam_handle : camera handle
   3398  *   @cam_ops    : ptr to camera ops table
   3399  *   @pp_mask    : post-proccess feature mask
   3400  *
   3401  * RETURN     : none
   3402  *==========================================================================*/
   3403 QCamera3ReprocessChannel::QCamera3ReprocessChannel(uint32_t cam_handle,
   3404                                                  uint32_t channel_handle,
   3405                                                  mm_camera_ops_t *cam_ops,
   3406                                                  channel_cb_routine cb_routine,
   3407                                                  cam_padding_info_t *paddingInfo,
   3408                                                  uint32_t postprocess_mask,
   3409                                                  void *userData, void *ch_hdl) :
   3410     /* In case of framework reprocessing, pproc and jpeg operations could be
   3411      * parallelized by allowing 1 extra buffer for reprocessing output:
   3412      * ch_hdl->getNumBuffers() + 1 */
   3413     QCamera3Channel(cam_handle, channel_handle, cam_ops, cb_routine, paddingInfo,
   3414                     postprocess_mask, userData,
   3415                     ((QCamera3ProcessingChannel *)ch_hdl)->getNumBuffers()
   3416                               + (MAX_REPROCESS_PIPELINE_STAGES - 1)),
   3417     inputChHandle(ch_hdl),
   3418     mOfflineBuffersIndex(-1),
   3419     mFrameLen(0),
   3420     mReprocessType(REPROCESS_TYPE_NONE),
   3421     m_pSrcChannel(NULL),
   3422     m_pMetaChannel(NULL),
   3423     mMemory(NULL),
   3424     mGrallocMemory(0)
   3425 {
   3426     memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles));
   3427     mOfflineBuffersIndex = mNumBuffers -1;
   3428     mOfflineMetaIndex = (int32_t) (2*mNumBuffers -1);
   3429 }
   3430 
   3431 
   3432 /*===========================================================================
   3433  * FUNCTION   : QCamera3ReprocessChannel
   3434  *
   3435  * DESCRIPTION: constructor of QCamera3ReprocessChannel
   3436  *
   3437  * PARAMETERS :
   3438  *   @cam_handle : camera handle
   3439  *   @cam_ops    : ptr to camera ops table
   3440  *   @pp_mask    : post-proccess feature mask
   3441  *
   3442  * RETURN     : none
   3443  *==========================================================================*/
   3444 int32_t QCamera3ReprocessChannel::initialize(cam_is_type_t isType)
   3445 {
   3446     int32_t rc = NO_ERROR;
   3447     mm_camera_channel_attr_t attr;
   3448 
   3449     memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
   3450     attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS;
   3451     attr.max_unmatched_frames = 1;
   3452 
   3453     m_handle = m_camOps->add_channel(m_camHandle,
   3454                                       &attr,
   3455                                       NULL,
   3456                                       this);
   3457     if (m_handle == 0) {
   3458         ALOGE("%s: Add channel failed", __func__);
   3459         return UNKNOWN_ERROR;
   3460     }
   3461 
   3462     mIsType = isType;
   3463     return rc;
   3464 }
   3465 
   3466 /*===========================================================================
   3467  * FUNCTION   : registerBuffer
   3468  *
   3469  * DESCRIPTION: register streaming buffer to the channel object
   3470  *
   3471  * PARAMETERS :
   3472  *   @buffer     : buffer to be registered
   3473  *   @isType     : the image stabilization type for the buffer
   3474  *
   3475  * RETURN     : int32_t type of status
   3476  *              NO_ERROR  -- success
   3477  *              none-zero failure code
   3478  *==========================================================================*/
   3479 int32_t QCamera3ReprocessChannel::registerBuffer(buffer_handle_t *buffer,
   3480         cam_is_type_t isType)
   3481 {
   3482     ATRACE_CALL();
   3483     int rc = 0;
   3484     mIsType = isType;
   3485     cam_stream_type_t streamType;
   3486 
   3487     if (buffer == NULL) {
   3488         ALOGE("%s: Error: Cannot register a NULL buffer", __func__);
   3489         return BAD_VALUE;
   3490     }
   3491 
   3492     if ((uint32_t)mGrallocMemory.getCnt() > (mNumBuffers - 1)) {
   3493         ALOGE("%s: Trying to register more buffers than initially requested",
   3494                 __func__);
   3495         return BAD_VALUE;
   3496     }
   3497 
   3498     if (0 == m_numStreams) {
   3499         rc = initialize(mIsType);
   3500         if (rc != NO_ERROR) {
   3501             ALOGE("%s: Couldn't initialize camera stream %d",
   3502                     __func__, rc);
   3503             return rc;
   3504         }
   3505     }
   3506 
   3507     streamType = mStreams[0]->getMyType();
   3508     rc = mGrallocMemory.registerBuffer(buffer, streamType);
   3509     if (ALREADY_EXISTS == rc) {
   3510         return NO_ERROR;
   3511     } else if (NO_ERROR != rc) {
   3512         ALOGE("%s: Buffer %p couldn't be registered %d", __func__, buffer, rc);
   3513         return rc;
   3514     }
   3515 
   3516     return rc;
   3517 }
   3518 
   3519 /*===========================================================================
   3520  * FUNCTION   : QCamera3ReprocessChannel
   3521  *
   3522  * DESCRIPTION: constructor of QCamera3ReprocessChannel
   3523  *
   3524  * PARAMETERS :
   3525  *   @cam_handle : camera handle
   3526  *   @cam_ops    : ptr to camera ops table
   3527  *   @pp_mask    : post-proccess feature mask
   3528  *
   3529  * RETURN     : none
   3530  *==========================================================================*/
   3531 void QCamera3ReprocessChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
   3532                                   QCamera3Stream *stream)
   3533 {
   3534     //Got the pproc data callback. Now send to jpeg encoding
   3535     uint8_t frameIndex;
   3536     uint32_t resultFrameNumber;
   3537     mm_camera_super_buf_t* frame = NULL;
   3538     QCamera3ProcessingChannel *obj = (QCamera3ProcessingChannel *)inputChHandle;
   3539 
   3540     if(!super_frame) {
   3541          ALOGE("%s: Invalid Super buffer",__func__);
   3542          return;
   3543     }
   3544 
   3545     if(super_frame->num_bufs != 1) {
   3546          ALOGE("%s: Multiple streams are not supported",__func__);
   3547          return;
   3548     }
   3549     if(super_frame->bufs[0] == NULL ) {
   3550          ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
   3551                   __func__);
   3552          return;
   3553     }
   3554     frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
   3555 
   3556     if (mYUVDump) {
   3557         cam_dimension_t dim;
   3558         memset(&dim, 0, sizeof(dim));
   3559         stream->getFrameDimension(dim);
   3560         cam_frame_len_offset_t offset;
   3561         memset(&offset, 0, sizeof(cam_frame_len_offset_t));
   3562         stream->getFrameOffset(offset);
   3563         dumpYUV(super_frame->bufs[0], dim, offset, 2);
   3564     }
   3565 
   3566     if (mReprocessType == REPROCESS_TYPE_JPEG) {
   3567         resultFrameNumber =  mMemory->getFrameNumber(frameIndex);
   3568         frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
   3569         if (frame == NULL) {
   3570            ALOGE("%s: Error allocating memory to save received_frame structure.",
   3571                                                                         __func__);
   3572            if(stream) {
   3573                stream->bufDone(frameIndex);
   3574            }
   3575            return;
   3576         }
   3577         CDBG("%s: bufIndex: %u recvd from post proc",
   3578             __func__, (uint32_t)frameIndex);
   3579         *frame = *super_frame;
   3580 
   3581         /* Since reprocessing is done, send the callback to release the input buffer */
   3582         // Release offline buffers.
   3583         obj->releaseOfflineMemory(resultFrameNumber);
   3584         if (mChannelCB) {
   3585             mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData);
   3586         }
   3587         obj->m_postprocessor.processPPData(frame);
   3588     } else {
   3589         buffer_handle_t *resultBuffer;
   3590         frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
   3591         resultBuffer = (buffer_handle_t *)mGrallocMemory.getBufferHandle(frameIndex);
   3592         resultFrameNumber = mGrallocMemory.getFrameNumber(frameIndex);
   3593         int32_t rc = stream->bufRelease(frameIndex);
   3594         if (NO_ERROR != rc) {
   3595             ALOGE("%s: Error %d releasing stream buffer %d",
   3596                     __func__, rc, frameIndex);
   3597         }
   3598         rc = mGrallocMemory.unregisterBuffer(frameIndex);
   3599         if (NO_ERROR != rc) {
   3600             ALOGE("%s: Error %d unregistering stream buffer %d",
   3601                     __func__, rc, frameIndex);
   3602         }
   3603         obj->reprocessCbRoutine(resultBuffer, resultFrameNumber);
   3604 
   3605         obj->m_postprocessor.releaseOfflineBuffers();
   3606         qcamera_hal3_pp_data_t *pp_job = obj->m_postprocessor.dequeuePPJob(resultFrameNumber);
   3607         if (pp_job != NULL) {
   3608             obj->m_postprocessor.releasePPJobData(pp_job);
   3609         }
   3610         free(pp_job);
   3611     }
   3612     free(super_frame);
   3613     return;
   3614 }
   3615 
   3616 /*===========================================================================
   3617  * FUNCTION   : getStreamBufs
   3618  *
   3619  * DESCRIPTION: register the buffers of the reprocess channel
   3620  *
   3621  * PARAMETERS : none
   3622  *
   3623  * RETURN     : QCamera3StreamMem *
   3624  *==========================================================================*/
   3625 QCamera3StreamMem* QCamera3ReprocessChannel::getStreamBufs(uint32_t len)
   3626 {
   3627     int rc = 0;
   3628     if (mReprocessType == REPROCESS_TYPE_JPEG) {
   3629         mMemory = new QCamera3StreamMem(mNumBuffers, false);
   3630         if (!mMemory) {
   3631             ALOGE("%s: unable to create reproc memory", __func__);
   3632             return NULL;
   3633         }
   3634         mFrameLen = len;
   3635         return mMemory;
   3636     }
   3637     return &mGrallocMemory;
   3638 }
   3639 
   3640 /*===========================================================================
   3641  * FUNCTION   : putStreamBufs
   3642  *
   3643  * DESCRIPTION: release the reprocess channel buffers
   3644  *
   3645  * PARAMETERS : none
   3646  *
   3647  * RETURN     :
   3648  *==========================================================================*/
   3649 void QCamera3ReprocessChannel::putStreamBufs()
   3650 {
   3651    if (mReprocessType == REPROCESS_TYPE_JPEG) {
   3652        mMemory->deallocate();
   3653        delete mMemory;
   3654        mMemory = NULL;
   3655        mFreeBufferList.clear();
   3656    } else {
   3657        mGrallocMemory.unregisterBuffers();
   3658    }
   3659 }
   3660 
   3661 /*===========================================================================
   3662  * FUNCTION   : ~QCamera3ReprocessChannel
   3663  *
   3664  * DESCRIPTION: destructor of QCamera3ReprocessChannel
   3665  *
   3666  * PARAMETERS : none
   3667  *
   3668  * RETURN     : none
   3669  *==========================================================================*/
   3670 QCamera3ReprocessChannel::~QCamera3ReprocessChannel()
   3671 {
   3672     if (m_bIsActive)
   3673         stop();
   3674 
   3675     for (uint32_t i = 0; i < m_numStreams; i++) {
   3676         if (mStreams[i] != NULL) {
   3677             delete mStreams[i];
   3678             mStreams[i] = 0;
   3679         }
   3680     }
   3681     if (m_handle) {
   3682         m_camOps->delete_channel(m_camHandle, m_handle);
   3683         ALOGE("%s: deleting channel %d", __func__, m_handle);
   3684         m_handle = 0;
   3685     }
   3686     m_numStreams = 0;
   3687 }
   3688 
   3689 /*===========================================================================
   3690  * FUNCTION   : start
   3691  *
   3692  * DESCRIPTION: start reprocess channel.
   3693  *
   3694  * PARAMETERS :
   3695  *
   3696  * RETURN     : int32_t type of status
   3697  *              NO_ERROR  -- success
   3698  *              none-zero failure code
   3699  *==========================================================================*/
   3700 int32_t QCamera3ReprocessChannel::start()
   3701 {
   3702     ATRACE_CALL();
   3703     int32_t rc = NO_ERROR;
   3704 
   3705     rc = QCamera3Channel::start();
   3706 
   3707     if (rc == NO_ERROR) {
   3708        rc = m_camOps->start_channel(m_camHandle, m_handle);
   3709 
   3710        // Check failure
   3711        if (rc != NO_ERROR) {
   3712            ALOGE("%s: start_channel failed %d", __func__, rc);
   3713            QCamera3Channel::stop();
   3714        }
   3715     }
   3716     return rc;
   3717 }
   3718 
   3719 /*===========================================================================
   3720  * FUNCTION   : stop
   3721  *
   3722  * DESCRIPTION: stop reprocess channel.
   3723  *
   3724  * PARAMETERS : none
   3725  *
   3726  * RETURN     : int32_t type of status
   3727  *              NO_ERROR  -- success
   3728  *              none-zero failure code
   3729  *==========================================================================*/
   3730 int32_t QCamera3ReprocessChannel::stop()
   3731 {
   3732     ATRACE_CALL();
   3733     int32_t rc = NO_ERROR;
   3734 
   3735     rc = QCamera3Channel::stop();
   3736 
   3737     rc != m_camOps->stop_channel(m_camHandle, m_handle);
   3738 
   3739     unmapOfflineBuffers(true);
   3740 
   3741     return rc;
   3742 }
   3743 
   3744 /*===========================================================================
   3745  * FUNCTION   : getStreamBySrcHandle
   3746  *
   3747  * DESCRIPTION: find reprocess stream by its source stream handle
   3748  *
   3749  * PARAMETERS :
   3750  *   @srcHandle : source stream handle
   3751  *
   3752  * RETURN     : ptr to reprocess stream if found. NULL if not found
   3753  *==========================================================================*/
   3754 QCamera3Stream * QCamera3ReprocessChannel::getStreamBySrcHandle(uint32_t srcHandle)
   3755 {
   3756     QCamera3Stream *pStream = NULL;
   3757 
   3758     for (uint32_t i = 0; i < m_numStreams; i++) {
   3759         if (mSrcStreamHandles[i] == srcHandle) {
   3760             pStream = mStreams[i];
   3761             break;
   3762         }
   3763     }
   3764     return pStream;
   3765 }
   3766 
   3767 /*===========================================================================
   3768  * FUNCTION   : getSrcStreamBySrcHandle
   3769  *
   3770  * DESCRIPTION: find source stream by source stream handle
   3771  *
   3772  * PARAMETERS :
   3773  *   @srcHandle : source stream handle
   3774  *
   3775  * RETURN     : ptr to reprocess stream if found. NULL if not found
   3776  *==========================================================================*/
   3777 QCamera3Stream * QCamera3ReprocessChannel::getSrcStreamBySrcHandle(uint32_t srcHandle)
   3778 {
   3779     QCamera3Stream *pStream = NULL;
   3780 
   3781     if (NULL == m_pSrcChannel) {
   3782         return NULL;
   3783     }
   3784 
   3785     for (uint32_t i = 0; i < m_numStreams; i++) {
   3786         if (mSrcStreamHandles[i] == srcHandle) {
   3787             pStream = m_pSrcChannel->getStreamByIndex(i);
   3788             break;
   3789         }
   3790     }
   3791     return pStream;
   3792 }
   3793 
   3794 /*===========================================================================
   3795  * FUNCTION   : unmapOfflineBuffers
   3796  *
   3797  * DESCRIPTION: Unmaps offline buffers
   3798  *
   3799  * PARAMETERS : none
   3800  *
   3801  * RETURN     : int32_t type of status
   3802  *              NO_ERROR  -- success
   3803  *              none-zero failure code
   3804  *==========================================================================*/
   3805 int32_t QCamera3ReprocessChannel::unmapOfflineBuffers(bool all)
   3806 {
   3807     int rc = NO_ERROR;
   3808     if (!mOfflineBuffers.empty()) {
   3809         QCamera3Stream *stream = NULL;
   3810         List<OfflineBuffer>::iterator it = mOfflineBuffers.begin();
   3811         for (; it != mOfflineBuffers.end(); it++) {
   3812            stream = (*it).stream;
   3813            if (NULL != stream) {
   3814                rc = stream->unmapBuf((*it).type,
   3815                                      (*it).index,
   3816                                         -1);
   3817                if (NO_ERROR != rc) {
   3818                    ALOGE("%s: Error during offline buffer unmap %d",
   3819                          __func__, rc);
   3820                }
   3821                CDBG("%s: Unmapped buffer with index %d", __func__, (*it).index);
   3822            }
   3823            if (!all) {
   3824                mOfflineBuffers.erase(it);
   3825                break;
   3826            }
   3827         }
   3828         if (all) {
   3829            mOfflineBuffers.clear();
   3830         }
   3831     }
   3832 
   3833     if (!mOfflineMetaBuffers.empty()) {
   3834         QCamera3Stream *stream = NULL;
   3835         List<OfflineBuffer>::iterator it = mOfflineMetaBuffers.begin();
   3836         for (; it != mOfflineMetaBuffers.end(); it++) {
   3837            stream = (*it).stream;
   3838            if (NULL != stream) {
   3839                rc = stream->unmapBuf((*it).type,
   3840                                      (*it).index,
   3841                                         -1);
   3842                if (NO_ERROR != rc) {
   3843                    ALOGE("%s: Error during offline buffer unmap %d",
   3844                          __func__, rc);
   3845                }
   3846                CDBG("%s: Unmapped meta buffer with index %d", __func__, (*it).index);
   3847            }
   3848            if (!all) {
   3849                mOfflineMetaBuffers.erase(it);
   3850                break;
   3851            }
   3852         }
   3853         if (all) {
   3854            mOfflineMetaBuffers.clear();
   3855         }
   3856     }
   3857     return rc;
   3858 }
   3859 
   3860 /*===========================================================================
   3861  * FUNCTION   : bufDone
   3862  *
   3863  * DESCRIPTION: Return reprocess stream buffer to free buffer list.
   3864  *              Note that this function doesn't queue buffer back to kernel.
   3865  *              It's up to doReprocessOffline to do that instead.
   3866  * PARAMETERS :
   3867  *   @recvd_frame  : stream buf frame to be returned
   3868  *
   3869  * RETURN     : int32_t type of status
   3870  *              NO_ERROR  -- success
   3871  *              none-zero failure code
   3872  *==========================================================================*/
   3873 int32_t QCamera3ReprocessChannel::bufDone(mm_camera_super_buf_t *recvd_frame)
   3874 {
   3875     int rc = NO_ERROR;
   3876     if (recvd_frame && recvd_frame->num_bufs == 1) {
   3877         Mutex::Autolock lock(mFreeBuffersLock);
   3878         uint32_t buf_idx = recvd_frame->bufs[0]->buf_idx;
   3879         mFreeBufferList.push_back(buf_idx);
   3880 
   3881     } else {
   3882         ALOGE("%s: Fatal. Not supposed to be here", __func__);
   3883         rc = BAD_VALUE;
   3884     }
   3885 
   3886     return rc;
   3887 }
   3888 
   3889 /*===========================================================================
   3890  * FUNCTION   : overrideMetadata
   3891  *
   3892  * DESCRIPTION: Override metadata entry such as rotation, crop, and CDS info.
   3893  *
   3894  * PARAMETERS :
   3895  *   @frame     : input frame from source stream
   3896  *   meta_buffer: metadata buffer
   3897  *   @metadata  : corresponding metadata
   3898  *   @fwk_frame :
   3899  *
   3900  * RETURN     : int32_t type of status
   3901  *              NO_ERROR  -- success
   3902  *              none-zero failure code
   3903  *==========================================================================*/
   3904 int32_t QCamera3ReprocessChannel::overrideMetadata(qcamera_hal3_pp_buffer_t *pp_buffer,
   3905         mm_camera_buf_def_t *meta_buffer, jpeg_settings_t *jpeg_settings,
   3906         qcamera_fwk_input_pp_data_t &fwk_frame)
   3907 {
   3908     int32_t rc = NO_ERROR;
   3909     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
   3910     if ((NULL == meta_buffer) || (NULL == pp_buffer) || (NULL == pp_buffer->input) ||
   3911             (NULL == hal_obj)) {
   3912         return BAD_VALUE;
   3913     }
   3914 
   3915     metadata_buffer_t *meta = (metadata_buffer_t *)meta_buffer->buffer;
   3916     mm_camera_super_buf_t *frame = pp_buffer->input;
   3917     if (NULL == meta) {
   3918         return BAD_VALUE;
   3919     }
   3920 
   3921     for (uint32_t i = 0; i < frame->num_bufs; i++) {
   3922         QCamera3Stream *pStream = getStreamBySrcHandle(frame->bufs[i]->stream_id);
   3923         QCamera3Stream *pSrcStream = getSrcStreamBySrcHandle(frame->bufs[i]->stream_id);
   3924 
   3925         if (pStream != NULL && pSrcStream != NULL) {
   3926             if (jpeg_settings) {
   3927                 // Find rotation info for reprocess stream
   3928                 cam_rotation_info_t rotation_info;
   3929                 memset(&rotation_info, 0, sizeof(rotation_info));
   3930                 if (jpeg_settings->jpeg_orientation == 0) {
   3931                    rotation_info.rotation = ROTATE_0;
   3932                 } else if (jpeg_settings->jpeg_orientation == 90) {
   3933                    rotation_info.rotation = ROTATE_90;
   3934                 } else if (jpeg_settings->jpeg_orientation == 180) {
   3935                    rotation_info.rotation = ROTATE_180;
   3936                 } else if (jpeg_settings->jpeg_orientation == 270) {
   3937                    rotation_info.rotation = ROTATE_270;
   3938                 }
   3939                 rotation_info.streamId = mStreams[0]->getMyServerID();
   3940                 ADD_SET_PARAM_ENTRY_TO_BATCH(meta, CAM_INTF_PARM_ROTATION, rotation_info);
   3941             }
   3942 
   3943             // Find and insert crop info for reprocess stream
   3944             IF_META_AVAILABLE(cam_crop_data_t, crop_data, CAM_INTF_META_CROP_DATA, meta) {
   3945                 if (MAX_NUM_STREAMS > crop_data->num_of_streams) {
   3946                     for (int j = 0; j < crop_data->num_of_streams; j++) {
   3947                         if (crop_data->crop_info[j].stream_id ==
   3948                                 pSrcStream->getMyServerID()) {
   3949 
   3950                             // Store crop/roi information for offline reprocess
   3951                             // in the reprocess stream slot
   3952                             crop_data->crop_info[crop_data->num_of_streams].crop =
   3953                                     crop_data->crop_info[j].crop;
   3954                             crop_data->crop_info[crop_data->num_of_streams].roi_map =
   3955                                     crop_data->crop_info[j].roi_map;
   3956                             crop_data->crop_info[crop_data->num_of_streams].stream_id =
   3957                                     mStreams[0]->getMyServerID();
   3958                             crop_data->num_of_streams++;
   3959 
   3960                             CDBG("%s: Reprocess stream server id: %d",
   3961                                     __func__, mStreams[0]->getMyServerID());
   3962                             CDBG("%s: Found offline reprocess crop %dx%d %dx%d",
   3963                                     __func__,
   3964                                     crop_data->crop_info[j].crop.left,
   3965                                     crop_data->crop_info[j].crop.top,
   3966                                     crop_data->crop_info[j].crop.width,
   3967                                     crop_data->crop_info[j].crop.height);
   3968                             CDBG("%s: Found offline reprocess roimap %dx%d %dx%d",
   3969                                     __func__,
   3970                                     crop_data->crop_info[j].roi_map.left,
   3971                                     crop_data->crop_info[j].roi_map.top,
   3972                                     crop_data->crop_info[j].roi_map.width,
   3973                                     crop_data->crop_info[j].roi_map.height);
   3974 
   3975                             break;
   3976                         }
   3977                     }
   3978                 } else {
   3979                     ALOGE("%s: No space to add reprocess stream crop/roi information",
   3980                             __func__);
   3981                 }
   3982             }
   3983 
   3984             IF_META_AVAILABLE(cam_cds_data_t, cdsInfo, CAM_INTF_META_CDS_DATA, meta) {
   3985                 uint8_t cnt = cdsInfo->num_of_streams;
   3986                 if (cnt <= MAX_NUM_STREAMS) {
   3987                     cam_stream_cds_info_t repro_cds_info;
   3988                     memset(&repro_cds_info, 0, sizeof(repro_cds_info));
   3989                     repro_cds_info.stream_id = mStreams[0]->getMyServerID();
   3990                     for (size_t i = 0; i < cnt; i++) {
   3991                         if (cdsInfo->cds_info[i].stream_id ==
   3992                                 pSrcStream->getMyServerID()) {
   3993                             repro_cds_info.cds_enable =
   3994                                     cdsInfo->cds_info[i].cds_enable;
   3995                             break;
   3996                         }
   3997                     }
   3998                     cdsInfo->num_of_streams = 1;
   3999                     cdsInfo->cds_info[0] = repro_cds_info;
   4000                 } else {
   4001                     ALOGE("%s: No space to add reprocess stream cds information",
   4002                             __func__);
   4003                 }
   4004             }
   4005 
   4006             fwk_frame.input_buffer = *frame->bufs[i];
   4007             fwk_frame.metadata_buffer = *meta_buffer;
   4008             fwk_frame.output_buffer = pp_buffer->output;
   4009             break;
   4010         } else {
   4011             ALOGE("%s: Source/Re-process streams are invalid", __func__);
   4012             rc |= BAD_VALUE;
   4013         }
   4014     }
   4015 
   4016     return rc;
   4017 }
   4018 
   4019 /*===========================================================================
   4020 * FUNCTION : overrideFwkMetadata
   4021 *
   4022 * DESCRIPTION: Override frameworks metadata such as crop, and CDS data.
   4023 *
   4024 * PARAMETERS :
   4025 * @frame : input frame for reprocessing
   4026 *
   4027 * RETURN : int32_t type of status
   4028 * NO_ERROR -- success
   4029 * none-zero failure code
   4030 *==========================================================================*/
   4031 int32_t QCamera3ReprocessChannel::overrideFwkMetadata(
   4032         qcamera_fwk_input_pp_data_t *frame)
   4033 {
   4034     if (NULL == frame) {
   4035         ALOGE("%s: Incorrect input frame", __func__);
   4036         return BAD_VALUE;
   4037     }
   4038 
   4039 
   4040     if (NULL == frame->metadata_buffer.buffer) {
   4041         ALOGE("%s: No metadata available", __func__);
   4042         return BAD_VALUE;
   4043     }
   4044 
   4045     // Find and insert crop info for reprocess stream
   4046     metadata_buffer_t *meta = (metadata_buffer_t *) frame->metadata_buffer.buffer;
   4047     IF_META_AVAILABLE(cam_crop_data_t, crop_data, CAM_INTF_META_CROP_DATA, meta) {
   4048         if (1 == crop_data->num_of_streams) {
   4049             // Store crop/roi information for offline reprocess
   4050             // in the reprocess stream slot
   4051             crop_data->crop_info[crop_data->num_of_streams].crop =
   4052                     crop_data->crop_info[0].crop;
   4053             crop_data->crop_info[crop_data->num_of_streams].roi_map =
   4054                     crop_data->crop_info[0].roi_map;
   4055             crop_data->crop_info[crop_data->num_of_streams].stream_id =
   4056                     mStreams[0]->getMyServerID();
   4057             crop_data->num_of_streams++;
   4058 
   4059             CDBG("%s: Reprocess stream server id: %d",
   4060                     __func__, mStreams[0]->getMyServerID());
   4061             CDBG("%s: Found offline reprocess crop %dx%d %dx%d", __func__,
   4062                     crop_data->crop_info[0].crop.left,
   4063                     crop_data->crop_info[0].crop.top,
   4064                     crop_data->crop_info[0].crop.width,
   4065                     crop_data->crop_info[0].crop.height);
   4066             CDBG("%s: Found offline reprocess roi map %dx%d %dx%d", __func__,
   4067                     crop_data->crop_info[0].roi_map.left,
   4068                     crop_data->crop_info[0].roi_map.top,
   4069                     crop_data->crop_info[0].roi_map.width,
   4070                     crop_data->crop_info[0].roi_map.height);
   4071         } else {
   4072             ALOGE("%s: Incorrect number of offline crop data entries %d",
   4073                     __func__,
   4074                     crop_data->num_of_streams);
   4075             return BAD_VALUE;
   4076         }
   4077     } else {
   4078         CDBG_HIGH("%s: Crop data not present", __func__);
   4079     }
   4080 
   4081     IF_META_AVAILABLE(cam_cds_data_t, cdsInfo, CAM_INTF_META_CDS_DATA, meta) {
   4082         if (1 == cdsInfo->num_of_streams) {
   4083             cdsInfo->cds_info[0].stream_id = mStreams[0]->getMyServerID();
   4084         } else {
   4085             ALOGE("%s: Incorrect number of offline cds info entries %d",
   4086                     __func__, cdsInfo->num_of_streams);
   4087             return BAD_VALUE;
   4088         }
   4089     }
   4090 
   4091     return NO_ERROR;
   4092 }
   4093 
   4094 /*===========================================================================
   4095  * FUNCTION   : doReprocessOffline
   4096  *
   4097  * DESCRIPTION: request to do a reprocess on the frame
   4098  *
   4099  * PARAMETERS :
   4100  *   @frame     : input frame for reprocessing
   4101  *
   4102  * RETURN     : int32_t type of status
   4103  *              NO_ERROR  -- success
   4104  *              none-zero failure code
   4105  *==========================================================================*/
   4106  int32_t QCamera3ReprocessChannel::doReprocessOffline(qcamera_fwk_input_pp_data_t *frame)
   4107 {
   4108     int32_t rc = 0;
   4109     int index;
   4110     OfflineBuffer mappedBuffer;
   4111 
   4112     if (m_numStreams < 1) {
   4113         ALOGE("%s: No reprocess stream is created", __func__);
   4114         return -1;
   4115     }
   4116 
   4117     if (NULL == frame) {
   4118         ALOGE("%s: Incorrect input frame", __func__);
   4119         return BAD_VALUE;
   4120     }
   4121 
   4122     if (NULL == frame->metadata_buffer.buffer) {
   4123         ALOGE("%s: No metadata available", __func__);
   4124         return BAD_VALUE;
   4125     }
   4126 
   4127     if (NULL == frame->input_buffer.buffer) {
   4128         ALOGE("%s: No input buffer available", __func__);
   4129         return BAD_VALUE;
   4130     }
   4131 
   4132     if ((0 == m_numStreams) || (NULL == mStreams[0])) {
   4133         ALOGE("%s: Reprocess stream not initialized!", __func__);
   4134         return NO_INIT;
   4135     }
   4136 
   4137     QCamera3Stream *pStream = mStreams[0];
   4138 
   4139     //qbuf the output buffer if it was allocated by the framework
   4140     if (mReprocessType != REPROCESS_TYPE_JPEG && frame->output_buffer != NULL) {
   4141         if(!m_bIsActive) {
   4142             rc = registerBuffer(frame->output_buffer, mIsType);
   4143             if (NO_ERROR != rc) {
   4144                 ALOGE("%s: On-the-fly buffer registration failed %d",
   4145                         __func__, rc);
   4146                 return rc;
   4147             }
   4148 
   4149             rc = start();
   4150             if (NO_ERROR != rc) {
   4151                 return rc;
   4152             }
   4153         }
   4154         index = mGrallocMemory.getMatchBufIndex((void*)frame->output_buffer);
   4155         if(index < 0) {
   4156             rc = registerBuffer(frame->output_buffer, mIsType);
   4157             if (NO_ERROR != rc) {
   4158                 ALOGE("%s: On-the-fly buffer registration failed %d",
   4159                         __func__, rc);
   4160                 return rc;
   4161             }
   4162 
   4163             index = mGrallocMemory.getMatchBufIndex((void*)frame->output_buffer);
   4164             if (index < 0) {
   4165                 ALOGE("%s: Could not find object among registered buffers",
   4166                         __func__);
   4167                 return DEAD_OBJECT;
   4168             }
   4169         }
   4170         rc = pStream->bufDone(index);
   4171         if(rc != NO_ERROR) {
   4172             ALOGE("%s: Failed to Q new buffer to stream",__func__);
   4173             return rc;
   4174         }
   4175         rc = mGrallocMemory.markFrameNumber(index, frame->frameNumber);
   4176 
   4177     } else if (mReprocessType == REPROCESS_TYPE_JPEG) {
   4178         Mutex::Autolock lock(mFreeBuffersLock);
   4179         uint32_t bufIdx;
   4180         if (mFreeBufferList.empty()) {
   4181             rc = mMemory->allocateOne(mFrameLen);
   4182             if (rc < 0) {
   4183                 ALOGE("%s: Failed allocating heap buffer. Fatal", __func__);
   4184                 return BAD_VALUE;
   4185             } else {
   4186                 bufIdx = (uint32_t)rc;
   4187             }
   4188         } else {
   4189             bufIdx = *(mFreeBufferList.begin());
   4190             mFreeBufferList.erase(mFreeBufferList.begin());
   4191         }
   4192 
   4193         mMemory->markFrameNumber(bufIdx, frame->frameNumber);
   4194         rc = pStream->bufDone(bufIdx);
   4195         if (rc != NO_ERROR) {
   4196             ALOGE("%s: Failed to queue new buffer to stream", __func__);
   4197             return rc;
   4198         }
   4199     }
   4200 
   4201     int32_t max_idx = (int32_t) (mNumBuffers - 1);
   4202     //loop back the indices if max burst count reached
   4203     if (mOfflineBuffersIndex == max_idx) {
   4204        mOfflineBuffersIndex = -1;
   4205     }
   4206     uint32_t buf_idx = (uint32_t)(mOfflineBuffersIndex + 1);
   4207     rc = pStream->mapBuf(
   4208             CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
   4209             buf_idx, -1,
   4210             frame->input_buffer.fd, frame->input_buffer.frame_len);
   4211     if (NO_ERROR == rc) {
   4212         mappedBuffer.index = buf_idx;
   4213         mappedBuffer.stream = pStream;
   4214         mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF;
   4215         mOfflineBuffers.push_back(mappedBuffer);
   4216         mOfflineBuffersIndex = (int32_t)buf_idx;
   4217         CDBG("%s: Mapped buffer with index %d", __func__, mOfflineBuffersIndex);
   4218     }
   4219 
   4220     max_idx = (int32_t) ((mNumBuffers * 2) - 1);
   4221     //loop back the indices if max burst count reached
   4222     if (mOfflineMetaIndex == max_idx) {
   4223        mOfflineMetaIndex = (int32_t) (mNumBuffers - 1);
   4224     }
   4225     uint32_t meta_buf_idx = (uint32_t)(mOfflineMetaIndex + 1);
   4226     rc |= pStream->mapBuf(
   4227             CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF,
   4228             meta_buf_idx, -1,
   4229             frame->metadata_buffer.fd, frame->metadata_buffer.frame_len);
   4230     if (NO_ERROR == rc) {
   4231         mappedBuffer.index = meta_buf_idx;
   4232         mappedBuffer.stream = pStream;
   4233         mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF;
   4234         mOfflineMetaBuffers.push_back(mappedBuffer);
   4235         mOfflineMetaIndex = (int32_t)meta_buf_idx;
   4236         CDBG("%s: Mapped meta buffer with index %d", __func__, mOfflineMetaIndex);
   4237     }
   4238 
   4239     if (rc == NO_ERROR) {
   4240         cam_stream_parm_buffer_t param;
   4241         memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
   4242         param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
   4243         param.reprocess.buf_index = buf_idx;
   4244         param.reprocess.frame_idx = frame->input_buffer.frame_idx;
   4245         param.reprocess.meta_present = 1;
   4246         param.reprocess.meta_buf_index = meta_buf_idx;
   4247         rc = pStream->setParameter(param);
   4248         if (rc != NO_ERROR) {
   4249             ALOGE("%s: stream setParameter for reprocess failed", __func__);
   4250         }
   4251     } else {
   4252         ALOGE("%s: Input buffer memory map failed: %d", __func__, rc);
   4253     }
   4254 
   4255     if (rc != NO_ERROR) {
   4256         //Try to recover by returning input with error status
   4257         camera3_stream_buffer_t result;
   4258         memset(&result, 0, sizeof(result));
   4259         result.status = CAMERA3_BUFFER_STATUS_ERROR;
   4260         mChannelCB(NULL, &result, frame->frameNumber, true, mUserData);
   4261     }
   4262 
   4263     return rc;
   4264 }
   4265 
   4266 /*===========================================================================
   4267  * FUNCTION   : doReprocess
   4268  *
   4269  * DESCRIPTION: request to do a reprocess on the frame
   4270  *
   4271  * PARAMETERS :
   4272  *   @buf_fd     : fd to the input buffer that needs reprocess
   4273  *   @buf_lenght : length of the input buffer
   4274  *   @ret_val    : result of reprocess.
   4275  *                 Example: Could be faceID in case of register face image.
   4276  *   @meta_frame : metadata frame.
   4277  *
   4278  * RETURN     : int32_t type of status
   4279  *              NO_ERROR  -- success
   4280  *              none-zero failure code
   4281  *==========================================================================*/
   4282 int32_t QCamera3ReprocessChannel::doReprocess(int buf_fd, size_t buf_length,
   4283         int32_t &ret_val, mm_camera_super_buf_t *meta_frame)
   4284 {
   4285     int32_t rc = 0;
   4286     if (m_numStreams < 1) {
   4287         ALOGE("%s: No reprocess stream is created", __func__);
   4288         return -1;
   4289     }
   4290     if (meta_frame == NULL) {
   4291         ALOGE("%s: Did not get corresponding metadata in time", __func__);
   4292         return -1;
   4293     }
   4294 
   4295     uint8_t buf_idx = 0;
   4296     for (uint32_t i = 0; i < m_numStreams; i++) {
   4297         rc = mStreams[i]->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
   4298                                  buf_idx, -1,
   4299                                  buf_fd, buf_length);
   4300 
   4301         if (rc == NO_ERROR) {
   4302             cam_stream_parm_buffer_t param;
   4303             memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
   4304             param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
   4305             param.reprocess.buf_index = buf_idx;
   4306             param.reprocess.meta_present = 1;
   4307             param.reprocess.meta_stream_handle = m_pMetaChannel->mStreams[0]->getMyServerID();
   4308             param.reprocess.meta_buf_index = meta_frame->bufs[0]->buf_idx;
   4309             rc = mStreams[i]->setParameter(param);
   4310             if (rc == NO_ERROR) {
   4311                 ret_val = param.reprocess.ret_val;
   4312             }
   4313             mStreams[i]->unmapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
   4314                                   buf_idx, -1);
   4315         }
   4316     }
   4317     return rc;
   4318 }
   4319 
   4320 /*===========================================================================
   4321  * FUNCTION   : addReprocStreamsFromSource
   4322  *
   4323  * DESCRIPTION: add reprocess streams from input source channel
   4324  *
   4325  * PARAMETERS :
   4326  *   @config         : pp feature configuration
   4327  *   @src_config     : source reprocess configuration
   4328  *   @isType         : type of image stabilization required on this stream
   4329  *   @pMetaChannel   : ptr to metadata channel to get corresp. metadata
   4330  *
   4331  *
   4332  * RETURN     : int32_t type of status
   4333  *              NO_ERROR  -- success
   4334  *              none-zero failure code
   4335  *==========================================================================*/
   4336 int32_t QCamera3ReprocessChannel::addReprocStreamsFromSource(cam_pp_feature_config_t &pp_config,
   4337         const reprocess_config_t &src_config , cam_is_type_t is_type,
   4338         QCamera3Channel *pMetaChannel)
   4339 {
   4340     int32_t rc = 0;
   4341     cam_stream_reproc_config_t reprocess_config;
   4342     cam_stream_type_t streamType;
   4343 
   4344     cam_dimension_t streamDim = src_config.output_stream_dim;
   4345 
   4346     if (NULL != src_config.src_channel) {
   4347         QCamera3Stream *pSrcStream = src_config.src_channel->getStreamByIndex(0);
   4348         if (pSrcStream == NULL) {
   4349            ALOGE("%s: source channel doesn't have a stream", __func__);
   4350            return BAD_VALUE;
   4351         }
   4352         mSrcStreamHandles[m_numStreams] = pSrcStream->getMyHandle();
   4353     }
   4354 
   4355     streamType = CAM_STREAM_TYPE_OFFLINE_PROC;
   4356     reprocess_config.pp_type = CAM_OFFLINE_REPROCESS_TYPE;
   4357 
   4358     reprocess_config.offline.input_fmt = src_config.stream_format;
   4359     reprocess_config.offline.input_dim = src_config.input_stream_dim;
   4360     reprocess_config.offline.input_buf_planes.plane_info =
   4361             src_config.input_stream_plane_info.plane_info;
   4362     reprocess_config.offline.num_of_bufs = (uint8_t)mNumBuffers;
   4363     reprocess_config.offline.input_type = src_config.stream_type;
   4364 
   4365     reprocess_config.pp_feature_config = pp_config;
   4366     QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
   4367             m_handle,
   4368             m_camOps,
   4369             mPaddingInfo,
   4370             (QCamera3Channel*)this);
   4371     if (pStream == NULL) {
   4372         ALOGE("%s: No mem for Stream", __func__);
   4373         return NO_MEMORY;
   4374     }
   4375 
   4376     rc = pStream->init(streamType, src_config.stream_format,
   4377             streamDim, ROTATE_0, &reprocess_config,
   4378             (uint8_t)mNumBuffers,
   4379             reprocess_config.pp_feature_config.feature_mask,
   4380             is_type,
   4381             0,/* batchSize */
   4382             QCamera3Channel::streamCbRoutine, this);
   4383 
   4384     if (rc == 0) {
   4385         mStreams[m_numStreams] = pStream;
   4386         m_numStreams++;
   4387     } else {
   4388         ALOGE("%s: failed to create reprocess stream", __func__);
   4389         delete pStream;
   4390     }
   4391 
   4392     if (rc == NO_ERROR) {
   4393         m_pSrcChannel = src_config.src_channel;
   4394         m_pMetaChannel = pMetaChannel;
   4395         mReprocessType = src_config.reprocess_type;
   4396         CDBG("%s: mReprocessType is %d", __func__, mReprocessType);
   4397     }
   4398     if(m_camOps->request_super_buf(m_camHandle,m_handle,1,0) < 0) {
   4399         ALOGE("%s: Request for super buffer failed",__func__);
   4400     }
   4401     return rc;
   4402 }
   4403 
   4404 /* QCamera3SupportChannel methods */
   4405 
   4406 cam_dimension_t QCamera3SupportChannel::kDim = {640, 480};
   4407 
   4408 QCamera3SupportChannel::QCamera3SupportChannel(uint32_t cam_handle,
   4409                     uint32_t channel_handle,
   4410                     mm_camera_ops_t *cam_ops,
   4411                     cam_padding_info_t *paddingInfo,
   4412                     uint32_t postprocess_mask,
   4413                     cam_stream_type_t streamType,
   4414                     cam_dimension_t *dim,
   4415                     cam_format_t streamFormat,
   4416                     void *userData, uint32_t numBuffers) :
   4417                         QCamera3Channel(cam_handle, channel_handle, cam_ops,
   4418                                 NULL, paddingInfo, postprocess_mask,
   4419                                 userData, numBuffers),
   4420                         mMemory(NULL)
   4421 {
   4422     memcpy(&mDim, dim, sizeof(cam_dimension_t));
   4423     mStreamType = streamType;
   4424     mStreamFormat = streamFormat;
   4425 }
   4426 
   4427 QCamera3SupportChannel::~QCamera3SupportChannel()
   4428 {
   4429     if (m_bIsActive)
   4430         stop();
   4431 
   4432     if (mMemory) {
   4433         mMemory->deallocate();
   4434         delete mMemory;
   4435         mMemory = NULL;
   4436     }
   4437 }
   4438 
   4439 int32_t QCamera3SupportChannel::initialize(cam_is_type_t isType)
   4440 {
   4441     int32_t rc;
   4442 
   4443     if (mMemory || m_numStreams > 0) {
   4444         ALOGE("%s: metadata channel already initialized", __func__);
   4445         return -EINVAL;
   4446     }
   4447 
   4448     mIsType = isType;
   4449     rc = QCamera3Channel::addStream(mStreamType,
   4450         mStreamFormat, mDim, ROTATE_0, MIN_STREAMING_BUFFER_NUM,
   4451         mPostProcMask, mIsType);
   4452     if (rc < 0) {
   4453         ALOGE("%s: addStream failed", __func__);
   4454     }
   4455     return rc;
   4456 }
   4457 
   4458 int32_t QCamera3SupportChannel::request(buffer_handle_t * /*buffer*/,
   4459                                                 uint32_t /*frameNumber*/)
   4460 {
   4461     return NO_ERROR;
   4462 }
   4463 
   4464 void QCamera3SupportChannel::streamCbRoutine(
   4465                         mm_camera_super_buf_t *super_frame,
   4466                         QCamera3Stream * /*stream*/)
   4467 {
   4468     if (super_frame == NULL || super_frame->num_bufs != 1) {
   4469         ALOGE("%s: super_frame is not valid", __func__);
   4470         return;
   4471     }
   4472     bufDone(super_frame);
   4473     free(super_frame);
   4474 }
   4475 
   4476 QCamera3StreamMem* QCamera3SupportChannel::getStreamBufs(uint32_t len)
   4477 {
   4478     int rc;
   4479     mMemory = new QCamera3StreamMem(mNumBuffers);
   4480     if (!mMemory) {
   4481         ALOGE("%s: unable to create heap memory", __func__);
   4482         return NULL;
   4483     }
   4484     rc = mMemory->allocateAll(len);
   4485     if (rc < 0) {
   4486         ALOGE("%s: unable to allocate heap memory", __func__);
   4487         delete mMemory;
   4488         mMemory = NULL;
   4489         return NULL;
   4490     }
   4491     return mMemory;
   4492 }
   4493 
   4494 void QCamera3SupportChannel::putStreamBufs()
   4495 {
   4496     mMemory->deallocate();
   4497     delete mMemory;
   4498     mMemory = NULL;
   4499 }
   4500 
   4501 }; // namespace qcamera
   4502