OMXFD.cpp revision 967f1197f015b6d2f3b34e60fa787f7066efb824
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 33c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevnamespace android { 34c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 35c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatus_t OMXCameraAdapter::setParametersFD(const CameraParameters ¶ms, 36c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev BaseCameraAdapter::AdapterState state) 37c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 38c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev status_t ret = NO_ERROR; 39c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 40c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev LOG_FUNCTION_NAME; 41c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 42c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev LOG_FUNCTION_NAME_EXIT; 43c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 44c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return ret; 45c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 46c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 47c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatus_t OMXCameraAdapter::startFaceDetection() 48c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 49c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman status_t ret = NO_ERROR; 50c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman 51c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev Mutex::Autolock lock(mFaceDetectionLock); 52c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman 53c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman ret = setFaceDetection(true, mDeviceOrientation); 54c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman if (ret != NO_ERROR) { 55c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman goto out; 56c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman } 57c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman 58c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman // Set 3A modes to face priority 59c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman ret = setExposureMode(mParameters3A); 60c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman if (ret != NO_ERROR) { 61c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman goto out; 62c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman } 63c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman 64c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman 658cb48e582f4f3c93aa25159c1116a7c83bfa388aSundar Raman //Note: White balance will not be face prioritized, since 668cb48e582f4f3c93aa25159c1116a7c83bfa388aSundar Raman //the algorithm needs full frame statistics, and not face 678cb48e582f4f3c93aa25159c1116a7c83bfa388aSundar Raman //regions alone. 688cb48e582f4f3c93aa25159c1116a7c83bfa388aSundar Raman 69c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman 70c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman out: 71c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman return ret; 72c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 73c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 74c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatus_t OMXCameraAdapter::stopFaceDetection() 75c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 76c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman status_t ret = NO_ERROR; 77c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman const char *str = NULL; 78c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman BaseCameraAdapter::AdapterState state; 79c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman BaseCameraAdapter::getState(state); 80c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman 81c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev Mutex::Autolock lock(mFaceDetectionLock); 82c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman 83c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman ret = setFaceDetection(false, mDeviceOrientation); 84c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman if (ret != NO_ERROR) { 85c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman goto out; 86c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman } 87c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman 88c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman // Reset 3A settings 89c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman ret = setParameters3A(mParams, state); 90c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman if (ret != NO_ERROR) { 91c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman goto out; 92c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman } 93c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman 94c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman if (mPending3Asettings) { 95c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman apply3Asettings(mParameters3A); 96c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman } 97c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman 98c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman out: 99c0fc811b503ef0c0ccd024f77f9ac7d6972f77c8Sundar Raman return ret; 100c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 101c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 102aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luuvoid OMXCameraAdapter::pauseFaceDetection(bool pause) 103aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu{ 104aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu Mutex::Autolock lock(mFaceDetectionLock); 105aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu // pausing will only take affect if fd is already running 106aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu if (mFaceDetectionRunning) { 107aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu mFaceDetectionPaused = pause; 108aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu } 109aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu} 110aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu 111c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatus_t OMXCameraAdapter::setFaceDetection(bool enable, OMX_U32 orientation) 112c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 113c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev status_t ret = NO_ERROR; 114c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev OMX_ERRORTYPE eError = OMX_ErrorNone; 115c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev OMX_CONFIG_EXTRADATATYPE extraDataControl; 116c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev OMX_CONFIG_OBJDETECTIONTYPE objDetection; 117c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 118c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev LOG_FUNCTION_NAME; 119c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 120c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( OMX_StateInvalid == mComponentState ) 121c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev { 122c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGEA("OMX component is in invalid state"); 123c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev ret = -EINVAL; 124c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 125c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 126c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( NO_ERROR == ret ) 127c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev { 128c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( orientation < 0 || orientation > 270 ) { 129c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev orientation = 0; 130c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 131c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 132c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev OMX_INIT_STRUCT_PTR (&objDetection, OMX_CONFIG_OBJDETECTIONTYPE); 133c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev objDetection.nPortIndex = mCameraAdapterParameters.mPrevPortIndex; 134c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev objDetection.nDeviceOrientation = orientation; 135c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( enable ) 136c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev { 137c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev objDetection.bEnable = OMX_TRUE; 138c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 139c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev else 140c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev { 141c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev objDetection.bEnable = OMX_FALSE; 142c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 143c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 144c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, 145c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev ( OMX_INDEXTYPE ) OMX_IndexConfigImageFaceDetection, 146c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev &objDetection); 147c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( OMX_ErrorNone != eError ) 148c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev { 149c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGEB("Error while configuring face detection 0x%x", eError); 150c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev ret = -1; 151c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 152c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev else 153c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev { 154c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGDA("Face detection configured successfully"); 155c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 156c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 157c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 158c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( NO_ERROR == ret ) 159c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev { 160c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev OMX_INIT_STRUCT_PTR (&extraDataControl, OMX_CONFIG_EXTRADATATYPE); 161c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev extraDataControl.nPortIndex = mCameraAdapterParameters.mPrevPortIndex; 162c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev extraDataControl.eExtraDataType = OMX_FaceDetection; 163c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev extraDataControl.eCameraView = OMX_2D; 164c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( enable ) 165c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev { 166c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev extraDataControl.bEnable = OMX_TRUE; 167c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 168c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev else 169c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev { 170c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev extraDataControl.bEnable = OMX_FALSE; 171c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 172c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 173c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, 174c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev ( OMX_INDEXTYPE ) OMX_IndexConfigOtherExtraDataControl, 175c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev &extraDataControl); 176c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( OMX_ErrorNone != eError ) 177c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev { 178c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGEB("Error while configuring face detection extra data 0x%x", 179c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev eError); 180c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev ret = -1; 181c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 182c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev else 183c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev { 184c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGDA("Face detection extra data configured successfully"); 185c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 186c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 187c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 188c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( NO_ERROR == ret ) 189c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev { 190c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev mFaceDetectionRunning = enable; 191aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu mFaceDetectionPaused = !enable; 192c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 193c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 194c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev LOG_FUNCTION_NAME_EXIT; 195c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 196c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return ret; 197c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 198c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 199c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatus_t OMXCameraAdapter::detectFaces(OMX_BUFFERHEADERTYPE* pBuffHeader, 200c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev sp<CameraFDResult> &result, 201c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev size_t previewWidth, 202c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev size_t previewHeight) 203c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 204c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev status_t ret = NO_ERROR; 205c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev OMX_ERRORTYPE eError = OMX_ErrorNone; 206c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev OMX_TI_FACERESULT *faceResult; 207c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev OMX_OTHER_EXTRADATATYPE *extraData; 208c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev OMX_FACEDETECTIONTYPE *faceData; 209c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev OMX_TI_PLATFORMPRIVATE *platformPrivate; 210c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev camera_frame_metadata_t *faces; 211c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 212c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev LOG_FUNCTION_NAME; 213c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 214c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( OMX_StateExecuting != mComponentState ) { 215c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGEA("OMX component is not in executing state"); 216c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return NO_INIT; 217c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 218c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 219c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( NULL == pBuffHeader ) { 220c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGEA("Invalid Buffer header"); 221c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return-EINVAL; 222c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 223c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 224c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev platformPrivate = (OMX_TI_PLATFORMPRIVATE *) (pBuffHeader->pPlatformPrivate); 225c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( NULL != platformPrivate ) { 226c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( sizeof(OMX_TI_PLATFORMPRIVATE) == platformPrivate->nSize ) { 227c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGVB("Size = %d, sizeof = %d, pAuxBuf = 0x%x, pAuxBufSize= %d, pMetaDataBufer = 0x%x, nMetaDataSize = %d", 228c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev platformPrivate->nSize, 229c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev sizeof(OMX_TI_PLATFORMPRIVATE), 230c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev platformPrivate->pAuxBuf1, 231c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev platformPrivate->pAuxBufSize1, 232c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev platformPrivate->pMetaDataBuffer, 233c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev platformPrivate->nMetaDataSize); 234c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } else { 235c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGEB("OMX_TI_PLATFORMPRIVATE size mismatch: expected = %d, received = %d", 236c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev ( unsigned int ) sizeof(OMX_TI_PLATFORMPRIVATE), 237c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev ( unsigned int ) platformPrivate->nSize); 238c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev ret = -EINVAL; 239c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 240c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } else { 241c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGEA("Invalid OMX_TI_PLATFORMPRIVATE"); 242c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return-EINVAL; 243c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 244c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 245c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 246c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( 0 >= platformPrivate->nMetaDataSize ) { 247c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGEB("OMX_TI_PLATFORMPRIVATE nMetaDataSize is size is %d", 248c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev ( unsigned int ) platformPrivate->nMetaDataSize); 249c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return -EINVAL; 250c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 251c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 252c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev extraData = (OMX_OTHER_EXTRADATATYPE *) (platformPrivate->pMetaDataBuffer); 253c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( NULL != extraData ) { 254c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGVB("Size = %d, sizeof = %d, eType = 0x%x, nDataSize= %d, nPortIndex = 0x%x, nVersion = 0x%x", 255c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev extraData->nSize, 256c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev sizeof(OMX_OTHER_EXTRADATATYPE), 257c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev extraData->eType, 258c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev extraData->nDataSize, 259c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev extraData->nPortIndex, 260c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev extraData->nVersion); 261c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } else { 262c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGEA("Invalid OMX_OTHER_EXTRADATATYPE"); 263c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return -EINVAL; 264c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 265c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 266c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faceData = ( OMX_FACEDETECTIONTYPE * ) extraData->data; 267c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( NULL != faceData ) { 268c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( sizeof(OMX_FACEDETECTIONTYPE) == faceData->nSize ) { 269c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGVB("Faces detected %d", 270c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faceData->ulFaceCount, 271c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faceData->nSize, 272c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev sizeof(OMX_FACEDETECTIONTYPE), 273c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faceData->eCameraView, 274c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faceData->nPortIndex, 275c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faceData->nVersion); 276c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } else { 277782a084e5fec691d3985b31c3ab7be1584d879b3Iliyan Malchev CAMHAL_LOGEB("OMX_FACEDETECTIONTYPE size mismatch: expected = %d, received = %d", 278c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev ( unsigned int ) sizeof(OMX_FACEDETECTIONTYPE), 279c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev ( unsigned int ) faceData->nSize); 280c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return -EINVAL; 281c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 282c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } else { 283c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGEA("Invalid OMX_FACEDETECTIONTYPE"); 284c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return -EINVAL; 285c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 286c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 287c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev ret = encodeFaceCoordinates(faceData, &faces, previewWidth, previewHeight); 288c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 289c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( NO_ERROR == ret ) { 290c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev result = new CameraFDResult(faces); 291c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } else { 292c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev result.clear(); 293c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev result = NULL; 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, 302c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev camera_frame_metadata_t **pFaces, 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 camera_frame_metadata_t *faceResult; 309c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev size_t hRange, vRange; 310c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev double tmp; 311c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 312c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev LOG_FUNCTION_NAME; 313c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 314c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( NULL == faceData ) { 315c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev CAMHAL_LOGEA("Invalid OMX_FACEDETECTIONTYPE parameter"); 316c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return EINVAL; 317c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 318c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 319c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev LOG_FUNCTION_NAME 320c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 321c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev hRange = CameraFDResult::RIGHT - CameraFDResult::LEFT; 322c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev vRange = CameraFDResult::BOTTOM - CameraFDResult::TOP; 323c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 324c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faceResult = ( camera_frame_metadata_t * ) malloc(sizeof(camera_frame_metadata_t)); 325c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( NULL == faceResult ) { 326c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return -ENOMEM; 327c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 328c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 329c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( 0 < faceData->ulFaceCount ) { 330fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu int orient_mult; 331fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu int trans_left, trans_top, trans_right, trans_bot; 332c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 333c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faces = ( camera_face_t * ) malloc(sizeof(camera_face_t)*faceData->ulFaceCount); 334c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if ( NULL == faces ) { 335c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return -ENOMEM; 336c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 337c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 338fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu /** 339fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * When device is 180 degrees oriented to the sensor, need to translate 340fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * the output from Ducati to what Android expects 341fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * Ducati always gives face coordinates in this form, irrespective of 342fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * rotation, i.e (l,t) always represents the point towards the left eye 343fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * and top of hair. 344fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * (l, t) 345fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * --------------- 346fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - ,,,,,,, - 347fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - | | - 348fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - |<a <a| - 349fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - (| ^ |) - 350fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - | -=- | - 351fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - \_____/ - 352fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * --------------- 353fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * (r, b) 354fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * 355fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * However, Android expects the coords to be in respect with what the 356fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * sensor is viewing, i.e Android expects sensor to see this with (l,t) 357fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * and (r,b) like so: 358fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * (l, t) 359fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * --------------- 360fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - _____ - 361fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - / \ - 362fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - | -=- | - 363fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - (| ^ |) - 364fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - |a> a>| - 365fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - | | - 366fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * - ,,,,,,, - 367fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * --------------- 368fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu / * (r, b) 369fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu */ 370fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu if (mDeviceOrientation == 180) { 371fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu orient_mult = -1; 372fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu trans_left = 2; // right is now left 373fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu trans_top = 3; // bottom is now top 374fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu trans_right = 0; // left is now right 375fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu trans_bot = 1; // top is not bottom 376fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu } else { 377fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu orient_mult = 1; 378fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu trans_left = 0; // left 379fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu trans_top = 1; // top 380fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu trans_right = 2; // right 381fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu trans_bot = 3; // bottom 382fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu 383fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu } 384c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 385967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman int j = 0, i = 0; 386967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman for ( ; j < faceData->ulFaceCount ; j++) 387967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman { 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 396967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman tmp = ( double ) faceData->tFacePosition[j].nLeft / ( double ) previewWidth; 397c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev tmp *= hRange; 398c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev tmp -= hRange/2; 399fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu faces[i].rect[trans_left] = tmp; 400c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 401967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman tmp = ( double ) faceData->tFacePosition[j].nTop / ( double )previewHeight; 402c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev tmp *= vRange; 403c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev tmp -= vRange/2; 404fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu faces[i].rect[trans_top] = tmp; 405c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 406967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman tmp = ( double ) faceData->tFacePosition[j].nWidth / ( double ) previewWidth; 407c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev tmp *= hRange; 408fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu tmp *= orient_mult; 409fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu faces[i].rect[trans_right] = faces[i].rect[trans_left] + tmp; 410c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 411967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman tmp = ( double ) faceData->tFacePosition[j].nHeight / ( double ) previewHeight; 412c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev tmp *= vRange; 413fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu tmp *= orient_mult; 414fa28dae0efd774ddd8919e99c0add3e69300ea3aTyler Luu faces[i].rect[trans_bot] = faces[i].rect[trans_top] + tmp; 415c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 416967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman faces[i].score = faceData->tFacePosition[j].nScore; 417c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faces[i].id = 0; 418c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faces[i].left_eye[0] = CameraFDResult::INVALID_DATA; 419c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faces[i].left_eye[1] = CameraFDResult::INVALID_DATA; 420c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faces[i].right_eye[0] = CameraFDResult::INVALID_DATA; 421c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faces[i].right_eye[1] = CameraFDResult::INVALID_DATA; 422c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faces[i].mouth[0] = CameraFDResult::INVALID_DATA; 423c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faces[i].mouth[1] = CameraFDResult::INVALID_DATA; 424967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman i++; 425c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 426c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 427967f1197f015b6d2f3b34e60fa787f7066efb824Sundar Raman faceResult->number_of_faces = i; 428c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faceResult->faces = faces; 429c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 430c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } else { 431c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faceResult->number_of_faces = 0; 432c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev faceResult->faces = NULL; 433c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 434c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 435c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev *pFaces = faceResult; 436c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 437c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev LOG_FUNCTION_NAME_EXIT; 438c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 439c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return ret; 440c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 441c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 442c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev}; 443