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