From 1b639e5f00871d952ee89088893c5c1143a44e15 Mon Sep 17 00:00:00 2001 From: Shuzhen Wang Date: Fri, 9 Apr 2021 17:27:37 -0700 Subject: [PATCH] Camera: Add new hidden tag for multiResolutionStream support This addresses the ambiguity when a physical camera backs more than one logical camera, and only one of the logical cameras support multi-resolution streams. Address couple of TODOs on handling interactions between multiResolution streams and ultra high resolution camera. Test: Camera CTS, VTS Bug: 184663916 Change-Id: I370f35bc8e25649134e1a1ba38db0f3ece3b3f1e --- .../camera2/CameraCharacteristics.java | 27 +++++++++++++++++ .../hardware/camera2/CameraManager.java | 30 ++++++++++++++----- .../camera2/MultiResolutionImageReader.java | 14 +++++++-- .../camera2/impl/CameraMetadataNative.java | 5 +++- .../camera2/params/InputConfiguration.java | 1 - .../camera2/params/OutputConfiguration.java | 5 +++- 6 files changed, 70 insertions(+), 12 deletions(-) diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java index 6654c2c710497..1cf8e9cc302f8 100644 --- a/core/java/android/hardware/camera2/CameraCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraCharacteristics.java @@ -3165,6 +3165,33 @@ public final class CameraCharacteristics extends CameraMetadata SCALER_MANDATORY_MAXIMUM_RESOLUTION_STREAM_COMBINATIONS = new Key("android.scaler.mandatoryMaximumResolutionStreamCombinations", android.hardware.camera2.params.MandatoryStreamCombination[].class); + /** + *

Whether the camera device supports multi-resolution input or output streams

+ *

A logical multi-camera or an ultra high resolution camera may support multi-resolution + * input or output streams. With multi-resolution output streams, the camera device is able + * to output different resolution images depending on the current active physical camera or + * pixel mode. With multi-resolution input streams, the camera device can reprocess images + * of different resolutions from different physical cameras or sensor pixel modes.

+ *

When set to TRUE: + * * For a logical multi-camera, the camera framework derives + * {@link CameraCharacteristics#SCALER_MULTI_RESOLUTION_STREAM_CONFIGURATION_MAP android.scaler.multiResolutionStreamConfigurationMap} by combining the + * android.scaler.physicalCameraMultiResolutionStreamConfigurations from its physical + * cameras. + * * For an ultra-high resolution sensor camera, the camera framework directly copies + * the value of android.scaler.physicalCameraMultiResolutionStreamConfigurations to + * {@link CameraCharacteristics#SCALER_MULTI_RESOLUTION_STREAM_CONFIGURATION_MAP android.scaler.multiResolutionStreamConfigurationMap}.

+ *

Optional - The value for this key may be {@code null} on some devices.

+ *

Limited capability - + * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the + * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key

+ * + * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL + * @see CameraCharacteristics#SCALER_MULTI_RESOLUTION_STREAM_CONFIGURATION_MAP + * @hide + */ + public static final Key SCALER_MULTI_RESOLUTION_STREAM_SUPPORTED = + new Key("android.scaler.multiResolutionStreamSupported", boolean.class); + /** *

The area of the image sensor which corresponds to active pixels after any geometric * distortion correction has been applied.

diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java index c1009ffb38140..651f02591b4d0 100644 --- a/core/java/android/hardware/camera2/CameraManager.java +++ b/core/java/android/hardware/camera2/CameraManager.java @@ -379,17 +379,36 @@ public final class CameraManager { *

For a logical multi-camera, query the map between physical camera id and * the physical camera's multi-resolution stream configuration. This map is in turn * combined to form the logical camera's multi-resolution stream configuration map.

+ * + *

For an ultra high resolution camera, directly use + * android.scaler.physicalCameraMultiResolutionStreamConfigurations as the camera device's + * multi-resolution stream configuration map.

*/ private Map getPhysicalCameraMultiResolutionConfigs( - CameraMetadataNative info, ICameraService cameraService) + String cameraId, CameraMetadataNative info, ICameraService cameraService) throws CameraAccessException { HashMap multiResolutionStreamConfigurations = new HashMap(); + Boolean multiResolutionStreamSupported = info.get( + CameraCharacteristics.SCALER_MULTI_RESOLUTION_STREAM_SUPPORTED); + if (multiResolutionStreamSupported == null || !multiResolutionStreamSupported) { + return multiResolutionStreamConfigurations; + } + // Query the characteristics of all physical sub-cameras, and combine the multi-resolution - // stream configurations. Note that framework derived formats such as HEIC and DEPTH_JPEG - // aren't supported as multi-resolution input or output formats. + // stream configurations. Alternatively, for ultra-high resolution camera, direclty use + // its multi-resolution stream configurations. Note that framework derived formats such as + // HEIC and DEPTH_JPEG aren't supported as multi-resolution input or output formats. Set physicalCameraIds = info.getPhysicalCameraIds(); + if (physicalCameraIds.size() == 0 && info.isUltraHighResolutionSensor()) { + StreamConfiguration[] configs = info.get(CameraCharacteristics. + SCALER_PHYSICAL_CAMERA_MULTI_RESOLUTION_STREAM_CONFIGURATIONS); + if (configs != null) { + multiResolutionStreamConfigurations.put(cameraId, configs); + } + return multiResolutionStreamConfigurations; + } try { for (String physicalCameraId : physicalCameraIds) { CameraMetadataNative physicalCameraInfo = @@ -401,9 +420,6 @@ public final class CameraManager { multiResolutionStreamConfigurations.put(physicalCameraId, configs); } } - - // TODO: If this is an ultra high resolution sensor camera, combine the multi-resolution - // stream combination from "info" as well. } catch (RemoteException e) { ServiceSpecificException sse = new ServiceSpecificException( ICameraService.ERROR_DISCONNECTED, @@ -468,7 +484,7 @@ public final class CameraManager { info.setDisplaySize(displaySize); Map multiResolutionSizeMap = - getPhysicalCameraMultiResolutionConfigs(info, cameraService); + getPhysicalCameraMultiResolutionConfigs(cameraId, info, cameraService); if (multiResolutionSizeMap.size() > 0) { info.setMultiResolutionStreamConfigurationMap(multiResolutionSizeMap); } diff --git a/core/java/android/hardware/camera2/MultiResolutionImageReader.java b/core/java/android/hardware/camera2/MultiResolutionImageReader.java index bb3d91dbc65ca..3af1b5b03d35b 100644 --- a/core/java/android/hardware/camera2/MultiResolutionImageReader.java +++ b/core/java/android/hardware/camera2/MultiResolutionImageReader.java @@ -265,8 +265,18 @@ public class MultiResolutionImageReader implements AutoCloseable { * @return a {@link Surface} to use as the target for a capture request. */ public @NonNull Surface getSurface() { - //TODO: Pick the surface from the reader for default mode stream. - return mReaders[0].getSurface(); + // Pick the surface of smallest size. This is necessary for an ultra high resolution + // camera not to default to maximum resolution pixel mode. + int minReaderSize = mReaders[0].getWidth() * mReaders[0].getHeight(); + Surface candidateSurface = mReaders[0].getSurface(); + for (int i = 1; i < mReaders.length; i++) { + int readerSize = mReaders[i].getWidth() * mReaders[i].getHeight(); + if (readerSize < minReaderSize) { + minReaderSize = readerSize; + candidateSurface = mReaders[i].getSurface(); + } + } + return candidateSurface; } /** diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java index aa84b024f69d3..2e841f50e84dd 100644 --- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java +++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java @@ -1322,7 +1322,10 @@ public class CameraMetadataNative implements Parcelable { return ret; } - private boolean isUltraHighResolutionSensor() { + /** + * @hide + */ + public boolean isUltraHighResolutionSensor() { return isCapabilitySupported( CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR); diff --git a/core/java/android/hardware/camera2/params/InputConfiguration.java b/core/java/android/hardware/camera2/params/InputConfiguration.java index d63683feed9b0..8dfc0a7b41ca8 100644 --- a/core/java/android/hardware/camera2/params/InputConfiguration.java +++ b/core/java/android/hardware/camera2/params/InputConfiguration.java @@ -90,7 +90,6 @@ public final class InputConfiguration { public InputConfiguration(@NonNull Collection multiResolutionInputs, @Format int format) { checkCollectionNotEmpty(multiResolutionInputs, "Input multi-resolution stream info"); - //TODO: Pick the default mode stream info for ultra-high resolution sensor camera MultiResolutionStreamInfo info = multiResolutionInputs.iterator().next(); mWidth = info.getWidth(); mHeight = info.getHeight(); diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java index 84736dc73ad60..0662f160a0098 100644 --- a/core/java/android/hardware/camera2/params/OutputConfiguration.java +++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java @@ -353,7 +353,10 @@ public final class OutputConfiguration implements Parcelable { config.setPhysicalCameraId(streamInfo.getPhysicalCameraId()); config.setMultiResolutionOutput(); configs.add(config); - // TODO: Set sensor pixel mode for ultra high resolution sensor camera. + + // No need to call addSensorPixelModeUsed for ultra high resolution sensor camera, + // because regular and max resolution output configurations are used for DEFAULT mode + // and MAX_RESOLUTION mode respectively by default. } return configs;