FrameProcessor.cpp revision 663c2cd909cb9c0699b4d58c1db7c6252afd77ea
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "Camera2Client::FrameProcessor" 18#define ATRACE_TAG ATRACE_TAG_CAMERA 19//#define LOG_NDEBUG 0 20 21#include <utils/Log.h> 22#include <utils/Trace.h> 23 24#include "FrameProcessor.h" 25#include "../Camera2Device.h" 26#include "../Camera2Client.h" 27 28namespace android { 29namespace camera2 { 30 31FrameProcessor::FrameProcessor(wp<Camera2Client> client): 32 Thread(false), mClient(client) { 33} 34 35FrameProcessor::~FrameProcessor() { 36 ALOGV("%s: Exit", __FUNCTION__); 37} 38 39status_t FrameProcessor::registerListener(int32_t id, 40 wp<FilteredListener> listener) { 41 Mutex::Autolock l(mInputMutex); 42 ALOGV("%s: Registering listener for frame id %d", 43 __FUNCTION__, id); 44 return mListeners.replaceValueFor(id, listener); 45} 46 47status_t FrameProcessor::removeListener(int32_t id) { 48 Mutex::Autolock l(mInputMutex); 49 return mListeners.removeItem(id); 50} 51 52void FrameProcessor::dump(int fd, const Vector<String16>& args) { 53 String8 result(" Latest received frame:\n"); 54 write(fd, result.string(), result.size()); 55 mLastFrame.dump(fd, 2, 6); 56} 57 58bool FrameProcessor::threadLoop() { 59 status_t res; 60 61 sp<Camera2Device> device; 62 { 63 sp<Camera2Client> client = mClient.promote(); 64 if (client == 0) return false; 65 device = client->getCameraDevice(); 66 if (device == 0) return false; 67 } 68 69 res = device->waitForNextFrame(kWaitDuration); 70 if (res == OK) { 71 sp<Camera2Client> client = mClient.promote(); 72 if (client == 0) return false; 73 processNewFrames(client); 74 } else if (res != TIMED_OUT) { 75 ALOGE("Camera2Client::FrameProcessor: Error waiting for new " 76 "frames: %s (%d)", strerror(-res), res); 77 } 78 79 return true; 80} 81 82void FrameProcessor::processNewFrames(sp<Camera2Client> &client) { 83 status_t res; 84 ATRACE_CALL(); 85 CameraMetadata frame; 86 while ( (res = client->getCameraDevice()->getNextFrame(&frame)) == OK) { 87 camera_metadata_entry_t entry; 88 89 entry = frame.find(ANDROID_REQUEST_FRAME_COUNT); 90 if (entry.count == 0) { 91 ALOGE("%s: Camera %d: Error reading frame number", 92 __FUNCTION__, client->getCameraId()); 93 break; 94 } 95 96 res = processFaceDetect(frame, client); 97 if (res != OK) break; 98 99 // Must be last - listener can take ownership of frame 100 res = processListener(frame, client); 101 if (res != OK) break; 102 103 if (!frame.isEmpty()) { 104 mLastFrame.acquire(frame); 105 } 106 } 107 if (res != NOT_ENOUGH_DATA) { 108 ALOGE("%s: Camera %d: Error getting next frame: %s (%d)", 109 __FUNCTION__, client->getCameraId(), strerror(-res), res); 110 return; 111 } 112 113 return; 114} 115 116status_t FrameProcessor::processListener(CameraMetadata &frame, 117 sp<Camera2Client> &client) { 118 status_t res; 119 ATRACE_CALL(); 120 camera_metadata_entry_t entry; 121 122 entry = frame.find(ANDROID_REQUEST_ID); 123 if (entry.count == 0) { 124 ALOGE("%s: Camera %d: Error reading frame id", 125 __FUNCTION__, client->getCameraId()); 126 return BAD_VALUE; 127 } 128 int32_t frameId = entry.data.i32[0]; 129 ALOGV("%s: Got frame with ID %d", __FUNCTION__, frameId); 130 131 sp<FilteredListener> listener; 132 { 133 Mutex::Autolock l(mInputMutex); 134 ssize_t listenerIndex = mListeners.indexOfKey(frameId); 135 if (listenerIndex != NAME_NOT_FOUND) { 136 listener = mListeners[listenerIndex].promote(); 137 if (listener == 0) { 138 mListeners.removeItemsAt(listenerIndex, 1); 139 } 140 } 141 } 142 143 if (listener != 0) { 144 listener->onFrameAvailable(frameId, frame); 145 } 146 return OK; 147} 148 149status_t FrameProcessor::processFaceDetect(const CameraMetadata &frame, 150 sp<Camera2Client> &client) { 151 status_t res; 152 ATRACE_CALL(); 153 camera_metadata_ro_entry_t entry; 154 bool enableFaceDetect; 155 int maxFaces; 156 { 157 SharedParameters::Lock l(client->getParameters()); 158 enableFaceDetect = l.mParameters.enableFaceDetect; 159 } 160 entry = frame.find(ANDROID_STATS_FACE_DETECT_MODE); 161 162 // TODO: This should be an error once implementations are compliant 163 if (entry.count == 0) { 164 return OK; 165 } 166 167 uint8_t faceDetectMode = entry.data.u8[0]; 168 169 camera_frame_metadata metadata; 170 Vector<camera_face_t> faces; 171 metadata.number_of_faces = 0; 172 173 if (enableFaceDetect && faceDetectMode != ANDROID_STATS_FACE_DETECTION_OFF) { 174 SharedParameters::Lock l(client->getParameters()); 175 entry = frame.find(ANDROID_STATS_FACE_RECTANGLES); 176 if (entry.count == 0) { 177 // No faces this frame 178 return res; 179 } 180 metadata.number_of_faces = entry.count / 4; 181 if (metadata.number_of_faces > 182 l.mParameters.fastInfo.maxFaces) { 183 ALOGE("%s: Camera %d: More faces than expected! (Got %d, max %d)", 184 __FUNCTION__, client->getCameraId(), 185 metadata.number_of_faces, l.mParameters.fastInfo.maxFaces); 186 return res; 187 } 188 const int32_t *faceRects = entry.data.i32; 189 190 entry = frame.find(ANDROID_STATS_FACE_SCORES); 191 if (entry.count == 0) { 192 ALOGE("%s: Camera %d: Unable to read face scores", 193 __FUNCTION__, client->getCameraId()); 194 return res; 195 } 196 const uint8_t *faceScores = entry.data.u8; 197 198 const int32_t *faceLandmarks = NULL; 199 const int32_t *faceIds = NULL; 200 201 if (faceDetectMode == ANDROID_STATS_FACE_DETECTION_FULL) { 202 entry = frame.find(ANDROID_STATS_FACE_LANDMARKS); 203 if (entry.count == 0) { 204 ALOGE("%s: Camera %d: Unable to read face landmarks", 205 __FUNCTION__, client->getCameraId()); 206 return res; 207 } 208 faceLandmarks = entry.data.i32; 209 210 entry = frame.find(ANDROID_STATS_FACE_IDS); 211 212 if (entry.count == 0) { 213 ALOGE("%s: Camera %d: Unable to read face IDs", 214 __FUNCTION__, client->getCameraId()); 215 return res; 216 } 217 faceIds = entry.data.i32; 218 } 219 220 faces.setCapacity(metadata.number_of_faces); 221 222 size_t maxFaces = metadata.number_of_faces; 223 for (size_t i = 0; i < maxFaces; i++) { 224 if (faceScores[i] == 0) { 225 metadata.number_of_faces--; 226 continue; 227 } 228 229 camera_face_t face; 230 231 face.rect[0] = l.mParameters.arrayXToNormalized(faceRects[i*4 + 0]); 232 face.rect[1] = l.mParameters.arrayYToNormalized(faceRects[i*4 + 1]); 233 face.rect[2] = l.mParameters.arrayXToNormalized(faceRects[i*4 + 2]); 234 face.rect[3] = l.mParameters.arrayYToNormalized(faceRects[i*4 + 3]); 235 236 face.score = faceScores[i]; 237 if (faceDetectMode == ANDROID_STATS_FACE_DETECTION_FULL) { 238 face.id = faceIds[i]; 239 face.left_eye[0] = 240 l.mParameters.arrayXToNormalized(faceLandmarks[i*6 + 0]); 241 face.left_eye[1] = 242 l.mParameters.arrayYToNormalized(faceLandmarks[i*6 + 1]); 243 face.right_eye[0] = 244 l.mParameters.arrayXToNormalized(faceLandmarks[i*6 + 2]); 245 face.right_eye[1] = 246 l.mParameters.arrayYToNormalized(faceLandmarks[i*6 + 3]); 247 face.mouth[0] = 248 l.mParameters.arrayXToNormalized(faceLandmarks[i*6 + 4]); 249 face.mouth[1] = 250 l.mParameters.arrayYToNormalized(faceLandmarks[i*6 + 5]); 251 } else { 252 face.id = 0; 253 face.left_eye[0] = face.left_eye[1] = -2000; 254 face.right_eye[0] = face.right_eye[1] = -2000; 255 face.mouth[0] = face.mouth[1] = -2000; 256 } 257 faces.push_back(face); 258 } 259 260 metadata.faces = faces.editArray(); 261 } 262 263 if (metadata.number_of_faces != 0) { 264 Camera2Client::SharedCameraClient::Lock l(client->mSharedCameraClient); 265 if (l.mCameraClient != NULL) { 266 l.mCameraClient->dataCallback(CAMERA_MSG_PREVIEW_METADATA, 267 NULL, &metadata); 268 } 269 } 270 return OK; 271} 272 273}; // namespace camera2 274}; // namespace android 275