Skip to content

Commit

Permalink
feat(MediaCap): get mediaKeySystemAccess via decodingInfo
Browse files Browse the repository at this point in the history
In StreamUtils, add a MediaCapabilitiesKeySystemConfiguration
for each key system for the encrypted variant passed to the
decodingInfo API, to get the mediaKeySystemAccess as a part of
the decodingInfo results.

We create a list of mediaDecodingConfigurations for each variant,
and call decodingInfo() with each mediaDecodingConfiguration to
get the mediaKeySystemAccess.

Eventually, we'll use the mediaKeySystemAccess from the
decodingInfo results to replace the call of
navigator.requestMediaKeySystemAccess() in DrmEngine. That will be
in the next CL.

Also, adding MediaCapabilties polyfill with mediaKeysSystemAccess.

Issue shaka-project#1391

Change-Id: Ied4a27dd8a1ade43209bcf07f21f0c9b31c2693c
  • Loading branch information
michellezhuogg committed Mar 30, 2021
1 parent 96e87c2 commit aca343b
Show file tree
Hide file tree
Showing 6 changed files with 304 additions and 36 deletions.
16 changes: 10 additions & 6 deletions lib/media/drm_engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ shaka.media.DrmEngine = class {
// persistent licenses.
this.usePersistentLicenses_ = usePersistentLicenses;

return this.init_(variants);
return this.init_(variants, /* useMediaCapabilities= */ false);
}

/**
Expand All @@ -223,13 +223,14 @@ shaka.media.DrmEngine = class {
* @param {!Array.<shaka.extern.Variant>} variants
* The variants that we want to support playing.
* @param {!Array.<string>} offlineSessionIds
* @param {boolean=} useMediaCapabilities
* @return {!Promise}
*/
initForPlayback(variants, offlineSessionIds) {
initForPlayback(variants, offlineSessionIds, useMediaCapabilities) {
this.offlineSessionIds_ = offlineSessionIds;
this.usePersistentLicenses_ = offlineSessionIds.length > 0;

return this.init_(variants);
return this.init_(variants, !!useMediaCapabilities);
}

/**
Expand Down Expand Up @@ -284,10 +285,11 @@ shaka.media.DrmEngine = class {
* @param {!Array.<shaka.extern.Variant>} variants
* The variants that we expect to operate with during the drm engine's
* lifespan of the drm engine.
* @param {boolean} useMediaCapabilities
* @return {!Promise} Resolved if/when a key system has been chosen.
* @private
*/
async init_(variants) {
async init_(variants, useMediaCapabilities) {
goog.asserts.assert(this.config_,
'DrmEngine configure() must be called before init()!');

Expand Down Expand Up @@ -344,8 +346,10 @@ shaka.media.DrmEngine = class {

// 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);

if (useMediaCapabilities) {
await shaka.util.StreamUtils.getDecodingInfosForVariants(variants,
this.usePersistentLicenses_);
}
/** @type {!Map.<string, MediaKeySystemConfiguration>} */
const configsByKeySystem =
this.prepareMediaKeyConfigsForVariants_(variants);
Expand Down
2 changes: 2 additions & 0 deletions lib/offline/storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,8 @@ shaka.offline.Storage = class {

// Filter the manifest based on what we know media source will be able to
// play later (no point storing something we can't play).
// TODO: add an argument of usePersistentLicense, and use the value of
// config.offline.usePersistentLicense.
shaka.util.ManifestFilter.filterByMediaSourceSupport(manifest);

// Filter the manifest based on what we know our drm system will support
Expand Down
11 changes: 9 additions & 2 deletions lib/player.js
Original file line number Diff line number Diff line change
Expand Up @@ -1735,11 +1735,17 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
},
});

// TODO: remove once MediaCap implementation is complete.
if (!this.config_.useMediaCapabilities) {
shaka.util.StreamUtils.filterManifestByMediaSource(this.manifest_);
}

this.drmEngine_.configure(this.config_.drm);

await this.drmEngine_.initForPlayback(
this.manifest_.variants,
this.manifest_.offlineSessionIds);
this.manifest_.offlineSessionIds,
this.config_.useMediaCapabilities);

await this.drmEngine_.attach(has.mediaElement);

Expand Down Expand Up @@ -4606,7 +4612,8 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
this.streamingEngine_.getCurrentVariant() : null;

await shaka.util.StreamUtils.filterManifest(
this.drmEngine_, currentVariant, manifest);
this.drmEngine_, currentVariant, manifest,
this.config_.useMediaCapabilities);
this.checkPlayableVariants_(manifest);
}

