summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/hardware/camera2/impl/CameraMetadataNative.java92
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java136
2 files changed, 209 insertions, 19 deletions
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index 0d4a4cb..c5e5753 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -461,6 +461,10 @@ public class CameraMetadataNative extends CameraMetadata implements Parcelable {
return (T) getFaces();
} else if (key.equals(CaptureResult.STATISTICS_FACE_RECTANGLES)) {
return (T) getFaceRectangles();
+ } else if (key.equals(CameraCharacteristics.SCALER_AVAILABLE_STREAM_CONFIGURATIONS)) {
+ return (T) getAvailableStreamConfigurations();
+ } else if (key.equals(CameraCharacteristics.SCALER_AVAILABLE_MIN_FRAME_DURATIONS)) {
+ return (T) getAvailableMinFrameDurations();
}
// For other keys, get() falls back to getBase()
@@ -481,6 +485,50 @@ public class CameraMetadataNative extends CameraMetadata implements Parcelable {
return availableFormats;
}
+ private int[] getAvailableStreamConfigurations() {
+ final int NUM_ELEMENTS_IN_CONFIG = 4;
+ int[] availableConfigs =
+ getBase(CameraCharacteristics.SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
+ if (availableConfigs != null) {
+ if (availableConfigs.length % NUM_ELEMENTS_IN_CONFIG != 0) {
+ Log.w(TAG, "availableStreamConfigurations is malformed, length must be multiple"
+ + " of " + NUM_ELEMENTS_IN_CONFIG);
+ return availableConfigs;
+ }
+
+ for (int i = 0; i < availableConfigs.length; i += NUM_ELEMENTS_IN_CONFIG) {
+ // JPEG has different value between native and managed side, need override.
+ if (availableConfigs[i] == NATIVE_JPEG_FORMAT) {
+ availableConfigs[i] = ImageFormat.JPEG;
+ }
+ }
+ }
+
+ return availableConfigs;
+ }
+
+ private long[] getAvailableMinFrameDurations() {
+ final int NUM_ELEMENTS_IN_DURATION = 4;
+ long[] availableMinDurations =
+ getBase(CameraCharacteristics.SCALER_AVAILABLE_MIN_FRAME_DURATIONS);
+ if (availableMinDurations != null) {
+ if (availableMinDurations.length % NUM_ELEMENTS_IN_DURATION != 0) {
+ Log.w(TAG, "availableStreamConfigurations is malformed, length must be multiple"
+ + " of " + NUM_ELEMENTS_IN_DURATION);
+ return availableMinDurations;
+ }
+
+ for (int i = 0; i < availableMinDurations.length; i += NUM_ELEMENTS_IN_DURATION) {
+ // JPEG has different value between native and managed side, need override.
+ if (availableMinDurations[i] == NATIVE_JPEG_FORMAT) {
+ availableMinDurations[i] = ImageFormat.JPEG;
+ }
+ }
+ }
+
+ return availableMinDurations;
+ }
+
private Face[] getFaces() {
final int FACE_LANDMARK_SIZE = 6;
@@ -607,12 +655,56 @@ public class CameraMetadataNative extends CameraMetadata implements Parcelable {
return setAvailableFormats((int[]) value);
} else if (key.equals(CaptureResult.STATISTICS_FACE_RECTANGLES)) {
return setFaceRectangles((Rect[]) value);
+ } else if (key.equals(CameraCharacteristics.SCALER_AVAILABLE_STREAM_CONFIGURATIONS)) {
+ return setAvailableStreamConfigurations((int[])value);
+ } else if (key.equals(CameraCharacteristics.SCALER_AVAILABLE_MIN_FRAME_DURATIONS)) {
+ return setAvailableMinFrameDurations((long[])value);
}
// For other keys, set() falls back to setBase().
return false;
}
+ private boolean setAvailableStreamConfigurations(int[] value) {
+ final int NUM_ELEMENTS_IN_CONFIG = 4;
+ int[] availableConfigs = value;
+ if (value == null) {
+ // Let setBase() to handle the null value case.
+ return false;
+ }
+
+ int[] newValues = new int[availableConfigs.length];
+ for (int i = 0; i < availableConfigs.length; i++) {
+ newValues[i] = availableConfigs[i];
+ if (i % NUM_ELEMENTS_IN_CONFIG == 0 && availableConfigs[i] == ImageFormat.JPEG) {
+ newValues[i] = NATIVE_JPEG_FORMAT;
+ }
+ }
+
+ setBase(CameraCharacteristics.SCALER_AVAILABLE_STREAM_CONFIGURATIONS, newValues);
+ return true;
+ }
+
+ private boolean setAvailableMinFrameDurations(long[] value) {
+ final int NUM_ELEMENTS_IN_DURATION = 4;
+ long[] availableDurations = value;
+ if (value == null) {
+ // Let setBase() to handle the null value case.
+ return false;
+ }
+
+ long[] newValues = new long[availableDurations.length];
+ for (int i = 0; i < availableDurations.length; i++) {
+ newValues[i] = availableDurations[i];
+ if (i % NUM_ELEMENTS_IN_DURATION == 0 && availableDurations[i] == ImageFormat.JPEG) {
+ newValues[i] = NATIVE_JPEG_FORMAT;
+ }
+ }
+
+ setBase(CameraCharacteristics.SCALER_AVAILABLE_MIN_FRAME_DURATIONS, newValues);
+ return true;
+ }
+
private boolean setAvailableFormats(int[] value) {
int[] availableFormat = value;
if (value == null) {
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 26498ca..edfa36a 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
@@ -552,29 +552,72 @@ public class CameraMetadataTest extends junit.framework.TestCase {
};
int availableFormatTag = CameraMetadataNative.getTag("android.scaler.availableFormats");
- // Write
- mMetadata.set(CameraCharacteristics.SCALER_AVAILABLE_FORMATS, availableFormats);
+ Key<int[]> formatKey = CameraCharacteristics.SCALER_AVAILABLE_FORMATS;
- byte[] availableFormatValues = mMetadata.readValues(availableFormatTag);
+ validateArrayMetadataReadWriteOverride(formatKey, availableFormats,
+ expectedIntValues, availableFormatTag);
- ByteBuffer bf = ByteBuffer.wrap(availableFormatValues).order(ByteOrder.nativeOrder());
+ //
+ // android.scaler.availableStreamConfigurations (int x n x 4 array)
+ //
+ final int OUTPUT = CameraCharacteristics.SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT;
+ int[] availableStreamConfigs = new int[] {
+ 0x20, 3280, 2464, OUTPUT, // RAW16
+ 0x23, 3264, 2448, OUTPUT, // YCbCr_420_888
+ 0x23, 3200, 2400, OUTPUT, // YCbCr_420_888
+ 0x100, 3264, 2448, OUTPUT, // ImageFormat.JPEG
+ 0x100, 3200, 2400, OUTPUT, // ImageFormat.JPEG
+ 0x100, 2592, 1944, OUTPUT, // ImageFormat.JPEG
+ 0x100, 2048, 1536, OUTPUT, // ImageFormat.JPEG
+ 0x100, 1920, 1080, OUTPUT // ImageFormat.JPEG
+ };
+ int[] expectedAvailableStreamConfigs = new int[] {
+ 0x20, 3280, 2464, OUTPUT, // RAW16
+ 0x23, 3264, 2448, OUTPUT, // YCbCr_420_888
+ 0x23, 3200, 2400, OUTPUT, // YCbCr_420_888
+ 0x21, 3264, 2448, OUTPUT, // BLOB
+ 0x21, 3200, 2400, OUTPUT, // BLOB
+ 0x21, 2592, 1944, OUTPUT, // BLOB
+ 0x21, 2048, 1536, OUTPUT, // BLOB
+ 0x21, 1920, 1080, OUTPUT // BLOB
+ };
+ int availableStreamConfigTag =
+ CameraMetadataNative.getTag("android.scaler.availableStreamConfigurations");
- assertEquals(expectedIntValues.length * 4, availableFormatValues.length);
- for (int i = 0; i < expectedIntValues.length; ++i) {
- assertEquals(expectedIntValues[i], bf.getInt());
- }
- // Read
- byte[] availableFormatsAsByteArray = new byte[expectedIntValues.length * 4];
- ByteBuffer availableFormatsByteBuffer =
- ByteBuffer.wrap(availableFormatsAsByteArray).order(ByteOrder.nativeOrder());
- for (int value : expectedIntValues) {
- availableFormatsByteBuffer.putInt(value);
- }
- mMetadata.writeValues(availableFormatTag, availableFormatsAsByteArray);
+ Key<int[]> configKey = CameraCharacteristics.SCALER_AVAILABLE_STREAM_CONFIGURATIONS;
+ validateArrayMetadataReadWriteOverride(configKey, availableStreamConfigs,
+ expectedAvailableStreamConfigs, availableStreamConfigTag);
- int[] resultFormats = mMetadata.get(CameraCharacteristics.SCALER_AVAILABLE_FORMATS);
- assertNotNull("result available formats shouldn't be null", resultFormats);
- assertArrayEquals(availableFormats, resultFormats);
+ //
+ // android.scaler.availableMinFrameDurations (int x n x 4 array)
+
+ //
+ long[] availableMinDurations = new long[] {
+ 0x20, 3280, 2464, 33333336, // RAW16
+ 0x23, 3264, 2448, 33333336, // YCbCr_420_888
+ 0x23, 3200, 2400, 33333336, // YCbCr_420_888
+ 0x100, 3264, 2448, 33333336, // ImageFormat.JPEG
+ 0x100, 3200, 2400, 33333336, // ImageFormat.JPEG
+ 0x100, 2592, 1944, 33333336, // ImageFormat.JPEG
+ 0x100, 2048, 1536, 33333336, // ImageFormat.JPEG
+ 0x100, 1920, 1080, 33333336 // ImageFormat.JPEG
+ };
+ long[] expectedAvailableMinDurations = new long[] {
+ 0x20, 3280, 2464, 33333336, // RAW16
+ 0x23, 3264, 2448, 33333336, // YCbCr_420_888
+ 0x23, 3200, 2400, 33333336, // YCbCr_420_888
+ 0x21, 3264, 2448, 33333336, // BLOB
+ 0x21, 3200, 2400, 33333336, // BLOB
+ 0x21, 2592, 1944, 33333336, // BLOB
+ 0x21, 2048, 1536, 33333336, // BLOB
+ 0x21, 1920, 1080, 33333336 // BLOB
+ };
+ int availableMinDurationsTag =
+ CameraMetadataNative.getTag("android.scaler.availableMinFrameDurations");
+
+ Key<long[]> durationKey = CameraCharacteristics.SCALER_AVAILABLE_MIN_FRAME_DURATIONS;
+ validateArrayMetadataReadWriteOverride(durationKey, availableMinDurations,
+ expectedAvailableMinDurations, availableMinDurationsTag);
//
// android.statistics.faces (Face x n array)
@@ -639,4 +682,59 @@ public class CameraMetadataTest extends junit.framework.TestCase {
}
}
+
+ /**
+ * Validate metadata array tag read/write override.
+ *
+ * <p>Only support long and int array for now, can be easily extend to support other
+ * primitive arrays.</p>
+ */
+ private <T> void validateArrayMetadataReadWriteOverride(Key<T> key, T writeValues,
+ T readValues, int tag) {
+ Class<T> type = key.getType();
+ if (!type.isArray()) {
+ throw new IllegalArgumentException("This function expects an key with array type");
+ } else if (type != int[].class && type != long[].class) {
+ throw new IllegalArgumentException("This function expects long or int array values");
+ }
+
+ // Write
+ mMetadata.set(key, writeValues);
+
+ byte[] readOutValues = mMetadata.readValues(tag);
+
+ ByteBuffer bf = ByteBuffer.wrap(readOutValues).order(ByteOrder.nativeOrder());
+
+ int readValuesLength = Array.getLength(readValues);
+ int readValuesNumBytes = readValuesLength * 4;
+ if (type == long[].class) {
+ readValuesNumBytes = readValuesLength * 8;
+ }
+
+ assertEquals(readValuesNumBytes, readOutValues.length);
+ for (int i = 0; i < readValuesLength; ++i) {
+ if (type == int[].class) {
+ assertEquals(Array.getInt(readValues, i), bf.getInt());
+ } else if (type == long[].class) {
+ assertEquals(Array.getLong(readValues, i), bf.getLong());
+ }
+ }
+
+ // Read
+ byte[] readOutValuesAsByteArray = new byte[readValuesNumBytes];
+ ByteBuffer readOutValuesByteBuffer =
+ ByteBuffer.wrap(readOutValuesAsByteArray).order(ByteOrder.nativeOrder());
+ for (int i = 0; i < readValuesLength; ++i) {
+ if (type == int[].class) {
+ readOutValuesByteBuffer.putInt(Array.getInt(readValues, i));
+ } else if (type == long[].class) {
+ readOutValuesByteBuffer.putLong(Array.getLong(readValues, i));
+ }
+ }
+ mMetadata.writeValues(tag, readOutValuesAsByteArray);
+
+ T result = mMetadata.get(key);
+ assertNotNull(key.getName() + " result shouldn't be null", result);
+ assertArrayEquals(writeValues, result);
+ }
}