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

Force DRM license request #6337

Closed
kgrevehagen opened this issue Aug 23, 2019 · 8 comments
Closed

Force DRM license request #6337

kgrevehagen opened this issue Aug 23, 2019 · 8 comments
Assignees
Labels

Comments

@kgrevehagen
Copy link

Use case description

In order to fetch a DRM license from our license server, I need to supply a short-lived security token.

When playing in a ConcatenatingMediaSource, the security token(which is retrieved along with other playback data when preparing a MediaSource) might have expired at the time the DefaultDrmSession tries to get the license key. In case of a 4xx error on the license key call, I need to refetch the security token and then retry the license key request.

Proposed solution

  • In onDrmSessionManagerError I can fetch a new security token and then force a new key request. The latter is afaik not possible, but would be helpful. The reason I want to do it in onDrmSessionManagerError is because it's most likely still in the clear lead and the music still plays.
  • With your expertise there might exist a better solution.

Alternatives considered

  • I can handle it in onPlayerError, but then I get a pause in playback, which is not good.
  • I can catch the exception in my implementation of MediaDrmCallback and do the retry there myself, but that feels kinda backwards.
  • Force a fetch of the license security token right before we request the license key, but this feels kinda backwards and makes double calls to our backend, which we don't want to do.
@tonihei
Copy link
Collaborator

tonihei commented Aug 23, 2019

There are some ways to avoid this problem from occurring I think:

  • You can use a ResolvingDataSource to resolve your security token just in time for the license request. This way you don't load it in advance, but it can't expire either.
  • You can turn on lazyPreparation in the ConcatenatingMediaSource (in the long constructor) to only prepare the MediaSource when they are actually needed. That means they are not prepared long in advance, but only when we start pre-buffering the media. Be aware however that if you prepared a MediaSource once, it stays prepared and if you'd like to come back later, your keys mat have expired again.

@AquilesCanta
Copy link
Contributor

Can't you generate the token at the moment MediaDrmCallback.executeKeyRequest is invoked?

Retrial of licence requests is being tracked by #6334.

@kgrevehagen
Copy link
Author

  • You can use a ResolvingDataSource to resolve your security token just in time for the license request. This way you don't load it in advance, but it can't expire either.

As far as I've understood, the ResolvingDataSource will still resolve when it is pre-buffering media(as opposed to when I create the DataSource). Or have I misunderstood? This means that if I pause playback right after it has been resolved(but before executeKeyRequest has been called), I can resume playback after it has expired, and when the next media source starts playing, my token would have been expired.

  • You can turn on lazyPreparation in the ConcatenatingMediaSource (in the long constructor) to only prepare the MediaSource when they are actually needed. That means they are not prepared long in advance, but only when we start pre-buffering the media. Be aware however that if you prepared a MediaSource once, it stays prepared and if you'd like to come back later, your keys mat have expired again.

Lazy preparation seems for me to work similarly.

Maybe you can clarify the difference between using a ResolvingDataSource with/without lazy preparation and just using a regular DataSource with/without lazy preparation?

Can't you generate the token at the moment MediaDrmCallback.executeKeyRequest is invoked?

I can(this was what I tried to say in the third alternative solution), but this token is tied to the asset url, so it is fetched from backend(not generated on the client side) together with that. Fetching it again would be bad for obvious reasons(same call twice in a row even if it has not expired).

Retrial of licence requests is being tracked by #6334.

This would only retry or not retry the same request, as it would just call executeKeyRequest again(or not). But when executeKeyRequest is called again, I have no idea of why it failed or how many times it has failed. This information could help me to make the correct decision in executeKeyRequest(whether or not I should refetch my short-lived token or just retry with the same). Is this something you would consider implementing?

@AquilesCanta
Copy link
Contributor

but this token is tied to the asset url, so it is fetched from backend(not generated on the client side) together with that.

I don't really see the issue.

Let's imagine you have a component with its own handler thread which is the TokenManager. Your media drm callback requests the token from the TokenManager each time it needs it.

If the TokenManager doesn't have a token or is renewing a token at the moment, the token request blocks the MediaDrmCallback from making the license request.

If the license request returns 4xx, then it notifies the TokenManager that it should invalidate the existing token. A later retry may be blocked until the TokenManager has a new token. You can then preemptively renew a token if you suspect it wont be valid in a shortly required license request.

I think it's better for you to know (and act upon) the error as soon as it happens, instead of waiting until the retry call (that includes the error history) is made.

Please clarify why an approach similar to the suggest above wouldn't work.

@google-oss-bot
Copy link
Collaborator

Hey @kgrevehagen. We need more information to resolve this issue but there hasn't been an update in 14 days. I'm marking the issue as stale and if there are no new updates in the next 7 days I will close it automatically.

If you have more information that will help us get to the bottom of this, just add a comment!

@kgrevehagen
Copy link
Author

If #4133 does what I think it does, this will no longer be an issue.

Can you verify(and is it guaranteed) that mediaDrmCallback.executeKeyRequest() will be called very close to mediaSource.prepare() even though we e.g. pause right after it is prepared? If this is the case, my token will never expire by that time, and there is no need for special handling around that, which simplifies implementation a lot.

Again, this is only an issue when it prepares the next track while current is playing.

@AquilesCanta
Copy link
Contributor

Can you verify(and is it guaranteed) that mediaDrmCallback.executeKeyRequest() will be called very close to mediaSource.prepare() even though we e.g. pause right after it is prepared?

No, this is not correct, and I doubt this can be guaranteed in general. I don't think you should count on this happening. The reason is that the key acquisition information may be obtained when buffering starts, which does not necessarily happen close to mediaSource.prepare() (for example in the case of a concatenating media source, where the buffering position is before the item).

We will be working on prefetching keys soon: Please track #4133 for key pre-fetching. This doesn't mean we will be doing it during preparation, though, just whenever we load the key acquisition information (for example, the pssh box).

If you really need to load the keys during preparation, you will have to adapt your app to whatever media type you are using. Preparation works differently in DASH and HLS. And if you are playing DASH, the key acquisition information may be obtained from the manifest or the chunks, and you'll have to act accordingly.

Is the original question answered?

@ojw28 ojw28 closed this as completed Jun 21, 2021
@ojw28
Copy link
Contributor

ojw28 commented Jun 21, 2021

Closing due to inactivity.

@google google locked and limited conversation to collaborators Aug 21, 2021
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

5 participants