shaka-player 3.3.4 → 3.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/build-and-test.yaml +0 -1
- package/.github/workflows/release-please.yaml +4 -3
- package/.github/workflows/selenium-lab-tests.yaml +0 -1
- package/AUTHORS +1 -0
- package/CHANGELOG.md +38 -0
- package/CONTRIBUTORS +1 -0
- package/README.md +4 -4
- package/build/README.md +2 -2
- package/build/generateTsDefs.py +0 -2
- package/build/test.py +8 -2
- package/build/types/core +0 -1
- package/demo/demo.less +0 -1
- package/demo/main.js +3 -3
- package/dist/controls.css +3 -3
- package/dist/controls.css.map +1 -1
- package/dist/demo.compiled.debug.js +2 -2
- package/dist/demo.compiled.debug.map +2 -2
- package/dist/demo.compiled.js +2 -2
- package/dist/demo.compiled.map +2 -2
- package/dist/demo.css +1 -1
- package/dist/demo.css.map +1 -1
- package/dist/deps.js +2 -3
- package/dist/locales.js +31 -31
- package/dist/shaka-player.compiled.d.ts +1 -2
- package/dist/shaka-player.compiled.debug.d.ts +1 -2
- package/dist/shaka-player.compiled.debug.externs.js +1 -0
- package/dist/shaka-player.compiled.debug.js +153 -151
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +1 -0
- package/dist/shaka-player.compiled.js +845 -843
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +1 -2
- package/dist/shaka-player.ui.debug.d.ts +1 -2
- package/dist/shaka-player.ui.debug.externs.js +1 -0
- package/dist/shaka-player.ui.debug.js +225 -223
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +1 -0
- package/dist/shaka-player.ui.js +953 -951
- package/dist/shaka-player.ui.map +4 -4
- package/karma.conf.js +4 -0
- package/lib/abr/simple_abr_manager.js +2 -1
- package/lib/dash/dash_parser.js +2 -3
- package/lib/hls/hls_parser.js +37 -14
- package/lib/media/drm_engine.js +3 -0
- package/lib/media/media_source_engine.js +7 -1
- package/lib/offline/indexeddb/storage_mechanism.js +4 -2
- package/lib/offline/storage.js +92 -91
- package/lib/player.js +165 -107
- package/lib/util/config_utils.js +25 -0
- package/lib/util/error.js +7 -0
- package/lib/util/manifest_parser_utils.js +1 -1
- package/lib/util/mime_utils.js +62 -6
- package/lib/util/periods.js +5 -4
- package/lib/util/player_configuration.js +9 -14
- package/lib/util/stream_utils.js +5 -2
- package/package.json +2 -2
- package/test/cast/cast_utils_unit.js +1 -0
- package/test/dash/dash_parser_manifest_unit.js +0 -24
- package/test/hls/hls_live_unit.js +86 -7
- package/test/hls/manifest_text_parser_unit.js +19 -0
- package/test/media/media_source_engine_integration.js +1 -0
- package/test/media/media_source_engine_unit.js +4 -4
- package/test/media/streaming_engine_integration.js +2 -0
- package/test/offline/indexeddb_storage_unit.js +1 -1
- package/test/offline/storage_compatibility_unit.js +1 -1
- package/test/player_external.js +7 -1
- package/test/player_integration.js +6 -10
- package/test/player_src_equals_integration.js +81 -83
- package/test/player_unit.js +98 -1
- package/test/test/boot.js +9 -0
- package/test/test/externs/filters.js +4 -0
- package/test/test/util/simple_fakes.js +31 -2
- package/test/util/mime_utils_unit.js +54 -0
- package/test/util/periods_unit.js +79 -0
- package/ui/less/containers.less +1 -1
- package/ui/less/general.less +1 -1
- package/ui/less/range_elements.less +1 -0
- package/.github/pull_request_template.md +0 -10
- package/docs/tutorials/gsoc-ideas-list.md +0 -3
- package/lib/util/mutex.js +0 -52
package/test/player_unit.js
CHANGED
|
@@ -122,7 +122,13 @@ describe('Player', () => {
|
|
|
122
122
|
|
|
123
123
|
player.createDrmEngine = () => drmEngine;
|
|
124
124
|
player.createNetworkingEngine = () => networkingEngine;
|
|
125
|
-
player.createPlayhead = () =>
|
|
125
|
+
player.createPlayhead = (startTime) => {
|
|
126
|
+
const callableSetStartTime =
|
|
127
|
+
shaka.test.Util.spyFunc(playhead.setStartTime);
|
|
128
|
+
callableSetStartTime(startTime);
|
|
129
|
+
playhead.setStartTime.calls.reset();
|
|
130
|
+
return playhead;
|
|
131
|
+
};
|
|
126
132
|
player.createMediaSourceEngine = () => mediaSourceEngine;
|
|
127
133
|
player.createStreamingEngine = () => streamingEngine;
|
|
128
134
|
}
|
|
@@ -154,6 +160,7 @@ describe('Player', () => {
|
|
|
154
160
|
window.MediaSource.isTypeSupported = originalIsTypeSupported;
|
|
155
161
|
shaka.media.ManifestParser.unregisterParserByMime(fakeMimeType);
|
|
156
162
|
navigator.mediaCapabilities.decodingInfo = originalDecodingInfo;
|
|
163
|
+
onError.calls.reset();
|
|
157
164
|
}
|
|
158
165
|
});
|
|
159
166
|
|
|
@@ -2632,6 +2639,51 @@ describe('Player', () => {
|
|
|
2632
2639
|
expect(activeVariant.id).toBe(1);
|
|
2633
2640
|
});
|
|
2634
2641
|
|
|
2642
|
+
// Regression test for https://github.com/shaka-project/shaka-player/issues/4190
|
|
2643
|
+
it('throws only one RESTRICTIONS_CANNOT_BE_MET error', async () => {
|
|
2644
|
+
manifest = shaka.test.ManifestGenerator.generate((manifest) => {
|
|
2645
|
+
manifest.addVariant(0, (variant) => {
|
|
2646
|
+
variant.addVideo(1, (stream) => {
|
|
2647
|
+
stream.keyIds = new Set(['abc']);
|
|
2648
|
+
});
|
|
2649
|
+
});
|
|
2650
|
+
});
|
|
2651
|
+
|
|
2652
|
+
// Check that error is RESTRICTIONS_CANNOT_BE_MET
|
|
2653
|
+
onError.and.callFake((e) => {
|
|
2654
|
+
const error = e.detail;
|
|
2655
|
+
shaka.test.Util.expectToEqualError(
|
|
2656
|
+
error,
|
|
2657
|
+
new shaka.util.Error(
|
|
2658
|
+
shaka.util.Error.Severity.CRITICAL,
|
|
2659
|
+
shaka.util.Error.Category.MANIFEST,
|
|
2660
|
+
shaka.util.Error.Code.RESTRICTIONS_CANNOT_BE_MET, {
|
|
2661
|
+
hasAppRestrictions: false,
|
|
2662
|
+
missingKeys: ['abc'],
|
|
2663
|
+
restrictedKeyStatuses: [],
|
|
2664
|
+
}));
|
|
2665
|
+
});
|
|
2666
|
+
|
|
2667
|
+
await player.load(fakeManifestUri, 0, fakeMimeType);
|
|
2668
|
+
const activeVariant = getActiveVariantTrack();
|
|
2669
|
+
expect(activeVariant.id).toBe(0);
|
|
2670
|
+
|
|
2671
|
+
abrManager.chooseIndex = 0;
|
|
2672
|
+
abrManager.chooseVariant.calls.reset();
|
|
2673
|
+
|
|
2674
|
+
onKeyStatus({'abc': 'output-restricted'});
|
|
2675
|
+
|
|
2676
|
+
// Ensure that RESTRICTIONS_CANNOT_BE_MET is thrown once
|
|
2677
|
+
expect(onError).toHaveBeenCalledTimes(1);
|
|
2678
|
+
|
|
2679
|
+
// It does not call chooseVariant
|
|
2680
|
+
expect(abrManager.chooseVariant).not.toHaveBeenCalled();
|
|
2681
|
+
|
|
2682
|
+
// The first variant is disallowed.
|
|
2683
|
+
expect(manifest.variants[0].id).toBe(0);
|
|
2684
|
+
expect(manifest.variants[0].allowedByKeySystem).toBe(false);
|
|
2685
|
+
});
|
|
2686
|
+
|
|
2635
2687
|
it('doesn\'t switch if the active stream isn\'t restricted', async () => {
|
|
2636
2688
|
manifest = shaka.test.ManifestGenerator.generate((manifest) => {
|
|
2637
2689
|
manifest.addVariant(0, (variant) => {
|
|
@@ -3638,6 +3690,51 @@ describe('Player', () => {
|
|
|
3638
3690
|
});
|
|
3639
3691
|
});
|
|
3640
3692
|
|
|
3693
|
+
describe('config streaming.startAtSegmentBoundary', () => {
|
|
3694
|
+
// Test for https://github.com/shaka-project/shaka-player/issues/4188
|
|
3695
|
+
// In that issue, using streaming.startAtSegmentBoundary in v4.0.0 caused
|
|
3696
|
+
// an exception due to the use of a removed method.
|
|
3697
|
+
it('adjusts start time', async () => {
|
|
3698
|
+
player.configure('streaming.startAtSegmentBoundary', true);
|
|
3699
|
+
|
|
3700
|
+
// In order to adjust the start time to a segment boundary, we need
|
|
3701
|
+
// segment descriptions in the segment index. So create a non-default
|
|
3702
|
+
// fake manifest.
|
|
3703
|
+
const timeline = new shaka.media.PresentationTimeline(300, 0);
|
|
3704
|
+
timeline.setStatic(true);
|
|
3705
|
+
// This duration is used by useSegmentTemplate below to decide how many
|
|
3706
|
+
// references to generate.
|
|
3707
|
+
timeline.setDuration(300);
|
|
3708
|
+
manifest = shaka.test.ManifestGenerator.generate((manifest) => {
|
|
3709
|
+
manifest.presentationTimeline = timeline;
|
|
3710
|
+
manifest.addVariant(0, (variant) => {
|
|
3711
|
+
variant.addVideo(1, (stream) => {
|
|
3712
|
+
stream.useSegmentTemplate(
|
|
3713
|
+
'$Number$.mp4', /* segmentDuration= */ 10);
|
|
3714
|
+
});
|
|
3715
|
+
});
|
|
3716
|
+
});
|
|
3717
|
+
|
|
3718
|
+
await player.load(fakeManifestUri, 12, fakeMimeType);
|
|
3719
|
+
|
|
3720
|
+
expect(playhead.setStartTime).toHaveBeenCalledWith(10);
|
|
3721
|
+
});
|
|
3722
|
+
|
|
3723
|
+
it('does not fail with no segments', async () => {
|
|
3724
|
+
player.configure('streaming.startAtSegmentBoundary', true);
|
|
3725
|
+
|
|
3726
|
+
// Without useSegmentTemplate in the fake manifest, the call to
|
|
3727
|
+
// getIteratorForTime() in Player produces a null iterator. Using the
|
|
3728
|
+
// default fake manifest should cover that case. But just to make sure,
|
|
3729
|
+
// verify that we have no segments before calling load().
|
|
3730
|
+
const variant = manifest.variants[0];
|
|
3731
|
+
expect(variant.video.segmentIndex.getIteratorForTime(0)).toBeNull();
|
|
3732
|
+
expect(variant.audio.segmentIndex.getIteratorForTime(0)).toBeNull();
|
|
3733
|
+
|
|
3734
|
+
await player.load(fakeManifestUri, 0, fakeMimeType);
|
|
3735
|
+
});
|
|
3736
|
+
});
|
|
3737
|
+
|
|
3641
3738
|
/**
|
|
3642
3739
|
* Gets the currently active variant track.
|
|
3643
3740
|
* @return {shaka.extern.Track}
|
package/test/test/boot.js
CHANGED
|
@@ -242,6 +242,15 @@ window.xfilterDescribe = (describeName, cond, describeBody) => {
|
|
|
242
242
|
window['describe'] = oldDescribe;
|
|
243
243
|
};
|
|
244
244
|
|
|
245
|
+
/**
|
|
246
|
+
* A very short alias for filtering offline integration tests.
|
|
247
|
+
*
|
|
248
|
+
* @return {boolean}
|
|
249
|
+
*/
|
|
250
|
+
window.offlineSupported = () => {
|
|
251
|
+
return shaka.offline.StorageMuxer.support();
|
|
252
|
+
};
|
|
253
|
+
|
|
245
254
|
/**
|
|
246
255
|
* Load node modules used in testing and install them into window.
|
|
247
256
|
* @return {!Promise}
|
|
@@ -152,9 +152,27 @@ shaka.test.FakeVideo = class {
|
|
|
152
152
|
constructor(currentTime) {
|
|
153
153
|
/** @const {!Object.<string, !Function>} */
|
|
154
154
|
this.on = {}; // event listeners
|
|
155
|
+
|
|
155
156
|
/** @type {!Array.<!TextTrack>} */
|
|
156
157
|
this.textTracks = [];
|
|
157
158
|
|
|
159
|
+
// In a real video element, textTracks is an event target.
|
|
160
|
+
// Since Player listens to events on textTracks, we need to fake that
|
|
161
|
+
// interface.
|
|
162
|
+
this.textTracksEventTarget = new shaka.util.FakeEventTarget();
|
|
163
|
+
this.textTracks.addEventListener =
|
|
164
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
165
|
+
this.textTracksEventTarget.addEventListener.bind(
|
|
166
|
+
this.textTracksEventTarget);
|
|
167
|
+
this.textTracks.removeEventListener =
|
|
168
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
169
|
+
this.textTracksEventTarget.removeEventListener.bind(
|
|
170
|
+
this.textTracksEventTarget);
|
|
171
|
+
this.textTracks.dispatchEvent =
|
|
172
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
173
|
+
this.textTracksEventTarget.dispatchEvent.bind(
|
|
174
|
+
this.textTracksEventTarget);
|
|
175
|
+
|
|
158
176
|
this.currentTime = currentTime || 0;
|
|
159
177
|
this.readyState = 0;
|
|
160
178
|
this.playbackRate = 1;
|
|
@@ -173,6 +191,10 @@ shaka.test.FakeVideo = class {
|
|
|
173
191
|
jasmine.createSpy('addTextTrack').and.callFake((kind, id) => {
|
|
174
192
|
const track = new shaka.test.FakeTextTrack();
|
|
175
193
|
this.textTracks.push(track);
|
|
194
|
+
|
|
195
|
+
const trackEvent = new shaka.util.FakeEvent('addtrack', {track});
|
|
196
|
+
this.textTracksEventTarget.dispatchEvent(trackEvent);
|
|
197
|
+
|
|
176
198
|
return track;
|
|
177
199
|
});
|
|
178
200
|
|
|
@@ -308,11 +330,18 @@ shaka.test.FakePlayhead = class {
|
|
|
308
330
|
/** @type {!jasmine.Spy} */
|
|
309
331
|
this.setRebufferingGoal = jasmine.createSpy('setRebufferingGoal');
|
|
310
332
|
|
|
333
|
+
/** @private {number} */
|
|
334
|
+
this.startTime_ = 0;
|
|
335
|
+
|
|
311
336
|
/** @type {!jasmine.Spy} */
|
|
312
|
-
this.setStartTime = jasmine.createSpy('setStartTime')
|
|
337
|
+
this.setStartTime = jasmine.createSpy('setStartTime')
|
|
338
|
+
.and.callFake((value) => {
|
|
339
|
+
this.startTime_ = value;
|
|
340
|
+
});
|
|
313
341
|
|
|
314
342
|
/** @type {!jasmine.Spy} */
|
|
315
|
-
this.getTime = jasmine.createSpy('getTime')
|
|
343
|
+
this.getTime = jasmine.createSpy('getTime')
|
|
344
|
+
.and.callFake(() => this.startTime_);
|
|
316
345
|
|
|
317
346
|
/** @type {!jasmine.Spy} */
|
|
318
347
|
this.setBuffering = jasmine.createSpy('setBuffering');
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/*! @license
|
|
2
|
+
* Shaka Player
|
|
3
|
+
* Copyright 2016 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
describe('MimeUtils', () => {
|
|
8
|
+
const getNormalizedCodec = (codecs) =>
|
|
9
|
+
shaka.util.MimeUtils.getNormalizedCodec(codecs);
|
|
10
|
+
|
|
11
|
+
it('normalizes codecs', () => {
|
|
12
|
+
expect(getNormalizedCodec('mp4a.66')).toBe('aac');
|
|
13
|
+
expect(getNormalizedCodec('mp4a.67')).toBe('aac');
|
|
14
|
+
expect(getNormalizedCodec('mp4a.68')).toBe('aac');
|
|
15
|
+
|
|
16
|
+
expect(getNormalizedCodec('mp3')).toBe('mp3');
|
|
17
|
+
expect(getNormalizedCodec('mp4a.69')).toBe('mp3');
|
|
18
|
+
expect(getNormalizedCodec('mp4a.6B')).toBe('mp3');
|
|
19
|
+
expect(getNormalizedCodec('mp4a.6b')).toBe('mp3');
|
|
20
|
+
|
|
21
|
+
expect(getNormalizedCodec('mp4a.40.2')).toBe('aac');
|
|
22
|
+
expect(getNormalizedCodec('mp4a.40.02')).toBe('aac');
|
|
23
|
+
expect(getNormalizedCodec('mp4a.40.5')).toBe('aac');
|
|
24
|
+
expect(getNormalizedCodec('mp4a.40.05')).toBe('aac');
|
|
25
|
+
expect(getNormalizedCodec('mp4a.40.29')).toBe('aac');
|
|
26
|
+
expect(getNormalizedCodec('mp4a.40.42')).toBe('aac');
|
|
27
|
+
|
|
28
|
+
expect(getNormalizedCodec('ac-3')).toBe('ac-3');
|
|
29
|
+
expect(getNormalizedCodec('mp4a.a5')).toBe('ac-3');
|
|
30
|
+
expect(getNormalizedCodec('mp4a.A5')).toBe('ac-3');
|
|
31
|
+
|
|
32
|
+
expect(getNormalizedCodec('ec-3')).toBe('ec-3');
|
|
33
|
+
expect(getNormalizedCodec('mp4a.a6')).toBe('ec-3');
|
|
34
|
+
expect(getNormalizedCodec('mp4a.A6')).toBe('ec-3');
|
|
35
|
+
|
|
36
|
+
expect(getNormalizedCodec('dtsc')).toBe('dtsc');
|
|
37
|
+
expect(getNormalizedCodec('mp4a.a9')).toBe('dtsc');
|
|
38
|
+
|
|
39
|
+
expect(getNormalizedCodec('dtsx')).toBe('dtsx');
|
|
40
|
+
expect(getNormalizedCodec('mp4a.b2')).toBe('dtsx');
|
|
41
|
+
|
|
42
|
+
expect(getNormalizedCodec('vp8')).toBe('vp8');
|
|
43
|
+
expect(getNormalizedCodec('vp8.0')).toBe('vp8');
|
|
44
|
+
|
|
45
|
+
expect(getNormalizedCodec('avc1')).toBe('avc');
|
|
46
|
+
expect(getNormalizedCodec('avc3')).toBe('avc');
|
|
47
|
+
|
|
48
|
+
expect(getNormalizedCodec('hvc1')).toBe('hevc');
|
|
49
|
+
expect(getNormalizedCodec('hev1')).toBe('hevc');
|
|
50
|
+
|
|
51
|
+
expect(getNormalizedCodec('dvh1.05')).toBe('dovi');
|
|
52
|
+
expect(getNormalizedCodec('dvhe.05')).toBe('dovi');
|
|
53
|
+
});
|
|
54
|
+
});
|
|
@@ -996,6 +996,85 @@ describe('PeriodCombiner', () => {
|
|
|
996
996
|
expect(audio2.originalId).toBe('2,4');
|
|
997
997
|
});
|
|
998
998
|
|
|
999
|
+
it('Matches streams with related codecs', async () => {
|
|
1000
|
+
const stream1 = makeVideoStream(1080);
|
|
1001
|
+
stream1.originalId = '1';
|
|
1002
|
+
stream1.bandwidth = 120000;
|
|
1003
|
+
stream1.codecs = 'hvc1.1.4.L126.B0';
|
|
1004
|
+
|
|
1005
|
+
const stream2 = makeVideoStream(1080);
|
|
1006
|
+
stream2.originalId = '2';
|
|
1007
|
+
stream2.bandwidth = 120000;
|
|
1008
|
+
stream2.codecs = 'hev1.2.4.L123.B0';
|
|
1009
|
+
|
|
1010
|
+
const stream3 = makeVideoStream(1080);
|
|
1011
|
+
stream3.originalId = '3';
|
|
1012
|
+
stream3.bandwidth = 120000;
|
|
1013
|
+
stream3.codecs = 'dvhe.05.01';
|
|
1014
|
+
|
|
1015
|
+
const stream4 = makeVideoStream(1080);
|
|
1016
|
+
stream4.originalId = '4';
|
|
1017
|
+
stream4.bandwidth = 120000;
|
|
1018
|
+
stream4.codecs = 'dvh1.05.01';
|
|
1019
|
+
|
|
1020
|
+
const stream5 = makeVideoStream(1080);
|
|
1021
|
+
stream5.originalId = '5';
|
|
1022
|
+
stream5.bandwidth = 120000;
|
|
1023
|
+
stream5.codecs = 'avc1.42001f';
|
|
1024
|
+
|
|
1025
|
+
const stream6 = makeVideoStream(1080);
|
|
1026
|
+
stream6.originalId = '6';
|
|
1027
|
+
stream6.bandwidth = 120000;
|
|
1028
|
+
stream6.codecs = 'avc3.42001f';
|
|
1029
|
+
|
|
1030
|
+
const stream7 = makeVideoStream(1080);
|
|
1031
|
+
stream7.originalId = '7';
|
|
1032
|
+
stream7.bandwidth = 120000;
|
|
1033
|
+
stream7.codecs = 'vp09.00.10.08';
|
|
1034
|
+
|
|
1035
|
+
const stream8 = makeVideoStream(1080);
|
|
1036
|
+
stream8.originalId = '8';
|
|
1037
|
+
stream8.bandwidth = 120000;
|
|
1038
|
+
stream8.codecs = 'vp09.01.20.08.01';
|
|
1039
|
+
|
|
1040
|
+
/** @type {!Array.<shaka.util.PeriodCombiner.Period>} */
|
|
1041
|
+
const periods = [
|
|
1042
|
+
{
|
|
1043
|
+
id: '0',
|
|
1044
|
+
videoStreams: [
|
|
1045
|
+
stream1, stream3, stream5, stream7,
|
|
1046
|
+
],
|
|
1047
|
+
audioStreams: [],
|
|
1048
|
+
textStreams: [],
|
|
1049
|
+
imageStreams: [],
|
|
1050
|
+
},
|
|
1051
|
+
{
|
|
1052
|
+
id: '1',
|
|
1053
|
+
videoStreams: [
|
|
1054
|
+
stream2, stream4, stream6, stream8,
|
|
1055
|
+
],
|
|
1056
|
+
audioStreams: [],
|
|
1057
|
+
textStreams: [],
|
|
1058
|
+
imageStreams: [],
|
|
1059
|
+
},
|
|
1060
|
+
];
|
|
1061
|
+
|
|
1062
|
+
await combiner.combinePeriods(periods, /* isDynamic= */ true);
|
|
1063
|
+
const variants = combiner.getVariants();
|
|
1064
|
+
expect(variants.length).toBe(4);
|
|
1065
|
+
// We can use the originalId field to see what each track is composed of.
|
|
1066
|
+
const video1 = variants[0].video;
|
|
1067
|
+
expect(video1.originalId).toBe('1,2');
|
|
1068
|
+
|
|
1069
|
+
const video2 = variants[1].video;
|
|
1070
|
+
expect(video2.originalId).toBe('3,4');
|
|
1071
|
+
|
|
1072
|
+
const video3 = variants[2].video;
|
|
1073
|
+
expect(video3.originalId).toBe('5,6');
|
|
1074
|
+
|
|
1075
|
+
const video4 = variants[3].video;
|
|
1076
|
+
expect(video4.originalId).toBe('7,8');
|
|
1077
|
+
});
|
|
999
1078
|
|
|
1000
1079
|
it('Matches streams with most roles in common', async () => {
|
|
1001
1080
|
const makeAudioStreamWithRoles = (roles) => {
|
package/ui/less/containers.less
CHANGED
|
@@ -161,7 +161,7 @@
|
|
|
161
161
|
/* Consistent margins (external) and padding (internal) between controls. */
|
|
162
162
|
.bottom-panels-elements-margin();
|
|
163
163
|
|
|
164
|
-
padding: 0;
|
|
164
|
+
padding: 0 5px;
|
|
165
165
|
|
|
166
166
|
/* Transparent backgrounds, no borders, and a pointer when you mouse over
|
|
167
167
|
* them. */
|
package/ui/less/general.less
CHANGED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
Please remember to:
|
|
3
|
-
|
|
4
|
-
1. Use Conventional Commits syntax (fix: ..., feat: ..., etc.) in commits and
|
|
5
|
-
PR title (https://www.conventionalcommits.org/)
|
|
6
|
-
2. Tag any related or fixed issues ("Issue #123", "Closes #420")
|
|
7
|
-
3. Sign the Google CLA if you haven't (https://cla.developers.google.com)
|
|
8
|
-
|
|
9
|
-
You may delete this comment from the PR description.
|
|
10
|
-
-->
|
package/lib/util/mutex.js
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
/*! @license
|
|
2
|
-
* Shaka Player
|
|
3
|
-
* Copyright 2016 Google LLC
|
|
4
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
goog.provide('shaka.util.Mutex');
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* @summary A simple mutex.
|
|
12
|
-
*/
|
|
13
|
-
shaka.util.Mutex = class {
|
|
14
|
-
/** Creates the mutex. */
|
|
15
|
-
constructor() {
|
|
16
|
-
/** @private {!Array.<function()>} */
|
|
17
|
-
this.waiting_ = [];
|
|
18
|
-
|
|
19
|
-
/** @private {number} */
|
|
20
|
-
this.nextMutexId_ = 0;
|
|
21
|
-
|
|
22
|
-
/** @private {number} */
|
|
23
|
-
this.acquiredMutexId_ = 0;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/** @return {!Promise.<number>} mutexId */
|
|
27
|
-
async acquire() {
|
|
28
|
-
const mutexId = ++this.nextMutexId_;
|
|
29
|
-
if (!this.acquiredMutexId_) {
|
|
30
|
-
this.acquiredMutexId_ = mutexId;
|
|
31
|
-
} else {
|
|
32
|
-
await (new Promise((resolve, reject) => {
|
|
33
|
-
this.waiting_.push(() => {
|
|
34
|
-
this.acquiredMutexId_ = mutexId;
|
|
35
|
-
resolve();
|
|
36
|
-
});
|
|
37
|
-
}));
|
|
38
|
-
}
|
|
39
|
-
return mutexId;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/** @param {number} mutexId */
|
|
43
|
-
release(mutexId) {
|
|
44
|
-
if (mutexId == this.acquiredMutexId_) {
|
|
45
|
-
this.acquiredMutexId_ = 0;
|
|
46
|
-
if (this.waiting_.length > 0) {
|
|
47
|
-
const callback = this.waiting_.shift();
|
|
48
|
-
callback();
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
};
|