camera2: Add scene and effect mode for LEGACY.
Bug: 15116722
Change-Id: I0797fccb5fdd8b959622c100f25b2950cfe4e115
diff --git a/core/java/android/hardware/camera2/legacy/CaptureCollector.java b/core/java/android/hardware/camera2/legacy/CaptureCollector.java
index af58a8a..307e466 100644
--- a/core/java/android/hardware/camera2/legacy/CaptureCollector.java
+++ b/core/java/android/hardware/camera2/legacy/CaptureCollector.java
@@ -236,6 +236,11 @@
Log.d(TAG, "queueRequest for request " + holder.getRequestId() +
" - " + mInFlight + " requests remain in flight.");
}
+
+ if (!(h.needsJpeg || h.needsPreview)) {
+ throw new IllegalStateException("Request must target at least one output surface!");
+ }
+
if (h.needsJpeg) {
// Wait for all current requests to finish before queueing jpeg.
while (mInFlight > 0) {
@@ -259,9 +264,6 @@
mInFlightPreviews++;
}
- if (!(h.needsJpeg || h.needsPreview)) {
- throw new IllegalStateException("Request must target at least one output surface!");
- }
mInFlight++;
return true;
diff --git a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
index 633bada..533c9a8 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
@@ -78,6 +78,8 @@
private static final long APPROXIMATE_SENSOR_AREA_PX = (1 << 23); // 8 megapixels
private static final long APPROXIMATE_JPEG_ENCODE_TIME_MS = 600; // 600 milliseconds
+ static final int UNKNOWN_MODE = -1;
+
/*
* Development hijinks: Lie about not supporting certain capabilities
*
@@ -458,7 +460,22 @@
m.set(CONTROL_MAX_REGIONS, maxRegions);
- // TODO rest of control fields
+ /*
+ * android.control.availableEffects
+ */
+ List<String> effectModes = p.getSupportedColorEffects();
+ int[] supportedEffectModes = (effectModes == null) ? new int[0] :
+ ArrayUtils.convertStringListToIntArray(effectModes, sLegacyEffectMode,
+ sEffectModes);
+ m.set(CONTROL_AVAILABLE_EFFECTS, supportedEffectModes);
+
+ /*
+ * android.control.availableSceneModes
+ */
+ List<String> sceneModes = p.getSupportedSceneModes();
+ int[] supportedSceneModes = (sceneModes == null) ? new int[0] :
+ ArrayUtils.convertStringListToIntArray(sceneModes, sLegacySceneModes, sSceneModes);
+ m.set(CONTROL_AVAILABLE_SCENE_MODES, supportedSceneModes);
}
private static void mapLens(CameraMetadataNative m, Camera.Parameters p) {
@@ -680,6 +697,106 @@
}
}
+ private final static String[] sLegacySceneModes = {
+ Parameters.SCENE_MODE_AUTO,
+ Parameters.SCENE_MODE_ACTION,
+ Parameters.SCENE_MODE_PORTRAIT,
+ Parameters.SCENE_MODE_LANDSCAPE,
+ Parameters.SCENE_MODE_NIGHT,
+ Parameters.SCENE_MODE_NIGHT_PORTRAIT,
+ Parameters.SCENE_MODE_THEATRE,
+ Parameters.SCENE_MODE_BEACH,
+ Parameters.SCENE_MODE_SNOW,
+ Parameters.SCENE_MODE_SUNSET,
+ Parameters.SCENE_MODE_STEADYPHOTO,
+ Parameters.SCENE_MODE_FIREWORKS,
+ Parameters.SCENE_MODE_SPORTS,
+ Parameters.SCENE_MODE_PARTY,
+ Parameters.SCENE_MODE_CANDLELIGHT,
+ Parameters.SCENE_MODE_BARCODE,
+ };
+
+ private final static int[] sSceneModes = {
+ CameraCharacteristics.CONTROL_SCENE_MODE_DISABLED,
+ CameraCharacteristics.CONTROL_SCENE_MODE_ACTION,
+ CameraCharacteristics.CONTROL_SCENE_MODE_PORTRAIT,
+ CameraCharacteristics.CONTROL_SCENE_MODE_LANDSCAPE,
+ CameraCharacteristics.CONTROL_SCENE_MODE_NIGHT,
+ CameraCharacteristics.CONTROL_SCENE_MODE_NIGHT_PORTRAIT,
+ CameraCharacteristics.CONTROL_SCENE_MODE_THEATRE,
+ CameraCharacteristics.CONTROL_SCENE_MODE_BEACH,
+ CameraCharacteristics.CONTROL_SCENE_MODE_SNOW,
+ CameraCharacteristics.CONTROL_SCENE_MODE_SUNSET,
+ CameraCharacteristics.CONTROL_SCENE_MODE_STEADYPHOTO,
+ CameraCharacteristics.CONTROL_SCENE_MODE_FIREWORKS,
+ CameraCharacteristics.CONTROL_SCENE_MODE_SPORTS,
+ CameraCharacteristics.CONTROL_SCENE_MODE_PARTY,
+ CameraCharacteristics.CONTROL_SCENE_MODE_CANDLELIGHT,
+ CameraCharacteristics.CONTROL_SCENE_MODE_BARCODE,
+ };
+
+ static int convertSceneModeFromLegacy(String mode) {
+ if (mode == null) {
+ return CameraCharacteristics.CONTROL_SCENE_MODE_DISABLED;
+ }
+ int index = ArrayUtils.getArrayIndex(sLegacySceneModes, mode);
+ if (index < 0) {
+ return UNKNOWN_MODE;
+ }
+ return sSceneModes[index];
+ }
+
+ static String convertSceneModeToLegacy(int mode) {
+ int index = ArrayUtils.getArrayIndex(sSceneModes, mode);
+ if (index < 0) {
+ return null;
+ }
+ return sLegacySceneModes[index];
+ }
+
+ private final static String[] sLegacyEffectMode = {
+ Parameters.EFFECT_NONE,
+ Parameters.EFFECT_MONO,
+ Parameters.EFFECT_NEGATIVE,
+ Parameters.EFFECT_SOLARIZE,
+ Parameters.EFFECT_SEPIA,
+ Parameters.EFFECT_POSTERIZE,
+ Parameters.EFFECT_WHITEBOARD,
+ Parameters.EFFECT_BLACKBOARD,
+ Parameters.EFFECT_AQUA,
+ };
+
+ private final static int[] sEffectModes = {
+ CameraCharacteristics.CONTROL_EFFECT_MODE_OFF,
+ CameraCharacteristics.CONTROL_EFFECT_MODE_MONO,
+ CameraCharacteristics.CONTROL_EFFECT_MODE_NEGATIVE,
+ CameraCharacteristics.CONTROL_EFFECT_MODE_SOLARIZE,
+ CameraCharacteristics.CONTROL_EFFECT_MODE_SEPIA,
+ CameraCharacteristics.CONTROL_EFFECT_MODE_POSTERIZE,
+ CameraCharacteristics.CONTROL_EFFECT_MODE_WHITEBOARD,
+ CameraCharacteristics.CONTROL_EFFECT_MODE_BLACKBOARD,
+ CameraCharacteristics.CONTROL_EFFECT_MODE_AQUA,
+ };
+
+ static int convertEffectModeFromLegacy(String mode) {
+ if (mode == null) {
+ return CameraCharacteristics.CONTROL_EFFECT_MODE_OFF;
+ }
+ int index = ArrayUtils.getArrayIndex(sLegacyEffectMode, mode);
+ if (index < 0) {
+ return UNKNOWN_MODE;
+ }
+ return sEffectModes[index];
+ }
+
+ static String convertEffectModeToLegacy(int mode) {
+ int index = ArrayUtils.getArrayIndex(sEffectModes, mode);
+ if (index < 0) {
+ return null;
+ }
+ return sLegacyEffectMode[index];
+ }
+
/**
* Convert the ae antibanding mode from api1 into api2.
*
diff --git a/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java b/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java
index fbfc39f..28726e6 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java
@@ -238,6 +238,57 @@
+ infinityFocusSupported + ", only 0.0f is supported");
}
}
+
+ // control.sceneMode, control.mode
+ {
+ // TODO: Map FACE_PRIORITY scene mode to face detection.
+
+ if (params.getSupportedSceneModes() != null) {
+ int controlMode = ParamsUtils.getOrDefault(request, CONTROL_MODE,
+ /*defaultValue*/CONTROL_MODE_AUTO);
+ String modeToSet;
+ switch (controlMode) {
+ case CONTROL_MODE_USE_SCENE_MODE: {
+ int sceneMode = ParamsUtils.getOrDefault(request, CONTROL_SCENE_MODE,
+ /*defaultValue*/CONTROL_SCENE_MODE_DISABLED);
+ String legacySceneMode = LegacyMetadataMapper.
+ convertSceneModeToLegacy(sceneMode);
+ if (legacySceneMode != null) {
+ modeToSet = legacySceneMode;
+ } else {
+ modeToSet = Parameters.SCENE_MODE_AUTO;
+ Log.w(TAG, "Skipping unknown requested scene mode: " + sceneMode);
+ }
+ break;
+ }
+ case CONTROL_MODE_AUTO: {
+ modeToSet = Parameters.SCENE_MODE_AUTO;
+ break;
+ }
+ default: {
+ Log.w(TAG, "Control mode " + controlMode +
+ " is unsupported, defaulting to AUTO");
+ modeToSet = Parameters.SCENE_MODE_AUTO;
+ }
+ }
+ params.setSceneMode(modeToSet);
+ }
+ }
+
+ // control.effectMode
+ {
+ if (params.getSupportedColorEffects() != null) {
+ int effectMode = ParamsUtils.getOrDefault(request, CONTROL_EFFECT_MODE,
+ /*defaultValue*/CONTROL_EFFECT_MODE_OFF);
+ String legacyEffectMode = LegacyMetadataMapper.convertEffectModeToLegacy(effectMode);
+ if (legacyEffectMode != null) {
+ params.setColorEffect(legacyEffectMode);
+ } else {
+ params.setColorEffect(Parameters.EFFECT_NONE);
+ Log.w(TAG, "Skipping unknown requested effect mode: " + effectMode);
+ }
+ }
+ }
}
private static List<Camera.Area> convertMeteringRegionsToLegacy(
diff --git a/core/java/android/hardware/camera2/legacy/LegacyResultMapper.java b/core/java/android/hardware/camera2/legacy/LegacyResultMapper.java
index 07852b9..6da5dd0 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyResultMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyResultMapper.java
@@ -28,6 +28,7 @@
import android.hardware.camera2.legacy.ParameterUtils.ZoomData;
import android.hardware.camera2.params.MeteringRectangle;
import android.hardware.camera2.utils.ListUtils;
+import android.hardware.camera2.utils.ParamsUtils;
import android.util.Log;
import android.util.Size;
@@ -153,6 +154,51 @@
request.get(CaptureRequest.CONTROL_AWB_MODE));
}
+
+ /*
+ * control.mode
+ */
+ {
+ int controlMode = ParamsUtils.getOrDefault(request, CaptureRequest.CONTROL_MODE,
+ CONTROL_MODE_AUTO);
+ if (controlMode == CaptureResult.CONTROL_MODE_USE_SCENE_MODE) {
+ result.set(CONTROL_MODE, CONTROL_MODE_USE_SCENE_MODE);
+ } else {
+ result.set(CONTROL_MODE, CONTROL_MODE_AUTO);
+ }
+ }
+
+ /*
+ * control.sceneMode
+ */
+ {
+ String legacySceneMode = params.getSceneMode();
+ int mode = LegacyMetadataMapper.convertSceneModeFromLegacy(legacySceneMode);
+ if (mode != LegacyMetadataMapper.UNKNOWN_MODE) {
+ result.set(CaptureResult.CONTROL_SCENE_MODE, mode);
+ } else {
+ Log.w(TAG, "Unknown scene mode " + legacySceneMode +
+ " returned by camera HAL, setting to disabled.");
+ result.set(CaptureResult.CONTROL_SCENE_MODE, CONTROL_SCENE_MODE_DISABLED);
+ }
+ }
+
+
+ /*
+ * control.effectMode
+ */
+ {
+ String legacyEffectMode = params.getColorEffect();
+ int mode = LegacyMetadataMapper.convertEffectModeFromLegacy(legacyEffectMode);
+ if (mode != LegacyMetadataMapper.UNKNOWN_MODE) {
+ result.set(CaptureResult.CONTROL_EFFECT_MODE, mode);
+ } else {
+ Log.w(TAG, "Unknown effect mode " + legacyEffectMode +
+ " returned by camera HAL, setting to off.");
+ result.set(CaptureResult.CONTROL_EFFECT_MODE, CONTROL_EFFECT_MODE_OFF);
+ }
+ }
+
/*
* flash
*/
diff --git a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
index 0687264..3f24b2c 100644
--- a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
+++ b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
@@ -329,6 +329,9 @@
mSurfaces.clear();
mConversionSurfaces.clear();
mPBufferPixels = null;
+ if (mSurfaceTexture != null) {
+ mSurfaceTexture.release();
+ }
mSurfaceTexture = null;
}
diff --git a/core/java/android/hardware/camera2/utils/ArrayUtils.java b/core/java/android/hardware/camera2/utils/ArrayUtils.java
index 24c85d0..9d12ab92 100644
--- a/core/java/android/hardware/camera2/utils/ArrayUtils.java
+++ b/core/java/android/hardware/camera2/utils/ArrayUtils.java
@@ -47,6 +47,19 @@
return -1;
}
+ /** Return the index of {@code needle} in the {@code array}, or else {@code -1} */
+ public static int getArrayIndex(int[] array, int needle) {
+ if (array == null) {
+ return -1;
+ }
+ for (int i = 0; i < array.length; ++i) {
+ if (array[i] == needle) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
/**
* Create an {@code int[]} from the {@code List<>} by using {@code convertFrom} and
* {@code convertTo} as a one-to-one map (via the index).