Skip to content

Commit

Permalink
feat(MediaCap): Use MediaCapabilities for offline storage
Browse files Browse the repository at this point in the history
Issue shaka-project#1391

Change-Id: Ifdf4477d3798ddacf77036f7d85d9cb29438becc
  • Loading branch information
michellezhuogg committed Apr 7, 2021
1 parent 879264a commit 2f65b97
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 100 deletions.
1 change: 0 additions & 1 deletion build/types/core
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@
+../../lib/util/iterables.js
+../../lib/util/language_utils.js
+../../lib/util/lazy.js
+../../lib/util/manifest_filter.js
+../../lib/util/manifest_parser_utils.js
+../../lib/util/map_utils.js
+../../lib/util/media_ready_state_utils.js
Expand Down
19 changes: 10 additions & 9 deletions lib/offline/storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ goog.require('shaka.util.Error');
goog.require('shaka.util.Functional');
goog.require('shaka.util.IDestroyable');
goog.require('shaka.util.Iterables');
goog.require('shaka.util.ManifestFilter');
goog.require('shaka.util.MimeUtils');
goog.require('shaka.util.Networking');
goog.require('shaka.util.Platform');
Expand Down Expand Up @@ -483,25 +482,27 @@ shaka.offline.Storage = class {
// Filter the manifest based on the restrictions given in the player
// configuration.
const maxHwRes = {width: Infinity, height: Infinity};
shaka.util.ManifestFilter.filterByRestrictions(
manifest, config.restrictions, maxHwRes);
StreamUtils.filterByRestrictions(manifest, config.restrictions, maxHwRes);

// 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);
if (config.useMediaCapabilities) {
StreamUtils.filterManifestByMediaCapabilities(
manifest, config.offline.usePersistentLicense);
} else {
StreamUtils.filterManifestByMediaSource(manifest);
}

// Filter the manifest based on what we know our drm system will support
// playing later.
shaka.util.ManifestFilter.filterByDrmSupport(manifest, drmEngine);
StreamUtils.filterManifestByDrm(manifest, drmEngine);

// Gather all tracks.
const allTracks = [];

// Choose the codec that has the lowest average bandwidth.
const preferredAudioChannelCount = config.preferredAudioChannelCount;
shaka.util.StreamUtils.chooseCodecsAndFilterManifest(
StreamUtils.chooseCodecsAndFilterManifest(
manifest, preferredAudioChannelCount);

for (const variant of manifest.variants) {
Expand Down Expand Up @@ -998,7 +999,7 @@ shaka.offline.Storage = class {
drmEngine.configure(config.drm);
await drmEngine.initForStorage(
manifest.variants, config.offline.usePersistentLicense,
/* useMediaCapabilities= */ config.useMediaCapabilities);
config.useMediaCapabilities);
await drmEngine.setServerCertificate();
await drmEngine.createOrLoad();

Expand Down
70 changes: 0 additions & 70 deletions lib/util/manifest_filter.js

This file was deleted.

40 changes: 28 additions & 12 deletions lib/util/stream_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,21 @@ shaka.util.StreamUtils = class {
return baseVideoCodec + '-' + baseAudioCodec;
}

/**
* Filter the variants in |manifest| to only include the variants that meet
* the given restrictions.
*
* @param {shaka.extern.Manifest} manifest
* @param {shaka.extern.Restrictions} restrictions
* @param {{width: number, height:number}} maxHwResolution
*/
static filterByRestrictions(manifest, restrictions, maxHwResolution) {
manifest.variants = manifest.variants.filter((variant) => {
return shaka.util.StreamUtils.meetsRestrictions(
variant, restrictions, maxHwResolution);
});
}

/**
* @param {shaka.extern.Variant} variant
* @param {shaka.extern.Restrictions} restrictions
Expand Down Expand Up @@ -278,10 +293,11 @@ shaka.util.StreamUtils = class {
// needed.
// TODO: remove the first parameter 'drmEngine' and the function
// 'filterManifestByDrm_'.
shaka.util.StreamUtils.filterManifestByDrm_(drmEngine, manifest);
shaka.util.StreamUtils.filterManifestByDrm(manifest, drmEngine);

if (useMediaCapabilities) {
await shaka.util.StreamUtils.filterManifestByMediaCapabilities_(manifest);
await shaka.util.StreamUtils.filterManifestByMediaCapabilities(manifest,
manifest.offlineSessionIds.length > 0);
} else {
shaka.util.StreamUtils.filterManifestByMediaSource(manifest);
}
Expand All @@ -293,13 +309,12 @@ shaka.util.StreamUtils = class {


/**
* Alters the given Manifest to filter out any streams unsupported by the DRM.
*
* @param {shaka.media.DrmEngine} drmEngine
* Filter the variants in |manifest| to only include those that are supported
* by |drm|.
* @param {shaka.extern.Manifest} manifest
* @private
* @param {shaka.media.DrmEngine} drmEngine
*/
static filterManifestByDrm_(drmEngine, manifest) {
static filterManifestByDrm(manifest, drmEngine) {
manifest.variants = manifest.variants.filter((variant) => {
if (drmEngine && drmEngine.initialized()) {
if (!drmEngine.supportsVariant(variant)) {
Expand All @@ -308,6 +323,7 @@ shaka.util.StreamUtils = class {
return false;
}
}
shaka.log.debug('DrmEngine is not initialized yet.');
return true;
});
}
Expand All @@ -318,13 +334,13 @@ shaka.util.StreamUtils = class {
* platform via MediaCapabilities.decodingInfo() API.
*
* @param {shaka.extern.Manifest} manifest
* @private
* @param {boolean} usePersistentLicenses
*/
static async filterManifestByMediaCapabilities_(manifest) {
static async filterManifestByMediaCapabilities(
manifest, usePersistentLicenses) {
goog.asserts.assert(navigator.mediaCapabilities,
'MediaCapabilities should be valid.');

const usePersistentLicenses = manifest.offlineSessionIds.length > 0;
await shaka.util.StreamUtils.getDecodingInfosForVariants(
manifest.variants, usePersistentLicenses);
manifest.variants = manifest.variants.filter((variant) => {
Expand All @@ -342,8 +358,8 @@ shaka.util.StreamUtils = class {


/**
* Alters the given variants to filter out any streams unsupported by the
* MediaSource.
* Filter the variants in the |manifest| to only include those that are
* supported by media source.
* TODO: remove once MediaCap implementations are done.
* @param {shaka.extern.Manifest} manifest
*/
Expand Down
27 changes: 19 additions & 8 deletions test/offline/storage_integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,15 @@ filterDescribe('Storage', storageSupport, () => {
}
});

filterDescribe('persistent license', drmStorageSupport, () => {
for (const useMediaCapabilities of [true, false]) {
const isEnabled = useMediaCapabilities ? 'enabled' : 'disabled';
filterDescribe('persistent license with MediaCapabilities ' + isEnabled,
drmStorageSupport, () => {
testPersistentLicense(useMediaCapabilities);
});
}

function testPersistentLicense(useMediaCapabilities) {
/** @type {!shaka.Player} */
let player;
/** @type {!shaka.offline.Storage} */
Expand All @@ -158,6 +166,7 @@ filterDescribe('Storage', storageSupport, () => {
// networking engine. This allows us to use Player.configure in these
// tests.
player = new shaka.Player();
player.configure({'useMediaCapabilities': useMediaCapabilities});
storage = new shaka.offline.Storage(player);
});

Expand Down Expand Up @@ -192,7 +201,7 @@ filterDescribe('Storage', storageSupport, () => {
expect(manifest.offlineSessionIds.length).toBeTruthy();

// PART 2 - Check that the licences are stored.
await withDrm(player, manifest, (drm) => {
await withDrm(player, manifest, useMediaCapabilities, (drm) => {
return Promise.all(manifest.offlineSessionIds.map(async (session) => {
const foundSession = await loadOfflineSession(drm, session);
expect(foundSession).toBeTruthy();
Expand All @@ -204,7 +213,7 @@ filterDescribe('Storage', storageSupport, () => {
await storage.remove(uri.toString());

// PART 4 - Check that the licenses were removed.
const p = withDrm(player, manifest, (drm) => {
const p = withDrm(player, manifest, useMediaCapabilities, (drm) => {
return Promise.all(manifest.offlineSessionIds.map(async (session) => {
const notFoundSession = await loadOfflineSession(drm, session);
expect(notFoundSession).toBeFalsy();
Expand Down Expand Up @@ -248,7 +257,7 @@ filterDescribe('Storage', storageSupport, () => {
const storedContents = await storage.list();
expect(storedContents).toEqual([]);

await withDrm(player, manifest, (drm) => {
await withDrm(player, manifest, useMediaCapabilities, (drm) => {
return Promise.all(manifest.offlineSessionIds.map(async (session) => {
const foundSession = await loadOfflineSession(drm, session);
expect(foundSession).toBeTruthy();
Expand All @@ -261,7 +270,7 @@ filterDescribe('Storage', storageSupport, () => {
expect(didRemoveAll).toBe(true);

// PART 6 - Check that the licenses were removed.
const p = withDrm(player, manifest, (drm) => {
const p = withDrm(player, manifest, useMediaCapabilities, (drm) => {
return Promise.all(manifest.offlineSessionIds.map(async (session) => {
const notFoundSession = await loadOfflineSession(drm, session);
expect(notFoundSession).toBeFalsy();
Expand All @@ -273,7 +282,7 @@ filterDescribe('Storage', storageSupport, () => {
shaka.util.Error.Code.OFFLINE_SESSION_REMOVED));
await expectAsync(p).toBeRejectedWith(expected);
});
});
}

describe('default track selection callback', () => {
const PlayerConfiguration = shaka.util.PlayerConfiguration;
Expand Down Expand Up @@ -1672,10 +1681,11 @@ filterDescribe('Storage', storageSupport, () => {
/**
* @param {!shaka.Player} player
* @param {shaka.extern.Manifest} manifest
* @param {boolean} useMediaCapabilities
* @param {function(!shaka.media.DrmEngine):Promise} action
* @return {!Promise}
*/
async function withDrm(player, manifest, action) {
async function withDrm(player, manifest, useMediaCapabilities, action) {
const net = player.getNetworkingEngine();
goog.asserts.assert(net, 'Player should have a net engine right now');

Expand All @@ -1693,7 +1703,8 @@ filterDescribe('Storage', storageSupport, () => {
try {
drm.configure(player.getConfiguration().drm);
const variants = manifest.variants;
await drm.initForStorage(variants, /* usePersistentLicenses= */ true);
await drm.initForStorage(variants, /* usePersistentLicenses= */ true,
useMediaCapabilities);
await action(drm);
} finally {
await drm.destroy();
Expand Down

0 comments on commit 2f65b97

Please sign in to comment.