cameraserver: Add HAL plumbing + capture request verification for quad bayer sensor apis.
- Verify that for 'high resolution' sensors, capture requests have
sensor pixel modes which are consistent with what their output targets
were configured with.
- Add support for
@3.7::ICameraDevice::isSessionConfigurationSupported_3_7
@3.7::ICameraDevice::configureStreams_3_7
@2.7::ICameraProvider::isConcurrentSessionConfigurationSupported_2_7
- For ZoomRatio(Distortion)Mapper, use MAXIMUM_RESOLUTION variants of SENSOR_INFO*
and LENS_CALIBRATION / LENS_DISTORTION while doing coordinate calculations.
Bug: 152813564
Test: Camera CTS
Test: Camera binder tests
Change-Id: I41a86a55e619b25e17e701955ba8c345013329b9
Signed-off-by: Jayant Chowdhary <jchowdhary@google.com>
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 35a06d8..00983f2 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -60,6 +60,7 @@
#include "device3/Camera3SharedOutputStream.h"
#include "CameraService.h"
#include "utils/CameraThreadState.h"
+#include "utils/SessionConfigurationUtils.h"
#include "utils/TraceHFR.h"
#include "utils/CameraServiceProxyWrapper.h"
@@ -69,6 +70,7 @@
using namespace android::camera3;
using namespace android::hardware::camera;
using namespace android::hardware::camera::device::V3_2;
+using android::hardware::camera::metadata::V3_6::CameraMetadataEnumAndroidSensorPixelMode;
namespace android {
@@ -489,8 +491,13 @@
const int STREAM_WIDTH_OFFSET = 1;
const int STREAM_HEIGHT_OFFSET = 2;
const int STREAM_IS_INPUT_OFFSET = 3;
+ bool isHighResolutionSensor =
+ camera3::SessionConfigurationUtils::isUltraHighResolutionSensor(mDeviceInfo);
+ int32_t scalerSizesTag = isHighResolutionSensor ?
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION :
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS;
camera_metadata_ro_entry_t availableStreamConfigs =
- mDeviceInfo.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
+ mDeviceInfo.find(scalerSizesTag);
if (availableStreamConfigs.count == 0 ||
availableStreamConfigs.count % STREAM_CONFIGURATION_SIZE != 0) {
return camera3::Size(0, 0);
@@ -628,6 +635,8 @@
ssize_t jpegBufferSize = scaleFactor * (maxJpegBufferSize - kMinJpegBufferSize) +
kMinJpegBufferSize;
if (jpegBufferSize > maxJpegBufferSize) {
+ ALOGI("%s: jpeg buffer size calculated is > maxJpeg bufferSize(%zd), clamping",
+ __FUNCTION__, maxJpegBufferSize);
jpegBufferSize = maxJpegBufferSize;
}
@@ -647,13 +656,17 @@
return maxBytesForPointCloud;
}
-ssize_t Camera3Device::getRawOpaqueBufferSize(int32_t width, int32_t height) const {
+ssize_t Camera3Device::getRawOpaqueBufferSize(int32_t width, int32_t height,
+ bool maxResolution) const {
const int PER_CONFIGURATION_SIZE = 3;
const int WIDTH_OFFSET = 0;
const int HEIGHT_OFFSET = 1;
const int SIZE_OFFSET = 2;
camera_metadata_ro_entry rawOpaqueSizes =
- mDeviceInfo.find(ANDROID_SENSOR_OPAQUE_RAW_SIZE);
+ mDeviceInfo.find(
+ camera3::SessionConfigurationUtils::getAppropriateModeTag(
+ ANDROID_SENSOR_OPAQUE_RAW_SIZE,
+ maxResolution));
size_t count = rawOpaqueSizes.count;
if (count == 0 || (count % PER_CONFIGURATION_SIZE)) {
ALOGE("%s: Camera %s: bad opaque RAW size static metadata length(%zu)!",
@@ -1325,8 +1338,9 @@
uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id,
const String8& physicalCameraId,
- std::vector<int> *surfaceIds, int streamSetId, bool isShared,
- bool isMultiResolution, uint64_t consumerUsage) {
+ const std::unordered_set<int32_t> &sensorPixelModesUsed,
+ std::vector<int> *surfaceIds, int streamSetId, bool isShared, bool isMultiResolution,
+ uint64_t consumerUsage) {
ATRACE_CALL();
if (consumer == nullptr) {
@@ -1338,14 +1352,26 @@
consumers.push_back(consumer);
return createStream(consumers, /*hasDeferredConsumer*/ false, width, height,
- format, dataSpace, rotation, id, physicalCameraId, surfaceIds, streamSetId,
- isShared, isMultiResolution, consumerUsage);
+ format, dataSpace, rotation, id, physicalCameraId, sensorPixelModesUsed, surfaceIds,
+ streamSetId, isShared, isMultiResolution, consumerUsage);
+}
+
+static bool isRawFormat(int format) {
+ switch (format) {
+ case HAL_PIXEL_FORMAT_RAW16:
+ case HAL_PIXEL_FORMAT_RAW12:
+ case HAL_PIXEL_FORMAT_RAW10:
+ case HAL_PIXEL_FORMAT_RAW_OPAQUE:
+ return true;
+ default:
+ return false;
+ }
}
status_t Camera3Device::createStream(const std::vector<sp<Surface>>& consumers,
bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id,
- const String8& physicalCameraId,
+ const String8& physicalCameraId, const std::unordered_set<int32_t> &sensorPixelModesUsed,
std::vector<int> *surfaceIds, int streamSetId, bool isShared, bool isMultiResolution,
uint64_t consumerUsage) {
ATRACE_CALL();
@@ -1399,6 +1425,12 @@
return BAD_VALUE;
}
+ if (isRawFormat(format) && sensorPixelModesUsed.size() > 1) {
+ // We can't use one stream with a raw format in both sensor pixel modes since its going to
+ // be found in only one sensor pixel mode.
+ ALOGE("%s: RAW opaque stream cannot be used with > 1 sensor pixel modes", __FUNCTION__);
+ return BAD_VALUE;
+ }
if (format == HAL_PIXEL_FORMAT_BLOB) {
ssize_t blobBufferSize;
if (dataSpace == HAL_DATASPACE_DEPTH) {
@@ -1418,28 +1450,36 @@
}
newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
width, height, blobBufferSize, format, dataSpace, rotation,
- mTimestampOffset, physicalCameraId, streamSetId, isMultiResolution);
+ mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
+ isMultiResolution);
} else if (format == HAL_PIXEL_FORMAT_RAW_OPAQUE) {
- ssize_t rawOpaqueBufferSize = getRawOpaqueBufferSize(width, height);
+ bool maxResolution =
+ sensorPixelModesUsed.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
+ sensorPixelModesUsed.end();
+ ssize_t rawOpaqueBufferSize = getRawOpaqueBufferSize(width, height, maxResolution);
if (rawOpaqueBufferSize <= 0) {
SET_ERR_L("Invalid RAW opaque buffer size %zd", rawOpaqueBufferSize);
return BAD_VALUE;
}
newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
width, height, rawOpaqueBufferSize, format, dataSpace, rotation,
- mTimestampOffset, physicalCameraId, streamSetId, isMultiResolution);
+ mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
+ isMultiResolution);
} else if (isShared) {
newStream = new Camera3SharedOutputStream(mNextStreamId, consumers,
width, height, format, consumerUsage, dataSpace, rotation,
- mTimestampOffset, physicalCameraId, streamSetId, mUseHalBufManager);
+ mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
+ mUseHalBufManager);
} else if (consumers.size() == 0 && hasDeferredConsumer) {
newStream = new Camera3OutputStream(mNextStreamId,
width, height, format, consumerUsage, dataSpace, rotation,
- mTimestampOffset, physicalCameraId, streamSetId, isMultiResolution);
+ mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
+ isMultiResolution);
} else {
newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
width, height, format, dataSpace, rotation,
- mTimestampOffset, physicalCameraId, streamSetId, isMultiResolution);
+ mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
+ isMultiResolution);
}
size_t consumerCount = consumers.size();
@@ -3212,7 +3252,7 @@
dst3_2.usage = mapToConsumerUsage(cam3stream->getUsage());
dst3_2.rotation = mapToStreamRotation((camera_stream_rotation_t) src->rotation);
// For HidlSession version 3.5 or newer, the format and dataSpace sent
- // to HAL are original, not the overriden ones.
+ // to HAL are original, not the overridden ones.
if (mHidlSession_3_5 != nullptr) {
dst3_2.format = mapToPixelFormat(cam3stream->isFormatOverridden() ?
cam3stream->getOriginalFormat() : src->format);
@@ -3229,7 +3269,12 @@
}
dst3_7.v3_4 = dst3_4;
dst3_7.groupId = cam3stream->getHalStreamGroupId();
-
+ dst3_7.sensorPixelModesUsed.resize(src->sensor_pixel_modes_used.size());
+ size_t j = 0;
+ for (int mode : src->sensor_pixel_modes_used) {
+ dst3_7.sensorPixelModesUsed[j++] =
+ static_cast<CameraMetadataEnumAndroidSensorPixelMode>(mode);
+ }
activeStreams.insert(streamId);
// Create Buffer ID map if necessary
mBufferRecords.tryCreateBufferCache(streamId);
@@ -3246,13 +3291,15 @@
}
requestedConfiguration3_2.operationMode = operationMode;
requestedConfiguration3_4.operationMode = operationMode;
+ requestedConfiguration3_7.operationMode = operationMode;
+ size_t sessionParamSize = get_camera_metadata_size(sessionParams);
requestedConfiguration3_4.sessionParams.setToExternal(
reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
- get_camera_metadata_size(sessionParams));
+ sessionParamSize);
requestedConfiguration3_7.operationMode = operationMode;
requestedConfiguration3_7.sessionParams.setToExternal(
reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
- get_camera_metadata_size(sessionParams));
+ sessionParamSize);
// Invoke configureStreams
device::V3_3::HalStreamConfiguration finalConfiguration;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 018dbe5..fccf384 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -132,14 +132,17 @@
uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id,
const String8& physicalCameraId,
+ const std::unordered_set<int32_t> &sensorPixelModesUsed,
std::vector<int> *surfaceIds = nullptr,
int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
bool isShared = false, bool isMultiResolution = false,
uint64_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, camera_stream_rotation_t rotation, int *id,
const String8& physicalCameraId,
+ const std::unordered_set<int32_t> &sensorPixelModesUsed,
std::vector<int> *surfaceIds = nullptr,
int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
bool isShared = false, bool isMultiResolution = false,
@@ -190,7 +193,7 @@
ssize_t getJpegBufferSize(uint32_t width, uint32_t height) const override;
ssize_t getPointCloudBufferSize() const;
- ssize_t getRawOpaqueBufferSize(int32_t width, int32_t height) const;
+ ssize_t getRawOpaqueBufferSize(int32_t width, int32_t height, bool maxResolution) const;
// Methods called by subclasses
void notifyStatus(bool idle); // updates from StatusTracker
diff --git a/services/camera/libcameraservice/device3/Camera3FakeStream.cpp b/services/camera/libcameraservice/device3/Camera3FakeStream.cpp
index 2196c7d..8cc6833 100644
--- a/services/camera/libcameraservice/device3/Camera3FakeStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3FakeStream.cpp
@@ -31,7 +31,7 @@
Camera3FakeStream::Camera3FakeStream(int id) :
Camera3IOStreamBase(id, CAMERA_STREAM_OUTPUT, FAKE_WIDTH, FAKE_HEIGHT,
/*maxSize*/0, FAKE_FORMAT, FAKE_DATASPACE, FAKE_ROTATION,
- FAKE_ID) {
+ FAKE_ID, std::unordered_set<int32_t>{ANDROID_SENSOR_PIXEL_MODE_DEFAULT}) {
}
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
index a837900..0204d49 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
@@ -32,10 +32,12 @@
Camera3IOStreamBase::Camera3IOStreamBase(int id, camera_stream_type_t type,
uint32_t width, uint32_t height, size_t maxSize, int format,
android_dataspace dataSpace, camera_stream_rotation_t rotation,
- const String8& physicalCameraId, int setId, bool isMultiResolution) :
+ const String8& physicalCameraId,
+ const std::unordered_set<int32_t> &sensorPixelModesUsed,
+ int setId, bool isMultiResolution) :
Camera3Stream(id, type,
width, height, maxSize, format, dataSpace, rotation,
- physicalCameraId, setId, isMultiResolution),
+ physicalCameraId, sensorPixelModesUsed, setId, isMultiResolution),
mTotalBufferCount(0),
mHandoutTotalBufferCount(0),
mHandoutOutputBufferCount(0),
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
index 2e744ee..90c8a7b 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
@@ -36,6 +36,7 @@
uint32_t width, uint32_t height, size_t maxSize, int format,
android_dataspace dataSpace, camera_stream_rotation_t rotation,
const String8& physicalCameraId,
+ const std::unordered_set<int32_t> &sensorPixelModesUsed,
int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false);
public:
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.cpp b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
index b00a963..6d8317b 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
@@ -33,7 +33,8 @@
uint32_t width, uint32_t height, int format) :
Camera3IOStreamBase(id, CAMERA_STREAM_INPUT, width, height, /*maxSize*/0,
format, HAL_DATASPACE_UNKNOWN, CAMERA_STREAM_ROTATION_0,
- FAKE_ID) {
+ FAKE_ID,
+ std::unordered_set<int32_t>{ANDROID_SENSOR_PIXEL_MODE_DEFAULT}) {
if (format == HAL_PIXEL_FORMAT_BLOB) {
ALOGE("%s: Bad format, BLOB not supported", __FUNCTION__);
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index 3ec3b6b..221bebb 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -44,10 +44,11 @@
uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera_stream_rotation_t rotation,
nsecs_t timestampOffset, const String8& physicalCameraId,
+ const std::unordered_set<int32_t> &sensorPixelModesUsed,
int setId, bool isMultiResolution) :
Camera3IOStreamBase(id, CAMERA_STREAM_OUTPUT, width, height,
/*maxSize*/0, format, dataSpace, rotation,
- physicalCameraId, setId, isMultiResolution),
+ physicalCameraId, sensorPixelModesUsed, setId, isMultiResolution),
mConsumer(consumer),
mTransform(0),
mTraceFirstBuffer(true),
@@ -70,11 +71,12 @@
sp<Surface> consumer,
uint32_t width, uint32_t height, size_t maxSize, int format,
android_dataspace dataSpace, camera_stream_rotation_t rotation,
- nsecs_t timestampOffset, const String8& physicalCameraId, int setId,
- bool isMultiResolution) :
+ nsecs_t timestampOffset, const String8& physicalCameraId,
+ const std::unordered_set<int32_t> &sensorPixelModesUsed,
+ int setId, bool isMultiResolution) :
Camera3IOStreamBase(id, CAMERA_STREAM_OUTPUT, width, height, maxSize,
- format, dataSpace, rotation, physicalCameraId, setId,
- isMultiResolution),
+ format, dataSpace, rotation, physicalCameraId, sensorPixelModesUsed,
+ setId, isMultiResolution),
mConsumer(consumer),
mTransform(0),
mTraceFirstBuffer(true),
@@ -104,10 +106,12 @@
uint32_t width, uint32_t height, int format,
uint64_t consumerUsage, android_dataspace dataSpace,
camera_stream_rotation_t rotation, nsecs_t timestampOffset,
- const String8& physicalCameraId, int setId, bool isMultiResolution) :
+ const String8& physicalCameraId,
+ const std::unordered_set<int32_t> &sensorPixelModesUsed,
+ int setId, bool isMultiResolution) :
Camera3IOStreamBase(id, CAMERA_STREAM_OUTPUT, width, height,
/*maxSize*/0, format, dataSpace, rotation,
- physicalCameraId, setId, isMultiResolution),
+ physicalCameraId, sensorPixelModesUsed, setId, isMultiResolution),
mConsumer(nullptr),
mTransform(0),
mTraceFirstBuffer(true),
@@ -142,12 +146,13 @@
android_dataspace dataSpace,
camera_stream_rotation_t rotation,
const String8& physicalCameraId,
+ const std::unordered_set<int32_t> &sensorPixelModesUsed,
uint64_t consumerUsage, nsecs_t timestampOffset,
int setId, bool isMultiResolution) :
Camera3IOStreamBase(id, type, width, height,
/*maxSize*/0,
format, dataSpace, rotation,
- physicalCameraId, setId, isMultiResolution),
+ physicalCameraId, sensorPixelModesUsed, setId, isMultiResolution),
mTransform(0),
mTraceFirstBuffer(true),
mUseMonoTimestamp(false),
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index c82f2a6..00e4854 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -87,8 +87,8 @@
uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera_stream_rotation_t rotation,
nsecs_t timestampOffset, const String8& physicalCameraId,
+ const std::unordered_set<int32_t> &sensorPixelModesUsed,
int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false);
-
/**
* Set up a stream for formats that have a variable buffer size for the same
* dimensions, such as compressed JPEG.
@@ -99,8 +99,8 @@
uint32_t width, uint32_t height, size_t maxSize, int format,
android_dataspace dataSpace, camera_stream_rotation_t rotation,
nsecs_t timestampOffset, const String8& physicalCameraId,
+ const std::unordered_set<int32_t> &sensorPixelModesUsed,
int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false);
-
/**
* 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
@@ -110,6 +110,7 @@
uint64_t consumerUsage, android_dataspace dataSpace,
camera_stream_rotation_t rotation, nsecs_t timestampOffset,
const String8& physicalCameraId,
+ const std::unordered_set<int32_t> &sensorPixelModesUsed,
int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false);
virtual ~Camera3OutputStream();
@@ -234,6 +235,7 @@
uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera_stream_rotation_t rotation,
const String8& physicalCameraId,
+ const std::unordered_set<int32_t> &sensorPixelModesUsed,
uint64_t consumerUsage = 0, nsecs_t timestampOffset = 0,
int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false);
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
index 8aa5f1a..15cf7f4 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
@@ -32,9 +32,10 @@
uint64_t consumerUsage, android_dataspace dataSpace,
camera_stream_rotation_t rotation,
nsecs_t timestampOffset, const String8& physicalCameraId,
+ const std::unordered_set<int32_t> &sensorPixelModesUsed,
int setId, bool useHalBufManager) :
Camera3OutputStream(id, CAMERA_STREAM_OUTPUT, width, height,
- format, dataSpace, rotation, physicalCameraId,
+ format, dataSpace, rotation, physicalCameraId, sensorPixelModesUsed,
consumerUsage, timestampOffset, setId),
mUseHalBufManager(useHalBufManager) {
size_t consumerCount = std::min(surfaces.size(), kMaxOutputs);
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
index a61316c..4b6341b 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
@@ -38,6 +38,7 @@
uint64_t consumerUsage, android_dataspace dataSpace,
camera_stream_rotation_t rotation, nsecs_t timestampOffset,
const String8& physicalCameraId,
+ const std::unordered_set<int32_t> &sensorPixelModesUsed,
int setId = CAMERA3_STREAM_SET_ID_INVALID,
bool useHalBufManager = false);
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index c6e7002..02b6585 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -49,7 +49,9 @@
camera_stream_type type,
uint32_t width, uint32_t height, size_t maxSize, int format,
android_dataspace dataSpace, camera_stream_rotation_t rotation,
- const String8& physicalCameraId, int setId, bool isMultiResolution) :
+ const String8& physicalCameraId,
+ const std::unordered_set<int32_t> &sensorPixelModesUsed,
+ int setId, bool isMultiResolution) :
camera_stream(),
mId(id),
mSetId(setId),
@@ -84,6 +86,7 @@
camera_stream::rotation = rotation;
camera_stream::max_buffers = 0;
camera_stream::physical_camera_id = mPhysicalCameraId.string();
+ camera_stream::sensor_pixel_modes_used = sensorPixelModesUsed;
if ((format == HAL_PIXEL_FORMAT_BLOB || format == HAL_PIXEL_FORMAT_RAW_OPAQUE) &&
maxSize == 0) {
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h
index 45d8478..5a364ab 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.h
+++ b/services/camera/libcameraservice/device3/Camera3Stream.h
@@ -498,7 +498,9 @@
Camera3Stream(int id, camera_stream_type type,
uint32_t width, uint32_t height, size_t maxSize, int format,
android_dataspace dataSpace, camera_stream_rotation_t rotation,
- const String8& physicalCameraId, int setId, bool isMultiResolution);
+ const String8& physicalCameraId,
+ const std::unordered_set<int32_t> &sensorPixelModesUsed,
+ int setId, bool isMultiResolution);
wp<Camera3StreamBufferFreedListener> mBufferFreedListener;
diff --git a/services/camera/libcameraservice/device3/Camera3StreamInterface.h b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
index a567cb4..ca80595 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamInterface.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
@@ -62,6 +62,8 @@
android_dataspace_t data_space;
camera_stream_rotation_t rotation;
const char* physical_camera_id;
+
+ std::unordered_set<int32_t> sensor_pixel_modes_used;
} camera_stream_t;
typedef struct camera_stream_buffer {
@@ -104,13 +106,15 @@
uint64_t consumerUsage;
bool finalized = false;
bool supportsOffline = false;
+ std::unordered_set<int32_t> sensorPixelModesUsed;
OutputStreamInfo() :
width(-1), height(-1), format(-1), dataSpace(HAL_DATASPACE_UNKNOWN),
consumerUsage(0) {}
OutputStreamInfo(int _width, int _height, int _format, android_dataspace _dataSpace,
- uint64_t _consumerUsage) :
+ uint64_t _consumerUsage, const std::unordered_set<int32_t>& _sensorPixelModesUsed) :
width(_width), height(_height), format(_format),
- dataSpace(_dataSpace), consumerUsage(_consumerUsage) {}
+ dataSpace(_dataSpace), consumerUsage(_consumerUsage),
+ sensorPixelModesUsed(_sensorPixelModesUsed) {}
};
/**
diff --git a/services/camera/libcameraservice/device3/DistortionMapper.cpp b/services/camera/libcameraservice/device3/DistortionMapper.cpp
index 316303e..89dd115 100644
--- a/services/camera/libcameraservice/device3/DistortionMapper.cpp
+++ b/services/camera/libcameraservice/device3/DistortionMapper.cpp
@@ -22,13 +22,14 @@
#include <cmath>
#include "device3/DistortionMapper.h"
+#include "utils/SessionConfigurationUtils.h"
namespace android {
namespace camera3 {
-DistortionMapper::DistortionMapper() : mValidMapping(false), mValidGrids(false) {
+DistortionMapper::DistortionMapper() {
initRemappedKeys();
}
@@ -61,41 +62,81 @@
status_t DistortionMapper::setupStaticInfo(const CameraMetadata &deviceInfo) {
std::lock_guard<std::mutex> lock(mMutex);
+ status_t res = setupStaticInfoLocked(deviceInfo, /*maxResolution*/false);
+ if (res != OK) {
+ return res;
+ }
+
+ bool mMaxResolution = SessionConfigurationUtils::isUltraHighResolutionSensor(deviceInfo);
+ if (mMaxResolution) {
+ res = setupStaticInfoLocked(deviceInfo, /*maxResolution*/true);
+ }
+ return res;
+}
+
+status_t DistortionMapper::setupStaticInfoLocked(const CameraMetadata &deviceInfo,
+ bool maxResolution) {
+ DistortionMapperInfo *mapperInfo = maxResolution ? &mDistortionMapperInfoMaximumResolution :
+ &mDistortionMapperInfo;
+
camera_metadata_ro_entry_t array;
- array = deviceInfo.find(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE);
+ array = deviceInfo.find(
+ SessionConfigurationUtils::getAppropriateModeTag(
+ ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE, maxResolution));
if (array.count != 4) return BAD_VALUE;
float arrayX = static_cast<float>(array.data.i32[0]);
float arrayY = static_cast<float>(array.data.i32[1]);
- mArrayWidth = static_cast<float>(array.data.i32[2]);
- mArrayHeight = static_cast<float>(array.data.i32[3]);
+ mapperInfo->mArrayWidth = static_cast<float>(array.data.i32[2]);
+ mapperInfo->mArrayHeight = static_cast<float>(array.data.i32[3]);
- array = deviceInfo.find(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE);
+ array = deviceInfo.find(
+ SessionConfigurationUtils::getAppropriateModeTag(
+ ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, maxResolution));
if (array.count != 4) return BAD_VALUE;
float activeX = static_cast<float>(array.data.i32[0]);
float activeY = static_cast<float>(array.data.i32[1]);
- mActiveWidth = static_cast<float>(array.data.i32[2]);
- mActiveHeight = static_cast<float>(array.data.i32[3]);
+ mapperInfo->mActiveWidth = static_cast<float>(array.data.i32[2]);
+ mapperInfo->mActiveHeight = static_cast<float>(array.data.i32[3]);
- mArrayDiffX = activeX - arrayX;
- mArrayDiffY = activeY - arrayY;
+ mapperInfo->mArrayDiffX = activeX - arrayX;
+ mapperInfo->mArrayDiffY = activeY - arrayY;
- return updateCalibration(deviceInfo);
+ return updateCalibration(deviceInfo, /*isStatic*/ true, maxResolution);
+}
+
+static bool doesSettingsHaveMaxResolution(const CameraMetadata *settings) {
+ if (settings == nullptr) {
+ return false;
+ }
+ // First we get the sensorPixelMode from the settings metadata.
+ camera_metadata_ro_entry sensorPixelModeEntry = settings->find(ANDROID_SENSOR_PIXEL_MODE);
+ if (sensorPixelModeEntry.count != 0) {
+ return (sensorPixelModeEntry.data.u8[0] == ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION);
+ }
+ return false;
}
bool DistortionMapper::calibrationValid() const {
std::lock_guard<std::mutex> lock(mMutex);
-
- return mValidMapping;
+ bool isValid = mDistortionMapperInfo.mValidMapping;
+ if (mMaxResolution) {
+ isValid = isValid && mDistortionMapperInfoMaximumResolution.mValidMapping;
+ }
+ return isValid;
}
status_t DistortionMapper::correctCaptureRequest(CameraMetadata *request) {
std::lock_guard<std::mutex> lock(mMutex);
status_t res;
- if (!mValidMapping) return OK;
+ bool maxResolution = doesSettingsHaveMaxResolution(request);
+ DistortionMapperInfo *mapperInfo = maxResolution ? &mDistortionMapperInfoMaximumResolution :
+ &mDistortionMapperInfo;
+
+ if (!mapperInfo->mValidMapping) return OK;
camera_metadata_entry_t e;
e = request->find(ANDROID_DISTORTION_CORRECTION_MODE);
@@ -107,27 +148,30 @@
if (weight == 0) {
continue;
}
- res = mapCorrectedToRaw(e.data.i32 + j, 2, /*clamp*/true);
+ res = mapCorrectedToRaw(e.data.i32 + j, 2, mapperInfo, /*clamp*/true);
if (res != OK) return res;
}
}
for (auto rect : kRectsToCorrect) {
e = request->find(rect);
- res = mapCorrectedRectToRaw(e.data.i32, e.count / 4, /*clamp*/true);
+ res = mapCorrectedRectToRaw(e.data.i32, e.count / 4, mapperInfo, /*clamp*/true);
if (res != OK) return res;
}
}
-
return OK;
}
status_t DistortionMapper::correctCaptureResult(CameraMetadata *result) {
std::lock_guard<std::mutex> lock(mMutex);
+
+ bool maxResolution = doesSettingsHaveMaxResolution(result);
+ DistortionMapperInfo *mapperInfo = maxResolution ? &mDistortionMapperInfoMaximumResolution :
+ &mDistortionMapperInfo;
status_t res;
- if (!mValidMapping) return OK;
+ if (!mapperInfo->mValidMapping) return OK;
- res = updateCalibration(*result);
+ res = updateCalibration(*result, /*isStatic*/ false, maxResolution);
if (res != OK) {
ALOGE("Failure to update lens calibration information");
return INVALID_OPERATION;
@@ -143,18 +187,18 @@
if (weight == 0) {
continue;
}
- res = mapRawToCorrected(e.data.i32 + j, 2, /*clamp*/true);
+ res = mapRawToCorrected(e.data.i32 + j, 2, mapperInfo, /*clamp*/true);
if (res != OK) return res;
}
}
for (auto rect : kRectsToCorrect) {
e = result->find(rect);
- res = mapRawRectToCorrected(e.data.i32, e.count / 4, /*clamp*/true);
+ res = mapRawRectToCorrected(e.data.i32, e.count / 4, mapperInfo, /*clamp*/true);
if (res != OK) return res;
}
for (auto pts : kResultPointsToCorrectNoClamp) {
e = result->find(pts);
- res = mapRawToCorrected(e.data.i32, e.count / 2, /*clamp*/false);
+ res = mapRawToCorrected(e.data.i32, e.count / 2, mapperInfo, /*clamp*/false);
if (res != OK) return res;
}
}
@@ -164,25 +208,37 @@
// Utility methods; not guarded by mutex
-status_t DistortionMapper::updateCalibration(const CameraMetadata &result) {
+status_t DistortionMapper::updateCalibration(const CameraMetadata &result, bool isStatic,
+ bool maxResolution) {
camera_metadata_ro_entry_t calib, distortion;
+ DistortionMapperInfo *mapperInfo =
+ maxResolution ? &mDistortionMapperInfoMaximumResolution : &mDistortionMapperInfo;
+ // We only need maximum resolution version of LENS_INTRINSIC_CALIBRATION and
+ // LENS_DISTORTION since CaptureResults would still use the same key
+ // regardless of sensor pixel mode.
+ int calibrationKey =
+ SessionConfigurationUtils::getAppropriateModeTag(ANDROID_LENS_INTRINSIC_CALIBRATION,
+ maxResolution && isStatic);
+ int distortionKey =
+ SessionConfigurationUtils::getAppropriateModeTag(ANDROID_LENS_DISTORTION,
+ maxResolution && isStatic);
- calib = result.find(ANDROID_LENS_INTRINSIC_CALIBRATION);
- distortion = result.find(ANDROID_LENS_DISTORTION);
+ calib = result.find(calibrationKey);
+ distortion = result.find(distortionKey);
if (calib.count != 5) return BAD_VALUE;
if (distortion.count != 5) return BAD_VALUE;
// Skip redoing work if no change to calibration fields
- if (mValidMapping &&
- mFx == calib.data.f[0] &&
- mFy == calib.data.f[1] &&
- mCx == calib.data.f[2] &&
- mCy == calib.data.f[3] &&
- mS == calib.data.f[4]) {
+ if (mapperInfo->mValidMapping &&
+ mapperInfo->mFx == calib.data.f[0] &&
+ mapperInfo->mFy == calib.data.f[1] &&
+ mapperInfo->mCx == calib.data.f[2] &&
+ mapperInfo->mCy == calib.data.f[3] &&
+ mapperInfo->mS == calib.data.f[4]) {
bool noChange = true;
for (size_t i = 0; i < distortion.count; i++) {
- if (mK[i] != distortion.data.f[i]) {
+ if (mapperInfo->mK[i] != distortion.data.f[i]) {
noChange = false;
break;
}
@@ -190,39 +246,39 @@
if (noChange) return OK;
}
- mFx = calib.data.f[0];
- mFy = calib.data.f[1];
- mCx = calib.data.f[2];
- mCy = calib.data.f[3];
- mS = calib.data.f[4];
+ mapperInfo->mFx = calib.data.f[0];
+ mapperInfo->mFy = calib.data.f[1];
+ mapperInfo->mCx = calib.data.f[2];
+ mapperInfo->mCy = calib.data.f[3];
+ mapperInfo->mS = calib.data.f[4];
- mInvFx = 1 / mFx;
- mInvFy = 1 / mFy;
+ mapperInfo->mInvFx = 1 / mapperInfo->mFx;
+ mapperInfo->mInvFy = 1 / mapperInfo->mFy;
for (size_t i = 0; i < distortion.count; i++) {
- mK[i] = distortion.data.f[i];
+ mapperInfo->mK[i] = distortion.data.f[i];
}
- mValidMapping = true;
+ mapperInfo->mValidMapping = true;
// Need to recalculate grid
- mValidGrids = false;
+ mapperInfo->mValidGrids = false;
return OK;
}
status_t DistortionMapper::mapRawToCorrected(int32_t *coordPairs, int coordCount,
- bool clamp, bool simple) {
- if (!mValidMapping) return INVALID_OPERATION;
+ DistortionMapperInfo *mapperInfo, bool clamp, bool simple) {
+ if (!mapperInfo->mValidMapping) return INVALID_OPERATION;
- if (simple) return mapRawToCorrectedSimple(coordPairs, coordCount, clamp);
+ if (simple) return mapRawToCorrectedSimple(coordPairs, coordCount, mapperInfo, clamp);
- if (!mValidGrids) {
- status_t res = buildGrids();
+ if (!mapperInfo->mValidGrids) {
+ status_t res = buildGrids(mapperInfo);
if (res != OK) return res;
}
for (int i = 0; i < coordCount * 2; i += 2) {
- const GridQuad *quad = findEnclosingQuad(coordPairs + i, mDistortedGrid);
+ const GridQuad *quad = findEnclosingQuad(coordPairs + i, mapperInfo->mDistortedGrid);
if (quad == nullptr) {
ALOGE("Raw to corrected mapping failure: No quad found for (%d, %d)",
*(coordPairs + i), *(coordPairs + i + 1));
@@ -258,8 +314,8 @@
// Clamp to within active array
if (clamp) {
- corrX = std::min(mActiveWidth - 1, std::max(0.f, corrX));
- corrY = std::min(mActiveHeight - 1, std::max(0.f, corrY));
+ corrX = std::min(mapperInfo->mActiveWidth - 1, std::max(0.f, corrX));
+ corrY = std::min(mapperInfo->mActiveHeight - 1, std::max(0.f, corrY));
}
coordPairs[i] = static_cast<int32_t>(std::round(corrX));
@@ -270,19 +326,19 @@
}
status_t DistortionMapper::mapRawToCorrectedSimple(int32_t *coordPairs, int coordCount,
- bool clamp) const {
- if (!mValidMapping) return INVALID_OPERATION;
+ const DistortionMapperInfo *mapperInfo, bool clamp) const {
+ if (!mapperInfo->mValidMapping) return INVALID_OPERATION;
- float scaleX = mActiveWidth / mArrayWidth;
- float scaleY = mActiveHeight / mArrayHeight;
+ float scaleX = mapperInfo->mActiveWidth / mapperInfo->mArrayWidth;
+ float scaleY = mapperInfo->mActiveHeight / mapperInfo->mArrayHeight;
for (int i = 0; i < coordCount * 2; i += 2) {
float x = coordPairs[i];
float y = coordPairs[i + 1];
float corrX = x * scaleX;
float corrY = y * scaleY;
if (clamp) {
- corrX = std::min(mActiveWidth - 1, std::max(0.f, corrX));
- corrY = std::min(mActiveHeight - 1, std::max(0.f, corrY));
+ corrX = std::min(mapperInfo->mActiveWidth - 1, std::max(0.f, corrX));
+ corrY = std::min(mapperInfo->mActiveHeight - 1, std::max(0.f, corrY));
}
coordPairs[i] = static_cast<int32_t>(std::round(corrX));
coordPairs[i + 1] = static_cast<int32_t>(std::round(corrY));
@@ -291,9 +347,9 @@
return OK;
}
-status_t DistortionMapper::mapRawRectToCorrected(int32_t *rects, int rectCount, bool clamp,
- bool simple) {
- if (!mValidMapping) return INVALID_OPERATION;
+status_t DistortionMapper::mapRawRectToCorrected(int32_t *rects, int rectCount,
+ DistortionMapperInfo *mapperInfo, bool clamp, bool simple) {
+ if (!mapperInfo->mValidMapping) return INVALID_OPERATION;
for (int i = 0; i < rectCount * 4; i += 4) {
// Map from (l, t, width, height) to (l, t, r, b)
int32_t coords[4] = {
@@ -303,7 +359,7 @@
rects[i + 1] + rects[i + 3] - 1
};
- mapRawToCorrected(coords, 2, clamp, simple);
+ mapRawToCorrected(coords, 2, mapperInfo, clamp, simple);
// Map back to (l, t, width, height)
rects[i] = coords[0];
@@ -315,60 +371,60 @@
return OK;
}
-status_t DistortionMapper::mapCorrectedToRaw(int32_t *coordPairs, int coordCount, bool clamp,
- bool simple) const {
- return mapCorrectedToRawImpl(coordPairs, coordCount, clamp, simple);
+status_t DistortionMapper::mapCorrectedToRaw(int32_t *coordPairs, int coordCount,
+ const DistortionMapperInfo *mapperInfo, bool clamp, bool simple) const {
+ return mapCorrectedToRawImpl(coordPairs, coordCount, mapperInfo, clamp, simple);
}
template<typename T>
-status_t DistortionMapper::mapCorrectedToRawImpl(T *coordPairs, int coordCount, bool clamp,
- bool simple) const {
- if (!mValidMapping) return INVALID_OPERATION;
+status_t DistortionMapper::mapCorrectedToRawImpl(T *coordPairs, int coordCount,
+ const DistortionMapperInfo *mapperInfo, bool clamp, bool simple) const {
+ if (!mapperInfo->mValidMapping) return INVALID_OPERATION;
- if (simple) return mapCorrectedToRawImplSimple(coordPairs, coordCount, clamp);
+ if (simple) return mapCorrectedToRawImplSimple(coordPairs, coordCount, mapperInfo, clamp);
- float activeCx = mCx - mArrayDiffX;
- float activeCy = mCy - mArrayDiffY;
+ float activeCx = mapperInfo->mCx - mapperInfo->mArrayDiffX;
+ float activeCy = mapperInfo->mCy - mapperInfo->mArrayDiffY;
for (int i = 0; i < coordCount * 2; i += 2) {
// Move to normalized space from active array space
- float ywi = (coordPairs[i + 1] - activeCy) * mInvFy;
- float xwi = (coordPairs[i] - activeCx - mS * ywi) * mInvFx;
+ float ywi = (coordPairs[i + 1] - activeCy) * mapperInfo->mInvFy;
+ float xwi = (coordPairs[i] - activeCx - mapperInfo->mS * ywi) * mapperInfo->mInvFx;
// Apply distortion model to calculate raw image coordinates
+ const std::array<float, 5> &kK = mapperInfo->mK;
float rSq = xwi * xwi + ywi * ywi;
- float Fr = 1.f + (mK[0] * rSq) + (mK[1] * rSq * rSq) + (mK[2] * rSq * rSq * rSq);
- float xc = xwi * Fr + (mK[3] * 2 * xwi * ywi) + mK[4] * (rSq + 2 * xwi * xwi);
- float yc = ywi * Fr + (mK[4] * 2 * xwi * ywi) + mK[3] * (rSq + 2 * ywi * ywi);
+ float Fr = 1.f + (kK[0] * rSq) + (kK[1] * rSq * rSq) + (kK[2] * rSq * rSq * rSq);
+ float xc = xwi * Fr + (kK[3] * 2 * xwi * ywi) + kK[4] * (rSq + 2 * xwi * xwi);
+ float yc = ywi * Fr + (kK[4] * 2 * xwi * ywi) + kK[3] * (rSq + 2 * ywi * ywi);
// Move back to image space
- float xr = mFx * xc + mS * yc + mCx;
- float yr = mFy * yc + mCy;
+ float xr = mapperInfo->mFx * xc + mapperInfo->mS * yc + mapperInfo->mCx;
+ float yr = mapperInfo->mFy * yc + mapperInfo->mCy;
// Clamp to within pre-correction active array
if (clamp) {
- xr = std::min(mArrayWidth - 1, std::max(0.f, xr));
- yr = std::min(mArrayHeight - 1, std::max(0.f, yr));
+ xr = std::min(mapperInfo->mArrayWidth - 1, std::max(0.f, xr));
+ yr = std::min(mapperInfo->mArrayHeight - 1, std::max(0.f, yr));
}
coordPairs[i] = static_cast<T>(std::round(xr));
coordPairs[i + 1] = static_cast<T>(std::round(yr));
}
-
return OK;
}
template<typename T>
status_t DistortionMapper::mapCorrectedToRawImplSimple(T *coordPairs, int coordCount,
- bool clamp) const {
- if (!mValidMapping) return INVALID_OPERATION;
+ const DistortionMapperInfo *mapperInfo, bool clamp) const {
+ if (!mapperInfo->mValidMapping) return INVALID_OPERATION;
- float scaleX = mArrayWidth / mActiveWidth;
- float scaleY = mArrayHeight / mActiveHeight;
+ float scaleX = mapperInfo->mArrayWidth / mapperInfo->mActiveWidth;
+ float scaleY = mapperInfo->mArrayHeight / mapperInfo->mActiveHeight;
for (int i = 0; i < coordCount * 2; i += 2) {
float x = coordPairs[i];
float y = coordPairs[i + 1];
float rawX = x * scaleX;
float rawY = y * scaleY;
if (clamp) {
- rawX = std::min(mArrayWidth - 1, std::max(0.f, rawX));
- rawY = std::min(mArrayHeight - 1, std::max(0.f, rawY));
+ rawX = std::min(mapperInfo->mArrayWidth - 1, std::max(0.f, rawX));
+ rawY = std::min(mapperInfo->mArrayHeight - 1, std::max(0.f, rawY));
}
coordPairs[i] = static_cast<T>(std::round(rawX));
coordPairs[i + 1] = static_cast<T>(std::round(rawY));
@@ -377,9 +433,9 @@
return OK;
}
-status_t DistortionMapper::mapCorrectedRectToRaw(int32_t *rects, int rectCount, bool clamp,
- bool simple) const {
- if (!mValidMapping) return INVALID_OPERATION;
+status_t DistortionMapper::mapCorrectedRectToRaw(int32_t *rects, int rectCount,
+ const DistortionMapperInfo *mapperInfo, bool clamp, bool simple) const {
+ if (!mapperInfo->mValidMapping) return INVALID_OPERATION;
for (int i = 0; i < rectCount * 4; i += 4) {
// Map from (l, t, width, height) to (l, t, r, b)
@@ -390,7 +446,7 @@
rects[i + 1] + rects[i + 3] - 1
};
- mapCorrectedToRaw(coords, 2, clamp, simple);
+ mapCorrectedToRaw(coords, 2, mapperInfo, clamp, simple);
// Map back to (l, t, width, height)
rects[i] = coords[0];
@@ -402,37 +458,37 @@
return OK;
}
-status_t DistortionMapper::buildGrids() {
- if (mCorrectedGrid.size() != kGridSize * kGridSize) {
- mCorrectedGrid.resize(kGridSize * kGridSize);
- mDistortedGrid.resize(kGridSize * kGridSize);
+status_t DistortionMapper::buildGrids(DistortionMapperInfo *mapperInfo) {
+ if (mapperInfo->mCorrectedGrid.size() != kGridSize * kGridSize) {
+ mapperInfo->mCorrectedGrid.resize(kGridSize * kGridSize);
+ mapperInfo->mDistortedGrid.resize(kGridSize * kGridSize);
}
- float gridMargin = mArrayWidth * kGridMargin;
- float gridSpacingX = (mArrayWidth + 2 * gridMargin) / kGridSize;
- float gridSpacingY = (mArrayHeight + 2 * gridMargin) / kGridSize;
+ float gridMargin = mapperInfo->mArrayWidth * kGridMargin;
+ float gridSpacingX = (mapperInfo->mArrayWidth + 2 * gridMargin) / kGridSize;
+ float gridSpacingY = (mapperInfo->mArrayHeight + 2 * gridMargin) / kGridSize;
size_t index = 0;
float x = -gridMargin;
for (size_t i = 0; i < kGridSize; i++, x += gridSpacingX) {
float y = -gridMargin;
for (size_t j = 0; j < kGridSize; j++, y += gridSpacingY, index++) {
- mCorrectedGrid[index].src = nullptr;
- mCorrectedGrid[index].coords = {
+ mapperInfo->mCorrectedGrid[index].src = nullptr;
+ mapperInfo->mCorrectedGrid[index].coords = {
x, y,
x + gridSpacingX, y,
x + gridSpacingX, y + gridSpacingY,
x, y + gridSpacingY
};
- mDistortedGrid[index].src = &mCorrectedGrid[index];
- mDistortedGrid[index].coords = mCorrectedGrid[index].coords;
- status_t res = mapCorrectedToRawImpl(mDistortedGrid[index].coords.data(), 4,
- /*clamp*/false, /*simple*/false);
+ mapperInfo->mDistortedGrid[index].src = &(mapperInfo->mCorrectedGrid[index]);
+ mapperInfo->mDistortedGrid[index].coords = mapperInfo->mCorrectedGrid[index].coords;
+ status_t res = mapCorrectedToRawImpl(mapperInfo->mDistortedGrid[index].coords.data(), 4,
+ mapperInfo, /*clamp*/false, /*simple*/false);
if (res != OK) return res;
}
}
- mValidGrids = true;
+ mapperInfo->mValidGrids = true;
return OK;
}
diff --git a/services/camera/libcameraservice/device3/DistortionMapper.h b/services/camera/libcameraservice/device3/DistortionMapper.h
index 5027bd0..96f4fda 100644
--- a/services/camera/libcameraservice/device3/DistortionMapper.h
+++ b/services/camera/libcameraservice/device3/DistortionMapper.h
@@ -37,13 +37,8 @@
DistortionMapper();
DistortionMapper(const DistortionMapper& other) :
- mValidMapping(other.mValidMapping), mValidGrids(other.mValidGrids),
- mFx(other.mFx), mFy(other.mFy), mCx(other.mCx), mCy(other.mCy), mS(other.mS),
- mInvFx(other.mInvFx), mInvFy(other.mInvFy), mK(other.mK),
- mArrayWidth(other.mArrayWidth), mArrayHeight(other.mArrayHeight),
- mActiveWidth(other.mActiveWidth), mActiveHeight(other.mActiveHeight),
- mArrayDiffX(other.mArrayDiffX), mArrayDiffY(other.mArrayDiffY),
- mCorrectedGrid(other.mCorrectedGrid), mDistortedGrid(other.mDistortedGrid) {
+ mDistortionMapperInfo(other.mDistortionMapperInfo),
+ mDistortionMapperInfoMaximumResolution(other.mDistortionMapperInfoMaximumResolution) {
initRemappedKeys(); }
void initRemappedKeys() override;
@@ -75,10 +70,14 @@
public: // Visible for testing. Not guarded by mutex; do not use concurrently
+
+ struct DistortionMapperInfo;
+
/**
* Update lens calibration from capture results or equivalent
*/
- status_t updateCalibration(const CameraMetadata &result);
+ status_t updateCalibration(const CameraMetadata &result, bool isStatic = false,
+ bool maxResolution = false);
/**
* Transform from distorted (original) to corrected (warped) coordinates.
@@ -89,8 +88,8 @@
* clamp: Whether to clamp the result to the bounds of the active array
* simple: Whether to do complex correction or just a simple linear map
*/
- status_t mapRawToCorrected(int32_t *coordPairs, int coordCount, bool clamp,
- bool simple = true);
+ status_t mapRawToCorrected(int32_t *coordPairs, int coordCount,
+ DistortionMapperInfo *mapperInfo, bool clamp, bool simple = true);
/**
* Transform from distorted (original) to corrected (warped) coordinates.
@@ -101,8 +100,8 @@
* clamp: Whether to clamp the result to the bounds of the active array
* simple: Whether to do complex correction or just a simple linear map
*/
- status_t mapRawRectToCorrected(int32_t *rects, int rectCount, bool clamp,
- bool simple = true);
+ status_t mapRawRectToCorrected(int32_t *rects, int rectCount,
+ DistortionMapperInfo *mapperInfo, bool clamp, bool simple = true);
/**
* Transform from corrected (warped) to distorted (original) coordinates.
@@ -113,8 +112,8 @@
* clamp: Whether to clamp the result to the bounds of the precorrection active array
* simple: Whether to do complex correction or just a simple linear map
*/
- status_t mapCorrectedToRaw(int32_t* coordPairs, int coordCount, bool clamp,
- bool simple = true) const;
+ status_t mapCorrectedToRaw(int32_t* coordPairs, int coordCount,
+ const DistortionMapperInfo *mapperInfo, bool clamp, bool simple = true) const;
/**
* Transform from corrected (warped) to distorted (original) coordinates.
@@ -125,8 +124,8 @@
* clamp: Whether to clamp the result to the bounds of the precorrection active array
* simple: Whether to do complex correction or just a simple linear map
*/
- status_t mapCorrectedRectToRaw(int32_t *rects, int rectCount, bool clamp,
- bool simple = true) const;
+ status_t mapCorrectedRectToRaw(int32_t *rects, int rectCount,
+ const DistortionMapperInfo *mapperInfo, bool clamp, bool simple = true) const;
struct GridQuad {
// Source grid quad, or null
@@ -136,6 +135,28 @@
std::array<float, 8> coords;
};
+ struct DistortionMapperInfo {
+ bool mValidMapping = false;
+ bool mValidGrids = false;
+
+ // intrisic parameters, in pixels
+ float mFx, mFy, mCx, mCy, mS;
+ // pre-calculated inverses for speed
+ float mInvFx, mInvFy;
+ // radial/tangential distortion parameters
+ std::array<float, 5> mK;
+
+ // pre-correction active array dimensions
+ float mArrayWidth, mArrayHeight;
+ // active array dimensions
+ float mActiveWidth, mActiveHeight;
+ // corner offsets between pre-correction and active arrays
+ float mArrayDiffX, mArrayDiffY;
+
+ std::vector<GridQuad> mCorrectedGrid;
+ std::vector<GridQuad> mDistortedGrid;
+ };
+
// Find which grid quad encloses the point; returns null if none do
static const GridQuad* findEnclosingQuad(
const int32_t pt[2], const std::vector<GridQuad>& grid);
@@ -153,6 +174,11 @@
// if it is false, then an interpolation coordinate for edges E14 and E23 is found.
static float calculateUorV(const int32_t pt[2], const GridQuad& quad, bool calculateU);
+ DistortionMapperInfo *getMapperInfo(bool maxResolution = false) {
+ return maxResolution ? &mDistortionMapperInfoMaximumResolution :
+ &mDistortionMapperInfo;
+ };
+
private:
mutable std::mutex mMutex;
@@ -163,39 +189,28 @@
// Fuzziness for float inequality tests
constexpr static float kFloatFuzz = 1e-4;
+ bool mMaxResolution = false;
+
+ status_t setupStaticInfoLocked(const CameraMetadata &deviceInfo, bool maxResolution);
+
// Single implementation for various mapCorrectedToRaw methods
template<typename T>
- status_t mapCorrectedToRawImpl(T* coordPairs, int coordCount, bool clamp, bool simple) const;
+ status_t mapCorrectedToRawImpl(T* coordPairs, int coordCount,
+ const DistortionMapperInfo *mapperInfo, bool clamp, bool simple) const;
// Simple linear interpolation option
template<typename T>
- status_t mapCorrectedToRawImplSimple(T* coordPairs, int coordCount, bool clamp) const;
+ status_t mapCorrectedToRawImplSimple(T* coordPairs, int coordCount,
+ const DistortionMapperInfo *mapperInfo, bool clamp) const;
- status_t mapRawToCorrectedSimple(int32_t *coordPairs, int coordCount, bool clamp) const;
+ status_t mapRawToCorrectedSimple(int32_t *coordPairs, int coordCount,
+ const DistortionMapperInfo *mapperInfo, bool clamp) const;
// Utility to create reverse mapping grids
- status_t buildGrids();
+ status_t buildGrids(DistortionMapperInfo *mapperInfo);
-
- bool mValidMapping;
- bool mValidGrids;
-
- // intrisic parameters, in pixels
- float mFx, mFy, mCx, mCy, mS;
- // pre-calculated inverses for speed
- float mInvFx, mInvFy;
- // radial/tangential distortion parameters
- std::array<float, 5> mK;
-
- // pre-correction active array dimensions
- float mArrayWidth, mArrayHeight;
- // active array dimensions
- float mActiveWidth, mActiveHeight;
- // corner offsets between pre-correction and active arrays
- float mArrayDiffX, mArrayDiffY;
-
- std::vector<GridQuad> mCorrectedGrid;
- std::vector<GridQuad> mDistortedGrid;
+ DistortionMapperInfo mDistortionMapperInfo;
+ DistortionMapperInfo mDistortionMapperInfoMaximumResolution;
}; // class DistortionMapper
diff --git a/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp b/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp
index 1bc2081..1a39510 100644
--- a/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp
+++ b/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp
@@ -20,6 +20,7 @@
#include <algorithm>
#include "device3/ZoomRatioMapper.h"
+#include "utils/SessionConfigurationUtils.h"
namespace android {
@@ -128,43 +129,120 @@
return OK;
}
+static bool getArrayWidthAndHeight(const CameraMetadata *deviceInfo,
+ int32_t arrayTag, int32_t *width, int32_t *height) {
+ if (width == nullptr || height == nullptr) {
+ ALOGE("%s: width / height nullptr", __FUNCTION__);
+ return false;
+ }
+ camera_metadata_ro_entry_t entry;
+ entry = deviceInfo->find(arrayTag);
+ if (entry.count != 4) return false;
+ *width = entry.data.i32[2];
+ *height = entry.data.i32[3];
+ return true;
+}
+
ZoomRatioMapper::ZoomRatioMapper(const CameraMetadata* deviceInfo,
bool supportNativeZoomRatio, bool usePrecorrectArray) {
initRemappedKeys();
- camera_metadata_ro_entry_t entry;
+ int32_t arrayW = 0;
+ int32_t arrayH = 0;
+ int32_t arrayMaximumResolutionW = 0;
+ int32_t arrayMaximumResolutionH = 0;
+ int32_t activeW = 0;
+ int32_t activeH = 0;
+ int32_t activeMaximumResolutionW = 0;
+ int32_t activeMaximumResolutionH = 0;
- entry = deviceInfo->find(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE);
- if (entry.count != 4) return;
- int32_t arrayW = entry.data.i32[2];
- int32_t arrayH = entry.data.i32[3];
+ if (!getArrayWidthAndHeight(deviceInfo, ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE,
+ &arrayW, &arrayH)) {
+ ALOGE("%s: Couldn't get pre correction active array size", __FUNCTION__);
+ return;
+ }
+ if (!getArrayWidthAndHeight(deviceInfo, ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
+ &activeW, &activeH)) {
+ ALOGE("%s: Couldn't get active array size", __FUNCTION__);
+ return;
+ }
- entry = deviceInfo->find(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE);
- if (entry.count != 4) return;
- int32_t activeW = entry.data.i32[2];
- int32_t activeH = entry.data.i32[3];
+ bool isUltraHighResolutionSensor =
+ camera3::SessionConfigurationUtils::isUltraHighResolutionSensor(*deviceInfo);
+ if (isUltraHighResolutionSensor) {
+ if (!getArrayWidthAndHeight(deviceInfo,
+ ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION,
+ &arrayMaximumResolutionW, &arrayMaximumResolutionH)) {
+ ALOGE("%s: Couldn't get maximum resolution pre correction active array size",
+ __FUNCTION__);
+ return;
+ }
+ if (!getArrayWidthAndHeight(deviceInfo,
+ ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION,
+ &activeMaximumResolutionW, &activeMaximumResolutionH)) {
+ ALOGE("%s: Couldn't get maximum resolution pre correction active array size",
+ __FUNCTION__);
+ return;
+ }
+ }
if (usePrecorrectArray) {
mArrayWidth = arrayW;
mArrayHeight = arrayH;
+ mArrayWidthMaximumResolution = arrayMaximumResolutionW;
+ mArrayHeightMaximumResolution = arrayMaximumResolutionH;
} else {
mArrayWidth = activeW;
mArrayHeight = activeH;
+ mArrayWidthMaximumResolution = activeMaximumResolutionW;
+ mArrayHeightMaximumResolution = activeMaximumResolutionH;
}
mHalSupportsZoomRatio = supportNativeZoomRatio;
- ALOGV("%s: array size: %d x %d, mHalSupportsZoomRatio %d",
- __FUNCTION__, mArrayWidth, mArrayHeight, mHalSupportsZoomRatio);
+ ALOGV("%s: array size: %d x %d, full res array size: %d x %d, mHalSupportsZoomRatio %d",
+ __FUNCTION__, mArrayWidth, mArrayHeight, mArrayWidthMaximumResolution,
+ mArrayHeightMaximumResolution, mHalSupportsZoomRatio);
mIsValid = true;
}
+status_t ZoomRatioMapper::getArrayDimensionsToBeUsed(const CameraMetadata *settings,
+ int32_t *arrayWidth, int32_t *arrayHeight) {
+ if (settings == nullptr || arrayWidth == nullptr || arrayHeight == nullptr) {
+ return BAD_VALUE;
+ }
+ // First we get the sensorPixelMode from the settings metadata.
+ int32_t sensorPixelMode = ANDROID_SENSOR_PIXEL_MODE_DEFAULT;
+ camera_metadata_ro_entry sensorPixelModeEntry = settings->find(ANDROID_SENSOR_PIXEL_MODE);
+ if (sensorPixelModeEntry.count != 0) {
+ sensorPixelMode = sensorPixelModeEntry.data.u8[0];
+ if (sensorPixelMode != ANDROID_SENSOR_PIXEL_MODE_DEFAULT &&
+ sensorPixelMode != ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) {
+ ALOGE("%s: Request sensor pixel mode is not one of the valid values %d",
+ __FUNCTION__, sensorPixelMode);
+ return BAD_VALUE;
+ }
+ }
+ if (sensorPixelMode == ANDROID_SENSOR_PIXEL_MODE_DEFAULT) {
+ *arrayWidth = mArrayWidth;
+ *arrayHeight = mArrayHeight;
+ } else {
+ *arrayWidth = mArrayWidthMaximumResolution;
+ *arrayHeight = mArrayHeightMaximumResolution;
+ }
+ return OK;
+}
+
status_t ZoomRatioMapper::updateCaptureRequest(CameraMetadata* request) {
if (!mIsValid) return INVALID_OPERATION;
status_t res = OK;
bool zoomRatioIs1 = true;
camera_metadata_entry_t entry;
-
+ int arrayHeight, arrayWidth = 0;
+ res = getArrayDimensionsToBeUsed(request, &arrayWidth, &arrayHeight);
+ if (res != OK) {
+ return res;
+ }
entry = request->find(ANDROID_CONTROL_ZOOM_RATIO);
if (entry.count == 1 && entry.data.f[0] != 1.0f) {
zoomRatioIs1 = false;
@@ -174,19 +252,19 @@
if (cropRegionEntry.count == 4) {
int cropWidth = cropRegionEntry.data.i32[2];
int cropHeight = cropRegionEntry.data.i32[3];
- if (cropWidth < mArrayWidth && cropHeight < mArrayHeight) {
+ if (cropWidth < arrayWidth && cropHeight < arrayHeight) {
cropRegionEntry.data.i32[0] = 0;
cropRegionEntry.data.i32[1] = 0;
- cropRegionEntry.data.i32[2] = mArrayWidth;
- cropRegionEntry.data.i32[3] = mArrayHeight;
+ cropRegionEntry.data.i32[2] = arrayWidth;
+ cropRegionEntry.data.i32[3] = arrayHeight;
}
}
}
if (mHalSupportsZoomRatio && zoomRatioIs1) {
- res = separateZoomFromCropLocked(request, false/*isResult*/);
+ res = separateZoomFromCropLocked(request, false/*isResult*/, arrayWidth, arrayHeight);
} else if (!mHalSupportsZoomRatio && !zoomRatioIs1) {
- res = combineZoomAndCropLocked(request, false/*isResult*/);
+ res = combineZoomAndCropLocked(request, false/*isResult*/, arrayWidth, arrayHeight);
}
// If CONTROL_ZOOM_RATIO is in request, but HAL doesn't support
@@ -203,10 +281,15 @@
status_t res = OK;
+ int arrayHeight, arrayWidth = 0;
+ res = getArrayDimensionsToBeUsed(result, &arrayWidth, &arrayHeight);
+ if (res != OK) {
+ return res;
+ }
if (mHalSupportsZoomRatio && requestedZoomRatioIs1) {
- res = combineZoomAndCropLocked(result, true/*isResult*/);
+ res = combineZoomAndCropLocked(result, true/*isResult*/, arrayWidth, arrayHeight);
} else if (!mHalSupportsZoomRatio && !requestedZoomRatioIs1) {
- res = separateZoomFromCropLocked(result, true/*isResult*/);
+ res = separateZoomFromCropLocked(result, true/*isResult*/, arrayWidth, arrayHeight);
} else {
camera_metadata_entry_t entry = result->find(ANDROID_CONTROL_ZOOM_RATIO);
if (entry.count == 0) {
@@ -218,16 +301,22 @@
return res;
}
-float ZoomRatioMapper::deriveZoomRatio(const CameraMetadata* metadata) {
+status_t ZoomRatioMapper::deriveZoomRatio(const CameraMetadata* metadata, float *zoomRatioRet,
+ int arrayWidth, int arrayHeight) {
+ if (metadata == nullptr || zoomRatioRet == nullptr) {
+ return BAD_VALUE;
+ }
float zoomRatio = 1.0;
camera_metadata_ro_entry_t entry;
entry = metadata->find(ANDROID_SCALER_CROP_REGION);
- if (entry.count != 4) return zoomRatio;
-
+ if (entry.count != 4) {
+ *zoomRatioRet = 1;
+ return OK;
+ }
// Center of the preCorrection/active size
- float arrayCenterX = mArrayWidth / 2.0;
- float arrayCenterY = mArrayHeight / 2.0;
+ float arrayCenterX = arrayWidth / 2.0;
+ float arrayCenterY = arrayHeight / 2.0;
// Re-map crop region to coordinate system centered to (arrayCenterX,
// arrayCenterY).
@@ -237,22 +326,30 @@
float cropRegionBottom = entry.data.i32[1] + entry.data.i32[3] - arrayCenterY;
// Calculate the scaling factor for left, top, bottom, right
- float zoomRatioLeft = std::max(mArrayWidth / (2 * cropRegionLeft), 1.0f);
- float zoomRatioTop = std::max(mArrayHeight / (2 * cropRegionTop), 1.0f);
- float zoomRatioRight = std::max(mArrayWidth / (2 * cropRegionRight), 1.0f);
- float zoomRatioBottom = std::max(mArrayHeight / (2 * cropRegionBottom), 1.0f);
+ float zoomRatioLeft = std::max(arrayWidth / (2 * cropRegionLeft), 1.0f);
+ float zoomRatioTop = std::max(arrayHeight / (2 * cropRegionTop), 1.0f);
+ float zoomRatioRight = std::max(arrayWidth / (2 * cropRegionRight), 1.0f);
+ float zoomRatioBottom = std::max(arrayHeight / (2 * cropRegionBottom), 1.0f);
// Use minimum scaling factor to handle letterboxing or pillarboxing
zoomRatio = std::min(std::min(zoomRatioLeft, zoomRatioRight),
std::min(zoomRatioTop, zoomRatioBottom));
ALOGV("%s: derived zoomRatio is %f", __FUNCTION__, zoomRatio);
- return zoomRatio;
+ *zoomRatioRet = zoomRatio;
+ return OK;
}
-status_t ZoomRatioMapper::separateZoomFromCropLocked(CameraMetadata* metadata, bool isResult) {
- status_t res;
- float zoomRatio = deriveZoomRatio(metadata);
+status_t ZoomRatioMapper::separateZoomFromCropLocked(CameraMetadata* metadata, bool isResult,
+ int arrayWidth, int arrayHeight) {
+ float zoomRatio = 1.0;
+ status_t res = deriveZoomRatio(metadata, &zoomRatio, arrayWidth, arrayHeight);
+
+ if (res != OK) {
+ ALOGE("%s: Failed to derive zoom ratio: %s(%d)",
+ __FUNCTION__, strerror(-res), res);
+ return res;
+ }
// Update zoomRatio metadata tag
res = metadata->update(ANDROID_CONTROL_ZOOM_RATIO, &zoomRatio, 1);
@@ -272,12 +369,14 @@
continue;
}
// Top left (inclusive)
- scaleCoordinates(entry.data.i32 + j, 1, zoomRatio, true /*clamp*/);
+ scaleCoordinates(entry.data.i32 + j, 1, zoomRatio, true /*clamp*/, arrayWidth,
+ arrayHeight);
// Bottom right (exclusive): Use adjacent inclusive pixel to
// calculate.
entry.data.i32[j+2] -= 1;
entry.data.i32[j+3] -= 1;
- scaleCoordinates(entry.data.i32 + j + 2, 1, zoomRatio, true /*clamp*/);
+ scaleCoordinates(entry.data.i32 + j + 2, 1, zoomRatio, true /*clamp*/, arrayWidth,
+ arrayHeight);
entry.data.i32[j+2] += 1;
entry.data.i32[j+3] += 1;
}
@@ -285,20 +384,22 @@
for (auto rect : kRectsToCorrect) {
entry = metadata->find(rect);
- scaleRects(entry.data.i32, entry.count / 4, zoomRatio);
+ scaleRects(entry.data.i32, entry.count / 4, zoomRatio, arrayWidth, arrayHeight);
}
if (isResult) {
for (auto pts : kResultPointsToCorrectNoClamp) {
entry = metadata->find(pts);
- scaleCoordinates(entry.data.i32, entry.count / 2, zoomRatio, false /*clamp*/);
+ scaleCoordinates(entry.data.i32, entry.count / 2, zoomRatio, false /*clamp*/,
+ arrayWidth, arrayHeight);
}
}
return OK;
}
-status_t ZoomRatioMapper::combineZoomAndCropLocked(CameraMetadata* metadata, bool isResult) {
+status_t ZoomRatioMapper::combineZoomAndCropLocked(CameraMetadata* metadata, bool isResult,
+ int arrayWidth, int arrayHeight) {
float zoomRatio = 1.0f;
camera_metadata_entry_t entry;
entry = metadata->find(ANDROID_CONTROL_ZOOM_RATIO);
@@ -307,7 +408,6 @@
}
// Unscale regions with zoomRatio
- status_t res;
for (auto region : kMeteringRegionsToCorrect) {
entry = metadata->find(region);
for (size_t j = 0; j < entry.count; j += 5) {
@@ -316,29 +416,32 @@
continue;
}
// Top-left (inclusive)
- scaleCoordinates(entry.data.i32 + j, 1, 1.0 / zoomRatio, true /*clamp*/);
+ scaleCoordinates(entry.data.i32 + j, 1, 1.0 / zoomRatio, true /*clamp*/, arrayWidth,
+ arrayHeight);
// Bottom-right (exclusive): Use adjacent inclusive pixel to
// calculate.
entry.data.i32[j+2] -= 1;
entry.data.i32[j+3] -= 1;
- scaleCoordinates(entry.data.i32 + j + 2, 1, 1.0 / zoomRatio, true /*clamp*/);
+ scaleCoordinates(entry.data.i32 + j + 2, 1, 1.0 / zoomRatio, true /*clamp*/, arrayWidth,
+ arrayHeight);
entry.data.i32[j+2] += 1;
entry.data.i32[j+3] += 1;
}
}
for (auto rect : kRectsToCorrect) {
entry = metadata->find(rect);
- scaleRects(entry.data.i32, entry.count / 4, 1.0 / zoomRatio);
+ scaleRects(entry.data.i32, entry.count / 4, 1.0 / zoomRatio, arrayWidth, arrayHeight);
}
if (isResult) {
for (auto pts : kResultPointsToCorrectNoClamp) {
entry = metadata->find(pts);
- scaleCoordinates(entry.data.i32, entry.count / 2, 1.0 / zoomRatio, false /*clamp*/);
+ scaleCoordinates(entry.data.i32, entry.count / 2, 1.0 / zoomRatio, false /*clamp*/,
+ arrayWidth, arrayHeight);
}
}
zoomRatio = 1.0;
- res = metadata->update(ANDROID_CONTROL_ZOOM_RATIO, &zoomRatio, 1);
+ status_t res = metadata->update(ANDROID_CONTROL_ZOOM_RATIO, &zoomRatio, 1);
if (res != OK) {
return res;
}
@@ -347,7 +450,7 @@
}
void ZoomRatioMapper::scaleCoordinates(int32_t* coordPairs, int coordCount,
- float scaleRatio, bool clamp) {
+ float scaleRatio, bool clamp, int32_t arrayWidth, int32_t arrayHeight) {
// A pixel's coordinate is represented by the position of its top-left corner.
// To avoid the rounding error, we use the coordinate for the center of the
// pixel instead:
@@ -360,18 +463,18 @@
for (int i = 0; i < coordCount * 2; i += 2) {
float x = coordPairs[i];
float y = coordPairs[i + 1];
- float xCentered = x - (mArrayWidth - 2) / 2;
- float yCentered = y - (mArrayHeight - 2) / 2;
+ float xCentered = x - (arrayWidth - 2) / 2;
+ float yCentered = y - (arrayHeight - 2) / 2;
float scaledX = xCentered * scaleRatio;
float scaledY = yCentered * scaleRatio;
- scaledX += (mArrayWidth - 2) / 2;
- scaledY += (mArrayHeight - 2) / 2;
+ scaledX += (arrayWidth - 2) / 2;
+ scaledY += (arrayHeight - 2) / 2;
coordPairs[i] = static_cast<int32_t>(std::round(scaledX));
coordPairs[i+1] = static_cast<int32_t>(std::round(scaledY));
// Clamp to within activeArray/preCorrectionActiveArray
if (clamp) {
- int32_t right = mArrayWidth - 1;
- int32_t bottom = mArrayHeight - 1;
+ int32_t right = arrayWidth - 1;
+ int32_t bottom = arrayHeight - 1;
coordPairs[i] =
std::min(right, std::max(0, coordPairs[i]));
coordPairs[i+1] =
@@ -382,7 +485,7 @@
}
void ZoomRatioMapper::scaleRects(int32_t* rects, int rectCount,
- float scaleRatio) {
+ float scaleRatio, int32_t arrayWidth, int32_t arrayHeight) {
for (int i = 0; i < rectCount * 4; i += 4) {
// Map from (l, t, width, height) to (l, t, l+width-1, t+height-1),
// where both top-left and bottom-right are inclusive.
@@ -394,9 +497,9 @@
};
// top-left
- scaleCoordinates(coords, 1, scaleRatio, true /*clamp*/);
+ scaleCoordinates(coords, 1, scaleRatio, true /*clamp*/, arrayWidth, arrayHeight);
// bottom-right
- scaleCoordinates(coords+2, 1, scaleRatio, true /*clamp*/);
+ scaleCoordinates(coords+2, 1, scaleRatio, true /*clamp*/, arrayWidth, arrayHeight);
// Map back to (l, t, width, height)
rects[i] = coords[0];
diff --git a/services/camera/libcameraservice/device3/ZoomRatioMapper.h b/services/camera/libcameraservice/device3/ZoomRatioMapper.h
index 3769299..b7a9e41 100644
--- a/services/camera/libcameraservice/device3/ZoomRatioMapper.h
+++ b/services/camera/libcameraservice/device3/ZoomRatioMapper.h
@@ -68,22 +68,31 @@
public: // Visible for testing. Do not use concurently.
void scaleCoordinates(int32_t* coordPairs, int coordCount,
- float scaleRatio, bool clamp);
+ float scaleRatio, bool clamp, int32_t arrayWidth, int32_t arrayHeight);
bool isValid() { return mIsValid; }
private:
// const after construction
bool mHalSupportsZoomRatio;
- // active array / pre-correction array dimension
+
+ // active array / pre-correction array dimension for default and maximum
+ // resolution modes.
int32_t mArrayWidth, mArrayHeight;
+ int32_t mArrayWidthMaximumResolution, mArrayHeightMaximumResolution;
bool mIsValid = false;
- float deriveZoomRatio(const CameraMetadata* metadata);
- void scaleRects(int32_t* rects, int rectCount, float scaleRatio);
+ status_t deriveZoomRatio(const CameraMetadata* metadata, float *zoomRatio, int arrayWidth,
+ int arrayHeight);
+ void scaleRects(int32_t* rects, int rectCount, float scaleRatio, int32_t arrayWidth,
+ int32_t arrayHeight);
- status_t separateZoomFromCropLocked(CameraMetadata* metadata, bool isResult);
- status_t combineZoomAndCropLocked(CameraMetadata* metadata, bool isResult);
+ status_t separateZoomFromCropLocked(CameraMetadata* metadata, bool isResult, int arrayWidth,
+ int arrayHeight);
+ status_t combineZoomAndCropLocked(CameraMetadata* metadata, bool isResult, int arrayWidth,
+ int arrayHeight);
+ status_t getArrayDimensionsToBeUsed(const CameraMetadata *settings, int32_t *arrayWidth,
+ int32_t *arrayHeight);
};
} // namespace camera3