summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorEino-Ville Talvala <etalvala@google.com>2013-03-11 14:13:50 -0700
committerEino-Ville Talvala <etalvala@google.com>2013-03-27 16:54:34 -0700
commitd0158c38ad82c1c3033a6dd5806435def3727784 (patch)
tree2cfa23bdec603f7ec796fe111cc3b3c15425be54 /services
parent3b53bc9b41c262d22f094406e3751bc5a41ef2ef (diff)
downloadframeworks_av-d0158c38ad82c1c3033a6dd5806435def3727784.zip
frameworks_av-d0158c38ad82c1c3033a6dd5806435def3727784.tar.gz
frameworks_av-d0158c38ad82c1c3033a6dd5806435def3727784.tar.bz2
Camera: Add output side to camera3 HAL device
- Notifications - Result queue and processing Change-Id: Id6b4746708ce6c6dcc7262666b6ac3130fa3d225
Diffstat (limited to 'services')
-rw-r--r--services/camera/libcameraservice/Camera2Client.cpp3
-rw-r--r--services/camera/libcameraservice/Camera3Device.cpp205
-rw-r--r--services/camera/libcameraservice/Camera3Device.h27
3 files changed, 219 insertions, 16 deletions
diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp
index d3adbdc..9421a77 100644
--- a/services/camera/libcameraservice/Camera2Client.cpp
+++ b/services/camera/libcameraservice/Camera2Client.cpp
@@ -145,9 +145,10 @@ Camera2Client::~Camera2Client() {
status_t Camera2Client::dump(int fd, const Vector<String16>& args) {
String8 result;
- result.appendFormat("Client2[%d] (%p) PID: %d, dump:\n",
+ result.appendFormat("Client2[%d] (%p) Client: %s PID: %d, dump:\n",
mCameraId,
getRemoteCallback()->asBinder().get(),
+ String8(mClientPackageName).string(),
mClientPid);
result.append(" State: ");
#define CASE_APPEND_ENUM(x) case x: result.append(#x "\n"); break;
diff --git a/services/camera/libcameraservice/Camera3Device.cpp b/services/camera/libcameraservice/Camera3Device.cpp
index e6fb33e..6cf652c 100644
--- a/services/camera/libcameraservice/Camera3Device.cpp
+++ b/services/camera/libcameraservice/Camera3Device.cpp
@@ -38,7 +38,8 @@ namespace android {
Camera3Device::Camera3Device(int id):
mId(id),
mHal3Device(NULL),
- mStatus(STATUS_UNINITIALIZED)
+ mStatus(STATUS_UNINITIALIZED),
+ mListener(NULL)
{
ATRACE_CALL();
camera3_callback_ops::notify = &sNotify;
@@ -652,32 +653,53 @@ status_t Camera3Device::waitUntilDrainedLocked() {
status_t Camera3Device::setNotifyCallback(NotificationListener *listener) {
ATRACE_CALL();
- (void)listener;
+ Mutex::Autolock l(mOutputLock);
- ALOGE("%s: Unimplemented", __FUNCTION__);
- return INVALID_OPERATION;
+ if (listener != NULL && mListener != NULL) {
+ ALOGW("%s: Replacing old callback listener", __FUNCTION__);
+ }
+ mListener = listener;
+
+ return OK;
}
status_t Camera3Device::waitForNextFrame(nsecs_t timeout) {
- (void)timeout;
+ ATRACE_CALL();
+ status_t res;
+ Mutex::Autolock l(mOutputLock);
- ALOGE("%s: Unimplemented", __FUNCTION__);
- return INVALID_OPERATION;
+ while (mResultQueue.empty()) {
+ res = mResultSignal.waitRelative(mOutputLock, timeout);
+ if (res == TIMED_OUT) {
+ return res;
+ } else if (res != OK) {
+ ALOGE("%s: Camera %d: Error waiting for frame: %s (%d)",
+ __FUNCTION__, mId, strerror(-res), res);
+ return res;
+ }
+ }
+ return OK;
}
status_t Camera3Device::getNextFrame(CameraMetadata *frame) {
ATRACE_CALL();
- (void)frame;
+ Mutex::Autolock l(mOutputLock);
- ALOGE("%s: Unimplemented", __FUNCTION__);
- return INVALID_OPERATION;
+ if (mResultQueue.empty()) {
+ return NOT_ENOUGH_DATA;
+ }
+
+ CameraMetadata &result = *(mResultQueue.begin());
+ frame->acquire(result);
+ mResultQueue.erase(mResultQueue.begin());
+
+ return OK;
}
status_t Camera3Device::triggerAutofocus(uint32_t id) {
ATRACE_CALL();
(void)id;
-
ALOGE("%s: Unimplemented", __FUNCTION__);
return INVALID_OPERATION;
}
@@ -853,15 +875,168 @@ status_t Camera3Device::configureStreamsLocked() {
*/
void Camera3Device::processCaptureResult(const camera3_capture_result *result) {
- (void)result;
+ ATRACE_CALL();
+
+ status_t res;
+
+ if (result->result == NULL) {
+ // TODO: Report error upstream
+ ALOGW("%s: No metadata for frame %d", __FUNCTION__,
+ result->frame_number);
+ return;
+ }
+
+ nsecs_t timestamp = 0;
+ AlgState cur3aState;
+ AlgState new3aState;
+ int32_t aeTriggerId = 0;
+ int32_t afTriggerId = 0;
+
+ NotificationListener *listener;
+
+ {
+ Mutex::Autolock l(mOutputLock);
+
+ // Push result metadata into queue
+ mResultQueue.push_back(CameraMetadata());
+ CameraMetadata &captureResult = *(mResultQueue.end());
+
+ captureResult = result->result;
+ captureResult.update(ANDROID_REQUEST_FRAME_COUNT,
+ (int32_t*)&result->frame_number, 1);
+
+ // Get timestamp from result metadata
+
+ camera_metadata_entry entry =
+ captureResult.find(ANDROID_SENSOR_TIMESTAMP);
+ if (entry.count == 0) {
+ ALOGE("%s: Camera %d: No timestamp provided by HAL for frame %d!",
+ __FUNCTION__, mId, result->frame_number);
+ // TODO: Report error upstream
+ } else {
+ timestamp = entry.data.i64[0];
+ }
+
+ // Get 3A states from result metadata
+
+ entry = captureResult.find(ANDROID_CONTROL_AE_STATE);
+ if (entry.count == 0) {
+ ALOGE("%s: Camera %d: No AE state provided by HAL for frame %d!",
+ __FUNCTION__, mId, result->frame_number);
+ } else {
+ new3aState.aeState =
+ static_cast<camera_metadata_enum_android_control_ae_state>(
+ entry.data.u8[0]);
+ }
+
+ entry = captureResult.find(ANDROID_CONTROL_AF_STATE);
+ if (entry.count == 0) {
+ ALOGE("%s: Camera %d: No AF state provided by HAL for frame %d!",
+ __FUNCTION__, mId, result->frame_number);
+ } else {
+ new3aState.afState =
+ static_cast<camera_metadata_enum_android_control_af_state>(
+ entry.data.u8[0]);
+ }
+
+ entry = captureResult.find(ANDROID_CONTROL_AWB_STATE);
+ if (entry.count == 0) {
+ ALOGE("%s: Camera %d: No AWB state provided by HAL for frame %d!",
+ __FUNCTION__, mId, result->frame_number);
+ } else {
+ new3aState.awbState =
+ static_cast<camera_metadata_enum_android_control_awb_state>(
+ entry.data.u8[0]);
+ }
+
+ entry = captureResult.find(ANDROID_CONTROL_AF_TRIGGER_ID);
+ if (entry.count == 0) {
+ ALOGE("%s: Camera %d: No AF trigger ID provided by HAL for frame %d!",
+ __FUNCTION__, mId, result->frame_number);
+ } else {
+ afTriggerId = entry.data.i32[0];
+ }
+
+ entry = captureResult.find(ANDROID_CONTROL_AE_PRECAPTURE_ID);
+ if (entry.count == 0) {
+ ALOGE("%s: Camera %d: No AE precapture trigger ID provided by HAL"
+ " for frame %d!", __FUNCTION__, mId, result->frame_number);
+ } else {
+ aeTriggerId = entry.data.i32[0];
+ }
+
+ listener = mListener;
+ cur3aState = m3AState;
+
+ m3AState = new3aState;
+ } // scope for mOutputLock
+
+ // Return completed buffers to their streams
+ for (size_t i = 0; i < result->num_output_buffers; i++) {
+ Camera3Stream *stream =
+ Camera3Stream::cast(result->output_buffers[i].stream);
+ res = stream->returnBuffer(result->output_buffers[i], timestamp);
+ // Note: stream may be deallocated at this point, if this buffer was the
+ // last reference to it.
+ if (res != OK) {
+ ALOGE("%s: Camera %d: Can't return buffer %d for frame %d to its"
+ " stream:%s (%d)", __FUNCTION__, mId, i,
+ result->frame_number, strerror(-res), res);
+ // TODO: Report error upstream
+ }
+ }
+
+ // Dispatch any 3A change events to listeners
+ if (listener != NULL) {
+ if (new3aState.aeState != cur3aState.aeState) {
+ listener->notifyAutoExposure(new3aState.aeState, aeTriggerId);
+ }
+ if (new3aState.afState != cur3aState.afState) {
+ listener->notifyAutoFocus(new3aState.afState, afTriggerId);
+ }
+ if (new3aState.awbState != cur3aState.awbState) {
+ listener->notifyAutoWhitebalance(new3aState.awbState, aeTriggerId);
+ }
+ }
- ALOGE("%s: Unimplemented", __FUNCTION__);
}
void Camera3Device::notify(const camera3_notify_msg *msg) {
- (void)msg;
+ NotificationListener *listener;
+ {
+ Mutex::Autolock l(mOutputLock);
+ if (mListener == NULL) return;
+ listener = mListener;
+ }
- ALOGE("%s: Unimplemented", __FUNCTION__);
+ if (msg == NULL) {
+ ALOGE("%s: Camera %d: HAL sent NULL notify message!",
+ __FUNCTION__, mId);
+ return;
+ }
+
+ switch (msg->type) {
+ case CAMERA3_MSG_ERROR: {
+ int streamId = 0;
+ if (msg->message.error.error_stream != NULL) {
+ Camera3Stream *stream =
+ Camera3Stream::cast(
+ msg->message.error.error_stream);
+ streamId = stream->getId();
+ }
+ listener->notifyError(msg->message.error.error_code,
+ msg->message.error.frame_number, streamId);
+ break;
+ }
+ case CAMERA3_MSG_SHUTTER: {
+ listener->notifyShutter(msg->message.shutter.frame_number,
+ msg->message.shutter.timestamp);
+ break;
+ }
+ default:
+ ALOGE("%s: Camera %d: Unknown notify message from HAL: %d",
+ __FUNCTION__, mId, msg->type);
+ }
}
/**
diff --git a/services/camera/libcameraservice/Camera3Device.h b/services/camera/libcameraservice/Camera3Device.h
index 86f4c6a..8600c6c 100644
--- a/services/camera/libcameraservice/Camera3Device.h
+++ b/services/camera/libcameraservice/Camera3Device.h
@@ -255,6 +255,33 @@ class Camera3Device :
sp<RequestThread> mRequestThread;
/**
+ * Output result queue and current HAL device 3A state
+ */
+
+ // Lock for output side of device
+ Mutex mOutputLock;
+
+ /**** Scope for mOutputLock ****/
+
+ List<CameraMetadata> mResultQueue;
+ Condition mResultSignal;
+ NotificationListener *mListener;
+
+ struct AlgState {
+ camera_metadata_enum_android_control_ae_state aeState;
+ camera_metadata_enum_android_control_af_state afState;
+ camera_metadata_enum_android_control_awb_state awbState;
+
+ AlgState() :
+ aeState(ANDROID_CONTROL_AE_STATE_INACTIVE),
+ afState(ANDROID_CONTROL_AF_STATE_INACTIVE),
+ awbState(ANDROID_CONTROL_AWB_STATE_INACTIVE) {
+ }
+ } m3AState;
+
+ /**** End scope for mOutputLock ****/
+
+ /**
* Callback functions from HAL device
*/
void processCaptureResult(const camera3_capture_result *result);