Home | History | Annotate | Download | only in HAL3
      1 /* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
      2 *
      3 * Redistribution and use in source and binary forms, with or without
      4 * modification, are permitted provided that the following conditions are
      5 * met:
      6 *     * Redistributions of source code must retain the above copyright
      7 *       notice, this list of conditions and the following disclaimer.
      8 *     * Redistributions in binary form must reproduce the above
      9 *       copyright notice, this list of conditions and the following
     10 *       disclaimer in the documentation and/or other materials provided
     11 *       with the distribution.
     12 *     * Neither the name of The Linux Foundation nor the names of its
     13 *       contributors may be used to endorse or promote products derived
     14 *       from this software without specific prior written permission.
     15 *
     16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 *
     28 */
     29 
     30 #define LOG_TAG "QCamera3Stream"
     31 
     32 // Camera dependencies
     33 #include "QCamera3HWI.h"
     34 #include "QCamera3Stream.h"
     35 #include <cutils/properties.h>
     36 #include "QCameraTrace.h"
     37 
     38 extern "C" {
     39 #include "mm_camera_dbg.h"
     40 }
     41 
     42 using namespace android;
     43 
     44 namespace qcamera {
     45 #define MAX_BATCH_SIZE   32
     46 
     47 const char* QCamera3Stream::mStreamNames[] = {
     48         "CAM_DEFAULT",
     49         "CAM_PREVIEW",
     50         "CAM_POSTVIEW",
     51         "CAM_SNAPSHOT",
     52         "CAM_VIDEO",
     53         "CAM_CALLBACK",
     54         "CAM_IMPL_DEFINED",
     55         "CAM_METADATA",
     56         "CAM_RAW",
     57         "CAM_OFFLINE_PROC",
     58         "CAM_PARM",
     59         "CAM_ANALYSIS"
     60         "CAM_MAX" };
     61 
     62 /*===========================================================================
     63  * FUNCTION   : get_bufs
     64  *
     65  * DESCRIPTION: static function entry to allocate stream buffers
     66  *
     67  * PARAMETERS :
     68  *   @offset     : offset info of stream buffers
     69  *   @num_bufs   : number of buffers allocated
     70  *   @initial_reg_flag: flag to indicate if buffer needs to be registered
     71  *                      at kernel initially
     72  *   @bufs       : output of allocated buffers
     73  *   @ops_tbl    : ptr to buf mapping/unmapping ops
     74  *   @user_data  : user data ptr of ops_tbl
     75  *
     76  * RETURN     : int32_t type of status
     77  *              NO_ERROR  -- success
     78  *              none-zero failure code
     79  *==========================================================================*/
     80 int32_t QCamera3Stream::get_bufs(
     81                      cam_frame_len_offset_t *offset,
     82                      uint8_t *num_bufs,
     83                      uint8_t **initial_reg_flag,
     84                      mm_camera_buf_def_t **bufs,
     85                      mm_camera_map_unmap_ops_tbl_t *ops_tbl,
     86                      void *user_data)
     87 {
     88     int32_t rc = NO_ERROR;
     89     QCamera3Stream *stream = reinterpret_cast<QCamera3Stream *>(user_data);
     90     if (!stream) {
     91         LOGE("getBufs invalid stream pointer");
     92         return NO_MEMORY;
     93     }
     94     rc = stream->getBufs(offset, num_bufs, initial_reg_flag, bufs, ops_tbl);
     95     if (NO_ERROR != rc) {
     96         LOGE("stream->getBufs failed");
     97         return NO_MEMORY;
     98     }
     99     if (stream->mBatchSize) {
    100         //Allocate batch buffers if mBatchSize is non-zero. All the output
    101         //arguments correspond to batch containers and not image buffers
    102         rc = stream->getBatchBufs(num_bufs, initial_reg_flag,
    103                 bufs, ops_tbl);
    104     }
    105     return rc;
    106 }
    107 
    108 /*===========================================================================
    109  * FUNCTION   : put_bufs
    110  *
    111  * DESCRIPTION: static function entry to deallocate stream buffers
    112  *
    113  * PARAMETERS :
    114  *   @ops_tbl    : ptr to buf mapping/unmapping ops
    115  *   @user_data  : user data ptr of ops_tbl
    116  *
    117  * RETURN     : int32_t type of status
    118  *              NO_ERROR  -- success
    119  *              none-zero failure code
    120  *==========================================================================*/
    121 int32_t QCamera3Stream::put_bufs(
    122                      mm_camera_map_unmap_ops_tbl_t *ops_tbl,
    123                      void *user_data)
    124 {
    125     int32_t rc = NO_ERROR;
    126     QCamera3Stream *stream = reinterpret_cast<QCamera3Stream *>(user_data);
    127     if (!stream) {
    128         LOGE("putBufs invalid stream pointer");
    129         return NO_MEMORY;
    130     }
    131 
    132     if (stream->mBatchSize) {
    133         rc = stream->putBatchBufs(ops_tbl);
    134         if (NO_ERROR != rc) {
    135             LOGE("stream->putBatchBufs failed");
    136         }
    137     }
    138     rc = stream->putBufs(ops_tbl);
    139     return rc;
    140 }
    141 
    142 /*===========================================================================
    143  * FUNCTION   : invalidate_buf
    144  *
    145  * DESCRIPTION: static function entry to invalidate a specific stream buffer
    146  *
    147  * PARAMETERS :
    148  *   @index      : index of the stream buffer to invalidate
    149  *   @user_data  : user data ptr of ops_tbl
    150  *
    151  * RETURN     : int32_t type of status
    152  *              NO_ERROR  -- success
    153  *              none-zero failure code
    154  *==========================================================================*/
    155 int32_t QCamera3Stream::invalidate_buf(uint32_t index, void *user_data)
    156 {
    157     int32_t rc = NO_ERROR;
    158 
    159     QCamera3Stream *stream = reinterpret_cast<QCamera3Stream *>(user_data);
    160     if (!stream) {
    161         LOGE("invalid stream pointer");
    162         return NO_MEMORY;
    163     }
    164     if (stream->mBatchSize) {
    165         int32_t retVal = NO_ERROR;
    166         for (size_t i = 0;
    167                 i < stream->mBatchBufDefs[index].user_buf.bufs_used; i++) {
    168             uint32_t buf_idx = stream->mBatchBufDefs[index].user_buf.buf_idx[i];
    169             retVal = stream->invalidateBuf(buf_idx);
    170             if (NO_ERROR != retVal) {
    171                 LOGE("invalidateBuf failed for buf_idx: %d err: %d",
    172                          buf_idx, retVal);
    173             }
    174             rc |= retVal;
    175         }
    176     } else {
    177         rc = stream->invalidateBuf(index);
    178     }
    179     return rc;
    180 }
    181 
    182 /*===========================================================================
    183  * FUNCTION   : clean_invalidate_buf
    184  *
    185  * DESCRIPTION: static function entry to clean and invalidate a specific stream buffer
    186  *
    187  * PARAMETERS :
    188  *   @index      : index of the stream buffer to invalidate
    189  *   @user_data  : user data ptr of ops_tbl
    190  *
    191  * RETURN     : int32_t type of status
    192  *              NO_ERROR  -- success
    193  *              none-zero failure code
    194  *==========================================================================*/
    195 int32_t QCamera3Stream::clean_invalidate_buf(uint32_t index, void *user_data)
    196 {
    197     int32_t rc = NO_ERROR;
    198 
    199     QCamera3Stream *stream = reinterpret_cast<QCamera3Stream *>(user_data);
    200     if (!stream) {
    201         LOGE("invalid stream pointer");
    202         return NO_MEMORY;
    203     }
    204     if (stream->mBatchSize) {
    205         int32_t retVal = NO_ERROR;
    206         for (size_t i = 0;
    207                 i < stream->mBatchBufDefs[index].user_buf.bufs_used; i++) {
    208             uint32_t buf_idx = stream->mBatchBufDefs[index].user_buf.buf_idx[i];
    209             retVal = stream->cleanInvalidateBuf(buf_idx);
    210             if (NO_ERROR != retVal) {
    211                 LOGE("invalidateBuf failed for buf_idx: %d err: %d",
    212                          buf_idx, retVal);
    213             }
    214             rc |= retVal;
    215         }
    216     } else {
    217         rc = stream->cleanInvalidateBuf(index);
    218     }
    219     return rc;
    220 }
    221 
    222 /*===========================================================================
    223  * FUNCTION   : clean_buf
    224  *
    225  * DESCRIPTION: static function entry to clean  a specific stream buffer
    226  *
    227  * PARAMETERS :
    228  *   @index      : index of the stream buffer to invalidate
    229  *   @user_data  : user data ptr of ops_tbl
    230  *
    231  * RETURN     : int32_t type of status
    232  *              NO_ERROR  -- success
    233  *              none-zero failure code
    234  *==========================================================================*/
    235 int32_t QCamera3Stream::clean_buf(uint32_t index, void *user_data)
    236 {
    237     int32_t rc = NO_ERROR;
    238 
    239     QCamera3Stream *stream = reinterpret_cast<QCamera3Stream *>(user_data);
    240     if (!stream) {
    241         LOGE("invalid stream pointer");
    242         return NO_MEMORY;
    243     }
    244     if (stream->mBatchSize) {
    245         int32_t retVal = NO_ERROR;
    246         for (size_t i = 0;
    247                 i < stream->mBatchBufDefs[index].user_buf.bufs_used; i++) {
    248             uint32_t buf_idx = stream->mBatchBufDefs[index].user_buf.buf_idx[i];
    249             retVal = stream->cleanBuf(buf_idx);
    250             if (NO_ERROR != retVal) {
    251                 LOGE("invalidateBuf failed for buf_idx: %d err: %d",
    252                     buf_idx, retVal);
    253             }
    254             rc |= retVal;
    255         }
    256     } else {
    257         rc = stream->cleanBuf(index);
    258     }
    259     return rc;
    260 }
    261 
    262 
    263 /*===========================================================================
    264  * FUNCTION   : QCamera3Stream
    265  *
    266  * DESCRIPTION: constructor of QCamera3Stream
    267  *
    268  * PARAMETERS :
    269  *   @allocator  : memory allocator obj
    270  *   @camHandle  : camera handle
    271  *   @chId       : channel handle
    272  *   @camOps     : ptr to camera ops table
    273  *   @paddingInfo: ptr to padding info
    274  *
    275  * RETURN     : None
    276  *==========================================================================*/
    277 QCamera3Stream::QCamera3Stream(uint32_t camHandle,
    278                              uint32_t chId,
    279                              mm_camera_ops_t *camOps,
    280                              cam_padding_info_t *paddingInfo,
    281                              QCamera3Channel *channel,
    282                              bool mapStreamBuffers) :
    283         mCamHandle(camHandle),
    284         mChannelHandle(chId),
    285         mHandle(0),
    286         mCamOps(camOps),
    287         mStreamInfo(NULL),
    288         mMemOps(NULL),
    289         mNumBufs(0),
    290         mDataCB(NULL),
    291         mUserData(NULL),
    292         mDataQ(releaseFrameData, this),
    293         mStreamInfoBuf(NULL),
    294         mStreamBufs(NULL),
    295         mBufDefs(NULL),
    296         mChannel(channel),
    297         mBatchSize(0),
    298         mNumBatchBufs(0),
    299         mStreamBatchBufs(NULL),
    300         mBatchBufDefs(NULL),
    301         mCurrentBatchBufDef(NULL),
    302         mBufsStaged(0),
    303         mFreeBatchBufQ(NULL, this),
    304         mNRMode(0),
    305         mMapStreamBuffers(mapStreamBuffers)
    306 {
    307     mMemVtbl.user_data = this;
    308     mMemVtbl.get_bufs = get_bufs;
    309     mMemVtbl.put_bufs = put_bufs;
    310     mMemVtbl.invalidate_buf = invalidate_buf;
    311     mMemVtbl.clean_invalidate_buf = clean_invalidate_buf;
    312     mMemVtbl.clean_buf = clean_buf;
    313     mMemVtbl.set_config_ops = NULL;
    314     memset(&mFrameLenOffset, 0, sizeof(mFrameLenOffset));
    315     memcpy(&mPaddingInfo, paddingInfo, sizeof(cam_padding_info_t));
    316     if (nullptr != channel) {
    317         mNRMode = channel->getNRMode();
    318     }
    319 }
    320 
    321 /*===========================================================================
    322  * FUNCTION   : ~QCamera3Stream
    323  *
    324  * DESCRIPTION: deconstructor of QCamera3Stream
    325  *
    326  * PARAMETERS : None
    327  *
    328  * RETURN     : None
    329  *==========================================================================*/
    330 QCamera3Stream::~QCamera3Stream()
    331 {
    332     if (mStreamInfoBuf != NULL) {
    333         int rc = mCamOps->unmap_stream_buf(mCamHandle,
    334                     mChannelHandle, mHandle, CAM_MAPPING_BUF_TYPE_STREAM_INFO, 0, -1);
    335         if (rc < 0) {
    336             LOGE("Failed to un-map stream info buffer");
    337         }
    338         mStreamInfoBuf->deallocate();
    339         delete mStreamInfoBuf;
    340         mStreamInfoBuf = NULL;
    341     }
    342     // delete stream
    343     if (mHandle > 0) {
    344         mCamOps->delete_stream(mCamHandle, mChannelHandle, mHandle);
    345         mHandle = 0;
    346     }
    347 }
    348 
    349 /*===========================================================================
    350  * FUNCTION   : init
    351  *
    352  * DESCRIPTION: initialize stream obj
    353  *
    354  * PARAMETERS :
    355  *   @streamType     : stream type
    356  *   @streamFormat   : stream format
    357  *   @streamDim      : stream dimension
    358  *   @reprocess_config: reprocess stream input configuration
    359  *   @minNumBuffers  : minimal buffer count for particular stream type
    360  *   @postprocess_mask: PP mask
    361  *   @is_type  : Image stabilization type, cam_is_type_t
    362  *   @batchSize  : Number of image buffers in a batch.
    363  *                 0: No batch. N: container with N image buffers
    364  *   @stream_cb      : callback handle
    365  *   @userdata       : user data
    366  *
    367  * RETURN     : int32_t type of status
    368  *              NO_ERROR  -- success
    369  *              none-zero failure code
    370  *==========================================================================*/
    371 int32_t QCamera3Stream::init(cam_stream_type_t streamType,
    372                             cam_format_t streamFormat,
    373                             cam_dimension_t streamDim,
    374                             cam_rotation_t streamRotation,
    375                             cam_stream_reproc_config_t* reprocess_config,
    376                             uint8_t minNumBuffers,
    377                             cam_feature_mask_t postprocess_mask,
    378                             cam_is_type_t is_type,
    379                             uint32_t batchSize,
    380                             hal3_stream_cb_routine stream_cb,
    381                             void *userdata)
    382 {
    383     int32_t rc = OK;
    384     ssize_t bufSize = BAD_INDEX;
    385     char value[PROPERTY_VALUE_MAX];
    386     uint32_t bOptimizeCacheOps = 0;
    387     mm_camera_stream_config_t stream_config;
    388     LOGD("batch size is %d", batchSize);
    389 
    390     mHandle = mCamOps->add_stream(mCamHandle, mChannelHandle);
    391     if (!mHandle) {
    392         LOGE("add_stream failed");
    393         rc = UNKNOWN_ERROR;
    394         goto done;
    395     }
    396 
    397     // allocate and map stream info memory
    398     mStreamInfoBuf = new QCamera3HeapMemory(1);
    399     if (mStreamInfoBuf == NULL) {
    400         LOGE("no memory for stream info buf obj");
    401         rc = -ENOMEM;
    402         goto err1;
    403     }
    404     rc = mStreamInfoBuf->allocate(sizeof(cam_stream_info_t));
    405     if (rc < 0) {
    406         LOGE("no memory for stream info");
    407         rc = -ENOMEM;
    408         goto err2;
    409     }
    410 
    411     mStreamInfo =
    412         reinterpret_cast<cam_stream_info_t *>(mStreamInfoBuf->getPtr(0));
    413     memset(mStreamInfo, 0, sizeof(cam_stream_info_t));
    414     mStreamInfo->stream_type = streamType;
    415     mStreamInfo->fmt = streamFormat;
    416     mStreamInfo->dim = streamDim;
    417     mStreamInfo->num_bufs = minNumBuffers;
    418     mStreamInfo->pp_config.feature_mask = postprocess_mask;
    419     mStreamInfo->is_type = is_type;
    420     mStreamInfo->pp_config.rotation = streamRotation;
    421     mStreamInfo->nr_mode = mNRMode;
    422 
    423     memset(value, 0, sizeof(value));
    424     property_get("persist.camera.cache.optimize", value, "1");
    425     bOptimizeCacheOps = atoi(value);
    426 
    427     if (bOptimizeCacheOps) {
    428         mStreamInfo->cache_ops = CAM_STREAM_CACHE_OPS_HONOUR_FLAGS;
    429     } else {
    430         mStreamInfo->cache_ops = CAM_STREAM_CACHE_OPS_DISABLED;
    431     }
    432     LOGD("stream_type is %d, feature_mask is %Ld",
    433            mStreamInfo->stream_type, mStreamInfo->pp_config.feature_mask);
    434 
    435     bufSize = mStreamInfoBuf->getSize(0);
    436     if (BAD_INDEX != bufSize) {
    437         rc = mCamOps->map_stream_buf(mCamHandle,
    438                 mChannelHandle, mHandle, CAM_MAPPING_BUF_TYPE_STREAM_INFO,
    439                 0, -1, mStreamInfoBuf->getFd(0), (size_t)bufSize,
    440                 mStreamInfoBuf->getPtr(0));
    441         if (rc < 0) {
    442             LOGE("Failed to map stream info buffer");
    443             goto err3;
    444         }
    445     } else {
    446         LOGE("Failed to retrieve buffer size (bad index)");
    447         goto err3;
    448     }
    449 
    450     mNumBufs = minNumBuffers;
    451     if (reprocess_config != NULL) {
    452         mStreamInfo->reprocess_config = *reprocess_config;
    453         mStreamInfo->streaming_mode = CAM_STREAMING_MODE_BURST;
    454         //mStreamInfo->num_of_burst = reprocess_config->offline.num_of_bufs;
    455         mStreamInfo->num_of_burst = 1;
    456     } else if (batchSize) {
    457         if (batchSize > MAX_BATCH_SIZE) {
    458             LOGE("batchSize:%d is very large", batchSize);
    459             rc = BAD_VALUE;
    460             goto err4;
    461         }
    462         else {
    463             mNumBatchBufs = MAX_INFLIGHT_HFR_REQUESTS / batchSize;
    464             mStreamInfo->streaming_mode = CAM_STREAMING_MODE_BATCH;
    465             mStreamInfo->user_buf_info.frame_buf_cnt = batchSize;
    466             mStreamInfo->user_buf_info.size =
    467                     (uint32_t)(sizeof(msm_camera_user_buf_cont_t));
    468             mStreamInfo->num_bufs = mNumBatchBufs;
    469             //Frame interval is irrelavent since time stamp calculation is not
    470             //required from the mCamOps
    471             mStreamInfo->user_buf_info.frameInterval = 0;
    472             LOGD("batch size is %d", batchSize);
    473         }
    474     } else {
    475         mStreamInfo->streaming_mode = CAM_STREAMING_MODE_CONTINUOUS;
    476     }
    477 
    478     // Configure the stream
    479     stream_config.stream_info = mStreamInfo;
    480     stream_config.mem_vtbl = mMemVtbl;
    481     stream_config.padding_info = mPaddingInfo;
    482     stream_config.userdata = this;
    483     stream_config.stream_cb = dataNotifyCB;
    484     stream_config.stream_cb_sync = NULL;
    485 
    486     rc = mCamOps->config_stream(mCamHandle,
    487             mChannelHandle, mHandle, &stream_config);
    488     if (rc < 0) {
    489         LOGE("Failed to config stream, rc = %d", rc);
    490         goto err4;
    491     }
    492 
    493     mDataCB = stream_cb;
    494     mUserData = userdata;
    495     mBatchSize = batchSize;
    496     return 0;
    497 
    498 err4:
    499     mCamOps->unmap_stream_buf(mCamHandle,
    500             mChannelHandle, mHandle, CAM_MAPPING_BUF_TYPE_STREAM_INFO, 0, -1);
    501 err3:
    502     mStreamInfoBuf->deallocate();
    503 err2:
    504     delete mStreamInfoBuf;
    505     mStreamInfoBuf = NULL;
    506     mStreamInfo = NULL;
    507 err1:
    508     mCamOps->delete_stream(mCamHandle, mChannelHandle, mHandle);
    509     mHandle = 0;
    510     mNumBufs = 0;
    511 done:
    512     return rc;
    513 }
    514 
    515 /*===========================================================================
    516  * FUNCTION   : start
    517  *
    518  * DESCRIPTION: start stream. Will start main stream thread to handle stream
    519  *              related ops.
    520  *
    521  * PARAMETERS : none
    522  *
    523  * RETURN     : int32_t type of status
    524  *              NO_ERROR  -- success
    525  *              none-zero failure code
    526  *==========================================================================*/
    527 int32_t QCamera3Stream::start()
    528 {
    529     int32_t rc = 0;
    530 
    531     mDataQ.init();
    532     mTimeoutFrameQ.clear();
    533     if (mBatchSize)
    534         mFreeBatchBufQ.init();
    535     rc = mProcTh.launch(dataProcRoutine, this);
    536     return rc;
    537 }
    538 
    539 /*===========================================================================
    540  * FUNCTION   : stop
    541  *
    542  * DESCRIPTION: stop stream. Will stop main stream thread
    543  *
    544  * PARAMETERS : none
    545  *
    546  * RETURN     : int32_t type of status
    547  *              NO_ERROR  -- success
    548  *              none-zero failure code
    549  *==========================================================================*/
    550 int32_t QCamera3Stream::stop()
    551 {
    552     int32_t rc = 0;
    553     rc = mProcTh.exit();
    554     return rc;
    555 }
    556 
    557 /*===========================================================================
    558  * FUNCTION   : timeoutFrame
    559  *
    560  * DESCRIPTION: Function to issue timeout on frame
    561  *
    562  * PARAMETERS :
    563  *   @bufIdx  : buffer index of the frame to be timed out
    564  *
    565  * RETURN     : int32_t type of status
    566  *              NO_ERROR  -- success
    567  *              none-zero failure code
    568  *==========================================================================*/
    569 int32_t QCamera3Stream::timeoutFrame(int32_t bufIdx)
    570 {
    571     LOGD("E\n");
    572     int32_t rc;
    573     {
    574         Mutex::Autolock lock(mTimeoutFrameQLock);
    575         mTimeoutFrameQ.push_back(bufIdx);
    576     }
    577     rc = mProcTh.sendCmd(CAMERA_CMD_TYPE_TIMEOUT, FALSE, FALSE);
    578     LOGD("X\n");
    579     return rc;
    580 }
    581 
    582 /*===========================================================================
    583  * FUNCTION   : processDataNotify
    584  *
    585  * DESCRIPTION: process stream data notify
    586  *
    587  * PARAMETERS :
    588  *   @frame   : stream frame received
    589  *
    590  * RETURN     : int32_t type of status
    591  *              NO_ERROR  -- success
    592  *              none-zero failure code
    593  *==========================================================================*/
    594 int32_t QCamera3Stream::processDataNotify(mm_camera_super_buf_t *frame)
    595 {
    596     LOGD("E\n");
    597     int32_t rc;
    598     if (mDataQ.enqueue((void *)frame)) {
    599         rc = mProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
    600     } else {
    601         LOGD("Stream thread is not active, no ops here");
    602         bufDone(frame->bufs[0]->buf_idx);
    603         free(frame);
    604         rc = NO_ERROR;
    605     }
    606     LOGD("X\n");
    607     return rc;
    608 }
    609 
    610 /*===========================================================================
    611  * FUNCTION   : dataNotifyCB
    612  *
    613  * DESCRIPTION: callback for data notify. This function is registered with
    614  *              mm-camera-interface to handle data notify
    615  *
    616  * PARAMETERS :
    617  *   @recvd_frame   : stream frame received
    618  *   userdata       : user data ptr
    619  *
    620  * RETURN     : none
    621  *==========================================================================*/
    622 void QCamera3Stream::dataNotifyCB(mm_camera_super_buf_t *recvd_frame,
    623                                  void *userdata)
    624 {
    625     LOGD("E\n");
    626     QCamera3Stream* stream = (QCamera3Stream *)userdata;
    627     if (stream == NULL ||
    628         recvd_frame == NULL ||
    629         recvd_frame->bufs[0] == NULL ||
    630         recvd_frame->bufs[0]->stream_id != stream->getMyHandle()) {
    631         LOGE("Not a valid stream to handle buf");
    632         return;
    633     }
    634 
    635     mm_camera_super_buf_t *frame =
    636         (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
    637     if (frame == NULL) {
    638         LOGE("No mem for mm_camera_buf_def_t");
    639         stream->bufDone(recvd_frame->bufs[0]->buf_idx);
    640         return;
    641     }
    642     *frame = *recvd_frame;
    643     stream->processDataNotify(frame);
    644     return;
    645 }
    646 
    647 /*===========================================================================
    648  * FUNCTION   : dataProcRoutine
    649  *
    650  * DESCRIPTION: function to process data in the main stream thread
    651  *
    652  * PARAMETERS :
    653  *   @data    : user data ptr
    654  *
    655  * RETURN     : none
    656  *==========================================================================*/
    657 void *QCamera3Stream::dataProcRoutine(void *data)
    658 {
    659     int running = 1;
    660     int ret;
    661     QCamera3Stream *pme = (QCamera3Stream *)data;
    662     QCameraCmdThread *cmdThread = &pme->mProcTh;
    663 
    664     cmdThread->setName(mStreamNames[pme->mStreamInfo->stream_type]);
    665 
    666     LOGD("E");
    667     do {
    668         do {
    669             ret = cam_sem_wait(&cmdThread->cmd_sem);
    670             if (ret != 0 && errno != EINVAL) {
    671                 LOGE("cam_sem_wait error (%s)",
    672                        strerror(errno));
    673                 return NULL;
    674             }
    675         } while (ret != 0);
    676 
    677         // we got notified about new cmd avail in cmd queue
    678         camera_cmd_type_t cmd = cmdThread->getCmd();
    679         switch (cmd) {
    680         case CAMERA_CMD_TYPE_TIMEOUT:
    681             {
    682                 int32_t bufIdx;
    683                 {
    684                     Mutex::Autolock lock(pme->mTimeoutFrameQLock);
    685                     if (pme->mTimeoutFrameQ.size()) {
    686                         auto itr = pme->mTimeoutFrameQ.begin();
    687                         bufIdx = *itr;
    688                         itr = pme->mTimeoutFrameQ.erase(itr);
    689                     } else {
    690                         LOGE("Timeout command received but Q is empty");
    691                         break;
    692                     }
    693                 }
    694                 pme->cancelBuffer(bufIdx);
    695                 break;
    696             }
    697         case CAMERA_CMD_TYPE_DO_NEXT_JOB:
    698             {
    699                 LOGD("Do next job");
    700                 mm_camera_super_buf_t *frame =
    701                     (mm_camera_super_buf_t *)pme->mDataQ.dequeue();
    702                 if (NULL != frame) {
    703                     if (UNLIKELY(frame->bufs[0]->buf_type ==
    704                             CAM_STREAM_BUF_TYPE_USERPTR)) {
    705                         pme->handleBatchBuffer(frame);
    706                     } else if (pme->mDataCB != NULL) {
    707                         pme->mDataCB(frame, pme, pme->mUserData);
    708                     } else {
    709                         // no data cb routine, return buf here
    710                         pme->bufDone(frame->bufs[0]->buf_idx);
    711                     }
    712                 }
    713             }
    714             break;
    715         case CAMERA_CMD_TYPE_EXIT:
    716             LOGH("Exit");
    717             pme->flushFreeBatchBufQ();
    718             /* flush data buf queue */
    719             pme->mDataQ.flush();
    720             pme->mTimeoutFrameQ.clear();
    721             running = 0;
    722             break;
    723         default:
    724             break;
    725         }
    726     } while (running);
    727     LOGD("X");
    728     return NULL;
    729 }
    730 
    731 /*===========================================================================
    732  * FUNCTION   : bufDone
    733  *
    734  * DESCRIPTION: return stream buffer to kernel
    735  *
    736  * PARAMETERS :
    737  *   @index   : index of buffer to be returned
    738  *
    739  * RETURN     : int32_t type of status
    740  *              NO_ERROR  -- success
    741  *              none-zero failure code
    742  *==========================================================================*/
    743 int32_t QCamera3Stream::bufDone(uint32_t index)
    744 {
    745     Mutex::Autolock lock(mLock);
    746     return bufDoneLocked(index);
    747 }
    748 
    749 /*===========================================================================
    750  * FUNCTION   : bufDoneLocked
    751  *
    752  * DESCRIPTION: return stream buffer to kernel while holding the lock
    753  *
    754  * PARAMETERS :
    755  *   @index   : index of buffer to be returned
    756  *
    757  * RETURN     : int32_t type of status
    758  *              NO_ERROR  -- success
    759  *              none-zero failure code
    760  *==========================================================================*/
    761 int32_t QCamera3Stream::bufDoneLocked(uint32_t index)
    762 {
    763     int32_t rc = NO_ERROR;
    764 
    765     if ((index >= mNumBufs) || (mBufDefs == NULL)) {
    766         LOGE("index; %d, mNumBufs: %d", index, mNumBufs);
    767         return BAD_INDEX;
    768     }
    769     if (mStreamBufs == NULL)
    770     {
    771         LOGE("putBufs already called");
    772         return INVALID_OPERATION;
    773     }
    774 
    775     if( NULL == mBufDefs[index].mem_info) {
    776         if (NULL == mMemOps) {
    777             LOGE("Camera operations not initialized");
    778             return NO_INIT;
    779         }
    780 
    781         ssize_t bufSize = mStreamBufs->getSize(index);
    782 
    783         if (BAD_INDEX != bufSize) {
    784             LOGD("Map streamBufIdx: %d", index);
    785             void* buffer = (mMapStreamBuffers ?
    786                             mStreamBufs->getPtr(index) : NULL);
    787             rc = mMemOps->map_ops(index, -1, mStreamBufs->getFd(index),
    788                     (size_t)bufSize, buffer,
    789                     CAM_MAPPING_BUF_TYPE_STREAM_BUF, mMemOps->userdata);
    790             if (rc < 0) {
    791                 LOGE("Failed to map camera buffer %d", index);
    792                 return rc;
    793             }
    794 
    795             rc = mStreamBufs->getBufDef(mFrameLenOffset, mBufDefs[index], index, mMapStreamBuffers);
    796             if (NO_ERROR != rc) {
    797                 LOGE("Couldn't find camera buffer definition");
    798                 mMemOps->unmap_ops(index, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF, mMemOps->userdata);
    799                 return rc;
    800             }
    801         } else {
    802             LOGE("Failed to retrieve buffer size (bad index)");
    803             return INVALID_OPERATION;
    804         }
    805     }
    806 
    807     if (UNLIKELY(mBatchSize)) {
    808         rc = aggregateBufToBatch(mBufDefs[index]);
    809     } else {
    810         // Cache invalidation should happen in lockNextBuffer or during
    811         // reprocessing. No need to invalidate every buffer without knowing
    812         // which buffer is accessed by CPU.
    813         rc = mCamOps->qbuf(mCamHandle, mChannelHandle, &mBufDefs[index]);
    814         if (rc < 0) {
    815             return FAILED_TRANSACTION;
    816         }
    817     }
    818 
    819     return rc;
    820 }
    821 
    822 /*===========================================================================
    823  * FUNCTION   : cancelBuffer
    824  *
    825  * DESCRIPTION: Issue cancel buffer request to kernel
    826  *
    827  * PARAMETERS :
    828  *   @index   : index of buffer to be cancelled
    829  *
    830  * RETURN     : int32_t type of status
    831  *              NO_ERROR  -- success
    832  *              none-zero failure code
    833  *==========================================================================*/
    834 int32_t QCamera3Stream::cancelBuffer(uint32_t index)
    835 {
    836     int32_t rc = NO_ERROR;
    837     Mutex::Autolock lock(mLock);
    838 
    839     if ((index >= mNumBufs) || (mBufDefs == NULL)) {
    840         LOGE("index; %d, mNumBufs: %d", index, mNumBufs);
    841         return BAD_INDEX;
    842     }
    843     if (mStreamBufs == NULL)
    844     {
    845         LOGE("putBufs already called");
    846         return INVALID_OPERATION;
    847     }
    848 
    849     /* if (UNLIKELY(mBatchSize)) {
    850         FIXME
    851     } else */{
    852         LOGE("Calling cancel buf on idx:%d for stream type:%d",index, getMyType());
    853         rc = mCamOps->cancel_buffer(mCamHandle, mChannelHandle, mHandle, index);
    854         if (rc < 0) {
    855             return FAILED_TRANSACTION;
    856         }
    857     }
    858 
    859     return rc;
    860 }
    861 
    862 /*===========================================================================
    863  * FUNCTION   : bufRelease
    864  *
    865  * DESCRIPTION: release all resources associated with this buffer
    866  *
    867  * PARAMETERS :
    868  *   @index   : index of buffer to be released
    869  *
    870  * RETURN     : int32_t type of status
    871  *              NO_ERROR  -- success
    872  *              none-zero failure code
    873  *==========================================================================*/
    874 int32_t QCamera3Stream::bufRelease(int32_t index)
    875 {
    876     int32_t rc = NO_ERROR;
    877     Mutex::Autolock lock(mLock);
    878 
    879     if ((index >= mNumBufs) || (mBufDefs == NULL)) {
    880         return BAD_INDEX;
    881     }
    882 
    883     if (NULL != mBufDefs[index].mem_info) {
    884         if (NULL == mMemOps) {
    885             LOGE("Camera operations not initialized");
    886             return NO_INIT;
    887         }
    888 
    889         rc = mMemOps->unmap_ops(index, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF,
    890                 mMemOps->userdata);
    891         if (rc < 0) {
    892             LOGE("Failed to un-map camera buffer %d", index);
    893             return rc;
    894         }
    895 
    896         mBufDefs[index].mem_info = NULL;
    897     } else {
    898         LOGE("Buffer at index %d not registered");
    899         return BAD_INDEX;
    900     }
    901 
    902     return rc;
    903 }
    904 
    905 /*===========================================================================
    906  * FUNCTION   : getBufs
    907  *
    908  * DESCRIPTION: allocate stream buffers
    909  *
    910  * PARAMETERS :
    911  *   @offset     : offset info of stream buffers
    912  *   @num_bufs   : number of buffers allocated
    913  *   @initial_reg_flag: flag to indicate if buffer needs to be registered
    914  *                      at kernel initially
    915  *   @bufs       : output of allocated buffers
    916  *   @ops_tbl    : ptr to buf mapping/unmapping ops
    917  *
    918  * RETURN     : int32_t type of status
    919  *              NO_ERROR  -- success
    920  *              none-zero failure code
    921  *==========================================================================*/
    922 int32_t QCamera3Stream::getBufs(cam_frame_len_offset_t *offset,
    923                      uint8_t *num_bufs,
    924                      uint8_t **initial_reg_flag,
    925                      mm_camera_buf_def_t **bufs,
    926                      mm_camera_map_unmap_ops_tbl_t *ops_tbl)
    927 {
    928     int rc = NO_ERROR;
    929     uint8_t *regFlags;
    930     Mutex::Autolock lock(mLock);
    931 
    932     if (!ops_tbl) {
    933         LOGE("ops_tbl is NULL");
    934         return INVALID_OPERATION;
    935     }
    936 
    937     mFrameLenOffset = *offset;
    938     mMemOps = ops_tbl;
    939 
    940     if (mStreamBufs != NULL) {
    941        LOGE("Failed getBufs being called twice in a row without a putBufs call");
    942        return INVALID_OPERATION;
    943     }
    944     mStreamBufs = mChannel->getStreamBufs(mFrameLenOffset.frame_len);
    945     if (!mStreamBufs) {
    946         LOGE("Failed to allocate stream buffers");
    947         return NO_MEMORY;
    948     }
    949 
    950     for (uint32_t i = 0; i < mNumBufs; i++) {
    951         if (mStreamBufs->valid(i)) {
    952             ssize_t bufSize = mStreamBufs->getSize(i);
    953             if (BAD_INDEX != bufSize) {
    954                 void* buffer = (mMapStreamBuffers ?
    955                         mStreamBufs->getPtr(i) : NULL);
    956                 rc = ops_tbl->map_ops(i, -1, mStreamBufs->getFd(i),
    957                         (size_t)bufSize, buffer,
    958                         CAM_MAPPING_BUF_TYPE_STREAM_BUF,
    959                         ops_tbl->userdata);
    960                 if (rc < 0) {
    961                     LOGE("map_stream_buf failed: %d", rc);
    962                     for (uint32_t j = 0; j < i; j++) {
    963                         if (mStreamBufs->valid(j)) {
    964                             ops_tbl->unmap_ops(j, -1,
    965                                     CAM_MAPPING_BUF_TYPE_STREAM_BUF,
    966                                     ops_tbl->userdata);
    967                         }
    968                     }
    969                     return INVALID_OPERATION;
    970                 }
    971             } else {
    972                 LOGE("Failed to retrieve buffer size (bad index)");
    973                 return INVALID_OPERATION;
    974             }
    975         }
    976     }
    977 
    978     //regFlags array is allocated by us, but consumed and freed by mm-camera-interface
    979     regFlags = (uint8_t *)malloc(sizeof(uint8_t) * mNumBufs);
    980     if (!regFlags) {
    981         LOGE("Out of memory");
    982         for (uint32_t i = 0; i < mNumBufs; i++) {
    983             if (mStreamBufs->valid(i)) {
    984                 ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF,
    985                         ops_tbl->userdata);
    986             }
    987         }
    988         return NO_MEMORY;
    989     }
    990     memset(regFlags, 0, sizeof(uint8_t) * mNumBufs);
    991 
    992     mBufDefs = (mm_camera_buf_def_t *)malloc(mNumBufs * sizeof(mm_camera_buf_def_t));
    993     if (mBufDefs == NULL) {
    994         LOGE("Failed to allocate mm_camera_buf_def_t %d", rc);
    995         for (uint32_t i = 0; i < mNumBufs; i++) {
    996             if (mStreamBufs->valid(i)) {
    997                 ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF,
    998                         ops_tbl->userdata);
    999             }
   1000         }
   1001         free(regFlags);
   1002         regFlags = NULL;
   1003         return INVALID_OPERATION;
   1004     }
   1005     memset(mBufDefs, 0, mNumBufs * sizeof(mm_camera_buf_def_t));
   1006     for (uint32_t i = 0; i < mNumBufs; i++) {
   1007         if (mStreamBufs->valid(i)) {
   1008             mStreamBufs->getBufDef(mFrameLenOffset, mBufDefs[i], i, mMapStreamBuffers);
   1009         }
   1010     }
   1011 
   1012     rc = mStreamBufs->getRegFlags(regFlags);
   1013     if (rc < 0) {
   1014         LOGE("getRegFlags failed %d", rc);
   1015         for (uint32_t i = 0; i < mNumBufs; i++) {
   1016             if (mStreamBufs->valid(i)) {
   1017                 ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF,
   1018                         ops_tbl->userdata);
   1019             }
   1020         }
   1021         free(mBufDefs);
   1022         mBufDefs = NULL;
   1023         free(regFlags);
   1024         regFlags = NULL;
   1025         return INVALID_OPERATION;
   1026     }
   1027 
   1028     *num_bufs = mNumBufs;
   1029     *initial_reg_flag = regFlags;
   1030     *bufs = mBufDefs;
   1031     return NO_ERROR;
   1032 }
   1033 
   1034 /*===========================================================================
   1035  * FUNCTION   : putBufs
   1036  *
   1037  * DESCRIPTION: deallocate stream buffers
   1038  *
   1039  * PARAMETERS :
   1040  *   @ops_tbl    : ptr to buf mapping/unmapping ops
   1041  *
   1042  * RETURN     : int32_t type of status
   1043  *              NO_ERROR  -- success
   1044  *              none-zero failure code
   1045  *==========================================================================*/
   1046 int32_t QCamera3Stream::putBufs(mm_camera_map_unmap_ops_tbl_t *ops_tbl)
   1047 {
   1048     int rc = NO_ERROR;
   1049     Mutex::Autolock lock(mLock);
   1050 
   1051     for (uint32_t i = 0; i < mNumBufs; i++) {
   1052         if (mStreamBufs->valid(i) && NULL != mBufDefs[i].mem_info) {
   1053             rc = ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF, ops_tbl->userdata);
   1054             if (rc < 0) {
   1055                 LOGE("un-map stream buf failed: %d", rc);
   1056             }
   1057         }
   1058     }
   1059     mBufDefs = NULL; // mBufDefs just keep a ptr to the buffer
   1060                      // mm-camera-interface own the buffer, so no need to free
   1061     memset(&mFrameLenOffset, 0, sizeof(mFrameLenOffset));
   1062 
   1063     if (mStreamBufs == NULL) {
   1064         LOGE("getBuf failed previously, or calling putBufs twice");
   1065     }
   1066 
   1067     mChannel->putStreamBufs();
   1068 
   1069     //need to set mStreamBufs to null because putStreamBufs deletes that memory
   1070     mStreamBufs = NULL;
   1071 
   1072     return rc;
   1073 }
   1074 
   1075 /*===========================================================================
   1076  * FUNCTION   : invalidateBuf
   1077  *
   1078  * DESCRIPTION: invalidate a specific stream buffer
   1079  *
   1080  * PARAMETERS :
   1081  *   @index   : index of the buffer to invalidate
   1082  *
   1083  * RETURN     : int32_t type of status
   1084  *              NO_ERROR  -- success
   1085  *              none-zero failure code
   1086  *==========================================================================*/
   1087 int32_t QCamera3Stream::invalidateBuf(uint32_t index)
   1088 {
   1089     if (mStreamBufs == NULL) {
   1090        LOGE("putBufs already called");
   1091        return INVALID_OPERATION;
   1092     } else
   1093        return mStreamBufs->invalidateCache(index);
   1094 }
   1095 
   1096 /*===========================================================================
   1097  * FUNCTION   : cleanInvalidateBuf
   1098  *
   1099  * DESCRIPTION: clean and invalidate a specific stream buffer
   1100  *
   1101  * PARAMETERS :
   1102  *   @index   : index of the buffer to invalidate
   1103  *
   1104  * RETURN     : int32_t type of status
   1105  *              NO_ERROR  -- success
   1106  *              none-zero failure code
   1107  *==========================================================================*/
   1108 int32_t QCamera3Stream::cleanInvalidateBuf(uint32_t index)
   1109 {
   1110     if (mStreamBufs == NULL) {
   1111         LOGE("putBufs already called");
   1112         return INVALID_OPERATION;
   1113     } else
   1114         return mStreamBufs->cleanInvalidateCache(index);
   1115 }
   1116 
   1117 /*===========================================================================
   1118  * FUNCTION   : cleanBuf
   1119  *
   1120  * DESCRIPTION: clean a specific stream buffer
   1121  *
   1122  * PARAMETERS :
   1123  *   @index   : index of the buffer to invalidate
   1124  *
   1125  * RETURN     : int32_t type of status
   1126  *              NO_ERROR  -- success
   1127  *              none-zero failure code
   1128  *==========================================================================*/
   1129 int32_t QCamera3Stream::cleanBuf(uint32_t index)
   1130 {
   1131     if (mStreamBufs == NULL) {
   1132         LOGE("putBufs already called");
   1133         return INVALID_OPERATION;
   1134     } else
   1135         return mStreamBufs->cleanCache(index);
   1136 }
   1137 
   1138 /*===========================================================================
   1139  * FUNCTION   : getFrameOffset
   1140  *
   1141  * DESCRIPTION: query stream buffer frame offset info
   1142  *
   1143  * PARAMETERS :
   1144  *   @offset  : reference to struct to store the queried frame offset info
   1145  *
   1146  * RETURN     : int32_t type of status
   1147  *              NO_ERROR  -- success
   1148  *              none-zero failure code
   1149  *==========================================================================*/
   1150 int32_t QCamera3Stream::getFrameOffset(cam_frame_len_offset_t &offset)
   1151 {
   1152     offset = mFrameLenOffset;
   1153     return 0;
   1154 }
   1155 
   1156 /*===========================================================================
   1157  * FUNCTION   : getFrameDimension
   1158  *
   1159  * DESCRIPTION: query stream frame dimension info
   1160  *
   1161  * PARAMETERS :
   1162  *   @dim     : reference to struct to store the queried frame dimension
   1163  *
   1164  * RETURN     : int32_t type of status
   1165  *              NO_ERROR  -- success
   1166  *              none-zero failure code
   1167  *==========================================================================*/
   1168 int32_t QCamera3Stream::getFrameDimension(cam_dimension_t &dim)
   1169 {
   1170     if (mStreamInfo != NULL) {
   1171         dim = mStreamInfo->dim;
   1172         return 0;
   1173     }
   1174     return -1;
   1175 }
   1176 
   1177 /*===========================================================================
   1178  * FUNCTION   : getFormat
   1179  *
   1180  * DESCRIPTION: query stream format
   1181  *
   1182  * PARAMETERS :
   1183  *   @fmt     : reference to stream format
   1184  *
   1185  * RETURN     : int32_t type of status
   1186  *              NO_ERROR  -- success
   1187  *              none-zero failure code
   1188  *==========================================================================*/
   1189 int32_t QCamera3Stream::getFormat(cam_format_t &fmt)
   1190 {
   1191     if (mStreamInfo != NULL) {
   1192         fmt = mStreamInfo->fmt;
   1193         return 0;
   1194     }
   1195     return -1;
   1196 }
   1197 
   1198 /*===========================================================================
   1199  * FUNCTION   : getMyServerID
   1200  *
   1201  * DESCRIPTION: query server stream ID
   1202  *
   1203  * PARAMETERS : None
   1204  *
   1205  * RETURN     : stream ID from server
   1206  *==========================================================================*/
   1207 uint32_t QCamera3Stream::getMyServerID() {
   1208     if (mStreamInfo != NULL) {
   1209         return mStreamInfo->stream_svr_id;
   1210     } else {
   1211         return 0;
   1212     }
   1213 }
   1214 
   1215 /*===========================================================================
   1216  * FUNCTION   : getMyType
   1217  *
   1218  * DESCRIPTION: query stream type
   1219  *
   1220  * PARAMETERS : None
   1221  *
   1222  * RETURN     : type of stream
   1223  *==========================================================================*/
   1224 cam_stream_type_t QCamera3Stream::getMyType() const
   1225 {
   1226     if (mStreamInfo != NULL) {
   1227         return mStreamInfo->stream_type;
   1228     } else {
   1229         return CAM_STREAM_TYPE_MAX;
   1230     }
   1231 }
   1232 
   1233 /*===========================================================================
   1234  * FUNCTION   : mapBuf
   1235  *
   1236  * DESCRIPTION: map stream related buffer to backend server
   1237  *
   1238  * PARAMETERS :
   1239  *   @buf_type : mapping type of buffer
   1240  *   @buf_idx  : index of buffer
   1241  *   @plane_idx: plane index
   1242  *   @fd       : fd of the buffer
   1243  *   @buffer : buffer ptr
   1244  *   @size     : lenght of the buffer
   1245  *
   1246  * RETURN     : int32_t type of status
   1247  *              NO_ERROR  -- success
   1248  *              none-zero failure code
   1249  *==========================================================================*/
   1250 int32_t QCamera3Stream::mapBuf(uint8_t buf_type, uint32_t buf_idx,
   1251         int32_t plane_idx, int fd, void *buffer, size_t size)
   1252 {
   1253     ATRACE_CALL();
   1254     return mCamOps->map_stream_buf(mCamHandle, mChannelHandle,
   1255                                    mHandle, buf_type,
   1256                                    buf_idx, plane_idx,
   1257                                    fd, size, buffer);
   1258 
   1259 }
   1260 
   1261 /*===========================================================================
   1262  * FUNCTION   : unmapBuf
   1263  *
   1264  * DESCRIPTION: unmap stream related buffer to backend server
   1265  *
   1266  * PARAMETERS :
   1267  *   @buf_type : mapping type of buffer
   1268  *   @buf_idx  : index of buffer
   1269  *   @plane_idx: plane index
   1270  *
   1271  * RETURN     : int32_t type of status
   1272  *              NO_ERROR  -- success
   1273  *              none-zero failure code
   1274  *==========================================================================*/
   1275 int32_t QCamera3Stream::unmapBuf(uint8_t buf_type, uint32_t buf_idx, int32_t plane_idx)
   1276 {
   1277     ATRACE_CALL();
   1278     return mCamOps->unmap_stream_buf(mCamHandle, mChannelHandle,
   1279                                      mHandle, buf_type,
   1280                                      buf_idx, plane_idx);
   1281 }
   1282 
   1283 /*===========================================================================
   1284  * FUNCTION   : setParameter
   1285  *
   1286  * DESCRIPTION: set stream based parameters
   1287  *
   1288  * PARAMETERS :
   1289  *   @param   : ptr to parameters to be set
   1290  *
   1291  * RETURN     : int32_t type of status
   1292  *              NO_ERROR  -- success
   1293  *              none-zero failure code
   1294  *==========================================================================*/
   1295 int32_t QCamera3Stream::setParameter(cam_stream_parm_buffer_t &param)
   1296 {
   1297     int32_t rc = NO_ERROR;
   1298     mStreamInfo->parm_buf = param;
   1299     ATRACE_CALL();
   1300     rc = mCamOps->set_stream_parms(mCamHandle,
   1301                                    mChannelHandle,
   1302                                    mHandle,
   1303                                    &mStreamInfo->parm_buf);
   1304     if (rc == NO_ERROR) {
   1305         param = mStreamInfo->parm_buf;
   1306     }
   1307     return rc;
   1308 }
   1309 
   1310 /*===========================================================================
   1311  * FUNCTION   : releaseFrameData
   1312  *
   1313  * DESCRIPTION: callback function to release frame data node
   1314  *
   1315  * PARAMETERS :
   1316  *   @data      : ptr to post process input data
   1317  *   @user_data : user data ptr (QCameraReprocessor)
   1318  *
   1319  * RETURN     : None
   1320  *==========================================================================*/
   1321 void QCamera3Stream::releaseFrameData(void *data, void *user_data)
   1322 {
   1323     QCamera3Stream *pme = (QCamera3Stream *)user_data;
   1324     mm_camera_super_buf_t *frame = (mm_camera_super_buf_t *)data;
   1325     if (NULL != pme) {
   1326         if (UNLIKELY(pme->mBatchSize)) {
   1327             /* For batch mode, the batch buffer is added to empty list */
   1328             if(!pme->mFreeBatchBufQ.enqueue((void*) frame->bufs[0])) {
   1329                 LOGE("batchBuf.buf_idx: %d enqueue failed",
   1330                         frame->bufs[0]->buf_idx);
   1331             }
   1332         } else {
   1333             pme->bufDone(frame->bufs[0]->buf_idx);
   1334         }
   1335     }
   1336 }
   1337 
   1338 /*===========================================================================
   1339  * FUNCTION   : getBatchBufs
   1340  *
   1341  * DESCRIPTION: allocate batch containers for the stream
   1342  *
   1343  * PARAMETERS :
   1344  *   @num_bufs   : number of buffers allocated
   1345  *   @initial_reg_flag: flag to indicate if buffer needs to be registered
   1346  *                      at kernel initially
   1347  *   @bufs       : output of allocated buffers
   1348   *  @ops_tbl    : ptr to buf mapping/unmapping ops
   1349  *
   1350  * RETURN     : int32_t type of status
   1351  *              NO_ERROR  -- success
   1352  *              none-zero failure code
   1353  *==========================================================================*/
   1354 int32_t QCamera3Stream::getBatchBufs(
   1355         uint8_t *num_bufs, uint8_t **initial_reg_flag,
   1356         mm_camera_buf_def_t **bufs,
   1357         mm_camera_map_unmap_ops_tbl_t *ops_tbl)
   1358 {
   1359     int rc = NO_ERROR;
   1360     uint8_t *regFlags;
   1361 
   1362     if (!ops_tbl || !num_bufs || !initial_reg_flag || !bufs) {
   1363         LOGE("input args NULL");
   1364         return INVALID_OPERATION;
   1365     }
   1366     LOGH("Batch container allocation stream type = %d",
   1367              getMyType());
   1368 
   1369     Mutex::Autolock lock(mLock);
   1370 
   1371     mMemOps = ops_tbl;
   1372 
   1373     //Allocate batch containers
   1374     mStreamBatchBufs = new QCamera3HeapMemory(1);
   1375     if (!mStreamBatchBufs) {
   1376         LOGE("unable to create batch container memory");
   1377         return NO_MEMORY;
   1378     }
   1379     // Allocating single buffer file-descriptor for all batch containers,
   1380     // mStreamBatchBufs considers all the container bufs as a single buffer. But
   1381     // QCamera3Stream manages that single buffer as multiple batch buffers
   1382     LOGD("Allocating batch container memory. numBatch: %d size: %d",
   1383              mNumBatchBufs, mStreamInfo->user_buf_info.size);
   1384     rc = mStreamBatchBufs->allocate(
   1385             mNumBatchBufs * mStreamInfo->user_buf_info.size);
   1386     if (rc < 0) {
   1387         LOGE("unable to allocate batch container memory");
   1388         rc = NO_MEMORY;
   1389         goto err1;
   1390     }
   1391 
   1392     /* map batch buffers. getCnt here returns 1 because of single FD across
   1393      * batch bufs */
   1394     for (uint32_t i = 0; i < mStreamBatchBufs->getCnt(); i++) {
   1395         if (mNumBatchBufs) {
   1396             //For USER_BUF, size = number_of_container bufs instead of the total
   1397             //buf size
   1398             void* buffer = (mMapStreamBuffers ? mStreamBufs->getPtr(i) : NULL);
   1399             rc = ops_tbl->map_ops(i, -1, mStreamBatchBufs->getFd(i),
   1400                     (size_t)mNumBatchBufs, buffer,
   1401                     CAM_MAPPING_BUF_TYPE_STREAM_USER_BUF,
   1402                     ops_tbl->userdata);
   1403             if (rc < 0) {
   1404                 LOGE("Failed to map stream container buffer: %d",
   1405                          rc);
   1406                 //Unmap all the buffers that were successfully mapped before
   1407                 //this buffer mapping failed
   1408                 for (size_t j = 0; j < i; j++) {
   1409                     ops_tbl->unmap_ops(j, -1,
   1410                             CAM_MAPPING_BUF_TYPE_STREAM_USER_BUF,
   1411                             ops_tbl->userdata);
   1412                 }
   1413                 goto err2;
   1414             }
   1415         } else {
   1416             LOGE("Failed to retrieve buffer size (bad index)");
   1417             return INVALID_OPERATION;
   1418         }
   1419     }
   1420 
   1421     LOGD("batch bufs successfully mmapped = %d",
   1422              mNumBatchBufs);
   1423 
   1424     /* regFlags array is allocated here, but consumed and freed by
   1425      * mm-camera-interface */
   1426     regFlags = (uint8_t *)malloc(sizeof(uint8_t) * mNumBatchBufs);
   1427     if (!regFlags) {
   1428         LOGE("Out of memory");
   1429         rc = NO_MEMORY;
   1430         goto err3;
   1431     }
   1432     memset(regFlags, 0, sizeof(uint8_t) * mNumBatchBufs);
   1433     /* Do not queue the container buffers as the image buffers are not yet
   1434      * queued. mStreamBatchBufs->getRegFlags is not called as mStreamBatchBufs
   1435      * considers single buffer is allocated */
   1436     for (uint32_t i = 0; i < mNumBatchBufs; i++) {
   1437         regFlags[i] = 0;
   1438     }
   1439 
   1440     mBatchBufDefs = (mm_camera_buf_def_t *)
   1441             malloc(mNumBatchBufs * sizeof(mm_camera_buf_def_t));
   1442     if (mBatchBufDefs == NULL) {
   1443         LOGE("mBatchBufDefs memory allocation failed");
   1444         rc = INVALID_OPERATION;
   1445         goto err4;
   1446     }
   1447     memset(mBatchBufDefs, 0, mNumBatchBufs * sizeof(mm_camera_buf_def_t));
   1448 
   1449     //Populate bufDef and queue to free batchBufQ
   1450     for (uint32_t i = 0; i < mNumBatchBufs; i++) {
   1451         getBatchBufDef(mBatchBufDefs[i], i);
   1452         if(mFreeBatchBufQ.enqueue((void*) &mBatchBufDefs[i])) {
   1453             LOGD("mBatchBufDefs[%d]: 0x%p", i, &mBatchBufDefs[i]);
   1454         } else {
   1455             LOGE("enqueue mBatchBufDefs[%d] failed", i);
   1456         }
   1457     }
   1458 
   1459     rc = aggregateStartingBufs(*initial_reg_flag);
   1460     if (rc != NO_ERROR) {
   1461         LOGE("Failed to aggregate starting buffers to the batch %d", rc);
   1462         goto err4;
   1463     }
   1464 
   1465     *num_bufs = mNumBatchBufs;
   1466     *initial_reg_flag = regFlags;
   1467     *bufs = mBatchBufDefs;
   1468     LOGH("stream type: %d, numBufs(batch): %d",
   1469              mStreamInfo->stream_type, mNumBatchBufs);
   1470 
   1471     return NO_ERROR;
   1472 err4:
   1473     free(regFlags);
   1474 err3:
   1475     for (size_t i = 0; i < mStreamBatchBufs->getCnt(); i++) {
   1476         ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_USER_BUF,
   1477                 ops_tbl->userdata);
   1478     }
   1479 err2:
   1480     mStreamBatchBufs->deallocate();
   1481 err1:
   1482     delete mStreamBatchBufs;
   1483     mStreamBatchBufs = NULL;
   1484     return rc;
   1485 }
   1486 
   1487 /*===========================================================================
   1488  * FUNCTION   : putBatchBufs
   1489  *
   1490  * DESCRIPTION: deallocate stream batch buffers
   1491  *
   1492  * PARAMETERS :
   1493  *   @ops_tbl    : ptr to buf mapping/unmapping ops
   1494  *
   1495  * RETURN     : int32_t type of status
   1496  *              NO_ERROR  -- success
   1497  *              none-zero failure code
   1498  *==========================================================================*/
   1499 int32_t QCamera3Stream::putBatchBufs(mm_camera_map_unmap_ops_tbl_t *ops_tbl)
   1500 {
   1501     int rc = NO_ERROR;
   1502     Mutex::Autolock lock(mLock);
   1503 
   1504     if (mStreamBatchBufs) {
   1505         for (uint32_t i = 0; i < mStreamBatchBufs->getCnt(); i++) {
   1506             rc = ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_USER_BUF,
   1507                     ops_tbl->userdata);
   1508             if (rc < 0) {
   1509                 LOGE("un-map batch buf failed: %d", rc);
   1510             }
   1511         }
   1512         mStreamBatchBufs->deallocate();
   1513         delete mStreamBatchBufs;
   1514         mStreamBatchBufs = NULL;
   1515     }
   1516     // mm-camera-interface frees bufDefs even though bufDefs are allocated by
   1517     // QCamera3Stream. Don't free here
   1518     mBatchBufDefs = NULL;
   1519 
   1520     return rc;
   1521 }
   1522 
   1523 /*===========================================================================
   1524  * FUNCTION   : getBatchBufDef
   1525  *
   1526  * DESCRIPTION: query detailed buffer information of batch buffer
   1527  *
   1528  * PARAMETERS :
   1529  *   @bufDef  : [output] reference to struct to store buffer definition
   1530  *   @@index  : [input] index of the buffer
   1531  *
   1532  * RETURN     : int32_t type of status
   1533  *              NO_ERROR  -- success
   1534  *              none-zero failure code
   1535  *==========================================================================*/
   1536 int32_t QCamera3Stream::getBatchBufDef(mm_camera_buf_def_t& batchBufDef,
   1537         int32_t index)
   1538 {
   1539     int rc = NO_ERROR;
   1540     memset(&batchBufDef, 0, sizeof(mm_camera_buf_def_t));
   1541     if (mStreamBatchBufs) {
   1542         //Single file descriptor for all batch buffers
   1543         batchBufDef.fd          = mStreamBatchBufs->getFd(0);
   1544         batchBufDef.buf_type    = CAM_STREAM_BUF_TYPE_USERPTR;
   1545         batchBufDef.frame_len   = mStreamInfo->user_buf_info.size;
   1546         batchBufDef.mem_info    = mStreamBatchBufs;
   1547         batchBufDef.buffer      = (uint8_t *)mStreamBatchBufs->getPtr(0) +
   1548                                     (index * mStreamInfo->user_buf_info.size);
   1549         batchBufDef.buf_idx     = index;
   1550         batchBufDef.user_buf.num_buffers = mBatchSize;
   1551         batchBufDef.user_buf.bufs_used = 0;
   1552         batchBufDef.user_buf.plane_buf = mBufDefs;
   1553     }
   1554 
   1555     return rc;
   1556 }
   1557 
   1558 /*===========================================================================
   1559  * FUNCTION   : aggregateBufToBatch
   1560  *
   1561  * DESCRIPTION: queue batch container to downstream.
   1562  *
   1563  * PARAMETERS :
   1564  *   @bufDef : image buffer to be aggregated into batch
   1565  *
   1566  * RETURN     : int32_t type of status
   1567  *              NO_ERROR  -- success always
   1568  *              none-zero failure code
   1569  *==========================================================================*/
   1570 int32_t QCamera3Stream::aggregateBufToBatch(mm_camera_buf_def_t& bufDef)
   1571 {
   1572     int32_t rc = NO_ERROR;
   1573 
   1574     if (UNLIKELY(!mBatchSize)) {
   1575         LOGE("Batch mod is not enabled");
   1576         return INVALID_OPERATION;
   1577     }
   1578     if (!mCurrentBatchBufDef) {
   1579         mCurrentBatchBufDef = (mm_camera_buf_def_t *)mFreeBatchBufQ.dequeue();
   1580         if (!mCurrentBatchBufDef) {
   1581             LOGE("No empty batch buffers is available");
   1582             return NO_MEMORY;
   1583         }
   1584         LOGD("batch buffer: %d dequeued from empty buffer list",
   1585                 mCurrentBatchBufDef->buf_idx);
   1586     }
   1587     if (mBufsStaged == mCurrentBatchBufDef->user_buf.num_buffers) {
   1588         LOGE("batch buffer is already full");
   1589         return NO_MEMORY;
   1590     }
   1591 
   1592     mCurrentBatchBufDef->user_buf.buf_idx[mBufsStaged] = bufDef.buf_idx;
   1593     mBufsStaged++;
   1594     LOGD("buffer id: %d aggregated into batch buffer id: %d",
   1595              bufDef.buf_idx, mCurrentBatchBufDef->buf_idx);
   1596     return rc;
   1597 }
   1598 
   1599 /*===========================================================================
   1600  * FUNCTION   : aggregateStartingBuffers
   1601  *
   1602  * DESCRIPTION: Aggregate initial buffers to the first batch before stream_on
   1603  *
   1604  * PARAMETERS :
   1605  *   @initial_reg_flag: flag to indicate if buffer needs to be registered
   1606  *                      at kernel initially
   1607  *
   1608  * RETURN     : int32_t type of status
   1609  *              NO_ERROR  -- success always
   1610  *              none-zero failure code
   1611  *==========================================================================*/
   1612 int32_t QCamera3Stream::aggregateStartingBufs(const uint8_t *initial_reg_flag)
   1613 {
   1614     int32_t rc = NO_ERROR;
   1615 
   1616     for (uint8_t i = 0; i < mBatchSize; i++) {
   1617         if (initial_reg_flag[i]) {
   1618             rc = bufDoneLocked(i);
   1619             if (rc != NO_ERROR) {
   1620                 LOGE("Failed to aggregate buffer %d to batch", i);
   1621                 break;
   1622             }
   1623         }
   1624     }
   1625     return rc;
   1626 }
   1627 
   1628 /*===========================================================================
   1629  * FUNCTION   : queueBatchBuf
   1630  *
   1631  * DESCRIPTION: queue batch container to downstream.
   1632  *
   1633  * PARAMETERS : None
   1634  *
   1635  * RETURN     : int32_t type of status
   1636  *              NO_ERROR  -- success always
   1637  *              none-zero failure code
   1638  *==========================================================================*/
   1639 int32_t QCamera3Stream::queueBatchBuf()
   1640 {
   1641     int32_t rc = NO_ERROR;
   1642 
   1643     if (!mCurrentBatchBufDef) {
   1644         LOGE("No buffers were queued into batch");
   1645         return INVALID_OPERATION;
   1646     }
   1647     //bufs_used: number of valid buffers in the batch buffers
   1648     mCurrentBatchBufDef->user_buf.bufs_used = mBufsStaged;
   1649 
   1650     //if mBufsStaged < num_buffers, initialize the buf_idx to -1 for rest of the
   1651     //buffers
   1652     for (size_t i = mBufsStaged; i < mCurrentBatchBufDef->user_buf.num_buffers;
   1653             i++) {
   1654         mCurrentBatchBufDef->user_buf.buf_idx[i] = -1;
   1655     }
   1656 
   1657     rc = mCamOps->qbuf(mCamHandle, mChannelHandle, mCurrentBatchBufDef);
   1658     if (rc < 0) {
   1659         LOGE("queueing of batch buffer: %d failed with err: %d",
   1660                 mCurrentBatchBufDef->buf_idx, rc);
   1661         return FAILED_TRANSACTION;
   1662     }
   1663     LOGD("Batch buf id: %d queued. bufs_used: %d",
   1664             mCurrentBatchBufDef->buf_idx,
   1665             mCurrentBatchBufDef->user_buf.bufs_used);
   1666 
   1667     mCurrentBatchBufDef = NULL;
   1668     mBufsStaged = 0;
   1669 
   1670     return rc;
   1671 }
   1672 
   1673 /*===========================================================================
   1674  * FUNCTION   : handleBatchBuffer
   1675  *
   1676  * DESCRIPTION: separate individual buffers from the batch and issue callback
   1677  *
   1678  * PARAMETERS :
   1679  *   @superBuf : Received superbuf containing batch buffer
   1680  *
   1681  * RETURN     : int32_t type of status
   1682  *              NO_ERROR  -- success always
   1683  *              none-zero failure code
   1684  *==========================================================================*/
   1685 int32_t QCamera3Stream::handleBatchBuffer(mm_camera_super_buf_t *superBuf)
   1686 {
   1687     int32_t rc = NO_ERROR;
   1688     mm_camera_super_buf_t *frame;
   1689     mm_camera_buf_def_t batchBuf;
   1690 
   1691     if (LIKELY(!mBatchSize)) {
   1692         LOGE("Stream: %d not in batch mode, but batch buffer received",
   1693                  getMyType());
   1694         return INVALID_OPERATION;
   1695     }
   1696     if (!mDataCB) {
   1697         LOGE("Data callback not set for batch mode");
   1698         return BAD_VALUE;
   1699     }
   1700     if (!superBuf->bufs[0]) {
   1701         LOGE("superBuf->bufs[0] is NULL!!");
   1702         return BAD_VALUE;
   1703     }
   1704 
   1705     /* Copy the batch buffer to local and queue the batch buffer to  empty queue
   1706      * to handle the new requests received while callbacks are in progress */
   1707     batchBuf = *superBuf->bufs[0];
   1708     if (!mFreeBatchBufQ.enqueue((void*) superBuf->bufs[0])) {
   1709         LOGE("batchBuf.buf_idx: %d enqueue failed",
   1710                 batchBuf.buf_idx);
   1711         free(superBuf);
   1712         return NO_MEMORY;
   1713     }
   1714     LOGD("Received batch buffer: %d bufs_used: %d",
   1715             batchBuf.buf_idx, batchBuf.user_buf.bufs_used);
   1716     //dummy local bufDef to issue multiple callbacks
   1717     mm_camera_buf_def_t buf;
   1718     memset(&buf, 0, sizeof(mm_camera_buf_def_t));
   1719 
   1720     for (size_t i = 0; i < batchBuf.user_buf.bufs_used; i++) {
   1721         int32_t buf_idx = batchBuf.user_buf.buf_idx[i];
   1722         buf = mBufDefs[buf_idx];
   1723 
   1724         /* this memory is freed inside dataCB. Should not be freed here */
   1725         frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
   1726         if (!frame) {
   1727             LOGE("malloc failed. Buffers will be dropped");
   1728             break;
   1729         } else {
   1730             memcpy(frame, superBuf, sizeof(mm_camera_super_buf_t));
   1731             frame->bufs[0] = &buf;
   1732 
   1733             mDataCB(frame, this, mUserData);
   1734         }
   1735     }
   1736     LOGD("batch buffer: %d callbacks done",
   1737             batchBuf.buf_idx);
   1738 
   1739     free(superBuf);
   1740     return rc;
   1741 }
   1742 
   1743 /*===========================================================================
   1744  * FUNCTION   : flushFreeBatchBufQ
   1745  *
   1746  * DESCRIPTION: dequeue all the entries of mFreeBatchBufQ and call flush.
   1747  *              QCameraQueue::flush calls 'free(node->data)' which should be
   1748  *              avoided for mFreeBatchBufQ as the entries are not allocated
   1749  *              during each enqueue
   1750  *
   1751  * PARAMETERS : None
   1752  *
   1753  * RETURN     : None
   1754  *==========================================================================*/
   1755 void QCamera3Stream::flushFreeBatchBufQ()
   1756 {
   1757     while (!mFreeBatchBufQ.isEmpty()) {
   1758         mFreeBatchBufQ.dequeue();
   1759     }
   1760     mFreeBatchBufQ.flush();
   1761 }
   1762 
   1763 }; // namespace qcamera
   1764