From 741dcc52bd3e2953bc3ca4c2db1d266ade3663fa Mon Sep 17 00:00:00 2001
From: Emilian Peev This value must always remain aligned with the public ImageFormat Jpeg/R definition and is
+ * valid with formats:
+ * HAL_PIXEL_FORMAT_BLOB: JPEG image encoded by Jpeg/R encoder according to ISO/IEC TBD.
+ * The image contains a standard SDR JPEG and a recovery map. Jpeg/R decoders can use the
+ * map to recover the input image. The available Jpeg/R stream
+ * configurations that this camera device supports
+ * (i.e. format, width, height, output/input stream). The configurations are listed as If the camera device supports Jpeg/R, it will support the same stream combinations with
+ * Jpeg/R as it does with P010. The stream combinations with Jpeg/R (or P010) supported
+ * by the device is determined by the device's hardware level and capabilities. All the static, control, and dynamic metadata tags related to JPEG apply to Jpeg/R formats.
+ * Configuring JPEG and Jpeg/R streams at the same time is not supported. 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 This lists the minimum frame duration for each
+ * format/size combination for Jpeg/R output formats. This should correspond to the frame duration when only that
+ * stream is active, with all processing (typically in android.*.mode)
+ * set to either OFF or FAST. When multiple streams are used in a request, the minimum frame
+ * duration will be max(individual stream min durations). See {@link CaptureRequest#SENSOR_FRAME_DURATION android.sensor.frameDuration} and
+ * android.scaler.availableStallDurations for more details about
+ * calculating the max frame rate. Units: (format, width, height, ns) x n 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 This lists the maximum stall duration for each
+ * output format/size combination for Jpeg/R streams. A stall duration is how much extra time would get added
+ * to the normal minimum frame duration for a repeating request
+ * that has streams with non-zero stall. This functions similarly to
+ * android.scaler.availableStallDurations for Jpeg/R
+ * streams. All Jpeg/R output stream formats may have a nonzero stall
+ * duration. Units: (format, width, height, ns) x n 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 The available Jpeg/R stream
+ * configurations that this camera device supports
+ * (i.e. format, width, height, output/input stream). Refer to android.jpegr.availableJpegRStreamConfigurations for details. Optional - The value for this key may be {@code null} on some devices. This lists the minimum frame duration for each
+ * format/size combination for Jpeg/R output formats for CaptureRequests where
+ * {@link CaptureRequest#SENSOR_PIXEL_MODE android.sensor.pixelMode} is set to
+ * {@link android.hardware.camera2.CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION }. Refer to android.jpegr.availableJpegRMinFrameDurations for details. Units: (format, width, height, ns) x n Optional - The value for this key may be {@code null} on some devices. This lists the maximum stall duration for each
+ * output format/size combination for Jpeg/R streams for CaptureRequests where
+ * {@link CaptureRequest#SENSOR_PIXEL_MODE android.sensor.pixelMode} is set to
+ * {@link android.hardware.camera2.CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION }. Refer to android.jpegr.availableJpegRStallDurations for details. Units: (format, width, height, ns) x n Optional - The value for this key may be {@code null} on some devices.(format, width, height, input?) tuples.
{@link android.graphics.ImageFormat#JPEG_R} may also be supported if advertised by + * {@link android.hardware.camera2.params.StreamConfigurationMap}. When initializing a capture + * session that includes a Jpeg/R camera output clients must consider the following items w.r.t. + * the 10-bit mandatory stream combination table: + * + *
Devices with the STREAM_USE_CASE capability ({@link * CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES} includes {@link diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java index 012fad52fddf8..9a164743bc8d1 100644 --- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java +++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java @@ -1351,6 +1351,9 @@ public class CameraMetadataNative implements Parcelable { /*heicconfiguration*/ null, /*heicminduration*/ null, /*heicstallduration*/ null, + /*jpegRconfiguration*/ null, + /*jpegRminduration*/ null, + /*jpegRstallduration*/ null, /*highspeedvideoconfigurations*/ null, /*inputoutputformatsmap*/ null, listHighResolution, supportsPrivate[i]); break; @@ -1365,6 +1368,9 @@ public class CameraMetadataNative implements Parcelable { /*heicconfiguration*/ null, /*heicminduration*/ null, /*heicstallduration*/ null, + /*jpegRconfiguration*/ null, + /*jpegRminduration*/ null, + /*jpegRstallduration*/ null, highSpeedVideoConfigurations, /*inputoutputformatsmap*/ null, listHighResolution, supportsPrivate[i]); break; @@ -1379,6 +1385,9 @@ public class CameraMetadataNative implements Parcelable { /*heicconfiguration*/ null, /*heicminduration*/ null, /*heicstallduration*/ null, + /*jpegRconfiguration*/ null, + /*jpegRminduration*/ null, + /*jpegRstallduration*/ null, /*highSpeedVideoConfigurations*/ null, inputOutputFormatsMap, listHighResolution, supportsPrivate[i]); break; @@ -1393,6 +1402,9 @@ public class CameraMetadataNative implements Parcelable { /*heicconfiguration*/ null, /*heicminduration*/ null, /*heicstallduration*/ null, + /*jpegRconfiguration*/ null, + /*jpegRminduration*/ null, + /*jpegRstallduration*/ null, /*highSpeedVideoConfigurations*/ null, /*inputOutputFormatsMap*/ null, listHighResolution, supportsPrivate[i]); } @@ -1546,6 +1558,12 @@ public class CameraMetadataNative implements Parcelable { CameraCharacteristics.HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS); StreamConfigurationDuration[] heicStallDurations = getBase( CameraCharacteristics.HEIC_AVAILABLE_HEIC_STALL_DURATIONS); + StreamConfiguration[] jpegRConfigurations = getBase( + CameraCharacteristics.JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS); + StreamConfigurationDuration[] jpegRMinFrameDurations = getBase( + CameraCharacteristics.JPEGR_AVAILABLE_JPEG_R_MIN_FRAME_DURATIONS); + StreamConfigurationDuration[] jpegRStallDurations = getBase( + CameraCharacteristics.JPEGR_AVAILABLE_JPEG_R_STALL_DURATIONS); HighSpeedVideoConfiguration[] highSpeedVideoConfigurations = getBase( CameraCharacteristics.CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS); ReprocessFormatsMap inputOutputFormatsMap = getBase( @@ -1557,6 +1575,7 @@ public class CameraMetadataNative implements Parcelable { dynamicDepthConfigurations, dynamicDepthMinFrameDurations, dynamicDepthStallDurations, heicConfigurations, heicMinFrameDurations, heicStallDurations, + jpegRConfigurations, jpegRMinFrameDurations, jpegRStallDurations, highSpeedVideoConfigurations, inputOutputFormatsMap, listHighResolution); } @@ -1589,6 +1608,12 @@ public class CameraMetadataNative implements Parcelable { CameraCharacteristics.HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION); StreamConfigurationDuration[] heicStallDurations = getBase( CameraCharacteristics.HEIC_AVAILABLE_HEIC_STALL_DURATIONS_MAXIMUM_RESOLUTION); + StreamConfiguration[] jpegRConfigurations = getBase( + CameraCharacteristics.JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION); + StreamConfigurationDuration[] jpegRMinFrameDurations = getBase( + CameraCharacteristics.JPEGR_AVAILABLE_JPEG_R_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION); + StreamConfigurationDuration[] jpegRStallDurations = getBase( + CameraCharacteristics.JPEGR_AVAILABLE_JPEG_R_STALL_DURATIONS_MAXIMUM_RESOLUTION); HighSpeedVideoConfiguration[] highSpeedVideoConfigurations = getBase( CameraCharacteristics.CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS_MAXIMUM_RESOLUTION); ReprocessFormatsMap inputOutputFormatsMap = getBase( @@ -1601,6 +1626,7 @@ public class CameraMetadataNative implements Parcelable { dynamicDepthConfigurations, dynamicDepthMinFrameDurations, dynamicDepthStallDurations, heicConfigurations, heicMinFrameDurations, heicStallDurations, + jpegRConfigurations, jpegRMinFrameDurations, jpegRStallDurations, highSpeedVideoConfigurations, inputOutputFormatsMap, listHighResolution, false); } diff --git a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java index 5981d279227d9..cb678b98a9980 100644 --- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java +++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java @@ -26,6 +26,7 @@ import android.hardware.camera2.CameraMetadata; import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.utils.HashCodeHelpers; import android.hardware.camera2.utils.SurfaceUtils; +import android.util.Log; import android.util.Range; import android.util.Size; import android.util.SparseIntArray; @@ -95,6 +96,11 @@ public final class StreamConfigurationMap { * {@link StreamConfigurationDuration} * @param heicStallDurations a non-{@code null} array of heic * {@link StreamConfigurationDuration} + * @param jpegRConfigurations a non-{@code null} array of Jpeg/R {@link StreamConfiguration} + * @param jpegRMinFrameDurations a non-{@code null} array of Jpeg/R + * {@link StreamConfigurationDuration} + * @param jpegRStallDurations a non-{@code null} array of Jpeg/R + * {@link StreamConfigurationDuration} * @param highSpeedVideoConfigurations an array of {@link HighSpeedVideoConfiguration}, null if * camera device does not support high speed video recording * @param listHighResolution a flag indicating whether the device supports BURST_CAPTURE @@ -117,6 +123,9 @@ public final class StreamConfigurationMap { StreamConfiguration[] heicConfigurations, StreamConfigurationDuration[] heicMinFrameDurations, StreamConfigurationDuration[] heicStallDurations, + StreamConfiguration[] jpegRConfigurations, + StreamConfigurationDuration[] jpegRMinFrameDurations, + StreamConfigurationDuration[] jpegRStallDurations, HighSpeedVideoConfiguration[] highSpeedVideoConfigurations, ReprocessFormatsMap inputOutputFormatsMap, boolean listHighResolution) { @@ -125,6 +134,7 @@ public final class StreamConfigurationMap { dynamicDepthConfigurations, dynamicDepthMinFrameDurations, dynamicDepthStallDurations, heicConfigurations, heicMinFrameDurations, heicStallDurations, + jpegRConfigurations, jpegRMinFrameDurations, jpegRStallDurations, highSpeedVideoConfigurations, inputOutputFormatsMap, listHighResolution, /*enforceImplementationDefined*/ true); } @@ -154,6 +164,11 @@ public final class StreamConfigurationMap { * {@link StreamConfigurationDuration} * @param heicStallDurations a non-{@code null} array of heic * {@link StreamConfigurationDuration} + * @param jpegRConfigurations a non-{@code null} array of Jpeg/R {@link StreamConfiguration} + * @param jpegRMinFrameDurations a non-{@code null} array of Jpeg/R + * {@link StreamConfigurationDuration} + * @param jpegRStallDurations a non-{@code null} array of Jpeg/R + * {@link StreamConfigurationDuration} * @param highSpeedVideoConfigurations an array of {@link HighSpeedVideoConfiguration}, null if * camera device does not support high speed video recording * @param listHighResolution a flag indicating whether the device supports BURST_CAPTURE @@ -178,6 +193,9 @@ public final class StreamConfigurationMap { StreamConfiguration[] heicConfigurations, StreamConfigurationDuration[] heicMinFrameDurations, StreamConfigurationDuration[] heicStallDurations, + StreamConfiguration[] jpegRConfigurations, + StreamConfigurationDuration[] jpegRMinFrameDurations, + StreamConfigurationDuration[] jpegRStallDurations, HighSpeedVideoConfiguration[] highSpeedVideoConfigurations, ReprocessFormatsMap inputOutputFormatsMap, boolean listHighResolution, @@ -242,6 +260,20 @@ public final class StreamConfigurationMap { "heicStallDurations"); } + + if (jpegRConfigurations == null) { + mJpegRConfigurations = new StreamConfiguration[0]; + mJpegRMinFrameDurations = new StreamConfigurationDuration[0]; + mJpegRStallDurations = new StreamConfigurationDuration[0]; + } else { + mJpegRConfigurations = checkArrayElementsNotNull(jpegRConfigurations, + "jpegRConfigurations"); + mJpegRMinFrameDurations = checkArrayElementsNotNull(jpegRMinFrameDurations, + "jpegRFrameDurations"); + mJpegRStallDurations = checkArrayElementsNotNull(jpegRStallDurations, + "jpegRStallDurations"); + } + if (highSpeedVideoConfigurations == null) { mHighSpeedVideoConfigurations = new HighSpeedVideoConfiguration[0]; } else { @@ -305,6 +337,17 @@ public final class StreamConfigurationMap { mHeicOutputFormats.get(config.getFormat()) + 1); } + // For each Jpeg/R format, track how many sizes there are available to configure + for (StreamConfiguration config : mJpegRConfigurations) { + if (!config.isOutput()) { + // Ignoring input Jpeg/R configs + continue; + } + + mJpegROutputFormats.put(config.getFormat(), + mJpegROutputFormats.get(config.getFormat()) + 1); + } + if (configurations != null && enforceImplementationDefined && mOutputFormats.indexOfKey(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) < 0) { throw new AssertionError( @@ -447,6 +490,8 @@ public final class StreamConfigurationMap { return mDynamicDepthOutputFormats.indexOfKey(internalFormat) >= 0; } else if (dataspace == HAL_DATASPACE_HEIF) { return mHeicOutputFormats.indexOfKey(internalFormat) >= 0; + } else if (dataspace == HAL_DATASPACE_JPEG_R) { + return mJpegROutputFormats.indexOfKey(internalFormat) >= 0; } else { return getFormatsMap(/*output*/true).indexOfKey(internalFormat) >= 0; } @@ -561,6 +606,7 @@ public final class StreamConfigurationMap { surfaceDataspace == HAL_DATASPACE_DEPTH ? mDepthConfigurations : surfaceDataspace == HAL_DATASPACE_DYNAMIC_DEPTH ? mDynamicDepthConfigurations : surfaceDataspace == HAL_DATASPACE_HEIF ? mHeicConfigurations : + surfaceDataspace == HAL_DATASPACE_JPEG_R ? mJpegRConfigurations : mConfigurations; for (StreamConfiguration config : configs) { if (config.getFormat() == surfaceFormat && config.isOutput()) { @@ -597,6 +643,7 @@ public final class StreamConfigurationMap { dataspace == HAL_DATASPACE_DEPTH ? mDepthConfigurations : dataspace == HAL_DATASPACE_DYNAMIC_DEPTH ? mDynamicDepthConfigurations : dataspace == HAL_DATASPACE_HEIF ? mHeicConfigurations : + dataspace == HAL_DATASPACE_JPEG_R ? mJpegRConfigurations : mConfigurations; for (StreamConfiguration config : configs) { if ((config.getFormat() == internalFormat) && config.isOutput() && @@ -1120,6 +1167,9 @@ public final class StreamConfigurationMap { Arrays.equals(mHeicConfigurations, other.mHeicConfigurations) && Arrays.equals(mHeicMinFrameDurations, other.mHeicMinFrameDurations) && Arrays.equals(mHeicStallDurations, other.mHeicStallDurations) && + Arrays.equals(mJpegRConfigurations, other.mJpegRConfigurations) && + Arrays.equals(mJpegRMinFrameDurations, other.mJpegRMinFrameDurations) && + Arrays.equals(mJpegRStallDurations, other.mJpegRStallDurations) && Arrays.equals(mHighSpeedVideoConfigurations, other.mHighSpeedVideoConfigurations); } @@ -1138,6 +1188,7 @@ public final class StreamConfigurationMap { mDynamicDepthConfigurations, mDynamicDepthMinFrameDurations, mDynamicDepthStallDurations, mHeicConfigurations, mHeicMinFrameDurations, mHeicStallDurations, + mJpegRConfigurations, mJpegRMinFrameDurations, mJpegRStallDurations, mHighSpeedVideoConfigurations); } @@ -1161,6 +1212,10 @@ public final class StreamConfigurationMap { if (mHeicOutputFormats.indexOfKey(internalFormat) >= 0) { return format; } + } else if (internalDataspace == HAL_DATASPACE_JPEG_R) { + if (mJpegROutputFormats.indexOfKey(internalFormat) >= 0) { + return format; + } } else { if (mAllOutputFormats.indexOfKey(internalFormat) >= 0) { return format; @@ -1365,6 +1420,7 @@ public final class StreamConfigurationMap { *
JPEG compressed main image along with XMP embedded recovery map + * following ISO TBD.
+ */ + public static final int JPEG_R = 0x1005; + /** *Multi-plane Android YUV 420 format
* @@ -886,6 +895,7 @@ public class ImageFormat { case Y8: case DEPTH_JPEG: case HEIC: + case JPEG_R: return true; } diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java index f223bfd357d6f..72aaa3554ddb5 100644 --- a/media/java/android/media/ImageReader.java +++ b/media/java/android/media/ImageReader.java @@ -1199,6 +1199,7 @@ public class ImageReader implements AutoCloseable { case ImageFormat.RAW_PRIVATE: case ImageFormat.DEPTH_JPEG: case ImageFormat.HEIC: + case ImageFormat.JPEG_R: width = ImageReader.this.getWidth(); break; default: @@ -1217,6 +1218,7 @@ public class ImageReader implements AutoCloseable { case ImageFormat.RAW_PRIVATE: case ImageFormat.DEPTH_JPEG: case ImageFormat.HEIC: + case ImageFormat.JPEG_R: height = ImageReader.this.getHeight(); break; default: diff --git a/media/java/android/media/ImageUtils.java b/media/java/android/media/ImageUtils.java index 2f1a36cba9d0a..8f7019d4e494a 100644 --- a/media/java/android/media/ImageUtils.java +++ b/media/java/android/media/ImageUtils.java @@ -68,6 +68,7 @@ class ImageUtils { case ImageFormat.RAW_DEPTH10: case ImageFormat.DEPTH_JPEG: case ImageFormat.HEIC: + case ImageFormat.JPEG_R: return 1; case ImageFormat.PRIVATE: return 0; @@ -231,6 +232,7 @@ class ImageUtils { case ImageFormat.DEPTH_POINT_CLOUD: case ImageFormat.DEPTH_JPEG: case ImageFormat.HEIC: + case ImageFormat.JPEG_R: estimatedBytePerPixel = 0.3; break; case ImageFormat.Y8: @@ -304,6 +306,7 @@ class ImageUtils { case ImageFormat.RAW_DEPTH: case ImageFormat.RAW_DEPTH10: case ImageFormat.HEIC: + case ImageFormat.JPEG_R: return new Size(image.getWidth(), image.getHeight()); case ImageFormat.PRIVATE: return new Size(0, 0);