summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYin-Chia Yeh <yinchiayeh@google.com>2014-07-15 10:37:31 -0700
committerYin-Chia Yeh <yinchiayeh@google.com>2014-07-18 16:00:53 -0700
commit12da140082323d9aa048b3e928505a0a2adfdda7 (patch)
treeed8d6f11bc72817b7f9f69c6d8b3c4d2c5764109
parenta4ab780877808dbee334f7c7cc4acefa0aa313b2 (diff)
downloadframeworks_base-12da140082323d9aa048b3e928505a0a2adfdda7.zip
frameworks_base-12da140082323d9aa048b3e928505a0a2adfdda7.tar.gz
frameworks_base-12da140082323d9aa048b3e928505a0a2adfdda7.tar.bz2
Camera2: add highSpeedVideoConfig wrapper and APIs
- Add wrapper class for highSpeedVideoConfiguration. - Add APIs to query high speed video recording configurations in StreamConfigurationMap - Fix ColorSpaceTransform unit test in CameraMetadataTest - Fix a bug in HashCodeHelper Change-Id: I192e57f6ab5dfbba6d958571352f067a9eaec7b2
-rw-r--r--api/current.txt4
-rw-r--r--core/java/android/hardware/camera2/CameraCharacteristics.java8
-rw-r--r--core/java/android/hardware/camera2/impl/CameraMetadataNative.java8
-rw-r--r--core/java/android/hardware/camera2/marshal/impl/MarshalQueryableHighSpeedVideoConfiguration.java83
-rw-r--r--core/java/android/hardware/camera2/params/HighSpeedVideoConfiguration.java157
-rw-r--r--core/java/android/hardware/camera2/params/StreamConfigurationMap.java193
-rw-r--r--core/java/android/hardware/camera2/utils/HashCodeHelpers.java11
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java30
8 files changed, 483 insertions, 11 deletions
diff --git a/api/current.txt b/api/current.txt
index 623c281..2c07d55 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -12946,6 +12946,10 @@ package android.hardware.camera2.params {
}
public final class StreamConfigurationMap {
+ 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();
+ method public android.util.Size[] getHighSpeedVideoSizesFor(android.util.Range<java.lang.Integer>);
method public final int[] getOutputFormats();
method public long getOutputMinFrameDuration(int, android.util.Size);
method public long getOutputMinFrameDuration(java.lang.Class<T>, android.util.Size);
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 4b1659f..f2553b19 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -494,7 +494,9 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
* to do high speed recording, it can select the maximum size reported by this metadata to
* configure output streams. Once the size is selected, application can filter this metadata
* by selected size and get the supported fps ranges, and use these fps ranges to setup the
- * recording requests.</p>
+ * recording requests. Note that for the use case of multiple output streams, application
+ * must select one unique size from this metadata to use. Otherwise a request error might
+ * occur.</p>
* <p>For normal video recording use case, where some application will NOT set
* {@link CaptureRequest#CONTROL_SCENE_MODE android.control.sceneMode} to HIGH_SPEED_VIDEO in capture requests, the fps ranges
* reported in this metadata must not be used to setup capture requests, or it will cause
@@ -504,8 +506,8 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
* @see CaptureRequest#CONTROL_SCENE_MODE
* @hide
*/
- public static final Key<int[]> CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS =
- new Key<int[]>("android.control.availableHighSpeedVideoConfigurations", int[].class);
+ public static final Key<android.hardware.camera2.params.HighSpeedVideoConfiguration[]> CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS =
+ new Key<android.hardware.camera2.params.HighSpeedVideoConfiguration[]>("android.control.availableHighSpeedVideoConfigurations", android.hardware.camera2.params.HighSpeedVideoConfiguration[].class);
/**
* <p>The set of edge enhancement modes supported by this camera device.</p>
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index 6de5c25..5f87efb 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -30,6 +30,7 @@ import android.hardware.camera2.marshal.impl.MarshalQueryableBoolean;
import android.hardware.camera2.marshal.impl.MarshalQueryableBlackLevelPattern;
import android.hardware.camera2.marshal.impl.MarshalQueryableColorSpaceTransform;
import android.hardware.camera2.marshal.impl.MarshalQueryableEnum;
+import android.hardware.camera2.marshal.impl.MarshalQueryableHighSpeedVideoConfiguration;
import android.hardware.camera2.marshal.impl.MarshalQueryableMeteringRectangle;
import android.hardware.camera2.marshal.impl.MarshalQueryableNativeByteToInteger;
import android.hardware.camera2.marshal.impl.MarshalQueryablePair;
@@ -45,6 +46,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.Face;
+import android.hardware.camera2.params.HighSpeedVideoConfiguration;
import android.hardware.camera2.params.LensShadingMap;
import android.hardware.camera2.params.StreamConfiguration;
import android.hardware.camera2.params.StreamConfigurationDuration;
@@ -665,8 +667,11 @@ public class CameraMetadataNative implements Parcelable {
CameraCharacteristics.SCALER_AVAILABLE_MIN_FRAME_DURATIONS);
StreamConfigurationDuration[] stallDurations = getBase(
CameraCharacteristics.SCALER_AVAILABLE_STALL_DURATIONS);
+ HighSpeedVideoConfiguration[] highSpeedVideoConfigurations = getBase(
+ CameraCharacteristics.CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS);
- return new StreamConfigurationMap(configurations, minFrameDurations, stallDurations);
+ return new StreamConfigurationMap(
+ configurations, minFrameDurations, stallDurations, highSpeedVideoConfigurations);
}
private <T> Integer getMaxRegions(Key<T> key) {
@@ -1015,6 +1020,7 @@ public class CameraMetadataNative implements Parcelable {
new MarshalQueryableStreamConfigurationDuration(),
new MarshalQueryableRggbChannelVector(),
new MarshalQueryableBlackLevelPattern(),
+ new MarshalQueryableHighSpeedVideoConfiguration(),
// generic parcelable marshaler (MUST BE LAST since it has lowest priority)
new MarshalQueryableParcelable(),
diff --git a/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableHighSpeedVideoConfiguration.java b/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableHighSpeedVideoConfiguration.java
new file mode 100644
index 0000000..c03144b
--- /dev/null
+++ b/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableHighSpeedVideoConfiguration.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2014 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.marshal.impl;
+
+import android.hardware.camera2.marshal.Marshaler;
+import android.hardware.camera2.marshal.MarshalQueryable;
+import android.hardware.camera2.params.HighSpeedVideoConfiguration;
+import android.hardware.camera2.utils.TypeReference;
+
+import static android.hardware.camera2.impl.CameraMetadataNative.*;
+import static android.hardware.camera2.marshal.MarshalHelpers.*;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Marshaler for {@code android.control.availableHighSpeedVideoConfigurations} custom class
+ * {@link HighSpeedVideoConfiguration}
+ *
+ * <p>Data is stored as {@code (width, height, fpsMin, fpsMax)} tuples (int32).</p>
+ */
+public class MarshalQueryableHighSpeedVideoConfiguration
+ implements MarshalQueryable<HighSpeedVideoConfiguration> {
+ private static final int SIZE = SIZEOF_INT32 * 4;
+
+ private class MarshalerHighSpeedVideoConfiguration
+ extends Marshaler<HighSpeedVideoConfiguration> {
+ protected MarshalerHighSpeedVideoConfiguration(
+ TypeReference<HighSpeedVideoConfiguration> typeReference,
+ int nativeType) {
+ super(MarshalQueryableHighSpeedVideoConfiguration.this, typeReference, nativeType);
+ }
+
+ @Override
+ public void marshal(HighSpeedVideoConfiguration value, ByteBuffer buffer) {
+ buffer.putInt(value.getWidth());
+ buffer.putInt(value.getHeight());
+ buffer.putInt(value.getFpsMin());
+ buffer.putInt(value.getFpsMax());
+ }
+
+ @Override
+ public HighSpeedVideoConfiguration unmarshal(ByteBuffer buffer) {
+ int width = buffer.getInt();
+ int height = buffer.getInt();
+ int fpsMin = buffer.getInt();
+ int fpsMax = buffer.getInt();
+
+ return new HighSpeedVideoConfiguration(width, height, fpsMin, fpsMax);
+ }
+
+ @Override
+ public int getNativeSize() {
+ return SIZE;
+ }
+
+ }
+
+ @Override
+ public Marshaler<HighSpeedVideoConfiguration> createMarshaler(
+ TypeReference<HighSpeedVideoConfiguration> managedType, int nativeType) {
+ return new MarshalerHighSpeedVideoConfiguration(managedType, nativeType);
+ }
+
+ @Override
+ public boolean isTypeMappingSupported(TypeReference<HighSpeedVideoConfiguration> managedType,
+ int nativeType) {
+ return nativeType == TYPE_INT32 &&
+ managedType.getType().equals(HighSpeedVideoConfiguration.class);
+ }
+}
diff --git a/core/java/android/hardware/camera2/params/HighSpeedVideoConfiguration.java b/core/java/android/hardware/camera2/params/HighSpeedVideoConfiguration.java
new file mode 100644
index 0000000..088049f
--- /dev/null
+++ b/core/java/android/hardware/camera2/params/HighSpeedVideoConfiguration.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2014 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 static com.android.internal.util.Preconditions.*;
+
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.utils.HashCodeHelpers;
+import android.util.Range;
+import android.util.Size;
+
+/**
+ * Immutable class to store the available
+ * {@link CameraCharacteristics#CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS high speed video
+ * configurations}
+ *
+ * @see CameraCharacteristics#CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS
+ *
+ * @hide
+ */
+public final class HighSpeedVideoConfiguration {
+
+ /**
+ * Create a new {@link HighSpeedVideoConfiguration}.
+ *
+ * @param width image width, in pixels (positive)
+ * @param height image height, in pixels (positive)
+ * @param fpsMin minimum frames per second for the configuration (positive)
+ * @param fpsMax maximum frames per second for the configuration (larger or equal to 60)
+ *
+ * @throws IllegalArgumentException
+ * if width/height/fpsMin were not positive or fpsMax less than 60
+ *
+ * @hide
+ */
+ public HighSpeedVideoConfiguration(
+ final int width, final int height, final int fpsMin, final int fpsMax) {
+ if (fpsMax < 60) {
+ throw new IllegalArgumentException("fpsMax must be at least 60");
+ }
+ mFpsMax = fpsMax;
+ mWidth = checkArgumentPositive(width, "width must be positive");
+ mHeight = checkArgumentPositive(height, "height must be positive");
+ mFpsMin = checkArgumentPositive(fpsMin, "fpsMin must be positive");
+ mSize = new Size(mWidth, mHeight);
+ mFpsRange = new Range<Integer>(mFpsMin, mFpsMax);
+ }
+
+ /**
+ * Return the width of the high speed video configuration.
+ *
+ * @return width > 0
+ */
+ public int getWidth() {
+ return mWidth;
+ }
+
+ /**
+ * Return the height of the high speed video configuration.
+ *
+ * @return height > 0
+ */
+ public int getHeight() {
+ return mHeight;
+ }
+
+ /**
+ * Return the minimum frame per second of the high speed video configuration.
+ *
+ * @return fpsMin > 0
+ */
+ public int getFpsMin() {
+ return mFpsMin;
+ }
+
+ /**
+ * Return the maximum frame per second of the high speed video configuration.
+ *
+ * @return fpsMax >= 60
+ */
+ public int getFpsMax() {
+ return mFpsMax;
+ }
+
+ /**
+ * Convenience method to return the size of this high speed video configuration.
+ *
+ * @return a Size with positive width and height
+ */
+ public Size getSize() {
+ return mSize;
+ }
+
+ /**
+ * Convenience method to return the FPS range of this high speed video configuration.
+ *
+ * @return a Range with high bound >= 60
+ */
+ public Range<Integer> getFpsRange() {
+ return mFpsRange;
+ }
+
+ /**
+ * Check if this {@link HighSpeedVideoConfiguration} is equal to another
+ * {@link HighSpeedVideoConfiguration}.
+ *
+ * <p>Two configurations are equal if and only if each of the respective elements is equal.</p>
+ *
+ * @return {@code true} if the objects were equal, {@code false} otherwise
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof HighSpeedVideoConfiguration) {
+ final HighSpeedVideoConfiguration other = (HighSpeedVideoConfiguration) obj;
+ return mWidth == other.mWidth &&
+ mHeight == other.mHeight &&
+ mFpsMin == other.mFpsMin &&
+ mFpsMax == other.mFpsMax;
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ return HashCodeHelpers.hashCode(mWidth, mHeight, mFpsMin, mFpsMax);
+ }
+
+ private final int mWidth;
+ private final int mHeight;
+ private final int mFpsMin;
+ private final int mFpsMax;
+ private final Size mSize;
+ private final Range<Integer> mFpsRange;
+}
diff --git a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
index 8385d63..8c30fd4 100644
--- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
+++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
@@ -24,6 +24,7 @@ import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.utils.HashCodeHelpers;
import android.view.Surface;
import android.util.Log;
+import android.util.Range;
import android.util.Size;
import java.util.Arrays;
@@ -78,19 +79,29 @@ public final class StreamConfigurationMap {
* @param configurations a non-{@code null} array of {@link StreamConfiguration}
* @param minFrameDurations a non-{@code null} array of {@link StreamConfigurationDuration}
* @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
*
- * @throws NullPointerException if any of the arguments or subelements were {@code null}
+ * @throws NullPointerException if any of the arguments except highSpeedVideoConfigurations
+ * were {@code null} or any subelements were {@code null}
*
* @hide
*/
public StreamConfigurationMap(
StreamConfiguration[] configurations,
StreamConfigurationDuration[] minFrameDurations,
- StreamConfigurationDuration[] stallDurations) {
+ StreamConfigurationDuration[] stallDurations,
+ HighSpeedVideoConfiguration[] highSpeedVideoConfigurations) {
mConfigurations = checkArrayElementsNotNull(configurations, "configurations");
mMinFrameDurations = checkArrayElementsNotNull(minFrameDurations, "minFrameDurations");
mStallDurations = checkArrayElementsNotNull(stallDurations, "stallDurations");
+ if (highSpeedVideoConfigurations == null) {
+ mHighSpeedVideoConfigurations = new HighSpeedVideoConfiguration[0];
+ } else {
+ mHighSpeedVideoConfigurations = checkArrayElementsNotNull(
+ highSpeedVideoConfigurations, "highSpeedVideoConfigurations");
+ }
// For each format, track how many sizes there are available to configure
for (StreamConfiguration config : configurations) {
@@ -110,6 +121,22 @@ public final class StreamConfigurationMap {
throw new AssertionError(
"At least one stream configuration for IMPLEMENTATION_DEFINED must exist");
}
+
+ // For each Size/FPS range, track how many FPS range/Size there are available
+ for (HighSpeedVideoConfiguration config : mHighSpeedVideoConfigurations) {
+ Size size = config.getSize();
+ Range<Integer> fpsRange = config.getFpsRange();
+ Integer fpsRangeCount = mHighSpeedVideoSizeMap.get(size);
+ if (fpsRangeCount == null) {
+ fpsRangeCount = 0;
+ }
+ mHighSpeedVideoSizeMap.put(size, fpsRangeCount + 1);
+ Integer sizeCount = mHighSpeedVideoFpsRangeMap.get(fpsRange);
+ if (sizeCount == null) {
+ sizeCount = 0;
+ }
+ mHighSpeedVideoFpsRangeMap.put(fpsRange, sizeCount + 1);
+ }
}
/**
@@ -343,6 +370,153 @@ public final class StreamConfigurationMap {
}
/**
+ * Get a list of supported high speed video recording sizes.
+ *
+ * <p> When HIGH_SPEED_VIDEO is supported in
+ * {@link CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES available scene modes}, this
+ * method will list the supported high speed video size configurations. All the sizes listed
+ * will be a subset of the sizes reported by {@link #getOutputSizes} for processed non-stalling
+ * formats (typically ImageFormat#YUV_420_888, ImageFormat#NV21, ImageFormat#YV12)</p>
+ *
+ * <p> To enable high speed video recording, application must set
+ * {@link CaptureRequest#CONTROL_SCENE_MODE} to
+ * {@link CaptureRequest#CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO HIGH_SPEED_VIDEO} in capture
+ * requests and select the video size from this method and
+ * {@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE FPS range} from
+ * {@link #getHighSpeedVideoFpsRangesFor} to configure the recording and preview streams and
+ * setup the recording requests. For example, if the application intends to do high speed
+ * recording, it can select the maximum size reported by this method to configure output
+ * streams. Note that for the use case of multiple output streams, application must select one
+ * unique size from this method to use. Otherwise a request error might occur. Once the size is
+ * selected, application can get the supported FPS ranges by
+ * {@link #getHighSpeedVideoFpsRangesFor}, and use these FPS ranges to setup the recording
+ * requests.</p>
+ *
+ * @return
+ * an array of supported high speed video recording sizes
+ *
+ * @see #getHighSpeedVideoFpsRangesFor(Size)
+ */
+ public Size[] getHighSpeedVideoSizes() {
+ return (Size[]) mHighSpeedVideoSizeMap.keySet().toArray();
+ }
+
+ /**
+ * Get the frame per second ranges (fpsMin, fpsMax) for input high speed video size.
+ *
+ * <p> See {@link #getHighSpeedVideoSizes} for how to enable high speed recording.</p>
+ *
+ * <p> For normal video recording use case, where some application will NOT set
+ * {@link CaptureRequest#CONTROL_SCENE_MODE} to
+ * {@link CaptureRequest#CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO HIGH_SPEED_VIDEO} in capture
+ * requests, the {@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE FPS ranges} reported in
+ * this method must not be used to setup capture requests, or it will cause request error.</p>
+ *
+ * @param size one of the sizes returned by {@link #getHighSpeedVideoSizes()}
+ * @return
+ * An array of FPS range to use with
+ * {@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE TARGET_FPS_RANGE} when using
+ * {@link CaptureRequest#CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO HIGH_SPEED_VIDEO} scene
+ * mode.
+ * The upper bound of returned ranges is guaranteed to be larger or equal to 60.
+ *
+ * @throws IllegalArgumentException if input size does not exist in the return value of
+ * getHighSpeedVideoSizes
+ * @see #getHighSpeedVideoSizes()
+ */
+ public Range<Integer>[] getHighSpeedVideoFpsRangesFor(Size size) {
+ Integer fpsRangeCount = mHighSpeedVideoSizeMap.get(size);
+ if (fpsRangeCount == null || fpsRangeCount == 0) {
+ throw new IllegalArgumentException(String.format(
+ "Size %s does not support high speed video recording", size));
+ }
+
+ @SuppressWarnings("unchecked")
+ Range<Integer>[] fpsRanges = new Range[fpsRangeCount];
+ int i = 0;
+ for (HighSpeedVideoConfiguration config : mHighSpeedVideoConfigurations) {
+ if (size.equals(config.getSize())) {
+ fpsRanges[i++] = config.getFpsRange();
+ }
+ }
+ return fpsRanges;
+ }
+
+ /**
+ * Get a list of supported high speed video recording FPS ranges.
+ *
+ * <p> When HIGH_SPEED_VIDEO is supported in
+ * {@link CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES available scene modes}, this
+ * method will list the supported high speed video FPS range configurations. Application can
+ * then use {@link #getHighSpeedVideoSizesFor} to query available sizes for one of returned
+ * FPS range.</p>
+ *
+ * <p> To enable high speed video recording, application must set
+ * {@link CaptureRequest#CONTROL_SCENE_MODE} to
+ * {@link CaptureRequest#CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO HIGH_SPEED_VIDEO} in capture
+ * requests and select the video size from {@link #getHighSpeedVideoSizesFor} and
+ * {@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE FPS range} from
+ * this method to configure the recording and preview streams and setup the recording requests.
+ * For example, if the application intends to do high speed recording, it can select one FPS
+ * range reported by this method, query the video sizes corresponding to this FPS range by
+ * {@link #getHighSpeedVideoSizesFor} and select one of reported sizes to configure output
+ * streams. Note that for the use case of multiple output streams, application must select one
+ * unique size from {@link #getHighSpeedVideoSizesFor}, and use it for all output streams.
+ * Otherwise a request error might occur when attempting to enable
+ * {@link CaptureRequest#CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO HIGH_SPEED_VIDEO}.
+ * Once the stream is configured, application can set the FPS range in the recording requests.
+ * </p>
+ *
+ * @return
+ * an array of supported high speed video recording FPS ranges
+ * The upper bound of returned ranges is guaranteed to be larger or equal to 60.
+ *
+ * @see #getHighSpeedVideoSizesFor
+ */
+ @SuppressWarnings("unchecked")
+ public Range<Integer>[] getHighSpeedVideoFpsRanges() {
+ return (Range<Integer>[]) mHighSpeedVideoFpsRangeMap.keySet().toArray();
+ }
+
+ /**
+ * Get the supported video sizes for input FPS range.
+ *
+ * <p> See {@link #getHighSpeedVideoFpsRanges} for how to enable high speed recording.</p>
+ *
+ * <p> For normal video recording use case, where the application will NOT set
+ * {@link CaptureRequest#CONTROL_SCENE_MODE} to
+ * {@link CaptureRequest#CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO HIGH_SPEED_VIDEO} in capture
+ * requests, the {@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE FPS ranges} reported in
+ * this method must not be used to setup capture requests, or it will cause request error.</p>
+ *
+ * @param fpsRange one of the FPS range returned by {@link #getHighSpeedVideoFpsRanges()}
+ * @return
+ * An array of video sizes to configure output stream when using
+ * {@link CaptureRequest#CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO HIGH_SPEED_VIDEO} scene
+ * mode.
+ *
+ * @throws IllegalArgumentException if input FPS range does not exist in the return value of
+ * getHighSpeedVideoFpsRanges
+ * @see #getHighSpeedVideoFpsRanges()
+ */
+ public Size[] getHighSpeedVideoSizesFor(Range<Integer> fpsRange) {
+ Integer sizeCount = mHighSpeedVideoFpsRangeMap.get(fpsRange);
+ if (sizeCount == null || sizeCount == 0) {
+ throw new IllegalArgumentException(String.format(
+ "FpsRange %s does not support high speed video recording", fpsRange));
+ }
+
+ Size[] sizes = new Size[sizeCount];
+ int i = 0;
+ for (HighSpeedVideoConfiguration config : mHighSpeedVideoConfigurations) {
+ if (fpsRange.equals(config.getFpsRange())) {
+ sizes[i++] = config.getSize();
+ }
+ }
+ return sizes;
+ }
+
+ /**
* Get the minimum {@link CaptureRequest#SENSOR_FRAME_DURATION frame duration}
* for the format/size combination (in nanoseconds).
*
@@ -587,7 +761,9 @@ public final class StreamConfigurationMap {
// XX: do we care about order?
return Arrays.equals(mConfigurations, other.mConfigurations) &&
Arrays.equals(mMinFrameDurations, other.mMinFrameDurations) &&
- Arrays.equals(mStallDurations, other.mStallDurations);
+ Arrays.equals(mStallDurations, other.mStallDurations) &&
+ Arrays.equals(mHighSpeedVideoConfigurations,
+ other.mHighSpeedVideoConfigurations);
}
return false;
}
@@ -598,7 +774,9 @@ public final class StreamConfigurationMap {
@Override
public int hashCode() {
// XX: do we care about order?
- return HashCodeHelpers.hashCode(mConfigurations, mMinFrameDurations, mStallDurations);
+ return HashCodeHelpers.hashCode(
+ mConfigurations, mMinFrameDurations,
+ mStallDurations, mHighSpeedVideoConfigurations);
}
// Check that the argument is supported by #getOutputFormats or #getInputFormats
@@ -956,6 +1134,7 @@ public final class StreamConfigurationMap {
private final StreamConfiguration[] mConfigurations;
private final StreamConfigurationDuration[] mMinFrameDurations;
private final StreamConfigurationDuration[] mStallDurations;
+ private final HighSpeedVideoConfiguration[] mHighSpeedVideoConfigurations;
/** ImageFormat -> num output sizes mapping */
private final HashMap</*ImageFormat*/Integer, /*Count*/Integer> mOutputFormats =
@@ -963,5 +1142,11 @@ public final class StreamConfigurationMap {
/** ImageFormat -> num input sizes mapping */
private final HashMap</*ImageFormat*/Integer, /*Count*/Integer> mInputFormats =
new HashMap<Integer, Integer>();
+ /** High speed video Size -> FPS range count mapping*/
+ private final HashMap</*HighSpeedVideoSize*/Size, /*Count*/Integer> mHighSpeedVideoSizeMap =
+ new HashMap<Size, Integer>();
+ /** High speed video FPS range -> Size count mapping*/
+ private final HashMap</*HighSpeedVideoFpsRange*/Range<Integer>, /*Count*/Integer>
+ mHighSpeedVideoFpsRangeMap = new HashMap<Range<Integer>, Integer>();
}
diff --git a/core/java/android/hardware/camera2/utils/HashCodeHelpers.java b/core/java/android/hardware/camera2/utils/HashCodeHelpers.java
index b980549..7b4aa09 100644
--- a/core/java/android/hardware/camera2/utils/HashCodeHelpers.java
+++ b/core/java/android/hardware/camera2/utils/HashCodeHelpers.java
@@ -113,7 +113,16 @@ public final class HashCodeHelpers {
public static <T> int hashCode(T a, T b, T c) {
int h = hashCode(a, b);
- int x = (a == null) ? 0 : a.hashCode();
+ 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;
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
index ef06d2c..29c3c75 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
@@ -36,6 +36,7 @@ import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.marshal.impl.MarshalQueryableEnum;
import android.hardware.camera2.params.ColorSpaceTransform;
import android.hardware.camera2.params.Face;
+import android.hardware.camera2.params.HighSpeedVideoConfiguration;
import android.hardware.camera2.params.MeteringRectangle;
import android.hardware.camera2.params.ReprocessFormatsMap;
import android.hardware.camera2.params.RggbChannelVector;
@@ -51,7 +52,6 @@ import static com.android.mediaframeworktest.unit.ByteArrayHelpers.*;
import java.lang.reflect.Array;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
-import java.util.Arrays;
import java.util.List;
/**
@@ -730,6 +730,32 @@ public class CameraMetadataTest extends junit.framework.TestCase {
}
@SmallTest
+ public void testReadWriteHighSpeedVideoConfiguration() {
+ // int32 x 4 x 1
+ checkKeyMarshal("android.control.availableHighSpeedVideoConfigurations",
+ new HighSpeedVideoConfiguration(
+ /*width*/1000, /*height*/255, /*fpsMin*/30, /*fpsMax*/200),
+ /* width, height, fpsMin, fpsMax */
+ toByteArray(1000, 255, 30, 200));
+
+ // int32 x 4 x 3
+ checkKeyMarshal("android.control.availableHighSpeedVideoConfigurations",
+ new HighSpeedVideoConfiguration[] {
+ new HighSpeedVideoConfiguration(
+ /*width*/1280, /*height*/720, /*fpsMin*/60, /*fpsMax*/120),
+ new HighSpeedVideoConfiguration(
+ /*width*/123, /*height*/456, /*fpsMin*/1, /*fpsMax*/200),
+ new HighSpeedVideoConfiguration(
+ /*width*/4096, /*height*/2592, /*fpsMin*/30, /*fpsMax*/60)
+ },
+ toByteArray(
+ 1280, 720, 60, 120,
+ 123, 456, 1, 200,
+ 4096, 2592, 30, 60
+ ));
+ }
+
+ @SmallTest
public void testReadWriteColorSpaceTransform() {
// rational x 3 x 3
checkKeyMarshal("android.colorCorrection.transform",
@@ -741,7 +767,7 @@ public class CameraMetadataTest extends junit.framework.TestCase {
toByteArray(
1, 2, 3, 4, 5, 6,
7, 8, 8, 9, 10, 11,
- 1, 5, 2, 8, 3, 9));
+ 1, 5, 1, 4, 1, 3));
}
@SmallTest