OMXFocus.cpp revision c492aa718bc3f43eaf689b72595352f5348a0c39
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 32#define TOUCH_FOCUS_RANGE 0xFF 33#define AF_CALLBACK_TIMEOUT 10000000 //10 seconds timeout 34 35namespace android { 36 37status_t OMXCameraAdapter::setParametersFocus(const CameraParameters ¶ms, 38 BaseCameraAdapter::AdapterState state) 39{ 40 status_t ret = NO_ERROR; 41 const char *str = NULL; 42 43 LOG_FUNCTION_NAME; 44 45 str = params.get(CameraParameters::KEY_FOCUS_AREAS); 46 mFocusAreas.clear(); 47 if ( NULL != str ) { 48 ret = CameraArea::parseFocusArea(str, strlen(str), mFocusAreas); 49 } 50 51 if ( NO_ERROR == ret ) { 52 if ( MAX_FOCUS_AREAS < mFocusAreas.size() ) { 53 CAMHAL_LOGEB("Focus areas supported %d, focus areas set %d", 54 MAX_FOCUS_AREAS, 55 mFocusAreas.size()); 56 ret = -EINVAL; 57 } 58 } 59 60 LOG_FUNCTION_NAME; 61 62 return ret; 63} 64 65status_t OMXCameraAdapter::doAutoFocus() 66{ 67 status_t ret = NO_ERROR; 68 OMX_ERRORTYPE eError = OMX_ErrorNone; 69 OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focusControl; 70 size_t top, left, width, height, weight; 71 sp<CameraArea> focusArea = NULL; 72 73 LOG_FUNCTION_NAME; 74 75 if ( OMX_StateExecuting != mComponentState ) 76 { 77 CAMHAL_LOGEA("OMX component not in executing state"); 78 returnFocusStatus(false); 79 return NO_INIT; 80 } 81 82 if ( 0 != mDoAFSem.Count() ) 83 { 84 CAMHAL_LOGEB("Error mDoAFSem semaphore count %d", mDoAFSem.Count()); 85 return NO_INIT; 86 } 87 88 // If the app calls autoFocus, the camera will stop sending face callbacks. 89 pauseFaceDetection(true); 90 91 if ( NO_ERROR == ret ) 92 { 93 if ( !mFocusAreas.isEmpty() ) 94 { 95 focusArea = mFocusAreas.itemAt(0); 96 } 97 98 OMX_INIT_STRUCT_PTR (&focusControl, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE); 99 focusControl.eFocusControl = ( OMX_IMAGE_FOCUSCONTROLTYPE ) mParameters3A.Focus; 100 101 //If touch AF is set, then necessary configuration first 102 if ( ( NULL != focusArea.get() ) && ( focusArea->isValid() ) ) 103 { 104 105 //Disable face priority first 106 setAlgoPriority(FACE_PRIORITY, FOCUS_ALGO, false); 107 108 //Enable region algorithm priority 109 setAlgoPriority(REGION_PRIORITY, FOCUS_ALGO, true); 110 111 //Set position 112 OMXCameraPortParameters * mPreviewData = NULL; 113 mPreviewData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex]; 114 focusArea->transfrom(mPreviewData->mWidth, 115 mPreviewData->mHeight, 116 top, 117 left, 118 width, 119 height); 120 setTouchFocus(left, 121 top, 122 width, 123 height, 124 mPreviewData->mWidth, 125 mPreviewData->mHeight); 126 127 //Do normal focus afterwards 128 focusControl.eFocusControl = ( OMX_IMAGE_FOCUSCONTROLTYPE ) OMX_IMAGE_FocusControlExtended; 129 130 } 131 else if ( FOCUS_FACE_PRIORITY == focusControl.eFocusControl ) 132 { 133 134 //Disable region priority first 135 setAlgoPriority(REGION_PRIORITY, FOCUS_ALGO, false); 136 137 //Enable face algorithm priority 138 setAlgoPriority(FACE_PRIORITY, FOCUS_ALGO, true); 139 140 //Do normal focus afterwards 141 focusControl.eFocusControl = ( OMX_IMAGE_FOCUSCONTROLTYPE ) OMX_IMAGE_FocusControlExtended; 142 143 } 144 else 145 { 146 147 //Disable both region and face priority 148 setAlgoPriority(REGION_PRIORITY, FOCUS_ALGO, false); 149 150 setAlgoPriority(FACE_PRIORITY, FOCUS_ALGO, false); 151 152 } 153 154 if ( ( mParameters3A.Focus != OMX_IMAGE_FocusControlAuto ) && 155 ( mParameters3A.Focus != OMX_IMAGE_FocusControlAutoInfinity ) ) 156 { 157 158 ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp, 159 (OMX_EVENTTYPE) OMX_EventIndexSettingChanged, 160 OMX_ALL, 161 OMX_IndexConfigCommonFocusStatus, 162 mDoAFSem); 163 164 if ( NO_ERROR == ret ) 165 { 166 ret = setFocusCallback(true); 167 } 168 } 169 170 eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, 171 OMX_IndexConfigFocusControl, 172 &focusControl); 173 174 if ( OMX_ErrorNone != eError ) 175 { 176 CAMHAL_LOGEB("Error while starting focus 0x%x", eError); 177 return INVALID_OPERATION; 178 } 179 else 180 { 181 CAMHAL_LOGDA("Autofocus started successfully"); 182 } 183 } 184 185 if ( ( mParameters3A.Focus != OMX_IMAGE_FocusControlAuto ) && 186 ( mParameters3A.Focus != OMX_IMAGE_FocusControlAutoInfinity ) ) 187 { 188 ret = mDoAFSem.WaitTimeout(AF_CALLBACK_TIMEOUT); 189 //Disable auto focus callback from Ducati 190 setFocusCallback(false); 191 //Signal a dummy AF event so that in case the callback from ducati 192 //does come then it doesnt crash after 193 //exiting this function since eventSem will go out of scope. 194 if(ret != NO_ERROR) 195 { 196 CAMHAL_LOGEA("Autofocus callback timeout expired"); 197 SignalEvent(mCameraAdapterParameters.mHandleComp, 198 (OMX_EVENTTYPE) OMX_EventIndexSettingChanged, 199 OMX_ALL, 200 OMX_IndexConfigCommonFocusStatus, 201 NULL ); 202 returnFocusStatus(true); 203 } 204 else 205 { 206 CAMHAL_LOGDA("Autofocus callback received"); 207 ret = returnFocusStatus(false); 208 } 209 210 } 211 else 212 { 213 if ( NO_ERROR == ret ) 214 { 215 ret = returnFocusStatus(false); 216 } 217 } 218 219 LOG_FUNCTION_NAME_EXIT; 220 221 return ret; 222} 223 224status_t OMXCameraAdapter::stopAutoFocus() 225{ 226 status_t ret = NO_ERROR; 227 OMX_ERRORTYPE eError = OMX_ErrorNone; 228 OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focusControl; 229 230 LOG_FUNCTION_NAME; 231 232 if ( OMX_StateExecuting != mComponentState ) 233 { 234 CAMHAL_LOGEA("OMX component not in executing state"); 235 return NO_INIT; 236 } 237 238 if ( mParameters3A.Focus == OMX_IMAGE_FocusControlAutoInfinity ) { 239 // No need to stop focus if we are in infinity mode. Nothing to stop. 240 return NO_ERROR; 241 } 242 243 if ( NO_ERROR == ret ) 244 { 245 //Disable the callback first 246 ret = setFocusCallback(false); 247 } 248 249 if ( NO_ERROR == ret ) 250 { 251 OMX_INIT_STRUCT_PTR (&focusControl, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE); 252 focusControl.eFocusControl = OMX_IMAGE_FocusControlOff; 253 254 eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, 255 OMX_IndexConfigFocusControl, 256 &focusControl); 257 if ( OMX_ErrorNone != eError ) 258 { 259 CAMHAL_LOGEB("Error while stopping focus 0x%x", eError); 260 ret = -1; 261 } 262 else 263 { 264 mParameters3A.Focus = OMX_IMAGE_FocusControlOff; 265 CAMHAL_LOGDA("Autofocus stopped successfully"); 266 } 267 } 268 269 //Query current focus distance after AF is complete 270 updateFocusDistances(mParameters); 271 272 LOG_FUNCTION_NAME_EXIT; 273 274 return ret; 275} 276 277status_t OMXCameraAdapter::cancelAutoFocus() 278{ 279 status_t ret = NO_ERROR; 280 OMX_ERRORTYPE eError = OMX_ErrorNone; 281 282 LOG_FUNCTION_NAME; 283 // Unlock 3A locks since they were locked by AF 284 if( set3ALock(OMX_FALSE) != NO_ERROR) { 285 CAMHAL_LOGEA("Error Unlocking 3A locks"); 286 } 287 else{ 288 CAMHAL_LOGDA("AE/AWB unlocked successfully"); 289 } 290 291 stopAutoFocus(); 292 //Signal a dummy AF event so that in case the callback from ducati 293 //does come then it doesnt crash after 294 //exiting this function since eventSem will go out of scope. 295 ret |= SignalEvent(mCameraAdapterParameters.mHandleComp, 296 (OMX_EVENTTYPE) OMX_EventIndexSettingChanged, 297 OMX_ALL, 298 OMX_IndexConfigCommonFocusStatus, 299 NULL ); 300 301 // If the apps call #cancelAutoFocus()}, the face callbacks will also resume. 302 pauseFaceDetection(false); 303 304 LOG_FUNCTION_NAME_EXIT; 305 306 return ret; 307 308} 309 310status_t OMXCameraAdapter::setFocusCallback(bool enabled) 311{ 312 status_t ret = NO_ERROR; 313 OMX_ERRORTYPE eError = OMX_ErrorNone; 314 OMX_CONFIG_CALLBACKREQUESTTYPE focusRequstCallback; 315 316 LOG_FUNCTION_NAME; 317 318 if ( OMX_StateExecuting != mComponentState ) 319 { 320 CAMHAL_LOGEA("OMX component not in executing state"); 321 ret = -1; 322 } 323 324 if ( NO_ERROR == ret ) 325 { 326 327 OMX_INIT_STRUCT_PTR (&focusRequstCallback, OMX_CONFIG_CALLBACKREQUESTTYPE); 328 focusRequstCallback.nPortIndex = OMX_ALL; 329 focusRequstCallback.nIndex = OMX_IndexConfigCommonFocusStatus; 330 331 if ( enabled ) 332 { 333 focusRequstCallback.bEnable = OMX_TRUE; 334 } 335 else 336 { 337 focusRequstCallback.bEnable = OMX_FALSE; 338 } 339 340 eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, 341 (OMX_INDEXTYPE) OMX_IndexConfigCallbackRequest, 342 &focusRequstCallback); 343 if ( OMX_ErrorNone != eError ) 344 { 345 CAMHAL_LOGEB("Error registering focus callback 0x%x", eError); 346 ret = -1; 347 } 348 else 349 { 350 CAMHAL_LOGDB("Autofocus callback for index 0x%x registered successfully", 351 OMX_IndexConfigCommonFocusStatus); 352 } 353 } 354 355 LOG_FUNCTION_NAME_EXIT; 356 357 return ret; 358} 359 360status_t OMXCameraAdapter::returnFocusStatus(bool timeoutReached) 361{ 362 status_t ret = NO_ERROR; 363 OMX_PARAM_FOCUSSTATUSTYPE eFocusStatus; 364 bool focusStatus = false; 365 BaseCameraAdapter::AdapterState state; 366 BaseCameraAdapter::getState(state); 367 368 LOG_FUNCTION_NAME; 369 370 OMX_INIT_STRUCT(eFocusStatus, OMX_PARAM_FOCUSSTATUSTYPE); 371 372 if( ( AF_ACTIVE & state ) != AF_ACTIVE ) 373 { 374 /// We don't send focus callback if focus was not started 375 return NO_ERROR; 376 } 377 378 if ( NO_ERROR == ret ) 379 { 380 381 if ( !timeoutReached ) 382 { 383 ret = checkFocus(&eFocusStatus); 384 385 if ( NO_ERROR != ret ) 386 { 387 CAMHAL_LOGEA("Focus status check failed!"); 388 } 389 } 390 } 391 392 if ( NO_ERROR == ret ) 393 { 394 395 if ( timeoutReached ) 396 { 397 focusStatus = false; 398 } 399 ///FIXME: The ducati seems to return focus as false always if continuous focus is enabled 400 ///So, return focus as locked always until this is fixed. 401 else if(mParameters3A.Focus == OMX_IMAGE_FocusControlAuto ) 402 { 403 focusStatus = true; 404 } 405 else 406 { 407 switch (eFocusStatus.eFocusStatus) 408 { 409 case OMX_FocusStatusReached: 410 { 411 focusStatus = true; 412 //Lock the AE and AWB here sinc the focus is locked 413 // Apply 3A locks after AF 414 if( set3ALock(OMX_TRUE) != NO_ERROR) { 415 CAMHAL_LOGEA("Error Applying 3A locks"); 416 } 417 else 418 { 419 CAMHAL_LOGDA("Focus locked. Applied focus locks successfully"); 420 } 421 break; 422 } 423 case OMX_FocusStatusOff: 424 case OMX_FocusStatusUnableToReach: 425 case OMX_FocusStatusRequest: 426 default: 427 { 428 focusStatus = false; 429 break; 430 } 431 } 432 433 stopAutoFocus(); 434 } 435 } 436 437 if ( NO_ERROR == ret ) 438 { 439 440 ret = BaseCameraAdapter::setState(CAMERA_CANCEL_AUTOFOCUS); 441 442 if ( NO_ERROR == ret ) 443 { 444 ret = BaseCameraAdapter::commitState(); 445 } 446 else 447 { 448 ret |= BaseCameraAdapter::rollbackState(); 449 } 450 451 } 452 453 if ( NO_ERROR == ret ) 454 { 455 notifyFocusSubscribers(focusStatus); 456 } 457 458 // After focus, face detection will resume sending face callbacks 459 pauseFaceDetection(false); 460 461 LOG_FUNCTION_NAME_EXIT; 462 463 return ret; 464} 465 466status_t OMXCameraAdapter::checkFocus(OMX_PARAM_FOCUSSTATUSTYPE *eFocusStatus) 467{ 468 status_t ret = NO_ERROR; 469 OMX_ERRORTYPE eError = OMX_ErrorNone; 470 471 LOG_FUNCTION_NAME; 472 473 if ( NULL == eFocusStatus ) 474 { 475 CAMHAL_LOGEA("Invalid focus status"); 476 ret = -EINVAL; 477 } 478 479 if ( OMX_StateExecuting != mComponentState ) 480 { 481 CAMHAL_LOGEA("OMX component not in executing state"); 482 ret = -EINVAL; 483 } 484 485 if ( NO_ERROR == ret ) 486 { 487 OMX_INIT_STRUCT_PTR (eFocusStatus, OMX_PARAM_FOCUSSTATUSTYPE); 488 489 eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp, 490 OMX_IndexConfigCommonFocusStatus, 491 eFocusStatus); 492 if ( OMX_ErrorNone != eError ) 493 { 494 CAMHAL_LOGEB("Error while retrieving focus status: 0x%x", eError); 495 ret = -1; 496 } 497 } 498 499 if ( NO_ERROR == ret ) 500 { 501 CAMHAL_LOGDB("Focus Status: %d", eFocusStatus->eFocusStatus); 502 } 503 504 LOG_FUNCTION_NAME_EXIT; 505 506 return ret; 507} 508 509status_t OMXCameraAdapter::updateFocusDistances(CameraParameters ¶ms) 510{ 511 OMX_U32 focusNear, focusOptimal, focusFar; 512 status_t ret = NO_ERROR; 513 514 LOG_FUNCTION_NAME; 515 516 ret = getFocusDistances(focusNear, focusOptimal, focusFar); 517 if ( NO_ERROR == ret) 518 { 519 ret = addFocusDistances(focusNear, focusOptimal, focusFar, params); 520 if ( NO_ERROR != ret ) 521 { 522 CAMHAL_LOGEB("Error in call to addFocusDistances() 0x%x", ret); 523 } 524 } 525 else 526 { 527 CAMHAL_LOGEB("Error in call to getFocusDistances() 0x%x", ret); 528 } 529 530 LOG_FUNCTION_NAME_EXIT; 531 532 return ret; 533} 534 535status_t OMXCameraAdapter::getFocusDistances(OMX_U32 &near,OMX_U32 &optimal, OMX_U32 &far) 536{ 537 status_t ret = NO_ERROR; 538 OMX_ERRORTYPE eError; 539 540 OMX_TI_CONFIG_FOCUSDISTANCETYPE focusDist; 541 542 LOG_FUNCTION_NAME; 543 544 if ( OMX_StateInvalid == mComponentState ) 545 { 546 CAMHAL_LOGEA("OMX component is in invalid state"); 547 ret = UNKNOWN_ERROR; 548 } 549 550 if ( NO_ERROR == ret ) 551 { 552 OMX_INIT_STRUCT_PTR(&focusDist, OMX_TI_CONFIG_FOCUSDISTANCETYPE); 553 focusDist.nPortIndex = mCameraAdapterParameters.mPrevPortIndex; 554 555 eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp, 556 ( OMX_INDEXTYPE ) OMX_TI_IndexConfigFocusDistance, 557 &focusDist); 558 if ( OMX_ErrorNone != eError ) 559 { 560 CAMHAL_LOGEB("Error while querying focus distances 0x%x", eError); 561 ret = UNKNOWN_ERROR; 562 } 563 564 } 565 566 if ( NO_ERROR == ret ) 567 { 568 near = focusDist.nFocusDistanceNear; 569 optimal = focusDist.nFocusDistanceOptimal; 570 far = focusDist.nFocusDistanceFar; 571 } 572 573 LOG_FUNCTION_NAME_EXIT; 574 575 return ret; 576} 577 578status_t OMXCameraAdapter::encodeFocusDistance(OMX_U32 dist, char *buffer, size_t length) 579{ 580 status_t ret = NO_ERROR; 581 uint32_t focusScale = 1000; 582 float distFinal; 583 584 LOG_FUNCTION_NAME; 585 586 if(mParameters3A.Focus == OMX_IMAGE_FocusControlAutoInfinity) 587 { 588 dist=0; 589 } 590 591 if ( NO_ERROR == ret ) 592 { 593 if ( 0 == dist ) 594 { 595 strncpy(buffer, CameraParameters::FOCUS_DISTANCE_INFINITY, ( length - 1 )); 596 } 597 else 598 { 599 distFinal = dist; 600 distFinal /= focusScale; 601 snprintf(buffer, ( length - 1 ) , "%5.3f", distFinal); 602 } 603 } 604 605 LOG_FUNCTION_NAME_EXIT; 606 607 return ret; 608} 609 610status_t OMXCameraAdapter::addFocusDistances(OMX_U32 &near, 611 OMX_U32 &optimal, 612 OMX_U32 &far, 613 CameraParameters& params) 614{ 615 status_t ret = NO_ERROR; 616 617 LOG_FUNCTION_NAME; 618 619 if ( NO_ERROR == ret ) 620 { 621 ret = encodeFocusDistance(near, mFocusDistNear, FOCUS_DIST_SIZE); 622 if ( NO_ERROR != ret ) 623 { 624 CAMHAL_LOGEB("Error encoding near focus distance 0x%x", ret); 625 } 626 } 627 628 if ( NO_ERROR == ret ) 629 { 630 ret = encodeFocusDistance(optimal, mFocusDistOptimal, FOCUS_DIST_SIZE); 631 if ( NO_ERROR != ret ) 632 { 633 CAMHAL_LOGEB("Error encoding near focus distance 0x%x", ret); 634 } 635 } 636 637 if ( NO_ERROR == ret ) 638 { 639 ret = encodeFocusDistance(far, mFocusDistFar, FOCUS_DIST_SIZE); 640 if ( NO_ERROR != ret ) 641 { 642 CAMHAL_LOGEB("Error encoding near focus distance 0x%x", ret); 643 } 644 } 645 646 if ( NO_ERROR == ret ) 647 { 648 snprintf(mFocusDistBuffer, ( FOCUS_DIST_BUFFER_SIZE - 1) ,"%s,%s,%s", mFocusDistNear, 649 mFocusDistOptimal, 650 mFocusDistFar); 651 652 params.set(CameraParameters::KEY_FOCUS_DISTANCES, mFocusDistBuffer); 653 } 654 655 LOG_FUNCTION_NAME_EXIT; 656 657 return ret; 658} 659 660status_t OMXCameraAdapter::setTouchFocus(size_t posX, 661 size_t posY, 662 size_t posWidth, 663 size_t posHeight, 664 size_t previewWidth, 665 size_t previewHeight) 666{ 667 status_t ret = NO_ERROR; 668 OMX_ERRORTYPE eError = OMX_ErrorNone; 669 OMX_CONFIG_EXTFOCUSREGIONTYPE touchControl; 670 671 LOG_FUNCTION_NAME; 672 673 if ( OMX_StateInvalid == mComponentState ) 674 { 675 CAMHAL_LOGEA("OMX component is in invalid state"); 676 ret = -1; 677 } 678 679 if ( NO_ERROR == ret ) 680 { 681 OMX_INIT_STRUCT_PTR (&touchControl, OMX_CONFIG_EXTFOCUSREGIONTYPE); 682 touchControl.nLeft = ( posX * TOUCH_FOCUS_RANGE ) / previewWidth; 683 touchControl.nTop = ( posY * TOUCH_FOCUS_RANGE ) / previewHeight; 684 touchControl.nWidth = ( posWidth * TOUCH_FOCUS_RANGE ) / previewWidth; 685 touchControl.nHeight = ( posHeight * TOUCH_FOCUS_RANGE ) / previewHeight; 686 687 eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, 688 ( OMX_INDEXTYPE ) OMX_IndexConfigExtFocusRegion, 689 &touchControl); 690 if ( OMX_ErrorNone != eError ) 691 { 692 CAMHAL_LOGEB("Error while configuring touch focus 0x%x", eError); 693 ret = -1; 694 } 695 else 696 { 697 CAMHAL_LOGDB("Touch focus %d,%d %d,%d configured successfuly", 698 ( int ) touchControl.nLeft, 699 ( int ) touchControl.nTop, 700 ( int ) touchControl.nWidth, 701 ( int ) touchControl.nHeight); 702 } 703 } 704 705 LOG_FUNCTION_NAME_EXIT; 706 707 return ret; 708} 709 710}; 711