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