1c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev/* 2c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * Copyright (C) Texas Instruments - http://www.ti.com/ 3c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * 4c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * Licensed under the Apache License, Version 2.0 (the "License"); 5c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * you may not use this file except in compliance with the License. 6c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * You may obtain a copy of the License at 7c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * 8c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * http://www.apache.org/licenses/LICENSE-2.0 9c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * 10c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * Unless required by applicable law or agreed to in writing, software 11c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * distributed under the License is distributed on an "AS IS" BASIS, 12c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * See the License for the specific language governing permissions and 14c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * limitations under the License. 15c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev */ 16c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 17c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev/** 18c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev* @file OMXFD.cpp 19c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev* 20c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev* This file contains functionality for handling face detection. 21c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev* 22c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev*/ 23c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 24c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#include "CameraHal.h" 25c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#include "OMXCameraAdapter.h" 26c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 27f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsnamespace Ti { 28f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsnamespace Camera { 297762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu 30f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsconst uint32_t OMXCameraAdapter::FACE_DETECTION_THRESHOLD = 80; 317762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu 32f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsstatus_t OMXCameraAdapter::setParametersFD(const android::CameraParameters ¶ms, 33c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev BaseCameraAdapter::AdapterState state) 34c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 35c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev status_t ret = NO_ERROR; 36c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 37c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev LOG_FUNCTION_NAME; 38c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 39c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev LOG_FUNCTION_NAME_EXIT; 40c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 41c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return ret; 42c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 43c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 44c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatus_t OMXCameraAdapter::startFaceDetection() 45c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 46c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman status_t ret = NO_ERROR; 47c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman 48f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons android::AutoMutex lock(mFaceDetectionLock); 49c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman 50f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons ret = setFaceDetection(true, mFaceOrientation); 51c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman if (ret != NO_ERROR) { 52c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman goto out; 53c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman } 54c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman 55f2170decdf6bf41e590842b0fe5c0ed3852ebec3Emilian Peev if ( mFaceDetectionRunning ) { 56f2170decdf6bf41e590842b0fe5c0ed3852ebec3Emilian Peev mFDSwitchAlgoPriority = true; 57f2170decdf6bf41e590842b0fe5c0ed3852ebec3Emilian Peev } 58c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman 597762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu // Note: White balance will not be face prioritized, since 607762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu // the algorithm needs full frame statistics, and not face 617762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu // regions alone. 62c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman 637762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu faceDetectionNumFacesLastOutput = 0; 64c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman out: 65c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman return ret; 66c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 67c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 68c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatus_t OMXCameraAdapter::stopFaceDetection() 69c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 70c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman status_t ret = NO_ERROR; 71c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman const char *str = NULL; 72c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman BaseCameraAdapter::AdapterState state; 73c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman BaseCameraAdapter::getState(state); 74c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman 75f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons android::AutoMutex lock(mFaceDetectionLock); 76c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman 77f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons ret = setFaceDetection(false, mFaceOrientation); 78c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman if (ret != NO_ERROR) { 79c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman goto out; 80c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman } 81c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman 82f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons if ( mFaceDetectionRunning ) { 83f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons //Enable region priority and disable face priority for AF 84f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons setAlgoPriority(REGION_PRIORITY, FOCUS_ALGO, true); 85f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons setAlgoPriority(FACE_PRIORITY, FOCUS_ALGO , false); 86f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 87f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons //Enable Region priority and disable Face priority 88f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons setAlgoPriority(REGION_PRIORITY, EXPOSURE_ALGO, true); 89f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons setAlgoPriority(FACE_PRIORITY, EXPOSURE_ALGO, false); 90c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman } 91c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman 92c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman if (mPending3Asettings) { 93c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman apply3Asettings(mParameters3A); 94c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman } 95c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman 967762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu faceDetectionNumFacesLastOutput = 0; 97c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman out: 98c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman return ret; 99c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 100c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 101aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luuvoid OMXCameraAdapter::pauseFaceDetection(bool pause) 102aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu{ 103f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons android::AutoMutex lock(mFaceDetectionLock); 104aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu // pausing will only take affect if fd is already running 105aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu if (mFaceDetectionRunning) { 106aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu mFaceDetectionPaused = pause; 1077762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu faceDetectionNumFacesLastOutput = 0; 108aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu } 109aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu} 110aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu 111f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsstatus_t OMXCameraAdapter::setFaceDetectionOrientation(OMX_U32 orientation) 112f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons{ 113f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons status_t ret = NO_ERROR; 114f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 115f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons android::AutoMutex lock(mFaceDetectionLock); 116f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 117f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons mFaceOrientation = orientation; 118f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 119f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons if (mFaceDetectionRunning) { 120f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons // restart face detection with new rotation 121f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons setFaceDetection(true, orientation); 122f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons } 123f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 124f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons return ret; 125f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons} 126f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 127c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatus_t OMXCameraAdapter::setFaceDetection(bool enable, OMX_U32 orientation) 128c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 129c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev status_t ret = NO_ERROR; 130c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev OMX_ERRORTYPE eError = OMX_ErrorNone; 131c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev OMX_CONFIG_OBJDETECTIONTYPE objDetection; 132c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 133c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev LOG_FUNCTION_NAME; 134c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 135c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( OMX_StateInvalid == mComponentState ) 136c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev { 137c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGEA("OMX component is in invalid state"); 138c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev ret = -EINVAL; 139c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 140c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 141c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( NO_ERROR == ret ) 142c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev { 1437762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu if ( orientation > 270 ) { 144c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev orientation = 0; 145c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 146c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 147c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev OMX_INIT_STRUCT_PTR (&objDetection, OMX_CONFIG_OBJDETECTIONTYPE); 148c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev objDetection.nPortIndex = mCameraAdapterParameters.mPrevPortIndex; 149c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev objDetection.nDeviceOrientation = orientation; 150c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( enable ) 151c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev { 152c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev objDetection.bEnable = OMX_TRUE; 153c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 154c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev else 155c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev { 156c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev objDetection.bEnable = OMX_FALSE; 157c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 158c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 159c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, 160c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev ( OMX_INDEXTYPE ) OMX_IndexConfigImageFaceDetection, 161c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev &objDetection); 162c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( OMX_ErrorNone != eError ) 163c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev { 164c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGEB("Error while configuring face detection 0x%x", eError); 165c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev ret = -1; 166c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 167c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev else 168c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev { 169c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGDA("Face detection configured successfully"); 170c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 171c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 172c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 173c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( NO_ERROR == ret ) 174c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev { 175f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons // TODO(XXX): Should enable/disable FD extra data separately 176f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons // on each port. 177f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons ret = setExtraData(enable, OMX_ALL, OMX_FaceDetection); 178c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 179ef73bec8a83a2fd7fbb072d009382c64eb2da0eeTyler Luu if ( NO_ERROR != ret ) 180c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev { 181ef73bec8a83a2fd7fbb072d009382c64eb2da0eeTyler Luu CAMHAL_LOGEA("Error while configuring face detection extra data"); 182c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 183c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev else 184c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev { 185c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGDA("Face detection extra data configured successfully"); 186c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 187c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 188c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 189c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( NO_ERROR == ret ) 190c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev { 191c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev mFaceDetectionRunning = enable; 192aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu mFaceDetectionPaused = !enable; 193c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 194c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 195c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev LOG_FUNCTION_NAME_EXIT; 196c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 197c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return ret; 198c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 199c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 200f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsstatus_t OMXCameraAdapter::createPreviewMetadata(OMX_BUFFERHEADERTYPE* pBuffHeader, 201f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons android::sp<CameraMetadataResult> &result, 202f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons size_t previewWidth, 203f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons size_t previewHeight) 204c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 205c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev status_t ret = NO_ERROR; 206f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons status_t faceRet = NO_ERROR; 207f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons status_t metaRet = NO_ERROR; 208f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons OMX_FACEDETECTIONTYPE *faceData = NULL; 209c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 210c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev LOG_FUNCTION_NAME; 211c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 212c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( OMX_StateExecuting != mComponentState ) { 213c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGEA("OMX component is not in executing state"); 214c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return NO_INIT; 215c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 216c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 217c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( NULL == pBuffHeader ) { 218c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGEA("Invalid Buffer header"); 219c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return-EINVAL; 220c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 221c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 222f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons if ( mFaceDetectionRunning && !mFaceDetectionPaused ) { 223f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons OMX_OTHER_EXTRADATATYPE *extraData; 224f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 225f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons extraData = getExtradata(pBuffHeader->pPlatformPrivate, 226f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons (OMX_EXTRADATATYPE)OMX_FaceDetection); 227f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 228f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons if ( NULL != extraData ) { 229f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons CAMHAL_LOGVB("Size = %d, sizeof = %d, eType = 0x%x, nDataSize= %d, nPortIndex = 0x%x, nVersion = 0x%x", 230f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons extraData->nSize, 231f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons sizeof(OMX_OTHER_EXTRADATATYPE), 232f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons extraData->eType, 233f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons extraData->nDataSize, 234f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons extraData->nPortIndex, 235f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons extraData->nVersion); 236c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } else { 237f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons CAMHAL_LOGD("FD extra data not found!"); 23882640237cf0ca200932a66777fd1907d66cd0322Akwasi Boateng return -EINVAL; 239c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 240c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 241f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons faceData = ( OMX_FACEDETECTIONTYPE * ) extraData->data; 242f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons if ( NULL != faceData ) { 243f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons if ( sizeof(OMX_FACEDETECTIONTYPE) == faceData->nSize ) { 244f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons CAMHAL_LOGVB("Faces detected %d", 245f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons faceData->ulFaceCount, 246f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons faceData->nSize, 247f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons sizeof(OMX_FACEDETECTIONTYPE), 248f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons faceData->eCameraView, 249f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons faceData->nPortIndex, 250f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons faceData->nVersion); 251f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons } else { 252f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons CAMHAL_LOGEB("OMX_FACEDETECTIONTYPE size mismatch: expected = %d, received = %d", 253f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons ( unsigned int ) sizeof(OMX_FACEDETECTIONTYPE), 254f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons ( unsigned int ) faceData->nSize); 255f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons return -EINVAL; 256f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons } 257f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons } else { 258f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons CAMHAL_LOGEA("Invalid OMX_FACEDETECTIONTYPE"); 259f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons return -EINVAL; 260f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons } 261c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 262c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 263f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons result = new (std::nothrow) CameraMetadataResult; 264f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons if(NULL == result.get()) { 265f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons ret = NO_MEMORY; 266f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons return ret; 267c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 268c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 269f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons //Encode face coordinates 270f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons faceRet = encodeFaceCoordinates(faceData, result->getMetadataResult() 271f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons , previewWidth, previewHeight); 272f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons if ((NO_ERROR == faceRet) || (NOT_ENOUGH_DATA == faceRet)) { 273f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons // Ignore harmless errors (no error and no update) and go ahead and encode 274f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons // the preview meta data 275f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons metaRet = encodePreviewMetadata(result->getMetadataResult() 276f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons , pBuffHeader->pPlatformPrivate); 277f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons if ( (NO_ERROR != metaRet) && (NOT_ENOUGH_DATA != metaRet) ) { 278f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons // Some 'real' error occurred during preview meta data encod, clear metadata 279f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons // result and return correct error code 280f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons result.clear(); 281f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons ret = metaRet; 282c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 283c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } else { 284f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons //Some real error occurred during face encoding, clear metadata result 285f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons // and return correct error code 286f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons result.clear(); 287f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons ret = faceRet; 288c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 289c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 290f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons if((NOT_ENOUGH_DATA == faceRet) && (NOT_ENOUGH_DATA == metaRet)) { 291f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons //No point sending the callback if nothing is changed 292c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev result.clear(); 293f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons ret = faceRet; 294c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 295c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 296c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev LOG_FUNCTION_NAME_EXIT; 297c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 298c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return ret; 299c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 300c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 301c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatus_t OMXCameraAdapter::encodeFaceCoordinates(const OMX_FACEDETECTIONTYPE *faceData, 302f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons camera_frame_metadata_t *metadataResult, 303c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev size_t previewWidth, 304c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev size_t previewHeight) 305c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 306c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev status_t ret = NO_ERROR; 307c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev camera_face_t *faces; 308c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev size_t hRange, vRange; 309c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev double tmp; 310f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons bool faceArrayChanged = false; 311c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 312c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev LOG_FUNCTION_NAME; 313c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 314f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons hRange = CameraMetadataResult::RIGHT - CameraMetadataResult::LEFT; 315f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons vRange = CameraMetadataResult::BOTTOM - CameraMetadataResult::TOP; 316c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 317f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons android::AutoMutex lock(mFaceDetectionLock); 318c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 319f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons // Avoid memory leak if called twice on same CameraMetadataResult 320f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons if ( (0 < metadataResult->number_of_faces) && (NULL != metadataResult->faces) ) { 321f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons free(metadataResult->faces); 322f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons metadataResult->number_of_faces = 0; 323f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons metadataResult->faces = NULL; 324c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 325c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 326f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons if ( (NULL != faceData) && (0 < faceData->ulFaceCount) ) { 327fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu int orient_mult; 328fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu int trans_left, trans_top, trans_right, trans_bot; 329c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 330c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faces = ( camera_face_t * ) malloc(sizeof(camera_face_t)*faceData->ulFaceCount); 331c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( NULL == faces ) { 332f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons ret = NO_MEMORY; 333f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons goto out; 334c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 335c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 336fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu /** 337fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * When device is 180 degrees oriented to the sensor, need to translate 338fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * the output from Ducati to what Android expects 339fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * Ducati always gives face coordinates in this form, irrespective of 340fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * rotation, i.e (l,t) always represents the point towards the left eye 341fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * and top of hair. 342fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * (l, t) 343fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * --------------- 344fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - ,,,,,,, - 345fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - | | - 346fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - |<a <a| - 347fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - (| ^ |) - 348fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - | -=- | - 349fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - \_____/ - 350fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * --------------- 351fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * (r, b) 352fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * 353fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * However, Android expects the coords to be in respect with what the 354fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * sensor is viewing, i.e Android expects sensor to see this with (l,t) 355fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * and (r,b) like so: 356fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * (l, t) 357fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * --------------- 358fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - _____ - 359fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - / \ - 360fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - | -=- | - 361fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - (| ^ |) - 362fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - |a> a>| - 363fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - | | - 364fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - ,,,,,,, - 365fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * --------------- 366fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * (r, b) 367fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu */ 368c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 369f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons if (mFaceOrientation == 180) { 3707762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu orient_mult = -1; 3717762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu trans_left = 2; // right is now left 3727762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu trans_top = 3; // bottom is now top 3737762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu trans_right = 0; // left is now right 3747762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu trans_bot = 1; // top is not bottom 3757762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu } else { 3767762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu orient_mult = 1; 3777762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu trans_left = 0; // left 3787762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu trans_top = 1; // top 3797762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu trans_right = 2; // right 3807762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu trans_bot = 3; // bottom 3817762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu } 3827762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu 383967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman int j = 0, i = 0; 384967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman for ( ; j < faceData->ulFaceCount ; j++) 385967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman { 38652d3388c121469e22bf41d7362640257d8268858Tyler Luu OMX_S32 nLeft = 0; 387e45763a2a361324f1771a6991525e631365ca954Tyler Luu OMX_S32 nTop = 0; 388967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman //Face filtering 389967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman //For real faces, it is seen that the h/w passes a score >=80 390967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman //For false faces, we seem to get even a score of 70 sometimes. 391967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman //In order to avoid any issue at application level, we filter 392967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman //<=70 score here. 393967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman if(faceData->tFacePosition[j].nScore <= FACE_DETECTION_THRESHOLD) 394967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman continue; 395967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman 396f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons if (mFaceOrientation == 180) { 39752d3388c121469e22bf41d7362640257d8268858Tyler Luu // from sensor pov, the left pos is the right corner of the face in pov of frame 3987762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu nLeft = faceData->tFacePosition[j].nLeft + faceData->tFacePosition[j].nWidth; 399e45763a2a361324f1771a6991525e631365ca954Tyler Luu nTop = faceData->tFacePosition[j].nTop + faceData->tFacePosition[j].nHeight; 40052d3388c121469e22bf41d7362640257d8268858Tyler Luu } else { 4017762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu nLeft = faceData->tFacePosition[j].nLeft; 402e45763a2a361324f1771a6991525e631365ca954Tyler Luu nTop = faceData->tFacePosition[j].nTop; 40352d3388c121469e22bf41d7362640257d8268858Tyler Luu } 40452d3388c121469e22bf41d7362640257d8268858Tyler Luu 40552d3388c121469e22bf41d7362640257d8268858Tyler Luu tmp = ( double ) nLeft / ( double ) previewWidth; 406c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev tmp *= hRange; 407c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev tmp -= hRange/2; 408fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu faces[i].rect[trans_left] = tmp; 409c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 410e45763a2a361324f1771a6991525e631365ca954Tyler Luu tmp = ( double ) nTop / ( double )previewHeight; 411c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev tmp *= vRange; 412c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev tmp -= vRange/2; 413fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu faces[i].rect[trans_top] = tmp; 414c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 415967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman tmp = ( double ) faceData->tFacePosition[j].nWidth / ( double ) previewWidth; 416c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev tmp *= hRange; 417fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu tmp *= orient_mult; 418fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu faces[i].rect[trans_right] = faces[i].rect[trans_left] + tmp; 419c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 420967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman tmp = ( double ) faceData->tFacePosition[j].nHeight / ( double ) previewHeight; 421c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev tmp *= vRange; 422fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu tmp *= orient_mult; 423fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu faces[i].rect[trans_bot] = faces[i].rect[trans_top] + tmp; 424c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 425967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman faces[i].score = faceData->tFacePosition[j].nScore; 426c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faces[i].id = 0; 427f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons faces[i].left_eye[0] = CameraMetadataResult::INVALID_DATA; 428f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons faces[i].left_eye[1] = CameraMetadataResult::INVALID_DATA; 429f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons faces[i].right_eye[0] = CameraMetadataResult::INVALID_DATA; 430f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons faces[i].right_eye[1] = CameraMetadataResult::INVALID_DATA; 431f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons faces[i].mouth[0] = CameraMetadataResult::INVALID_DATA; 432f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons faces[i].mouth[1] = CameraMetadataResult::INVALID_DATA; 433967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman i++; 434c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 435c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 436f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons metadataResult->number_of_faces = i; 437f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons metadataResult->faces = faces; 438c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 439f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons for (int i = 0; i < metadataResult->number_of_faces; i++) 4407762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu { 441f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons bool faceChanged = true; 4427762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu int centerX = (faces[i].rect[trans_left] + faces[i].rect[trans_right] ) / 2; 4437762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu int centerY = (faces[i].rect[trans_top] + faces[i].rect[trans_bot] ) / 2; 4447762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu 4457762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu int sizeX = (faces[i].rect[trans_right] - faces[i].rect[trans_left] ) ; 4467762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu int sizeY = (faces[i].rect[trans_bot] - faces[i].rect[trans_top] ) ; 4477762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu 4487762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu for (int j = 0; j < faceDetectionNumFacesLastOutput; j++) 4497762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu { 4507762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu int tempCenterX = (faceDetectionLastOutput[j].rect[trans_left] + 4517762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu faceDetectionLastOutput[j].rect[trans_right] ) / 2; 4527762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu int tempCenterY = (faceDetectionLastOutput[j].rect[trans_top] + 4537762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu faceDetectionLastOutput[j].rect[trans_bot] ) / 2; 4547762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu int tempSizeX = (faceDetectionLastOutput[j].rect[trans_right] - 4557762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu faceDetectionLastOutput[j].rect[trans_left] ) ; 4567762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu int tempSizeY = (faceDetectionLastOutput[j].rect[trans_bot] - 4577762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu faceDetectionLastOutput[j].rect[trans_top] ) ; 4587762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu 459f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons if ( ( tempCenterX == centerX) && 460f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons ( tempCenterY == centerY) ) { 461f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons // Found Face. 462f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons // Now check size of rectangle 463f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons // compare to last output. 464f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons if ( ( tempSizeX == sizeX ) && 465f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons ( tempSizeY == sizeY ) ) { 466f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons faceChanged = false; 4677762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu } 4687762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu } 4697762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu } 470f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons // Send face detection data after some face coordinate changes 471f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons if (faceChanged) { 472f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons faceArrayChanged = true; 473f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons } 4747762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu } 4757762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu 4767762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu // Save this output for next iteration 477f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons for (int i = 0; i < metadataResult->number_of_faces; i++) 4787762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu { 4797762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu faceDetectionLastOutput[i] = faces[i]; 4807762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu } 481c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } else { 482f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons metadataResult->number_of_faces = 0; 483f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons metadataResult->faces = NULL; 484c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 485c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 486f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons // Send face detection data after face count changes 487f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons if (faceDetectionNumFacesLastOutput != metadataResult->number_of_faces) { 488f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons faceArrayChanged = true; 489f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons } 490f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons faceDetectionNumFacesLastOutput = metadataResult->number_of_faces; 491f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 492f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons if ( !faceArrayChanged ) { 493f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons ret = NOT_ENOUGH_DATA; 494f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons } 495c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 496c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev LOG_FUNCTION_NAME_EXIT; 497c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 498f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsout: 499f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 500c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return ret; 501c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 502c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 503f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons} // namespace Camera 504f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons} // namespace Ti 505