shaka-player 4.3.8 → 4.3.9
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/ISSUE_TEMPLATE/bug_report.md +11 -0
- package/.github/workflows/build-and-test.yaml +8 -0
- package/.github/workflows/selenium-lab-tests.yaml +3 -2
- package/.github/workflows/update-issues.yaml +1 -0
- package/CHANGELOG.md +19 -0
- package/dist/deps.js +1 -1
- package/dist/locales.js +30 -30
- package/dist/shaka-player.compiled.d.ts +2 -2
- package/dist/shaka-player.compiled.debug.d.ts +2 -2
- package/dist/shaka-player.compiled.debug.js +50 -48
- package/dist/shaka-player.compiled.debug.map +3 -3
- package/dist/shaka-player.compiled.js +385 -385
- package/dist/shaka-player.compiled.map +2 -2
- package/dist/shaka-player.ui.d.ts +2 -2
- package/dist/shaka-player.ui.debug.d.ts +2 -2
- package/dist/shaka-player.ui.debug.js +54 -52
- package/dist/shaka-player.ui.debug.map +3 -3
- package/dist/shaka-player.ui.js +400 -399
- package/dist/shaka-player.ui.map +3 -3
- package/docs/tutorials/selenium-grid-config.md +60 -8
- package/externs/shaka/manifest.js +5 -1
- package/externs/shaka/offline.js +5 -1
- package/karma.conf.js +50 -7
- package/lib/abr/simple_abr_manager.js +5 -5
- package/lib/dash/dash_parser.js +1 -0
- package/lib/hls/hls_parser.js +1 -0
- package/lib/media/media_source_engine.js +6 -5
- package/lib/media/streaming_engine.js +2 -2
- package/lib/offline/indexeddb/v1_storage_cell.js +1 -0
- package/lib/offline/indexeddb/v2_storage_cell.js +1 -0
- package/lib/offline/manifest_converter.js +1 -0
- package/lib/offline/storage.js +1 -0
- package/lib/player.js +9 -5
- package/lib/polyfill/orientation.js +34 -7
- package/lib/text/vtt_text_parser.js +1 -0
- package/lib/util/manifest_parser_utils.js +4 -2
- package/lib/util/periods.js +2 -0
- package/lib/util/platform.js +14 -0
- package/lib/util/stream_utils.js +69 -26
- package/package.json +2 -2
- package/test/cast/cast_utils_unit.js +4 -1
- package/test/hls/hls_parser_unit.js +72 -0
- package/test/media/adaptation_set_unit.js +1 -0
- package/test/media/drm_engine_integration.js +2 -2
- package/test/media/media_source_engine_unit.js +1 -1
- package/test/media/segment_index_unit.js +3 -3
- package/test/media/streaming_engine_integration.js +14 -11
- package/test/offline/manifest_convert_unit.js +5 -0
- package/test/offline/offline_integration.js +6 -3
- package/test/player_external.js +19 -16
- package/test/player_integration.js +35 -48
- package/test/player_src_equals_integration.js +9 -5
- package/test/test/util/fake_demo_main.js +7 -3
- package/test/test/util/layout_tests.js +2 -2
- package/test/test/util/manifest_generator.js +2 -0
- package/test/test/util/offline_utils.js +1 -0
- package/test/test/util/streaming_engine_util.js +3 -0
- package/test/test/util/ui_utils.js +9 -2
- package/test/test/util/util.js +6 -27
- package/test/test/util/waiter.js +73 -3
- package/test/ui/ad_ui_unit.js +9 -9
- package/test/util/stream_utils_unit.js +46 -0
- package/ui/range_element.js +5 -0
|
@@ -34,6 +34,9 @@ describe('Player', () => {
|
|
|
34
34
|
await shaka.test.TestScheme.createManifests(compiledShaka, '_compiled');
|
|
35
35
|
player = new compiledShaka.Player(video);
|
|
36
36
|
|
|
37
|
+
// Disable stall detection, which can interfere with playback tests.
|
|
38
|
+
player.configure('streaming.stallEnabled', false);
|
|
39
|
+
|
|
37
40
|
// Grab event manager from the uncompiled library:
|
|
38
41
|
eventManager = new shaka.util.EventManager();
|
|
39
42
|
waiter = new shaka.test.Waiter(eventManager);
|
|
@@ -81,11 +84,15 @@ describe('Player', () => {
|
|
|
81
84
|
// Unlike the other tests in this file, this uses an uncompiled build of
|
|
82
85
|
// Shaka, so that we don't need to expose shaka.util.Timer.activeTimers.
|
|
83
86
|
player = new shaka.Player(video);
|
|
87
|
+
|
|
88
|
+
// Disable stall detection, which can interfere with playback tests.
|
|
89
|
+
player.configure('streaming.stallEnabled', false);
|
|
90
|
+
|
|
84
91
|
waiter.setPlayer(player);
|
|
85
92
|
|
|
86
93
|
// Play the video for a little while.
|
|
87
94
|
await player.load('test:sintel');
|
|
88
|
-
video.play();
|
|
95
|
+
await video.play();
|
|
89
96
|
await waiter.waitUntilPlayheadReachesOrFailOnTimeout(video, 1, 10);
|
|
90
97
|
|
|
91
98
|
// Destroy the player.
|
|
@@ -127,7 +134,7 @@ describe('Player', () => {
|
|
|
127
134
|
}
|
|
128
135
|
});
|
|
129
136
|
await player.load('test:sintel_compiled');
|
|
130
|
-
video.play();
|
|
137
|
+
await video.play();
|
|
131
138
|
await waiter.waitUntilPlayheadReachesOrFailOnTimeout(video, 25, 30);
|
|
132
139
|
expect(results).toEqual(expected);
|
|
133
140
|
});
|
|
@@ -139,7 +146,7 @@ describe('Player', () => {
|
|
|
139
146
|
// This is tested more in player_unit.js. This is here to test the public
|
|
140
147
|
// API and to check for renaming.
|
|
141
148
|
await player.load('test:sintel_compiled');
|
|
142
|
-
video.play();
|
|
149
|
+
await video.play();
|
|
143
150
|
await waiter.waitUntilPlayheadReachesOrFailOnTimeout(video, 1, 10);
|
|
144
151
|
|
|
145
152
|
const stats = player.getStats();
|
|
@@ -210,7 +217,7 @@ describe('Player', () => {
|
|
|
210
217
|
|
|
211
218
|
it('does not cause cues to be null', async () => {
|
|
212
219
|
await player.load('test:sintel_compiled');
|
|
213
|
-
video.play();
|
|
220
|
+
await video.play();
|
|
214
221
|
await waiter.waitUntilPlayheadReachesOrFailOnTimeout(video, 1, 10);
|
|
215
222
|
|
|
216
223
|
// This TextTrack was created as part of load() when we set up the
|
|
@@ -249,7 +256,7 @@ describe('Player', () => {
|
|
|
249
256
|
await player.load('test:sintel_realistic_compiled');
|
|
250
257
|
|
|
251
258
|
// Play until a time at which the external cues would be on screen.
|
|
252
|
-
video.play();
|
|
259
|
+
await video.play();
|
|
253
260
|
await waiter.waitUntilPlayheadReachesOrFailOnTimeout(video, 4, 20);
|
|
254
261
|
|
|
255
262
|
expect(player.isTextTrackVisible()).toBe(true);
|
|
@@ -281,7 +288,7 @@ describe('Player', () => {
|
|
|
281
288
|
await waiter.waitForEvent(player, 'texttrackvisibility');
|
|
282
289
|
|
|
283
290
|
// Play until a time at which the external cues would be on screen.
|
|
284
|
-
video.play();
|
|
291
|
+
await video.play();
|
|
285
292
|
await waiter.waitUntilPlayheadReachesOrFailOnTimeout(video, 4, 20);
|
|
286
293
|
|
|
287
294
|
expect(player.isTextTrackVisible()).toBe(true);
|
|
@@ -352,7 +359,7 @@ describe('Player', () => {
|
|
|
352
359
|
player.setTextTrackVisibility(true);
|
|
353
360
|
player.selectTextLanguage('fr');
|
|
354
361
|
video.currentTime = 5;
|
|
355
|
-
video.play();
|
|
362
|
+
await video.play();
|
|
356
363
|
await waiter.waitForMovementOrFailOnTimeout(video, 10);
|
|
357
364
|
|
|
358
365
|
expect(video.textTracks[0].activeCues.length).toBe(1);
|
|
@@ -544,7 +551,7 @@ describe('Player', () => {
|
|
|
544
551
|
|
|
545
552
|
it('at higher playback rates', async () => {
|
|
546
553
|
await player.load('test:sintel_compiled');
|
|
547
|
-
video.play();
|
|
554
|
+
await video.play();
|
|
548
555
|
await waiter.waitUntilPlayheadReachesOrFailOnTimeout(video, 1, 10);
|
|
549
556
|
|
|
550
557
|
// Enabling trick play should change our playback rate to the same rate.
|
|
@@ -560,14 +567,12 @@ describe('Player', () => {
|
|
|
560
567
|
});
|
|
561
568
|
|
|
562
569
|
it('in sequence mode', async () => {
|
|
563
|
-
|
|
564
|
-
player = new compiledShaka.Player(video);
|
|
565
|
-
await player.load('test:sintel_sequence_compiled', 0, testSchemeMimeType);
|
|
570
|
+
await player.load('test:sintel_sequence_compiled');
|
|
566
571
|
expect(player.getManifest().sequenceMode).toBe(true);
|
|
567
572
|
|
|
568
573
|
// Ensure the video plays.
|
|
569
|
-
video.play();
|
|
570
|
-
await waiter.
|
|
574
|
+
await video.play();
|
|
575
|
+
await waiter.timeoutAfter(20).waitUntilPlayheadReaches(video, 5);
|
|
571
576
|
|
|
572
577
|
// Seek the video, and see if it can continue playing from that point.
|
|
573
578
|
video.currentTime = 20;
|
|
@@ -586,9 +591,8 @@ describe('Player', () => {
|
|
|
586
591
|
// even if one is not specified in load().
|
|
587
592
|
it('immediately after construction with MIME type', async () => {
|
|
588
593
|
const testSchemeMimeType = 'application/x-test-manifest';
|
|
589
|
-
player = new compiledShaka.Player(video);
|
|
590
594
|
await player.load('test:sintel_compiled', 0, testSchemeMimeType);
|
|
591
|
-
video.play();
|
|
595
|
+
await video.play();
|
|
592
596
|
await waiter.waitUntilPlayheadReachesOrFailOnTimeout(video, 1, 10);
|
|
593
597
|
});
|
|
594
598
|
|
|
@@ -627,7 +631,7 @@ describe('Player', () => {
|
|
|
627
631
|
// Regression test for https://github.com/shaka-project/shaka-player/issues/1187
|
|
628
632
|
it('does not throw on destroy', async () => {
|
|
629
633
|
await player.load('test:sintel_compiled');
|
|
630
|
-
video.play();
|
|
634
|
+
await video.play();
|
|
631
635
|
await waiter.waitUntilPlayheadReachesOrFailOnTimeout(video, 1, 10);
|
|
632
636
|
await player.unload();
|
|
633
637
|
// Before we fixed #1187, the call to destroy() on textDisplayer was
|
|
@@ -873,7 +877,7 @@ describe('Player', () => {
|
|
|
873
877
|
player.configure('streaming.observeQualityChanges', true);
|
|
874
878
|
|
|
875
879
|
await player.load('test:sintel_compiled');
|
|
876
|
-
video.play();
|
|
880
|
+
await video.play();
|
|
877
881
|
|
|
878
882
|
// Wait for the video to start playback. If it takes longer than 10
|
|
879
883
|
// seconds, fail the test.
|
|
@@ -887,7 +891,7 @@ describe('Player', () => {
|
|
|
887
891
|
player.configure('streaming.observeQualityChanges', false);
|
|
888
892
|
|
|
889
893
|
await player.load('test:sintel_compiled');
|
|
890
|
-
video.play();
|
|
894
|
+
await video.play();
|
|
891
895
|
|
|
892
896
|
// Wait for the video to start playback. If it takes longer than 10
|
|
893
897
|
// seconds, fail the test.
|
|
@@ -916,7 +920,7 @@ describe('Player', () => {
|
|
|
916
920
|
|
|
917
921
|
// Play the stream.
|
|
918
922
|
await player.load('/base/test/test/assets/3675/dash_0.mpd');
|
|
919
|
-
video.play();
|
|
923
|
+
await video.play();
|
|
920
924
|
|
|
921
925
|
// Wait for the stream to be over.
|
|
922
926
|
eventManager.listen(player, 'error', Util.spyFunc(onErrorSpy));
|
|
@@ -1004,22 +1008,22 @@ describe('Player', () => {
|
|
|
1004
1008
|
|
|
1005
1009
|
await player.load('test:sintel_long_compiled');
|
|
1006
1010
|
video.pause();
|
|
1007
|
-
await waitUntilBuffered(10);
|
|
1011
|
+
await waiter.waitUntilBuffered(video, 10);
|
|
1008
1012
|
|
|
1009
1013
|
player.configure('streaming.bufferingGoal', 30);
|
|
1010
|
-
await waitUntilBuffered(30);
|
|
1014
|
+
await waiter.waitUntilBuffered(video, 30);
|
|
1011
1015
|
|
|
1012
1016
|
player.configure('streaming.bufferingGoal', 60);
|
|
1013
|
-
await waitUntilBuffered(60);
|
|
1014
|
-
await Util.delay(
|
|
1017
|
+
await waiter.waitUntilBuffered(video, 60);
|
|
1018
|
+
await Util.delay(1);
|
|
1015
1019
|
expect(getBufferedAhead()).toBeLessThan(70); // 60 + segment_size
|
|
1016
1020
|
|
|
1017
1021
|
// We don't remove buffered content ahead of the playhead, so seek to
|
|
1018
1022
|
// clear the buffer.
|
|
1019
1023
|
player.configure('streaming.bufferingGoal', 10);
|
|
1020
1024
|
video.currentTime = 120;
|
|
1021
|
-
await waitUntilBuffered(10);
|
|
1022
|
-
await Util.delay(
|
|
1025
|
+
await waiter.waitUntilBuffered(video, 10);
|
|
1026
|
+
await Util.delay(1);
|
|
1023
1027
|
expect(getBufferedAhead()).toBeLessThan(20); // 10 + segment_size
|
|
1024
1028
|
});
|
|
1025
1029
|
|
|
@@ -1029,20 +1033,22 @@ describe('Player', () => {
|
|
|
1029
1033
|
|
|
1030
1034
|
await player.load('test:sintel_long_compiled');
|
|
1031
1035
|
video.pause();
|
|
1032
|
-
await waitUntilBuffered(30);
|
|
1036
|
+
await waiter.waitUntilBuffered(video, 30);
|
|
1033
1037
|
video.currentTime = 20;
|
|
1034
|
-
await waitUntilBuffered(30);
|
|
1038
|
+
await waiter.waitUntilBuffered(video, 30);
|
|
1035
1039
|
|
|
1036
1040
|
expect(getBufferedBehind()).toBe(20); // Buffered to start still.
|
|
1037
1041
|
video.currentTime = 50;
|
|
1038
|
-
await waitUntilBuffered(30);
|
|
1042
|
+
await waiter.waitUntilBuffered(video, 30);
|
|
1043
|
+
await Util.delay(1);
|
|
1039
1044
|
expect(getBufferedBehind()).toBeLessThan(40); // 30 + segment_size
|
|
1040
1045
|
|
|
1041
1046
|
player.configure('streaming.bufferBehind', 10);
|
|
1042
1047
|
// We only evict content when we append a segment, so increase the
|
|
1043
1048
|
// buffering goal so we append another segment.
|
|
1044
1049
|
player.configure('streaming.bufferingGoal', 40);
|
|
1045
|
-
await waitUntilBuffered(40);
|
|
1050
|
+
await waiter.waitUntilBuffered(video, 40);
|
|
1051
|
+
await Util.delay(1);
|
|
1046
1052
|
expect(getBufferedBehind()).toBeLessThanOrEqual(10);
|
|
1047
1053
|
});
|
|
1048
1054
|
|
|
@@ -1061,25 +1067,6 @@ describe('Player', () => {
|
|
|
1061
1067
|
}
|
|
1062
1068
|
return video.currentTime - start;
|
|
1063
1069
|
}
|
|
1064
|
-
|
|
1065
|
-
async function waitUntilBuffered(amount) {
|
|
1066
|
-
for (let i = 0; i < 50; i++) {
|
|
1067
|
-
// We buffer from an internal segment, so this shouldn't take long to
|
|
1068
|
-
// buffer.
|
|
1069
|
-
await Util.delay(0.1); // eslint-disable-line no-await-in-loop
|
|
1070
|
-
if (getBufferedAhead() >= amount) {
|
|
1071
|
-
return;
|
|
1072
|
-
}
|
|
1073
|
-
}
|
|
1074
|
-
|
|
1075
|
-
const ranges =
|
|
1076
|
-
shaka.media.TimeRangesUtils.getBufferedInfo(video.buffered);
|
|
1077
|
-
const currentTime = video.currentTime;
|
|
1078
|
-
const target = currentTime + amount;
|
|
1079
|
-
|
|
1080
|
-
throw new Error('Timeout waiting to buffer! ' +
|
|
1081
|
-
JSON.stringify({ranges, currentTime, target}));
|
|
1082
|
-
}
|
|
1083
1070
|
}); // describe('buffering')
|
|
1084
1071
|
|
|
1085
1072
|
describe('configuration', () => {
|
|
@@ -27,6 +27,10 @@ describe('Player Src Equals', () => {
|
|
|
27
27
|
beforeEach(() => {
|
|
28
28
|
player = new shaka.Player();
|
|
29
29
|
player.addEventListener('error', fail);
|
|
30
|
+
|
|
31
|
+
// Disable stall detection, which can interfere with playback tests.
|
|
32
|
+
player.configure('streaming.stallEnabled', false);
|
|
33
|
+
|
|
30
34
|
eventManager = new shaka.util.EventManager();
|
|
31
35
|
waiter = new shaka.test.Waiter(eventManager);
|
|
32
36
|
});
|
|
@@ -101,7 +105,7 @@ describe('Player Src Equals', () => {
|
|
|
101
105
|
expect(video.duration).not.toBeCloseTo(0);
|
|
102
106
|
|
|
103
107
|
// Start playback and wait for the playhead to move.
|
|
104
|
-
video.play();
|
|
108
|
+
await video.play();
|
|
105
109
|
await waiter.waitForMovementOrFailOnTimeout(video, /* timeout= */10);
|
|
106
110
|
|
|
107
111
|
// Make sure the playhead is roughly where we expect it to be before
|
|
@@ -138,7 +142,7 @@ describe('Player Src Equals', () => {
|
|
|
138
142
|
await loadWithSrcEquals(SMALL_MP4_CONTENT_URI, /* startTime= */ null);
|
|
139
143
|
|
|
140
144
|
// For playback to begin so that we have some content buffered.
|
|
141
|
-
video.play();
|
|
145
|
+
await video.play();
|
|
142
146
|
await waiter.waitForMovementOrFailOnTimeout(video, /* timeout= */10);
|
|
143
147
|
|
|
144
148
|
const buffered = player.getBufferedInfo();
|
|
@@ -162,7 +166,7 @@ describe('Player Src Equals', () => {
|
|
|
162
166
|
await loadWithSrcEquals(SMALL_MP4_CONTENT_URI, /* startTime= */ null);
|
|
163
167
|
|
|
164
168
|
// Let playback run for a little.
|
|
165
|
-
video.play();
|
|
169
|
+
await video.play();
|
|
166
170
|
await waiter.waitForMovementOrFailOnTimeout(video, /* timeout= */10);
|
|
167
171
|
|
|
168
172
|
let videoRateChange = false;
|
|
@@ -279,7 +283,7 @@ describe('Player Src Equals', () => {
|
|
|
279
283
|
expect(video.currentTime).toBeCloseTo(0);
|
|
280
284
|
|
|
281
285
|
// Start playback and wait. We should see the playhead move.
|
|
282
|
-
video.play();
|
|
286
|
+
await video.play();
|
|
283
287
|
await waiter.waitForMovementOrFailOnTimeout(video, /* timeout= */10);
|
|
284
288
|
await shaka.test.Util.delay(1.5);
|
|
285
289
|
|
|
@@ -296,7 +300,7 @@ describe('Player Src Equals', () => {
|
|
|
296
300
|
|
|
297
301
|
// Wait some time for playback to start so that we will have a load latency
|
|
298
302
|
// value.
|
|
299
|
-
video.play();
|
|
303
|
+
await video.play();
|
|
300
304
|
await waiter.waitForMovementOrFailOnTimeout(video, /* timeout= */10);
|
|
301
305
|
|
|
302
306
|
// Get the stats and check that some stats have been filled in.
|
|
@@ -12,9 +12,13 @@
|
|
|
12
12
|
*/
|
|
13
13
|
shaka.test.FakeDemoMain = class {
|
|
14
14
|
constructor() {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
// Using the player's constructor argument to attach a video element seems
|
|
16
|
+
// to cause flaky timeouts on teardown. If a video element is needed in
|
|
17
|
+
// the future, please explicitly call attach(video) and await the result
|
|
18
|
+
// during the test setup.
|
|
19
|
+
/** @type {!shaka.Player} */
|
|
20
|
+
this.player = new shaka.Player();
|
|
21
|
+
|
|
18
22
|
this.config_ = this.player.getConfiguration();
|
|
19
23
|
this.selectedAsset = null;
|
|
20
24
|
|
|
@@ -395,7 +395,7 @@ shaka.test.NativeTextLayoutTests = class extends shaka.test.TextLayoutTests {
|
|
|
395
395
|
// The this.video must be played a little now, after the cues were appended,
|
|
396
396
|
// but before the screenshot.
|
|
397
397
|
this.video.playbackRate = 1;
|
|
398
|
-
this.video.play();
|
|
398
|
+
await this.video.play();
|
|
399
399
|
await this.waiter.failOnTimeout(false).timeoutAfter(5)
|
|
400
400
|
.waitForMovement(this.video);
|
|
401
401
|
this.video.pause();
|
|
@@ -404,7 +404,7 @@ shaka.test.NativeTextLayoutTests = class extends shaka.test.TextLayoutTests {
|
|
|
404
404
|
this.video.currentTime = time;
|
|
405
405
|
// Get into a playing state, but without movement.
|
|
406
406
|
this.video.playbackRate = 0;
|
|
407
|
-
this.video.play();
|
|
407
|
+
await this.video.play();
|
|
408
408
|
|
|
409
409
|
// Add a short delay to ensure that the system has caught up and that
|
|
410
410
|
// native text displayers have been updated by the browser.
|
|
@@ -410,6 +410,7 @@ shaka.test.StreamingEngineUtil = class {
|
|
|
410
410
|
roles: [],
|
|
411
411
|
forced: false,
|
|
412
412
|
spatialAudio: false,
|
|
413
|
+
external: false,
|
|
413
414
|
};
|
|
414
415
|
}
|
|
415
416
|
|
|
@@ -447,6 +448,7 @@ shaka.test.StreamingEngineUtil = class {
|
|
|
447
448
|
roles: [],
|
|
448
449
|
forced: false,
|
|
449
450
|
spatialAudio: false,
|
|
451
|
+
external: false,
|
|
450
452
|
};
|
|
451
453
|
}
|
|
452
454
|
|
|
@@ -482,6 +484,7 @@ shaka.test.StreamingEngineUtil = class {
|
|
|
482
484
|
roles: [],
|
|
483
485
|
forced: false,
|
|
484
486
|
spatialAudio: false,
|
|
487
|
+
external: false,
|
|
485
488
|
};
|
|
486
489
|
}
|
|
487
490
|
};
|
|
@@ -115,11 +115,18 @@ shaka.test.UiUtils = class {
|
|
|
115
115
|
// Destroying the UI destroys the controls and player inside.
|
|
116
116
|
destroys.push(ui.destroy());
|
|
117
117
|
}
|
|
118
|
-
|
|
118
|
+
|
|
119
|
+
const allDestroyed = Promise.all(destroys);
|
|
120
|
+
// 10 seconds should be more than enough to tear down the UI.
|
|
121
|
+
// Adding this silent timeout fixes several tests that inconsistently hang
|
|
122
|
+
// during teardown and cause failures in afterEach() clauses.
|
|
123
|
+
await Promise.race([allDestroyed, shaka.test.Util.delay(10)]);
|
|
119
124
|
|
|
120
125
|
// Now remove all the containers from the DOM.
|
|
121
126
|
for (const container of containers) {
|
|
122
|
-
container.parentElement
|
|
127
|
+
if (container.parentElement) {
|
|
128
|
+
container.parentElement.removeChild(container);
|
|
129
|
+
}
|
|
123
130
|
}
|
|
124
131
|
}
|
|
125
132
|
|
package/test/test/util/util.js
CHANGED
|
@@ -255,33 +255,12 @@ shaka.test.Util = class {
|
|
|
255
255
|
* @param {string} uri
|
|
256
256
|
* @return {!Promise.<!ArrayBuffer>}
|
|
257
257
|
*/
|
|
258
|
-
static fetch(uri) {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
xhr.onload = (event) => {
|
|
265
|
-
if (xhr.status >= 200 &&
|
|
266
|
-
xhr.status <= 299 &&
|
|
267
|
-
!!xhr.response) {
|
|
268
|
-
resolve(/** @type {!ArrayBuffer} */(xhr.response));
|
|
269
|
-
} else {
|
|
270
|
-
let message = '';
|
|
271
|
-
if (xhr.response) {
|
|
272
|
-
message = ': ' + shaka.util.StringUtils.fromUTF8(
|
|
273
|
-
/** @type {!ArrayBuffer} */(xhr.response));
|
|
274
|
-
}
|
|
275
|
-
reject(xhr.status + message);
|
|
276
|
-
}
|
|
277
|
-
};
|
|
278
|
-
|
|
279
|
-
xhr.onerror = (event) => {
|
|
280
|
-
reject('shaka.test.Util.fetch failed: ' + uri);
|
|
281
|
-
};
|
|
282
|
-
|
|
283
|
-
xhr.send(/* body= */ null);
|
|
284
|
-
}));
|
|
258
|
+
static async fetch(uri) {
|
|
259
|
+
const response = await fetch(uri);
|
|
260
|
+
if (!response.ok) {
|
|
261
|
+
throw new Error('shaka.test.Util.fetch failed: ' + uri);
|
|
262
|
+
}
|
|
263
|
+
return response.arrayBuffer();
|
|
285
264
|
}
|
|
286
265
|
|
|
287
266
|
/**
|
package/test/test/util/waiter.js
CHANGED
|
@@ -109,6 +109,8 @@ shaka.test.Waiter = class {
|
|
|
109
109
|
* @return {!Promise}
|
|
110
110
|
*/
|
|
111
111
|
waitUntilPlayheadReaches(mediaElement, timeGoal) {
|
|
112
|
+
this.macPlaybackWorkaround_(mediaElement);
|
|
113
|
+
|
|
112
114
|
// The name of what we're waiting for
|
|
113
115
|
const goalName = 'movement from ' + mediaElement.currentTime +
|
|
114
116
|
' to ' + timeGoal;
|
|
@@ -153,6 +155,8 @@ shaka.test.Waiter = class {
|
|
|
153
155
|
* @return {!Promise}
|
|
154
156
|
*/
|
|
155
157
|
waitForEnd(mediaElement) {
|
|
158
|
+
this.macPlaybackWorkaround_(mediaElement);
|
|
159
|
+
|
|
156
160
|
// The name of what we're waiting for.
|
|
157
161
|
const goalName = 'end of media';
|
|
158
162
|
|
|
@@ -207,13 +211,64 @@ shaka.test.Waiter = class {
|
|
|
207
211
|
* Wait for the video to end or for |timeout| seconds to pass, whichever
|
|
208
212
|
* occurs first. The Promise is resolved when either of these happens.
|
|
209
213
|
*
|
|
210
|
-
* @param {!HTMLMediaElement}
|
|
214
|
+
* @param {!HTMLMediaElement} mediaElement
|
|
211
215
|
* @param {number} timeout in seconds, after which the Promise succeeds
|
|
212
216
|
* @return {!Promise}
|
|
213
217
|
*/
|
|
214
|
-
waitForEndOrTimeout(
|
|
218
|
+
waitForEndOrTimeout(mediaElement, timeout) {
|
|
215
219
|
this.failOnTimeout(false).timeoutAfter(timeout);
|
|
216
|
-
return this.waitForEnd(
|
|
220
|
+
return this.waitForEnd(mediaElement);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Wait until a certain amount of content is buffered.
|
|
225
|
+
*
|
|
226
|
+
* @param {!HTMLMediaElement} mediaElement
|
|
227
|
+
* @param {number} bufferingGoal in seconds, after which the Promise succeeds
|
|
228
|
+
* @return {!Promise}
|
|
229
|
+
*/
|
|
230
|
+
waitUntilBuffered(mediaElement, bufferingGoal) {
|
|
231
|
+
// The name of what we're waiting for.
|
|
232
|
+
const goalName = `${bufferingGoal} seconds buffered`;
|
|
233
|
+
|
|
234
|
+
// The conditions for success.
|
|
235
|
+
const bufferedEnough = () => {
|
|
236
|
+
const end = shaka.media.TimeRangesUtils.bufferEnd(mediaElement.buffered);
|
|
237
|
+
if (end == null) {
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
return end - mediaElement.currentTime >= bufferingGoal;
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
if (bufferedEnough()) {
|
|
244
|
+
return Promise.resolve();
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Cleanup on timeout.
|
|
248
|
+
let timer = null;
|
|
249
|
+
const cleanup = () => {
|
|
250
|
+
if (timer) {
|
|
251
|
+
timer.stop();
|
|
252
|
+
}
|
|
253
|
+
this.eventManager_.unlisten(mediaElement, 'timeupdate');
|
|
254
|
+
this.eventManager_.unlisten(mediaElement, 'ended');
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
const p = new Promise((resolve) => {
|
|
258
|
+
const check = () => {
|
|
259
|
+
if (bufferedEnough()) {
|
|
260
|
+
cleanup();
|
|
261
|
+
resolve();
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
timer = new shaka.util.Timer(check);
|
|
266
|
+
timer.tickEvery(/* seconds= */ 1);
|
|
267
|
+
this.eventManager_.listen(mediaElement, 'timeupdate', check);
|
|
268
|
+
this.eventManager_.listen(mediaElement, 'ended', check);
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
return this.waitUntilGeneric_(goalName, p, cleanup, mediaElement);
|
|
217
272
|
}
|
|
218
273
|
|
|
219
274
|
/**
|
|
@@ -333,4 +388,19 @@ shaka.test.Waiter = class {
|
|
|
333
388
|
`buffered: ${JSON.stringify(buffered)}\n`;
|
|
334
389
|
shaka.log.error(error.message);
|
|
335
390
|
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* @param {!HTMLMediaElement} mediaElement
|
|
394
|
+
* @private
|
|
395
|
+
*/
|
|
396
|
+
macPlaybackWorkaround_(mediaElement) {
|
|
397
|
+
if (shaka.util.Platform.isMac()) {
|
|
398
|
+
// Work around bizarre playback slowdowns that only seem to occur with
|
|
399
|
+
// WebDriver and only on Mac. Increasing the playback rate allows tests
|
|
400
|
+
// to complete without timing out.
|
|
401
|
+
if (mediaElement.playbackRate == 1) {
|
|
402
|
+
mediaElement.playbackRate = 2;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
336
406
|
};
|
package/test/ui/ad_ui_unit.js
CHANGED
|
@@ -25,15 +25,6 @@ describe('Ad UI', () => {
|
|
|
25
25
|
shaka.Player.setAdManagerFactory(() => new shaka.test.FakeAdManager());
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
-
afterEach(async () => {
|
|
29
|
-
await UiUtils.cleanupUI();
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
afterAll(() => {
|
|
33
|
-
document.head.removeChild(cssLink);
|
|
34
|
-
shaka.Player.setAdManagerFactory(() => new shaka.ads.AdManager());
|
|
35
|
-
});
|
|
36
|
-
|
|
37
28
|
beforeEach(() => {
|
|
38
29
|
container =
|
|
39
30
|
/** @type {!HTMLElement} */ (document.createElement('div'));
|
|
@@ -45,6 +36,15 @@ describe('Ad UI', () => {
|
|
|
45
36
|
adManager = video['ui'].getControls().getPlayer().getAdManager();
|
|
46
37
|
});
|
|
47
38
|
|
|
39
|
+
afterEach(async () => {
|
|
40
|
+
await UiUtils.cleanupUI();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
afterAll(() => {
|
|
44
|
+
document.head.removeChild(cssLink);
|
|
45
|
+
shaka.Player.setAdManagerFactory(() => new shaka.ads.AdManager());
|
|
46
|
+
});
|
|
47
|
+
|
|
48
48
|
it('is invisible if no ad is playing', () => {
|
|
49
49
|
const adControlsContainer =
|
|
50
50
|
UiUtils.getElementByClassName(container, 'shaka-ad-controls');
|
|
@@ -718,6 +718,52 @@ describe('StreamUtils', () => {
|
|
|
718
718
|
expect(manifest.variants.length).toBe(1);
|
|
719
719
|
});
|
|
720
720
|
|
|
721
|
+
it('supports fLaC codec', async () => {
|
|
722
|
+
if (!MediaSource.isTypeSupported('audio/mp4; codecs="flac"')) {
|
|
723
|
+
pending('Codec fLaC is not supported by the platform.');
|
|
724
|
+
}
|
|
725
|
+
manifest = shaka.test.ManifestGenerator.generate((manifest) => {
|
|
726
|
+
manifest.addVariant(0, (variant) => {
|
|
727
|
+
variant.addAudio(1, (stream) => {
|
|
728
|
+
stream.mime('audio/mp4', 'fLaC');
|
|
729
|
+
});
|
|
730
|
+
});
|
|
731
|
+
manifest.addVariant(2, (variant) => {
|
|
732
|
+
variant.addAudio(3, (stream) => {
|
|
733
|
+
stream.mime('audio/mp4', 'flac');
|
|
734
|
+
});
|
|
735
|
+
});
|
|
736
|
+
});
|
|
737
|
+
|
|
738
|
+
await shaka.util.StreamUtils.filterManifest(
|
|
739
|
+
fakeDrmEngine, /* currentVariant= */ null, manifest);
|
|
740
|
+
|
|
741
|
+
expect(manifest.variants.length).toBe(2);
|
|
742
|
+
});
|
|
743
|
+
|
|
744
|
+
it('supports Opus codec', async () => {
|
|
745
|
+
if (!MediaSource.isTypeSupported('audio/mp4; codecs="opus"')) {
|
|
746
|
+
pending('Codec Opus is not supported by the platform.');
|
|
747
|
+
}
|
|
748
|
+
manifest = shaka.test.ManifestGenerator.generate((manifest) => {
|
|
749
|
+
manifest.addVariant(0, (variant) => {
|
|
750
|
+
variant.addAudio(1, (stream) => {
|
|
751
|
+
stream.mime('audio/mp4', 'Opus');
|
|
752
|
+
});
|
|
753
|
+
});
|
|
754
|
+
manifest.addVariant(2, (variant) => {
|
|
755
|
+
variant.addAudio(3, (stream) => {
|
|
756
|
+
stream.mime('audio/mp4', 'opus');
|
|
757
|
+
});
|
|
758
|
+
});
|
|
759
|
+
});
|
|
760
|
+
|
|
761
|
+
await shaka.util.StreamUtils.filterManifest(
|
|
762
|
+
fakeDrmEngine, /* currentVariant= */ null, manifest);
|
|
763
|
+
|
|
764
|
+
expect(manifest.variants.length).toBe(2);
|
|
765
|
+
});
|
|
766
|
+
|
|
721
767
|
it('supports legacy AVC1 codec', async () => {
|
|
722
768
|
if (!MediaSource.isTypeSupported('video/mp4; codecs="avc1.42001e"')) {
|
|
723
769
|
pending('Codec avc1.42001e is not supported by the platform.');
|
package/ui/range_element.js
CHANGED
|
@@ -110,6 +110,11 @@ shaka.ui.RangeElement = class extends shaka.ui.Element {
|
|
|
110
110
|
this.onChangeEnd();
|
|
111
111
|
}
|
|
112
112
|
});
|
|
113
|
+
|
|
114
|
+
this.eventManager.listen(this.bar, 'contextmenu', (e) => {
|
|
115
|
+
e.preventDefault();
|
|
116
|
+
e.stopPropagation();
|
|
117
|
+
});
|
|
113
118
|
}
|
|
114
119
|
|
|
115
120
|
/** @override */
|