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