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