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