androidx / media

Jetpack Media3 support libraries for media use cases, including ExoPlayer, an extensible media player for Android
https://developer.android.com/media/media3
Apache License 2.0
1.59k stars 377 forks source link

Potential for Multiple Non-Internal Discontinuity Events #1483

Closed skidder closed 1 month ago

skidder commented 3 months ago

Version

Media3 1.1.1 / ExoPlayer 2.19.1

More version details

No response

Devices that reproduce the issue

Observed on Android OS 11-14, could include more.

Devices that do not reproduce the issue

No response

Reproducible in the demo app?

Not tested

Reproduction steps

  1. Implement a playback scenario with multiple periods or ads, ensuring the playback queue has distinct playing and reading periods.
  2. Induce a renderer error during playback, specifically when the playing period differs from the reading period.
  3. Observe the handling of discontinuity events following the renderer error, particularly the reporting of non-internal discontinuity reasons (Player.DISCONTINUITY_REASON_AUTO_TRANSITION) in quick succession or across different parts of the playback queue.

It's also manually reproducible in unit tests by instantiating PlaybackInfoUpdate and invoking setPositionDiscontinuity multiple times with non-internal events, i.e.

    // rapidly set position discontinuity
    playbackInfoUpdate.setPositionDiscontinuity(Player.DISCONTINUITY_REASON_SEEK);
    playbackInfoUpdate.setPositionDiscontinuity(Player.DISCONTINUITY_REASON_INTERNAL);
    playbackInfoUpdate.setPositionDiscontinuity(Player.DISCONTINUITY_REASON_SEEK);

Here's a draft PR showing the issue https://github.com/google/ExoPlayer/pull/11392

Expected result

No assert or unit test failures.

Actual result

In production we've seen app crashes with the following stack-trace:

java.lang.IllegalArgumentException: null
    at com.google.android.exoplayer2.util.Assertions.checkArgument
    at com.google.android.exoplayer2.ExoPlayerImplInternal$PlaybackInfoUpdate.setPositionDiscontinuity(SourceFile:121)
    at com.google.android.exoplayer2.ExoPlayerImplInternal.handlePositionDiscontinuity(SourceFile:2489)
    at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(SourceFile:626)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loopOnce(Looper.java:210)
    at android.os.Looper.loop(Looper.java:299)
    at android.os.HandlerThread.run(HandlerThread.java:67)

We began seeing this exception after upgrading from Exoplayer 2.13.3 to 2.19.1. This stack-trace follows a path introduced in commit 79b688ef30d4a3306d4d321ddf4464b428074ea2. It occurs across a broad range of Android OS (mostly 11-14) and Android device class.

Media

Not applicable

Bug Report

tonihei commented 3 months ago

Thanks for reporting! Reporting multiple non-internal discontinuities is not expected to happen within the same iteration generally, but the logic added in https://github.com/androidx/media/commit/79b688ef30d4a3306d4d321ddf4464b428074ea2 is special in that it can run after nearly every other piece of code in this class and needs to handle the potential for other pending events.