diff options
| author | 2015-06-17 11:34:41 -0700 | |
|---|---|---|
| committer | 2015-06-22 14:21:22 -0700 | |
| commit | 0819c75680c81a4e9c8a1ec518ac62cceccf3f56 (patch) | |
| tree | 687bb951b8a07f2c279ff4c2c633fb087c5465f9 | |
| parent | a77ef4b8b4c11a9fdfdca030462b7b055bf533bc (diff) | |
Camera2: Remove HIGH_RESOLUTION level and modify FULL requirements
- Reword requirements for FULL level
- Remove HIGH_RESOLUTION level
- Add StreamConfigurationMap#getHighResolutionOutputSizes
- Clean up StreamConfigurationMap implementation
- Add 5-argument HashCodeHelper
Bug: 20945581
Change-Id: I75ad4b23e902192c96ed501e10c7d55fc0ad72a6
| -rw-r--r-- | api/current.txt | 2 | ||||
| -rw-r--r-- | api/system-current.txt | 2 | ||||
| -rw-r--r-- | core/java/android/hardware/camera2/CameraCharacteristics.java | 19 | ||||
| -rw-r--r-- | core/java/android/hardware/camera2/CameraMetadata.java | 56 | ||||
| -rw-r--r-- | core/java/android/hardware/camera2/CaptureRequest.java | 2 | ||||
| -rw-r--r-- | core/java/android/hardware/camera2/impl/CameraMetadataNative.java | 12 | ||||
| -rw-r--r-- | core/java/android/hardware/camera2/params/StreamConfigurationMap.java | 257 | ||||
| -rw-r--r-- | core/java/android/hardware/camera2/params/TonemapCurve.java | 2 | ||||
| -rw-r--r-- | core/java/android/hardware/camera2/utils/HashCodeHelpers.java | 58 | ||||
| -rw-r--r-- | core/java/android/util/Range.java | 2 |
10 files changed, 235 insertions, 177 deletions
diff --git a/api/current.txt b/api/current.txt index 1287c74e370b..b806ddf238cd 100644 --- a/api/current.txt +++ b/api/current.txt @@ -13505,7 +13505,6 @@ package android.hardware.camera2 { field public static final int HOT_PIXEL_MODE_HIGH_QUALITY = 2; // 0x2 field public static final int HOT_PIXEL_MODE_OFF = 0; // 0x0 field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_FULL = 1; // 0x1 - field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_HIGH_RESOLUTION = 3; // 0x3 field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY = 2; // 0x2 field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED = 0; // 0x0 field public static final int LENS_FACING_BACK = 1; // 0x1 @@ -13858,6 +13857,7 @@ package android.hardware.camera2.params { } public final class StreamConfigurationMap { + method public android.util.Size[] getHighResolutionOutputSizes(int); method public android.util.Range<java.lang.Integer>[] getHighSpeedVideoFpsRanges(); method public android.util.Range<java.lang.Integer>[] getHighSpeedVideoFpsRangesFor(android.util.Size); method public android.util.Size[] getHighSpeedVideoSizes(); diff --git a/api/system-current.txt b/api/system-current.txt index 1f8f7a39c6c5..35d116e56b4e 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -13836,7 +13836,6 @@ package android.hardware.camera2 { field public static final int HOT_PIXEL_MODE_HIGH_QUALITY = 2; // 0x2 field public static final int HOT_PIXEL_MODE_OFF = 0; // 0x0 field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_FULL = 1; // 0x1 - field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_HIGH_RESOLUTION = 3; // 0x3 field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY = 2; // 0x2 field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED = 0; // 0x0 field public static final int LENS_FACING_BACK = 1; // 0x1 @@ -14189,6 +14188,7 @@ package android.hardware.camera2.params { } public final class StreamConfigurationMap { + method public android.util.Size[] getHighResolutionOutputSizes(int); method public android.util.Range<java.lang.Integer>[] getHighSpeedVideoFpsRanges(); method public android.util.Range<java.lang.Integer>[] getHighSpeedVideoFpsRangesFor(android.util.Size); method public android.util.Size[] getHighSpeedVideoSizes(); diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java index 27d14b3bbae5..261ce72bac34 100644 --- a/core/java/android/hardware/camera2/CameraCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraCharacteristics.java @@ -2679,9 +2679,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * <p>Camera devices will come in three flavors: LEGACY, LIMITED and FULL.</p> * <p>A FULL device will support below capabilities:</p> * <ul> - * <li>30fps operation at maximum resolution (== sensor resolution) is preferred, more than - * 20fps is required, for at least uncompressed YUV - * output. ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains BURST_CAPTURE)</li> + * <li>BURST_CAPTURE capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains BURST_CAPTURE)</li> * <li>Per frame control ({@link CameraCharacteristics#SYNC_MAX_LATENCY android.sync.maxLatency} <code>==</code> PER_FRAME_CONTROL)</li> * <li>Manual sensor control ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains MANUAL_SENSOR)</li> * <li>Manual post-processing control ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains @@ -2689,7 +2687,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * <li>Arbitrary cropping region ({@link CameraCharacteristics#SCALER_CROPPING_TYPE android.scaler.croppingType} <code>==</code> FREEFORM)</li> * <li>At least 3 processed (but not stalling) format output streams * ({@link CameraCharacteristics#REQUEST_MAX_NUM_OUTPUT_PROC android.request.maxNumOutputProc} <code>>=</code> 3)</li> - * <li>The required stream configuration defined in android.scaler.availableStreamConfigurations</li> + * <li>The required stream configurations defined in android.scaler.availableStreamConfigurations</li> * <li>The required exposure time range defined in {@link CameraCharacteristics#SENSOR_INFO_EXPOSURE_TIME_RANGE android.sensor.info.exposureTimeRange}</li> * <li>The required maxFrameDuration defined in {@link CameraCharacteristics#SENSOR_INFO_MAX_FRAME_DURATION android.sensor.info.maxFrameDuration}</li> * </ul> @@ -2709,23 +2707,11 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * post-processing, arbitrary cropping regions, and has relaxed performance constraints.</p> * <p>Each higher level supports everything the lower level supports * in this order: FULL <code>></code> LIMITED <code>></code> LEGACY.</p> - * <p>A HIGH_RESOLUTION device is equivalent to a FULL device, except that:</p> - * <ul> - * <li>At least one output resolution of 8 megapixels or higher in uncompressed YUV is - * supported at <code>>=</code> 20 fps.</li> - * <li>Maximum-size (sensor resolution) uncompressed YUV is supported at <code>>=</code> 10 - * fps.</li> - * <li>For devices that list the RAW capability and support either RAW10 or RAW12 output, - * maximum-resolution RAW10 or RAW12 capture will operate at least at the rate of - * maximum-resolution YUV capture, and at least one supported output resolution of - * 8 megapixels or higher in RAW10 or RAW12 is supported <code>>=</code> 20 fps.</li> - * </ul> * <p><b>Possible values:</b> * <ul> * <li>{@link #INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED}</li> * <li>{@link #INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL}</li> * <li>{@link #INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY}</li> - * <li>{@link #INFO_SUPPORTED_HARDWARE_LEVEL_HIGH_RESOLUTION HIGH_RESOLUTION}</li> * </ul></p> * <p>This key is available on all devices.</p> * @@ -2743,7 +2729,6 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * @see #INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED * @see #INFO_SUPPORTED_HARDWARE_LEVEL_FULL * @see #INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY - * @see #INFO_SUPPORTED_HARDWARE_LEVEL_HIGH_RESOLUTION */ @PublicKey public static final Key<Integer> INFO_SUPPORTED_HARDWARE_LEVEL = diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java index c656fb8b8352..5a80585cf55e 100644 --- a/core/java/android/hardware/camera2/CameraMetadata.java +++ b/core/java/android/hardware/camera2/CameraMetadata.java @@ -531,37 +531,32 @@ public abstract class CameraMetadata<TKey> { public static final int REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS = 5; /** - * <p>The camera device supports capturing maximum-resolution - * images at >= 20 frames per second, in at least the - * uncompressed YUV format, when post-processing settings - * are set to FAST.</p> - * <p>More specifically, this means that a size matching the - * camera device's active array size is listed as a - * supported size for the YUV_420_888 format in - * {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap}, the minimum frame - * duration for that format and size is <= 1/20 s, and - * the {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES android.control.aeAvailableTargetFpsRanges} entry - * lists at least one FPS range where the minimum FPS is</p> - * <blockquote> - * <p>= 1 / minimumFrameDuration for the maximum-size - * YUV_420_888 format.</p> - * </blockquote> - * <p>In addition, the {@link CameraCharacteristics#SYNC_MAX_LATENCY android.sync.maxLatency} field is - * guaranted to have a value between 0 and 4, inclusive. - * {@link CameraCharacteristics#CONTROL_AE_LOCK_AVAILABLE android.control.aeLockAvailable} and - * {@link CameraCharacteristics#CONTROL_AWB_LOCK_AVAILABLE android.control.awbLockAvailable} are also guaranteed - * to be <code>true</code> so burst capture with these two locks ON - * yields consistent image output.</p> - * <p>On a camera device that reports the HIGH_RESOLUTION hardware - * level, meaning the device supports very large capture sizes, - * BURST_CAPTURE means that at least 8-megapixel images can be - * captured at <code>>=</code> 20 fps, and maximum-resolution images can be - * captured at <code>>=</code> 10 fps.</p> + * <p>The camera device supports capturing high-resolution images at >= 20 frames per + * second, in at least the uncompressed YUV format, when post-processing settings are set + * to FAST. Additionally, maximum-resolution images can be captured at >= 10 frames + * per second. Here, 'high resolution' means at least 8 megapixels, or the maximum + * resolution of the device, whichever is smaller.</p> + * <p>More specifically, this means that a size matching the camera device's active array + * size is listed as a supported size for the {@link android.graphics.ImageFormat#YUV_420_888 } format in either {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputSizes } or {@link android.hardware.camera2.params.StreamConfigurationMap#getHighResolutionOutputSizes }, + * with a minimum frame duration for that format and size of either <= 1/20 s, or + * <= 1/10 s, respectively; and the {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES android.control.aeAvailableTargetFpsRanges} entry + * lists at least one FPS range where the minimum FPS is >= 1 / minimumFrameDuration + * for the maximum-size YUV_420_888 format. If that maximum size is listed in {@link android.hardware.camera2.params.StreamConfigurationMap#getHighResolutionOutputSizes }, + * then the list of resolutions for YUV_420_888 from {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputSizes } contains at + * least one resolution >= 8 megapixels, with a minimum frame duration of <= 1/20 + * s.</p> + * <p>If the device supports the {@link android.graphics.ImageFormat#RAW10 }, {@link android.graphics.ImageFormat#RAW12 }, then those can also be captured at the same rate + * as the maximum-size YUV_420_888 resolution is.</p> + * <p>If the device supports the PRIVATE_REPROCESSING capability, then the same guarantees + * as for the YUV_420_888 format also apply to the {@link android.graphics.ImageFormat#PRIVATE } format.</p> + * <p>In addition, the {@link CameraCharacteristics#SYNC_MAX_LATENCY android.sync.maxLatency} field is guaranted to have a value between 0 + * and 4, inclusive. {@link CameraCharacteristics#CONTROL_AE_LOCK_AVAILABLE android.control.aeLockAvailable} and {@link CameraCharacteristics#CONTROL_AWB_LOCK_AVAILABLE android.control.awbLockAvailable} + * are also guaranteed to be <code>true</code> so burst capture with these two locks ON yields + * consistent image output.</p> * * @see CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES * @see CameraCharacteristics#CONTROL_AE_LOCK_AVAILABLE * @see CameraCharacteristics#CONTROL_AWB_LOCK_AVAILABLE - * @see CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP * @see CameraCharacteristics#SYNC_MAX_LATENCY * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES */ @@ -954,13 +949,6 @@ public abstract class CameraMetadata<TKey> { */ public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY = 2; - /** - * <p>This camera device is capable of supporting advanced imaging applications at full rate, - * and additional high-resolution outputs at lower rates.</p> - * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL - */ - public static final int INFO_SUPPORTED_HARDWARE_LEVEL_HIGH_RESOLUTION = 3; - // // Enumeration values for CameraCharacteristics#SYNC_MAX_LATENCY // diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java index 9fa66879629d..e405ba6932e4 100644 --- a/core/java/android/hardware/camera2/CaptureRequest.java +++ b/core/java/android/hardware/camera2/CaptureRequest.java @@ -398,7 +398,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> @Override public int hashCode() { - return HashCodeHelpers.hashCode(mSettings, mSurfaceSet, mUserTag); + return HashCodeHelpers.hashCodeGeneric(mSettings, mSurfaceSet, mUserTag); } public static final Parcelable.Creator<CaptureRequest> CREATOR = diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java index 10dd8aed631e..7e50fd9f623a 100644 --- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java +++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java @@ -842,11 +842,19 @@ public class CameraMetadataNative implements Parcelable { CameraCharacteristics.CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS); ReprocessFormatsMap inputOutputFormatsMap = getBase( CameraCharacteristics.SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP); - + int[] capabilities = getBase(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES); + boolean listHighResolution = false; + for (int capability : capabilities) { + if (capability == CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE) { + listHighResolution = true; + break; + } + } return new StreamConfigurationMap( configurations, minFrameDurations, stallDurations, depthConfigurations, depthMinFrameDurations, depthStallDurations, - highSpeedVideoConfigurations, inputOutputFormatsMap); + highSpeedVideoConfigurations, inputOutputFormatsMap, + listHighResolution); } private <T> Integer getMaxRegions(Key<T> key) { diff --git a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java index c6ea4883f188..c186a0ec581a 100644 --- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java +++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java @@ -28,6 +28,7 @@ import android.hardware.camera2.legacy.LegacyExceptionUtils.BufferQueueAbandoned import android.view.Surface; import android.util.Range; import android.util.Size; +import android.util.SparseIntArray; import java.util.Arrays; import java.util.HashMap; @@ -79,7 +80,8 @@ public final class StreamConfigurationMap { * @param stallDurations a non-{@code null} array of {@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 + * and thus needs a separate list of slow high-resolution output sizes * @throws NullPointerException if any of the arguments except highSpeedVideoConfigurations * were {@code null} or any subelements were {@code null} * @@ -93,10 +95,12 @@ public final class StreamConfigurationMap { StreamConfigurationDuration[] depthMinFrameDurations, StreamConfigurationDuration[] depthStallDurations, HighSpeedVideoConfiguration[] highSpeedVideoConfigurations, - ReprocessFormatsMap inputOutputFormatsMap) { + ReprocessFormatsMap inputOutputFormatsMap, + boolean listHighResolution) { mConfigurations = checkArrayElementsNotNull(configurations, "configurations"); mMinFrameDurations = checkArrayElementsNotNull(minFrameDurations, "minFrameDurations"); mStallDurations = checkArrayElementsNotNull(stallDurations, "stallDurations"); + mListHighResolution = listHighResolution; if (depthConfigurations == null) { mDepthConfigurations = new StreamConfiguration[0]; @@ -120,15 +124,27 @@ public final class StreamConfigurationMap { // For each format, track how many sizes there are available to configure for (StreamConfiguration config : configurations) { - HashMap<Integer, Integer> map = config.isOutput() ? mOutputFormats : mInputFormats; - - Integer count = map.get(config.getFormat()); - - if (count == null) { - count = 0; + int fmt = config.getFormat(); + SparseIntArray map = null; + if (config.isOutput()) { + mAllOutputFormats.put(fmt, mAllOutputFormats.get(fmt) + 1); + long duration = 0; + if (mListHighResolution) { + for (StreamConfigurationDuration configurationDuration : mMinFrameDurations) { + if (configurationDuration.getFormat() == fmt && + configurationDuration.getWidth() == config.getSize().getWidth() && + configurationDuration.getHeight() == config.getSize().getHeight()) { + duration = configurationDuration.getDuration(); + break; + } + } + } + map = duration <= DURATION_20FPS_NS ? + mOutputFormats : mHighResOutputFormats; + } else { + map = mInputFormats; } - - map.put(config.getFormat(), count + 1); + map.put(fmt, map.get(fmt) + 1); } // For each depth format, track how many sizes there are available to configure @@ -138,16 +154,11 @@ public final class StreamConfigurationMap { continue; } - Integer count = mDepthOutputFormats.get(config.getFormat()); - - if (count == null) { - count = 0; - } - - mDepthOutputFormats.put(config.getFormat(), count + 1); + mDepthOutputFormats.put(config.getFormat(), + mDepthOutputFormats.get(config.getFormat()) + 1); } - if (!mOutputFormats.containsKey(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED)) { + if (mOutputFormats.indexOfKey(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) < 0) { throw new AssertionError( "At least one stream configuration for IMPLEMENTATION_DEFINED must exist"); } @@ -241,7 +252,7 @@ public final class StreamConfigurationMap { * @return a non-empty array of sizes, or {@code null} if the format was not available. */ public Size[] getInputSizes(final int format) { - return getPublicFormatSizes(format, /*output*/false); + return getPublicFormatSizes(format, /*output*/false, /*highRes*/false); } /** @@ -274,9 +285,9 @@ public final class StreamConfigurationMap { int internalFormat = imageFormatToInternal(format); int dataspace = imageFormatToDataspace(format); if (dataspace == HAL_DATASPACE_DEPTH) { - return mDepthOutputFormats.containsKey(internalFormat); + return mDepthOutputFormats.indexOfKey(internalFormat) >= 0; } else { - return getFormatsMap(/*output*/true).containsKey(internalFormat); + return getFormatsMap(/*output*/true).indexOfKey(internalFormat) >= 0; } } @@ -414,12 +425,12 @@ public final class StreamConfigurationMap { /** * Get a list of sizes compatible with {@code klass} to use as an output. * - * <p>Since some of the supported classes may support additional formats beyond + * <p>Some of the supported classes may support additional formats beyond * {@link ImageFormat#PRIVATE}; this function only returns * sizes for {@link ImageFormat#PRIVATE}. For example, {@link android.media.ImageReader} * supports {@link ImageFormat#YUV_420_888} and {@link ImageFormat#PRIVATE}, this method will * only return the sizes for {@link ImageFormat#PRIVATE} for {@link android.media.ImageReader} - * class .</p> + * class.</p> * * <p>If a well-defined format such as {@code NV21} is required, use * {@link #getOutputSizes(int)} instead.</p> @@ -444,7 +455,7 @@ public final class StreamConfigurationMap { } return getInternalFormatSizes(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, - HAL_DATASPACE_UNKNOWN,/*output*/true); + HAL_DATASPACE_UNKNOWN,/*output*/true, /*highRes*/false); } /** @@ -453,6 +464,14 @@ public final class StreamConfigurationMap { * <p>The {@code format} should be a supported format (one of the formats returned by * {@link #getOutputFormats}).</p> * + * As of API level 23, the {@link #getHighResolutionOutputSizes} method can be used on devices + * that support the + * {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE BURST_CAPTURE} + * capability to get a list of high-resolution output sizes that cannot operate at the preferred + * 20fps rate. This means that for some supported formats, this method will return an empty + * list, if all the supported resolutions operate at below 20fps. For devices that do not + * support the BURST_CAPTURE capability, all output resolutions are listed through this method. + * * @param format an image format from {@link ImageFormat} or {@link PixelFormat} * @return * an array of supported sizes, @@ -463,7 +482,7 @@ public final class StreamConfigurationMap { * @see #getOutputFormats */ public Size[] getOutputSizes(int format) { - return getPublicFormatSizes(format, /*output*/true); + return getPublicFormatSizes(format, /*output*/true, /*highRes*/ false); } /** @@ -616,6 +635,32 @@ public final class StreamConfigurationMap { } /** + * Get a list of supported high resolution sizes, which cannot operate at full BURST_CAPTURE + * rate. + * + * <p>This includes all output sizes that cannot meet the 20 fps frame rate requirements for the + * {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE BURST_CAPTURE} + * capability. This does not include the stall duration, so for example, a JPEG or RAW16 output + * resolution with a large stall duration but a minimum frame duration that's above 20 fps will + * still be listed in the regular {@link #getOutputSizes} list. All the sizes on this list are + * still guaranteed to operate at a rate of at least 10 fps, not including stall duration.</p> + * + * <p>For a device that does not support the BURST_CAPTURE capability, this list will be + * {@code null}, since resolutions in the {@link #getOutputSizes} list are already not + * guaranteed to meet >= 20 fps rate requirements. For a device that does support the + * BURST_CAPTURE capability, this list may be empty, if all supported resolutions meet the 20 + * fps requirement.</p> + * + * @return an array of supported slower high-resolution sizes, or {@code null} if the + * BURST_CAPTURE capability is not supported + */ + public Size[] getHighResolutionOutputSizes(int format) { + if (!mListHighResolution) return null; + + return getPublicFormatSizes(format, /*output*/true, /*highRes*/ true); + } + + /** * Get the minimum {@link CaptureRequest#SENSOR_FRAME_DURATION frame duration} * for the format/size combination (in nanoseconds). * @@ -867,6 +912,7 @@ public final class StreamConfigurationMap { return Arrays.equals(mConfigurations, other.mConfigurations) && Arrays.equals(mMinFrameDurations, other.mMinFrameDurations) && Arrays.equals(mStallDurations, other.mStallDurations) && + Arrays.equals(mDepthConfigurations, other.mDepthConfigurations) && Arrays.equals(mHighSpeedVideoConfigurations, other.mHighSpeedVideoConfigurations); } @@ -879,18 +925,31 @@ public final class StreamConfigurationMap { @Override public int hashCode() { // XX: do we care about order? - return HashCodeHelpers.hashCode( + return HashCodeHelpers.hashCodeGeneric( mConfigurations, mMinFrameDurations, - mStallDurations, mHighSpeedVideoConfigurations); + mStallDurations, + mDepthConfigurations, mHighSpeedVideoConfigurations); } // Check that the argument is supported by #getOutputFormats or #getInputFormats private int checkArgumentFormatSupported(int format, boolean output) { checkArgumentFormat(format); - int[] formats = output ? getOutputFormats() : getInputFormats(); - for (int i = 0; i < formats.length; ++i) { - if (format == formats[i]) { + int internalFormat = imageFormatToInternal(format); + int internalDataspace = imageFormatToDataspace(format); + + if (output) { + if (internalDataspace == HAL_DATASPACE_DEPTH) { + if (mDepthOutputFormats.indexOfKey(internalFormat) >= 0) { + return format; + } + } else { + if (mAllOutputFormats.indexOfKey(internalFormat) >= 0) { + return format; + } + } + } else { + if (mInputFormats.indexOfKey(internalFormat) >= 0) { return format; } } @@ -1175,7 +1234,7 @@ public final class StreamConfigurationMap { return formats; } - private Size[] getPublicFormatSizes(int format, boolean output) { + private Size[] getPublicFormatSizes(int format, boolean output, boolean highRes) { try { checkArgumentFormatSupported(format, output); } catch (IllegalArgumentException e) { @@ -1185,36 +1244,57 @@ public final class StreamConfigurationMap { int internalFormat = imageFormatToInternal(format); int dataspace = imageFormatToDataspace(format); - return getInternalFormatSizes(internalFormat, dataspace, output); + return getInternalFormatSizes(internalFormat, dataspace, output, highRes); } - private Size[] getInternalFormatSizes(int format, int dataspace, boolean output) { - - HashMap<Integer, Integer> formatsMap = - (dataspace == HAL_DATASPACE_DEPTH) ? mDepthOutputFormats : getFormatsMap(output); - - Integer sizesCount = formatsMap.get(format); - if (sizesCount == null) { + private Size[] getInternalFormatSizes(int format, int dataspace, + boolean output, boolean highRes) { + SparseIntArray formatsMap = + !output ? mInputFormats : + dataspace == HAL_DATASPACE_DEPTH ? mDepthOutputFormats : + highRes ? mHighResOutputFormats : + mOutputFormats; + + int sizesCount = formatsMap.get(format); + if ( ((!output || dataspace == HAL_DATASPACE_DEPTH) && sizesCount == 0) || + (output && dataspace != HAL_DATASPACE_DEPTH && mAllOutputFormats.get(format) == 0)) { + // Only throw if this is really not supported at all throw new IllegalArgumentException("format not available"); } - int len = sizesCount; - Size[] sizes = new Size[len]; + Size[] sizes = new Size[sizesCount]; int sizeIndex = 0; StreamConfiguration[] configurations = (dataspace == HAL_DATASPACE_DEPTH) ? mDepthConfigurations : mConfigurations; - for (StreamConfiguration config : configurations) { - if (config.getFormat() == format && config.isOutput() == output) { + int fmt = config.getFormat(); + if (fmt == format && config.isOutput() == output) { + if (output) { + // Filter slow high-res output formats; include for + // highRes, remove for !highRes + long duration = 0; + for (int i = 0; i < mMinFrameDurations.length; i++) { + StreamConfigurationDuration d = mMinFrameDurations[i]; + if (d.getFormat() == fmt && + d.getWidth() == config.getSize().getWidth() && + d.getHeight() == config.getSize().getHeight()) { + duration = d.getDuration(); + break; + } + } + if (highRes != (duration > DURATION_20FPS_NS)) { + continue; + } + } sizes[sizeIndex++] = config.getSize(); } } - if (sizeIndex != len) { + if (sizeIndex != sizesCount) { throw new AssertionError( - "Too few sizes (expected " + len + ", actual " + sizeIndex + ")"); + "Too few sizes (expected " + sizesCount + ", actual " + sizeIndex + ")"); } return sizes; @@ -1226,14 +1306,16 @@ public final class StreamConfigurationMap { int i = 0; - for (int format : getFormatsMap(output).keySet()) { + SparseIntArray map = getFormatsMap(output); + for (int j = 0; j < map.size(); j++) { + int format = map.keyAt(j); if (format != HAL_PIXEL_FORMAT_RAW_OPAQUE) { formats[i++] = imageFormatToPublic(format); } } if (output) { - for (int format : mDepthOutputFormats.keySet()) { - formats[i++] = depthFormatToPublic(format); + for (int j = 0; j < mDepthOutputFormats.size(); j++) { + formats[i++] = depthFormatToPublic(mDepthOutputFormats.keyAt(j)); } } if (formats.length != i) { @@ -1244,14 +1326,14 @@ public final class StreamConfigurationMap { } /** Get the format -> size count map for either output or input formats */ - private HashMap<Integer, Integer> getFormatsMap(boolean output) { - return output ? mOutputFormats : mInputFormats; + private SparseIntArray getFormatsMap(boolean output) { + return output ? mAllOutputFormats : mInputFormats; } private long getInternalFormatDuration(int format, int dataspace, Size size, int duration) { // assume format is already checked, since its internal - if (!arrayContains(getInternalFormatSizes(format, dataspace, /*output*/true), size)) { + if (!isSupportedInternalConfiguration(format, dataspace, size)) { throw new IllegalArgumentException("size was not supported"); } @@ -1289,10 +1371,9 @@ public final class StreamConfigurationMap { /** Count the number of publicly-visible output formats */ private int getPublicFormatCount(boolean output) { - HashMap<Integer, Integer> formatsMap = getFormatsMap(output); - + SparseIntArray formatsMap = getFormatsMap(output); int size = formatsMap.size(); - if (formatsMap.containsKey(HAL_PIXEL_FORMAT_RAW_OPAQUE)) { + if (formatsMap.indexOfKey(HAL_PIXEL_FORMAT_RAW_OPAQUE) >= 0) { size -= 1; } if (output) { @@ -1316,6 +1397,21 @@ public final class StreamConfigurationMap { return false; } + private boolean isSupportedInternalConfiguration(int format, int dataspace, + Size size) { + StreamConfiguration[] configurations = + (dataspace == HAL_DATASPACE_DEPTH) ? mDepthConfigurations : mConfigurations; + + for (int i = 0; i < configurations.length; i++) { + if (configurations[i].getFormat() == format && + configurations[i].getSize().equals(size)) { + return true; + } + } + + return false; + } + /** * Return this {@link StreamConfigurationMap} as a string representation. * @@ -1351,6 +1447,8 @@ public final class StreamConfigurationMap { StringBuilder sb = new StringBuilder("StreamConfiguration("); appendOutputsString(sb); sb.append(", "); + appendHighResOutputsString(sb); + sb.append(", "); appendInputsString(sb); sb.append(", "); appendValidOutputFormatsForInputString(sb); @@ -1381,6 +1479,27 @@ public final class StreamConfigurationMap { sb.append(")"); } + private void appendHighResOutputsString(StringBuilder sb) { + sb.append("HighResolutionOutputs("); + int[] formats = getOutputFormats(); + for (int format : formats) { + Size[] sizes = getHighResolutionOutputSizes(format); + if (sizes == null) continue; + for (Size size : sizes) { + long minFrameDuration = getOutputMinFrameDuration(format, size); + long stallDuration = getOutputStallDuration(format, size); + sb.append(String.format("[w:%d, h:%d, format:%s(%d), min_duration:%d, " + + "stall:%d], ", size.getWidth(), size.getHeight(), formatToString(format), + format, minFrameDuration, stallDuration)); + } + } + // Remove the pending ", " + if (sb.charAt(sb.length() - 1) == ' ') { + sb.delete(sb.length() - 2, sb.length()); + } + sb.append(")"); + } + private void appendInputsString(StringBuilder sb) { sb.append("Inputs("); int[] formats = getInputFormats(); @@ -1479,15 +1598,21 @@ public final class StreamConfigurationMap { } // from system/core/include/system/graphics.h + private static final int HAL_PIXEL_FORMAT_RAW16 = 0x20; private static final int HAL_PIXEL_FORMAT_BLOB = 0x21; private static final int HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED = 0x22; + private static final int HAL_PIXEL_FORMAT_YCbCr_420_888 = 0x23; private static final int HAL_PIXEL_FORMAT_RAW_OPAQUE = 0x24; + private static final int HAL_PIXEL_FORMAT_RAW10 = 0x25; + private static final int HAL_PIXEL_FORMAT_RAW12 = 0x26; private static final int HAL_PIXEL_FORMAT_Y16 = 0x20363159; + private static final int HAL_DATASPACE_UNKNOWN = 0x0; private static final int HAL_DATASPACE_JFIF = 0x101; private static final int HAL_DATASPACE_DEPTH = 0x1000; + private static final long DURATION_20FPS_NS = 50000000L; /** * @see #getDurations(int, int) */ @@ -1505,15 +1630,20 @@ public final class StreamConfigurationMap { private final HighSpeedVideoConfiguration[] mHighSpeedVideoConfigurations; private final ReprocessFormatsMap mInputOutputFormatsMap; - /** ImageFormat -> num output sizes mapping */ - private final HashMap</*ImageFormat*/Integer, /*Count*/Integer> mOutputFormats = - new HashMap<Integer, Integer>(); - /** ImageFormat -> num input sizes mapping */ - private final HashMap</*ImageFormat*/Integer, /*Count*/Integer> mInputFormats = - new HashMap<Integer, Integer>(); - /** ImageFormat -> num depth output sizes mapping */ - private final HashMap</*ImageFormat*/Integer, /*Count*/Integer> mDepthOutputFormats = - new HashMap<Integer, Integer>(); + private final boolean mListHighResolution; + + /** internal format -> num output sizes mapping, not including slow high-res sizes, for + * non-depth dataspaces */ + private final SparseIntArray mOutputFormats = new SparseIntArray(); + /** internal format -> num output sizes mapping for slow high-res sizes, for non-depth + * dataspaces */ + private final SparseIntArray mHighResOutputFormats = new SparseIntArray(); + /** internal format -> num output sizes mapping for all non-depth dataspaces */ + private final SparseIntArray mAllOutputFormats = new SparseIntArray(); + /** internal format -> num input sizes mapping, for input reprocessing formats */ + private final SparseIntArray mInputFormats = new SparseIntArray(); + /** internal format -> num depth output sizes mapping, for HAL_DATASPACE_DEPTH */ + private final SparseIntArray mDepthOutputFormats = new SparseIntArray(); /** High speed video Size -> FPS range count mapping*/ private final HashMap</*HighSpeedVideoSize*/Size, /*Count*/Integer> mHighSpeedVideoSizeMap = new HashMap<Size, Integer>(); @@ -1522,4 +1652,3 @@ public final class StreamConfigurationMap { mHighSpeedVideoFpsRangeMap = new HashMap<Range<Integer>, Integer>(); } - diff --git a/core/java/android/hardware/camera2/params/TonemapCurve.java b/core/java/android/hardware/camera2/params/TonemapCurve.java index 398a7e91a53d..2d7bbaa21c54 100644 --- a/core/java/android/hardware/camera2/params/TonemapCurve.java +++ b/core/java/android/hardware/camera2/params/TonemapCurve.java @@ -277,7 +277,7 @@ public final class TonemapCurve { return mHashCode; } - mHashCode = HashCodeHelpers.hashCode(mRed, mGreen, mBlue); + mHashCode = HashCodeHelpers.hashCodeGeneric(mRed, mGreen, mBlue); mHashCalculated = true; return mHashCode; diff --git a/core/java/android/hardware/camera2/utils/HashCodeHelpers.java b/core/java/android/hardware/camera2/utils/HashCodeHelpers.java index 7b4aa09f86ff..731da8b6a721 100644 --- a/core/java/android/hardware/camera2/utils/HashCodeHelpers.java +++ b/core/java/android/hardware/camera2/utils/HashCodeHelpers.java @@ -30,7 +30,7 @@ public final class HashCodeHelpers { * * @return the numeric hash code */ - public static int hashCode(int[] array) { + public static int hashCode(int... array) { if (array == null) { return 0; } @@ -60,7 +60,7 @@ public final class HashCodeHelpers { * * @return the numeric hash code */ - public static int hashCode(float[] array) { + public static int hashCode(float... array) { if (array == null) { return 0; } @@ -83,7 +83,7 @@ public final class HashCodeHelpers { * * @return the numeric hash code */ - public static <T> int hashCode(T[] array) { + public static <T> int hashCodeGeneric(T... array) { if (array == null) { return 0; } @@ -97,56 +97,4 @@ public final class HashCodeHelpers { return h; } - public static <T> int hashCode(T a) { - return (a == null) ? 0 : a.hashCode(); - } - - public static <T> int hashCode(T a, T b) { - int h = hashCode(a); - - int x = (b == null) ? 0 : b.hashCode(); - h = ((h << 5) - h) ^ x; // (h * 31) XOR x - - return h; - } - - public static <T> int hashCode(T a, T b, T c) { - int h = hashCode(a, b); - - int x = (c == null) ? 0 : c.hashCode(); - h = ((h << 5) - h) ^ x; // (h * 31) XOR x - - return h; - } - - public static <T> int hashCode(T a, T b, T c, T d) { - int h = hashCode(a, b, c); - - int x = (d == null) ? 0 : d.hashCode(); - h = ((h << 5) - h) ^ x; // (h * 31) XOR x - - return h; - } - - public static int hashCode(int x) { - return hashCode(new int[] { x } ); - } - - public static int hashCode(int x, int y) { - return hashCode(new int[] { x, y } ); - } - - public static int hashCode(int x, int y, int z) { - return hashCode(new int[] { x, y, z } ); - } - - public static int hashCode(int x, int y, int z, int w) { - return hashCode(new int[] { x, y, z, w } ); - } - - public static int hashCode(int x, int y, int z, int w, int t) { - return hashCode(new int[] { x, y, z, w, t } ); - } - - } diff --git a/core/java/android/util/Range.java b/core/java/android/util/Range.java index 211d01a9e2ef..55245065c082 100644 --- a/core/java/android/util/Range.java +++ b/core/java/android/util/Range.java @@ -350,7 +350,7 @@ public final class Range<T extends Comparable<? super T>> { */ @Override public int hashCode() { - return HashCodeHelpers.hashCode(mLower, mUpper); + return HashCodeHelpers.hashCodeGeneric(mLower, mUpper); } private final T mLower; |