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