diff --git a/core/api/current.txt b/core/api/current.txt index d6fa24d21d720..c4807bf304ef6 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -17378,6 +17378,7 @@ package android.hardware.camera2 { field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key SCALER_DEFAULT_SECURE_IMAGE_SIZE; field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key SCALER_MANDATORY_CONCURRENT_STREAM_COMBINATIONS; field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key SCALER_MANDATORY_MAXIMUM_RESOLUTION_STREAM_COMBINATIONS; + field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key SCALER_MANDATORY_PREVIEW_STABILIZATION_OUTPUT_STREAM_COMBINATIONS; field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key SCALER_MANDATORY_STREAM_COMBINATIONS; field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key SCALER_MANDATORY_TEN_BIT_OUTPUT_STREAM_COMBINATIONS; field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key SCALER_MANDATORY_USE_CASE_STREAM_COMBINATIONS; diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java index a06566c240198..524fe795cb75c 100644 --- a/core/java/android/hardware/camera2/CameraCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraCharacteristics.java @@ -3454,6 +3454,30 @@ public final class CameraCharacteristics extends CameraMetadata SCALER_MANDATORY_TEN_BIT_OUTPUT_STREAM_COMBINATIONS = new Key("android.scaler.mandatoryTenBitOutputStreamCombinations", android.hardware.camera2.params.MandatoryStreamCombination[].class); + /** + *

An array of mandatory stream combinations which are applicable when device lists + * {@code PREVIEW_STABILIZATION} in {@link CameraCharacteristics#CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES android.control.availableVideoStabilizationModes}. + * This is an app-readable conversion of the maximum resolution mandatory stream combination + * {@link android.hardware.camera2.CameraDevice#createCaptureSession tables}.

+ *

The array of + * {@link android.hardware.camera2.params.MandatoryStreamCombination combinations} is + * generated according to the documented + * {@link android.hardware.camera2.CameraDevice#createCaptureSession guideline} for each + * device which supports {@code PREVIEW_STABILIZATION} + * Clients can use the array as a quick reference to find an appropriate camera stream + * combination. + * The mandatory stream combination array will be {@code null} in case the device does not + * list {@code PREVIEW_STABILIZATION} in {@link CameraCharacteristics#CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES android.control.availableVideoStabilizationModes}.

+ *

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

+ * + * @see CameraCharacteristics#CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES + */ + @PublicKey + @NonNull + @SyntheticKey + public static final Key SCALER_MANDATORY_PREVIEW_STABILIZATION_OUTPUT_STREAM_COMBINATIONS = + new Key("android.scaler.mandatoryPreviewStabilizationOutputStreamCombinations", 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 diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java index 1a42eaf541cad..8f42b1f6f3556 100644 --- a/core/java/android/hardware/camera2/CameraDevice.java +++ b/core/java/android/hardware/camera2/CameraDevice.java @@ -883,6 +883,27 @@ public abstract class CameraDevice implements AutoCloseable { *
*

* + *

For devices where {@link CameraCharacteristics#CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES} + * includes {@link CameraMetadata#CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION}, + * the following stream combinations are guaranteed, + * for CaptureRequests where {@link CaptureRequest#CONTROL_VIDEO_STABILIZATION_MODE} is set to + * {@link CameraMetadata#CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION}

+ * + * + * + * + * + * + * + *
Preview stabilization guaranteed stream configurations
Target 1Target 2Sample use case(s)
TypeMax sizeTypeMax size
{@code PRIV / YUV}{@code RECORD} Stabilized preview, GPU video processing, or no-preview stabilized video recording.
{@code PRIV / YUV}{@code PREVIEW} {@code JPEG / YUV}{@code MAXIMUM }Standard still imaging with stabilized preview.
{@code PRIV / YUV}{@code PREVIEW} {@code PRIV / YUV}{@code RECORD }High-resolution recording with stabilized preview and recording stream.

+ *

+ * For the maximum size column, PREVIEW refers to the best size match to the device's screen + * resolution, or to 1080p (1920x1080), whichever is smaller. RECORD refers to the camera + * device's maximum supported recording resolution, as determined by + * {@link android.media.CamcorderProfile}. MAXIMUM refers to the camera device's maximum output + * resolution for that format or target from {@link StreamConfigurationMap#getOutputSizes(int)}. + *

+ * *

Since the capabilities of camera devices vary greatly, a given camera device may support * target combinations with sizes outside of these guarantees, but this can only be tested for * by calling {@link #isSessionConfigurationSupported} or attempting to create a session with diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java index 9b67633fe72bb..4fb496d66fbdd 100644 --- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java +++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java @@ -334,6 +334,7 @@ public class CameraMetadataNative implements Parcelable { private static final int MANDATORY_STREAM_CONFIGURATIONS_CONCURRENT = 2; private static final int MANDATORY_STREAM_CONFIGURATIONS_10BIT = 3; private static final int MANDATORY_STREAM_CONFIGURATIONS_USE_CASE = 4; + private static final int MANDATORY_STREAM_CONFIGURATIONS_PREVIEW_STABILIZATION = 5; private static String translateLocationProviderToProcess(final String provider) { if (provider == null) { @@ -709,6 +710,15 @@ public class CameraMetadataNative implements Parcelable { return (T) metadata.getMandatoryUseCaseStreamCombinations(); } }); + sGetCommandMap.put( + CameraCharacteristics.SCALER_MANDATORY_PREVIEW_STABILIZATION_OUTPUT_STREAM_COMBINATIONS.getNativeKey(), + new GetCommand() { + @Override + @SuppressWarnings("unchecked") + public T getValue(CameraMetadataNative metadata, Key key) { + return (T) metadata.getMandatoryPreviewStabilizationStreamCombinations(); + } + }); sGetCommandMap.put( CameraCharacteristics.CONTROL_MAX_REGIONS_AE.getNativeKey(), new GetCommand() { @@ -1400,6 +1410,24 @@ public class CameraMetadataNative implements Parcelable { CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE); } + private boolean isPreviewStabilizationSupported() { + boolean ret = false; + + int[] videoStabilizationModes = + getBase(CameraCharacteristics.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES); + if (videoStabilizationModes == null) { + return false; + } + for (int mode : videoStabilizationModes) { + if (mode == CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION) { + ret = true; + break; + } + } + + return ret; + } + private MandatoryStreamCombination[] getMandatoryStreamCombinationsHelper( int mandatoryStreamsType) { int[] capabilities = getBase(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES); @@ -1411,7 +1439,7 @@ public class CameraMetadataNative implements Parcelable { int hwLevel = getBase(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL); MandatoryStreamCombination.Builder build = new MandatoryStreamCombination.Builder( mCameraId, hwLevel, mDisplaySize, caps, getStreamConfigurationMap(), - getStreamConfigurationMapMaximumResolution()); + getStreamConfigurationMapMaximumResolution(), isPreviewStabilizationSupported()); List combs = null; switch (mandatoryStreamsType) { @@ -1427,6 +1455,9 @@ public class CameraMetadataNative implements Parcelable { case MANDATORY_STREAM_CONFIGURATIONS_USE_CASE: combs = build.getAvailableMandatoryStreamUseCaseCombinations(); break; + case MANDATORY_STREAM_CONFIGURATIONS_PREVIEW_STABILIZATION: + combs = build.getAvailableMandatoryPreviewStabilizedStreamCombinations(); + break; default: combs = build.getAvailableMandatoryStreamCombinations(); } @@ -1464,6 +1495,11 @@ public class CameraMetadataNative implements Parcelable { return getMandatoryStreamCombinationsHelper(MANDATORY_STREAM_CONFIGURATIONS_USE_CASE); } + private MandatoryStreamCombination[] getMandatoryPreviewStabilizationStreamCombinations() { + return getMandatoryStreamCombinationsHelper( + MANDATORY_STREAM_CONFIGURATIONS_PREVIEW_STABILIZATION); + } + private StreamConfigurationMap getStreamConfigurationMap() { StreamConfiguration[] configurations = getBase( CameraCharacteristics.SCALER_AVAILABLE_STREAM_CONFIGURATIONS); diff --git a/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java b/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java index 0d93c985b7931..8c0dcfcf06934 100644 --- a/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java +++ b/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java @@ -1262,6 +1262,50 @@ public final class MandatoryStreamCombination { "Preview, in-application image processing, and YUV still image capture"), }; + private static StreamCombinationTemplate sPreviewStabilizedStreamCombinations[] = { + // 1 stream combinations + new StreamCombinationTemplate(new StreamTemplate [] { + new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.RECORD)}, + "Stabilized preview, GPU video processing, or no-preview stabilized recording"), + new StreamCombinationTemplate(new StreamTemplate [] { + new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.RECORD)}, + "Stabilized preview, GPU video processing, or no-preview stabilized recording"), + //2 stream combinations + new StreamCombinationTemplate(new StreamTemplate [] { + new StreamTemplate(ImageFormat.JPEG, SizeThreshold.MAXIMUM), + new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.PREVIEW)}, + "Standard JPEG still imaging with stabilized preview"), + new StreamCombinationTemplate(new StreamTemplate [] { + new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.MAXIMUM), + new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.PREVIEW)}, + "Standard YUV still imaging with stabilized preview"), + new StreamCombinationTemplate(new StreamTemplate [] { + new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.MAXIMUM), + new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.PREVIEW)}, + "Standard YUV still imaging with stabilized in-app image processing stream"), + new StreamCombinationTemplate(new StreamTemplate [] { + new StreamTemplate(ImageFormat.JPEG, SizeThreshold.MAXIMUM), + new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.PREVIEW)}, + "Standard JPEG still imaging with stabilized in-app image processing stream"), + + new StreamCombinationTemplate(new StreamTemplate [] { + new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.RECORD), + new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.PREVIEW)}, + "High-resolution video recording with preview both streams stabilized"), + new StreamCombinationTemplate(new StreamTemplate [] { + new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.RECORD), + new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.PREVIEW)}, + "High-resolution video recording with preview both streams stabilized"), + new StreamCombinationTemplate(new StreamTemplate [] { + new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.RECORD), + new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.PREVIEW)}, + "High-resolution video recording with preview both streams stabilized"), + new StreamCombinationTemplate(new StreamTemplate [] { + new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.RECORD), + new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.PREVIEW)}, + "High-resolution video recording with preview both streams stabilized"), + }; + /** * Helper builder class to generate a list of available mandatory stream combinations. * @hide @@ -1273,6 +1317,7 @@ public final class MandatoryStreamCombination { private StreamConfigurationMap mStreamConfigMap; private StreamConfigurationMap mStreamConfigMapMaximumResolution; private boolean mIsHiddenPhysicalCamera; + private boolean mIsPreviewStabilizationSupported; private final Size kPreviewSizeBound = new Size(1920, 1088); @@ -1289,7 +1334,7 @@ public final class MandatoryStreamCombination { */ public Builder(int cameraId, int hwLevel, @NonNull Size displaySize, @NonNull List capabilities, @NonNull StreamConfigurationMap sm, - StreamConfigurationMap smMaxResolution) { + StreamConfigurationMap smMaxResolution, boolean previewStabilization) { mCameraId = cameraId; mDisplaySize = displaySize; mCapabilities = capabilities; @@ -1298,24 +1343,12 @@ public final class MandatoryStreamCombination { mHwLevel = hwLevel; mIsHiddenPhysicalCamera = CameraManager.isHiddenPhysicalCamera(Integer.toString(mCameraId)); + mIsPreviewStabilizationSupported = previewStabilization; } - /** - * Retrieve a list of all available mandatory 10-bit output capable stream combinations. - * - * @return a non-modifiable list of supported mandatory 10-bit capable stream combinations, - * null in case device is not 10-bit output capable. - */ - public @NonNull List - getAvailableMandatory10BitStreamCombinations() { - // Since 10-bit streaming support is optional, we mandate these stream - // combinations regardless of camera device capabilities. - - StreamCombinationTemplate []chosenStreamCombinations = s10BitOutputStreamCombinations; - if (!is10BitOutputSupported()) { - Log.v(TAG, "Device is not able to output 10-bit!"); - return null; - } + private @Nullable List + getAvailableMandatoryStreamCombinationsInternal( + StreamCombinationTemplate []chosenStreamCombinations, boolean s10Bit) { HashMap, List> availableSizes = enumerateAvailableSizes(); @@ -1334,7 +1367,7 @@ public final class MandatoryStreamCombination { Pair pair; pair = new Pair<>(template.mSizeThreshold, new Integer(template.mFormat)); sizes = availableSizes.get(pair); - if (template.mFormat == ImageFormat.YCBCR_P010) { + if (s10Bit && template.mFormat == ImageFormat.YCBCR_P010) { // Make sure that exactly the same 10 and 8-bit YUV streams sizes are // supported pair = new Pair<>(template.mSizeThreshold, @@ -1354,7 +1387,8 @@ public final class MandatoryStreamCombination { streamInfo = new MandatoryStreamInformation(sizes, template.mFormat, isMaximumSize, /*isInput*/ false, /*isUltraHighResolution*/ false, - /*is10BitCapable*/ template.mFormat != ImageFormat.JPEG); + /*is10BitCapable*/ s10Bit ? template.mFormat != ImageFormat.JPEG : + false); } catch (IllegalArgumentException e) { Log.e(TAG, "No available sizes found for format: " + template.mFormat + " size threshold: " + template.mSizeThreshold + " combination: " + @@ -1380,6 +1414,52 @@ public final class MandatoryStreamCombination { return Collections.unmodifiableList(availableStreamCombinations); } + /** + * Retrieve a list of all available mandatory stream combinations for devices supporting + * preview stabilization. + * + * @return a non-modifiable list of supported mandatory stream combinations on which + * preview stabilization is supported., + * null in case device is not 10-bit output capable. + */ + public @Nullable List + getAvailableMandatoryPreviewStabilizedStreamCombinations() { + // Since preview stabilization support is optional, we mandate these stream + // combinations regardless of camera device capabilities. + + StreamCombinationTemplate []chosenStreamCombinations = + sPreviewStabilizedStreamCombinations; + + if (mIsPreviewStabilizationSupported) { + Log.v(TAG, "Device does not support preview stabilization"); + return null; + } + + return getAvailableMandatoryStreamCombinationsInternal(chosenStreamCombinations, + /*10bit*/false); + } + + + /** + * Retrieve a list of all available mandatory 10-bit output capable stream combinations. + * + * @return a non-modifiable list of supported mandatory 10-bit capable stream combinations, + * null in case device is not 10-bit output capable. + */ + public @Nullable List + getAvailableMandatory10BitStreamCombinations() { + // Since 10-bit streaming support is optional, we mandate these stream + // combinations regardless of camera device capabilities. + + StreamCombinationTemplate []chosenStreamCombinations = s10BitOutputStreamCombinations; + if (!is10BitOutputSupported()) { + Log.v(TAG, "Device is not able to output 10-bit!"); + return null; + } + return getAvailableMandatoryStreamCombinationsInternal(chosenStreamCombinations, + /*10bit*/true); + } + /** * Retrieve a list of all available mandatory stream combinations with stream use cases. * when the camera device has {@link