shaka-player 4.3.7 → 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/appspot.yaml +39 -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 +44 -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 +2 -2
- package/dist/locales.js +31 -31
- package/dist/shaka-player.compiled.d.ts +24 -2
- package/dist/shaka-player.compiled.debug.d.ts +24 -2
- package/dist/shaka-player.compiled.debug.js +251 -247
- package/dist/shaka-player.compiled.debug.map +3 -3
- package/dist/shaka-player.compiled.js +796 -793
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +24 -2
- package/dist/shaka-player.ui.debug.d.ts +24 -2
- package/dist/shaka-player.ui.debug.js +289 -286
- package/dist/shaka-player.ui.debug.map +3 -3
- package/dist/shaka-player.ui.js +831 -827
- 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/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 +6 -6
- package/lib/cea/mp4_cea_parser.js +24 -18
- package/lib/dash/dash_parser.js +19 -3
- package/lib/hls/hls_parser.js +24 -4
- package/lib/media/drm_engine.js +14 -8
- package/lib/media/gap_jumping_controller.js +24 -2
- package/lib/media/media_source_engine.js +11 -8
- package/lib/media/playhead.js +11 -0
- package/lib/media/region_observer.js +19 -1
- package/lib/media/streaming_engine.js +41 -21
- package/lib/media/video_wrapper.js +6 -1
- 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 +20 -9
- 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/periods.js +2 -0
- package/lib/util/platform.js +14 -0
- package/lib/util/stream_utils.js +70 -26
- package/package.json +2 -2
- package/test/cast/cast_utils_unit.js +4 -1
- package/test/cea/mp4_cea_parser_unit.js +28 -5
- package/test/dash/dash_parser_manifest_unit.js +120 -0
- package/test/hls/hls_parser_unit.js +216 -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/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/media/streaming_engine_unit.js +26 -2
- 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/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/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
- package/ui/resolution_selection.js +7 -1
|
@@ -244,7 +244,7 @@ describe('DrmEngine', () => {
|
|
|
244
244
|
/* hasClosedCaptions= */ false);
|
|
245
245
|
|
|
246
246
|
expect(video.buffered.end(0)).toBeGreaterThan(0);
|
|
247
|
-
video.play();
|
|
247
|
+
await video.play();
|
|
248
248
|
|
|
249
249
|
const waiter = new shaka.test.Waiter(eventManager).timeoutAfter(15);
|
|
250
250
|
waiter.setMediaSourceEngine(mediaSourceEngine);
|
|
@@ -327,7 +327,7 @@ describe('DrmEngine', () => {
|
|
|
327
327
|
/* hasClosedCaptions= */ false);
|
|
328
328
|
|
|
329
329
|
expect(video.buffered.end(0)).toBeGreaterThan(0);
|
|
330
|
-
video.play();
|
|
330
|
+
await video.play();
|
|
331
331
|
|
|
332
332
|
const waiter = new shaka.test.Waiter(eventManager).timeoutAfter(15);
|
|
333
333
|
waiter.setMediaSourceEngine(mediaSourceEngine);
|
|
@@ -1262,7 +1262,7 @@ describe('MediaSourceEngine', () => {
|
|
|
1262
1262
|
});
|
|
1263
1263
|
|
|
1264
1264
|
it('destroys text engines', async () => {
|
|
1265
|
-
mediaSourceEngine.reinitText('text/vtt', false);
|
|
1265
|
+
mediaSourceEngine.reinitText('text/vtt', false, false);
|
|
1266
1266
|
|
|
1267
1267
|
await mediaSourceEngine.destroy();
|
|
1268
1268
|
expect(mockTextEngine).toBeTruthy();
|
|
@@ -31,7 +31,8 @@ describe('RegionObserver', () => {
|
|
|
31
31
|
timeline = new shaka.media.RegionTimeline(
|
|
32
32
|
shaka.test.Util.spyFunc(onSeekRange));
|
|
33
33
|
|
|
34
|
-
observer = new shaka.media.RegionObserver(
|
|
34
|
+
observer = new shaka.media.RegionObserver(
|
|
35
|
+
timeline, /* startsPastZero= */ false);
|
|
35
36
|
observer.addEventListener('enter', (event) => {
|
|
36
37
|
shaka.test.Util.spyFunc(onEnterRegion)(event['region'], event['seeking']);
|
|
37
38
|
});
|
|
@@ -974,9 +974,9 @@ describe('SegmentIndex', /** @suppress {accessControls} */ () => {
|
|
|
974
974
|
return [newRefs.shift()];
|
|
975
975
|
});
|
|
976
976
|
});
|
|
977
|
-
|
|
978
|
-
//
|
|
979
|
-
await
|
|
977
|
+
|
|
978
|
+
// Wait for the new refs to be appended.
|
|
979
|
+
await done;
|
|
980
980
|
|
|
981
981
|
expect(Array.from(metaIndex)).toEqual(oldRefs.concat(inputRefs2));
|
|
982
982
|
});
|
|
@@ -57,6 +57,9 @@ describe('StreamingEngine', () => {
|
|
|
57
57
|
beforeEach(() => {
|
|
58
58
|
config = shaka.util.PlayerConfiguration.createDefault().streaming;
|
|
59
59
|
|
|
60
|
+
// Disable stall detection, which can interfere with playback tests.
|
|
61
|
+
config.stallEnabled = false;
|
|
62
|
+
|
|
60
63
|
onError = jasmine.createSpy('onError');
|
|
61
64
|
onError.and.callFake(fail);
|
|
62
65
|
onEvent = jasmine.createSpy('onEvent');
|
|
@@ -279,7 +282,7 @@ describe('StreamingEngine', () => {
|
|
|
279
282
|
// Let's go!
|
|
280
283
|
streamingEngine.switchVariant(variant);
|
|
281
284
|
await streamingEngine.start();
|
|
282
|
-
video.play();
|
|
285
|
+
await video.play();
|
|
283
286
|
// The overall test timeout is 120 seconds, and the content is 40
|
|
284
287
|
// seconds. It should be possible to complete this test in 100 seconds,
|
|
285
288
|
// and if not, we want the error thrown to be within the overall test's
|
|
@@ -299,7 +302,7 @@ describe('StreamingEngine', () => {
|
|
|
299
302
|
// Let's go!
|
|
300
303
|
streamingEngine.switchVariant(variant);
|
|
301
304
|
await streamingEngine.start();
|
|
302
|
-
video.play();
|
|
305
|
+
await video.play();
|
|
303
306
|
|
|
304
307
|
// Wait for playback to begin before increasing the playback rate. This
|
|
305
308
|
// improves test reliability on slow platforms like Chromecast.
|
|
@@ -313,7 +316,7 @@ describe('StreamingEngine', () => {
|
|
|
313
316
|
// Let's go!
|
|
314
317
|
streamingEngine.switchVariant(variant);
|
|
315
318
|
await streamingEngine.start();
|
|
316
|
-
video.play();
|
|
319
|
+
await video.play();
|
|
317
320
|
|
|
318
321
|
// After 35 seconds seek back 10 seconds into the first Period.
|
|
319
322
|
await waiter.timeoutAfter(80).waitUntilPlayheadReaches(video, 35);
|
|
@@ -325,7 +328,7 @@ describe('StreamingEngine', () => {
|
|
|
325
328
|
// Let's go!
|
|
326
329
|
streamingEngine.switchVariant(variant);
|
|
327
330
|
await streamingEngine.start();
|
|
328
|
-
video.play();
|
|
331
|
+
await video.play();
|
|
329
332
|
await waiter.timeoutAfter(60).waitUntilPlayheadReaches(video, 20);
|
|
330
333
|
video.currentTime = 40;
|
|
331
334
|
await waiter.timeoutAfter(60).waitForEnd(video);
|
|
@@ -353,7 +356,7 @@ describe('StreamingEngine', () => {
|
|
|
353
356
|
streamingEngine.switchVariant(variant);
|
|
354
357
|
await streamingEngine.start();
|
|
355
358
|
|
|
356
|
-
video.play();
|
|
359
|
+
await video.play();
|
|
357
360
|
await waiter.timeoutAfter(60).waitUntilPlayheadReaches(video, 305);
|
|
358
361
|
|
|
359
362
|
const segmentType = shaka.net.NetworkingEngine.RequestType.SEGMENT;
|
|
@@ -373,7 +376,7 @@ describe('StreamingEngine', () => {
|
|
|
373
376
|
// Seek outside the availability window right away. The playhead
|
|
374
377
|
// should adjust the video's current time.
|
|
375
378
|
video.currentTime = segmentAvailability.end + 120;
|
|
376
|
-
video.play();
|
|
379
|
+
await video.play();
|
|
377
380
|
|
|
378
381
|
// Wait until the repositioning is complete so we don't
|
|
379
382
|
// immediately hit this case.
|
|
@@ -398,7 +401,7 @@ describe('StreamingEngine', () => {
|
|
|
398
401
|
video.currentTime = segmentAvailability.start - 120;
|
|
399
402
|
expect(video.currentTime).toBeGreaterThan(0);
|
|
400
403
|
|
|
401
|
-
video.play();
|
|
404
|
+
await video.play();
|
|
402
405
|
await waiter.timeoutAfter(60).waitUntilPlayheadReaches(video, 305);
|
|
403
406
|
|
|
404
407
|
// We are playing close to the beginning of the availability window.
|
|
@@ -426,7 +429,7 @@ describe('StreamingEngine', () => {
|
|
|
426
429
|
// Let's go!
|
|
427
430
|
streamingEngine.switchVariant(variant);
|
|
428
431
|
await streamingEngine.start();
|
|
429
|
-
video.play();
|
|
432
|
+
await video.play();
|
|
430
433
|
|
|
431
434
|
await waiter.timeoutAfter(5).waitUntilPlayheadReaches(video, 0.01);
|
|
432
435
|
expect(video.buffered.length).toBeGreaterThan(0);
|
|
@@ -441,7 +444,7 @@ describe('StreamingEngine', () => {
|
|
|
441
444
|
// Let's go!
|
|
442
445
|
streamingEngine.switchVariant(variant);
|
|
443
446
|
await streamingEngine.start();
|
|
444
|
-
video.play();
|
|
447
|
+
await video.play();
|
|
445
448
|
|
|
446
449
|
await waiter.timeoutAfter(5).waitUntilPlayheadReaches(video, 0.01);
|
|
447
450
|
expect(video.buffered.length).toBeGreaterThan(0);
|
|
@@ -460,7 +463,7 @@ describe('StreamingEngine', () => {
|
|
|
460
463
|
await waiter.timeoutAfter(5).waitForEvent(video, 'loadeddata');
|
|
461
464
|
|
|
462
465
|
video.currentTime = 8;
|
|
463
|
-
video.play();
|
|
466
|
+
await video.play();
|
|
464
467
|
|
|
465
468
|
await waiter.timeoutAfter(60).waitUntilPlayheadReaches(video, 23);
|
|
466
469
|
// Should be close enough to still have the gap buffered.
|
|
@@ -477,7 +480,7 @@ describe('StreamingEngine', () => {
|
|
|
477
480
|
await waiter.timeoutAfter(5).waitForEvent(video, 'loadeddata');
|
|
478
481
|
|
|
479
482
|
video.currentTime = 8;
|
|
480
|
-
video.play();
|
|
483
|
+
await video.play();
|
|
481
484
|
|
|
482
485
|
await waiter.timeoutAfter(60).waitUntilPlayheadReaches(video, 23);
|
|
483
486
|
// Should be close enough to still have the gap buffered.
|
|
@@ -2913,10 +2913,14 @@ describe('StreamingEngine', () => {
|
|
|
2913
2913
|
expect(onManifestUpdate).toHaveBeenCalled();
|
|
2914
2914
|
});
|
|
2915
2915
|
|
|
2916
|
-
it('triggers metadata event', async () => {
|
|
2916
|
+
it('triggers both emsg event and metadata event for ID3', async () => {
|
|
2917
2917
|
setSegment0(emsgSegmentV0ID3);
|
|
2918
2918
|
videoStream.emsgSchemeIdUris = [id3SchemeUri];
|
|
2919
2919
|
|
|
2920
|
+
onEvent.and.callFake((emsgEvent) => {
|
|
2921
|
+
expect(emsgEvent.type).toBe('emsg');
|
|
2922
|
+
});
|
|
2923
|
+
|
|
2920
2924
|
// Here we go!
|
|
2921
2925
|
streamingEngine.switchVariant(variant);
|
|
2922
2926
|
streamingEngine.switchTextStream(textStream);
|
|
@@ -2924,10 +2928,30 @@ describe('StreamingEngine', () => {
|
|
|
2924
2928
|
playing = true;
|
|
2925
2929
|
await runTest();
|
|
2926
2930
|
|
|
2927
|
-
expect(onEvent).
|
|
2931
|
+
expect(onEvent).toHaveBeenCalled();
|
|
2928
2932
|
expect(onMetadata).toHaveBeenCalled();
|
|
2929
2933
|
});
|
|
2930
2934
|
|
|
2935
|
+
it('only triggers emsg event for ID3 if event canceled', async () => {
|
|
2936
|
+
setSegment0(emsgSegmentV0ID3);
|
|
2937
|
+
videoStream.emsgSchemeIdUris = [id3SchemeUri];
|
|
2938
|
+
|
|
2939
|
+
onEvent.and.callFake((emsgEvent) => {
|
|
2940
|
+
expect(emsgEvent.type).toBe('emsg');
|
|
2941
|
+
emsgEvent.preventDefault();
|
|
2942
|
+
});
|
|
2943
|
+
|
|
2944
|
+
// Here we go!
|
|
2945
|
+
streamingEngine.switchVariant(variant);
|
|
2946
|
+
streamingEngine.switchTextStream(textStream);
|
|
2947
|
+
await streamingEngine.start();
|
|
2948
|
+
playing = true;
|
|
2949
|
+
await runTest();
|
|
2950
|
+
|
|
2951
|
+
expect(onEvent).toHaveBeenCalled();
|
|
2952
|
+
expect(onMetadata).not.toHaveBeenCalled();
|
|
2953
|
+
});
|
|
2954
|
+
|
|
2931
2955
|
it('event start matches presentation time', async () => {
|
|
2932
2956
|
// This box has a non-zero event time, which doesn't matter.
|
|
2933
2957
|
setSegment0(emsgSegmentV1NonZeroStart);
|
|
@@ -316,6 +316,7 @@ describe('ManifestConverter', () => {
|
|
|
316
316
|
audioSamplingRate: null,
|
|
317
317
|
spatialAudio: false,
|
|
318
318
|
closedCaptions: null,
|
|
319
|
+
external: false,
|
|
319
320
|
};
|
|
320
321
|
|
|
321
322
|
return streamDB;
|
|
@@ -389,6 +390,7 @@ describe('ManifestConverter', () => {
|
|
|
389
390
|
spatialAudio: false,
|
|
390
391
|
closedCaptions: null,
|
|
391
392
|
tilesLayout: undefined,
|
|
393
|
+
external: false,
|
|
392
394
|
};
|
|
393
395
|
}
|
|
394
396
|
|
|
@@ -438,6 +440,7 @@ describe('ManifestConverter', () => {
|
|
|
438
440
|
spatialAudio: false,
|
|
439
441
|
closedCaptions: null,
|
|
440
442
|
tilesLayout: undefined,
|
|
443
|
+
external: false,
|
|
441
444
|
};
|
|
442
445
|
}
|
|
443
446
|
|
|
@@ -486,6 +489,7 @@ describe('ManifestConverter', () => {
|
|
|
486
489
|
spatialAudio: false,
|
|
487
490
|
closedCaptions: null,
|
|
488
491
|
tilesLayout: undefined,
|
|
492
|
+
external: false,
|
|
489
493
|
};
|
|
490
494
|
}
|
|
491
495
|
|
|
@@ -531,6 +535,7 @@ describe('ManifestConverter', () => {
|
|
|
531
535
|
spatialAudio: streamDb.spatialAudio,
|
|
532
536
|
closedCaptions: streamDb.closedCaptions,
|
|
533
537
|
tilesLayout: streamDb.tilesLayout,
|
|
538
|
+
external: streamDb.external,
|
|
534
539
|
};
|
|
535
540
|
|
|
536
541
|
expect(stream).toEqual(expectedStream);
|
|
@@ -33,6 +33,9 @@ filterDescribe('Offline', supportsStorage, () => {
|
|
|
33
33
|
player = new shaka.Player(video);
|
|
34
34
|
player.addEventListener('error', fail);
|
|
35
35
|
|
|
36
|
+
// Disable stall detection, which can interfere with playback tests.
|
|
37
|
+
player.configure('streaming.stallEnabled', false);
|
|
38
|
+
|
|
36
39
|
eventManager = new shaka.util.EventManager();
|
|
37
40
|
waiter = new shaka.test.Waiter(eventManager);
|
|
38
41
|
waiter.setPlayer(player);
|
|
@@ -67,7 +70,7 @@ filterDescribe('Offline', supportsStorage, () => {
|
|
|
67
70
|
|
|
68
71
|
await player.load(contentUri);
|
|
69
72
|
|
|
70
|
-
video.play();
|
|
73
|
+
await video.play();
|
|
71
74
|
await playTo(/* end= */ 3, /* timeout= */ 20);
|
|
72
75
|
await player.unload();
|
|
73
76
|
await storage.remove(contentUri);
|
|
@@ -103,7 +106,7 @@ filterDescribe('Offline', supportsStorage, () => {
|
|
|
103
106
|
|
|
104
107
|
await player.load(contentUri);
|
|
105
108
|
|
|
106
|
-
video.play();
|
|
109
|
+
await video.play();
|
|
107
110
|
await playTo(/* end= */ 3, /* timeout= */ 20);
|
|
108
111
|
await player.unload();
|
|
109
112
|
await storage.remove(contentUri);
|
|
@@ -146,7 +149,7 @@ filterDescribe('Offline', supportsStorage, () => {
|
|
|
146
149
|
|
|
147
150
|
await player.load(contentUri);
|
|
148
151
|
|
|
149
|
-
video.play();
|
|
152
|
+
await video.play();
|
|
150
153
|
await playTo(/* end= */ 3, /* timeout= */ 20);
|
|
151
154
|
await player.unload();
|
|
152
155
|
await storage.remove(contentUri);
|
package/test/player_external.js
CHANGED
|
@@ -36,6 +36,24 @@ describe('Player', () => {
|
|
|
36
36
|
beforeEach(() => {
|
|
37
37
|
player = new compiledShaka.Player(video);
|
|
38
38
|
|
|
39
|
+
// Make sure we are playing the lowest res available to avoid test flake
|
|
40
|
+
// based on network issues. Note that disabling ABR and setting a low
|
|
41
|
+
// abr.defaultBandwidthEstimate would not be sufficient, because it
|
|
42
|
+
// would only affect the choice of track on the first period. When we
|
|
43
|
+
// cross a period boundary, the default bandwidth estimate will no
|
|
44
|
+
// longer be in effect, and AbrManager may choose higher res tracks for
|
|
45
|
+
// the new period. Using abr.restrictions.maxHeight will let us force
|
|
46
|
+
// AbrManager to the lowest resolution, which is its fallback when these
|
|
47
|
+
// soft restrictions cannot be met.
|
|
48
|
+
player.configure('abr.restrictions.maxHeight', 1);
|
|
49
|
+
|
|
50
|
+
// Make sure that live streams are synced against a good clock.
|
|
51
|
+
player.configure('manifest.dash.clockSyncUri',
|
|
52
|
+
'https://shaka-player-demo.appspot.com/time.txt');
|
|
53
|
+
|
|
54
|
+
// Disable stall detection, which can interfere with playback tests.
|
|
55
|
+
player.configure('streaming.stallEnabled', false);
|
|
56
|
+
|
|
39
57
|
// Grab event manager from the uncompiled library:
|
|
40
58
|
eventManager = new shaka.util.EventManager();
|
|
41
59
|
waiter = new shaka.test.Waiter(eventManager);
|
|
@@ -92,21 +110,6 @@ describe('Player', () => {
|
|
|
92
110
|
}
|
|
93
111
|
}
|
|
94
112
|
|
|
95
|
-
// Make sure we are playing the lowest res available to avoid test flake
|
|
96
|
-
// based on network issues. Note that disabling ABR and setting a low
|
|
97
|
-
// abr.defaultBandwidthEstimate would not be sufficient, because it
|
|
98
|
-
// would only affect the choice of track on the first period. When we
|
|
99
|
-
// cross a period boundary, the default bandwidth estimate will no
|
|
100
|
-
// longer be in effect, and AbrManager may choose higher res tracks for
|
|
101
|
-
// the new period. Using abr.restrictions.maxHeight will let us force
|
|
102
|
-
// AbrManager to the lowest resolution, which is its fallback when these
|
|
103
|
-
// soft restrictions cannot be met.
|
|
104
|
-
player.configure('abr.restrictions.maxHeight', 1);
|
|
105
|
-
|
|
106
|
-
// Make sure that live streams are synced against a good clock.
|
|
107
|
-
player.configure('manifest.dash.clockSyncUri',
|
|
108
|
-
'https://shaka-player-demo.appspot.com/time.txt');
|
|
109
|
-
|
|
110
113
|
// Add asset-specific configuration.
|
|
111
114
|
player.configure(asset.getConfiguration());
|
|
112
115
|
|
|
@@ -125,7 +128,7 @@ describe('Player', () => {
|
|
|
125
128
|
const isLive = asset.features.includes(Feature.LIVE);
|
|
126
129
|
expect(player.isLive()).toBe(isLive);
|
|
127
130
|
}
|
|
128
|
-
video.play();
|
|
131
|
+
await video.play();
|
|
129
132
|
|
|
130
133
|
// Wait for the video to start playback. If it takes longer than 20
|
|
131
134
|
// seconds, fail the test.
|
|
@@ -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.
|
|
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
|
|