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