Expand Down
73 changes: 67 additions & 6 deletions lib/polyfill/media_capabilities.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ shaka.polyfill.MediaCapabilities = class {
* @return {!Promise.<!MediaCapabilitiesDecodingInfo>}
* @private
*/
static decodingInfo_(mediaDecodingConfig) {
static async decodingInfo_(mediaDecodingConfig) {
const res = {
supported: false,
powerEfficient: true,
Expand All @@ -48,28 +48,89 @@ shaka.polyfill.MediaCapabilities = class {
};

if (!mediaDecodingConfig) {
return Promise.resolve(res);
return res;
}

// Use 'MediaSource.isTypeSupported' to check if the stream is supported.
if (mediaDecodingConfig['video']) {
const contentType = mediaDecodingConfig['video'].contentType;
const isSupported = MediaSource.isTypeSupported(contentType);
if (!isSupported) {
return Promise.resolve(res);
return res;
}
}

if (mediaDecodingConfig['audio']) {
const contentType = mediaDecodingConfig['audio'].contentType;
const isSupported = MediaSource.isTypeSupported(contentType);
if (!isSupported) {
return Promise.resolve(res);
return res;
}
}

if (!mediaDecodingConfig.keySystemConfiguration) {
// The variant is supported if it's unencrypted.
res.supported = true;
return Promise.resolve(res);
} else {
// Get the MediaKeySystemAccess for the key system.
// Convert the MediaDecodingConfiguration object to a
// MediaKeySystemConfiguration object.

/** @type {MediaCapabilitiesKeySystemConfiguration} */
const mediaCapkeySystemConfig =
mediaDecodingConfig.keySystemConfiguration;
const audioCapabilities = [];
const videoCapabilities = [];

if (mediaCapkeySystemConfig.audio) {
const capability = {
robustness: mediaCapkeySystemConfig.audio.robustness || '',
contentType: mediaDecodingConfig.audio.contentType,
};
audioCapabilities.push(capability);
}

if (mediaCapkeySystemConfig.video) {
const capability = {
robustness: mediaCapkeySystemConfig.video.robustness || '',
contentType: mediaDecodingConfig.video.contentType,
};
videoCapabilities.push(capability);
}

/** @type {MediaKeySystemConfiguration} */
const mediaKeySystemConfig = {
initDataTypes: [mediaCapkeySystemConfig.initDataType],
distinctiveIdentifier: mediaCapkeySystemConfig.distinctiveIdentifier,
persistentState: mediaCapkeySystemConfig.persistentState,
sessionTypes: mediaCapkeySystemConfig.sessionTypes,
};

// Only add the audio video capablities if they have valid data.
// Otherwise the query will fail.
if (audioCapabilities.length) {
mediaKeySystemConfig.audioCapabilities = audioCapabilities;
}
if (videoCapabilities.length) {
mediaKeySystemConfig.videoCapabilities = videoCapabilities;
}

let keySystemAccess;
try {
keySystemAccess = await navigator.requestMediaKeySystemAccess(
mediaCapkeySystemConfig.keySystem, [mediaKeySystemConfig]);
} catch (e) {
shaka.log.info('navigator.requestMediaKeySystemAccess failed.');
}

if (keySystemAccess) {
res.supported = true;
res.keySystemAccess = keySystemAccess;
}
}

res.supported = true;
return Promise.resolve(res);
return res;
}
};

Expand Down
Loading

0 comments on commit aca343b

Please sign in to comment.