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/camera/CameraUtils.cpp b/camera/CameraUtils.cpp
index af3c492..3473780 100644
--- a/camera/CameraUtils.cpp
+++ b/camera/CameraUtils.cpp
@@ -18,6 +18,7 @@
//#define LOG_NDEBUG 0
#include <camera/CameraUtils.h>
+#include <camera/camera2/OutputConfiguration.h>
#include <media/hardware/HardwareAPI.h>
#include <android-base/properties.h>
@@ -31,7 +32,7 @@
const char *kCameraServiceDisabledProperty = "config.disable_cameraservice";
status_t CameraUtils::getRotationTransform(const CameraMetadata& staticInfo,
- /*out*/int32_t* transform) {
+ int mirrorMode, /*out*/int32_t* transform) {
ALOGV("%s", __FUNCTION__);
if (transform == NULL) {
@@ -55,9 +56,18 @@
int32_t& flags = *transform;
- bool mirror = (entryFacing.data.u8[0] == ANDROID_LENS_FACING_FRONT);
+ int32_t mirror = 0;
+ if (mirrorMode == OutputConfiguration::MIRROR_MODE_AUTO &&
+ entryFacing.data.u8[0] == ANDROID_LENS_FACING_FRONT) {
+ mirror = NATIVE_WINDOW_TRANSFORM_FLIP_H;
+ } else if (mirrorMode == OutputConfiguration::MIRROR_MODE_H) {
+ mirror = NATIVE_WINDOW_TRANSFORM_FLIP_H;
+ } else if (mirrorMode == OutputConfiguration::MIRROR_MODE_V) {
+ mirror = NATIVE_WINDOW_TRANSFORM_FLIP_V;
+ }
+
int orientation = entry.data.i32[0];
- if (!mirror) {
+ if (mirror == 0) {
switch (orientation) {
case 0:
flags = 0;
@@ -77,25 +87,25 @@
return INVALID_OPERATION;
}
} else {
- // Front camera needs to be horizontally flipped for mirror-like behavior.
+ // - Front camera needs to be horizontally flipped for mirror-like behavior.
+ // - Application-specified mirroring needs to be applied.
// Note: Flips are applied before rotates; using XOR here as some of these flags are
// composed in terms of other flip/rotation flags, and are not bitwise-ORable.
switch (orientation) {
case 0:
- flags = NATIVE_WINDOW_TRANSFORM_FLIP_H;
+ flags = mirror;
break;
case 90:
- flags = NATIVE_WINDOW_TRANSFORM_FLIP_H ^
+ flags = mirror ^
NATIVE_WINDOW_TRANSFORM_ROT_270;
break;
case 180:
- flags = NATIVE_WINDOW_TRANSFORM_FLIP_H ^
+ flags = mirror ^
NATIVE_WINDOW_TRANSFORM_ROT_180;
break;
case 270:
- flags = NATIVE_WINDOW_TRANSFORM_FLIP_H ^
+ flags = mirror ^
NATIVE_WINDOW_TRANSFORM_ROT_90;
-
break;
default:
ALOGE("%s: Invalid HAL android.sensor.orientation value: %d",
diff --git a/camera/camera2/OutputConfiguration.cpp b/camera/camera2/OutputConfiguration.cpp
index a16e747..4300f9a 100644
--- a/camera/camera2/OutputConfiguration.cpp
+++ b/camera/camera2/OutputConfiguration.cpp
@@ -89,6 +89,10 @@
return mTimestampBase;
}
+int OutputConfiguration::getMirrorMode() const {
+ return mMirrorMode;
+}
+
OutputConfiguration::OutputConfiguration() :
mRotation(INVALID_ROTATION),
mSurfaceSetID(INVALID_SET_ID),
@@ -100,7 +104,8 @@
mIsMultiResolution(false),
mDynamicRangeProfile(ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD),
mStreamUseCase(ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT),
- mTimestampBase(TIMESTAMP_BASE_DEFAULT) {
+ mTimestampBase(TIMESTAMP_BASE_DEFAULT),
+ mMirrorMode(MIRROR_MODE_AUTO) {
}
OutputConfiguration::OutputConfiguration(const android::Parcel& parcel) :
@@ -199,6 +204,12 @@
return err;
}
+ int mirrorMode = MIRROR_MODE_AUTO;
+ if ((err = parcel->readInt32(&mirrorMode)) != OK) {
+ ALOGE("%s: Failed to read mirroring mode from parcel", __FUNCTION__);
+ return err;
+ }
+
mRotation = rotation;
mSurfaceSetID = setID;
mSurfaceType = surfaceType;
@@ -209,6 +220,7 @@
mIsMultiResolution = isMultiResolution != 0;
mStreamUseCase = streamUseCase;
mTimestampBase = timestampBase;
+ mMirrorMode = mirrorMode;
for (auto& surface : surfaceShims) {
ALOGV("%s: OutputConfiguration: %p, name %s", __FUNCTION__,
surface.graphicBufferProducer.get(),
@@ -220,9 +232,11 @@
mDynamicRangeProfile = dynamicProfile;
ALOGV("%s: OutputConfiguration: rotation = %d, setId = %d, surfaceType = %d,"
- " physicalCameraId = %s, isMultiResolution = %d, streamUseCase = %d, timestampBase = %d",
+ " physicalCameraId = %s, isMultiResolution = %d, streamUseCase = %d, timestampBase = %d,"
+ " mirrorMode = %d",
__FUNCTION__, mRotation, mSurfaceSetID, mSurfaceType,
- String8(mPhysicalCameraId).string(), mIsMultiResolution, mStreamUseCase, timestampBase);
+ String8(mPhysicalCameraId).string(), mIsMultiResolution, mStreamUseCase, timestampBase,
+ mMirrorMode);
return err;
}
@@ -240,6 +254,7 @@
mDynamicRangeProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD;
mStreamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT;
mTimestampBase = TIMESTAMP_BASE_DEFAULT;
+ mMirrorMode = MIRROR_MODE_AUTO;
}
OutputConfiguration::OutputConfiguration(
@@ -251,7 +266,8 @@
mPhysicalCameraId(physicalCameraId), mIsMultiResolution(false),
mDynamicRangeProfile(ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD),
mStreamUseCase(ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT),
- mTimestampBase(TIMESTAMP_BASE_DEFAULT) { }
+ mTimestampBase(TIMESTAMP_BASE_DEFAULT),
+ mMirrorMode(MIRROR_MODE_AUTO) { }
status_t OutputConfiguration::writeToParcel(android::Parcel* parcel) const {
@@ -307,6 +323,9 @@
err = parcel->writeInt32(mTimestampBase);
if (err != OK) return err;
+ err = parcel->writeInt32(mMirrorMode);
+ if (err != OK) return err;
+
return OK;
}
diff --git a/camera/include/camera/CameraUtils.h b/camera/include/camera/CameraUtils.h
index a397ccd..31d25e7 100644
--- a/camera/include/camera/CameraUtils.h
+++ b/camera/include/camera/CameraUtils.h
@@ -37,10 +37,13 @@
* metadata. This is based on the sensor orientation and lens facing
* attributes of the camera device.
*
+ * If mirrorMode is not AUTO, it will be used to override the lens
+ * facing based mirror.
+ *
* Returns OK on success, or a negative error code.
*/
static status_t getRotationTransform(const CameraMetadata& staticInfo,
- /*out*/int32_t* transform);
+ int mirrorMode, /*out*/int32_t* transform);
/**
* Check if the image data is VideoNativeHandleMetadata, that contains a native handle.
diff --git a/camera/include/camera/camera2/OutputConfiguration.h b/camera/include/camera/camera2/OutputConfiguration.h
index 9a91cc0..d7abfba 100644
--- a/camera/include/camera/camera2/OutputConfiguration.h
+++ b/camera/include/camera/camera2/OutputConfiguration.h
@@ -38,13 +38,19 @@
SURFACE_TYPE_SURFACE_VIEW = 0,
SURFACE_TYPE_SURFACE_TEXTURE = 1
};
- enum TimestampBaseByte {
+ enum TimestampBaseType {
TIMESTAMP_BASE_DEFAULT = 0,
TIMESTAMP_BASE_SENSOR = 1,
TIMESTAMP_BASE_MONOTONIC = 2,
TIMESTAMP_BASE_REALTIME = 3,
TIMESTAMP_BASE_CHOREOGRAPHER_SYNCED = 4
};
+ enum MirrorModeType {
+ MIRROR_MODE_AUTO = 0,
+ MIRROR_MODE_NONE = 1,
+ MIRROR_MODE_H = 2,
+ MIRROR_MODE_V = 3,
+ };
const std::vector<sp<IGraphicBufferProducer>>& getGraphicBufferProducers() const;
int getRotation() const;
@@ -59,6 +65,7 @@
bool isMultiResolution() const;
int getStreamUseCase() const;
int getTimestampBase() const;
+ int getMirrorMode() const;
// set of sensor pixel mode resolutions allowed {MAX_RESOLUTION, DEFAULT_MODE};
const std::vector<int32_t>& getSensorPixelModesUsed() const;
@@ -103,7 +110,8 @@
sensorPixelModesUsedEqual(other) &&
mDynamicRangeProfile == other.mDynamicRangeProfile &&
mStreamUseCase == other.mStreamUseCase &&
- mTimestampBase == other.mTimestampBase);
+ mTimestampBase == other.mTimestampBase &&
+ mMirrorMode == other.mMirrorMode);
}
bool operator != (const OutputConfiguration& other) const {
return !(*this == other);
@@ -149,6 +157,9 @@
if (mTimestampBase != other.mTimestampBase) {
return mTimestampBase < other.mTimestampBase;
}
+ if (mMirrorMode != other.mMirrorMode) {
+ return mMirrorMode < other.mMirrorMode;
+ }
return gbpsLessThan(other);
}
@@ -176,6 +187,7 @@
int mDynamicRangeProfile;
int mStreamUseCase;
int mTimestampBase;
+ int mMirrorMode;
};
} // namespace params
} // namespace camera2