summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorIgor Murashkin <iam@google.com>2014-07-09 17:20:23 -0700
committerIgor Murashkin <iam@google.com>2014-07-11 12:59:50 -0700
commit3e280b4bb23be4e5e66ea6381fd63c74fdbd927e (patch)
tree274b80cd28fa5a9f41fb03a634f38d21043abc2a /core
parent7ee78d1ee3ee068897b9313af2ed6446675c1be0 (diff)
downloadframeworks_base-3e280b4bb23be4e5e66ea6381fd63c74fdbd927e.zip
frameworks_base-3e280b4bb23be4e5e66ea6381fd63c74fdbd927e.tar.gz
frameworks_base-3e280b4bb23be4e5e66ea6381fd63c74fdbd927e.tar.bz2
camera2: (Legacy) Implement ae compensation step ranges and ae/awb locks
Characteristics: * control.aeCompensationRange * control.aeCompensationStep Request/Result: * control.aeExposureCompensation * control.aeLock * control.awbLock Change-Id: I911616c9cf3e0e9a03a0cb383bcf232cab8ca772
Diffstat (limited to 'core')
-rw-r--r--core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java19
-rw-r--r--core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java70
-rw-r--r--core/java/android/hardware/camera2/legacy/LegacyResultMapper.java20
-rw-r--r--core/java/android/hardware/camera2/utils/ParamsUtils.java53
4 files changed, 160 insertions, 2 deletions
diff --git a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
index 149f4c8..d413cbd 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
@@ -355,6 +355,25 @@ public class LegacyMetadataMapper {
// Note that AE_MODE_OFF is never available.
m.set(CONTROL_AE_AVAILABLE_MODES, aeAvail);
}
+
+ /*
+ * control.aeCompensationRanges
+ */
+ {
+ int min = p.getMinExposureCompensation();
+ int max = p.getMaxExposureCompensation();
+
+ m.set(CONTROL_AE_COMPENSATION_RANGE, Range.create(min, max));
+ }
+
+ /*
+ * control.aeCompensationStep
+ */
+ {
+ float step = p.getExposureCompensationStep();
+
+ m.set(CONTROL_AE_COMPENSATION_STEP, ParamsUtils.createRational(step));
+ }
}
private static void mapControlAwb(CameraMetadataNative m, Camera.Parameters p) {
diff --git a/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java b/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java
index cc18865..124fa42 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java
@@ -30,6 +30,7 @@ import android.util.Size;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
import static com.android.internal.util.Preconditions.*;
import static android.hardware.camera2.CaptureRequest.*;
@@ -153,13 +154,52 @@ public class LegacyRequestMapper {
* control
*/
+ // control.aeExposureCompensation
+ {
+ Range<Integer> compensationRange =
+ characteristics.get(CameraCharacteristics.CONTROL_AE_COMPENSATION_RANGE);
+ int compensation = getOrDefault(request,
+ CONTROL_AE_EXPOSURE_COMPENSATION,
+ /*defaultValue*/0);
+
+ if (!compensationRange.inRange(compensation)) {
+ Log.w(TAG,
+ "convertRequestMetadata - control.aeExposureCompensation " +
+ "is out of range, ignoring value");
+ compensation = 0;
+ }
+
+ params.setExposureCompensation(compensation);
+ }
+
+ // control.aeLock
+ {
+ Boolean aeLock = getIfSupported(request, CONTROL_AE_LOCK, /*defaultValue*/false,
+ params.isAutoExposureLockSupported(),
+ /*allowedValue*/false);
+
+ if (aeLock != null) {
+ params.setAutoExposureLock(aeLock);
+ }
+
+ // TODO: Don't add control.aeLock to availableRequestKeys if it's not supported
+ }
+
// control.aeMode, flash.mode
mapAeAndFlashMode(request, /*out*/params);
// control.awbLock
- Boolean awbLock = request.get(CONTROL_AWB_LOCK);
- params.setAutoWhiteBalanceLock(awbLock == null ? false : awbLock);
+ {
+ Boolean awbLock = getIfSupported(request, CONTROL_AWB_LOCK, /*defaultValue*/false,
+ params.isAutoWhiteBalanceLockSupported(),
+ /*allowedValue*/false);
+ if (awbLock != null) {
+ params.setAutoWhiteBalanceLock(awbLock);
+ }
+
+ // TODO: Don't add control.awbLock to availableRequestKeys if it's not supported
+ }
}
private static List<Camera.Area> convertMeteringRegionsToLegacy(
@@ -275,6 +315,7 @@ public class LegacyRequestMapper {
return legacyFps;
}
+ /** Return the value set by the key, or the {@code defaultValue} if no value was set. */
private static <T> T getOrDefault(CaptureRequest r, CaptureRequest.Key<T> key, T defaultValue) {
checkNotNull(r, "r must not be null");
checkNotNull(key, "key must not be null");
@@ -287,4 +328,29 @@ public class LegacyRequestMapper {
return value;
}
}
+
+ /**
+ * Return {@code null} if the value is not supported, otherwise return the retrieved key's
+ * value from the request (or the default value if it wasn't set).
+ *
+ * <p>If the fetched value in the request is equivalent to {@code allowedValue},
+ * then omit the warning (e.g. turning off AF lock on a camera
+ * that always has the AF lock turned off is a silent no-op), but still return {@code null}.</p>
+ *
+ * <p>Logs a warning to logcat if the key is not supported by api1 camera device.</p.
+ */
+ private static <T> T getIfSupported(
+ CaptureRequest r, CaptureRequest.Key<T> key, T defaultValue, boolean isSupported,
+ T allowedValue) {
+ T val = getOrDefault(r, key, defaultValue);
+
+ if (!isSupported) {
+ if (!Objects.equals(val, allowedValue)) {
+ Log.w(TAG, key.getName() + " is not supported; ignoring requested value " + val);
+ }
+ return null;
+ }
+
+ return val;
+ }
}
diff --git a/core/java/android/hardware/camera2/legacy/LegacyResultMapper.java b/core/java/android/hardware/camera2/legacy/LegacyResultMapper.java
index b592b8c..375e6e0 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyResultMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyResultMapper.java
@@ -28,7 +28,9 @@ import android.hardware.camera2.legacy.ParameterUtils.WeightedRectangle;
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.Rational;
import android.util.Size;
import java.util.ArrayList;
@@ -125,6 +127,17 @@ public class LegacyResultMapper {
m.set(CONTROL_AE_ANTIBANDING_MODE, antiBandingMode);
}
+ // control.aeExposureCompensation
+ {
+ m.set(CONTROL_AE_EXPOSURE_COMPENSATION, p.getExposureCompensation());
+ }
+
+ // control.aeLock
+ {
+ boolean lock = p.isAutoExposureLockSupported() ? p.getAutoExposureLock() : false;
+ m.set(CONTROL_AE_LOCK, lock);
+ }
+
// control.aeMode, flash.mode
mapAeAndFlashMode(m, p);
@@ -160,6 +173,13 @@ public class LegacyResultMapper {
m.set(CONTROL_AF_REGIONS, meteringRectArray);
}
+
+ // control.awbLock
+ {
+ boolean lock = p.isAutoWhiteBalanceLockSupported() ?
+ p.getAutoWhiteBalanceLock() : false;
+ m.set(CONTROL_AWB_LOCK, lock);
+ }
}
private static MeteringRectangle[] getMeteringRectangles(Rect activeArray, ZoomData zoomData,
diff --git a/core/java/android/hardware/camera2/utils/ParamsUtils.java b/core/java/android/hardware/camera2/utils/ParamsUtils.java
index 6c0fd2d..232a4f6 100644
--- a/core/java/android/hardware/camera2/utils/ParamsUtils.java
+++ b/core/java/android/hardware/camera2/utils/ParamsUtils.java
@@ -19,6 +19,7 @@ package android.hardware.camera2.utils;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
+import android.util.Rational;
import android.util.Size;
import static com.android.internal.util.Preconditions.*;
@@ -28,6 +29,9 @@ import static com.android.internal.util.Preconditions.*;
*/
public class ParamsUtils {
+ /** Arbitrary denominator used to estimate floats as rationals */
+ private static final int RATIONAL_DENOMINATOR = 1000000; // 1million
+
/**
* Create a {@link Rect} from a {@code Size} by creating a new rectangle with
* left, top = {@code (0, 0)} and right, bottom = {@code (width, height)}
@@ -104,6 +108,55 @@ public class ParamsUtils {
}
/**
+ * Create a {@link Rational} value by approximating the float value as a rational.
+ *
+ * <p>Floating points too large to be represented as an integer will be converted to
+ * to {@link Integer#MAX_VALUE}; floating points too small to be represented as an integer
+ * will be converted to {@link Integer#MIN_VALUE}.</p>
+ *
+ * @param value a floating point value
+ * @return the rational representation of the float
+ */
+ public static Rational createRational(float value) {
+ if (Float.isNaN(value)) {
+ return Rational.NaN;
+ } else if (value == Float.POSITIVE_INFINITY) {
+ return Rational.POSITIVE_INFINITY;
+ } else if (value == Float.NEGATIVE_INFINITY) {
+ return Rational.NEGATIVE_INFINITY;
+ } else if (value == 0.0f) {
+ return Rational.ZERO;
+ }
+
+ // normal finite value: approximate it
+
+ /*
+ * Start out trying to approximate with denominator = 1million,
+ * but if the numerator doesn't fit into an Int then keep making the denominator
+ * smaller until it does.
+ */
+ int den = RATIONAL_DENOMINATOR;
+ float numF;
+ do {
+ numF = value * den;
+
+ if ((numF > Integer.MIN_VALUE && numF < Integer.MAX_VALUE) || (den == 1)) {
+ break;
+ }
+
+ den /= 10;
+ } while (true);
+
+ /*
+ * By float -> int narrowing conversion in JLS 5.1.3, this will automatically become
+ * MIN_VALUE or MAX_VALUE if numF is too small/large to be represented by an integer
+ */
+ int num = (int) numF;
+
+ return new Rational(num, den);
+ }
+
+ /**
* Convert an integral rectangle ({@code source}) to a floating point rectangle
* ({@code destination}) in-place.
*