summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEino-Ville Talvala <etalvala@google.com>2012-08-03 13:53:39 -0700
committerEino-Ville Talvala <etalvala@google.com>2012-08-10 09:19:18 -0700
commit174181eec57c963a2a17bd156d81c3f18b3ba75c (patch)
tree9eea6b8bf3577f1f24d80b5d37d714fe6374a734
parenta59bf2c58311dfc28f46220383d66869e8f3f57f (diff)
downloadframeworks_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.cpp128
-rw-r--r--services/camera/libcameraservice/Camera2Client.h12
-rw-r--r--services/camera/libcameraservice/Camera2Device.cpp36
-rw-r--r--services/camera/libcameraservice/Camera2Device.h21
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 &params);
status_t updateRecordingStream(const Parameters &params);
+ /** 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;