From c804d1cc871c1ab6091c16098a12457a6a3079e0 Mon Sep 17 00:00:00 2001 From: Chien-Yu Chen Date: Thu, 15 Feb 2018 12:44:19 -0800 Subject: camera: Add OisSamples synthetic key Add a synthetic OisSamples key containing timestamps and shifts. Test: CTS Bug: 64847201 Change-Id: I0d7ce67a91de7dec65543d626e67ddac76c985c5 --- api/current.txt | 11 +- .../android/hardware/camera2/CameraMetadata.java | 4 + .../android/hardware/camera2/CaptureRequest.java | 5 - .../android/hardware/camera2/CaptureResult.java | 40 +++--- .../camera2/impl/CameraMetadataNative.java | 60 ++++++++- .../android/hardware/camera2/params/OisSample.java | 137 +++++++++++++++++++++ 6 files changed, 230 insertions(+), 27 deletions(-) create mode 100644 core/java/android/hardware/camera2/params/OisSample.java diff --git a/api/current.txt b/api/current.txt index ad0945b446b1..463cef89bd67 100644 --- a/api/current.txt +++ b/api/current.txt @@ -16271,9 +16271,7 @@ package android.hardware.camera2 { field public static final android.hardware.camera2.CaptureResult.Key STATISTICS_LENS_SHADING_CORRECTION_MAP; field public static final android.hardware.camera2.CaptureResult.Key STATISTICS_LENS_SHADING_MAP_MODE; field public static final android.hardware.camera2.CaptureResult.Key STATISTICS_OIS_DATA_MODE; - field public static final android.hardware.camera2.CaptureResult.Key STATISTICS_OIS_TIMESTAMPS; - field public static final android.hardware.camera2.CaptureResult.Key STATISTICS_OIS_X_SHIFTS; - field public static final android.hardware.camera2.CaptureResult.Key STATISTICS_OIS_Y_SHIFTS; + field public static final android.hardware.camera2.CaptureResult.Key STATISTICS_OIS_SAMPLES; field public static final android.hardware.camera2.CaptureResult.Key STATISTICS_SCENE_FLICKER; field public static final android.hardware.camera2.CaptureResult.Key TONEMAP_CURVE; field public static final android.hardware.camera2.CaptureResult.Key TONEMAP_GAMMA; @@ -16369,6 +16367,13 @@ package android.hardware.camera2.params { field public static final int METERING_WEIGHT_MIN = 0; // 0x0 } + public final class OisSample { + ctor public OisSample(long, float, float); + method public long getTimestamp(); + method public float getXshift(); + method public float getYshift(); + } + public final class OutputConfiguration implements android.os.Parcelable { ctor public OutputConfiguration(android.view.Surface); ctor public OutputConfiguration(int, android.view.Surface); diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java index e558b7e29a20..52aefcc48304 100644 --- a/core/java/android/hardware/camera2/CameraMetadata.java +++ b/core/java/android/hardware/camera2/CameraMetadata.java @@ -2646,6 +2646,10 @@ public abstract class CameraMetadata { /** *

Include OIS data in the capture result.

+ *

{@link CaptureResult#STATISTICS_OIS_SAMPLES android.statistics.oisSamples} provides OIS sample data in the + * output result metadata.

+ * + * @see CaptureResult#STATISTICS_OIS_SAMPLES * @see CaptureRequest#STATISTICS_OIS_DATA_MODE */ public static final int STATISTICS_OIS_DATA_MODE_ON = 1; diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java index 3ed533a4efcb..b6c96e7d9e6a 100644 --- a/core/java/android/hardware/camera2/CaptureRequest.java +++ b/core/java/android/hardware/camera2/CaptureRequest.java @@ -2759,9 +2759,6 @@ public final class CaptureRequest extends CameraMetadata> /** *

A control for selecting whether OIS position information is included in output * result metadata.

- *

When set to ON, - * {@link CaptureResult#STATISTICS_OIS_TIMESTAMPS android.statistics.oisTimestamps}, android.statistics.oisShiftPixelX, - * and android.statistics.oisShiftPixelY provide OIS data in the output result metadata.

*

Possible values: *

    *
  • {@link #STATISTICS_OIS_DATA_MODE_OFF OFF}
  • @@ -2770,8 +2767,6 @@ public final class CaptureRequest extends CameraMetadata> *

    Available values for this device:
    * android.Statistics.info.availableOisDataModes

    *

    Optional - This value may be {@code null} on some devices.

    - * - * @see CaptureResult#STATISTICS_OIS_TIMESTAMPS * @see #STATISTICS_OIS_DATA_MODE_OFF * @see #STATISTICS_OIS_DATA_MODE_ON */ diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java index c332d3028aed..8c2f8c1e8553 100644 --- a/core/java/android/hardware/camera2/CaptureResult.java +++ b/core/java/android/hardware/camera2/CaptureResult.java @@ -3911,9 +3911,6 @@ public class CaptureResult extends CameraMetadata> { /** *

    A control for selecting whether OIS position information is included in output * result metadata.

    - *

    When set to ON, - * {@link CaptureResult#STATISTICS_OIS_TIMESTAMPS android.statistics.oisTimestamps}, android.statistics.oisShiftPixelX, - * and android.statistics.oisShiftPixelY provide OIS data in the output result metadata.

    *

    Possible values: *

      *
    • {@link #STATISTICS_OIS_DATA_MODE_OFF OFF}
    • @@ -3922,8 +3919,6 @@ public class CaptureResult extends CameraMetadata> { *

      Available values for this device:
      * android.Statistics.info.availableOisDataModes

      *

      Optional - This value may be {@code null} on some devices.

      - * - * @see CaptureResult#STATISTICS_OIS_TIMESTAMPS * @see #STATISTICS_OIS_DATA_MODE_OFF * @see #STATISTICS_OIS_DATA_MODE_ON */ @@ -3939,8 +3934,8 @@ public class CaptureResult extends CameraMetadata> { *

      Optional - This value may be {@code null} on some devices.

      * * @see CaptureResult#SENSOR_TIMESTAMP + * @hide */ - @PublicKey public static final Key STATISTICS_OIS_TIMESTAMPS = new Key("android.statistics.oisTimestamps", long[].class); @@ -3948,16 +3943,14 @@ public class CaptureResult extends CameraMetadata> { *

      An array of shifts of OIS samples, in x direction.

      *

      The array contains the amount of shifts in x direction, in pixels, based on OIS samples. * A positive value is a shift from left to right in active array coordinate system. For - * example, if the optical center is (1000, 500) in active array coordinates, an shift of + * example, if the optical center is (1000, 500) in active array coordinates, a shift of * (3, 0) puts the new optical center at (1003, 500).

      *

      The number of shifts must match the number of timestamps in - * {@link CaptureResult#STATISTICS_OIS_TIMESTAMPS android.statistics.oisTimestamps}.

      + * android.statistics.oisTimestamps.

      *

      Units: Pixels in active array.

      *

      Optional - This value may be {@code null} on some devices.

      - * - * @see CaptureResult#STATISTICS_OIS_TIMESTAMPS + * @hide */ - @PublicKey public static final Key STATISTICS_OIS_X_SHIFTS = new Key("android.statistics.oisXShifts", float[].class); @@ -3965,19 +3958,34 @@ public class CaptureResult extends CameraMetadata> { *

      An array of shifts of OIS samples, in y direction.

      *

      The array contains the amount of shifts in y direction, in pixels, based on OIS samples. * A positive value is a shift from top to bottom in active array coordinate system. For - * example, if the optical center is (1000, 500) in active array coordinates, an shift of + * example, if the optical center is (1000, 500) in active array coordinates, a shift of * (0, 5) puts the new optical center at (1000, 505).

      *

      The number of shifts must match the number of timestamps in - * {@link CaptureResult#STATISTICS_OIS_TIMESTAMPS android.statistics.oisTimestamps}.

      + * android.statistics.oisTimestamps.

      *

      Units: Pixels in active array.

      *

      Optional - This value may be {@code null} on some devices.

      - * - * @see CaptureResult#STATISTICS_OIS_TIMESTAMPS + * @hide */ - @PublicKey public static final Key STATISTICS_OIS_Y_SHIFTS = new Key("android.statistics.oisYShifts", float[].class); + /** + *

      An array of OIS samples.

      + *

      Each OIS sample contains the timestamp and the amount of shifts in x and y direction, + * in pixels, of the OIS sample.

      + *

      A positive value for a shift in x direction is a shift from left to right in active array + * coordinate system. For example, if the optical center is (1000, 500) in active array + * coordinates, a shift of (3, 0) puts the new optical center at (1003, 500).

      + *

      A positive value for a shift in y direction is a shift from top to bottom in active array + * coordinate system. For example, if the optical center is (1000, 500) in active array + * coordinates, a shift of (0, 5) puts the new optical center at (1000, 505).

      + *

      Optional - This value may be {@code null} on some devices.

      + */ + @PublicKey + @SyntheticKey + public static final Key STATISTICS_OIS_SAMPLES = + new Key("android.statistics.oisSamples", android.hardware.camera2.params.OisSample[].class); + /** *

      Tonemapping / contrast / gamma curve for the blue * channel, to use when {@link CaptureRequest#TONEMAP_MODE android.tonemap.mode} is diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java index ebe2fa17a7c2..e4b1339fd663 100644 --- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java +++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java @@ -22,12 +22,12 @@ import android.graphics.Rect; import android.hardware.camera2.CameraCharacteristics; import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.CaptureResult; -import android.hardware.camera2.marshal.Marshaler; import android.hardware.camera2.marshal.MarshalQueryable; import android.hardware.camera2.marshal.MarshalRegistry; +import android.hardware.camera2.marshal.Marshaler; import android.hardware.camera2.marshal.impl.MarshalQueryableArray; -import android.hardware.camera2.marshal.impl.MarshalQueryableBoolean; import android.hardware.camera2.marshal.impl.MarshalQueryableBlackLevelPattern; +import android.hardware.camera2.marshal.impl.MarshalQueryableBoolean; import android.hardware.camera2.marshal.impl.MarshalQueryableColorSpaceTransform; import android.hardware.camera2.marshal.impl.MarshalQueryableEnum; import android.hardware.camera2.marshal.impl.MarshalQueryableHighSpeedVideoConfiguration; @@ -48,6 +48,7 @@ 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.OisSample; import android.hardware.camera2.params.ReprocessFormatsMap; import android.hardware.camera2.params.StreamConfiguration; import android.hardware.camera2.params.StreamConfigurationDuration; @@ -56,8 +57,8 @@ import android.hardware.camera2.params.TonemapCurve; import android.hardware.camera2.utils.TypeReference; import android.location.Location; import android.location.LocationManager; -import android.os.Parcelable; import android.os.Parcel; +import android.os.Parcelable; import android.os.ServiceSpecificException; import android.util.Log; import android.util.Size; @@ -614,6 +615,15 @@ public class CameraMetadataNative implements Parcelable { return (T) metadata.getLensShadingMap(); } }); + sGetCommandMap.put( + CaptureResult.STATISTICS_OIS_SAMPLES.getNativeKey(), + new GetCommand() { + @Override + @SuppressWarnings("unchecked") + public T getValue(CameraMetadataNative metadata, Key key) { + return (T) metadata.getOisSamples(); + } + }); } private int[] getAvailableFormats() { @@ -962,6 +972,50 @@ public class CameraMetadataNative implements Parcelable { return tc; } + private OisSample[] getOisSamples() { + long[] timestamps = getBase(CaptureResult.STATISTICS_OIS_TIMESTAMPS); + float[] xShifts = getBase(CaptureResult.STATISTICS_OIS_X_SHIFTS); + float[] yShifts = getBase(CaptureResult.STATISTICS_OIS_Y_SHIFTS); + + if (timestamps == null) { + if (xShifts != null) { + throw new AssertionError("timestamps is null but xShifts is not"); + } + + if (yShifts != null) { + throw new AssertionError("timestamps is null but yShifts is not"); + } + + return null; + } + + if (xShifts == null) { + throw new AssertionError("timestamps is not null but xShifts is"); + } + + if (yShifts == null) { + throw new AssertionError("timestamps is not null but yShifts is"); + } + + if (xShifts.length != timestamps.length) { + throw new AssertionError(String.format( + "timestamps has %d entries but xShifts has %d", timestamps.length, + xShifts.length)); + } + + if (yShifts.length != timestamps.length) { + throw new AssertionError(String.format( + "timestamps has %d entries but yShifts has %d", timestamps.length, + yShifts.length)); + } + + OisSample[] samples = new OisSample[timestamps.length]; + for (int i = 0; i < timestamps.length; i++) { + samples[i] = new OisSample(timestamps[i], xShifts[i], yShifts[i]); + } + return samples; + } + private void setBase(CameraCharacteristics.Key key, T value) { setBase(key.getNativeKey(), value); } diff --git a/core/java/android/hardware/camera2/params/OisSample.java b/core/java/android/hardware/camera2/params/OisSample.java new file mode 100644 index 000000000000..7ebaae35f3bf --- /dev/null +++ b/core/java/android/hardware/camera2/params/OisSample.java @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2018 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 android.hardware.camera2.CaptureResult; +import android.hardware.camera2.utils.HashCodeHelpers; + +import com.android.internal.util.Preconditions; + +/** + * Immutable class to store an + * {@link CaptureResult#STATISTICS_OIS_SAMPLES optical image stabilization sample}. + */ +public final class OisSample { + /** + * Create a new {@link OisSample}. + * + *

      {@link OisSample} contains the timestamp and the amount of shifts in x and y direction, + * in pixels, of the OIS sample. + * + *

      A positive value for a shift in x direction is a shift from left to right in active array + * coordinate system. For example, if the optical center is {@code (1000, 500)} in active array + * coordinates, a shift of {@code (3, 0)} puts the new optical center at {@code (1003, 500)}. + *

      + * + *

      A positive value for a shift in y direction is a shift from top to bottom in active array + * coordinate system. For example, if the optical center is {@code (1000, 500)} in active array + * coordinates, a shift of {@code (0, 5)} puts the new optical center at {@code (1000, 505)}. + *

      + * + *

      xShift and yShift must be finite; NaN and infinity is not allowed.

      + * + * @param timestamp timestamp of the OIS sample. + * @param xShift shift of the OIS sample in x direction. + * @param yShift shift of the OIS sample in y direction. + * + * @throws IllegalArgumentException if xShift or yShift is not finite + */ + public OisSample(final long timestamp, final float xShift, final float yShift) { + mTimestampNs = timestamp; + mXShift = Preconditions.checkArgumentFinite(xShift, "xShift must be finite"); + mYShift = Preconditions.checkArgumentFinite(yShift, "yShift must be finite"); + } + + /** + * Get the timestamp in nanoseconds. + * + *

      The timestamps are in the same timebase as and comparable to + *{@link CaptureResult#SENSOR_TIMESTAMP android.sensor.timestamp}.

      + * + * @return a long value (guaranteed to be finite) + */ + public long getTimestamp() { + return mTimestampNs; + } + + /** + * Get the shift in x direction. + * + * @return a floating point value (guaranteed to be finite) + */ + public float getXshift() { + return mXShift; + } + + /** + * Get the shift in y direction. + * + * @return a floating point value (guaranteed to be finite) + */ + public float getYshift() { + return mYShift; + } + + /** + * Check if this {@link OisSample} is equal to another {@link OisSample}. + * + *

      Two samples are only equal if and only if each of the OIS information is equal.

      + * + * @return {@code true} if the objects were equal, {@code false} otherwise + */ + @Override + public boolean equals(final Object obj) { + if (obj == null) { + return false; + } else if (this == obj) { + return true; + } else if (obj instanceof OisSample) { + final OisSample other = (OisSample) obj; + return mTimestampNs == other.mTimestampNs + && mXShift == other.mXShift + && mYShift == other.mYShift; + } + return false; + } + + /** + * {@inheritDoc} + */ + @Override + public int hashCode() { + int timestampHash = HashCodeHelpers.hashCode(mTimestampNs); + return HashCodeHelpers.hashCode(mXShift, mYShift, timestampHash); + } + + /** + * Return the OisSample as a string representation. + * + *

      {@code "OisSample{timestamp:%l, shift_x:%f, shift_y:%f}"} represents the OIS sample's + * timestamp, shift in x direction, and shift in y direction.

      + * + * @return string representation of {@link OisSample} + */ + @Override + public String toString() { + return String.format("OisSample{timestamp:%d, shift_x:%f, shift_y:%f}", mTimestampNs, + mXShift, mYShift); + } + + private final long mTimestampNs; + private final float mXShift; + private final float mYShift; +} -- cgit v1.2.3-59-g8ed1b