Skip to content

Digital Rights Management (DRM) and license acquisition

Daniel Silhavy edited this page Jan 31, 2022 · 12 revisions

dash.js offers support for playback of DRM protected content. In this context, multiple adjustments can be made:

Different versions of the EME

The EME is the API that enables playback of protected content in the browser. It provides the necessary function calls to discover and interact with the underlying DRM system. Like any other API, EME changed over time and the current version is a lot different compared to the one in 2013. While desktop and mobile browsers are frequently updated, some embedded devices and set-top boxes are still running on outdated or even customized versions of the EME. For that reason dash.js detects the EME version on the client and triggers the right API functions [1].

By default, dash.js ships with support for three different versions of EME:

  • ProtectionModel_01b.js: initial implementation of the EME, implemented by Google Chrome prior to version 36. This EME version is not-promised based and uses outdated or prefixed events like “needkey” or “webkitneedkey”.
  • ProtectionModel_3Feb2014.js: implementation of EME APIs as of the 3 Feb 2014 state of the specification. Implemented by Internet Explorer 11 (Windows 8.1).
  • ProtectionModel_21Jan2015.js: most recent EME implementation. Latest changes in the EME specification are added to this model and It supports the promised-based EME function calls.

The detection of the appropriate EME version is done automatically in Protection.js:

if ((!videoElement || videoElement.onencrypted !== undefined) &&
  (!videoElement || videoElement.mediaKeys !== undefined)) {
   logger.info('EME detected on this user agent! (ProtectionModel_21Jan2015)');
   return ProtectionModel_21Jan2015(context).create();
} else if (getAPI(videoElement, APIS_ProtectionModel_3Feb2014)) {
   logger.info('EME detected on this user agent! (ProtectionModel_3Feb2014)');
   return ProtectionModel_3Feb2014(context).create();
} else if (getAPI(videoElement, APIS_ProtectionModel_01b)) {
   logger.info('EME detected on this user agent! (ProtectionModel_01b)');
   return ProtectionModel_01b(context).create();
} else {
   logger.warn('No supported version of EME detected on this user agent! - Attempts to play encrypted content will fail!');
   return null;
}

License server settings

In order to specify the license server for a specific key system dash.js defines the following API:

const protData = {
   "com.widevine.alpha": {
       "serverURL": "https://drm-widevine-licensing.axtest.net/AcquireLicense"
     },
   "com.microsoft.playready": {
       "serverURL": "https://drm-playready-licensing.axtest.net/AcquireLicense"
     }
};

player.setProtectionData(protData);

Key system priority

In some cases the underlying platform supports multiple DRM systems, for instance Widevine and Playready. In order to prioritize a specific system in the players selection process the priority attribute can be used:

{
    "com.widevine.alpha": {
        "serverURL": "someurl",
        "priority": 1
    },
    "com.microsoft.playready": {
        "serverURL": "someurl",
        "priority": 2
    }
}

In this case, dash.js checks for the support of Widevine before Playready.

DRM specific headers

License servers might require custom headers in order to provide a valid license. dash.js allows the addition of custom headers:

const protData = {
   "com.microsoft.playready": {
        "serverURL": "https://drm-playready-licensing.axtest.net/AcquireLicense",
        "httpRequestHeaders": {
             "custom-header": "data"
        }
    }
};
player.setProtectionData(protData)

Key System String - Priority

In some cases, multiple key system strings map to the same uuid/schemeIdUri of a key system. As an example, multiple platforms support the call to requestMediaKeySystemAccess for the Playready DRM system using the system strings com.microsoft.playready and com.microsoft.playready.recommendation. A detailed explanation is given here and here.

dash.js allows the application to define a system string priority for each key system as part of the protection data:

var protData = {
  'com.widevine.alpha': {
    'serverURL': 'https://drm-widevine-licensing.axtest.net/AcquireLicense',
    'systemStringPriority': [
      'com.widevine.something',
      'com.widevine.alpha'
    ]
  },
  'com.microsoft.playready': {
    'serverURL': 'https://drm-playready-licensing.axtest.net/AcquireLicense',
    'systemStringPriority': [
      'com.microsoft.playready.something',
      'com.microsoft.playready.recommendation',
      'com.microsoft.playready.hardware',
      'com.microsoft.playready'
    ]
  }
};

An example can be found in the sample section.

Robustness levels (Hard- & Software DRM)

Some DRM systems like Widevine require specific robustness levels to enable L1-L3 DRM playback. The robustness level can be set as part of the protection data in the following way:

"protData": {
    "com.widevine.alpha": {
          "serverURL": "https://drm-widevine-licensing.axtest.net/AcquireLicense",
           "audioRobustness": "SW_SECURE_CRYPTO",
           "videoRobustness": "HW_SECURE_ALL"
  }
}

License server url via MPD

DRM systems generally use the concept of license requests as the mechanism for obtaining content keys and associated usage constraints. For DRM systems that use this concept, one or more dashif:Laurl elements may be present under the ContentProtection descriptor, with the value of the element being the URL to send license requests to. An example looks the following:

<ContentProtection
	schemeIdUri="urn:uuid:d0ee2730-09b5-459f-8452-200e52b37567"
	value="FirstDRM 2.0">
	<cenc:pssh>
		YmFzZTY0IGVuY29kZWQgY29udGVudHMgb2YgkXBzc2iSIGJveCB3aXRoIHRoaXMgU3lzdGVtSUQ=
	</cenc:pssh>
	<dashif:Authzurl>https://example.com/tenants/5341/authorize</dashif:Authzurl>
	<dashif:Laurl>https://example.com/AcquireLicense</dashif:Laurl>
</ContentProtection>

Note: dash.js prioritizes the license server urls in the following order:

  1. URL provided via the the API
  2. URL provided via the MPD
  3. URL provided via pssh

Ignoring init data from the PSSH

By default, dash.js listens to needkey and encrypted events thrown by the EME. In case the init data has changed a new key session is created and a license request is triggered. In order to ignore init data coming from init and media segments the settings object needs to be adjusted:

player.updateSettings(
  {
    streaming: {
        protection: {
          ignoreEmeEncryptedEvent: true
        }
    }
  }
)

Modifying the license payload

In addition, dash.js allows the modification of the license request payload and the license response body.

License request modification

In order to modify the license request, filter functions can be added and removed dynamically.

Note: The filter functions are reset when calling player.destroy().

const player = dashjs.MediaPlayer().create();
const callback = (payload) => {
   return new Promise((resolve,reject) => {
    resolve(payload)
  })
}
player.initialize(video, url, false);
player.registerLicenseRequestFilter(callback)
player.unregisterLicenseRequestFilter(callback)

The registered functions are called within the ProtectionController class before the license request is send to the license server

let licenseRequest = new LicenseRequest(url, reqMethod, responseType, reqHeaders, withCredentials, messageType, sessionId, reqPayload);
applyFilters(licenseRequestFilters, licenseRequest).then(() => {
   doLicenseRequest(licenseRequest, LICENSE_SERVER_REQUEST_RETRIES, timeout, onLoad, onAbort, onError);
});

License response modification

In order to modify the license response, filter functions can be added and removed dynamically:

const player = dashjs.MediaPlayer().create();
const callback = (payload) => {
   return new Promise((resolve,reject) => {
    resolve(payload)
  })
}
player.initialize(video, url, false);
player.registerLicenseResponseFilter(callback)
player.unregisterLicenseResponseFilter(callback)

Examples

Multiple samples implementing the functionalities described in this documentation can be found here in the DRM section.

References

[1] dash.js: License acquisition for multiple EME versions

Clone this wiki locally