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