Bugzilla – Bug 21855
Avoid network traffic and duplicate sessions for the same key(s)
Last modified: 2014-01-18 01:48:03 UTC
There have been several bugs and feature requests related to scenarios where the CDM already has the key(s) for given initData and it would be preferable not to create a new session or key exchange. This bug will track addressing these scenarios with one or more changes in behavior.
The following bugs contain useful background discussion but will be closed as duplicates of this bug.
* Bug 16553: Consider not firing a needkey event when a potentially encrypted stream is encountered if the key is already known
* Bug 19208: Keymessage event not needed when Key System already has Key
Resolution of this bug is tightly related to and dependent on the
MediaKeySession life cycle (bug 21854).
* Some applications may actually want to be notified when init data is encountered or want to create another session.
* The Initialization Data may not contain sufficient information for the CDM to know whether it has all the keys associated with the Initialization Data. (Exact match may be the best we can do.)
* The UA should not need to interact with the CDM, which may not be loaded, in order to determine whether to fire needkey.
*** Bug 16553 has been marked as a duplicate of this bug. ***
*** Bug 19208 has been marked as a duplicate of this bug. ***
We must address the following scenarios:
* A key request is in progress (i.e. createSesison() has been called but the key has not been provided).
- For example, multiple Initialization Data instances are encountered at about the same time (i.e. parsing a video and audio stream during initial loading).
* The key is already known in the CDM.
As noted in bug 16553#c8, step 5 of http://dvcs.w3.org/hg/html-media/raw-file/tip/encrypted-media/encrypted-media.html#algorithms-encrypted-stream uses the "cdm to determine whether the key is known" and skips firing the event if the key is known. That step needs to be updated as part of resolving this issue.
Per https://www.w3.org/Bugs/Public/show_bug.cgi?id=19788#c1, the "Potentially Encrypted Stream Encountered" algorithm is now the "First Time a Key Reference is Encountered" algorithm.
The change to "key reference" may be helpful here since we could define that for ISO BMFF (see https://www.w3.org/Bugs/Public/show_bug.cgi?id=17673#c12) to be an exact PSSH box(es) and trigger this algorithm (and thus needkey) the first time an exact PSSH box(es) is encountered in the media element.
Note that "First Time a Key Reference is Encountered" puts responsibility on the UA to track what has been seen so far. Hopefully this is not too much burden. As noted in the original description, we do not want the CDM involved in firing needkey, so the UA is the only entity that can track this.
As part of resolving this, we should be able to remove references to |cdm| and |key ID| from that algorithm, eliminating most of the (existing) complexity from it.
Our proposal sits on top of the proposal for Bug 21854. When initdata is encountered, it always results in a needkey event. When a session is created, it may move immediately from the CREATED state to the READY state if no other input is required.
If the CDM detects that there is already another session "A" in the PENDING state acquiring a key that matches the initdata for a new session "B" then the CDM MAY choose to keep session "B" in the CREATED state until the session "A" leaves the PENDING state and then fire keyerror or keyready at session "B".
I like that the UA is not involved in deciding whether Initialization Data is duplicate. I think that is an important requirement for any solution to this issue.
Some of the downsides I see are:
* Calling createSession() for every needkey event could result in a continually growing set of MediaKeySession objects (and related resource usage), which serve no purpose, as, for example, the player adaptively switches among streams.
* The CDM-specific behavior may/will likely lead to potentially inconsistent behavior across implementations and require apps to deal with the worst case implementation in apps.
Sharing underlying session/keys among MediaKeySession objects raises some interesting questions. Are all such objects treated as identical? If not, what is the expected behavior?
- Can update() & close() be called on any of them?
- Which MediaKeySession objects will receive keymessage events (i.e. for renewal)? What about keyerror events?
- When something like renewal happens and a session transitions (on a keymessage) from Ready to Pending, do all MediaKeySession objects transition (with the corresponding event)?
Similarly, as mentioned in https://www.w3.org/Bugs/Public/show_bug.cgi?id=17750#c5, the sharing of underlying sessions/keys complicates close(). We can address this by eliminating close() or defining it in a compatible way, but we need to resolve these issues together.
I don't think we should try to completely solve this issue in v1. I think it is reasonable to allow an optimization to allow a session to move from CREATED to READY to avoid an initial duplicate network request. It is not necessary for all CDMs to support this optimization. The only impact is that an application has to know it could get a keyready event without a keymessage event. At this point we don't support further optimizations. If a session needs to go back to PENDING it does so independently (meaning all "shared" sessions may also go back to PENDING).
This avoids the questions about which sessions should receive subsequent messages. The question about the ever growing set of MediaKeySession objects exists beyond this issue. I'm not sure if we need to do anything in v1 to handle this.
(In reply to Adrian Bateman [MSFT] from comment in bug 17750)
> ... there is no explicit sharing - just
> that you don't necessarily need to go through PENDING to get to READY.
So sharing (or any other method to bypass PENDING) is an implementation detail, but the CDM must do whatever is necessary to present the sessions as independent? That includes firing events at each session to transition states, handling close() (bug 17750) on each session without clearing keys in use by other sessions(?), etc.
(In reply to Adrian Bateman [MSFT] from comment #7)
> ... If a
> session needs to go back to PENDING it does so independently (meaning all
> "shared" sessions may also go back to PENDING).
> This avoids the questions about which sessions should receive subsequent
Does this mean the CDM must either a) fire the keymessage at each "shared" session and thus transition them to PENDING or b) fire the keymessage at one session and leave the others in CREATED/READY until they are READY or an error occurs?
(In reply to David Dorwin from comment #8)
What I meant was to propose that there is no such thing as a "shared" key, except perhaps during the acquisition as an optimization (skipping PENDING). I don't think there is anything to prevent implementations being smarter if they want but note that firing keymessage at multiple sessions _will_ result in multiple connections to the license service. I don't think the spec should do anything explicitly to describe how to manage this.
Discussed in the telcon 10/15. Proposed text:
"we should have non-normative text that the CDM should ensure all sessions appear distinct (in events/states) regardless of the underlying implementation, and maybe we should call out the CREATED-to-READY transition is possible since most of the spec uses/describes the flow that includes keymessage/PENDING."
I proposed something via email here: http://lists.w3.org/Archives/Public/public-html-media/2013Oct/0031.html
I removed CDM- and key ID-related text from the "needkey algorithm" in https://dvcs.w3.org/hg/html-media/rev/84be32b27d5d
(In reply to Adrian Bateman [MSFT] from comment #10)
> Discussed in the telcon 10/15. Proposed text:
> "we should have non-normative text that the CDM should ensure all sessions
> appear distinct (in events/states) regardless of the underlying
> implementation, and maybe we should call out the CREATED-to-READY transition
> is possible since most of the spec uses/describes the flow that includes
I added an informative note in the spec: