Camera: Combine handling of deferred surface and shared surface
- Refactor the OutputConfiguration to contain isDeferred and isShared
flag, and not contain NULL surface.
- Unify the handling of deferred surface and shared surface.
Test: Camera CTS, and manual testing of GoogleCamera use cases
Bug: 33777818
Change-Id: I5dd3472f0f2133699b0e9fbdd8ba456956222746
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 1675584..977e7a8 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -1292,7 +1292,7 @@
status_t Camera3Device::createStream(sp<Surface> consumer,
uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
- int streamSetId, uint32_t consumerUsage) {
+ int streamSetId, bool isShared, uint32_t consumerUsage) {
ATRACE_CALL();
if (consumer == nullptr) {
@@ -1304,19 +1304,19 @@
consumers.push_back(consumer);
return createStream(consumers, /*hasDeferredConsumer*/ false, width, height,
- format, dataSpace, rotation, id, streamSetId, consumerUsage);
+ format, dataSpace, rotation, id, streamSetId, isShared, consumerUsage);
}
status_t Camera3Device::createStream(const std::vector<sp<Surface>>& consumers,
bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
- int streamSetId, uint32_t consumerUsage) {
+ int streamSetId, bool isShared, uint32_t consumerUsage) {
ATRACE_CALL();
Mutex::Autolock il(mInterfaceLock);
Mutex::Autolock l(mLock);
ALOGV("Camera %s: Creating new stream %d: %d x %d, format %d, dataspace %d rotation %d"
- " consumer usage 0x%x", mId.string(), mNextStreamId, width, height, format, dataSpace, rotation,
- consumerUsage);
+ " consumer usage 0x%x, isShared %d", mId.string(), mNextStreamId, width, height, format,
+ dataSpace, rotation, consumerUsage, isShared);
status_t res;
bool wasActive = false;
@@ -1370,8 +1370,6 @@
return BAD_VALUE;
}
- bool streamSharing = consumers.size() > 1 || (consumers.size() > 0 && hasDeferredConsumer);
-
// Use legacy dataspace values for older HALs
if (mDeviceVersion <= CAMERA_DEVICE_API_VERSION_3_3) {
dataSpace = mapToLegacyDataspace(dataSpace);
@@ -1403,14 +1401,14 @@
newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
width, height, rawOpaqueBufferSize, format, dataSpace, rotation,
mTimestampOffset, streamSetId);
+ } else if (isShared) {
+ newStream = new Camera3SharedOutputStream(mNextStreamId, consumers,
+ width, height, format, consumerUsage, dataSpace, rotation,
+ mTimestampOffset, streamSetId);
} else if (consumers.size() == 0 && hasDeferredConsumer) {
newStream = new Camera3OutputStream(mNextStreamId,
width, height, format, consumerUsage, dataSpace, rotation,
mTimestampOffset, streamSetId);
- } else if (streamSharing) {
- newStream = new Camera3SharedOutputStream(mNextStreamId, consumers,
- hasDeferredConsumer, width, height, format, consumerUsage,
- dataSpace, rotation, mTimestampOffset, streamSetId);
} else {
newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
width, height, format, dataSpace, rotation,
@@ -2067,14 +2065,16 @@
}
}
-status_t Camera3Device::setConsumerSurface(int streamId, sp<Surface> consumer) {
+status_t Camera3Device::setConsumerSurfaces(int streamId,
+ const std::vector<sp<Surface>>& consumers) {
ATRACE_CALL();
- ALOGV("%s: Camera %s: set consumer surface for stream %d", __FUNCTION__, mId.string(), streamId);
+ ALOGV("%s: Camera %s: set consumer surface for stream %d",
+ __FUNCTION__, mId.string(), streamId);
Mutex::Autolock il(mInterfaceLock);
Mutex::Autolock l(mLock);
- if (consumer == nullptr) {
- CLOGE("Null consumer is passed!");
+ if (consumers.size() == 0) {
+ CLOGE("No consumer is passed!");
return BAD_VALUE;
}
@@ -2084,7 +2084,7 @@
return idx;
}
sp<Camera3OutputStreamInterface> stream = mOutputStreams[idx];
- status_t res = stream->setConsumer(consumer);
+ status_t res = stream->setConsumers(consumers);
if (res != OK) {
CLOGE("Stream %d set consumer failed (error %d %s) ", streamId, res, strerror(-res));
return res;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 9b869a9..91d682e 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -109,18 +109,18 @@
// Actual stream creation/deletion is delayed until first request is submitted
// If adding streams while actively capturing, will pause device before adding
// stream, reconfiguring device, and unpausing. If the client create a stream
- // with nullptr consumer surface, the client must then call setConsumer()
+ // with nullptr consumer surface, the client must then call setConsumers()
// and finish the stream configuration before starting output streaming.
status_t createStream(sp<Surface> consumer,
uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
- uint32_t consumerUsage = 0) override;
+ bool isShared = false, uint32_t consumerUsage = 0) override;
status_t createStream(const std::vector<sp<Surface>>& consumers,
bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
- uint32_t consumerUsage = 0) override;
+ bool isShared = false, uint32_t consumerUsage = 0) override;
status_t createInputStream(
uint32_t width, uint32_t height, int format,
@@ -183,10 +183,10 @@
void notifyStatus(bool idle); // updates from StatusTracker
/**
- * Set the deferred consumer surface to the output stream and finish the deferred
+ * Set the deferred consumer surfaces to the output stream and finish the deferred
* consumer configuration.
*/
- status_t setConsumerSurface(int streamId, sp<Surface> consumer) override;
+ status_t setConsumerSurfaces(int streamId, const std::vector<sp<Surface>>& consumers) override;
private:
static const size_t kDumpLockAttempts = 10;
diff --git a/services/camera/libcameraservice/device3/Camera3DummyStream.cpp b/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
index 7f61c7a..1a730d6 100644
--- a/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
@@ -115,9 +115,9 @@
return false;
}
-status_t Camera3DummyStream::setConsumer(sp<Surface> consumer) {
- ALOGE("%s: Stream %d: Dummy stream doesn't support set consumer surface %p!",
- __FUNCTION__, mId, consumer.get());
+status_t Camera3DummyStream::setConsumers(const std::vector<sp<Surface>>& /*consumers*/) {
+ ALOGE("%s: Stream %d: Dummy stream doesn't support set consumer surface!",
+ __FUNCTION__, mId);
return INVALID_OPERATION;
}
}; // namespace camera3
diff --git a/services/camera/libcameraservice/device3/Camera3DummyStream.h b/services/camera/libcameraservice/device3/Camera3DummyStream.h
index 37efbbb..b6ec99c 100644
--- a/services/camera/libcameraservice/device3/Camera3DummyStream.h
+++ b/services/camera/libcameraservice/device3/Camera3DummyStream.h
@@ -70,9 +70,9 @@
virtual bool isConsumerConfigurationDeferred(size_t surface_id) const;
/**
- * Set the consumer surface to the output stream.
+ * Set the consumer surfaces to the output stream.
*/
- virtual status_t setConsumer(sp<Surface> consumer);
+ virtual status_t setConsumers(const std::vector<sp<Surface>>& consumers);
protected:
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index 1e76a27..b5883e3 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -710,14 +710,19 @@
Mutex::Autolock l(mLock);
if (surface_id != 0) {
- ALOGE("%s: surface_id for Camera3OutputStream should be 0!", __FUNCTION__);
+ ALOGE("%s: surface_id %zu for Camera3OutputStream should be 0!", __FUNCTION__, surface_id);
}
return mConsumer == nullptr;
}
-status_t Camera3OutputStream::setConsumer(sp<Surface> consumer) {
- if (consumer == nullptr) {
- ALOGE("%s: it's illegal to set a null consumer surface!", __FUNCTION__);
+status_t Camera3OutputStream::setConsumers(const std::vector<sp<Surface>>& consumers) {
+ if (consumers.size() != 1) {
+ ALOGE("%s: it's illegal to set %zu consumer surfaces!",
+ __FUNCTION__, consumers.size());
+ return INVALID_OPERATION;
+ }
+ if (consumers[0] == nullptr) {
+ ALOGE("%s: it's illegal to set null consumer surface!", __FUNCTION__);
return INVALID_OPERATION;
}
@@ -726,7 +731,7 @@
return INVALID_OPERATION;
}
- mConsumer = consumer;
+ mConsumer = consumers[0];
return OK;
}
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index 26ea63f..080c721 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -138,9 +138,9 @@
virtual bool isConsumerConfigurationDeferred(size_t surface_id) const;
/**
- * Set the consumer surface to the output stream.
+ * Set the consumer surfaces to the output stream.
*/
- virtual status_t setConsumer(sp<Surface> consumer);
+ virtual status_t setConsumers(const std::vector<sp<Surface>>& consumers);
class BufferReleasedListener : public BnProducerListener {
public:
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h b/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h
index 6a911c6..11868e7 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h
@@ -46,9 +46,9 @@
virtual bool isConsumerConfigurationDeferred(size_t surface_id = 0) const = 0;
/**
- * Set the consumer surface to the output stream.
+ * Set the consumer surfaces to the output stream.
*/
- virtual status_t setConsumer(sp<Surface> consumer) = 0;
+ virtual status_t setConsumers(const std::vector<sp<Surface>>& consumers) = 0;
/**
* Detach an unused buffer from the stream.
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
index b419e06..0d6a96c 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
@@ -22,7 +22,6 @@
Camera3SharedOutputStream::Camera3SharedOutputStream(int id,
const std::vector<sp<Surface>>& surfaces,
- bool hasDeferredSurface,
uint32_t width, uint32_t height, int format,
uint32_t consumerUsage, android_dataspace dataSpace,
camera3_stream_rotation_t rotation,
@@ -30,8 +29,7 @@
Camera3OutputStream(id, CAMERA3_STREAM_OUTPUT, width, height,
format, dataSpace, rotation, consumerUsage,
timestampOffset, setId),
- mSurfaces(surfaces),
- mDeferred(hasDeferredSurface) {
+ mSurfaces(surfaces) {
}
Camera3SharedOutputStream::~Camera3SharedOutputStream() {
@@ -70,23 +68,35 @@
bool Camera3SharedOutputStream::isConsumerConfigurationDeferred(size_t surface_id) const {
Mutex::Autolock l(mLock);
- return (mDeferred && surface_id >= mSurfaces.size());
+ return (surface_id >= mSurfaces.size());
}
-status_t Camera3SharedOutputStream::setConsumer(sp<Surface> surface) {
- if (surface == nullptr) {
- ALOGE("%s: it's illegal to set a null consumer surface!", __FUNCTION__);
+status_t Camera3SharedOutputStream::setConsumers(const std::vector<sp<Surface>>& surfaces) {
+ if (surfaces.size() == 0) {
+ ALOGE("%s: it's illegal to set zero consumer surfaces!", __FUNCTION__);
return INVALID_OPERATION;
}
- if (!mDeferred) {
- ALOGE("%s: Current stream isn't deferred!", __FUNCTION__);
- return INVALID_OPERATION;
+ status_t ret = OK;
+ for (auto& surface : surfaces) {
+ if (surface == nullptr) {
+ ALOGE("%s: it's illegal to set a null consumer surface!", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+
+ mSurfaces.push_back(surface);
+
+ // Only call addOutput if the splitter has been connected.
+ if (mStreamSplitter != nullptr) {
+ ret = mStreamSplitter->addOutput(surface, camera3_stream::max_buffers);
+ if (ret != OK) {
+ ALOGE("%s: addOutput failed with error code %d", __FUNCTION__, ret);
+ return ret;
+
+ }
+ }
}
-
- mSurfaces.push_back(surface);
-
- return mStreamSplitter->addOutput(surface, camera3_stream::max_buffers);
+ return ret;
}
status_t Camera3SharedOutputStream::configureQueueLocked() {
@@ -124,7 +134,7 @@
status_t Camera3SharedOutputStream::getEndpointUsage(uint32_t *usage) const {
- status_t res;
+ status_t res = OK;
uint32_t u = 0;
if (mConsumer == nullptr) {
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
index 1b37d7c..cc96076 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
@@ -33,7 +33,7 @@
* sharing between multiple streams.
*/
Camera3SharedOutputStream(int id, const std::vector<sp<Surface>>& surfaces,
- bool hasDeferredSurface, uint32_t width, uint32_t height, int format,
+ uint32_t width, uint32_t height, int format,
uint32_t consumerUsage, android_dataspace dataSpace,
camera3_stream_rotation_t rotation, nsecs_t timestampOffset,
int setId = CAMERA3_STREAM_SET_ID_INVALID);
@@ -45,7 +45,7 @@
virtual bool isConsumerConfigurationDeferred(size_t surface_id) const;
- virtual status_t setConsumer(sp<Surface> consumer);
+ virtual status_t setConsumers(const std::vector<sp<Surface>>& consumers);
private:
// Surfaces passed in constructor from app
@@ -68,8 +68,6 @@
virtual status_t getEndpointUsage(uint32_t *usage) const;
- bool mDeferred;
-
}; // class Camera3SharedOutputStream
} // namespace camera3
diff --git a/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp b/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
index b935141..07f9491 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
+++ b/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
@@ -55,14 +55,15 @@
// Add output surfaces. This has to be before creating internal buffer queue
// in order to get max consumer side buffers.
for (size_t i = 0; i < surfaces.size(); i++) {
- if (surfaces[i] != nullptr) {
- res = addOutputLocked(surfaces[i], hal_max_buffers,
- OutputType::NonDeferred);
- if (res != OK) {
- ALOGE("%s: Failed to add output surface: %s(%d)",
- __FUNCTION__, strerror(-res), res);
- return res;
- }
+ if (surfaces[i] == nullptr) {
+ ALOGE("%s: Fatal: surface is NULL", __FUNCTION__);
+ return BAD_VALUE;
+ }
+ res = addOutputLocked(surfaces[i], hal_max_buffers, OutputType::NonDeferred);
+ if (res != OK) {
+ ALOGE("%s: Failed to add output surface: %s(%d)",
+ __FUNCTION__, strerror(-res), res);
+ return res;
}
}
@@ -110,7 +111,7 @@
}
status_t Camera3StreamSplitter::addOutput(
- sp<Surface>& outputQueue, size_t hal_max_buffers) {
+ const sp<Surface>& outputQueue, size_t hal_max_buffers) {
Mutex::Autolock lock(mMutex);
return addOutputLocked(outputQueue, hal_max_buffers, OutputType::Deferred);
}
diff --git a/services/camera/libcameraservice/device3/Camera3StreamSplitter.h b/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
index 5a25712..32ae073 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
@@ -61,7 +61,7 @@
// outputQueue has not been added to the splitter. BAD_VALUE is returned if
// outputQueue is NULL. See IGraphicBufferProducer::connect for explanations
// of other error codes.
- status_t addOutput(sp<Surface>& outputQueue, size_t hal_max_buffers);
+ status_t addOutput(const sp<Surface>& outputQueue, size_t hal_max_buffers);
// Request surfaces for a particular frame number. The requested surfaces
// are stored in a FIFO queue. And when the buffer becomes available from the