summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorIgor Murashkin <iam@google.com>2013-05-13 14:53:44 -0700
committerIgor Murashkin <iam@google.com>2013-05-13 18:21:41 -0700
commit5282713a976184e41451315f1286d8075b257d58 (patch)
treed6d3484980644d1d66d00aba3f2113e3c70cddf6 /services
parent8dbaa56a9de51d506977bda112f75b8af50920e9 (diff)
downloadframeworks_av-5282713a976184e41451315f1286d8075b257d58.zip
frameworks_av-5282713a976184e41451315f1286d8075b257d58.tar.gz
frameworks_av-5282713a976184e41451315f1286d8075b257d58.tar.bz2
Camera: Pause preview when needing to delete jpeg/zsl streams
Bug: 8876221 Change-Id: Idf9490a48462fa44d49c4ebe99425c3149ae6378
Diffstat (limited to 'services')
-rw-r--r--services/camera/libcameraservice/Camera2Client.cpp48
-rw-r--r--services/camera/libcameraservice/Camera2Client.h3
-rw-r--r--services/camera/libcameraservice/Camera3Device.cpp4
-rw-r--r--services/camera/libcameraservice/camera2/JpegProcessor.cpp6
-rw-r--r--services/camera/libcameraservice/camera2/StreamingProcessor.cpp64
-rw-r--r--services/camera/libcameraservice/camera2/StreamingProcessor.h4
-rw-r--r--services/camera/libcameraservice/camera2/ZslProcessor3.cpp6
7 files changed, 126 insertions, 9 deletions
diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp
index 48f3606..2e01dae 100644
--- a/services/camera/libcameraservice/Camera2Client.cpp
+++ b/services/camera/libcameraservice/Camera2Client.cpp
@@ -690,7 +690,7 @@ status_t Camera2Client::startPreviewL(Parameters &params, bool restart) {
outputStreams.push(getCallbackStreamId());
}
if (params.zslMode && !params.recordingHint) {
- res = mZslProcessor->updateStream(params);
+ res = updateProcessorStream(mZslProcessor, params);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to update ZSL stream: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
@@ -718,7 +718,7 @@ status_t Camera2Client::startPreviewL(Parameters &params, bool restart) {
// assumption that the user will record video. To optimize recording
// startup time, create the necessary output streams for recording and
// video snapshot now if they don't already exist.
- res = mJpegProcessor->updateStream(params);
+ res = updateProcessorStream(mJpegProcessor, params);
if (res != OK) {
ALOGE("%s: Camera %d: Can't pre-configure still image "
"stream: %s (%d)",
@@ -1125,7 +1125,7 @@ status_t Camera2Client::takePicture(int msgType) {
ALOGV("%s: Camera %d: Starting picture capture", __FUNCTION__, mCameraId);
- res = mJpegProcessor->updateStream(l.mParameters);
+ res = updateProcessorStream(mJpegProcessor, l.mParameters);
if (res != OK) {
ALOGE("%s: Camera %d: Can't set up still image stream: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
@@ -1605,5 +1605,47 @@ status_t Camera2Client::syncWithDevice() {
return res;
}
+template <typename ProcessorT>
+status_t Camera2Client::updateProcessorStream(sp<ProcessorT> processor,
+ camera2::Parameters params) {
+ status_t res;
+
+ res = processor->updateStream(params);
+
+ /**
+ * Can't update the stream if it's busy?
+ *
+ * Then we need to stop the device (by temporarily clearing the request
+ * queue) and then try again. Resume streaming once we're done.
+ */
+ if (res == -EBUSY) {
+ res = mStreamingProcessor->togglePauseStream(/*pause*/true);
+ if (res != OK) {
+ ALOGE("%s: Camera %d: Can't pause streaming: %s (%d)",
+ __FUNCTION__, mCameraId, strerror(-res), res);
+ }
+
+ res = mDevice->waitUntilDrained();
+ if (res != OK) {
+ ALOGE("%s: Camera %d: Waiting to stop streaming failed: %s (%d)",
+ __FUNCTION__, mCameraId, strerror(-res), res);
+ }
+
+ res = processor->updateStream(params);
+ if (res != OK) {
+ ALOGE("%s: Camera %d: Failed to update processing stream "
+ " despite having halted streaming first: %s (%d)",
+ __FUNCTION__, mCameraId, strerror(-res), res);
+ }
+
+ res = mStreamingProcessor->togglePauseStream(/*pause*/false);
+ if (res != OK) {
+ ALOGE("%s: Camera %d: Can't unpause streaming: %s (%d)",
+ __FUNCTION__, mCameraId, strerror(-res), res);
+ }
+ }
+
+ return res;
+}
} // namespace android
diff --git a/services/camera/libcameraservice/Camera2Client.h b/services/camera/libcameraservice/Camera2Client.h
index af72ab2..f42d022 100644
--- a/services/camera/libcameraservice/Camera2Client.h
+++ b/services/camera/libcameraservice/Camera2Client.h
@@ -159,6 +159,9 @@ private:
// Used with stream IDs
static const int NO_STREAM = -1;
+ template <typename ProcessorT>
+ status_t updateProcessorStream(sp<ProcessorT> processor, Parameters params);
+
sp<camera2::FrameProcessor> mFrameProcessor;
/* Preview/Recording related members */
diff --git a/services/camera/libcameraservice/Camera3Device.cpp b/services/camera/libcameraservice/Camera3Device.cpp
index 5e5bfc2..6f4f4c8 100644
--- a/services/camera/libcameraservice/Camera3Device.cpp
+++ b/services/camera/libcameraservice/Camera3Device.cpp
@@ -680,8 +680,8 @@ status_t Camera3Device::deleteStream(int id) {
// CameraDevice semantics require device to already be idle before
// deleteStream is called, unlike for createStream.
if (mStatus != STATUS_IDLE) {
- CLOGE("Device not idle");
- return INVALID_OPERATION;
+ ALOGV("%s: Camera %d: Device not idle", __FUNCTION__, mId);
+ return -EBUSY;
}
sp<Camera3StreamInterface> deletedStream;
diff --git a/services/camera/libcameraservice/camera2/JpegProcessor.cpp b/services/camera/libcameraservice/camera2/JpegProcessor.cpp
index 01d7f9c..f0a13ca 100644
--- a/services/camera/libcameraservice/camera2/JpegProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/JpegProcessor.cpp
@@ -113,7 +113,11 @@ status_t JpegProcessor::updateStream(const Parameters &params) {
ALOGV("%s: Camera %d: Deleting stream %d since the buffer dimensions changed",
__FUNCTION__, mId, mCaptureStreamId);
res = device->deleteStream(mCaptureStreamId);
- if (res != OK) {
+ if (res == -EBUSY) {
+ ALOGV("%s: Camera %d: Device is busy, call updateStream again "
+ " after it becomes idle", __FUNCTION__, mId);
+ return res;
+ } else if (res != OK) {
ALOGE("%s: Camera %d: Unable to delete old output stream "
"for capture: %s (%d)", __FUNCTION__,
mId, strerror(-res), res);
diff --git a/services/camera/libcameraservice/camera2/StreamingProcessor.cpp b/services/camera/libcameraservice/camera2/StreamingProcessor.cpp
index c36cf87..ab83714 100644
--- a/services/camera/libcameraservice/camera2/StreamingProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/StreamingProcessor.cpp
@@ -36,6 +36,7 @@ StreamingProcessor::StreamingProcessor(sp<Camera2Client> client):
mDevice(client->getCameraDevice()),
mId(client->getCameraId()),
mActiveRequest(NONE),
+ mPaused(false),
mPreviewRequestId(Camera2Client::kPreviewRequestIdStart),
mPreviewStreamId(NO_STREAM),
mRecordingRequestId(Camera2Client::kRecordingRequestIdStart),
@@ -419,10 +420,59 @@ status_t StreamingProcessor::startStream(StreamType type,
return res;
}
mActiveRequest = type;
+ mPaused = false;
return OK;
}
+status_t StreamingProcessor::togglePauseStream(bool pause) {
+ ATRACE_CALL();
+ status_t res;
+
+ sp<CameraDeviceBase> device = mDevice.promote();
+ if (device == 0) {
+ ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
+ return INVALID_OPERATION;
+ }
+
+ ALOGV("%s: Camera %d: toggling pause to %d", __FUNCTION__, mId, pause);
+
+ Mutex::Autolock m(mMutex);
+
+ if (mActiveRequest == NONE) {
+ ALOGE("%s: Camera %d: Can't toggle pause, streaming was not started",
+ __FUNCTION__, mId);
+ return INVALID_OPERATION;
+ }
+
+ if (mPaused == pause) {
+ return OK;
+ }
+
+ if (pause) {
+ res = device->clearStreamingRequest();
+ if (res != OK) {
+ ALOGE("%s: Camera %d: Can't clear stream request: %s (%d)",
+ __FUNCTION__, mId, strerror(-res), res);
+ return res;
+ }
+ } else {
+ CameraMetadata &request =
+ (mActiveRequest == PREVIEW) ? mPreviewRequest
+ : mRecordingRequest;
+ res = device->setStreamingRequest(request);
+ if (res != OK) {
+ ALOGE("%s: Camera %d: Unable to set preview request to resume: "
+ "%s (%d)",
+ __FUNCTION__, mId, strerror(-res), res);
+ return res;
+ }
+ }
+
+ mPaused = pause;
+ return OK;
+}
+
status_t StreamingProcessor::stopStream() {
ATRACE_CALL();
status_t res;
@@ -443,6 +493,7 @@ status_t StreamingProcessor::stopStream() {
}
mActiveRequest = NONE;
+ mPaused = false;
return OK;
}
@@ -662,20 +713,29 @@ status_t StreamingProcessor::dump(int fd, const Vector<String16>& /*args*/) {
result.append(" Preview request:\n");
write(fd, result.string(), result.size());
mPreviewRequest.dump(fd, 2, 6);
+ result.clear();
} else {
result.append(" Preview request: undefined\n");
- write(fd, result.string(), result.size());
}
if (mRecordingRequest.entryCount() != 0) {
result = " Recording request:\n";
write(fd, result.string(), result.size());
mRecordingRequest.dump(fd, 2, 6);
+ result.clear();
} else {
result = " Recording request: undefined\n";
- write(fd, result.string(), result.size());
}
+ const char* streamTypeString[] = {
+ "none", "preview", "record"
+ };
+ result.append(String8::format(" Active request: %s (paused: %s)\n",
+ streamTypeString[mActiveRequest],
+ mPaused ? "yes" : "no"));
+
+ write(fd, result.string(), result.size());
+
return OK;
}
diff --git a/services/camera/libcameraservice/camera2/StreamingProcessor.h b/services/camera/libcameraservice/camera2/StreamingProcessor.h
index 643114e..281b344 100644
--- a/services/camera/libcameraservice/camera2/StreamingProcessor.h
+++ b/services/camera/libcameraservice/camera2/StreamingProcessor.h
@@ -65,6 +65,9 @@ class StreamingProcessor: public BufferItemConsumer::FrameAvailableListener {
status_t startStream(StreamType type,
const Vector<uint8_t> &outputStreams);
+ // Toggle between paused and unpaused. Stream must be started first.
+ status_t togglePauseStream(bool pause);
+
status_t stopStream();
// Returns the request ID for the currently streaming request
@@ -91,6 +94,7 @@ class StreamingProcessor: public BufferItemConsumer::FrameAvailableListener {
int mId;
StreamType mActiveRequest;
+ bool mPaused;
// Preview-related members
int32_t mPreviewRequestId;
diff --git a/services/camera/libcameraservice/camera2/ZslProcessor3.cpp b/services/camera/libcameraservice/camera2/ZslProcessor3.cpp
index be1ffeb..defcafc 100644
--- a/services/camera/libcameraservice/camera2/ZslProcessor3.cpp
+++ b/services/camera/libcameraservice/camera2/ZslProcessor3.cpp
@@ -112,7 +112,11 @@ status_t ZslProcessor3::updateStream(const Parameters &params) {
"dimensions changed",
__FUNCTION__, client->getCameraId(), mZslStreamId);
res = device->deleteStream(mZslStreamId);
- if (res != OK) {
+ if (res == -EBUSY) {
+ ALOGV("%s: Camera %d: Device is busy, call updateStream again "
+ " after it becomes idle", __FUNCTION__, mId);
+ return res;
+ } else if(res != OK) {
ALOGE("%s: Camera %d: Unable to delete old output stream "
"for ZSL: %s (%d)", __FUNCTION__,
client->getCameraId(), strerror(-res), res);