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