summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorEino-Ville Talvala <etalvala@google.com>2012-10-02 13:30:28 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2012-10-04 16:31:05 -0700
commit4865c526e681366481b0ab242ffa1ead57bb02cc (patch)
tree1a9d2465bbd037a7d7bbc657cc44295363632fed /services
parent9942f62d6a5ee0a65da751b681217d3c4243cd89 (diff)
downloadframeworks_av-4865c526e681366481b0ab242ffa1ead57bb02cc.zip
frameworks_av-4865c526e681366481b0ab242ffa1ead57bb02cc.tar.gz
frameworks_av-4865c526e681366481b0ab242ffa1ead57bb02cc.tar.bz2
Camera2: Synchronize mode changes and triggers
Make sure that changes to various parameters have reached the HAL before triggering asynchronous events like autofocus or precapture metering. Bug: 7107220 Change-Id: I3c50038de1671968eb32004ce538435121934e7e
Diffstat (limited to 'services')
-rw-r--r--services/camera/libcameraservice/Camera2Client.cpp65
-rw-r--r--services/camera/libcameraservice/Camera2Client.h21
-rw-r--r--services/camera/libcameraservice/Camera2Device.cpp33
-rw-r--r--services/camera/libcameraservice/Camera2Device.h12
-rw-r--r--services/camera/libcameraservice/camera2/CaptureSequencer.cpp18
-rw-r--r--services/camera/libcameraservice/camera2/CaptureSequencer.h2
-rw-r--r--services/camera/libcameraservice/camera2/FrameProcessor.cpp62
-rw-r--r--services/camera/libcameraservice/camera2/FrameProcessor.h24
-rw-r--r--services/camera/libcameraservice/camera2/StreamingProcessor.cpp64
-rw-r--r--services/camera/libcameraservice/camera2/StreamingProcessor.h10
-rw-r--r--services/camera/libcameraservice/camera2/ZslProcessor.cpp12
-rw-r--r--services/camera/libcameraservice/camera2/ZslProcessor.h2
12 files changed, 259 insertions, 66 deletions
diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp
index 948b59f..9bcaef1 100644
--- a/services/camera/libcameraservice/Camera2Client.cpp
+++ b/services/camera/libcameraservice/Camera2Client.cpp
@@ -536,7 +536,7 @@ status_t Camera2Client::setPreviewWindowL(const sp<IBinder>& binder,
// Already running preview - need to stop and create a new stream
// TODO: Optimize this so that we don't wait for old stream to drain
// before spinning up new stream
- mDevice->clearStreamingRequest();
+ mStreamingProcessor->stopStream();
l.mParameters.state = Parameters::WAITING_FOR_PREVIEW_WINDOW;
break;
}
@@ -719,6 +719,7 @@ void Camera2Client::stopPreview() {
void Camera2Client::stopPreviewL() {
ATRACE_CALL();
+ status_t res;
Parameters::State state;
{
SharedParameters::Lock l(mParameters);
@@ -740,6 +741,11 @@ void Camera2Client::stopPreviewL() {
// no break - identical to preview
case Parameters::PREVIEW:
mStreamingProcessor->stopStream();
+ res = mDevice->waitUntilDrained();
+ if (res != OK) {
+ ALOGE("%s: Camera %d: Waiting to stop streaming failed: %s (%d)",
+ __FUNCTION__, mCameraId, strerror(-res), res);
+ }
// no break
case Parameters::WAITING_FOR_PREVIEW_WINDOW: {
SharedParameters::Lock l(mParameters);
@@ -946,9 +952,14 @@ status_t Camera2Client::autoFocus() {
int triggerId;
{
SharedParameters::Lock l(mParameters);
+ if (l.mParameters.state < Parameters::PREVIEW) {
+ return INVALID_OPERATION;
+ }
+
l.mParameters.currentAfTriggerId = ++l.mParameters.afTriggerCounter;
triggerId = l.mParameters.currentAfTriggerId;
}
+ syncWithDevice();
mDevice->triggerAutofocus(triggerId);
@@ -967,6 +978,7 @@ status_t Camera2Client::cancelAutoFocus() {
SharedParameters::Lock l(mParameters);
triggerId = ++l.mParameters.afTriggerCounter;
}
+ syncWithDevice();
mDevice->triggerCancelAutofocus(triggerId);
@@ -1017,6 +1029,9 @@ status_t Camera2Client::takePicture(int msgType) {
return res;
}
+ // Need HAL to have correct settings before (possibly) triggering precapture
+ syncWithDevice();
+
res = mCaptureSequencer->startCapture();
if (res != OK) {
ALOGE("%s: Camera %d: Unable to start capture: %s (%d)",
@@ -1397,13 +1412,18 @@ int Camera2Client::getZslStreamId() const {
return mZslProcessor->getStreamId();
}
-status_t Camera2Client::registerFrameListener(int32_t id,
+status_t Camera2Client::registerFrameListener(int32_t minId, int32_t maxId,
+ wp<camera2::FrameProcessor::FilteredListener> listener) {
+ return mFrameProcessor->registerListener(minId, maxId, listener);
+}
+
+status_t Camera2Client::removeFrameListener(int32_t minId, int32_t maxId,
wp<camera2::FrameProcessor::FilteredListener> listener) {
- return mFrameProcessor->registerListener(id, listener);
+ return mFrameProcessor->removeListener(minId, maxId, listener);
}
-status_t Camera2Client::removeFrameListener(int32_t id) {
- return mFrameProcessor->removeListener(id);
+status_t Camera2Client::stopStream() {
+ return mStreamingProcessor->stopStream();
}
Camera2Client::SharedCameraClient::Lock::Lock(SharedCameraClient &client):
@@ -1432,9 +1452,12 @@ void Camera2Client::SharedCameraClient::clear() {
mCameraClient.clear();
}
-const int32_t Camera2Client::kPreviewRequestId;
-const int32_t Camera2Client::kRecordRequestId;
-const int32_t Camera2Client::kFirstCaptureRequestId;
+const int32_t Camera2Client::kPreviewRequestIdStart;
+const int32_t Camera2Client::kPreviewRequestIdEnd;
+const int32_t Camera2Client::kRecordingRequestIdStart;
+const int32_t Camera2Client::kRecordingRequestIdEnd;
+const int32_t Camera2Client::kCaptureRequestIdStart;
+const int32_t Camera2Client::kCaptureRequestIdEnd;
/** Utility methods */
@@ -1443,6 +1466,13 @@ status_t Camera2Client::updateRequests(Parameters &params) {
ALOGV("%s: Camera %d: state = %d", __FUNCTION__, getCameraId(), params.state);
+ res = mStreamingProcessor->incrementStreamingIds();
+ if (res != OK) {
+ ALOGE("%s: Camera %d: Unable to increment request IDs: %s (%d)",
+ __FUNCTION__, mCameraId, strerror(-res), res);
+ return res;
+ }
+
res = mStreamingProcessor->updatePreviewRequest(params);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to update preview request: %s (%d)",
@@ -1504,4 +1534,23 @@ size_t Camera2Client::calculateBufferSize(int width, int height,
}
}
+status_t Camera2Client::syncWithDevice() {
+ ATRACE_CALL();
+ const nsecs_t kMaxSyncTimeout = 100000000; // 100 ms
+ status_t res;
+
+ int32_t activeRequestId = mStreamingProcessor->getActiveRequestId();
+ if (activeRequestId == 0) return OK;
+
+ res = mDevice->waitUntilRequestReceived(activeRequestId, kMaxSyncTimeout);
+ if (res == TIMED_OUT) {
+ ALOGE("%s: Camera %d: Timed out waiting sync with HAL",
+ __FUNCTION__, mCameraId);
+ } else if (res != OK) {
+ ALOGE("%s: Camera %d: Error while waiting to sync with HAL",
+ __FUNCTION__, mCameraId);
+ }
+ return res;
+}
+
} // namespace android
diff --git a/services/camera/libcameraservice/Camera2Client.h b/services/camera/libcameraservice/Camera2Client.h
index fb1dcde..55ead02 100644
--- a/services/camera/libcameraservice/Camera2Client.h
+++ b/services/camera/libcameraservice/Camera2Client.h
@@ -107,9 +107,12 @@ public:
int getRecordingStreamId() const;
int getZslStreamId() const;
- status_t registerFrameListener(int32_t id,
+ status_t registerFrameListener(int32_t minId, int32_t maxId,
wp<camera2::FrameProcessor::FilteredListener> listener);
- status_t removeFrameListener(int32_t id);
+ status_t removeFrameListener(int32_t minId, int32_t maxId,
+ wp<camera2::FrameProcessor::FilteredListener> listener);
+
+ status_t stopStream();
// Simple class to ensure that access to ICameraClient is serialized by
// requiring mCameraClientLock to be locked before access to mCameraClient
@@ -135,9 +138,14 @@ public:
static size_t calculateBufferSize(int width, int height,
int format, int stride);
- static const int32_t kPreviewRequestId = 1000;
- static const int32_t kRecordRequestId = 2000;
- static const int32_t kFirstCaptureRequestId = 3000;
+ static const int32_t kPreviewRequestIdStart = 10000000;
+ static const int32_t kPreviewRequestIdEnd = 20000000;
+
+ static const int32_t kRecordingRequestIdStart = 20000000;
+ static const int32_t kRecordingRequestIdEnd = 30000000;
+
+ static const int32_t kCaptureRequestIdStart = 30000000;
+ static const int32_t kCaptureRequestIdEnd = 40000000;
private:
/** ICamera interface-related private members */
@@ -208,6 +216,9 @@ private:
/** Utility members */
+ // Wait until the camera device has received the latest control settings
+ status_t syncWithDevice();
+
// Verify that caller is the owner of the camera
status_t checkPid(const char *checkLocation) const;
};
diff --git a/services/camera/libcameraservice/Camera2Device.cpp b/services/camera/libcameraservice/Camera2Device.cpp
index 25b7a58..d6445c1 100644
--- a/services/camera/libcameraservice/Camera2Device.cpp
+++ b/services/camera/libcameraservice/Camera2Device.cpp
@@ -27,6 +27,7 @@
#include <utils/Log.h>
#include <utils/Trace.h>
+#include <utils/Timers.h>
#include "Camera2Device.h"
namespace android {
@@ -228,6 +229,11 @@ status_t Camera2Device::clearStreamingRequest() {
return mRequestQueue.setStreamSlot(NULL);
}
+status_t Camera2Device::waitUntilRequestReceived(int32_t requestId, nsecs_t timeout) {
+ ATRACE_CALL();
+ return mRequestQueue.waitForDequeue(requestId, timeout);
+}
+
status_t Camera2Device::createStream(sp<ANativeWindow> consumer,
uint32_t width, uint32_t height, int format, size_t size, int *id) {
ATRACE_CALL();
@@ -567,6 +573,7 @@ Camera2Device::NotificationListener::~NotificationListener() {
Camera2Device::MetadataQueue::MetadataQueue():
mDevice(NULL),
mFrameCount(0),
+ mLatestRequestId(0),
mCount(0),
mStreamSlotCount(0),
mSignalConsumer(true)
@@ -678,6 +685,16 @@ status_t Camera2Device::MetadataQueue::dequeue(camera_metadata_t **buf,
mFrameCount++;
}
+ // Check for request ID, and if present, signal waiters.
+ camera_metadata_entry_t requestId;
+ res = find_camera_metadata_entry(b,
+ ANDROID_REQUEST_ID,
+ &requestId);
+ if (res == OK) {
+ mLatestRequestId = requestId.data.i32[0];
+ mNewRequestId.signal();
+ }
+
*buf = b;
mCount--;
@@ -695,6 +712,22 @@ status_t Camera2Device::MetadataQueue::waitForBuffer(nsecs_t timeout)
return OK;
}
+status_t Camera2Device::MetadataQueue::waitForDequeue(int32_t id,
+ nsecs_t timeout) {
+ Mutex::Autolock l(mMutex);
+ status_t res;
+ while (mLatestRequestId != id) {
+ nsecs_t startTime = systemTime();
+
+ res = mNewRequestId.waitRelative(mMutex, timeout);
+ if (res != OK) return res;
+
+ timeout -= (systemTime() - startTime);
+ }
+
+ return OK;
+}
+
status_t Camera2Device::MetadataQueue::setStreamSlot(camera_metadata_t *buf)
{
ATRACE_CALL();
diff --git a/services/camera/libcameraservice/Camera2Device.h b/services/camera/libcameraservice/Camera2Device.h
index 38662e3..29830bd 100644
--- a/services/camera/libcameraservice/Camera2Device.h
+++ b/services/camera/libcameraservice/Camera2Device.h
@@ -67,6 +67,13 @@ class Camera2Device : public virtual RefBase {
status_t clearStreamingRequest();
/**
+ * Wait until a request with the given ID has been dequeued by the
+ * HAL. Returns TIMED_OUT if the timeout duration is reached. Returns
+ * immediately if the latest request received by the HAL has this id.
+ */
+ status_t waitUntilRequestReceived(int32_t requestId, nsecs_t timeout);
+
+ /**
* Create an output stream of the requested size and format.
*
* If format is CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, then the HAL device selects
@@ -226,6 +233,9 @@ class Camera2Device : public virtual RefBase {
status_t dequeue(camera_metadata_t **buf, bool incrementCount = true);
int getBufferCount();
status_t waitForBuffer(nsecs_t timeout);
+ // Wait until a buffer with the given ID is dequeued. Will return
+ // immediately if the latest buffer dequeued has that ID.
+ status_t waitForDequeue(int32_t id, nsecs_t timeout);
// Set repeating buffer(s); if the queue is empty on a dequeue call, the
// queue copies the contents of the stream slot into the queue, and then
@@ -247,6 +257,8 @@ class Camera2Device : public virtual RefBase {
Condition notEmpty;
int mFrameCount;
+ int32_t mLatestRequestId;
+ Condition mNewRequestId;
int mCount;
List<camera_metadata_t*> mEntries;
diff --git a/services/camera/libcameraservice/camera2/CaptureSequencer.cpp b/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
index d56af64..a849246 100644
--- a/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
+++ b/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
@@ -44,7 +44,7 @@ CaptureSequencer::CaptureSequencer(wp<Camera2Client> client):
mCaptureState(IDLE),
mTriggerId(0),
mTimeoutCount(0),
- mCaptureId(Camera2Client::kFirstCaptureRequestId) {
+ mCaptureId(Camera2Client::kCaptureRequestIdStart) {
ALOGV("%s", __FUNCTION__);
}
@@ -84,12 +84,12 @@ void CaptureSequencer::notifyAutoExposure(uint8_t newState, int triggerId) {
}
void CaptureSequencer::onFrameAvailable(int32_t frameId,
- CameraMetadata &frame) {
+ const CameraMetadata &frame) {
ALOGV("%s: Listener found new frame", __FUNCTION__);
ATRACE_CALL();
Mutex::Autolock l(mInputMutex);
mNewFrameId = frameId;
- mNewFrame.acquire(frame);
+ mNewFrame = frame;
if (!mNewFrameReceived) {
mNewFrameReceived = true;
mNewFrameSignal.signal();
@@ -203,7 +203,9 @@ CaptureSequencer::CaptureState CaptureSequencer::manageDone(sp<Camera2Client> &c
status_t res = OK;
ATRACE_CALL();
mCaptureId++;
-
+ if (mCaptureId >= Camera2Client::kCaptureRequestIdEnd) {
+ mCaptureId = Camera2Client::kCaptureRequestIdStart;
+ }
{
Mutex::Autolock l(mInputMutex);
mBusy = false;
@@ -286,7 +288,7 @@ CaptureSequencer::CaptureState CaptureSequencer::manageZslStart(
return DONE;
}
- client->registerFrameListener(mCaptureId,
+ client->registerFrameListener(mCaptureId, mCaptureId + 1,
this);
// TODO: Actually select the right thing here.
@@ -326,7 +328,7 @@ CaptureSequencer::CaptureState CaptureSequencer::manageZslReprocessing(
CaptureSequencer::CaptureState CaptureSequencer::manageStandardStart(
sp<Camera2Client> &client) {
ATRACE_CALL();
- client->registerFrameListener(mCaptureId,
+ client->registerFrameListener(mCaptureId, mCaptureId + 1,
this);
{
SharedParameters::Lock l(client->getParameters());
@@ -421,7 +423,7 @@ CaptureSequencer::CaptureState CaptureSequencer::manageStandardCapture(
}
if (l.mParameters.state == Parameters::STILL_CAPTURE) {
- res = client->getCameraDevice()->clearStreamingRequest();
+ res = client->stopStream();
if (res != OK) {
ALOGE("%s: Camera %d: Unable to stop preview for still capture: "
"%s (%d)",
@@ -482,7 +484,7 @@ CaptureSequencer::CaptureState CaptureSequencer::manageStandardCaptureWait(
ALOGW("Mismatched capture timestamps: Metadata frame %lld,"
" captured buffer %lld", entry.data.i64[0], mCaptureTimestamp);
}
- client->removeFrameListener(mCaptureId);
+ client->removeFrameListener(mCaptureId, mCaptureId + 1, this);
mNewFrameReceived = false;
mNewCaptureReceived = false;
diff --git a/services/camera/libcameraservice/camera2/CaptureSequencer.h b/services/camera/libcameraservice/camera2/CaptureSequencer.h
index 27f3f1c..07e4c01 100644
--- a/services/camera/libcameraservice/camera2/CaptureSequencer.h
+++ b/services/camera/libcameraservice/camera2/CaptureSequencer.h
@@ -57,7 +57,7 @@ class CaptureSequencer:
void notifyAutoExposure(uint8_t newState, int triggerId);
// Notifications from the frame processor
- virtual void onFrameAvailable(int32_t frameId, CameraMetadata &frame);
+ virtual void onFrameAvailable(int32_t frameId, const CameraMetadata &frame);
// Notifications from the JPEG processor
void onCaptureAvailable(nsecs_t timestamp, sp<MemoryBase> captureBuffer);
diff --git a/services/camera/libcameraservice/camera2/FrameProcessor.cpp b/services/camera/libcameraservice/camera2/FrameProcessor.cpp
index 0c8560b..064607c 100644
--- a/services/camera/libcameraservice/camera2/FrameProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/FrameProcessor.cpp
@@ -36,17 +36,30 @@ FrameProcessor::~FrameProcessor() {
ALOGV("%s: Exit", __FUNCTION__);
}
-status_t FrameProcessor::registerListener(int32_t id,
- wp<FilteredListener> listener) {
+status_t FrameProcessor::registerListener(int32_t minId,
+ int32_t maxId, wp<FilteredListener> listener) {
Mutex::Autolock l(mInputMutex);
- ALOGV("%s: Registering listener for frame id %d",
- __FUNCTION__, id);
- return mListeners.replaceValueFor(id, listener);
+ 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 FrameProcessor::removeListener(int32_t id) {
+status_t FrameProcessor::removeListener(int32_t minId,
+ int32_t maxId, wp<FilteredListener> listener) {
Mutex::Autolock l(mInputMutex);
- return mListeners.removeItem(id);
+ 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 FrameProcessor::dump(int fd, const Vector<String16>& args) {
@@ -97,8 +110,7 @@ void FrameProcessor::processNewFrames(sp<Camera2Client> &client) {
res = processFaceDetect(frame, client);
if (res != OK) break;
- // Must be last - listener can take ownership of frame
- res = processListener(frame, client);
+ res = processListeners(frame, client);
if (res != OK) break;
if (!frame.isEmpty()) {
@@ -114,11 +126,11 @@ void FrameProcessor::processNewFrames(sp<Camera2Client> &client) {
return;
}
-status_t FrameProcessor::processListener(CameraMetadata &frame,
+status_t FrameProcessor::processListeners(const CameraMetadata &frame,
sp<Camera2Client> &client) {
status_t res;
ATRACE_CALL();
- camera_metadata_entry_t entry;
+ camera_metadata_ro_entry_t entry;
entry = frame.find(ANDROID_REQUEST_ID);
if (entry.count == 0) {
@@ -127,22 +139,30 @@ status_t FrameProcessor::processListener(CameraMetadata &frame,
return BAD_VALUE;
}
int32_t frameId = entry.data.i32[0];
- ALOGV("%s: Got frame with ID %d", __FUNCTION__, frameId);
- sp<FilteredListener> listener;
+ List<sp<FilteredListener> > listeners;
{
Mutex::Autolock l(mInputMutex);
- ssize_t listenerIndex = mListeners.indexOfKey(frameId);
- if (listenerIndex != NAME_NOT_FOUND) {
- listener = mListeners[listenerIndex].promote();
- if (listener == 0) {
- mListeners.removeItemsAt(listenerIndex, 1);
+
+ 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++;
}
}
-
- if (listener != 0) {
- listener->onFrameAvailable(frameId, frame);
+ 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;
}
diff --git a/services/camera/libcameraservice/camera2/FrameProcessor.h b/services/camera/libcameraservice/camera2/FrameProcessor.h
index cc8c128..3bd4e25 100644
--- a/services/camera/libcameraservice/camera2/FrameProcessor.h
+++ b/services/camera/libcameraservice/camera2/FrameProcessor.h
@@ -21,6 +21,7 @@
#include <utils/String16.h>
#include <utils/Vector.h>
#include <utils/KeyedVector.h>
+#include <utils/List.h>
#include "CameraMetadata.h"
struct camera_frame_metadata;
@@ -40,15 +41,14 @@ class FrameProcessor: public Thread {
~FrameProcessor();
struct FilteredListener: virtual public RefBase {
- // Listener may take ownership of frame
- virtual void onFrameAvailable(int32_t frameId, CameraMetadata &frame) = 0;
+ virtual void onFrameAvailable(int32_t frameId,
+ const CameraMetadata &frame) = 0;
};
- // Register a listener for a specific frame ID (android.request.id).
- // De-registers any existing listeners for that ID
- status_t registerListener(int32_t id, wp<FilteredListener> listener);
-
- status_t removeListener(int32_t id);
+ // 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:
@@ -58,14 +58,20 @@ class FrameProcessor: public Thread {
virtual bool threadLoop();
Mutex mInputMutex;
- KeyedVector<int32_t, wp<FilteredListener> > mListeners;
+
+ struct RangeListener {
+ int32_t minId;
+ int32_t maxId;
+ wp<FilteredListener> listener;
+ };
+ List<RangeListener> mRangeListeners;
void processNewFrames(sp<Camera2Client> &client);
status_t processFaceDetect(const CameraMetadata &frame,
sp<Camera2Client> &client);
- status_t processListener(CameraMetadata &frame,
+ status_t processListeners(const CameraMetadata &frame,
sp<Camera2Client> &client);
CameraMetadata mLastFrame;
diff --git a/services/camera/libcameraservice/camera2/StreamingProcessor.cpp b/services/camera/libcameraservice/camera2/StreamingProcessor.cpp
index 8921172..207f780 100644
--- a/services/camera/libcameraservice/camera2/StreamingProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/StreamingProcessor.cpp
@@ -33,7 +33,10 @@ namespace camera2 {
StreamingProcessor::StreamingProcessor(wp<Camera2Client> client):
mClient(client),
+ mActiveRequest(NONE),
+ mPreviewRequestId(Camera2Client::kPreviewRequestIdStart),
mPreviewStreamId(NO_STREAM),
+ mRecordingRequestId(Camera2Client::kRecordingRequestIdStart),
mRecordingStreamId(NO_STREAM),
mRecordingHeapCount(kDefaultRecordingHeapCount)
{
@@ -90,7 +93,12 @@ status_t StreamingProcessor::updatePreviewRequest(const Parameters &params) {
}
res = mPreviewRequest.update(ANDROID_REQUEST_ID,
- &Camera2Client::kPreviewRequestId, 1);
+ &mPreviewRequestId, 1);
+ if (res != OK) {
+ ALOGE("%s: Camera %d: Unable to update request id for preview: %s (%d)",
+ __FUNCTION__, client->getCameraId(), strerror(-res), res);
+ return res;
+ }
return OK;
}
@@ -190,7 +198,7 @@ status_t StreamingProcessor::deletePreviewStream() {
return OK;
}
-status_t StreamingProcessor::getPreviewStreamId() const {
+int StreamingProcessor::getPreviewStreamId() const {
Mutex::Autolock m(mMutex);
return mPreviewStreamId;
}
@@ -246,6 +254,14 @@ status_t StreamingProcessor::updateRecordingRequest(const Parameters &params) {
return res;
}
+ res = mRecordingRequest.update(ANDROID_REQUEST_ID,
+ &mRecordingRequestId, 1);
+ if (res != OK) {
+ ALOGE("%s: Camera %d: Unable to update request id for request: %s (%d)",
+ __FUNCTION__, client->getCameraId(), strerror(-res), res);
+ return res;
+ }
+
return OK;
}
@@ -342,7 +358,7 @@ status_t StreamingProcessor::deleteRecordingStream() {
return OK;
}
-status_t StreamingProcessor::getRecordingStreamId() const {
+int StreamingProcessor::getRecordingStreamId() const {
return mRecordingStreamId;
}
@@ -351,6 +367,8 @@ status_t StreamingProcessor::startStream(StreamType type,
ATRACE_CALL();
status_t res;
+ if (type == NONE) return INVALID_OPERATION;
+
sp<Camera2Client> client = mClient.promote();
if (client == 0) return INVALID_OPERATION;
@@ -384,6 +402,7 @@ status_t StreamingProcessor::startStream(StreamType type,
__FUNCTION__, client->getCameraId(), strerror(-res), res);
return res;
}
+ mActiveRequest = type;
return OK;
}
@@ -392,6 +411,8 @@ status_t StreamingProcessor::stopStream() {
ATRACE_CALL();
status_t res;
+ Mutex::Autolock m(mMutex);
+
sp<Camera2Client> client = mClient.promote();
if (client == 0) return INVALID_OPERATION;
sp<Camera2Device> device = client->getCameraDevice();
@@ -402,11 +423,38 @@ status_t StreamingProcessor::stopStream() {
__FUNCTION__, client->getCameraId(), strerror(-res), res);
return res;
}
- res = device->waitUntilDrained();
- if (res != OK) {
- ALOGE("%s: Camera %d: Waiting to stop streaming failed: %s (%d)",
- __FUNCTION__, client->getCameraId(), strerror(-res), res);
- return res;
+ mActiveRequest = NONE;
+
+ return OK;
+}
+
+int32_t StreamingProcessor::getActiveRequestId() const {
+ Mutex::Autolock m(mMutex);
+ switch (mActiveRequest) {
+ case NONE:
+ return 0;
+ case PREVIEW:
+ return mPreviewRequestId;
+ case RECORD:
+ return mRecordingRequestId;
+ default:
+ ALOGE("%s: Unexpected mode %d", __FUNCTION__, mActiveRequest);
+ return 0;
+ }
+}
+
+status_t StreamingProcessor::incrementStreamingIds() {
+ ATRACE_CALL();
+ Mutex::Autolock m(mMutex);
+
+ status_t res;
+ mPreviewRequestId++;
+ if (mPreviewRequestId >= Camera2Client::kPreviewRequestIdEnd) {
+ mPreviewRequestId = Camera2Client::kPreviewRequestIdStart;
+ }
+ mRecordingRequestId++;
+ if (mRecordingRequestId >= Camera2Client::kRecordingRequestIdEnd) {
+ mRecordingRequestId = Camera2Client::kRecordingRequestIdStart;
}
return OK;
}
diff --git a/services/camera/libcameraservice/camera2/StreamingProcessor.h b/services/camera/libcameraservice/camera2/StreamingProcessor.h
index ac58614..96b100f 100644
--- a/services/camera/libcameraservice/camera2/StreamingProcessor.h
+++ b/services/camera/libcameraservice/camera2/StreamingProcessor.h
@@ -57,6 +57,7 @@ class StreamingProcessor: public BufferItemConsumer::FrameAvailableListener {
int getRecordingStreamId() const;
enum StreamType {
+ NONE,
PREVIEW,
RECORD
};
@@ -65,6 +66,11 @@ class StreamingProcessor: public BufferItemConsumer::FrameAvailableListener {
status_t stopStream();
+ // Returns the request ID for the currently streaming request
+ // Returns 0 if there is no active request.
+ status_t getActiveRequestId() const;
+ status_t incrementStreamingIds();
+
// Callback for new recording frames from HAL
virtual void onFrameAvailable();
// Callback from stagefright which returns used recording frames
@@ -81,12 +87,16 @@ class StreamingProcessor: public BufferItemConsumer::FrameAvailableListener {
wp<Camera2Client> mClient;
+ StreamType mActiveRequest;
+
// Preview-related members
+ int32_t mPreviewRequestId;
int mPreviewStreamId;
CameraMetadata mPreviewRequest;
sp<ANativeWindow> mPreviewWindow;
// Recording-related members
+ int32_t mRecordingRequestId;
int mRecordingStreamId;
int mRecordingFrameCount;
sp<BufferItemConsumer> mRecordingConsumer;
diff --git a/services/camera/libcameraservice/camera2/ZslProcessor.cpp b/services/camera/libcameraservice/camera2/ZslProcessor.cpp
index 56e9743..5208574 100644
--- a/services/camera/libcameraservice/camera2/ZslProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/ZslProcessor.cpp
@@ -69,16 +69,16 @@ void ZslProcessor::onFrameAvailable() {
}
}
-void ZslProcessor::onFrameAvailable(int32_t frameId, CameraMetadata &frame) {
+void ZslProcessor::onFrameAvailable(int32_t frameId, const CameraMetadata &frame) {
Mutex::Autolock l(mInputMutex);
- camera_metadata_entry_t entry;
+ camera_metadata_ro_entry_t entry;
entry = frame.find(ANDROID_SENSOR_TIMESTAMP);
nsecs_t timestamp = entry.data.i64[0];
ALOGVV("Got preview frame for timestamp %lld", timestamp);
if (mState != RUNNING) return;
- mFrameList.editItemAt(mFrameListHead).acquire(frame);
+ mFrameList.editItemAt(mFrameListHead) = frame;
mFrameListHead = (mFrameListHead + 1) % kFrameListDepth;
findMatchesLocked();
@@ -185,7 +185,9 @@ status_t ZslProcessor::updateStream(const Parameters &params) {
return res;
}
}
- client->registerFrameListener(Camera2Client::kPreviewRequestId, this);
+ client->registerFrameListener(Camera2Client::kPreviewRequestIdStart,
+ Camera2Client::kPreviewRequestIdEnd,
+ this);
return OK;
}
@@ -297,7 +299,7 @@ status_t ZslProcessor::pushToReprocess(int32_t requestId) {
return INVALID_OPERATION;
}
- res = client->getCameraDevice()->clearStreamingRequest();
+ res = client->stopStream();
if (res != OK) {
ALOGE("%s: Camera %d: Unable to stop preview for ZSL capture: "
"%s (%d)",
diff --git a/services/camera/libcameraservice/camera2/ZslProcessor.h b/services/camera/libcameraservice/camera2/ZslProcessor.h
index 1f433ce..c80e7f4 100644
--- a/services/camera/libcameraservice/camera2/ZslProcessor.h
+++ b/services/camera/libcameraservice/camera2/ZslProcessor.h
@@ -52,7 +52,7 @@ class ZslProcessor:
// From mZslConsumer
virtual void onFrameAvailable();
// From FrameProcessor
- virtual void onFrameAvailable(int32_t frameId, CameraMetadata &frame);
+ virtual void onFrameAvailable(int32_t frameId, const CameraMetadata &frame);
virtual void onBufferReleased(buffer_handle_t *handle);