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