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