diff options
author | Igor Murashkin <iam@google.com> | 2013-02-21 12:02:29 -0800 |
---|---|---|
committer | Igor Murashkin <iam@google.com> | 2013-02-22 10:50:15 -0800 |
commit | a91537e268f2b35f9f0dfdc0c4f84655c93285ae (patch) | |
tree | 114691436e16b7c8dfc5929d922712edd2c41aff /services | |
parent | eb72e1796b3af548e87891a6d2b73b0567807f25 (diff) | |
download | frameworks_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')
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 |