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