OMXFocus.cpp revision 8a35a0ca4d30702b693c92f8cee360a8d102f49e
1/*
2 * Copyright (C) Texas Instruments - http://www.ti.com/
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18/**
19* @file OMXFocus.cpp
20*
21* This file contains functionality for handling focus configurations.
22*
23*/
24
25#undef LOG_TAG
26
27#define LOG_TAG "CameraHAL"
28
29#include "CameraHal.h"
30#include "OMXCameraAdapter.h"
31#include "ErrorUtils.h"
32
33#define TOUCH_FOCUS_RANGE 0xFF
34#define AF_CALLBACK_TIMEOUT 5000000 //5 seconds timeout
35
36namespace android {
37
38status_t OMXCameraAdapter::setParametersFocus(const CameraParameters &params,
39                                              BaseCameraAdapter::AdapterState state)
40{
41    status_t ret = NO_ERROR;
42    const char *str = NULL;
43    Vector< sp<CameraArea> > tempAreas;
44    size_t MAX_FOCUS_AREAS;
45
46    LOG_FUNCTION_NAME;
47
48    Mutex::Autolock lock(mFocusAreasLock);
49
50    str = params.get(CameraParameters::KEY_FOCUS_AREAS);
51
52    MAX_FOCUS_AREAS = atoi(params.get(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;
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
86    LOG_FUNCTION_NAME;
87
88    if ( OMX_StateExecuting != mComponentState )
89        {
90        CAMHAL_LOGEA("OMX component not in executing state");
91        returnFocusStatus(false);
92        return NO_INIT;
93        }
94
95    if ( 0 != mDoAFSem.Count() )
96        {
97        CAMHAL_LOGEB("Error mDoAFSem semaphore count %d", mDoAFSem.Count());
98        return NO_INIT;
99        }
100
101    // If the app calls autoFocus, the camera will stop sending face callbacks.
102    pauseFaceDetection(true);
103
104    // This is needed for applying FOCUS_REGION correctly
105    if ( (!mFocusAreas.isEmpty()) && (!mFocusAreas.itemAt(0)->isZeroArea()))
106    {
107    //Disable face priority
108    setAlgoPriority(FACE_PRIORITY, FOCUS_ALGO, false);
109
110    //Enable region algorithm priority
111    setAlgoPriority(REGION_PRIORITY, FOCUS_ALGO, true);
112    }
113
114    OMX_INIT_STRUCT_PTR (&focusControl, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE);
115    focusControl.eFocusControl = ( OMX_IMAGE_FOCUSCONTROLTYPE ) mParameters3A.Focus;
116
117    if (mParameters3A.FocusLock) {
118        // this basically means user never called cancelAutoFocus after a scan...
119        // if this is the case we need to unlock AF to ensure we will do a scan
120        if (set3ALock(mUserSetExpLock, mUserSetWbLock, OMX_FALSE) != NO_ERROR) {
121            CAMHAL_LOGEA("Error Unlocking 3A locks");
122        } else {
123            CAMHAL_LOGDA("AE/AWB unlocked successfully");
124        }
125
126    } else if ( mParameters3A.Focus == OMX_IMAGE_FocusControlAuto ) {
127        // In case we have CAF running we should first check the AF status.
128        // If it has managed to lock, then do as usual and return status
129        // immediately. If lock is not available, then switch temporarily
130        // to 'autolock' and do normal AF.
131        ret = checkFocus(&focusStatus);
132        if ( NO_ERROR != ret ) {
133            CAMHAL_LOGEB("Focus status check failed 0x%x!", ret);
134            return ret;
135        } else {
136            CAMHAL_LOGDB("Focus status check 0x%x!", focusStatus.eFocusStatus);
137        }
138    }
139
140    if ( ( focusControl.eFocusControl != OMX_IMAGE_FocusControlAuto ) &&
141         ( focusControl.eFocusControl != ( OMX_IMAGE_FOCUSCONTROLTYPE )
142                 OMX_IMAGE_FocusControlAutoInfinity ) ) {
143
144        ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
145                                    (OMX_EVENTTYPE) OMX_EventIndexSettingChanged,
146                                    OMX_ALL,
147                                    OMX_IndexConfigCommonFocusStatus,
148                                    mDoAFSem);
149
150        if ( NO_ERROR == ret ) {
151            ret = setFocusCallback(true);
152        }
153
154        eError =  OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
155                                OMX_IndexConfigFocusControl,
156                                &focusControl);
157
158        if ( OMX_ErrorNone != eError ) {
159            CAMHAL_LOGEB("Error while starting focus 0x%x", eError);
160            return INVALID_OPERATION;
161        } else {
162            CAMHAL_LOGDA("Autofocus started successfully");
163        }
164
165       if(mDoAFSem.WaitTimeout(AF_CALLBACK_TIMEOUT) != NO_ERROR) {
166            //If somethiing bad happened while we wait
167            if (mComponentState == OMX_StateInvalid) {
168                CAMHAL_LOGEA("Invalid State after Auto Focus Exitting!!!");
169                return EINVAL;
170            }
171
172            //Disable auto focus callback from Ducati
173            setFocusCallback(false);
174            CAMHAL_LOGEA("Autofocus callback timeout expired");
175            RemoveEvent(mCameraAdapterParameters.mHandleComp,
176                                        (OMX_EVENTTYPE) OMX_EventIndexSettingChanged,
177                                        OMX_ALL,
178                                        OMX_IndexConfigCommonFocusStatus,
179                                        NULL );
180            returnFocusStatus(true);
181        } else {
182            CAMHAL_LOGDA("Autofocus callback received");
183            //Disable auto focus callback from Ducati
184            setFocusCallback(false);
185            ret = returnFocusStatus(false);
186        }
187    } else { // Focus mode in continuous
188        if ( NO_ERROR == ret ) {
189            ret = returnFocusStatus(false);
190            mPending3Asettings |= SetFocus;
191        }
192    }
193
194    LOG_FUNCTION_NAME_EXIT;
195
196    return ret;
197}
198
199status_t OMXCameraAdapter::stopAutoFocus()
200{
201    status_t ret = NO_ERROR;
202    OMX_ERRORTYPE eError = OMX_ErrorNone;
203    OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focusControl;
204
205    LOG_FUNCTION_NAME;
206
207    if ( OMX_StateExecuting != mComponentState )
208        {
209        CAMHAL_LOGEA("OMX component not in executing state");
210        return NO_INIT;
211        }
212
213    if ( mParameters3A.Focus == OMX_IMAGE_FocusControlAutoInfinity ) {
214        // No need to stop focus if we are in infinity mode. Nothing to stop.
215        return NO_ERROR;
216    }
217
218    if ( NO_ERROR == ret )
219       {
220       //Disable the callback first
221       ret = setFocusCallback(false);
222       }
223
224    if ( NO_ERROR == ret )
225        {
226        OMX_INIT_STRUCT_PTR (&focusControl, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE);
227        focusControl.eFocusControl = OMX_IMAGE_FocusControlOff;
228
229        eError =  OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
230                                OMX_IndexConfigFocusControl,
231                                &focusControl);
232        if ( OMX_ErrorNone != eError )
233            {
234            CAMHAL_LOGEB("Error while stopping focus 0x%x", eError);
235            return ErrorUtils::omxToAndroidError(eError);
236            }
237        }
238
239    //Query current focus distance after AF is complete
240    updateFocusDistances(mParameters);
241
242    LOG_FUNCTION_NAME_EXIT;
243
244    return ret;
245}
246
247status_t OMXCameraAdapter::getFocusMode(OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE &focusMode)
248{;
249    OMX_ERRORTYPE eError = OMX_ErrorNone;
250
251    LOG_FUNCTION_NAME;
252
253    if ( OMX_StateInvalid == mComponentState ) {
254        CAMHAL_LOGEA("OMX component is in invalid state");
255        return NO_INIT;
256    }
257
258    OMX_INIT_STRUCT_PTR (&focusMode, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE);
259    focusMode.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
260
261    eError =  OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
262                            OMX_IndexConfigFocusControl,
263                            &focusMode);
264
265    if ( OMX_ErrorNone != eError ) {
266        CAMHAL_LOGEB("Error while retrieving focus mode 0x%x", eError);
267    }
268
269    LOG_FUNCTION_NAME_EXIT;
270
271    return ErrorUtils::omxToAndroidError(eError);
272}
273
274status_t OMXCameraAdapter::cancelAutoFocus()
275{
276    status_t ret = NO_ERROR;
277    OMX_ERRORTYPE eError = OMX_ErrorNone;
278    OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focusMode;
279
280    LOG_FUNCTION_NAME;
281    // Unlock 3A locks since they were locked by AF conditionally
282    if( set3ALock(mUserSetExpLock, mUserSetWbLock, OMX_FALSE) != NO_ERROR) {
283      CAMHAL_LOGEA("Error Unlocking 3A locks");
284    }
285    else{
286      CAMHAL_LOGDA("AE/AWB unlocked successfully");
287    }
288
289    ret = getFocusMode(focusMode);
290    if ( NO_ERROR != ret ) {
291        return ret;
292    }
293
294    //Stop the AF only for modes other than CAF  or Inifinity
295    if ( ( focusMode.eFocusControl != OMX_IMAGE_FocusControlAuto ) &&
296         ( focusMode.eFocusControl != ( OMX_IMAGE_FOCUSCONTROLTYPE )
297                 OMX_IMAGE_FocusControlAutoInfinity ) ) {
298        stopAutoFocus();
299        //Signal a dummy AF event so that in case the callback from ducati
300        //does come then it doesnt crash after
301        //exiting this function since eventSem will go out of scope.
302        ret |= SignalEvent(mCameraAdapterParameters.mHandleComp,
303                                    (OMX_EVENTTYPE) OMX_EventIndexSettingChanged,
304                                    OMX_ALL,
305                                    OMX_IndexConfigCommonFocusStatus,
306                                    NULL );
307    } else if (focusMode.eFocusControl == OMX_IMAGE_FocusControlAuto) {
308       // re-apply CAF after unlocking and canceling
309       mPending3Asettings |= SetFocus;
310    }
311
312    // If the apps call #cancelAutoFocus()}, the face callbacks will also resume.
313    pauseFaceDetection(false);
314
315    LOG_FUNCTION_NAME_EXIT;
316
317    return ret;
318
319}
320
321status_t OMXCameraAdapter::setFocusCallback(bool enabled)
322{
323    status_t ret = NO_ERROR;
324    OMX_ERRORTYPE eError = OMX_ErrorNone;
325    OMX_CONFIG_CALLBACKREQUESTTYPE focusRequstCallback;
326
327    LOG_FUNCTION_NAME;
328
329    if ( OMX_StateExecuting != mComponentState )
330        {
331        CAMHAL_LOGEA("OMX component not in executing state");
332        ret = -1;
333        }
334
335    if ( NO_ERROR == ret )
336        {
337
338        OMX_INIT_STRUCT_PTR (&focusRequstCallback, OMX_CONFIG_CALLBACKREQUESTTYPE);
339        focusRequstCallback.nPortIndex = OMX_ALL;
340        focusRequstCallback.nIndex = OMX_IndexConfigCommonFocusStatus;
341
342        if ( enabled )
343            {
344            focusRequstCallback.bEnable = OMX_TRUE;
345            }
346        else
347            {
348            focusRequstCallback.bEnable = OMX_FALSE;
349            }
350
351        eError =  OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
352                                (OMX_INDEXTYPE) OMX_IndexConfigCallbackRequest,
353                                &focusRequstCallback);
354        if ( OMX_ErrorNone != eError )
355            {
356            CAMHAL_LOGEB("Error registering focus callback 0x%x", eError);
357            ret = -1;
358            }
359        else
360            {
361            CAMHAL_LOGDB("Autofocus callback for index 0x%x registered successfully",
362                         OMX_IndexConfigCommonFocusStatus);
363            }
364        }
365
366    LOG_FUNCTION_NAME_EXIT;
367
368    return ret;
369}
370
371status_t OMXCameraAdapter::returnFocusStatus(bool timeoutReached)
372{
373    status_t ret = NO_ERROR;
374    OMX_PARAM_FOCUSSTATUSTYPE eFocusStatus;
375    bool focusStatus = false;
376    BaseCameraAdapter::AdapterState state, nextState;
377    BaseCameraAdapter::getState(state);
378    BaseCameraAdapter::getNextState(nextState);
379
380    LOG_FUNCTION_NAME;
381
382    OMX_INIT_STRUCT(eFocusStatus, OMX_PARAM_FOCUSSTATUSTYPE);
383
384    if( ((AF_ACTIVE & state ) != AF_ACTIVE) && ((AF_ACTIVE & nextState ) != AF_ACTIVE) )
385       {
386        /// We don't send focus callback if focus was not started
387       CAMHAL_LOGDA("Not sending focus callback because focus was not started");
388       return NO_ERROR;
389       }
390
391    if ( NO_ERROR == ret )
392        {
393
394        if ( !timeoutReached )
395            {
396            ret = checkFocus(&eFocusStatus);
397
398            if ( NO_ERROR != ret )
399                {
400                CAMHAL_LOGEA("Focus status check failed!");
401                }
402            }
403        }
404
405    if ( NO_ERROR == ret )
406        {
407
408        if ( timeoutReached )
409            {
410            focusStatus = false;
411            }
412        else
413            {
414            switch (eFocusStatus.eFocusStatus)
415                {
416                    case OMX_FocusStatusReached:
417                        {
418                        focusStatus = true;
419                        break;
420                        }
421                    case OMX_FocusStatusOff:
422                    case OMX_FocusStatusUnableToReach:
423                    case OMX_FocusStatusRequest:
424                    default:
425                        {
426                        focusStatus = false;
427                        break;
428                        }
429                }
430            // Lock CAF after AF call
431            if( set3ALock(mUserSetExpLock, mUserSetWbLock, OMX_TRUE) != NO_ERROR) {
432                CAMHAL_LOGEA("Error Applying 3A locks");
433            } else {
434                CAMHAL_LOGDA("Focus locked. Applied focus locks successfully");
435            }
436
437            stopAutoFocus();
438            }
439        }
440
441    ret =  BaseCameraAdapter::setState(CAMERA_CANCEL_AUTOFOCUS);
442    if ( NO_ERROR == ret )
443        {
444        ret = BaseCameraAdapter::commitState();
445        }
446    else
447        {
448        ret |= BaseCameraAdapter::rollbackState();
449        }
450
451    if ( NO_ERROR == ret )
452        {
453        notifyFocusSubscribers(focusStatus);
454        }
455
456    // After focus, face detection will resume sending face callbacks
457    pauseFaceDetection(false);
458
459    LOG_FUNCTION_NAME_EXIT;
460
461    return ret;
462}
463
464status_t OMXCameraAdapter::checkFocus(OMX_PARAM_FOCUSSTATUSTYPE *eFocusStatus)
465{
466    status_t ret = NO_ERROR;
467    OMX_ERRORTYPE eError = OMX_ErrorNone;
468
469    LOG_FUNCTION_NAME;
470
471    if ( NULL == eFocusStatus )
472        {
473        CAMHAL_LOGEA("Invalid focus status");
474        ret = -EINVAL;
475        }
476
477    if ( OMX_StateExecuting != mComponentState )
478        {
479        CAMHAL_LOGEA("OMX component not in executing state");
480        ret = -EINVAL;
481        }
482
483    if ( NO_ERROR == ret )
484        {
485        OMX_INIT_STRUCT_PTR (eFocusStatus, OMX_PARAM_FOCUSSTATUSTYPE);
486
487        eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
488                               OMX_IndexConfigCommonFocusStatus,
489                               eFocusStatus);
490        if ( OMX_ErrorNone != eError )
491            {
492            CAMHAL_LOGEB("Error while retrieving focus status: 0x%x", eError);
493            ret = -1;
494            }
495        }
496
497    if ( NO_ERROR == ret )
498        {
499        CAMHAL_LOGDB("Focus Status: %d", eFocusStatus->eFocusStatus);
500        }
501
502    LOG_FUNCTION_NAME_EXIT;
503
504    return ret;
505}
506
507status_t OMXCameraAdapter::updateFocusDistances(CameraParameters &params)
508{
509    OMX_U32 focusNear, focusOptimal, focusFar;
510    status_t ret = NO_ERROR;
511
512    LOG_FUNCTION_NAME;
513
514    ret = getFocusDistances(focusNear, focusOptimal, focusFar);
515    if ( NO_ERROR == ret)
516        {
517        ret = addFocusDistances(focusNear, focusOptimal, focusFar, params);
518            if ( NO_ERROR != ret )
519                {
520                CAMHAL_LOGEB("Error in call to addFocusDistances() 0x%x", ret);
521                }
522        }
523    else
524        {
525        CAMHAL_LOGEB("Error in call to getFocusDistances() 0x%x", ret);
526        }
527
528    LOG_FUNCTION_NAME_EXIT;
529
530    return ret;
531}
532
533status_t OMXCameraAdapter::getFocusDistances(OMX_U32 &near,OMX_U32 &optimal, OMX_U32 &far)
534{
535    status_t ret = NO_ERROR;
536    OMX_ERRORTYPE eError;
537
538    OMX_TI_CONFIG_FOCUSDISTANCETYPE focusDist;
539
540    LOG_FUNCTION_NAME;
541
542    if ( OMX_StateInvalid == mComponentState )
543        {
544        CAMHAL_LOGEA("OMX component is in invalid state");
545        ret = UNKNOWN_ERROR;
546        }
547
548    if ( NO_ERROR == ret )
549        {
550        OMX_INIT_STRUCT_PTR(&focusDist, OMX_TI_CONFIG_FOCUSDISTANCETYPE);
551        focusDist.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
552
553        eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
554                               ( OMX_INDEXTYPE ) OMX_TI_IndexConfigFocusDistance,
555                               &focusDist);
556        if ( OMX_ErrorNone != eError )
557            {
558            CAMHAL_LOGEB("Error while querying focus distances 0x%x", eError);
559            ret = UNKNOWN_ERROR;
560            }
561
562        }
563
564    if ( NO_ERROR == ret )
565        {
566        near = focusDist.nFocusDistanceNear;
567        optimal = focusDist.nFocusDistanceOptimal;
568        far = focusDist.nFocusDistanceFar;
569        }
570
571    LOG_FUNCTION_NAME_EXIT;
572
573    return ret;
574}
575
576status_t OMXCameraAdapter::encodeFocusDistance(OMX_U32 dist, char *buffer, size_t length)
577{
578    status_t ret = NO_ERROR;
579    uint32_t focusScale = 1000;
580    float distFinal;
581
582    LOG_FUNCTION_NAME;
583
584    if(mParameters3A.Focus == OMX_IMAGE_FocusControlAutoInfinity)
585        {
586        dist=0;
587        }
588
589    if ( NO_ERROR == ret )
590        {
591        if ( 0 == dist )
592            {
593            strncpy(buffer, CameraParameters::FOCUS_DISTANCE_INFINITY, ( length - 1 ));
594            }
595        else
596            {
597            distFinal = dist;
598            distFinal /= focusScale;
599            snprintf(buffer, ( length - 1 ) , "%5.3f", distFinal);
600            }
601        }
602
603    LOG_FUNCTION_NAME_EXIT;
604
605    return ret;
606}
607
608status_t OMXCameraAdapter::addFocusDistances(OMX_U32 &near,
609                                             OMX_U32 &optimal,
610                                             OMX_U32 &far,
611                                             CameraParameters& params)
612{
613    status_t ret = NO_ERROR;
614
615    LOG_FUNCTION_NAME;
616
617    if ( NO_ERROR == ret )
618        {
619        ret = encodeFocusDistance(near, mFocusDistNear, FOCUS_DIST_SIZE);
620        if ( NO_ERROR != ret )
621            {
622            CAMHAL_LOGEB("Error encoding near focus distance 0x%x", ret);
623            }
624        }
625
626    if ( NO_ERROR == ret )
627        {
628        ret = encodeFocusDistance(optimal, mFocusDistOptimal, FOCUS_DIST_SIZE);
629        if ( NO_ERROR != ret )
630            {
631            CAMHAL_LOGEB("Error encoding near focus distance 0x%x", ret);
632            }
633        }
634
635    if ( NO_ERROR == ret )
636        {
637        ret = encodeFocusDistance(far, mFocusDistFar, FOCUS_DIST_SIZE);
638        if ( NO_ERROR != ret )
639            {
640            CAMHAL_LOGEB("Error encoding near focus distance 0x%x", ret);
641            }
642        }
643
644    if ( NO_ERROR == ret )
645        {
646        snprintf(mFocusDistBuffer, ( FOCUS_DIST_BUFFER_SIZE - 1) ,"%s,%s,%s", mFocusDistNear,
647                                                                              mFocusDistOptimal,
648                                                                              mFocusDistFar);
649
650        params.set(CameraParameters::KEY_FOCUS_DISTANCES, mFocusDistBuffer);
651        }
652
653    LOG_FUNCTION_NAME_EXIT;
654
655    return ret;
656}
657
658status_t OMXCameraAdapter::setTouchFocus()
659{
660    status_t ret = NO_ERROR;
661    OMX_ERRORTYPE eError = OMX_ErrorNone;
662
663    OMX_ALGOAREASTYPE **focusAreas;
664    OMX_TI_CONFIG_SHAREDBUFFER sharedBuffer;
665    MemoryManager memMgr;
666    int areasSize = 0;
667
668    LOG_FUNCTION_NAME;
669
670    if ( OMX_StateInvalid == mComponentState )
671        {
672        CAMHAL_LOGEA("OMX component is in invalid state");
673        ret = -1;
674        }
675
676    if ( NO_ERROR == ret )
677        {
678
679        areasSize = ((sizeof(OMX_ALGOAREASTYPE)+4095)/4096)*4096;
680        focusAreas = (OMX_ALGOAREASTYPE**) memMgr.allocateBuffer(0, 0, NULL, areasSize, 1);
681
682        OMXCameraPortParameters * mPreviewData = NULL;
683        mPreviewData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex];
684
685        if (!focusAreas)
686            {
687            CAMHAL_LOGEB("Error allocating buffer for focus areas %d", eError);
688            return -ENOMEM;
689            }
690
691        OMX_INIT_STRUCT_PTR (focusAreas[0], OMX_ALGOAREASTYPE);
692
693        focusAreas[0]->nPortIndex = OMX_ALL;
694        focusAreas[0]->nNumAreas = mFocusAreas.size();
695        focusAreas[0]->nAlgoAreaPurpose = OMX_AlgoAreaFocus;
696
697        // If the area is the special case of (0, 0, 0, 0, 0), then
698        // the algorithm needs nNumAreas to be set to 0,
699        // in order to automatically choose the best fitting areas.
700        if ( mFocusAreas.itemAt(0)->isZeroArea() )
701            {
702            focusAreas[0]->nNumAreas = 0;
703            }
704
705        for ( unsigned int n = 0; n < mFocusAreas.size(); n++)
706            {
707            // transform the coordinates to 3A-type coordinates
708            mFocusAreas.itemAt(n)->transfrom((size_t)mPreviewData->mWidth,
709                                            (size_t)mPreviewData->mHeight,
710                                            (size_t&)focusAreas[0]->tAlgoAreas[n].nTop,
711                                            (size_t&)focusAreas[0]->tAlgoAreas[n].nLeft,
712                                            (size_t&)focusAreas[0]->tAlgoAreas[n].nWidth,
713                                            (size_t&)focusAreas[0]->tAlgoAreas[n].nHeight);
714
715            focusAreas[0]->tAlgoAreas[n].nLeft =
716                    ( focusAreas[0]->tAlgoAreas[n].nLeft * TOUCH_FOCUS_RANGE ) / mPreviewData->mWidth;
717            focusAreas[0]->tAlgoAreas[n].nTop =
718                    ( focusAreas[0]->tAlgoAreas[n].nTop* TOUCH_FOCUS_RANGE ) / mPreviewData->mHeight;
719            focusAreas[0]->tAlgoAreas[n].nWidth =
720                    ( focusAreas[0]->tAlgoAreas[n].nWidth * TOUCH_FOCUS_RANGE ) / mPreviewData->mWidth;
721            focusAreas[0]->tAlgoAreas[n].nHeight =
722                    ( focusAreas[0]->tAlgoAreas[n].nHeight * TOUCH_FOCUS_RANGE ) / mPreviewData->mHeight;
723            focusAreas[0]->tAlgoAreas[n].nPriority = mFocusAreas.itemAt(n)->getWeight();
724
725             CAMHAL_LOGDB("Focus area %d : top = %d left = %d width = %d height = %d prio = %d",
726                    n, (int)focusAreas[0]->tAlgoAreas[n].nTop, (int)focusAreas[0]->tAlgoAreas[n].nLeft,
727                    (int)focusAreas[0]->tAlgoAreas[n].nWidth, (int)focusAreas[0]->tAlgoAreas[n].nHeight,
728                    (int)focusAreas[0]->tAlgoAreas[n].nPriority);
729             }
730
731        OMX_INIT_STRUCT_PTR (&sharedBuffer, OMX_TI_CONFIG_SHAREDBUFFER);
732
733        sharedBuffer.nPortIndex = OMX_ALL;
734        sharedBuffer.nSharedBuffSize = areasSize;
735        sharedBuffer.pSharedBuff = (OMX_U8 *) focusAreas[0];
736
737        if ( NULL == sharedBuffer.pSharedBuff )
738            {
739            CAMHAL_LOGEA("No resources to allocate OMX shared buffer");
740            ret = -ENOMEM;
741            goto EXIT;
742            }
743
744            eError =  OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
745                                      (OMX_INDEXTYPE) OMX_TI_IndexConfigAlgoAreas, &sharedBuffer);
746
747        if ( OMX_ErrorNone != eError )
748            {
749            CAMHAL_LOGEB("Error while setting Focus Areas configuration 0x%x", eError);
750            ret = -EINVAL;
751            }
752
753    EXIT:
754        if (NULL != focusAreas)
755            {
756            memMgr.freeBuffer((void*) focusAreas);
757            focusAreas = NULL;
758            }
759        }
760
761    LOG_FUNCTION_NAME_EXIT;
762
763    return ret;
764}
765
766};
767