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