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