Merge "Camera: Unhide readout timestamp APIs"

This commit is contained in:
Shuzhen Wang
2022-12-21 17:22:12 +00:00
committed by Android (Google) Code Review
5 changed files with 115 additions and 43 deletions

View File

@@ -17787,6 +17787,7 @@ package android.hardware.camera2 {
method public void onCaptureSequenceAborted(@NonNull android.hardware.camera2.CameraCaptureSession, int);
method public void onCaptureSequenceCompleted(@NonNull android.hardware.camera2.CameraCaptureSession, int, long);
method public void onCaptureStarted(@NonNull android.hardware.camera2.CameraCaptureSession, @NonNull android.hardware.camera2.CaptureRequest, long, long);
method public void onReadoutStarted(@NonNull android.hardware.camera2.CameraCaptureSession, @NonNull android.hardware.camera2.CaptureRequest, long, long);
}
public abstract static class CameraCaptureSession.StateCallback {
@@ -18780,6 +18781,7 @@ package android.hardware.camera2.params {
method public int getSurfaceGroupId();
method @NonNull public java.util.List<android.view.Surface> getSurfaces();
method public int getTimestampBase();
method public boolean isReadoutTimestampUsed();
method public void removeSensorPixelModeUsed(int);
method public void removeSurface(@NonNull android.view.Surface);
method public void setDynamicRangeProfile(long);
@@ -18787,6 +18789,7 @@ package android.hardware.camera2.params {
method public void setPhysicalCameraId(@Nullable String);
method public void setStreamUseCase(long);
method public void setTimestampBase(int);
method public void useReadoutTimestamp(boolean);
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.hardware.camera2.params.OutputConfiguration> CREATOR;
field public static final int MIRROR_MODE_AUTO = 0; // 0x0

View File

@@ -1245,10 +1245,28 @@ public abstract class CameraCaptureSession implements AutoCloseable {
* the start of exposure, particularly when autoexposure is changing exposure duration
* between frames.</p>
*
* <p>This timestamp may not match {@link CaptureResult#SENSOR_TIMESTAMP the result
* timestamp field}. It will, however, match the timestamp of buffers sent to the
* output surfaces with {@link OutputConfiguration#TIMESTAMP_BASE_READOUT_SENSOR}
* timestamp base.</p>
* <p>The timestamps match the timestamps of the output surfaces with readout timestamp
* enabled (via {@link OutputConfiguration#useReadoutTimestamp}) if:</p>
* <ul>
* <li> Timestamp base is {@link OutputConfiguration#TIMESTAMP_BASE_DEFAULT} and the
* output
* <ul>
* <li> is not a SurfaceView surface, and </li>
* <li> is not a MediaRecoder, MediaCodec, or ImageReader surface with {@link
* android.hardware.HardwareBuffer#USAGE_VIDEO_ENCODE} usage flag or the device's {@link
* CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE} is {@code UNKNOWN}</li>
* </ul>
* </li>
* <li> Timestamp base is {@link OutputConfiguration#TIMESTAMP_BASE_SENSOR},</li>
* <li> Timestamp base is {@link OutputConfiguration#TIMESTAMP_BASE_MONOTONIC} and the
* device's {@link CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE} is {@code
* UNKNOWN},</li>
* <li> Timestamp base is {@link OutputConfiguration#TIMESTAMP_BASE_REALTIME} and the
* device's {@link CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE} is {@code REALTIME}
* </li>
* </ul>
* <p>Otherwise, the timestamps won't match the timestamp of the output surfaces. See
* the possible parameters for {@link OutputConfiguration#setTimestampBase} for details.</p>
*
* <p>This callback will be called only if {@link
* CameraCharacteristics#SENSOR_READOUT_TIMESTAMP} is
@@ -1261,8 +1279,6 @@ public abstract class CameraCaptureSession implements AutoCloseable {
* the timestamp at the input image's start of readout for a
* reprocess request, in nanoseconds.
* @param frameNumber the frame number for this capture
*
* @hide
*/
public void onReadoutStarted(@NonNull CameraCaptureSession session,
@NonNull CaptureRequest request, long timestamp, long frameNumber) {

View File

@@ -4588,22 +4588,26 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
/**
* <p>Whether or not the camera device supports readout timestamp and
* onReadoutStarted callback.</p>
* <p>If this tag is HARDWARE, the camera device calls onReadoutStarted in addition to the
* onCaptureStarted callback for each capture. The timestamp passed into the callback
* is the start of camera image readout rather than the start of the exposure. In
* addition, the application can configure an
* {@link android.hardware.camera2.params.OutputConfiguration } with
* TIMESTAMP_BASE_READOUT_SENSOR timestamp base, in which case, the timestamp of the
* output surface matches the timestamp from the corresponding onReadoutStarted callback.</p>
* {@code onReadoutStarted} callback.</p>
* <p>If this tag is {@code HARDWARE}, the camera device calls
* {@link CameraCaptureSession.CaptureCallback#onReadoutStarted } in addition to the
* {@link CameraCaptureSession.CaptureCallback#onCaptureStarted } callback for each capture.
* The timestamp passed into the callback is the start of camera image readout rather than
* the start of the exposure. The timestamp source of
* {@link CameraCaptureSession.CaptureCallback#onReadoutStarted } is the same as that of
* {@link CameraCaptureSession.CaptureCallback#onCaptureStarted }.</p>
* <p>In addition, the application can switch an output surface's timestamp from start of
* exposure to start of readout by calling
* {@link android.hardware.camera2.params.OutputConfiguration#useReadoutTimestamp }.</p>
* <p>The readout timestamp is beneficial for video recording, because the encoder favors
* uniform timestamps, and the readout timestamps better reflect the cadence camera sensors
* output data.</p>
* <p>If this tag is HARDWARE, the camera device produces the start-of-exposure and
* start-of-readout together. As a result, the onReadoutStarted is called right after
* onCaptureStarted. The difference in start-of-readout and start-of-exposure is the sensor
* exposure time, plus certain constant offset. The offset is usually due to camera sensor
* level crop, and it remains constant for a given camera sensor mode.</p>
* <p>Note that the camera device produces the start-of-exposure and start-of-readout callbacks
* together. As a result, the {@link CameraCaptureSession.CaptureCallback#onReadoutStarted }
* is called right after {@link CameraCaptureSession.CaptureCallback#onCaptureStarted }. The
* difference in start-of-readout and start-of-exposure is the sensor exposure time, plus
* certain constant offset. The offset is usually due to camera sensor level crop, and it is
* generally constant over time for the same set of output resolutions and capture settings.</p>
* <p><b>Possible values:</b></p>
* <ul>
* <li>{@link #SENSOR_READOUT_TIMESTAMP_NOT_SUPPORTED NOT_SUPPORTED}</li>

View File

@@ -1700,9 +1700,8 @@ public abstract class CameraMetadata<TKey> {
/**
* <p>This camera device supports the onReadoutStarted callback as well as outputting
* readout timestamp for streams with TIMESTAMP_BASE_READOUT_SENSOR timestamp base. The
* readout timestamp is generated by the camera hardware and it has the same accuracy
* and timing characteristics of the start-of-exposure time.</p>
* readout timestamps. The readout timestamp is generated by the camera hardware and it
* has the same accuracy and timing characteristics of the start-of-exposure time.</p>
* @see CameraCharacteristics#SENSOR_READOUT_TIMESTAMP
*/
public static final int SENSOR_READOUT_TIMESTAMP_HARDWARE = 1;

View File

@@ -191,7 +191,9 @@ public final class OutputConfiguration implements Parcelable {
*
* <p>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.</p>
* corresponding result metadata by matching the timestamp with a {@link
* CameraCaptureSession.CaptureCallback#onCaptureStarted}, or with a {@link
* CameraCaptureSession.CaptureCallback#onReadoutStarted} if readout timestamp is used.</p>
*/
public static final int TIMESTAMP_BASE_SENSOR = 1;
@@ -204,7 +206,8 @@ public final class OutputConfiguration implements Parcelable {
*
* <p>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 CameraCaptureSession.CaptureCallback#onCaptureStarted}, {@link
* CameraCaptureSession.CaptureCallback#onReadoutStarted}, or the sensor timestamps in
* {@link android.hardware.camera2.CaptureResult}.</p>
*/
public static final int TIMESTAMP_BASE_MONOTONIC = 2;
@@ -218,7 +221,8 @@ public final class OutputConfiguration implements Parcelable {
*
* <p>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 CameraCaptureSession.CaptureCallback#onCaptureStarted}, {@link
* CameraCaptureSession.CaptureCallback#onReadoutStarted}, or the sensor timestamps in
* {@link android.hardware.camera2.CaptureResult}.</p>
*
* <p>If using a REALTIME timestamp base on a device that supports only
@@ -243,7 +247,8 @@ public final class OutputConfiguration implements Parcelable {
* displayed right away.</p>
*
* <p>Timestamps with this time base cannot directly match the timestamps in
* {@link CameraCaptureSession.CaptureCallback#onCaptureStarted} or the sensor timestamps in
* {@link CameraCaptureSession.CaptureCallback#onCaptureStarted}, {@link
* CameraCaptureSession.CaptureCallback#onReadoutStarted}, 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.</p>
*/
@@ -252,18 +257,7 @@ public final class OutputConfiguration implements Parcelable {
/**
* Timestamp is the start of readout in the same time domain as TIMESTAMP_BASE_SENSOR.
*
* <p>The start of the camera sensor readout after exposure. For a rolling shutter camera
* sensor, the timestamp is typically equal to the start of exposure time +
* exposure time + certain fixed offset. The fixed offset could be due to camera sensor
* level crop. The benefit of using readout time is that when camera runs in a fixed
* frame rate, the timestamp intervals between frames are constant.</p>
*
* <p>This timestamp is in the same time domain as in TIMESTAMP_BASE_SENSOR, with the exception
* that one is start of exposure, and the other is start of readout.</p>
*
* <p>This timestamp base is supported only if {@link
* CameraCharacteristics#SENSOR_READOUT_TIMESTAMP} is
* {@link CameraMetadata#SENSOR_READOUT_TIMESTAMP_HARDWARE}.</p>
* <p>NOTE: do not use! Use useReadoutTimestamp instead.</p>
*
* @hide
*/
@@ -579,6 +573,8 @@ public final class OutputConfiguration implements Parcelable {
mStreamUseCase = CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT;
mTimestampBase = TIMESTAMP_BASE_DEFAULT;
mMirrorMode = MIRROR_MODE_AUTO;
mUseReadoutTimestamp = false;
mIsReadoutSensorTimestampBase = false;
}
/**
@@ -679,6 +675,8 @@ public final class OutputConfiguration implements Parcelable {
mDynamicRangeProfile = DynamicRangeProfiles.STANDARD;
mColorSpace = ColorSpaceProfiles.UNSPECIFIED;
mStreamUseCase = CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT;
mUseReadoutTimestamp = false;
mIsReadoutSensorTimestampBase = false;
}
/**
@@ -1048,7 +1046,15 @@ public final class OutputConfiguration implements Parcelable {
throw new IllegalArgumentException("Not a valid timestamp base value " +
timestampBase);
}
mTimestampBase = timestampBase;
if (timestampBase == TIMESTAMP_BASE_READOUT_SENSOR) {
mTimestampBase = TIMESTAMP_BASE_SENSOR;
mUseReadoutTimestamp = true;
mIsReadoutSensorTimestampBase = true;
} else {
mTimestampBase = timestampBase;
mIsReadoutSensorTimestampBase = false;
}
}
/**
@@ -1060,7 +1066,11 @@ public final class OutputConfiguration implements Parcelable {
* @return The currently set timestamp base
*/
public @TimestampBase int getTimestampBase() {
return mTimestampBase;
if (mIsReadoutSensorTimestampBase) {
return TIMESTAMP_BASE_READOUT_SENSOR;
} else {
return mTimestampBase;
}
}
/**
@@ -1099,6 +1109,37 @@ public final class OutputConfiguration implements Parcelable {
return mMirrorMode;
}
/**
* Use the camera sensor's readout time for the image timestamp.
*
* <p>The start of the camera sensor readout after exposure. For a rolling shutter camera
* sensor, the timestamp is typically equal to {@code (the start of exposure time) +
* (exposure time) + (certain fixed offset)}. The fixed offset can vary per session, depending
* on the underlying sensor configuration. The benefit of using readout time is that when
* camera runs in a fixed frame rate, the timestamp intervals between frames are constant.</p>
*
* <p>Readout timestamp is supported only if {@link
* CameraCharacteristics#SENSOR_READOUT_TIMESTAMP} is
* {@link CameraMetadata#SENSOR_READOUT_TIMESTAMP_HARDWARE}.</p>
*
* <p>As long as readout timestamp is supported, if the timestamp base isi
* {@link #TIMESTAMP_BASE_CHOREOGRAPHER_SYNCED}, or if the timestamp base is DEFAULT for a
* SurfaceView output, the image timestamps for the output are always readout time regardless
* of whether this function is called.</p>
*
* @param on The output image timestamp is the start of exposure time if false, and
* the start of readout time if true.
*/
public void useReadoutTimestamp(boolean on) {
mUseReadoutTimestamp = on;
}
/** Whether readout timestamp is used for this OutputConfiguration.
*/
public boolean isReadoutTimestampUsed() {
return mUseReadoutTimestamp;
}
/**
* Create a new {@link OutputConfiguration} instance with another {@link OutputConfiguration}
* instance.
@@ -1130,6 +1171,7 @@ public final class OutputConfiguration implements Parcelable {
this.mStreamUseCase = other.mStreamUseCase;
this.mTimestampBase = other.mTimestampBase;
this.mMirrorMode = other.mMirrorMode;
this.mUseReadoutTimestamp = other.mUseReadoutTimestamp;
}
/**
@@ -1157,6 +1199,7 @@ public final class OutputConfiguration implements Parcelable {
int timestampBase = source.readInt();
int mirrorMode = source.readInt();
boolean useReadoutTimestamp = source.readInt() == 1;
mSurfaceGroupId = surfaceSetId;
mRotation = rotation;
@@ -1185,6 +1228,7 @@ public final class OutputConfiguration implements Parcelable {
mStreamUseCase = streamUseCase;
mTimestampBase = timestampBase;
mMirrorMode = mirrorMode;
mUseReadoutTimestamp = useReadoutTimestamp;
}
/**
@@ -1305,6 +1349,7 @@ public final class OutputConfiguration implements Parcelable {
dest.writeLong(mStreamUseCase);
dest.writeInt(mTimestampBase);
dest.writeInt(mMirrorMode);
dest.writeInt(mUseReadoutTimestamp ? 1 : 0);
}
/**
@@ -1338,7 +1383,8 @@ public final class OutputConfiguration implements Parcelable {
mIsMultiResolution != other.mIsMultiResolution ||
mStreamUseCase != other.mStreamUseCase ||
mTimestampBase != other.mTimestampBase ||
mMirrorMode != other.mMirrorMode)
mMirrorMode != other.mMirrorMode ||
mUseReadoutTimestamp != other.mUseReadoutTimestamp)
return false;
if (mSensorPixelModesUsed.size() != other.mSensorPixelModesUsed.size()) {
return false;
@@ -1381,7 +1427,7 @@ public final class OutputConfiguration implements Parcelable {
mPhysicalCameraId == null ? 0 : mPhysicalCameraId.hashCode(),
mIsMultiResolution ? 1 : 0, mSensorPixelModesUsed.hashCode(),
mDynamicRangeProfile, mColorSpace, mStreamUseCase,
mTimestampBase, mMirrorMode);
mTimestampBase, mMirrorMode, mUseReadoutTimestamp ? 1 : 0);
}
return HashCodeHelpers.hashCode(
@@ -1391,7 +1437,7 @@ public final class OutputConfiguration implements Parcelable {
mPhysicalCameraId == null ? 0 : mPhysicalCameraId.hashCode(),
mIsMultiResolution ? 1 : 0, mSensorPixelModesUsed.hashCode(),
mDynamicRangeProfile, mColorSpace, mStreamUseCase, mTimestampBase,
mMirrorMode);
mMirrorMode, mUseReadoutTimestamp ? 1 : 0);
}
private static final String TAG = "OutputConfiguration";
@@ -1433,4 +1479,8 @@ public final class OutputConfiguration implements Parcelable {
private int mTimestampBase;
// Mirroring mode
private int mMirrorMode;
// Use readout timestamp
private boolean mUseReadoutTimestamp;
// Whether the timestamp base is set to READOUT_SENSOR
private boolean mIsReadoutSensorTimestampBase;
}