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