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

Proposal: improved protected content workflow #1367

Closed
sandersaares opened this issue Apr 28, 2016 · 13 comments
Closed

Proposal: improved protected content workflow #1367

sandersaares opened this issue Apr 28, 2016 · 13 comments
Labels
Code Refactor EME/DRM Feature Enhancement stale To be used by automatic issue staling and closing to indicate that this issue is about to be closed

Comments

@sandersaares
Copy link
Member

Some recent discussion in Slack and GitHub (#1346) hinted to me that the logic initializing playback of protected content in dash.js could perhaps use a review. I investigated the situation and I propose here a design for initializing playback of protected content in a way that overcomes some difficulties currently present, defines behavior for some currently undefined/unsupported/unexplored scenarios and overall leads us towards a more interoperable state that is better aligned with DASH-IF IOP.

The approach described here integrates elements not only from DASH-IF IOP but also several topics that are still evolving (and which may influence future versions of DASH-IF IOP to narrow the gap). The focus here is on defining for dash.js a very well defined mechanism for initiating playback of protected content in a highly interoperable way that is capable of functioning in different business scenarios and integrating with different DRMs.

To accomplish this, various constraints on the DASH presentations are placed and relevant dash.js behavior is defined. All statements below describe the proposed state, not the current state, even if they are written in present tense.

Basic concepts

This section defines the "goal state" that the proposed scheme aims to satisfy and the concepts to be implemented.

basics

Let's start by stating the obvious. Dash.js is capable of playing back encrypted content. To do this, it provides content keys to a suitable CDM that is connected to a MediaSource, to which dash.js provides media segments. Multiple CDMs may be made available to dash.js by the user agent, in which case it is up to dash.js to select which one to use.

content key flexibility

There may be one or more content keys required at the same time to play back protected content (different adaptation sets) and the set of content keys may change between (but not within) periods. The presence or absence of encryption may also change between (but not within) periods.

<ContentProtection schemeIdUri="urn:mpeg:dash:mp4protection:2011" value="cenc" cenc:default_KID="4fa993f3-e954-4bf3-9495-77add8d3bced" />

The presence of encryption in an adaptation is signaled by the presence of a ContentProtection element whose schemeIdUri and value attributes match the values in the sample above (IOP 7.7.2). The required content key is identified by the default_KID attribute.

Media segments are opaque blobs to dash.js and neither segments nor any data extracted from them by the user agent are processed by dash.js (at least in scope of protected content workflows - this proposal makes no comment on media sample playback workflows).

derived key

The encryption of media data within media segments is not necessarily performed using content keys - the only relevant constraint here is that a content key is associated with the media segments (via manifest reference) and providing this content key to the CDM must be sufficient to decrypt the samples in the media segment. On a lower level content keys may instead be combined with custom data embedded within the media segments, deriving hierarchical media keys which in turn are used to encrypt samples and thus enabling scalable re-authorization scenarios (see IOP 7.5). All of this is opaque to dash.js which only deals with the content keys that are provided to CDMs.

All CDMs require initialization data for each content key in order to become capable of decrypting content using that content key. This initialization data is passed to the CDM via the generateRequest() method defined by EME.

<ContentProtection value="MSPR 2.0" schemeIdUri="urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95">
    <cenc:pssh>AAAB5HBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAcTEAQAAAQABALoBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgA4ADUATwBwAFQAMQBUAHAAOAAwAHUAVQBsAFgAZQB0ADIATgBPADgANwBRAD0APQA8AC8ASwBJAEQAPgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA==</cenc:pssh>
</ContentProtection>
<ContentProtection value="Widevine" schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed">
    <cenc:pssh>AAAANHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABQIARIQT6mT8+lUS/OUlXet2NO87Q==</cenc:pssh>
</ContentProtection>

DASH presentations may provide default CDM initialization data in ContentProtection/cenc:pssh elements, as illustrated above (IOP 7.7.2). Alternatively, client code may provide the initialization data to dash.js. The initialization data in the manifest is ignored if it is provided by client code. Initialization data is NOT loaded from DASH segments in any circumstances.

EME defines the encrypted event that notifies dash.js when DRM system specific data is detected in the media segments. This data is treated as an opaque blob and passed directly to the active CDM (via update()) without further processing by dash.js. Use of this data for CDM initialization is forbidden, although CDMs may use it for other purposes (notably, this is the mechanism that passes media key derivation input data to the CDM, in situations where derived keys are used).

Content keys are provided to CDMs within licenses that are opaque to dash.js. Dash.js mediates the flow of license requests from the CDM to a license server and back, potentially enhancing the flow with supplementary information about application/business layer logic (e.g. the identity of the logged in user), in the form of HTTP request headers or similar metadata.

CDMs may supply dash.js with a default URL of the license server (either deliberately or by including it in the license request data itself). Alternatively, client code may provide this URL, or override the one provided by the CDM.

Client code is the ultimate authority on the behavior of dash.js and may override any defaults provided by the DASH manifest or the CDM.

Client code may express an order of preference of CDMs.

Implementation

This section defines the mechanisms to implement in order to reach the goal state and to make the described concepts a reality. Not all aspects of the implementation are covered here, as many are likely to be trivial.

Detecting encrypted content

Dash.js shall use the presence of a <ContentProtection schemeIdUri="urn:mpeg:dash:mp4protection:2011" value="cenc" ... /> element in the manifest to determine whether an adaptation set is encrypted or not.

The EME encrypted event shall not be used for the purpose of detecting encryption and any data supplied by encrypted is simply passed to the active CDM's update() method without inspection.

Selecting the CDM

When encrypted content is detected, dash.js shall use the algorithm described here to select the CDM to be used decrypt it. A single CDM shall be used to decrypt all data from the same DASH presentation - this algorithm is only executed once per DASH presentation.

The CDM selection algorithm shall only be run against a single content key even in the presence of multiple content keys signaled by the manifest. It is assumed that the result of the algorithm does not depend on which content key is selected, so dash.js may pick any one of them.

The algorithm description follows.

All CDMs provided by the user agent shall initially be considered valid candidates.

Next, dash.js shall exclude CDMs for which neither the DASH manifest nor client code (via protData) has provided initialization data.

{
    "name": "Video that cannot be played back using Widevine",
    "url": "http://media.axprod.net/TestVectors/v6-MultiDRM/Manifest_1080p.mpd",
    "protData": {
        "com.widevine.alpha": {
            "enabled": false
        }
    }
}

Next, any CDMs explicitly disabled by client code shall be excluded. This is signalled via the protData structure by setting the "enabled" property to false, as shown above.

{
    "name": "Video for which we prefer Widevine to be used",
    "url": "http://media.axprod.net/TestVectors/v6-MultiDRM/Manifest_1080p.mpd",
    "protData": {
        "com.widevine.alpha": {
            "priority": 100,
            "serverURL": "http://drm-widevine-licensing.axtest.net/AcquireLicense"
        },
        "com.microsoft.playready": {
            "serverURL": "http://drm-playready-licensing.axtest.net/AcquireLicense"
        }
    }
}

Then the remaining CDMs are sorted according to an order of preference defined by client code. This order is signaled via the protData structure by assining a numeric identifier to the priority property, as shown above. The default value is 0 and higher values indicate greater preference.

Finally, the CDM with the highest priority value shall be selected from among the remaining candidates.

CDM initialization

Upon encountering a content key for the first time, dash.js shall initialize the selected CDM to decrypt that content key, by creating an EME key session and supplying the initialization data to the generateRequest() method. This may cause a license request to be triggered by the CDM if it requires the content key to be retrieved from an external source.

{
    "name": "Example video",
    "url": "http://media.axprod.net/TestVectors/v6-MultiDRM/Manifest_1080p.mpd",
    "protData": {
        "com.microsoft.playready": {
            "serverURL": "http://drm-playready-licensing.axtest.net/AcquireLicense",
            "initData": {
                "5eff1fb9-6309-46fd-b9d5-23329badd982": "AAAB5HBzc2gAAAAAmgTweZhAQoarkuZb4Ih",
                "bf3f4a25-a5a8-4adc-9871-00d742972b3e": "DAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQAS"
            }
        }
    }
}

The initialization data shall be obtained from the DASH manifest unless overridden by client code via protData, in a CDM-specific map of key ID to initialization data. See above for an example.

Initialization data generation by dash.js

There are CDMs for which initialization data is trivial to generate from scratch (e.g. clear key). Dash.js shall not generate initialization data unless explicitly configured by client code to do so (via some appropriate entry in protData). If dash.js is configured to generate initialization data, it shall be considered as having initialization data by the CDM selection algorithm.

This matches current behavior and is perhaps stating the obvious but deserves emphasis anyway because it is important to ensure that the CDM selection algorithm is predictable and to differentiate between the following scenarios:

  • Initialization data intentionally not provided - do not use this CDM.
  • Initialization data intentionally not provided - generate it on demand.

This is perhaps most relevant with the clear key scenario, though not exclusively so (in many real-world cases, initialization data serves to simply pass the default_KID to the CDM, so initialization data generation might be a likely future enhancement to keep in mind).

EME key session handling

There is a 1:1 relationship between each unique content key (differentiated by key ID supplied in default_KID) and an EME key session. Key sessions are created when the first adaptation set using a particular content key is detected and destroyed when no active adaptation sets use that key anymore.

Implications on content and capabilities

From the above, we can draw some potentially relevant conclusions and see how content is affected and what capabilities are created:

  • CDM initialization and selection can be entirely driven by client code - dash.js can work with any CENC compatible content and use any CENC compatible CDM to decrypt it without requiring modification of the content. (Enabling this was the main motivation for the proposal)
  • While initialization data is permitted in media segments, it will not be used to initialize CDMs. Initialization data must be present either in the manifest or provided by client code, in all scenarios.
  • Periodic re-authorization (IOP 7.5) is enabled by being flexible in adaptation set and content key associations and by facilitating the use of hierarchical media keys (IOP 7.5.3.4). The latter is intentionally designed to be completely opaque to dash.js and takes place entirely within the CDM, reducing implementation complexity.

Sample scenarios

This section provides some brief examples of dash.js usage in various common scenarios and describes how this model of protected content processing applies.

Sample 1: Single-DRM single-key presentation using PlayReady

This is a very basic scenario where a single content key protects all the data in a video and that we wish to play back using PlayReady. First, let us observe the case where all the data is provided using the default values specified in the DASH manifest.

In the manifest, we require two ContenProtection elements in this scenario - one to signal the default_KID and another to provide the initialization data for the PlayReady CDM.

<ContentProtection schemeIdUri="urn:mpeg:dash:mp4protection:2011" value="cenc" cenc:default_KID="4fa993f3-e954-4bf3-9495-77add8d3bced" />
<ContentProtection value="MSPR 2.0" schemeIdUri="urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95">
    <cenc:pssh>AAAB5HBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAcTEAQAAAQABALoBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgA4ADUATwBwAFQAMQBUAHAAOAAwAHUAVQBsAFgAZQB0ADIATgBPADgANwBRAD0APQA8AC8ASwBJAEQAPgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA==</cenc:pssh>
</ContentProtection>

In this scenario, client code provides only the presentation URL to dash.js.

{
    "name": "Example video",
    "url": "http://examplecom/manifest.mpd"
},

When playback is started, the following notable events occur:

  1. Dash.js notes the ContentProtection element and concludes that the presentation includes encrypted content.
  2. Dash.js selects PlayReady (if available) as the CDM because there was no initialization data for any other CDM.
  3. Dash.js initializes the PlayReady CDM using the initialization data loaded from the manifest.

Naturally, the CDM selection step (and playback) will fail if the user agent does not actually provide the PlayReady CDM.

Sample 2: Single-DRM single-key presentation using clear key and configuring CDM via client code

In this scenario, the DASH presentation is encrypted but contains no information to configure a CDM. Instead, client code provides all such data.

In the manifest, we require only a single ContenProtection element in this scenario, in order to signal the default_KID and mark the content as encrypted.

<ContentProtection schemeIdUri="urn:mpeg:dash:mp4protection:2011" value="cenc" cenc:default_KID="4fa993f3-e954-4bf3-9495-77add8d3bced" />

In this scenario, client code supplies the CDM initialization data:

{
    "name": "Example video",
    "url": "http://examplecom/manifest.mpd",
    "protData": {
        "org.w3.clearkey": {
            "initData": {
                "4fa993f3-e954-4bf3-9495-77add8d3bced": "eyJraWRzIjpbIlQ2bVQ4LWxVU19PVWxYZXQyTk84N1E9PSJdfQ"
            }
        }
    }
}

When playback is started, the following notable events occur:

  1. Dash.js notes the ContentProtection element and concludes that the presentation includes encrypted content.
  2. Dash.js selects clear key as the CDM because there was no initialization data for any other CDM.
  3. Dash.js initializes the clear key CDM using the initialization data provided by client code.

Note: the method of providing the content key itself to the clear key CDM is intentionally not described here and considered out of scope of this proposal.

Sample 3: Multi-drm presentation with CDM preference

Here we have a DASH presentation that supports both PlayReady and Widevine and provides the initialization data in the manifest. Client code simply expresses a preference for which CDM to use if both are available.

Three ContentProtection elements are present in the manifest, one for default_KID and two for providing initialization data for the different CDMs.

<ContentProtection schemeIdUri="urn:mpeg:dash:mp4protection:2011" value="cenc" cenc:default_KID="4fa993f3-e954-4bf3-9495-77add8d3bced" />
<ContentProtection value="MSPR 2.0" schemeIdUri="urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95">
    <cenc:pssh>AAAB5HBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAcTEAQAAAQABALoBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgA4ADUATwBwAFQAMQBUAHAAOAAwAHUAVQBsAFgAZQB0ADIATgBPADgANwBRAD0APQA8AC8ASwBJAEQAPgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA==</cenc:pssh>
</ContentProtection>
<ContentProtection value="Widevine" schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed">
    <cenc:pssh>AAAANHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABQIARIQT6mT8+lUS/OUlXet2NO87Q==</cenc:pssh>
</ContentProtection>

Client code simply expresses a preference for one above the other:

{
    "name": "Axinom multi-DRM (1080p)",
    "url": "http://media.axprod.net/TestVectors/v6-MultiDRM/Manifest_1080p.mpd",
    "protData": {
        "com.widevine.alpha": {
            "priority": 10
        },
        "com.microsoft.playready": {
            "priority": 5
        }
    }
}

When playback is started, the following notable events occur:

  1. Dash.js notes the ContentProtection elements and concludes that the presentation includes encrypted content.
  2. Dash.js selects either PlayReady or Widevine as the CDM, preferring Widevine if both are available.
  3. Dash.js initializes the CDM using the initialization data provided in the DASH manifest.

Sample 4: Overriding the manifest

Here we have a manifest that defines CDM initialization data that client code wants to ignore.

In the manifest, we have ContentProtection elements for the default_KID and for two CDMs.

<ContentProtection schemeIdUri="urn:mpeg:dash:mp4protection:2011" value="cenc" cenc:default_KID="4fa993f3-e954-4bf3-9495-77add8d3bced" />
<ContentProtection value="MSPR 2.0" schemeIdUri="urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95">
    <cenc:pssh>AAAB5HBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAcTEAQAAAQABALoBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgA4ADUATwBwAFQAMQBUAHAAOAAwAHUAVQBsAFgAZQB0ADIATgBPADgANwBRAD0APQA8AC8ASwBJAEQAPgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA==</cenc:pssh>
</ContentProtection>
<ContentProtection value="Widevine" schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed">
    <cenc:pssh>AAAANHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABQIARIQT6mT8+lUS/OUlXet2NO87Q==</cenc:pssh>
</ContentProtection>

Client code, however, wants to ensure that Widevine is never used and to provide custom initialization data for PlayReady.

{
    "name": "Axinom multi-DRM (1080p)",
    "url": "http://media.axprod.net/TestVectors/v6-MultiDRM/Manifest_1080p.mpd",
    "protData": {
        "com.widevine.alpha": {
            "enabled": false
        },
        "com.microsoft.playready": {
            "initData": {
                "4fa993f3-e954-4bf3-9495-77add8d3bced": "AAAB5HBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAcTEAQAAAQABALoBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG"
            }
        }
    }
}

When playback is started, the following notable events occur:

  1. Dash.js notes the ContentProtection elements and concludes that the presentation includes encrypted content.
  2. Dash.js selects PlayReady as the CDM and does not use Widevine even if available.
  3. Dash.js initializes the CDM using the initialization data provided by the client code, ignoring the initialization data in the manifest.

Compatibility notes

All DASH presentations that this approach can play are compatible with DASH-IF IOP but not all presentations compatible with DASH-IF IOP can be played by this approach. This is intentional. The latter is not really a feasible target in any case, as there remains quite a lot of flexibility even in DASH-IF IOP.

Future work

It might be desirable for a DASH presentation to supply default license server URLs (per-CDM) in a form easily usable by dash.js, via the presentation manifest. At present, this data is present in the initData of some DRM systems but this requires parsing and is not very interoperable. I seem to recall that some standardization work on this topic has been discussed but I cannot find any specific references.

Footnote

My knowledge of dash.js internals is minimal and I mainly approach it from a high-level architectural perspective, assuming nothing about the existing implementation. Please excuse my use of any terminology that differs from existing dash.js practices.

Many thanks to @kilroyh for helping me understand the background and logic behind many of these topics!

@dsparacio
Copy link
Contributor

@sandersaares Wow, fantastic job on capturing this info! Thank you so much for taking this on.

@wilaw
Copy link
Member

wilaw commented Apr 28, 2016

@sandersaares - firstly - great article that is clearly presented. I'd definitely encourage a discussion of this approach and the changes it would require to the current code base with other developers who have contributed to, or have an interest in, the content protection performance of dash.js. The bulk of the original development was done by @greg80303 who has moved on to another position within CableLabs but still monitors these lists. Also @bwidtmann from Maxdome and @colde from XStream have worked on protection in the past and Michael Zinn on Slack channel is interested now.

Are you able to make the face-to-face meeting in Munich in May? That would be the best time to discuss this. If not, it can be done via email and issue threads, or perhaps we can arrange some special calls as talking is easier than typing.

I have a question upfront:

  1. What happens when multi-DRM is declared in the manifest, but no preference is expressed by the client code. Should dash.js just choose the first listed in the manifest?
  2. Should dash.js interrogate the CDMs and find out which are supported by the environment and use that as a filter to restrict the choice of available CDMs? For example, if a manifest declares CENC with Widevine and Playready, but you are in Chrome, which component figures out that Playready is not available? Is this a complex procedure? Should dash.js apply it as a filter, or do we expect the client code to do it?

Cheers
Will

@sandersaares
Copy link
Member Author

I fear I will not be present at the F2F meeting and will have to try to take part in the discussion by electronic channels instead. Will there be a call-in possibility to take part in F2F discussions in a limited capacity?

What happens when multi-DRM is declared in the manifest, but no preference is expressed by the client code. Should dash.js just choose the first listed in the manifest?

I cannot immediately think of any better behavior to suggest nor can I think of any significant issues this behavior might cause. Sounds like it would be sufficient, yes.

Should dash.js interrogate the CDMs and find out which are supported by the environment and use that as a filter to restrict the choice of available CDMs? For example, if a manifest declares CENC with Widevine and Playready, but you are in Chrome, which component figures out that Playready is not available? Is this a complex procedure? Should dash.js apply it as a filter, or do we expect the client code to do it?

I would expect dash.js to determine the set of available CDMs, yes. In fact, based on the log entries I see in the console when dash.js is starting up, I believe it already does so and reports what it finds in the log. The requestMediaKeySystemAccess() function defined by EME is presumably used for this purpose.

However, perhaps a developer with more familiarity can correct me on this, as I am not overly familiar with the actual codebase.

@colde
Copy link
Contributor

colde commented Apr 29, 2016

@sandersaares - Nice writeup, you cover a lot of area well, and it is clear that there is a lot of though behind your suggestion. It is rare that i see things presented this well for projects.

That being said, i think what you are proposing is slightly too limiting of the DRM support in dash.js. Right now it handles quite a few cases of different types of content with different packages and does so pretty well. What you are suggesting would certainly result in a lot of content no longer being supported for encrypted playback. I will try and go through the most problematic ones from my point of view here. I am not saying it is not the right way to go, it might very well be, but it will remove some of dash.js's status as the swiss army knife of MPEG-DASH playback.

  1. Requiring CENC headers to be set. I understand that it will be very easy to spot encrypted content from the CENC header alone, but there is very little use for the CENC header in practice beyond signalling that you are doing CENC compatible encryption. I think realistically the presence of any ContentProtection header should be enough to signal that the content is encrypted. I doubt we will need to handle the encrypted events from the EME stack though, as we should know well beforehand.
  2. No parsing of media segments. I don't think we really need to parse the pssh boxes of the individual segments in most cases, but i do think there are cases where we need to do it. I.e. for key rotation scenarios, where we cannot rely only on the data in the manifest.

In general, it seems you have been looking a lot at PlayReady as the primary DRM system. I think you should probably validate your assumptions with at least Widevine as well, as some things (e.g. key rotation) is implemented wildly different between those two systems.

I do also sort of disagree with the idea that being able to play all DASH-IF IOP compatible protected content is unfeasible. In fact, i think that is exactly what our target should be.

@sandersaares
Copy link
Member Author

Thanks for the criticism, @colde! Can you outline in more detail the potential difficulties you see with regard to different DRM systems? For example, the case of Widevine key rotation that you mentioned - what is the issue you foresee there?

@bwidtmann
Copy link
Contributor

Some thoughts from my developer perspective:

  1. We already discussed the prohibiting of parsing media segments for retrieving pssh with @kilroyh on last DASH-IF F2F in December referencing this W3C EME issue: EME should support continuous key rotation per MPEG Common Encryption (ISO/IEC 23001-7) w3c/encrypted-media#132
    As a workaround we added a logic in ProtectionController.js L143 which is very dirty and I like to get rid of. But this is a rather big effort implementing in existing dash.js code base.
  2. Regarding selecting of CDM:
    Currently dash.js goes through all CDMs stated in pssh and tries to access them. It selects the first CDM that has been accessed successfully. The order of accessing is defined hard in ProtectionKeyController.js L67 (Playready, Widevine, Clearkey).
  3. Because of the complexity of DRM I am thinking about extracting the complete DRM logic into an own npm package that is consumed by dash.js. what do you think? this would decrease complexity of overall dash.js project by using the separation of concerns pattern.

@pjdicke
Copy link

pjdicke commented Mar 17, 2017

@wilaw,
Did you ever get anymore details around the scenario you described here? I'm in Chrome but getting intiData for Playready which doesn't seem correct, plus the fact that I'm not getting playback.

Regarding selecting of CDM:
Currently dash.js goes through all CDMs stated in pssh and tries to access them. It selects the first CDM that has been accessed successfully. The order of accessing is defined hard in ProtectionKeyController.js L67 (Playready, Widevine, Clearkey).

@wilaw
Copy link
Member

wilaw commented Mar 18, 2017

@pjdicke - that scenario was described by @bwidtmann and not myself. He is closer to the DRM issue than I am and may have an answer for you.

@bwidtmann
Copy link
Contributor

@pjdicke what do you mean with "getting initData for Playready"? In the concept of MPEG Common Encryption it is totally valid because at content creation time you do not know which DRM is implemented by the client (browser). It is up to the client (dash.js) to determine the correct DRM at run time. This is done by try-and-error.

@pjdicke
Copy link

pjdicke commented Mar 18, 2017

@bwidtmann, I'm trying to isolate Widevine for testing but it looks like it's choosing Playready while I'm testing in Chrome. So I guess I don't have a way to do that??

@bwidtmann
Copy link
Contributor

@pjdicke can you please open a separate issue following our guidelines (public available link to your manifest, browser log, ...). Then I can help you better with your concrete problem.

@stale
Copy link

stale bot commented Feb 26, 2021

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale To be used by automatic issue staling and closing to indicate that this issue is about to be closed label Feb 26, 2021
@stale
Copy link

stale bot commented Mar 5, 2021

This issue has been automatically closed because no further activity occurred. If you think this issue is still relevant please reopen it. Thank you for your contributions.

@stale stale bot closed this as completed Mar 5, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Code Refactor EME/DRM Feature Enhancement stale To be used by automatic issue staling and closing to indicate that this issue is about to be closed
Projects
None yet
Development

No branches or pull requests

6 participants