diff --git a/core/api/current.txt b/core/api/current.txt index d9e856a6ddc02..894910d3bf89e 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -18168,14 +18168,21 @@ package android.hardware.camera2.params { method @Nullable public android.view.Surface getSurface(); method public int getSurfaceGroupId(); method @NonNull public java.util.List getSurfaces(); + method public int getTimestampBase(); method public void removeSensorPixelModeUsed(int); method public void removeSurface(@NonNull android.view.Surface); method public void setDynamicRangeProfile(int); method public void setPhysicalCameraId(@Nullable String); method public void setStreamUseCase(int); + method public void setTimestampBase(int); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator CREATOR; field public static final int SURFACE_GROUP_ID_NONE = -1; // 0xffffffff + field public static final int TIMESTAMP_BASE_CHOREOGRAPHER_SYNCED = 4; // 0x4 + field public static final int TIMESTAMP_BASE_DEFAULT = 0; // 0x0 + field public static final int TIMESTAMP_BASE_MONOTONIC = 2; // 0x2 + field public static final int TIMESTAMP_BASE_REALTIME = 3; // 0x3 + field public static final int TIMESTAMP_BASE_SENSOR = 1; // 0x1 } public final class RecommendedStreamConfigurationMap { diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java index d8295c9621540..f67a5b44a8e9c 100644 --- a/core/java/android/hardware/camera2/params/OutputConfiguration.java +++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java @@ -37,7 +37,6 @@ import android.hardware.camera2.utils.SurfaceUtils; import android.media.ImageReader; import android.os.Parcel; import android.os.Parcelable; -import android.util.ArraySet; import android.util.Log; import android.util.Size; import android.view.Surface; @@ -152,6 +151,100 @@ public final class OutputConfiguration implements Parcelable { */ public static final int SURFACE_GROUP_ID_NONE = -1; + /** + * Default timestamp base. + * + *

The camera device decides the timestamp based on the properties of the + * output surface.

+ * + *
  • For a SurfaceView output surface, the timestamp base is {@link + * #TIMESTAMP_BASE_CHOREOGRAPHER_SYNCED}. The timestamp is overridden with choreographer + * pulses from the display subsystem for smoother display of camera frames. The timestamp + * is roughly in the same time base as {@link android.os.SystemClock#uptimeMillis}.
  • + *
  • For an output surface of MediaRecorder, MediaCodec, or ImageReader with {@link + * android.hardware.HardwareBuffer#USAGE_VIDEO_ENCODE} usge flag, the timestamp base is + * {@link #TIMESTAMP_BASE_MONOTONIC}, which is roughly the same time base as + * {@link android.os.SystemClock#uptimeMillis}.
  • + *
  • For all other cases, the timestamp base is {@link #TIMESTAMP_BASE_SENSOR}, the same + * as what's specified by {@link CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE}.
  • + * + * @see #TIMESTAMP_BASE_CHOREOGRAPHER_SYNCED + * @see #TIMESTAMP_BASE_MONOTONIC + * @see #TIMESTAMP_BASE_SENSOR + */ + public static final int TIMESTAMP_BASE_DEFAULT = 0; + + /** + * Timestamp base of {@link CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE}. + * + *

    The timestamps of the output images are in the time base as specified by {@link + * CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE}. The application can look up the + * corresponding result metadata for a particular output image using this timestamp.

    + */ + public static final int TIMESTAMP_BASE_SENSOR = 1; + + /** + * Timestamp base roughly the same as {@link android.os.SystemClock#uptimeMillis}. + * + *

    The timestamps of the output images are monotonically increasing, and are roughly in the + * same time base as {@link android.os.SystemClock#uptimeMillis}. The timestamps with this + * time base can be directly used for audio-video sync in video recording.

    + * + *

    If the camera device's {@link CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE} is + * REALTIME, timestamps with this time base cannot directly match the timestamps in + * {@link CameraCaptureSession.CaptureCallback#onCaptureStarted} or the sensor timestamps in + * {@link android.hardware.camera2.CaptureResult}.

    + */ + public static final int TIMESTAMP_BASE_MONOTONIC = 2; + + /** + * Timestamp base roughly the same as {@link android.os.SystemClock#elapsedRealtime}. + * + *

    The timestamps of the output images are roughly in the + * same time base as {@link android.os.SystemClock#elapsedRealtime}. The timestamps with this + * time base cannot be directly used for audio-video sync in video recording.

    + * + *

    If the camera device's {@link CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE} is + * UNKNOWN, timestamps with this time base cannot directly match the timestamps in + * {@link CameraCaptureSession.CaptureCallback#onCaptureStarted} or the sensor timestamps in + * {@link android.hardware.camera2.CaptureResult}.

    + * + *

    If using a REALTIME timestamp base on a device that supports only + * TIMESTAMP_SOURCE_UNKNOWN, the accuracy of timestamps is only what is guaranteed in the + * documentation for UNKNOWN. In particular, they have no guarantees about being accurate + * enough to use in fusing image data with the output of inertial sensors, for features such as + * image stabilization or augmented reality.

    + */ + public static final int TIMESTAMP_BASE_REALTIME = 3; + + /** + * Timestamp is synchronized to choreographer. + * + *

    The timestamp of the output images are overridden with choreographer pulses from the + * display subsystem for smoother display of camera frames. An output target of SurfaceView + * uses this time base by default.

    + * + *

    The choreographer synchronized timestamps are also reasonable to use when drawing to a + * TextureView. So this timestamp base can be used for a SurfaceTexture as part of a + * TextureView, in addition to SurfaceView.

    + * + *

    Timestamps with this time base cannot directly match the timestamps in + * {@link CameraCaptureSession.CaptureCallback#onCaptureStarted} or the sensor timestamps in + * {@link android.hardware.camera2.CaptureResult}. This timestamp base shouldn't be used if the + * timestamp needs to be used for audio-video synchronization.

    + */ + public static final int TIMESTAMP_BASE_CHOREOGRAPHER_SYNCED = 4; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"TIMESTAMP_BASE_"}, value = + {TIMESTAMP_BASE_DEFAULT, + TIMESTAMP_BASE_SENSOR, + TIMESTAMP_BASE_MONOTONIC, + TIMESTAMP_BASE_REALTIME, + TIMESTAMP_BASE_CHOREOGRAPHER_SYNCED}) + public @interface TimestampBase {}; + /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = {"SENSOR_PIXEL_MODE_"}, value = @@ -367,6 +460,7 @@ public final class OutputConfiguration implements Parcelable { mSensorPixelModesUsed = new ArrayList(); mDynamicRangeProfile = DynamicRangeProfiles.STANDARD; mStreamUseCase = CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT; + mTimestampBase = TIMESTAMP_BASE_DEFAULT; } /** @@ -809,6 +903,47 @@ public final class OutputConfiguration implements Parcelable { return mStreamUseCase; } + /** + * Set timestamp base for this output target + * + *

    Timestamp base describes the time domain of images from this + * camera output and its relationship with {@link + * CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE}.

    + * + *

    If this function is not called, the timestamp base for this output + * is {@link #TIMESTAMP_BASE_DEFAULT}, with which the camera device adjusts + * timestamps based on the output target.

    + * + *

    See {@link #TIMESTAMP_BASE_DEFAULT}, {@link #TIMESTAMP_BASE_SENSOR}, + * and {@link #TIMESTAMP_BASE_CHOREOGRAPHER_SYNCED} for details of each timestamp base.

    + * + * @param timestampBase The timestamp base to be set. + * + * @throws IllegalArgumentException If the timestamp base isn't within the range of valid + * values. + */ + public void setTimestampBase(@TimestampBase int timestampBase) { + // Verify that the value is in range + if (timestampBase < TIMESTAMP_BASE_DEFAULT || + timestampBase > TIMESTAMP_BASE_CHOREOGRAPHER_SYNCED) { + throw new IllegalArgumentException("Not a valid timestamp base value " + + timestampBase); + } + mTimestampBase = timestampBase; + } + + /** + * Get the current timestamp base + * + *

    If no {@link #setTimestampBase} is called first, this function returns + * {@link #TIMESTAMP_BASE_DEFAULT}.

    + * + * @return The currently set timestamp base + */ + public @TimestampBase int getTimestampBase() { + return mTimestampBase; + } + /** * Create a new {@link OutputConfiguration} instance with another {@link OutputConfiguration} * instance. @@ -837,6 +972,7 @@ public final class OutputConfiguration implements Parcelable { this.mSensorPixelModesUsed = other.mSensorPixelModesUsed; this.mDynamicRangeProfile = other.mDynamicRangeProfile; this.mStreamUseCase = other.mStreamUseCase; + this.mTimestampBase = other.mTimestampBase; } /** @@ -861,6 +997,7 @@ public final class OutputConfiguration implements Parcelable { int dynamicRangeProfile = source.readInt(); DynamicRangeProfiles.checkProfileValue(dynamicRangeProfile); + int timestampBase = source.readInt(); mSurfaceGroupId = surfaceSetId; mRotation = rotation; mSurfaces = surfaces; @@ -885,6 +1022,7 @@ public final class OutputConfiguration implements Parcelable { mSensorPixelModesUsed = convertIntArrayToIntegerList(sensorPixelModesUsed); mDynamicRangeProfile = dynamicRangeProfile; mStreamUseCase = streamUseCase; + mTimestampBase = timestampBase; } /** @@ -1002,6 +1140,7 @@ public final class OutputConfiguration implements Parcelable { dest.writeIntArray(convertIntegerToIntList(mSensorPixelModesUsed)); dest.writeInt(mDynamicRangeProfile); dest.writeInt(mStreamUseCase); + dest.writeInt(mTimestampBase); } /** @@ -1033,7 +1172,8 @@ public final class OutputConfiguration implements Parcelable { mConfiguredGenerationId != other.mConfiguredGenerationId || !Objects.equals(mPhysicalCameraId, other.mPhysicalCameraId) || mIsMultiResolution != other.mIsMultiResolution || - mStreamUseCase != other.mStreamUseCase) + mStreamUseCase != other.mStreamUseCase || + mTimestampBase != other.mTimestampBase) return false; if (mSensorPixelModesUsed.size() != other.mSensorPixelModesUsed.size()) { return false; @@ -1071,7 +1211,7 @@ public final class OutputConfiguration implements Parcelable { mSurfaceGroupId, mSurfaceType, mIsShared ? 1 : 0, mPhysicalCameraId == null ? 0 : mPhysicalCameraId.hashCode(), mIsMultiResolution ? 1 : 0, mSensorPixelModesUsed.hashCode(), - mDynamicRangeProfile, mStreamUseCase); + mDynamicRangeProfile, mStreamUseCase, mTimestampBase); } return HashCodeHelpers.hashCode( @@ -1080,7 +1220,7 @@ public final class OutputConfiguration implements Parcelable { mConfiguredDataspace, mSurfaceGroupId, mIsShared ? 1 : 0, mPhysicalCameraId == null ? 0 : mPhysicalCameraId.hashCode(), mIsMultiResolution ? 1 : 0, mSensorPixelModesUsed.hashCode(), - mDynamicRangeProfile, mStreamUseCase); + mDynamicRangeProfile, mStreamUseCase, mTimestampBase); } private static final String TAG = "OutputConfiguration"; @@ -1116,4 +1256,6 @@ public final class OutputConfiguration implements Parcelable { private int mDynamicRangeProfile; // Stream use case private int mStreamUseCase; + // Timestamp base + private int mTimestampBase; }