This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.
One of the basic models for EME is to receive a needkey event and immediately pass the initData to createSession(). This is simple and straightforward, but in practice, the same or equivalent initData may be seen many times - from various streams (i.e. audio and video) and during each adaptive stream switch. That simple concept results in many sessions and potentially many license requests (and related denials for too many requests). We have discussed this before (bug 16553, bug 19208, bug 21855) but did not reach a good solution. I'd like to revisit the issue now that we have implementation experience and come up with a better solution. Let's use this bug to track the problem and discuss ideas. The current workaround is for applications to avoid calling createSession() unless appropriate. The simplest implementation is to ignore all but the first needkey event. (This assumes the license server will return the appropriate keys for all streams.) Another possible solution is to only call createSession() for each unique initData value. This works in some cases, but can cause problems for license management. Also, applications must save and compare initData such as concatenated PSSH boxes. These workarounds start to break down when key rotation is involved - how can an application know when there is a new set of keys vs. a different version of initData for the same time period? Another option, which was the outcome of bug 21855 was to allow implementations to avoid firing a message event if there is already an in-memory session, possibly already containing a license, for the provided initData. I don't think this is a good solution (bug 25267). There might be similar solutions that make sense, but I think avoiding the problem altogether would be better for applications.
One of the issues we had during previous discussions is that createSession() always returned a MediaKeySession. With the introduction of Promises (bug 25199), we have the option to not return a session based on asynchronous processing. Thus, instead of creating a useless session object (bug 25267), implementations can reject the promise with an appropriate DOMException if the specified initData was not used to create any of the existing active (i.e. not closed) sessions for this MediaKeys object. This would allow applications to always call createSession() in response to a needkey event while avoiding creation of unnecessary sessions and potentially license requests. We might need a unique DOMException value so that applications can easily check for and ignore this non-error rejection of the Promise. Since the problem described in this bug needs to be solved for all implementations, we would specify this as the behavior for *all* implementations. This would prevent applications from creating a second session for the same initData. If there is a use case for this, we should think about how to allow an application for force this (without releasing the existing session). Since the result is reported asynchronously, the de-duplication of initData can be performed in either the UA or CDM. In either case, existing values should be removed when a session is closed. This does require some extra processing and time for each createSession() call, but it seems worth it to simplify applications. This does *not* solve all scenarios, such as where the initData differs between audio and video streams and the applicaiton only wants to make one license request, but it significantly reduces the number of sessions that are created, especially in adaptive streaming cases. It should also correctly handle key rotation (assuming different initData for different streams is handled correctly). I think this is a significant improvement over the current state, but I would be interested in other proposals, especially if they address the forced session creation and/or different initData issues mentioned above.
(In reply to David Dorwin from comment #1) > Thus, instead of creating a useless session object (bug 25267), > implementations can reject the promise with an appropriate DOMException if > the specified initData was not used to create any of the existing active > (i.e. not closed) sessions for this MediaKeys object. Actually, per [1] we should not reject the promise. Instead we should resolve it with undefined or null. This is similar to how loadSession() resolves with undefined when the session is not found. This is also easier for applications to reason about: void onResolved(value) { if (!value) { // I must already have a session for this initData. return; } ... } I'm not sure whether undefined or null is technically more appropriate. It doesn't really affect applications, but we need to pick one. undefined makes sense when something couldn't be found. Maybe null makes more sense in this case because we explicitly chose to return a null object. > We might need a unique DOMException value so > that applications can easily check for and ignore this non-error rejection > of the Promise. Thus, there is no need for such a DOMException name. [1] https://github.com/w3ctag/promises-guide#rejections-should-be-used-for-exceptional-situations
I implemented the proposal in https://dvcs.w3.org/hg/html-media/rev/b8934774026e. createSession() will resolve the promise with null if a session already exists for the provided initData.
Note: Since the initData used to create a session is removed from the "list of active session Initialization Data" when a session is closed, as long as the CDM/application closes the session when keys are no longer valid, there should be no problems with 1) increasing memory usage for the list 2) Seeking to points in the media resource that use different key(s) and thus initData value(s).
tl;dr: The current solution is broken and does not help many applications. Thus, I propose removing all deduplication of initData from the spec and implementations. Thinking about this more, I have two concerns about the solution (comment #3). 1) While the solution reduces the number of sessions created (particularly for a very simple needkey => createSession() app), it does not reduce the burden on other apps, especially those that do not want a separate session for each unique initData. For such apps, the comparison occurs *after* the application needs to deduplicate initData - the app needs to determine whether to create a session before calling createSession(), so it is still deduplicating all the initData from all needkey events. The app could see whether it gets a session when the promise is resolved, but that seems hacky. What such applications really need is to avoid receiving the needkey event. Since initData comparison an be implemented in the user agent, we could do this, but: * The HTMLMediaElement would need to interact with its MediaKeys object before firing the event, which seems odd. * There was previously a desire to allow applications to receive all such events. 2) The current solution has a race condition between checking the "list of active session Initialization Data" and adding a session created by another call being added to the list. The intent was to avoid adding a session until it was successfully created, but this causes non-deterministic behavior. Instead, a session needs to be added immediately after checking (and implementations need to make these two steps atomic) and removed if there is a faiulre. This could result in no session being created for a given initData if the first createSession() call failed. This seems acceptable and the application can also retry when the first promise is rejected. It might just be better to give applications full flexibility (Why does the UA really care if there are duplicate sessions?) and provide best practices for handling needkey events for various application models.
Per comment #5, I reverted the changeset in comment #3 in https://dvcs.w3.org/hg/html-media/rev/7672bc3b95ca. This issue is now open again for suggestions and discussion.
Because this bug suggests an optimization that is not critical to achieve correct functionality, it may be postponed to a future version if no technical proposal is forthcoming.
Reducing the priority per per the comment above.
We will keep this open until the f2f. If there are no proposals then, we will close it.
There were no proposals. Resolving for now. Proposals welcome!