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 "QCameraTrace.h"
     36 #include <cutils/properties.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         mCamHandle(camHandle),
    283         mChannelHandle(chId),
    284         mHandle(0),
    285         mCamOps(camOps),
    286         mStreamInfo(NULL),
    287         mMemOps(NULL),
    288         mNumBufs(0),
    289         mDataCB(NULL),
    290         mUserData(NULL),
    291         mDataQ(releaseFrameData, this),
    292         mStreamInfoBuf(NULL),
    293         mStreamBufs(NULL),
    294         mBufDefs(NULL),
    295         mChannel(channel),
    296         mBatchSize(0),
    297         mNumBatchBufs(0),
    298         mStreamBatchBufs(NULL),
    299         mBatchBufDefs(NULL),
    300         mCurrentBatchBufDef(NULL),
    301         mBufsStaged(0),
    302         mFreeBatchBufQ(NULL, this)
    303 {
    304     mMemVtbl.user_data = this;
    305     mMemVtbl.get_bufs = get_bufs;
    306     mMemVtbl.put_bufs = put_bufs;
    307     mMemVtbl.invalidate_buf = invalidate_buf;
    308     mMemVtbl.clean_invalidate_buf = clean_invalidate_buf;
    309     mMemVtbl.clean_buf = clean_buf;
    310     mMemVtbl.set_config_ops = NULL;
    311     memset(&mFrameLenOffset, 0, sizeof(mFrameLenOffset));
    312     memcpy(&mPaddingInfo, paddingInfo, sizeof(cam_padding_info_t));
    313 }
    314 
    315 /*===========================================================================
    316  * FUNCTION   : ~QCamera3Stream
    317  *
    318  * DESCRIPTION: deconstructor of QCamera3Stream
    319  *
    320  * PARAMETERS : None
    321  *
    322  * RETURN     : None
    323  *==========================================================================*/
    324 QCamera3Stream::~QCamera3Stream()
    325 {
    326     if (mStreamInfoBuf != NULL) {
    327         int rc = mCamOps->unmap_stream_buf(mCamHandle,
    328                     mChannelHandle, mHandle, CAM_MAPPING_BUF_TYPE_STREAM_INFO, 0, -1);
    329         if (rc < 0) {
    330             LOGE("Failed to un-map stream info buffer");
    331         }
    332         mStreamInfoBuf->deallocate();
    333         delete mStreamInfoBuf;
    334         mStreamInfoBuf = NULL;
    335     }
    336     // delete stream
    337     if (mHandle > 0) {
    338         mCamOps->delete_stream(mCamHandle, mChannelHandle, mHandle);
    339         mHandle = 0;
    340     }
    341 }
    342 
    343 /*===========================================================================
    344  * FUNCTION   : init
    345  *
    346  * DESCRIPTION: initialize stream obj
    347  *
    348  * PARAMETERS :
    349  *   @streamType     : stream type
    350  *   @streamFormat   : stream format
    351  *   @streamDim      : stream dimension
    352  *   @reprocess_config: reprocess stream input configuration
    353  *   @minNumBuffers  : minimal buffer count for particular stream type
    354  *   @postprocess_mask: PP mask
    355  *   @is_type  : Image stabilization type, cam_is_type_t
    356  *   @batchSize  : Number of image buffers in a batch.
    357  *                 0: No batch. N: container with N image buffers
    358  *   @stream_cb      : callback handle
    359  *   @userdata       : user data
    360  *
    361  * RETURN     : int32_t type of status
    362  *              NO_ERROR  -- success
    363  *              none-zero failure code
    364  *==========================================================================*/
    365 int32_t QCamera3Stream::init(cam_stream_type_t streamType,
    366                             cam_format_t streamFormat,
    367                             cam_dimension_t streamDim,
    368                             cam_rotation_t streamRotation,
    369                             cam_stream_reproc_config_t* reprocess_config,
    370                             uint8_t minNumBuffers,
    371                             cam_feature_mask_t postprocess_mask,
    372                             cam_is_type_t is_type,
    373                             uint32_t batchSize,
    374                             hal3_stream_cb_routine stream_cb,
    375                             void *userdata)
    376 {
    377     int32_t rc = OK;
    378     ssize_t bufSize = BAD_INDEX;
    379     char value[PROPERTY_VALUE_MAX];
    380     uint32_t bOptimizeCacheOps = 0;
    381     mm_camera_stream_config_t stream_config;
    382     LOGD("batch size is %d", batchSize);
    383 
    384     mHandle = mCamOps->add_stream(mCamHandle, mChannelHandle);
    385     if (!mHandle) {
    386         LOGE("add_stream failed");
    387         rc = UNKNOWN_ERROR;
    388         goto done;
    389     }
    390 
    391     // allocate and map stream info memory
    392     mStreamInfoBuf = new QCamera3HeapMemory(1);
    393     if (mStreamInfoBuf == NULL) {
    394         LOGE("no memory for stream info buf obj");
    395         rc = -ENOMEM;
    396         goto err1;
    397     }
    398     rc = mStreamInfoBuf->allocate(sizeof(cam_stream_info_t));
    399     if (rc < 0) {
    400         LOGE("no memory for stream info");
    401         rc = -ENOMEM;
    402         goto err2;
    403     }
    404 
    405     mStreamInfo =
    406         reinterpret_cast<cam_stream_info_t *>(mStreamInfoBuf->getPtr(0));
    407     memset(mStreamInfo, 0, sizeof(cam_stream_info_t));
    408     mStreamInfo->stream_type = streamType;
    409     mStreamInfo->fmt = streamFormat;
    410     mStreamInfo->dim = streamDim;
    411     mStreamInfo->num_bufs = minNumBuffers;
    412     mStreamInfo->pp_config.feature_mask = postprocess_mask;
    413     mStreamInfo->is_type = is_type;
    414     mStreamInfo->pp_config.rotation = streamRotation;
    415 
    416     memset(value, 0, sizeof(value));
    417     property_get("persist.camera.cache.optimize", value, "1");
    418     bOptimizeCacheOps = atoi(value);
    419 
    420     if (bOptimizeCacheOps) {
    421         mStreamInfo->cache_ops = CAM_STREAM_CACHE_OPS_HONOUR_FLAGS;
    422     } else {
    423         mStreamInfo->cache_ops = CAM_STREAM_CACHE_OPS_DISABLED;
    424     }
    425     LOGD("stream_type is %d, feature_mask is %Ld",
    426            mStreamInfo->stream_type, mStreamInfo->pp_config.feature_mask);
    427 
    428     bufSize = mStreamInfoBuf->getSize(0);
    429     if (BAD_INDEX != bufSize) {
    430         rc = mCamOps->map_stream_buf(mCamHandle,
    431                 mChannelHandle, mHandle, CAM_MAPPING_BUF_TYPE_STREAM_INFO,
    432                 0, -1, mStreamInfoBuf->getFd(0), (size_t)bufSize,
    433                 mStreamInfoBuf->getPtr(0));
    434         if (rc < 0) {
    435             LOGE("Failed to map stream info buffer");
    436             goto err3;
    437         }
    438     } else {
    439         LOGE("Failed to retrieve buffer size (bad index)");
    440         goto err3;
    441     }
    442 
    443     mNumBufs = minNumBuffers;
    444     if (reprocess_config != NULL) {
    445         mStreamInfo->reprocess_config = *reprocess_config;
    446         mStreamInfo->streaming_mode = CAM_STREAMING_MODE_BURST;
    447         //mStreamInfo->num_of_burst = reprocess_config->offline.num_of_bufs;
    448         mStreamInfo->num_of_burst = 1;
    449     } else if (batchSize) {
    450         if (batchSize > MAX_BATCH_SIZE) {
    451             LOGE("batchSize:%d is very large", batchSize);
    452             rc = BAD_VALUE;
    453             goto err4;
    454         }
    455         else {
    456             mNumBatchBufs = MAX_INFLIGHT_HFR_REQUESTS / batchSize;
    457             mStreamInfo->streaming_mode = CAM_STREAMING_MODE_BATCH;
    458             mStreamInfo->user_buf_info.frame_buf_cnt = batchSize;
    459             mStreamInfo->user_buf_info.size =
    460                     (uint32_t)(sizeof(msm_camera_user_buf_cont_t));
    461             mStreamInfo->num_bufs = mNumBatchBufs;
    462             //Frame interval is irrelavent since time stamp calculation is not
    463             //required from the mCamOps
    464             mStreamInfo->user_buf_info.frameInterval = 0;
    465             LOGD("batch size is %d", batchSize);
    466         }
    467     } else {
    468         mStreamInfo->streaming_mode = CAM_STREAMING_MODE_CONTINUOUS;
    469     }
    470 
    471     // Configure the stream
    472     stream_config.stream_info = mStreamInfo;
    473     stream_config.mem_vtbl = mMemVtbl;
    474     stream_config.padding_info = mPaddingInfo;
    475     stream_config.userdata = this;
    476     stream_config.stream_cb = dataNotifyCB;
    477     stream_config.stream_cb_sync = NULL;
    478 
    479     rc = mCamOps->config_stream(mCamHandle,
    480             mChannelHandle, mHandle, &stream_config);
    481     if (rc < 0) {
    482         LOGE("Failed to config stream, rc = %d", rc);
    483         goto err4;
    484     }
    485 
    486     mDataCB = stream_cb;
    487     mUserData = userdata;
    488     mBatchSize = batchSize;
    489     return 0;
    490 
    491 err4:
    492     mCamOps->unmap_stream_buf(mCamHandle,
    493             mChannelHandle, mHandle, CAM_MAPPING_BUF_TYPE_STREAM_INFO, 0, -1);
    494 err3:
    495     mStreamInfoBuf->deallocate();
    496 err2:
    497     delete mStreamInfoBuf;
    498     mStreamInfoBuf = NULL;
    499     mStreamInfo = NULL;
    500 err1:
    501     mCamOps->delete_stream(mCamHandle, mChannelHandle, mHandle);
    502     mHandle = 0;
    503     mNumBufs = 0;
    504 done:
    505     return rc;
    506 }
    507 
    508 /*===========================================================================
    509  * FUNCTION   : start
    510  *
    511  * DESCRIPTION: start stream. Will start main stream thread to handle stream
    512  *              related ops.
    513  *
    514  * PARAMETERS : none
    515  *
    516  * RETURN     : int32_t type of status
    517  *              NO_ERROR  -- success
    518  *              none-zero failure code
    519  *==========================================================================*/
    520 int32_t QCamera3Stream::start()
    521 {
    522     int32_t rc = 0;
    523 
    524     mDataQ.init();
    525     mTimeoutFrameQ.clear();
    526     if (mBatchSize)
    527         mFreeBatchBufQ.init();
    528     rc = mProcTh.launch(dataProcRoutine, this);
    529     return rc;
    530 }
    531 
    532 /*===========================================================================
    533  * FUNCTION   : stop
    534  *
    535  * DESCRIPTION: stop stream. Will stop main stream thread
    536  *
    537  * PARAMETERS : none
    538  *
    539  * RETURN     : int32_t type of status
    540  *              NO_ERROR  -- success
    541  *              none-zero failure code
    542  *==========================================================================*/
    543 int32_t QCamera3Stream::stop()
    544 {
    545     int32_t rc = 0;
    546     rc = mProcTh.exit();
    547     return rc;
    548 }
    549 
    550 /*===========================================================================
    551  * FUNCTION   : timeoutFrame
    552  *
    553  * DESCRIPTION: Function to issue timeout on frame
    554  *
    555  * PARAMETERS :
    556  *   @bufIdx  : buffer index of the frame to be timed out
    557  *
    558  * RETURN     : int32_t type of status
    559  *              NO_ERROR  -- success
    560  *              none-zero failure code
    561  *==========================================================================*/
    562 int32_t QCamera3Stream::timeoutFrame(int32_t bufIdx)
    563 {
    564     LOGD("E\n");
    565     int32_t rc;
    566     {
    567         Mutex::Autolock lock(mTimeoutFrameQLock);
    568         mTimeoutFrameQ.push_back(bufIdx);
    569     }
    570     rc = mProcTh.sendCmd(CAMERA_CMD_TYPE_TIMEOUT, FALSE, FALSE);
    571     LOGD("X\n");
    572     return rc;
    573 }
    574 
    575 /*===========================================================================
    576  * FUNCTION   : processDataNotify
    577  *
    578  * DESCRIPTION: process stream data notify
    579  *
    580  * PARAMETERS :
    581  *   @frame   : stream frame received
    582  *
    583  * RETURN     : int32_t type of status
    584  *              NO_ERROR  -- success
    585  *              none-zero failure code
    586  *==========================================================================*/
    587 int32_t QCamera3Stream::processDataNotify(mm_camera_super_buf_t *frame)
    588 {
    589     LOGD("E\n");
    590     int32_t rc;
    591     if (mDataQ.enqueue((void *)frame)) {
    592         rc = mProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
    593     } else {
    594         LOGD("Stream thread is not active, no ops here");
    595         bufDone(frame->bufs[0]->buf_idx);
    596         free(frame);
    597         rc = NO_ERROR;
    598     }
    599     LOGD("X\n");
    600     return rc;
    601 }
    602 
    603 /*===========================================================================
    604  * FUNCTION   : dataNotifyCB
    605  *
    606  * DESCRIPTION: callback for data notify. This function is registered with
    607  *              mm-camera-interface to handle data notify
    608  *
    609  * PARAMETERS :
    610  *   @recvd_frame   : stream frame received
    611  *   userdata       : user data ptr
    612  *
    613  * RETURN     : none
    614  *==========================================================================*/
    615 void QCamera3Stream::dataNotifyCB(mm_camera_super_buf_t *recvd_frame,
    616                                  void *userdata)
    617 {
    618     LOGD("E\n");
    619     QCamera3Stream* stream = (QCamera3Stream *)userdata;
    620     if (stream == NULL ||
    621         recvd_frame == NULL ||
    622         recvd_frame->bufs[0] == NULL ||
    623         recvd_frame->bufs[0]->stream_id != stream->getMyHandle()) {
    624         LOGE("Not a valid stream to handle buf");
    625         return;
    626     }
    627 
    628     mm_camera_super_buf_t *frame =
    629         (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
    630     if (frame == NULL) {
    631         LOGE("No mem for mm_camera_buf_def_t");
    632         stream->bufDone(recvd_frame->bufs[0]->buf_idx);
    633         return;
    634     }
    635     *frame = *recvd_frame;
    636     stream->processDataNotify(frame);
    637     return;
    638 }
    639 
    640 /*===========================================================================
    641  * FUNCTION   : dataProcRoutine
    642  *
    643  * DESCRIPTION: function to process data in the main stream thread
    644  *
    645  * PARAMETERS :
    646  *   @data    : user data ptr
    647  *
    648  * RETURN     : none
    649  *==========================================================================*/
    650 void *QCamera3Stream::dataProcRoutine(void *data)
    651 {
    652     int running = 1;
    653     int ret;
    654     QCamera3Stream *pme = (QCamera3Stream *)data;
    655     QCameraCmdThread *cmdThread = &pme->mProcTh;
    656 
    657     cmdThread->setName(mStreamNames[pme->mStreamInfo->stream_type]);
    658 
    659     LOGD("E");
    660     do {
    661         do {
    662             ret = cam_sem_wait(&cmdThread->cmd_sem);
    663             if (ret != 0 && errno != EINVAL) {
    664                 LOGE("cam_sem_wait error (%s)",
    665                        strerror(errno));
    666                 return NULL;
    667             }
    668         } while (ret != 0);
    669 
    670         // we got notified about new cmd avail in cmd queue
    671         camera_cmd_type_t cmd = cmdThread->getCmd();
    672         switch (cmd) {
    673         case CAMERA_CMD_TYPE_TIMEOUT:
    674             {
    675                 int32_t bufIdx;
    676                 {
    677                     Mutex::Autolock lock(pme->mTimeoutFrameQLock);
    678                     if (pme->mTimeoutFrameQ.size()) {
    679                         auto itr = pme->mTimeoutFrameQ.begin();
    680                         bufIdx = *itr;
    681                         itr = pme->mTimeoutFrameQ.erase(itr);
    682                     } else {
    683                         LOGE("Timeout command received but Q is empty");
    684                         break;
    685                     }
    686                 }
    687                 pme->cancelBuffer(bufIdx);
    688                 break;
    689             }
    690         case CAMERA_CMD_TYPE_DO_NEXT_JOB:
    691             {
    692                 LOGD("Do next job");
    693                 mm_camera_super_buf_t *frame =
    694                     (mm_camera_super_buf_t *)pme->mDataQ.dequeue();
    695                 if (NULL != frame) {
    696                     if (UNLIKELY(frame->bufs[0]->buf_type ==
    697                             CAM_STREAM_BUF_TYPE_USERPTR)) {
    698                         pme->handleBatchBuffer(frame);
    699                     } else if (pme->mDataCB != NULL) {
    700                         pme->mDataCB(frame, pme, pme->mUserData);
    701                     } else {
    702                         // no data cb routine, return buf here
    703                         pme->bufDone(frame->bufs[0]->buf_idx);
    704                     }
    705                 }
    706             }
    707             break;
    708         case CAMERA_CMD_TYPE_EXIT:
    709             LOGH("Exit");
    710             pme->flushFreeBatchBufQ();
    711             /* flush data buf queue */
    712             pme->mDataQ.flush();
    713             pme->mTimeoutFrameQ.clear();
    714             running = 0;
    715             break;
    716         default:
    717             break;
    718         }
    719     } while (running);
    720     LOGD("X");
    721     return NULL;
    722 }
    723 
    724 /*===========================================================================
    725  * FUNCTION   : bufDone
    726  *
    727  * DESCRIPTION: return stream buffer to kernel
    728  *
    729  * PARAMETERS :
    730  *   @index   : index of buffer to be returned
    731  *
    732  * RETURN     : int32_t type of status
    733  *              NO_ERROR  -- success
    734  *              none-zero failure code
    735  *==========================================================================*/
    736 int32_t QCamera3Stream::bufDone(uint32_t index)
    737 {
    738     int32_t rc = NO_ERROR;
    739     Mutex::Autolock lock(mLock);
    740 
    741     if ((index >= mNumBufs) || (mBufDefs == NULL)) {
    742         LOGE("index; %d, mNumBufs: %d", index, mNumBufs);
    743         return BAD_INDEX;
    744     }
    745     if (mStreamBufs == NULL)
    746     {
    747         LOGE("putBufs already called");
    748         return INVALID_OPERATION;
    749     }
    750 
    751     if( NULL == mBufDefs[index].mem_info) {
    752         if (NULL == mMemOps) {
    753             LOGE("Camera operations not initialized");
    754             return NO_INIT;
    755         }
    756 
    757         ssize_t bufSize = mStreamBufs->getSize(index);
    758 
    759         if (BAD_INDEX != bufSize) {
    760             LOGD("Map streamBufIdx: %d", index);
    761             rc = mMemOps->map_ops(index, -1, mStreamBufs->getFd(index),
    762                     (size_t)bufSize, mStreamBufs->getPtr(index),
    763                     CAM_MAPPING_BUF_TYPE_STREAM_BUF, mMemOps->userdata);
    764             if (rc < 0) {
    765                 LOGE("Failed to map camera buffer %d", index);
    766                 return rc;
    767             }
    768 
    769             rc = mStreamBufs->getBufDef(mFrameLenOffset, mBufDefs[index], index);
    770             if (NO_ERROR != rc) {
    771                 LOGE("Couldn't find camera buffer definition");
    772                 mMemOps->unmap_ops(index, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF, mMemOps->userdata);
    773                 return rc;
    774             }
    775         } else {
    776             LOGE("Failed to retrieve buffer size (bad index)");
    777             return INVALID_OPERATION;
    778         }
    779     }
    780 
    781     if (UNLIKELY(mBatchSize)) {
    782         rc = aggregateBufToBatch(mBufDefs[index]);
    783     } else {
    784         // Cache invalidation should happen in lockNextBuffer or during
    785         // reprocessing. No need to invalidate every buffer without knowing
    786         // which buffer is accessed by CPU.
    787         rc = mCamOps->qbuf(mCamHandle, mChannelHandle, &mBufDefs[index]);
    788         if (rc < 0) {
    789             return FAILED_TRANSACTION;
    790         }
    791     }
    792 
    793     return rc;
    794 }
    795 
    796 /*===========================================================================
    797  * FUNCTION   : cancelBuffer
    798  *
    799  * DESCRIPTION: Issue cancel buffer request to kernel
    800  *
    801  * PARAMETERS :
    802  *   @index   : index of buffer to be cancelled
    803  *
    804  * RETURN     : int32_t type of status
    805  *              NO_ERROR  -- success
    806  *              none-zero failure code
    807  *==========================================================================*/
    808 int32_t QCamera3Stream::cancelBuffer(uint32_t index)
    809 {
    810     int32_t rc = NO_ERROR;
    811     Mutex::Autolock lock(mLock);
    812 
    813     if ((index >= mNumBufs) || (mBufDefs == NULL)) {
    814         LOGE("index; %d, mNumBufs: %d", index, mNumBufs);
    815         return BAD_INDEX;
    816     }
    817     if (mStreamBufs == NULL)
    818     {
    819         LOGE("putBufs already called");
    820         return INVALID_OPERATION;
    821     }
    822 
    823     /* if (UNLIKELY(mBatchSize)) {
    824         FIXME
    825     } else */{
    826         ALOGE("Calling cancel buf on idx:%d for stream type:%d",index, getMyType());
    827         rc = mCamOps->cancel_buffer(mCamHandle, mChannelHandle, mHandle, index);
    828         if (rc < 0) {
    829             return FAILED_TRANSACTION;
    830         }
    831     }
    832 
    833     return rc;
    834 }
    835 
    836 /*===========================================================================
    837  * FUNCTION   : bufRelease
    838  *
    839  * DESCRIPTION: release all resources associated with this buffer
    840  *
    841  * PARAMETERS :
    842  *   @index   : index of buffer to be released
    843  *
    844  * RETURN     : int32_t type of status
    845  *              NO_ERROR  -- success
    846  *              none-zero failure code
    847  *==========================================================================*/
    848 int32_t QCamera3Stream::bufRelease(int32_t index)
    849 {
    850     int32_t rc = NO_ERROR;
    851     Mutex::Autolock lock(mLock);
    852 
    853     if ((index >= mNumBufs) || (mBufDefs == NULL)) {
    854         return BAD_INDEX;
    855     }
    856 
    857     if (NULL != mBufDefs[index].mem_info) {
    858         if (NULL == mMemOps) {
    859             LOGE("Camera operations not initialized");
    860             return NO_INIT;
    861         }
    862 
    863         rc = mMemOps->unmap_ops(index, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF,
    864                 mMemOps->userdata);
    865         if (rc < 0) {
    866             LOGE("Failed to un-map camera buffer %d", index);
    867             return rc;
    868         }
    869 
    870         mBufDefs[index].mem_info = NULL;
    871     } else {
    872         LOGE("Buffer at index %d not registered", index);
    873         return BAD_INDEX;
    874     }
    875 
    876     return rc;
    877 }
    878 
    879 /*===========================================================================
    880  * FUNCTION   : getBufs
    881  *
    882  * DESCRIPTION: allocate stream buffers
    883  *
    884  * PARAMETERS :
    885  *   @offset     : offset info of stream buffers
    886  *   @num_bufs   : number of buffers allocated
    887  *   @initial_reg_flag: flag to indicate if buffer needs to be registered
    888  *                      at kernel initially
    889  *   @bufs       : output of allocated buffers
    890  *   @ops_tbl    : ptr to buf mapping/unmapping ops
    891  *
    892  * RETURN     : int32_t type of status
    893  *              NO_ERROR  -- success
    894  *              none-zero failure code
    895  *==========================================================================*/
    896 int32_t QCamera3Stream::getBufs(cam_frame_len_offset_t *offset,
    897                      uint8_t *num_bufs,
    898                      uint8_t **initial_reg_flag,
    899                      mm_camera_buf_def_t **bufs,
    900                      mm_camera_map_unmap_ops_tbl_t *ops_tbl)
    901 {
    902     int rc = NO_ERROR;
    903     uint8_t *regFlags;
    904     Mutex::Autolock lock(mLock);
    905 
    906     if (!ops_tbl) {
    907         LOGE("ops_tbl is NULL");
    908         return INVALID_OPERATION;
    909     }
    910 
    911     mFrameLenOffset = *offset;
    912     mMemOps = ops_tbl;
    913 
    914     if (mStreamBufs != NULL) {
    915        LOGE("Failed getBufs being called twice in a row without a putBufs call");
    916        return INVALID_OPERATION;
    917     }
    918     mStreamBufs = mChannel->getStreamBufs(mFrameLenOffset.frame_len);
    919     if (!mStreamBufs) {
    920         LOGE("Failed to allocate stream buffers");
    921         return NO_MEMORY;
    922     }
    923 
    924     for (uint32_t i = 0; i < mNumBufs; i++) {
    925         if (mStreamBufs->valid(i)) {
    926             ssize_t bufSize = mStreamBufs->getSize(i);
    927             if (BAD_INDEX != bufSize) {
    928                 rc = ops_tbl->map_ops(i, -1, mStreamBufs->getFd(i),
    929                         (size_t)bufSize, mStreamBufs->getPtr(i),
    930                         CAM_MAPPING_BUF_TYPE_STREAM_BUF,
    931                         ops_tbl->userdata);
    932                 if (rc < 0) {
    933                     LOGE("map_stream_buf failed: %d", rc);
    934                     for (uint32_t j = 0; j < i; j++) {
    935                         if (mStreamBufs->valid(j)) {
    936                             ops_tbl->unmap_ops(j, -1,
    937                                     CAM_MAPPING_BUF_TYPE_STREAM_BUF,
    938                                     ops_tbl->userdata);
    939                         }
    940                     }
    941                     return INVALID_OPERATION;
    942                 }
    943             } else {
    944                 LOGE("Failed to retrieve buffer size (bad index)");
    945                 return INVALID_OPERATION;
    946             }
    947         }
    948     }
    949 
    950     //regFlags array is allocated by us, but consumed and freed by mm-camera-interface
    951     regFlags = (uint8_t *)malloc(sizeof(uint8_t) * mNumBufs);
    952     if (!regFlags) {
    953         LOGE("Out of memory");
    954         for (uint32_t i = 0; i < mNumBufs; i++) {
    955             if (mStreamBufs->valid(i)) {
    956                 ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF,
    957                         ops_tbl->userdata);
    958             }
    959         }
    960         return NO_MEMORY;
    961     }
    962     memset(regFlags, 0, sizeof(uint8_t) * mNumBufs);
    963 
    964     mBufDefs = (mm_camera_buf_def_t *)malloc(mNumBufs * sizeof(mm_camera_buf_def_t));
    965     if (mBufDefs == NULL) {
    966         LOGE("Failed to allocate mm_camera_buf_def_t %d", rc);
    967         for (uint32_t i = 0; i < mNumBufs; i++) {
    968             if (mStreamBufs->valid(i)) {
    969                 ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF,
    970                         ops_tbl->userdata);
    971             }
    972         }
    973         free(regFlags);
    974         regFlags = NULL;
    975         return INVALID_OPERATION;
    976     }
    977     memset(mBufDefs, 0, mNumBufs * sizeof(mm_camera_buf_def_t));
    978     for (uint32_t i = 0; i < mNumBufs; i++) {
    979         if (mStreamBufs->valid(i)) {
    980             mStreamBufs->getBufDef(mFrameLenOffset, mBufDefs[i], i);
    981         }
    982     }
    983 
    984     rc = mStreamBufs->getRegFlags(regFlags);
    985     if (rc < 0) {
    986         LOGE("getRegFlags failed %d", rc);
    987         for (uint32_t i = 0; i < mNumBufs; i++) {
    988             if (mStreamBufs->valid(i)) {
    989                 ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF,
    990                         ops_tbl->userdata);
    991             }
    992         }
    993         free(mBufDefs);
    994         mBufDefs = NULL;
    995         free(regFlags);
    996         regFlags = NULL;
    997         return INVALID_OPERATION;
    998     }
    999 
   1000     *num_bufs = mNumBufs;
   1001     *initial_reg_flag = regFlags;
   1002     *bufs = mBufDefs;
   1003     return NO_ERROR;
   1004 }
   1005 
   1006 /*===========================================================================
   1007  * FUNCTION   : putBufs
   1008  *
   1009  * DESCRIPTION: deallocate stream buffers
   1010  *
   1011  * PARAMETERS :
   1012  *   @ops_tbl    : ptr to buf mapping/unmapping ops
   1013  *
   1014  * RETURN     : int32_t type of status
   1015  *              NO_ERROR  -- success
   1016  *              none-zero failure code
   1017  *==========================================================================*/
   1018 int32_t QCamera3Stream::putBufs(mm_camera_map_unmap_ops_tbl_t *ops_tbl)
   1019 {
   1020     int rc = NO_ERROR;
   1021     Mutex::Autolock lock(mLock);
   1022 
   1023     for (uint32_t i = 0; i < mNumBufs; i++) {
   1024         if (mStreamBufs->valid(i) && NULL != mBufDefs[i].mem_info) {
   1025             rc = ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF, ops_tbl->userdata);
   1026             if (rc < 0) {
   1027                 LOGE("un-map stream buf failed: %d", rc);
   1028             }
   1029         }
   1030     }
   1031     mBufDefs = NULL; // mBufDefs just keep a ptr to the buffer
   1032                      // mm-camera-interface own the buffer, so no need to free
   1033     memset(&mFrameLenOffset, 0, sizeof(mFrameLenOffset));
   1034 
   1035     if (mStreamBufs == NULL) {
   1036         LOGE("getBuf failed previously, or calling putBufs twice");
   1037     }
   1038 
   1039     mChannel->putStreamBufs();
   1040 
   1041     //need to set mStreamBufs to null because putStreamBufs deletes that memory
   1042     mStreamBufs = NULL;
   1043 
   1044     return rc;
   1045 }
   1046 
   1047 /*===========================================================================
   1048  * FUNCTION   : invalidateBuf
   1049  *
   1050  * DESCRIPTION: invalidate a specific stream buffer
   1051  *
   1052  * PARAMETERS :
   1053  *   @index   : index of the buffer to invalidate
   1054  *
   1055  * RETURN     : int32_t type of status
   1056  *              NO_ERROR  -- success
   1057  *              none-zero failure code
   1058  *==========================================================================*/
   1059 int32_t QCamera3Stream::invalidateBuf(uint32_t index)
   1060 {
   1061     if (mStreamBufs == NULL) {
   1062        LOGE("putBufs already called");
   1063        return INVALID_OPERATION;
   1064     } else
   1065        return mStreamBufs->invalidateCache(index);
   1066 }
   1067 
   1068 /*===========================================================================
   1069  * FUNCTION   : cleanInvalidateBuf
   1070  *
   1071  * DESCRIPTION: clean and invalidate a specific stream buffer
   1072  *
   1073  * PARAMETERS :
   1074  *   @index   : index of the buffer to invalidate
   1075  *
   1076  * RETURN     : int32_t type of status
   1077  *              NO_ERROR  -- success
   1078  *              none-zero failure code
   1079  *==========================================================================*/
   1080 int32_t QCamera3Stream::cleanInvalidateBuf(uint32_t index)
   1081 {
   1082     if (mStreamBufs == NULL) {
   1083         LOGE("putBufs already called");
   1084         return INVALID_OPERATION;
   1085     } else
   1086         return mStreamBufs->cleanInvalidateCache(index);
   1087 }
   1088 
   1089 /*===========================================================================
   1090  * FUNCTION   : cleanBuf
   1091  *
   1092  * DESCRIPTION: clean a specific stream buffer
   1093  *
   1094  * PARAMETERS :
   1095  *   @index   : index of the buffer to invalidate
   1096  *
   1097  * RETURN     : int32_t type of status
   1098  *              NO_ERROR  -- success
   1099  *              none-zero failure code
   1100  *==========================================================================*/
   1101 int32_t QCamera3Stream::cleanBuf(uint32_t index)
   1102 {
   1103     if (mStreamBufs == NULL) {
   1104         LOGE("putBufs already called");
   1105         return INVALID_OPERATION;
   1106     } else
   1107         return mStreamBufs->cleanCache(index);
   1108 }
   1109 
   1110 /*===========================================================================
   1111  * FUNCTION   : getFrameOffset
   1112  *
   1113  * DESCRIPTION: query stream buffer frame offset info
   1114  *
   1115  * PARAMETERS :
   1116  *   @offset  : reference to struct to store the queried frame offset info
   1117  *
   1118  * RETURN     : int32_t type of status
   1119  *              NO_ERROR  -- success
   1120  *              none-zero failure code
   1121  *==========================================================================*/
   1122 int32_t QCamera3Stream::getFrameOffset(cam_frame_len_offset_t &offset)
   1123 {
   1124     offset = mFrameLenOffset;
   1125     return 0;
   1126 }
   1127 
   1128 /*===========================================================================
   1129  * FUNCTION   : getFrameDimension
   1130  *
   1131  * DESCRIPTION: query stream frame dimension info
   1132  *
   1133  * PARAMETERS :
   1134  *   @dim     : reference to struct to store the queried frame dimension
   1135  *
   1136  * RETURN     : int32_t type of status
   1137  *              NO_ERROR  -- success
   1138  *              none-zero failure code
   1139  *==========================================================================*/
   1140 int32_t QCamera3Stream::getFrameDimension(cam_dimension_t &dim)
   1141 {
   1142     if (mStreamInfo != NULL) {
   1143         dim = mStreamInfo->dim;
   1144         return 0;
   1145     }
   1146     return -1;
   1147 }
   1148 
   1149 /*===========================================================================
   1150  * FUNCTION   : getFormat
   1151  *
   1152  * DESCRIPTION: query stream format
   1153  *
   1154  * PARAMETERS :
   1155  *   @fmt     : reference to stream format
   1156  *
   1157  * RETURN     : int32_t type of status
   1158  *              NO_ERROR  -- success
   1159  *              none-zero failure code
   1160  *==========================================================================*/
   1161 int32_t QCamera3Stream::getFormat(cam_format_t &fmt)
   1162 {
   1163     if (mStreamInfo != NULL) {
   1164         fmt = mStreamInfo->fmt;
   1165         return 0;
   1166     }
   1167     return -1;
   1168 }
   1169 
   1170 /*===========================================================================
   1171  * FUNCTION   : getMyServerID
   1172  *
   1173  * DESCRIPTION: query server stream ID
   1174  *
   1175  * PARAMETERS : None
   1176  *
   1177  * RETURN     : stream ID from server
   1178  *==========================================================================*/
   1179 uint32_t QCamera3Stream::getMyServerID() {
   1180     if (mStreamInfo != NULL) {
   1181         return mStreamInfo->stream_svr_id;
   1182     } else {
   1183         return 0;
   1184     }
   1185 }
   1186 
   1187 /*===========================================================================
   1188  * FUNCTION   : getMyType
   1189  *
   1190  * DESCRIPTION: query stream type
   1191  *
   1192  * PARAMETERS : None
   1193  *
   1194  * RETURN     : type of stream
   1195  *==========================================================================*/
   1196 cam_stream_type_t QCamera3Stream::getMyType() const
   1197 {
   1198     if (mStreamInfo != NULL) {
   1199         return mStreamInfo->stream_type;
   1200     } else {
   1201         return CAM_STREAM_TYPE_MAX;
   1202     }
   1203 }
   1204 
   1205 /*===========================================================================
   1206  * FUNCTION   : mapBuf
   1207  *
   1208  * DESCRIPTION: map stream related buffer to backend server
   1209  *
   1210  * PARAMETERS :
   1211  *   @buf_type : mapping type of buffer
   1212  *   @buf_idx  : index of buffer
   1213  *   @plane_idx: plane index
   1214  *   @fd       : fd of the buffer
   1215  *   @buffer : buffer ptr
   1216  *   @size     : lenght of the buffer
   1217  *
   1218  * RETURN     : int32_t type of status
   1219  *              NO_ERROR  -- success
   1220  *              none-zero failure code
   1221  *==========================================================================*/
   1222 int32_t QCamera3Stream::mapBuf(uint8_t buf_type, uint32_t buf_idx,
   1223         int32_t plane_idx, int fd, void *buffer, size_t size)
   1224 {
   1225     ATRACE_CALL();
   1226     return mCamOps->map_stream_buf(mCamHandle, mChannelHandle,
   1227                                    mHandle, buf_type,
   1228                                    buf_idx, plane_idx,
   1229                                    fd, size, buffer);
   1230 
   1231 }
   1232 
   1233 /*===========================================================================
   1234  * FUNCTION   : unmapBuf
   1235  *
   1236  * DESCRIPTION: unmap 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  *
   1243  * RETURN     : int32_t type of status
   1244  *              NO_ERROR  -- success
   1245  *              none-zero failure code
   1246  *==========================================================================*/
   1247 int32_t QCamera3Stream::unmapBuf(uint8_t buf_type, uint32_t buf_idx, int32_t plane_idx)
   1248 {
   1249     ATRACE_CALL();
   1250     return mCamOps->unmap_stream_buf(mCamHandle, mChannelHandle,
   1251                                      mHandle, buf_type,
   1252                                      buf_idx, plane_idx);
   1253 }
   1254 
   1255 /*===========================================================================
   1256  * FUNCTION   : setParameter
   1257  *
   1258  * DESCRIPTION: set stream based parameters
   1259  *
   1260  * PARAMETERS :
   1261  *   @param   : ptr to parameters to be set
   1262  *
   1263  * RETURN     : int32_t type of status
   1264  *              NO_ERROR  -- success
   1265  *              none-zero failure code
   1266  *==========================================================================*/
   1267 int32_t QCamera3Stream::setParameter(cam_stream_parm_buffer_t &param)
   1268 {
   1269     int32_t rc = NO_ERROR;
   1270     mStreamInfo->parm_buf = param;
   1271     ATRACE_CALL();
   1272     rc = mCamOps->set_stream_parms(mCamHandle,
   1273                                    mChannelHandle,
   1274                                    mHandle,
   1275                                    &mStreamInfo->parm_buf);
   1276     if (rc == NO_ERROR) {
   1277         param = mStreamInfo->parm_buf;
   1278     }
   1279     return rc;
   1280 }
   1281 
   1282 /*===========================================================================
   1283  * FUNCTION   : releaseFrameData
   1284  *
   1285  * DESCRIPTION: callback function to release frame data node
   1286  *
   1287  * PARAMETERS :
   1288  *   @data      : ptr to post process input data
   1289  *   @user_data : user data ptr (QCameraReprocessor)
   1290  *
   1291  * RETURN     : None
   1292  *==========================================================================*/
   1293 void QCamera3Stream::releaseFrameData(void *data, void *user_data)
   1294 {
   1295     QCamera3Stream *pme = (QCamera3Stream *)user_data;
   1296     mm_camera_super_buf_t *frame = (mm_camera_super_buf_t *)data;
   1297     if (NULL != pme) {
   1298         if (UNLIKELY(pme->mBatchSize)) {
   1299             /* For batch mode, the batch buffer is added to empty list */
   1300             if(!pme->mFreeBatchBufQ.enqueue((void*) frame->bufs[0])) {
   1301                 LOGE("batchBuf.buf_idx: %d enqueue failed",
   1302                         frame->bufs[0]->buf_idx);
   1303             }
   1304         } else {
   1305             pme->bufDone(frame->bufs[0]->buf_idx);
   1306         }
   1307     }
   1308 }
   1309 
   1310 /*===========================================================================
   1311  * FUNCTION   : getBatchBufs
   1312  *
   1313  * DESCRIPTION: allocate batch containers for the stream
   1314  *
   1315  * PARAMETERS :
   1316  *   @num_bufs   : number of buffers allocated
   1317  *   @initial_reg_flag: flag to indicate if buffer needs to be registered
   1318  *                      at kernel initially
   1319  *   @bufs       : output of allocated buffers
   1320   *  @ops_tbl    : ptr to buf mapping/unmapping ops
   1321  *
   1322  * RETURN     : int32_t type of status
   1323  *              NO_ERROR  -- success
   1324  *              none-zero failure code
   1325  *==========================================================================*/
   1326 int32_t QCamera3Stream::getBatchBufs(
   1327         uint8_t *num_bufs, uint8_t **initial_reg_flag,
   1328         mm_camera_buf_def_t **bufs,
   1329         mm_camera_map_unmap_ops_tbl_t *ops_tbl)
   1330 {
   1331     int rc = NO_ERROR;
   1332     uint8_t *regFlags;
   1333 
   1334     if (!ops_tbl || !num_bufs || !initial_reg_flag || !bufs) {
   1335         LOGE("input args NULL");
   1336         return INVALID_OPERATION;
   1337     }
   1338     LOGH("Batch container allocation stream type = %d",
   1339              getMyType());
   1340 
   1341     Mutex::Autolock lock(mLock);
   1342 
   1343     mMemOps = ops_tbl;
   1344 
   1345     //Allocate batch containers
   1346     mStreamBatchBufs = new QCamera3HeapMemory(1);
   1347     if (!mStreamBatchBufs) {
   1348         LOGE("unable to create batch container memory");
   1349         return NO_MEMORY;
   1350     }
   1351     // Allocating single buffer file-descriptor for all batch containers,
   1352     // mStreamBatchBufs considers all the container bufs as a single buffer. But
   1353     // QCamera3Stream manages that single buffer as multiple batch buffers
   1354     LOGD("Allocating batch container memory. numBatch: %d size: %d",
   1355              mNumBatchBufs, mStreamInfo->user_buf_info.size);
   1356     rc = mStreamBatchBufs->allocate(
   1357             mNumBatchBufs * mStreamInfo->user_buf_info.size);
   1358     if (rc < 0) {
   1359         LOGE("unable to allocate batch container memory");
   1360         rc = NO_MEMORY;
   1361         goto err1;
   1362     }
   1363 
   1364     /* map batch buffers. getCnt here returns 1 because of single FD across
   1365      * batch bufs */
   1366     for (uint32_t i = 0; i < mStreamBatchBufs->getCnt(); i++) {
   1367         if (mNumBatchBufs) {
   1368             //For USER_BUF, size = number_of_container bufs instead of the total
   1369             //buf size
   1370             rc = ops_tbl->map_ops(i, -1, mStreamBatchBufs->getFd(i),
   1371                     (size_t)mNumBatchBufs, mStreamBatchBufs->getPtr(i),
   1372                     CAM_MAPPING_BUF_TYPE_STREAM_USER_BUF,
   1373                     ops_tbl->userdata);
   1374             if (rc < 0) {
   1375                 LOGE("Failed to map stream container buffer: %d",
   1376                          rc);
   1377                 //Unmap all the buffers that were successfully mapped before
   1378                 //this buffer mapping failed
   1379                 for (size_t j = 0; j < i; j++) {
   1380                     ops_tbl->unmap_ops(j, -1,
   1381                             CAM_MAPPING_BUF_TYPE_STREAM_USER_BUF,
   1382                             ops_tbl->userdata);
   1383                 }
   1384                 goto err2;
   1385             }
   1386         } else {
   1387             LOGE("Failed to retrieve buffer size (bad index)");
   1388             return INVALID_OPERATION;
   1389         }
   1390     }
   1391 
   1392     LOGD("batch bufs successfully mmapped = %d",
   1393              mNumBatchBufs);
   1394 
   1395     /* regFlags array is allocated here, but consumed and freed by
   1396      * mm-camera-interface */
   1397     regFlags = (uint8_t *)malloc(sizeof(uint8_t) * mNumBatchBufs);
   1398     if (!regFlags) {
   1399         LOGE("Out of memory");
   1400         rc = NO_MEMORY;
   1401         goto err3;
   1402     }
   1403     memset(regFlags, 0, sizeof(uint8_t) * mNumBatchBufs);
   1404     /* Do not queue the container buffers as the image buffers are not yet
   1405      * queued. mStreamBatchBufs->getRegFlags is not called as mStreamBatchBufs
   1406      * considers single buffer is allocated */
   1407     for (uint32_t i = 0; i < mNumBatchBufs; i++) {
   1408         regFlags[i] = 0;
   1409     }
   1410 
   1411     mBatchBufDefs = (mm_camera_buf_def_t *)
   1412             malloc(mNumBatchBufs * sizeof(mm_camera_buf_def_t));
   1413     if (mBatchBufDefs == NULL) {
   1414         LOGE("mBatchBufDefs memory allocation failed");
   1415         rc = INVALID_OPERATION;
   1416         goto err4;
   1417     }
   1418     memset(mBatchBufDefs, 0, mNumBatchBufs * sizeof(mm_camera_buf_def_t));
   1419 
   1420     //Populate bufDef and queue to free batchBufQ
   1421     for (uint32_t i = 0; i < mNumBatchBufs; i++) {
   1422         getBatchBufDef(mBatchBufDefs[i], i);
   1423         if(mFreeBatchBufQ.enqueue((void*) &mBatchBufDefs[i])) {
   1424             LOGD("mBatchBufDefs[%d]: 0x%p", i, &mBatchBufDefs[i]);
   1425         } else {
   1426             LOGE("enqueue mBatchBufDefs[%d] failed", i);
   1427         }
   1428     }
   1429 
   1430     *num_bufs = mNumBatchBufs;
   1431     *initial_reg_flag = regFlags;
   1432     *bufs = mBatchBufDefs;
   1433     LOGH("stream type: %d, numBufs(batch): %d",
   1434              mStreamInfo->stream_type, mNumBatchBufs);
   1435 
   1436     return NO_ERROR;
   1437 err4:
   1438     free(regFlags);
   1439 err3:
   1440     for (size_t i = 0; i < mStreamBatchBufs->getCnt(); i++) {
   1441         ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_USER_BUF,
   1442                 ops_tbl->userdata);
   1443     }
   1444 err2:
   1445     mStreamBatchBufs->deallocate();
   1446 err1:
   1447     delete mStreamBatchBufs;
   1448     mStreamBatchBufs = NULL;
   1449     return rc;
   1450 }
   1451 
   1452 /*===========================================================================
   1453  * FUNCTION   : putBatchBufs
   1454  *
   1455  * DESCRIPTION: deallocate stream batch buffers
   1456  *
   1457  * PARAMETERS :
   1458  *   @ops_tbl    : ptr to buf mapping/unmapping ops
   1459  *
   1460  * RETURN     : int32_t type of status
   1461  *              NO_ERROR  -- success
   1462  *              none-zero failure code
   1463  *==========================================================================*/
   1464 int32_t QCamera3Stream::putBatchBufs(mm_camera_map_unmap_ops_tbl_t *ops_tbl)
   1465 {
   1466     int rc = NO_ERROR;
   1467     Mutex::Autolock lock(mLock);
   1468 
   1469     if (mStreamBatchBufs) {
   1470         for (uint32_t i = 0; i < mStreamBatchBufs->getCnt(); i++) {
   1471             rc = ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_USER_BUF,
   1472                     ops_tbl->userdata);
   1473             if (rc < 0) {
   1474                 LOGE("un-map batch buf failed: %d", rc);
   1475             }
   1476         }
   1477         mStreamBatchBufs->deallocate();
   1478         delete mStreamBatchBufs;
   1479         mStreamBatchBufs = NULL;
   1480     }
   1481     // mm-camera-interface frees bufDefs even though bufDefs are allocated by
   1482     // QCamera3Stream. Don't free here
   1483     mBatchBufDefs = NULL;
   1484 
   1485     return rc;
   1486 }
   1487 
   1488 /*===========================================================================
   1489  * FUNCTION   : getBatchBufDef
   1490  *
   1491  * DESCRIPTION: query detailed buffer information of batch buffer
   1492  *
   1493  * PARAMETERS :
   1494  *   @bufDef  : [output] reference to struct to store buffer definition
   1495  *   @@index  : [input] index of the buffer
   1496  *
   1497  * RETURN     : int32_t type of status
   1498  *              NO_ERROR  -- success
   1499  *              none-zero failure code
   1500  *==========================================================================*/
   1501 int32_t QCamera3Stream::getBatchBufDef(mm_camera_buf_def_t& batchBufDef,
   1502         int32_t index)
   1503 {
   1504     int rc = NO_ERROR;
   1505     memset(&batchBufDef, 0, sizeof(mm_camera_buf_def_t));
   1506     if (mStreamBatchBufs) {
   1507         //Single file descriptor for all batch buffers
   1508         batchBufDef.fd          = mStreamBatchBufs->getFd(0);
   1509         batchBufDef.buf_type    = CAM_STREAM_BUF_TYPE_USERPTR;
   1510         batchBufDef.frame_len   = mStreamInfo->user_buf_info.size;
   1511         batchBufDef.mem_info    = mStreamBatchBufs;
   1512         batchBufDef.buffer      = (uint8_t *)mStreamBatchBufs->getPtr(0) +
   1513                                     (index * mStreamInfo->user_buf_info.size);
   1514         batchBufDef.buf_idx     = index;
   1515         batchBufDef.user_buf.num_buffers = mBatchSize;
   1516         batchBufDef.user_buf.bufs_used = 0;
   1517         batchBufDef.user_buf.plane_buf = mBufDefs;
   1518     }
   1519 
   1520     return rc;
   1521 }
   1522 
   1523 /*===========================================================================
   1524  * FUNCTION   : aggregateBufToBatch
   1525  *
   1526  * DESCRIPTION: queue batch container to downstream.
   1527  *
   1528  * PARAMETERS :
   1529  *   @bufDef : image buffer to be aggregated into batch
   1530  *
   1531  * RETURN     : int32_t type of status
   1532  *              NO_ERROR  -- success always
   1533  *              none-zero failure code
   1534  *==========================================================================*/
   1535 int32_t QCamera3Stream::aggregateBufToBatch(mm_camera_buf_def_t& bufDef)
   1536 {
   1537     int32_t rc = NO_ERROR;
   1538 
   1539     if (UNLIKELY(!mBatchSize)) {
   1540         LOGE("Batch mod is not enabled");
   1541         return INVALID_OPERATION;
   1542     }
   1543     if (!mCurrentBatchBufDef) {
   1544         mCurrentBatchBufDef = (mm_camera_buf_def_t *)mFreeBatchBufQ.dequeue();
   1545         if (!mCurrentBatchBufDef) {
   1546             LOGE("No empty batch buffers is available");
   1547             return NO_MEMORY;
   1548         }
   1549         LOGD("batch buffer: %d dequeued from empty buffer list",
   1550                 mCurrentBatchBufDef->buf_idx);
   1551     }
   1552     if (mBufsStaged == mCurrentBatchBufDef->user_buf.num_buffers) {
   1553         LOGE("batch buffer is already full");
   1554         return NO_MEMORY;
   1555     }
   1556 
   1557     mCurrentBatchBufDef->user_buf.buf_idx[mBufsStaged] = bufDef.buf_idx;
   1558     mBufsStaged++;
   1559     LOGD("buffer id: %d aggregated into batch buffer id: %d",
   1560              bufDef.buf_idx, mCurrentBatchBufDef->buf_idx);
   1561     return rc;
   1562 }
   1563 
   1564 /*===========================================================================
   1565  * FUNCTION   : queueBatchBuf
   1566  *
   1567  * DESCRIPTION: queue batch container to downstream.
   1568  *
   1569  * PARAMETERS : None
   1570  *
   1571  * RETURN     : int32_t type of status
   1572  *              NO_ERROR  -- success always
   1573  *              none-zero failure code
   1574  *==========================================================================*/
   1575 int32_t QCamera3Stream::queueBatchBuf()
   1576 {
   1577     int32_t rc = NO_ERROR;
   1578 
   1579     if (!mCurrentBatchBufDef) {
   1580         LOGE("No buffers were queued into batch");
   1581         return INVALID_OPERATION;
   1582     }
   1583     //bufs_used: number of valid buffers in the batch buffers
   1584     mCurrentBatchBufDef->user_buf.bufs_used = mBufsStaged;
   1585 
   1586     //if mBufsStaged < num_buffers, initialize the buf_idx to -1 for rest of the
   1587     //buffers
   1588     for (size_t i = mBufsStaged; i < mCurrentBatchBufDef->user_buf.num_buffers;
   1589             i++) {
   1590         mCurrentBatchBufDef->user_buf.buf_idx[i] = -1;
   1591     }
   1592 
   1593     rc = mCamOps->qbuf(mCamHandle, mChannelHandle, mCurrentBatchBufDef);
   1594     if (rc < 0) {
   1595         LOGE("queueing of batch buffer: %d failed with err: %d",
   1596                 mCurrentBatchBufDef->buf_idx, rc);
   1597         return FAILED_TRANSACTION;
   1598     }
   1599     LOGD("Batch buf id: %d queued. bufs_used: %d",
   1600             mCurrentBatchBufDef->buf_idx,
   1601             mCurrentBatchBufDef->user_buf.bufs_used);
   1602 
   1603     mCurrentBatchBufDef = NULL;
   1604     mBufsStaged = 0;
   1605 
   1606     return rc;
   1607 }
   1608 
   1609 /*===========================================================================
   1610  * FUNCTION   : handleBatchBuffer
   1611  *
   1612  * DESCRIPTION: separate individual buffers from the batch and issue callback
   1613  *
   1614  * PARAMETERS :
   1615  *   @superBuf : Received superbuf containing batch buffer
   1616  *
   1617  * RETURN     : int32_t type of status
   1618  *              NO_ERROR  -- success always
   1619  *              none-zero failure code
   1620  *==========================================================================*/
   1621 int32_t QCamera3Stream::handleBatchBuffer(mm_camera_super_buf_t *superBuf)
   1622 {
   1623     int32_t rc = NO_ERROR;
   1624     mm_camera_super_buf_t *frame;
   1625     mm_camera_buf_def_t batchBuf;
   1626 
   1627     if (LIKELY(!mBatchSize)) {
   1628         LOGE("Stream: %d not in batch mode, but batch buffer received",
   1629                  getMyType());
   1630         return INVALID_OPERATION;
   1631     }
   1632     if (!mDataCB) {
   1633         LOGE("Data callback not set for batch mode");
   1634         return BAD_VALUE;
   1635     }
   1636     if (!superBuf->bufs[0]) {
   1637         LOGE("superBuf->bufs[0] is NULL!!");
   1638         return BAD_VALUE;
   1639     }
   1640 
   1641     /* Copy the batch buffer to local and queue the batch buffer to  empty queue
   1642      * to handle the new requests received while callbacks are in progress */
   1643     batchBuf = *superBuf->bufs[0];
   1644     if (!mFreeBatchBufQ.enqueue((void*) superBuf->bufs[0])) {
   1645         LOGE("batchBuf.buf_idx: %d enqueue failed",
   1646                 batchBuf.buf_idx);
   1647         free(superBuf);
   1648         return NO_MEMORY;
   1649     }
   1650     LOGD("Received batch buffer: %d bufs_used: %d",
   1651             batchBuf.buf_idx, batchBuf.user_buf.bufs_used);
   1652     //dummy local bufDef to issue multiple callbacks
   1653     mm_camera_buf_def_t buf;
   1654     memset(&buf, 0, sizeof(mm_camera_buf_def_t));
   1655 
   1656     for (size_t i = 0; i < batchBuf.user_buf.bufs_used; i++) {
   1657         int32_t buf_idx = batchBuf.user_buf.buf_idx[i];
   1658         buf = mBufDefs[buf_idx];
   1659 
   1660         /* this memory is freed inside dataCB. Should not be freed here */
   1661         frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
   1662         if (!frame) {
   1663             LOGE("malloc failed. Buffers will be dropped");
   1664             break;
   1665         } else {
   1666             memcpy(frame, superBuf, sizeof(mm_camera_super_buf_t));
   1667             frame->bufs[0] = &buf;
   1668 
   1669             mDataCB(frame, this, mUserData);
   1670         }
   1671     }
   1672     LOGD("batch buffer: %d callbacks done",
   1673             batchBuf.buf_idx);
   1674 
   1675     free(superBuf);
   1676     return rc;
   1677 }
   1678 
   1679 /*===========================================================================
   1680  * FUNCTION   : flushFreeBatchBufQ
   1681  *
   1682  * DESCRIPTION: dequeue all the entries of mFreeBatchBufQ and call flush.
   1683  *              QCameraQueue::flush calls 'free(node->data)' which should be
   1684  *              avoided for mFreeBatchBufQ as the entries are not allocated
   1685  *              during each enqueue
   1686  *
   1687  * PARAMETERS : None
   1688  *
   1689  * RETURN     : None
   1690  *==========================================================================*/
   1691 void QCamera3Stream::flushFreeBatchBufQ()
   1692 {
   1693     while (!mFreeBatchBufQ.isEmpty()) {
   1694         mFreeBatchBufQ.dequeue();
   1695     }
   1696     mFreeBatchBufQ.flush();
   1697 }
   1698 
   1699 }; // namespace qcamera
   1700