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