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     mYUVDump = property_get_int32("persist.camera.dumpimg", 0);
    101 }
    102 
    103 /*===========================================================================
    104  * FUNCTION   : ~QCamera3Channel
    105  *
    106  * DESCRIPTION: destructor of QCamera3Channel
    107  *
    108  * PARAMETERS : none
    109  *
    110  * RETURN     : none
    111  *==========================================================================*/
    112 QCamera3Channel::~QCamera3Channel()
    113 {
    114 }
    115 
    116 /*===========================================================================
    117  * FUNCTION   : destroy
    118  *
    119  * DESCRIPTION: internal destructor of QCamera3Channel called by the subclasses
    120  *              this destructor will call pure virtual functions.  stop will eventuall call
    121  *              QCamera3Stream::putBufs.  The putBufs function will
    122  *              call QCamera3Channel::putStreamBufs which is pure virtual
    123  *
    124  * PARAMETERS : none
    125  *
    126  * RETURN     : none
    127  *==========================================================================*/
    128 void QCamera3Channel::destroy()
    129 {
    130     if (m_bIsActive)
    131         stop();
    132 
    133     for (uint32_t i = 0; i < m_numStreams; i++) {
    134         if (mStreams[i] != NULL) {
    135             delete mStreams[i];
    136             mStreams[i] = 0;
    137         }
    138     }
    139     m_numStreams = 0;
    140 }
    141 
    142 /*===========================================================================
    143  * FUNCTION   : addStream
    144  *
    145  * DESCRIPTION: add a stream into channel
    146  *
    147  * PARAMETERS :
    148  *   @streamType     : stream type
    149  *   @streamFormat   : stream format
    150  *   @streamDim      : stream dimension
    151  *   @streamRotation : rotation of the stream
    152  *   @minStreamBufNum : minimal buffer count for particular stream type
    153  *   @postprocessMask : post-proccess feature mask
    154  *   @isType         : type of image stabilization required on the stream
    155  *
    156  * RETURN     : int32_t type of status
    157  *              NO_ERROR  -- success
    158  *              none-zero failure code
    159  *==========================================================================*/
    160 int32_t QCamera3Channel::addStream(cam_stream_type_t streamType,
    161                                   cam_format_t streamFormat,
    162                                   cam_dimension_t streamDim,
    163                                   cam_rotation_t streamRotation,
    164                                   uint8_t minStreamBufNum,
    165                                   cam_feature_mask_t postprocessMask,
    166                                   cam_is_type_t isType,
    167                                   uint32_t batchSize)
    168 {
    169     int32_t rc = NO_ERROR;
    170 
    171     if (m_numStreams >= 1) {
    172         LOGE("Only one stream per channel supported in v3 Hal");
    173         return BAD_VALUE;
    174     }
    175 
    176     if (m_numStreams >= MAX_STREAM_NUM_IN_BUNDLE) {
    177         LOGE("stream number (%d) exceeds max limit (%d)",
    178                m_numStreams, MAX_STREAM_NUM_IN_BUNDLE);
    179         return BAD_VALUE;
    180     }
    181     QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
    182                                                m_handle,
    183                                                m_camOps,
    184                                                &mPaddingInfo,
    185                                                this);
    186     if (pStream == NULL) {
    187         LOGE("No mem for Stream");
    188         return NO_MEMORY;
    189     }
    190     LOGD("batch size is %d", batchSize);
    191 
    192     rc = pStream->init(streamType, streamFormat, streamDim, streamRotation,
    193             NULL, minStreamBufNum, postprocessMask, isType, batchSize,
    194             streamCbRoutine, this);
    195     if (rc == 0) {
    196         mStreams[m_numStreams] = pStream;
    197         m_numStreams++;
    198     } else {
    199         delete pStream;
    200     }
    201     return rc;
    202 }
    203 
    204 /*===========================================================================
    205  * FUNCTION   : start
    206  *
    207  * DESCRIPTION: start channel, which will start all streams belong to this channel
    208  *
    209  * PARAMETERS :
    210  *
    211  * RETURN     : int32_t type of status
    212  *              NO_ERROR  -- success
    213  *              none-zero failure code
    214  *==========================================================================*/
    215 int32_t QCamera3Channel::start()
    216 {
    217     ATRACE_CALL();
    218     int32_t rc = NO_ERROR;
    219 
    220     if (m_numStreams > 1) {
    221         LOGW("bundle not supported");
    222     } else if (m_numStreams == 0) {
    223         return NO_INIT;
    224     }
    225 
    226     if(m_bIsActive) {
    227         LOGW("Attempt to start active channel");
    228         return rc;
    229     }
    230 
    231     for (uint32_t i = 0; i < m_numStreams; i++) {
    232         if (mStreams[i] != NULL) {
    233             mStreams[i]->start();
    234         }
    235     }
    236 
    237     m_bIsActive = true;
    238 
    239     return rc;
    240 }
    241 
    242 /*===========================================================================
    243  * FUNCTION   : stop
    244  *
    245  * DESCRIPTION: stop a channel, which will stop all streams belong to this channel
    246  *
    247  * PARAMETERS : none
    248  *
    249  * RETURN     : int32_t type of status
    250  *              NO_ERROR  -- success
    251  *              none-zero failure code
    252  *==========================================================================*/
    253 int32_t QCamera3Channel::stop()
    254 {
    255     ATRACE_CALL();
    256     int32_t rc = NO_ERROR;
    257     if(!m_bIsActive) {
    258         LOGE("Attempt to stop inactive channel");
    259         return rc;
    260     }
    261 
    262     for (uint32_t i = 0; i < m_numStreams; i++) {
    263         if (mStreams[i] != NULL) {
    264             mStreams[i]->stop();
    265         }
    266     }
    267 
    268     m_bIsActive = false;
    269     return rc;
    270 }
    271 
    272 /*===========================================================================
    273  * FUNCTION   : setBatchSize
    274  *
    275  * DESCRIPTION: Set batch size for the channel. This is a dummy implementation
    276  *              for the base class
    277  *
    278  * PARAMETERS :
    279  *   @batchSize  : Number of image buffers in a batch
    280  *
    281  * RETURN     : int32_t type of status
    282  *              NO_ERROR  -- success always
    283  *              none-zero failure code
    284  *==========================================================================*/
    285 int32_t QCamera3Channel::setBatchSize(uint32_t batchSize)
    286 {
    287     LOGD("Dummy method. batchSize: %d unused ", batchSize);
    288     return NO_ERROR;
    289 }
    290 
    291 /*===========================================================================
    292  * FUNCTION   : queueBatchBuf
    293  *
    294  * DESCRIPTION: This is a dummy implementation for the base class
    295  *
    296  * PARAMETERS :
    297  *
    298  * RETURN     : int32_t type of status
    299  *              NO_ERROR  -- success always
    300  *              none-zero failure code
    301  *==========================================================================*/
    302 int32_t QCamera3Channel::queueBatchBuf()
    303 {
    304     LOGD("Dummy method. Unused ");
    305     return NO_ERROR;
    306 }
    307 
    308 /*===========================================================================
    309  * FUNCTION   : setPerFrameMapUnmap
    310  *
    311  * DESCRIPTION: Sets internal enable flag
    312  *
    313  * PARAMETERS :
    314  *  @enable : Bool value for the enable flag
    315  *
    316  * RETURN     : int32_t type of status
    317  *              NO_ERROR  -- success always
    318  *              none-zero failure code
    319  *==========================================================================*/
    320 int32_t QCamera3Channel::setPerFrameMapUnmap(bool enable)
    321 {
    322     mPerFrameMapUnmapEnable = enable;
    323     return NO_ERROR;
    324 }
    325 
    326 /*===========================================================================
    327  * FUNCTION   : flush
    328  *
    329  * DESCRIPTION: flush a channel
    330  *
    331  * PARAMETERS : none
    332  *
    333  * RETURN     : int32_t type of status
    334  *              NO_ERROR  -- success
    335  *              none-zero failure code
    336  *==========================================================================*/
    337 int32_t QCamera3Channel::flush()
    338 {
    339     ATRACE_CALL();
    340     return NO_ERROR;
    341 }
    342 
    343 /*===========================================================================
    344  * FUNCTION   : bufDone
    345  *
    346  * DESCRIPTION: return a stream buf back to kernel
    347  *
    348  * PARAMETERS :
    349  *   @recvd_frame  : stream buf frame to be returned
    350  *
    351  * RETURN     : int32_t type of status
    352  *              NO_ERROR  -- success
    353  *              none-zero failure code
    354  *==========================================================================*/
    355 int32_t QCamera3Channel::bufDone(mm_camera_super_buf_t *recvd_frame)
    356 {
    357     int32_t rc = NO_ERROR;
    358     for (uint32_t i = 0; i < recvd_frame->num_bufs; i++) {
    359          if (recvd_frame->bufs[i] != NULL) {
    360              for (uint32_t j = 0; j < m_numStreams; j++) {
    361                  if (mStreams[j] != NULL &&
    362                      mStreams[j]->getMyHandle() == recvd_frame->bufs[i]->stream_id) {
    363                      rc = mStreams[j]->bufDone(recvd_frame->bufs[i]->buf_idx);
    364                      break; // break loop j
    365                  }
    366              }
    367          }
    368     }
    369 
    370     return rc;
    371 }
    372 
    373 int32_t QCamera3Channel::setBundleInfo(const cam_bundle_config_t &bundleInfo)
    374 {
    375     int32_t rc = NO_ERROR;
    376     cam_stream_parm_buffer_t param;
    377     memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
    378     param.type = CAM_STREAM_PARAM_TYPE_SET_BUNDLE_INFO;
    379     param.bundleInfo = bundleInfo;
    380     rc = mStreams[0]->setParameter(param);
    381     if (rc != NO_ERROR) {
    382         LOGE("stream setParameter for set bundle failed");
    383     }
    384 
    385     return rc;
    386 }
    387 
    388 /*===========================================================================
    389  * FUNCTION   : getStreamTypeMask
    390  *
    391  * DESCRIPTION: Get bit mask of all stream types in this channel
    392  *
    393  * PARAMETERS : None
    394  *
    395  * RETURN     : Bit mask of all stream types in this channel
    396  *==========================================================================*/
    397 uint32_t QCamera3Channel::getStreamTypeMask()
    398 {
    399     uint32_t mask = 0;
    400     for (uint32_t i = 0; i < m_numStreams; i++) {
    401        mask |= (1U << mStreams[i]->getMyType());
    402     }
    403     return mask;
    404 }
    405 
    406 /*===========================================================================
    407  * FUNCTION   : getStreamID
    408  *
    409  * DESCRIPTION: Get StreamID of requested stream type
    410  *
    411  * PARAMETERS : streamMask
    412  *
    413  * RETURN     : Stream ID
    414  *==========================================================================*/
    415 uint32_t QCamera3Channel::getStreamID(uint32_t streamMask)
    416 {
    417     uint32_t streamID = 0;
    418     for (uint32_t i = 0; i < m_numStreams; i++) {
    419         if (streamMask == (uint32_t )(0x1 << mStreams[i]->getMyType())) {
    420             streamID = mStreams[i]->getMyServerID();
    421             break;
    422         }
    423     }
    424     return streamID;
    425 }
    426 
    427 /*===========================================================================
    428  * FUNCTION   : getStreamByHandle
    429  *
    430  * DESCRIPTION: return stream object by stream handle
    431  *
    432  * PARAMETERS :
    433  *   @streamHandle : stream handle
    434  *
    435  * RETURN     : stream object. NULL if not found
    436  *==========================================================================*/
    437 QCamera3Stream *QCamera3Channel::getStreamByHandle(uint32_t streamHandle)
    438 {
    439     for (uint32_t i = 0; i < m_numStreams; i++) {
    440         if (mStreams[i] != NULL && mStreams[i]->getMyHandle() == streamHandle) {
    441             return mStreams[i];
    442         }
    443     }
    444     return NULL;
    445 }
    446 
    447 /*===========================================================================
    448  * FUNCTION   : getStreamByIndex
    449  *
    450  * DESCRIPTION: return stream object by index
    451  *
    452  * PARAMETERS :
    453  *   @streamHandle : stream handle
    454  *
    455  * RETURN     : stream object. NULL if not found
    456  *==========================================================================*/
    457 QCamera3Stream *QCamera3Channel::getStreamByIndex(uint32_t index)
    458 {
    459     if (index < m_numStreams) {
    460         return mStreams[index];
    461     }
    462     return NULL;
    463 }
    464 
    465 /*===========================================================================
    466  * FUNCTION   : streamCbRoutine
    467  *
    468  * DESCRIPTION: callback routine for stream
    469  *
    470  * PARAMETERS :
    471  *   @streamHandle : stream handle
    472  *
    473  * RETURN     : stream object. NULL if not found
    474  *==========================================================================*/
    475 void QCamera3Channel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
    476                 QCamera3Stream *stream, void *userdata)
    477 {
    478     QCamera3Channel *channel = (QCamera3Channel *)userdata;
    479     if (channel == NULL) {
    480         LOGE("invalid channel pointer");
    481         return;
    482     }
    483     channel->streamCbRoutine(super_frame, stream);
    484 }
    485 
    486 /*===========================================================================
    487  * FUNCTION   : dumpYUV
    488  *
    489  * DESCRIPTION: function to dump the YUV data from ISP/pproc
    490  *
    491  * PARAMETERS :
    492  *   @frame   : frame to be dumped
    493  *   @dim     : dimension of the stream
    494  *   @offset  : offset of the data
    495  *   @name    : 1 if it is ISP output/pproc input, 2 if it is pproc output
    496  *
    497  * RETURN  :
    498  *==========================================================================*/
    499 void QCamera3Channel::dumpYUV(mm_camera_buf_def_t *frame, cam_dimension_t dim,
    500         cam_frame_len_offset_t offset, uint8_t dump_type)
    501 {
    502     char buf[FILENAME_MAX];
    503     memset(buf, 0, sizeof(buf));
    504     static int counter = 0;
    505     if (mYUVDump & dump_type) {
    506         mFrmNum = ((mYUVDump & 0xffff0000) >> 16);
    507         if (mFrmNum == 0) {
    508             mFrmNum = 10;
    509         }
    510         if (mFrmNum > 256) {
    511             mFrmNum = 256;
    512         }
    513         mSkipMode = ((mYUVDump & 0x0000ff00) >> 8);
    514         if (mSkipMode == 0) {
    515             mSkipMode = 1;
    516         }
    517         if (mDumpSkipCnt == 0) {
    518             mDumpSkipCnt = 1;
    519         }
    520         if (mDumpSkipCnt % mSkipMode == 0) {
    521             if (mDumpFrmCnt <= mFrmNum) {
    522                 /* Note that the image dimension will be the unrotated stream dimension.
    523                 * If you feel that the image would have been rotated during reprocess
    524                 * then swap the dimensions while opening the file
    525                 * */
    526                 switch (dump_type) {
    527                     case QCAMERA_DUMP_FRM_PREVIEW:
    528                         snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"p_%d_%d_%dx%d.yuv",
    529                             counter, frame->frame_idx, dim.width, dim.height);
    530                     break;
    531                     case QCAMERA_DUMP_FRM_VIDEO:
    532                         snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"v_%d_%d_%dx%d.yuv",
    533                             counter, frame->frame_idx, dim.width, dim.height);
    534                     break;
    535                     case QCAMERA_DUMP_FRM_SNAPSHOT:
    536                         snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"s_%d_%d_%dx%d.yuv",
    537                             counter, frame->frame_idx, dim.width, dim.height);
    538                     break;
    539                     case QCAMERA_DUMP_FRM_INPUT_REPROCESS:
    540                         snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"ir_%d_%d_%dx%d.yuv",
    541                             counter, frame->frame_idx, dim.width, dim.height);
    542                     break;
    543                     case QCAMERA_DUMP_FRM_CALLBACK:
    544                         snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"c_%d_%d_%dx%d.yuv",
    545                             counter, frame->frame_idx, dim.width, dim.height);
    546                     break;
    547                     default :
    548                         LOGE("dumping not enabled for stream type %d",dump_type);
    549                     break;
    550                 }
    551                 counter++;
    552                 int file_fd = open(buf, O_RDWR | O_CREAT, 0777);
    553                 ssize_t written_len = 0;
    554                 if (file_fd >= 0) {
    555                     void *data = NULL;
    556                     fchmod(file_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
    557                     for (uint32_t i = 0; i < offset.num_planes; i++) {
    558                         uint32_t index = offset.mp[i].offset;
    559                         if (i > 0) {
    560                             index += offset.mp[i-1].len;
    561                         }
    562                         for (int j = 0; j < offset.mp[i].height; j++) {
    563                             data = (void *)((uint8_t *)frame->buffer + index);
    564                             written_len += write(file_fd, data,
    565                                     (size_t)offset.mp[i].width);
    566                             index += (uint32_t)offset.mp[i].stride;
    567                         }
    568                     }
    569                     LOGH("written number of bytes %ld\n", written_len);
    570                     mDumpFrmCnt++;
    571                     frame->cache_flags |= CPU_HAS_READ;
    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         //Make sure cache coherence because extra processing is done
   2199         mMemory.cleanCache(super_frame->bufs[0]->buf_idx);
   2200     }
   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           frame->cache_flags |= CPU_HAS_READ;
   2227           close(file_fd);
   2228        } else {
   2229           LOGE("failed to open file to dump image");
   2230        }
   2231    } else {
   2232        LOGE("Could not find stream");
   2233    }
   2234 
   2235 }
   2236 
   2237 void QCamera3RawChannel::convertLegacyToRaw16(mm_camera_buf_def_t *frame)
   2238 {
   2239     // Convert image buffer from Opaque raw format to RAW16 format
   2240     // 10bit Opaque raw is stored in the format of:
   2241     // 0000 - p5 - p4 - p3 - p2 - p1 - p0
   2242     // where p0 to p5 are 6 pixels (each is 10bit)_and most significant
   2243     // 4 bits are 0s. Each 64bit word contains 6 pixels.
   2244 
   2245   QCamera3Stream *stream = getStreamByIndex(0);
   2246   if (stream != NULL) {
   2247       cam_dimension_t dim;
   2248       memset(&dim, 0, sizeof(dim));
   2249       stream->getFrameDimension(dim);
   2250 
   2251       cam_frame_len_offset_t offset;
   2252       memset(&offset, 0, sizeof(cam_frame_len_offset_t));
   2253       stream->getFrameOffset(offset);
   2254 
   2255       uint32_t raw16_stride = ((uint32_t)dim.width + 15U) & ~15U;
   2256       uint16_t* raw16_buffer = (uint16_t *)frame->buffer;
   2257 
   2258       // In-place format conversion.
   2259       // Raw16 format always occupy more memory than opaque raw10.
   2260       // Convert to Raw16 by iterating through all pixels from bottom-right
   2261       // to top-left of the image.
   2262       // One special notes:
   2263       // 1. Cross-platform raw16's stride is 16 pixels.
   2264       // 2. Opaque raw10's stride is 6 pixels, and aligned to 16 bytes.
   2265       for (int32_t ys = dim.height - 1; ys >= 0; ys--) {
   2266           uint32_t y = (uint32_t)ys;
   2267           uint64_t* row_start = (uint64_t *)frame->buffer +
   2268                   y * (uint32_t)offset.mp[0].stride_in_bytes / 8;
   2269           for (int32_t xs = dim.width - 1; xs >= 0; xs--) {
   2270               uint32_t x = (uint32_t)xs;
   2271               uint16_t raw16_pixel = 0x3FF & (row_start[x/6] >> (10*(x%6)));
   2272               raw16_buffer[y*raw16_stride+x] = raw16_pixel;
   2273           }
   2274       }
   2275   } else {
   2276       LOGE("Could not find stream");
   2277   }
   2278 
   2279 }
   2280 
   2281 void QCamera3RawChannel::convertMipiToRaw16(mm_camera_buf_def_t *frame)
   2282 {
   2283     // Convert image buffer from mipi10 raw format to RAW16 format
   2284     // mipi10 opaque raw is stored in the format of:
   2285     // P3(1:0) P2(1:0) P1(1:0) P0(1:0) P3(9:2) P2(9:2) P1(9:2) P0(9:2)
   2286     // 4 pixels occupy 5 bytes, no padding needed
   2287 
   2288     QCamera3Stream *stream = getStreamByIndex(0);
   2289     if (stream != NULL) {
   2290         cam_dimension_t dim;
   2291         memset(&dim, 0, sizeof(dim));
   2292         stream->getFrameDimension(dim);
   2293 
   2294         cam_frame_len_offset_t offset;
   2295         memset(&offset, 0, sizeof(cam_frame_len_offset_t));
   2296         stream->getFrameOffset(offset);
   2297 
   2298         uint32_t raw16_stride = ((uint32_t)dim.width + 15U) & ~15U;
   2299         uint16_t* raw16_buffer = (uint16_t *)frame->buffer;
   2300         uint8_t first_quintuple[5];
   2301         memcpy(first_quintuple, raw16_buffer, sizeof(first_quintuple));
   2302 
   2303         // In-place format conversion.
   2304         // Raw16 format always occupy more memory than opaque raw10.
   2305         // Convert to Raw16 by iterating through all pixels from bottom-right
   2306         // to top-left of the image.
   2307         // One special notes:
   2308         // 1. Cross-platform raw16's stride is 16 pixels.
   2309         // 2. mipi raw10's stride is 4 pixels, and aligned to 16 bytes.
   2310         for (int32_t ys = dim.height - 1; ys >= 0; ys--) {
   2311             uint32_t y = (uint32_t)ys;
   2312             uint8_t* row_start = (uint8_t *)frame->buffer +
   2313                     y * (uint32_t)offset.mp[0].stride_in_bytes;
   2314             for (int32_t xs = dim.width - 1; xs >= 0; xs--) {
   2315                 uint32_t x = (uint32_t)xs;
   2316                 uint8_t upper_8bit = row_start[5*(x/4)+x%4];
   2317                 uint8_t lower_2bit = ((row_start[5*(x/4)+4] >> ((x%4) << 1)) & 0x3);
   2318                 uint16_t raw16_pixel =
   2319                         (uint16_t)(((uint16_t)upper_8bit)<<2 |
   2320                         (uint16_t)lower_2bit);
   2321                 raw16_buffer[y*raw16_stride+x] = raw16_pixel;
   2322             }
   2323         }
   2324 
   2325         // Re-convert the first 2 pixels of the buffer because the loop above messes
   2326         // them up by reading the first quintuple while modifying it.
   2327         raw16_buffer[0] = ((uint16_t)first_quintuple[0]<<2) | (first_quintuple[4] & 0x3);
   2328         raw16_buffer[1] = ((uint16_t)first_quintuple[1]<<2) | ((first_quintuple[4] >> 2) & 0x3);
   2329 
   2330     } else {
   2331         LOGE("Could not find stream");
   2332     }
   2333 
   2334 }
   2335 
   2336 /*===========================================================================
   2337  * FUNCTION   : getReprocessType
   2338  *
   2339  * DESCRIPTION: get the type of reprocess output supported by this channel
   2340  *
   2341  * PARAMETERS : NONE
   2342  *
   2343  * RETURN     : reprocess_type_t : type of reprocess
   2344  *==========================================================================*/
   2345 reprocess_type_t QCamera3RawChannel::getReprocessType()
   2346 {
   2347     return REPROCESS_TYPE_RAW;
   2348 }
   2349 
   2350 
   2351 /*************************************************************************************/
   2352 // RAW Dump Channel related functions
   2353 
   2354 /*===========================================================================
   2355  * FUNCTION   : QCamera3RawDumpChannel
   2356  *
   2357  * DESCRIPTION: Constructor for RawDumpChannel
   2358  *
   2359  * PARAMETERS :
   2360  *   @cam_handle    : Handle for Camera
   2361  *   @cam_ops       : Function pointer table
   2362  *   @rawDumpSize   : Dimensions for the Raw stream
   2363  *   @paddinginfo   : Padding information for stream
   2364  *   @userData      : Cookie for parent
   2365  *   @pp mask       : PP feature mask for this stream
   2366  *   @numBuffers    : number of max dequeued buffers
   2367  *
   2368  * RETURN           : NA
   2369  *==========================================================================*/
   2370 QCamera3RawDumpChannel::QCamera3RawDumpChannel(uint32_t cam_handle,
   2371                     uint32_t channel_handle,
   2372                     mm_camera_ops_t *cam_ops,
   2373                     cam_dimension_t rawDumpSize,
   2374                     cam_padding_info_t *paddingInfo,
   2375                     void *userData,
   2376                     cam_feature_mask_t postprocess_mask, uint32_t numBuffers) :
   2377                         QCamera3Channel(cam_handle, channel_handle, cam_ops, NULL,
   2378                                 NULL, paddingInfo, postprocess_mask,
   2379                                 userData, numBuffers),
   2380                         mDim(rawDumpSize),
   2381                         mMemory(NULL)
   2382 {
   2383     char prop[PROPERTY_VALUE_MAX];
   2384     property_get("persist.camera.raw.dump", prop, "0");
   2385     mRawDump = atoi(prop);
   2386 }
   2387 
   2388 /*===========================================================================
   2389  * FUNCTION   : QCamera3RawDumpChannel
   2390  *
   2391  * DESCRIPTION: Destructor for RawDumpChannel
   2392  *
   2393  * PARAMETERS :
   2394  *
   2395  * RETURN           : NA
   2396  *==========================================================================*/
   2397 
   2398 QCamera3RawDumpChannel::~QCamera3RawDumpChannel()
   2399 {
   2400     destroy();
   2401 }
   2402 
   2403 /*===========================================================================
   2404  * FUNCTION   : dumpRawSnapshot
   2405  *
   2406  * DESCRIPTION: Helper function to dump Raw frames
   2407  *
   2408  * PARAMETERS :
   2409  *  @frame      : stream buf frame to be dumped
   2410  *
   2411  *  RETURN      : NA
   2412  *==========================================================================*/
   2413 void QCamera3RawDumpChannel::dumpRawSnapshot(mm_camera_buf_def_t *frame)
   2414 {
   2415     QCamera3Stream *stream = getStreamByIndex(0);
   2416     if (stream != NULL) {
   2417         char buf[FILENAME_MAX];
   2418         struct timeval tv;
   2419         struct tm timeinfo_data;
   2420         struct tm *timeinfo;
   2421 
   2422         cam_dimension_t dim;
   2423         memset(&dim, 0, sizeof(dim));
   2424         stream->getFrameDimension(dim);
   2425 
   2426         cam_frame_len_offset_t offset;
   2427         memset(&offset, 0, sizeof(cam_frame_len_offset_t));
   2428         stream->getFrameOffset(offset);
   2429 
   2430         gettimeofday(&tv, NULL);
   2431         timeinfo = localtime_r(&tv.tv_sec, &timeinfo_data);
   2432 
   2433         if (NULL != timeinfo) {
   2434             memset(buf, 0, sizeof(buf));
   2435             /* Consistent naming for Jpeg+meta+raw: Raw name */
   2436             snprintf(buf, sizeof(buf),
   2437                     QCAMERA_DUMP_FRM_LOCATION
   2438                     "IMG_%04d%02d%02d_%02d%02d%02d_%dx%d.raw",
   2439                     timeinfo->tm_year + 1900, timeinfo->tm_mon + 1,
   2440                     timeinfo->tm_mday, timeinfo->tm_hour,
   2441                     timeinfo->tm_min, timeinfo->tm_sec,
   2442                     dim.width, dim.height);
   2443             /* Consistent naming for Jpeg+meta+raw: Raw name end*/
   2444             int file_fd = open(buf, O_RDWR| O_CREAT, 0777);
   2445             if (file_fd >= 0) {
   2446                 ssize_t written_len =
   2447                         write(file_fd, frame->buffer, offset.frame_len);
   2448                 LOGD("written number of bytes %zd", written_len);
   2449                 frame->cache_flags |= CPU_HAS_READ;
   2450                 close(file_fd);
   2451             } else {
   2452                 LOGE("failed to open file to dump image");
   2453             }
   2454         } else {
   2455             LOGE("localtime_r() error");
   2456         }
   2457     } else {
   2458         LOGE("Could not find stream");
   2459     }
   2460 
   2461 }
   2462 
   2463 /*===========================================================================
   2464  * FUNCTION   : streamCbRoutine
   2465  *
   2466  * DESCRIPTION: Callback routine invoked for each frame generated for
   2467  *              Rawdump channel
   2468  *
   2469  * PARAMETERS :
   2470  *   @super_frame  : stream buf frame generated
   2471  *   @stream       : Underlying Stream object cookie
   2472  *
   2473  * RETURN          : NA
   2474  *==========================================================================*/
   2475 void QCamera3RawDumpChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
   2476                                                 __unused QCamera3Stream *stream)
   2477 {
   2478     LOGD("E");
   2479     if (super_frame == NULL || super_frame->num_bufs != 1) {
   2480         LOGE("super_frame is not valid");
   2481         return;
   2482     }
   2483 
   2484     if (mRawDump)
   2485         dumpRawSnapshot(super_frame->bufs[0]);
   2486 
   2487     bufDone(super_frame);
   2488     free(super_frame);
   2489 }
   2490 
   2491 /*===========================================================================
   2492  * FUNCTION   : getStreamBufs
   2493  *
   2494  * DESCRIPTION: Callback function provided to interface to get buffers.
   2495  *
   2496  * PARAMETERS :
   2497  *   @len       : Length of each buffer to be allocated
   2498  *
   2499  * RETURN     : NULL on buffer allocation failure
   2500  *              QCamera3StreamMem object on sucess
   2501  *==========================================================================*/
   2502 QCamera3StreamMem* QCamera3RawDumpChannel::getStreamBufs(uint32_t len)
   2503 {
   2504     int rc;
   2505     mMemory = new QCamera3StreamMem(mNumBuffers);
   2506 
   2507     if (!mMemory) {
   2508         LOGE("unable to create heap memory");
   2509         return NULL;
   2510     }
   2511     rc = mMemory->allocateAll((size_t)len);
   2512     if (rc < 0) {
   2513         LOGE("unable to allocate heap memory");
   2514         delete mMemory;
   2515         mMemory = NULL;
   2516         return NULL;
   2517     }
   2518     return mMemory;
   2519 }
   2520 
   2521 /*===========================================================================
   2522  * FUNCTION   : putStreamBufs
   2523  *
   2524  * DESCRIPTION: Callback function provided to interface to return buffers.
   2525  *              Although no handles are actually returned, implicitl assumption
   2526  *              that interface will no longer use buffers and channel can
   2527  *              deallocated if necessary.
   2528  *
   2529  * PARAMETERS : NA
   2530  *
   2531  * RETURN     : NA
   2532  *==========================================================================*/
   2533 void QCamera3RawDumpChannel::putStreamBufs()
   2534 {
   2535     mMemory->deallocate();
   2536     delete mMemory;
   2537     mMemory = NULL;
   2538 }
   2539 
   2540 /*===========================================================================
   2541  * FUNCTION : request
   2542  *
   2543  * DESCRIPTION: Request function used as trigger
   2544  *
   2545  * PARAMETERS :
   2546  * @recvd_frame : buffer- this will be NULL since this is internal channel
   2547  * @frameNumber : Undefined again since this is internal stream
   2548  *
   2549  * RETURN     : int32_t type of status
   2550  *              NO_ERROR  -- success
   2551  *              none-zero failure code
   2552  *==========================================================================*/
   2553 int32_t QCamera3RawDumpChannel::request(buffer_handle_t * /*buffer*/,
   2554                                                 uint32_t /*frameNumber*/,
   2555                                                 int & /*indexUsed*/)
   2556 {
   2557     if (!m_bIsActive) {
   2558         return QCamera3Channel::start();
   2559     }
   2560     else
   2561         return 0;
   2562 }
   2563 
   2564 /*===========================================================================
   2565  * FUNCTION : intialize
   2566  *
   2567  * DESCRIPTION: Initializes channel params and creates underlying stream
   2568  *
   2569  * PARAMETERS :
   2570  *    @isType : type of image stabilization required on this stream
   2571  *
   2572  * RETURN     : int32_t type of status
   2573  *              NO_ERROR  -- success
   2574  *              none-zero failure code
   2575  *==========================================================================*/
   2576 int32_t QCamera3RawDumpChannel::initialize(cam_is_type_t isType)
   2577 {
   2578     int32_t rc;
   2579 
   2580     mIsType = isType;
   2581     rc = QCamera3Channel::addStream(CAM_STREAM_TYPE_RAW,
   2582         CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG, mDim, ROTATE_0, (uint8_t)mNumBuffers,
   2583         mPostProcMask, mIsType);
   2584     if (rc < 0) {
   2585         LOGE("addStream failed");
   2586     }
   2587     return rc;
   2588 }
   2589 /*************************************************************************************/
   2590 
   2591 /* QCamera3YUVChannel methods */
   2592 
   2593 /*===========================================================================
   2594  * FUNCTION   : QCamera3YUVChannel
   2595  *
   2596  * DESCRIPTION: constructor of QCamera3YUVChannel
   2597  *
   2598  * PARAMETERS :
   2599  *   @cam_handle : camera handle
   2600  *   @cam_ops    : ptr to camera ops table
   2601  *   @cb_routine : callback routine to frame aggregator
   2602  *   @paddingInfo : padding information for the stream
   2603  *   @stream     : camera3_stream_t structure
   2604  *   @stream_type: Channel stream type
   2605  *   @postprocess_mask: the postprocess mask for streams of this channel
   2606  *   @metadataChannel: handle to the metadataChannel
   2607  * RETURN     : none
   2608  *==========================================================================*/
   2609 QCamera3YUVChannel::QCamera3YUVChannel(uint32_t cam_handle,
   2610         uint32_t channel_handle,
   2611         mm_camera_ops_t *cam_ops,
   2612         channel_cb_routine cb_routine,
   2613         channel_cb_buffer_err cb_buf_err,
   2614         cam_padding_info_t *paddingInfo,
   2615         void *userData,
   2616         camera3_stream_t *stream,
   2617         cam_stream_type_t stream_type,
   2618         cam_feature_mask_t postprocess_mask,
   2619         QCamera3Channel *metadataChannel) :
   2620             QCamera3ProcessingChannel(cam_handle, channel_handle, cam_ops,
   2621                     cb_routine, cb_buf_err, paddingInfo, userData, stream, stream_type,
   2622                     postprocess_mask, metadataChannel)
   2623 {
   2624 
   2625     mBypass = (postprocess_mask == CAM_QCOM_FEATURE_NONE);
   2626     mFrameLen = 0;
   2627     mEdgeMode.edge_mode = CAM_EDGE_MODE_OFF;
   2628     mEdgeMode.sharpness = 0;
   2629     mNoiseRedMode = CAM_NOISE_REDUCTION_MODE_OFF;
   2630     memset(&mCropRegion, 0, sizeof(mCropRegion));
   2631 }
   2632 
   2633 /*===========================================================================
   2634  * FUNCTION   : ~QCamera3YUVChannel
   2635  *
   2636  * DESCRIPTION: destructor of QCamera3YUVChannel
   2637  *
   2638  * PARAMETERS : none
   2639  *
   2640  *
   2641  * RETURN     : none
   2642  *==========================================================================*/
   2643 QCamera3YUVChannel::~QCamera3YUVChannel()
   2644 {
   2645    // Deallocation of heap buffers allocated in mMemory is freed
   2646    // automatically by its destructor
   2647 }
   2648 
   2649 /*===========================================================================
   2650  * FUNCTION   : initialize
   2651  *
   2652  * DESCRIPTION: Initialize and add camera channel & stream
   2653  *
   2654  * PARAMETERS :
   2655  * @isType    : the image stabilization type
   2656  *
   2657  * RETURN     : int32_t type of status
   2658  *              NO_ERROR  -- success
   2659  *              none-zero failure code
   2660  *==========================================================================*/
   2661 int32_t QCamera3YUVChannel::initialize(cam_is_type_t isType)
   2662 {
   2663     ATRACE_CALL();
   2664     int32_t rc = NO_ERROR;
   2665     cam_dimension_t streamDim;
   2666 
   2667     if (NULL == mCamera3Stream) {
   2668         LOGE("Camera stream uninitialized");
   2669         return NO_INIT;
   2670     }
   2671 
   2672     if (1 <= m_numStreams) {
   2673         // Only one stream per channel supported in v3 Hal
   2674         return NO_ERROR;
   2675     }
   2676 
   2677     mIsType  = isType;
   2678     mStreamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_CALLBACK,
   2679             mCamera3Stream->width, mCamera3Stream->height);
   2680     streamDim.width = mCamera3Stream->width;
   2681     streamDim.height = mCamera3Stream->height;
   2682 
   2683     rc = QCamera3Channel::addStream(mStreamType,
   2684             mStreamFormat,
   2685             streamDim,
   2686             ROTATE_0,
   2687             mNumBufs,
   2688             mPostProcMask,
   2689             mIsType);
   2690     if (rc < 0) {
   2691         LOGE("addStream failed");
   2692         return rc;
   2693     }
   2694 
   2695     cam_stream_buf_plane_info_t buf_planes;
   2696     cam_padding_info_t paddingInfo = mPaddingInfo;
   2697 
   2698     memset(&buf_planes, 0, sizeof(buf_planes));
   2699     //to ensure a big enough buffer size set the height and width
   2700     //padding to max(height padding, width padding)
   2701     paddingInfo.width_padding = MAX(paddingInfo.width_padding, paddingInfo.height_padding);
   2702     paddingInfo.height_padding = paddingInfo.width_padding;
   2703 
   2704     rc = mm_stream_calc_offset_snapshot(mStreamFormat, &streamDim, &paddingInfo,
   2705             &buf_planes);
   2706     if (rc < 0) {
   2707         LOGE("mm_stream_calc_offset_preview failed");
   2708         return rc;
   2709     }
   2710 
   2711     mFrameLen = buf_planes.plane_info.frame_len;
   2712 
   2713     if (NO_ERROR != rc) {
   2714         LOGE("Initialize failed, rc = %d", rc);
   2715         return rc;
   2716     }
   2717 
   2718     /* initialize offline meta memory for input reprocess */
   2719     rc = QCamera3ProcessingChannel::initialize(isType);
   2720     if (NO_ERROR != rc) {
   2721         LOGE("Processing Channel initialize failed, rc = %d",
   2722                  rc);
   2723     }
   2724 
   2725     return rc;
   2726 }
   2727 
   2728 /*===========================================================================
   2729  * FUNCTION   : request
   2730  *
   2731  * DESCRIPTION: entry function for a request on a YUV stream. This function
   2732  *              has the logic to service a request based on its type
   2733  *
   2734  * PARAMETERS :
   2735  * @buffer          : pointer to the output buffer
   2736  * @frameNumber     : frame number of the request
   2737  * @pInputBuffer    : pointer to input buffer if an input request
   2738  * @metadata        : parameters associated with the request
   2739  *
   2740  * RETURN     : 0 on a success start of capture
   2741  *              -EINVAL on invalid input
   2742  *              -ENODEV on serious error
   2743  *==========================================================================*/
   2744 int32_t QCamera3YUVChannel::request(buffer_handle_t *buffer,
   2745         uint32_t frameNumber,
   2746         camera3_stream_buffer_t* pInputBuffer,
   2747         metadata_buffer_t* metadata, bool &needMetadata,
   2748         int &indexUsed)
   2749 {
   2750     int32_t rc = NO_ERROR;
   2751     Mutex::Autolock lock(mOfflinePpLock);
   2752 
   2753     LOGD("pInputBuffer is %p frame number %d", pInputBuffer, frameNumber);
   2754     if (NULL == buffer || NULL == metadata) {
   2755         LOGE("Invalid buffer/metadata in channel request");
   2756         return BAD_VALUE;
   2757     }
   2758 
   2759     PpInfo ppInfo;
   2760     memset(&ppInfo, 0, sizeof(ppInfo));
   2761     ppInfo.frameNumber = frameNumber;
   2762     ppInfo.offlinePpFlag = false;
   2763     if (mBypass && !pInputBuffer ) {
   2764         ppInfo.offlinePpFlag = needsFramePostprocessing(metadata);
   2765         ppInfo.output = buffer;
   2766         mOfflinePpInfoList.push_back(ppInfo);
   2767     }
   2768 
   2769     LOGD("offlinePpFlag is %d", ppInfo.offlinePpFlag);
   2770     needMetadata = ppInfo.offlinePpFlag;
   2771     if (!ppInfo.offlinePpFlag) {
   2772         // regular request
   2773         return QCamera3ProcessingChannel::request(buffer, frameNumber,
   2774                 pInputBuffer, metadata, indexUsed);
   2775     } else {
   2776         if(!m_bIsActive) {
   2777             rc = start();
   2778             if (NO_ERROR != rc)
   2779                 return rc;
   2780         } else {
   2781             LOGD("Request on an existing stream");
   2782         }
   2783 
   2784         //we need to send this frame through the CPP
   2785         //Allocate heap memory, then buf done on the buffer
   2786         uint32_t bufIdx;
   2787         if (mFreeHeapBufferList.empty()) {
   2788             rc = mMemory.allocateOne(mFrameLen);
   2789             if (rc < 0) {
   2790                 LOGE("Failed allocating heap buffer. Fatal");
   2791                 return BAD_VALUE;
   2792             } else {
   2793                 bufIdx = (uint32_t)rc;
   2794             }
   2795         } else {
   2796             bufIdx = *(mFreeHeapBufferList.begin());
   2797             mFreeHeapBufferList.erase(mFreeHeapBufferList.begin());
   2798         }
   2799 
   2800         /* Configure and start postproc if necessary */
   2801         reprocess_config_t reproc_cfg;
   2802         cam_dimension_t dim;
   2803         memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
   2804         memset(&dim, 0, sizeof(dim));
   2805         mStreams[0]->getFrameDimension(dim);
   2806         setReprocConfig(reproc_cfg, NULL, metadata, mStreamFormat, dim);
   2807 
   2808         // Start postprocessor without input buffer
   2809         startPostProc(reproc_cfg);
   2810 
   2811         LOGD("erasing %d", bufIdx);
   2812 
   2813         mMemory.markFrameNumber(bufIdx, frameNumber);
   2814         indexUsed = bufIdx;
   2815         mStreams[0]->bufDone(bufIdx);
   2816 
   2817     }
   2818     return rc;
   2819 }
   2820 
   2821 /*===========================================================================
   2822  * FUNCTION   : streamCbRoutine
   2823  *
   2824  * DESCRIPTION:
   2825  *
   2826  * PARAMETERS :
   2827  * @super_frame : the super frame with filled buffer
   2828  * @stream      : stream on which the buffer was requested and filled
   2829  *
   2830  * RETURN     : none
   2831  *==========================================================================*/
   2832 void QCamera3YUVChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
   2833         QCamera3Stream *stream)
   2834 {
   2835     ATRACE_CALL();
   2836     uint8_t frameIndex;
   2837     int32_t resultFrameNumber;
   2838 
   2839     if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
   2840         LOGE("Error with the stream callback");
   2841         return;
   2842     }
   2843 
   2844     frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
   2845     if(frameIndex >= mNumBufs) {
   2846          LOGE("Error, Invalid index for buffer");
   2847          stream->bufDone(frameIndex);
   2848          return;
   2849     }
   2850 
   2851     if (mBypass) {
   2852         {
   2853             List<PpInfo>::iterator ppInfo;
   2854 
   2855             Mutex::Autolock lock(mOfflinePpLock);
   2856             resultFrameNumber = mMemory.getFrameNumber(frameIndex);
   2857             for (ppInfo = mOfflinePpInfoList.begin();
   2858                     ppInfo != mOfflinePpInfoList.end(); ppInfo++) {
   2859                 if (ppInfo->frameNumber == (uint32_t)resultFrameNumber) {
   2860                     break;
   2861                 }
   2862             }
   2863             LOGD("frame index %d, frame number %d", frameIndex,
   2864                     resultFrameNumber);
   2865             //check the reprocessing required flag against the frame number
   2866             if (ppInfo == mOfflinePpInfoList.end()) {
   2867                 LOGE("Error, request for frame number is a reprocess.");
   2868                 stream->bufDone(frameIndex);
   2869                 return;
   2870             }
   2871 
   2872             if (ppInfo->offlinePpFlag) {
   2873                 mm_camera_super_buf_t *frame =
   2874                         (mm_camera_super_buf_t *)malloc(sizeof(
   2875                                 mm_camera_super_buf_t));
   2876                 if (frame == NULL) {
   2877                     LOGE("Error allocating memory to save received_frame structure.");
   2878                     if(stream) {
   2879                         stream->bufDone(frameIndex);
   2880                     }
   2881                     return;
   2882                 }
   2883 
   2884                 *frame = *super_frame;
   2885                 m_postprocessor.processData(frame, ppInfo->output,
   2886                         resultFrameNumber);
   2887                 free(super_frame);
   2888                 return;
   2889             } else {
   2890                 if (ppInfo != mOfflinePpInfoList.begin()) {
   2891                     // There is pending reprocess buffer, cache current buffer
   2892                     if (ppInfo->callback_buffer != NULL) {
   2893                         LOGE("Fatal: cached callback_buffer is already present");
   2894                     }
   2895                     ppInfo->callback_buffer = super_frame;
   2896                     return;
   2897                 } else {
   2898                     mOfflinePpInfoList.erase(ppInfo);
   2899                 }
   2900             }
   2901         }
   2902 
   2903         if (IS_BUFFER_ERROR(super_frame->bufs[0]->flags)) {
   2904             mChannelCbBufErr(this, resultFrameNumber,
   2905                             CAMERA3_BUFFER_STATUS_ERROR, mUserData);
   2906         }
   2907 
   2908     }
   2909 
   2910     QCamera3ProcessingChannel::streamCbRoutine(super_frame, stream);
   2911 
   2912     /* return any pending buffers that were received out of order earlier */
   2913     while((super_frame = getNextPendingCbBuffer())) {
   2914         QCamera3ProcessingChannel::streamCbRoutine(super_frame, stream);
   2915     }
   2916 
   2917     return;
   2918 }
   2919 
   2920 /*===========================================================================
   2921  * FUNCTION   : getNextPendingCbBuffer
   2922  *
   2923  * DESCRIPTION: Returns the callback_buffer from the first entry of
   2924  *              mOfflinePpInfoList
   2925  *
   2926  * PARAMETERS : none
   2927  *
   2928  * RETURN     : callback_buffer
   2929  *==========================================================================*/
   2930 mm_camera_super_buf_t* QCamera3YUVChannel::getNextPendingCbBuffer() {
   2931     mm_camera_super_buf_t* super_frame = NULL;
   2932     if (mOfflinePpInfoList.size()) {
   2933         if ((super_frame = mOfflinePpInfoList.begin()->callback_buffer)) {
   2934             mOfflinePpInfoList.erase(mOfflinePpInfoList.begin());
   2935         }
   2936     }
   2937     return super_frame;
   2938 }
   2939 
   2940 /*===========================================================================
   2941  * FUNCTION   : reprocessCbRoutine
   2942  *
   2943  * DESCRIPTION: callback function for the reprocessed frame. This frame now
   2944  *              should be returned to the framework. This same callback is
   2945  *              used during input reprocessing or offline postprocessing
   2946  *
   2947  * PARAMETERS :
   2948  * @resultBuffer      : buffer containing the reprocessed data
   2949  * @resultFrameNumber : frame number on which the buffer was requested
   2950  *
   2951  * RETURN     : NONE
   2952  *
   2953  *==========================================================================*/
   2954 void QCamera3YUVChannel::reprocessCbRoutine(buffer_handle_t *resultBuffer,
   2955         uint32_t resultFrameNumber)
   2956 {
   2957     LOGD("E: frame number %d", resultFrameNumber);
   2958     Vector<mm_camera_super_buf_t *> pendingCbs;
   2959 
   2960     /* release the input buffer and input metadata buffer if used */
   2961     if (0 > mMemory.getHeapBufferIndex(resultFrameNumber)) {
   2962         /* mOfflineMemory and mOfflineMetaMemory used only for input reprocessing */
   2963         int32_t rc = releaseOfflineMemory(resultFrameNumber);
   2964         if (NO_ERROR != rc) {
   2965             LOGE("Error releasing offline memory rc = %d", rc);
   2966         }
   2967         /* Since reprocessing is done, send the callback to release the input buffer */
   2968         if (mChannelCB) {
   2969             mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData);
   2970         }
   2971     }
   2972 
   2973     if (mBypass) {
   2974         int32_t rc = handleOfflinePpCallback(resultFrameNumber, pendingCbs);
   2975         if (rc != NO_ERROR) {
   2976             return;
   2977         }
   2978     }
   2979 
   2980     issueChannelCb(resultBuffer, resultFrameNumber);
   2981 
   2982     // Call all pending callbacks to return buffers
   2983     for (size_t i = 0; i < pendingCbs.size(); i++) {
   2984         QCamera3ProcessingChannel::streamCbRoutine(
   2985                 pendingCbs[i], mStreams[0]);
   2986     }
   2987 
   2988 }
   2989 
   2990 /*===========================================================================
   2991  * FUNCTION   : needsFramePostprocessing
   2992  *
   2993  * DESCRIPTION:
   2994  *
   2995  * PARAMETERS :
   2996  *
   2997  * RETURN     :
   2998  *  TRUE if frame needs to be postprocessed
   2999  *  FALSE is frame does not need to be postprocessed
   3000  *
   3001  *==========================================================================*/
   3002 bool QCamera3YUVChannel::needsFramePostprocessing(metadata_buffer_t *meta)
   3003 {
   3004     bool ppNeeded = false;
   3005 
   3006     //sharpness
   3007     IF_META_AVAILABLE(cam_edge_application_t, edgeMode,
   3008             CAM_INTF_META_EDGE_MODE, meta) {
   3009         mEdgeMode = *edgeMode;
   3010     }
   3011 
   3012     //wnr
   3013     IF_META_AVAILABLE(uint32_t, noiseRedMode,
   3014             CAM_INTF_META_NOISE_REDUCTION_MODE, meta) {
   3015         mNoiseRedMode = *noiseRedMode;
   3016     }
   3017 
   3018     //crop region
   3019     IF_META_AVAILABLE(cam_crop_region_t, scalerCropRegion,
   3020             CAM_INTF_META_SCALER_CROP_REGION, meta) {
   3021         mCropRegion = *scalerCropRegion;
   3022     }
   3023 
   3024     if ((CAM_EDGE_MODE_OFF != mEdgeMode.edge_mode) &&
   3025             (CAM_EDGE_MODE_ZERO_SHUTTER_LAG != mEdgeMode.edge_mode)) {
   3026         ppNeeded = true;
   3027     }
   3028     if ((CAM_NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG != mNoiseRedMode) &&
   3029             (CAM_NOISE_REDUCTION_MODE_OFF != mNoiseRedMode) &&
   3030             (CAM_NOISE_REDUCTION_MODE_MINIMAL != mNoiseRedMode)) {
   3031         ppNeeded = true;
   3032     }
   3033     if ((mCropRegion.width < (int32_t)mCamera3Stream->width) ||
   3034             (mCropRegion.height < (int32_t)mCamera3Stream->height)) {
   3035         ppNeeded = true;
   3036     }
   3037 
   3038     return ppNeeded;
   3039 }
   3040 
   3041 /*===========================================================================
   3042  * FUNCTION   : handleOfflinePpCallback
   3043  *
   3044  * DESCRIPTION: callback function for the reprocessed frame from offline
   3045  *              postprocessing.
   3046  *
   3047  * PARAMETERS :
   3048  * @resultFrameNumber : frame number on which the buffer was requested
   3049  * @pendingCbs        : pending buffers to be returned first
   3050  *
   3051  * RETURN     : int32_t type of status
   3052  *              NO_ERROR  -- success
   3053  *              none-zero failure code
   3054  *==========================================================================*/
   3055 int32_t QCamera3YUVChannel::handleOfflinePpCallback(uint32_t resultFrameNumber,
   3056             Vector<mm_camera_super_buf_t *>& pendingCbs)
   3057 {
   3058     Mutex::Autolock lock(mOfflinePpLock);
   3059     List<PpInfo>::iterator ppInfo;
   3060 
   3061     for (ppInfo = mOfflinePpInfoList.begin();
   3062             ppInfo != mOfflinePpInfoList.end(); ppInfo++) {
   3063         if (ppInfo->frameNumber == resultFrameNumber) {
   3064             break;
   3065         }
   3066     }
   3067 
   3068     if (ppInfo == mOfflinePpInfoList.end()) {
   3069         LOGI("Request of frame number %d is reprocessing",
   3070                  resultFrameNumber);
   3071         return NO_ERROR;
   3072     } else if (ppInfo != mOfflinePpInfoList.begin()) {
   3073         LOGE("callback for frame number %d should be head of list",
   3074                  resultFrameNumber);
   3075         return BAD_VALUE;
   3076     }
   3077 
   3078     if (ppInfo->offlinePpFlag) {
   3079         // Need to get the input buffer frame index from the
   3080         // mMemory object and add that to the free heap buffers list.
   3081         int32_t bufferIndex =
   3082                 mMemory.getHeapBufferIndex(resultFrameNumber);
   3083         if (bufferIndex < 0) {
   3084             LOGE("Fatal %d: no buffer index for frame number %d",
   3085                      bufferIndex, resultFrameNumber);
   3086             return BAD_VALUE;
   3087         }
   3088         mMemory.markFrameNumber(bufferIndex, -1);
   3089         mFreeHeapBufferList.push_back(bufferIndex);
   3090         //Move heap buffer into free pool and invalidate the frame number
   3091         ppInfo = mOfflinePpInfoList.erase(ppInfo);
   3092 
   3093         /* return any pending buffers that were received out of order
   3094             earlier */
   3095         mm_camera_super_buf_t* super_frame;
   3096         while((super_frame = getNextPendingCbBuffer())) {
   3097             pendingCbs.push_back(super_frame);
   3098         }
   3099     } else {
   3100         LOGE("Fatal: request of frame number %d doesn't need"
   3101                 " offline postprocessing. However there is"
   3102                 " reprocessing callback.",
   3103                 resultFrameNumber);
   3104         return BAD_VALUE;
   3105     }
   3106 
   3107     return NO_ERROR;
   3108 }
   3109 
   3110 /*===========================================================================
   3111  * FUNCTION   : getReprocessType
   3112  *
   3113  * DESCRIPTION: get the type of reprocess output supported by this channel
   3114  *
   3115  * PARAMETERS : NONE
   3116  *
   3117  * RETURN     : reprocess_type_t : type of reprocess
   3118  *==========================================================================*/
   3119 reprocess_type_t QCamera3YUVChannel::getReprocessType()
   3120 {
   3121     return REPROCESS_TYPE_YUV;
   3122 }
   3123 
   3124 /* QCamera3PicChannel methods */
   3125 
   3126 /*===========================================================================
   3127  * FUNCTION   : jpegEvtHandle
   3128  *
   3129  * DESCRIPTION: Function registerd to mm-jpeg-interface to handle jpeg events.
   3130                 Construct result payload and call mChannelCb to deliver buffer
   3131                 to framework.
   3132  *
   3133  * PARAMETERS :
   3134  *   @status    : status of jpeg job
   3135  *   @client_hdl: jpeg client handle
   3136  *   @jobId     : jpeg job Id
   3137  *   @p_ouput   : ptr to jpeg output result struct
   3138  *   @userdata  : user data ptr
   3139  *
   3140  * RETURN     : none
   3141  *==========================================================================*/
   3142 void QCamera3PicChannel::jpegEvtHandle(jpeg_job_status_t status,
   3143                                               uint32_t /*client_hdl*/,
   3144                                               uint32_t jobId,
   3145                                               mm_jpeg_output_t *p_output,
   3146                                               void *userdata)
   3147 {
   3148     ATRACE_CALL();
   3149     buffer_handle_t *resultBuffer = NULL;
   3150     buffer_handle_t *jpegBufferHandle = NULL;
   3151     int resultStatus = CAMERA3_BUFFER_STATUS_OK;
   3152     camera3_stream_buffer_t result;
   3153     camera3_jpeg_blob_t jpegHeader;
   3154 
   3155     QCamera3PicChannel *obj = (QCamera3PicChannel *)userdata;
   3156     if (obj) {
   3157         //Construct payload for process_capture_result. Call mChannelCb
   3158 
   3159         qcamera_hal3_jpeg_data_t *job = obj->m_postprocessor.findJpegJobByJobId(jobId);
   3160 
   3161         if ((job == NULL) || (status == JPEG_JOB_STATUS_ERROR)) {
   3162             LOGE("Error in jobId: (%d) with status: %d", jobId, status);
   3163             resultStatus = CAMERA3_BUFFER_STATUS_ERROR;
   3164         }
   3165 
   3166         if (NULL != job) {
   3167             uint32_t bufIdx = (uint32_t)job->jpeg_settings->out_buf_index;
   3168             LOGD("jpeg out_buf_index: %d", bufIdx);
   3169 
   3170             //Construct jpeg transient header of type camera3_jpeg_blob_t
   3171             //Append at the end of jpeg image of buf_filled_len size
   3172 
   3173             jpegHeader.jpeg_blob_id = CAMERA3_JPEG_BLOB_ID;
   3174             if (JPEG_JOB_STATUS_DONE == status) {
   3175                 jpegHeader.jpeg_size = (uint32_t)p_output->buf_filled_len;
   3176                 char* jpeg_buf = (char *)p_output->buf_vaddr;
   3177 
   3178                 ssize_t maxJpegSize = -1;
   3179 
   3180                 // Gralloc buffer may have additional padding for 4K page size
   3181                 // Follow size guidelines based on spec since framework relies
   3182                 // on that to reach end of buffer and with it the header
   3183 
   3184                 //Handle same as resultBuffer, but for readablity
   3185                 jpegBufferHandle =
   3186                         (buffer_handle_t *)obj->mMemory.getBufferHandle(bufIdx);
   3187 
   3188                 if (NULL != jpegBufferHandle) {
   3189                     maxJpegSize = ((private_handle_t*)(*jpegBufferHandle))->width;
   3190                     if (maxJpegSize > obj->mMemory.getSize(bufIdx)) {
   3191                         maxJpegSize = obj->mMemory.getSize(bufIdx);
   3192                     }
   3193 
   3194                     size_t jpeg_eof_offset =
   3195                             (size_t)(maxJpegSize - (ssize_t)sizeof(jpegHeader));
   3196                     char *jpeg_eof = &jpeg_buf[jpeg_eof_offset];
   3197                     memcpy(jpeg_eof, &jpegHeader, sizeof(jpegHeader));
   3198                     obj->mMemory.cleanInvalidateCache(bufIdx);
   3199                     bool jpegDump = false;
   3200                     char prop[PROPERTY_VALUE_MAX];
   3201                     property_get("persist.camera.jpeg.dump", prop, "0");
   3202                     jpegDump = atoi(prop);
   3203                     if (jpegDump) {
   3204                         char buf[FILENAME_MAX];
   3205                         char timeBuf[FILENAME_MAX];
   3206                         memset(buf, 0, sizeof(buf));
   3207                         memset(timeBuf, 0, sizeof(timeBuf));
   3208                         time_t current_time;
   3209                         struct tm * timeinfo;
   3210                         time (&current_time);
   3211                         timeinfo = localtime (&current_time);
   3212                         if (timeinfo != NULL) {
   3213                             /* Consistent naming for Jpeg+meta+raw: meta name */
   3214                             strftime (timeBuf, sizeof(timeBuf),
   3215                                     QCAMERA_DUMP_FRM_LOCATION"IMG_%Y%m%d_%H%M%S", timeinfo);
   3216                             /* Consistent naming for Jpeg+meta+raw: meta name end*/
   3217                         }
   3218                         String8 filePath(timeBuf);
   3219                         snprintf(buf, sizeof(buf), "_%d.jpg",
   3220                                 obj->mMemory.getFrameNumber(bufIdx));
   3221                         filePath.append(buf);
   3222                         int file_fd = open(filePath.string(), O_RDWR | O_CREAT, 0777);
   3223                         ssize_t written_len = 0;
   3224                         if (file_fd >= 0) {
   3225                             fchmod(file_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
   3226                             written_len += write(file_fd, jpeg_buf,
   3227                                     (size_t)maxJpegSize);
   3228                             LOGI("written number of bytes %ld attempted: %ld\n", written_len,
   3229                                 maxJpegSize);
   3230                             close(file_fd);
   3231                         } else {
   3232                             LOGE("failed to open file to dump image");
   3233                         }
   3234 
   3235                     }
   3236                 } else {
   3237                     LOGE("JPEG buffer not found and index: %d",
   3238                             bufIdx);
   3239                     resultStatus = CAMERA3_BUFFER_STATUS_ERROR;
   3240                 }
   3241             }
   3242 
   3243             ////Use below data to issue framework callback
   3244             resultBuffer =
   3245                     (buffer_handle_t *)obj->mMemory.getBufferHandle(bufIdx);
   3246             int32_t resultFrameNumber = obj->mMemory.getFrameNumber(bufIdx);
   3247             int32_t rc = obj->mMemory.unregisterBuffer(bufIdx);
   3248             if (NO_ERROR != rc) {
   3249                 LOGE("Error %d unregistering stream buffer %d",
   3250                      rc, bufIdx);
   3251             }
   3252 
   3253             result.stream = obj->mCamera3Stream;
   3254             result.buffer = resultBuffer;
   3255             result.status = resultStatus;
   3256             result.acquire_fence = -1;
   3257             result.release_fence = -1;
   3258 
   3259             // Release any snapshot buffers before calling
   3260             // the user callback. The callback can potentially
   3261             // unblock pending requests to snapshot stream.
   3262             int32_t snapshotIdx = -1;
   3263             mm_camera_super_buf_t* src_frame = NULL;
   3264 
   3265             if (job->src_reproc_frame)
   3266                 src_frame = job->src_reproc_frame;
   3267             else
   3268                 src_frame = job->src_frame;
   3269 
   3270             if (src_frame) {
   3271                 if (obj->mStreams[0]->getMyHandle() ==
   3272                         src_frame->bufs[0]->stream_id) {
   3273                     snapshotIdx = (int32_t)src_frame->bufs[0]->buf_idx;
   3274                     if (0 <= snapshotIdx) {
   3275                         Mutex::Autolock lock(obj->mFreeBuffersLock);
   3276                         obj->mFreeBufferList.push_back((uint32_t)snapshotIdx);
   3277                     }
   3278                 }
   3279             }
   3280 
   3281             LOGI("Issue Jpeg Callback frameNumber = %d status = %d",
   3282                     resultFrameNumber, resultStatus);
   3283             KPI_ATRACE_ASYNC_END("SNAPSHOT", resultFrameNumber);
   3284             if (obj->mChannelCB) {
   3285                 obj->mChannelCB(NULL,
   3286                         &result,
   3287                         (uint32_t)resultFrameNumber,
   3288                         false,
   3289                         obj->mUserData);
   3290             }
   3291 
   3292             // release internal data for jpeg job
   3293             if ((NULL != job->fwk_frame) || (NULL != job->fwk_src_buffer)) {
   3294                 /* unregister offline input buffer */
   3295                 int32_t inputBufIndex =
   3296                         obj->mOfflineMemory.getGrallocBufferIndex((uint32_t)resultFrameNumber);
   3297                 if (0 <= inputBufIndex) {
   3298                     rc = obj->mOfflineMemory.unregisterBuffer(inputBufIndex);
   3299                 } else {
   3300                     LOGE("could not find the input buf index, frame number %d",
   3301                              resultFrameNumber);
   3302                 }
   3303                 if (NO_ERROR != rc) {
   3304                     LOGE("Error %d unregistering input buffer %d",
   3305                              rc, bufIdx);
   3306                 }
   3307 
   3308                 /* unregister offline meta buffer */
   3309                 int32_t metaBufIndex =
   3310                         obj->mOfflineMetaMemory.getHeapBufferIndex((uint32_t)resultFrameNumber);
   3311                 if (0 <= metaBufIndex) {
   3312                     Mutex::Autolock lock(obj->mFreeOfflineMetaBuffersLock);
   3313                     obj->mFreeOfflineMetaBuffersList.push_back((uint32_t)metaBufIndex);
   3314                 } else {
   3315                     LOGE("could not find the input meta buf index, frame number %d",
   3316                              resultFrameNumber);
   3317                 }
   3318             }
   3319             obj->m_postprocessor.releaseOfflineBuffers(false);
   3320             obj->m_postprocessor.releaseJpegJobData(job);
   3321             free(job);
   3322         }
   3323 
   3324         obj->resetCppPerfParam();
   3325         return;
   3326         // }
   3327     } else {
   3328         LOGE("Null userdata in jpeg callback");
   3329     }
   3330 }
   3331 
   3332 QCamera3PicChannel::QCamera3PicChannel(uint32_t cam_handle,
   3333                     uint32_t channel_handle,
   3334                     mm_camera_ops_t *cam_ops,
   3335                     channel_cb_routine cb_routine,
   3336                     channel_cb_buffer_err cb_buf_err,
   3337                     cam_padding_info_t *paddingInfo,
   3338                     void *userData,
   3339                     camera3_stream_t *stream,
   3340                     cam_feature_mask_t postprocess_mask,
   3341                     __unused bool is4KVideo,
   3342                     bool isInputStreamConfigured,
   3343                     QCamera3Channel *metadataChannel,
   3344                     uint32_t numBuffers) :
   3345                         QCamera3ProcessingChannel(cam_handle, channel_handle,
   3346                                 cam_ops, cb_routine, cb_buf_err, paddingInfo, userData,
   3347                                 stream, CAM_STREAM_TYPE_SNAPSHOT,
   3348                                 postprocess_mask, metadataChannel, numBuffers),
   3349                         mNumSnapshotBufs(0),
   3350                         mInputBufferHint(isInputStreamConfigured),
   3351                         mYuvMemory(NULL),
   3352                         mFrameLen(0)
   3353 {
   3354     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
   3355     m_max_pic_dim = hal_obj->calcMaxJpegDim();
   3356     mYuvWidth = stream->width;
   3357     mYuvHeight = stream->height;
   3358     mStreamType = CAM_STREAM_TYPE_SNAPSHOT;
   3359     mPendingLiveSnapshotFrames = 0;
   3360     // Use same pixelformat for 4K video case
   3361     mStreamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_SNAPSHOT,
   3362             stream->width, stream->height);
   3363     int32_t rc = m_postprocessor.initJpeg(jpegEvtHandle, &m_max_pic_dim, this);
   3364     if (rc != 0) {
   3365         LOGE("Init Postprocessor failed");
   3366     }
   3367 }
   3368 
   3369 /*===========================================================================
   3370  * FUNCTION   : flush
   3371  *
   3372  * DESCRIPTION: flush pic channel, which will stop all processing within, including
   3373  *              the reprocessing channel in postprocessor and YUV stream.
   3374  *
   3375  * PARAMETERS : none
   3376  *
   3377  * RETURN     : int32_t type of status
   3378  *              NO_ERROR  -- success
   3379  *              none-zero failure code
   3380  *==========================================================================*/
   3381 int32_t QCamera3PicChannel::flush()
   3382 {
   3383     int32_t rc = NO_ERROR;
   3384     if(!m_bIsActive) {
   3385         LOGE("Attempt to flush inactive channel");
   3386         return NO_INIT;
   3387     }
   3388 
   3389     rc = m_postprocessor.flush();
   3390     if (rc == 0) {
   3391         LOGE("Postprocessor flush failed, rc = %d", rc);
   3392         return rc;
   3393     }
   3394 
   3395     if (0 < mOfflineMetaMemory.getCnt()) {
   3396         mOfflineMetaMemory.deallocate();
   3397     }
   3398     if (0 < mOfflineMemory.getCnt()) {
   3399         mOfflineMemory.unregisterBuffers();
   3400     }
   3401     Mutex::Autolock lock(mFreeBuffersLock);
   3402     mFreeBufferList.clear();
   3403     for (uint32_t i = 0; i < mCamera3Stream->max_buffers; i++) {
   3404         mFreeBufferList.push_back(i);
   3405     }
   3406     return rc;
   3407 }
   3408 
   3409 
   3410 QCamera3PicChannel::~QCamera3PicChannel()
   3411 {
   3412 }
   3413 
   3414 int32_t QCamera3PicChannel::initialize(cam_is_type_t isType)
   3415 {
   3416     int32_t rc = NO_ERROR;
   3417     cam_dimension_t streamDim;
   3418     cam_stream_type_t streamType;
   3419     cam_format_t streamFormat;
   3420 
   3421     if (NULL == mCamera3Stream) {
   3422         LOGE("Camera stream uninitialized");
   3423         return NO_INIT;
   3424     }
   3425 
   3426     if (1 <= m_numStreams) {
   3427         // Only one stream per channel supported in v3 Hal
   3428         return NO_ERROR;
   3429     }
   3430 
   3431     mIsType = isType;
   3432     streamType = mStreamType;
   3433     streamFormat = mStreamFormat;
   3434     streamDim.width = (int32_t)mYuvWidth;
   3435     streamDim.height = (int32_t)mYuvHeight;
   3436 
   3437     mNumSnapshotBufs = mCamera3Stream->max_buffers;
   3438     rc = QCamera3Channel::addStream(streamType, streamFormat, streamDim,
   3439             ROTATE_0, (uint8_t)mCamera3Stream->max_buffers, mPostProcMask,
   3440             mIsType);
   3441 
   3442     if (NO_ERROR != rc) {
   3443         LOGE("Initialize failed, rc = %d", rc);
   3444         return rc;
   3445     }
   3446 
   3447     /* initialize offline meta memory for input reprocess */
   3448     rc = QCamera3ProcessingChannel::initialize(isType);
   3449     if (NO_ERROR != rc) {
   3450         LOGE("Processing Channel initialize failed, rc = %d",
   3451                  rc);
   3452     }
   3453 
   3454     return rc;
   3455 }
   3456 
   3457 /*===========================================================================
   3458  * FUNCTION   : request
   3459  *
   3460  * DESCRIPTION: handle the request - either with an input buffer or a direct
   3461  *              output request
   3462  *
   3463  * PARAMETERS :
   3464  * @buffer       : pointer to the output buffer
   3465  * @frameNumber  : frame number of the request
   3466  * @pInputBuffer : pointer to input buffer if an input request
   3467  * @metadata     : parameters associated with the request
   3468  *
   3469  * RETURN     : 0 on a success start of capture
   3470  *              -EINVAL on invalid input
   3471  *              -ENODEV on serious error
   3472  *==========================================================================*/
   3473 int32_t QCamera3PicChannel::request(buffer_handle_t *buffer,
   3474         uint32_t frameNumber,
   3475         camera3_stream_buffer_t *pInputBuffer,
   3476         metadata_buffer_t *metadata, int &indexUsed)
   3477 {
   3478     ATRACE_CALL();
   3479     //FIX ME: Return buffer back in case of failures below.
   3480 
   3481     int32_t rc = NO_ERROR;
   3482 
   3483     reprocess_config_t reproc_cfg;
   3484     cam_dimension_t dim;
   3485     memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
   3486     //make sure to set the correct input stream dim in case of YUV size override
   3487     //and recalculate the plane info
   3488     dim.width = (int32_t)mYuvWidth;
   3489     dim.height = (int32_t)mYuvHeight;
   3490     setReprocConfig(reproc_cfg, pInputBuffer, metadata, mStreamFormat, dim);
   3491 
   3492     // Picture stream has already been started before any request comes in
   3493     if (!m_bIsActive) {
   3494         LOGE("Channel not started!!");
   3495         return NO_INIT;
   3496     }
   3497 
   3498     int index = mMemory.getMatchBufIndex((void*)buffer);
   3499 
   3500     if(index < 0) {
   3501         rc = registerBuffer(buffer, mIsType);
   3502         if (NO_ERROR != rc) {
   3503             LOGE("On-the-fly buffer registration failed %d",
   3504                      rc);
   3505             return rc;
   3506         }
   3507 
   3508         index = mMemory.getMatchBufIndex((void*)buffer);
   3509         if (index < 0) {
   3510             LOGE("Could not find object among registered buffers");
   3511             return DEAD_OBJECT;
   3512         }
   3513     }
   3514     LOGD("buffer index %d, frameNumber: %u", index, frameNumber);
   3515 
   3516     rc = mMemory.markFrameNumber((uint32_t)index, frameNumber);
   3517 
   3518     // Start postprocessor
   3519     startPostProc(reproc_cfg);
   3520 
   3521     // Only set the perf mode for online cpp processing
   3522     if (reproc_cfg.reprocess_type == REPROCESS_TYPE_NONE) {
   3523         setCppPerfParam();
   3524     }
   3525 
   3526     // Queue jpeg settings
   3527     rc = queueJpegSetting((uint32_t)index, metadata);
   3528 
   3529     if (pInputBuffer == NULL) {
   3530         Mutex::Autolock lock(mFreeBuffersLock);
   3531         uint32_t bufIdx;
   3532         if (mFreeBufferList.empty()) {
   3533             rc = mYuvMemory->allocateOne(mFrameLen);
   3534             if (rc < 0) {
   3535                 LOGE("Failed to allocate heap buffer. Fatal");
   3536                 return rc;
   3537             } else {
   3538                 bufIdx = (uint32_t)rc;
   3539             }
   3540         } else {
   3541             List<uint32_t>::iterator it = mFreeBufferList.begin();
   3542             bufIdx = *it;
   3543             mFreeBufferList.erase(it);
   3544         }
   3545         mYuvMemory->markFrameNumber(bufIdx, frameNumber);
   3546         mStreams[0]->bufDone(bufIdx);
   3547         indexUsed = bufIdx;
   3548     } else {
   3549         qcamera_fwk_input_pp_data_t *src_frame = NULL;
   3550         src_frame = (qcamera_fwk_input_pp_data_t *)calloc(1,
   3551                 sizeof(qcamera_fwk_input_pp_data_t));
   3552         if (src_frame == NULL) {
   3553             LOGE("No memory for src frame");
   3554             return NO_MEMORY;
   3555         }
   3556         rc = setFwkInputPPData(src_frame, pInputBuffer, &reproc_cfg, metadata,
   3557                 NULL /*fwk output buffer*/, frameNumber);
   3558         if (NO_ERROR != rc) {
   3559             LOGE("Error %d while setting framework input PP data", rc);
   3560             free(src_frame);
   3561             return rc;
   3562         }
   3563         LOGH("Post-process started");
   3564         m_postprocessor.processData(src_frame);
   3565     }
   3566     return rc;
   3567 }
   3568 
   3569 
   3570 
   3571 /*===========================================================================
   3572  * FUNCTION   : dataNotifyCB
   3573  *
   3574  * DESCRIPTION: Channel Level callback used for super buffer data notify.
   3575  *              This function is registered with mm-camera-interface to handle
   3576  *              data notify
   3577  *
   3578  * PARAMETERS :
   3579  *   @recvd_frame   : stream frame received
   3580  *   userdata       : user data ptr
   3581  *
   3582  * RETURN     : none
   3583  *==========================================================================*/
   3584 void QCamera3PicChannel::dataNotifyCB(mm_camera_super_buf_t *recvd_frame,
   3585                                  void *userdata)
   3586 {
   3587     ATRACE_CALL();
   3588     LOGD("E\n");
   3589     QCamera3PicChannel *channel = (QCamera3PicChannel *)userdata;
   3590 
   3591     if (channel == NULL) {
   3592         LOGE("invalid channel pointer");
   3593         return;
   3594     }
   3595 
   3596     if(channel->m_numStreams != 1) {
   3597         LOGE("Error: Bug: This callback assumes one stream per channel");
   3598         return;
   3599     }
   3600 
   3601 
   3602     if(channel->mStreams[0] == NULL) {
   3603         LOGE("Error: Invalid Stream object");
   3604         return;
   3605     }
   3606 
   3607     channel->QCamera3PicChannel::streamCbRoutine(recvd_frame, channel->mStreams[0]);
   3608 
   3609     LOGD("X\n");
   3610     return;
   3611 }
   3612 
   3613 /*===========================================================================
   3614  * FUNCTION   : streamCbRoutine
   3615  *
   3616  * DESCRIPTION:
   3617  *
   3618  * PARAMETERS :
   3619  * @super_frame : the super frame with filled buffer
   3620  * @stream      : stream on which the buffer was requested and filled
   3621  *
   3622  * RETURN     : none
   3623  *==========================================================================*/
   3624 void QCamera3PicChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
   3625                             QCamera3Stream *stream)
   3626 {
   3627     ATRACE_CALL();
   3628     //TODO
   3629     //Used only for getting YUV. Jpeg callback will be sent back from channel
   3630     //directly to HWI. Refer to func jpegEvtHandle
   3631 
   3632     //Got the yuv callback. Calling yuv callback handler in PostProc
   3633     uint8_t frameIndex;
   3634     mm_camera_super_buf_t* frame = NULL;
   3635     cam_dimension_t dim;
   3636     cam_frame_len_offset_t offset;
   3637 
   3638     memset(&dim, 0, sizeof(dim));
   3639     memset(&offset, 0, sizeof(cam_frame_len_offset_t));
   3640 
   3641     if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
   3642         LOGE("Error with the stream callback");
   3643         return;
   3644     }
   3645 
   3646     frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
   3647     LOGD("recvd buf_idx: %u for further processing",
   3648          (uint32_t)frameIndex);
   3649     if(frameIndex >= mNumSnapshotBufs) {
   3650          LOGE("Error, Invalid index for buffer");
   3651          if(stream) {
   3652              Mutex::Autolock lock(mFreeBuffersLock);
   3653              mFreeBufferList.push_back(frameIndex);
   3654              stream->bufDone(frameIndex);
   3655          }
   3656          return;
   3657     }
   3658 
   3659     frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
   3660     if (frame == NULL) {
   3661        LOGE("Error allocating memory to save received_frame structure.");
   3662        if(stream) {
   3663            Mutex::Autolock lock(mFreeBuffersLock);
   3664            mFreeBufferList.push_back(frameIndex);
   3665            stream->bufDone(frameIndex);
   3666        }
   3667        return;
   3668     }
   3669     *frame = *super_frame;
   3670     stream->getFrameDimension(dim);
   3671     stream->getFrameOffset(offset);
   3672     dumpYUV(frame->bufs[0], dim, offset, QCAMERA_DUMP_FRM_INPUT_REPROCESS);
   3673 
   3674     if (IS_BUFFER_ERROR(super_frame->bufs[0]->flags)) {
   3675         mChannelCbBufErr(this, mYuvMemory->getFrameNumber(frameIndex),
   3676                             CAMERA3_BUFFER_STATUS_ERROR, mUserData);
   3677     }
   3678 
   3679     m_postprocessor.processData(frame);
   3680     free(super_frame);
   3681     return;
   3682 }
   3683 
   3684 QCamera3StreamMem* QCamera3PicChannel::getStreamBufs(uint32_t len)
   3685 {
   3686     mYuvMemory = new QCamera3StreamMem(mCamera3Stream->max_buffers, false);
   3687     if (!mYuvMemory) {
   3688         LOGE("unable to create metadata memory");
   3689         return NULL;
   3690     }
   3691     mFrameLen = len;
   3692 
   3693     return mYuvMemory;
   3694 }
   3695 
   3696 void QCamera3PicChannel::putStreamBufs()
   3697 {
   3698     QCamera3ProcessingChannel::putStreamBufs();
   3699 
   3700     mYuvMemory->deallocate();
   3701     delete mYuvMemory;
   3702     mYuvMemory = NULL;
   3703     mFreeBufferList.clear();
   3704 }
   3705 
   3706 int32_t QCamera3PicChannel::queueJpegSetting(uint32_t index, metadata_buffer_t *metadata)
   3707 {
   3708     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
   3709     jpeg_settings_t *settings =
   3710             (jpeg_settings_t *)malloc(sizeof(jpeg_settings_t));
   3711 
   3712     if (!settings) {
   3713         LOGE("out of memory allocating jpeg_settings");
   3714         return -ENOMEM;
   3715     }
   3716 
   3717     memset(settings, 0, sizeof(jpeg_settings_t));
   3718 
   3719     settings->out_buf_index = index;
   3720 
   3721     settings->jpeg_orientation = 0;
   3722     IF_META_AVAILABLE(int32_t, orientation, CAM_INTF_META_JPEG_ORIENTATION, metadata) {
   3723         settings->jpeg_orientation = *orientation;
   3724     }
   3725 
   3726     settings->jpeg_quality = 85;
   3727     IF_META_AVAILABLE(uint32_t, quality1, CAM_INTF_META_JPEG_QUALITY, metadata) {
   3728         settings->jpeg_quality = (uint8_t) *quality1;
   3729     }
   3730 
   3731     IF_META_AVAILABLE(uint32_t, quality2, CAM_INTF_META_JPEG_THUMB_QUALITY, metadata) {
   3732         settings->jpeg_thumb_quality = (uint8_t) *quality2;
   3733     }
   3734 
   3735     IF_META_AVAILABLE(cam_dimension_t, dimension, CAM_INTF_META_JPEG_THUMB_SIZE, metadata) {
   3736         settings->thumbnail_size = *dimension;
   3737     }
   3738 
   3739     settings->gps_timestamp_valid = 0;
   3740     IF_META_AVAILABLE(int64_t, timestamp, CAM_INTF_META_JPEG_GPS_TIMESTAMP, metadata) {
   3741         settings->gps_timestamp = *timestamp;
   3742         settings->gps_timestamp_valid = 1;
   3743     }
   3744 
   3745     settings->gps_coordinates_valid = 0;
   3746     IF_META_AVAILABLE(double, coordinates, CAM_INTF_META_JPEG_GPS_COORDINATES, metadata) {
   3747         memcpy(settings->gps_coordinates, coordinates, 3*sizeof(double));
   3748         settings->gps_coordinates_valid = 1;
   3749     }
   3750 
   3751     IF_META_AVAILABLE(uint8_t, proc_methods, CAM_INTF_META_JPEG_GPS_PROC_METHODS, metadata) {
   3752         memset(settings->gps_processing_method, 0,
   3753                 sizeof(settings->gps_processing_method));
   3754         strlcpy(settings->gps_processing_method, (const char *)proc_methods,
   3755                 sizeof(settings->gps_processing_method));
   3756     }
   3757 
   3758     // Image description
   3759     const char *eepromVersion = hal_obj->getEepromVersionInfo();
   3760     const uint32_t *ldafCalib = hal_obj->getLdafCalib();
   3761     if ((eepromVersion && strlen(eepromVersion)) ||
   3762             ldafCalib) {
   3763         int len = 0;
   3764         settings->image_desc_valid = true;
   3765         if (eepromVersion && strlen(eepromVersion)) {
   3766             len = snprintf(settings->image_desc, sizeof(settings->image_desc),
   3767                     "M:%s ", eepromVersion);
   3768         }
   3769         if (ldafCalib) {
   3770             snprintf(settings->image_desc + len,
   3771                     sizeof(settings->image_desc) - len, "L:%u-%u",
   3772                     ldafCalib[0], ldafCalib[1]);
   3773         }
   3774     }
   3775 
   3776     return m_postprocessor.processJpegSettingData(settings);
   3777 }
   3778 
   3779 
   3780 void QCamera3PicChannel::overrideYuvSize(uint32_t width, uint32_t height)
   3781 {
   3782    mYuvWidth = width;
   3783    mYuvHeight = height;
   3784 }
   3785 
   3786 /*===========================================================================
   3787  * FUNCTION   : getReprocessType
   3788  *
   3789  * DESCRIPTION: get the type of reprocess output supported by this channel
   3790  *
   3791  * PARAMETERS : NONE
   3792  *
   3793  * RETURN     : reprocess_type_t : type of reprocess
   3794  *==========================================================================*/
   3795 reprocess_type_t QCamera3PicChannel::getReprocessType()
   3796 {
   3797     /* a picture channel could either use the postprocessor for reprocess+jpeg
   3798        or only for reprocess */
   3799     reprocess_type_t expectedReprocess;
   3800     if (mPostProcMask == CAM_QCOM_FEATURE_NONE || mInputBufferHint) {
   3801         expectedReprocess = REPROCESS_TYPE_JPEG;
   3802     } else {
   3803         expectedReprocess = REPROCESS_TYPE_NONE;
   3804     }
   3805     LOGH("expectedReprocess from Pic Channel is %d", expectedReprocess);
   3806     return expectedReprocess;
   3807 }
   3808 
   3809 /*===========================================================================
   3810  * FUNCTION   : setCppPerfParam
   3811  *
   3812  * DESCRIPTION: set the performance related stream params
   3813  *
   3814  * PARAMETERS : NONE
   3815  *
   3816  * RETURN     : NONE
   3817  *==========================================================================*/
   3818 
   3819 void QCamera3PicChannel::setCppPerfParam()
   3820 {
   3821     if (mPendingLiveSnapshotFrames == 0) {
   3822         int32_t rc = 0;
   3823         QCamera3Stream *pStream = mStreams[0];
   3824         cam_stream_parm_buffer_t param;
   3825         memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
   3826         param.type = CAM_STREAM_PARAM_TYPE_REQUEST_OPS_MODE;
   3827         param.perf_mode = CAM_PERF_SET;
   3828         rc = pStream->setParameter(param);
   3829         if (rc != NO_ERROR) {
   3830             LOGE("%s: setParameter for CAM_PERF_SET failed",
   3831                 __func__);
   3832         }
   3833     }
   3834     mPendingLiveSnapshotFrames++;
   3835 }
   3836 
   3837 /*===========================================================================
   3838  * FUNCTION   : resetCppPerfParam
   3839  *
   3840  * DESCRIPTION: reset the performance related stream params
   3841  *
   3842  * PARAMETERS : NONE
   3843  *
   3844  * RETURN     : NONE
   3845  *==========================================================================*/
   3846 
   3847 void QCamera3PicChannel::resetCppPerfParam()
   3848 {
   3849     if (mPendingLiveSnapshotFrames > 0) {
   3850         int32_t rc = NO_ERROR;
   3851         QCamera3Stream *pStream = mStreams[0];
   3852         cam_stream_parm_buffer_t param;
   3853         memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
   3854         param.type = CAM_STREAM_PARAM_TYPE_REQUEST_OPS_MODE;
   3855         param.perf_mode = CAM_PERF_RESET;
   3856         rc = pStream->setParameter(param);
   3857         if (rc != NO_ERROR) {
   3858             LOGE("%s: setParameter for CAM_PERF_RESET failed",
   3859                 __func__);
   3860         }
   3861         mPendingLiveSnapshotFrames--;
   3862     }
   3863 }
   3864 
   3865 /*===========================================================================
   3866  * FUNCTION   : timeoutFrame
   3867  *
   3868  * DESCRIPTION: Method to indicate to channel that a given frame has take too
   3869  *              long to be generated
   3870  *
   3871  * PARAMETERS : framenumber indicating the framenumber of the buffer timingout
   3872  *
   3873  * RETURN     : int32_t type of status
   3874  *              NO_ERROR  -- success
   3875  *              none-zero failure code
   3876  *==========================================================================*/
   3877 int32_t QCamera3PicChannel::timeoutFrame(uint32_t frameNumber)
   3878 {
   3879     int32_t bufIdx;
   3880 
   3881     bufIdx = mYuvMemory->getBufferIndex(frameNumber);
   3882 
   3883     if (bufIdx < 0) {
   3884         ALOGE("%s: Buffer not found for frame:%d", __func__, frameNumber);
   3885         return -1;
   3886     }
   3887 
   3888     mStreams[0]->timeoutFrame(bufIdx);
   3889 
   3890     return NO_ERROR;
   3891 }
   3892 
   3893 /*===========================================================================
   3894  * FUNCTION   : QCamera3ReprocessChannel
   3895  *
   3896  * DESCRIPTION: constructor of QCamera3ReprocessChannel
   3897  *
   3898  * PARAMETERS :
   3899  *   @cam_handle : camera handle
   3900  *   @cam_ops    : ptr to camera ops table
   3901  *   @pp_mask    : post-proccess feature mask
   3902  *
   3903  * RETURN     : none
   3904  *==========================================================================*/
   3905 QCamera3ReprocessChannel::QCamera3ReprocessChannel(uint32_t cam_handle,
   3906                                                  uint32_t channel_handle,
   3907                                                  mm_camera_ops_t *cam_ops,
   3908                                                  channel_cb_routine cb_routine,
   3909                                                  channel_cb_buffer_err cb_buf_err,
   3910                                                  cam_padding_info_t *paddingInfo,
   3911                                                  cam_feature_mask_t postprocess_mask,
   3912                                                  void *userData, void *ch_hdl) :
   3913     /* In case of framework reprocessing, pproc and jpeg operations could be
   3914      * parallelized by allowing 1 extra buffer for reprocessing output:
   3915      * ch_hdl->getNumBuffers() + 1 */
   3916     QCamera3Channel(cam_handle, channel_handle, cam_ops, cb_routine, cb_buf_err, paddingInfo,
   3917                     postprocess_mask, userData,
   3918                     ((QCamera3ProcessingChannel *)ch_hdl)->getNumBuffers()
   3919                               + (MAX_REPROCESS_PIPELINE_STAGES - 1)),
   3920     inputChHandle(ch_hdl),
   3921     mOfflineBuffersIndex(-1),
   3922     mFrameLen(0),
   3923     mReprocessType(REPROCESS_TYPE_NONE),
   3924     m_pSrcChannel(NULL),
   3925     m_pMetaChannel(NULL),
   3926     mMemory(NULL),
   3927     mGrallocMemory(0),
   3928     mReprocessPerfMode(false)
   3929 {
   3930     memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles));
   3931     mOfflineBuffersIndex = mNumBuffers -1;
   3932     mOfflineMetaIndex = (int32_t) (2*mNumBuffers -1);
   3933 }
   3934 
   3935 
   3936 /*===========================================================================
   3937  * FUNCTION   : QCamera3ReprocessChannel
   3938  *
   3939  * DESCRIPTION: constructor of QCamera3ReprocessChannel
   3940  *
   3941  * PARAMETERS :
   3942  *   @cam_handle : camera handle
   3943  *   @cam_ops    : ptr to camera ops table
   3944  *   @pp_mask    : post-proccess feature mask
   3945  *
   3946  * RETURN     : none
   3947  *==========================================================================*/
   3948 int32_t QCamera3ReprocessChannel::initialize(cam_is_type_t isType)
   3949 {
   3950     int32_t rc = NO_ERROR;
   3951     mm_camera_channel_attr_t attr;
   3952 
   3953     memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
   3954     attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS;
   3955     attr.max_unmatched_frames = 1;
   3956 
   3957     m_handle = m_camOps->add_channel(m_camHandle,
   3958                                       &attr,
   3959                                       NULL,
   3960                                       this);
   3961     if (m_handle == 0) {
   3962         LOGE("Add channel failed");
   3963         return UNKNOWN_ERROR;
   3964     }
   3965 
   3966     mIsType = isType;
   3967     return rc;
   3968 }
   3969 
   3970 /*===========================================================================
   3971  * FUNCTION   : registerBuffer
   3972  *
   3973  * DESCRIPTION: register streaming buffer to the channel object
   3974  *
   3975  * PARAMETERS :
   3976  *   @buffer     : buffer to be registered
   3977  *   @isType     : the image stabilization type for the buffer
   3978  *
   3979  * RETURN     : int32_t type of status
   3980  *              NO_ERROR  -- success
   3981  *              none-zero failure code
   3982  *==========================================================================*/
   3983 int32_t QCamera3ReprocessChannel::registerBuffer(buffer_handle_t *buffer,
   3984         cam_is_type_t isType)
   3985 {
   3986     ATRACE_CALL();
   3987     int rc = 0;
   3988     mIsType = isType;
   3989     cam_stream_type_t streamType;
   3990 
   3991     if (buffer == NULL) {
   3992         LOGE("Error: Cannot register a NULL buffer");
   3993         return BAD_VALUE;
   3994     }
   3995 
   3996     if ((uint32_t)mGrallocMemory.getCnt() > (mNumBuffers - 1)) {
   3997         LOGE("Trying to register more buffers than initially requested");
   3998         return BAD_VALUE;
   3999     }
   4000 
   4001     if (0 == m_numStreams) {
   4002         rc = initialize(mIsType);
   4003         if (rc != NO_ERROR) {
   4004             LOGE("Couldn't initialize camera stream %d",
   4005                      rc);
   4006             return rc;
   4007         }
   4008     }
   4009 
   4010     streamType = mStreams[0]->getMyType();
   4011     rc = mGrallocMemory.registerBuffer(buffer, streamType);
   4012     if (ALREADY_EXISTS == rc) {
   4013         return NO_ERROR;
   4014     } else if (NO_ERROR != rc) {
   4015         LOGE("Buffer %p couldn't be registered %d", buffer, rc);
   4016         return rc;
   4017     }
   4018 
   4019     return rc;
   4020 }
   4021 
   4022 /*===========================================================================
   4023  * FUNCTION   : QCamera3ReprocessChannel
   4024  *
   4025  * DESCRIPTION: constructor of QCamera3ReprocessChannel
   4026  *
   4027  * PARAMETERS :
   4028  *   @cam_handle : camera handle
   4029  *   @cam_ops    : ptr to camera ops table
   4030  *   @pp_mask    : post-proccess feature mask
   4031  *
   4032  * RETURN     : none
   4033  *==========================================================================*/
   4034 void QCamera3ReprocessChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
   4035                                   QCamera3Stream *stream)
   4036 {
   4037     //Got the pproc data callback. Now send to jpeg encoding
   4038     uint8_t frameIndex;
   4039     uint32_t resultFrameNumber;
   4040     ATRACE_CALL();
   4041     mm_camera_super_buf_t* frame = NULL;
   4042     QCamera3ProcessingChannel *obj = (QCamera3ProcessingChannel *)inputChHandle;
   4043     cam_dimension_t dim;
   4044     cam_frame_len_offset_t offset;
   4045 
   4046     memset(&dim, 0, sizeof(dim));
   4047     memset(&offset, 0, sizeof(cam_frame_len_offset_t));
   4048     if(!super_frame) {
   4049          LOGE("Invalid Super buffer");
   4050          return;
   4051     }
   4052 
   4053     if(super_frame->num_bufs != 1) {
   4054          LOGE("Multiple streams are not supported");
   4055          return;
   4056     }
   4057     if(super_frame->bufs[0] == NULL ) {
   4058          LOGE("Error, Super buffer frame does not contain valid buffer");
   4059          return;
   4060     }
   4061     frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
   4062 
   4063 
   4064     if (mReprocessType == REPROCESS_TYPE_JPEG) {
   4065         resultFrameNumber =  mMemory->getFrameNumber(frameIndex);
   4066         frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
   4067         if (frame == NULL) {
   4068            LOGE("Error allocating memory to save received_frame structure.");
   4069            if(stream) {
   4070                stream->bufDone(frameIndex);
   4071            }
   4072            return;
   4073         }
   4074         LOGI("bufIndex: %u recvd from post proc",
   4075                  (uint32_t)frameIndex);
   4076         *frame = *super_frame;
   4077 
   4078         stream->getFrameDimension(dim);
   4079         stream->getFrameOffset(offset);
   4080         dumpYUV(frame->bufs[0], dim, offset, QCAMERA_DUMP_FRM_SNAPSHOT);
   4081         /* Since reprocessing is done, send the callback to release the input buffer */
   4082         // Release offline buffers.
   4083         obj->releaseOfflineMemory(resultFrameNumber);
   4084         if (mChannelCB) {
   4085             mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData);
   4086         }
   4087         obj->m_postprocessor.processPPData(frame);
   4088     } else {
   4089         buffer_handle_t *resultBuffer;
   4090         frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
   4091         resultBuffer = (buffer_handle_t *)mGrallocMemory.getBufferHandle(frameIndex);
   4092         resultFrameNumber = mGrallocMemory.getFrameNumber(frameIndex);
   4093         int32_t rc = stream->bufRelease(frameIndex);
   4094         if (NO_ERROR != rc) {
   4095             LOGE("Error %d releasing stream buffer %d",
   4096                      rc, frameIndex);
   4097         }
   4098         rc = mGrallocMemory.unregisterBuffer(frameIndex);
   4099         if (NO_ERROR != rc) {
   4100             LOGE("Error %d unregistering stream buffer %d",
   4101                      rc, frameIndex);
   4102         }
   4103         obj->reprocessCbRoutine(resultBuffer, resultFrameNumber);
   4104 
   4105         obj->m_postprocessor.releaseOfflineBuffers(false);
   4106         qcamera_hal3_pp_data_t *pp_job = obj->m_postprocessor.dequeuePPJob(resultFrameNumber);
   4107         if (pp_job != NULL) {
   4108             obj->m_postprocessor.releasePPJobData(pp_job);
   4109         }
   4110         free(pp_job);
   4111     }
   4112     resetToCamPerfNormal(resultFrameNumber);
   4113     free(super_frame);
   4114     return;
   4115 }
   4116 
   4117 /*===========================================================================
   4118  * FUNCTION   : resetToCamPerfNormal
   4119  *
   4120  * DESCRIPTION: Set the perf mode to normal if all the priority frames
   4121  *              have been reprocessed
   4122  *
   4123  * PARAMETERS :
   4124  *      @frameNumber: Frame number of the reprocess completed frame
   4125  *
   4126  * RETURN     : QCamera3StreamMem *
   4127  *==========================================================================*/
   4128 int32_t QCamera3ReprocessChannel::resetToCamPerfNormal(uint32_t frameNumber)
   4129 {
   4130     int32_t rc = NO_ERROR;
   4131     bool resetToPerfNormal = false;
   4132     {
   4133         Mutex::Autolock lock(mPriorityFramesLock);
   4134         /* remove the priority frame number from the list */
   4135         for (size_t i = 0; i < mPriorityFrames.size(); i++) {
   4136             if (mPriorityFrames[i] == frameNumber) {
   4137                 mPriorityFrames.removeAt(i);
   4138             }
   4139         }
   4140         /* reset the perf mode if pending priority frame list is empty */
   4141         if (mReprocessPerfMode && mPriorityFrames.empty()) {
   4142             resetToPerfNormal = true;
   4143         }
   4144     }
   4145     if (resetToPerfNormal) {
   4146         QCamera3Stream *pStream = mStreams[0];
   4147         cam_stream_parm_buffer_t param;
   4148         memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
   4149 
   4150         param.type = CAM_STREAM_PARAM_TYPE_REQUEST_OPS_MODE;
   4151         param.perf_mode = CAM_PERF_NORMAL;
   4152         rc = pStream->setParameter(param);
   4153         {
   4154             Mutex::Autolock lock(mPriorityFramesLock);
   4155             mReprocessPerfMode = false;
   4156         }
   4157     }
   4158     return rc;
   4159 }
   4160 
   4161 /*===========================================================================
   4162  * FUNCTION   : getStreamBufs
   4163  *
   4164  * DESCRIPTION: register the buffers of the reprocess channel
   4165  *
   4166  * PARAMETERS : none
   4167  *
   4168  * RETURN     : QCamera3StreamMem *
   4169  *==========================================================================*/
   4170 QCamera3StreamMem* QCamera3ReprocessChannel::getStreamBufs(uint32_t len)
   4171 {
   4172     if (mReprocessType == REPROCESS_TYPE_JPEG) {
   4173         mMemory = new QCamera3StreamMem(mNumBuffers, false);
   4174         if (!mMemory) {
   4175             LOGE("unable to create reproc memory");
   4176             return NULL;
   4177         }
   4178         mFrameLen = len;
   4179         return mMemory;
   4180     }
   4181     return &mGrallocMemory;
   4182 }
   4183 
   4184 /*===========================================================================
   4185  * FUNCTION   : putStreamBufs
   4186  *
   4187  * DESCRIPTION: release the reprocess channel buffers
   4188  *
   4189  * PARAMETERS : none
   4190  *
   4191  * RETURN     :
   4192  *==========================================================================*/
   4193 void QCamera3ReprocessChannel::putStreamBufs()
   4194 {
   4195    if (mReprocessType == REPROCESS_TYPE_JPEG) {
   4196        mMemory->deallocate();
   4197        delete mMemory;
   4198        mMemory = NULL;
   4199        mFreeBufferList.clear();
   4200    } else {
   4201        mGrallocMemory.unregisterBuffers();
   4202    }
   4203 }
   4204 
   4205 /*===========================================================================
   4206  * FUNCTION   : ~QCamera3ReprocessChannel
   4207  *
   4208  * DESCRIPTION: destructor of QCamera3ReprocessChannel
   4209  *
   4210  * PARAMETERS : none
   4211  *
   4212  * RETURN     : none
   4213  *==========================================================================*/
   4214 QCamera3ReprocessChannel::~QCamera3ReprocessChannel()
   4215 {
   4216     destroy();
   4217 
   4218     if (m_handle) {
   4219         m_camOps->delete_channel(m_camHandle, m_handle);
   4220         LOGD("deleting channel %d", m_handle);
   4221         m_handle = 0;
   4222     }
   4223 }
   4224 
   4225 /*===========================================================================
   4226  * FUNCTION   : start
   4227  *
   4228  * DESCRIPTION: start reprocess channel.
   4229  *
   4230  * PARAMETERS :
   4231  *
   4232  * RETURN     : int32_t type of status
   4233  *              NO_ERROR  -- success
   4234  *              none-zero failure code
   4235  *==========================================================================*/
   4236 int32_t QCamera3ReprocessChannel::start()
   4237 {
   4238     ATRACE_CALL();
   4239     int32_t rc = NO_ERROR;
   4240 
   4241     rc = QCamera3Channel::start();
   4242 
   4243     if (rc == NO_ERROR) {
   4244        rc = m_camOps->start_channel(m_camHandle, m_handle);
   4245 
   4246        // Check failure
   4247        if (rc != NO_ERROR) {
   4248            LOGE("start_channel failed %d", rc);
   4249            QCamera3Channel::stop();
   4250        }
   4251     }
   4252     return rc;
   4253 }
   4254 
   4255 /*===========================================================================
   4256  * FUNCTION   : stop
   4257  *
   4258  * DESCRIPTION: stop reprocess channel.
   4259  *
   4260  * PARAMETERS : none
   4261  *
   4262  * RETURN     : int32_t type of status
   4263  *              NO_ERROR  -- success
   4264  *              none-zero failure code
   4265  *==========================================================================*/
   4266 int32_t QCamera3ReprocessChannel::stop()
   4267 {
   4268     ATRACE_CALL();
   4269     int32_t rc = NO_ERROR;
   4270 
   4271     rc = QCamera3Channel::stop();
   4272     unmapOfflineBuffers(true);
   4273 
   4274     rc |= m_camOps->stop_channel(m_camHandle, m_handle);
   4275 
   4276     return rc;
   4277 }
   4278 
   4279 /*===========================================================================
   4280  * FUNCTION   : getStreamBySrcHandle
   4281  *
   4282  * DESCRIPTION: find reprocess stream by its source stream handle
   4283  *
   4284  * PARAMETERS :
   4285  *   @srcHandle : source stream handle
   4286  *
   4287  * RETURN     : ptr to reprocess stream if found. NULL if not found
   4288  *==========================================================================*/
   4289 QCamera3Stream * QCamera3ReprocessChannel::getStreamBySrcHandle(uint32_t srcHandle)
   4290 {
   4291     QCamera3Stream *pStream = NULL;
   4292 
   4293     for (uint32_t i = 0; i < m_numStreams; i++) {
   4294         if (mSrcStreamHandles[i] == srcHandle) {
   4295             pStream = mStreams[i];
   4296             break;
   4297         }
   4298     }
   4299     return pStream;
   4300 }
   4301 
   4302 /*===========================================================================
   4303  * FUNCTION   : getSrcStreamBySrcHandle
   4304  *
   4305  * DESCRIPTION: find source stream by source stream handle
   4306  *
   4307  * PARAMETERS :
   4308  *   @srcHandle : source stream handle
   4309  *
   4310  * RETURN     : ptr to reprocess stream if found. NULL if not found
   4311  *==========================================================================*/
   4312 QCamera3Stream * QCamera3ReprocessChannel::getSrcStreamBySrcHandle(uint32_t srcHandle)
   4313 {
   4314     QCamera3Stream *pStream = NULL;
   4315 
   4316     if (NULL == m_pSrcChannel) {
   4317         return NULL;
   4318     }
   4319 
   4320     for (uint32_t i = 0; i < m_numStreams; i++) {
   4321         if (mSrcStreamHandles[i] == srcHandle) {
   4322             pStream = m_pSrcChannel->getStreamByIndex(i);
   4323             break;
   4324         }
   4325     }
   4326     return pStream;
   4327 }
   4328 
   4329 /*===========================================================================
   4330  * FUNCTION   : unmapOfflineBuffers
   4331  *
   4332  * DESCRIPTION: Unmaps offline buffers
   4333  *
   4334  * PARAMETERS : none
   4335  *
   4336  * RETURN     : int32_t type of status
   4337  *              NO_ERROR  -- success
   4338  *              none-zero failure code
   4339  *==========================================================================*/
   4340 int32_t QCamera3ReprocessChannel::unmapOfflineBuffers(bool all)
   4341 {
   4342     int rc = NO_ERROR;
   4343     Mutex::Autolock l(mOfflineBuffersLock);
   4344     if (!mOfflineBuffers.empty()) {
   4345         QCamera3Stream *stream = NULL;
   4346         List<OfflineBuffer>::iterator it = mOfflineBuffers.begin();
   4347         for (; it != mOfflineBuffers.end(); it++) {
   4348            stream = (*it).stream;
   4349            if (NULL != stream) {
   4350                rc = stream->unmapBuf((*it).type,
   4351                                      (*it).index,
   4352                                         -1);
   4353                if (NO_ERROR != rc) {
   4354                    LOGE("Error during offline buffer unmap %d",
   4355                           rc);
   4356                }
   4357                LOGD("Unmapped buffer with index %d", (*it).index);
   4358            }
   4359            if (!all) {
   4360                mOfflineBuffers.erase(it);
   4361                break;
   4362            }
   4363         }
   4364         if (all) {
   4365            mOfflineBuffers.clear();
   4366         }
   4367     }
   4368 
   4369     if (!mOfflineMetaBuffers.empty()) {
   4370         QCamera3Stream *stream = NULL;
   4371         List<OfflineBuffer>::iterator it = mOfflineMetaBuffers.begin();
   4372         for (; it != mOfflineMetaBuffers.end(); it++) {
   4373            stream = (*it).stream;
   4374            if (NULL != stream) {
   4375                rc = stream->unmapBuf((*it).type,
   4376                                      (*it).index,
   4377                                         -1);
   4378                if (NO_ERROR != rc) {
   4379                    LOGE("Error during offline buffer unmap %d",
   4380                           rc);
   4381                }
   4382                LOGD("Unmapped meta buffer with index %d", (*it).index);
   4383            }
   4384            if (!all) {
   4385                mOfflineMetaBuffers.erase(it);
   4386                break;
   4387            }
   4388         }
   4389         if (all) {
   4390            mOfflineMetaBuffers.clear();
   4391         }
   4392     }
   4393     return rc;
   4394 }
   4395 
   4396 /*===========================================================================
   4397  * FUNCTION   : bufDone
   4398  *
   4399  * DESCRIPTION: Return reprocess stream buffer to free buffer list.
   4400  *              Note that this function doesn't queue buffer back to kernel.
   4401  *              It's up to doReprocessOffline to do that instead.
   4402  * PARAMETERS :
   4403  *   @recvd_frame  : stream buf frame to be returned
   4404  *
   4405  * RETURN     : int32_t type of status
   4406  *              NO_ERROR  -- success
   4407  *              none-zero failure code
   4408  *==========================================================================*/
   4409 int32_t QCamera3ReprocessChannel::bufDone(mm_camera_super_buf_t *recvd_frame)
   4410 {
   4411     int rc = NO_ERROR;
   4412     if (recvd_frame && recvd_frame->num_bufs == 1) {
   4413         Mutex::Autolock lock(mFreeBuffersLock);
   4414         uint32_t buf_idx = recvd_frame->bufs[0]->buf_idx;
   4415         mFreeBufferList.push_back(buf_idx);
   4416 
   4417     } else {
   4418         LOGE("Fatal. Not supposed to be here");
   4419         rc = BAD_VALUE;
   4420     }
   4421 
   4422     return rc;
   4423 }
   4424 
   4425 /*===========================================================================
   4426  * FUNCTION   : overrideMetadata
   4427  *
   4428  * DESCRIPTION: Override metadata entry such as rotation, crop, and CDS info.
   4429  *
   4430  * PARAMETERS :
   4431  *   @frame     : input frame from source stream
   4432  *   meta_buffer: metadata buffer
   4433  *   @metadata  : corresponding metadata
   4434  *   @fwk_frame :
   4435  *
   4436  * RETURN     : int32_t type of status
   4437  *              NO_ERROR  -- success
   4438  *              none-zero failure code
   4439  *==========================================================================*/
   4440 int32_t QCamera3ReprocessChannel::overrideMetadata(qcamera_hal3_pp_buffer_t *pp_buffer,
   4441         mm_camera_buf_def_t *meta_buffer, jpeg_settings_t *jpeg_settings,
   4442         qcamera_fwk_input_pp_data_t &fwk_frame)
   4443 {
   4444     int32_t rc = NO_ERROR;
   4445     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
   4446     if ((NULL == meta_buffer) || (NULL == pp_buffer) || (NULL == pp_buffer->input) ||
   4447             (NULL == hal_obj)) {
   4448         return BAD_VALUE;
   4449     }
   4450 
   4451     metadata_buffer_t *meta = (metadata_buffer_t *)meta_buffer->buffer;
   4452     mm_camera_super_buf_t *frame = pp_buffer->input;
   4453     if (NULL == meta) {
   4454         return BAD_VALUE;
   4455     }
   4456 
   4457     for (uint32_t i = 0; i < frame->num_bufs; i++) {
   4458         QCamera3Stream *pStream = getStreamBySrcHandle(frame->bufs[i]->stream_id);
   4459         QCamera3Stream *pSrcStream = getSrcStreamBySrcHandle(frame->bufs[i]->stream_id);
   4460 
   4461         if (pStream != NULL && pSrcStream != NULL) {
   4462             if (jpeg_settings) {
   4463                 // Find rotation info for reprocess stream
   4464                 cam_rotation_info_t rotation_info;
   4465                 memset(&rotation_info, 0, sizeof(rotation_info));
   4466                 if (jpeg_settings->jpeg_orientation == 0) {
   4467                    rotation_info.rotation = ROTATE_0;
   4468                 } else if (jpeg_settings->jpeg_orientation == 90) {
   4469                    rotation_info.rotation = ROTATE_90;
   4470                 } else if (jpeg_settings->jpeg_orientation == 180) {
   4471                    rotation_info.rotation = ROTATE_180;
   4472                 } else if (jpeg_settings->jpeg_orientation == 270) {
   4473                    rotation_info.rotation = ROTATE_270;
   4474                 }
   4475                 rotation_info.device_rotation = ROTATE_0;
   4476                 rotation_info.streamId = mStreams[0]->getMyServerID();
   4477                 ADD_SET_PARAM_ENTRY_TO_BATCH(meta, CAM_INTF_PARM_ROTATION, rotation_info);
   4478             }
   4479 
   4480             // Find and insert crop info for reprocess stream
   4481             IF_META_AVAILABLE(cam_crop_data_t, crop_data, CAM_INTF_META_CROP_DATA, meta) {
   4482                 if (MAX_NUM_STREAMS > crop_data->num_of_streams) {
   4483                     for (int j = 0; j < crop_data->num_of_streams; j++) {
   4484                         if (crop_data->crop_info[j].stream_id ==
   4485                                 pSrcStream->getMyServerID()) {
   4486 
   4487                             // Store crop/roi information for offline reprocess
   4488                             // in the reprocess stream slot
   4489                             crop_data->crop_info[crop_data->num_of_streams].crop =
   4490                                     crop_data->crop_info[j].crop;
   4491                             crop_data->crop_info[crop_data->num_of_streams].roi_map =
   4492                                     crop_data->crop_info[j].roi_map;
   4493                             crop_data->crop_info[crop_data->num_of_streams].stream_id =
   4494                                     mStreams[0]->getMyServerID();
   4495                             crop_data->num_of_streams++;
   4496 
   4497                             LOGD("Reprocess stream server id: %d",
   4498                                      mStreams[0]->getMyServerID());
   4499                             LOGD("Found offline reprocess crop %dx%d %dx%d",
   4500                                     crop_data->crop_info[j].crop.left,
   4501                                     crop_data->crop_info[j].crop.top,
   4502                                     crop_data->crop_info[j].crop.width,
   4503                                     crop_data->crop_info[j].crop.height);
   4504                             LOGD("Found offline reprocess roimap %dx%d %dx%d",
   4505                                     crop_data->crop_info[j].roi_map.left,
   4506                                     crop_data->crop_info[j].roi_map.top,
   4507                                     crop_data->crop_info[j].roi_map.width,
   4508                                     crop_data->crop_info[j].roi_map.height);
   4509 
   4510                             break;
   4511                         }
   4512                     }
   4513                 } else {
   4514                     LOGE("No space to add reprocess stream crop/roi information");
   4515                 }
   4516             }
   4517 
   4518             IF_META_AVAILABLE(cam_cds_data_t, cdsInfo, CAM_INTF_META_CDS_DATA, meta) {
   4519                 uint8_t cnt = cdsInfo->num_of_streams;
   4520                 if (cnt <= MAX_NUM_STREAMS) {
   4521                     cam_stream_cds_info_t repro_cds_info;
   4522                     memset(&repro_cds_info, 0, sizeof(repro_cds_info));
   4523                     repro_cds_info.stream_id = mStreams[0]->getMyServerID();
   4524                     for (size_t i = 0; i < cnt; i++) {
   4525                         if (cdsInfo->cds_info[i].stream_id ==
   4526                                 pSrcStream->getMyServerID()) {
   4527                             repro_cds_info.cds_enable =
   4528                                     cdsInfo->cds_info[i].cds_enable;
   4529                             break;
   4530                         }
   4531                     }
   4532                     cdsInfo->num_of_streams = 1;
   4533                     cdsInfo->cds_info[0] = repro_cds_info;
   4534                 } else {
   4535                     LOGE("No space to add reprocess stream cds information");
   4536                 }
   4537             }
   4538 
   4539             fwk_frame.input_buffer = *frame->bufs[i];
   4540             fwk_frame.metadata_buffer = *meta_buffer;
   4541             fwk_frame.output_buffer = pp_buffer->output;
   4542             break;
   4543         } else {
   4544             LOGE("Source/Re-process streams are invalid");
   4545             rc |= BAD_VALUE;
   4546         }
   4547     }
   4548 
   4549     return rc;
   4550 }
   4551 
   4552 /*===========================================================================
   4553 * FUNCTION : overrideFwkMetadata
   4554 *
   4555 * DESCRIPTION: Override frameworks metadata such as crop, and CDS data.
   4556 *
   4557 * PARAMETERS :
   4558 * @frame : input frame for reprocessing
   4559 *
   4560 * RETURN : int32_t type of status
   4561 * NO_ERROR -- success
   4562 * none-zero failure code
   4563 *==========================================================================*/
   4564 int32_t QCamera3ReprocessChannel::overrideFwkMetadata(
   4565         qcamera_fwk_input_pp_data_t *frame)
   4566 {
   4567     if (NULL == frame) {
   4568         LOGE("Incorrect input frame");
   4569         return BAD_VALUE;
   4570     }
   4571 
   4572     if (NULL == frame->metadata_buffer.buffer) {
   4573         LOGE("No metadata available");
   4574         return BAD_VALUE;
   4575     }
   4576 
   4577     // Find and insert crop info for reprocess stream
   4578     metadata_buffer_t *meta = (metadata_buffer_t *) frame->metadata_buffer.buffer;
   4579     IF_META_AVAILABLE(cam_crop_data_t, crop_data, CAM_INTF_META_CROP_DATA, meta) {
   4580         if (1 == crop_data->num_of_streams) {
   4581             // Store crop/roi information for offline reprocess
   4582             // in the reprocess stream slot
   4583             crop_data->crop_info[crop_data->num_of_streams].crop =
   4584                     crop_data->crop_info[0].crop;
   4585             crop_data->crop_info[crop_data->num_of_streams].roi_map =
   4586                     crop_data->crop_info[0].roi_map;
   4587             crop_data->crop_info[crop_data->num_of_streams].stream_id =
   4588                     mStreams[0]->getMyServerID();
   4589             crop_data->num_of_streams++;
   4590 
   4591             LOGD("Reprocess stream server id: %d",
   4592                      mStreams[0]->getMyServerID());
   4593             LOGD("Found offline reprocess crop %dx%d %dx%d",
   4594                     crop_data->crop_info[0].crop.left,
   4595                     crop_data->crop_info[0].crop.top,
   4596                     crop_data->crop_info[0].crop.width,
   4597                     crop_data->crop_info[0].crop.height);
   4598             LOGD("Found offline reprocess roi map %dx%d %dx%d",
   4599                     crop_data->crop_info[0].roi_map.left,
   4600                     crop_data->crop_info[0].roi_map.top,
   4601                     crop_data->crop_info[0].roi_map.width,
   4602                     crop_data->crop_info[0].roi_map.height);
   4603         } else {
   4604             LOGE("Incorrect number of offline crop data entries %d",
   4605                     crop_data->num_of_streams);
   4606             return BAD_VALUE;
   4607         }
   4608     } else {
   4609         LOGW("Crop data not present");
   4610     }
   4611 
   4612     IF_META_AVAILABLE(cam_cds_data_t, cdsInfo, CAM_INTF_META_CDS_DATA, meta) {
   4613         if (1 == cdsInfo->num_of_streams) {
   4614             cdsInfo->cds_info[0].stream_id = mStreams[0]->getMyServerID();
   4615         } else {
   4616             LOGE("Incorrect number of offline cds info entries %d",
   4617                      cdsInfo->num_of_streams);
   4618             return BAD_VALUE;
   4619         }
   4620     }
   4621 
   4622     return NO_ERROR;
   4623 }
   4624 
   4625 /*===========================================================================
   4626  * FUNCTION   : doReprocessOffline
   4627  *
   4628  * DESCRIPTION: request to do a reprocess on the frame
   4629  *
   4630  * PARAMETERS :
   4631  *   @frame     : input frame for reprocessing
   4632  *   @isPriorityFrame: Hint that this frame is of priority, equivalent to
   4633  *              real time, even though it is processed in offline mechanism
   4634  *
   4635  * RETURN     : int32_t type of status
   4636  *              NO_ERROR  -- success
   4637  *              none-zero failure code
   4638  *==========================================================================*/
   4639  int32_t  QCamera3ReprocessChannel::doReprocessOffline(
   4640         qcamera_fwk_input_pp_data_t *frame, bool isPriorityFrame)
   4641 {
   4642     int32_t rc = 0;
   4643     int index;
   4644     OfflineBuffer mappedBuffer;
   4645     ATRACE_CALL();
   4646 
   4647     if (m_numStreams < 1) {
   4648         LOGE("No reprocess stream is created");
   4649         return -1;
   4650     }
   4651 
   4652     if (NULL == frame) {
   4653         LOGE("Incorrect input frame");
   4654         return BAD_VALUE;
   4655     }
   4656 
   4657     if (NULL == frame->metadata_buffer.buffer) {
   4658         LOGE("No metadata available");
   4659         return BAD_VALUE;
   4660     }
   4661 
   4662     if (NULL == frame->input_buffer.buffer) {
   4663         LOGE("No input buffer available");
   4664         return BAD_VALUE;
   4665     }
   4666 
   4667     if ((0 == m_numStreams) || (NULL == mStreams[0])) {
   4668         LOGE("Reprocess stream not initialized!");
   4669         return NO_INIT;
   4670     }
   4671 
   4672     QCamera3Stream *pStream = mStreams[0];
   4673 
   4674     //qbuf the output buffer if it was allocated by the framework
   4675     if (mReprocessType != REPROCESS_TYPE_JPEG && frame->output_buffer != NULL) {
   4676         if(!m_bIsActive) {
   4677             rc = registerBuffer(frame->output_buffer, mIsType);
   4678             if (NO_ERROR != rc) {
   4679                 LOGE("On-the-fly buffer registration failed %d",
   4680                          rc);
   4681                 return rc;
   4682             }
   4683 
   4684             rc = start();
   4685             if (NO_ERROR != rc) {
   4686                 return rc;
   4687             }
   4688         }
   4689         index = mGrallocMemory.getMatchBufIndex((void*)frame->output_buffer);
   4690         if(index < 0) {
   4691             rc = registerBuffer(frame->output_buffer, mIsType);
   4692             if (NO_ERROR != rc) {
   4693                 LOGE("On-the-fly buffer registration failed %d",
   4694                          rc);
   4695                 return rc;
   4696             }
   4697 
   4698             index = mGrallocMemory.getMatchBufIndex((void*)frame->output_buffer);
   4699             if (index < 0) {
   4700                 LOGE("Could not find object among registered buffers");
   4701                 return DEAD_OBJECT;
   4702             }
   4703         }
   4704         rc = mGrallocMemory.markFrameNumber(index, frame->frameNumber);
   4705         if(rc != NO_ERROR) {
   4706             LOGE("Failed to mark frame#:%d, index:%d",frame->frameNumber,index);
   4707             return rc;
   4708         }
   4709         rc = pStream->bufDone(index);
   4710         if(rc != NO_ERROR) {
   4711             LOGE("Failed to Q new buffer to stream");
   4712             mGrallocMemory.markFrameNumber(index, -1);
   4713             return rc;
   4714         }
   4715 
   4716     } else if (mReprocessType == REPROCESS_TYPE_JPEG) {
   4717         Mutex::Autolock lock(mFreeBuffersLock);
   4718         uint32_t bufIdx;
   4719         if (mFreeBufferList.empty()) {
   4720             rc = mMemory->allocateOne(mFrameLen);
   4721             if (rc < 0) {
   4722                 LOGE("Failed allocating heap buffer. Fatal");
   4723                 return BAD_VALUE;
   4724             } else {
   4725                 bufIdx = (uint32_t)rc;
   4726             }
   4727         } else {
   4728             bufIdx = *(mFreeBufferList.begin());
   4729             mFreeBufferList.erase(mFreeBufferList.begin());
   4730         }
   4731 
   4732         mMemory->markFrameNumber(bufIdx, frame->frameNumber);
   4733         rc = pStream->bufDone(bufIdx);
   4734         if (rc != NO_ERROR) {
   4735             LOGE("Failed to queue new buffer to stream");
   4736             return rc;
   4737         }
   4738     }
   4739 
   4740     int32_t max_idx = (int32_t) (mNumBuffers - 1);
   4741     //loop back the indices if max burst count reached
   4742     if (mOfflineBuffersIndex == max_idx) {
   4743        mOfflineBuffersIndex = -1;
   4744     }
   4745     uint32_t buf_idx = (uint32_t)(mOfflineBuffersIndex + 1);
   4746 
   4747     //Do cache ops before sending for reprocess
   4748     if (mMemory != NULL) {
   4749         mMemory->cleanInvalidateCache(buf_idx);
   4750     }
   4751 
   4752     rc = pStream->mapBuf(
   4753             CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
   4754             buf_idx, -1,
   4755             frame->input_buffer.fd, frame->input_buffer.buffer,
   4756             frame->input_buffer.frame_len);
   4757     if (NO_ERROR == rc) {
   4758         Mutex::Autolock l(mOfflineBuffersLock);
   4759         mappedBuffer.index = buf_idx;
   4760         mappedBuffer.stream = pStream;
   4761         mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF;
   4762         mOfflineBuffers.push_back(mappedBuffer);
   4763         mOfflineBuffersIndex = (int32_t)buf_idx;
   4764         LOGD("Mapped buffer with index %d", mOfflineBuffersIndex);
   4765     }
   4766 
   4767     max_idx = (int32_t) ((mNumBuffers * 2) - 1);
   4768     //loop back the indices if max burst count reached
   4769     if (mOfflineMetaIndex == max_idx) {
   4770        mOfflineMetaIndex = (int32_t) (mNumBuffers - 1);
   4771     }
   4772     uint32_t meta_buf_idx = (uint32_t)(mOfflineMetaIndex + 1);
   4773     rc |= pStream->mapBuf(
   4774             CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF,
   4775             meta_buf_idx, -1,
   4776             frame->metadata_buffer.fd, frame->metadata_buffer.buffer,
   4777             frame->metadata_buffer.frame_len);
   4778     if (NO_ERROR == rc) {
   4779         Mutex::Autolock l(mOfflineBuffersLock);
   4780         mappedBuffer.index = meta_buf_idx;
   4781         mappedBuffer.stream = pStream;
   4782         mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF;
   4783         mOfflineMetaBuffers.push_back(mappedBuffer);
   4784         mOfflineMetaIndex = (int32_t)meta_buf_idx;
   4785         LOGD("Mapped meta buffer with index %d", mOfflineMetaIndex);
   4786     }
   4787 
   4788     if (rc == NO_ERROR) {
   4789         cam_stream_parm_buffer_t param;
   4790         uint32_t numPendingPriorityFrames = 0;
   4791 
   4792         if(isPriorityFrame) {
   4793             Mutex::Autolock lock(mPriorityFramesLock);
   4794             /* read the length before pushing the frame number to check if
   4795              * vector is empty */
   4796             numPendingPriorityFrames = mPriorityFrames.size();
   4797             mPriorityFrames.push(frame->frameNumber);
   4798         }
   4799 
   4800         if(isPriorityFrame && !numPendingPriorityFrames) {
   4801             memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
   4802             param.type = CAM_STREAM_PARAM_TYPE_REQUEST_OPS_MODE;
   4803             param.perf_mode = CAM_PERF_HIGH_PERFORMANCE;
   4804             rc = pStream->setParameter(param);
   4805 
   4806             if (rc != NO_ERROR) {
   4807                 ALOGE("%s: setParameter for CAM_PERF_HIGH_PERFORMANCE failed",
   4808                     __func__);
   4809             }
   4810             {
   4811                 Mutex::Autolock lock(mPriorityFramesLock);
   4812                 mReprocessPerfMode = true;
   4813             }
   4814         }
   4815 
   4816         memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
   4817         param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
   4818         param.reprocess.buf_index = buf_idx;
   4819         param.reprocess.frame_idx = frame->input_buffer.frame_idx;
   4820         param.reprocess.meta_present = 1;
   4821         param.reprocess.meta_buf_index = meta_buf_idx;
   4822 
   4823         LOGI("Offline reprocessing id = %d buf Id = %d meta index = %d",
   4824                     param.reprocess.frame_idx, param.reprocess.buf_index,
   4825                     param.reprocess.meta_buf_index);
   4826         rc = pStream->setParameter(param);
   4827         if (rc != NO_ERROR) {
   4828             LOGE("stream setParameter for reprocess failed");
   4829             resetToCamPerfNormal(frame->frameNumber);
   4830         }
   4831     } else {
   4832         LOGE("Input buffer memory map failed: %d", rc);
   4833     }
   4834 
   4835     return rc;
   4836 }
   4837 
   4838 /*===========================================================================
   4839  * FUNCTION   : doReprocess
   4840  *
   4841  * DESCRIPTION: request to do a reprocess on the frame
   4842  *
   4843  * PARAMETERS :
   4844  *   @buf_fd     : fd to the input buffer that needs reprocess
   4845  *   @buffer     : Buffer ptr
   4846  *   @buf_lenght : length of the input buffer
   4847  *   @ret_val    : result of reprocess.
   4848  *                 Example: Could be faceID in case of register face image.
   4849  *   @meta_frame : metadata frame.
   4850  *
   4851  * RETURN     : int32_t type of status
   4852  *              NO_ERROR  -- success
   4853  *              none-zero failure code
   4854  *==========================================================================*/
   4855 int32_t QCamera3ReprocessChannel::doReprocess(int buf_fd, void *buffer, size_t buf_length,
   4856         int32_t &ret_val, mm_camera_super_buf_t *meta_frame)
   4857 {
   4858     int32_t rc = 0;
   4859     if (m_numStreams < 1) {
   4860         LOGE("No reprocess stream is created");
   4861         return -1;
   4862     }
   4863     if (meta_frame == NULL) {
   4864         LOGE("Did not get corresponding metadata in time");
   4865         return -1;
   4866     }
   4867 
   4868     uint8_t buf_idx = 0;
   4869     for (uint32_t i = 0; i < m_numStreams; i++) {
   4870         rc = mStreams[i]->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
   4871                                  buf_idx, -1,
   4872                                  buf_fd, buffer, buf_length);
   4873 
   4874         //Do cache ops before sending for reprocess
   4875         if (mMemory != NULL) {
   4876             mMemory->cleanInvalidateCache(buf_idx);
   4877         }
   4878 
   4879         if (rc == NO_ERROR) {
   4880             cam_stream_parm_buffer_t param;
   4881             memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
   4882             param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
   4883             param.reprocess.buf_index = buf_idx;
   4884             param.reprocess.meta_present = 1;
   4885             param.reprocess.meta_stream_handle = m_pMetaChannel->mStreams[0]->getMyServerID();
   4886             param.reprocess.meta_buf_index = meta_frame->bufs[0]->buf_idx;
   4887 
   4888             LOGI("Online reprocessing id = %d buf Id = %d meta index = %d",
   4889                     param.reprocess.frame_idx, param.reprocess.buf_index,
   4890                     param.reprocess.meta_buf_index);
   4891             rc = mStreams[i]->setParameter(param);
   4892             if (rc == NO_ERROR) {
   4893                 ret_val = param.reprocess.ret_val;
   4894             }
   4895             mStreams[i]->unmapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
   4896                                   buf_idx, -1);
   4897         }
   4898     }
   4899     return rc;
   4900 }
   4901 
   4902 /*===========================================================================
   4903  * FUNCTION   : addReprocStreamsFromSource
   4904  *
   4905  * DESCRIPTION: add reprocess streams from input source channel
   4906  *
   4907  * PARAMETERS :
   4908  *   @config         : pp feature configuration
   4909  *   @src_config     : source reprocess configuration
   4910  *   @isType         : type of image stabilization required on this stream
   4911  *   @pMetaChannel   : ptr to metadata channel to get corresp. metadata
   4912  *
   4913  *
   4914  * RETURN     : int32_t type of status
   4915  *              NO_ERROR  -- success
   4916  *              none-zero failure code
   4917  *==========================================================================*/
   4918 int32_t QCamera3ReprocessChannel::addReprocStreamsFromSource(cam_pp_feature_config_t &pp_config,
   4919         const reprocess_config_t &src_config , cam_is_type_t is_type,
   4920         QCamera3Channel *pMetaChannel)
   4921 {
   4922     int32_t rc = 0;
   4923     cam_stream_reproc_config_t reprocess_config;
   4924     cam_stream_type_t streamType;
   4925 
   4926     cam_dimension_t streamDim = src_config.output_stream_dim;
   4927 
   4928     if (NULL != src_config.src_channel) {
   4929         QCamera3Stream *pSrcStream = src_config.src_channel->getStreamByIndex(0);
   4930         if (pSrcStream == NULL) {
   4931            LOGE("source channel doesn't have a stream");
   4932            return BAD_VALUE;
   4933         }
   4934         mSrcStreamHandles[m_numStreams] = pSrcStream->getMyHandle();
   4935     }
   4936 
   4937     streamType = CAM_STREAM_TYPE_OFFLINE_PROC;
   4938     reprocess_config.pp_type = CAM_OFFLINE_REPROCESS_TYPE;
   4939 
   4940     reprocess_config.offline.input_fmt = src_config.stream_format;
   4941     reprocess_config.offline.input_dim = src_config.input_stream_dim;
   4942     reprocess_config.offline.input_buf_planes.plane_info =
   4943             src_config.input_stream_plane_info.plane_info;
   4944     reprocess_config.offline.num_of_bufs = (uint8_t)mNumBuffers;
   4945     reprocess_config.offline.input_type = src_config.stream_type;
   4946 
   4947     reprocess_config.pp_feature_config = pp_config;
   4948     QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
   4949             m_handle,
   4950             m_camOps,
   4951             &mPaddingInfo,
   4952             (QCamera3Channel*)this);
   4953     if (pStream == NULL) {
   4954         LOGE("No mem for Stream");
   4955         return NO_MEMORY;
   4956     }
   4957 
   4958     rc = pStream->init(streamType, src_config.stream_format,
   4959             streamDim, ROTATE_0, &reprocess_config,
   4960             (uint8_t)mNumBuffers,
   4961             reprocess_config.pp_feature_config.feature_mask,
   4962             is_type,
   4963             0,/* batchSize */
   4964             QCamera3Channel::streamCbRoutine, this);
   4965 
   4966     if (rc == 0) {
   4967         mStreams[m_numStreams] = pStream;
   4968         m_numStreams++;
   4969     } else {
   4970         LOGE("failed to create reprocess stream");
   4971         delete pStream;
   4972     }
   4973 
   4974     if (rc == NO_ERROR) {
   4975         m_pSrcChannel = src_config.src_channel;
   4976         m_pMetaChannel = pMetaChannel;
   4977         mReprocessType = src_config.reprocess_type;
   4978         LOGD("mReprocessType is %d", mReprocessType);
   4979     }
   4980     mm_camera_req_buf_t buf;
   4981     memset(&buf, 0x0, sizeof(buf));
   4982     buf.type = MM_CAMERA_REQ_SUPER_BUF;
   4983     buf.num_buf_requested = 1;
   4984     if(m_camOps->request_super_buf(m_camHandle,m_handle, &buf) < 0) {
   4985         LOGE("Request for super buffer failed");
   4986     }
   4987     return rc;
   4988 }
   4989 
   4990 /* QCamera3SupportChannel methods */
   4991 
   4992 cam_dimension_t QCamera3SupportChannel::kDim = {640, 480};
   4993 
   4994 QCamera3SupportChannel::QCamera3SupportChannel(uint32_t cam_handle,
   4995                     uint32_t channel_handle,
   4996                     mm_camera_ops_t *cam_ops,
   4997                     cam_padding_info_t *paddingInfo,
   4998                     cam_feature_mask_t postprocess_mask,
   4999                     cam_stream_type_t streamType,
   5000                     cam_dimension_t *dim,
   5001                     cam_format_t streamFormat,
   5002                     uint8_t hw_analysis_supported,
   5003                     void *userData, uint32_t numBuffers) :
   5004                         QCamera3Channel(cam_handle, channel_handle, cam_ops,
   5005                                 NULL, NULL, paddingInfo, postprocess_mask,
   5006                                 userData, numBuffers),
   5007                         mMemory(NULL)
   5008 {
   5009     memcpy(&mDim, dim, sizeof(cam_dimension_t));
   5010     mStreamType = streamType;
   5011     mStreamFormat = streamFormat;
   5012    // Make Analysis same as Preview format
   5013    if (!hw_analysis_supported && mStreamType == CAM_STREAM_TYPE_ANALYSIS) {
   5014         mStreamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_PREVIEW,
   5015                 dim->width, dim->height);
   5016    }
   5017 }
   5018 
   5019 QCamera3SupportChannel::~QCamera3SupportChannel()
   5020 {
   5021     destroy();
   5022 
   5023     if (mMemory) {
   5024         mMemory->deallocate();
   5025         delete mMemory;
   5026         mMemory = NULL;
   5027     }
   5028 }
   5029 
   5030 int32_t QCamera3SupportChannel::initialize(cam_is_type_t isType)
   5031 {
   5032     int32_t rc;
   5033 
   5034     if (mMemory || m_numStreams > 0) {
   5035         LOGE("metadata channel already initialized");
   5036         return -EINVAL;
   5037     }
   5038 
   5039     mIsType = isType;
   5040     rc = QCamera3Channel::addStream(mStreamType,
   5041             mStreamFormat, mDim, ROTATE_0, MIN_STREAMING_BUFFER_NUM,
   5042             mPostProcMask, mIsType);
   5043     if (rc < 0) {
   5044         LOGE("addStream failed");
   5045     }
   5046     return rc;
   5047 }
   5048 
   5049 int32_t QCamera3SupportChannel::request(buffer_handle_t * /*buffer*/,
   5050                                                 uint32_t /*frameNumber*/,
   5051                                                 int & /*indexUsed*/)
   5052 {
   5053     return NO_ERROR;
   5054 }
   5055 
   5056 void QCamera3SupportChannel::streamCbRoutine(
   5057                         mm_camera_super_buf_t *super_frame,
   5058                         QCamera3Stream * /*stream*/)
   5059 {
   5060     if (super_frame == NULL || super_frame->num_bufs != 1) {
   5061         LOGE("super_frame is not valid");
   5062         return;
   5063     }
   5064     bufDone(super_frame);
   5065     free(super_frame);
   5066 }
   5067 
   5068 QCamera3StreamMem* QCamera3SupportChannel::getStreamBufs(uint32_t len)
   5069 {
   5070     int rc;
   5071     mMemory = new QCamera3StreamMem(mNumBuffers);
   5072     if (!mMemory) {
   5073         LOGE("unable to create heap memory");
   5074         return NULL;
   5075     }
   5076     rc = mMemory->allocateAll(len);
   5077     if (rc < 0) {
   5078         LOGE("unable to allocate heap memory");
   5079         delete mMemory;
   5080         mMemory = NULL;
   5081         return NULL;
   5082     }
   5083     return mMemory;
   5084 }
   5085 
   5086 void QCamera3SupportChannel::putStreamBufs()
   5087 {
   5088     mMemory->deallocate();
   5089     delete mMemory;
   5090     mMemory = NULL;
   5091 }
   5092 
   5093 }; // namespace qcamera
   5094