1 /* 2 * Copyright (C) Texas Instruments - http://www.ti.com/ 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 18 /** 19 * @file OMXFocus.cpp 20 * 21 * This file contains functionality for handling focus configurations. 22 * 23 */ 24 25 #undef LOG_TAG 26 27 #define LOG_TAG "CameraHAL" 28 29 #include "CameraHal.h" 30 #include "OMXCameraAdapter.h" 31 #include "ErrorUtils.h" 32 33 #define TOUCH_FOCUS_RANGE 0xFF 34 #define AF_IMAGE_CALLBACK_TIMEOUT 5000000 //5 seconds timeout 35 #define AF_VIDEO_CALLBACK_TIMEOUT 2800000 //2.8 seconds timeout 36 37 namespace android { 38 39 status_t OMXCameraAdapter::setParametersFocus(const CameraParameters ¶ms, 40 BaseCameraAdapter::AdapterState state) 41 { 42 status_t ret = NO_ERROR; 43 const char *str = NULL; 44 Vector< sp<CameraArea> > tempAreas; 45 size_t MAX_FOCUS_AREAS; 46 47 LOG_FUNCTION_NAME; 48 49 Mutex::Autolock lock(mFocusAreasLock); 50 51 str = params.get(CameraParameters::KEY_FOCUS_AREAS); 52 53 MAX_FOCUS_AREAS = atoi(params.get(CameraParameters::KEY_MAX_NUM_FOCUS_AREAS)); 54 55 if ( NULL != str ) { 56 ret = CameraArea::parseAreas(str, ( strlen(str) + 1 ), tempAreas); 57 } 58 59 if ( (NO_ERROR == ret) && CameraArea::areAreasDifferent(mFocusAreas, tempAreas) ) { 60 mFocusAreas.clear(); 61 mFocusAreas = tempAreas; 62 if ( MAX_FOCUS_AREAS < mFocusAreas.size() ) { 63 CAMHAL_LOGEB("Focus areas supported %d, focus areas set %d", 64 MAX_FOCUS_AREAS, 65 mFocusAreas.size()); 66 ret = -EINVAL; 67 } 68 else { 69 if ( !mFocusAreas.isEmpty() ) { 70 setTouchFocus(); 71 } 72 } 73 } 74 75 LOG_FUNCTION_NAME; 76 77 return ret; 78 } 79 80 status_t OMXCameraAdapter::doAutoFocus() 81 { 82 status_t ret = NO_ERROR; 83 OMX_ERRORTYPE eError = OMX_ErrorNone; 84 OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focusControl; 85 OMX_PARAM_FOCUSSTATUSTYPE focusStatus; 86 OMX_CONFIG_BOOLEANTYPE bOMX; 87 nsecs_t timeout = 0; 88 89 LOG_FUNCTION_NAME; 90 91 if ( OMX_StateInvalid == mComponentState ) 92 { 93 CAMHAL_LOGEA("OMX component in Invalid state"); 94 returnFocusStatus(false); 95 return -EINVAL; 96 } 97 98 if ( OMX_StateExecuting != mComponentState ) 99 { 100 CAMHAL_LOGEA("OMX component not in executing state"); 101 returnFocusStatus(false); 102 return NO_ERROR; 103 } 104 105 106 if( ((AF_ACTIVE & getState()) != AF_ACTIVE) && ((AF_ACTIVE & getNextState()) != AF_ACTIVE) ) { 107 CAMHAL_LOGDA("Auto focus got canceled before doAutoFocus could be called"); 108 return NO_ERROR; 109 } 110 111 OMX_INIT_STRUCT_PTR (&focusStatus, OMX_PARAM_FOCUSSTATUSTYPE); 112 113 // If the app calls autoFocus, the camera will stop sending face callbacks. 114 pauseFaceDetection(true); 115 116 // This is needed for applying FOCUS_REGION correctly 117 if ( (!mFocusAreas.isEmpty()) && (!mFocusAreas.itemAt(0)->isZeroArea())) 118 { 119 //Disable face priority 120 setAlgoPriority(FACE_PRIORITY, FOCUS_ALGO, false); 121 122 //Enable region algorithm priority 123 setAlgoPriority(REGION_PRIORITY, FOCUS_ALGO, true); 124 } 125 126 OMX_INIT_STRUCT_PTR (&focusControl, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE); 127 focusControl.eFocusControl = ( OMX_IMAGE_FOCUSCONTROLTYPE ) mParameters3A.Focus; 128 129 if (mParameters3A.FocusLock) { 130 // this basically means user never called cancelAutoFocus after a scan... 131 // if this is the case we need to unlock AF to ensure we will do a scan 132 if (set3ALock(mUserSetExpLock, mUserSetWbLock, OMX_FALSE) != NO_ERROR) { 133 CAMHAL_LOGEA("Error Unlocking 3A locks"); 134 } else { 135 CAMHAL_LOGDA("AE/AWB unlocked successfully"); 136 } 137 138 } else if ( mParameters3A.Focus == OMX_IMAGE_FocusControlAuto ) { 139 // In case we have CAF running we should first check the AF status. 140 // If it has managed to lock, then do as usual and return status 141 // immediately. 142 ret = checkFocus(&focusStatus); 143 if ( NO_ERROR != ret ) { 144 CAMHAL_LOGEB("Focus status check failed 0x%x!", ret); 145 return ret; 146 } else { 147 CAMHAL_LOGDB("Focus status check 0x%x!", focusStatus.eFocusStatus); 148 } 149 } 150 151 if ( (focusControl.eFocusControl == OMX_IMAGE_FocusControlAuto && 152 ( focusStatus.eFocusStatus == OMX_FocusStatusRequest || 153 focusStatus.eFocusStatus == OMX_FocusStatusUnableToReach || 154 focusStatus.eFocusStatus == OMX_FocusStatusLost ) ) || 155 (mParameters3A.Focus != (OMX_IMAGE_FOCUSCONTROLTYPE)OMX_IMAGE_FocusControlAuto) ) 156 { 157 OMX_INIT_STRUCT_PTR (&bOMX, OMX_CONFIG_BOOLEANTYPE); 158 bOMX.bEnabled = OMX_TRUE; 159 160 //Enable focus scanning 161 eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, 162 (OMX_INDEXTYPE)OMX_TI_IndexConfigAutofocusEnable, 163 &bOMX); 164 165 // force AF, Ducati will take care of whether CAF 166 // or AF will be performed, depending on light conditions 167 if ( focusControl.eFocusControl == OMX_IMAGE_FocusControlAuto && 168 ( focusStatus.eFocusStatus == OMX_FocusStatusUnableToReach || 169 focusStatus.eFocusStatus == OMX_FocusStatusLost ) ) { 170 focusControl.eFocusControl = OMX_IMAGE_FocusControlAutoLock; 171 } 172 173 if ( focusControl.eFocusControl != OMX_IMAGE_FocusControlAuto ) 174 { 175 eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, 176 OMX_IndexConfigFocusControl, 177 &focusControl); 178 } 179 180 if ( OMX_ErrorNone != eError ) { 181 CAMHAL_LOGEB("Error while starting focus 0x%x", eError); 182 return INVALID_OPERATION; 183 } else { 184 CAMHAL_LOGDA("Autofocus started successfully"); 185 } 186 187 // configure focus timeout based on capture mode 188 timeout = (mCapMode == VIDEO_MODE) ? 189 ( ( nsecs_t ) AF_VIDEO_CALLBACK_TIMEOUT * 1000 ) : 190 ( ( nsecs_t ) AF_IMAGE_CALLBACK_TIMEOUT * 1000 ); 191 192 { 193 Mutex::Autolock lock(mDoAFMutex); 194 ret = mDoAFCond.waitRelative(mDoAFMutex, timeout); 195 } 196 197 //If somethiing bad happened while we wait 198 if (mComponentState == OMX_StateInvalid) { 199 CAMHAL_LOGEA("Invalid State after Auto Focus Exitting!!!"); 200 return -EINVAL; 201 } 202 203 if(ret != NO_ERROR) { 204 CAMHAL_LOGEA("Autofocus callback timeout expired"); 205 ret = returnFocusStatus(true); 206 } else { 207 ret = returnFocusStatus(false); 208 } 209 } else { // Focus mode in continuous 210 if ( NO_ERROR == ret ) { 211 ret = returnFocusStatus(true); 212 mPending3Asettings |= SetFocus; 213 } 214 } 215 216 LOG_FUNCTION_NAME_EXIT; 217 218 return ret; 219 } 220 221 status_t OMXCameraAdapter::stopAutoFocus() 222 { 223 OMX_ERRORTYPE eError = OMX_ErrorNone; 224 OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focusControl; 225 226 LOG_FUNCTION_NAME; 227 228 if ( OMX_StateInvalid == mComponentState ) 229 { 230 CAMHAL_LOGEA("OMX component in Invalid state"); 231 returnFocusStatus(false); 232 return -EINVAL; 233 } 234 235 if ( OMX_StateExecuting != mComponentState ) 236 { 237 CAMHAL_LOGEA("OMX component not in executing state"); 238 return NO_ERROR; 239 } 240 241 if ( mParameters3A.Focus == OMX_IMAGE_FocusControlAutoInfinity ) { 242 // No need to stop focus if we are in infinity mode. Nothing to stop. 243 return NO_ERROR; 244 } 245 246 OMX_INIT_STRUCT_PTR (&focusControl, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE); 247 focusControl.eFocusControl = OMX_IMAGE_FocusControlOff; 248 249 eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, 250 OMX_IndexConfigFocusControl, 251 &focusControl); 252 if ( OMX_ErrorNone != eError ) 253 { 254 CAMHAL_LOGEB("Error while stopping focus 0x%x", eError); 255 return ErrorUtils::omxToAndroidError(eError); 256 } else { 257 // This is a WA. Usually the OMX Camera component should 258 // generate AF status change OMX event fairly quickly 259 // ( after one preview frame ) and this notification should 260 // actually come from 'handleFocusCallback()'. 261 Mutex::Autolock lock(mDoAFMutex); 262 mDoAFCond.broadcast(); 263 } 264 265 266 LOG_FUNCTION_NAME_EXIT; 267 268 return NO_ERROR; 269 } 270 271 status_t OMXCameraAdapter::getFocusMode(OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE &focusMode) 272 {; 273 OMX_ERRORTYPE eError = OMX_ErrorNone; 274 275 LOG_FUNCTION_NAME; 276 277 if ( OMX_StateInvalid == mComponentState ) { 278 CAMHAL_LOGEA("OMX component is in invalid state"); 279 return NO_INIT; 280 } 281 282 OMX_INIT_STRUCT_PTR (&focusMode, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE); 283 focusMode.nPortIndex = mCameraAdapterParameters.mPrevPortIndex; 284 285 eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp, 286 OMX_IndexConfigFocusControl, 287 &focusMode); 288 289 if ( OMX_ErrorNone != eError ) { 290 CAMHAL_LOGEB("Error while retrieving focus mode 0x%x", eError); 291 } 292 293 LOG_FUNCTION_NAME_EXIT; 294 295 return ErrorUtils::omxToAndroidError(eError); 296 } 297 298 status_t OMXCameraAdapter::cancelAutoFocus() 299 { 300 status_t ret = NO_ERROR; 301 OMX_ERRORTYPE eError = OMX_ErrorNone; 302 OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focusMode; 303 304 LOG_FUNCTION_NAME; 305 306 ret = getFocusMode(focusMode); 307 if ( NO_ERROR != ret ) { 308 return ret; 309 } 310 311 //Stop the AF only for modes other than CAF or Inifinity 312 if ( ( focusMode.eFocusControl != OMX_IMAGE_FocusControlAuto ) && 313 ( focusMode.eFocusControl != ( OMX_IMAGE_FOCUSCONTROLTYPE ) 314 OMX_IMAGE_FocusControlAutoInfinity ) ) { 315 stopAutoFocus(); 316 } else if (focusMode.eFocusControl == OMX_IMAGE_FocusControlAuto) { 317 // This re-enabling of CAF doesn't seem to 318 // be needed any more. 319 // re-apply CAF after unlocking and canceling 320 // mPending3Asettings |= SetFocus; 321 } 322 // If the apps call #cancelAutoFocus()}, the face callbacks will also resume. 323 pauseFaceDetection(false); 324 325 LOG_FUNCTION_NAME_EXIT; 326 327 return ret; 328 329 } 330 331 status_t OMXCameraAdapter::setFocusCallback(bool enabled) 332 { 333 status_t ret = NO_ERROR; 334 OMX_ERRORTYPE eError = OMX_ErrorNone; 335 OMX_CONFIG_CALLBACKREQUESTTYPE focusRequstCallback; 336 337 LOG_FUNCTION_NAME; 338 339 if ( OMX_StateInvalid == mComponentState ) 340 { 341 CAMHAL_LOGEA("OMX component in Invalid state"); 342 ret = -EINVAL; 343 } 344 345 if ( OMX_StateExecuting != mComponentState ) 346 { 347 CAMHAL_LOGEA("OMX component not in executing state"); 348 ret = NO_ERROR; 349 } 350 351 if ( NO_ERROR == ret ) 352 { 353 354 OMX_INIT_STRUCT_PTR (&focusRequstCallback, OMX_CONFIG_CALLBACKREQUESTTYPE); 355 focusRequstCallback.nPortIndex = OMX_ALL; 356 focusRequstCallback.nIndex = OMX_IndexConfigCommonFocusStatus; 357 358 if ( enabled ) 359 { 360 focusRequstCallback.bEnable = OMX_TRUE; 361 } 362 else 363 { 364 focusRequstCallback.bEnable = OMX_FALSE; 365 } 366 367 eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, 368 (OMX_INDEXTYPE) OMX_IndexConfigCallbackRequest, 369 &focusRequstCallback); 370 if ( OMX_ErrorNone != eError ) 371 { 372 CAMHAL_LOGEB("Error registering focus callback 0x%x", eError); 373 ret = -1; 374 } 375 else 376 { 377 CAMHAL_LOGDB("Autofocus callback for index 0x%x registered successfully", 378 OMX_IndexConfigCommonFocusStatus); 379 } 380 } 381 382 LOG_FUNCTION_NAME_EXIT; 383 384 return ret; 385 } 386 387 status_t OMXCameraAdapter::returnFocusStatus(bool timeoutReached) 388 { 389 status_t ret = NO_ERROR; 390 OMX_PARAM_FOCUSSTATUSTYPE eFocusStatus; 391 CameraHalEvent::FocusStatus focusStatus = CameraHalEvent::FOCUS_STATUS_FAIL; 392 BaseCameraAdapter::AdapterState state, nextState; 393 BaseCameraAdapter::getState(state); 394 BaseCameraAdapter::getNextState(nextState); 395 396 LOG_FUNCTION_NAME; 397 398 OMX_INIT_STRUCT(eFocusStatus, OMX_PARAM_FOCUSSTATUSTYPE); 399 400 if( ((AF_ACTIVE & state ) != AF_ACTIVE) && ((AF_ACTIVE & nextState ) != AF_ACTIVE) ) 401 { 402 /// We don't send focus callback if focus was not started 403 CAMHAL_LOGDA("Not sending focus callback because focus was not started"); 404 return NO_ERROR; 405 } 406 407 if ( NO_ERROR == ret ) 408 { 409 410 if ( !timeoutReached ) 411 { 412 ret = checkFocus(&eFocusStatus); 413 414 if ( NO_ERROR != ret ) 415 { 416 CAMHAL_LOGEA("Focus status check failed!"); 417 } 418 } 419 } 420 421 if ( NO_ERROR == ret ) 422 { 423 424 if ( timeoutReached ) 425 { 426 focusStatus = CameraHalEvent::FOCUS_STATUS_FAIL; 427 } 428 else 429 { 430 switch (eFocusStatus.eFocusStatus) 431 { 432 case OMX_FocusStatusReached: 433 { 434 focusStatus = CameraHalEvent::FOCUS_STATUS_SUCCESS; 435 break; 436 } 437 case OMX_FocusStatusOff: // AF got canceled 438 return NO_ERROR; 439 case OMX_FocusStatusUnableToReach: 440 case OMX_FocusStatusRequest: 441 default: 442 { 443 focusStatus = CameraHalEvent::FOCUS_STATUS_FAIL; 444 break; 445 } 446 } 447 // Lock CAF after AF call 448 if( set3ALock(mUserSetExpLock, mUserSetWbLock, OMX_TRUE) != NO_ERROR) { 449 CAMHAL_LOGEA("Error Applying 3A locks"); 450 } else { 451 CAMHAL_LOGDA("Focus locked. Applied focus locks successfully"); 452 } 453 stopAutoFocus(); 454 } 455 456 //Query current focus distance after AF is complete 457 updateFocusDistances(mParameters); 458 } 459 460 ret = BaseCameraAdapter::setState(CAMERA_CANCEL_AUTOFOCUS); 461 if ( NO_ERROR == ret ) 462 { 463 ret = BaseCameraAdapter::commitState(); 464 } 465 else 466 { 467 ret |= BaseCameraAdapter::rollbackState(); 468 } 469 470 if ( NO_ERROR == ret ) 471 { 472 notifyFocusSubscribers(focusStatus); 473 } 474 475 // After focus, face detection will resume sending face callbacks 476 pauseFaceDetection(false); 477 478 LOG_FUNCTION_NAME_EXIT; 479 480 return ret; 481 } 482 483 status_t OMXCameraAdapter::checkFocus(OMX_PARAM_FOCUSSTATUSTYPE *eFocusStatus) 484 { 485 status_t ret = NO_ERROR; 486 OMX_ERRORTYPE eError = OMX_ErrorNone; 487 488 LOG_FUNCTION_NAME; 489 490 if ( NULL == eFocusStatus ) 491 { 492 CAMHAL_LOGEA("Invalid focus status"); 493 ret = -EINVAL; 494 } 495 496 if ( OMX_StateInvalid == mComponentState ) 497 { 498 CAMHAL_LOGEA("OMX component in Invalid state"); 499 ret = -EINVAL; 500 } 501 502 if ( OMX_StateExecuting != mComponentState ) 503 { 504 CAMHAL_LOGEA("OMX component not in executing state"); 505 ret = NO_ERROR; 506 } 507 508 if ( NO_ERROR == ret ) 509 { 510 OMX_INIT_STRUCT_PTR (eFocusStatus, OMX_PARAM_FOCUSSTATUSTYPE); 511 eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp, 512 OMX_IndexConfigCommonFocusStatus, 513 eFocusStatus); 514 if ( OMX_ErrorNone != eError ) 515 { 516 CAMHAL_LOGEB("Error while retrieving focus status: 0x%x", eError); 517 ret = -1; 518 } 519 } 520 521 if ( NO_ERROR == ret ) 522 { 523 CAMHAL_LOGDB("Focus Status: %d", eFocusStatus->eFocusStatus); 524 } 525 526 LOG_FUNCTION_NAME_EXIT; 527 528 return ret; 529 } 530 531 status_t OMXCameraAdapter::updateFocusDistances(CameraParameters ¶ms) 532 { 533 OMX_U32 focusNear, focusOptimal, focusFar; 534 status_t ret = NO_ERROR; 535 536 LOG_FUNCTION_NAME; 537 538 ret = getFocusDistances(focusNear, focusOptimal, focusFar); 539 if ( NO_ERROR == ret) 540 { 541 ret = addFocusDistances(focusNear, focusOptimal, focusFar, params); 542 if ( NO_ERROR != ret ) 543 { 544 CAMHAL_LOGEB("Error in call to addFocusDistances() 0x%x", ret); 545 } 546 } 547 else 548 { 549 CAMHAL_LOGEB("Error in call to getFocusDistances() 0x%x", ret); 550 } 551 552 LOG_FUNCTION_NAME_EXIT; 553 554 return ret; 555 } 556 557 status_t OMXCameraAdapter::getFocusDistances(OMX_U32 &near,OMX_U32 &optimal, OMX_U32 &far) 558 { 559 status_t ret = NO_ERROR; 560 OMX_ERRORTYPE eError; 561 562 OMX_TI_CONFIG_FOCUSDISTANCETYPE focusDist; 563 564 LOG_FUNCTION_NAME; 565 566 if ( OMX_StateInvalid == mComponentState ) 567 { 568 CAMHAL_LOGEA("OMX component is in invalid state"); 569 ret = UNKNOWN_ERROR; 570 } 571 572 if ( NO_ERROR == ret ) 573 { 574 OMX_INIT_STRUCT_PTR(&focusDist, OMX_TI_CONFIG_FOCUSDISTANCETYPE); 575 focusDist.nPortIndex = mCameraAdapterParameters.mPrevPortIndex; 576 577 eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp, 578 ( OMX_INDEXTYPE ) OMX_TI_IndexConfigFocusDistance, 579 &focusDist); 580 if ( OMX_ErrorNone != eError ) 581 { 582 CAMHAL_LOGEB("Error while querying focus distances 0x%x", eError); 583 ret = UNKNOWN_ERROR; 584 } 585 586 } 587 588 if ( NO_ERROR == ret ) 589 { 590 near = focusDist.nFocusDistanceNear; 591 optimal = focusDist.nFocusDistanceOptimal; 592 far = focusDist.nFocusDistanceFar; 593 } 594 595 LOG_FUNCTION_NAME_EXIT; 596 597 return ret; 598 } 599 600 status_t OMXCameraAdapter::encodeFocusDistance(OMX_U32 dist, char *buffer, size_t length) 601 { 602 status_t ret = NO_ERROR; 603 uint32_t focusScale = 1000; 604 float distFinal; 605 606 LOG_FUNCTION_NAME; 607 608 if(mParameters3A.Focus == OMX_IMAGE_FocusControlAutoInfinity) 609 { 610 dist=0; 611 } 612 613 if ( NO_ERROR == ret ) 614 { 615 if ( 0 == dist ) 616 { 617 strncpy(buffer, CameraParameters::FOCUS_DISTANCE_INFINITY, ( length - 1 )); 618 } 619 else 620 { 621 distFinal = dist; 622 distFinal /= focusScale; 623 snprintf(buffer, ( length - 1 ) , "%5.3f", distFinal); 624 } 625 } 626 627 LOG_FUNCTION_NAME_EXIT; 628 629 return ret; 630 } 631 632 status_t OMXCameraAdapter::addFocusDistances(OMX_U32 &near, 633 OMX_U32 &optimal, 634 OMX_U32 &far, 635 CameraParameters& params) 636 { 637 status_t ret = NO_ERROR; 638 639 LOG_FUNCTION_NAME; 640 641 if ( NO_ERROR == ret ) 642 { 643 ret = encodeFocusDistance(near, mFocusDistNear, FOCUS_DIST_SIZE); 644 if ( NO_ERROR != ret ) 645 { 646 CAMHAL_LOGEB("Error encoding near focus distance 0x%x", ret); 647 } 648 } 649 650 if ( NO_ERROR == ret ) 651 { 652 ret = encodeFocusDistance(optimal, mFocusDistOptimal, FOCUS_DIST_SIZE); 653 if ( NO_ERROR != ret ) 654 { 655 CAMHAL_LOGEB("Error encoding near focus distance 0x%x", ret); 656 } 657 } 658 659 if ( NO_ERROR == ret ) 660 { 661 ret = encodeFocusDistance(far, mFocusDistFar, FOCUS_DIST_SIZE); 662 if ( NO_ERROR != ret ) 663 { 664 CAMHAL_LOGEB("Error encoding near focus distance 0x%x", ret); 665 } 666 } 667 668 if ( NO_ERROR == ret ) 669 { 670 snprintf(mFocusDistBuffer, ( FOCUS_DIST_BUFFER_SIZE - 1) ,"%s,%s,%s", mFocusDistNear, 671 mFocusDistOptimal, 672 mFocusDistFar); 673 674 params.set(CameraParameters::KEY_FOCUS_DISTANCES, mFocusDistBuffer); 675 } 676 677 LOG_FUNCTION_NAME_EXIT; 678 679 return ret; 680 } 681 682 status_t OMXCameraAdapter::setTouchFocus() 683 { 684 status_t ret = NO_ERROR; 685 OMX_ERRORTYPE eError = OMX_ErrorNone; 686 687 OMX_ALGOAREASTYPE **focusAreas; 688 OMX_TI_CONFIG_SHAREDBUFFER sharedBuffer; 689 MemoryManager memMgr; 690 int areasSize = 0; 691 692 LOG_FUNCTION_NAME; 693 694 if ( OMX_StateInvalid == mComponentState ) 695 { 696 CAMHAL_LOGEA("OMX component is in invalid state"); 697 ret = -1; 698 } 699 700 if ( NO_ERROR == ret ) 701 { 702 703 areasSize = ((sizeof(OMX_ALGOAREASTYPE)+4095)/4096)*4096; 704 focusAreas = (OMX_ALGOAREASTYPE**) memMgr.allocateBuffer(0, 0, NULL, areasSize, 1); 705 706 OMXCameraPortParameters * mPreviewData = NULL; 707 mPreviewData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex]; 708 709 if (!focusAreas) 710 { 711 CAMHAL_LOGEB("Error allocating buffer for focus areas %d", eError); 712 return -ENOMEM; 713 } 714 715 OMX_INIT_STRUCT_PTR (focusAreas[0], OMX_ALGOAREASTYPE); 716 717 focusAreas[0]->nPortIndex = OMX_ALL; 718 focusAreas[0]->nNumAreas = mFocusAreas.size(); 719 focusAreas[0]->nAlgoAreaPurpose = OMX_AlgoAreaFocus; 720 721 // If the area is the special case of (0, 0, 0, 0, 0), then 722 // the algorithm needs nNumAreas to be set to 0, 723 // in order to automatically choose the best fitting areas. 724 if ( mFocusAreas.itemAt(0)->isZeroArea() ) 725 { 726 focusAreas[0]->nNumAreas = 0; 727 } 728 729 for ( unsigned int n = 0; n < mFocusAreas.size(); n++) 730 { 731 // transform the coordinates to 3A-type coordinates 732 mFocusAreas.itemAt(n)->transfrom((size_t)mPreviewData->mWidth, 733 (size_t)mPreviewData->mHeight, 734 (size_t&)focusAreas[0]->tAlgoAreas[n].nTop, 735 (size_t&)focusAreas[0]->tAlgoAreas[n].nLeft, 736 (size_t&)focusAreas[0]->tAlgoAreas[n].nWidth, 737 (size_t&)focusAreas[0]->tAlgoAreas[n].nHeight); 738 739 focusAreas[0]->tAlgoAreas[n].nLeft = 740 ( focusAreas[0]->tAlgoAreas[n].nLeft * TOUCH_FOCUS_RANGE ) / mPreviewData->mWidth; 741 focusAreas[0]->tAlgoAreas[n].nTop = 742 ( focusAreas[0]->tAlgoAreas[n].nTop* TOUCH_FOCUS_RANGE ) / mPreviewData->mHeight; 743 focusAreas[0]->tAlgoAreas[n].nWidth = 744 ( focusAreas[0]->tAlgoAreas[n].nWidth * TOUCH_FOCUS_RANGE ) / mPreviewData->mWidth; 745 focusAreas[0]->tAlgoAreas[n].nHeight = 746 ( focusAreas[0]->tAlgoAreas[n].nHeight * TOUCH_FOCUS_RANGE ) / mPreviewData->mHeight; 747 focusAreas[0]->tAlgoAreas[n].nPriority = mFocusAreas.itemAt(n)->getWeight(); 748 749 CAMHAL_LOGDB("Focus area %d : top = %d left = %d width = %d height = %d prio = %d", 750 n, (int)focusAreas[0]->tAlgoAreas[n].nTop, (int)focusAreas[0]->tAlgoAreas[n].nLeft, 751 (int)focusAreas[0]->tAlgoAreas[n].nWidth, (int)focusAreas[0]->tAlgoAreas[n].nHeight, 752 (int)focusAreas[0]->tAlgoAreas[n].nPriority); 753 } 754 755 OMX_INIT_STRUCT_PTR (&sharedBuffer, OMX_TI_CONFIG_SHAREDBUFFER); 756 757 sharedBuffer.nPortIndex = OMX_ALL; 758 sharedBuffer.nSharedBuffSize = areasSize; 759 sharedBuffer.pSharedBuff = (OMX_U8 *) focusAreas[0]; 760 761 if ( NULL == sharedBuffer.pSharedBuff ) 762 { 763 CAMHAL_LOGEA("No resources to allocate OMX shared buffer"); 764 ret = -ENOMEM; 765 goto EXIT; 766 } 767 768 eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, 769 (OMX_INDEXTYPE) OMX_TI_IndexConfigAlgoAreas, &sharedBuffer); 770 771 if ( OMX_ErrorNone != eError ) 772 { 773 CAMHAL_LOGEB("Error while setting Focus Areas configuration 0x%x", eError); 774 ret = -EINVAL; 775 } 776 777 EXIT: 778 if (NULL != focusAreas) 779 { 780 memMgr.freeBuffer((void*) focusAreas); 781 focusAreas = NULL; 782 } 783 } 784 785 LOG_FUNCTION_NAME_EXIT; 786 787 return ret; 788 } 789 790 void OMXCameraAdapter::handleFocusCallback() { 791 OMX_PARAM_FOCUSSTATUSTYPE eFocusStatus; 792 CameraHalEvent::FocusStatus focusStatus = CameraHalEvent::FOCUS_STATUS_FAIL; 793 status_t ret = NO_ERROR; 794 BaseCameraAdapter::AdapterState nextState; 795 BaseCameraAdapter::getNextState(nextState); 796 797 OMX_INIT_STRUCT(eFocusStatus, OMX_PARAM_FOCUSSTATUSTYPE); 798 799 ret = checkFocus(&eFocusStatus); 800 801 if (NO_ERROR != ret) { 802 CAMHAL_LOGEA("Focus status check failed!"); 803 // signal and unblock doAutoFocus 804 if (AF_ACTIVE & nextState) { 805 Mutex::Autolock lock(mDoAFMutex); 806 mDoAFCond.broadcast(); 807 } 808 return; 809 } 810 811 if ( ( eFocusStatus.eFocusStatus != OMX_FocusStatusRequest ) && 812 ( eFocusStatus.eFocusStatus != OMX_FocusStatusOff ) ) { 813 // signal doAutoFocus when a end of scan message comes 814 // ignore start of scan 815 Mutex::Autolock lock(mDoAFMutex); 816 mDoAFCond.broadcast(); 817 } 818 819 if (mParameters3A.Focus != (OMX_IMAGE_FOCUSCONTROLTYPE) OMX_IMAGE_FocusControlAuto) { 820 CAMHAL_LOGDA("unregistered focus callback when not in CAF or doAutoFocus... not handling"); 821 return; 822 } 823 824 // Handling for CAF Callbacks 825 switch (eFocusStatus.eFocusStatus) { 826 case OMX_FocusStatusRequest: 827 focusStatus = CameraHalEvent::FOCUS_STATUS_PENDING; 828 break; 829 case OMX_FocusStatusReached: 830 case OMX_FocusStatusOff: 831 case OMX_FocusStatusUnableToReach: 832 default: 833 focusStatus = CameraHalEvent::FOCUS_STATUS_DONE; 834 break; 835 } 836 837 notifyFocusSubscribers(focusStatus); 838 } 839 840 }; 841