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