diff --git a/tools/emulator/system/camera/EmulatedFakeCamera2.cpp b/tools/emulator/system/camera/EmulatedFakeCamera2.cpp index 70297c6ca..d630db40a 100644 --- a/tools/emulator/system/camera/EmulatedFakeCamera2.cpp +++ b/tools/emulator/system/camera/EmulatedFakeCamera2.cpp @@ -101,6 +101,9 @@ EmulatedFakeCamera2::~EmulatedFakeCamera2() { status_t EmulatedFakeCamera2::Initialize() { status_t res; + set_camera_metadata_vendor_tag_ops( + static_cast(&mVendorTagOps)); + res = constructStaticInfo(&mCameraInfo, true); if (res != OK) { ALOGE("%s: Unable to allocate static info: %s (%d)", @@ -959,8 +962,9 @@ bool EmulatedFakeCamera2::ReadoutThread::threadLoop() { size_t frame_entries = get_camera_metadata_entry_count(mRequest); size_t frame_data = get_camera_metadata_data_count(mRequest); - frame_entries += 2; - frame_data += 8; + // TODO: Dynamically calculate based on enabled statistics, etc + frame_entries += 10; + frame_data += 100; res = mParent->mFrameQueueDst->dequeue_frame(mParent->mFrameQueueDst, frame_entries, frame_data, &frame); @@ -1001,6 +1005,7 @@ bool EmulatedFakeCamera2::ReadoutThread::threadLoop() { ALOGE("Error looking up vendor tag"); } + collectStatisticsMetadata(frame); // TODO: Collect all final values used from sensor in addition to timestamp mParent->mFrameQueueDst->enqueue_frame(mParent->mFrameQueueDst, @@ -1058,6 +1063,115 @@ bool EmulatedFakeCamera2::ReadoutThread::threadLoop() { return true; } +status_t EmulatedFakeCamera2::ReadoutThread::collectStatisticsMetadata( + camera_metadata_t *frame) { + // Completely fake face rectangles, don't correspond to real faces in scene + ALOGV("Collecting statistics metadata"); + + status_t res; + camera_metadata_entry_t entry; + res = find_camera_metadata_entry(frame, + ANDROID_STATS_FACE_DETECT_MODE, + &entry); + if (res != OK) { + ALOGE("%s: Unable to find face detect mode!", __FUNCTION__); + return BAD_VALUE; + } + + if (entry.data.u8[0] == ANDROID_STATS_FACE_DETECTION_OFF) return OK; + + // The coordinate system for the face regions is the raw sensor pixel + // coordinates. Here, we map from the scene coordinates (0-19 in both axis) + // to raw pixels, for the scene defined in fake-pipeline2/Scene.cpp. We + // approximately place two faces on top of the windows of the house. No + // actual faces exist there, but might one day. Note that this doesn't + // account for the offsets used to account for aspect ratio differences, so + // the rectangles don't line up quite right. + const size_t numFaces = 2; + int32_t rects[numFaces * 4] = { + Sensor::kResolution[0] * 10 / 20, + Sensor::kResolution[1] * 15 / 20, + Sensor::kResolution[0] * 12 / 20, + Sensor::kResolution[1] * 17 / 20, + + Sensor::kResolution[0] * 16 / 20, + Sensor::kResolution[1] * 15 / 20, + Sensor::kResolution[0] * 18 / 20, + Sensor::kResolution[1] * 17 / 20 + }; + // To simulate some kind of real detection going on, we jitter the rectangles on + // each frame by a few pixels in each dimension. + for (size_t i = 0; i < numFaces * 4; i++) { + rects[i] += (int32_t)(((float)rand() / RAND_MAX) * 6 - 3); + } + // The confidence scores (0-100) are similarly jittered. + uint8_t scores[numFaces] = { 85, 95 }; + for (size_t i = 0; i < numFaces; i++) { + scores[i] += (int32_t)(((float)rand() / RAND_MAX) * 10 - 5); + } + + res = add_camera_metadata_entry(frame, ANDROID_STATS_FACE_RECTANGLES, + rects, numFaces * 4); + if (res != OK) { + ALOGE("%s: Unable to add face rectangles!", __FUNCTION__); + return BAD_VALUE; + } + + res = add_camera_metadata_entry(frame, ANDROID_STATS_FACE_SCORES, + scores, numFaces); + if (res != OK) { + ALOGE("%s: Unable to add face scores!", __FUNCTION__); + return BAD_VALUE; + } + + if (entry.data.u8[0] == ANDROID_STATS_FACE_DETECTION_SIMPLE) return OK; + + // Advanced face detection options - add eye/mouth coordinates. The + // coordinates in order are (leftEyeX, leftEyeY, rightEyeX, rightEyeY, + // mouthX, mouthY). The mapping is the same as the face rectangles. + int32_t features[numFaces * 6] = { + Sensor::kResolution[0] * 10.5 / 20, + Sensor::kResolution[1] * 16 / 20, + Sensor::kResolution[0] * 11.5 / 20, + Sensor::kResolution[1] * 16 / 20, + Sensor::kResolution[0] * 11 / 20, + Sensor::kResolution[1] * 16.5 / 20, + + Sensor::kResolution[0] * 16.5 / 20, + Sensor::kResolution[1] * 16 / 20, + Sensor::kResolution[0] * 17.5 / 20, + Sensor::kResolution[1] * 16 / 20, + Sensor::kResolution[0] * 17 / 20, + Sensor::kResolution[1] * 16.5 / 20, + }; + // Jitter these a bit less than the rects + for (size_t i = 0; i < numFaces * 6; i++) { + features[i] += (int32_t)(((float)rand() / RAND_MAX) * 4 - 2); + } + // These are unique IDs that are used to identify each face while it's + // visible to the detector (if a face went away and came back, it'd get a + // new ID). + int32_t ids[numFaces] = { + 100, 200 + }; + + res = add_camera_metadata_entry(frame, ANDROID_STATS_FACE_LANDMARKS, + features, numFaces * 6); + if (res != OK) { + ALOGE("%s: Unable to add face landmarks!", __FUNCTION__); + return BAD_VALUE; + } + + res = add_camera_metadata_entry(frame, ANDROID_STATS_FACE_IDS, + ids, numFaces); + if (res != OK) { + ALOGE("%s: Unable to add face scores!", __FUNCTION__); + return BAD_VALUE; + } + + return OK; +} + EmulatedFakeCamera2::ControlThread::ControlThread(EmulatedFakeCamera2 *parent): Thread(false), mParent(parent) { @@ -1588,13 +1702,16 @@ status_t EmulatedFakeCamera2::constructStaticInfo( // android.stats static const uint8_t availableFaceDetectModes[] = { - ANDROID_STATS_FACE_DETECTION_OFF + ANDROID_STATS_FACE_DETECTION_OFF, + ANDROID_STATS_FACE_DETECTION_SIMPLE, + ANDROID_STATS_FACE_DETECTION_FULL }; + ADD_OR_SIZE(ANDROID_STATS_AVAILABLE_FACE_DETECT_MODES, availableFaceDetectModes, sizeof(availableFaceDetectModes)); - static const int32_t maxFaceCount = 0; + static const int32_t maxFaceCount = 8; ADD_OR_SIZE(ANDROID_STATS_MAX_FACE_COUNT, &maxFaceCount, 1); @@ -1737,7 +1854,7 @@ status_t EmulatedFakeCamera2::constructDefaultRequest( /** android.request */ - static const uint8_t metadataMode = ANDROID_REQUEST_METADATA_NONE; + static const uint8_t metadataMode = ANDROID_REQUEST_METADATA_FULL; ADD_OR_SIZE(ANDROID_REQUEST_METADATA_MODE, &metadataMode, 1); static const int32_t id = 0; diff --git a/tools/emulator/system/camera/EmulatedFakeCamera2.h b/tools/emulator/system/camera/EmulatedFakeCamera2.h index 4621ceccb..e9e0dfcc6 100644 --- a/tools/emulator/system/camera/EmulatedFakeCamera2.h +++ b/tools/emulator/system/camera/EmulatedFakeCamera2.h @@ -221,6 +221,8 @@ private: bool mRunning; bool threadLoop(); + status_t collectStatisticsMetadata(camera_metadata_t *frame); + // Inputs Mutex mInputMutex; // Protects mActive, mInFlightQueue, mRequestCount Condition mInputSignal;