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