Merge "camera: Add crop and metering region correction for max resolution requests." into sc-dev am: 2a7630de12 am: a4cead956d
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/av/+/15301357
Change-Id: I397a9aab9a3b12fb4d72b855bc7956358aba2755
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index c28c24b..26562e0 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -83,6 +83,7 @@
"device3/Camera3OutputStreamInterface.cpp",
"device3/Camera3OutputUtils.cpp",
"device3/Camera3DeviceInjectionMethods.cpp",
+ "device3/UHRCropAndMeteringRegionMapper.cpp",
"gui/RingBufferConsumer.cpp",
"hidl/AidlCameraDeviceCallbacks.cpp",
"hidl/AidlCameraServiceListener.cpp",
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index ef727aa..877b683 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -171,6 +171,13 @@
mZoomRatioMappers[physicalId] = ZoomRatioMapper(
&mPhysicalDeviceInfoMap[physicalId],
mSupportNativeZoomRatio, usePrecorrectArray);
+
+ if (SessionConfigurationUtils::isUltraHighResolutionSensor(
+ mPhysicalDeviceInfoMap[physicalId])) {
+ mUHRCropAndMeteringRegionMappers[physicalId] =
+ UHRCropAndMeteringRegionMapper(mPhysicalDeviceInfoMap[physicalId],
+ usePrecorrectArray);
+ }
}
}
@@ -348,6 +355,11 @@
mZoomRatioMappers[mId.c_str()] = ZoomRatioMapper(&mDeviceInfo,
mSupportNativeZoomRatio, usePrecorrectArray);
+ if (SessionConfigurationUtils::isUltraHighResolutionSensor(mDeviceInfo)) {
+ mUHRCropAndMeteringRegionMappers[mId.c_str()] =
+ UHRCropAndMeteringRegionMapper(mDeviceInfo, usePrecorrectArray);
+ }
+
if (RotateAndCropMapper::isNeeded(&mDeviceInfo)) {
mRotateAndCropMappers.emplace(mId.c_str(), &mDeviceInfo);
}
@@ -4826,12 +4838,33 @@
}
{
- // Correct metadata regions for distortion correction if enabled
sp<Camera3Device> parent = mParent.promote();
if (parent != nullptr) {
List<PhysicalCameraSettings>::iterator it;
for (it = captureRequest->mSettingsList.begin();
it != captureRequest->mSettingsList.end(); it++) {
+ if (parent->mUHRCropAndMeteringRegionMappers.find(it->cameraId) ==
+ parent->mUHRCropAndMeteringRegionMappers.end()) {
+ continue;
+ }
+
+ if (!captureRequest->mUHRCropAndMeteringRegionsUpdated) {
+ res = parent->mUHRCropAndMeteringRegionMappers[it->cameraId].
+ updateCaptureRequest(&(it->metadata));
+ if (res != OK) {
+ SET_ERR("RequestThread: Unable to correct capture requests "
+ "for scaler crop region and metering regions for request "
+ "%d: %s (%d)", halRequest->frame_number, strerror(-res),
+ res);
+ return INVALID_OPERATION;
+ }
+ captureRequest->mUHRCropAndMeteringRegionsUpdated = true;
+ }
+ }
+
+ // Correct metadata regions for distortion correction if enabled
+ for (it = captureRequest->mSettingsList.begin();
+ it != captureRequest->mSettingsList.end(); it++) {
if (parent->mDistortionMappers.find(it->cameraId) ==
parent->mDistortionMappers.end()) {
continue;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index e67777d..310ee27 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -50,6 +50,7 @@
#include "device3/DistortionMapper.h"
#include "device3/ZoomRatioMapper.h"
#include "device3/RotateAndCropMapper.h"
+#include "device3/UHRCropAndMeteringRegionMapper.h"
#include "device3/InFlightRequest.h"
#include "device3/Camera3OutputInterface.h"
#include "device3/Camera3OfflineSession.h"
@@ -589,6 +590,9 @@
bool mRotationAndCropUpdated = false;
// Whether this capture request's zoom ratio update has been done.
bool mZoomRatioUpdated = false;
+ // Whether this max resolution capture request's crop / metering region update has been
+ // done.
+ bool mUHRCropAndMeteringRegionsUpdated = false;
};
typedef List<sp<CaptureRequest> > RequestList;
@@ -1224,6 +1228,12 @@
std::unordered_map<std::string, camera3::ZoomRatioMapper> mZoomRatioMappers;
/**
+ * UHR request crop / metering region mapper support
+ */
+ std::unordered_map<std::string, camera3::UHRCropAndMeteringRegionMapper>
+ mUHRCropAndMeteringRegionMappers;
+
+ /**
* RotateAndCrop mapper support
*/
std::unordered_map<std::string, camera3::RotateAndCropMapper> mRotateAndCropMappers;
diff --git a/services/camera/libcameraservice/device3/UHRCropAndMeteringRegionMapper.cpp b/services/camera/libcameraservice/device3/UHRCropAndMeteringRegionMapper.cpp
new file mode 100644
index 0000000..c558d91
--- /dev/null
+++ b/services/camera/libcameraservice/device3/UHRCropAndMeteringRegionMapper.cpp
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Camera3-UHRCropAndMeteringRegionMapper"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+//#define LOG_NDEBUG 0
+
+#include <algorithm>
+#include <cmath>
+
+#include "device3/UHRCropAndMeteringRegionMapper.h"
+#include "utils/SessionConfigurationUtils.h"
+
+namespace android {
+
+namespace camera3 {
+// For Capture request
+// metering region -> {fwk private key for metering region set, true}
+static std::unordered_map<uint32_t, std::pair<uint32_t, uint32_t>> kMeteringRegionsToCorrect = {
+ {ANDROID_CONTROL_AF_REGIONS,
+ {ANDROID_CONTROL_AF_REGIONS_SET, ANDROID_CONTROL_AF_REGIONS_SET_TRUE}},
+ {ANDROID_CONTROL_AE_REGIONS,
+ {ANDROID_CONTROL_AE_REGIONS_SET, ANDROID_CONTROL_AE_REGIONS_SET_TRUE}},
+ {ANDROID_CONTROL_AWB_REGIONS,
+ {ANDROID_CONTROL_AWB_REGIONS_SET, ANDROID_CONTROL_AWB_REGIONS_SET_TRUE}}
+};
+
+UHRCropAndMeteringRegionMapper::UHRCropAndMeteringRegionMapper(const CameraMetadata &deviceInfo,
+ bool usePreCorrectedArray) {
+
+ if (usePreCorrectedArray) {
+ if (!SessionConfigurationUtils::getArrayWidthAndHeight(&deviceInfo,
+ ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE, &mArrayWidth,
+ &mArrayHeight)) {
+ ALOGE("%s: Couldn't get pre correction active array size", __FUNCTION__);
+ return;
+ }
+ if (!SessionConfigurationUtils::getArrayWidthAndHeight(&deviceInfo,
+ ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION,
+ &mArrayWidthMaximumResolution, &mArrayHeightMaximumResolution)) {
+ ALOGE("%s: Couldn't get maximum resolution pre correction active array size",
+ __FUNCTION__);
+ return;
+ }
+ } else {
+ if (!SessionConfigurationUtils::getArrayWidthAndHeight(&deviceInfo,
+ ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, &mArrayWidth,
+ &mArrayHeight)) {
+ ALOGE("%s: Couldn't get active array size", __FUNCTION__);
+ return;
+ }
+ if (!SessionConfigurationUtils::getArrayWidthAndHeight(&deviceInfo,
+ ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION,
+ &mArrayWidthMaximumResolution, &mArrayHeightMaximumResolution)) {
+ ALOGE("%s: Couldn't get maximum resolution active array size", __FUNCTION__);
+ return;
+ }
+
+ }
+
+ mIsValid = true;
+
+ ALOGV("%s: array size: %d x %d, full res array size: %d x %d,",
+ __FUNCTION__, mArrayWidth, mArrayHeight, mArrayWidthMaximumResolution,
+ mArrayHeightMaximumResolution);
+}
+
+void UHRCropAndMeteringRegionMapper::fixMeteringRegionsIfNeeded(CameraMetadata *request) {
+ if (request == nullptr) {
+ ALOGE("%s request is nullptr, can't fix crop region", __FUNCTION__);
+ return;
+ }
+ for (const auto &entry : kMeteringRegionsToCorrect) {
+ // Check if the metering region Set key is set to TRUE, we don't
+ // need to correct the metering regions.
+ camera_metadata_entry meteringRegionsSetEntry =
+ request->find(entry.second.first);
+ if (meteringRegionsSetEntry.count == 1 &&
+ meteringRegionsSetEntry.data.u8[0] == entry.second.second) {
+ // metering region set by client, doesn't need to be fixed.
+ continue;
+ }
+ camera_metadata_entry meteringRegionEntry = request->find(entry.first);
+ if (meteringRegionEntry.count % 5 != 0) {
+ ALOGE("%s: Metering region entry for tag %d does not have a valid number of entries, "
+ "skipping", __FUNCTION__, (int)entry.first);
+ continue;
+ }
+ for (size_t j = 0; j < meteringRegionEntry.count; j += 5) {
+ int32_t *meteringRegionStart = meteringRegionEntry.data.i32 + j;
+ meteringRegionStart[0] = 0;
+ meteringRegionStart[1] = 0;
+ meteringRegionStart[2] = mArrayWidthMaximumResolution;
+ meteringRegionStart[3] = mArrayHeightMaximumResolution;
+ }
+ }
+}
+
+void UHRCropAndMeteringRegionMapper::fixCropRegionsIfNeeded(CameraMetadata *request) {
+ if (request == nullptr) {
+ ALOGE("%s request is nullptr, can't fix crop region", __FUNCTION__);
+ return;
+ }
+ // Check if the scalerCropRegionSet key is set to TRUE, we don't
+ // need to correct the crop region.
+ camera_metadata_entry cropRegionSetEntry =
+ request->find(ANDROID_SCALER_CROP_REGION_SET);
+ if (cropRegionSetEntry.count == 1 &&
+ cropRegionSetEntry.data.u8[0] == ANDROID_SCALER_CROP_REGION_SET_TRUE) {
+ // crop regions set by client, doesn't need to be fixed.
+ return;
+ }
+ camera_metadata_entry_t cropRegionEntry = request->find(ANDROID_SCALER_CROP_REGION);
+ if (cropRegionEntry.count == 4) {
+ cropRegionEntry.data.i32[0] = 0;
+ cropRegionEntry.data.i32[1] = 0;
+ cropRegionEntry.data.i32[2] = mArrayWidthMaximumResolution;
+ cropRegionEntry.data.i32[3] = mArrayHeightMaximumResolution;
+ }
+}
+
+status_t UHRCropAndMeteringRegionMapper::updateCaptureRequest(CameraMetadata* request) {
+ if (request == nullptr) {
+ ALOGE("%s Invalid request, request is nullptr", __FUNCTION__);
+ return BAD_VALUE;
+ }
+ if (!mIsValid) {
+ ALOGE("%s UHRCropAndMeteringRegionMapper didn't initialize correctly", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+
+ camera_metadata_entry sensorPixelModeEntry = request->find(ANDROID_SENSOR_PIXEL_MODE);
+
+ // Check if this is max resolution capture, if not, we don't need to do
+ // anything.
+ if (sensorPixelModeEntry.count != 0) {
+ int32_t sensorPixelMode = sensorPixelModeEntry.data.u8[0];
+ if (sensorPixelMode != ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) {
+ // Correction not needed for default mode requests.
+ return OK;
+ }
+ } else {
+ // sensor pixel mode not set -> default sensor pixel mode request, which
+ // doesn't need correction.
+ return OK;
+ }
+
+ fixCropRegionsIfNeeded(request);
+ fixMeteringRegionsIfNeeded(request);
+ return OK;
+}
+
+} // namespace camera3
+
+} // namespace android
diff --git a/services/camera/libcameraservice/device3/UHRCropAndMeteringRegionMapper.h b/services/camera/libcameraservice/device3/UHRCropAndMeteringRegionMapper.h
new file mode 100644
index 0000000..a026e6d
--- /dev/null
+++ b/services/camera/libcameraservice/device3/UHRCropAndMeteringRegionMapper.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SERVERS_UHRCROP_REGIONS_MAPPER_H
+#define ANDROID_SERVERS_UHRCROP_REGIONS_MAPPER_H
+
+#include <utils/Errors.h>
+#include <array>
+
+#include "camera/CameraMetadata.h"
+
+namespace android {
+
+namespace camera3 {
+
+/**
+ * Utilities to transform SCALER_CROP_REGION and metering regions for ultra high
+ * resolution sensors.
+ */
+class UHRCropAndMeteringRegionMapper {
+ public:
+ UHRCropAndMeteringRegionMapper() = default;
+ UHRCropAndMeteringRegionMapper(const CameraMetadata &deviceInfo, bool usePreCorrectionArray);
+
+ /**
+ * Adjust capture request assuming rotate and crop AUTO is enabled
+ */
+ status_t updateCaptureRequest(CameraMetadata *request);
+
+ private:
+
+ void fixCropRegionsIfNeeded(CameraMetadata *request);
+ void fixMeteringRegionsIfNeeded(CameraMetadata *request);
+
+ int32_t mArrayWidth = 0;
+ int32_t mArrayHeight = 0;
+ int32_t mArrayWidthMaximumResolution = 0;
+ int32_t mArrayHeightMaximumResolution = 0;
+ bool mIsValid = false;
+}; // class UHRCropAndMeteringRegionMapper
+
+} // namespace camera3
+
+} // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp b/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp
index 1a39510..7ec0956 100644
--- a/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp
+++ b/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp
@@ -129,20 +129,6 @@
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();
@@ -156,13 +142,13 @@
int32_t activeMaximumResolutionW = 0;
int32_t activeMaximumResolutionH = 0;
- if (!getArrayWidthAndHeight(deviceInfo, ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE,
- &arrayW, &arrayH)) {
+ if (!SessionConfigurationUtils::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)) {
+ if (!SessionConfigurationUtils::getArrayWidthAndHeight(deviceInfo,
+ ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, &activeW, &activeH)) {
ALOGE("%s: Couldn't get active array size", __FUNCTION__);
return;
}
@@ -170,14 +156,14 @@
bool isUltraHighResolutionSensor =
camera3::SessionConfigurationUtils::isUltraHighResolutionSensor(*deviceInfo);
if (isUltraHighResolutionSensor) {
- if (!getArrayWidthAndHeight(deviceInfo,
+ if (!SessionConfigurationUtils::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,
+ if (!SessionConfigurationUtils::getArrayWidthAndHeight(deviceInfo,
ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION,
&activeMaximumResolutionW, &activeMaximumResolutionH)) {
ALOGE("%s: Couldn't get maximum resolution pre correction active array size",
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
index 454c05f..c1fcfb8 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
@@ -169,6 +169,19 @@
return -1;
}
+bool SessionConfigurationUtils::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;
+}
StreamConfigurationPair
SessionConfigurationUtils::getStreamConfigurationPair(const CameraMetadata &staticInfo) {
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
index 1fbaa69..192e241 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
@@ -85,6 +85,9 @@
android_dataspace dataSpace, const CameraMetadata& info, bool maxResolution,
/*out*/int32_t* outWidth, /*out*/int32_t* outHeight);
+ static bool getArrayWidthAndHeight(const CameraMetadata *deviceInfo, int32_t arrayTag,
+ int32_t *width, int32_t *height);
+
//check if format is not custom format
static bool isPublicFormat(int32_t format);