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#include "CameraHal.h"
26#include "OMXCameraAdapter.h"
27#include "ErrorUtils.h"
28
29#define TOUCH_FOCUS_RANGE 0xFF
30#define AF_IMAGE_CALLBACK_TIMEOUT 5000000 //5 seconds timeout
31#define AF_VIDEO_CALLBACK_TIMEOUT 2800000 //2.8 seconds timeout
32
33namespace Ti {
34namespace Camera {
35
36const nsecs_t OMXCameraAdapter::CANCEL_AF_TIMEOUT =  seconds_to_nanoseconds(1);
37
38status_t OMXCameraAdapter::setParametersFocus(const android::CameraParameters &params,
39                                              BaseCameraAdapter::AdapterState state)
40{
41    status_t ret = NO_ERROR;
42    const char *str = NULL;
43    android::Vector<android::sp<CameraArea> > tempAreas;
44    size_t MAX_FOCUS_AREAS;
45
46    LOG_FUNCTION_NAME;
47
48    android::AutoMutex lock(mFocusAreasLock);
49
50    str = params.get(android::CameraParameters::KEY_FOCUS_AREAS);
51
52    MAX_FOCUS_AREAS = atoi(params.get(android::CameraParameters::KEY_MAX_NUM_FOCUS_AREAS));
53
54    if ( NULL != str ) {
55        ret = CameraArea::parseAreas(str, ( strlen(str) + 1 ), tempAreas);
56    }
57
58    if ( (NO_ERROR == ret) && CameraArea::areAreasDifferent(mFocusAreas, tempAreas) ) {
59        mFocusAreas.clear();
60        mFocusAreas = tempAreas;
61        if ( MAX_FOCUS_AREAS < mFocusAreas.size() ) {
62            CAMHAL_LOGEB("Focus areas supported %d, focus areas set %d",
63                         MAX_FOCUS_AREAS,
64                         mFocusAreas.size());
65            ret = -EINVAL;
66        }
67        else {
68            if ( !mFocusAreas.isEmpty() ) {
69                setTouchFocus();
70            }
71        }
72    }
73
74    LOG_FUNCTION_NAME_EXIT;
75
76    return ret;
77}
78
79status_t OMXCameraAdapter::doAutoFocus()
80{
81    status_t ret = NO_ERROR;
82    OMX_ERRORTYPE eError = OMX_ErrorNone;
83    OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focusControl;
84    OMX_PARAM_FOCUSSTATUSTYPE focusStatus;
85    OMX_CONFIG_BOOLEANTYPE bOMX;
86    CameraAdapter::AdapterState state;
87    nsecs_t timeout = 0;
88
89    LOG_FUNCTION_NAME;
90
91    if ( OMX_StateInvalid == mComponentState )
92      {
93        CAMHAL_LOGEA("OMX component in Invalid state");
94        returnFocusStatus(false);
95        return -EINVAL;
96      }
97
98    if ( OMX_StateExecuting != mComponentState )
99        {
100        CAMHAL_LOGEA("OMX component not in executing state");
101        returnFocusStatus(false);
102        return NO_ERROR;
103        }
104
105    if( ((AF_ACTIVE & getState()) != AF_ACTIVE) && ((AF_ACTIVE & getNextState()) != AF_ACTIVE) ) {
106       CAMHAL_LOGDA("Auto focus got canceled before doAutoFocus could be called");
107       return NO_ERROR;
108    }
109
110    // AF when fixed focus modes are set should be a no-op.
111    if ( ( mParameters3A.Focus == OMX_IMAGE_FocusControlOff ) ||
112         ( mParameters3A.Focus == OMX_IMAGE_FocusControlAutoInfinity ) ||
113         ( mParameters3A.Focus == OMX_IMAGE_FocusControlHyperfocal ) ) {
114        returnFocusStatus(true);
115        return NO_ERROR;
116    }
117
118    OMX_INIT_STRUCT_PTR (&focusStatus, OMX_PARAM_FOCUSSTATUSTYPE);
119
120    // If the app calls autoFocus, the camera will stop sending face callbacks.
121    pauseFaceDetection(true);
122
123    // This is needed for applying FOCUS_REGION correctly
124    if ( (!mFocusAreas.isEmpty()) && (!mFocusAreas.itemAt(0)->isZeroArea()))
125    {
126    //Disable face priority
127    setAlgoPriority(FACE_PRIORITY, FOCUS_ALGO, false);
128
129    //Enable region algorithm priority
130    setAlgoPriority(REGION_PRIORITY, FOCUS_ALGO, true);
131    }
132
133    OMX_INIT_STRUCT_PTR (&focusControl, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE);
134    focusControl.eFocusControl = ( OMX_IMAGE_FOCUSCONTROLTYPE ) mParameters3A.Focus;
135
136    if (mParameters3A.FocusLock) {
137        // this basically means user never called cancelAutoFocus after a scan...
138        // if this is the case we need to unlock AF to ensure we will do a scan
139        if (set3ALock(mUserSetExpLock, mUserSetWbLock, OMX_FALSE) != NO_ERROR) {
140            CAMHAL_LOGEA("Error Unlocking 3A locks");
141        } else {
142            CAMHAL_LOGDA("AE/AWB unlocked successfully");
143        }
144
145    } else if ( mParameters3A.Focus == OMX_IMAGE_FocusControlAuto ) {
146        // In case we have CAF running we should first check the AF status.
147        // If it has managed to lock, then do as usual and return status
148        // immediately.
149        ret = checkFocus(&focusStatus);
150        if ( NO_ERROR != ret ) {
151            CAMHAL_LOGEB("Focus status check failed 0x%x!", ret);
152            return ret;
153        } else {
154            CAMHAL_LOGDB("Focus status check 0x%x!", focusStatus.eFocusStatus);
155        }
156    }
157
158    if ( (focusControl.eFocusControl == OMX_IMAGE_FocusControlAuto &&
159         ( focusStatus.eFocusStatus == OMX_FocusStatusRequest ||
160           focusStatus.eFocusStatus == OMX_FocusStatusUnableToReach ||
161           focusStatus.eFocusStatus == OMX_FocusStatusLost ) ) ||
162            (mParameters3A.Focus !=  (OMX_IMAGE_FOCUSCONTROLTYPE)OMX_IMAGE_FocusControlAuto) ) {
163        OMX_INIT_STRUCT_PTR (&bOMX, OMX_CONFIG_BOOLEANTYPE);
164        bOMX.bEnabled = OMX_TRUE;
165
166        //Enable focus scanning
167        eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
168                               (OMX_INDEXTYPE)OMX_TI_IndexConfigAutofocusEnable,
169                               &bOMX);
170        if ( OMX_ErrorNone != eError ) {
171            return Utils::ErrorUtils::omxToAndroidError(eError);
172        }
173
174        {
175            android::AutoMutex lock(mDoAFMutex);
176
177        // force AF, Ducati will take care of whether CAF
178        // or AF will be performed, depending on light conditions
179        if ( focusControl.eFocusControl == OMX_IMAGE_FocusControlAuto &&
180             ( focusStatus.eFocusStatus == OMX_FocusStatusUnableToReach ||
181               focusStatus.eFocusStatus == OMX_FocusStatusLost ) ) {
182            focusControl.eFocusControl = OMX_IMAGE_FocusControlAutoLock;
183        }
184
185            eError =  OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
186                                    OMX_IndexConfigFocusControl,
187                                    &focusControl);
188
189            if ( OMX_ErrorNone != eError ) {
190                CAMHAL_LOGEB("Error while starting focus 0x%x", eError);
191                return INVALID_OPERATION;
192            } else {
193                CAMHAL_LOGDA("Autofocus started successfully");
194            }
195
196            // No need to wait if preview is about to stop
197            getNextState(state);
198            if ( ( PREVIEW_ACTIVE & state ) != PREVIEW_ACTIVE ) {
199                return NO_ERROR;
200            }
201
202            // configure focus timeout based on capture mode
203            timeout = (mCapMode == VIDEO_MODE) || (mCapMode == VIDEO_MODE_HQ) ?
204                            ( ( nsecs_t ) AF_VIDEO_CALLBACK_TIMEOUT * 1000 ) :
205                            ( ( nsecs_t ) AF_IMAGE_CALLBACK_TIMEOUT * 1000 );
206
207
208            ret = mDoAFCond.waitRelative(mDoAFMutex, timeout);
209        }
210
211        //If somethiing bad happened while we wait
212        if (mComponentState == OMX_StateInvalid) {
213          CAMHAL_LOGEA("Invalid State after Auto Focus Exitting!!!");
214          return -EINVAL;
215        }
216
217        if(ret != NO_ERROR) {
218            CAMHAL_LOGEA("Autofocus callback timeout expired");
219            ret = returnFocusStatus(true);
220        } else {
221            CAMHAL_LOGDA("Autofocus callback received");
222            ret = returnFocusStatus(false);
223        }
224    } else { // Focus mode in continuous
225        if ( NO_ERROR == ret ) {
226            ret = returnFocusStatus(true);
227            mPending3Asettings |= SetFocus;
228        }
229    }
230
231    LOG_FUNCTION_NAME_EXIT;
232
233    return ret;
234}
235
236status_t OMXCameraAdapter::stopAutoFocus()
237{
238    OMX_ERRORTYPE eError = OMX_ErrorNone;
239    OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focusControl;
240
241    LOG_FUNCTION_NAME;
242
243    if ( OMX_StateInvalid == mComponentState )  {
244        CAMHAL_LOGEA("OMX component in Invalid state");
245        returnFocusStatus(false);
246        return -EINVAL;
247    }
248
249    if ( OMX_StateExecuting != mComponentState ) {
250          CAMHAL_LOGEA("OMX component not in executing state");
251        return NO_ERROR;
252    }
253
254    if ( mParameters3A.Focus == OMX_IMAGE_FocusControlAutoInfinity ) {
255        // No need to stop focus if we are in infinity mode. Nothing to stop.
256        return NO_ERROR;
257    }
258
259    OMX_INIT_STRUCT_PTR (&focusControl, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE);
260    focusControl.eFocusControl = OMX_IMAGE_FocusControlOff;
261
262    eError =  OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
263                            OMX_IndexConfigFocusControl,
264                            &focusControl);
265    if ( OMX_ErrorNone != eError ) {
266        CAMHAL_LOGEB("Error while stopping focus 0x%x", eError);
267        return Utils::ErrorUtils::omxToAndroidError(eError);
268    }
269#ifdef CAMERAHAL_TUNA
270    else {
271        // This is a WA. Usually the OMX Camera component should
272        // generate AF status change OMX event fairly quickly
273        // ( after one preview frame ) and this notification should
274        // actually come from 'handleFocusCallback()'.
275        android::AutoMutex lock(mDoAFMutex);
276        mDoAFCond.broadcast();
277    }
278#endif
279
280    LOG_FUNCTION_NAME_EXIT;
281
282    return NO_ERROR;
283}
284
285status_t OMXCameraAdapter::getFocusMode(OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE &focusMode)
286{;
287    OMX_ERRORTYPE eError = OMX_ErrorNone;
288
289    LOG_FUNCTION_NAME;
290
291    if ( OMX_StateInvalid == mComponentState ) {
292        CAMHAL_LOGEA("OMX component is in invalid state");
293        return NO_INIT;
294    }
295
296    OMX_INIT_STRUCT_PTR (&focusMode, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE);
297    focusMode.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
298
299    eError =  OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
300                            OMX_IndexConfigFocusControl,
301                            &focusMode);
302
303    if ( OMX_ErrorNone != eError ) {
304        CAMHAL_LOGEB("Error while retrieving focus mode 0x%x", eError);
305    }
306
307    LOG_FUNCTION_NAME_EXIT;
308
309    return Utils::ErrorUtils::omxToAndroidError(eError);
310}
311
312status_t OMXCameraAdapter::cancelAutoFocus()
313{
314    status_t ret = NO_ERROR;
315    OMX_ERRORTYPE eError = OMX_ErrorNone;
316    OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focusMode;
317
318    LOG_FUNCTION_NAME;
319
320    ret = getFocusMode(focusMode);
321    if ( NO_ERROR != ret ) {
322        return ret;
323    }
324
325    //Stop the AF only for modes other than CAF, Inifinity or Off
326    if ( ( focusMode.eFocusControl != OMX_IMAGE_FocusControlAuto ) &&
327         ( focusMode.eFocusControl != ( OMX_IMAGE_FOCUSCONTROLTYPE )
328                 OMX_IMAGE_FocusControlAutoInfinity ) &&
329         ( focusMode.eFocusControl != OMX_IMAGE_FocusControlOff ) ) {
330        android::AutoMutex lock(mCancelAFMutex);
331        stopAutoFocus();
332        ret = mCancelAFCond.waitRelative(mCancelAFMutex, CANCEL_AF_TIMEOUT);
333        if ( NO_ERROR != ret ) {
334            CAMHAL_LOGE("Cancel AF timeout!");
335        }
336    } else if (focusMode.eFocusControl == OMX_IMAGE_FocusControlAuto) {
337       // This re-enabling of CAF doesn't seem to
338       // be needed any more.
339       // re-apply CAF after unlocking and canceling
340       // mPending3Asettings |= SetFocus;
341    }
342
343    {
344        // Signal to 'doAutoFocus()'
345        android::AutoMutex lock(mDoAFMutex);
346        mDoAFCond.broadcast();
347    }
348
349    // If the apps call #cancelAutoFocus()}, the face callbacks will also resume.
350    pauseFaceDetection(false);
351
352    LOG_FUNCTION_NAME_EXIT;
353
354    return ret;
355
356}
357
358status_t OMXCameraAdapter::setFocusCallback(bool enabled)
359{
360    status_t ret = NO_ERROR;
361    OMX_ERRORTYPE eError = OMX_ErrorNone;
362    OMX_CONFIG_CALLBACKREQUESTTYPE focusRequstCallback;
363
364    LOG_FUNCTION_NAME;
365
366    if ( OMX_StateInvalid == mComponentState )
367      {
368        CAMHAL_LOGEA("OMX component in Invalid state");
369        ret = -EINVAL;
370      }
371
372    if ( OMX_StateExecuting != mComponentState )
373        {
374          CAMHAL_LOGEA("OMX component not in executing state");
375        return NO_ERROR;
376        }
377
378    if ( NO_ERROR == ret )
379        {
380
381        OMX_INIT_STRUCT_PTR (&focusRequstCallback, OMX_CONFIG_CALLBACKREQUESTTYPE);
382        focusRequstCallback.nPortIndex = OMX_ALL;
383        focusRequstCallback.nIndex = OMX_IndexConfigCommonFocusStatus;
384
385        if ( enabled )
386            {
387            focusRequstCallback.bEnable = OMX_TRUE;
388            }
389        else
390            {
391            focusRequstCallback.bEnable = OMX_FALSE;
392            }
393
394        eError =  OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
395                                (OMX_INDEXTYPE) OMX_IndexConfigCallbackRequest,
396                                &focusRequstCallback);
397        if ( OMX_ErrorNone != eError )
398            {
399            CAMHAL_LOGEB("Error registering focus callback 0x%x", eError);
400            ret = -1;
401            }
402        else
403            {
404            CAMHAL_LOGDB("Autofocus callback for index 0x%x registered successfully",
405                         OMX_IndexConfigCommonFocusStatus);
406            }
407        }
408
409    LOG_FUNCTION_NAME_EXIT;
410
411    return ret;
412}
413
414status_t OMXCameraAdapter::returnFocusStatus(bool timeoutReached)
415{
416    status_t ret = NO_ERROR;
417    OMX_PARAM_FOCUSSTATUSTYPE eFocusStatus;
418    CameraHalEvent::FocusStatus focusStatus = CameraHalEvent::FOCUS_STATUS_FAIL;
419    BaseCameraAdapter::AdapterState state, nextState;
420    BaseCameraAdapter::getState(state);
421    BaseCameraAdapter::getNextState(nextState);
422
423    LOG_FUNCTION_NAME;
424
425    OMX_INIT_STRUCT(eFocusStatus, OMX_PARAM_FOCUSSTATUSTYPE);
426
427    if( ((AF_ACTIVE & state ) != AF_ACTIVE) && ((AF_ACTIVE & nextState ) != AF_ACTIVE) )
428       {
429        /// We don't send focus callback if focus was not started
430       CAMHAL_LOGDA("Not sending focus callback because focus was not started");
431       return NO_ERROR;
432       }
433
434    if ( NO_ERROR == ret )
435        {
436
437        if ( !timeoutReached )
438            {
439            ret = checkFocus(&eFocusStatus);
440
441            if ( NO_ERROR != ret )
442                {
443                CAMHAL_LOGEA("Focus status check failed!");
444                }
445            }
446        }
447
448    if ( NO_ERROR == ret )
449        {
450
451        if ( timeoutReached )
452            {
453            focusStatus = CameraHalEvent::FOCUS_STATUS_FAIL;
454            }
455        else
456            {
457            switch (eFocusStatus.eFocusStatus)
458                {
459                    case OMX_FocusStatusReached:
460                        {
461                        focusStatus = CameraHalEvent::FOCUS_STATUS_SUCCESS;
462                        break;
463                        }
464                    case OMX_FocusStatusOff: // AF got canceled
465                        return NO_ERROR;
466                    case OMX_FocusStatusUnableToReach:
467                    case OMX_FocusStatusRequest:
468                    default:
469                        {
470                        focusStatus = CameraHalEvent::FOCUS_STATUS_FAIL;
471                        break;
472                        }
473                }
474            // Lock CAF after AF call
475            if( set3ALock(mUserSetExpLock, mUserSetWbLock, OMX_TRUE) != NO_ERROR) {
476                CAMHAL_LOGEA("Error Applying 3A locks");
477            } else {
478                CAMHAL_LOGDA("Focus locked. Applied focus locks successfully");
479            }
480
481            stopAutoFocus();
482            }
483        //Query current focus distance after AF is complete
484        updateFocusDistances(mParameters);
485       }
486
487    ret =  BaseCameraAdapter::setState(CAMERA_CANCEL_AUTOFOCUS);
488    if ( NO_ERROR == ret )
489        {
490        ret = BaseCameraAdapter::commitState();
491        }
492    else
493        {
494        ret |= BaseCameraAdapter::rollbackState();
495        }
496
497    if ( NO_ERROR == ret )
498        {
499        notifyFocusSubscribers(focusStatus);
500        }
501
502    // After focus, face detection will resume sending face callbacks
503    pauseFaceDetection(false);
504
505    LOG_FUNCTION_NAME_EXIT;
506
507    return ret;
508}
509
510status_t OMXCameraAdapter::checkFocus(OMX_PARAM_FOCUSSTATUSTYPE *eFocusStatus)
511{
512    status_t ret = NO_ERROR;
513    OMX_ERRORTYPE eError = OMX_ErrorNone;
514
515    LOG_FUNCTION_NAME;
516
517    if ( NULL == eFocusStatus )
518        {
519        CAMHAL_LOGEA("Invalid focus status");
520        ret = -EINVAL;
521        }
522
523    if ( OMX_StateInvalid == mComponentState )
524      {
525        CAMHAL_LOGEA("OMX component in Invalid state");
526        ret = -EINVAL;
527      }
528
529    if ( OMX_StateExecuting != mComponentState )
530        {
531        CAMHAL_LOGEA("OMX component not in executing state");
532        ret = NO_ERROR;
533        }
534
535    if ( NO_ERROR == ret )
536        {
537        OMX_INIT_STRUCT_PTR (eFocusStatus, OMX_PARAM_FOCUSSTATUSTYPE);
538
539        eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
540                               OMX_IndexConfigCommonFocusStatus,
541                               eFocusStatus);
542        if ( OMX_ErrorNone != eError )
543            {
544            CAMHAL_LOGEB("Error while retrieving focus status: 0x%x", eError);
545            ret = -1;
546            }
547        }
548
549    if ( NO_ERROR == ret )
550        {
551        CAMHAL_LOGDB("Focus Status: %d", eFocusStatus->eFocusStatus);
552        }
553
554    LOG_FUNCTION_NAME_EXIT;
555
556    return ret;
557}
558
559status_t OMXCameraAdapter::updateFocusDistances(android::CameraParameters &params)
560{
561    OMX_U32 focusNear, focusOptimal, focusFar;
562    status_t ret = NO_ERROR;
563
564    LOG_FUNCTION_NAME;
565
566    ret = getFocusDistances(focusNear, focusOptimal, focusFar);
567    if ( NO_ERROR == ret)
568        {
569        ret = addFocusDistances(focusNear, focusOptimal, focusFar, params);
570            if ( NO_ERROR != ret )
571                {
572                CAMHAL_LOGEB("Error in call to addFocusDistances() 0x%x", ret);
573                }
574        }
575    else
576        {
577        CAMHAL_LOGEB("Error in call to getFocusDistances() 0x%x", ret);
578        }
579
580    LOG_FUNCTION_NAME_EXIT;
581
582    return ret;
583}
584
585status_t OMXCameraAdapter::getFocusDistances(OMX_U32 &near,OMX_U32 &optimal, OMX_U32 &far)
586{
587    status_t ret = NO_ERROR;
588    OMX_ERRORTYPE eError;
589
590    OMX_TI_CONFIG_FOCUSDISTANCETYPE focusDist;
591
592    LOG_FUNCTION_NAME;
593
594    if ( OMX_StateInvalid == mComponentState )
595        {
596        CAMHAL_LOGEA("OMX component is in invalid state");
597        ret = UNKNOWN_ERROR;
598        }
599
600    if ( NO_ERROR == ret )
601        {
602        OMX_INIT_STRUCT_PTR(&focusDist, OMX_TI_CONFIG_FOCUSDISTANCETYPE);
603        focusDist.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
604
605        eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
606                               ( OMX_INDEXTYPE ) OMX_TI_IndexConfigFocusDistance,
607                               &focusDist);
608        if ( OMX_ErrorNone != eError )
609            {
610            CAMHAL_LOGEB("Error while querying focus distances 0x%x", eError);
611            ret = UNKNOWN_ERROR;
612            }
613
614        }
615
616    if ( NO_ERROR == ret )
617        {
618        near = focusDist.nFocusDistanceNear;
619        optimal = focusDist.nFocusDistanceOptimal;
620        far = focusDist.nFocusDistanceFar;
621        }
622
623    LOG_FUNCTION_NAME_EXIT;
624
625    return ret;
626}
627
628status_t OMXCameraAdapter::encodeFocusDistance(OMX_U32 dist, char *buffer, size_t length)
629{
630    status_t ret = NO_ERROR;
631    uint32_t focusScale = 1000;
632    float distFinal;
633
634    LOG_FUNCTION_NAME;
635
636    if(mParameters3A.Focus == OMX_IMAGE_FocusControlAutoInfinity)
637        {
638        dist=0;
639        }
640
641    if ( NO_ERROR == ret )
642        {
643        if ( 0 == dist )
644            {
645            strncpy(buffer, android::CameraParameters::FOCUS_DISTANCE_INFINITY, ( length - 1 ));
646            }
647        else
648            {
649            distFinal = dist;
650            distFinal /= focusScale;
651            snprintf(buffer, ( length - 1 ) , "%5.3f", distFinal);
652            }
653        }
654
655    LOG_FUNCTION_NAME_EXIT;
656
657    return ret;
658}
659
660status_t OMXCameraAdapter::addFocusDistances(OMX_U32 &near,
661                                             OMX_U32 &optimal,
662                                             OMX_U32 &far,
663                                             android::CameraParameters& params)
664{
665    status_t ret = NO_ERROR;
666
667    LOG_FUNCTION_NAME;
668
669    if ( NO_ERROR == ret )
670        {
671        ret = encodeFocusDistance(near, mFocusDistNear, FOCUS_DIST_SIZE);
672        if ( NO_ERROR != ret )
673            {
674            CAMHAL_LOGEB("Error encoding near focus distance 0x%x", ret);
675            }
676        }
677
678    if ( NO_ERROR == ret )
679        {
680        ret = encodeFocusDistance(optimal, mFocusDistOptimal, FOCUS_DIST_SIZE);
681        if ( NO_ERROR != ret )
682            {
683            CAMHAL_LOGEB("Error encoding near focus distance 0x%x", ret);
684            }
685        }
686
687    if ( NO_ERROR == ret )
688        {
689        ret = encodeFocusDistance(far, mFocusDistFar, FOCUS_DIST_SIZE);
690        if ( NO_ERROR != ret )
691            {
692            CAMHAL_LOGEB("Error encoding near focus distance 0x%x", ret);
693            }
694        }
695
696    if ( NO_ERROR == ret )
697        {
698        snprintf(mFocusDistBuffer, ( FOCUS_DIST_BUFFER_SIZE - 1) ,"%s,%s,%s", mFocusDistNear,
699                                                                              mFocusDistOptimal,
700                                                                              mFocusDistFar);
701
702        params.set(android::CameraParameters::KEY_FOCUS_DISTANCES, mFocusDistBuffer);
703        }
704
705    LOG_FUNCTION_NAME_EXIT;
706
707    return ret;
708}
709
710status_t OMXCameraAdapter::setTouchFocus()
711{
712    status_t ret = NO_ERROR;
713    OMX_ERRORTYPE eError = OMX_ErrorNone;
714
715    OMX_ALGOAREASTYPE *focusAreas;
716    OMX_TI_CONFIG_SHAREDBUFFER sharedBuffer;
717    CameraBuffer *bufferlist;
718    int areasSize = 0;
719
720    LOG_FUNCTION_NAME;
721
722    if ( OMX_StateInvalid == mComponentState )
723        {
724        CAMHAL_LOGEA("OMX component is in invalid state");
725        ret = -1;
726        }
727
728    if ( NO_ERROR == ret )
729        {
730
731        areasSize = ((sizeof(OMX_ALGOAREASTYPE)+4095)/4096)*4096;
732        bufferlist = mMemMgr.allocateBufferList(0, 0, NULL, areasSize, 1);
733        focusAreas = (OMX_ALGOAREASTYPE*) bufferlist[0].opaque;
734
735        OMXCameraPortParameters * mPreviewData = NULL;
736        mPreviewData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex];
737
738        if (!focusAreas)
739            {
740            CAMHAL_LOGEB("Error allocating buffer for focus areas %d", eError);
741            return -ENOMEM;
742            }
743
744        OMX_INIT_STRUCT_PTR (focusAreas, OMX_ALGOAREASTYPE);
745
746        focusAreas->nPortIndex = OMX_ALL;
747        focusAreas->nNumAreas = mFocusAreas.size();
748        focusAreas->nAlgoAreaPurpose = OMX_AlgoAreaFocus;
749
750        // If the area is the special case of (0, 0, 0, 0, 0), then
751        // the algorithm needs nNumAreas to be set to 0,
752        // in order to automatically choose the best fitting areas.
753        if ( mFocusAreas.itemAt(0)->isZeroArea() )
754            {
755            focusAreas->nNumAreas = 0;
756            }
757
758        for ( unsigned int n = 0; n < mFocusAreas.size(); n++) {
759            int widthDivisor = 1;
760            int heightDivisor = 1;
761
762            if (mPreviewData->mFrameLayoutType == OMX_TI_StereoFrameLayoutTopBottom) {
763                heightDivisor = 2;
764            }
765            if (mPreviewData->mFrameLayoutType == OMX_TI_StereoFrameLayoutLeftRight) {
766                widthDivisor = 2;
767            }
768
769            // transform the coordinates to 3A-type coordinates
770            mFocusAreas.itemAt(n)->transfrom((size_t)mPreviewData->mWidth/widthDivisor,
771                                            (size_t)mPreviewData->mHeight/heightDivisor,
772                                            (size_t&)focusAreas->tAlgoAreas[n].nTop,
773                                            (size_t&)focusAreas->tAlgoAreas[n].nLeft,
774                                            (size_t&)focusAreas->tAlgoAreas[n].nWidth,
775                                            (size_t&)focusAreas->tAlgoAreas[n].nHeight);
776
777            focusAreas->tAlgoAreas[n].nLeft =
778                    ( focusAreas->tAlgoAreas[n].nLeft * TOUCH_FOCUS_RANGE ) / mPreviewData->mWidth;
779            focusAreas->tAlgoAreas[n].nTop =
780                    ( focusAreas->tAlgoAreas[n].nTop* TOUCH_FOCUS_RANGE ) / mPreviewData->mHeight;
781            focusAreas->tAlgoAreas[n].nWidth =
782                    ( focusAreas->tAlgoAreas[n].nWidth * TOUCH_FOCUS_RANGE ) / mPreviewData->mWidth;
783            focusAreas->tAlgoAreas[n].nHeight =
784                    ( focusAreas->tAlgoAreas[n].nHeight * TOUCH_FOCUS_RANGE ) / mPreviewData->mHeight;
785            focusAreas->tAlgoAreas[n].nPriority = mFocusAreas.itemAt(n)->getWeight();
786
787             CAMHAL_LOGDB("Focus area %d : top = %d left = %d width = %d height = %d prio = %d",
788                    n, (int)focusAreas->tAlgoAreas[n].nTop, (int)focusAreas->tAlgoAreas[n].nLeft,
789                    (int)focusAreas->tAlgoAreas[n].nWidth, (int)focusAreas->tAlgoAreas[n].nHeight,
790                    (int)focusAreas->tAlgoAreas[n].nPriority);
791        }
792
793        OMX_INIT_STRUCT_PTR (&sharedBuffer, OMX_TI_CONFIG_SHAREDBUFFER);
794
795        sharedBuffer.nPortIndex = OMX_ALL;
796        sharedBuffer.nSharedBuffSize = areasSize;
797        sharedBuffer.pSharedBuff = (OMX_U8 *) camera_buffer_get_omx_ptr (&bufferlist[0]);
798
799        if ( NULL == sharedBuffer.pSharedBuff )
800            {
801            CAMHAL_LOGEA("No resources to allocate OMX shared buffer");
802            ret = -ENOMEM;
803            goto EXIT;
804            }
805
806            eError =  OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
807                                      (OMX_INDEXTYPE) OMX_TI_IndexConfigAlgoAreas, &sharedBuffer);
808
809        if ( OMX_ErrorNone != eError )
810            {
811            CAMHAL_LOGEB("Error while setting Focus Areas configuration 0x%x", eError);
812            ret = -EINVAL;
813            }
814
815    EXIT:
816        if (NULL != bufferlist)
817            {
818            mMemMgr.freeBufferList (bufferlist);
819            }
820        }
821
822    LOG_FUNCTION_NAME_EXIT;
823
824    return ret;
825}
826
827void OMXCameraAdapter::handleFocusCallback() {
828    OMX_PARAM_FOCUSSTATUSTYPE eFocusStatus;
829    CameraHalEvent::FocusStatus focusStatus = CameraHalEvent::FOCUS_STATUS_FAIL;
830    status_t ret = NO_ERROR;
831    BaseCameraAdapter::AdapterState nextState;
832    BaseCameraAdapter::getNextState(nextState);
833
834    OMX_INIT_STRUCT(eFocusStatus, OMX_PARAM_FOCUSSTATUSTYPE);
835
836    ret = checkFocus(&eFocusStatus);
837
838    if (NO_ERROR != ret) {
839        CAMHAL_LOGEA("Focus status check failed!");
840        // signal and unblock doAutoFocus
841        if (AF_ACTIVE & nextState) {
842            android::AutoMutex lock(mDoAFMutex);
843            mDoAFCond.broadcast();
844        }
845        return;
846    }
847
848    if ( eFocusStatus.eFocusStatus == OMX_FocusStatusOff ) {
849        android::AutoMutex lock(mCancelAFMutex);
850        mCancelAFCond.signal();
851        return;
852    }
853
854    if (eFocusStatus.eFocusStatus != OMX_FocusStatusRequest) {
855        // signal doAutoFocus when a end of scan message comes
856        // ignore start of scan
857        android::AutoMutex lock(mDoAFMutex);
858        mDoAFCond.broadcast();
859    }
860
861    if (mParameters3A.Focus != (OMX_IMAGE_FOCUSCONTROLTYPE) OMX_IMAGE_FocusControlAuto) {
862       CAMHAL_LOGDA("unregistered focus callback when not in CAF or doAutoFocus... not handling");
863       return;
864    }
865
866    // Handling for CAF Callbacks
867    switch (eFocusStatus.eFocusStatus) {
868        case OMX_FocusStatusRequest:
869            focusStatus = CameraHalEvent::FOCUS_STATUS_PENDING;
870            break;
871        case OMX_FocusStatusReached:
872        case OMX_FocusStatusOff:
873        case OMX_FocusStatusUnableToReach:
874        default:
875            focusStatus = CameraHalEvent::FOCUS_STATUS_DONE;
876            break;
877    }
878
879    notifyFocusSubscribers(focusStatus);
880}
881
882} // namespace Camera
883} // namespace Ti
884