Skip to content

Commit

Permalink
fix(preload): Wait for drm keys when preloading (#7698)
Browse files Browse the repository at this point in the history
Closes #7520
  • Loading branch information
theodab authored and avelad committed Dec 4, 2024
1 parent 755e9d2 commit c2242dc
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 3 deletions.
23 changes: 23 additions & 0 deletions lib/media/drm_engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ goog.provide('shaka.media.DrmEngine');
goog.require('goog.asserts');
goog.require('shaka.log');
goog.require('shaka.net.NetworkingEngine');
goog.require('shaka.util.ArrayUtils');
goog.require('shaka.util.BufferUtils');
goog.require('shaka.util.Destroyer');
goog.require('shaka.util.DrmUtils');
Expand Down Expand Up @@ -67,12 +68,18 @@ shaka.media.DrmEngine = class {
*/
this.activeSessions_ = new Map();

/** @private {!Array.<!shaka.net.NetworkingEngine.PendingRequest>} */
this.activeRequests_ = [];

/**
* @private {!Map<string,
* {initData: ?Uint8Array, initDataType: ?string}>}
*/
this.storedPersistentSessions_ = new Map();

/** @private {boolean} */
this.hasInitData_ = false;

/** @private {!shaka.util.PublicPromise} */
this.allSessionsLoaded_ = new shaka.util.PublicPromise();

Expand Down Expand Up @@ -706,6 +713,7 @@ shaka.media.DrmEngine = class {

// Reset the promise for the next sessions to come if key needs aren't
// satisfied with persistent sessions
this.hasInitData_ = false;
this.allSessionsLoaded_ = new shaka.util.PublicPromise();
this.allSessionsLoaded_.catch(() => {});
}
Expand Down Expand Up @@ -767,11 +775,16 @@ shaka.media.DrmEngine = class {
}
}

// Mark that there is init data, so that the preloader will know to wait
// for sessions to be loaded.
this.hasInitData_ = true;

// If there are pre-existing sessions that have all been loaded
// then reset the allSessionsLoaded_ promise, which can now be
// used to wait for new sesssions to be loaded
if (this.activeSessions_.size > 0 && this.areAllSessionsLoaded_()) {
this.allSessionsLoaded_.resolve();
this.hasInitData_ = false;
this.allSessionsLoaded_ = new shaka.util.PublicPromise();
this.allSessionsLoaded_.catch(() => {});
}
Expand Down Expand Up @@ -1381,6 +1394,14 @@ shaka.media.DrmEngine = class {
this.video_.paused && !this.initialRequestsSent_);
}

/** @return {!Promise} */
async waitForActiveRequests() {
if (this.hasInitData_) {
await this.allSessionsLoaded_;
await Promise.all(this.activeRequests_.map((req) => req.promise));
}
}

/**
* Sends a license request.
* @param {!MediaKeyMessageEvent} event
Expand Down Expand Up @@ -1440,7 +1461,9 @@ shaka.media.DrmEngine = class {
try {
const req = this.playerInterface_.netEngine.request(
requestType, request, {isPreload: this.isPreload_()});
this.activeRequests_.push(req);
response = await req.promise;
shaka.util.ArrayUtils.remove(this.activeRequests_, req);
} catch (error) {
if (this.destroyer_.destroyed()) {
return;
Expand Down
12 changes: 9 additions & 3 deletions lib/media/preload_manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,13 @@ shaka.media.PreloadManager = class extends shaka.util.FakeEventTarget {
await this.initializeDrmInner_();
this.throwIfDestroyed_();

await this.chooseInitialVariantInner_();
await this.chooseInitialVariantAndPrefetchInner_();
this.throwIfDestroyed_();

// We don't need the drm keys to load completely for the initial variant
// to be chosen, but we won't mark the load as a success until it has
// been loaded. So wait for it here, not inside initializeDrmInner_.
await this.drmEngine_.waitForActiveRequests();
this.throwIfDestroyed_();

this.successPromise_.resolve();
Expand Down Expand Up @@ -610,12 +616,12 @@ shaka.media.PreloadManager = class extends shaka.util.FakeEventTarget {

/**
* Performs a final filtering of the manifest, and chooses the initial
* variant.
* variant. Also prefetches segments.
*
* @return {!Promise}
* @private
*/
async chooseInitialVariantInner_() {
async chooseInitialVariantAndPrefetchInner_() {
goog.asserts.assert(
this.manifest_, 'The manifest should already be parsed.');

Expand Down
4 changes: 4 additions & 0 deletions test/test/util/fake_drm_engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ shaka.test.FakeDrmEngine = class {
this.offlineSessions_.push('session-' + num);
});

/** @type {!jasmine.Spy} */
this.waitForActiveRequests = jasmine.createSpy('waitForActiveRequests');
this.waitForActiveRequests.and.returnValue(Promise.resolve());

/** @type {!jasmine.Spy} */
this.getExpiration = jasmine.createSpy('getExpiration');
this.getExpiration.and.returnValue(Infinity);
Expand Down

0 comments on commit c2242dc

Please sign in to comment.