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#undef LOG_TAG 25c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 26c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#define LOG_TAG "CameraHAL" 27c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 28c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#include "CameraHal.h" 29c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#include "OMXCameraAdapter.h" 30c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 31967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman#define FACE_DETECTION_THRESHOLD 80 32967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman 337762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu// constants used for face smooth filtering 347762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luustatic const int HorizontalFilterThreshold = 40; 357762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luustatic const int VerticalFilterThreshold = 40; 367762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luustatic const int HorizontalFaceSizeThreshold = 30; 377762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luustatic const int VerticalFaceSizeThreshold = 30; 387762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu 397762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu 40c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevnamespace android { 41c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 42c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatus_t OMXCameraAdapter::setParametersFD(const CameraParameters ¶ms, 43c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev BaseCameraAdapter::AdapterState state) 44c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 45c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev status_t ret = NO_ERROR; 46c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 47c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev LOG_FUNCTION_NAME; 48c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 49c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev LOG_FUNCTION_NAME_EXIT; 50c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 51c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return ret; 52c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 53c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 54c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatus_t OMXCameraAdapter::startFaceDetection() 55c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 56c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman status_t ret = NO_ERROR; 57c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman 58c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev Mutex::Autolock lock(mFaceDetectionLock); 59c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman 60c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman ret = setFaceDetection(true, mDeviceOrientation); 61c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman if (ret != NO_ERROR) { 62c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman goto out; 63c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman } 64c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman 65f2170decdf6bf41e590842b0fe5c0ed3852ebec3Emilian Peev if ( mFaceDetectionRunning ) { 66f2170decdf6bf41e590842b0fe5c0ed3852ebec3Emilian Peev mFDSwitchAlgoPriority = true; 67f2170decdf6bf41e590842b0fe5c0ed3852ebec3Emilian Peev } 68c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman 697762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu // Note: White balance will not be face prioritized, since 707762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu // the algorithm needs full frame statistics, and not face 717762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu // regions alone. 72c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman 737762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu faceDetectionNumFacesLastOutput = 0; 74c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman out: 75c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman return ret; 76c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 77c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 78c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatus_t OMXCameraAdapter::stopFaceDetection() 79c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 80c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman status_t ret = NO_ERROR; 81c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman const char *str = NULL; 82c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman BaseCameraAdapter::AdapterState state; 83c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman BaseCameraAdapter::getState(state); 84c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman 85c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev Mutex::Autolock lock(mFaceDetectionLock); 86c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman 87c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman ret = setFaceDetection(false, mDeviceOrientation); 88c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman if (ret != NO_ERROR) { 89c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman goto out; 90c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman } 91c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman 92c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman // Reset 3A settings 93c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman ret = setParameters3A(mParams, state); 94c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman if (ret != NO_ERROR) { 95c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman goto out; 96c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman } 97c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman 98c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman if (mPending3Asettings) { 99c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman apply3Asettings(mParameters3A); 100c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman } 101c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman 1027762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu faceDetectionNumFacesLastOutput = 0; 103c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman out: 104c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman return ret; 105c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 106c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 107aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luuvoid OMXCameraAdapter::pauseFaceDetection(bool pause) 108aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu{ 109aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu Mutex::Autolock lock(mFaceDetectionLock); 110aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu // pausing will only take affect if fd is already running 111aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu if (mFaceDetectionRunning) { 112aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu mFaceDetectionPaused = pause; 1137762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu faceDetectionNumFacesLastOutput = 0; 114aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu } 115aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu} 116aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu 117c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatus_t OMXCameraAdapter::setFaceDetection(bool enable, OMX_U32 orientation) 118c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 119c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev status_t ret = NO_ERROR; 120c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev OMX_ERRORTYPE eError = OMX_ErrorNone; 121c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev OMX_CONFIG_OBJDETECTIONTYPE objDetection; 122c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 123c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev LOG_FUNCTION_NAME; 124c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 125c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( OMX_StateInvalid == mComponentState ) 126c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev { 127c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGEA("OMX component is in invalid state"); 128c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev ret = -EINVAL; 129c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 130c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 131c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( NO_ERROR == ret ) 132c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev { 1337762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu if ( orientation > 270 ) { 134c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev orientation = 0; 135c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 136c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 137c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev OMX_INIT_STRUCT_PTR (&objDetection, OMX_CONFIG_OBJDETECTIONTYPE); 138c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev objDetection.nPortIndex = mCameraAdapterParameters.mPrevPortIndex; 139c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev objDetection.nDeviceOrientation = orientation; 140c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( enable ) 141c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev { 142c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev objDetection.bEnable = OMX_TRUE; 143c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 144c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev else 145c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev { 146c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev objDetection.bEnable = OMX_FALSE; 147c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 148c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 149c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, 150c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev ( OMX_INDEXTYPE ) OMX_IndexConfigImageFaceDetection, 151c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev &objDetection); 152c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( OMX_ErrorNone != eError ) 153c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev { 154c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGEB("Error while configuring face detection 0x%x", eError); 155c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev ret = -1; 156c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 157c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev else 158c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev { 159c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGDA("Face detection configured successfully"); 160c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 161c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 162c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 163c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( NO_ERROR == ret ) 164c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev { 165ef73bec8a83a2fd7fbb072d009382c64eb2da0eeTyler Luu ret = setExtraData(enable, mCameraAdapterParameters.mPrevPortIndex, OMX_FaceDetection); 166c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 167ef73bec8a83a2fd7fbb072d009382c64eb2da0eeTyler Luu if ( NO_ERROR != ret ) 168c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev { 169ef73bec8a83a2fd7fbb072d009382c64eb2da0eeTyler Luu CAMHAL_LOGEA("Error while configuring face detection extra data"); 170c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 171c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev else 172c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev { 173c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGDA("Face detection extra data configured successfully"); 174c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 175c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 176c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 177c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( NO_ERROR == ret ) 178c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev { 179c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev mFaceDetectionRunning = enable; 180aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu mFaceDetectionPaused = !enable; 181c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 182c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 183c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev LOG_FUNCTION_NAME_EXIT; 184c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 185c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return ret; 186c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 187c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 188c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatus_t OMXCameraAdapter::detectFaces(OMX_BUFFERHEADERTYPE* pBuffHeader, 189c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev sp<CameraFDResult> &result, 190c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev size_t previewWidth, 191c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev size_t previewHeight) 192c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 193c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev status_t ret = NO_ERROR; 194c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev OMX_ERRORTYPE eError = OMX_ErrorNone; 195c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev OMX_TI_FACERESULT *faceResult; 196c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev OMX_OTHER_EXTRADATATYPE *extraData; 197c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev OMX_FACEDETECTIONTYPE *faceData; 198c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev OMX_TI_PLATFORMPRIVATE *platformPrivate; 199c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev camera_frame_metadata_t *faces; 200c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 201c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev LOG_FUNCTION_NAME; 202c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 203c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( OMX_StateExecuting != mComponentState ) { 204c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGEA("OMX component is not in executing state"); 205c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return NO_INIT; 206c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 207c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 208c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( NULL == pBuffHeader ) { 209c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGEA("Invalid Buffer header"); 210c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return-EINVAL; 211c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 212c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 213c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev platformPrivate = (OMX_TI_PLATFORMPRIVATE *) (pBuffHeader->pPlatformPrivate); 214c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( NULL != platformPrivate ) { 215c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( sizeof(OMX_TI_PLATFORMPRIVATE) == platformPrivate->nSize ) { 216c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGVB("Size = %d, sizeof = %d, pAuxBuf = 0x%x, pAuxBufSize= %d, pMetaDataBufer = 0x%x, nMetaDataSize = %d", 217c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev platformPrivate->nSize, 218c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev sizeof(OMX_TI_PLATFORMPRIVATE), 219c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev platformPrivate->pAuxBuf1, 220c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev platformPrivate->pAuxBufSize1, 221c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev platformPrivate->pMetaDataBuffer, 222c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev platformPrivate->nMetaDataSize); 223c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } else { 22441a31123a0fc59b8112460285d3f1ba73c5537c0Emilian Peev CAMHAL_LOGDB("OMX_TI_PLATFORMPRIVATE size mismatch: expected = %d, received = %d", 225c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev ( unsigned int ) sizeof(OMX_TI_PLATFORMPRIVATE), 226c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev ( unsigned int ) platformPrivate->nSize); 22782640237cf0ca200932a66777fd1907d66cd0322Akwasi Boateng return -EINVAL; 228c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 229c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } else { 23041a31123a0fc59b8112460285d3f1ba73c5537c0Emilian Peev CAMHAL_LOGDA("Invalid OMX_TI_PLATFORMPRIVATE"); 231c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return-EINVAL; 232c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 233c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 234c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 235c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( 0 >= platformPrivate->nMetaDataSize ) { 23641a31123a0fc59b8112460285d3f1ba73c5537c0Emilian Peev CAMHAL_LOGDB("OMX_TI_PLATFORMPRIVATE nMetaDataSize is size is %d", 237c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev ( unsigned int ) platformPrivate->nMetaDataSize); 238c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return -EINVAL; 239c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 240c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 241cf0a61f13533d70cb7ad700330de94142c2afe6aMilen Mitkov extraData = getExtradata((OMX_OTHER_EXTRADATATYPE *) (platformPrivate->pMetaDataBuffer), 242cf0a61f13533d70cb7ad700330de94142c2afe6aMilen Mitkov (OMX_EXTRADATATYPE)OMX_FaceDetection); 243cf0a61f13533d70cb7ad700330de94142c2afe6aMilen Mitkov 244c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( NULL != extraData ) { 245c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGVB("Size = %d, sizeof = %d, eType = 0x%x, nDataSize= %d, nPortIndex = 0x%x, nVersion = 0x%x", 246c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev extraData->nSize, 247c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev sizeof(OMX_OTHER_EXTRADATATYPE), 248c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev extraData->eType, 249c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev extraData->nDataSize, 250c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev extraData->nPortIndex, 251c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev extraData->nVersion); 252c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } else { 25341a31123a0fc59b8112460285d3f1ba73c5537c0Emilian Peev CAMHAL_LOGDA("Invalid OMX_OTHER_EXTRADATATYPE"); 254c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return -EINVAL; 255c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 256c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 257c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faceData = ( OMX_FACEDETECTIONTYPE * ) extraData->data; 258c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( NULL != faceData ) { 259c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( sizeof(OMX_FACEDETECTIONTYPE) == faceData->nSize ) { 260c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGVB("Faces detected %d", 261c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faceData->ulFaceCount, 262c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faceData->nSize, 263c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev sizeof(OMX_FACEDETECTIONTYPE), 264c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faceData->eCameraView, 265c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faceData->nPortIndex, 266c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faceData->nVersion); 267c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } else { 26841a31123a0fc59b8112460285d3f1ba73c5537c0Emilian Peev CAMHAL_LOGDB("OMX_FACEDETECTIONTYPE size mismatch: expected = %d, received = %d", 269c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev ( unsigned int ) sizeof(OMX_FACEDETECTIONTYPE), 270c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev ( unsigned int ) faceData->nSize); 271c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return -EINVAL; 272c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 273c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } else { 274c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGEA("Invalid OMX_FACEDETECTIONTYPE"); 275c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return -EINVAL; 276c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 277c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 278c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev ret = encodeFaceCoordinates(faceData, &faces, previewWidth, previewHeight); 279c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 280c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( NO_ERROR == ret ) { 281c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev result = new CameraFDResult(faces); 282c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } else { 283c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev result.clear(); 284c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev result = NULL; 285c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 286c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 287c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev LOG_FUNCTION_NAME_EXIT; 288c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 289c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return ret; 290c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 291c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 292c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatus_t OMXCameraAdapter::encodeFaceCoordinates(const OMX_FACEDETECTIONTYPE *faceData, 293c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev camera_frame_metadata_t **pFaces, 294c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev size_t previewWidth, 295c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev size_t previewHeight) 296c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 297c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev status_t ret = NO_ERROR; 298c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev camera_face_t *faces; 299c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev camera_frame_metadata_t *faceResult; 300c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev size_t hRange, vRange; 301c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev double tmp; 302c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 303c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev LOG_FUNCTION_NAME; 304c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 305c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( NULL == faceData ) { 306c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGEA("Invalid OMX_FACEDETECTIONTYPE parameter"); 307c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return EINVAL; 308c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 309c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 310c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev LOG_FUNCTION_NAME 311c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 312c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev hRange = CameraFDResult::RIGHT - CameraFDResult::LEFT; 313c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev vRange = CameraFDResult::BOTTOM - CameraFDResult::TOP; 314c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 315c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faceResult = ( camera_frame_metadata_t * ) malloc(sizeof(camera_frame_metadata_t)); 316c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( NULL == faceResult ) { 317c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return -ENOMEM; 318c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 319c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 320c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( 0 < faceData->ulFaceCount ) { 321fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu int orient_mult; 322fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu int trans_left, trans_top, trans_right, trans_bot; 323c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 324c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faces = ( camera_face_t * ) malloc(sizeof(camera_face_t)*faceData->ulFaceCount); 325c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( NULL == faces ) { 326c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return -ENOMEM; 327c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 328c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 329fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu /** 330fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * When device is 180 degrees oriented to the sensor, need to translate 331fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * the output from Ducati to what Android expects 332fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * Ducati always gives face coordinates in this form, irrespective of 333fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * rotation, i.e (l,t) always represents the point towards the left eye 334fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * and top of hair. 335fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * (l, t) 336fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * --------------- 337fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - ,,,,,,, - 338fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - | | - 339fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - |<a <a| - 340fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - (| ^ |) - 341fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - | -=- | - 342fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - \_____/ - 343fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * --------------- 344fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * (r, b) 345fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * 346fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * However, Android expects the coords to be in respect with what the 347fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * sensor is viewing, i.e Android expects sensor to see this with (l,t) 348fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * and (r,b) like so: 349fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * (l, t) 350fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * --------------- 351fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - _____ - 352fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - / \ - 353fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - | -=- | - 354fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - (| ^ |) - 355fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - |a> a>| - 356fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - | | - 357fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - ,,,,,,, - 358fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * --------------- 359fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * (r, b) 360fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu */ 361c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 3627762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu if (mDeviceOrientation == 180) { 3637762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu orient_mult = -1; 3647762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu trans_left = 2; // right is now left 3657762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu trans_top = 3; // bottom is now top 3667762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu trans_right = 0; // left is now right 3677762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu trans_bot = 1; // top is not bottom 3687762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu } else { 3697762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu orient_mult = 1; 3707762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu trans_left = 0; // left 3717762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu trans_top = 1; // top 3727762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu trans_right = 2; // right 3737762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu trans_bot = 3; // bottom 3747762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu } 3757762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu 376967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman int j = 0, i = 0; 377967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman for ( ; j < faceData->ulFaceCount ; j++) 378967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman { 37952d3388c121469e22bf41d7362640257d8268858Tyler Luu OMX_S32 nLeft = 0; 380e45763a2a361324f1771a6991525e631365ca954Tyler Luu OMX_S32 nTop = 0; 381967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman //Face filtering 382967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman //For real faces, it is seen that the h/w passes a score >=80 383967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman //For false faces, we seem to get even a score of 70 sometimes. 384967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman //In order to avoid any issue at application level, we filter 385967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman //<=70 score here. 386967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman if(faceData->tFacePosition[j].nScore <= FACE_DETECTION_THRESHOLD) 387967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman continue; 388967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman 38952d3388c121469e22bf41d7362640257d8268858Tyler Luu if (mDeviceOrientation == 180) { 39052d3388c121469e22bf41d7362640257d8268858Tyler Luu // from sensor pov, the left pos is the right corner of the face in pov of frame 3917762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu nLeft = faceData->tFacePosition[j].nLeft + faceData->tFacePosition[j].nWidth; 392e45763a2a361324f1771a6991525e631365ca954Tyler Luu nTop = faceData->tFacePosition[j].nTop + faceData->tFacePosition[j].nHeight; 39352d3388c121469e22bf41d7362640257d8268858Tyler Luu } else { 3947762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu nLeft = faceData->tFacePosition[j].nLeft; 395e45763a2a361324f1771a6991525e631365ca954Tyler Luu nTop = faceData->tFacePosition[j].nTop; 39652d3388c121469e22bf41d7362640257d8268858Tyler Luu } 39752d3388c121469e22bf41d7362640257d8268858Tyler Luu 39852d3388c121469e22bf41d7362640257d8268858Tyler Luu tmp = ( double ) nLeft / ( double ) previewWidth; 399c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev tmp *= hRange; 400c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev tmp -= hRange/2; 401fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu faces[i].rect[trans_left] = tmp; 402c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 403e45763a2a361324f1771a6991525e631365ca954Tyler Luu tmp = ( double ) nTop / ( double )previewHeight; 404c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev tmp *= vRange; 405c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev tmp -= vRange/2; 406fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu faces[i].rect[trans_top] = tmp; 407c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 408967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman tmp = ( double ) faceData->tFacePosition[j].nWidth / ( double ) previewWidth; 409c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev tmp *= hRange; 410fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu tmp *= orient_mult; 411fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu faces[i].rect[trans_right] = faces[i].rect[trans_left] + tmp; 412c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 413967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman tmp = ( double ) faceData->tFacePosition[j].nHeight / ( double ) previewHeight; 414c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev tmp *= vRange; 415fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu tmp *= orient_mult; 416fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu faces[i].rect[trans_bot] = faces[i].rect[trans_top] + tmp; 417c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 418967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman faces[i].score = faceData->tFacePosition[j].nScore; 419c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faces[i].id = 0; 420c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faces[i].left_eye[0] = CameraFDResult::INVALID_DATA; 421c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faces[i].left_eye[1] = CameraFDResult::INVALID_DATA; 422c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faces[i].right_eye[0] = CameraFDResult::INVALID_DATA; 423c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faces[i].right_eye[1] = CameraFDResult::INVALID_DATA; 424c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faces[i].mouth[0] = CameraFDResult::INVALID_DATA; 425c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faces[i].mouth[1] = CameraFDResult::INVALID_DATA; 426967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman i++; 427c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 428c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 429967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman faceResult->number_of_faces = i; 430c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faceResult->faces = faces; 431c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 4327762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu for (int i = 0; i < faceResult->number_of_faces; i++) 4337762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu { 4347762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu int centerX = (faces[i].rect[trans_left] + faces[i].rect[trans_right] ) / 2; 4357762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu int centerY = (faces[i].rect[trans_top] + faces[i].rect[trans_bot] ) / 2; 4367762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu 4377762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu int sizeX = (faces[i].rect[trans_right] - faces[i].rect[trans_left] ) ; 4387762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu int sizeY = (faces[i].rect[trans_bot] - faces[i].rect[trans_top] ) ; 4397762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu 4407762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu for (int j = 0; j < faceDetectionNumFacesLastOutput; j++) 4417762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu { 4427762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu int tempCenterX = (faceDetectionLastOutput[j].rect[trans_left] + 4437762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu faceDetectionLastOutput[j].rect[trans_right] ) / 2; 4447762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu int tempCenterY = (faceDetectionLastOutput[j].rect[trans_top] + 4457762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu faceDetectionLastOutput[j].rect[trans_bot] ) / 2; 4467762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu int tempSizeX = (faceDetectionLastOutput[j].rect[trans_right] - 4477762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu faceDetectionLastOutput[j].rect[trans_left] ) ; 4487762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu int tempSizeY = (faceDetectionLastOutput[j].rect[trans_bot] - 4497762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu faceDetectionLastOutput[j].rect[trans_top] ) ; 4507762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu 4517762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu if ( (abs(tempCenterX - centerX) < HorizontalFilterThreshold) && 4527762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu (abs(tempCenterY - centerY) < VerticalFilterThreshold) ) 4537762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu { 4547762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu // Found Face. It did not move too far. 4557762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu // Now check size of rectangle compare to last output 4567762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu if ( (abs (tempSizeX -sizeX) < HorizontalFaceSizeThreshold) && 4577762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu (abs (tempSizeY -sizeY) < VerticalFaceSizeThreshold) ) 4587762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu { 4597762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu // Rectangle is almost same as last time 4607762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu // Output exactly what was done for this face last time. 4617762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu faces[i] = faceDetectionLastOutput[j]; 4627762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu } 4637762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu else 4647762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu { 4657762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu // TODO(XXX): Rectangle size changed but position is same. 4667762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu // Possibly we can apply just positional correctness. 4677762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu } 4687762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu } 4697762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu } 4707762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu } 4717762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu 4727762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu // Save this output for next iteration 4737762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu for (int i = 0; i < faceResult->number_of_faces; i++) 4747762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu { 4757762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu faceDetectionLastOutput[i] = faces[i]; 4767762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu } 4777762bf32b7bd874ce34948eb53a3bfa3906f4aefTyler Luu faceDetectionNumFacesLastOutput = faceResult->number_of_faces; 478c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } else { 479c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faceResult->number_of_faces = 0; 480c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faceResult->faces = NULL; 481c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 482c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 483c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev *pFaces = faceResult; 484c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 485c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev LOG_FUNCTION_NAME_EXIT; 486c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 487c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return ret; 488c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 489c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 490c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev}; 491