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