diff options
author | Eino-Ville Talvala <etalvala@google.com> | 2012-08-03 13:53:39 -0700 |
---|---|---|
committer | Eino-Ville Talvala <etalvala@google.com> | 2012-08-10 09:19:18 -0700 |
commit | 174181eec57c963a2a17bd156d81c3f18b3ba75c (patch) | |
tree | 9eea6b8bf3577f1f24d80b5d37d714fe6374a734 | |
parent | a59bf2c58311dfc28f46220383d66869e8f3f57f (diff) | |
download | frameworks_av-174181eec57c963a2a17bd156d81c3f18b3ba75c.zip frameworks_av-174181eec57c963a2a17bd156d81c3f18b3ba75c.tar.gz frameworks_av-174181eec57c963a2a17bd156d81c3f18b3ba75c.tar.bz2 |
Camera2: Add trigger support, and implement autofocus
- Add skeletons for all triggering actions into Camera2Device
- Add support for AF triggers to HAL
- Add support for AF notifications from HAL
Bug: 6243944
Change-Id: I21025440849ae41f7083e1dcb72c99f8e5b2d5f7
-rw-r--r-- | services/camera/libcameraservice/Camera2Client.cpp | 128 | ||||
-rw-r--r-- | services/camera/libcameraservice/Camera2Client.h | 12 | ||||
-rw-r--r-- | services/camera/libcameraservice/Camera2Device.cpp | 36 | ||||
-rw-r--r-- | services/camera/libcameraservice/Camera2Device.h | 21 |
4 files changed, 190 insertions, 7 deletions
diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp index cd74e6d..4566c75 100644 --- a/services/camera/libcameraservice/Camera2Client.cpp +++ b/services/camera/libcameraservice/Camera2Client.cpp @@ -88,6 +88,8 @@ status_t Camera2Client::initialize(camera_module_t *module) return NO_INIT; } + res = mDevice->setNotifyCallback(this); + res = buildDefaultParameters(); if (res != OK) { ALOGE("%s: Camera %d: unable to build defaults: %s (%d)", @@ -846,6 +848,15 @@ status_t Camera2Client::autoFocus() { status_t res; if ( (res = checkPid(__FUNCTION__) ) != OK) return res; + int triggerId; + { + LockedParameters::Key k(mParameters); + k.mParameters.currentAfTriggerId = ++k.mParameters.afTriggerCounter; + triggerId = k.mParameters.currentAfTriggerId; + } + + mDevice->triggerAutofocus(triggerId); + return OK; } @@ -855,6 +866,14 @@ status_t Camera2Client::cancelAutoFocus() { status_t res; if ( (res = checkPid(__FUNCTION__) ) != OK) return res; + int triggerId; + { + LockedParameters::Key k(mParameters); + triggerId = ++k.mParameters.afTriggerCounter; + } + + mDevice->triggerCancelAutofocus(triggerId); + return OK; } @@ -1453,6 +1472,9 @@ status_t Camera2Client::setParameters(const String8& params) { k.mParameters.sceneMode = sceneMode; k.mParameters.flashMode = flashMode; + if (focusMode != k.mParameters.focusMode) { + k.mParameters.currentAfTriggerId = -1; + } k.mParameters.focusMode = focusMode; k.mParameters.focusingAreas = focusingAreas; @@ -1625,7 +1647,9 @@ status_t Camera2Client::commandStopFaceDetectionL() { } status_t Camera2Client::commandEnableFocusMoveMsgL(bool enable) { - ALOGE("%s: Unimplemented!", __FUNCTION__); + LockedParameters::Key k(mParameters); + k.mParameters.enableFocusMoveMessages = enable; + return OK; } @@ -1678,6 +1702,102 @@ void Camera2Client::notifyShutter(int frameNumber, nsecs_t timestamp) { void Camera2Client::notifyAutoFocus(uint8_t newState, int triggerId) { ALOGV("%s: Autofocus state now %d, last trigger %d", __FUNCTION__, newState, triggerId); + bool sendCompletedMessage = false; + bool sendMovingMessage = false; + + bool success = false; + bool afInMotion = false; + { + LockedParameters::Key k(mParameters); + switch (k.mParameters.focusMode) { + case Parameters::FOCUS_MODE_AUTO: + case Parameters::FOCUS_MODE_MACRO: + // Don't send notifications upstream if they're not for the current AF + // trigger. For example, if cancel was called in between, or if we + // already sent a notification about this AF call. + if (triggerId != k.mParameters.currentAfTriggerId) break; + switch (newState) { + case ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED: + success = true; + // no break + case ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED: + sendCompletedMessage = true; + k.mParameters.currentAfTriggerId = -1; + break; + case ANDROID_CONTROL_AF_STATE_ACTIVE_SCAN: + // Just starting focusing, ignore + break; + case ANDROID_CONTROL_AF_STATE_INACTIVE: + case ANDROID_CONTROL_AF_STATE_PASSIVE_SCAN: + case ANDROID_CONTROL_AF_STATE_PASSIVE_FOCUSED: + default: + // Unexpected in AUTO/MACRO mode + ALOGE("%s: Unexpected AF state transition in AUTO/MACRO mode: %d", + __FUNCTION__, newState); + break; + } + break; + case Parameters::FOCUS_MODE_CONTINUOUS_VIDEO: + case Parameters::FOCUS_MODE_CONTINUOUS_PICTURE: + switch (newState) { + case ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED: + success = true; + // no break + case ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED: + // Don't send notifications upstream if they're not for + // the current AF trigger. For example, if cancel was + // called in between, or if we already sent a + // notification about this AF call. + // Send both a 'AF done' callback and a 'AF move' callback + if (triggerId != k.mParameters.currentAfTriggerId) break; + sendCompletedMessage = true; + afInMotion = false; + if (k.mParameters.enableFocusMoveMessages && + k.mParameters.afInMotion) { + sendMovingMessage = true; + } + k.mParameters.currentAfTriggerId = -1; + break; + case ANDROID_CONTROL_AF_STATE_INACTIVE: + // Cancel was called, or we switched state; care if + // currently moving + afInMotion = false; + if (k.mParameters.enableFocusMoveMessages && + k.mParameters.afInMotion) { + sendMovingMessage = true; + } + break; + case ANDROID_CONTROL_AF_STATE_PASSIVE_SCAN: + // Start passive scan, inform upstream + afInMotion = true; + // no break + case ANDROID_CONTROL_AF_STATE_PASSIVE_FOCUSED: + // Stop passive scan, inform upstream + if (k.mParameters.enableFocusMoveMessages) { + sendMovingMessage = true; + } + break; + } + k.mParameters.afInMotion = afInMotion; + break; + case Parameters::FOCUS_MODE_EDOF: + case Parameters::FOCUS_MODE_INFINITY: + case Parameters::FOCUS_MODE_FIXED: + default: + if (newState != ANDROID_CONTROL_AF_STATE_INACTIVE) { + ALOGE("%s: Unexpected AF state change %d (ID %d) in focus mode %d", + __FUNCTION__, newState, triggerId, k.mParameters.focusMode); + } + } + } + if (sendCompletedMessage) { + mCameraClient->notifyCallback(CAMERA_MSG_FOCUS, success ? 1 : 0, 0); + } + if (sendMovingMessage) { + mCameraClient->notifyCallback(CAMERA_MSG_FOCUS_MOVE, + afInMotion ? 1 : 0, 0); + } + } void Camera2Client::notifyAutoExposure(uint8_t newState, int triggerId) { @@ -2394,9 +2514,7 @@ status_t Camera2Client::buildDefaultParameters() { k.mParameters.focusMode = Parameters::FOCUS_MODE_AUTO; params.set(CameraParameters::KEY_FOCUS_MODE, CameraParameters::FOCUS_MODE_AUTO); - String8 supportedFocusModes(CameraParameters::FOCUS_MODE_FIXED); - supportedFocusModes = supportedFocusModes + "," + - CameraParameters::FOCUS_MODE_INFINITY; + String8 supportedFocusModes(CameraParameters::FOCUS_MODE_INFINITY); bool addComma = true; for (size_t i=0; i < availableAfModes.count; i++) { @@ -2573,6 +2691,8 @@ status_t Camera2Client::buildDefaultParameters() { k.mParameters.storeMetadataInBuffers = true; k.mParameters.playShutterSound = true; + k.mParameters.afTriggerCounter = 0; + k.mParameters.currentAfTriggerId = -1; k.mParameters.paramsFlattened = params.flatten(); diff --git a/services/camera/libcameraservice/Camera2Client.h b/services/camera/libcameraservice/Camera2Client.h index 8c10d6b..dffd4ab 100644 --- a/services/camera/libcameraservice/Camera2Client.h +++ b/services/camera/libcameraservice/Camera2Client.h @@ -200,6 +200,11 @@ private: // listed in Camera.Parameters bool storeMetadataInBuffers; bool playShutterSound; + bool enableFocusMoveMessages; + + int afTriggerCounter; + int currentAfTriggerId; + bool afInMotion; }; class LockedParameters { @@ -313,9 +318,6 @@ private: camera_metadata_t *mRecordingRequest; sp<Camera2Heap> mRecordingHeap; - // TODO: This needs to be queried from somewhere, or the BufferQueue needs - // to be passed all the way to stagefright. Right now, set to a large number - // to avoid starvation of the video encoders. static const size_t kDefaultRecordingHeapCount = 8; size_t mRecordingHeapCount; size_t mRecordingHeapHead, mRecordingHeapFree; @@ -325,6 +327,10 @@ private: status_t updateRecordingRequest(const Parameters ¶ms); status_t updateRecordingStream(const Parameters ¶ms); + /** Notification-related members */ + + bool mAfInMotion; + /** Camera2Device instance wrapping HAL2 entry */ sp<Camera2Device> mDevice; diff --git a/services/camera/libcameraservice/Camera2Device.cpp b/services/camera/libcameraservice/Camera2Device.cpp index d48c163..a009636 100644 --- a/services/camera/libcameraservice/Camera2Device.cpp +++ b/services/camera/libcameraservice/Camera2Device.cpp @@ -339,6 +339,42 @@ void Camera2Device::notificationCallback(int32_t msg_type, } } +status_t Camera2Device::triggerAutofocus(uint32_t id) { + status_t res; + ALOGV("%s: Triggering autofocus, id %d", __FUNCTION__, id); + res = mDevice->ops->trigger_action(mDevice, + CAMERA2_TRIGGER_AUTOFOCUS, id, 0); + if (res != OK) { + ALOGE("%s: Error triggering autofocus (id %d)", + __FUNCTION__, id); + } + return res; +} + +status_t Camera2Device::triggerCancelAutofocus(uint32_t id) { + status_t res; + ALOGV("%s: Canceling autofocus, id %d", __FUNCTION__, id); + res = mDevice->ops->trigger_action(mDevice, + CAMERA2_TRIGGER_CANCEL_AUTOFOCUS, id, 0); + if (res != OK) { + ALOGE("%s: Error canceling autofocus (id %d)", + __FUNCTION__, id); + } + return res; +} + +status_t Camera2Device::triggerPrecaptureMetering(uint32_t id) { + status_t res; + ALOGV("%s: Triggering precapture metering, id %d", __FUNCTION__, id); + res = mDevice->ops->trigger_action(mDevice, + CAMERA2_TRIGGER_PRECAPTURE_METERING, id, 0); + if (res != OK) { + ALOGE("%s: Error triggering precapture metering (id %d)", + __FUNCTION__, id); + } + return res; +} + /** * Camera2Device::NotificationListener */ diff --git a/services/camera/libcameraservice/Camera2Device.h b/services/camera/libcameraservice/Camera2Device.h index 91a3fbd..9be370f 100644 --- a/services/camera/libcameraservice/Camera2Device.h +++ b/services/camera/libcameraservice/Camera2Device.h @@ -123,6 +123,27 @@ class Camera2Device : public virtual RefBase { */ status_t setNotifyCallback(NotificationListener *listener); + /** + * Trigger auto-focus. The latest ID used in a trigger autofocus or cancel + * autofocus call will be returned by the HAL in all subsequent AF + * notifications. + */ + status_t triggerAutofocus(uint32_t id); + + /** + * Cancel auto-focus. The latest ID used in a trigger autofocus/cancel + * autofocus call will be returned by the HAL in all subsequent AF + * notifications. + */ + status_t triggerCancelAutofocus(uint32_t id); + + /** + * Trigger pre-capture metering. The latest ID used in a trigger pre-capture + * call will be returned by the HAL in all subsequent AE and AWB + * notifications. + */ + status_t triggerPrecaptureMetering(uint32_t id); + private: const int mId; |