| /* |
| * Copyright (C) Texas Instruments - http://www.ti.com/ |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| |
| /** |
| * @file OMXFocus.cpp |
| * |
| * This file contains functionality for handling focus configurations. |
| * |
| */ |
| |
| #undef LOG_TAG |
| |
| #define LOG_TAG "CameraHAL" |
| |
| #include "CameraHal.h" |
| #include "OMXCameraAdapter.h" |
| #include "ErrorUtils.h" |
| |
| #define TOUCH_FOCUS_RANGE 0xFF |
| #define AF_IMAGE_CALLBACK_TIMEOUT 5000000 //5 seconds timeout |
| #define AF_VIDEO_CALLBACK_TIMEOUT 2800000 //2.8 seconds timeout |
| |
| namespace android { |
| |
| status_t OMXCameraAdapter::setParametersFocus(const CameraParameters ¶ms, |
| BaseCameraAdapter::AdapterState state) |
| { |
| status_t ret = NO_ERROR; |
| const char *str = NULL; |
| Vector< sp<CameraArea> > tempAreas; |
| size_t MAX_FOCUS_AREAS; |
| |
| LOG_FUNCTION_NAME; |
| |
| Mutex::Autolock lock(mFocusAreasLock); |
| |
| str = params.get(CameraParameters::KEY_FOCUS_AREAS); |
| |
| MAX_FOCUS_AREAS = atoi(params.get(CameraParameters::KEY_MAX_NUM_FOCUS_AREAS)); |
| |
| if ( NULL != str ) { |
| ret = CameraArea::parseAreas(str, ( strlen(str) + 1 ), tempAreas); |
| } |
| |
| if ( (NO_ERROR == ret) && CameraArea::areAreasDifferent(mFocusAreas, tempAreas) ) { |
| mFocusAreas.clear(); |
| mFocusAreas = tempAreas; |
| if ( MAX_FOCUS_AREAS < mFocusAreas.size() ) { |
| CAMHAL_LOGEB("Focus areas supported %d, focus areas set %d", |
| MAX_FOCUS_AREAS, |
| mFocusAreas.size()); |
| ret = -EINVAL; |
| } |
| else { |
| if ( !mFocusAreas.isEmpty() ) { |
| setTouchFocus(); |
| } |
| } |
| } |
| |
| LOG_FUNCTION_NAME; |
| |
| return ret; |
| } |
| |
| status_t OMXCameraAdapter::doAutoFocus() |
| { |
| status_t ret = NO_ERROR; |
| OMX_ERRORTYPE eError = OMX_ErrorNone; |
| OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focusControl; |
| OMX_PARAM_FOCUSSTATUSTYPE focusStatus; |
| OMX_CONFIG_BOOLEANTYPE bOMX; |
| nsecs_t timeout = 0; |
| |
| LOG_FUNCTION_NAME; |
| |
| if ( OMX_StateInvalid == mComponentState ) |
| { |
| CAMHAL_LOGEA("OMX component in Invalid state"); |
| returnFocusStatus(false); |
| return -EINVAL; |
| } |
| |
| if ( OMX_StateExecuting != mComponentState ) |
| { |
| CAMHAL_LOGEA("OMX component not in executing state"); |
| returnFocusStatus(false); |
| return NO_ERROR; |
| } |
| |
| |
| if( ((AF_ACTIVE & getState()) != AF_ACTIVE) && ((AF_ACTIVE & getNextState()) != AF_ACTIVE) ) { |
| CAMHAL_LOGDA("Auto focus got canceled before doAutoFocus could be called"); |
| return NO_ERROR; |
| } |
| |
| OMX_INIT_STRUCT_PTR (&focusStatus, OMX_PARAM_FOCUSSTATUSTYPE); |
| |
| // If the app calls autoFocus, the camera will stop sending face callbacks. |
| pauseFaceDetection(true); |
| |
| // This is needed for applying FOCUS_REGION correctly |
| if ( (!mFocusAreas.isEmpty()) && (!mFocusAreas.itemAt(0)->isZeroArea())) |
| { |
| //Disable face priority |
| setAlgoPriority(FACE_PRIORITY, FOCUS_ALGO, false); |
| |
| //Enable region algorithm priority |
| setAlgoPriority(REGION_PRIORITY, FOCUS_ALGO, true); |
| } |
| |
| OMX_INIT_STRUCT_PTR (&focusControl, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE); |
| focusControl.eFocusControl = ( OMX_IMAGE_FOCUSCONTROLTYPE ) mParameters3A.Focus; |
| |
| if (mParameters3A.FocusLock) { |
| // this basically means user never called cancelAutoFocus after a scan... |
| // if this is the case we need to unlock AF to ensure we will do a scan |
| if (set3ALock(mUserSetExpLock, mUserSetWbLock, OMX_FALSE) != NO_ERROR) { |
| CAMHAL_LOGEA("Error Unlocking 3A locks"); |
| } else { |
| CAMHAL_LOGDA("AE/AWB unlocked successfully"); |
| } |
| |
| } else if ( mParameters3A.Focus == OMX_IMAGE_FocusControlAuto ) { |
| // In case we have CAF running we should first check the AF status. |
| // If it has managed to lock, then do as usual and return status |
| // immediately. |
| ret = checkFocus(&focusStatus); |
| if ( NO_ERROR != ret ) { |
| CAMHAL_LOGEB("Focus status check failed 0x%x!", ret); |
| return ret; |
| } else { |
| CAMHAL_LOGDB("Focus status check 0x%x!", focusStatus.eFocusStatus); |
| } |
| } |
| |
| if ( (focusControl.eFocusControl == OMX_IMAGE_FocusControlAuto |
| && (focusStatus.eFocusStatus == OMX_FocusStatusRequest |
| || focusStatus.eFocusStatus == OMX_FocusStatusUnableToReach) ) || |
| (mParameters3A.Focus != (OMX_IMAGE_FOCUSCONTROLTYPE)OMX_IMAGE_FocusControlAuto) ) |
| { |
| OMX_INIT_STRUCT_PTR (&bOMX, OMX_CONFIG_BOOLEANTYPE); |
| bOMX.bEnabled = OMX_TRUE; |
| |
| //Enable focus scanning |
| eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, |
| (OMX_INDEXTYPE)OMX_TI_IndexConfigAutofocusEnable, |
| &bOMX); |
| |
| // force AF, Ducati will take care of whether CAF |
| // or AF will be performed, depending on light conditions |
| if ( focusControl.eFocusControl == OMX_IMAGE_FocusControlAuto |
| && focusStatus.eFocusStatus == OMX_FocusStatusUnableToReach ) |
| { |
| focusControl.eFocusControl = OMX_IMAGE_FocusControlAutoLock; |
| } |
| |
| if ( focusControl.eFocusControl != OMX_IMAGE_FocusControlAuto ) |
| { |
| eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, |
| OMX_IndexConfigFocusControl, |
| &focusControl); |
| } |
| |
| if ( OMX_ErrorNone != eError ) { |
| CAMHAL_LOGEB("Error while starting focus 0x%x", eError); |
| return INVALID_OPERATION; |
| } else { |
| CAMHAL_LOGDA("Autofocus started successfully"); |
| } |
| |
| // configure focus timeout based on capture mode |
| timeout = (mCapMode == VIDEO_MODE) ? |
| ( ( nsecs_t ) AF_VIDEO_CALLBACK_TIMEOUT * 1000 ) : |
| ( ( nsecs_t ) AF_IMAGE_CALLBACK_TIMEOUT * 1000 ); |
| |
| { |
| Mutex::Autolock lock(mDoAFMutex); |
| ret = mDoAFCond.waitRelative(mDoAFMutex, timeout); |
| } |
| |
| //If somethiing bad happened while we wait |
| if (mComponentState == OMX_StateInvalid) { |
| CAMHAL_LOGEA("Invalid State after Auto Focus Exitting!!!"); |
| return -EINVAL; |
| } |
| |
| if(ret != NO_ERROR) { |
| CAMHAL_LOGEA("Autofocus callback timeout expired"); |
| ret = returnFocusStatus(true); |
| } else { |
| ret = returnFocusStatus(false); |
| } |
| } else { // Focus mode in continuous |
| if ( NO_ERROR == ret ) { |
| ret = returnFocusStatus(true); |
| mPending3Asettings |= SetFocus; |
| } |
| } |
| |
| LOG_FUNCTION_NAME_EXIT; |
| |
| return ret; |
| } |
| |
| status_t OMXCameraAdapter::stopAutoFocus() |
| { |
| OMX_ERRORTYPE eError = OMX_ErrorNone; |
| OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focusControl; |
| |
| LOG_FUNCTION_NAME; |
| |
| if ( OMX_StateInvalid == mComponentState ) |
| { |
| CAMHAL_LOGEA("OMX component in Invalid state"); |
| returnFocusStatus(false); |
| return -EINVAL; |
| } |
| |
| if ( OMX_StateExecuting != mComponentState ) |
| { |
| CAMHAL_LOGEA("OMX component not in executing state"); |
| return NO_ERROR; |
| } |
| |
| if ( mParameters3A.Focus == OMX_IMAGE_FocusControlAutoInfinity ) { |
| // No need to stop focus if we are in infinity mode. Nothing to stop. |
| return NO_ERROR; |
| } |
| |
| OMX_INIT_STRUCT_PTR (&focusControl, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE); |
| focusControl.eFocusControl = OMX_IMAGE_FocusControlOff; |
| |
| eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, |
| OMX_IndexConfigFocusControl, |
| &focusControl); |
| if ( OMX_ErrorNone != eError ) |
| { |
| CAMHAL_LOGEB("Error while stopping focus 0x%x", eError); |
| return ErrorUtils::omxToAndroidError(eError); |
| } else { |
| // This is a WA. Usually the OMX Camera component should |
| // generate AF status change OMX event fairly quickly |
| // ( after one preview frame ) and this notification should |
| // actually come from 'handleFocusCallback()'. |
| Mutex::Autolock lock(mDoAFMutex); |
| mDoAFCond.broadcast(); |
| } |
| |
| |
| LOG_FUNCTION_NAME_EXIT; |
| |
| return NO_ERROR; |
| } |
| |
| status_t OMXCameraAdapter::getFocusMode(OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE &focusMode) |
| {; |
| OMX_ERRORTYPE eError = OMX_ErrorNone; |
| |
| LOG_FUNCTION_NAME; |
| |
| if ( OMX_StateInvalid == mComponentState ) { |
| CAMHAL_LOGEA("OMX component is in invalid state"); |
| return NO_INIT; |
| } |
| |
| OMX_INIT_STRUCT_PTR (&focusMode, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE); |
| focusMode.nPortIndex = mCameraAdapterParameters.mPrevPortIndex; |
| |
| eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp, |
| OMX_IndexConfigFocusControl, |
| &focusMode); |
| |
| if ( OMX_ErrorNone != eError ) { |
| CAMHAL_LOGEB("Error while retrieving focus mode 0x%x", eError); |
| } |
| |
| LOG_FUNCTION_NAME_EXIT; |
| |
| return ErrorUtils::omxToAndroidError(eError); |
| } |
| |
| status_t OMXCameraAdapter::cancelAutoFocus() |
| { |
| status_t ret = NO_ERROR; |
| OMX_ERRORTYPE eError = OMX_ErrorNone; |
| OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focusMode; |
| |
| LOG_FUNCTION_NAME; |
| |
| ret = getFocusMode(focusMode); |
| if ( NO_ERROR != ret ) { |
| return ret; |
| } |
| |
| //Stop the AF only for modes other than CAF or Inifinity |
| if ( ( focusMode.eFocusControl != OMX_IMAGE_FocusControlAuto ) && |
| ( focusMode.eFocusControl != ( OMX_IMAGE_FOCUSCONTROLTYPE ) |
| OMX_IMAGE_FocusControlAutoInfinity ) ) { |
| stopAutoFocus(); |
| } else if (focusMode.eFocusControl == OMX_IMAGE_FocusControlAuto) { |
| // This re-enabling of CAF doesn't seem to |
| // be needed any more. |
| // re-apply CAF after unlocking and canceling |
| // mPending3Asettings |= SetFocus; |
| } |
| // If the apps call #cancelAutoFocus()}, the face callbacks will also resume. |
| pauseFaceDetection(false); |
| |
| LOG_FUNCTION_NAME_EXIT; |
| |
| return ret; |
| |
| } |
| |
| status_t OMXCameraAdapter::setFocusCallback(bool enabled) |
| { |
| status_t ret = NO_ERROR; |
| OMX_ERRORTYPE eError = OMX_ErrorNone; |
| OMX_CONFIG_CALLBACKREQUESTTYPE focusRequstCallback; |
| |
| LOG_FUNCTION_NAME; |
| |
| if ( OMX_StateInvalid == mComponentState ) |
| { |
| CAMHAL_LOGEA("OMX component in Invalid state"); |
| ret = -EINVAL; |
| } |
| |
| if ( OMX_StateExecuting != mComponentState ) |
| { |
| CAMHAL_LOGEA("OMX component not in executing state"); |
| ret = NO_ERROR; |
| } |
| |
| if ( NO_ERROR == ret ) |
| { |
| |
| OMX_INIT_STRUCT_PTR (&focusRequstCallback, OMX_CONFIG_CALLBACKREQUESTTYPE); |
| focusRequstCallback.nPortIndex = OMX_ALL; |
| focusRequstCallback.nIndex = OMX_IndexConfigCommonFocusStatus; |
| |
| if ( enabled ) |
| { |
| focusRequstCallback.bEnable = OMX_TRUE; |
| } |
| else |
| { |
| focusRequstCallback.bEnable = OMX_FALSE; |
| } |
| |
| eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, |
| (OMX_INDEXTYPE) OMX_IndexConfigCallbackRequest, |
| &focusRequstCallback); |
| if ( OMX_ErrorNone != eError ) |
| { |
| CAMHAL_LOGEB("Error registering focus callback 0x%x", eError); |
| ret = -1; |
| } |
| else |
| { |
| CAMHAL_LOGDB("Autofocus callback for index 0x%x registered successfully", |
| OMX_IndexConfigCommonFocusStatus); |
| } |
| } |
| |
| LOG_FUNCTION_NAME_EXIT; |
| |
| return ret; |
| } |
| |
| status_t OMXCameraAdapter::returnFocusStatus(bool timeoutReached) |
| { |
| status_t ret = NO_ERROR; |
| OMX_PARAM_FOCUSSTATUSTYPE eFocusStatus; |
| CameraHalEvent::FocusStatus focusStatus = CameraHalEvent::FOCUS_STATUS_FAIL; |
| BaseCameraAdapter::AdapterState state, nextState; |
| BaseCameraAdapter::getState(state); |
| BaseCameraAdapter::getNextState(nextState); |
| |
| LOG_FUNCTION_NAME; |
| |
| OMX_INIT_STRUCT(eFocusStatus, OMX_PARAM_FOCUSSTATUSTYPE); |
| |
| if( ((AF_ACTIVE & state ) != AF_ACTIVE) && ((AF_ACTIVE & nextState ) != AF_ACTIVE) ) |
| { |
| /// We don't send focus callback if focus was not started |
| CAMHAL_LOGDA("Not sending focus callback because focus was not started"); |
| return NO_ERROR; |
| } |
| |
| if ( NO_ERROR == ret ) |
| { |
| |
| if ( !timeoutReached ) |
| { |
| ret = checkFocus(&eFocusStatus); |
| |
| if ( NO_ERROR != ret ) |
| { |
| CAMHAL_LOGEA("Focus status check failed!"); |
| } |
| } |
| } |
| |
| if ( NO_ERROR == ret ) |
| { |
| |
| if ( timeoutReached ) |
| { |
| focusStatus = CameraHalEvent::FOCUS_STATUS_FAIL; |
| } |
| else |
| { |
| switch (eFocusStatus.eFocusStatus) |
| { |
| case OMX_FocusStatusReached: |
| { |
| focusStatus = CameraHalEvent::FOCUS_STATUS_SUCCESS; |
| break; |
| } |
| case OMX_FocusStatusOff: // AF got canceled |
| return NO_ERROR; |
| case OMX_FocusStatusUnableToReach: |
| case OMX_FocusStatusRequest: |
| default: |
| { |
| focusStatus = CameraHalEvent::FOCUS_STATUS_FAIL; |
| break; |
| } |
| } |
| // Lock CAF after AF call |
| if( set3ALock(mUserSetExpLock, mUserSetWbLock, OMX_TRUE) != NO_ERROR) { |
| CAMHAL_LOGEA("Error Applying 3A locks"); |
| } else { |
| CAMHAL_LOGDA("Focus locked. Applied focus locks successfully"); |
| } |
| stopAutoFocus(); |
| } |
| |
| //Query current focus distance after AF is complete |
| updateFocusDistances(mParameters); |
| } |
| |
| ret = BaseCameraAdapter::setState(CAMERA_CANCEL_AUTOFOCUS); |
| if ( NO_ERROR == ret ) |
| { |
| ret = BaseCameraAdapter::commitState(); |
| } |
| else |
| { |
| ret |= BaseCameraAdapter::rollbackState(); |
| } |
| |
| if ( NO_ERROR == ret ) |
| { |
| notifyFocusSubscribers(focusStatus); |
| } |
| |
| // After focus, face detection will resume sending face callbacks |
| pauseFaceDetection(false); |
| |
| LOG_FUNCTION_NAME_EXIT; |
| |
| return ret; |
| } |
| |
| status_t OMXCameraAdapter::checkFocus(OMX_PARAM_FOCUSSTATUSTYPE *eFocusStatus) |
| { |
| status_t ret = NO_ERROR; |
| OMX_ERRORTYPE eError = OMX_ErrorNone; |
| |
| LOG_FUNCTION_NAME; |
| |
| if ( NULL == eFocusStatus ) |
| { |
| CAMHAL_LOGEA("Invalid focus status"); |
| ret = -EINVAL; |
| } |
| |
| if ( OMX_StateInvalid == mComponentState ) |
| { |
| CAMHAL_LOGEA("OMX component in Invalid state"); |
| ret = -EINVAL; |
| } |
| |
| if ( OMX_StateExecuting != mComponentState ) |
| { |
| CAMHAL_LOGEA("OMX component not in executing state"); |
| ret = NO_ERROR; |
| } |
| |
| if ( NO_ERROR == ret ) |
| { |
| OMX_INIT_STRUCT_PTR (eFocusStatus, OMX_PARAM_FOCUSSTATUSTYPE); |
| eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp, |
| OMX_IndexConfigCommonFocusStatus, |
| eFocusStatus); |
| if ( OMX_ErrorNone != eError ) |
| { |
| CAMHAL_LOGEB("Error while retrieving focus status: 0x%x", eError); |
| ret = -1; |
| } |
| } |
| |
| if ( NO_ERROR == ret ) |
| { |
| CAMHAL_LOGDB("Focus Status: %d", eFocusStatus->eFocusStatus); |
| } |
| |
| LOG_FUNCTION_NAME_EXIT; |
| |
| return ret; |
| } |
| |
| status_t OMXCameraAdapter::updateFocusDistances(CameraParameters ¶ms) |
| { |
| OMX_U32 focusNear, focusOptimal, focusFar; |
| status_t ret = NO_ERROR; |
| |
| LOG_FUNCTION_NAME; |
| |
| ret = getFocusDistances(focusNear, focusOptimal, focusFar); |
| if ( NO_ERROR == ret) |
| { |
| ret = addFocusDistances(focusNear, focusOptimal, focusFar, params); |
| if ( NO_ERROR != ret ) |
| { |
| CAMHAL_LOGEB("Error in call to addFocusDistances() 0x%x", ret); |
| } |
| } |
| else |
| { |
| CAMHAL_LOGEB("Error in call to getFocusDistances() 0x%x", ret); |
| } |
| |
| LOG_FUNCTION_NAME_EXIT; |
| |
| return ret; |
| } |
| |
| status_t OMXCameraAdapter::getFocusDistances(OMX_U32 &near,OMX_U32 &optimal, OMX_U32 &far) |
| { |
| status_t ret = NO_ERROR; |
| OMX_ERRORTYPE eError; |
| |
| OMX_TI_CONFIG_FOCUSDISTANCETYPE focusDist; |
| |
| LOG_FUNCTION_NAME; |
| |
| if ( OMX_StateInvalid == mComponentState ) |
| { |
| CAMHAL_LOGEA("OMX component is in invalid state"); |
| ret = UNKNOWN_ERROR; |
| } |
| |
| if ( NO_ERROR == ret ) |
| { |
| OMX_INIT_STRUCT_PTR(&focusDist, OMX_TI_CONFIG_FOCUSDISTANCETYPE); |
| focusDist.nPortIndex = mCameraAdapterParameters.mPrevPortIndex; |
| |
| eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp, |
| ( OMX_INDEXTYPE ) OMX_TI_IndexConfigFocusDistance, |
| &focusDist); |
| if ( OMX_ErrorNone != eError ) |
| { |
| CAMHAL_LOGEB("Error while querying focus distances 0x%x", eError); |
| ret = UNKNOWN_ERROR; |
| } |
| |
| } |
| |
| if ( NO_ERROR == ret ) |
| { |
| near = focusDist.nFocusDistanceNear; |
| optimal = focusDist.nFocusDistanceOptimal; |
| far = focusDist.nFocusDistanceFar; |
| } |
| |
| LOG_FUNCTION_NAME_EXIT; |
| |
| return ret; |
| } |
| |
| status_t OMXCameraAdapter::encodeFocusDistance(OMX_U32 dist, char *buffer, size_t length) |
| { |
| status_t ret = NO_ERROR; |
| uint32_t focusScale = 1000; |
| float distFinal; |
| |
| LOG_FUNCTION_NAME; |
| |
| if(mParameters3A.Focus == OMX_IMAGE_FocusControlAutoInfinity) |
| { |
| dist=0; |
| } |
| |
| if ( NO_ERROR == ret ) |
| { |
| if ( 0 == dist ) |
| { |
| strncpy(buffer, CameraParameters::FOCUS_DISTANCE_INFINITY, ( length - 1 )); |
| } |
| else |
| { |
| distFinal = dist; |
| distFinal /= focusScale; |
| snprintf(buffer, ( length - 1 ) , "%5.3f", distFinal); |
| } |
| } |
| |
| LOG_FUNCTION_NAME_EXIT; |
| |
| return ret; |
| } |
| |
| status_t OMXCameraAdapter::addFocusDistances(OMX_U32 &near, |
| OMX_U32 &optimal, |
| OMX_U32 &far, |
| CameraParameters& params) |
| { |
| status_t ret = NO_ERROR; |
| |
| LOG_FUNCTION_NAME; |
| |
| if ( NO_ERROR == ret ) |
| { |
| ret = encodeFocusDistance(near, mFocusDistNear, FOCUS_DIST_SIZE); |
| if ( NO_ERROR != ret ) |
| { |
| CAMHAL_LOGEB("Error encoding near focus distance 0x%x", ret); |
| } |
| } |
| |
| if ( NO_ERROR == ret ) |
| { |
| ret = encodeFocusDistance(optimal, mFocusDistOptimal, FOCUS_DIST_SIZE); |
| if ( NO_ERROR != ret ) |
| { |
| CAMHAL_LOGEB("Error encoding near focus distance 0x%x", ret); |
| } |
| } |
| |
| if ( NO_ERROR == ret ) |
| { |
| ret = encodeFocusDistance(far, mFocusDistFar, FOCUS_DIST_SIZE); |
| if ( NO_ERROR != ret ) |
| { |
| CAMHAL_LOGEB("Error encoding near focus distance 0x%x", ret); |
| } |
| } |
| |
| if ( NO_ERROR == ret ) |
| { |
| snprintf(mFocusDistBuffer, ( FOCUS_DIST_BUFFER_SIZE - 1) ,"%s,%s,%s", mFocusDistNear, |
| mFocusDistOptimal, |
| mFocusDistFar); |
| |
| params.set(CameraParameters::KEY_FOCUS_DISTANCES, mFocusDistBuffer); |
| } |
| |
| LOG_FUNCTION_NAME_EXIT; |
| |
| return ret; |
| } |
| |
| status_t OMXCameraAdapter::setTouchFocus() |
| { |
| status_t ret = NO_ERROR; |
| OMX_ERRORTYPE eError = OMX_ErrorNone; |
| |
| OMX_ALGOAREASTYPE **focusAreas; |
| OMX_TI_CONFIG_SHAREDBUFFER sharedBuffer; |
| MemoryManager memMgr; |
| int areasSize = 0; |
| |
| LOG_FUNCTION_NAME; |
| |
| if ( OMX_StateInvalid == mComponentState ) |
| { |
| CAMHAL_LOGEA("OMX component is in invalid state"); |
| ret = -1; |
| } |
| |
| if ( NO_ERROR == ret ) |
| { |
| |
| areasSize = ((sizeof(OMX_ALGOAREASTYPE)+4095)/4096)*4096; |
| focusAreas = (OMX_ALGOAREASTYPE**) memMgr.allocateBuffer(0, 0, NULL, areasSize, 1); |
| |
| OMXCameraPortParameters * mPreviewData = NULL; |
| mPreviewData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex]; |
| |
| if (!focusAreas) |
| { |
| CAMHAL_LOGEB("Error allocating buffer for focus areas %d", eError); |
| return -ENOMEM; |
| } |
| |
| OMX_INIT_STRUCT_PTR (focusAreas[0], OMX_ALGOAREASTYPE); |
| |
| focusAreas[0]->nPortIndex = OMX_ALL; |
| focusAreas[0]->nNumAreas = mFocusAreas.size(); |
| focusAreas[0]->nAlgoAreaPurpose = OMX_AlgoAreaFocus; |
| |
| // If the area is the special case of (0, 0, 0, 0, 0), then |
| // the algorithm needs nNumAreas to be set to 0, |
| // in order to automatically choose the best fitting areas. |
| if ( mFocusAreas.itemAt(0)->isZeroArea() ) |
| { |
| focusAreas[0]->nNumAreas = 0; |
| } |
| |
| for ( unsigned int n = 0; n < mFocusAreas.size(); n++) |
| { |
| // transform the coordinates to 3A-type coordinates |
| mFocusAreas.itemAt(n)->transfrom((size_t)mPreviewData->mWidth, |
| (size_t)mPreviewData->mHeight, |
| (size_t&)focusAreas[0]->tAlgoAreas[n].nTop, |
| (size_t&)focusAreas[0]->tAlgoAreas[n].nLeft, |
| (size_t&)focusAreas[0]->tAlgoAreas[n].nWidth, |
| (size_t&)focusAreas[0]->tAlgoAreas[n].nHeight); |
| |
| focusAreas[0]->tAlgoAreas[n].nLeft = |
| ( focusAreas[0]->tAlgoAreas[n].nLeft * TOUCH_FOCUS_RANGE ) / mPreviewData->mWidth; |
| focusAreas[0]->tAlgoAreas[n].nTop = |
| ( focusAreas[0]->tAlgoAreas[n].nTop* TOUCH_FOCUS_RANGE ) / mPreviewData->mHeight; |
| focusAreas[0]->tAlgoAreas[n].nWidth = |
| ( focusAreas[0]->tAlgoAreas[n].nWidth * TOUCH_FOCUS_RANGE ) / mPreviewData->mWidth; |
| focusAreas[0]->tAlgoAreas[n].nHeight = |
| ( focusAreas[0]->tAlgoAreas[n].nHeight * TOUCH_FOCUS_RANGE ) / mPreviewData->mHeight; |
| focusAreas[0]->tAlgoAreas[n].nPriority = mFocusAreas.itemAt(n)->getWeight(); |
| |
| CAMHAL_LOGDB("Focus area %d : top = %d left = %d width = %d height = %d prio = %d", |
| n, (int)focusAreas[0]->tAlgoAreas[n].nTop, (int)focusAreas[0]->tAlgoAreas[n].nLeft, |
| (int)focusAreas[0]->tAlgoAreas[n].nWidth, (int)focusAreas[0]->tAlgoAreas[n].nHeight, |
| (int)focusAreas[0]->tAlgoAreas[n].nPriority); |
| } |
| |
| OMX_INIT_STRUCT_PTR (&sharedBuffer, OMX_TI_CONFIG_SHAREDBUFFER); |
| |
| sharedBuffer.nPortIndex = OMX_ALL; |
| sharedBuffer.nSharedBuffSize = areasSize; |
| sharedBuffer.pSharedBuff = (OMX_U8 *) focusAreas[0]; |
| |
| if ( NULL == sharedBuffer.pSharedBuff ) |
| { |
| CAMHAL_LOGEA("No resources to allocate OMX shared buffer"); |
| ret = -ENOMEM; |
| goto EXIT; |
| } |
| |
| eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, |
| (OMX_INDEXTYPE) OMX_TI_IndexConfigAlgoAreas, &sharedBuffer); |
| |
| if ( OMX_ErrorNone != eError ) |
| { |
| CAMHAL_LOGEB("Error while setting Focus Areas configuration 0x%x", eError); |
| ret = -EINVAL; |
| } |
| |
| EXIT: |
| if (NULL != focusAreas) |
| { |
| memMgr.freeBuffer((void*) focusAreas); |
| focusAreas = NULL; |
| } |
| } |
| |
| LOG_FUNCTION_NAME_EXIT; |
| |
| return ret; |
| } |
| |
| void OMXCameraAdapter::handleFocusCallback() { |
| OMX_PARAM_FOCUSSTATUSTYPE eFocusStatus; |
| CameraHalEvent::FocusStatus focusStatus = CameraHalEvent::FOCUS_STATUS_FAIL; |
| status_t ret = NO_ERROR; |
| BaseCameraAdapter::AdapterState nextState; |
| BaseCameraAdapter::getNextState(nextState); |
| |
| OMX_INIT_STRUCT(eFocusStatus, OMX_PARAM_FOCUSSTATUSTYPE); |
| |
| ret = checkFocus(&eFocusStatus); |
| |
| if (NO_ERROR != ret) { |
| CAMHAL_LOGEA("Focus status check failed!"); |
| // signal and unblock doAutoFocus |
| if (AF_ACTIVE & nextState) { |
| Mutex::Autolock lock(mDoAFMutex); |
| mDoAFCond.broadcast(); |
| } |
| return; |
| } |
| |
| if ( ( eFocusStatus.eFocusStatus != OMX_FocusStatusRequest ) && |
| ( eFocusStatus.eFocusStatus != OMX_FocusStatusOff ) ) { |
| // signal doAutoFocus when a end of scan message comes |
| // ignore start of scan |
| Mutex::Autolock lock(mDoAFMutex); |
| mDoAFCond.broadcast(); |
| } |
| |
| if (mParameters3A.Focus != (OMX_IMAGE_FOCUSCONTROLTYPE) OMX_IMAGE_FocusControlAuto) { |
| CAMHAL_LOGDA("unregistered focus callback when not in CAF or doAutoFocus... not handling"); |
| return; |
| } |
| |
| // Handling for CAF Callbacks |
| switch (eFocusStatus.eFocusStatus) { |
| case OMX_FocusStatusRequest: |
| focusStatus = CameraHalEvent::FOCUS_STATUS_PENDING; |
| break; |
| case OMX_FocusStatusReached: |
| case OMX_FocusStatusOff: |
| case OMX_FocusStatusUnableToReach: |
| default: |
| focusStatus = CameraHalEvent::FOCUS_STATUS_DONE; |
| break; |
| } |
| |
| notifyFocusSubscribers(focusStatus); |
| } |
| |
| }; |