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