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  *==========================================================================*/
get_bufs(cam_frame_len_offset_t * offset,uint8_t * num_bufs,uint8_t ** initial_reg_flag,mm_camera_buf_def_t ** bufs,mm_camera_map_unmap_ops_tbl_t * ops_tbl,void * user_data)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  *==========================================================================*/
put_bufs(mm_camera_map_unmap_ops_tbl_t * ops_tbl,void * user_data)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  *==========================================================================*/
invalidate_buf(uint32_t index,void * user_data)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  *==========================================================================*/
clean_invalidate_buf(uint32_t index,void * user_data)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  *==========================================================================*/
QCamera3Stream(uint32_t camHandle,uint32_t chId,mm_camera_ops_t * camOps,cam_padding_info_t * paddingInfo,QCamera3Channel * channel)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  *==========================================================================*/
~QCamera3Stream()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  *==========================================================================*/
init(cam_stream_type_t streamType,cam_format_t streamFormat,cam_dimension_t streamDim,cam_rotation_t streamRotation,cam_stream_reproc_config_t * reprocess_config,uint8_t minNumBuffers,uint32_t postprocess_mask,cam_is_type_t is_type,uint32_t batchSize,hal3_stream_cb_routine stream_cb,void * userdata)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  *==========================================================================*/
start()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  *==========================================================================*/
stop()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  *==========================================================================*/
processDataNotify(mm_camera_super_buf_t * frame)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  *==========================================================================*/
dataNotifyCB(mm_camera_super_buf_t * recvd_frame,void * userdata)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  *==========================================================================*/
dataProcRoutine(void * data)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  *==========================================================================*/
bufDone(uint32_t index)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  *==========================================================================*/
bufRelease(int32_t index)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  *==========================================================================*/
getBufs(cam_frame_len_offset_t * offset,uint8_t * num_bufs,uint8_t ** initial_reg_flag,mm_camera_buf_def_t ** bufs,mm_camera_map_unmap_ops_tbl_t * ops_tbl)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  *==========================================================================*/
putBufs(mm_camera_map_unmap_ops_tbl_t * ops_tbl)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  *==========================================================================*/
invalidateBuf(uint32_t index)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  *==========================================================================*/
cleanInvalidateBuf(uint32_t index)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  *==========================================================================*/
getFrameOffset(cam_frame_len_offset_t & offset)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  *==========================================================================*/
getFrameDimension(cam_dimension_t & dim)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  *==========================================================================*/
getFormat(cam_format_t & fmt)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  *==========================================================================*/
getMyServerID()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  *==========================================================================*/
getMyType() const984 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  *==========================================================================*/
mapBuf(uint8_t buf_type,uint32_t buf_idx,int32_t plane_idx,int fd,size_t size)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  *==========================================================================*/
unmapBuf(uint8_t buf_type,uint32_t buf_idx,int32_t plane_idx)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  *==========================================================================*/
setParameter(cam_stream_parm_buffer_t & param)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  *==========================================================================*/
releaseFrameData(void * data,void * user_data)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  *==========================================================================*/
getBatchBufs(uint8_t * num_bufs,uint8_t ** initial_reg_flag,mm_camera_buf_def_t ** bufs,mm_camera_map_unmap_ops_tbl_t * ops_tbl)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  *==========================================================================*/
putBatchBufs(mm_camera_map_unmap_ops_tbl_t * ops_tbl)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  *==========================================================================*/
getBatchBufDef(mm_camera_buf_def_t & batchBufDef,int32_t index)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  *==========================================================================*/
aggregateBufToBatch(mm_camera_buf_def_t & bufDef)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  *==========================================================================*/
queueBatchBuf()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  *==========================================================================*/
handleBatchBuffer(mm_camera_super_buf_t * superBuf)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  *==========================================================================*/
flushFreeBatchBufQ()1477 void QCamera3Stream::flushFreeBatchBufQ()
1478 {
1479     while (!mFreeBatchBufQ.isEmpty()) {
1480         mFreeBatchBufQ.dequeue();
1481     }
1482     mFreeBatchBufQ.flush();
1483 }
1484 
1485 }; // namespace qcamera
1486