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