summaryrefslogtreecommitdiffstats
path: root/services/camera
diff options
context:
space:
mode:
authorIgor Murashkin <iam@google.com>2013-02-21 12:02:29 -0800
committerIgor Murashkin <iam@google.com>2013-02-22 10:50:15 -0800
commita91537e268f2b35f9f0dfdc0c4f84655c93285ae (patch)
tree114691436e16b7c8dfc5929d922712edd2c41aff /services/camera
parenteb72e1796b3af548e87891a6d2b73b0567807f25 (diff)
downloadframeworks_av-a91537e268f2b35f9f0dfdc0c4f84655c93285ae.zip
frameworks_av-a91537e268f2b35f9f0dfdc0c4f84655c93285ae.tar.gz
frameworks_av-a91537e268f2b35f9f0dfdc0c4f84655c93285ae.tar.bz2
Camera: ProCamera - implement onResultReceived callback for metadata callbacks
Change-Id: I46775402b007244bc383d6343a620eebbd492aad
Diffstat (limited to 'services/camera')
-rw-r--r--services/camera/libcameraservice/Android.mk3
-rw-r--r--services/camera/libcameraservice/ProCamera2Client.cpp35
-rw-r--r--services/camera/libcameraservice/ProCamera2Client.h12
-rw-r--r--services/camera/libcameraservice/camera2/ProFrameProcessor.cpp168
-rw-r--r--services/camera/libcameraservice/camera2/ProFrameProcessor.h81
5 files changed, 297 insertions, 2 deletions
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
index c7a8e4a..f76c861 100644
--- a/services/camera/libcameraservice/Android.mk
+++ b/services/camera/libcameraservice/Android.mk
@@ -20,7 +20,8 @@ LOCAL_SRC_FILES:= \
camera2/ZslProcessor.cpp \
camera2/BurstCapture.cpp \
camera2/JpegCompressor.cpp \
- camera2/CaptureSequencer.cpp
+ camera2/CaptureSequencer.cpp \
+ camera2/ProFrameProcessor.cpp \
LOCAL_SHARED_LIBRARIES:= \
libui \
diff --git a/services/camera/libcameraservice/ProCamera2Client.cpp b/services/camera/libcameraservice/ProCamera2Client.cpp
index f850034..7611796 100644
--- a/services/camera/libcameraservice/ProCamera2Client.cpp
+++ b/services/camera/libcameraservice/ProCamera2Client.cpp
@@ -26,6 +26,7 @@
#include <gui/Surface.h>
#include "camera2/Parameters.h"
#include "ProCamera2Client.h"
+#include "camera2/ProFrameProcessor.h"
namespace android {
using namespace camera2;
@@ -82,6 +83,16 @@ status_t ProCamera2Client::initialize(camera_module_t *module)
res = mDevice->setNotifyCallback(this);
+ String8 threadName;
+ mFrameProcessor = new ProFrameProcessor(this);
+ threadName = String8::format("PC2-%d-FrameProc",
+ mCameraId);
+ mFrameProcessor->run(threadName.string());
+
+ mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
+ FRAME_PROCESSOR_LISTENER_MAX_ID,
+ /*listener*/this);
+
return OK;
}
@@ -307,6 +318,7 @@ status_t ProCamera2Client::dump(int fd, const Vector<String16>& args) {
result.append(" State: ");
// TODO: print dynamic/request section from most recent requests
+ mFrameProcessor->dump(fd, args);
#define CASE_APPEND_ENUM(x) case x: result.append(#x "\n"); break;
@@ -338,7 +350,12 @@ void ProCamera2Client::disconnect() {
if (mDevice == 0) return;
ALOGV("Camera %d: Shutting down", mCameraId);
+ mFrameProcessor->removeListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
+ FRAME_PROCESSOR_LISTENER_MAX_ID,
+ /*listener*/this);
+ mFrameProcessor->requestExit();
ALOGV("Camera %d: Waiting for threads", mCameraId);
+ mFrameProcessor->join();
ALOGV("Camera %d: Disconnecting device", mCameraId);
mDevice->disconnect();
@@ -446,4 +463,22 @@ void ProCamera2Client::SharedCameraCallbacks::clear() {
mRemoteCallback.clear();
}
+void ProCamera2Client::onFrameAvailable(int32_t frameId,
+ const CameraMetadata& frame) {
+ ATRACE_CALL();
+ ALOGV("%s", __FUNCTION__);
+
+ Mutex::Autolock icl(mIProCameraUserLock);
+ SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
+
+ if (mRemoteCallback != NULL) {
+ CameraMetadata tmp(frame);
+ camera_metadata_t* meta = tmp.release();
+ ALOGV("%s: meta = %p ", __FUNCTION__, meta);
+ mRemoteCallback->onResultReceived(frameId, meta);
+ tmp.acquire(meta);
+ }
+
+}
+
} // namespace android
diff --git a/services/camera/libcameraservice/ProCamera2Client.h b/services/camera/libcameraservice/ProCamera2Client.h
index b72fd63..dfea1e1 100644
--- a/services/camera/libcameraservice/ProCamera2Client.h
+++ b/services/camera/libcameraservice/ProCamera2Client.h
@@ -19,6 +19,7 @@
#include "Camera2Device.h"
#include "CameraService.h"
+#include "camera2/ProFrameProcessor.h"
namespace android {
@@ -29,7 +30,8 @@ class IMemory;
*/
class ProCamera2Client :
public CameraService::ProClient,
- public Camera2Device::NotificationListener
+ public Camera2Device::NotificationListener,
+ public camera2::ProFrameProcessor::FilteredListener
{
public:
/**
@@ -120,6 +122,10 @@ public:
mutable Mutex mRemoteCallbackLock;
} mSharedCameraCallbacks;
+protected:
+ /** FilteredListener implementation **/
+ virtual void onFrameAvailable(int32_t frameId, const CameraMetadata& frame);
+
private:
/** IProCameraUser interface-related private members */
@@ -137,6 +143,10 @@ private:
sp<IBinder> mPreviewSurface;
/** Preview callback related members */
+ sp<camera2::ProFrameProcessor> mFrameProcessor;
+ static const int32_t FRAME_PROCESSOR_LISTENER_MIN_ID = 0;
+ static const int32_t FRAME_PROCESSOR_LISTENER_MAX_ID = 0x7fffffffL;
+
/** Camera2Device instance wrapping HAL2 entry */
sp<Camera2Device> mDevice;
diff --git a/services/camera/libcameraservice/camera2/ProFrameProcessor.cpp b/services/camera/libcameraservice/camera2/ProFrameProcessor.cpp
new file mode 100644
index 0000000..8d4933c
--- /dev/null
+++ b/services/camera/libcameraservice/camera2/ProFrameProcessor.cpp
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Camera2-ProFrameProcessor"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+#include <utils/Trace.h>
+
+#include "ProFrameProcessor.h"
+#include "../Camera2Device.h"
+#include "../ProCamera2Client.h"
+
+namespace android {
+namespace camera2 {
+
+ProFrameProcessor::ProFrameProcessor(wp<ProCamera2Client> client):
+ Thread(false), mClient(client) {
+}
+
+ProFrameProcessor::~ProFrameProcessor() {
+ ALOGV("%s: Exit", __FUNCTION__);
+}
+
+status_t ProFrameProcessor::registerListener(int32_t minId,
+ int32_t maxId, wp<FilteredListener> listener) {
+ Mutex::Autolock l(mInputMutex);
+ ALOGV("%s: Registering listener for frame id range %d - %d",
+ __FUNCTION__, minId, maxId);
+ RangeListener rListener = { minId, maxId, listener };
+ mRangeListeners.push_back(rListener);
+ return OK;
+}
+
+status_t ProFrameProcessor::removeListener(int32_t minId,
+ int32_t maxId, wp<FilteredListener> listener) {
+ Mutex::Autolock l(mInputMutex);
+ List<RangeListener>::iterator item = mRangeListeners.begin();
+ while (item != mRangeListeners.end()) {
+ if (item->minId == minId &&
+ item->maxId == maxId &&
+ item->listener == listener) {
+ item = mRangeListeners.erase(item);
+ } else {
+ item++;
+ }
+ }
+ return OK;
+}
+
+void ProFrameProcessor::dump(int fd, const Vector<String16>& args) {
+ String8 result(" Latest received frame:\n");
+ write(fd, result.string(), result.size());
+ mLastFrame.dump(fd, 2, 6);
+}
+
+bool ProFrameProcessor::threadLoop() {
+ status_t res;
+
+ sp<Camera2Device> device;
+ {
+ sp<ProCamera2Client> client = mClient.promote();
+ if (client == 0) return false;
+ device = client->getCameraDevice();
+ if (device == 0) return false;
+ }
+
+ res = device->waitForNextFrame(kWaitDuration);
+ if (res == OK) {
+ sp<ProCamera2Client> client = mClient.promote();
+ if (client == 0) return false;
+ processNewFrames(client);
+ } else if (res != TIMED_OUT) {
+ ALOGE("ProCamera2Client::ProFrameProcessor: Error waiting for new "
+ "frames: %s (%d)", strerror(-res), res);
+ }
+
+ return true;
+}
+
+void ProFrameProcessor::processNewFrames(sp<ProCamera2Client> &client) {
+ status_t res;
+ ATRACE_CALL();
+ CameraMetadata frame;
+ while ( (res = client->getCameraDevice()->getNextFrame(&frame)) == OK) {
+ camera_metadata_entry_t entry;
+
+ entry = frame.find(ANDROID_REQUEST_FRAME_COUNT);
+ if (entry.count == 0) {
+ ALOGE("%s: Camera %d: Error reading frame number",
+ __FUNCTION__, client->getCameraId());
+ break;
+ }
+ ATRACE_INT("cam2_frame", entry.data.i32[0]);
+
+ res = processListeners(frame, client);
+ if (res != OK) break;
+
+ if (!frame.isEmpty()) {
+ mLastFrame.acquire(frame);
+ }
+ }
+ if (res != NOT_ENOUGH_DATA) {
+ ALOGE("%s: Camera %d: Error getting next frame: %s (%d)",
+ __FUNCTION__, client->getCameraId(), strerror(-res), res);
+ return;
+ }
+
+ return;
+}
+
+status_t ProFrameProcessor::processListeners(const CameraMetadata &frame,
+ sp<ProCamera2Client> &client) {
+ status_t res;
+ ATRACE_CALL();
+ camera_metadata_ro_entry_t entry;
+
+ entry = frame.find(ANDROID_REQUEST_ID);
+ if (entry.count == 0) {
+ ALOGE("%s: Camera %d: Error reading frame id",
+ __FUNCTION__, client->getCameraId());
+ return BAD_VALUE;
+ }
+ int32_t frameId = entry.data.i32[0];
+
+ List<sp<FilteredListener> > listeners;
+ {
+ Mutex::Autolock l(mInputMutex);
+
+ List<RangeListener>::iterator item = mRangeListeners.begin();
+ while (item != mRangeListeners.end()) {
+ if (frameId >= item->minId &&
+ frameId < item->maxId) {
+ sp<FilteredListener> listener = item->listener.promote();
+ if (listener == 0) {
+ item = mRangeListeners.erase(item);
+ continue;
+ } else {
+ listeners.push_back(listener);
+ }
+ }
+ item++;
+ }
+ }
+ ALOGV("Got %d range listeners out of %d", listeners.size(), mRangeListeners.size());
+ List<sp<FilteredListener> >::iterator item = listeners.begin();
+ for (; item != listeners.end(); item++) {
+ (*item)->onFrameAvailable(frameId, frame);
+ }
+ return OK;
+}
+
+}; // namespace camera2
+}; // namespace android
diff --git a/services/camera/libcameraservice/camera2/ProFrameProcessor.h b/services/camera/libcameraservice/camera2/ProFrameProcessor.h
new file mode 100644
index 0000000..e4094a6
--- /dev/null
+++ b/services/camera/libcameraservice/camera2/ProFrameProcessor.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SERVERS_CAMERA_CAMERA2_PROFRAMEPROCESSOR_H
+#define ANDROID_SERVERS_CAMERA_CAMERA2_PROFRAMEPROCESSOR_H
+
+#include <utils/Thread.h>
+#include <utils/String16.h>
+#include <utils/Vector.h>
+#include <utils/KeyedVector.h>
+#include <utils/List.h>
+#include <camera/CameraMetadata.h>
+
+struct camera_frame_metadata;
+
+namespace android {
+
+class ProCamera2Client;
+
+namespace camera2 {
+
+/* Output frame metadata processing thread. This thread waits for new
+ * frames from the device, and analyzes them as necessary.
+ */
+class ProFrameProcessor: public Thread {
+ public:
+ ProFrameProcessor(wp<ProCamera2Client> client);
+ ~ProFrameProcessor();
+
+ struct FilteredListener: virtual public RefBase {
+ virtual void onFrameAvailable(int32_t frameId,
+ const CameraMetadata &frame) = 0;
+ };
+
+ // Register a listener for a range of IDs [minId, maxId). Multiple listeners
+ // can be listening to the same range
+ status_t registerListener(int32_t minId, int32_t maxId, wp<FilteredListener> listener);
+ status_t removeListener(int32_t minId, int32_t maxId, wp<FilteredListener> listener);
+
+ void dump(int fd, const Vector<String16>& args);
+ private:
+ static const nsecs_t kWaitDuration = 10000000; // 10 ms
+ wp<ProCamera2Client> mClient;
+
+ virtual bool threadLoop();
+
+ Mutex mInputMutex;
+
+ struct RangeListener {
+ int32_t minId;
+ int32_t maxId;
+ wp<FilteredListener> listener;
+ };
+ List<RangeListener> mRangeListeners;
+
+ void processNewFrames(sp<ProCamera2Client> &client);
+
+ status_t processListeners(const CameraMetadata &frame,
+ sp<ProCamera2Client> &client);
+
+ CameraMetadata mLastFrame;
+};
+
+
+}; //namespace camera2
+}; //namespace android
+
+#endif