OMXFocus.cpp revision c322989ae6ff6769490828de1b5eda12b749cce9
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 break; 388 } 389 case OMX_FocusStatusOff: 390 case OMX_FocusStatusUnableToReach: 391 case OMX_FocusStatusRequest: 392 default: 393 { 394 focusStatus = false; 395 break; 396 } 397 } 398 399 stopAutoFocus(); 400 } 401 } 402 403 if ( NO_ERROR == ret ) 404 { 405 406 ret = BaseCameraAdapter::setState(CAMERA_CANCEL_AUTOFOCUS); 407 408 if ( NO_ERROR == ret ) 409 { 410 ret = BaseCameraAdapter::commitState(); 411 } 412 else 413 { 414 ret |= BaseCameraAdapter::rollbackState(); 415 } 416 417 } 418 419 if ( NO_ERROR == ret ) 420 { 421 notifyFocusSubscribers(focusStatus); 422 } 423 424 LOG_FUNCTION_NAME_EXIT; 425 426 return ret; 427} 428 429status_t OMXCameraAdapter::checkFocus(OMX_PARAM_FOCUSSTATUSTYPE *eFocusStatus) 430{ 431 status_t ret = NO_ERROR; 432 OMX_ERRORTYPE eError = OMX_ErrorNone; 433 434 LOG_FUNCTION_NAME; 435 436 if ( NULL == eFocusStatus ) 437 { 438 CAMHAL_LOGEA("Invalid focus status"); 439 ret = -EINVAL; 440 } 441 442 if ( OMX_StateExecuting != mComponentState ) 443 { 444 CAMHAL_LOGEA("OMX component not in executing state"); 445 ret = -EINVAL; 446 } 447 448 if ( NO_ERROR == ret ) 449 { 450 OMX_INIT_STRUCT_PTR (eFocusStatus, OMX_PARAM_FOCUSSTATUSTYPE); 451 452 eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp, 453 OMX_IndexConfigCommonFocusStatus, 454 eFocusStatus); 455 if ( OMX_ErrorNone != eError ) 456 { 457 CAMHAL_LOGEB("Error while retrieving focus status: 0x%x", eError); 458 ret = -1; 459 } 460 } 461 462 if ( NO_ERROR == ret ) 463 { 464 CAMHAL_LOGDB("Focus Status: %d", eFocusStatus->eFocusStatus); 465 } 466 467 LOG_FUNCTION_NAME_EXIT; 468 469 return ret; 470} 471 472status_t OMXCameraAdapter::updateFocusDistances(CameraParameters ¶ms) 473{ 474 OMX_U32 focusNear, focusOptimal, focusFar; 475 status_t ret = NO_ERROR; 476 477 LOG_FUNCTION_NAME; 478 479 ret = getFocusDistances(focusNear, focusOptimal, focusFar); 480 if ( NO_ERROR == ret) 481 { 482 ret = addFocusDistances(focusNear, focusOptimal, focusFar, params); 483 if ( NO_ERROR != ret ) 484 { 485 CAMHAL_LOGEB("Error in call to addFocusDistances() 0x%x", ret); 486 } 487 } 488 else 489 { 490 CAMHAL_LOGEB("Error in call to getFocusDistances() 0x%x", ret); 491 } 492 493 LOG_FUNCTION_NAME_EXIT; 494 495 return ret; 496} 497 498status_t OMXCameraAdapter::getFocusDistances(OMX_U32 &near,OMX_U32 &optimal, OMX_U32 &far) 499{ 500 status_t ret = NO_ERROR; 501 OMX_ERRORTYPE eError; 502 503 OMX_TI_CONFIG_FOCUSDISTANCETYPE focusDist; 504 505 LOG_FUNCTION_NAME; 506 507 if ( OMX_StateInvalid == mComponentState ) 508 { 509 CAMHAL_LOGEA("OMX component is in invalid state"); 510 ret = UNKNOWN_ERROR; 511 } 512 513 if ( NO_ERROR == ret ) 514 { 515 OMX_INIT_STRUCT_PTR(&focusDist, OMX_TI_CONFIG_FOCUSDISTANCETYPE); 516 focusDist.nPortIndex = mCameraAdapterParameters.mPrevPortIndex; 517 518 eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp, 519 ( OMX_INDEXTYPE ) OMX_TI_IndexConfigFocusDistance, 520 &focusDist); 521 if ( OMX_ErrorNone != eError ) 522 { 523 CAMHAL_LOGEB("Error while querying focus distances 0x%x", eError); 524 ret = UNKNOWN_ERROR; 525 } 526 527 } 528 529 if ( NO_ERROR == ret ) 530 { 531 near = focusDist.nFocusDistanceNear; 532 optimal = focusDist.nFocusDistanceOptimal; 533 far = focusDist.nFocusDistanceFar; 534 } 535 536 LOG_FUNCTION_NAME_EXIT; 537 538 return ret; 539} 540 541status_t OMXCameraAdapter::encodeFocusDistance(OMX_U32 dist, char *buffer, size_t length) 542{ 543 status_t ret = NO_ERROR; 544 uint32_t focusScale = 1000; 545 float distFinal; 546 547 LOG_FUNCTION_NAME; 548 549 if(mParameters3A.Focus == OMX_IMAGE_FocusControlAutoInfinity) 550 { 551 dist=0; 552 } 553 554 if ( NO_ERROR == ret ) 555 { 556 if ( 0 == dist ) 557 { 558 strncpy(buffer, CameraParameters::FOCUS_DISTANCE_INFINITY, ( length - 1 )); 559 } 560 else 561 { 562 distFinal = dist; 563 distFinal /= focusScale; 564 snprintf(buffer, ( length - 1 ) , "%5.3f", distFinal); 565 } 566 } 567 568 LOG_FUNCTION_NAME_EXIT; 569 570 return ret; 571} 572 573status_t OMXCameraAdapter::addFocusDistances(OMX_U32 &near, 574 OMX_U32 &optimal, 575 OMX_U32 &far, 576 CameraParameters& params) 577{ 578 status_t ret = NO_ERROR; 579 580 LOG_FUNCTION_NAME; 581 582 if ( NO_ERROR == ret ) 583 { 584 ret = encodeFocusDistance(near, mFocusDistNear, FOCUS_DIST_SIZE); 585 if ( NO_ERROR != ret ) 586 { 587 CAMHAL_LOGEB("Error encoding near focus distance 0x%x", ret); 588 } 589 } 590 591 if ( NO_ERROR == ret ) 592 { 593 ret = encodeFocusDistance(optimal, mFocusDistOptimal, 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(far, mFocusDistFar, 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 snprintf(mFocusDistBuffer, ( FOCUS_DIST_BUFFER_SIZE - 1) ,"%s,%s,%s", mFocusDistNear, 612 mFocusDistOptimal, 613 mFocusDistFar); 614 615 params.set(CameraParameters::KEY_FOCUS_DISTANCES, mFocusDistBuffer); 616 } 617 618 LOG_FUNCTION_NAME_EXIT; 619 620 return ret; 621} 622 623status_t OMXCameraAdapter::setTouchFocus(size_t posX, 624 size_t posY, 625 size_t posWidth, 626 size_t posHeight, 627 size_t previewWidth, 628 size_t previewHeight) 629{ 630 status_t ret = NO_ERROR; 631 OMX_ERRORTYPE eError = OMX_ErrorNone; 632 OMX_CONFIG_EXTFOCUSREGIONTYPE touchControl; 633 634 LOG_FUNCTION_NAME; 635 636 if ( OMX_StateInvalid == mComponentState ) 637 { 638 CAMHAL_LOGEA("OMX component is in invalid state"); 639 ret = -1; 640 } 641 642 if ( NO_ERROR == ret ) 643 { 644 OMX_INIT_STRUCT_PTR (&touchControl, OMX_CONFIG_EXTFOCUSREGIONTYPE); 645 touchControl.nLeft = ( posX * TOUCH_FOCUS_RANGE ) / previewWidth; 646 touchControl.nTop = ( posY * TOUCH_FOCUS_RANGE ) / previewHeight; 647 touchControl.nWidth = ( posWidth * TOUCH_FOCUS_RANGE ) / previewWidth; 648 touchControl.nHeight = ( posHeight * TOUCH_FOCUS_RANGE ) / previewHeight; 649 650 eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, 651 ( OMX_INDEXTYPE ) OMX_IndexConfigExtFocusRegion, 652 &touchControl); 653 if ( OMX_ErrorNone != eError ) 654 { 655 CAMHAL_LOGEB("Error while configuring touch focus 0x%x", eError); 656 ret = -1; 657 } 658 else 659 { 660 CAMHAL_LOGDB("Touch focus %d,%d %d,%d configured successfuly", 661 ( int ) touchControl.nLeft, 662 ( int ) touchControl.nTop, 663 ( int ) touchControl.nWidth, 664 ( int ) touchControl.nHeight); 665 } 666 } 667 668 LOG_FUNCTION_NAME_EXIT; 669 670 return ret; 671} 672 673}; 674