1 /* Copyright (c) 2012-2014 The Linux Foundataion. All rights reserved. 2 * 3 * Redistribution and use in source and binary forms, with or without 4 * modification, are permitted provided that the following conditions are 5 * met: 6 * * Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * * Redistributions in binary form must reproduce the above 9 * copyright notice, this list of conditions and the following 10 * disclaimer in the documentation and/or other materials provided 11 * with the distribution. 12 * * Neither the name of The Linux Foundation nor the names of its 13 * contributors may be used to endorse or promote products derived 14 * from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 */ 29 30 #define LOG_TAG "QCameraChannel" 31 32 #include <utils/Errors.h> 33 #include "QCameraParameters.h" 34 #include "QCamera2HWI.h" 35 #include "QCameraChannel.h" 36 37 using namespace android; 38 39 namespace qcamera { 40 41 /*=========================================================================== 42 * FUNCTION : QCameraChannel 43 * 44 * DESCRIPTION: constrcutor of QCameraChannel 45 * 46 * PARAMETERS : 47 * @cam_handle : camera handle 48 * @cam_ops : ptr to camera ops table 49 * 50 * RETURN : none 51 *==========================================================================*/ 52 QCameraChannel::QCameraChannel(uint32_t cam_handle, 53 mm_camera_ops_t *cam_ops) 54 { 55 m_camHandle = cam_handle; 56 m_camOps = cam_ops; 57 m_bIsActive = false; 58 m_bAllowDynBufAlloc = false; 59 60 m_handle = 0; 61 m_numStreams = 0; 62 memset(mStreams, 0, sizeof(mStreams)); 63 } 64 65 /*=========================================================================== 66 * FUNCTION : QCameraChannel 67 * 68 * DESCRIPTION: default constrcutor of QCameraChannel 69 * 70 * PARAMETERS : none 71 * 72 * RETURN : none 73 *==========================================================================*/ 74 QCameraChannel::QCameraChannel() 75 { 76 m_camHandle = 0; 77 m_camOps = NULL; 78 m_bIsActive = false; 79 80 m_handle = 0; 81 m_numStreams = 0; 82 memset(mStreams, 0, sizeof(mStreams)); 83 } 84 85 /*=========================================================================== 86 * FUNCTION : ~QCameraChannel 87 * 88 * DESCRIPTION: destructor of QCameraChannel 89 * 90 * PARAMETERS : none 91 * 92 * RETURN : none 93 *==========================================================================*/ 94 QCameraChannel::~QCameraChannel() 95 { 96 if (m_bIsActive) { 97 stop(); 98 } 99 100 for (int i = 0; i < m_numStreams; i++) { 101 if (mStreams[i] != NULL) { 102 delete mStreams[i]; 103 mStreams[i] = 0; 104 } 105 } 106 m_numStreams = 0; 107 m_camOps->delete_channel(m_camHandle, m_handle); 108 m_handle = 0; 109 } 110 111 /*=========================================================================== 112 * FUNCTION : deleteChannel 113 * 114 * DESCRIPTION: deletes a camera channel 115 * 116 * PARAMETERS : none 117 * 118 * RETURN : none 119 *==========================================================================*/ 120 void QCameraChannel::deleteChannel() 121 { 122 if (m_bIsActive) { 123 stop(); 124 } 125 126 for (int i = 0; i < m_numStreams; i++) { 127 if (mStreams[i] != NULL) { 128 mStreams[i]->deleteStream(); 129 } 130 } 131 m_camOps->delete_channel(m_camHandle, m_handle); 132 } 133 134 /*=========================================================================== 135 * FUNCTION : init 136 * 137 * DESCRIPTION: initialization of channel 138 * 139 * PARAMETERS : 140 * @attr : channel bundle attribute setting 141 * @dataCB : data notify callback 142 * @userData: user data ptr 143 * 144 * RETURN : int32_t type of status 145 * NO_ERROR -- success 146 * none-zero failure code 147 *==========================================================================*/ 148 int32_t QCameraChannel::init(mm_camera_channel_attr_t *attr, 149 mm_camera_buf_notify_t dataCB, 150 void *userData) 151 { 152 m_handle = m_camOps->add_channel(m_camHandle, 153 attr, 154 dataCB, 155 userData); 156 if (m_handle == 0) { 157 ALOGE("%s: Add channel failed", __func__); 158 return UNKNOWN_ERROR; 159 } 160 return NO_ERROR; 161 } 162 163 /*=========================================================================== 164 * FUNCTION : addStream 165 * 166 * DESCRIPTION: add a stream into channel 167 * 168 * PARAMETERS : 169 * @allocator : stream related buffer allocator 170 * @streamInfoBuf : ptr to buf that constains stream info 171 * @minStreamBufNum: number of stream buffers needed 172 * @paddingInfo : padding information 173 * @stream_cb : stream data notify callback 174 * @userdata : user data ptr 175 * @bDynAllocBuf : flag indicating if allow allocate buffers in 2 steps 176 * 177 * RETURN : int32_t type of status 178 * NO_ERROR -- success 179 * none-zero failure code 180 *==========================================================================*/ 181 int32_t QCameraChannel::addStream(QCameraAllocator &allocator, 182 QCameraHeapMemory *streamInfoBuf, 183 uint8_t minStreamBufNum, 184 cam_padding_info_t *paddingInfo, 185 stream_cb_routine stream_cb, 186 void *userdata, 187 bool bDynAllocBuf, 188 bool bDeffAlloc) 189 { 190 int32_t rc = NO_ERROR; 191 if (m_numStreams >= MAX_STREAM_NUM_IN_BUNDLE) { 192 ALOGE("%s: stream number (%d) exceeds max limit (%d)", 193 __func__, m_numStreams, MAX_STREAM_NUM_IN_BUNDLE); 194 return BAD_VALUE; 195 } 196 QCameraStream *pStream = new QCameraStream(allocator, 197 m_camHandle, 198 m_handle, 199 m_camOps, 200 paddingInfo, 201 bDeffAlloc); 202 if (pStream == NULL) { 203 ALOGE("%s: No mem for Stream", __func__); 204 return NO_MEMORY; 205 } 206 207 rc = pStream->init(streamInfoBuf, minStreamBufNum, 208 stream_cb, userdata, bDynAllocBuf); 209 if (rc == 0) { 210 mStreams[m_numStreams] = pStream; 211 m_numStreams++; 212 } else { 213 delete pStream; 214 } 215 return rc; 216 } 217 /*=========================================================================== 218 * FUNCTION : config 219 * 220 * DESCRIPTION: Configure any deffered channel streams 221 * 222 * PARAMETERS : None 223 * 224 * RETURN : int32_t type of status 225 * NO_ERROR -- success 226 * none-zero failure code 227 *==========================================================================*/ 228 int32_t QCameraChannel::config() 229 { 230 int32_t rc = NO_ERROR; 231 232 for (int i = 0; i < m_numStreams; ++i) { 233 if ( mStreams[i]->isDeffered() ) { 234 rc = mStreams[i]->configStream(); 235 if (rc != NO_ERROR) { 236 break; 237 } 238 } 239 } 240 241 return rc; 242 } 243 244 /*=========================================================================== 245 * FUNCTION : start 246 * 247 * DESCRIPTION: start channel, which will start all streams belong to this channel 248 * 249 * PARAMETERS : None 250 * 251 * RETURN : int32_t type of status 252 * NO_ERROR -- success 253 * none-zero failure code 254 *==========================================================================*/ 255 int32_t QCameraChannel::start() 256 { 257 int32_t rc = NO_ERROR; 258 259 if (m_numStreams > 1) { 260 // there is more than one stream in the channel 261 // we need to notify mctl that all streams in this channel need to be bundled 262 cam_bundle_config_t bundleInfo; 263 memset(&bundleInfo, 0, sizeof(bundleInfo)); 264 rc = m_camOps->get_bundle_info(m_camHandle, m_handle, &bundleInfo); 265 if (rc != NO_ERROR) { 266 ALOGE("%s: get_bundle_info failed", __func__); 267 return rc; 268 } 269 if (bundleInfo.num_of_streams > 1) { 270 for (int i = 0; i < bundleInfo.num_of_streams; i++) { 271 QCameraStream *pStream = getStreamByServerID(bundleInfo.stream_ids[i]); 272 if (pStream != NULL) { 273 if (pStream->isTypeOf(CAM_STREAM_TYPE_METADATA)) { 274 // Skip metadata for reprocess now because PP module cannot handle meta data 275 // May need furthur discussion if Imaginglib need meta data 276 continue; 277 } 278 279 cam_stream_parm_buffer_t param; 280 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t)); 281 param.type = CAM_STREAM_PARAM_TYPE_SET_BUNDLE_INFO; 282 param.bundleInfo = bundleInfo; 283 rc = pStream->setParameter(param); 284 if (rc != NO_ERROR) { 285 ALOGE("%s: stream setParameter for set bundle failed", __func__); 286 return rc; 287 } 288 } 289 } 290 } 291 } 292 293 for (int i = 0; i < m_numStreams; i++) { 294 if (mStreams[i] != NULL) { 295 mStreams[i]->start(); 296 } 297 } 298 rc = m_camOps->start_channel(m_camHandle, m_handle); 299 300 if (rc != NO_ERROR) { 301 for (int i = 0; i < m_numStreams; i++) { 302 if (mStreams[i] != NULL) { 303 mStreams[i]->stop(); 304 } 305 } 306 } else { 307 m_bIsActive = true; 308 for (int i = 0; i < m_numStreams; i++) { 309 if (mStreams[i] != NULL) { 310 mStreams[i]->cond_signal(); 311 } 312 } 313 } 314 315 return rc; 316 } 317 318 /*=========================================================================== 319 * FUNCTION : stop 320 * 321 * DESCRIPTION: stop a channel, which will stop all streams belong to this channel 322 * 323 * PARAMETERS : none 324 * 325 * RETURN : int32_t type of status 326 * NO_ERROR -- success 327 * none-zero failure code 328 *==========================================================================*/ 329 int32_t QCameraChannel::stop() 330 { 331 int32_t rc = NO_ERROR; 332 for (int i = 0; i < m_numStreams; i++) { 333 if (mStreams[i] != NULL) { 334 mStreams[i]->stop(); 335 } 336 } 337 338 rc = m_camOps->stop_channel(m_camHandle, m_handle); 339 340 m_bIsActive = false; 341 return rc; 342 } 343 344 /*=========================================================================== 345 * FUNCTION : bufDone 346 * 347 * DESCRIPTION: return a stream buf back to kernel 348 * 349 * PARAMETERS : 350 * @recvd_frame : stream buf frame to be returned 351 * 352 * RETURN : int32_t type of status 353 * NO_ERROR -- success 354 * none-zero failure code 355 *==========================================================================*/ 356 int32_t QCameraChannel::bufDone(mm_camera_super_buf_t *recvd_frame) 357 { 358 int32_t rc = NO_ERROR; 359 for (int i = 0; i < recvd_frame->num_bufs; i++) { 360 if (recvd_frame->bufs[i] != NULL) { 361 for (int j = 0; j < m_numStreams; j++) { 362 if (mStreams[j] != NULL && 363 mStreams[j]->getMyHandle() == recvd_frame->bufs[i]->stream_id) { 364 rc = mStreams[j]->bufDone(recvd_frame->bufs[i]->buf_idx); 365 break; // break loop j 366 } 367 } 368 } 369 } 370 371 return rc; 372 } 373 374 /*=========================================================================== 375 * FUNCTION : processZoomDone 376 * 377 * DESCRIPTION: process zoom done event 378 * 379 * PARAMETERS : 380 * @previewWindoe : ptr to preview window ops table, needed to set preview 381 * crop information 382 * @crop_info : crop info as a result of zoom operation 383 * 384 * RETURN : int32_t type of status 385 * NO_ERROR -- success 386 * none-zero failure code 387 *==========================================================================*/ 388 int32_t QCameraChannel::processZoomDone(preview_stream_ops_t *previewWindow, 389 cam_crop_data_t &crop_info) 390 { 391 int32_t rc = NO_ERROR; 392 for (int i = 0; i < m_numStreams; i++) { 393 if (mStreams[i] != NULL) { 394 rc = mStreams[i]->processZoomDone(previewWindow, crop_info); 395 } 396 } 397 return rc; 398 } 399 400 /*=========================================================================== 401 * FUNCTION : getStreamByHandle 402 * 403 * DESCRIPTION: return stream object by stream handle 404 * 405 * PARAMETERS : 406 * @streamHandle : stream handle 407 * 408 * RETURN : stream object. NULL if not found 409 *==========================================================================*/ 410 QCameraStream *QCameraChannel::getStreamByHandle(uint32_t streamHandle) 411 { 412 for (int i = 0; i < m_numStreams; i++) { 413 if (mStreams[i] != NULL && mStreams[i]->getMyHandle() == streamHandle) { 414 return mStreams[i]; 415 } 416 } 417 return NULL; 418 } 419 420 /*=========================================================================== 421 * FUNCTION : getStreamByServerID 422 * 423 * DESCRIPTION: return stream object by stream server ID from daemon 424 * 425 * PARAMETERS : 426 * @serverID : stream server ID 427 * 428 * RETURN : stream object. NULL if not found 429 *==========================================================================*/ 430 QCameraStream *QCameraChannel::getStreamByServerID(uint32_t serverID) 431 { 432 for (int i = 0; i < m_numStreams; i++) { 433 if (mStreams[i] != NULL && mStreams[i]->getMyServerID() == serverID) { 434 return mStreams[i]; 435 } 436 } 437 return NULL; 438 } 439 440 /*=========================================================================== 441 * FUNCTION : getStreamByIndex 442 * 443 * DESCRIPTION: return stream object by index of streams in the channel 444 * 445 * PARAMETERS : 446 * @index : index of stream in the channel 447 * 448 * RETURN : stream object. NULL if not found 449 *==========================================================================*/ 450 QCameraStream *QCameraChannel::getStreamByIndex(uint8_t index) 451 { 452 if (index >= MAX_STREAM_NUM_IN_BUNDLE) { 453 return NULL; 454 } 455 456 if (index < m_numStreams) { 457 return mStreams[index]; 458 } 459 return NULL; 460 } 461 462 /*=========================================================================== 463 * FUNCTION : UpdateStreamBasedParameters 464 * 465 * DESCRIPTION: update any stream based settings from parameters 466 * 467 * PARAMETERS : 468 * @param : reference to parameters object 469 * 470 * RETURN : int32_t type of status 471 * NO_ERROR -- success 472 * none-zero failure code 473 *==========================================================================*/ 474 int32_t QCameraChannel::UpdateStreamBasedParameters(QCameraParameters ¶m) 475 { 476 int32_t rc = NO_ERROR; 477 if (param.isPreviewFlipChanged()) { 478 // try to find preview stream 479 for (int i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) { 480 if (mStreams[i] != NULL && 481 (mStreams[i]->isTypeOf(CAM_STREAM_TYPE_PREVIEW) || 482 (mStreams[i]->isOrignalTypeOf(CAM_STREAM_TYPE_PREVIEW))) ) { 483 cam_stream_parm_buffer_t param_buf; 484 memset(¶m_buf, 0, sizeof(cam_stream_parm_buffer_t)); 485 param_buf.type = CAM_STREAM_PARAM_TYPE_SET_FLIP; 486 param_buf.flipInfo.flip_mask = param.getFlipMode(CAM_STREAM_TYPE_PREVIEW); 487 rc = mStreams[i]->setParameter(param_buf); 488 if (rc != NO_ERROR) { 489 ALOGE("%s: set preview stream flip failed", __func__); 490 } 491 } 492 } 493 } 494 if (param.isVideoFlipChanged()) { 495 // try to find video stream 496 for (int i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) { 497 if (mStreams[i] != NULL && 498 (mStreams[i]->isTypeOf(CAM_STREAM_TYPE_VIDEO) || 499 (mStreams[i]->isOrignalTypeOf(CAM_STREAM_TYPE_VIDEO))) ) { 500 cam_stream_parm_buffer_t param_buf; 501 memset(¶m_buf, 0, sizeof(cam_stream_parm_buffer_t)); 502 param_buf.type = CAM_STREAM_PARAM_TYPE_SET_FLIP; 503 param_buf.flipInfo.flip_mask = param.getFlipMode(CAM_STREAM_TYPE_VIDEO); 504 rc = mStreams[i]->setParameter(param_buf); 505 if (rc != NO_ERROR) { 506 ALOGE("%s: set video stream flip failed", __func__); 507 } 508 } 509 } 510 } 511 if (param.isSnapshotFlipChanged()) { 512 // try to find snapshot/postview stream 513 for (int i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) { 514 if (mStreams[i] != NULL && 515 (mStreams[i]->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) || 516 mStreams[i]->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT) || 517 mStreams[i]->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) || 518 mStreams[i]->isOrignalTypeOf(CAM_STREAM_TYPE_POSTVIEW) ) ) { 519 cam_stream_parm_buffer_t param_buf; 520 memset(¶m_buf, 0, sizeof(cam_stream_parm_buffer_t)); 521 param_buf.type = CAM_STREAM_PARAM_TYPE_SET_FLIP; 522 param_buf.flipInfo.flip_mask = param.getFlipMode(CAM_STREAM_TYPE_SNAPSHOT); 523 rc = mStreams[i]->setParameter(param_buf); 524 if (rc != NO_ERROR) { 525 ALOGE("%s: set snapshot stream flip failed", __func__); 526 } 527 } 528 } 529 } 530 return rc; 531 } 532 533 /*=========================================================================== 534 * FUNCTION : QCameraPicChannel 535 * 536 * DESCRIPTION: constructor of QCameraPicChannel 537 * 538 * PARAMETERS : 539 * @cam_handle : camera handle 540 * @cam_ops : ptr to camera ops table 541 * 542 * RETURN : none 543 *==========================================================================*/ 544 QCameraPicChannel::QCameraPicChannel(uint32_t cam_handle, 545 mm_camera_ops_t *cam_ops) : 546 QCameraChannel(cam_handle, cam_ops) 547 { 548 m_bAllowDynBufAlloc = true; 549 } 550 551 /*=========================================================================== 552 * FUNCTION : QCameraPicChannel 553 * 554 * DESCRIPTION: default constructor of QCameraPicChannel 555 * 556 * PARAMETERS : none 557 * 558 * RETURN : none 559 *==========================================================================*/ 560 QCameraPicChannel::QCameraPicChannel() 561 { 562 m_bAllowDynBufAlloc = true; 563 } 564 565 /*=========================================================================== 566 * FUNCTION : ~QCameraPicChannel 567 * 568 * DESCRIPTION: destructor of QCameraPicChannel 569 * 570 * PARAMETERS : none 571 * 572 * RETURN : none 573 *==========================================================================*/ 574 QCameraPicChannel::~QCameraPicChannel() 575 { 576 } 577 578 /*=========================================================================== 579 * FUNCTION : takePicture 580 * 581 * DESCRIPTION: send request for queued snapshot frames 582 * 583 * PARAMETERS : 584 * @num_of_snapshot : number of snapshot frames requested 585 * @num_of_retro_snapshot : number of retro snapshot frames requested 586 * 587 * RETURN : int32_t type of status 588 * NO_ERROR -- success 589 * none-zero failure code 590 *==========================================================================*/ 591 int32_t QCameraPicChannel::takePicture ( 592 uint8_t num_of_snapshot, 593 uint8_t num_of_retro_snapshot) 594 { 595 int32_t rc = m_camOps->request_super_buf(m_camHandle, 596 m_handle, 597 num_of_snapshot, 598 num_of_retro_snapshot); 599 return rc; 600 } 601 602 /*=========================================================================== 603 * FUNCTION : cancelPicture 604 * 605 * DESCRIPTION: cancel request for queued snapshot frames 606 * 607 * PARAMETERS : none 608 * 609 * RETURN : int32_t type of status 610 * NO_ERROR -- success 611 * none-zero failure code 612 *==========================================================================*/ 613 int32_t QCameraPicChannel::cancelPicture() 614 { 615 int32_t rc = m_camOps->cancel_super_buf_request(m_camHandle, m_handle); 616 return rc; 617 } 618 619 /*=========================================================================== 620 * FUNCTION : startAdvancedCapture 621 * 622 * DESCRIPTION: start advanced capture based on advanced capture type. 623 * 624 * PARAMETERS : 625 * @type : advanced capture type. 626 * 627 * RETURN : int32_t type of status 628 * NO_ERROR -- success 629 * none-zero failure code 630 *==========================================================================*/ 631 int32_t QCameraPicChannel::startAdvancedCapture(mm_camera_advanced_capture_t type) 632 { 633 int32_t rc = m_camOps->process_advanced_capture(m_camHandle, type, 634 m_handle, 1); 635 return rc; 636 } 637 638 /*=========================================================================== 639 * FUNCTION : QCameraVideoChannel 640 * 641 * DESCRIPTION: constructor of QCameraVideoChannel 642 * 643 * PARAMETERS : 644 * @cam_handle : camera handle 645 * @cam_ops : ptr to camera ops table 646 * 647 * RETURN : none 648 *==========================================================================*/ 649 QCameraVideoChannel::QCameraVideoChannel(uint32_t cam_handle, 650 mm_camera_ops_t *cam_ops) : 651 QCameraChannel(cam_handle, cam_ops) 652 { 653 } 654 655 /*=========================================================================== 656 * FUNCTION : QCameraVideoChannel 657 * 658 * DESCRIPTION: default constructor of QCameraVideoChannel 659 * 660 * PARAMETERS : none 661 * 662 * RETURN : none 663 *==========================================================================*/ 664 QCameraVideoChannel::QCameraVideoChannel() 665 { 666 } 667 668 /*=========================================================================== 669 * FUNCTION : ~QCameraVideoChannel 670 * 671 * DESCRIPTION: destructor of QCameraVideoChannel 672 * 673 * PARAMETERS : none 674 * 675 * RETURN : none 676 *==========================================================================*/ 677 QCameraVideoChannel::~QCameraVideoChannel() 678 { 679 } 680 681 /*=========================================================================== 682 * FUNCTION : releaseFrame 683 * 684 * DESCRIPTION: return video frame from app 685 * 686 * PARAMETERS : 687 * @opaque : ptr to video frame to be returned 688 * @isMetaData : if frame is a metadata or real frame 689 * 690 * RETURN : int32_t type of status 691 * NO_ERROR -- success 692 * none-zero failure code 693 *==========================================================================*/ 694 int32_t QCameraVideoChannel::releaseFrame(const void * opaque, bool isMetaData) 695 { 696 QCameraStream *pVideoStream = NULL; 697 for (int i = 0; i < m_numStreams; i++) { 698 if (mStreams[i] != NULL && mStreams[i]->isTypeOf(CAM_STREAM_TYPE_VIDEO)) { 699 pVideoStream = mStreams[i]; 700 break; 701 } 702 } 703 704 if (NULL == pVideoStream) { 705 ALOGE("%s: No video stream in the channel", __func__); 706 return BAD_VALUE; 707 } 708 709 int32_t rc = pVideoStream->bufDone(opaque, isMetaData); 710 return rc; 711 } 712 713 /*=========================================================================== 714 * FUNCTION : QCameraReprocessChannel 715 * 716 * DESCRIPTION: constructor of QCameraReprocessChannel 717 * 718 * PARAMETERS : 719 * @cam_handle : camera handle 720 * @cam_ops : ptr to camera ops table 721 * @pp_mask : post-proccess feature mask 722 * 723 * RETURN : none 724 *==========================================================================*/ 725 QCameraReprocessChannel::QCameraReprocessChannel(uint32_t cam_handle, 726 mm_camera_ops_t *cam_ops) : 727 QCameraChannel(cam_handle, cam_ops), 728 m_pSrcChannel(NULL) 729 { 730 memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles)); 731 } 732 733 /*=========================================================================== 734 * FUNCTION : QCameraReprocessChannel 735 * 736 * DESCRIPTION: default constructor of QCameraReprocessChannel 737 * 738 * PARAMETERS : none 739 * 740 * RETURN : none 741 *==========================================================================*/ 742 QCameraReprocessChannel::QCameraReprocessChannel() : 743 m_pSrcChannel(NULL) 744 { 745 } 746 747 /*=========================================================================== 748 * FUNCTION : ~QCameraReprocessChannel 749 * 750 * DESCRIPTION: destructor of QCameraReprocessChannel 751 * 752 * PARAMETERS : none 753 * 754 * RETURN : none 755 *==========================================================================*/ 756 QCameraReprocessChannel::~QCameraReprocessChannel() 757 { 758 } 759 760 /*=========================================================================== 761 * FUNCTION : addReprocStreamsFromSource 762 * 763 * DESCRIPTION: add reprocess streams from input source channel 764 * 765 * PARAMETERS : 766 * @allocator : stream related buffer allocator 767 * @config : pp feature configuration 768 * @pSrcChannel : ptr to input source channel that needs reprocess 769 * @minStreamBufNum: number of stream buffers needed 770 * @burstNum : number of burst captures needed 771 * @paddingInfo : padding information 772 * @param : reference to parameters 773 * @contStream : continous streaming mode or burst 774 * @offline : configure for offline reprocessing 775 * 776 * RETURN : int32_t type of status 777 * NO_ERROR -- success 778 * none-zero failure code 779 *==========================================================================*/ 780 int32_t QCameraReprocessChannel::addReprocStreamsFromSource(QCameraAllocator& allocator, 781 cam_pp_feature_config_t &config, 782 QCameraChannel *pSrcChannel, 783 uint8_t minStreamBufNum, 784 uint32_t burstNum, 785 cam_padding_info_t *paddingInfo, 786 QCameraParameters ¶m, 787 bool contStream, 788 bool offline) 789 { 790 int32_t rc = 0; 791 QCameraStream *pStream = NULL; 792 QCameraHeapMemory *pStreamInfoBuf = NULL; 793 cam_stream_info_t *streamInfo = NULL; 794 795 memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles)); 796 797 for (int i = 0; i < pSrcChannel->getNumOfStreams(); i++) { 798 pStream = pSrcChannel->getStreamByIndex(i); 799 if (pStream != NULL) { 800 if (pStream->isTypeOf(CAM_STREAM_TYPE_METADATA) || 801 pStream->isTypeOf(CAM_STREAM_TYPE_RAW)) { 802 // Skip metadata&raw for reprocess now because PP module cannot handle 803 // meta data&raw. May need furthur discussion if Imaginglib need meta data 804 continue; 805 } 806 807 if (pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) || 808 pStream->isTypeOf(CAM_STREAM_TYPE_PREVIEW)) { 809 // Skip postview: in non zsl case, dont want to send 810 // thumbnail through reprocess. 811 // Skip preview: for same reason for zsl case 812 continue; 813 } 814 815 if(pStream->isTypeOf(CAM_STREAM_TYPE_PREVIEW) || 816 pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) || 817 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_PREVIEW) || 818 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_POSTVIEW)) { 819 uint32_t feature_mask = config.feature_mask; 820 821 if ((feature_mask & ~CAM_QCOM_FEATURE_HDR) == 0 822 && param.isHDREnabled() 823 && !param.isHDRThumbnailProcessNeeded()) { 824 825 // Skip thumbnail stream reprocessing in HDR 826 // if only hdr is enabled 827 continue; 828 } 829 830 // skip thumbnail reprocessing if not needed 831 if (!param.needThumbnailReprocess(&feature_mask)) { 832 continue; 833 } 834 835 //Don't do WNR for thumbnail 836 feature_mask &= ~CAM_QCOM_FEATURE_DENOISE2D; 837 if(!feature_mask) { 838 // Skip thumbnail stream reprocessing since no other 839 //reprocessing is enabled. 840 continue; 841 } 842 } 843 844 pStreamInfoBuf = allocator.allocateStreamInfoBuf(CAM_STREAM_TYPE_OFFLINE_PROC); 845 if (pStreamInfoBuf == NULL) { 846 ALOGE("%s: no mem for stream info buf", __func__); 847 rc = NO_MEMORY; 848 break; 849 } 850 851 streamInfo = (cam_stream_info_t *)pStreamInfoBuf->getPtr(0); 852 memset(streamInfo, 0, sizeof(cam_stream_info_t)); 853 streamInfo->stream_type = CAM_STREAM_TYPE_OFFLINE_PROC; 854 rc = pStream->getFormat(streamInfo->fmt); 855 rc = pStream->getFrameDimension(streamInfo->dim); 856 if ( contStream ) { 857 streamInfo->streaming_mode = CAM_STREAMING_MODE_CONTINUOUS; 858 streamInfo->num_of_burst = 0; 859 } else { 860 streamInfo->streaming_mode = CAM_STREAMING_MODE_BURST; 861 streamInfo->num_of_burst = burstNum; 862 } 863 864 cam_stream_reproc_config_t rp_cfg; 865 memset(&rp_cfg, 0, sizeof(cam_stream_reproc_config_t)); 866 if (offline) { 867 cam_frame_len_offset_t offset; 868 memset(&offset, 0, sizeof(cam_frame_len_offset_t)); 869 870 rp_cfg.pp_type = CAM_OFFLINE_REPROCESS_TYPE; 871 pStream->getFormat(rp_cfg.offline.input_fmt); 872 pStream->getFrameDimension(rp_cfg.offline.input_dim); 873 pStream->getFrameOffset(offset); 874 rp_cfg.offline.input_buf_planes.plane_info = offset; 875 rp_cfg.offline.input_type = pStream->getMyType(); 876 //For input metadata + input buffer 877 rp_cfg.offline.num_of_bufs = 2; 878 } else { 879 rp_cfg.pp_type = CAM_ONLINE_REPROCESS_TYPE; 880 rp_cfg.online.input_stream_id = pStream->getMyServerID(); 881 rp_cfg.online.input_stream_type = pStream->getMyType(); 882 } 883 streamInfo->reprocess_config = rp_cfg; 884 streamInfo->reprocess_config.pp_feature_config = config; 885 886 if (!(pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) || 887 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT))) { 888 streamInfo->reprocess_config.pp_feature_config.feature_mask &= ~CAM_QCOM_FEATURE_CAC; 889 //Don't do WNR for thumbnail 890 streamInfo->reprocess_config.pp_feature_config.feature_mask &= ~CAM_QCOM_FEATURE_DENOISE2D; 891 892 if (param.isHDREnabled() 893 && !param.isHDRThumbnailProcessNeeded()){ 894 streamInfo->reprocess_config.pp_feature_config.feature_mask 895 &= ~CAM_QCOM_FEATURE_HDR; 896 } 897 } 898 899 if (streamInfo->reprocess_config.pp_feature_config.feature_mask & CAM_QCOM_FEATURE_ROTATION) { 900 if (streamInfo->reprocess_config.pp_feature_config.rotation == ROTATE_90 || 901 streamInfo->reprocess_config.pp_feature_config.rotation == ROTATE_270) { 902 // rotated by 90 or 270, need to switch width and height 903 int32_t temp = streamInfo->dim.height; 904 streamInfo->dim.height = streamInfo->dim.width; 905 streamInfo->dim.width = temp; 906 } 907 } 908 909 if (param.isZSLMode() && 910 (streamInfo->reprocess_config.online.input_stream_type == CAM_STREAM_TYPE_SNAPSHOT)) { 911 // ZSL mode snapshot need reprocess to do the flip 912 int flipMode = 913 param.getFlipMode(streamInfo->reprocess_config.online.input_stream_type); 914 if (flipMode > 0) { 915 streamInfo->reprocess_config.pp_feature_config.feature_mask |= CAM_QCOM_FEATURE_FLIP; 916 streamInfo->reprocess_config.pp_feature_config.flip = flipMode; 917 } 918 } 919 920 if(streamInfo->reprocess_config.pp_feature_config.feature_mask & CAM_QCOM_FEATURE_SCALE){ 921 //we only Scale Snapshot frame 922 if(pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT)){ 923 //also check whether rotation is needed 924 if((streamInfo->reprocess_config.pp_feature_config.feature_mask & CAM_QCOM_FEATURE_ROTATION) && 925 (streamInfo->reprocess_config.pp_feature_config.rotation == ROTATE_90 || 926 streamInfo->reprocess_config.pp_feature_config.rotation == ROTATE_270)){ 927 //need swap 928 streamInfo->dim.width = streamInfo->reprocess_config.pp_feature_config.scale_param.output_height; 929 streamInfo->dim.height = streamInfo->reprocess_config.pp_feature_config.scale_param.output_width; 930 }else{ 931 streamInfo->dim.width = streamInfo->reprocess_config.pp_feature_config.scale_param.output_width; 932 streamInfo->dim.height = streamInfo->reprocess_config.pp_feature_config.scale_param.output_height; 933 } 934 } 935 CDBG_HIGH("%s: stream width=%d, height=%d.", __func__, streamInfo->dim.width, streamInfo->dim.height); 936 } 937 938 // save source stream handler 939 mSrcStreamHandles[m_numStreams] = pStream->getMyHandle(); 940 941 // add reprocess stream 942 rc = addStream(allocator, 943 pStreamInfoBuf, minStreamBufNum, 944 paddingInfo, 945 NULL, NULL, false); 946 if (rc != NO_ERROR) { 947 ALOGE("%s: add reprocess stream failed, ret = %d", __func__, rc); 948 break; 949 } 950 } 951 } 952 953 if (rc == NO_ERROR) { 954 m_pSrcChannel = pSrcChannel; 955 } 956 return rc; 957 } 958 959 /*=========================================================================== 960 * FUNCTION : getStreamBySrouceHandle 961 * 962 * DESCRIPTION: find reprocess stream by its source stream handle 963 * 964 * PARAMETERS : 965 * @srcHandle : source stream handle 966 * 967 * RETURN : ptr to reprocess stream if found. NULL if not found 968 *==========================================================================*/ 969 QCameraStream * QCameraReprocessChannel::getStreamBySrouceHandle(uint32_t srcHandle) 970 { 971 QCameraStream *pStream = NULL; 972 973 for (int i = 0; i < m_numStreams; i++) { 974 if (mSrcStreamHandles[i] == srcHandle) { 975 pStream = mStreams[i]; 976 break; 977 } 978 } 979 980 return pStream; 981 } 982 983 /*=========================================================================== 984 * FUNCTION : stop 985 * 986 * DESCRIPTION: Unmap offline buffers and stop channel 987 * 988 * PARAMETERS : none 989 * 990 * RETURN : int32_t type of status 991 * NO_ERROR -- success 992 * none-zero failure code 993 *==========================================================================*/ 994 int32_t QCameraReprocessChannel::stop() 995 { 996 if (!mOfflineBuffers.empty()) { 997 QCameraStream *stream = NULL; 998 List<OfflineBuffer>::iterator it = mOfflineBuffers.begin(); 999 int error = NO_ERROR; 1000 for( ; it != mOfflineBuffers.end(); it++) { 1001 stream = (*it).stream; 1002 if (NULL != stream) { 1003 error = stream->unmapBuf((*it).type, 1004 (*it).index, 1005 -1); 1006 if (NO_ERROR != error) { 1007 ALOGE("%s: Error during offline buffer unmap %d", 1008 __func__, error); 1009 } 1010 } 1011 } 1012 mOfflineBuffers.clear(); 1013 } 1014 1015 return QCameraChannel::stop(); 1016 } 1017 1018 /*=========================================================================== 1019 * FUNCTION : doReprocessOffline 1020 * 1021 * DESCRIPTION: request to do offline reprocess on the frame 1022 * 1023 * PARAMETERS : 1024 * @frame : frame to be performed a reprocess 1025 * 1026 * RETURN : int32_t type of status 1027 * NO_ERROR -- success 1028 * none-zero failure code 1029 *==========================================================================*/ 1030 int32_t QCameraReprocessChannel::doReprocessOffline( 1031 mm_camera_super_buf_t *frame) 1032 { 1033 int32_t rc = 0; 1034 OfflineBuffer mappedBuffer; 1035 1036 if (m_numStreams < 1) { 1037 ALOGE("%s: No reprocess stream is created", __func__); 1038 return -1; 1039 } 1040 if (m_pSrcChannel == NULL) { 1041 ALOGE("%s: No source channel for reprocess", __func__); 1042 return -1; 1043 } 1044 1045 if (frame == NULL) { 1046 ALOGE("%s: Invalid source frame", __func__); 1047 return BAD_VALUE; 1048 } 1049 1050 // find meta data stream and index of meta data frame in the superbuf 1051 uint8_t meta_buf_index = -1; 1052 mm_camera_buf_def_t *meta_buf = NULL; 1053 QCameraStream *pStream = NULL; 1054 for (int i = 0; i < frame->num_bufs; i++) { 1055 pStream = m_pSrcChannel->getStreamByHandle(frame->bufs[i]->stream_id); 1056 if (pStream != NULL) { 1057 if (pStream->isTypeOf(CAM_STREAM_TYPE_METADATA)) { 1058 meta_buf = frame->bufs[i]; 1059 break; 1060 } 1061 } 1062 } 1063 1064 for (int i = 0; i < frame->num_bufs; i++) { 1065 pStream = getStreamBySrouceHandle(frame->bufs[i]->stream_id); 1066 if (pStream != NULL) { 1067 if (pStream->isTypeOf(CAM_STREAM_TYPE_METADATA)) { 1068 continue; 1069 } 1070 1071 meta_buf_index = 0; 1072 if (NULL != meta_buf) { 1073 rc = pStream->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF, 1074 meta_buf_index, 1075 -1, 1076 meta_buf->fd, 1077 meta_buf->frame_len); 1078 if (NO_ERROR != rc ) { 1079 ALOGE("%s : Error during metadata buffer mapping", 1080 __func__); 1081 break; 1082 } 1083 } 1084 mappedBuffer.index = meta_buf_index; 1085 mappedBuffer.stream = pStream; 1086 mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF; 1087 mOfflineBuffers.push_back(mappedBuffer); 1088 1089 int buf_index = 1; 1090 rc = pStream->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF, 1091 buf_index, 1092 -1, 1093 frame->bufs[i]->fd, 1094 frame->bufs[i]->frame_len); 1095 if (NO_ERROR != rc ) { 1096 ALOGE("%s : Error during reprocess input buffer mapping", 1097 __func__); 1098 break; 1099 } 1100 mappedBuffer.index = buf_index; 1101 mappedBuffer.stream = pStream; 1102 mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF; 1103 mOfflineBuffers.push_back(mappedBuffer); 1104 1105 cam_stream_parm_buffer_t param; 1106 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t)); 1107 param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS; 1108 param.reprocess.buf_index = buf_index; 1109 param.reprocess.frame_pp_config.uv_upsample = 1110 frame->bufs[i]->is_uv_subsampled; 1111 if (NULL != meta_buf) { 1112 // we have meta data sent together with reprocess frame 1113 param.reprocess.meta_present = 1; 1114 param.reprocess.meta_buf_index = meta_buf_index; 1115 uint32_t stream_id = frame->bufs[i]->stream_id; 1116 QCameraStream *srcStream = 1117 m_pSrcChannel->getStreamByHandle(stream_id); 1118 metadata_buffer_t *pMetaData = 1119 (metadata_buffer_t *)meta_buf->buffer; 1120 if (NULL != pMetaData) { 1121 cam_crop_data_t *crop = NULL; 1122 if (IS_META_AVAILABLE(CAM_INTF_META_CROP_DATA, pMetaData)) { 1123 crop = (cam_crop_data_t *) 1124 POINTER_OF_META(CAM_INTF_META_CROP_DATA, pMetaData); 1125 } 1126 1127 if ((NULL != crop) && (NULL != srcStream)) { 1128 for (int j = 0; j < MAX_NUM_STREAMS; j++) { 1129 if (crop->crop_info[j].stream_id == 1130 srcStream->getMyServerID()) { 1131 param.reprocess.frame_pp_config.crop.crop_enabled = 1; 1132 param.reprocess.frame_pp_config.crop.input_crop = 1133 crop->crop_info[j].crop; 1134 break; 1135 } 1136 } 1137 } 1138 } 1139 } 1140 rc = pStream->setParameter(param); 1141 if (rc != NO_ERROR) { 1142 ALOGE("%s: stream setParameter for reprocess failed", 1143 __func__); 1144 break; 1145 } 1146 } 1147 } 1148 return rc; 1149 } 1150 1151 /*=========================================================================== 1152 * FUNCTION : doReprocess 1153 * 1154 * DESCRIPTION: request to do a reprocess on the frame 1155 * 1156 * PARAMETERS : 1157 * @frame : frame to be performed a reprocess 1158 * 1159 * RETURN : int32_t type of status 1160 * NO_ERROR -- success 1161 * none-zero failure code 1162 *==========================================================================*/ 1163 int32_t QCameraReprocessChannel::doReprocess(mm_camera_super_buf_t *frame) 1164 { 1165 int32_t rc = 0; 1166 if (m_numStreams < 1) { 1167 ALOGE("%s: No reprocess stream is created", __func__); 1168 return -1; 1169 } 1170 if (m_pSrcChannel == NULL) { 1171 ALOGE("%s: No source channel for reprocess", __func__); 1172 return -1; 1173 } 1174 1175 // find meta data stream and index of meta data frame in the superbuf 1176 QCameraStream *pMetaStream = NULL; 1177 uint8_t meta_buf_index = 0; 1178 for (int i = 0; i < frame->num_bufs; i++) { 1179 QCameraStream *pStream = m_pSrcChannel->getStreamByHandle(frame->bufs[i]->stream_id); 1180 if (pStream != NULL) { 1181 if (pStream->isTypeOf(CAM_STREAM_TYPE_METADATA)) { 1182 meta_buf_index = frame->bufs[i]->buf_idx; 1183 pMetaStream = pStream; 1184 break; 1185 } 1186 } 1187 } 1188 1189 for (int i = 0; i < frame->num_bufs; i++) { 1190 QCameraStream *pStream = getStreamBySrouceHandle(frame->bufs[i]->stream_id); 1191 if (pStream != NULL) { 1192 if (pStream->isTypeOf(CAM_STREAM_TYPE_METADATA)) { 1193 // Skip metadata for reprocess now because PP module cannot handle meta data 1194 // May need furthur discussion if Imaginglib need meta data 1195 continue; 1196 } 1197 1198 if (pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) || 1199 pStream->isTypeOf(CAM_STREAM_TYPE_PREVIEW)) { 1200 // Skip postview: In non zsl case, dont want to send 1201 // thumbnail through reprocess. 1202 // Skip preview: for same reason in ZSL case 1203 continue; 1204 } 1205 1206 cam_stream_parm_buffer_t param; 1207 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t)); 1208 param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS; 1209 param.reprocess.buf_index = frame->bufs[i]->buf_idx; 1210 param.reprocess.frame_idx = frame->bufs[i]->frame_idx; 1211 param.reprocess.frame_pp_config.uv_upsample = frame->bufs[i]->is_uv_subsampled; 1212 if (pMetaStream != NULL) { 1213 // we have meta data frame bundled, sent together with reprocess frame 1214 param.reprocess.meta_present = 1; 1215 param.reprocess.meta_stream_handle = pMetaStream->getMyServerID(); 1216 param.reprocess.meta_buf_index = meta_buf_index; 1217 } 1218 rc = pStream->setParameter(param); 1219 if (rc != NO_ERROR) { 1220 ALOGE("%s: stream setParameter for reprocess failed", __func__); 1221 break; 1222 } 1223 } 1224 } 1225 return rc; 1226 } 1227 1228 /*=========================================================================== 1229 * FUNCTION : doReprocess 1230 * 1231 * DESCRIPTION: request to do a reprocess on the frame 1232 * 1233 * PARAMETERS : 1234 * @buf_fd : fd to the input buffer that needs reprocess 1235 * @buf_lenght : length of the input buffer 1236 * @ret_val : result of reprocess. 1237 * Example: Could be faceID in case of register face image. 1238 * 1239 * RETURN : int32_t type of status 1240 * NO_ERROR -- success 1241 * none-zero failure code 1242 *==========================================================================*/ 1243 int32_t QCameraReprocessChannel::doReprocess(int buf_fd, 1244 uint32_t buf_length, 1245 int32_t &ret_val) 1246 { 1247 int32_t rc = 0; 1248 if (m_numStreams < 1) { 1249 ALOGE("%s: No reprocess stream is created", __func__); 1250 return -1; 1251 } 1252 1253 uint32_t buf_idx = 0; 1254 for (int i = 0; i < m_numStreams; i++) { 1255 rc = mStreams[i]->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF, 1256 buf_idx, -1, 1257 buf_fd, buf_length); 1258 1259 if (rc == NO_ERROR) { 1260 cam_stream_parm_buffer_t param; 1261 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t)); 1262 param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS; 1263 param.reprocess.buf_index = buf_idx; 1264 rc = mStreams[i]->setParameter(param); 1265 if (rc == NO_ERROR) { 1266 ret_val = param.reprocess.ret_val; 1267 } 1268 mStreams[i]->unmapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF, 1269 buf_idx, -1); 1270 } 1271 } 1272 return rc; 1273 } 1274 1275 }; // namespace qcamera 1276