summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIgor Murashkin <iam@google.com>2013-02-28 11:21:00 -0800
committerIgor Murashkin <iam@google.com>2013-02-28 16:25:55 -0800
commitba5ca4ee770fa0fe9e14990fd13b23f1010f5c98 (patch)
tree435f4462759de475b36d98f9f893fbfb8a8b7e41
parentbfc9915f482520eb9676c6d2dbf7f1ac078d937d (diff)
downloadframeworks_av-ba5ca4ee770fa0fe9e14990fd13b23f1010f5c98.zip
frameworks_av-ba5ca4ee770fa0fe9e14990fd13b23f1010f5c98.tar.gz
frameworks_av-ba5ca4ee770fa0fe9e14990fd13b23f1010f5c98.tar.bz2
ProCamera: Add CpuConsumer asynchronous mode support
Bug: 8290146 Bug: 8291751 Change-Id: I25423a2b8a70ac7169911b1c7b482aa17190fe0f
-rw-r--r--camera/ProCamera.cpp21
-rw-r--r--camera/tests/ProCameraTests.cpp56
-rw-r--r--include/camera/ProCamera.h7
3 files changed, 81 insertions, 3 deletions
diff --git a/camera/ProCamera.cpp b/camera/ProCamera.cpp
index 13ba07c..3cfabf6 100644
--- a/camera/ProCamera.cpp
+++ b/camera/ProCamera.cpp
@@ -241,6 +241,17 @@ status_t ProCamera::createStreamCpu(int width, int height, int format,
int heapCount,
/*out*/
sp<CpuConsumer>* cpuConsumer,
+ int* streamId) {
+ return createStreamCpu(width, height, format, heapCount,
+ /*synchronousMode*/true,
+ cpuConsumer, streamId);
+}
+
+status_t ProCamera::createStreamCpu(int width, int height, int format,
+ int heapCount,
+ bool synchronousMode,
+ /*out*/
+ sp<CpuConsumer>* cpuConsumer,
int* streamId)
{
ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
@@ -251,7 +262,7 @@ status_t ProCamera::createStreamCpu(int width, int height, int format,
sp <IProCameraUser> c = mCamera;
if (c == 0) return NO_INIT;
- sp<CpuConsumer> cc = new CpuConsumer(heapCount);
+ sp<CpuConsumer> cc = new CpuConsumer(heapCount, synchronousMode);
cc->setName(String8("ProCamera::mCpuConsumer"));
sp<Surface> stc = new Surface(
@@ -272,6 +283,7 @@ status_t ProCamera::createStreamCpu(int width, int height, int format,
getStreamInfo(*streamId).cpuStream = true;
getStreamInfo(*streamId).cpuConsumer = cc;
+ getStreamInfo(*streamId).synchronousMode = synchronousMode;
getStreamInfo(*streamId).stc = stc;
// for lifetime management
getStreamInfo(*streamId).frameAvailableListener = frameAvailableListener;
@@ -373,6 +385,13 @@ int ProCamera::dropFrameBuffer(int streamId, int count) {
return BAD_VALUE;
}
+ if (!si.synchronousMode) {
+ ALOGW("%s: No need to drop frames on asynchronous streams,"
+ " as asynchronous mode only keeps 1 latest frame around.",
+ __FUNCTION__);
+ return BAD_VALUE;
+ }
+
int numDropped = 0;
for (int i = 0; i < count; ++i) {
CpuConsumer::LockedBuffer buffer;
diff --git a/camera/tests/ProCameraTests.cpp b/camera/tests/ProCameraTests.cpp
index c61e71a..1a8564e 100644
--- a/camera/tests/ProCameraTests.cpp
+++ b/camera/tests/ProCameraTests.cpp
@@ -1061,7 +1061,7 @@ TEST_F(ProCameraTest, WaitForDualStreamBuffer) {
EXPECT_OK(mCamera->exclusiveUnlock());
}
-TEST_F(ProCameraTest, WaitForSingleStreamBufferAndDropFrames) {
+TEST_F(ProCameraTest, WaitForSingleStreamBufferAndDropFramesSync) {
if (HasFatalFailure()) {
return;
}
@@ -1071,7 +1071,8 @@ TEST_F(ProCameraTest, WaitForSingleStreamBufferAndDropFrames) {
int streamId = -1;
sp<CpuConsumer> consumer;
EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
- TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT, &consumer, &streamId));
+ TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT,
+ /*synchronousMode*/true, &consumer, &streamId));
EXPECT_NE(-1, streamId);
EXPECT_OK(mCamera->exclusiveTryLock());
@@ -1114,6 +1115,57 @@ TEST_F(ProCameraTest, WaitForSingleStreamBufferAndDropFrames) {
EXPECT_OK(mCamera->exclusiveUnlock());
}
+TEST_F(ProCameraTest, WaitForSingleStreamBufferAndDropFramesAsync) {
+ if (HasFatalFailure()) {
+ return;
+ }
+
+ const int NUM_REQUESTS = 20 * TEST_CPU_FRAME_COUNT;
+
+ int streamId = -1;
+ sp<CpuConsumer> consumer;
+ EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
+ TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT,
+ /*synchronousMode*/false, &consumer, &streamId));
+ EXPECT_NE(-1, streamId);
+
+ EXPECT_OK(mCamera->exclusiveTryLock());
+
+ uint8_t streams[] = { streamId };
+ ASSERT_NO_FATAL_FAILURE(createSubmitRequestForStreams(streams, /*count*/1,
+ /*requests*/NUM_REQUESTS));
+
+ // Consume a couple of results
+ for (int i = 0; i < NUM_REQUESTS; ++i) {
+ int numFrames;
+ EXPECT_TRUE((numFrames = mCamera->waitForFrameBuffer(streamId)) > 0);
+
+ dout << "Dropped " << (numFrames - 1) << " frames" << std::endl;
+
+ // Skip the counter ahead, don't try to consume these frames again
+ i += numFrames-1;
+
+ // "Consume" the buffer
+ CpuConsumer::LockedBuffer buf;
+ EXPECT_OK(consumer->lockNextBuffer(&buf));
+
+ dout << "Buffer asynchronously received on streamId = " << streamId <<
+ ", dataPtr = " << (void*)buf.data <<
+ ", timestamp = " << buf.timestamp << std::endl;
+
+ // Process at 10fps, stream is at 15fps.
+ // This means we will definitely fill up the buffer queue with
+ // extra buffers and need to drop them.
+ usleep(TEST_FRAME_PROCESSING_DELAY_US);
+
+ EXPECT_OK(consumer->unlockBuffer(buf));
+ }
+
+ // Done: clean up
+ EXPECT_OK(mCamera->deleteStream(streamId));
+ EXPECT_OK(mCamera->exclusiveUnlock());
+}
+
//TODO: refactor into separate file
diff --git a/include/camera/ProCamera.h b/include/camera/ProCamera.h
index e8dcdef..5d6cfaa 100644
--- a/include/camera/ProCamera.h
+++ b/include/camera/ProCamera.h
@@ -201,6 +201,12 @@ public:
/*out*/
sp<CpuConsumer>* cpuConsumer,
int* streamId);
+ status_t createStreamCpu(int width, int height, int format,
+ int heapCount,
+ bool synchronousMode,
+ /*out*/
+ sp<CpuConsumer>* cpuConsumer,
+ int* streamId);
// Create a request object from a template.
status_t createDefaultRequest(int templateId,
@@ -296,6 +302,7 @@ private:
int streamID;
bool cpuStream;
sp<CpuConsumer> cpuConsumer;
+ bool synchronousMode;
sp<ProFrameListener> frameAvailableListener;
sp<Surface> stc;
int frameReady;