Camera: Plumb through stream mirroring mode
The stream mirroring mode is used to override the default flip for front
facing camera.
Test: Camera CTS
Bug: 200309079
Change-Id: I161875ccf33267686d54ba3c1c94b597032bd4e8
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index d26b730..16ea67d 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -862,6 +862,7 @@
int dynamicRangeProfile = outputConfiguration.getDynamicRangeProfile();
int streamUseCase = outputConfiguration.getStreamUseCase();
int timestampBase = outputConfiguration.getTimestampBase();
+ int mirrorMode = outputConfiguration.getMirrorMode();
res = SessionConfigurationUtils::checkSurfaceType(numBufferProducers, deferredConsumer,
outputConfiguration.getSurfaceType());
@@ -906,7 +907,7 @@
res = SessionConfigurationUtils::createSurfaceFromGbp(streamInfo,
isStreamInfoValid, surface, bufferProducer, mCameraIdStr,
mDevice->infoPhysical(physicalCameraId), sensorPixelModesUsed, dynamicRangeProfile,
- streamUseCase, timestampBase);
+ streamUseCase, timestampBase, mirrorMode);
if (!res.isOk())
return res;
@@ -953,7 +954,7 @@
&streamId, physicalCameraId, streamInfo.sensorPixelModesUsed, &surfaceIds,
outputConfiguration.getSurfaceSetID(), isShared, isMultiResolution,
/*consumerUsage*/0, streamInfo.dynamicRangeProfile, streamInfo.streamUseCase,
- streamInfo.timestampBase);
+ streamInfo.timestampBase, streamInfo.mirrorMode);
}
if (err != OK) {
@@ -979,7 +980,7 @@
streamInfo.height, streamInfo.format);
// Set transform flags to ensure preview to be rotated correctly.
- res = setStreamTransformLocked(streamId);
+ res = setStreamTransformLocked(streamId, streamInfo.mirrorMode);
// Fill in mHighResolutionCameraIdToStreamIdSet map
const String8 &cameraIdUsed =
@@ -1049,7 +1050,8 @@
outputConfiguration.getSurfaceSetID(), isShared,
outputConfiguration.isMultiResolution(), consumerUsage,
outputConfiguration.getDynamicRangeProfile(),
- outputConfiguration.getStreamUseCase());
+ outputConfiguration.getStreamUseCase(),
+ outputConfiguration.getMirrorMode());
if (err != OK) {
res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
@@ -1065,14 +1067,15 @@
overriddenSensorPixelModesUsed,
outputConfiguration.getDynamicRangeProfile(),
outputConfiguration.getStreamUseCase(),
- outputConfiguration.getTimestampBase()));
+ outputConfiguration.getTimestampBase(),
+ outputConfiguration.getMirrorMode()));
ALOGV("%s: Camera %s: Successfully created a new stream ID %d for a deferred surface"
" (%d x %d) stream with format 0x%x.",
__FUNCTION__, mCameraIdStr.string(), streamId, width, height, format);
// Set transform flags to ensure preview to be rotated correctly.
- res = setStreamTransformLocked(streamId);
+ res = setStreamTransformLocked(streamId, outputConfiguration.getMirrorMode());
*newStreamId = streamId;
// Fill in mHighResolutionCameraIdToStreamIdSet
@@ -1086,7 +1089,7 @@
return res;
}
-binder::Status CameraDeviceClient::setStreamTransformLocked(int streamId) {
+binder::Status CameraDeviceClient::setStreamTransformLocked(int streamId, int mirrorMode) {
int32_t transform = 0;
status_t err;
binder::Status res;
@@ -1095,7 +1098,7 @@
return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
}
- err = getRotationTransformLocked(&transform);
+ err = getRotationTransformLocked(mirrorMode, &transform);
if (err != OK) {
// Error logged by getRotationTransformLocked.
return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION,
@@ -1256,6 +1259,7 @@
int streamUseCase = outputConfiguration.getStreamUseCase();
int timestampBase = outputConfiguration.getTimestampBase();
int dynamicRangeProfile = outputConfiguration.getDynamicRangeProfile();
+ int mirrorMode = outputConfiguration.getMirrorMode();
for (size_t i = 0; i < newOutputsMap.size(); i++) {
OutputStreamInfo outInfo;
@@ -1263,7 +1267,7 @@
res = SessionConfigurationUtils::createSurfaceFromGbp(outInfo,
/*isStreamInfoValid*/ false, surface, newOutputsMap.valueAt(i), mCameraIdStr,
mDevice->infoPhysical(physicalCameraId), sensorPixelModesUsed, dynamicRangeProfile,
- streamUseCase, timestampBase);
+ streamUseCase, timestampBase, mirrorMode);
if (!res.isOk())
return res;
@@ -1623,6 +1627,7 @@
int dynamicRangeProfile = outputConfiguration.getDynamicRangeProfile();
int streamUseCase= outputConfiguration.getStreamUseCase();
int timestampBase = outputConfiguration.getTimestampBase();
+ int mirrorMode = outputConfiguration.getMirrorMode();
for (auto& bufferProducer : bufferProducers) {
// Don't create multiple streams for the same target surface
ssize_t index = mStreamMap.indexOfKey(IInterface::asBinder(bufferProducer));
@@ -1636,7 +1641,7 @@
res = SessionConfigurationUtils::createSurfaceFromGbp(mStreamInfoMap[streamId],
true /*isStreamInfoValid*/, surface, bufferProducer, mCameraIdStr,
mDevice->infoPhysical(physicalId), sensorPixelModesUsed, dynamicRangeProfile,
- streamUseCase, timestampBase);
+ streamUseCase, timestampBase, mirrorMode);
if (!res.isOk())
return res;
@@ -2118,11 +2123,12 @@
return true;
}
-status_t CameraDeviceClient::getRotationTransformLocked(int32_t* transform) {
+status_t CameraDeviceClient::getRotationTransformLocked(int mirrorMode,
+ int32_t* transform) {
ALOGV("%s: begin", __FUNCTION__);
const CameraMetadata& staticInfo = mDevice->info();
- return CameraUtils::getRotationTransform(staticInfo, transform);
+ return CameraUtils::getRotationTransform(staticInfo, mirrorMode, transform);
}
binder::Status CameraDeviceClient::mapRequestTemplate(int templateId,
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 1b0c61a..dad10a7 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -227,7 +227,7 @@
virtual void detachDevice();
// Calculate the ANativeWindow transform from android.sensor.orientation
- status_t getRotationTransformLocked(/*out*/int32_t* transform);
+ status_t getRotationTransformLocked(int mirrorMode, /*out*/int32_t* transform);
bool isUltraHighResolutionSensor(const String8 &cameraId);
@@ -287,7 +287,7 @@
// Set the stream transform flags to automatically rotate the camera stream for preview use
// cases.
- binder::Status setStreamTransformLocked(int streamId);
+ binder::Status setStreamTransformLocked(int streamId, int mirrorMode);
// Utility method to insert the surface into SurfaceMap
binder::Status insertGbpLocked(const sp<IGraphicBufferProducer>& gbp,
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index baa21f0..bde0693 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -185,7 +185,8 @@
uint64_t consumerUsage = 0,
int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
- int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT) = 0;
+ int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT,
+ int mirrorMode = OutputConfiguration::MIRROR_MODE_AUTO) = 0;
/**
* Create an output stream of the requested size, format, rotation and
@@ -205,7 +206,8 @@
uint64_t consumerUsage = 0,
int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
- int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT) = 0;
+ int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT,
+ int mirrorMode = OutputConfiguration::MIRROR_MODE_AUTO) = 0;
/**
* Create an input stream of width, height, and format.
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index f31241c..e4338b9 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -980,7 +980,8 @@
const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
std::vector<int> *surfaceIds, int streamSetId, bool isShared, bool isMultiResolution,
- uint64_t consumerUsage, int dynamicRangeProfile, int streamUseCase, int timestampBase) {
+ uint64_t consumerUsage, int dynamicRangeProfile, int streamUseCase, int timestampBase,
+ int mirrorMode) {
ATRACE_CALL();
if (consumer == nullptr) {
@@ -994,7 +995,7 @@
return createStream(consumers, /*hasDeferredConsumer*/ false, width, height,
format, dataSpace, rotation, id, physicalCameraId, sensorPixelModesUsed, surfaceIds,
streamSetId, isShared, isMultiResolution, consumerUsage, dynamicRangeProfile,
- streamUseCase, timestampBase);
+ streamUseCase, timestampBase, mirrorMode);
}
static bool isRawFormat(int format) {
@@ -1014,7 +1015,8 @@
android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id,
const String8& physicalCameraId, const std::unordered_set<int32_t> &sensorPixelModesUsed,
std::vector<int> *surfaceIds, int streamSetId, bool isShared, bool isMultiResolution,
- uint64_t consumerUsage, int dynamicRangeProfile, int streamUseCase, int timestampBase) {
+ uint64_t consumerUsage, int dynamicRangeProfile, int streamUseCase, int timestampBase,
+ int mirrorMode) {
ATRACE_CALL();
Mutex::Autolock il(mInterfaceLock);
@@ -1022,10 +1024,10 @@
Mutex::Autolock l(mLock);
ALOGV("Camera %s: Creating new stream %d: %d x %d, format %d, dataspace %d rotation %d"
" consumer usage %" PRIu64 ", isShared %d, physicalCameraId %s, isMultiResolution %d"
- " dynamicRangeProfile %d, streamUseCase %d, timestampBase %d",
+ " dynamicRangeProfile %d, streamUseCase %d, timestampBase %d, mirrorMode %d",
mId.string(), mNextStreamId, width, height, format, dataSpace, rotation,
consumerUsage, isShared, physicalCameraId.string(), isMultiResolution,
- dynamicRangeProfile, streamUseCase, timestampBase);
+ dynamicRangeProfile, streamUseCase, timestampBase, mirrorMode);
status_t res;
bool wasActive = false;
@@ -1095,7 +1097,7 @@
width, height, blobBufferSize, format, dataSpace, rotation,
mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
isMultiResolution, dynamicRangeProfile, streamUseCase, mDeviceTimeBaseIsRealtime,
- timestampBase);
+ timestampBase, mirrorMode);
} else if (format == HAL_PIXEL_FORMAT_RAW_OPAQUE) {
bool maxResolution =
sensorPixelModesUsed.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
@@ -1110,25 +1112,25 @@
width, height, rawOpaqueBufferSize, format, dataSpace, rotation,
mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
isMultiResolution, dynamicRangeProfile, streamUseCase, mDeviceTimeBaseIsRealtime,
- timestampBase);
+ timestampBase, mirrorMode);
} else if (isShared) {
newStream = new Camera3SharedOutputStream(mNextStreamId, consumers,
width, height, format, consumerUsage, dataSpace, rotation,
mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
mUseHalBufManager, dynamicRangeProfile, streamUseCase, mDeviceTimeBaseIsRealtime,
- timestampBase);
+ timestampBase, mirrorMode);
} else if (consumers.size() == 0 && hasDeferredConsumer) {
newStream = new Camera3OutputStream(mNextStreamId,
width, height, format, consumerUsage, dataSpace, rotation,
mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
isMultiResolution, dynamicRangeProfile, streamUseCase, mDeviceTimeBaseIsRealtime,
- timestampBase);
+ timestampBase, mirrorMode);
} else {
newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
width, height, format, dataSpace, rotation,
mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
isMultiResolution, dynamicRangeProfile, streamUseCase, mDeviceTimeBaseIsRealtime,
- timestampBase);
+ timestampBase, mirrorMode);
}
size_t consumerCount = consumers.size();
@@ -1247,7 +1249,7 @@
CLOGE("Stream %d does not exist", id);
return BAD_VALUE;
}
- return stream->setTransform(transform);
+ return stream->setTransform(transform, false /*mayChangeMirror*/);
}
status_t Camera3Device::deleteStream(int id) {
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 0f5e65b..5f0a296 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -136,7 +136,8 @@
int dynamicRangeProfile =
ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
- int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT) override;
+ int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT,
+ int mirrorMode = OutputConfiguration::MIRROR_MODE_AUTO) override;
status_t createStream(const std::vector<sp<Surface>>& consumers,
bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
@@ -150,7 +151,8 @@
int dynamicRangeProfile =
ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
- int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT) override;
+ int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT,
+ int mirrorMode = OutputConfiguration::MIRROR_MODE_AUTO) override;
status_t createInputStream(
uint32_t width, uint32_t height, int format, bool isMultiResolution,
diff --git a/services/camera/libcameraservice/device3/Camera3FakeStream.cpp b/services/camera/libcameraservice/device3/Camera3FakeStream.cpp
index 61e43cb..19afd69 100644
--- a/services/camera/libcameraservice/device3/Camera3FakeStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3FakeStream.cpp
@@ -76,7 +76,7 @@
Camera3IOStreamBase::dump(fd, args);
}
-status_t Camera3FakeStream::setTransform(int) {
+status_t Camera3FakeStream::setTransform(int, bool) {
ATRACE_CALL();
// Do nothing
return OK;
diff --git a/services/camera/libcameraservice/device3/Camera3FakeStream.h b/services/camera/libcameraservice/device3/Camera3FakeStream.h
index df19c3d..48e44dc 100644
--- a/services/camera/libcameraservice/device3/Camera3FakeStream.h
+++ b/services/camera/libcameraservice/device3/Camera3FakeStream.h
@@ -52,7 +52,7 @@
virtual void dump(int fd, const Vector<String16> &args) const;
- status_t setTransform(int transform);
+ status_t setTransform(int transform, bool mayChangeMirror);
virtual status_t detachBuffer(sp<GraphicBuffer>* buffer, int* fenceFd);
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index a82d19b..9574309 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -47,7 +47,8 @@
nsecs_t timestampOffset, const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
int setId, bool isMultiResolution, int dynamicRangeProfile,
- int streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase) :
+ int streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase,
+ int mirrorMode) :
Camera3IOStreamBase(id, CAMERA_STREAM_OUTPUT, width, height,
/*maxSize*/0, format, dataSpace, rotation,
physicalCameraId, sensorPixelModesUsed, setId, isMultiResolution,
@@ -60,6 +61,7 @@
mTimestampOffset(timestampOffset),
mConsumerUsage(0),
mDropBuffers(false),
+ mMirrorMode(mirrorMode),
mDequeueBufferLatency(kDequeueLatencyBinSize) {
if (mConsumer == NULL) {
@@ -78,7 +80,8 @@
nsecs_t timestampOffset, const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
int setId, bool isMultiResolution, int dynamicRangeProfile,
- int streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase) :
+ int streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase,
+ int mirrorMode) :
Camera3IOStreamBase(id, CAMERA_STREAM_OUTPUT, width, height, maxSize,
format, dataSpace, rotation, physicalCameraId, sensorPixelModesUsed,
setId, isMultiResolution, dynamicRangeProfile, streamUseCase,
@@ -90,6 +93,7 @@
mTimestampOffset(timestampOffset),
mConsumerUsage(0),
mDropBuffers(false),
+ mMirrorMode(mirrorMode),
mDequeueBufferLatency(kDequeueLatencyBinSize) {
if (format != HAL_PIXEL_FORMAT_BLOB && format != HAL_PIXEL_FORMAT_RAW_OPAQUE) {
@@ -114,7 +118,8 @@
const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
int setId, bool isMultiResolution, int dynamicRangeProfile,
- int streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase) :
+ int streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase,
+ int mirrorMode) :
Camera3IOStreamBase(id, CAMERA_STREAM_OUTPUT, width, height,
/*maxSize*/0, format, dataSpace, rotation,
physicalCameraId, sensorPixelModesUsed, setId, isMultiResolution,
@@ -127,6 +132,7 @@
mTimestampOffset(timestampOffset),
mConsumerUsage(consumerUsage),
mDropBuffers(false),
+ mMirrorMode(mirrorMode),
mDequeueBufferLatency(kDequeueLatencyBinSize) {
// Deferred consumer only support preview surface format now.
if (format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
@@ -158,7 +164,8 @@
uint64_t consumerUsage, nsecs_t timestampOffset,
int setId, bool isMultiResolution,
int dynamicRangeProfile, int streamUseCase,
- bool deviceTimeBaseIsRealtime, int timestampBase) :
+ bool deviceTimeBaseIsRealtime, int timestampBase,
+ int mirrorMode) :
Camera3IOStreamBase(id, type, width, height,
/*maxSize*/0,
format, dataSpace, rotation,
@@ -171,6 +178,7 @@
mTimestampOffset(timestampOffset),
mConsumerUsage(consumerUsage),
mDropBuffers(false),
+ mMirrorMode(mirrorMode),
mDequeueBufferLatency(kDequeueLatencyBinSize) {
bool needsReleaseNotify = setId > CAMERA3_STREAM_SET_ID_INVALID;
@@ -379,7 +387,7 @@
return res;
}
} else {
- setTransform(transform);
+ setTransform(transform, true/*mayChangeMirror*/);
res = native_window_set_buffers_timestamp(mConsumer.get(), t);
if (res != OK) {
ALOGE("%s: Stream %d: Error setting timestamp: %s (%d)",
@@ -426,9 +434,15 @@
" DequeueBuffer latency histogram:");
}
-status_t Camera3OutputStream::setTransform(int transform) {
+status_t Camera3OutputStream::setTransform(int transform, bool mayChangeMirror) {
ATRACE_CALL();
Mutex::Autolock l(mLock);
+ if (mMirrorMode != OutputConfiguration::MIRROR_MODE_AUTO && mayChangeMirror) {
+ // If the mirroring mode is not AUTO, do not allow transform update
+ // which may change mirror.
+ return OK;
+ }
+
return setTransformLocked(transform);
}
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index c7910b7..80901d6 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -93,7 +93,8 @@
int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
bool deviceTimeBaseIsRealtime = false,
- int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT);
+ int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT,
+ int mirrorMode = OutputConfiguration::MIRROR_MODE_AUTO);
/**
* Set up a stream for formats that have a variable buffer size for the same
* dimensions, such as compressed JPEG.
@@ -109,7 +110,8 @@
int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
bool deviceTimeBaseIsRealtime = false,
- int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT);
+ int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT,
+ int mirrorMode = OutputConfiguration::MIRROR_MODE_AUTO);
/**
* Set up a stream with deferred consumer for formats that have 2 dimensions, such as
* RAW and YUV. The consumer must be set before using this stream for output. A valid
@@ -124,7 +126,8 @@
int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
bool deviceTimeBaseIsRealtime = false,
- int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT);
+ int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT,
+ int mirrorMode = OutputConfiguration::MIRROR_MODE_AUTO);
virtual ~Camera3OutputStream();
@@ -138,7 +141,7 @@
* Set the transform on the output stream; one of the
* HAL_TRANSFORM_* / NATIVE_WINDOW_TRANSFORM_* constants.
*/
- status_t setTransform(int transform);
+ status_t setTransform(int transform, bool mayChangeMirror);
/**
* Return if this output stream is for video encoding.
@@ -255,7 +258,8 @@
int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
bool deviceTimeBaseIsRealtime = false,
- int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT);
+ int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT,
+ int mirrorMode = OutputConfiguration::MIRROR_MODE_AUTO);
/**
* Note that we release the lock briefly in this function
@@ -343,6 +347,8 @@
std::vector<Surface::BatchBuffer> mBatchedBuffers;
// ---- End of mBatchLock protected scope ----
+ const int mMirrorMode;
+
/**
* Internal Camera3Stream interface
*/
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h b/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h
index 49f9f62..e44e795 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h
@@ -34,7 +34,7 @@
* Set the transform on the output stream; one of the
* HAL_TRANSFORM_* / NATIVE_WINDOW_TRANSFORM_* constants.
*/
- virtual status_t setTransform(int transform) = 0;
+ virtual status_t setTransform(int transform, bool mayChangeMirror) = 0;
/**
* Return if this output stream is for video encoding.
diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
index d8cc685..ab25322 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
@@ -532,7 +532,7 @@
auto orientation = deviceInfo->second.find(ANDROID_SENSOR_ORIENTATION);
if (orientation.count > 0) {
ret = CameraUtils::getRotationTransform(deviceInfo->second,
- &request.transform);
+ OutputConfiguration::MIRROR_MODE_AUTO, &request.transform);
if (ret != OK) {
ALOGE("%s: Failed to calculate current stream transformation: %s (%d)",
__FUNCTION__, strerror(-ret), ret);
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
index 047897e..9bf7b6a 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
@@ -34,11 +34,13 @@
nsecs_t timestampOffset, const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
int setId, bool useHalBufManager, int dynamicProfile,
- int streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase) :
+ int streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase,
+ int mirrorMode) :
Camera3OutputStream(id, CAMERA_STREAM_OUTPUT, width, height,
format, dataSpace, rotation, physicalCameraId, sensorPixelModesUsed,
consumerUsage, timestampOffset, setId, /*isMultiResolution*/false,
- dynamicProfile, streamUseCase, deviceTimeBaseIsRealtime, timestampBase),
+ dynamicProfile, streamUseCase, deviceTimeBaseIsRealtime, timestampBase,
+ mirrorMode),
mUseHalBufManager(useHalBufManager) {
size_t consumerCount = std::min(surfaces.size(), kMaxOutputs);
if (surfaces.size() > consumerCount) {
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
index dc22c42..0061a52 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
@@ -44,7 +44,8 @@
int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
bool deviceTimeBaseIsRealtime = false,
- int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT);
+ int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT,
+ int mirrorMode = OutputConfiguration::MIRROR_MODE_AUTO);
virtual ~Camera3SharedOutputStream();
diff --git a/services/camera/libcameraservice/device3/Camera3StreamInterface.h b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
index 8962fac..148e511 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamInterface.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
@@ -113,19 +113,21 @@
int dynamicRangeProfile;
int streamUseCase;
int timestampBase;
+ int mirrorMode;
OutputStreamInfo() :
width(-1), height(-1), format(-1), dataSpace(HAL_DATASPACE_UNKNOWN),
consumerUsage(0),
dynamicRangeProfile(ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD),
streamUseCase(ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT),
- timestampBase(OutputConfiguration::TIMESTAMP_BASE_DEFAULT) {}
+ timestampBase(OutputConfiguration::TIMESTAMP_BASE_DEFAULT),
+ mirrorMode(OutputConfiguration::MIRROR_MODE_AUTO) {}
OutputStreamInfo(int _width, int _height, int _format, android_dataspace _dataSpace,
uint64_t _consumerUsage, const std::unordered_set<int32_t>& _sensorPixelModesUsed,
- int _dynamicRangeProfile, int _streamUseCase, int _timestampBase) :
+ int _dynamicRangeProfile, int _streamUseCase, int _timestampBase, int _mirrorMode) :
width(_width), height(_height), format(_format),
dataSpace(_dataSpace), consumerUsage(_consumerUsage),
sensorPixelModesUsed(_sensorPixelModesUsed), dynamicRangeProfile(_dynamicRangeProfile),
- streamUseCase(_streamUseCase), timestampBase(_timestampBase) {}
+ streamUseCase(_streamUseCase), timestampBase(_timestampBase), mirrorMode(_mirrorMode) {}
};
/**
diff --git a/services/camera/libcameraservice/device3/PreviewFrameScheduler.cpp b/services/camera/libcameraservice/device3/PreviewFrameScheduler.cpp
index 6135f9e..154e6f5 100644
--- a/services/camera/libcameraservice/device3/PreviewFrameScheduler.cpp
+++ b/services/camera/libcameraservice/device3/PreviewFrameScheduler.cpp
@@ -187,7 +187,7 @@
status_t PreviewFrameScheduler::queueBufferToClientLocked(
const BufferHolder& bufferHolder, nsecs_t timestamp) {
- mParent.setTransform(bufferHolder.transform);
+ mParent.setTransform(bufferHolder.transform, true/*mayChangeMirror*/);
status_t res = native_window_set_buffers_timestamp(mConsumer.get(), timestamp);
if (res != OK) {
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
index 751f24f..e38140b 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
@@ -334,7 +334,7 @@
sp<Surface>& surface, const sp<IGraphicBufferProducer>& gbp,
const String8 &logicalCameraId, const CameraMetadata &physicalCameraMetadata,
const std::vector<int32_t> &sensorPixelModesUsed, int dynamicRangeProfile,
- int streamUseCase, int timestampBase) {
+ int streamUseCase, int timestampBase, int mirrorMode) {
// bufferProducer must be non-null
if (gbp == nullptr) {
String8 msg = String8::format("Camera %s: Surface is NULL", logicalCameraId.string());
@@ -461,6 +461,13 @@
ALOGE("%s: %s", __FUNCTION__, msg.string());
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
}
+ if (mirrorMode < OutputConfiguration::MIRROR_MODE_AUTO ||
+ mirrorMode > OutputConfiguration::MIRROR_MODE_V) {
+ String8 msg = String8::format("Camera %s: invalid mirroring mode %d",
+ logicalCameraId.string(), mirrorMode);
+ ALOGE("%s: %s", __FUNCTION__, msg.string());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+ }
if (!isStreamInfoValid) {
streamInfo.width = width;
@@ -472,6 +479,7 @@
streamInfo.dynamicRangeProfile = dynamicRangeProfile;
streamInfo.streamUseCase = streamUseCase;
streamInfo.timestampBase = timestampBase;
+ streamInfo.mirrorMode = mirrorMode;
return binder::Status::ok();
}
if (width != streamInfo.width) {
@@ -706,6 +714,7 @@
int streamUseCase = it.getStreamUseCase();
int timestampBase = it.getTimestampBase();
+ int mirrorMode = it.getMirrorMode();
if (deferredConsumer) {
streamInfo.width = it.getWidth();
streamInfo.height = it.getHeight();
@@ -740,7 +749,7 @@
sp<Surface> surface;
res = createSurfaceFromGbp(streamInfo, isStreamInfoValid, surface, bufferProducer,
logicalCameraId, metadataChosen, sensorPixelModesUsed, dynamicRangeProfile,
- streamUseCase, timestampBase);
+ streamUseCase, timestampBase, mirrorMode);
if (!res.isOk())
return res;
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
index 3dcbdbc..1e690e4 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
@@ -98,7 +98,7 @@
sp<Surface>& surface, const sp<IGraphicBufferProducer>& gbp,
const String8 &logicalCameraId, const CameraMetadata &physicalCameraMetadata,
const std::vector<int32_t> &sensorPixelModesUsed, int dynamicRangeProfile,
- int streamUseCase, int timestampBase);
+ int streamUseCase, int timestampBase, int mirrorMode);
void mapStreamInfo(const camera3::OutputStreamInfo &streamInfo,
camera3::camera_stream_rotation_t rotation, String8 physicalId, int32_t groupId,