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