Open Kolyall opened 3 years ago
All works fine if: click on playFirstButton click on playSecondButton click on stopButton click on playFirstButton click on playSecondButton
But error occurs if: click on playFirstButton click on stopButton click on playFirstButton
This line in the stack trace indicates something is interacting with the same DefaultDrmSessionManager
instance from different 'playback' threads:
com.google.android.exoplayer2.drm.DefaultDrmSessionManager.initPlaybackLooper(DefaultDrmSessionManager.java:668)
The playback thread is created inside the ExoPlayer library - there's one playback thread associated with each instance of SimpleExoPlayer
.
It looks like this multi-threaded access is happening roughly because:
DashMediaSource.Factory
instance is being used across multiple SimpleExoPlayer
instances (because pauseAndStop()
nulls out the player, so getOrCreateExoPlayer()
always creates a new one).DefaultDrmSessionManagerProvider
used inside DashMediaSource.Factory
will re-use a previously created DefaultDrmSessionManager
instance if the MediaItem
DRM fields match:
https://github.com/google/ExoPlayer/blob/b2333c86c1eac9a1f95992960a8495f1e5b79200/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSessionManagerProvider.java#L86-L90(2) explains why you don't see the problem when playing different items - the different drmKeySetId
values cause a different DefaultDrmSessionManager
to be instantiated each time (which itself might not be necessary, since that particular value is only needed for a setter, not the constructor, but that's getting a bit off topic for this issue).
To make your code work, I think you should couple your DashMediaSource.Factory
lifecycle to your SimpleExoPlayer
instance. i.e. in pauseAndStop()
*also** null the DashMediaSource.Factory
and recreate it each time when you create the player.
We should either make the currently broken sequence of operations work correctly (which we could do by removing the caching from DefaultDrmSessionManagerProvider
, but unfortunately that's there to fix a different issue: https://github.com/google/ExoPlayer/issues/8523)) or clearly document which part of what you're doing isn't/shouldn't be allowed. I'll keep this open for now to track that work and discuss with the rest of the team.
Another ExoPlayer change that might make this work (untested) is to null out the playbackLooper
field in DefaultDrmSessionManager#release()
. Since in the sequence above the player (and thus the DefaultDrmSessionManager
) is fully released before being re-instantiated.
@icbaker as you suggested I made this: Don't null out the player instance (you should definitely still release() it).
But after exoplayer.release()
exoPlayer?.playbackState
remains Player.STATE_READY
exoPlayer?.currentMediaItem
is not null
How can I determinate that player was released?
Sorry, when I made that suggestion I'd got mixed up between DrmSessionManager
(which can be re-prepared after being released) and Player
(which can't). So my suggestion to release it without nulling it out doesn't make any sense, because there's no way to re-prepare it. From the Player#release()
javadoc:
The player must not be used after calling this method.
I'll edit my comment above to remove that suggestion - I think that means your only workaround option for now is to instantiate the DashMediaSource.Factory
each time.
Error: