[EME] Object-oriented API design proposal #2b (using a MediaKeys constructor)

While the second proposal [2] seems to make sense from an API point of
view, it appears to be problematic for implementations. In short, the
problem is that the session object is not strongly associated with a media
element, making key lookup for decryption more difficult. Therefore, I
propose modifying the proposal to include an object that all sessions are
associated with.

*Problem*
Since there is no concept of session during frame decryption and the
association of available keys with a media element is weak, the CDM may
need to search all sessions associated with the media element for the key
ID when decrypting. Depending on the CDM implementation, this may be
difficult or otherwise problematic. Even sharing sessions within a page
might be difficult to implement. There are certainly ways to work around
this, but it would be better if the API enabled a simpler implementation.

*Solution*
Since implementations will need a representation of all sessions for a
media element internally, we might as well expose that externally and
simplify implementations. I think the best way to solve the problem is to
ensure that:

   1. All sessions are strongly/permanently associated with a single
   "collection".
   2. Media elements can use at most one "collection" at a time.


This allows the creation of a pool of keys that is strictly the set that
can be used for a given media element.

[If we choose to allow it,] Entire "collections" can still be shared among
media elements, but subsets (i.e. individual sessions) cannot be shared
between "collections" (or elements). (I can't come up with a good use case
where the former wouldn't be sufficient.)

One possible design is that the "collection" is the media element. This is
essentially the first proposal [1]. Another possible design is to have a
collections objects that can create sessions and be assigned to a media
element to use for decryption. Below is a proposal using the second design.

*Proposal*
Changes from [2] are in red.

partial interface HTMLMediaElement {
  // Adds optional 'keySystem' parameter.
  DOMString canPlayType
<https://mail.google.com/mail/ca/u/0/?ui=2&view=btop&ver=d2splbkr2oxk&search=sent&th=1383a191e954b21f&cvid=3#1383a191e954b21f_1383a1251bcff681_1383a07710268a0d_dom-canplaytype>(in
DOMString type, in DOMstring? keySystem
<https://mail.google.com/mail/ca/u/0/?ui=2&view=btop&ver=d2splbkr2oxk&search=sent&th=1383a191e954b21f&cvid=3#1383a191e954b21f_1383a1251bcff681_1383a07710268a0d_key-system>);

  // Encrypted media             attribute MediaKeys keys;};
[Constructor (in DOMString *keySystem*)]
interface *MediaKeys* {  *MediaKeySession* createSession(in DOMString?
type, in Uint8Array? initData);
}

interface MediaKeySession : EventTarget
<https://mail.google.com/mail/ca/u/0/?ui=2&view=btop&ver=d2splbkr2oxk&search=sent&th=1383a191e954b21f&cvid=3#1383a191e954b21f_1383a1251bcff681_1383a07710268a0d_dom-eventtarget>
{
  // error state
  readonly attribute MediaKeyError
<https://mail.google.com/mail/ca/u/0/?ui=2&view=btop&ver=d2splbkr2oxk&search=sent&th=1383a191e954b21f&cvid=3#1383a191e954b21f_1383a1251bcff681_1383a07710268a0d_dom-mediakeyerror>?
error <https://mail.google.com/mail/ca/u/0/?ui=2&view=btop&ver=d2splbkr2oxk&search=sent&th=1383a191e954b21f&cvid=3#1383a191e954b21f_1383a1251bcff681_1383a07710268a0d_dom-error>;

  // session properties
  readonly attribute DOMString keySystem
<https://mail.google.com/mail/ca/u/0/?ui=2&view=btop&ver=d2splbkr2oxk&search=sent&th=1383a191e954b21f&cvid=3#1383a191e954b21f_1383a1251bcff681_1383a07710268a0d_dom-keysystem>;
  readonly attribute DOMString sessionId
<https://mail.google.com/mail/ca/u/0/?ui=2&view=btop&ver=d2splbkr2oxk&search=sent&th=1383a191e954b21f&cvid=3#1383a191e954b21f_1383a1251bcff681_1383a07710268a0d_dom-sessionid>;

  // session operations
  void addKey <https://mail.google.com/mail/ca/u/0/?ui=2&view=btop&ver=d2splbkr2oxk&search=sent&th=1383a191e954b21f&cvid=3#1383a191e954b21f_1383a1251bcff681_1383a07710268a0d_dom-addkey>(in
Uint8Array key);
  void close <https://mail.google.com/mail/ca/u/0/?ui=2&view=btop&ver=d2splbkr2oxk&search=sent&th=1383a191e954b21f&cvid=3#1383a191e954b21f_1383a1251bcff681_1383a07710268a0d_dom-close>();
};

partial interface HTMLSourceElement {
             attribute DOMString keySystem
<https://mail.google.com/mail/ca/u/0/?ui=2&view=btop&ver=d2splbkr2oxk&search=sent&th=1383a191e954b21f&cvid=3#1383a191e954b21f_1383a1251bcff681_1383a07710268a0d_dom-sourcekeysystem>;
};


*Example Use*
Changes from [2] are in red.

  function handleNeedKey(event) {
    var mediaKeys = MediaKeys(keySystem);
    if (!mediaKeys)
      return;

    var session = mediaKeys.createSession(mimeType, initData);
    if (!session)
      return;

    session.onkeymessage = handleKeyMessage;
    session.onkeyerror = handleKeyError;

    var video = event.target;
    video.keys = mediaKeys;
  }

*Comparison to Other Proposals*
Below are some properties of this proposal and the impact of each.

   1. Encapsulation - just moves methods.
   2. Session objects allow removal of sessionId parameters, clear
   association of messages, keys, etc., and potentially destruction of a
   subset of keys.
   3. Explicitly allocated objects (collection or session) - allows sharing
   and actions before the media element is loaded or after reload, etc.
   4. 1:1 of collection to element simplifies implementation and ensures
   one key system per element.

The other proposals have various subsets of these properties:

   - v0.1 has #4.
   - The first proposal [1] has #1, #2, and #4.
   - The second proposal [2] has #1, #2, and #3.


*Advantages of the Constructor Approach*
Below is a restatement of the advantages - originally described in [3] - of
separating key session creation from the media element over the first
proposal [1].

   1. Makes more sense if we eventually decide to support sharing sessions
   between media elements.
      1. This is still the case, but we share collections of sessions.
      2. If sessions are not directly associated with a media element (as
      in [1]), we need an intermediary object.
   2. Enables initiating key exchange before the media element starts
   loading.
   3. Could be used for Key Release without needing to create a "dummy"
   media element.
      1. A single object can be created that contains all sessions for
      release keys (for a given key system) rather than creating
session objects
      until there are no more key releases as in [2].
   4. This proposal is even closer to the Media Source object-based design
   than the second proposal [2]. The object-oriented Media Source Extensions
   design involves a MediaSource object that is assigned to a media element
   (via .src) and SourceBuffer objects that are created by the MediaSource
   object. The SourceBuffer objects are where data is managed, similar to how
   a key session is managed in a session object.
   5. N/A.


*Open Questions*
The following are new questions in addition to those in [2].

   - 9. Is there a real use case for multiple collections being actively
   used on a media element at the same time?
      - This would require adding add/remove methods to HTMLMediaElement
      instead of a simple property.
   - 10. Is there a real use case for multiple key systems being actively
   used on a media element at the same time?
      - I think this would add unnecessary complexity to implementations.
   - 11. Should we allow individual sessions (a subset of keys for an
   element) to be closed/released?
      - If so, the implementations of session objects need a reference back
      to the collection/media element so they can be updated when the session
      object is closed. More synchronization may also be required. This is
      probably true for the first proposal [1] as well.
   - 12. Should we expose a list of sessions from the collection (or media
   element in [1] and [2])?
      - None of the proposals exposes a list of sessions (like
      SourceBuffers are exposed from MediaSource). Applications must store
      references if they want to access them in the future. This seems
fine since
      operations on the session object will generally be in response
to events on
      it. This might be required if we want to use the collection object to
      obtain saved key releases. (See advantage #3 above.)



[1] http://lists.w3.org/Archives/Public/public-html-media/2012Jun/0136.html
 [2] http://lists.w3.org/Archives/Public/public-html-media/2012Jun/0143.html
[3] http://lists.w3.org/Archives/Public/public-html-media/2012Jun/0134.html

Received on Monday, 2 July 2012 23:15:39 UTC