Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

seekToNextMediaItem() affected by DRM latency, while automatic playlist transitions are not #1602

Closed
gi11es opened this issue Aug 7, 2024 · 3 comments
Assignees
Labels

Comments

@gi11es
Copy link

gi11es commented Aug 7, 2024

The context is using ExoPlayer with Widevine-protected videos exclusively, each requiring their own DRM license. The videos do not have an unencrypted start, they are fully encrypted from the very beginning. They are most of the time cached locally with DashDownloader.

If the media items are set up as a playlist on the player, automatic transitions from one item to the next are seamless and the player gets the DRM license ahead of the next video starting to play. No black screen between the media items.

If the user skips to the next video themselves, via calling seekToNextMediaItem(), the player turns black while the DRM license request happens. Only after it's completed will the next video start playing. A black screen will flash for however long the DRM request takes to complete. This happens even if the video segments are locally cached.

I have a feeling that this issue hasn't been seen much by others before, because most DRM packagers tend to have a default setting of having the first few seconds of a video in the clear, which would likely mask this issue.

I've spent days trying to override all the different parts (DRM session manager, etc.) but I can't find a way to essential prepare the next media item for a player for its DRM license, without the player making that item the current one.

I'm looking for a way to perform either of these scenarios:

  • Ask the player to play the next video as soon as its DRM license is ready. Essentially the DRM request duration is spent still playing the current video before going to the next one. (least desirable option)
  • Ask the player to get the DRM license for the next media item ahead of time, with a long enough session keepalive duratio + multisession enabled on the DRM session manager, so that when the user eventually skips to the next media item, its DRM license has already been acquired (most desirable option)

After trying very hard, I have the impression that neither option is possible as-is without some upstream changes, but I'd be very happy to be proven wrong and pointed to existing mechanics that would allow either of these scenarios to be implemented.

I think that having more fine-grained control over when DRM license requests happen for an arbitrary media item, decoupled from when it plays, would be very useful for a variety of scenarios.

@icbaker
Copy link
Collaborator

icbaker commented Aug 7, 2024

As you've seen, ExoPlayer's default behaviour is to request a DRM license for content as soon as it loads the content into memory (SampleQueue). By default, we buffer 50s ahead of the playback position (this is configurable via LoadControl), and so DRM licenses are also requested 50s ahead.

This happens even if the video segments are locally cached.

I assume this mneans "cached on disk", because if the video segment has been loaded into memory by ExoPlayer then we should already have requested the DRM license.


The best way to manually trigger this session acquisition is via DrmSessionManager.preacquireSession. For this you will need a Format object representing the content you want the session for, with the correct drmInitData set. You will also need to hold onto the returned DrmSessionReference object, so you can release it either when the content starts playing (at this point the session will be held open by the player until playback is complete), or when you've decided that the content actually won't be played. This doesn't rely on the keepalive timeout, the session will be held open by your DrmSessionReference unless the player encounters playback issues due to shortage of DRM sessions on the device, at which point any preacquired sessions will be released in order to free up the resources to unblock playback.

You can get a handle to the right DrmSessionManager instance by providing a DrmSessionManagerProvider when building your ExoPlayer instance.

It sounds like you might have already tried something like this, but I'm afraid you haven't really provided enough detail about why it didn't work.

@gi11es
Copy link
Author

gi11es commented Aug 7, 2024

Thank you so much for your fast reply! You've given me enough information to find a workaround.

I did go down the preacquireSession rabbit hole, figured out how to make a custom DrmSessionManagerProvider, but didn't get far enough to passing the correct Format/drmInitData. Thanks for confirming that this is the "correct" approach for fine-grained control over triggering a DRM request for an upcoming item.

The LoadControl settings, however, are something I hadn't been able to find before. I was really wondering where that prefetching of the DRM license for the next playlist item logic was defined and you've provided the answer.

This has allowed me to implement a workaround: setting a buffering window greater than the current item via DefaultLoadControl.Builder().setBufferDurationsMs, and waiting before setting REPEAT_MODE_ONE for the current video, to give the player time to prepare the next item before the repetition of the current item kicks in. I was setting the repeat mode upon STATE_READY previously and that was too early: the player logic was seeing that the next item was the current one repeated and wouldn't attempt to load the next item.

If I'm not mistaken, ExoPlayer currently doesn't support any visual transitions between video media items like crossfades, does it? Is that typically implemented with 2 or more players in separate views rendered on top of each other?

@icbaker
Copy link
Collaborator

icbaker commented Aug 7, 2024

If I'm not mistaken, ExoPlayer currently doesn't support any visual transitions between video media items like crossfades, does it? Is that typically implemented with 2 or more players in separate views rendered on top of each other?

That's correct. Audio crossfade support is tracked by #2. I don't think we have an issue tracking video crossfade, though it is discussed a bit in this closed issue (in the context of the androidx.media3.transformer API: #624

Feel free to open a new enhancement issue to track video crossfade support, I suspect an implementation of this would use the Transformer/Effect machinery.

It sounds like you've got a solution to your immediate problem, so I'm going to close this issue.

@icbaker icbaker closed this as completed Aug 7, 2024
@androidx androidx locked and limited conversation to collaborators Oct 7, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

2 participants