Commit f191000e by tonihei Committed by kim-vde

Report unexpected discontinuity as non-fatal audio sink error.

This is preferable to just logging to LogCat so that listeners can
report this to analytics systems if required.

Issue: #6384
PiperOrigin-RevId: 357906079
parent dea6a67c
...@@ -9,6 +9,9 @@ ...@@ -9,6 +9,9 @@
* Audio: * Audio:
* Fix `SimpleExoPlayer` reporting audio session ID as 0 in some cases * Fix `SimpleExoPlayer` reporting audio session ID as 0 in some cases
([#8585](https://github.com/google/ExoPlayer/issues/8585)). ([#8585](https://github.com/google/ExoPlayer/issues/8585)).
* Report unexpected discontinuities in
`AnalyticsListener.onAudioSinkError`
([#6384](https://github.com/google/ExoPlayer/issues/6384)).
* Analytics: * Analytics:
* Add `onAudioCodecError` and `onVideoCodecError` to `AnalyticsListener`. * Add `onAudioCodecError` and `onVideoCodecError` to `AnalyticsListener`.
* Library restructuring: * Library restructuring:
......
...@@ -854,8 +854,9 @@ public interface AnalyticsListener { ...@@ -854,8 +854,9 @@ public interface AnalyticsListener {
* wishes to do so. * wishes to do so.
* *
* @param eventTime The event time. * @param eventTime The event time.
* @param audioSinkError Either a {@link AudioSink.InitializationException} or a {@link * @param audioSinkError The error that occurred. Typically an {@link
* AudioSink.WriteException} describing the error. * AudioSink.InitializationException}, a {@link AudioSink.WriteException}, or an {@link
* AudioSink.UnexpectedDiscontinuityException}.
*/ */
default void onAudioSinkError(EventTime eventTime, Exception audioSinkError) {} default void onAudioSinkError(EventTime eventTime, Exception audioSinkError) {}
......
...@@ -144,7 +144,8 @@ public interface AudioRendererEventListener { ...@@ -144,7 +144,8 @@ public interface AudioRendererEventListener {
* wishes to do so. * wishes to do so.
* *
* @param audioSinkError The error that occurred. Typically an {@link * @param audioSinkError The error that occurred. Typically an {@link
* AudioSink.InitializationException} or a {@link AudioSink.WriteException}. * AudioSink.InitializationException}, a {@link AudioSink.WriteException}, or an {@link
* AudioSink.UnexpectedDiscontinuityException}.
*/ */
default void onAudioSinkError(Exception audioSinkError) {} default void onAudioSinkError(Exception audioSinkError) {}
......
...@@ -126,8 +126,8 @@ public interface AudioSink { ...@@ -126,8 +126,8 @@ public interface AudioSink {
* <p>Fatal errors that cannot be recovered will be reported wrapped in a {@link * <p>Fatal errors that cannot be recovered will be reported wrapped in a {@link
* ExoPlaybackException} by {@link Player.EventListener#onPlayerError(ExoPlaybackException)}. * ExoPlaybackException} by {@link Player.EventListener#onPlayerError(ExoPlaybackException)}.
* *
* @param audioSinkError Either an {@link AudioSink.InitializationException} or a {@link * @param audioSinkError The error that occurred. Typically an {@link InitializationException},
* AudioSink.WriteException} describing the error. * a {@link WriteException}, or an {@link UnexpectedDiscontinuityException}.
*/ */
default void onAudioSinkError(Exception audioSinkError) {} default void onAudioSinkError(Exception audioSinkError) {}
} }
...@@ -226,6 +226,27 @@ public interface AudioSink { ...@@ -226,6 +226,27 @@ public interface AudioSink {
} }
/** Thrown when the sink encounters an unexpected timestamp discontinuity. */
final class UnexpectedDiscontinuityException extends Exception {
/** The actual presentation time of a sample, in microseconds. */
public final long actualPresentationTimeUs;
/** The expected presentation time of a sample, in microseconds. */
public final long expectedPresentationTimeUs;
/**
* Creates an instance.
*
* @param actualPresentationTimeUs The actual presentation time of a sample, in microseconds.
* @param expectedPresentationTimeUs The expected presentation time of a sample, in
* microseconds.
*/
public UnexpectedDiscontinuityException(
long actualPresentationTimeUs, long expectedPresentationTimeUs) {
this.actualPresentationTimeUs = actualPresentationTimeUs;
this.expectedPresentationTimeUs = expectedPresentationTimeUs;
}
}
/** /**
* The level of support the sink provides for a format. One of {@link * The level of support the sink provides for a format. One of {@link
* #SINK_FORMAT_SUPPORTED_DIRECTLY}, {@link #SINK_FORMAT_SUPPORTED_WITH_TRANSCODING} or {@link * #SINK_FORMAT_SUPPORTED_DIRECTLY}, {@link #SINK_FORMAT_SUPPORTED_WITH_TRANSCODING} or {@link
......
...@@ -762,13 +762,9 @@ public final class DefaultAudioSink implements AudioSink { ...@@ -762,13 +762,9 @@ public final class DefaultAudioSink implements AudioSink {
getSubmittedFrames() - trimmingAudioProcessor.getTrimmedFrameCount()); getSubmittedFrames() - trimmingAudioProcessor.getTrimmedFrameCount());
if (!startMediaTimeUsNeedsSync if (!startMediaTimeUsNeedsSync
&& Math.abs(expectedPresentationTimeUs - presentationTimeUs) > 200000) { && Math.abs(expectedPresentationTimeUs - presentationTimeUs) > 200000) {
Log.e( listener.onAudioSinkError(
TAG, new AudioSink.UnexpectedDiscontinuityException(
"Discontinuity detected [expected " presentationTimeUs, expectedPresentationTimeUs));
+ expectedPresentationTimeUs
+ ", got "
+ presentationTimeUs
+ "]");
startMediaTimeUsNeedsSync = true; startMediaTimeUsNeedsSync = true;
} }
if (startMediaTimeUsNeedsSync) { if (startMediaTimeUsNeedsSync) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment