Skip to content

Commit

Permalink
Merge pull request video-dev#2665 from springuper/chore/eme-options
Browse files Browse the repository at this point in the history
Support drm system options
  • Loading branch information
robwalch authored May 13, 2020
2 parents cfdb769 + 2c531ea commit b2d8f8a
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 8 deletions.
1 change: 1 addition & 0 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,7 @@ Configuration parameters could be provided to hls.js upon instantiation of `Hls`
minAutoBitrate: 0,
emeEnabled: false,
widevineLicenseUrl: undefined,
drmSystemOptions: {},
requestMediaKeySystemAccessFunc: requestMediaKeySystemAccess
};

Expand Down
7 changes: 7 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,16 @@ type CapLevelControllerConfig = {
capLevelToPlayerSize: boolean
};

export type DRMSystemOptions = {
audioRobustness?: string,
videoRobustness?: string,
}

export type EMEControllerConfig = {
licenseXhrSetup?: (xhr: XMLHttpRequest, url: string) => void,
emeEnabled: boolean,
widevineLicenseUrl?: string,
drmSystemOptions: DRMSystemOptions,
requestMediaKeySystemAccessFunc: MediaKeyFunc | null,
};

Expand Down Expand Up @@ -240,6 +246,7 @@ export const hlsDefaultConfig: HlsConfig = {
minAutoBitrate: 0, // used by hls
emeEnabled: false, // used by eme-controller
widevineLicenseUrl: void 0, // used by eme-controller
drmSystemOptions: {}, // used by eme-controller
requestMediaKeySystemAccessFunc: requestMediaKeySystemAccess, // used by eme-controller
testBandwidth: true,

Expand Down
33 changes: 25 additions & 8 deletions src/controller/eme-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Event from '../events';
import { ErrorTypes, ErrorDetails } from '../errors';

import { logger } from '../utils/logger';
import { EMEControllerConfig } from '../config';
import { DRMSystemOptions, EMEControllerConfig } from '../config';
import { KeySystems, MediaKeyFunc } from '../utils/mediakeys-helper';

const MAX_LICENSE_REQUEST_FAILURES = 3;
Expand All @@ -22,19 +22,31 @@ const MAX_LICENSE_REQUEST_FAILURES = 3;
* @returns {Array<MediaSystemConfiguration>} An array of supported configurations
*/

const createWidevineMediaKeySystemConfigurations = function (audioCodecs: string[], videoCodecs: string[]): MediaKeySystemConfiguration[] { /* jshint ignore:line */
const createWidevineMediaKeySystemConfigurations = function (
audioCodecs: string[],
videoCodecs: string[],
drmSystemOptions: DRMSystemOptions
): MediaKeySystemConfiguration[] { /* jshint ignore:line */
const baseConfig: MediaKeySystemConfiguration = {
// initDataTypes: ['keyids', 'mp4'],
// label: "",
// persistentState: "not-allowed", // or "required" ?
// distinctiveIdentifier: "not-allowed", // or "required" ?
// sessionTypes: ['temporary'],
audioCapabilities: [], // { contentType: 'audio/mp4; codecs="mp4a.40.2"' }
videoCapabilities: [] // { contentType: 'video/mp4; codecs="avc1.42E01E"' }
};

audioCodecs.forEach((codec) => {
baseConfig.audioCapabilities!.push({
contentType: `audio/mp4; codecs="${codec}"`,
robustness: drmSystemOptions.audioRobustness || ''
});
});
videoCodecs.forEach((codec) => {
baseConfig.videoCapabilities!.push({
contentType: `video/mp4; codecs="${codec}"`
contentType: `video/mp4; codecs="${codec}"`,
robustness: drmSystemOptions.videoRobustness || ''
});
});

Expand All @@ -55,10 +67,15 @@ const createWidevineMediaKeySystemConfigurations = function (audioCodecs: string
* @throws will throw an error if a unknown key system is passed
* @returns {Array<MediaSystemConfiguration>} A non-empty Array of MediaKeySystemConfiguration objects
*/
const getSupportedMediaKeySystemConfigurations = function (keySystem: KeySystems, audioCodecs: string[], videoCodecs: string[]): MediaKeySystemConfiguration[] {
const getSupportedMediaKeySystemConfigurations = function (
keySystem: KeySystems,
audioCodecs: string[],
videoCodecs: string[],
drmSystemOptions: DRMSystemOptions
): MediaKeySystemConfiguration[] {
switch (keySystem) {
case KeySystems.WIDEVINE:
return createWidevineMediaKeySystemConfigurations(audioCodecs, videoCodecs);
return createWidevineMediaKeySystemConfigurations(audioCodecs, videoCodecs, drmSystemOptions);
default:
throw new Error(`Unknown key-system: ${keySystem}`);
}
Expand All @@ -84,6 +101,7 @@ class EMEController extends EventHandler {
private _licenseXhrSetup?: (xhr: XMLHttpRequest, url: string) => void;
private _emeEnabled: boolean;
private _requestMediaKeySystemAccess: MediaKeyFunc | null;
private _drmSystemOptions: DRMSystemOptions;

private _config: EMEControllerConfig;
private _mediaKeysList: MediaKeysListItem[] = [];
Expand All @@ -109,6 +127,7 @@ class EMEController extends EventHandler {
this._licenseXhrSetup = this._config.licenseXhrSetup;
this._emeEnabled = this._config.emeEnabled;
this._requestMediaKeySystemAccess = this._config.requestMediaKeySystemAccessFunc;
this._drmSystemOptions = hls.config.drmSystemOptions;
}

/**
Expand Down Expand Up @@ -137,10 +156,8 @@ class EMEController extends EventHandler {
* @throws When a unsupported KeySystem is passed
*/
private _attemptKeySystemAccess (keySystem: KeySystems, audioCodecs: string[], videoCodecs: string[]) {
// TODO: add other DRM "options"

// This can throw, but is caught in event handler callpath
const mediaKeySystemConfigs = getSupportedMediaKeySystemConfigurations(keySystem, audioCodecs, videoCodecs);
const mediaKeySystemConfigs = getSupportedMediaKeySystemConfigurations(keySystem, audioCodecs, videoCodecs, this._drmSystemOptions);

logger.log('Requesting encrypted media key-system access');

Expand Down
31 changes: 31 additions & 0 deletions tests/unit/controller/eme-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,37 @@ describe('EMEController', function () {
}, 0);
});

it('should request keys with specified robustness options when `emeEnabled` is true', function (done) {
let reqMediaKsAccessSpy = sinon.spy(function () {
return Promise.resolve({
// Media-keys mock
});
});

setupEach({
emeEnabled: true,
drmSystemOptions: {
audioRobustness: 'HW_SECURE_ALL',
videoRobustness: 'HW_SECURE_ALL'
},
requestMediaKeySystemAccessFunc: reqMediaKsAccessSpy
});

emeController.onMediaAttached({ media });

expect(media.setMediaKeys.callCount).to.equal(0);
expect(reqMediaKsAccessSpy.callCount).to.equal(0);

emeController.onManifestParsed({ levels: fakeLevels });

setTimeout(function () {
const baseConfig = reqMediaKsAccessSpy.getCall(0).args[1][0];
expect(baseConfig.audioCapabilities[0]).to.have.property('robustness', 'HW_SECURE_ALL');
expect(baseConfig.videoCapabilities[0]).to.have.property('robustness', 'HW_SECURE_ALL');
done();
}, 0);
});

it('should trigger key system error(s) when bad encrypted data is received', function (done) {
let reqMediaKsAccessSpy = sinon.spy(function () {
return Promise.resolve({
Expand Down

0 comments on commit b2d8f8a

Please sign in to comment.