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
This commit is contained in:
tonihei 2021-02-17 10:24:26 +00:00 committed by kim-vde
parent dea6a67ce9
commit f191000e20
5 changed files with 34 additions and 12 deletions

View file

@ -9,6 +9,9 @@
* Audio:
* Fix `SimpleExoPlayer` reporting audio session ID as 0 in some cases
([#8585](https://github.com/google/ExoPlayer/issues/8585)).
* Report unexpected discontinuities in
`AnalyticsListener.onAudioSinkError`
([#6384](https://github.com/google/ExoPlayer/issues/6384)).
* Analytics:
* Add `onAudioCodecError` and `onVideoCodecError` to `AnalyticsListener`.
* Library restructuring:

View file

@ -854,8 +854,9 @@ public interface AnalyticsListener {
* wishes to do so.
*
* @param eventTime The event time.
* @param audioSinkError Either a {@link AudioSink.InitializationException} or a {@link
* AudioSink.WriteException} describing the error.
* @param audioSinkError The error that occurred. Typically an {@link
* AudioSink.InitializationException}, a {@link AudioSink.WriteException}, or an {@link
* AudioSink.UnexpectedDiscontinuityException}.
*/
default void onAudioSinkError(EventTime eventTime, Exception audioSinkError) {}

View file

@ -144,7 +144,8 @@ public interface AudioRendererEventListener {
* wishes to do so.
*
* @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) {}

View file

@ -126,8 +126,8 @@ public interface AudioSink {
* <p>Fatal errors that cannot be recovered will be reported wrapped in a {@link
* ExoPlaybackException} by {@link Player.EventListener#onPlayerError(ExoPlaybackException)}.
*
* @param audioSinkError Either an {@link AudioSink.InitializationException} or a {@link
* AudioSink.WriteException} describing the error.
* @param audioSinkError The error that occurred. Typically an {@link InitializationException},
* a {@link WriteException}, or an {@link UnexpectedDiscontinuityException}.
*/
default void onAudioSinkError(Exception audioSinkError) {}
}
@ -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
* #SINK_FORMAT_SUPPORTED_DIRECTLY}, {@link #SINK_FORMAT_SUPPORTED_WITH_TRANSCODING} or {@link

View file

@ -762,13 +762,9 @@ public final class DefaultAudioSink implements AudioSink {
getSubmittedFrames() - trimmingAudioProcessor.getTrimmedFrameCount());
if (!startMediaTimeUsNeedsSync
&& Math.abs(expectedPresentationTimeUs - presentationTimeUs) > 200000) {
Log.e(
TAG,
"Discontinuity detected [expected "
+ expectedPresentationTimeUs
+ ", got "
+ presentationTimeUs
+ "]");
listener.onAudioSinkError(
new AudioSink.UnexpectedDiscontinuityException(
presentationTimeUs, expectedPresentationTimeUs));
startMediaTimeUsNeedsSync = true;
}
if (startMediaTimeUsNeedsSync) {