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