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  *==========================================================================*/
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)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  *==========================================================================*/
put_bufs(mm_camera_map_unmap_ops_tbl_t * ops_tbl,void * user_data)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  *==========================================================================*/
invalidate_buf(uint32_t index,void * user_data)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  *==========================================================================*/
clean_invalidate_buf(uint32_t index,void * user_data)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  *==========================================================================*/
QCamera3Stream(uint32_t camHandle,uint32_t chId,mm_camera_ops_t * camOps,cam_padding_info_t * paddingInfo,QCamera3Channel * channel)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  *==========================================================================*/
~QCamera3Stream()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  *==========================================================================*/
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)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  *==========================================================================*/
start()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  *==========================================================================*/
stop()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  *==========================================================================*/
processDataNotify(mm_camera_super_buf_t * frame)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  *==========================================================================*/
dataNotifyCB(mm_camera_super_buf_t * recvd_frame,void * userdata)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  *==========================================================================*/
dataProcRoutine(void * data)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  *==========================================================================*/
bufDone(uint32_t index)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  *==========================================================================*/
bufRelease(int32_t index)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  *==========================================================================*/
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)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  *==========================================================================*/
putBufs(mm_camera_map_unmap_ops_tbl_t * ops_tbl)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  *==========================================================================*/
invalidateBuf(uint32_t index)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  *==========================================================================*/
cleanInvalidateBuf(uint32_t index)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  *==========================================================================*/
getFrameOffset(cam_frame_len_offset_t & offset)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  *==========================================================================*/
getFrameDimension(cam_dimension_t & dim)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  *==========================================================================*/
getFormat(cam_format_t & fmt)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  *==========================================================================*/
getMyServerID()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  *==========================================================================*/
getMyType() const1029 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  *==========================================================================*/
mapBuf(uint8_t buf_type,uint32_t buf_idx,int32_t plane_idx,int fd,size_t size)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  *==========================================================================*/
unmapBuf(uint8_t buf_type,uint32_t buf_idx,int32_t plane_idx)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  *==========================================================================*/
setParameter(cam_stream_parm_buffer_t & param)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  *==========================================================================*/
releaseFrameData(void * data,void * user_data)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  *==========================================================================*/
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)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  *==========================================================================*/
putBatchBufs(mm_camera_map_unmap_ops_tbl_t * ops_tbl)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  *==========================================================================*/
getBatchBufDef(mm_camera_buf_def_t & batchBufDef,int32_t index)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  *==========================================================================*/
aggregateBufToBatch(mm_camera_buf_def_t & bufDef)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  *==========================================================================*/
queueBatchBuf()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  *==========================================================================*/
handleBatchBuffer(mm_camera_super_buf_t * superBuf)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  *==========================================================================*/
flushFreeBatchBufQ()1519 void QCamera3Stream::flushFreeBatchBufQ()
1520 {
1521     while (!mFreeBatchBufQ.isEmpty()) {
1522         mFreeBatchBufQ.dequeue();
1523     }
1524     mFreeBatchBufQ.flush();
1525 }
1526 
1527 }; // namespace qcamera
1528