shaka-player 4.2.11 → 4.2.13
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/appspot.yaml +39 -0
- package/.github/workflows/build-and-test.yaml +15 -0
- package/.github/workflows/selenium-lab-tests.yaml +3 -2
- package/.github/workflows/update-issues.yaml +1 -0
- package/CHANGELOG.md +42 -0
- package/CONTRIBUTORS +1 -0
- package/demo/custom.js +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/deps.js +3 -3
- package/dist/locales.js +33 -33
- package/dist/shaka-player.compiled.d.ts +22 -0
- package/dist/shaka-player.compiled.debug.d.ts +22 -0
- package/dist/shaka-player.compiled.debug.js +233 -232
- package/dist/shaka-player.compiled.debug.map +3 -3
- package/dist/shaka-player.compiled.js +738 -738
- package/dist/shaka-player.compiled.map +3 -3
- package/dist/shaka-player.ui.d.ts +22 -0
- package/dist/shaka-player.ui.debug.d.ts +22 -0
- package/dist/shaka-player.ui.debug.js +259 -258
- package/dist/shaka-player.ui.debug.map +3 -3
- package/dist/shaka-player.ui.js +917 -916
- package/dist/shaka-player.ui.map +4 -4
- package/docs/tutorials/drm-config.md +9 -6
- package/docs/tutorials/selenium-grid-config.md +60 -8
- package/externs/ima.js +34 -0
- package/karma.conf.js +50 -7
- package/lib/abr/simple_abr_manager.js +6 -6
- package/lib/cea/mp4_cea_parser.js +30 -14
- package/lib/dash/dash_parser.js +18 -3
- package/lib/hls/hls_parser.js +13 -2
- package/lib/media/drm_engine.js +14 -8
- package/lib/media/gap_jumping_controller.js +24 -2
- package/lib/media/media_source_engine.js +5 -3
- package/lib/media/playhead.js +11 -0
- package/lib/media/region_observer.js +19 -1
- package/lib/media/streaming_engine.js +7 -3
- package/lib/media/video_wrapper.js +6 -1
- package/lib/player.js +9 -8
- package/lib/polyfill/abort_controller.js +7 -0
- package/lib/polyfill/orientation.js +34 -7
- package/lib/text/vtt_text_parser.js +3 -1
- package/lib/util/manifest_parser_utils.js +5 -3
- package/lib/util/mp4_box_parsers.js +8 -3
- package/lib/util/platform.js +14 -0
- package/lib/util/stream_utils.js +70 -26
- package/package.json +2 -3
- package/test/cast/cast_utils_unit.js +4 -1
- package/test/cea/mp4_cea_parser_unit.js +26 -3
- package/test/dash/dash_parser_manifest_unit.js +120 -0
- package/test/hls/hls_parser_unit.js +222 -0
- package/test/media/drm_engine_integration.js +2 -2
- package/test/media/region_observer_unit.js +2 -1
- package/test/media/segment_index_unit.js +3 -3
- package/test/media/streaming_engine_integration.js +14 -11
- 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/assets/multiple-trun-init.mp4 +0 -0
- package/test/test/assets/multiple-trun-segment.mp4 +0 -0
- package/test/test/util/fake_demo_main.js +7 -3
- package/test/test/util/layout_tests.js +2 -2
- 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
- package/ui/resolution_selection.js +7 -1
|
@@ -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
|
|
@@ -331,7 +338,7 @@ describe('Player', () => {
|
|
|
331
338
|
await player.load('test:sintel_realistic_compiled');
|
|
332
339
|
|
|
333
340
|
// Play until a time at which the external cues would be on screen.
|
|
334
|
-
video.play();
|
|
341
|
+
await video.play();
|
|
335
342
|
await waiter.waitUntilPlayheadReachesOrFailOnTimeout(video, 4, 20);
|
|
336
343
|
|
|
337
344
|
expect(player.isTextTrackVisible()).toBe(true);
|
|
@@ -363,7 +370,7 @@ describe('Player', () => {
|
|
|
363
370
|
await waiter.waitForEvent(player, 'texttrackvisibility');
|
|
364
371
|
|
|
365
372
|
// Play until a time at which the external cues would be on screen.
|
|
366
|
-
video.play();
|
|
373
|
+
await video.play();
|
|
367
374
|
await waiter.waitUntilPlayheadReachesOrFailOnTimeout(video, 4, 20);
|
|
368
375
|
|
|
369
376
|
expect(player.isTextTrackVisible()).toBe(true);
|
|
@@ -434,7 +441,7 @@ describe('Player', () => {
|
|
|
434
441
|
player.setTextTrackVisibility(true);
|
|
435
442
|
player.selectTextLanguage('fr');
|
|
436
443
|
video.currentTime = 5;
|
|
437
|
-
video.play();
|
|
444
|
+
await video.play();
|
|
438
445
|
await waiter.waitForMovementOrFailOnTimeout(video, 10);
|
|
439
446
|
|
|
440
447
|
expect(video.textTracks[0].activeCues.length).toBe(1);
|
|
@@ -472,7 +479,7 @@ describe('Player', () => {
|
|
|
472
479
|
|
|
473
480
|
it('at higher playback rates', async () => {
|
|
474
481
|
await player.load('test:sintel_compiled');
|
|
475
|
-
video.play();
|
|
482
|
+
await video.play();
|
|
476
483
|
await waiter.waitUntilPlayheadReachesOrFailOnTimeout(video, 1, 10);
|
|
477
484
|
|
|
478
485
|
// Enabling trick play should change our playback rate to the same rate.
|
|
@@ -488,14 +495,12 @@ describe('Player', () => {
|
|
|
488
495
|
});
|
|
489
496
|
|
|
490
497
|
it('in sequence mode', async () => {
|
|
491
|
-
|
|
492
|
-
player = new compiledShaka.Player(video);
|
|
493
|
-
await player.load('test:sintel_sequence_compiled', 0, testSchemeMimeType);
|
|
498
|
+
await player.load('test:sintel_sequence_compiled');
|
|
494
499
|
expect(player.getManifest().sequenceMode).toBe(true);
|
|
495
500
|
|
|
496
501
|
// Ensure the video plays.
|
|
497
|
-
video.play();
|
|
498
|
-
await waiter.
|
|
502
|
+
await video.play();
|
|
503
|
+
await waiter.timeoutAfter(20).waitUntilPlayheadReaches(video, 5);
|
|
499
504
|
|
|
500
505
|
// Seek the video, and see if it can continue playing from that point.
|
|
501
506
|
video.currentTime = 20;
|
|
@@ -514,9 +519,8 @@ describe('Player', () => {
|
|
|
514
519
|
// even if one is not specified in load().
|
|
515
520
|
it('immediately after construction with MIME type', async () => {
|
|
516
521
|
const testSchemeMimeType = 'application/x-test-manifest';
|
|
517
|
-
player = new compiledShaka.Player(video);
|
|
518
522
|
await player.load('test:sintel_compiled', 0, testSchemeMimeType);
|
|
519
|
-
video.play();
|
|
523
|
+
await video.play();
|
|
520
524
|
await waiter.waitUntilPlayheadReachesOrFailOnTimeout(video, 1, 10);
|
|
521
525
|
});
|
|
522
526
|
|
|
@@ -555,7 +559,7 @@ describe('Player', () => {
|
|
|
555
559
|
// Regression test for https://github.com/shaka-project/shaka-player/issues/1187
|
|
556
560
|
it('does not throw on destroy', async () => {
|
|
557
561
|
await player.load('test:sintel_compiled');
|
|
558
|
-
video.play();
|
|
562
|
+
await video.play();
|
|
559
563
|
await waiter.waitUntilPlayheadReachesOrFailOnTimeout(video, 1, 10);
|
|
560
564
|
await player.unload();
|
|
561
565
|
// Before we fixed #1187, the call to destroy() on textDisplayer was
|
|
@@ -801,7 +805,7 @@ describe('Player', () => {
|
|
|
801
805
|
player.configure('streaming.observeQualityChanges', true);
|
|
802
806
|
|
|
803
807
|
await player.load('test:sintel_compiled');
|
|
804
|
-
video.play();
|
|
808
|
+
await video.play();
|
|
805
809
|
|
|
806
810
|
// Wait for the video to start playback. If it takes longer than 10
|
|
807
811
|
// seconds, fail the test.
|
|
@@ -815,7 +819,7 @@ describe('Player', () => {
|
|
|
815
819
|
player.configure('streaming.observeQualityChanges', false);
|
|
816
820
|
|
|
817
821
|
await player.load('test:sintel_compiled');
|
|
818
|
-
video.play();
|
|
822
|
+
await video.play();
|
|
819
823
|
|
|
820
824
|
// Wait for the video to start playback. If it takes longer than 10
|
|
821
825
|
// seconds, fail the test.
|
|
@@ -844,7 +848,7 @@ describe('Player', () => {
|
|
|
844
848
|
|
|
845
849
|
// Play the stream.
|
|
846
850
|
await player.load('/base/test/test/assets/3675/dash_0.mpd');
|
|
847
|
-
video.play();
|
|
851
|
+
await video.play();
|
|
848
852
|
|
|
849
853
|
// Wait for the stream to be over.
|
|
850
854
|
eventManager.listen(player, 'error', Util.spyFunc(onErrorSpy));
|
|
@@ -932,22 +936,22 @@ describe('Player', () => {
|
|
|
932
936
|
|
|
933
937
|
await player.load('test:sintel_long_compiled');
|
|
934
938
|
video.pause();
|
|
935
|
-
await waitUntilBuffered(10);
|
|
939
|
+
await waiter.waitUntilBuffered(video, 10);
|
|
936
940
|
|
|
937
941
|
player.configure('streaming.bufferingGoal', 30);
|
|
938
|
-
await waitUntilBuffered(30);
|
|
942
|
+
await waiter.waitUntilBuffered(video, 30);
|
|
939
943
|
|
|
940
944
|
player.configure('streaming.bufferingGoal', 60);
|
|
941
|
-
await waitUntilBuffered(60);
|
|
942
|
-
await Util.delay(
|
|
945
|
+
await waiter.waitUntilBuffered(video, 60);
|
|
946
|
+
await Util.delay(1);
|
|
943
947
|
expect(getBufferedAhead()).toBeLessThan(70); // 60 + segment_size
|
|
944
948
|
|
|
945
949
|
// We don't remove buffered content ahead of the playhead, so seek to
|
|
946
950
|
// clear the buffer.
|
|
947
951
|
player.configure('streaming.bufferingGoal', 10);
|
|
948
952
|
video.currentTime = 120;
|
|
949
|
-
await waitUntilBuffered(10);
|
|
950
|
-
await Util.delay(
|
|
953
|
+
await waiter.waitUntilBuffered(video, 10);
|
|
954
|
+
await Util.delay(1);
|
|
951
955
|
expect(getBufferedAhead()).toBeLessThan(20); // 10 + segment_size
|
|
952
956
|
});
|
|
953
957
|
|
|
@@ -957,20 +961,22 @@ describe('Player', () => {
|
|
|
957
961
|
|
|
958
962
|
await player.load('test:sintel_long_compiled');
|
|
959
963
|
video.pause();
|
|
960
|
-
await waitUntilBuffered(30);
|
|
964
|
+
await waiter.waitUntilBuffered(video, 30);
|
|
961
965
|
video.currentTime = 20;
|
|
962
|
-
await waitUntilBuffered(30);
|
|
966
|
+
await waiter.waitUntilBuffered(video, 30);
|
|
963
967
|
|
|
964
968
|
expect(getBufferedBehind()).toBe(20); // Buffered to start still.
|
|
965
969
|
video.currentTime = 50;
|
|
966
|
-
await waitUntilBuffered(30);
|
|
970
|
+
await waiter.waitUntilBuffered(video, 30);
|
|
971
|
+
await Util.delay(1);
|
|
967
972
|
expect(getBufferedBehind()).toBeLessThan(40); // 30 + segment_size
|
|
968
973
|
|
|
969
974
|
player.configure('streaming.bufferBehind', 10);
|
|
970
975
|
// We only evict content when we append a segment, so increase the
|
|
971
976
|
// buffering goal so we append another segment.
|
|
972
977
|
player.configure('streaming.bufferingGoal', 40);
|
|
973
|
-
await waitUntilBuffered(40);
|
|
978
|
+
await waiter.waitUntilBuffered(video, 40);
|
|
979
|
+
await Util.delay(1);
|
|
974
980
|
expect(getBufferedBehind()).toBeLessThanOrEqual(10);
|
|
975
981
|
});
|
|
976
982
|
|
|
@@ -989,25 +995,6 @@ describe('Player', () => {
|
|
|
989
995
|
}
|
|
990
996
|
return video.currentTime - start;
|
|
991
997
|
}
|
|
992
|
-
|
|
993
|
-
async function waitUntilBuffered(amount) {
|
|
994
|
-
for (let i = 0; i < 50; i++) {
|
|
995
|
-
// We buffer from an internal segment, so this shouldn't take long to
|
|
996
|
-
// buffer.
|
|
997
|
-
await Util.delay(0.1); // eslint-disable-line no-await-in-loop
|
|
998
|
-
if (getBufferedAhead() >= amount) {
|
|
999
|
-
return;
|
|
1000
|
-
}
|
|
1001
|
-
}
|
|
1002
|
-
|
|
1003
|
-
const ranges =
|
|
1004
|
-
shaka.media.TimeRangesUtils.getBufferedInfo(video.buffered);
|
|
1005
|
-
const currentTime = video.currentTime;
|
|
1006
|
-
const target = currentTime + amount;
|
|
1007
|
-
|
|
1008
|
-
throw new Error('Timeout waiting to buffer! ' +
|
|
1009
|
-
JSON.stringify({ranges, currentTime, target}));
|
|
1010
|
-
}
|
|
1011
998
|
}); // describe('buffering')
|
|
1012
999
|
|
|
1013
1000
|
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.
|
|
Binary file
|
|
Binary file
|
|
@@ -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.
|
|
@@ -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 */
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
goog.provide('shaka.ui.ResolutionSelection');
|
|
9
9
|
|
|
10
10
|
goog.require('goog.asserts');
|
|
11
|
+
goog.require('shaka.Player');
|
|
11
12
|
goog.require('shaka.ui.Controls');
|
|
12
13
|
goog.require('shaka.ui.Enums');
|
|
13
14
|
goog.require('shaka.ui.Locales');
|
|
@@ -67,7 +68,12 @@ shaka.ui.ResolutionSelection = class extends shaka.ui.SettingsMenu {
|
|
|
67
68
|
/** @private */
|
|
68
69
|
updateResolutionSelection_() {
|
|
69
70
|
/** @type {!Array.<shaka.extern.Track>} */
|
|
70
|
-
let tracks =
|
|
71
|
+
let tracks = [];
|
|
72
|
+
// When played with src=, the variant tracks available from
|
|
73
|
+
// player.getVariantTracks() represent languages, not resolutions.
|
|
74
|
+
if (this.player.getLoadMode() != shaka.Player.LoadMode.SRC_EQUALS) {
|
|
75
|
+
tracks = this.player.getVariantTracks();
|
|
76
|
+
}
|
|
71
77
|
|
|
72
78
|
// If there is a selected variant track, then we filter out any tracks in
|
|
73
79
|
// a different language. Then we use those remaining tracks to display the
|