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