Skip to content

Commit b1e13fa

Browse files
committed
Fix async tracks callback
PR #2387 introduced a bug. It awaited the track selection callback, but that was done in a loop, the results of which were not awaited. This would cause storage to continue before the complete list of tracks was available. Closes #2383 Change-Id: I18a429cf0f40b829020c520c622ffdae8b12622e
1 parent 39eb6cf commit b1e13fa

File tree

3 files changed

+34
-23
lines changed

3 files changed

+34
-23
lines changed

lib/offline/storage.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ shaka.offline.Storage = class {
356356
throw drmError;
357357
}
358358

359-
this.filterManifest_(manifest, drmEngine);
359+
await this.filterManifest_(manifest, drmEngine);
360360

361361
await muxer.init();
362362
this.ensureNotDestroyed_();
@@ -413,9 +413,10 @@ shaka.offline.Storage = class {
413413
*
414414
* @param {shaka.extern.Manifest} manifest
415415
* @param {!shaka.media.DrmEngine} drmEngine
416+
* @return {!Promise}
416417
* @private
417418
*/
418-
filterManifest_(manifest, drmEngine) {
419+
async filterManifest_(manifest, drmEngine) {
419420
// Filter the manifest based on the restrictions given in the player
420421
// configuration.
421422
const maxHwRes = {width: Infinity, height: Infinity};
@@ -437,7 +438,7 @@ shaka.offline.Storage = class {
437438
// Filter each variant based on what the app says they want to store. The
438439
// app will only be given variants that are compatible with all previous
439440
// post-filtered periods.
440-
shaka.util.ManifestFilter.rollingFilter(manifest, async (period) => {
441+
await shaka.util.ManifestFilter.rollingFilter(manifest, async (period) => {
441442
const StreamUtils = shaka.util.StreamUtils;
442443
const allTracks = [];
443444

lib/util/manifest_filter.js

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,10 @@ shaka.util.ManifestFilter = class {
118118
* are compatible with at least one variant in the previous period.
119119
*
120120
* @param {shaka.extern.Manifest} manifest
121-
* @param {function(shaka.extern.Period)} filter
121+
* @param {function(shaka.extern.Period):!Promise} filter
122+
* @return {!Promise}
122123
*/
123-
static rollingFilter(manifest, filter) {
124-
const ManifestFilter = shaka.util.ManifestFilter;
125-
124+
static async rollingFilter(manifest, filter) {
126125
// Store a reference to the variants so that the next period can easily
127126
// reference them too.
128127
/** @type {shaka.util.ManifestFilter.VariantCodecSummarySet} */
@@ -135,17 +134,19 @@ shaka.util.ManifestFilter = class {
135134
// path across all periods.
136135
if (previous) {
137136
period.variants = period.variants.filter((variant) => {
138-
const summary = new ManifestFilter.VariantCodecSummary(variant);
137+
const summary =
138+
new shaka.util.ManifestFilter.VariantCodecSummary(variant);
139139
return previous.contains(summary);
140140
});
141141
}
142142

143-
filter(period);
143+
// eslint-disable-next-line no-await-in-loop
144+
await filter(period);
144145

145146
// Use the results of filtering this period as the "previous" for the
146147
// next period.
147-
previous =
148-
ManifestFilter.VariantCodecSummarySet.fromVariants(period.variants);
148+
previous = shaka.util.ManifestFilter.VariantCodecSummarySet.fromVariants(
149+
period.variants);
149150
}
150151
}
151152
};

test/offline/storage_integration.js

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -724,32 +724,29 @@ filterDescribe('Storage', storageSupport, () => {
724724

725725
it('only stores chosen tracks', async () => {
726726
// Change storage to only store one track so that it will be easy
727-
// for use to ensure that only the one track was stored.
728-
const selectTrack = (tracks) => {
727+
// for us to ensure that only the one track was stored.
728+
const selectTracks = (tracks) => {
729729
const selected = tracks.filter((t) => t.language == frenchCanadian);
730730
expect(selected.length).toBe(1);
731731
return selected;
732732
};
733733
storage.configure({
734734
offline: {
735-
trackSelectionCallback: selectTrack,
735+
trackSelectionCallback: selectTracks,
736736
},
737737
});
738738

739739
// Stored content should reflect the tracks in the first period, so we
740740
// should only find track there.
741741
const stored = await storage.store(
742742
manifestWithPerStreamBandwidthUri, noMetadata, FakeManifestParser);
743-
expect(stored).toBeTruthy();
744-
expect(stored.tracks).toBeTruthy();
745743
expect(stored.tracks.length).toBe(1);
746744
expect(stored.tracks[0].language).toBe(frenchCanadian);
747745

748746
// Pull the manifest out of storage so that we can ensure that it only
749747
// has one variant.
750748
/** @type {shaka.offline.OfflineUri} */
751749
const uri = shaka.offline.OfflineUri.parse(stored.offlineUri);
752-
expect(uri).toBeTruthy();
753750

754751
/** @type {!shaka.offline.StorageMuxer} */
755752
const muxer = new shaka.offline.StorageMuxer();
@@ -758,28 +755,40 @@ filterDescribe('Storage', storageSupport, () => {
758755
await muxer.init();
759756
const cell = await muxer.getCell(uri.mechanism(), uri.cell());
760757
const manifests = await cell.getManifests([uri.key()]);
761-
expect(manifests).toBeTruthy();
762758
expect(manifests.length).toBe(1);
763759

764760
const manifest = manifests[0];
765-
expect(manifest).toBeTruthy();
766-
expect(manifest.periods).toBeTruthy();
767761
expect(manifest.periods.length).toBe(1);
768762

769763
const period = manifest.periods[0];
770-
expect(period).toBeTruthy();
771-
expect(period.streams).toBeTruthy();
772764
// There should be 2 streams, an audio and a video stream.
773765
expect(period.streams.length).toBe(2);
774766

775767
const audio = period.streams.filter((s) => s.contentType == 'audio')[0];
776-
expect(audio).toBeTruthy();
777768
expect(audio.language).toBe(frenchCanadian);
778769
} finally {
779770
await muxer.destroy();
780771
}
781772
});
782773

774+
it('can choose tracks asynchronously', async () => {
775+
storage.configure({
776+
offline: {
777+
trackSelectionCallback: async (tracks) => {
778+
await Util.delay(0.1);
779+
const selected = tracks.filter((t) => t.language == frenchCanadian);
780+
expect(selected.length).toBe(1);
781+
return selected;
782+
},
783+
},
784+
});
785+
786+
const stored = await storage.store(
787+
manifestWithPerStreamBandwidthUri, noMetadata, FakeManifestParser);
788+
expect(stored.tracks.length).toBe(1);
789+
expect(stored.tracks[0].language).toBe(frenchCanadian);
790+
});
791+
783792
it('stores drm info without license', async () => {
784793
const drmInfo = makeDrmInfo();
785794
const session1 = 'session-1';

0 commit comments

Comments
 (0)