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