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 "QCameraChannel" 31 32 // System dependencies 33 #include <utils/Errors.h> 34 35 // Camera dependencies 36 #include "QCamera2HWI.h" 37 38 extern "C" { 39 #include "mm_camera_dbg.h" 40 } 41 42 using namespace android; 43 44 namespace qcamera { 45 46 /*=========================================================================== 47 * FUNCTION : QCameraChannel 48 * 49 * DESCRIPTION: constrcutor of QCameraChannel 50 * 51 * PARAMETERS : 52 * @cam_handle : camera handle 53 * @cam_ops : ptr to camera ops table 54 * 55 * RETURN : none 56 *==========================================================================*/ 57 QCameraChannel::QCameraChannel(uint32_t cam_handle, 58 mm_camera_ops_t *cam_ops) 59 { 60 m_camHandle = cam_handle; 61 m_camOps = cam_ops; 62 m_bIsActive = false; 63 m_bAllowDynBufAlloc = false; 64 mDualChannel = is_dual_camera_by_handle(cam_handle); 65 m_handle = 0; 66 mActiveHandle = 0; 67 } 68 69 /*=========================================================================== 70 * FUNCTION : QCameraChannel 71 * 72 * DESCRIPTION: default constrcutor of QCameraChannel 73 * 74 * PARAMETERS : none 75 * 76 * RETURN : none 77 *==========================================================================*/ 78 QCameraChannel::QCameraChannel() 79 { 80 m_camHandle = 0; 81 m_camOps = NULL; 82 m_bIsActive = false; 83 mDualChannel = 0; 84 m_handle = 0; 85 mActiveHandle = 0; 86 } 87 88 /*=========================================================================== 89 * FUNCTION : ~QCameraChannel 90 * 91 * DESCRIPTION: destructor of QCameraChannel 92 * 93 * PARAMETERS : none 94 * 95 * RETURN : none 96 *==========================================================================*/ 97 QCameraChannel::~QCameraChannel() 98 { 99 if (m_bIsActive) { 100 stop(); 101 } 102 for (size_t i = 0; i < mStreams.size(); i++) { 103 if (mStreams[i] != NULL) { 104 if (validate_handle(m_handle, mStreams[i]->getChannelHandle())) { 105 delete mStreams[i]; 106 } 107 } 108 } 109 mStreams.clear(); 110 m_camOps->delete_channel(m_camHandle, m_handle); 111 m_handle = 0; 112 mActiveHandle = 0; 113 } 114 115 /*=========================================================================== 116 * FUNCTION : deleteChannel 117 * 118 * DESCRIPTION: deletes a camera channel 119 * 120 * PARAMETERS : none 121 * 122 * RETURN : none 123 *==========================================================================*/ 124 void QCameraChannel::deleteChannel() 125 { 126 if (m_bIsActive) { 127 stop(); 128 } 129 for (size_t i = 0; i < mStreams.size(); i++) { 130 if ((mStreams[i] != NULL) && 131 (validate_handle(m_handle, mStreams[i]->getChannelHandle()))) { 132 mStreams[i]->deleteStream(); 133 } 134 } 135 m_camOps->delete_channel(m_camHandle, m_handle); 136 } 137 138 /*=========================================================================== 139 * FUNCTION : setStreamSyncCB 140 * 141 * DESCRIPTION: reg callback function to stream of stream type 142 * 143 * PARAMETERS : 144 * @stream_type : Stream type for which callback needs to be registered. 145 * @stream_cb : Callback function 146 147 * RETURN : int32_t type of status 148 * NO_ERROR -- success 149 * non-zero failure code 150 *==========================================================================*/ 151 int32_t QCameraChannel::setStreamSyncCB (cam_stream_type_t stream_type, 152 stream_cb_routine stream_cb) 153 { 154 int32_t rc = UNKNOWN_ERROR; 155 for (size_t i = 0; i < mStreams.size(); i++) { 156 if ((mStreams[i] != NULL) && (stream_type == mStreams[i]->getMyType())) { 157 rc = mStreams[i]->setSyncDataCB(stream_cb); 158 break; 159 } 160 } 161 return rc; 162 } 163 164 /*=========================================================================== 165 * FUNCTION : init 166 * 167 * DESCRIPTION: initialization of channel 168 * 169 * PARAMETERS : 170 * @attr : channel bundle attribute setting 171 * @dataCB : data notify callback 172 * @userData: user data ptr 173 * 174 * RETURN : int32_t type of status 175 * NO_ERROR -- success 176 * none-zero failure code 177 *==========================================================================*/ 178 int32_t QCameraChannel::init(mm_camera_channel_attr_t *attr, 179 mm_camera_buf_notify_t dataCB, 180 void *userData) 181 { 182 m_handle = m_camOps->add_channel(m_camHandle, 183 attr, 184 dataCB, 185 userData); 186 if (m_handle == 0) { 187 LOGE("Add channel failed"); 188 return UNKNOWN_ERROR; 189 } 190 mActiveHandle = m_handle; 191 mActiveCamera = MM_CAMERA_TYPE_MAIN; 192 if (isDualChannel()) { 193 mActiveCamera |= MM_CAMERA_TYPE_AUX; 194 } 195 return NO_ERROR; 196 } 197 198 /*=========================================================================== 199 * FUNCTION : getChHandleForStream 200 * 201 * DESCRIPTION: return actual channel handle based on use case per stream 202 * 203 * PARAMETERS : 204 * @ch_type : type of channel 205 * 206 * RETURN : number of buffers needed 207 * NOTE : Based on the use cases and auxillary camera type, 208 we can decide channel handle for streams. 209 Incase, we want to avoid any stream for auxillary camera, 210 we can decide here. 211 *==========================================================================*/ 212 uint32_t QCameraChannel::getChHandleForStream(cam_stream_type_t stream_type) 213 { 214 uint32_t handle = m_handle; 215 if (!mDualChannel) { 216 return m_handle; 217 } 218 219 /*Based on the use case, decide channel handle for channel*/ 220 switch (stream_type) { 221 case CAM_STREAM_TYPE_PREVIEW: 222 case CAM_STREAM_TYPE_SNAPSHOT: 223 case CAM_STREAM_TYPE_VIDEO: 224 case CAM_STREAM_TYPE_METADATA: 225 case CAM_STREAM_TYPE_ANALYSIS: 226 case CAM_STREAM_TYPE_CALLBACK: 227 handle = m_handle; 228 break; 229 case CAM_STREAM_TYPE_POSTVIEW: 230 case CAM_STREAM_TYPE_RAW: 231 case CAM_STREAM_TYPE_OFFLINE_PROC: 232 case CAM_STREAM_TYPE_DEFAULT: 233 case CAM_STREAM_TYPE_MAX: 234 default: 235 handle = get_main_camera_handle(m_handle); 236 break; 237 } 238 return handle; 239 } 240 241 /*=========================================================================== 242 * FUNCTION : addStream 243 * 244 * DESCRIPTION: add a stream into channel 245 * 246 * PARAMETERS : 247 * @allocator : stream related buffer allocator 248 * @streamInfoBuf : ptr to buf that contains stream info 249 * @miscBuf : ptr to buf that contains misc buffers 250 * @minStreamBufNum: number of stream buffers needed 251 * @paddingInfo : padding information 252 * @stream_cb : stream data notify callback 253 * @userdata : user data ptr 254 * @bDynAllocBuf : flag indicating if allow allocate buffers in 2 steps 255 * @online_rotation: rotation applied online 256 * 257 * RETURN : int32_t type of status 258 * NO_ERROR -- success 259 * none-zero failure code 260 *==========================================================================*/ 261 int32_t QCameraChannel::addStream(QCameraAllocator &allocator, 262 QCameraHeapMemory *streamInfoBuf, QCameraHeapMemory *miscBuf, 263 cam_padding_info_t *paddingInfo, stream_cb_routine stream_cb, 264 void *userdata, bool bDynAllocBuf, bool bDeffAlloc, 265 cam_rotation_t online_rotation) 266 { 267 int32_t rc = NO_ERROR; 268 if (mStreams.size() >= MAX_STREAM_NUM_IN_BUNDLE) { 269 LOGE("stream number (%zu) exceeds max limit (%d)", 270 mStreams.size(), MAX_STREAM_NUM_IN_BUNDLE); 271 if (streamInfoBuf != NULL) { 272 streamInfoBuf->deallocate(); 273 delete streamInfoBuf; 274 streamInfoBuf = NULL; 275 } 276 return BAD_VALUE; 277 } 278 QCameraStream *pStream = new QCameraStream(allocator, 279 m_camHandle, m_handle, m_camOps, paddingInfo, bDeffAlloc, 280 online_rotation); 281 if (pStream == NULL) { 282 LOGE("No mem for Stream"); 283 if (streamInfoBuf != NULL) { 284 streamInfoBuf->deallocate(); 285 delete streamInfoBuf; 286 streamInfoBuf = NULL; 287 } 288 return NO_MEMORY; 289 } 290 291 rc = pStream->init(streamInfoBuf, miscBuf, 292 stream_cb, userdata, bDynAllocBuf); 293 if (rc == 0) { 294 Mutex::Autolock lock(mStreamLock); 295 mStreams.add(pStream); 296 } else { 297 delete pStream; 298 } 299 return rc; 300 } 301 302 /*=========================================================================== 303 * FUNCTION : linkStream 304 * 305 * DESCRIPTION: link a stream into channel 306 * 307 * PARAMETERS : 308 * @ch : Channel which the stream belongs to 309 * @stream : Stream which needs to be linked 310 * 311 * RETURN : int32_t type of status 312 * NO_ERROR -- success 313 * none-zero failure code 314 *==========================================================================*/ 315 int32_t QCameraChannel::linkStream(QCameraChannel *ch, QCameraStream *stream) 316 { 317 int32_t rc = NO_ERROR; 318 319 if ((0 == m_handle) || (NULL == ch) || (NULL == stream)) { 320 return NO_INIT; 321 } 322 323 int32_t handle = m_camOps->link_stream(m_camHandle, 324 ch->getMyHandle(), 325 stream->getMyHandle(), 326 m_handle); 327 if (0 == handle) { 328 LOGE("Linking of stream failed"); 329 rc = INVALID_OPERATION; 330 } else { 331 Mutex::Autolock lock(mStreamLock); 332 mStreams.add(stream); 333 } 334 335 return rc; 336 } 337 338 /*=========================================================================== 339 * FUNCTION : start 340 * 341 * DESCRIPTION: start channel, which will start all streams belong to this channel 342 * 343 * PARAMETERS : None 344 * 345 * RETURN : int32_t type of status 346 * NO_ERROR -- success 347 * none-zero failure code 348 *==========================================================================*/ 349 int32_t QCameraChannel::start() 350 { 351 int32_t rc = NO_ERROR; 352 353 if(m_bIsActive) { 354 LOGW("Attempt to start active channel"); 355 return rc; 356 } 357 358 // there is more than one stream in the channel 359 // we need to notify mctl that all streams in this channel need to be bundled 360 for (size_t i = 0; i < mStreams.size(); i++) { 361 if ((mStreams[i] != NULL) && 362 (validate_handle(m_handle, mStreams[i]->getChannelHandle()))) { 363 mStreams[i]->setBundleInfo(); 364 } 365 } 366 367 368 for (size_t i = 0; i < mStreams.size(); i++) { 369 if ((mStreams[i] != NULL) && 370 (validate_handle(m_handle, mStreams[i]->getChannelHandle()))) { 371 mStreams[i]->start(); 372 } 373 } 374 rc = m_camOps->start_channel(m_camHandle, m_handle); 375 376 if (rc != NO_ERROR) { 377 for (size_t i = 0; i < mStreams.size(); i++) { 378 if ((mStreams[i] != NULL) && 379 (validate_handle(m_handle, mStreams[i]->getChannelHandle()))) { 380 mStreams[i]->stop(); 381 } 382 } 383 } else { 384 m_bIsActive = true; 385 for (size_t i = 0; i < mStreams.size(); i++) { 386 if (mStreams[i] != NULL) { 387 mStreams[i]->cond_signal(); 388 } 389 } 390 } 391 392 return rc; 393 } 394 395 /*=========================================================================== 396 * FUNCTION : stop 397 * 398 * DESCRIPTION: stop a channel, which will stop all streams belong to this channel 399 * 400 * PARAMETERS : none 401 * 402 * RETURN : int32_t type of status 403 * NO_ERROR -- success 404 * none-zero failure code 405 *==========================================================================*/ 406 int32_t QCameraChannel::stop() 407 { 408 int32_t rc = NO_ERROR; 409 size_t i = 0; 410 411 if (!m_bIsActive) { 412 return NO_INIT; 413 } 414 415 { 416 Mutex::Autolock lock(mStreamLock); 417 while(i < mStreams.size()) { 418 if (mStreams[i] != NULL) { 419 if (validate_handle(m_handle, mStreams[i]->getChannelHandle())) { 420 mStreams[i]->stop(); 421 i++; 422 } else { 423 // Remove linked stream from stream list 424 mStreams.removeAt(i); 425 } 426 } 427 } 428 } 429 430 rc = m_camOps->stop_channel(m_camHandle, m_handle); 431 432 m_bIsActive = false; 433 return rc; 434 } 435 436 /*=========================================================================== 437 * FUNCTION : bufDone 438 * 439 * DESCRIPTION: return a stream buf back to kernel 440 * 441 * PARAMETERS : 442 * @recvd_frame : stream buf frame to be returned 443 * 444 * RETURN : int32_t type of status 445 * NO_ERROR -- success 446 * none-zero failure code 447 *==========================================================================*/ 448 int32_t QCameraChannel::bufDone(mm_camera_super_buf_t *recvd_frame) 449 { 450 int32_t rc = NO_ERROR; 451 for (uint32_t i = 0; i < recvd_frame->num_bufs; i++) { 452 if (recvd_frame->bufs[i] != NULL) { 453 for (uint32_t j = 0; j < mStreams.size(); j++) { 454 if (mStreams[j] != NULL && 455 (validate_handle(mStreams[j]->getMyHandle(), 456 recvd_frame->bufs[i]->stream_id))) { 457 rc = mStreams[j]->bufDone(recvd_frame->bufs[i]->buf_idx); 458 break; // break loop j 459 } 460 } 461 } 462 } 463 464 return rc; 465 } 466 467 /*=========================================================================== 468 * FUNCTION : bufDone 469 * 470 * DESCRIPTION: return specified buffer from super buffer to kernel 471 * 472 * PARAMETERS : 473 * @recvd_frame : stream buf frame to be returned 474 * @stream_id : stream ID of the buffer to be released 475 * 476 * RETURN : int32_t type of status 477 * NO_ERROR -- success 478 * none-zero failure code 479 *==========================================================================*/ 480 int32_t QCameraChannel::bufDone(mm_camera_super_buf_t *recvd_frame, uint32_t stream_id) 481 { 482 int32_t rc = NO_ERROR; 483 int32_t index; 484 for (int32_t i = 0; i < (int32_t)recvd_frame->num_bufs; i++) { 485 index = -1; 486 if ((recvd_frame->bufs[i] != NULL) && 487 (recvd_frame->bufs[i]->stream_id == stream_id)) { 488 for (uint32_t j = 0; j < mStreams.size(); j++) { 489 if ((mStreams[j] != NULL) && 490 (validate_handle(mStreams[j]->getMyHandle(), 491 recvd_frame->bufs[i]->stream_id))) { 492 rc = mStreams[j]->bufDone(recvd_frame->bufs[i]->buf_idx); 493 index = i; 494 break; // break loop j 495 } 496 } 497 if ((index >= 0) && (index < (int32_t)recvd_frame->num_bufs)) { 498 for (int32_t j = index; j < (int32_t)(recvd_frame->num_bufs - 1); j++) { 499 recvd_frame->bufs[j] = recvd_frame->bufs[j + 1]; 500 } 501 recvd_frame->num_bufs--; 502 i--; 503 } 504 } 505 } 506 507 return rc; 508 } 509 510 /*=========================================================================== 511 * FUNCTION : processZoomDone 512 * 513 * DESCRIPTION: process zoom done event 514 * 515 * PARAMETERS : 516 * @previewWindoe : ptr to preview window ops table, needed to set preview 517 * crop information 518 * @crop_info : crop info as a result of zoom operation 519 * 520 * RETURN : int32_t type of status 521 * NO_ERROR -- success 522 * none-zero failure code 523 *==========================================================================*/ 524 int32_t QCameraChannel::processZoomDone(preview_stream_ops_t *previewWindow, 525 cam_crop_data_t &crop_info) 526 { 527 int32_t rc = NO_ERROR; 528 Mutex::Autolock lock(mStreamLock); 529 for (size_t i = 0; i < mStreams.size(); i++) { 530 if ((mStreams[i] != NULL) && 531 (validate_handle(m_handle, mStreams[i]->getChannelHandle()))) { 532 rc = mStreams[i]->processZoomDone(previewWindow, crop_info); 533 } 534 } 535 return rc; 536 } 537 538 /*=========================================================================== 539 * FUNCTION : getStreamByHandle 540 * 541 * DESCRIPTION: return stream object by stream handle 542 * 543 * PARAMETERS : 544 * @streamHandle : stream handle 545 * 546 * RETURN : stream object. NULL if not found 547 *==========================================================================*/ 548 QCameraStream *QCameraChannel::getStreamByHandle(uint32_t streamHandle) 549 { 550 for (size_t i = 0; i < mStreams.size(); i++) { 551 if (mStreams[i] != NULL && 552 (validate_handle(mStreams[i]->getMyHandle(), streamHandle))) { 553 return mStreams[i]; 554 } 555 } 556 return NULL; 557 } 558 559 /*=========================================================================== 560 * FUNCTION : getStreamByServerID 561 * 562 * DESCRIPTION: return stream object by stream server ID from daemon 563 * 564 * PARAMETERS : 565 * @serverID : stream server ID 566 * 567 * RETURN : stream object. NULL if not found 568 *==========================================================================*/ 569 QCameraStream *QCameraChannel::getStreamByServerID(uint32_t serverID) 570 { 571 for (size_t i = 0; i < mStreams.size(); i++) { 572 if (mStreams[i] != NULL && mStreams[i]->getMyServerID() == serverID) { 573 return mStreams[i]; 574 } 575 } 576 return NULL; 577 } 578 579 /*=========================================================================== 580 * FUNCTION : getStreamByIndex 581 * 582 * DESCRIPTION: return stream object by index of streams in the channel 583 * 584 * PARAMETERS : 585 * @index : index of stream in the channel 586 * 587 * RETURN : stream object. NULL if not found 588 *==========================================================================*/ 589 QCameraStream *QCameraChannel::getStreamByIndex(uint32_t index) 590 { 591 if (index >= MAX_STREAM_NUM_IN_BUNDLE) { 592 return NULL; 593 } 594 595 if (index < mStreams.size()) { 596 return mStreams[index]; 597 } 598 return NULL; 599 } 600 601 /*=========================================================================== 602 * FUNCTION : UpdateStreamBasedParameters 603 * 604 * DESCRIPTION: update any stream based settings from parameters 605 * 606 * PARAMETERS : 607 * @param : reference to parameters object 608 * 609 * RETURN : int32_t type of status 610 * NO_ERROR -- success 611 * none-zero failure code 612 *==========================================================================*/ 613 int32_t QCameraChannel::UpdateStreamBasedParameters(QCameraParametersIntf ¶m) 614 { 615 int32_t rc = NO_ERROR; 616 Mutex::Autolock lock(mStreamLock); 617 if (param.isPreviewFlipChanged()) { 618 // try to find preview stream 619 for (size_t i = 0; i < mStreams.size(); i++) { 620 if ((mStreams[i] != NULL) && 621 (validate_handle(m_handle, mStreams[i]->getChannelHandle())) && 622 (mStreams[i]->isTypeOf(CAM_STREAM_TYPE_PREVIEW) || 623 (mStreams[i]->isOrignalTypeOf(CAM_STREAM_TYPE_PREVIEW))) ) { 624 cam_stream_parm_buffer_t param_buf; 625 memset(¶m_buf, 0, sizeof(cam_stream_parm_buffer_t)); 626 param_buf.type = CAM_STREAM_PARAM_TYPE_SET_FLIP; 627 param_buf.flipInfo.flip_mask = 628 (uint32_t)param.getFlipMode(CAM_STREAM_TYPE_PREVIEW); 629 rc = mStreams[i]->setParameter(param_buf); 630 if (rc != NO_ERROR) { 631 LOGW("set preview stream flip failed"); 632 } 633 } 634 } 635 } 636 if (param.isVideoFlipChanged()) { 637 // try to find video stream 638 for (size_t i = 0; i < mStreams.size(); i++) { 639 if ((mStreams[i] != NULL) && 640 (validate_handle(m_handle, mStreams[i]->getChannelHandle())) && 641 (mStreams[i]->isTypeOf(CAM_STREAM_TYPE_VIDEO) || 642 (mStreams[i]->isOrignalTypeOf(CAM_STREAM_TYPE_VIDEO))) ) { 643 cam_stream_parm_buffer_t param_buf; 644 memset(¶m_buf, 0, sizeof(cam_stream_parm_buffer_t)); 645 param_buf.type = CAM_STREAM_PARAM_TYPE_SET_FLIP; 646 param_buf.flipInfo.flip_mask = 647 (uint32_t)param.getFlipMode(CAM_STREAM_TYPE_VIDEO); 648 rc = mStreams[i]->setParameter(param_buf); 649 if (rc != NO_ERROR) { 650 LOGW("set video stream flip failed"); 651 } 652 } 653 } 654 } 655 if (param.isSnapshotFlipChanged()) { 656 // try to find snapshot/postview stream 657 for (size_t i = 0; i < mStreams.size(); i++) { 658 if (mStreams[i] != NULL && 659 (validate_handle(m_handle, mStreams[i]->getChannelHandle())) && 660 (mStreams[i]->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) || 661 mStreams[i]->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT) || 662 mStreams[i]->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) || 663 mStreams[i]->isOrignalTypeOf(CAM_STREAM_TYPE_POSTVIEW) ) ) { 664 cam_stream_parm_buffer_t param_buf; 665 memset(¶m_buf, 0, sizeof(cam_stream_parm_buffer_t)); 666 param_buf.type = CAM_STREAM_PARAM_TYPE_SET_FLIP; 667 param_buf.flipInfo.flip_mask = 668 (uint32_t)param.getFlipMode(CAM_STREAM_TYPE_SNAPSHOT); 669 rc = mStreams[i]->setParameter(param_buf); 670 if (rc != NO_ERROR) { 671 LOGW("set snapshot stream flip failed"); 672 } 673 } 674 } 675 } 676 return rc; 677 } 678 679 /*=========================================================================== 680 * FUNCTION : processCameraControl 681 * 682 * DESCRIPTION: Suspend and resume camera 683 * 684 * PARAMETERS : 685 * @camState : Camera start. MAIN/AUX/MAIN&AUX 686 * 687 * RETURN : int32_t type of status 688 * NO_ERROR -- success 689 * none-zero failure code 690 *==========================================================================*/ 691 int32_t QCameraChannel::processCameraControl(uint32_t camState) 692 { 693 int32_t ret = NO_ERROR; 694 695 for (size_t i = 0; i < mStreams.size(); i++) { 696 if (mStreams[i] != NULL && mStreams[i]->isDualStream()) { 697 ret = mStreams[i]->processCameraControl(camState); 698 if (ret != NO_ERROR) { 699 LOGE("Stream Switch Failed"); 700 break; 701 } 702 } 703 } 704 705 if (ret == NO_ERROR) { 706 if (camState == MM_CAMERA_TYPE_MAIN) { 707 mActiveHandle = get_main_camera_handle(m_handle); 708 } else if (camState == MM_CAMERA_TYPE_AUX) { 709 mActiveHandle = get_aux_camera_handle(m_handle); 710 } else { 711 mActiveHandle = m_handle; 712 } 713 } 714 mActiveCamera = camState; 715 return ret; 716 } 717 718 /*=========================================================================== 719 * FUNCTION : switchChannelCb 720 * 721 * DESCRIPTION: switch channel's in case of dual camera 722 * 723 * PARAMETERS : 724 * 725 * RETURN : int32_t type of status 726 * NO_ERROR -- success 727 * none-zero failure code 728 *==========================================================================*/ 729 int32_t QCameraChannel::switchChannelCb() 730 { 731 int32_t ret = NO_ERROR; 732 733 for (size_t i = 0; i < mStreams.size(); i++) { 734 if (mStreams[i] != NULL && mStreams[i]->isDualStream()) { 735 ret = mStreams[i]->switchStreamCb(); 736 if (ret != NO_ERROR) { 737 LOGE("Stream Switch Failed"); 738 break; 739 } 740 } 741 } 742 743 if (ret == NO_ERROR && mActiveCamera == MM_CAMERA_DUAL_CAM) { 744 if (get_aux_camera_handle(m_handle) 745 == mActiveHandle) { 746 mActiveHandle = get_main_camera_handle(m_handle); 747 } else if (get_main_camera_handle(m_handle) 748 == mActiveHandle) { 749 mActiveHandle = get_aux_camera_handle(m_handle); 750 } else { 751 mActiveHandle = m_handle; 752 } 753 } 754 return ret; 755 } 756 757 /*=========================================================================== 758 * FUNCTION : QCameraPicChannel 759 * 760 * DESCRIPTION: constructor of QCameraPicChannel 761 * 762 * PARAMETERS : 763 * @cam_handle : camera handle 764 * @cam_ops : ptr to camera ops table 765 * 766 * RETURN : none 767 *==========================================================================*/ 768 QCameraPicChannel::QCameraPicChannel(uint32_t cam_handle, 769 mm_camera_ops_t *cam_ops) : 770 QCameraChannel(cam_handle, cam_ops) 771 { 772 m_bAllowDynBufAlloc = true; 773 } 774 775 /*=========================================================================== 776 * FUNCTION : QCameraPicChannel 777 * 778 * DESCRIPTION: default constructor of QCameraPicChannel 779 * 780 * PARAMETERS : none 781 * 782 * RETURN : none 783 *==========================================================================*/ 784 QCameraPicChannel::QCameraPicChannel() 785 { 786 m_bAllowDynBufAlloc = true; 787 } 788 789 /*=========================================================================== 790 * FUNCTION : ~QCameraPicChannel 791 * 792 * DESCRIPTION: destructor of QCameraPicChannel 793 * 794 * PARAMETERS : none 795 * 796 * RETURN : none 797 *==========================================================================*/ 798 QCameraPicChannel::~QCameraPicChannel() 799 { 800 } 801 802 /*=========================================================================== 803 * FUNCTION : takePicture 804 * 805 * DESCRIPTION: send request for queued snapshot frames 806 * 807 * PARAMETERS : 808 * @buf : request buf info 809 * 810 * RETURN : int32_t type of status 811 * NO_ERROR -- success 812 * none-zero failure code 813 *==========================================================================*/ 814 int32_t QCameraPicChannel::takePicture (mm_camera_req_buf_t *buf) 815 { 816 int32_t rc = m_camOps->request_super_buf(m_camHandle, mActiveHandle, buf); 817 return rc; 818 } 819 820 /*=========================================================================== 821 * FUNCTION : cancelPicture 822 * 823 * DESCRIPTION: cancel request for queued snapshot frames 824 * 825 * PARAMETERS : none 826 * 827 * RETURN : int32_t type of status 828 * NO_ERROR -- success 829 * none-zero failure code 830 *==========================================================================*/ 831 int32_t QCameraPicChannel::cancelPicture() 832 { 833 int32_t rc = m_camOps->cancel_super_buf_request(m_camHandle, m_handle); 834 return rc; 835 } 836 837 /*=========================================================================== 838 * FUNCTION : stopAdvancedCapture 839 * 840 * DESCRIPTION: stop advanced capture based on advanced capture type. 841 * 842 * PARAMETERS : 843 * @type : advanced capture type. 844 * 845 * RETURN : int32_t type of status 846 * NO_ERROR -- success 847 * none-zero failure code 848 *==========================================================================*/ 849 int32_t QCameraPicChannel::stopAdvancedCapture(mm_camera_advanced_capture_t type) 850 { 851 int32_t rc = m_camOps->process_advanced_capture(m_camHandle, 852 m_handle, type, 0, NULL); 853 return rc; 854 } 855 856 /*=========================================================================== 857 * FUNCTION : startAdvancedCapture 858 * 859 * DESCRIPTION: start advanced capture based on advanced capture type. 860 * 861 * PARAMETERS : 862 * @type : advanced capture type. 863 * @config: advance capture config 864 * 865 * RETURN : int32_t type of status 866 * NO_ERROR -- success 867 * none-zero failure code 868 *==========================================================================*/ 869 int32_t QCameraPicChannel::startAdvancedCapture(mm_camera_advanced_capture_t type, 870 cam_capture_frame_config_t *config) 871 { 872 int32_t rc = NO_ERROR; 873 874 rc = m_camOps->process_advanced_capture(m_camHandle, mActiveHandle, type, 875 1, config); 876 return rc; 877 } 878 879 /*=========================================================================== 880 * FUNCTION : flushSuperbuffer 881 * 882 * DESCRIPTION: flush the all superbuffer frames. 883 * 884 * PARAMETERS : 885 * @frame_idx : frame index of focused frame 886 * 887 * RETURN : int32_t type of status 888 * NO_ERROR -- success 889 * none-zero failure code 890 *==========================================================================*/ 891 int32_t QCameraPicChannel::flushSuperbuffer(uint32_t frame_idx) 892 { 893 int32_t rc = m_camOps->flush_super_buf_queue(m_camHandle, m_handle, frame_idx); 894 return rc; 895 } 896 897 /*=========================================================================== 898 * FUNCTION : QCameraVideoChannel 899 * 900 * DESCRIPTION: constructor of QCameraVideoChannel 901 * 902 * PARAMETERS : 903 * @cam_handle : camera handle 904 * @cam_ops : ptr to camera ops table 905 * 906 * RETURN : none 907 *==========================================================================*/ 908 QCameraVideoChannel::QCameraVideoChannel(uint32_t cam_handle, 909 mm_camera_ops_t *cam_ops) : 910 QCameraChannel(cam_handle, cam_ops) 911 { 912 } 913 914 /*=========================================================================== 915 * FUNCTION : QCameraVideoChannel 916 * 917 * DESCRIPTION: default constructor of QCameraVideoChannel 918 * 919 * PARAMETERS : none 920 * 921 * RETURN : none 922 *==========================================================================*/ 923 QCameraVideoChannel::QCameraVideoChannel() 924 { 925 } 926 927 /*=========================================================================== 928 * FUNCTION : ~QCameraVideoChannel 929 * 930 * DESCRIPTION: destructor of QCameraVideoChannel 931 * 932 * PARAMETERS : none 933 * 934 * RETURN : none 935 *==========================================================================*/ 936 QCameraVideoChannel::~QCameraVideoChannel() 937 { 938 } 939 940 /*=========================================================================== 941 * FUNCTION : takePicture 942 * 943 * DESCRIPTION: send request for queued snapshot frames 944 * 945 * PARAMETERS : 946 * @mm_camera_req_buf_t : request buf info 947 * 948 * RETURN : int32_t type of status 949 * NO_ERROR -- success 950 * none-zero failure code 951 *==========================================================================*/ 952 int32_t QCameraVideoChannel::takePicture(mm_camera_req_buf_t *buf) 953 { 954 int32_t rc = m_camOps->request_super_buf(m_camHandle, mActiveHandle, buf); 955 return rc; 956 } 957 958 /*=========================================================================== 959 * FUNCTION : cancelPicture 960 * 961 * DESCRIPTION: cancel request for queued snapshot frames 962 * 963 * PARAMETERS : none 964 * 965 * RETURN : int32_t type of status 966 * NO_ERROR -- success 967 * none-zero failure code 968 *==========================================================================*/ 969 int32_t QCameraVideoChannel::cancelPicture() 970 { 971 int32_t rc = m_camOps->cancel_super_buf_request(m_camHandle, m_handle); 972 return rc; 973 } 974 975 /*=========================================================================== 976 * FUNCTION : releaseFrame 977 * 978 * DESCRIPTION: return video frame from app 979 * 980 * PARAMETERS : 981 * @opaque : ptr to video frame to be returned 982 * @isMetaData : if frame is a metadata or real frame 983 * 984 * RETURN : int32_t type of status 985 * NO_ERROR -- success 986 * none-zero failure code 987 *==========================================================================*/ 988 int32_t QCameraVideoChannel::releaseFrame(const void * opaque, bool isMetaData) 989 { 990 QCameraStream *pVideoStream = NULL; 991 for (size_t i = 0; i < mStreams.size(); i++) { 992 if (mStreams[i] != NULL && mStreams[i]->isTypeOf(CAM_STREAM_TYPE_VIDEO)) { 993 pVideoStream = mStreams[i]; 994 break; 995 } 996 } 997 998 if (NULL == pVideoStream) { 999 LOGE("No video stream in the channel"); 1000 return BAD_VALUE; 1001 } 1002 1003 int32_t rc = pVideoStream->bufDone(opaque, isMetaData); 1004 return rc; 1005 } 1006 1007 /*=========================================================================== 1008 * FUNCTION : QCameraReprocessChannel 1009 * 1010 * DESCRIPTION: constructor of QCameraReprocessChannel 1011 * 1012 * PARAMETERS : 1013 * @cam_handle : camera handle 1014 * @cam_ops : ptr to camera ops table 1015 * 1016 * RETURN : none 1017 *==========================================================================*/ 1018 QCameraReprocessChannel::QCameraReprocessChannel(uint32_t cam_handle, 1019 mm_camera_ops_t *cam_ops) : 1020 QCameraChannel(cam_handle, cam_ops), 1021 m_pSrcChannel(NULL), 1022 mPassCount(0) 1023 { 1024 memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles)); 1025 } 1026 1027 /*=========================================================================== 1028 * FUNCTION : QCameraReprocessChannel 1029 * 1030 * DESCRIPTION: default constructor of QCameraReprocessChannel 1031 * 1032 * PARAMETERS : none 1033 * 1034 * RETURN : none 1035 *==========================================================================*/ 1036 QCameraReprocessChannel::QCameraReprocessChannel() : 1037 m_pSrcChannel(NULL), 1038 mPassCount(0) 1039 { 1040 } 1041 1042 /*=========================================================================== 1043 * FUNCTION : ~QCameraReprocessChannel 1044 * 1045 * DESCRIPTION: destructor of QCameraReprocessChannel 1046 * 1047 * PARAMETERS : none 1048 * 1049 * RETURN : none 1050 *==========================================================================*/ 1051 QCameraReprocessChannel::~QCameraReprocessChannel() 1052 { 1053 } 1054 1055 /*=========================================================================== 1056 * FUNCTION : addReprocStreamsFromSource 1057 * 1058 * DESCRIPTION: add reprocess streams from input source channel 1059 * 1060 * PARAMETERS : 1061 * @allocator : stream related buffer allocator 1062 * @featureConfig : pp feature configuration 1063 * @pSrcChannel : ptr to input source channel that needs reprocess 1064 * @minStreamBufNum: number of stream buffers needed 1065 * @burstNum : number of burst captures needed 1066 * @paddingInfo : padding information 1067 * @param : reference to parameters 1068 * @contStream : continous streaming mode or burst 1069 * @offline : configure for offline reprocessing 1070 * 1071 * RETURN : int32_t type of status 1072 * NO_ERROR -- success 1073 * none-zero failure code 1074 *==========================================================================*/ 1075 int32_t QCameraReprocessChannel::addReprocStreamsFromSource( 1076 QCameraAllocator& allocator, cam_pp_feature_config_t &featureConfig, 1077 QCameraChannel *pSrcChannel, uint8_t minStreamBufNum, uint8_t burstNum, 1078 cam_padding_info_t *paddingInfo, QCameraParametersIntf ¶m, bool contStream, 1079 bool offline) 1080 { 1081 int32_t rc = 0; 1082 QCameraStream *pStream = NULL; 1083 QCameraHeapMemory *pStreamInfoBuf = NULL; 1084 QCameraHeapMemory *pMiscBuf = NULL; 1085 cam_stream_info_t *streamInfo = NULL; 1086 cam_padding_info_t padding; 1087 1088 memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles)); 1089 if (NULL == paddingInfo) { 1090 return BAD_VALUE; 1091 } 1092 padding = *paddingInfo; 1093 //Use maximum padding so that the buffer 1094 //can be rotated 1095 padding.width_padding = MAX(padding.width_padding, padding.height_padding); 1096 padding.height_padding = padding.width_padding; 1097 padding.offset_info.offset_x = 0; 1098 padding.offset_info.offset_y = 0; 1099 1100 LOGD("num of src stream = %d", pSrcChannel->getNumOfStreams()); 1101 for (uint32_t i = 0; i < pSrcChannel->getNumOfStreams(); i++) { 1102 cam_pp_feature_config_t pp_featuremask = featureConfig; 1103 pStream = pSrcChannel->getStreamByIndex(i); 1104 if (pStream != NULL) { 1105 if (param.getofflineRAW() && !((pStream->isTypeOf(CAM_STREAM_TYPE_RAW)) 1106 || (pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW)) 1107 || (pStream->isTypeOf(CAM_STREAM_TYPE_METADATA)) 1108 || (pStream->isOrignalTypeOf(CAM_STREAM_TYPE_RAW)))) { 1109 //Skip all the stream other than RAW and POSTVIEW incase of offline of RAW 1110 continue; 1111 } 1112 1113 if (pStream->isTypeOf(CAM_STREAM_TYPE_RAW) 1114 && (!param.getofflineRAW())) { 1115 // Skip raw for reprocess now because PP module cannot handle 1116 // meta data&raw. May need furthur discussion if Imaginglib need meta data 1117 continue; 1118 } 1119 1120 if (((pStream->isTypeOf(CAM_STREAM_TYPE_METADATA)) 1121 && !(param.getManualCaptureMode() >= 1122 CAM_MANUAL_CAPTURE_TYPE_3)) 1123 || (pStream->isTypeOf(CAM_STREAM_TYPE_ANALYSIS))) { 1124 // Skip metadata 1125 continue; 1126 } 1127 1128 if (pStream->isTypeOf(CAM_STREAM_TYPE_PREVIEW) || 1129 pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) || 1130 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_PREVIEW) || 1131 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_POSTVIEW)) { 1132 cam_feature_mask_t feature_mask = featureConfig.feature_mask; 1133 1134 // skip thumbnail reprocessing if not needed 1135 if (!param.needThumbnailReprocess(&feature_mask)) { 1136 continue; 1137 } 1138 // CAC, SHARPNESS, FLIP and WNR would have been already applied - 1139 // on preview/postview stream in realtime. 1140 // So, need not apply again. 1141 feature_mask &= ~(CAM_QCOM_FEATURE_DENOISE2D | 1142 CAM_QCOM_FEATURE_CAC | 1143 CAM_QCOM_FEATURE_SHARPNESS | 1144 CAM_QCOM_FEATURE_FLIP | 1145 CAM_QCOM_FEATURE_RAW_PROCESSING); 1146 if (!feature_mask) { 1147 // Skip thumbnail stream reprocessing since no other 1148 //reprocessing is enabled. 1149 continue; 1150 } 1151 } 1152 1153 if (pStream->isTypeOf(CAM_STREAM_TYPE_METADATA)) { 1154 pp_featuremask.feature_mask = 0; 1155 pp_featuremask.feature_mask |= CAM_QCOM_FEATURE_METADATA_PROCESSING; 1156 } 1157 1158 pStreamInfoBuf = allocator.allocateStreamInfoBuf(CAM_STREAM_TYPE_OFFLINE_PROC); 1159 if (pStreamInfoBuf == NULL) { 1160 LOGE("no mem for stream info buf"); 1161 rc = NO_MEMORY; 1162 break; 1163 } 1164 1165 streamInfo = (cam_stream_info_t *)pStreamInfoBuf->getPtr(0); 1166 memset(streamInfo, 0, sizeof(cam_stream_info_t)); 1167 streamInfo->stream_type = CAM_STREAM_TYPE_OFFLINE_PROC; 1168 // Enable CPP high performance mode to put it in turbo frequency mode for 1169 // burst/longshot/HDR snapshot cases 1170 streamInfo->perf_mode = CAM_PERF_HIGH_PERFORMANCE; 1171 if (param.getofflineRAW() && (pStream->isTypeOf(CAM_STREAM_TYPE_RAW) 1172 || pStream->isOrignalTypeOf(CAM_STREAM_TYPE_RAW))) { 1173 if (pp_featuremask.feature_mask & CAM_QCOM_FEATURE_QUADRA_CFA) { 1174 param.getStreamFormat(CAM_STREAM_TYPE_OFFLINE_PROC, streamInfo->fmt); 1175 } else { 1176 streamInfo->fmt = CAM_FORMAT_YUV_420_NV21; 1177 } 1178 } else { 1179 rc = pStream->getFormat(streamInfo->fmt); 1180 } 1181 1182 if (pStream->isTypeOf(CAM_STREAM_TYPE_PREVIEW) || 1183 pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) || 1184 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_PREVIEW) || 1185 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_POSTVIEW)) { 1186 if (pp_featuremask.feature_mask & CAM_QCOM_FEATURE_SCALE) { 1187 param.getThumbnailSize(&(streamInfo->dim.width), 1188 &(streamInfo->dim.height)); 1189 } else { 1190 pStream->getFrameDimension(streamInfo->dim); 1191 } 1192 } else { 1193 if ((param.isPostProcScaling()) && 1194 (pp_featuremask.feature_mask & CAM_QCOM_FEATURE_SCALE)) { 1195 rc = param.getStreamDimension(CAM_STREAM_TYPE_OFFLINE_PROC, 1196 streamInfo->dim); 1197 } else if ((param.getofflineRAW()) && 1198 ((pStream->isTypeOf(CAM_STREAM_TYPE_RAW)) || 1199 (pStream->isOrignalTypeOf(CAM_STREAM_TYPE_RAW)))) { 1200 if ((param.getQuadraCfa()) && 1201 (pp_featuremask.feature_mask & CAM_QCOM_FEATURE_QUADRA_CFA)) { 1202 rc = pStream->getFrameDimension(streamInfo->dim); 1203 } else { 1204 param.getStreamDimension(CAM_STREAM_TYPE_SNAPSHOT,streamInfo->dim); 1205 } 1206 } else { 1207 rc = pStream->getFrameDimension(streamInfo->dim); 1208 } 1209 } 1210 1211 if ( contStream ) { 1212 streamInfo->streaming_mode = CAM_STREAMING_MODE_CONTINUOUS; 1213 streamInfo->num_of_burst = 0; 1214 } else { 1215 streamInfo->streaming_mode = CAM_STREAMING_MODE_BURST; 1216 streamInfo->num_of_burst = burstNum; 1217 } 1218 streamInfo->num_bufs = minStreamBufNum; 1219 streamInfo->buf_cnt = streamInfo->num_bufs; 1220 1221 cam_stream_reproc_config_t rp_cfg; 1222 memset(&rp_cfg, 0, sizeof(cam_stream_reproc_config_t)); 1223 if (offline) { 1224 cam_frame_len_offset_t offset; 1225 memset(&offset, 0, sizeof(cam_frame_len_offset_t)); 1226 1227 rp_cfg.pp_type = CAM_OFFLINE_REPROCESS_TYPE; 1228 pStream->getFormat(rp_cfg.offline.input_fmt); 1229 pStream->getFrameDimension(rp_cfg.offline.input_dim); 1230 pStream->getFrameOffset(offset); 1231 rp_cfg.offline.input_buf_planes.plane_info = offset; 1232 rp_cfg.offline.input_type = pStream->getMyOriginalType(); 1233 //For input metadata + input buffer 1234 rp_cfg.offline.num_of_bufs = 2; 1235 } else { 1236 rp_cfg.pp_type = CAM_ONLINE_REPROCESS_TYPE; 1237 rp_cfg.online.input_stream_id = pStream->getMyServerID(); 1238 rp_cfg.online.input_stream_type = pStream->getMyOriginalType(); 1239 } 1240 param.getStreamRotation(streamInfo->stream_type, 1241 streamInfo->pp_config, streamInfo->dim); 1242 streamInfo->reprocess_config = rp_cfg; 1243 streamInfo->reprocess_config.pp_feature_config = pp_featuremask; 1244 1245 if (!(pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) 1246 || pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT) 1247 || pStream->isTypeOf(CAM_STREAM_TYPE_RAW) 1248 || pStream->isOrignalTypeOf(CAM_STREAM_TYPE_RAW))) { 1249 // CAC, SHARPNESS, FLIP and WNR would have been already applied - 1250 // on preview/postview stream in realtime. Need not apply again. 1251 streamInfo->reprocess_config.pp_feature_config.feature_mask &= 1252 ~CAM_QCOM_FEATURE_CAC; 1253 streamInfo->reprocess_config.pp_feature_config.feature_mask &= 1254 ~CAM_QCOM_FEATURE_SHARPNESS; 1255 streamInfo->reprocess_config.pp_feature_config.feature_mask &= 1256 ~CAM_QCOM_FEATURE_FLIP; 1257 //Don't do WNR for thumbnail 1258 streamInfo->reprocess_config.pp_feature_config.feature_mask &= 1259 ~CAM_QCOM_FEATURE_DENOISE2D; 1260 streamInfo->reprocess_config.pp_feature_config.feature_mask &= 1261 ~CAM_QCOM_FEATURE_CDS; 1262 streamInfo->reprocess_config.pp_feature_config.feature_mask &= 1263 ~CAM_QCOM_FEATURE_DSDN; 1264 //No need of RAW processing for other than RAW streams 1265 streamInfo->reprocess_config.pp_feature_config.feature_mask &= 1266 ~CAM_QCOM_FEATURE_RAW_PROCESSING; 1267 1268 if (param.isHDREnabled() 1269 && !param.isHDRThumbnailProcessNeeded()){ 1270 streamInfo->reprocess_config.pp_feature_config.feature_mask 1271 &= ~CAM_QCOM_FEATURE_HDR; 1272 } 1273 } 1274 1275 cam_stream_type_t type = CAM_STREAM_TYPE_DEFAULT; 1276 if (offline) { 1277 type = streamInfo->reprocess_config.offline.input_type; 1278 } else { 1279 type = streamInfo->reprocess_config.online.input_stream_type; 1280 } 1281 if (type == CAM_STREAM_TYPE_SNAPSHOT) { 1282 int flipMode = param.getFlipMode(type); 1283 if (flipMode > 0) { 1284 streamInfo->reprocess_config.pp_feature_config.feature_mask |= 1285 CAM_QCOM_FEATURE_FLIP; 1286 streamInfo->reprocess_config.pp_feature_config.flip = (uint32_t)flipMode; 1287 } 1288 } 1289 1290 if ((streamInfo->reprocess_config.pp_feature_config.feature_mask 1291 & CAM_QCOM_FEATURE_SCALE) 1292 && param.isReprocScaleEnabled() 1293 && param.isUnderReprocScaling()) { 1294 //we only Scale Snapshot frame 1295 if (pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT)) { 1296 streamInfo->dim.width = 1297 streamInfo->reprocess_config.pp_feature_config.scale_param.output_width; 1298 streamInfo->dim.height = 1299 streamInfo->reprocess_config.pp_feature_config.scale_param.output_height; 1300 } 1301 LOGH("stream width=%d, height=%d.", 1302 streamInfo->dim.width, streamInfo->dim.height); 1303 } 1304 1305 // save source stream handler 1306 if (mDualChannel) { 1307 mSrcStreamHandles[mStreams.size()] = pStream->getMyHandle(); 1308 } else if (get_main_camera_handle(pStream->getMyHandle())) { 1309 mSrcStreamHandles[mStreams.size()] = 1310 get_main_camera_handle(pStream->getMyHandle()); 1311 } else if (get_aux_camera_handle(pStream->getMyHandle())) { 1312 mSrcStreamHandles[mStreams.size()] = 1313 get_aux_camera_handle(pStream->getMyHandle()); 1314 } else { 1315 LOGE("Invalid Handle. "); 1316 rc = BAD_VALUE; 1317 break; 1318 } 1319 1320 mSrcStreamHandles[mStreams.size()] = pStream->getMyHandle(); 1321 pMiscBuf = allocator.allocateMiscBuf(streamInfo); 1322 1323 LOGH("Configure Reprocessing: stream = %d, res = %dX%d, fmt = %d," 1324 "type = %d buf_cnt = %d", 1325 pStream->getMyOriginalType(), streamInfo->dim.width, 1326 streamInfo->dim.height, streamInfo->fmt, type, minStreamBufNum); 1327 1328 // add reprocess stream 1329 if (streamInfo->reprocess_config.pp_feature_config.feature_mask 1330 & CAM_QCOM_FEATURE_ROTATION) { 1331 rc = addStream(allocator, pStreamInfoBuf, pMiscBuf, 1332 &padding, NULL, NULL, false, false, 1333 streamInfo->reprocess_config.pp_feature_config.rotation); 1334 } else { 1335 rc = addStream(allocator, pStreamInfoBuf, pMiscBuf, 1336 &padding, NULL, NULL, false, false); 1337 } 1338 if (rc != NO_ERROR) { 1339 LOGE("add reprocess stream failed, ret = %d", rc); 1340 break; 1341 } 1342 } 1343 } 1344 1345 if (rc == NO_ERROR) { 1346 m_pSrcChannel = pSrcChannel; 1347 } 1348 return rc; 1349 } 1350 1351 /*=========================================================================== 1352 * FUNCTION : getStreamBySrouceHandle 1353 * 1354 * DESCRIPTION: find reprocess stream by its source stream handle 1355 * 1356 * PARAMETERS : 1357 * @srcHandle : source stream handle 1358 * 1359 * RETURN : ptr to reprocess stream if found. NULL if not found 1360 *==========================================================================*/ 1361 QCameraStream * QCameraReprocessChannel::getStreamBySrouceHandle(uint32_t srcHandle) 1362 { 1363 QCameraStream *pStream = NULL; 1364 1365 for (size_t i = 0; i < mStreams.size(); i++) { 1366 if (validate_handle(mSrcStreamHandles[i], srcHandle)) { 1367 pStream = mStreams[i]; 1368 break; 1369 } 1370 } 1371 1372 return pStream; 1373 } 1374 1375 /*=========================================================================== 1376 * FUNCTION : stop 1377 * 1378 * DESCRIPTION: stop channel and unmap offline buffers 1379 * 1380 * PARAMETERS : none 1381 * 1382 * RETURN : int32_t type of status 1383 * NO_ERROR -- success 1384 * none-zero failure code 1385 *==========================================================================*/ 1386 int32_t QCameraReprocessChannel::stop() 1387 { 1388 int32_t rc = QCameraChannel::stop(); 1389 1390 if (!mOfflineBuffers.empty()) { 1391 QCameraStream *stream = NULL; 1392 List<OfflineBuffer>::iterator it = mOfflineBuffers.begin(); 1393 int error = NO_ERROR; 1394 for( ; it != mOfflineBuffers.end(); it++) { 1395 stream = (*it).stream; 1396 if (NULL != stream) { 1397 error = stream->unmapBuf((*it).type, 1398 (*it).index, 1399 -1); 1400 if (NO_ERROR != error) { 1401 LOGE("Error during offline buffer unmap %d", 1402 error); 1403 } 1404 } 1405 } 1406 mOfflineBuffers.clear(); 1407 } 1408 return rc; 1409 } 1410 1411 /*=========================================================================== 1412 * FUNCTION : doReprocessOffline 1413 * 1414 * DESCRIPTION: request to do offline reprocess on the frame 1415 * 1416 * PARAMETERS : 1417 * @frame : frame to be performed a reprocess 1418 * @meta_buf : Metadata buffer for reprocessing 1419 * @pStream : Actual reprocess stream 1420 * 1421 * RETURN : int32_t type of status 1422 * NO_ERROR -- success 1423 * none-zero failure code 1424 *==========================================================================*/ 1425 int32_t QCameraReprocessChannel::doReprocessOffline(mm_camera_buf_def_t *frame, 1426 mm_camera_buf_def_t *meta_buf, QCameraStream *pStream) 1427 { 1428 int32_t rc = 0; 1429 OfflineBuffer mappedBuffer; 1430 uint32_t buf_index = 0; 1431 uint32_t meta_buf_index = 0; 1432 1433 if ((frame == NULL) || (meta_buf == NULL)) { 1434 LOGE("Invalid Input Paramters"); 1435 return INVALID_OPERATION; 1436 } 1437 1438 if (pStream == NULL) { 1439 pStream = getStreamBySrouceHandle(frame->stream_id); 1440 if (pStream == NULL) { 1441 LOGE("Input validation failed."); 1442 return INVALID_OPERATION; 1443 } 1444 } 1445 1446 if (!mOfflineBuffers.empty()) { 1447 List<OfflineBuffer>::iterator it = mOfflineBuffers.begin(); 1448 for( ; it != mOfflineBuffers.end(); it++) { 1449 buf_index = (buf_index < ((*it).index)) ? ((*it).index) : buf_index; 1450 } 1451 buf_index += 1; 1452 } 1453 1454 meta_buf_index = buf_index; 1455 if (meta_buf != NULL) { 1456 rc = pStream->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF, 1457 meta_buf_index, 1458 -1, 1459 meta_buf->fd, 1460 meta_buf->buffer, 1461 meta_buf->frame_len); 1462 if (NO_ERROR != rc ) { 1463 LOGE("Error during metadata buffer mapping"); 1464 rc = -1; 1465 return rc; 1466 } 1467 1468 mappedBuffer.index = meta_buf_index; 1469 mappedBuffer.stream = pStream; 1470 mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF; 1471 mOfflineBuffers.push_back(mappedBuffer); 1472 buf_index += 1; 1473 } 1474 1475 rc = pStream->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF, 1476 buf_index, 1477 -1, 1478 frame->fd, 1479 frame->buffer, 1480 frame->frame_len); 1481 if (NO_ERROR != rc ) { 1482 LOGE("Error during reprocess input buffer mapping"); 1483 rc = -1; 1484 return rc; 1485 } 1486 mappedBuffer.index = buf_index; 1487 mappedBuffer.stream = pStream; 1488 mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF; 1489 mOfflineBuffers.push_back(mappedBuffer); 1490 1491 cam_stream_parm_buffer_t param; 1492 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t)); 1493 1494 param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS; 1495 param.reprocess.buf_index = buf_index; 1496 param.reprocess.frame_idx = frame->frame_idx; 1497 1498 if (meta_buf != NULL) { 1499 param.reprocess.meta_present = 1; 1500 param.reprocess.meta_buf_index = meta_buf_index; 1501 } 1502 1503 LOGI("Offline reprocessing id = %d buf Id = %d meta index = %d type = %d", 1504 param.reprocess.frame_idx, param.reprocess.buf_index, 1505 param.reprocess.meta_buf_index, pStream->getMyOriginalType()); 1506 1507 rc = pStream->setParameter(param); 1508 if (rc != NO_ERROR) { 1509 LOGE("stream setParameter for reprocess failed"); 1510 return rc; 1511 } 1512 return rc; 1513 } 1514 1515 /*=========================================================================== 1516 * FUNCTION : doReprocessOffline 1517 * 1518 * DESCRIPTION: request to do offline reprocess on the frame 1519 * 1520 * PARAMETERS : 1521 * @frame : frame to be performed a reprocess 1522 * @meta_buf : Metadata buffer for reprocessing 1523 * @mParameter : camera parameters 1524 * 1525 * RETURN : int32_t type of status 1526 * NO_ERROR -- success 1527 * none-zero failure code 1528 *==========================================================================*/ 1529 int32_t QCameraReprocessChannel::doReprocessOffline(mm_camera_super_buf_t *frame, 1530 mm_camera_buf_def_t *meta_buf, QCameraParametersIntf &mParameter) 1531 { 1532 int32_t rc = 0; 1533 QCameraStream *pStream = NULL; 1534 1535 if (mStreams.size() < 1) { 1536 LOGE("No reprocess streams"); 1537 return -1; 1538 } 1539 if (m_pSrcChannel == NULL) { 1540 LOGE("No source channel for reprocess"); 1541 return -1; 1542 } 1543 1544 if (frame == NULL) { 1545 LOGE("Invalid source frame"); 1546 return BAD_VALUE; 1547 } 1548 1549 for (uint32_t i = 0; i < frame->num_bufs; i++) { 1550 pStream = getStreamBySrouceHandle(frame->bufs[i]->stream_id); 1551 if ((pStream != NULL) && 1552 (validate_handle(m_handle,pStream->getChannelHandle()))) { 1553 if (mParameter.getofflineRAW() && 1554 !((pStream->isOrignalTypeOf(CAM_STREAM_TYPE_RAW)) 1555 || (pStream->isOrignalTypeOf(CAM_STREAM_TYPE_METADATA)))) { 1556 continue; 1557 } 1558 1559 if ((pStream->isOrignalTypeOf(CAM_STREAM_TYPE_METADATA) 1560 && (mParameter.getManualCaptureMode() 1561 < CAM_MANUAL_CAPTURE_TYPE_3)) 1562 || (pStream->isTypeOf(CAM_STREAM_TYPE_ANALYSIS))) { 1563 // Skip metadata for reprocess now because PP module cannot handle meta data 1564 // May need furthur discussion if Imaginglib need meta data 1565 continue; 1566 } 1567 1568 // Update Metadata 1569 if (meta_buf != NULL) { 1570 uint32_t stream_id = frame->bufs[i]->stream_id; 1571 QCameraStream *srcStream = 1572 m_pSrcChannel->getStreamByHandle(stream_id); 1573 metadata_buffer_t *pMetaData = 1574 (metadata_buffer_t *)meta_buf->buffer; 1575 if ((NULL != pMetaData) && (NULL != srcStream)) { 1576 IF_META_AVAILABLE(cam_crop_data_t, crop, 1577 CAM_INTF_META_CROP_DATA, pMetaData) { 1578 if (MAX_NUM_STREAMS > crop->num_of_streams) { 1579 for (int j = 0; j < MAX_NUM_STREAMS; j++) { 1580 if (crop->crop_info[j].stream_id == 1581 srcStream->getMyServerID()) { 1582 // Store crop/roi information for offline reprocess 1583 // in the reprocess stream slot 1584 crop->crop_info[crop->num_of_streams].crop = 1585 crop->crop_info[j].crop; 1586 crop->crop_info[crop->num_of_streams].roi_map = 1587 crop->crop_info[j].roi_map; 1588 for (uint8_t k = 0; k < mStreams.size(); k++) { 1589 if (srcStream->getMyType() == 1590 mStreams[k]->getMyOriginalType()) { 1591 crop->crop_info[crop->num_of_streams].stream_id = 1592 mStreams[k]->getMyServerID(); 1593 break; 1594 } 1595 } 1596 crop->num_of_streams++; 1597 break; 1598 } 1599 } 1600 } else { 1601 LOGE("No space to add reprocess stream crop/roi information"); 1602 } 1603 } 1604 } 1605 } else { 1606 LOGE("Metadata NULL"); 1607 } 1608 1609 rc = doReprocessOffline (frame->bufs[i], meta_buf, pStream); 1610 } 1611 } 1612 return rc; 1613 } 1614 1615 /*=========================================================================== 1616 * FUNCTION : doReprocess 1617 * 1618 * DESCRIPTION: request to do a reprocess on the frame 1619 * 1620 * PARAMETERS : 1621 * @frame : frame to be performed a reprocess 1622 * @mParameter : camera parameters 1623 * @pMetaStream: Metadata stream handle 1624 * @meta_buf_index : Metadata buffer index 1625 * 1626 * RETURN : int32_t type of status 1627 * NO_ERROR -- success 1628 * none-zero failure code 1629 *==========================================================================*/ 1630 int32_t QCameraReprocessChannel::doReprocess(mm_camera_super_buf_t *frame, 1631 QCameraParametersIntf &mParameter, QCameraStream *pMetaStream, 1632 uint8_t meta_buf_index) 1633 { 1634 int32_t rc = 0; 1635 if (mStreams.size() < 1) { 1636 LOGE("No reprocess streams"); 1637 return -1; 1638 } 1639 if (m_pSrcChannel == NULL) { 1640 LOGE("No source channel for reprocess"); 1641 return -1; 1642 } 1643 1644 if (pMetaStream == NULL) { 1645 LOGW("Null Metadata buffer for processing"); 1646 } 1647 1648 for (uint32_t i = 0; i < frame->num_bufs; i++) { 1649 QCameraStream *pStream = getStreamBySrouceHandle(frame->bufs[i]->stream_id); 1650 if ((pStream != NULL) && 1651 (validate_handle(m_handle, pStream->getChannelHandle()))) { 1652 if (mParameter.getofflineRAW() && !((pStream->isOrignalTypeOf(CAM_STREAM_TYPE_RAW)) 1653 || (pStream->isOrignalTypeOf(CAM_STREAM_TYPE_POSTVIEW)) 1654 || (pStream->isOrignalTypeOf(CAM_STREAM_TYPE_METADATA)))) { 1655 //Skip all the stream other than RAW and POSTVIEW incase of offline of RAW 1656 continue; 1657 } 1658 if ((pStream->isOrignalTypeOf(CAM_STREAM_TYPE_METADATA) 1659 && (mParameter.getManualCaptureMode() 1660 < CAM_MANUAL_CAPTURE_TYPE_3)) 1661 || (pStream->isTypeOf(CAM_STREAM_TYPE_ANALYSIS))) { 1662 // Skip metadata for reprocess now because PP module cannot handle meta data 1663 // May need furthur discussion if Imaginglib need meta data 1664 continue; 1665 } 1666 1667 cam_stream_parm_buffer_t param; 1668 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t)); 1669 param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS; 1670 param.reprocess.buf_index = frame->bufs[i]->buf_idx; 1671 param.reprocess.frame_idx = frame->bufs[i]->frame_idx; 1672 if (pMetaStream != NULL) { 1673 // we have meta data frame bundled, sent together with reprocess frame 1674 param.reprocess.meta_present = 1; 1675 param.reprocess.meta_stream_handle = pMetaStream->getMyServerID(); 1676 param.reprocess.meta_buf_index = meta_buf_index; 1677 } 1678 1679 LOGI("Online reprocessing id = %d buf Id = %d meta index = %d type = %d", 1680 param.reprocess.frame_idx, param.reprocess.buf_index, 1681 param.reprocess.meta_buf_index, pStream->getMyOriginalType()); 1682 1683 rc = pStream->setParameter(param); 1684 if (rc != NO_ERROR) { 1685 LOGE("stream setParameter for reprocess failed"); 1686 break; 1687 } 1688 } 1689 } 1690 return rc; 1691 } 1692 1693 /*=========================================================================== 1694 * FUNCTION : doReprocess 1695 * 1696 * DESCRIPTION: request to do a reprocess on the frame 1697 * 1698 * PARAMETERS : 1699 * @buf_fd : fd to the input buffer that needs reprocess 1700 * @buffer : buffer pointer of actual buffer 1701 * @buf_lenght : length of the input buffer 1702 * @ret_val : result of reprocess. 1703 * Example: Could be faceID in case of register face image. 1704 * 1705 * RETURN : int32_t type of status 1706 * NO_ERROR -- success 1707 * none-zero failure code 1708 *==========================================================================*/ 1709 int32_t QCameraReprocessChannel::doReprocess(int buf_fd, void *buffer, 1710 size_t buf_length, int32_t &ret_val) 1711 { 1712 int32_t rc = 0; 1713 if (mStreams.size() < 1) { 1714 LOGE("No reprocess streams"); 1715 return -1; 1716 } 1717 1718 uint32_t buf_idx = 0; 1719 for (size_t i = 0; i < mStreams.size(); i++) { 1720 if ((mStreams[i] != NULL) && 1721 (validate_handle(m_handle, mStreams[i]->getChannelHandle()))) { 1722 continue; 1723 } 1724 rc = mStreams[i]->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF, 1725 buf_idx, -1, 1726 buf_fd, buffer, buf_length); 1727 1728 if (rc == NO_ERROR) { 1729 cam_stream_parm_buffer_t param; 1730 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t)); 1731 param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS; 1732 param.reprocess.buf_index = buf_idx; 1733 rc = mStreams[i]->setParameter(param); 1734 if (rc == NO_ERROR) { 1735 ret_val = param.reprocess.ret_val; 1736 } 1737 mStreams[i]->unmapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF, 1738 buf_idx, -1); 1739 } 1740 } 1741 return rc; 1742 } 1743 1744 }; // namespace qcamera 1745