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