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