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