• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
33 namespace Ti {
34 namespace Camera {
35 
36 const nsecs_t OMXCameraAdapter::CANCEL_AF_TIMEOUT =  seconds_to_nanoseconds(1);
37 
setParametersFocus(const android::CameraParameters & params,BaseCameraAdapter::AdapterState state)38 status_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 
doAutoFocus()79 status_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 
stopAutoFocus()236 status_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 
getFocusMode(OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE & focusMode)285 status_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 
cancelAutoFocus()312 status_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 
setFocusCallback(bool enabled)358 status_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 
returnFocusStatus(bool timeoutReached)414 status_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 
checkFocus(OMX_PARAM_FOCUSSTATUSTYPE * eFocusStatus)510 status_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 
updateFocusDistances(android::CameraParameters & params)559 status_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 
getFocusDistances(OMX_U32 & near,OMX_U32 & optimal,OMX_U32 & far)585 status_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 
encodeFocusDistance(OMX_U32 dist,char * buffer,size_t length)628 status_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 
addFocusDistances(OMX_U32 & near,OMX_U32 & optimal,OMX_U32 & far,android::CameraParameters & params)660 status_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 
setTouchFocus()710 status_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 
handleFocusCallback()827 void 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