diff options
-rw-r--r-- | core/api/current.txt | 14 | ||||
-rw-r--r-- | core/api/test-current.txt | 14 | ||||
-rw-r--r-- | core/java/android/hardware/CameraStreamStats.java | 12 | ||||
-rw-r--r-- | core/java/android/hardware/camera2/CameraCharacteristics.java | 78 | ||||
-rw-r--r-- | core/java/android/hardware/camera2/CameraMetadata.java | 30 | ||||
-rw-r--r-- | core/java/android/hardware/camera2/impl/CameraMetadataNative.java | 21 | ||||
-rw-r--r-- | core/java/android/hardware/camera2/params/ColorSpaceProfiles.java | 257 | ||||
-rw-r--r-- | core/java/android/hardware/camera2/params/OutputConfiguration.java | 67 | ||||
-rw-r--r-- | core/java/android/hardware/camera2/params/SessionConfiguration.java | 45 | ||||
-rw-r--r-- | proto/src/camera.proto | 2 |
10 files changed, 534 insertions, 6 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index 94d199cc00b6..abf8112908d6 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -17630,6 +17630,7 @@ package android.hardware.camera2 { field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES; field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REPROCESS_MAX_CAPTURE_STALL; field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> REQUEST_AVAILABLE_CAPABILITIES; + field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<android.hardware.camera2.params.ColorSpaceProfiles> REQUEST_AVAILABLE_COLOR_SPACE_PROFILES; field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<android.hardware.camera2.params.DynamicRangeProfiles> REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES; field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REQUEST_MAX_NUM_INPUT_STREAMS; field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REQUEST_MAX_NUM_OUTPUT_PROC; @@ -17993,6 +17994,7 @@ package android.hardware.camera2 { field public static final int NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG = 4; // 0x4 field public static final int REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE = 0; // 0x0 field public static final int REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE = 6; // 0x6 + field public static final int REQUEST_AVAILABLE_CAPABILITIES_COLOR_SPACE_PROFILES = 20; // 0x14 field public static final int REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO = 9; // 0x9 field public static final int REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT = 8; // 0x8 field public static final int REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT = 18; // 0x12 @@ -18344,6 +18346,15 @@ package android.hardware.camera2.params { method @NonNull public android.util.Range<java.lang.Float> getZoomRatioRange(); } + public final class ColorSpaceProfiles { + ctor public ColorSpaceProfiles(@NonNull long[]); + method @NonNull public java.util.Set<android.graphics.ColorSpace.Named> getSupportedColorSpaces(int); + method @NonNull public java.util.Set<android.graphics.ColorSpace.Named> getSupportedColorSpacesForDynamicRange(int, long); + method @NonNull public java.util.Set<java.lang.Long> getSupportedDynamicRangeProfiles(@NonNull android.graphics.ColorSpace.Named, int); + method @NonNull public java.util.Set<java.lang.Integer> getSupportedImageFormatsForColorSpace(@NonNull android.graphics.ColorSpace.Named); + field public static final int UNSPECIFIED = -1; // 0xffffffff + } + public final class ColorSpaceTransform { ctor public ColorSpaceTransform(android.util.Rational[]); ctor public ColorSpaceTransform(int[]); @@ -18575,13 +18586,16 @@ package android.hardware.camera2.params { public final class SessionConfiguration implements android.os.Parcelable { ctor public SessionConfiguration(int, @NonNull java.util.List<android.hardware.camera2.params.OutputConfiguration>, @NonNull java.util.concurrent.Executor, @NonNull android.hardware.camera2.CameraCaptureSession.StateCallback); + method public void clearColorSpace(); method public int describeContents(); + method @Nullable public android.graphics.ColorSpace getColorSpace(); method public java.util.concurrent.Executor getExecutor(); method public android.hardware.camera2.params.InputConfiguration getInputConfiguration(); method public java.util.List<android.hardware.camera2.params.OutputConfiguration> getOutputConfigurations(); method public android.hardware.camera2.CaptureRequest getSessionParameters(); method public int getSessionType(); method public android.hardware.camera2.CameraCaptureSession.StateCallback getStateCallback(); + method public void setColorSpace(@NonNull android.graphics.ColorSpace.Named); method public void setInputConfiguration(@NonNull android.hardware.camera2.params.InputConfiguration); method public void setSessionParameters(android.hardware.camera2.CaptureRequest); method public void writeToParcel(android.os.Parcel, int); diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 186e5be92524..ef74a3ef6c20 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -1170,6 +1170,20 @@ package android.hardware.camera2 { } +package android.hardware.camera2.params { + + public final class ColorSpaceProfiles { + method @NonNull public java.util.Map<android.graphics.ColorSpace.Named,java.util.Map<java.lang.Integer,java.util.Set<java.lang.Long>>> getProfileMap(); + } + + public final class OutputConfiguration implements android.os.Parcelable { + method public void clearColorSpace(); + method @Nullable public android.graphics.ColorSpace getColorSpace(); + method public void setColorSpace(@NonNull android.graphics.ColorSpace.Named); + } + +} + package android.hardware.devicestate { public final class DeviceStateManager { diff --git a/core/java/android/hardware/CameraStreamStats.java b/core/java/android/hardware/CameraStreamStats.java index 3952467324fe..aed5a129bd0b 100644 --- a/core/java/android/hardware/CameraStreamStats.java +++ b/core/java/android/hardware/CameraStreamStats.java @@ -16,6 +16,7 @@ package android.hardware; import android.hardware.camera2.CameraMetadata; +import android.hardware.camera2.params.ColorSpaceProfiles; import android.hardware.camera2.params.DynamicRangeProfiles; import android.os.Parcel; import android.os.Parcelable; @@ -50,6 +51,7 @@ public class CameraStreamStats implements Parcelable { private long[] mHistogramCounts; private long mDynamicRangeProfile; private long mStreamUseCase; + private int mColorSpace; private static final String TAG = "CameraStreamStats"; @@ -68,12 +70,13 @@ public class CameraStreamStats implements Parcelable { mHistogramType = HISTOGRAM_TYPE_UNKNOWN; mDynamicRangeProfile = DynamicRangeProfiles.STANDARD; mStreamUseCase = CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT; + mColorSpace = ColorSpaceProfiles.UNSPECIFIED; } public CameraStreamStats(int width, int height, int format, float maxPreviewFps, int dataSpace, long usage, long requestCount, long errorCount, int startLatencyMs, int maxHalBuffers, int maxAppBuffers, long dynamicRangeProfile, - long streamUseCase) { + long streamUseCase, int colorSpace) { mWidth = width; mHeight = height; mFormat = format; @@ -88,6 +91,7 @@ public class CameraStreamStats implements Parcelable { mHistogramType = HISTOGRAM_TYPE_UNKNOWN; mDynamicRangeProfile = dynamicRangeProfile; mStreamUseCase = streamUseCase; + mColorSpace = colorSpace; } public static final @android.annotation.NonNull Parcelable.Creator<CameraStreamStats> CREATOR = @@ -136,6 +140,7 @@ public class CameraStreamStats implements Parcelable { dest.writeLongArray(mHistogramCounts); dest.writeLong(mDynamicRangeProfile); dest.writeLong(mStreamUseCase); + dest.writeInt(mColorSpace); } public void readFromParcel(Parcel in) { @@ -155,6 +160,7 @@ public class CameraStreamStats implements Parcelable { mHistogramCounts = in.createLongArray(); mDynamicRangeProfile = in.readLong(); mStreamUseCase = in.readLong(); + mColorSpace = in.readInt(); } public int getWidth() { @@ -217,6 +223,10 @@ public class CameraStreamStats implements Parcelable { return mDynamicRangeProfile; } + public int getColorSpace() { + return mColorSpace; + } + public long getStreamUseCase() { return mStreamUseCase; } diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java index 8873807b7a98..f63472680bb0 100644 --- a/core/java/android/hardware/camera2/CameraCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraCharacteristics.java @@ -2224,6 +2224,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_REMOSAIC_REPROCESSING REMOSAIC_REPROCESSING}</li> * <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT DYNAMIC_RANGE_TEN_BIT}</li> * <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_STREAM_USE_CASE STREAM_USE_CASE}</li> + * <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_COLOR_SPACE_PROFILES COLOR_SPACE_PROFILES}</li> * </ul> * * <p>This key is available on all devices.</p> @@ -2249,6 +2250,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * @see #REQUEST_AVAILABLE_CAPABILITIES_REMOSAIC_REPROCESSING * @see #REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT * @see #REQUEST_AVAILABLE_CAPABILITIES_STREAM_USE_CASE + * @see #REQUEST_AVAILABLE_CAPABILITIES_COLOR_SPACE_PROFILES */ @PublicKey @NonNull @@ -2473,6 +2475,82 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri new Key<Long>("android.request.recommendedTenBitDynamicRangeProfile", long.class); /** + * <p>An interface for querying the color space profiles supported by a camera device.</p> + * <p>A color space profile is a combination of a color space, an image format, and a dynamic + * range profile. Camera clients can retrieve the list of supported color spaces by calling + * {@link android.hardware.camera2.params.ColorSpaceProfiles#getSupportedColorSpaces } or + * {@link android.hardware.camera2.params.ColorSpaceProfiles#getSupportedColorSpacesForDynamicRange }. + * If a camera does not support the + * {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT } + * capability, the dynamic range profile will always be + * {@link android.hardware.camera2.params.DynamicRangeProfiles#STANDARD }. Color space + * capabilities are queried in combination with an {@link android.graphics.ImageFormat }. + * If a camera client wants to know the general color space capabilities of a camera device + * regardless of image format, it can specify {@link android.graphics.ImageFormat#UNKNOWN }. + * The color space for a session can be configured by setting the SessionConfiguration + * color space via {@link android.hardware.camera2.params.SessionConfiguration#setColorSpace }.</p> + * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> + */ + @PublicKey + @NonNull + @SyntheticKey + public static final Key<android.hardware.camera2.params.ColorSpaceProfiles> REQUEST_AVAILABLE_COLOR_SPACE_PROFILES = + new Key<android.hardware.camera2.params.ColorSpaceProfiles>("android.request.availableColorSpaceProfiles", android.hardware.camera2.params.ColorSpaceProfiles.class); + + /** + * <p>A list of all possible color space profiles supported by a camera device.</p> + * <p>A color space profile is a combination of a color space, an image format, and a dynamic range + * profile. If a camera does not support the + * {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT } + * capability, the dynamic range profile will always be + * {@link android.hardware.camera2.params.DynamicRangeProfiles#STANDARD }. Camera clients can + * use {@link android.hardware.camera2.params.SessionConfiguration#setColorSpace } to select + * a color space.</p> + * <p><b>Possible values:</b></p> + * <ul> + * <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED UNSPECIFIED}</li> + * <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_SRGB SRGB}</li> + * <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_LINEAR_SRGB LINEAR_SRGB}</li> + * <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_EXTENDED_SRGB EXTENDED_SRGB}</li> + * <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_LINEAR_EXTENDED_SRGB LINEAR_EXTENDED_SRGB}</li> + * <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_BT709 BT709}</li> + * <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_BT2020 BT2020}</li> + * <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_DCI_P3 DCI_P3}</li> + * <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_DISPLAY_P3 DISPLAY_P3}</li> + * <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_NTSC_1953 NTSC_1953}</li> + * <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_SMPTE_C SMPTE_C}</li> + * <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_ADOBE_RGB ADOBE_RGB}</li> + * <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_PRO_PHOTO_RGB PRO_PHOTO_RGB}</li> + * <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_ACES ACES}</li> + * <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_ACESCG ACESCG}</li> + * <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_CIE_XYZ CIE_XYZ}</li> + * <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_CIE_LAB CIE_LAB}</li> + * </ul> + * + * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> + * @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED + * @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_SRGB + * @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_LINEAR_SRGB + * @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_EXTENDED_SRGB + * @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_LINEAR_EXTENDED_SRGB + * @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_BT709 + * @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_BT2020 + * @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_DCI_P3 + * @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_DISPLAY_P3 + * @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_NTSC_1953 + * @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_SMPTE_C + * @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_ADOBE_RGB + * @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_PRO_PHOTO_RGB + * @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_ACES + * @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_ACESCG + * @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_CIE_XYZ + * @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_CIE_LAB + * @hide + */ + public static final Key<long[]> REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP = + new Key<long[]>("android.request.availableColorSpaceProfilesMap", long[].class); + + /** * <p>The list of image formats that are supported by this * camera device for output streams.</p> * <p>All camera devices will support JPEG and YUV_420_888 formats.</p> diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java index c67a560b5885..1e1d44368713 100644 --- a/core/java/android/hardware/camera2/CameraMetadata.java +++ b/core/java/android/hardware/camera2/CameraMetadata.java @@ -1257,6 +1257,24 @@ public abstract class CameraMetadata<TKey> { */ public static final int REQUEST_AVAILABLE_CAPABILITIES_STREAM_USE_CASE = 19; + /** + * <p>The device supports querying the possible combinations of color spaces, image + * formats, and dynamic range profiles supported by the camera and requesting a + * particular color space for a session via + * {@link android.hardware.camera2.params.SessionConfiguration#setColorSpace }.</p> + * <p>Cameras that enable this capability may or may not also implement dynamic range + * profiles. If they don't, + * {@link android.hardware.camera2.params.ColorSpaceProfiles#getSupportedDynamicRangeProfiles } + * will return only + * {@link android.hardware.camera2.params.DynamicRangeProfiles#STANDARD } and + * {@link android.hardware.camera2.params.ColorSpaceProfiles#getSupportedColorSpacesForDynamicRange } + * will assume support of the + * {@link android.hardware.camera2.params.DynamicRangeProfiles#STANDARD } + * profile in all combinations of color spaces and image formats.</p> + * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES + */ + public static final int REQUEST_AVAILABLE_CAPABILITIES_COLOR_SPACE_PROFILES = 20; + // // Enumeration values for CameraCharacteristics#REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP // @@ -1367,6 +1385,18 @@ public abstract class CameraMetadata<TKey> { public static final int REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_MAX = 0x1000; // + // Enumeration values for CameraCharacteristics#REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP + // + + /** + * <p>Default value, when not explicitly specified. The Camera device will choose the color + * space to employ.</p> + * @see CameraCharacteristics#REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP + * @hide + */ + public static final int REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED = -1; + + // // Enumeration values for CameraCharacteristics#SCALER_CROPPING_TYPE // diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java index ee12df547291..012fad52fddf 100644 --- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java +++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java @@ -50,6 +50,7 @@ import android.hardware.camera2.marshal.impl.MarshalQueryableStreamConfiguration import android.hardware.camera2.marshal.impl.MarshalQueryableStreamConfigurationDuration; import android.hardware.camera2.marshal.impl.MarshalQueryableString; import android.hardware.camera2.params.Capability; +import android.hardware.camera2.params.ColorSpaceProfiles; import android.hardware.camera2.params.DeviceStateSensorOrientationMap; import android.hardware.camera2.params.DynamicRangeProfiles; import android.hardware.camera2.params.Face; @@ -813,6 +814,15 @@ public class CameraMetadataNative implements Parcelable { } }); sGetCommandMap.put( + CameraCharacteristics.REQUEST_AVAILABLE_COLOR_SPACE_PROFILES.getNativeKey(), + new GetCommand() { + @Override + @SuppressWarnings("unchecked") + public <T> T getValue(CameraMetadataNative metadata, Key<T> key) { + return (T) metadata.getColorSpaceProfiles(); + } + }); + sGetCommandMap.put( CaptureResult.STATISTICS_OIS_SAMPLES.getNativeKey(), new GetCommand() { @Override @@ -1068,6 +1078,17 @@ public class CameraMetadataNative implements Parcelable { return new DynamicRangeProfiles(profileArray); } + private ColorSpaceProfiles getColorSpaceProfiles() { + long[] profileArray = getBase( + CameraCharacteristics.REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP); + + if (profileArray == null) { + return null; + } + + return new ColorSpaceProfiles(profileArray); + } + private Location getGpsLocation() { String processingMethod = get(CaptureResult.JPEG_GPS_PROCESSING_METHOD); double[] coords = get(CaptureResult.JPEG_GPS_COORDINATES); diff --git a/core/java/android/hardware/camera2/params/ColorSpaceProfiles.java b/core/java/android/hardware/camera2/params/ColorSpaceProfiles.java new file mode 100644 index 000000000000..2e3af80f9cc0 --- /dev/null +++ b/core/java/android/hardware/camera2/params/ColorSpaceProfiles.java @@ -0,0 +1,257 @@ +/* + * Copyright (C) 2022 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. + */ + +package android.hardware.camera2.params; + +import android.annotation.NonNull; +import android.annotation.TestApi; +import android.graphics.ColorSpace; +import android.graphics.ImageFormat; +import android.hardware.camera2.CameraMetadata; +import android.util.ArrayMap; +import android.util.ArraySet; + +import java.util.Map; +import java.util.Set; + +/** + * Immutable class with information about supported color space profiles. + * + * <p>An instance of this class can be queried by retrieving the value of + * {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_COLOR_SPACE_PROFILES}. + * </p> + * + * <p>All camera devices supporting the + * {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_COLOR_SPACE_PROFILES} + * capability must advertise the supported color space profiles in + * {@link #getSupportedColorSpaces}</p> + * + * @see SessionConfiguration#setColorSpace + */ +public final class ColorSpaceProfiles { + /* + * @hide + */ + public static final int UNSPECIFIED = + CameraMetadata.REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED; + + private final Map<ColorSpace.Named, Map<Integer, Set<Long>>> mProfileMap = new ArrayMap<>(); + + /** + * Create a new immutable ColorSpaceProfiles instance. + * + * <p>This constructor takes over the array; do not write to the array afterwards.</p> + * + * <p>Do note that the constructor is available for testing purposes only! + * Camera clients must always retrieve the value of + * {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_COLOR_SPACE_PROFILES}. + * for a given camera id in order to retrieve the device capabilities.</p> + * + * @param elements + * An array of elements describing the map. It contains three elements per entry which + * describe the supported color space profile value in the first element, a compatible + * image format in the second, and in the third element a bitmap of compatible dynamic + * range profiles (see {@link DynamicRangeProfiles#STANDARD} and others for the + * individual bitmap components). + * + * @throws IllegalArgumentException + * if the {@code elements} array length is invalid, not divisible by 3 or contains + * invalid element values + * @throws NullPointerException + * if {@code elements} is {@code null} + * + */ + public ColorSpaceProfiles(@NonNull final long[] elements) { + if ((elements.length % 3) != 0) { + throw new IllegalArgumentException("Color space profile map length " + + elements.length + " is not divisible by 3!"); + } + + for (int i = 0; i < elements.length; i += 3) { + int colorSpace = (int) elements[i]; + checkProfileValue(colorSpace); + ColorSpace.Named namedColorSpace = ColorSpace.Named.values()[colorSpace]; + int imageFormat = (int) elements[i + 1]; + long dynamicRangeProfileBitmap = elements[i + 2]; + + if (!mProfileMap.containsKey(namedColorSpace)) { + ArrayMap<Integer, Set<Long>> imageFormatMap = new ArrayMap<>(); + mProfileMap.put(namedColorSpace, imageFormatMap); + } + + if (!mProfileMap.get(namedColorSpace).containsKey(imageFormat)) { + ArraySet<Long> dynamicRangeProfiles = new ArraySet<>(); + mProfileMap.get(namedColorSpace).put(imageFormat, dynamicRangeProfiles); + } + + if (dynamicRangeProfileBitmap != 0) { + for (long dynamicRangeProfile = DynamicRangeProfiles.STANDARD; + dynamicRangeProfile < DynamicRangeProfiles.PUBLIC_MAX; + dynamicRangeProfile <<= 1) { + if ((dynamicRangeProfileBitmap & dynamicRangeProfile) != 0) { + mProfileMap.get(namedColorSpace).get(imageFormat).add(dynamicRangeProfile); + } + } + } + } + } + + /** + * @hide + */ + public static void checkProfileValue(int colorSpace) { + boolean found = false; + for (ColorSpace.Named value : ColorSpace.Named.values()) { + if (colorSpace == value.ordinal()) { + found = true; + break; + } + } + + if (!found) { + throw new IllegalArgumentException("Unknown ColorSpace " + colorSpace); + } + } + + /** + * @hide + */ + @TestApi + public @NonNull Map<ColorSpace.Named, Map<Integer, Set<Long>>> getProfileMap() { + return mProfileMap; + } + + /** + * Return a list of color spaces that are compatible with an ImageFormat. If ImageFormat.UNKNOWN + * is provided, this function will return a set of all unique color spaces supported by the + * device, regardless of image format. + * + * Color spaces which are compatible with ImageFormat.PRIVATE are able to be used with + * SurfaceView, SurfaceTexture, MediaCodec and MediaRecorder. + * + * @return set of color spaces + * @see SessionConfiguration#setColorSpace + * @see ColorSpace.Named + */ + public @NonNull Set<ColorSpace.Named> getSupportedColorSpaces( + @ImageFormat.Format int imageFormat) { + ArraySet<ColorSpace.Named> supportedColorSpaceProfiles = new ArraySet<>(); + for (ColorSpace.Named colorSpace : mProfileMap.keySet()) { + if (imageFormat == ImageFormat.UNKNOWN) { + supportedColorSpaceProfiles.add(colorSpace); + } else { + Map<Integer, Set<Long>> imageFormatMap = mProfileMap.get(colorSpace); + if (imageFormatMap.containsKey(imageFormat)) { + supportedColorSpaceProfiles.add(colorSpace); + } + } + } + return supportedColorSpaceProfiles; + } + + /** + * Return a list of image formats that are compatible with a color space. + * + * Color spaces which are compatible with ImageFormat.PRIVATE are able to be used with + * SurfaceView, SurfaceTexture, MediaCodec and MediaRecorder. + * + * @return set of image formats + * @see SessionConfiguration#setColorSpace + * @see ColorSpace.Named + */ + public @NonNull Set<Integer> getSupportedImageFormatsForColorSpace( + @NonNull ColorSpace.Named colorSpace) { + Map<Integer, Set<Long>> imageFormatMap = mProfileMap.get(colorSpace); + if (imageFormatMap == null) { + return new ArraySet<Integer>(); + } + + return imageFormatMap.keySet(); + } + + /** + * Return a list of dynamic range profiles that are compatible with a color space and + * ImageFormat. If ImageFormat.UNKNOWN is provided, this function will return a set of + * all unique dynamic range profiles supported by the device given a color space, + * regardless of image format. + * + * @return set of dynamic range profiles. + * @see OutputConfiguration#setDynamicRangeProfile + * @see SessionConfiguration#setColorSpace + * @see ColorSpace.Named + * @see DynamicRangeProfiles.Profile + */ + public @NonNull Set<Long> getSupportedDynamicRangeProfiles(@NonNull ColorSpace.Named colorSpace, + @ImageFormat.Format int imageFormat) { + Map<Integer, Set<Long>> imageFormatMap = mProfileMap.get(colorSpace); + if (imageFormatMap == null) { + return new ArraySet<Long>(); + } + + Set<Long> dynamicRangeProfiles = null; + if (imageFormat == ImageFormat.UNKNOWN) { + dynamicRangeProfiles = new ArraySet<>(); + for (int supportedImageFormat : imageFormatMap.keySet()) { + Set<Long> supportedDynamicRangeProfiles = imageFormatMap.get( + supportedImageFormat); + for (Long supportedDynamicRangeProfile : supportedDynamicRangeProfiles) { + dynamicRangeProfiles.add(supportedDynamicRangeProfile); + } + } + } else { + dynamicRangeProfiles = imageFormatMap.get(imageFormat); + if (dynamicRangeProfiles == null) { + return new ArraySet<>(); + } + } + + return dynamicRangeProfiles; + } + + /** + * Return a list of color spaces that are compatible with an ImageFormat and a dynamic range + * profile. If ImageFormat.UNKNOWN is provided, this function will return a set of all unique + * color spaces compatible with the given dynamic range profile, regardless of image format. + * + * @return set of color spaces + * @see SessionConfiguration#setColorSpace + * @see OutputConfiguration#setDynamicRangeProfile + * @see ColorSpace.Named + * @see DynamicRangeProfiles.Profile + */ + public @NonNull Set<ColorSpace.Named> getSupportedColorSpacesForDynamicRange( + @ImageFormat.Format int imageFormat, + @DynamicRangeProfiles.Profile long dynamicRangeProfile) { + ArraySet<ColorSpace.Named> supportedColorSpaceProfiles = new ArraySet<>(); + for (ColorSpace.Named colorSpace : mProfileMap.keySet()) { + Map<Integer, Set<Long>> imageFormatMap = mProfileMap.get(colorSpace); + if (imageFormat == ImageFormat.UNKNOWN) { + for (int supportedImageFormat : imageFormatMap.keySet()) { + Set<Long> dynamicRangeProfiles = imageFormatMap.get(supportedImageFormat); + if (dynamicRangeProfiles.contains(dynamicRangeProfile)) { + supportedColorSpaceProfiles.add(colorSpace); + } + } + } else if (imageFormatMap.containsKey(imageFormat)) { + Set<Long> dynamicRangeProfiles = imageFormatMap.get(imageFormat); + if (dynamicRangeProfiles.contains(dynamicRangeProfile)) { + supportedColorSpaceProfiles.add(colorSpace); + } + } + } + return supportedColorSpaceProfiles; + } +} diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java index 90e92dbe2ab0..a0d8f8db6853 100644 --- a/core/java/android/hardware/camera2/params/OutputConfiguration.java +++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java @@ -22,7 +22,10 @@ import static com.android.internal.util.Preconditions.*; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.annotation.SystemApi; +import android.annotation.TestApi; +import android.graphics.ColorSpace; import android.graphics.ImageFormat; import android.hardware.camera2.CameraCaptureSession; import android.hardware.camera2.CameraCharacteristics; @@ -30,7 +33,6 @@ import android.hardware.camera2.CameraDevice; import android.hardware.camera2.CameraMetadata; import android.hardware.camera2.MultiResolutionImageReader; import android.hardware.camera2.params.DynamicRangeProfiles; -import android.hardware.camera2.params.DynamicRangeProfiles.Profile; import android.hardware.camera2.params.MultiResolutionStreamInfo; import android.hardware.camera2.utils.HashCodeHelpers; import android.hardware.camera2.utils.SurfaceUtils; @@ -454,7 +456,7 @@ public final class OutputConfiguration implements Parcelable { * {@link android.media.MediaCodec} etc.) * or {@link ImageFormat#YCBCR_P010}.</p> */ - public void setDynamicRangeProfile(@Profile long profile) { + public void setDynamicRangeProfile(@DynamicRangeProfiles.Profile long profile) { mDynamicRangeProfile = profile; } @@ -463,11 +465,54 @@ public final class OutputConfiguration implements Parcelable { * * @return the currently set dynamic range profile */ - public @Profile long getDynamicRangeProfile() { + public @DynamicRangeProfiles.Profile long getDynamicRangeProfile() { return mDynamicRangeProfile; } /** + * Set a specific device-supported color space. + * + * <p>Clients can choose from any profile advertised as supported in + * {@link CameraCharacteristics#REQUEST_AVAILABLE_COLOR_SPACE_PROFILES} + * queried using {@link ColorSpaceProfiles#getSupportedColorSpaces}. + * When set, the colorSpace will override the default color spaces of the output targets, + * or the color space implied by the dataSpace passed into an {@link ImageReader}'s + * constructor.</p> + * + * @hide + */ + @TestApi + public void setColorSpace(@NonNull ColorSpace.Named colorSpace) { + mColorSpace = colorSpace.ordinal(); + } + + /** + * Clear the color space, such that the default color space will be used. + * + * @hide + */ + @TestApi + public void clearColorSpace() { + mColorSpace = ColorSpaceProfiles.UNSPECIFIED; + } + + /** + * Return the current color space. + * + * @return the currently set color space + * @hide + */ + @TestApi + @SuppressLint("MethodNameUnits") + public @Nullable ColorSpace getColorSpace() { + if (mColorSpace != ColorSpaceProfiles.UNSPECIFIED) { + return ColorSpace.get(ColorSpace.Named.values()[mColorSpace]); + } else { + return null; + } + } + + /** * Create a new {@link OutputConfiguration} instance. * * <p>This constructor takes an argument for desired camera rotation</p> @@ -530,6 +575,7 @@ public final class OutputConfiguration implements Parcelable { mIsMultiResolution = false; mSensorPixelModesUsed = new ArrayList<Integer>(); mDynamicRangeProfile = DynamicRangeProfiles.STANDARD; + mColorSpace = ColorSpaceProfiles.UNSPECIFIED; mStreamUseCase = CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT; mTimestampBase = TIMESTAMP_BASE_DEFAULT; mMirrorMode = MIRROR_MODE_AUTO; @@ -631,6 +677,7 @@ public final class OutputConfiguration implements Parcelable { mIsMultiResolution = false; mSensorPixelModesUsed = new ArrayList<Integer>(); mDynamicRangeProfile = DynamicRangeProfiles.STANDARD; + mColorSpace = ColorSpaceProfiles.UNSPECIFIED; mStreamUseCase = CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT; } @@ -1079,6 +1126,7 @@ public final class OutputConfiguration implements Parcelable { this.mIsMultiResolution = other.mIsMultiResolution; this.mSensorPixelModesUsed = other.mSensorPixelModesUsed; this.mDynamicRangeProfile = other.mDynamicRangeProfile; + this.mColorSpace = other.mColorSpace; this.mStreamUseCase = other.mStreamUseCase; this.mTimestampBase = other.mTimestampBase; this.mMirrorMode = other.mMirrorMode; @@ -1105,6 +1153,7 @@ public final class OutputConfiguration implements Parcelable { checkArgumentInRange(rotation, ROTATION_0, ROTATION_270, "Rotation constant"); long dynamicRangeProfile = source.readLong(); DynamicRangeProfiles.checkProfileValue(dynamicRangeProfile); + int colorSpace = source.readInt(); int timestampBase = source.readInt(); int mirrorMode = source.readInt(); @@ -1132,6 +1181,7 @@ public final class OutputConfiguration implements Parcelable { mIsMultiResolution = isMultiResolutionOutput; mSensorPixelModesUsed = convertIntArrayToIntegerList(sensorPixelModesUsed); mDynamicRangeProfile = dynamicRangeProfile; + mColorSpace = colorSpace; mStreamUseCase = streamUseCase; mTimestampBase = timestampBase; mMirrorMode = mirrorMode; @@ -1251,6 +1301,7 @@ public final class OutputConfiguration implements Parcelable { // writeList doesn't seem to work well with Integer list. dest.writeIntArray(convertIntegerToIntList(mSensorPixelModesUsed)); dest.writeLong(mDynamicRangeProfile); + dest.writeInt(mColorSpace); dest.writeLong(mStreamUseCase); dest.writeInt(mTimestampBase); dest.writeInt(mMirrorMode); @@ -1305,6 +1356,9 @@ public final class OutputConfiguration implements Parcelable { if (mDynamicRangeProfile != other.mDynamicRangeProfile) { return false; } + if (mColorSpace != other.mColorSpace) { + return false; + } return true; } @@ -1325,7 +1379,8 @@ public final class OutputConfiguration implements Parcelable { mSurfaceGroupId, mSurfaceType, mIsShared ? 1 : 0, mPhysicalCameraId == null ? 0 : mPhysicalCameraId.hashCode(), mIsMultiResolution ? 1 : 0, mSensorPixelModesUsed.hashCode(), - mDynamicRangeProfile, mStreamUseCase, mTimestampBase, mMirrorMode); + mDynamicRangeProfile, mColorSpace, mStreamUseCase, + mTimestampBase, mMirrorMode); } return HashCodeHelpers.hashCode( @@ -1334,7 +1389,7 @@ public final class OutputConfiguration implements Parcelable { mConfiguredDataspace, mSurfaceGroupId, mIsShared ? 1 : 0, mPhysicalCameraId == null ? 0 : mPhysicalCameraId.hashCode(), mIsMultiResolution ? 1 : 0, mSensorPixelModesUsed.hashCode(), - mDynamicRangeProfile, mStreamUseCase, mTimestampBase, + mDynamicRangeProfile, mColorSpace, mStreamUseCase, mTimestampBase, mMirrorMode); } @@ -1369,6 +1424,8 @@ public final class OutputConfiguration implements Parcelable { private ArrayList<Integer> mSensorPixelModesUsed; // Dynamic range profile private long mDynamicRangeProfile; + // Color space + private int mColorSpace; // Stream use case private long mStreamUseCase; // Timestamp base diff --git a/core/java/android/hardware/camera2/params/SessionConfiguration.java b/core/java/android/hardware/camera2/params/SessionConfiguration.java index cfb6efa9ba3c..385f10719509 100644 --- a/core/java/android/hardware/camera2/params/SessionConfiguration.java +++ b/core/java/android/hardware/camera2/params/SessionConfiguration.java @@ -23,6 +23,8 @@ import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; +import android.graphics.ColorSpace; import android.hardware.camera2.CameraCaptureSession; import android.hardware.camera2.CameraCharacteristics; import android.hardware.camera2.CameraDevice; @@ -30,6 +32,7 @@ import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.params.InputConfiguration; import android.hardware.camera2.params.OutputConfiguration; import android.hardware.camera2.utils.HashCodeHelpers; +import android.media.ImageReader; import android.os.Parcel; import android.os.Parcelable; import android.util.Log; @@ -94,6 +97,7 @@ public final class SessionConfiguration implements Parcelable { private Executor mExecutor = null; private InputConfiguration mInputConfig = null; private CaptureRequest mSessionParameters = null; + private int mColorSpace; /** * Create a new {@link SessionConfiguration}. @@ -314,4 +318,45 @@ public final class SessionConfiguration implements Parcelable { public CaptureRequest getSessionParameters() { return mSessionParameters; } + + /** + * Set a specific device-supported color space. + * + * <p>Clients can choose from any profile advertised as supported in + * {@link CameraCharacteristics#REQUEST_AVAILABLE_COLOR_SPACE_PROFILES} + * queried using {@link ColorSpaceProfiles#getSupportedColorSpaces}. + * When set, the colorSpace will override the default color spaces of the output targets, + * or the color space implied by the dataSpace passed into an {@link ImageReader}'s + * constructor.</p> + */ + public void setColorSpace(@NonNull ColorSpace.Named colorSpace) { + mColorSpace = colorSpace.ordinal(); + for (OutputConfiguration outputConfiguration : mOutputConfigurations) { + outputConfiguration.setColorSpace(colorSpace); + } + } + + /** + * Clear the color space, such that the default color space will be used. + */ + public void clearColorSpace() { + mColorSpace = ColorSpaceProfiles.UNSPECIFIED; + for (OutputConfiguration outputConfiguration : mOutputConfigurations) { + outputConfiguration.clearColorSpace(); + } + } + + /** + * Return the current color space. + * + * @return the currently set color space + */ + @SuppressLint("MethodNameUnits") + public @Nullable ColorSpace getColorSpace() { + if (mColorSpace != ColorSpaceProfiles.UNSPECIFIED) { + return ColorSpace.get(ColorSpace.Named.values()[mColorSpace]); + } else { + return null; + } + } } diff --git a/proto/src/camera.proto b/proto/src/camera.proto index 38d74e4a73ce..205e806f534d 100644 --- a/proto/src/camera.proto +++ b/proto/src/camera.proto @@ -67,4 +67,6 @@ message CameraStreamProto { optional int64 dynamic_range_profile = 14; // The stream use case optional int64 stream_use_case = 15; + // The color space of the stream + optional int32 color_space = 16; } |