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 #include "QCameraTrace.h"
36 
37 extern "C" {
38 #include "mm_camera_dbg.h"
39 }
40 
41 using namespace android;
42 
43 namespace qcamera {
44 #define MAX_BATCH_SIZE   32
45 
46 const char* QCamera3Stream::mStreamNames[] = {
47         "CAM_DEFAULT",
48         "CAM_PREVIEW",
49         "CAM_POSTVIEW",
50         "CAM_SNAPSHOT",
51         "CAM_VIDEO",
52         "CAM_CALLBACK",
53         "CAM_IMPL_DEFINED",
54         "CAM_METADATA",
55         "CAM_RAW",
56         "CAM_OFFLINE_PROC",
57         "CAM_PARM",
58         "CAM_ANALYSIS"
59         "CAM_MAX" };
60 
61 /*===========================================================================
62  * FUNCTION   : get_bufs
63  *
64  * DESCRIPTION: static function entry to allocate stream buffers
65  *
66  * PARAMETERS :
67  *   @offset     : offset info of stream buffers
68  *   @num_bufs   : number of buffers allocated
69  *   @initial_reg_flag: flag to indicate if buffer needs to be registered
70  *                      at kernel initially
71  *   @bufs       : output of allocated buffers
72  *   @ops_tbl    : ptr to buf mapping/unmapping ops
73  *   @user_data  : user data ptr of ops_tbl
74  *
75  * RETURN     : int32_t type of status
76  *              NO_ERROR  -- success
77  *              none-zero failure code
78  *==========================================================================*/
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)79 int32_t QCamera3Stream::get_bufs(
80                      cam_frame_len_offset_t *offset,
81                      uint8_t *num_bufs,
82                      uint8_t **initial_reg_flag,
83                      mm_camera_buf_def_t **bufs,
84                      mm_camera_map_unmap_ops_tbl_t *ops_tbl,
85                      void *user_data)
86 {
87     int32_t rc = NO_ERROR;
88     QCamera3Stream *stream = reinterpret_cast<QCamera3Stream *>(user_data);
89     if (!stream) {
90         LOGE("getBufs invalid stream pointer");
91         return NO_MEMORY;
92     }
93     rc = stream->getBufs(offset, num_bufs, initial_reg_flag, bufs, ops_tbl);
94     if (NO_ERROR != rc) {
95         LOGE("stream->getBufs failed");
96         return NO_MEMORY;
97     }
98     if (stream->mBatchSize) {
99         //Allocate batch buffers if mBatchSize is non-zero. All the output
100         //arguments correspond to batch containers and not image buffers
101         rc = stream->getBatchBufs(num_bufs, initial_reg_flag,
102                 bufs, ops_tbl);
103     }
104     return rc;
105 }
106 
107 /*===========================================================================
108  * FUNCTION   : put_bufs
109  *
110  * DESCRIPTION: static function entry to deallocate stream buffers
111  *
112  * PARAMETERS :
113  *   @ops_tbl    : ptr to buf mapping/unmapping ops
114  *   @user_data  : user data ptr of ops_tbl
115  *
116  * RETURN     : int32_t type of status
117  *              NO_ERROR  -- success
118  *              none-zero failure code
119  *==========================================================================*/
put_bufs(mm_camera_map_unmap_ops_tbl_t * ops_tbl,void * user_data)120 int32_t QCamera3Stream::put_bufs(
121                      mm_camera_map_unmap_ops_tbl_t *ops_tbl,
122                      void *user_data)
123 {
124     int32_t rc = NO_ERROR;
125     QCamera3Stream *stream = reinterpret_cast<QCamera3Stream *>(user_data);
126     if (!stream) {
127         LOGE("putBufs invalid stream pointer");
128         return NO_MEMORY;
129     }
130 
131     if (stream->mBatchSize) {
132         rc = stream->putBatchBufs(ops_tbl);
133         if (NO_ERROR != rc) {
134             LOGE("stream->putBatchBufs failed");
135         }
136     }
137     rc = stream->putBufs(ops_tbl);
138     return rc;
139 }
140 
141 /*===========================================================================
142  * FUNCTION   : invalidate_buf
143  *
144  * DESCRIPTION: static function entry to invalidate a specific stream buffer
145  *
146  * PARAMETERS :
147  *   @index      : index of the stream buffer to invalidate
148  *   @user_data  : user data ptr of ops_tbl
149  *
150  * RETURN     : int32_t type of status
151  *              NO_ERROR  -- success
152  *              none-zero failure code
153  *==========================================================================*/
invalidate_buf(uint32_t index,void * user_data)154 int32_t QCamera3Stream::invalidate_buf(uint32_t index, void *user_data)
155 {
156     int32_t rc = NO_ERROR;
157 
158     QCamera3Stream *stream = reinterpret_cast<QCamera3Stream *>(user_data);
159     if (!stream) {
160         LOGE("invalid stream pointer");
161         return NO_MEMORY;
162     }
163     if (stream->mBatchSize) {
164         int32_t retVal = NO_ERROR;
165         for (size_t i = 0;
166                 i < stream->mBatchBufDefs[index].user_buf.bufs_used; i++) {
167             uint32_t buf_idx = stream->mBatchBufDefs[index].user_buf.buf_idx[i];
168             retVal = stream->invalidateBuf(buf_idx);
169             if (NO_ERROR != retVal) {
170                 LOGE("invalidateBuf failed for buf_idx: %d err: %d",
171                          buf_idx, retVal);
172             }
173             rc |= retVal;
174         }
175     } else {
176         rc = stream->invalidateBuf(index);
177     }
178     return rc;
179 }
180 
181 /*===========================================================================
182  * FUNCTION   : clean_invalidate_buf
183  *
184  * DESCRIPTION: static function entry to clean and invalidate a specific stream buffer
185  *
186  * PARAMETERS :
187  *   @index      : index of the stream buffer to invalidate
188  *   @user_data  : user data ptr of ops_tbl
189  *
190  * RETURN     : int32_t type of status
191  *              NO_ERROR  -- success
192  *              none-zero failure code
193  *==========================================================================*/
clean_invalidate_buf(uint32_t index,void * user_data)194 int32_t QCamera3Stream::clean_invalidate_buf(uint32_t index, void *user_data)
195 {
196     int32_t rc = NO_ERROR;
197 
198     QCamera3Stream *stream = reinterpret_cast<QCamera3Stream *>(user_data);
199     if (!stream) {
200         LOGE("invalid stream pointer");
201         return NO_MEMORY;
202     }
203     if (stream->mBatchSize) {
204         int32_t retVal = NO_ERROR;
205         for (size_t i = 0;
206                 i < stream->mBatchBufDefs[index].user_buf.bufs_used; i++) {
207             uint32_t buf_idx = stream->mBatchBufDefs[index].user_buf.buf_idx[i];
208             retVal = stream->cleanInvalidateBuf(buf_idx);
209             if (NO_ERROR != retVal) {
210                 LOGE("invalidateBuf failed for buf_idx: %d err: %d",
211                          buf_idx, retVal);
212             }
213             rc |= retVal;
214         }
215     } else {
216         rc = stream->cleanInvalidateBuf(index);
217     }
218     return rc;
219 }
220 
221 /*===========================================================================
222  * FUNCTION   : QCamera3Stream
223  *
224  * DESCRIPTION: constructor of QCamera3Stream
225  *
226  * PARAMETERS :
227  *   @allocator  : memory allocator obj
228  *   @camHandle  : camera handle
229  *   @chId       : channel handle
230  *   @camOps     : ptr to camera ops table
231  *   @paddingInfo: ptr to padding info
232  *
233  * RETURN     : None
234  *==========================================================================*/
QCamera3Stream(uint32_t camHandle,uint32_t chId,mm_camera_ops_t * camOps,cam_padding_info_t * paddingInfo,QCamera3Channel * channel)235 QCamera3Stream::QCamera3Stream(uint32_t camHandle,
236                              uint32_t chId,
237                              mm_camera_ops_t *camOps,
238                              cam_padding_info_t *paddingInfo,
239                              QCamera3Channel *channel) :
240         mCamHandle(camHandle),
241         mChannelHandle(chId),
242         mHandle(0),
243         mCamOps(camOps),
244         mStreamInfo(NULL),
245         mMemOps(NULL),
246         mNumBufs(0),
247         mDataCB(NULL),
248         mUserData(NULL),
249         mDataQ(releaseFrameData, 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.clear();
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     {
512         Mutex::Autolock lock(mTimeoutFrameQLock);
513         mTimeoutFrameQ.push_back(bufIdx);
514     }
515     rc = mProcTh.sendCmd(CAMERA_CMD_TYPE_TIMEOUT, FALSE, FALSE);
516     LOGD("X\n");
517     return rc;
518 }
519 
520 /*===========================================================================
521  * FUNCTION   : processDataNotify
522  *
523  * DESCRIPTION: process stream data notify
524  *
525  * PARAMETERS :
526  *   @frame   : stream frame received
527  *
528  * RETURN     : int32_t type of status
529  *              NO_ERROR  -- success
530  *              none-zero failure code
531  *==========================================================================*/
processDataNotify(mm_camera_super_buf_t * frame)532 int32_t QCamera3Stream::processDataNotify(mm_camera_super_buf_t *frame)
533 {
534     LOGD("E\n");
535     int32_t rc;
536     if (mDataQ.enqueue((void *)frame)) {
537         rc = mProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
538     } else {
539         LOGD("Stream thread is not active, no ops here");
540         bufDone(frame->bufs[0]->buf_idx);
541         free(frame);
542         rc = NO_ERROR;
543     }
544     LOGD("X\n");
545     return rc;
546 }
547 
548 /*===========================================================================
549  * FUNCTION   : dataNotifyCB
550  *
551  * DESCRIPTION: callback for data notify. This function is registered with
552  *              mm-camera-interface to handle data notify
553  *
554  * PARAMETERS :
555  *   @recvd_frame   : stream frame received
556  *   userdata       : user data ptr
557  *
558  * RETURN     : none
559  *==========================================================================*/
dataNotifyCB(mm_camera_super_buf_t * recvd_frame,void * userdata)560 void QCamera3Stream::dataNotifyCB(mm_camera_super_buf_t *recvd_frame,
561                                  void *userdata)
562 {
563     LOGD("E\n");
564     QCamera3Stream* stream = (QCamera3Stream *)userdata;
565     if (stream == NULL ||
566         recvd_frame == NULL ||
567         recvd_frame->bufs[0] == NULL ||
568         recvd_frame->bufs[0]->stream_id != stream->getMyHandle()) {
569         LOGE("Not a valid stream to handle buf");
570         return;
571     }
572 
573     mm_camera_super_buf_t *frame =
574         (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
575     if (frame == NULL) {
576         LOGE("No mem for mm_camera_buf_def_t");
577         stream->bufDone(recvd_frame->bufs[0]->buf_idx);
578         return;
579     }
580     *frame = *recvd_frame;
581     stream->processDataNotify(frame);
582     return;
583 }
584 
585 /*===========================================================================
586  * FUNCTION   : dataProcRoutine
587  *
588  * DESCRIPTION: function to process data in the main stream thread
589  *
590  * PARAMETERS :
591  *   @data    : user data ptr
592  *
593  * RETURN     : none
594  *==========================================================================*/
dataProcRoutine(void * data)595 void *QCamera3Stream::dataProcRoutine(void *data)
596 {
597     int running = 1;
598     int ret;
599     QCamera3Stream *pme = (QCamera3Stream *)data;
600     QCameraCmdThread *cmdThread = &pme->mProcTh;
601 
602     cmdThread->setName(mStreamNames[pme->mStreamInfo->stream_type]);
603 
604     LOGD("E");
605     do {
606         do {
607             ret = cam_sem_wait(&cmdThread->cmd_sem);
608             if (ret != 0 && errno != EINVAL) {
609                 LOGE("cam_sem_wait error (%s)",
610                        strerror(errno));
611                 return NULL;
612             }
613         } while (ret != 0);
614 
615         // we got notified about new cmd avail in cmd queue
616         camera_cmd_type_t cmd = cmdThread->getCmd();
617         switch (cmd) {
618         case CAMERA_CMD_TYPE_TIMEOUT:
619             {
620                 int32_t bufIdx;
621                 {
622                     Mutex::Autolock lock(pme->mTimeoutFrameQLock);
623                     if (pme->mTimeoutFrameQ.size()) {
624                         auto itr = pme->mTimeoutFrameQ.begin();
625                         bufIdx = *itr;
626                         itr = pme->mTimeoutFrameQ.erase(itr);
627                     } else {
628                         LOGE("Timeout command received but Q is empty");
629                         break;
630                     }
631                 }
632                 pme->cancelBuffer(bufIdx);
633                 break;
634             }
635         case CAMERA_CMD_TYPE_DO_NEXT_JOB:
636             {
637                 LOGD("Do next job");
638                 mm_camera_super_buf_t *frame =
639                     (mm_camera_super_buf_t *)pme->mDataQ.dequeue();
640                 if (NULL != frame) {
641                     if (UNLIKELY(frame->bufs[0]->buf_type ==
642                             CAM_STREAM_BUF_TYPE_USERPTR)) {
643                         pme->handleBatchBuffer(frame);
644                     } else if (pme->mDataCB != NULL) {
645                         pme->mDataCB(frame, pme, pme->mUserData);
646                     } else {
647                         // no data cb routine, return buf here
648                         pme->bufDone(frame->bufs[0]->buf_idx);
649                     }
650                 }
651             }
652             break;
653         case CAMERA_CMD_TYPE_EXIT:
654             LOGH("Exit");
655             /* flush data buf queue */
656             pme->mDataQ.flush();
657             pme->mTimeoutFrameQ.clear();
658             pme->flushFreeBatchBufQ();
659             running = 0;
660             break;
661         default:
662             break;
663         }
664     } while (running);
665     LOGD("X");
666     return NULL;
667 }
668 
669 /*===========================================================================
670  * FUNCTION   : bufDone
671  *
672  * DESCRIPTION: return stream buffer to kernel
673  *
674  * PARAMETERS :
675  *   @index   : index of buffer to be returned
676  *
677  * RETURN     : int32_t type of status
678  *              NO_ERROR  -- success
679  *              none-zero failure code
680  *==========================================================================*/
bufDone(uint32_t index)681 int32_t QCamera3Stream::bufDone(uint32_t index)
682 {
683     int32_t rc = NO_ERROR;
684     Mutex::Autolock lock(mLock);
685 
686     if ((index >= mNumBufs) || (mBufDefs == NULL)) {
687         LOGE("index; %d, mNumBufs: %d", index, mNumBufs);
688         return BAD_INDEX;
689     }
690     if (mStreamBufs == NULL)
691     {
692         LOGE("putBufs already called");
693         return INVALID_OPERATION;
694     }
695 
696     if( NULL == mBufDefs[index].mem_info) {
697         if (NULL == mMemOps) {
698             LOGE("Camera operations not initialized");
699             return NO_INIT;
700         }
701 
702         ssize_t bufSize = mStreamBufs->getSize(index);
703 
704         if (BAD_INDEX != bufSize) {
705             LOGD("Map streamBufIdx: %d", index);
706             rc = mMemOps->map_ops(index, -1, mStreamBufs->getFd(index),
707                     (size_t)bufSize, mStreamBufs->getPtr(index),
708                     CAM_MAPPING_BUF_TYPE_STREAM_BUF, mMemOps->userdata);
709             if (rc < 0) {
710                 LOGE("Failed to map camera buffer %d", index);
711                 return rc;
712             }
713 
714             rc = mStreamBufs->getBufDef(mFrameLenOffset, mBufDefs[index], index);
715             if (NO_ERROR != rc) {
716                 LOGE("Couldn't find camera buffer definition");
717                 mMemOps->unmap_ops(index, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF, mMemOps->userdata);
718                 return rc;
719             }
720         } else {
721             LOGE("Failed to retrieve buffer size (bad index)");
722             return INVALID_OPERATION;
723         }
724     }
725 
726     if (UNLIKELY(mBatchSize)) {
727         rc = aggregateBufToBatch(mBufDefs[index]);
728     } else {
729         rc = mCamOps->qbuf(mCamHandle, mChannelHandle, &mBufDefs[index]);
730         if (rc < 0) {
731             return FAILED_TRANSACTION;
732         }
733     }
734 
735     return rc;
736 }
737 
738 /*===========================================================================
739  * FUNCTION   : cancelBuffer
740  *
741  * DESCRIPTION: Issue cancel buffer request to kernel
742  *
743  * PARAMETERS :
744  *   @index   : index of buffer to be cancelled
745  *
746  * RETURN     : int32_t type of status
747  *              NO_ERROR  -- success
748  *              none-zero failure code
749  *==========================================================================*/
cancelBuffer(uint32_t index)750 int32_t QCamera3Stream::cancelBuffer(uint32_t index)
751 {
752     int32_t rc = NO_ERROR;
753     Mutex::Autolock lock(mLock);
754 
755     if ((index >= mNumBufs) || (mBufDefs == NULL)) {
756         LOGE("index; %d, mNumBufs: %d", index, mNumBufs);
757         return BAD_INDEX;
758     }
759     if (mStreamBufs == NULL)
760     {
761         LOGE("putBufs already called");
762         return INVALID_OPERATION;
763     }
764 
765     /* if (UNLIKELY(mBatchSize)) {
766         FIXME
767     } else */{
768         ALOGE("Calling cancel buf on idx:%d for stream type:%d",index, getMyType());
769         rc = mCamOps->cancel_buffer(mCamHandle, mChannelHandle, mHandle, index);
770         if (rc < 0) {
771             return FAILED_TRANSACTION;
772         }
773     }
774 
775     return rc;
776 }
777 
778 /*===========================================================================
779  * FUNCTION   : bufRelease
780  *
781  * DESCRIPTION: release all resources associated with this buffer
782  *
783  * PARAMETERS :
784  *   @index   : index of buffer to be released
785  *
786  * RETURN     : int32_t type of status
787  *              NO_ERROR  -- success
788  *              none-zero failure code
789  *==========================================================================*/
bufRelease(int32_t index)790 int32_t QCamera3Stream::bufRelease(int32_t index)
791 {
792     int32_t rc = NO_ERROR;
793     Mutex::Autolock lock(mLock);
794 
795     if ((index >= mNumBufs) || (mBufDefs == NULL)) {
796         return BAD_INDEX;
797     }
798 
799     if (NULL != mBufDefs[index].mem_info) {
800         if (NULL == mMemOps) {
801             LOGE("Camera operations not initialized");
802             return NO_INIT;
803         }
804 
805         rc = mMemOps->unmap_ops(index, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF,
806                 mMemOps->userdata);
807         if (rc < 0) {
808             LOGE("Failed to un-map camera buffer %d", index);
809             return rc;
810         }
811 
812         mBufDefs[index].mem_info = NULL;
813     } else {
814         LOGE("Buffer at index %d not registered", index);
815         return BAD_INDEX;
816     }
817 
818     return rc;
819 }
820 
821 /*===========================================================================
822  * FUNCTION   : getBufs
823  *
824  * DESCRIPTION: allocate stream buffers
825  *
826  * PARAMETERS :
827  *   @offset     : offset info of stream buffers
828  *   @num_bufs   : number of buffers allocated
829  *   @initial_reg_flag: flag to indicate if buffer needs to be registered
830  *                      at kernel initially
831  *   @bufs       : output of allocated buffers
832  *   @ops_tbl    : ptr to buf mapping/unmapping ops
833  *
834  * RETURN     : int32_t type of status
835  *              NO_ERROR  -- success
836  *              none-zero failure code
837  *==========================================================================*/
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)838 int32_t QCamera3Stream::getBufs(cam_frame_len_offset_t *offset,
839                      uint8_t *num_bufs,
840                      uint8_t **initial_reg_flag,
841                      mm_camera_buf_def_t **bufs,
842                      mm_camera_map_unmap_ops_tbl_t *ops_tbl)
843 {
844     int rc = NO_ERROR;
845     uint8_t *regFlags;
846     Mutex::Autolock lock(mLock);
847 
848     if (!ops_tbl) {
849         LOGE("ops_tbl is NULL");
850         return INVALID_OPERATION;
851     }
852 
853     mFrameLenOffset = *offset;
854     mMemOps = ops_tbl;
855 
856     if (mStreamBufs != NULL) {
857        LOGE("Failed getBufs being called twice in a row without a putBufs call");
858        return INVALID_OPERATION;
859     }
860     mStreamBufs = mChannel->getStreamBufs(mFrameLenOffset.frame_len);
861     if (!mStreamBufs) {
862         LOGE("Failed to allocate stream buffers");
863         return NO_MEMORY;
864     }
865 
866     for (uint32_t i = 0; i < mNumBufs; i++) {
867         if (mStreamBufs->valid(i)) {
868             ssize_t bufSize = mStreamBufs->getSize(i);
869             if (BAD_INDEX != bufSize) {
870                 rc = ops_tbl->map_ops(i, -1, mStreamBufs->getFd(i),
871                         (size_t)bufSize, mStreamBufs->getPtr(i),
872                         CAM_MAPPING_BUF_TYPE_STREAM_BUF,
873                         ops_tbl->userdata);
874                 if (rc < 0) {
875                     LOGE("map_stream_buf failed: %d", rc);
876                     for (uint32_t j = 0; j < i; j++) {
877                         if (mStreamBufs->valid(j)) {
878                             ops_tbl->unmap_ops(j, -1,
879                                     CAM_MAPPING_BUF_TYPE_STREAM_BUF,
880                                     ops_tbl->userdata);
881                         }
882                     }
883                     return INVALID_OPERATION;
884                 }
885             } else {
886                 LOGE("Failed to retrieve buffer size (bad index)");
887                 return INVALID_OPERATION;
888             }
889         }
890     }
891 
892     //regFlags array is allocated by us, but consumed and freed by mm-camera-interface
893     regFlags = (uint8_t *)malloc(sizeof(uint8_t) * mNumBufs);
894     if (!regFlags) {
895         LOGE("Out of memory");
896         for (uint32_t i = 0; i < mNumBufs; i++) {
897             if (mStreamBufs->valid(i)) {
898                 ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF,
899                         ops_tbl->userdata);
900             }
901         }
902         return NO_MEMORY;
903     }
904     memset(regFlags, 0, sizeof(uint8_t) * mNumBufs);
905 
906     mBufDefs = (mm_camera_buf_def_t *)malloc(mNumBufs * sizeof(mm_camera_buf_def_t));
907     if (mBufDefs == NULL) {
908         LOGE("Failed to allocate mm_camera_buf_def_t %d", rc);
909         for (uint32_t i = 0; i < mNumBufs; i++) {
910             if (mStreamBufs->valid(i)) {
911                 ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF,
912                         ops_tbl->userdata);
913             }
914         }
915         free(regFlags);
916         regFlags = NULL;
917         return INVALID_OPERATION;
918     }
919     memset(mBufDefs, 0, mNumBufs * sizeof(mm_camera_buf_def_t));
920     for (uint32_t i = 0; i < mNumBufs; i++) {
921         if (mStreamBufs->valid(i)) {
922             mStreamBufs->getBufDef(mFrameLenOffset, mBufDefs[i], i);
923         }
924     }
925 
926     rc = mStreamBufs->getRegFlags(regFlags);
927     if (rc < 0) {
928         LOGE("getRegFlags failed %d", rc);
929         for (uint32_t i = 0; i < mNumBufs; i++) {
930             if (mStreamBufs->valid(i)) {
931                 ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF,
932                         ops_tbl->userdata);
933             }
934         }
935         free(mBufDefs);
936         mBufDefs = NULL;
937         free(regFlags);
938         regFlags = NULL;
939         return INVALID_OPERATION;
940     }
941 
942     *num_bufs = mNumBufs;
943     *initial_reg_flag = regFlags;
944     *bufs = mBufDefs;
945     return NO_ERROR;
946 }
947 
948 /*===========================================================================
949  * FUNCTION   : putBufs
950  *
951  * DESCRIPTION: deallocate stream buffers
952  *
953  * PARAMETERS :
954  *   @ops_tbl    : ptr to buf mapping/unmapping ops
955  *
956  * RETURN     : int32_t type of status
957  *              NO_ERROR  -- success
958  *              none-zero failure code
959  *==========================================================================*/
putBufs(mm_camera_map_unmap_ops_tbl_t * ops_tbl)960 int32_t QCamera3Stream::putBufs(mm_camera_map_unmap_ops_tbl_t *ops_tbl)
961 {
962     int rc = NO_ERROR;
963     Mutex::Autolock lock(mLock);
964 
965     for (uint32_t i = 0; i < mNumBufs; i++) {
966         if (mStreamBufs->valid(i) && NULL != mBufDefs[i].mem_info) {
967             rc = ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF, ops_tbl->userdata);
968             if (rc < 0) {
969                 LOGE("un-map stream buf failed: %d", rc);
970             }
971         }
972     }
973     mBufDefs = NULL; // mBufDefs just keep a ptr to the buffer
974                      // mm-camera-interface own the buffer, so no need to free
975     memset(&mFrameLenOffset, 0, sizeof(mFrameLenOffset));
976 
977     if (mStreamBufs == NULL) {
978         LOGE("getBuf failed previously, or calling putBufs twice");
979     }
980 
981     mChannel->putStreamBufs();
982 
983     //need to set mStreamBufs to null because putStreamBufs deletes that memory
984     mStreamBufs = NULL;
985 
986     return rc;
987 }
988 
989 /*===========================================================================
990  * FUNCTION   : invalidateBuf
991  *
992  * DESCRIPTION: invalidate a specific stream buffer
993  *
994  * PARAMETERS :
995  *   @index   : index of the buffer to invalidate
996  *
997  * RETURN     : int32_t type of status
998  *              NO_ERROR  -- success
999  *              none-zero failure code
1000  *==========================================================================*/
invalidateBuf(uint32_t index)1001 int32_t QCamera3Stream::invalidateBuf(uint32_t index)
1002 {
1003     if (mStreamBufs == NULL) {
1004        LOGE("putBufs already called");
1005        return INVALID_OPERATION;
1006     } else
1007        return mStreamBufs->invalidateCache(index);
1008 }
1009 
1010 /*===========================================================================
1011  * FUNCTION   : cleanInvalidateBuf
1012  *
1013  * DESCRIPTION: clean and invalidate a specific stream buffer
1014  *
1015  * PARAMETERS :
1016  *   @index   : index of the buffer to invalidate
1017  *
1018  * RETURN     : int32_t type of status
1019  *              NO_ERROR  -- success
1020  *              none-zero failure code
1021  *==========================================================================*/
cleanInvalidateBuf(uint32_t index)1022 int32_t QCamera3Stream::cleanInvalidateBuf(uint32_t index)
1023 {
1024     if (mStreamBufs == NULL) {
1025         LOGE("putBufs already called");
1026         return INVALID_OPERATION;
1027     } else
1028         return mStreamBufs->cleanInvalidateCache(index);
1029 }
1030 
1031 /*===========================================================================
1032  * FUNCTION   : getFrameOffset
1033  *
1034  * DESCRIPTION: query stream buffer frame offset info
1035  *
1036  * PARAMETERS :
1037  *   @offset  : reference to struct to store the queried frame offset info
1038  *
1039  * RETURN     : int32_t type of status
1040  *              NO_ERROR  -- success
1041  *              none-zero failure code
1042  *==========================================================================*/
getFrameOffset(cam_frame_len_offset_t & offset)1043 int32_t QCamera3Stream::getFrameOffset(cam_frame_len_offset_t &offset)
1044 {
1045     offset = mFrameLenOffset;
1046     return 0;
1047 }
1048 
1049 /*===========================================================================
1050  * FUNCTION   : getFrameDimension
1051  *
1052  * DESCRIPTION: query stream frame dimension info
1053  *
1054  * PARAMETERS :
1055  *   @dim     : reference to struct to store the queried frame dimension
1056  *
1057  * RETURN     : int32_t type of status
1058  *              NO_ERROR  -- success
1059  *              none-zero failure code
1060  *==========================================================================*/
getFrameDimension(cam_dimension_t & dim)1061 int32_t QCamera3Stream::getFrameDimension(cam_dimension_t &dim)
1062 {
1063     if (mStreamInfo != NULL) {
1064         dim = mStreamInfo->dim;
1065         return 0;
1066     }
1067     return -1;
1068 }
1069 
1070 /*===========================================================================
1071  * FUNCTION   : getFormat
1072  *
1073  * DESCRIPTION: query stream format
1074  *
1075  * PARAMETERS :
1076  *   @fmt     : reference to stream format
1077  *
1078  * RETURN     : int32_t type of status
1079  *              NO_ERROR  -- success
1080  *              none-zero failure code
1081  *==========================================================================*/
getFormat(cam_format_t & fmt)1082 int32_t QCamera3Stream::getFormat(cam_format_t &fmt)
1083 {
1084     if (mStreamInfo != NULL) {
1085         fmt = mStreamInfo->fmt;
1086         return 0;
1087     }
1088     return -1;
1089 }
1090 
1091 /*===========================================================================
1092  * FUNCTION   : getMyServerID
1093  *
1094  * DESCRIPTION: query server stream ID
1095  *
1096  * PARAMETERS : None
1097  *
1098  * RETURN     : stream ID from server
1099  *==========================================================================*/
getMyServerID()1100 uint32_t QCamera3Stream::getMyServerID() {
1101     if (mStreamInfo != NULL) {
1102         return mStreamInfo->stream_svr_id;
1103     } else {
1104         return 0;
1105     }
1106 }
1107 
1108 /*===========================================================================
1109  * FUNCTION   : getMyType
1110  *
1111  * DESCRIPTION: query stream type
1112  *
1113  * PARAMETERS : None
1114  *
1115  * RETURN     : type of stream
1116  *==========================================================================*/
getMyType() const1117 cam_stream_type_t QCamera3Stream::getMyType() const
1118 {
1119     if (mStreamInfo != NULL) {
1120         return mStreamInfo->stream_type;
1121     } else {
1122         return CAM_STREAM_TYPE_MAX;
1123     }
1124 }
1125 
1126 /*===========================================================================
1127  * FUNCTION   : mapBuf
1128  *
1129  * DESCRIPTION: map stream related buffer to backend server
1130  *
1131  * PARAMETERS :
1132  *   @buf_type : mapping type of buffer
1133  *   @buf_idx  : index of buffer
1134  *   @plane_idx: plane index
1135  *   @fd       : fd of the buffer
1136  *   @buffer : buffer ptr
1137  *   @size     : lenght of the buffer
1138  *
1139  * RETURN     : int32_t type of status
1140  *              NO_ERROR  -- success
1141  *              none-zero failure code
1142  *==========================================================================*/
mapBuf(uint8_t buf_type,uint32_t buf_idx,int32_t plane_idx,int fd,void * buffer,size_t size)1143 int32_t QCamera3Stream::mapBuf(uint8_t buf_type, uint32_t buf_idx,
1144         int32_t plane_idx, int fd, void *buffer, size_t size)
1145 {
1146     ATRACE_CALL();
1147     return mCamOps->map_stream_buf(mCamHandle, mChannelHandle,
1148                                    mHandle, buf_type,
1149                                    buf_idx, plane_idx,
1150                                    fd, size, buffer);
1151 
1152 }
1153 
1154 /*===========================================================================
1155  * FUNCTION   : unmapBuf
1156  *
1157  * DESCRIPTION: unmap stream related buffer to backend server
1158  *
1159  * PARAMETERS :
1160  *   @buf_type : mapping type of buffer
1161  *   @buf_idx  : index of buffer
1162  *   @plane_idx: plane index
1163  *
1164  * RETURN     : int32_t type of status
1165  *              NO_ERROR  -- success
1166  *              none-zero failure code
1167  *==========================================================================*/
unmapBuf(uint8_t buf_type,uint32_t buf_idx,int32_t plane_idx)1168 int32_t QCamera3Stream::unmapBuf(uint8_t buf_type, uint32_t buf_idx, int32_t plane_idx)
1169 {
1170     ATRACE_CALL();
1171     return mCamOps->unmap_stream_buf(mCamHandle, mChannelHandle,
1172                                      mHandle, buf_type,
1173                                      buf_idx, plane_idx);
1174 }
1175 
1176 /*===========================================================================
1177  * FUNCTION   : setParameter
1178  *
1179  * DESCRIPTION: set stream based parameters
1180  *
1181  * PARAMETERS :
1182  *   @param   : ptr to parameters to be set
1183  *
1184  * RETURN     : int32_t type of status
1185  *              NO_ERROR  -- success
1186  *              none-zero failure code
1187  *==========================================================================*/
setParameter(cam_stream_parm_buffer_t & param)1188 int32_t QCamera3Stream::setParameter(cam_stream_parm_buffer_t &param)
1189 {
1190     int32_t rc = NO_ERROR;
1191     mStreamInfo->parm_buf = param;
1192     ATRACE_CALL();
1193     rc = mCamOps->set_stream_parms(mCamHandle,
1194                                    mChannelHandle,
1195                                    mHandle,
1196                                    &mStreamInfo->parm_buf);
1197     if (rc == NO_ERROR) {
1198         param = mStreamInfo->parm_buf;
1199     }
1200     return rc;
1201 }
1202 
1203 /*===========================================================================
1204  * FUNCTION   : releaseFrameData
1205  *
1206  * DESCRIPTION: callback function to release frame data node
1207  *
1208  * PARAMETERS :
1209  *   @data      : ptr to post process input data
1210  *   @user_data : user data ptr (QCameraReprocessor)
1211  *
1212  * RETURN     : None
1213  *==========================================================================*/
releaseFrameData(void * data,void * user_data)1214 void QCamera3Stream::releaseFrameData(void *data, void *user_data)
1215 {
1216     QCamera3Stream *pme = (QCamera3Stream *)user_data;
1217     mm_camera_super_buf_t *frame = (mm_camera_super_buf_t *)data;
1218     if (NULL != pme) {
1219         if (UNLIKELY(pme->mBatchSize)) {
1220             /* For batch mode, the batch buffer is added to empty list */
1221             if(!pme->mFreeBatchBufQ.enqueue((void*) frame->bufs[0])) {
1222                 LOGE("batchBuf.buf_idx: %d enqueue failed",
1223                         frame->bufs[0]->buf_idx);
1224             }
1225         } else {
1226             pme->bufDone(frame->bufs[0]->buf_idx);
1227         }
1228     }
1229 }
1230 
1231 /*===========================================================================
1232  * FUNCTION   : getBatchBufs
1233  *
1234  * DESCRIPTION: allocate batch containers for the stream
1235  *
1236  * PARAMETERS :
1237  *   @num_bufs   : number of buffers allocated
1238  *   @initial_reg_flag: flag to indicate if buffer needs to be registered
1239  *                      at kernel initially
1240  *   @bufs       : output of allocated buffers
1241   *  @ops_tbl    : ptr to buf mapping/unmapping ops
1242  *
1243  * RETURN     : int32_t type of status
1244  *              NO_ERROR  -- success
1245  *              none-zero failure code
1246  *==========================================================================*/
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)1247 int32_t QCamera3Stream::getBatchBufs(
1248         uint8_t *num_bufs, uint8_t **initial_reg_flag,
1249         mm_camera_buf_def_t **bufs,
1250         mm_camera_map_unmap_ops_tbl_t *ops_tbl)
1251 {
1252     int rc = NO_ERROR;
1253     uint8_t *regFlags;
1254 
1255     if (!ops_tbl || !num_bufs || !initial_reg_flag || !bufs) {
1256         LOGE("input args NULL");
1257         return INVALID_OPERATION;
1258     }
1259     LOGH("Batch container allocation stream type = %d",
1260              getMyType());
1261 
1262     Mutex::Autolock lock(mLock);
1263 
1264     mMemOps = ops_tbl;
1265 
1266     //Allocate batch containers
1267     mStreamBatchBufs = new QCamera3HeapMemory(1);
1268     if (!mStreamBatchBufs) {
1269         LOGE("unable to create batch container memory");
1270         return NO_MEMORY;
1271     }
1272     // Allocating single buffer file-descriptor for all batch containers,
1273     // mStreamBatchBufs considers all the container bufs as a single buffer. But
1274     // QCamera3Stream manages that single buffer as multiple batch buffers
1275     LOGD("Allocating batch container memory. numBatch: %d size: %d",
1276              mNumBatchBufs, mStreamInfo->user_buf_info.size);
1277     rc = mStreamBatchBufs->allocate(
1278             mNumBatchBufs * mStreamInfo->user_buf_info.size);
1279     if (rc < 0) {
1280         LOGE("unable to allocate batch container memory");
1281         rc = NO_MEMORY;
1282         goto err1;
1283     }
1284 
1285     /* map batch buffers. getCnt here returns 1 because of single FD across
1286      * batch bufs */
1287     for (uint32_t i = 0; i < mStreamBatchBufs->getCnt(); i++) {
1288         if (mNumBatchBufs) {
1289             //For USER_BUF, size = number_of_container bufs instead of the total
1290             //buf size
1291             rc = ops_tbl->map_ops(i, -1, mStreamBatchBufs->getFd(i),
1292                     (size_t)mNumBatchBufs, mStreamBatchBufs->getPtr(i),
1293                     CAM_MAPPING_BUF_TYPE_STREAM_USER_BUF,
1294                     ops_tbl->userdata);
1295             if (rc < 0) {
1296                 LOGE("Failed to map stream container buffer: %d",
1297                          rc);
1298                 //Unmap all the buffers that were successfully mapped before
1299                 //this buffer mapping failed
1300                 for (size_t j = 0; j < i; j++) {
1301                     ops_tbl->unmap_ops(j, -1,
1302                             CAM_MAPPING_BUF_TYPE_STREAM_USER_BUF,
1303                             ops_tbl->userdata);
1304                 }
1305                 goto err2;
1306             }
1307         } else {
1308             LOGE("Failed to retrieve buffer size (bad index)");
1309             return INVALID_OPERATION;
1310         }
1311     }
1312 
1313     LOGD("batch bufs successfully mmapped = %d",
1314              mNumBatchBufs);
1315 
1316     /* regFlags array is allocated here, but consumed and freed by
1317      * mm-camera-interface */
1318     regFlags = (uint8_t *)malloc(sizeof(uint8_t) * mNumBatchBufs);
1319     if (!regFlags) {
1320         LOGE("Out of memory");
1321         rc = NO_MEMORY;
1322         goto err3;
1323     }
1324     memset(regFlags, 0, sizeof(uint8_t) * mNumBatchBufs);
1325     /* Do not queue the container buffers as the image buffers are not yet
1326      * queued. mStreamBatchBufs->getRegFlags is not called as mStreamBatchBufs
1327      * considers single buffer is allocated */
1328     for (uint32_t i = 0; i < mNumBatchBufs; i++) {
1329         regFlags[i] = 0;
1330     }
1331 
1332     mBatchBufDefs = (mm_camera_buf_def_t *)
1333             malloc(mNumBatchBufs * sizeof(mm_camera_buf_def_t));
1334     if (mBatchBufDefs == NULL) {
1335         LOGE("mBatchBufDefs memory allocation failed");
1336         rc = INVALID_OPERATION;
1337         goto err4;
1338     }
1339     memset(mBatchBufDefs, 0, mNumBatchBufs * sizeof(mm_camera_buf_def_t));
1340 
1341     //Populate bufDef and queue to free batchBufQ
1342     for (uint32_t i = 0; i < mNumBatchBufs; i++) {
1343         getBatchBufDef(mBatchBufDefs[i], i);
1344         if(mFreeBatchBufQ.enqueue((void*) &mBatchBufDefs[i])) {
1345             LOGD("mBatchBufDefs[%d]: 0x%p", i, &mBatchBufDefs[i]);
1346         } else {
1347             LOGE("enqueue mBatchBufDefs[%d] failed", i);
1348         }
1349     }
1350 
1351     *num_bufs = mNumBatchBufs;
1352     *initial_reg_flag = regFlags;
1353     *bufs = mBatchBufDefs;
1354     LOGH("stream type: %d, numBufs(batch): %d",
1355              mStreamInfo->stream_type, mNumBatchBufs);
1356 
1357     return NO_ERROR;
1358 err4:
1359     free(regFlags);
1360 err3:
1361     for (size_t i = 0; i < mStreamBatchBufs->getCnt(); i++) {
1362         ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_USER_BUF,
1363                 ops_tbl->userdata);
1364     }
1365 err2:
1366     mStreamBatchBufs->deallocate();
1367 err1:
1368     delete mStreamBatchBufs;
1369     mStreamBatchBufs = NULL;
1370     return rc;
1371 }
1372 
1373 /*===========================================================================
1374  * FUNCTION   : putBatchBufs
1375  *
1376  * DESCRIPTION: deallocate stream batch buffers
1377  *
1378  * PARAMETERS :
1379  *   @ops_tbl    : ptr to buf mapping/unmapping ops
1380  *
1381  * RETURN     : int32_t type of status
1382  *              NO_ERROR  -- success
1383  *              none-zero failure code
1384  *==========================================================================*/
putBatchBufs(mm_camera_map_unmap_ops_tbl_t * ops_tbl)1385 int32_t QCamera3Stream::putBatchBufs(mm_camera_map_unmap_ops_tbl_t *ops_tbl)
1386 {
1387     int rc = NO_ERROR;
1388     Mutex::Autolock lock(mLock);
1389 
1390     if (mStreamBatchBufs) {
1391         for (uint32_t i = 0; i < mStreamBatchBufs->getCnt(); i++) {
1392             rc = ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_USER_BUF,
1393                     ops_tbl->userdata);
1394             if (rc < 0) {
1395                 LOGE("un-map batch buf failed: %d", rc);
1396             }
1397         }
1398         mStreamBatchBufs->deallocate();
1399         delete mStreamBatchBufs;
1400         mStreamBatchBufs = NULL;
1401     }
1402     // mm-camera-interface frees bufDefs even though bufDefs are allocated by
1403     // QCamera3Stream. Don't free here
1404     mBatchBufDefs = NULL;
1405 
1406     return rc;
1407 }
1408 
1409 /*===========================================================================
1410  * FUNCTION   : getBatchBufDef
1411  *
1412  * DESCRIPTION: query detailed buffer information of batch buffer
1413  *
1414  * PARAMETERS :
1415  *   @bufDef  : [output] reference to struct to store buffer definition
1416  *   @@index  : [input] index of the buffer
1417  *
1418  * RETURN     : int32_t type of status
1419  *              NO_ERROR  -- success
1420  *              none-zero failure code
1421  *==========================================================================*/
getBatchBufDef(mm_camera_buf_def_t & batchBufDef,int32_t index)1422 int32_t QCamera3Stream::getBatchBufDef(mm_camera_buf_def_t& batchBufDef,
1423         int32_t index)
1424 {
1425     int rc = NO_ERROR;
1426     memset(&batchBufDef, 0, sizeof(mm_camera_buf_def_t));
1427     if (mStreamBatchBufs) {
1428         //Single file descriptor for all batch buffers
1429         batchBufDef.fd          = mStreamBatchBufs->getFd(0);
1430         batchBufDef.buf_type    = CAM_STREAM_BUF_TYPE_USERPTR;
1431         batchBufDef.frame_len   = mStreamInfo->user_buf_info.size;
1432         batchBufDef.mem_info    = mStreamBatchBufs;
1433         batchBufDef.buffer      = (uint8_t *)mStreamBatchBufs->getPtr(0) +
1434                                     (index * mStreamInfo->user_buf_info.size);
1435         batchBufDef.buf_idx     = index;
1436         batchBufDef.user_buf.num_buffers = mBatchSize;
1437         batchBufDef.user_buf.bufs_used = 0;
1438         batchBufDef.user_buf.plane_buf = mBufDefs;
1439     }
1440 
1441     return rc;
1442 }
1443 
1444 /*===========================================================================
1445  * FUNCTION   : aggregateBufToBatch
1446  *
1447  * DESCRIPTION: queue batch container to downstream.
1448  *
1449  * PARAMETERS :
1450  *   @bufDef : image buffer to be aggregated into batch
1451  *
1452  * RETURN     : int32_t type of status
1453  *              NO_ERROR  -- success always
1454  *              none-zero failure code
1455  *==========================================================================*/
aggregateBufToBatch(mm_camera_buf_def_t & bufDef)1456 int32_t QCamera3Stream::aggregateBufToBatch(mm_camera_buf_def_t& bufDef)
1457 {
1458     int32_t rc = NO_ERROR;
1459 
1460     if (UNLIKELY(!mBatchSize)) {
1461         LOGE("Batch mod is not enabled");
1462         return INVALID_OPERATION;
1463     }
1464     if (!mCurrentBatchBufDef) {
1465         mCurrentBatchBufDef = (mm_camera_buf_def_t *)mFreeBatchBufQ.dequeue();
1466         if (!mCurrentBatchBufDef) {
1467             LOGE("No empty batch buffers is available");
1468             return NO_MEMORY;
1469         }
1470         LOGD("batch buffer: %d dequeued from empty buffer list",
1471                 mCurrentBatchBufDef->buf_idx);
1472     }
1473     if (mBufsStaged == mCurrentBatchBufDef->user_buf.num_buffers) {
1474         LOGE("batch buffer is already full");
1475         return NO_MEMORY;
1476     }
1477 
1478     mCurrentBatchBufDef->user_buf.buf_idx[mBufsStaged] = bufDef.buf_idx;
1479     mBufsStaged++;
1480     LOGD("buffer id: %d aggregated into batch buffer id: %d",
1481              bufDef.buf_idx, mCurrentBatchBufDef->buf_idx);
1482     return rc;
1483 }
1484 
1485 /*===========================================================================
1486  * FUNCTION   : queueBatchBuf
1487  *
1488  * DESCRIPTION: queue batch container to downstream.
1489  *
1490  * PARAMETERS : None
1491  *
1492  * RETURN     : int32_t type of status
1493  *              NO_ERROR  -- success always
1494  *              none-zero failure code
1495  *==========================================================================*/
queueBatchBuf()1496 int32_t QCamera3Stream::queueBatchBuf()
1497 {
1498     int32_t rc = NO_ERROR;
1499 
1500     if (!mCurrentBatchBufDef) {
1501         LOGE("No buffers were queued into batch");
1502         return INVALID_OPERATION;
1503     }
1504     //bufs_used: number of valid buffers in the batch buffers
1505     mCurrentBatchBufDef->user_buf.bufs_used = mBufsStaged;
1506 
1507     //if mBufsStaged < num_buffers, initialize the buf_idx to -1 for rest of the
1508     //buffers
1509     for (size_t i = mBufsStaged; i < mCurrentBatchBufDef->user_buf.num_buffers;
1510             i++) {
1511         mCurrentBatchBufDef->user_buf.buf_idx[i] = -1;
1512     }
1513 
1514     rc = mCamOps->qbuf(mCamHandle, mChannelHandle, mCurrentBatchBufDef);
1515     if (rc < 0) {
1516         LOGE("queueing of batch buffer: %d failed with err: %d",
1517                 mCurrentBatchBufDef->buf_idx, rc);
1518         return FAILED_TRANSACTION;
1519     }
1520     LOGD("Batch buf id: %d queued. bufs_used: %d",
1521             mCurrentBatchBufDef->buf_idx,
1522             mCurrentBatchBufDef->user_buf.bufs_used);
1523 
1524     mCurrentBatchBufDef = NULL;
1525     mBufsStaged = 0;
1526 
1527     return rc;
1528 }
1529 
1530 /*===========================================================================
1531  * FUNCTION   : handleBatchBuffer
1532  *
1533  * DESCRIPTION: separate individual buffers from the batch and issue callback
1534  *
1535  * PARAMETERS :
1536  *   @superBuf : Received superbuf containing batch buffer
1537  *
1538  * RETURN     : int32_t type of status
1539  *              NO_ERROR  -- success always
1540  *              none-zero failure code
1541  *==========================================================================*/
handleBatchBuffer(mm_camera_super_buf_t * superBuf)1542 int32_t QCamera3Stream::handleBatchBuffer(mm_camera_super_buf_t *superBuf)
1543 {
1544     int32_t rc = NO_ERROR;
1545     mm_camera_super_buf_t *frame;
1546     mm_camera_buf_def_t batchBuf;
1547 
1548     if (LIKELY(!mBatchSize)) {
1549         LOGE("Stream: %d not in batch mode, but batch buffer received",
1550                  getMyType());
1551         return INVALID_OPERATION;
1552     }
1553     if (!mDataCB) {
1554         LOGE("Data callback not set for batch mode");
1555         return BAD_VALUE;
1556     }
1557     if (!superBuf->bufs[0]) {
1558         LOGE("superBuf->bufs[0] is NULL!!");
1559         return BAD_VALUE;
1560     }
1561 
1562     /* Copy the batch buffer to local and queue the batch buffer to  empty queue
1563      * to handle the new requests received while callbacks are in progress */
1564     batchBuf = *superBuf->bufs[0];
1565     if (!mFreeBatchBufQ.enqueue((void*) superBuf->bufs[0])) {
1566         LOGE("batchBuf.buf_idx: %d enqueue failed",
1567                 batchBuf.buf_idx);
1568         free(superBuf);
1569         return NO_MEMORY;
1570     }
1571     LOGD("Received batch buffer: %d bufs_used: %d",
1572             batchBuf.buf_idx, batchBuf.user_buf.bufs_used);
1573     //dummy local bufDef to issue multiple callbacks
1574     mm_camera_buf_def_t buf;
1575     memset(&buf, 0, sizeof(mm_camera_buf_def_t));
1576 
1577     for (size_t i = 0; i < batchBuf.user_buf.bufs_used; i++) {
1578         int32_t buf_idx = batchBuf.user_buf.buf_idx[i];
1579         buf = mBufDefs[buf_idx];
1580 
1581         /* this memory is freed inside dataCB. Should not be freed here */
1582         frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
1583         if (!frame) {
1584             LOGE("malloc failed. Buffers will be dropped");
1585             break;
1586         } else {
1587             memcpy(frame, superBuf, sizeof(mm_camera_super_buf_t));
1588             frame->bufs[0] = &buf;
1589 
1590             mDataCB(frame, this, mUserData);
1591         }
1592     }
1593     LOGD("batch buffer: %d callbacks done",
1594             batchBuf.buf_idx);
1595 
1596     free(superBuf);
1597     return rc;
1598 }
1599 
1600 /*===========================================================================
1601  * FUNCTION   : flushFreeBatchBufQ
1602  *
1603  * DESCRIPTION: dequeue all the entries of mFreeBatchBufQ and call flush.
1604  *              QCameraQueue::flush calls 'free(node->data)' which should be
1605  *              avoided for mFreeBatchBufQ as the entries are not allocated
1606  *              during each enqueue
1607  *
1608  * PARAMETERS : None
1609  *
1610  * RETURN     : None
1611  *==========================================================================*/
flushFreeBatchBufQ()1612 void QCamera3Stream::flushFreeBatchBufQ()
1613 {
1614     while (!mFreeBatchBufQ.isEmpty()) {
1615         mFreeBatchBufQ.dequeue();
1616     }
1617     mFreeBatchBufQ.flush();
1618 }
1619 
1620 }; // namespace qcamera
1621