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