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