Camera: Avoid stream re-configuration when format gets overridden
It is allowed and expected some stream formats to get overriden
by the Hal implementation. In such cases the original format should
be stored and made available to device clients.
Bug: 64571102
Test: Camera CTS
Change-Id: Ic1153390e0c4d194475fbda8c8a13323bd7e73c0
diff --git a/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp b/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
index 3f4017f..0d2dba1 100644
--- a/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
@@ -121,18 +121,17 @@
if (mCallbackStreamId != NO_STREAM) {
// Check if stream parameters have to change
- uint32_t currentWidth, currentHeight, currentFormat;
- res = device->getStreamInfo(mCallbackStreamId,
- ¤tWidth, ¤tHeight, ¤tFormat, 0);
+ CameraDeviceBase::StreamInfo streamInfo;
+ res = device->getStreamInfo(mCallbackStreamId, &streamInfo);
if (res != OK) {
ALOGE("%s: Camera %d: Error querying callback output stream info: "
"%s (%d)", __FUNCTION__, mId,
strerror(-res), res);
return res;
}
- if (currentWidth != (uint32_t)params.previewWidth ||
- currentHeight != (uint32_t)params.previewHeight ||
- currentFormat != (uint32_t)callbackFormat) {
+ if (streamInfo.width != (uint32_t)params.previewWidth ||
+ streamInfo.height != (uint32_t)params.previewHeight ||
+ !streamInfo.matchFormat((uint32_t)callbackFormat)) {
// Since size should only change while preview is not running,
// assuming that all existing use of old callback stream is
// completed.
diff --git a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
index d6d8dde..d8b7af2 100644
--- a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
@@ -136,17 +136,16 @@
if (mCaptureStreamId != NO_STREAM) {
// Check if stream parameters have to change
- uint32_t currentWidth, currentHeight;
- res = device->getStreamInfo(mCaptureStreamId,
- ¤tWidth, ¤tHeight, 0, 0);
+ CameraDeviceBase::StreamInfo streamInfo;
+ res = device->getStreamInfo(mCaptureStreamId, &streamInfo);
if (res != OK) {
ALOGE("%s: Camera %d: Error querying capture output stream info: "
"%s (%d)", __FUNCTION__,
mId, strerror(-res), res);
return res;
}
- if (currentWidth != (uint32_t)params.pictureWidth ||
- currentHeight != (uint32_t)params.pictureHeight) {
+ if (streamInfo.width != (uint32_t)params.pictureWidth ||
+ streamInfo.height != (uint32_t)params.pictureHeight) {
ALOGV("%s: Camera %d: Deleting stream %d since the buffer dimensions changed",
__FUNCTION__, mId, mCaptureStreamId);
res = device->deleteStream(mCaptureStreamId);
diff --git a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
index d79e430..b6f443a 100644
--- a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
@@ -161,18 +161,17 @@
if (mPreviewStreamId != NO_STREAM) {
// Check if stream parameters have to change
- uint32_t currentWidth, currentHeight;
- res = device->getStreamInfo(mPreviewStreamId,
- ¤tWidth, ¤tHeight, 0, 0);
+ CameraDeviceBase::StreamInfo streamInfo;
+ res = device->getStreamInfo(mPreviewStreamId, &streamInfo);
if (res != OK) {
ALOGE("%s: Camera %d: Error querying preview stream info: "
"%s (%d)", __FUNCTION__, mId, strerror(-res), res);
return res;
}
- if (currentWidth != (uint32_t)params.previewWidth ||
- currentHeight != (uint32_t)params.previewHeight) {
+ if (streamInfo.width != (uint32_t)params.previewWidth ||
+ streamInfo.height != (uint32_t)params.previewHeight) {
ALOGV("%s: Camera %d: Preview size switch: %d x %d -> %d x %d",
- __FUNCTION__, mId, currentWidth, currentHeight,
+ __FUNCTION__, mId, streamInfo.width, streamInfo.height,
params.previewWidth, params.previewHeight);
res = device->waitUntilDrained();
if (res != OK) {
@@ -312,10 +311,8 @@
return INVALID_OPERATION;
}
- uint32_t currentWidth, currentHeight, currentFormat;
- android_dataspace currentDataSpace;
- res = device->getStreamInfo(mRecordingStreamId,
- ¤tWidth, ¤tHeight, ¤tFormat, ¤tDataSpace);
+ CameraDeviceBase::StreamInfo streamInfo;
+ res = device->getStreamInfo(mRecordingStreamId, &streamInfo);
if (res != OK) {
ALOGE("%s: Camera %d: Error querying recording output stream info: "
"%s (%d)", __FUNCTION__, mId,
@@ -324,10 +321,10 @@
}
if (mRecordingWindow == nullptr ||
- currentWidth != (uint32_t)params.videoWidth ||
- currentHeight != (uint32_t)params.videoHeight ||
- currentFormat != (uint32_t)params.videoFormat ||
- currentDataSpace != params.videoDataSpace) {
+ streamInfo.width != (uint32_t)params.videoWidth ||
+ streamInfo.height != (uint32_t)params.videoHeight ||
+ !streamInfo.matchFormat((uint32_t)params.videoFormat) ||
+ streamInfo.dataSpace != params.videoDataSpace) {
*needsUpdate = true;
return res;
}
@@ -348,22 +345,18 @@
if (mRecordingStreamId != NO_STREAM) {
// Check if stream parameters have to change
- uint32_t currentWidth, currentHeight;
- uint32_t currentFormat;
- android_dataspace currentDataSpace;
- res = device->getStreamInfo(mRecordingStreamId,
- ¤tWidth, ¤tHeight,
- ¤tFormat, ¤tDataSpace);
+ CameraDeviceBase::StreamInfo streamInfo;
+ res = device->getStreamInfo(mRecordingStreamId, &streamInfo);
if (res != OK) {
ALOGE("%s: Camera %d: Error querying recording output stream info: "
"%s (%d)", __FUNCTION__, mId,
strerror(-res), res);
return res;
}
- if (currentWidth != (uint32_t)params.videoWidth ||
- currentHeight != (uint32_t)params.videoHeight ||
- currentFormat != (uint32_t)params.videoFormat ||
- currentDataSpace != params.videoDataSpace) {
+ if (streamInfo.width != (uint32_t)params.videoWidth ||
+ streamInfo.height != (uint32_t)params.videoHeight ||
+ !streamInfo.matchFormat((uint32_t)params.videoFormat) ||
+ streamInfo.dataSpace != params.videoDataSpace) {
// TODO: Should wait to be sure previous recording has finished
res = device->deleteStream(mRecordingStreamId);
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
index 9bc31b9..b0607fb 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
@@ -233,17 +233,16 @@
if ((mZslStreamId != NO_STREAM) || (mInputStreamId != NO_STREAM)) {
// Check if stream parameters have to change
- uint32_t currentWidth, currentHeight;
- res = device->getStreamInfo(mZslStreamId,
- ¤tWidth, ¤tHeight, 0, 0);
+ CameraDeviceBase::StreamInfo streamInfo;
+ res = device->getStreamInfo(mZslStreamId, &streamInfo);
if (res != OK) {
ALOGE("%s: Camera %d: Error querying capture output stream info: "
"%s (%d)", __FUNCTION__,
client->getCameraId(), strerror(-res), res);
return res;
}
- if (currentWidth != (uint32_t)params.fastInfo.arrayWidth ||
- currentHeight != (uint32_t)params.fastInfo.arrayHeight) {
+ if (streamInfo.width != (uint32_t)params.fastInfo.arrayWidth ||
+ streamInfo.height != (uint32_t)params.fastInfo.arrayHeight) {
if (mZslStreamId != NO_STREAM) {
ALOGV("%s: Camera %d: Deleting stream %d since the buffer "
"dimensions changed",
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index 54fcb0a..fe4c8d7 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -142,12 +142,32 @@
virtual status_t createInputStream(uint32_t width, uint32_t height,
int32_t format, /*out*/ int32_t *id) = 0;
+ struct StreamInfo {
+ uint32_t width;
+ uint32_t height;
+ uint32_t format;
+ bool formatOverridden;
+ uint32_t originalFormat;
+ android_dataspace dataSpace;
+ StreamInfo() : width(0), height(0), format(0), formatOverridden(false), originalFormat(0),
+ dataSpace(HAL_DATASPACE_UNKNOWN) {}
+ /**
+ * Check whether the format matches the current or the original one in case
+ * it got overridden.
+ */
+ bool matchFormat(uint32_t clientFormat) {
+ if ((formatOverridden && (originalFormat == clientFormat)) ||
+ (format == clientFormat)) {
+ return true;
+ }
+ return false;
+ }
+ };
+
/**
* Get information about a given stream.
*/
- virtual status_t getStreamInfo(int id,
- uint32_t *width, uint32_t *height,
- uint32_t *format, android_dataspace *dataSpace) = 0;
+ virtual status_t getStreamInfo(int id, StreamInfo *streamInfo) = 0;
/**
* Set stream gralloc buffer transform
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 94e8f3b..669f763 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -1345,10 +1345,11 @@
return OK;
}
-status_t Camera3Device::getStreamInfo(int id,
- uint32_t *width, uint32_t *height,
- uint32_t *format, android_dataspace *dataSpace) {
+status_t Camera3Device::getStreamInfo(int id, StreamInfo *streamInfo) {
ATRACE_CALL();
+ if (nullptr == streamInfo) {
+ return BAD_VALUE;
+ }
Mutex::Autolock il(mInterfaceLock);
Mutex::Autolock l(mLock);
@@ -1375,10 +1376,12 @@
return idx;
}
- if (width) *width = mOutputStreams[idx]->getWidth();
- if (height) *height = mOutputStreams[idx]->getHeight();
- if (format) *format = mOutputStreams[idx]->getFormat();
- if (dataSpace) *dataSpace = mOutputStreams[idx]->getDataSpace();
+ streamInfo->width = mOutputStreams[idx]->getWidth();
+ streamInfo->height = mOutputStreams[idx]->getHeight();
+ streamInfo->format = mOutputStreams[idx]->getFormat();
+ streamInfo->dataSpace = mOutputStreams[idx]->getDataSpace();
+ streamInfo->formatOverridden = mOutputStreams[idx]->isFormatOverridden();
+ streamInfo->originalFormat = mOutputStreams[idx]->getOriginalFormat();
return OK;
}
@@ -3233,6 +3236,8 @@
}
HalStream &src = finalConfiguration.streams[realIdx];
+ Camera3Stream* dstStream = Camera3Stream::cast(dst);
+ dstStream->setFormatOverride(false);
int overrideFormat = mapToFrameworkFormat(src.overrideFormat);
if (dst->format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
if (dst->format != overrideFormat) {
@@ -3240,6 +3245,8 @@
streamId, dst->format);
}
} else {
+ dstStream->setFormatOverride((dst->format != overrideFormat) ? true : false);
+ dstStream->setOriginalFormat(dst->format);
// Override allowed with IMPLEMENTATION_DEFINED
dst->format = overrideFormat;
}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 363bd88..298a3d8 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -128,9 +128,7 @@
uint32_t width, uint32_t height, int format,
int *id) override;
- status_t getStreamInfo(int id,
- uint32_t *width, uint32_t *height,
- uint32_t *format, android_dataspace *dataSpace) override;
+ status_t getStreamInfo(int id, StreamInfo *streamInfo) override;
status_t setStreamTransform(int id, int transform) override;
status_t deleteStream(int id) override;
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index 25e44a5..c186208 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -62,7 +62,9 @@
mPrepared(false),
mPreparedBufferIdx(0),
mLastMaxCount(Camera3StreamInterface::ALLOCATE_PIPELINE_MAX),
- mBufferLimitLatency(kBufferLimitLatencyBinSize) {
+ mBufferLimitLatency(kBufferLimitLatencyBinSize),
+ mFormatOverridden(false),
+ mOriginalFormat(-1) {
camera3_stream::stream_type = type;
camera3_stream::width = width;
@@ -112,6 +114,22 @@
mUsage = usage;
}
+void Camera3Stream::setFormatOverride(bool formatOverridden) {
+ mFormatOverridden = formatOverridden;
+}
+
+bool Camera3Stream::isFormatOverridden() {
+ return mFormatOverridden;
+}
+
+void Camera3Stream::setOriginalFormat(int originalFormat) {
+ mOriginalFormat = originalFormat;
+}
+
+int Camera3Stream::getOriginalFormat() {
+ return mOriginalFormat;
+}
+
camera3_stream* Camera3Stream::startConfiguration() {
ATRACE_CALL();
Mutex::Autolock l(mLock);
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h
index 9090f83..1843ae8 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.h
+++ b/services/camera/libcameraservice/device3/Camera3Stream.h
@@ -146,6 +146,10 @@
android_dataspace getDataSpace() const;
uint64_t getUsage() const;
void setUsage(uint64_t usage);
+ void setFormatOverride(bool formatOverriden);
+ bool isFormatOverridden();
+ void setOriginalFormat(int originalFormat);
+ int getOriginalFormat();
camera3_stream* asHalStream() override {
return this;
@@ -514,6 +518,10 @@
// max_buffers.
static const int32_t kBufferLimitLatencyBinSize = 33; //in ms
CameraLatencyHistogram mBufferLimitLatency;
+
+ //Keep track of original format in case it gets overridden
+ bool mFormatOverridden;
+ int mOriginalFormat;
}; // class Camera3Stream
}; // namespace camera3
diff --git a/services/camera/libcameraservice/device3/Camera3StreamInterface.h b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
index 0544a1b..63456c4 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamInterface.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
@@ -71,6 +71,10 @@
virtual uint32_t getHeight() const = 0;
virtual int getFormat() const = 0;
virtual android_dataspace getDataSpace() const = 0;
+ virtual void setFormatOverride(bool formatOverriden) = 0;
+ virtual bool isFormatOverridden() = 0;
+ virtual void setOriginalFormat(int originalFormat) = 0;
+ virtual int getOriginalFormat() = 0;
/**
* Get a HAL3 handle for the stream, without starting stream configuration.