Skip to content

Commit

Permalink
feat: add support for multiple robustness levels in drm (#7753)
Browse files Browse the repository at this point in the history
This changes the `drm.advanced.videoRobustness` and `audioRobustness`
config options from a string to an array of strings. Internally, in the
drm engine, this gets expanded into an array of `DrmInfos` which have
those values as strings.

Best way to review this change is with whitespace turned off in the diff
options.

---------

Co-authored-by: Wojciech Tyczyński <[email protected]>
  • Loading branch information
gkatsev and tykus160 authored Dec 23, 2024
1 parent 7ef5e62 commit 88472b3
Show file tree
Hide file tree
Showing 9 changed files with 513 additions and 166 deletions.
13 changes: 9 additions & 4 deletions demo/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,8 @@ shakaDemo.Config = class {
.addBoolInput_('Ignore duplicate init data',
'drm.ignoreDuplicateInitData');
const advanced = shakaDemoMain.getConfiguration().drm.advanced || {};
const addDRMAdvancedField = (name, valueName, suggestions) => {
const addDRMAdvancedField = (name, valueName, suggestions,
arrayString = false) => {
// All advanced fields of a given type are set at once.
this.addDatalistInput_(name, suggestions, (input) => {
// Add in any common drmSystem not currently in advanced.
Expand All @@ -150,7 +151,9 @@ shakaDemo.Config = class {
}
// Set the robustness.
for (const drmSystem in advanced) {
advanced[drmSystem][valueName] = input.value;
advanced[drmSystem][valueName] = arrayString ?
input.value.split(',').filter(Boolean) :
input.value;
}
shakaDemoMain.configure('drm.advanced', advanced);
shakaDemoMain.remakeHash();
Expand All @@ -176,9 +179,11 @@ shakaDemo.Config = class {
const sessionTypeSuggestions = ['temporary', 'persistent-license'];

addDRMAdvancedField(
'Video Robustness', 'videoRobustness', robustnessSuggestions);
'Video Robustness', 'videoRobustness', robustnessSuggestions,
/* arrayString= */ true);
addDRMAdvancedField(
'Audio Robustness', 'audioRobustness', robustnessSuggestions);
'Audio Robustness', 'audioRobustness', robustnessSuggestions,
/* arrayString= */ true);
addDRMAdvancedField('Session Type', 'sessionType', sessionTypeSuggestions);

this.addRetrySection_('drm', 'DRM Retry Parameters');
Expand Down
26 changes: 18 additions & 8 deletions demo/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -949,12 +949,18 @@ shakaDemo.Main = class {
advanced[drmSystem] = shakaDemo.Main.defaultAdvancedDrmConfig();
}
if ('videoRobustness' in params) {
advanced[drmSystem].videoRobustness = params['videoRobustness'];
advanced[drmSystem].videoRobustness =
params['videoRobustness'].split(',');
}
if ('audioRobustness' in params) {
advanced[drmSystem].audioRobustness = params['audioRobustness'];
advanced[drmSystem].audioRobustness =
params['audioRobustness'].split(',');
}
}

if ('audioRobustness' in params || 'videoRobustness' in params) {
this.configure('drm.advanced', advanced);
}
}
}
if ('lang' in params) {
Expand Down Expand Up @@ -1499,11 +1505,15 @@ shakaDemo.Main = class {
for (const drmSystem of shakaDemo.Main.commonDrmSystems) {
const advancedFor = advanced[drmSystem];
if (advancedFor) {
if (advancedFor.videoRobustness) {
params.push('videoRobustness=' + advancedFor.videoRobustness);
if (advancedFor.videoRobustness &&
advancedFor.videoRobustness.length) {
params.push('videoRobustness=' +
advancedFor.videoRobustness.join());
}
if (advancedFor.audioRobustness) {
params.push('audioRobustness=' + advancedFor.audioRobustness);
if (advancedFor.audioRobustness &&
advancedFor.audioRobustness.length) {
params.push('audioRobustness=' +
advancedFor.audioRobustness.join());
}
break;
}
Expand Down Expand Up @@ -1933,8 +1943,8 @@ shakaDemo.Main = class {
return {
distinctiveIdentifierRequired: false,
persistentStateRequired: false,
videoRobustness: '',
audioRobustness: '',
videoRobustness: [],
audioRobustness: [],
sessionType: '',
serverCertificate: new Uint8Array(0),
serverCertificateUri: '',
Expand Down
1 change: 1 addition & 0 deletions docs/tutorials/upgrade.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ application:
`panicThreshold`. (deprecated in v4.10.0)
- `useSafariBehaviorForLive` has been removed.
- `parsePrftBox` has been removed.
- `videoRobustness` and `audioRobustness` are now only an array of strings. (deprecated in v4.13.0)

- Plugin changes:
- `TextDisplayer` plugins must implement the `configure()` method.
Expand Down
26 changes: 14 additions & 12 deletions externs/shaka/player.js
Original file line number Diff line number Diff line change
Expand Up @@ -808,8 +808,8 @@ shaka.extern.ProducerReferenceTime;
* @typedef {{
* distinctiveIdentifierRequired: boolean,
* persistentStateRequired: boolean,
* videoRobustness: string,
* audioRobustness: string,
* videoRobustness: Array.<string>,
* audioRobustness: Array.<string>,
* serverCertificate: Uint8Array,
* serverCertificateUri: string,
* individualizationServer: string,
Expand All @@ -827,16 +827,18 @@ shaka.extern.ProducerReferenceTime;
* state, e.g., for persistent license storage.
* <br>
* Defaults to <code>false</code>.
* @property {string} videoRobustness
* A key-system-specific string that specifies a required security level for
* video.
* <br>
* Defaults to <code>''</code>, i.e., no specific robustness required.
* @property {string} audioRobustness
* A key-system-specific string that specifies a required security level for
* audio.
* <br>
* Defaults to <code>''</code>, i.e., no specific robustness required.
* @property {Array.<string>} videoRobustness
* A key-system-specific Array of strings that specifies a required security
* level for video. For multiple robustness levels, list items in priority
* order.
* <br>
* Defaults to <code>[]</code>, i.e., no specific robustness required.
* @property {Array.<string>} audioRobustness
* A key-system-specific Array of strings that specifies a required security
* level for audio. For multiple robustness levels, list items in priority
* order.
* <br>
* Defaults to <code>[]</code>, i.e., no specific robustness required.
* @property {Uint8Array} serverCertificate
* <i>An empty certificate (<code>byteLength==0</code>) will be treated as
* <code>null</code>.</i> <br>
Expand Down
60 changes: 53 additions & 7 deletions lib/drm/drm_engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,57 @@ shaka.drm.DrmEngine = class {
/** @type {!Map.<string, MediaKeySystemConfiguration>} */
let configsByKeySystem;

/**
* Expand robustness into multiple drm infos if multiple video robustness
* levels were provided.
*
* robustness can be either a single item as a string or multiple items as
* an array of strings.
*/
const expandRobustness = (drmInfos, robustnessType) => {
const newDrmInfos = [];
for (const drmInfo of drmInfos) {
let items = drmInfo[robustnessType] ||
(this.config_.advanced &&
this.config_.advanced[drmInfo.keySystem] &&
this.config_.advanced[drmInfo.keySystem][robustnessType]) || '';
if (typeof items === 'string') {
// if drmInfo's robustness has already been expanded,
// use the drmInfo directly.
newDrmInfos.push(drmInfo);
} else if (Array.isArray(items)) {
if (items.length === 0) {
items = [''];
}
for (const item of items) {
newDrmInfos.push(
Object.assign({}, drmInfo, {[robustnessType]: item}),
);
}
}
}
return newDrmInfos;
};

for (const variant of variants) {
if (variant.video) {
variant.video.drmInfos =
expandRobustness(variant.video.drmInfos,
'videoRobustness');
variant.video.drmInfos =
expandRobustness(variant.video.drmInfos,
'audioRobustness');
}
if (variant.audio) {
variant.audio.drmInfos =
expandRobustness(variant.audio.drmInfos,
'videoRobustness');
variant.audio.drmInfos =
expandRobustness(variant.audio.drmInfos,
'audioRobustness');
}
}

// We should get the decodingInfo results for the variants after we filling
// in the drm infos, and before queryMediaKeys_().
await shaka.util.StreamUtils.getDecodingInfosForVariants(variants,
Expand Down Expand Up @@ -2505,13 +2556,8 @@ shaka.drm.DrmEngine = class {
advancedConfig.persistentStateRequired;
}

if (!drmInfo.videoRobustness) {
drmInfo.videoRobustness = advancedConfig.videoRobustness;
}

if (!drmInfo.audioRobustness) {
drmInfo.audioRobustness = advancedConfig.audioRobustness;
}
// robustness will be filled in with defaults, if needed, in
// expandRobustness

if (!drmInfo.serverCertificate) {
drmInfo.serverCertificate = advancedConfig.serverCertificate;
Expand Down
32 changes: 32 additions & 0 deletions lib/player.js
Original file line number Diff line number Diff line change
Expand Up @@ -4047,6 +4047,38 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
config['streaming']['autoLowLatencyMode'];
delete config['streaming']['autoLowLatencyMode'];
}

// Deprecate AdvancedDrmConfiguration's videoRobustness and audioRobustness
// as a string. It's now an array of strings.
if (config['drm'] && config['drm']['advanced']) {
let fixedUp = false;
for (const keySystem in config['drm']['advanced']) {
const {videoRobustness, audioRobustness} =
config['drm']['advanced'][keySystem];
if ('videoRobustness' in config['drm']['advanced'][keySystem] &&
!Array.isArray(
config['drm']['advanced'][keySystem]['videoRobustness'])) {
config['drm']['advanced'][keySystem]['videoRobustness'] =
[videoRobustness];
fixedUp = true;
}
if ('audioRobustness' in config['drm']['advanced'][keySystem] &&
!Array.isArray(
config['drm']['advanced'][keySystem]['audioRobustness'])) {
config['drm']['advanced'][keySystem]['audioRobustness'] =
[audioRobustness];
fixedUp = true;
}
}

if (fixedUp) {
shaka.Deprecate.deprecateFeature(5,
'AdvancedDrmConfiguration\'s videoRobustness and audioRobustness',
'These properties are no longer strings but array of strings, ' +
'please update your usage of these properties.');
}
}

const ret = shaka.util.PlayerConfiguration.mergeConfigObjects(
this.config_, config, this.defaultConfig_());

Expand Down
4 changes: 2 additions & 2 deletions lib/util/player_configuration.js
Original file line number Diff line number Diff line change
Expand Up @@ -540,8 +540,8 @@ shaka.util.PlayerConfiguration = class {
'.drm.advanced': {
distinctiveIdentifierRequired: false,
persistentStateRequired: false,
videoRobustness: '',
audioRobustness: '',
videoRobustness: [],
audioRobustness: [],
sessionType: '',
serverCertificate: new Uint8Array(0),
serverCertificateUri: '',
Expand Down
Loading

0 comments on commit 88472b3

Please sign in to comment.