• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 *     * Redistributions of source code must retain the above copyright
7 *       notice, this list of conditions and the following disclaimer.
8 *     * Redistributions in binary form must reproduce the above
9 *       copyright notice, this list of conditions and the following
10 *       disclaimer in the documentation and/or other materials provided
11 *       with the distribution.
12 *     * Neither the name of The Linux Foundation nor the names of its
13 *       contributors may be used to endorse or promote products derived
14 *       from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29 
30 #define LOG_TAG "QCamera3Stream"
31 
32 // Camera dependencies
33 #include "QCamera3HWI.h"
34 #include "QCamera3Stream.h"
35 #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     rc = mCamOps->config_stream(mCamHandle,
487             mChannelHandle, mHandle, &stream_config);
488     if (rc < 0) {
489         LOGE("Failed to config stream, rc = %d", rc);
490         goto err4;
491     }
492 
493     mDataCB = stream_cb;
494     mUserData = userdata;
495     mBatchSize = batchSize;
496     return 0;
497 
498 err4:
499     mCamOps->unmap_stream_buf(mCamHandle,
500             mChannelHandle, mHandle, CAM_MAPPING_BUF_TYPE_STREAM_INFO, 0, -1);
501 err3:
502     mStreamInfoBuf->deallocate();
503 err2:
504     delete mStreamInfoBuf;
505     mStreamInfoBuf = NULL;
506     mStreamInfo = NULL;
507 err1:
508     mCamOps->delete_stream(mCamHandle, mChannelHandle, mHandle);
509     mHandle = 0;
510     mNumBufs = 0;
511 done:
512     return rc;
513 }
514 
515 /*===========================================================================
516  * FUNCTION   : start
517  *
518  * DESCRIPTION: start stream. Will start main stream thread to handle stream
519  *              related ops.
520  *
521  * PARAMETERS : none
522  *
523  * RETURN     : int32_t type of status
524  *              NO_ERROR  -- success
525  *              none-zero failure code
526  *==========================================================================*/
start()527 int32_t QCamera3Stream::start()
528 {
529     int32_t rc = 0;
530 
531     mDataQ.init();
532     mTimeoutFrameQ.clear();
533     if (mBatchSize)
534         mFreeBatchBufQ.init();
535     rc = mProcTh.launch(dataProcRoutine, this);
536     return rc;
537 }
538 
539 /*===========================================================================
540  * FUNCTION   : stop
541  *
542  * DESCRIPTION: stop stream. Will stop main stream thread
543  *
544  * PARAMETERS : none
545  *
546  * RETURN     : int32_t type of status
547  *              NO_ERROR  -- success
548  *              none-zero failure code
549  *==========================================================================*/
stop()550 int32_t QCamera3Stream::stop()
551 {
552     int32_t rc = 0;
553     rc = mProcTh.exit();
554     return rc;
555 }
556 
557 /*===========================================================================
558  * FUNCTION   : timeoutFrame
559  *
560  * DESCRIPTION: Function to issue timeout on frame
561  *
562  * PARAMETERS :
563  *   @bufIdx  : buffer index of the frame to be timed out
564  *
565  * RETURN     : int32_t type of status
566  *              NO_ERROR  -- success
567  *              none-zero failure code
568  *==========================================================================*/
timeoutFrame(int32_t bufIdx)569 int32_t QCamera3Stream::timeoutFrame(int32_t bufIdx)
570 {
571     LOGD("E\n");
572     int32_t rc;
573     {
574         Mutex::Autolock lock(mTimeoutFrameQLock);
575         mTimeoutFrameQ.push_back(bufIdx);
576     }
577     rc = mProcTh.sendCmd(CAMERA_CMD_TYPE_TIMEOUT, FALSE, FALSE);
578     LOGD("X\n");
579     return rc;
580 }
581 
582 /*===========================================================================
583  * FUNCTION   : processDataNotify
584  *
585  * DESCRIPTION: process stream data notify
586  *
587  * PARAMETERS :
588  *   @frame   : stream frame received
589  *
590  * RETURN     : int32_t type of status
591  *              NO_ERROR  -- success
592  *              none-zero failure code
593  *==========================================================================*/
processDataNotify(mm_camera_super_buf_t * frame)594 int32_t QCamera3Stream::processDataNotify(mm_camera_super_buf_t *frame)
595 {
596     LOGD("E\n");
597     int32_t rc;
598     if (mDataQ.enqueue((void *)frame)) {
599         rc = mProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
600     } else {
601         LOGD("Stream thread is not active, no ops here");
602         bufDone(frame->bufs[0]->buf_idx);
603         free(frame);
604         rc = NO_ERROR;
605     }
606     LOGD("X\n");
607     return rc;
608 }
609 
610 /*===========================================================================
611  * FUNCTION   : dataNotifyCB
612  *
613  * DESCRIPTION: callback for data notify. This function is registered with
614  *              mm-camera-interface to handle data notify
615  *
616  * PARAMETERS :
617  *   @recvd_frame   : stream frame received
618  *   userdata       : user data ptr
619  *
620  * RETURN     : none
621  *==========================================================================*/
dataNotifyCB(mm_camera_super_buf_t * recvd_frame,void * userdata)622 void QCamera3Stream::dataNotifyCB(mm_camera_super_buf_t *recvd_frame,
623                                  void *userdata)
624 {
625     LOGD("E\n");
626     QCamera3Stream* stream = (QCamera3Stream *)userdata;
627     if (stream == NULL ||
628         recvd_frame == NULL ||
629         recvd_frame->bufs[0] == NULL ||
630         recvd_frame->bufs[0]->stream_id != stream->getMyHandle()) {
631         LOGE("Not a valid stream to handle buf");
632         return;
633     }
634 
635     mm_camera_super_buf_t *frame =
636         (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
637     if (frame == NULL) {
638         LOGE("No mem for mm_camera_buf_def_t");
639         stream->bufDone(recvd_frame->bufs[0]->buf_idx);
640         return;
641     }
642     *frame = *recvd_frame;
643     stream->processDataNotify(frame);
644     return;
645 }
646 
647 /*===========================================================================
648  * FUNCTION   : dataProcRoutine
649  *
650  * DESCRIPTION: function to process data in the main stream thread
651  *
652  * PARAMETERS :
653  *   @data    : user data ptr
654  *
655  * RETURN     : none
656  *==========================================================================*/
dataProcRoutine(void * data)657 void *QCamera3Stream::dataProcRoutine(void *data)
658 {
659     int running = 1;
660     int ret;
661     QCamera3Stream *pme = (QCamera3Stream *)data;
662     QCameraCmdThread *cmdThread = &pme->mProcTh;
663 
664     cmdThread->setName(mStreamNames[pme->mStreamInfo->stream_type]);
665 
666     LOGD("E");
667     do {
668         do {
669             ret = cam_sem_wait(&cmdThread->cmd_sem);
670             if (ret != 0 && errno != EINVAL) {
671                 LOGE("cam_sem_wait error (%s)",
672                        strerror(errno));
673                 return NULL;
674             }
675         } while (ret != 0);
676 
677         // we got notified about new cmd avail in cmd queue
678         camera_cmd_type_t cmd = cmdThread->getCmd();
679         switch (cmd) {
680         case CAMERA_CMD_TYPE_TIMEOUT:
681             {
682                 int32_t bufIdx;
683                 {
684                     Mutex::Autolock lock(pme->mTimeoutFrameQLock);
685                     if (pme->mTimeoutFrameQ.size()) {
686                         auto itr = pme->mTimeoutFrameQ.begin();
687                         bufIdx = *itr;
688                         itr = pme->mTimeoutFrameQ.erase(itr);
689                     } else {
690                         LOGE("Timeout command received but Q is empty");
691                         break;
692                     }
693                 }
694                 pme->cancelBuffer(bufIdx);
695                 break;
696             }
697         case CAMERA_CMD_TYPE_DO_NEXT_JOB:
698             {
699                 LOGD("Do next job");
700                 mm_camera_super_buf_t *frame =
701                     (mm_camera_super_buf_t *)pme->mDataQ.dequeue();
702                 if (NULL != frame) {
703                     if (UNLIKELY(frame->bufs[0]->buf_type ==
704                             CAM_STREAM_BUF_TYPE_USERPTR)) {
705                         pme->handleBatchBuffer(frame);
706                     } else if (pme->mDataCB != NULL) {
707                         pme->mDataCB(frame, pme, pme->mUserData);
708                     } else {
709                         // no data cb routine, return buf here
710                         pme->bufDone(frame->bufs[0]->buf_idx);
711                     }
712                 }
713             }
714             break;
715         case CAMERA_CMD_TYPE_EXIT:
716             LOGH("Exit");
717             pme->flushFreeBatchBufQ();
718             /* flush data buf queue */
719             pme->mDataQ.flush();
720             pme->mTimeoutFrameQ.clear();
721             running = 0;
722             break;
723         default:
724             break;
725         }
726     } while (running);
727     LOGD("X");
728     return NULL;
729 }
730 
731 /*===========================================================================
732  * FUNCTION   : bufDone
733  *
734  * DESCRIPTION: return stream buffer to kernel
735  *
736  * PARAMETERS :
737  *   @index   : index of buffer to be returned
738  *
739  * RETURN     : int32_t type of status
740  *              NO_ERROR  -- success
741  *              none-zero failure code
742  *==========================================================================*/
bufDone(uint32_t index)743 int32_t QCamera3Stream::bufDone(uint32_t index)
744 {
745     Mutex::Autolock lock(mLock);
746     return bufDoneLocked(index);
747 }
748 
749 /*===========================================================================
750  * FUNCTION   : bufDoneLocked
751  *
752  * DESCRIPTION: return stream buffer to kernel while holding the lock
753  *
754  * PARAMETERS :
755  *   @index   : index of buffer to be returned
756  *
757  * RETURN     : int32_t type of status
758  *              NO_ERROR  -- success
759  *              none-zero failure code
760  *==========================================================================*/
bufDoneLocked(uint32_t index)761 int32_t QCamera3Stream::bufDoneLocked(uint32_t index)
762 {
763     int32_t rc = NO_ERROR;
764 
765     if ((index >= mNumBufs) || (mBufDefs == NULL)) {
766         LOGE("index; %d, mNumBufs: %d", index, mNumBufs);
767         return BAD_INDEX;
768     }
769     if (mStreamBufs == NULL)
770     {
771         LOGE("putBufs already called");
772         return INVALID_OPERATION;
773     }
774 
775     if( NULL == mBufDefs[index].mem_info) {
776         if (NULL == mMemOps) {
777             LOGE("Camera operations not initialized");
778             return NO_INIT;
779         }
780 
781         ssize_t bufSize = mStreamBufs->getSize(index);
782 
783         if (BAD_INDEX != bufSize) {
784             LOGD("Map streamBufIdx: %d", index);
785             void* buffer = (mMapStreamBuffers ?
786                             mStreamBufs->getPtr(index) : NULL);
787             rc = mMemOps->map_ops(index, -1, mStreamBufs->getFd(index),
788                     (size_t)bufSize, buffer,
789                     CAM_MAPPING_BUF_TYPE_STREAM_BUF, mMemOps->userdata);
790             if (rc < 0) {
791                 LOGE("Failed to map camera buffer %d", index);
792                 return rc;
793             }
794 
795             rc = mStreamBufs->getBufDef(mFrameLenOffset, mBufDefs[index], index, mMapStreamBuffers);
796             if (NO_ERROR != rc) {
797                 LOGE("Couldn't find camera buffer definition");
798                 mMemOps->unmap_ops(index, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF, mMemOps->userdata);
799                 return rc;
800             }
801         } else {
802             LOGE("Failed to retrieve buffer size (bad index)");
803             return INVALID_OPERATION;
804         }
805     }
806 
807     if (UNLIKELY(mBatchSize)) {
808         rc = aggregateBufToBatch(mBufDefs[index]);
809     } else {
810         // Cache invalidation should happen in lockNextBuffer or during
811         // reprocessing. No need to invalidate every buffer without knowing
812         // which buffer is accessed by CPU.
813         rc = mCamOps->qbuf(mCamHandle, mChannelHandle, &mBufDefs[index]);
814         if (rc < 0) {
815             return FAILED_TRANSACTION;
816         }
817     }
818 
819     return rc;
820 }
821 
822 /*===========================================================================
823  * FUNCTION   : cancelBuffer
824  *
825  * DESCRIPTION: Issue cancel buffer request to kernel
826  *
827  * PARAMETERS :
828  *   @index   : index of buffer to be cancelled
829  *
830  * RETURN     : int32_t type of status
831  *              NO_ERROR  -- success
832  *              none-zero failure code
833  *==========================================================================*/
cancelBuffer(uint32_t index)834 int32_t QCamera3Stream::cancelBuffer(uint32_t index)
835 {
836     int32_t rc = NO_ERROR;
837     Mutex::Autolock lock(mLock);
838 
839     if ((index >= mNumBufs) || (mBufDefs == NULL)) {
840         LOGE("index; %d, mNumBufs: %d", index, mNumBufs);
841         return BAD_INDEX;
842     }
843     if (mStreamBufs == NULL)
844     {
845         LOGE("putBufs already called");
846         return INVALID_OPERATION;
847     }
848 
849     /* if (UNLIKELY(mBatchSize)) {
850         FIXME
851     } else */{
852         LOGE("Calling cancel buf on idx:%d for stream type:%d",index, getMyType());
853         rc = mCamOps->cancel_buffer(mCamHandle, mChannelHandle, mHandle, index);
854         if (rc < 0) {
855             return FAILED_TRANSACTION;
856         }
857     }
858 
859     return rc;
860 }
861 
862 /*===========================================================================
863  * FUNCTION   : bufRelease
864  *
865  * DESCRIPTION: release all resources associated with this buffer
866  *
867  * PARAMETERS :
868  *   @index   : index of buffer to be released
869  *
870  * RETURN     : int32_t type of status
871  *              NO_ERROR  -- success
872  *              none-zero failure code
873  *==========================================================================*/
bufRelease(int32_t index)874 int32_t QCamera3Stream::bufRelease(int32_t index)
875 {
876     int32_t rc = NO_ERROR;
877     Mutex::Autolock lock(mLock);
878 
879     if ((index >= mNumBufs) || (mBufDefs == NULL)) {
880         return BAD_INDEX;
881     }
882 
883     if (NULL != mBufDefs[index].mem_info) {
884         if (NULL == mMemOps) {
885             LOGE("Camera operations not initialized");
886             return NO_INIT;
887         }
888 
889         rc = mMemOps->unmap_ops(index, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF,
890                 mMemOps->userdata);
891         if (rc < 0) {
892             LOGE("Failed to un-map camera buffer %d", index);
893             return rc;
894         }
895 
896         mBufDefs[index].mem_info = NULL;
897     } else {
898         LOGE("Buffer at index %d not registered");
899         return BAD_INDEX;
900     }
901 
902     return rc;
903 }
904 
905 /*===========================================================================
906  * FUNCTION   : getBufs
907  *
908  * DESCRIPTION: allocate stream buffers
909  *
910  * PARAMETERS :
911  *   @offset     : offset info of stream buffers
912  *   @num_bufs   : number of buffers allocated
913  *   @initial_reg_flag: flag to indicate if buffer needs to be registered
914  *                      at kernel initially
915  *   @bufs       : output of allocated buffers
916  *   @ops_tbl    : ptr to buf mapping/unmapping ops
917  *
918  * RETURN     : int32_t type of status
919  *              NO_ERROR  -- success
920  *              none-zero failure code
921  *==========================================================================*/
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)922 int32_t QCamera3Stream::getBufs(cam_frame_len_offset_t *offset,
923                      uint8_t *num_bufs,
924                      uint8_t **initial_reg_flag,
925                      mm_camera_buf_def_t **bufs,
926                      mm_camera_map_unmap_ops_tbl_t *ops_tbl)
927 {
928     int rc = NO_ERROR;
929     uint8_t *regFlags;
930     Mutex::Autolock lock(mLock);
931 
932     if (!ops_tbl) {
933         LOGE("ops_tbl is NULL");
934         return INVALID_OPERATION;
935     }
936 
937     mFrameLenOffset = *offset;
938     mMemOps = ops_tbl;
939 
940     if (mStreamBufs != NULL) {
941        LOGE("Failed getBufs being called twice in a row without a putBufs call");
942        return INVALID_OPERATION;
943     }
944     mStreamBufs = mChannel->getStreamBufs(mFrameLenOffset.frame_len);
945     if (!mStreamBufs) {
946         LOGE("Failed to allocate stream buffers");
947         return NO_MEMORY;
948     }
949 
950     for (uint32_t i = 0; i < mNumBufs; i++) {
951         if (mStreamBufs->valid(i)) {
952             ssize_t bufSize = mStreamBufs->getSize(i);
953             if (BAD_INDEX != bufSize) {
954                 void* buffer = (mMapStreamBuffers ?
955                         mStreamBufs->getPtr(i) : NULL);
956                 rc = ops_tbl->map_ops(i, -1, mStreamBufs->getFd(i),
957                         (size_t)bufSize, buffer,
958                         CAM_MAPPING_BUF_TYPE_STREAM_BUF,
959                         ops_tbl->userdata);
960                 if (rc < 0) {
961                     LOGE("map_stream_buf failed: %d", rc);
962                     for (uint32_t j = 0; j < i; j++) {
963                         if (mStreamBufs->valid(j)) {
964                             ops_tbl->unmap_ops(j, -1,
965                                     CAM_MAPPING_BUF_TYPE_STREAM_BUF,
966                                     ops_tbl->userdata);
967                         }
968                     }
969                     return INVALID_OPERATION;
970                 }
971             } else {
972                 LOGE("Failed to retrieve buffer size (bad index)");
973                 return INVALID_OPERATION;
974             }
975         }
976     }
977 
978     //regFlags array is allocated by us, but consumed and freed by mm-camera-interface
979     regFlags = (uint8_t *)malloc(sizeof(uint8_t) * mNumBufs);
980     if (!regFlags) {
981         LOGE("Out of memory");
982         for (uint32_t i = 0; i < mNumBufs; i++) {
983             if (mStreamBufs->valid(i)) {
984                 ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF,
985                         ops_tbl->userdata);
986             }
987         }
988         return NO_MEMORY;
989     }
990     memset(regFlags, 0, sizeof(uint8_t) * mNumBufs);
991 
992     mBufDefs = (mm_camera_buf_def_t *)malloc(mNumBufs * sizeof(mm_camera_buf_def_t));
993     if (mBufDefs == NULL) {
994         LOGE("Failed to allocate mm_camera_buf_def_t %d", rc);
995         for (uint32_t i = 0; i < mNumBufs; i++) {
996             if (mStreamBufs->valid(i)) {
997                 ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF,
998                         ops_tbl->userdata);
999             }
1000         }
1001         free(regFlags);
1002         regFlags = NULL;
1003         return INVALID_OPERATION;
1004     }
1005     memset(mBufDefs, 0, mNumBufs * sizeof(mm_camera_buf_def_t));
1006     for (uint32_t i = 0; i < mNumBufs; i++) {
1007         if (mStreamBufs->valid(i)) {
1008             mStreamBufs->getBufDef(mFrameLenOffset, mBufDefs[i], i, mMapStreamBuffers);
1009         }
1010     }
1011 
1012     rc = mStreamBufs->getRegFlags(regFlags);
1013     if (rc < 0) {
1014         LOGE("getRegFlags failed %d", rc);
1015         for (uint32_t i = 0; i < mNumBufs; i++) {
1016             if (mStreamBufs->valid(i)) {
1017                 ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF,
1018                         ops_tbl->userdata);
1019             }
1020         }
1021         free(mBufDefs);
1022         mBufDefs = NULL;
1023         free(regFlags);
1024         regFlags = NULL;
1025         return INVALID_OPERATION;
1026     }
1027 
1028     *num_bufs = mNumBufs;
1029     *initial_reg_flag = regFlags;
1030     *bufs = mBufDefs;
1031     return NO_ERROR;
1032 }
1033 
1034 /*===========================================================================
1035  * FUNCTION   : putBufs
1036  *
1037  * DESCRIPTION: deallocate stream buffers
1038  *
1039  * PARAMETERS :
1040  *   @ops_tbl    : ptr to buf mapping/unmapping ops
1041  *
1042  * RETURN     : int32_t type of status
1043  *              NO_ERROR  -- success
1044  *              none-zero failure code
1045  *==========================================================================*/
putBufs(mm_camera_map_unmap_ops_tbl_t * ops_tbl)1046 int32_t QCamera3Stream::putBufs(mm_camera_map_unmap_ops_tbl_t *ops_tbl)
1047 {
1048     int rc = NO_ERROR;
1049     Mutex::Autolock lock(mLock);
1050 
1051     for (uint32_t i = 0; i < mNumBufs; i++) {
1052         if (mStreamBufs->valid(i) && NULL != mBufDefs[i].mem_info) {
1053             rc = ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF, ops_tbl->userdata);
1054             if (rc < 0) {
1055                 LOGE("un-map stream buf failed: %d", rc);
1056             }
1057         }
1058     }
1059     mBufDefs = NULL; // mBufDefs just keep a ptr to the buffer
1060                      // mm-camera-interface own the buffer, so no need to free
1061     memset(&mFrameLenOffset, 0, sizeof(mFrameLenOffset));
1062 
1063     if (mStreamBufs == NULL) {
1064         LOGE("getBuf failed previously, or calling putBufs twice");
1065     }
1066 
1067     mChannel->putStreamBufs();
1068 
1069     //need to set mStreamBufs to null because putStreamBufs deletes that memory
1070     mStreamBufs = NULL;
1071 
1072     return rc;
1073 }
1074 
1075 /*===========================================================================
1076  * FUNCTION   : invalidateBuf
1077  *
1078  * DESCRIPTION: invalidate a specific stream buffer
1079  *
1080  * PARAMETERS :
1081  *   @index   : index of the buffer to invalidate
1082  *
1083  * RETURN     : int32_t type of status
1084  *              NO_ERROR  -- success
1085  *              none-zero failure code
1086  *==========================================================================*/
invalidateBuf(uint32_t index)1087 int32_t QCamera3Stream::invalidateBuf(uint32_t index)
1088 {
1089     if (mStreamBufs == NULL) {
1090        LOGE("putBufs already called");
1091        return INVALID_OPERATION;
1092     } else
1093        return mStreamBufs->invalidateCache(index);
1094 }
1095 
1096 /*===========================================================================
1097  * FUNCTION   : cleanInvalidateBuf
1098  *
1099  * DESCRIPTION: clean and invalidate a specific stream buffer
1100  *
1101  * PARAMETERS :
1102  *   @index   : index of the buffer to invalidate
1103  *
1104  * RETURN     : int32_t type of status
1105  *              NO_ERROR  -- success
1106  *              none-zero failure code
1107  *==========================================================================*/
cleanInvalidateBuf(uint32_t index)1108 int32_t QCamera3Stream::cleanInvalidateBuf(uint32_t index)
1109 {
1110     if (mStreamBufs == NULL) {
1111         LOGE("putBufs already called");
1112         return INVALID_OPERATION;
1113     } else
1114         return mStreamBufs->cleanInvalidateCache(index);
1115 }
1116 
1117 /*===========================================================================
1118  * FUNCTION   : cleanBuf
1119  *
1120  * DESCRIPTION: clean a specific stream buffer
1121  *
1122  * PARAMETERS :
1123  *   @index   : index of the buffer to invalidate
1124  *
1125  * RETURN     : int32_t type of status
1126  *              NO_ERROR  -- success
1127  *              none-zero failure code
1128  *==========================================================================*/
cleanBuf(uint32_t index)1129 int32_t QCamera3Stream::cleanBuf(uint32_t index)
1130 {
1131     if (mStreamBufs == NULL) {
1132         LOGE("putBufs already called");
1133         return INVALID_OPERATION;
1134     } else
1135         return mStreamBufs->cleanCache(index);
1136 }
1137 
1138 /*===========================================================================
1139  * FUNCTION   : getFrameOffset
1140  *
1141  * DESCRIPTION: query stream buffer frame offset info
1142  *
1143  * PARAMETERS :
1144  *   @offset  : reference to struct to store the queried frame offset info
1145  *
1146  * RETURN     : int32_t type of status
1147  *              NO_ERROR  -- success
1148  *              none-zero failure code
1149  *==========================================================================*/
getFrameOffset(cam_frame_len_offset_t & offset)1150 int32_t QCamera3Stream::getFrameOffset(cam_frame_len_offset_t &offset)
1151 {
1152     offset = mFrameLenOffset;
1153     return 0;
1154 }
1155 
1156 /*===========================================================================
1157  * FUNCTION   : getFrameDimension
1158  *
1159  * DESCRIPTION: query stream frame dimension info
1160  *
1161  * PARAMETERS :
1162  *   @dim     : reference to struct to store the queried frame dimension
1163  *
1164  * RETURN     : int32_t type of status
1165  *              NO_ERROR  -- success
1166  *              none-zero failure code
1167  *==========================================================================*/
getFrameDimension(cam_dimension_t & dim)1168 int32_t QCamera3Stream::getFrameDimension(cam_dimension_t &dim)
1169 {
1170     if (mStreamInfo != NULL) {
1171         dim = mStreamInfo->dim;
1172         return 0;
1173     }
1174     return -1;
1175 }
1176 
1177 /*===========================================================================
1178  * FUNCTION   : getFormat
1179  *
1180  * DESCRIPTION: query stream format
1181  *
1182  * PARAMETERS :
1183  *   @fmt     : reference to stream format
1184  *
1185  * RETURN     : int32_t type of status
1186  *              NO_ERROR  -- success
1187  *              none-zero failure code
1188  *==========================================================================*/
getFormat(cam_format_t & fmt)1189 int32_t QCamera3Stream::getFormat(cam_format_t &fmt)
1190 {
1191     if (mStreamInfo != NULL) {
1192         fmt = mStreamInfo->fmt;
1193         return 0;
1194     }
1195     return -1;
1196 }
1197 
1198 /*===========================================================================
1199  * FUNCTION   : getMyServerID
1200  *
1201  * DESCRIPTION: query server stream ID
1202  *
1203  * PARAMETERS : None
1204  *
1205  * RETURN     : stream ID from server
1206  *==========================================================================*/
getMyServerID()1207 uint32_t QCamera3Stream::getMyServerID() {
1208     if (mStreamInfo != NULL) {
1209         return mStreamInfo->stream_svr_id;
1210     } else {
1211         return 0;
1212     }
1213 }
1214 
1215 /*===========================================================================
1216  * FUNCTION   : getMyType
1217  *
1218  * DESCRIPTION: query stream type
1219  *
1220  * PARAMETERS : None
1221  *
1222  * RETURN     : type of stream
1223  *==========================================================================*/
getMyType() const1224 cam_stream_type_t QCamera3Stream::getMyType() const
1225 {
1226     if (mStreamInfo != NULL) {
1227         return mStreamInfo->stream_type;
1228     } else {
1229         return CAM_STREAM_TYPE_MAX;
1230     }
1231 }
1232 
1233 /*===========================================================================
1234  * FUNCTION   : mapBuf
1235  *
1236  * DESCRIPTION: map stream related buffer to backend server
1237  *
1238  * PARAMETERS :
1239  *   @buf_type : mapping type of buffer
1240  *   @buf_idx  : index of buffer
1241  *   @plane_idx: plane index
1242  *   @fd       : fd of the buffer
1243  *   @buffer : buffer ptr
1244  *   @size     : lenght of the buffer
1245  *
1246  * RETURN     : int32_t type of status
1247  *              NO_ERROR  -- success
1248  *              none-zero failure code
1249  *==========================================================================*/
mapBuf(uint8_t buf_type,uint32_t buf_idx,int32_t plane_idx,int fd,void * buffer,size_t size)1250 int32_t QCamera3Stream::mapBuf(uint8_t buf_type, uint32_t buf_idx,
1251         int32_t plane_idx, int fd, void *buffer, size_t size)
1252 {
1253     ATRACE_CALL();
1254     return mCamOps->map_stream_buf(mCamHandle, mChannelHandle,
1255                                    mHandle, buf_type,
1256                                    buf_idx, plane_idx,
1257                                    fd, size, buffer);
1258 
1259 }
1260 
1261 /*===========================================================================
1262  * FUNCTION   : unmapBuf
1263  *
1264  * DESCRIPTION: unmap stream related buffer to backend server
1265  *
1266  * PARAMETERS :
1267  *   @buf_type : mapping type of buffer
1268  *   @buf_idx  : index of buffer
1269  *   @plane_idx: plane index
1270  *
1271  * RETURN     : int32_t type of status
1272  *              NO_ERROR  -- success
1273  *              none-zero failure code
1274  *==========================================================================*/
unmapBuf(uint8_t buf_type,uint32_t buf_idx,int32_t plane_idx)1275 int32_t QCamera3Stream::unmapBuf(uint8_t buf_type, uint32_t buf_idx, int32_t plane_idx)
1276 {
1277     ATRACE_CALL();
1278     return mCamOps->unmap_stream_buf(mCamHandle, mChannelHandle,
1279                                      mHandle, buf_type,
1280                                      buf_idx, plane_idx);
1281 }
1282 
1283 /*===========================================================================
1284  * FUNCTION   : setParameter
1285  *
1286  * DESCRIPTION: set stream based parameters
1287  *
1288  * PARAMETERS :
1289  *   @param   : ptr to parameters to be set
1290  *
1291  * RETURN     : int32_t type of status
1292  *              NO_ERROR  -- success
1293  *              none-zero failure code
1294  *==========================================================================*/
setParameter(cam_stream_parm_buffer_t & param)1295 int32_t QCamera3Stream::setParameter(cam_stream_parm_buffer_t &param)
1296 {
1297     int32_t rc = NO_ERROR;
1298     mStreamInfo->parm_buf = param;
1299     ATRACE_CALL();
1300     rc = mCamOps->set_stream_parms(mCamHandle,
1301                                    mChannelHandle,
1302                                    mHandle,
1303                                    &mStreamInfo->parm_buf);
1304     if (rc == NO_ERROR) {
1305         param = mStreamInfo->parm_buf;
1306     }
1307     return rc;
1308 }
1309 
1310 /*===========================================================================
1311  * FUNCTION   : releaseFrameData
1312  *
1313  * DESCRIPTION: callback function to release frame data node
1314  *
1315  * PARAMETERS :
1316  *   @data      : ptr to post process input data
1317  *   @user_data : user data ptr (QCameraReprocessor)
1318  *
1319  * RETURN     : None
1320  *==========================================================================*/
releaseFrameData(void * data,void * user_data)1321 void QCamera3Stream::releaseFrameData(void *data, void *user_data)
1322 {
1323     QCamera3Stream *pme = (QCamera3Stream *)user_data;
1324     mm_camera_super_buf_t *frame = (mm_camera_super_buf_t *)data;
1325     if (NULL != pme) {
1326         if (UNLIKELY(pme->mBatchSize)) {
1327             /* For batch mode, the batch buffer is added to empty list */
1328             if(!pme->mFreeBatchBufQ.enqueue((void*) frame->bufs[0])) {
1329                 LOGE("batchBuf.buf_idx: %d enqueue failed",
1330                         frame->bufs[0]->buf_idx);
1331             }
1332         } else {
1333             pme->bufDone(frame->bufs[0]->buf_idx);
1334         }
1335     }
1336 }
1337 
1338 /*===========================================================================
1339  * FUNCTION   : getBatchBufs
1340  *
1341  * DESCRIPTION: allocate batch containers for the stream
1342  *
1343  * PARAMETERS :
1344  *   @num_bufs   : number of buffers allocated
1345  *   @initial_reg_flag: flag to indicate if buffer needs to be registered
1346  *                      at kernel initially
1347  *   @bufs       : output of allocated buffers
1348   *  @ops_tbl    : ptr to buf mapping/unmapping ops
1349  *
1350  * RETURN     : int32_t type of status
1351  *              NO_ERROR  -- success
1352  *              none-zero failure code
1353  *==========================================================================*/
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)1354 int32_t QCamera3Stream::getBatchBufs(
1355         uint8_t *num_bufs, uint8_t **initial_reg_flag,
1356         mm_camera_buf_def_t **bufs,
1357         mm_camera_map_unmap_ops_tbl_t *ops_tbl)
1358 {
1359     int rc = NO_ERROR;
1360     uint8_t *regFlags;
1361 
1362     if (!ops_tbl || !num_bufs || !initial_reg_flag || !bufs) {
1363         LOGE("input args NULL");
1364         return INVALID_OPERATION;
1365     }
1366     LOGH("Batch container allocation stream type = %d",
1367              getMyType());
1368 
1369     Mutex::Autolock lock(mLock);
1370 
1371     mMemOps = ops_tbl;
1372 
1373     //Allocate batch containers
1374     mStreamBatchBufs = new QCamera3HeapMemory(1);
1375     if (!mStreamBatchBufs) {
1376         LOGE("unable to create batch container memory");
1377         return NO_MEMORY;
1378     }
1379     // Allocating single buffer file-descriptor for all batch containers,
1380     // mStreamBatchBufs considers all the container bufs as a single buffer. But
1381     // QCamera3Stream manages that single buffer as multiple batch buffers
1382     LOGD("Allocating batch container memory. numBatch: %d size: %d",
1383              mNumBatchBufs, mStreamInfo->user_buf_info.size);
1384     rc = mStreamBatchBufs->allocate(
1385             mNumBatchBufs * mStreamInfo->user_buf_info.size);
1386     if (rc < 0) {
1387         LOGE("unable to allocate batch container memory");
1388         rc = NO_MEMORY;
1389         goto err1;
1390     }
1391 
1392     /* map batch buffers. getCnt here returns 1 because of single FD across
1393      * batch bufs */
1394     for (uint32_t i = 0; i < mStreamBatchBufs->getCnt(); i++) {
1395         if (mNumBatchBufs) {
1396             //For USER_BUF, size = number_of_container bufs instead of the total
1397             //buf size
1398             void* buffer = (mMapStreamBuffers ? mStreamBufs->getPtr(i) : NULL);
1399             rc = ops_tbl->map_ops(i, -1, mStreamBatchBufs->getFd(i),
1400                     (size_t)mNumBatchBufs, buffer,
1401                     CAM_MAPPING_BUF_TYPE_STREAM_USER_BUF,
1402                     ops_tbl->userdata);
1403             if (rc < 0) {
1404                 LOGE("Failed to map stream container buffer: %d",
1405                          rc);
1406                 //Unmap all the buffers that were successfully mapped before
1407                 //this buffer mapping failed
1408                 for (size_t j = 0; j < i; j++) {
1409                     ops_tbl->unmap_ops(j, -1,
1410                             CAM_MAPPING_BUF_TYPE_STREAM_USER_BUF,
1411                             ops_tbl->userdata);
1412                 }
1413                 goto err2;
1414             }
1415         } else {
1416             LOGE("Failed to retrieve buffer size (bad index)");
1417             return INVALID_OPERATION;
1418         }
1419     }
1420 
1421     LOGD("batch bufs successfully mmapped = %d",
1422              mNumBatchBufs);
1423 
1424     /* regFlags array is allocated here, but consumed and freed by
1425      * mm-camera-interface */
1426     regFlags = (uint8_t *)malloc(sizeof(uint8_t) * mNumBatchBufs);
1427     if (!regFlags) {
1428         LOGE("Out of memory");
1429         rc = NO_MEMORY;
1430         goto err3;
1431     }
1432     memset(regFlags, 0, sizeof(uint8_t) * mNumBatchBufs);
1433     /* Do not queue the container buffers as the image buffers are not yet
1434      * queued. mStreamBatchBufs->getRegFlags is not called as mStreamBatchBufs
1435      * considers single buffer is allocated */
1436     for (uint32_t i = 0; i < mNumBatchBufs; i++) {
1437         regFlags[i] = 0;
1438     }
1439 
1440     mBatchBufDefs = (mm_camera_buf_def_t *)
1441             malloc(mNumBatchBufs * sizeof(mm_camera_buf_def_t));
1442     if (mBatchBufDefs == NULL) {
1443         LOGE("mBatchBufDefs memory allocation failed");
1444         rc = INVALID_OPERATION;
1445         goto err4;
1446     }
1447     memset(mBatchBufDefs, 0, mNumBatchBufs * sizeof(mm_camera_buf_def_t));
1448 
1449     //Populate bufDef and queue to free batchBufQ
1450     for (uint32_t i = 0; i < mNumBatchBufs; i++) {
1451         getBatchBufDef(mBatchBufDefs[i], i);
1452         if(mFreeBatchBufQ.enqueue((void*) &mBatchBufDefs[i])) {
1453             LOGD("mBatchBufDefs[%d]: 0x%p", i, &mBatchBufDefs[i]);
1454         } else {
1455             LOGE("enqueue mBatchBufDefs[%d] failed", i);
1456         }
1457     }
1458 
1459     rc = aggregateStartingBufs(*initial_reg_flag);
1460     if (rc != NO_ERROR) {
1461         LOGE("Failed to aggregate starting buffers to the batch %d", rc);
1462         goto err4;
1463     }
1464 
1465     *num_bufs = mNumBatchBufs;
1466     *initial_reg_flag = regFlags;
1467     *bufs = mBatchBufDefs;
1468     LOGH("stream type: %d, numBufs(batch): %d",
1469              mStreamInfo->stream_type, mNumBatchBufs);
1470 
1471     return NO_ERROR;
1472 err4:
1473     free(regFlags);
1474 err3:
1475     for (size_t i = 0; i < mStreamBatchBufs->getCnt(); i++) {
1476         ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_USER_BUF,
1477                 ops_tbl->userdata);
1478     }
1479 err2:
1480     mStreamBatchBufs->deallocate();
1481 err1:
1482     delete mStreamBatchBufs;
1483     mStreamBatchBufs = NULL;
1484     return rc;
1485 }
1486 
1487 /*===========================================================================
1488  * FUNCTION   : putBatchBufs
1489  *
1490  * DESCRIPTION: deallocate stream batch buffers
1491  *
1492  * PARAMETERS :
1493  *   @ops_tbl    : ptr to buf mapping/unmapping ops
1494  *
1495  * RETURN     : int32_t type of status
1496  *              NO_ERROR  -- success
1497  *              none-zero failure code
1498  *==========================================================================*/
putBatchBufs(mm_camera_map_unmap_ops_tbl_t * ops_tbl)1499 int32_t QCamera3Stream::putBatchBufs(mm_camera_map_unmap_ops_tbl_t *ops_tbl)
1500 {
1501     int rc = NO_ERROR;
1502     Mutex::Autolock lock(mLock);
1503 
1504     if (mStreamBatchBufs) {
1505         for (uint32_t i = 0; i < mStreamBatchBufs->getCnt(); i++) {
1506             rc = ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_USER_BUF,
1507                     ops_tbl->userdata);
1508             if (rc < 0) {
1509                 LOGE("un-map batch buf failed: %d", rc);
1510             }
1511         }
1512         mStreamBatchBufs->deallocate();
1513         delete mStreamBatchBufs;
1514         mStreamBatchBufs = NULL;
1515     }
1516     // mm-camera-interface frees bufDefs even though bufDefs are allocated by
1517     // QCamera3Stream. Don't free here
1518     mBatchBufDefs = NULL;
1519 
1520     return rc;
1521 }
1522 
1523 /*===========================================================================
1524  * FUNCTION   : getBatchBufDef
1525  *
1526  * DESCRIPTION: query detailed buffer information of batch buffer
1527  *
1528  * PARAMETERS :
1529  *   @bufDef  : [output] reference to struct to store buffer definition
1530  *   @@index  : [input] index of the buffer
1531  *
1532  * RETURN     : int32_t type of status
1533  *              NO_ERROR  -- success
1534  *              none-zero failure code
1535  *==========================================================================*/
getBatchBufDef(mm_camera_buf_def_t & batchBufDef,int32_t index)1536 int32_t QCamera3Stream::getBatchBufDef(mm_camera_buf_def_t& batchBufDef,
1537         int32_t index)
1538 {
1539     int rc = NO_ERROR;
1540     memset(&batchBufDef, 0, sizeof(mm_camera_buf_def_t));
1541     if (mStreamBatchBufs) {
1542         //Single file descriptor for all batch buffers
1543         batchBufDef.fd          = mStreamBatchBufs->getFd(0);
1544         batchBufDef.buf_type    = CAM_STREAM_BUF_TYPE_USERPTR;
1545         batchBufDef.frame_len   = mStreamInfo->user_buf_info.size;
1546         batchBufDef.mem_info    = mStreamBatchBufs;
1547         batchBufDef.buffer      = (uint8_t *)mStreamBatchBufs->getPtr(0) +
1548                                     (index * mStreamInfo->user_buf_info.size);
1549         batchBufDef.buf_idx     = index;
1550         batchBufDef.user_buf.num_buffers = mBatchSize;
1551         batchBufDef.user_buf.bufs_used = 0;
1552         batchBufDef.user_buf.plane_buf = mBufDefs;
1553     }
1554 
1555     return rc;
1556 }
1557 
1558 /*===========================================================================
1559  * FUNCTION   : aggregateBufToBatch
1560  *
1561  * DESCRIPTION: queue batch container to downstream.
1562  *
1563  * PARAMETERS :
1564  *   @bufDef : image buffer to be aggregated into batch
1565  *
1566  * RETURN     : int32_t type of status
1567  *              NO_ERROR  -- success always
1568  *              none-zero failure code
1569  *==========================================================================*/
aggregateBufToBatch(mm_camera_buf_def_t & bufDef)1570 int32_t QCamera3Stream::aggregateBufToBatch(mm_camera_buf_def_t& bufDef)
1571 {
1572     int32_t rc = NO_ERROR;
1573 
1574     if (UNLIKELY(!mBatchSize)) {
1575         LOGE("Batch mod is not enabled");
1576         return INVALID_OPERATION;
1577     }
1578     if (!mCurrentBatchBufDef) {
1579         mCurrentBatchBufDef = (mm_camera_buf_def_t *)mFreeBatchBufQ.dequeue();
1580         if (!mCurrentBatchBufDef) {
1581             LOGE("No empty batch buffers is available");
1582             return NO_MEMORY;
1583         }
1584         LOGD("batch buffer: %d dequeued from empty buffer list",
1585                 mCurrentBatchBufDef->buf_idx);
1586     }
1587     if (mBufsStaged == mCurrentBatchBufDef->user_buf.num_buffers) {
1588         LOGE("batch buffer is already full");
1589         return NO_MEMORY;
1590     }
1591 
1592     mCurrentBatchBufDef->user_buf.buf_idx[mBufsStaged] = bufDef.buf_idx;
1593     mBufsStaged++;
1594     LOGD("buffer id: %d aggregated into batch buffer id: %d",
1595              bufDef.buf_idx, mCurrentBatchBufDef->buf_idx);
1596     return rc;
1597 }
1598 
1599 /*===========================================================================
1600  * FUNCTION   : aggregateStartingBuffers
1601  *
1602  * DESCRIPTION: Aggregate initial buffers to the first batch before stream_on
1603  *
1604  * PARAMETERS :
1605  *   @initial_reg_flag: flag to indicate if buffer needs to be registered
1606  *                      at kernel initially
1607  *
1608  * RETURN     : int32_t type of status
1609  *              NO_ERROR  -- success always
1610  *              none-zero failure code
1611  *==========================================================================*/
aggregateStartingBufs(const uint8_t * initial_reg_flag)1612 int32_t QCamera3Stream::aggregateStartingBufs(const uint8_t *initial_reg_flag)
1613 {
1614     int32_t rc = NO_ERROR;
1615 
1616     for (uint8_t i = 0; i < mBatchSize; i++) {
1617         if (initial_reg_flag[i]) {
1618             rc = bufDoneLocked(i);
1619             if (rc != NO_ERROR) {
1620                 LOGE("Failed to aggregate buffer %d to batch", i);
1621                 break;
1622             }
1623         }
1624     }
1625     return rc;
1626 }
1627 
1628 /*===========================================================================
1629  * FUNCTION   : queueBatchBuf
1630  *
1631  * DESCRIPTION: queue batch container to downstream.
1632  *
1633  * PARAMETERS : None
1634  *
1635  * RETURN     : int32_t type of status
1636  *              NO_ERROR  -- success always
1637  *              none-zero failure code
1638  *==========================================================================*/
queueBatchBuf()1639 int32_t QCamera3Stream::queueBatchBuf()
1640 {
1641     int32_t rc = NO_ERROR;
1642 
1643     if (!mCurrentBatchBufDef) {
1644         LOGE("No buffers were queued into batch");
1645         return INVALID_OPERATION;
1646     }
1647     //bufs_used: number of valid buffers in the batch buffers
1648     mCurrentBatchBufDef->user_buf.bufs_used = mBufsStaged;
1649 
1650     //if mBufsStaged < num_buffers, initialize the buf_idx to -1 for rest of the
1651     //buffers
1652     for (size_t i = mBufsStaged; i < mCurrentBatchBufDef->user_buf.num_buffers;
1653             i++) {
1654         mCurrentBatchBufDef->user_buf.buf_idx[i] = -1;
1655     }
1656 
1657     rc = mCamOps->qbuf(mCamHandle, mChannelHandle, mCurrentBatchBufDef);
1658     if (rc < 0) {
1659         LOGE("queueing of batch buffer: %d failed with err: %d",
1660                 mCurrentBatchBufDef->buf_idx, rc);
1661         return FAILED_TRANSACTION;
1662     }
1663     LOGD("Batch buf id: %d queued. bufs_used: %d",
1664             mCurrentBatchBufDef->buf_idx,
1665             mCurrentBatchBufDef->user_buf.bufs_used);
1666 
1667     mCurrentBatchBufDef = NULL;
1668     mBufsStaged = 0;
1669 
1670     return rc;
1671 }
1672 
1673 /*===========================================================================
1674  * FUNCTION   : handleBatchBuffer
1675  *
1676  * DESCRIPTION: separate individual buffers from the batch and issue callback
1677  *
1678  * PARAMETERS :
1679  *   @superBuf : Received superbuf containing batch buffer
1680  *
1681  * RETURN     : int32_t type of status
1682  *              NO_ERROR  -- success always
1683  *              none-zero failure code
1684  *==========================================================================*/
handleBatchBuffer(mm_camera_super_buf_t * superBuf)1685 int32_t QCamera3Stream::handleBatchBuffer(mm_camera_super_buf_t *superBuf)
1686 {
1687     int32_t rc = NO_ERROR;
1688     mm_camera_super_buf_t *frame;
1689     mm_camera_buf_def_t batchBuf;
1690 
1691     if (LIKELY(!mBatchSize)) {
1692         LOGE("Stream: %d not in batch mode, but batch buffer received",
1693                  getMyType());
1694         return INVALID_OPERATION;
1695     }
1696     if (!mDataCB) {
1697         LOGE("Data callback not set for batch mode");
1698         return BAD_VALUE;
1699     }
1700     if (!superBuf->bufs[0]) {
1701         LOGE("superBuf->bufs[0] is NULL!!");
1702         return BAD_VALUE;
1703     }
1704 
1705     /* Copy the batch buffer to local and queue the batch buffer to  empty queue
1706      * to handle the new requests received while callbacks are in progress */
1707     batchBuf = *superBuf->bufs[0];
1708     if (!mFreeBatchBufQ.enqueue((void*) superBuf->bufs[0])) {
1709         LOGE("batchBuf.buf_idx: %d enqueue failed",
1710                 batchBuf.buf_idx);
1711         free(superBuf);
1712         return NO_MEMORY;
1713     }
1714     LOGD("Received batch buffer: %d bufs_used: %d",
1715             batchBuf.buf_idx, batchBuf.user_buf.bufs_used);
1716     //dummy local bufDef to issue multiple callbacks
1717     mm_camera_buf_def_t buf;
1718     memset(&buf, 0, sizeof(mm_camera_buf_def_t));
1719 
1720     for (size_t i = 0; i < batchBuf.user_buf.bufs_used; i++) {
1721         int32_t buf_idx = batchBuf.user_buf.buf_idx[i];
1722         buf = mBufDefs[buf_idx];
1723 
1724         /* this memory is freed inside dataCB. Should not be freed here */
1725         frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
1726         if (!frame) {
1727             LOGE("malloc failed. Buffers will be dropped");
1728             break;
1729         } else {
1730             memcpy(frame, superBuf, sizeof(mm_camera_super_buf_t));
1731             frame->bufs[0] = &buf;
1732 
1733             mDataCB(frame, this, mUserData);
1734         }
1735     }
1736     LOGD("batch buffer: %d callbacks done",
1737             batchBuf.buf_idx);
1738 
1739     free(superBuf);
1740     return rc;
1741 }
1742 
1743 /*===========================================================================
1744  * FUNCTION   : flushFreeBatchBufQ
1745  *
1746  * DESCRIPTION: dequeue all the entries of mFreeBatchBufQ and call flush.
1747  *              QCameraQueue::flush calls 'free(node->data)' which should be
1748  *              avoided for mFreeBatchBufQ as the entries are not allocated
1749  *              during each enqueue
1750  *
1751  * PARAMETERS : None
1752  *
1753  * RETURN     : None
1754  *==========================================================================*/
flushFreeBatchBufQ()1755 void QCamera3Stream::flushFreeBatchBufQ()
1756 {
1757     while (!mFreeBatchBufQ.isEmpty()) {
1758         mFreeBatchBufQ.dequeue();
1759     }
1760     mFreeBatchBufQ.flush();
1761 }
1762 
1763 }; // namespace qcamera
1764