shaka-player 2.5.1 → 2.5.5
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/.csslintrc +13 -0
- package/AUTHORS +3 -0
- package/CHANGELOG.md +156 -0
- package/CONTRIBUTORS +3 -0
- package/README.md +3 -0
- package/build/README.md +5 -5
- package/build/apps.py +3 -1
- package/build/build.py +5 -2
- package/build/check.py +17 -0
- package/build/compiler.py +49 -0
- package/build/conformance.textproto +1 -0
- package/build/docs.py +0 -6
- package/build/generateExterns.js +72 -20
- package/build/install-linux-prereqs.sh +4 -4
- package/build/shakaBuildHelpers.py +7 -8
- package/build/test.py +21 -9
- package/build/types/core +1 -0
- package/build/types/ui +6 -1
- package/demo/asset_card.js +129 -41
- package/demo/cast_receiver/receiver_app.css +27 -13
- package/demo/close_button.js +10 -15
- package/demo/common/asset.js +6 -6
- package/demo/common/assets.js +72 -14
- package/demo/config.js +28 -25
- package/demo/custom.js +20 -16
- package/demo/demo.less +107 -16
- package/demo/demo_uncompiled.js +33 -0
- package/demo/demo_utils.js +4 -3
- package/demo/front.js +12 -8
- package/demo/index.html +14 -17
- package/demo/input.js +30 -23
- package/demo/input_container.js +15 -11
- package/demo/load.js +5 -7
- package/demo/main.js +138 -49
- package/demo/search.js +40 -36
- package/demo/service_worker.js +1 -1
- package/demo/tooltip.js +16 -24
- package/dist/.csslintstamp +0 -0
- package/dist/controls.css +1 -1
- package/dist/controls.css.map +1 -1
- package/dist/demo.compiled.debug.js +165 -152
- package/dist/demo.compiled.debug.map +4 -4
- package/dist/demo.compiled.js +165 -152
- package/dist/demo.compiled.map +4 -4
- package/dist/demo.css +1 -1
- package/dist/demo.css.map +1 -1
- package/dist/deps.js +28 -11
- package/dist/receiver.compiled.debug.js +11 -11
- package/dist/receiver.compiled.debug.map +3 -3
- package/dist/receiver.compiled.js +11 -11
- package/dist/receiver.compiled.map +3 -3
- package/dist/shaka-player.compiled.debug.externs.js +232 -102
- package/dist/shaka-player.compiled.debug.js +189 -165
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +232 -102
- package/dist/shaka-player.compiled.js +567 -553
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.debug.externs.js +338 -113
- package/dist/shaka-player.ui.debug.js +296 -276
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +338 -113
- package/dist/shaka-player.ui.js +685 -671
- package/dist/shaka-player.ui.map +4 -4
- package/docs/tutorials/drm-config.md +1 -0
- package/docs/tutorials/fairplay.md +77 -0
- package/docs/tutorials/index.json +1 -0
- package/docs/tutorials/manifest-parser.md +1 -1
- package/docs/tutorials/ui-customization.md +5 -2
- package/docs/tutorials/ui.md +10 -4
- package/docs/tutorials/welcome.md +2 -2
- package/externs/mediasession.js +16 -1
- package/externs/shaka/net.js +14 -4
- package/externs/shaka/player.js +136 -90
- package/externs/tippy.js +30 -0
- package/externs/webkitmediakeys.js +4 -0
- package/karma.conf.js +30 -24
- package/lib/cast/cast_proxy.js +94 -23
- package/lib/cast/cast_receiver.js +8 -1
- package/lib/dash/content_protection.js +33 -1
- package/lib/dash/dash_parser.js +13 -5
- package/lib/hls/hls_parser.js +20 -4
- package/lib/media/drm_engine.js +29 -2
- package/lib/media/media_source_engine.js +9 -6
- package/lib/media/play_rate_controller.js +14 -3
- package/lib/media/playhead.js +8 -3
- package/lib/media/streaming_engine.js +68 -20
- package/lib/media/transmuxer.js +2 -2
- package/lib/media/video_wrapper.js +8 -3
- package/lib/net/data_uri_plugin.js +5 -2
- package/lib/net/http_fetch_plugin.js +3 -3
- package/lib/net/http_plugin_utils.js +2 -4
- package/lib/net/http_xhr_plugin.js +2 -2
- package/lib/net/networking_engine.js +1 -0
- package/lib/offline/offline_scheme.js +7 -2
- package/lib/player.js +18 -8
- package/lib/polyfill/input_event.js +7 -11
- package/lib/polyfill/mediasource.js +1 -1
- package/lib/polyfill/patchedmediakeys_apple.js +2 -72
- package/lib/text/cue.js +1 -1
- package/lib/text/ttml_text_parser.js +1 -1
- package/lib/util/config_utils.js +1 -0
- package/lib/util/error.js +45 -11
- package/lib/util/event_manager.js +211 -100
- package/lib/util/fairplay_utils.js +122 -0
- package/lib/util/i_releasable.js +1 -0
- package/lib/util/player_configuration.js +7 -0
- package/lib/util/pssh.js +41 -0
- package/lib/util/string_utils.js +42 -6
- package/lib/util/timer.js +1 -1
- package/package.json +33 -33
- package/roadmap.md +96 -0
- package/shaka-player.uncompiled.js +5 -1
- package/test/dash/dash_parser_content_protection_unit.js +35 -1
- package/test/dash/dash_parser_manifest_unit.js +60 -0
- package/test/hls/hls_live_unit.js +7 -1
- package/test/hls/hls_parser_unit.js +50 -0
- package/test/media/drm_engine_unit.js +10 -4
- package/test/media/media_source_engine_integration.js +12 -0
- package/test/media/media_source_engine_unit.js +3 -1
- package/test/media/playhead_unit.js +7 -5
- package/test/media/streaming_engine_unit.js +46 -1
- package/test/media/transmuxer_integration.js +13 -0
- package/test/net/data_uri_plugin_unit.js +13 -2
- package/test/net/http_plugin_unit.js +17 -12
- package/test/net/networking_engine_unit.js +17 -8
- package/test/offline/offline_scheme_unit.js +18 -8
- package/test/player_external.js +3 -2
- package/test/player_integration.js +94 -3
- package/test/player_src_equals_integration.js +2 -2
- package/test/player_unit.js +21 -8
- package/test/test/boot.js +20 -5
- package/test/test/externs/jasmine.js +48 -0
- package/test/test/util/expect_async_polyfill.js +145 -0
- package/test/test/util/fake_networking_engine.js +1 -0
- package/test/test/util/manifest_generator.js +2 -1
- package/test/test/util/test_scheme.js +34 -2
- package/test/test/util/ui_utils.js +41 -0
- package/test/test/util/util.js +16 -8
- package/test/ui/ui_unit.js +130 -4
- package/ui/audio_language_selection.js +17 -96
- package/ui/big_play_button.js +61 -0
- package/ui/controls.js +226 -335
- package/ui/controls.less +3 -5
- package/ui/element.js +24 -6
- package/ui/externs/ui.js +62 -9
- package/ui/fullscreen_button.js +2 -52
- package/ui/less/buttons.less +10 -16
- package/ui/less/containers.less +75 -20
- package/ui/less/general.less +18 -2
- package/ui/less/other_elements.less +2 -1
- package/ui/less/overflow_menu.less +11 -10
- package/ui/less/range_elements.less +12 -10
- package/ui/less/spinner.less +2 -0
- package/ui/overflow_menu.js +1 -1
- package/ui/pip_button.js +1 -1
- package/ui/{play_pause_button.js → play_button.js} +17 -47
- package/ui/presentation_time.js +17 -12
- package/ui/range_element.js +176 -0
- package/ui/resolution_selection.js +43 -106
- package/ui/seek_bar.js +204 -0
- package/ui/settings_menu.js +113 -0
- package/ui/small_play_button.js +73 -0
- package/ui/text_displayer.js +17 -14
- package/ui/text_selection.js +42 -107
- package/ui/ui.js +17 -40
- package/ui/volume_bar.js +40 -68
|
@@ -446,7 +446,10 @@ describe('StreamingEngine', function() {
|
|
|
446
446
|
config.bufferBehind = Infinity;
|
|
447
447
|
}
|
|
448
448
|
|
|
449
|
-
|
|
449
|
+
goog.asserts.assert(
|
|
450
|
+
presentationTimeInSeconds != undefined,
|
|
451
|
+
'All tests should have defined an initial presentation time by now!');
|
|
452
|
+
const playerInterface = {
|
|
450
453
|
getPresentationTime: () => presentationTimeInSeconds,
|
|
451
454
|
getBandwidthEstimate: Util.spyFunc(getBandwidthEstimate),
|
|
452
455
|
mediaSourceEngine: mediaSourceEngine,
|
|
@@ -985,6 +988,27 @@ describe('StreamingEngine', function() {
|
|
|
985
988
|
expect(timeline.setDuration).not.toHaveBeenCalled();
|
|
986
989
|
});
|
|
987
990
|
|
|
991
|
+
// https://github.com/google/shaka-player/issues/1967
|
|
992
|
+
it('does not change duration when 0', () => {
|
|
993
|
+
setupVod();
|
|
994
|
+
mediaSourceEngine = new shaka.test.FakeMediaSourceEngine(segmentData);
|
|
995
|
+
createStreamingEngine();
|
|
996
|
+
|
|
997
|
+
onStartupComplete.and.callFake(() => setupFakeGetTime(0));
|
|
998
|
+
onChooseStreams.and.callFake(defaultOnChooseStreams);
|
|
999
|
+
|
|
1000
|
+
// The duration can spuriously be set to 0, so we should ignore this and not
|
|
1001
|
+
// update the duration.
|
|
1002
|
+
mediaSourceEngine.getDuration.and.returnValue(0);
|
|
1003
|
+
|
|
1004
|
+
// Here we go!
|
|
1005
|
+
streamingEngine.start();
|
|
1006
|
+
|
|
1007
|
+
runTest();
|
|
1008
|
+
expect(mediaSourceEngine.endOfStream).toHaveBeenCalled();
|
|
1009
|
+
expect(timeline.setDuration).not.toHaveBeenCalled();
|
|
1010
|
+
});
|
|
1011
|
+
|
|
988
1012
|
it('applies fudge factor for appendWindowStart', function() {
|
|
989
1013
|
setupVod();
|
|
990
1014
|
mediaSourceEngine = new shaka.test.FakeMediaSourceEngine(segmentData);
|
|
@@ -1118,6 +1142,7 @@ describe('StreamingEngine', function() {
|
|
|
1118
1142
|
});
|
|
1119
1143
|
|
|
1120
1144
|
playing = false;
|
|
1145
|
+
presentationTimeInSeconds = 0;
|
|
1121
1146
|
createStreamingEngine();
|
|
1122
1147
|
|
|
1123
1148
|
onStartupComplete.and.callFake(setupFakeGetTime.bind(null, 0));
|
|
@@ -1932,6 +1957,26 @@ describe('StreamingEngine', function() {
|
|
|
1932
1957
|
runTest();
|
|
1933
1958
|
expect(onError).toHaveBeenCalled();
|
|
1934
1959
|
});
|
|
1960
|
+
|
|
1961
|
+
it('from failed clear in switchVariant', () => {
|
|
1962
|
+
const expectedError = new shaka.util.Error(
|
|
1963
|
+
shaka.util.Error.Severity.CRITICAL,
|
|
1964
|
+
shaka.util.Error.Category.MEDIA,
|
|
1965
|
+
shaka.util.Error.Code.MEDIA_SOURCE_OPERATION_FAILED);
|
|
1966
|
+
mediaSourceEngine.clear.and.returnValue(Promise.reject(expectedError));
|
|
1967
|
+
|
|
1968
|
+
onError.and.stub();
|
|
1969
|
+
onChooseStreams.and.callFake((period) => defaultOnChooseStreams(period));
|
|
1970
|
+
onStartupComplete.and.callFake(() => {
|
|
1971
|
+
streamingEngine.switchVariant(
|
|
1972
|
+
variant2, /* clear_buffer= */ true, /* safe_margin= */ 0);
|
|
1973
|
+
});
|
|
1974
|
+
|
|
1975
|
+
// Here we go!
|
|
1976
|
+
streamingEngine.start().catch(fail);
|
|
1977
|
+
runTest();
|
|
1978
|
+
expect(onError).toHaveBeenCalledWith(Util.jasmineError(expectedError));
|
|
1979
|
+
});
|
|
1935
1980
|
});
|
|
1936
1981
|
|
|
1937
1982
|
describe('handles network errors', function() {
|
|
@@ -59,6 +59,12 @@ describe('Transmuxer', function() {
|
|
|
59
59
|
expect(isSupported(transportStreamVideoMimeType, ContentType.VIDEO))
|
|
60
60
|
.toBe(true);
|
|
61
61
|
});
|
|
62
|
+
|
|
63
|
+
// Issue #1991
|
|
64
|
+
it('handles upper-case MIME types', () => {
|
|
65
|
+
const mimeType = transportStreamVideoMimeType.replace('mp2t', 'MP2T');
|
|
66
|
+
expect(isSupported(mimeType, ContentType.VIDEO)).toBe(true);
|
|
67
|
+
});
|
|
62
68
|
});
|
|
63
69
|
|
|
64
70
|
describe('convertTsCodecs', function() {
|
|
@@ -86,6 +92,13 @@ describe('Transmuxer', function() {
|
|
|
86
92
|
'video/mp2t; codecs="avc1.66.1"')).toEqual(
|
|
87
93
|
'video/mp4; codecs="avc1.420001"');
|
|
88
94
|
});
|
|
95
|
+
|
|
96
|
+
// Issue #1991
|
|
97
|
+
it('handles upper-case MIME types', () => {
|
|
98
|
+
expect(convertTsCodecs(
|
|
99
|
+
ContentType.VIDEO, 'video/MP2T; codecs="avc1.420001"'))
|
|
100
|
+
.toBe('video/mp4; codecs="avc1.420001"');
|
|
101
|
+
});
|
|
89
102
|
});
|
|
90
103
|
|
|
91
104
|
describe('transmuxing', function() {
|
|
@@ -65,10 +65,16 @@ describe('DataUriPlugin', function() {
|
|
|
65
65
|
});
|
|
66
66
|
|
|
67
67
|
function testSucceeds(uri, contentType, text, done) {
|
|
68
|
+
// An arbitrary request type.
|
|
69
|
+
const requestType = shaka.net.NetworkingEngine.RequestType.SEGMENT;
|
|
70
|
+
// A dummy progress callback.
|
|
71
|
+
const progressUpdated = (elapsedMs, bytes, bytesRemaining) => {};
|
|
72
|
+
|
|
68
73
|
let request =
|
|
69
74
|
shaka.net.NetworkingEngine.makeRequest([uri], retryParameters);
|
|
75
|
+
|
|
70
76
|
// eslint-disable-next-line new-cap
|
|
71
|
-
shaka.net.DataUriPlugin(uri, request).promise
|
|
77
|
+
shaka.net.DataUriPlugin(uri, request, requestType, progressUpdated).promise
|
|
72
78
|
.then(function(response) {
|
|
73
79
|
expect(response).toBeTruthy();
|
|
74
80
|
expect(response.uri).toBe(uri);
|
|
@@ -82,10 +88,15 @@ describe('DataUriPlugin', function() {
|
|
|
82
88
|
}
|
|
83
89
|
|
|
84
90
|
function testFails(uri, done, code) {
|
|
91
|
+
// An arbitrary request type.
|
|
92
|
+
const requestType = shaka.net.NetworkingEngine.RequestType.SEGMENT;
|
|
93
|
+
// A dummy progress callback.
|
|
94
|
+
const progressUpdated = (elapsedMs, bytes, bytesRemaining) => {};
|
|
95
|
+
|
|
85
96
|
let request =
|
|
86
97
|
shaka.net.NetworkingEngine.makeRequest([uri], retryParameters);
|
|
87
98
|
// eslint-disable-next-line new-cap
|
|
88
|
-
shaka.net.DataUriPlugin(uri, request).promise
|
|
99
|
+
shaka.net.DataUriPlugin(uri, request, requestType, progressUpdated).promise
|
|
89
100
|
.then(fail)
|
|
90
101
|
.catch(function(error) { expect(error.code).toBe(code); })
|
|
91
102
|
.then(function() {
|
|
@@ -25,6 +25,9 @@ function httpPluginTests(usingFetch) {
|
|
|
25
25
|
// Neither plugin uses the request type, so this is arbitrary.
|
|
26
26
|
const requestType = shaka.net.NetworkingEngine.RequestType.MANIFEST;
|
|
27
27
|
|
|
28
|
+
// A dummy progress callback.
|
|
29
|
+
const progressUpdated = (elapsedMs, bytes, bytesRemaining) => {};
|
|
30
|
+
|
|
28
31
|
/** @type {shaka.extern.RetryParameters} */
|
|
29
32
|
let retryParameters;
|
|
30
33
|
|
|
@@ -169,9 +172,9 @@ function httpPluginTests(usingFetch) {
|
|
|
169
172
|
request.method = 'POST';
|
|
170
173
|
request.headers['BAZ'] = '123';
|
|
171
174
|
|
|
172
|
-
plugin(request.uris[0], request, requestType).promise
|
|
173
|
-
.then(
|
|
174
|
-
|
|
175
|
+
plugin(request.uris[0], request, requestType, progressUpdated).promise
|
|
176
|
+
.then(() => {
|
|
177
|
+
const actual = mostRecentRequest();
|
|
175
178
|
expect(actual).toBeTruthy();
|
|
176
179
|
expect(actual.url).toBe(request.uris[0]);
|
|
177
180
|
expect(actual.method).toBe(request.method);
|
|
@@ -193,9 +196,9 @@ function httpPluginTests(usingFetch) {
|
|
|
193
196
|
request.body = null;
|
|
194
197
|
request.method = 'GET';
|
|
195
198
|
|
|
196
|
-
plugin(request.uris[0], request, requestType).promise
|
|
197
|
-
.then(
|
|
198
|
-
|
|
199
|
+
plugin(request.uris[0], request, requestType, progressUpdated).promise
|
|
200
|
+
.then(() => {
|
|
201
|
+
const actual = jasmine.Fetch.requests.mostRecent();
|
|
199
202
|
expect(actual).toBeTruthy();
|
|
200
203
|
expect(actual.body).toBeUndefined();
|
|
201
204
|
})
|
|
@@ -267,7 +270,7 @@ function httpPluginTests(usingFetch) {
|
|
|
267
270
|
it('detects cache headers', function(done) {
|
|
268
271
|
let request = shaka.net.NetworkingEngine.makeRequest(
|
|
269
272
|
['https://foo.bar/cache'], retryParameters);
|
|
270
|
-
plugin(request.uris[0], request, requestType).promise
|
|
273
|
+
plugin(request.uris[0], request, requestType, progressUpdated).promise
|
|
271
274
|
.catch(fail)
|
|
272
275
|
.then(function(response) {
|
|
273
276
|
expect(response).toBeTruthy();
|
|
@@ -284,7 +287,8 @@ function httpPluginTests(usingFetch) {
|
|
|
284
287
|
if (usingFetch) {
|
|
285
288
|
let request = shaka.net.NetworkingEngine.makeRequest(
|
|
286
289
|
['https://foo.bar/timeout'], retryParameters);
|
|
287
|
-
|
|
290
|
+
const operation = plugin(
|
|
291
|
+
request.uris[0], request, requestType, progressUpdated);
|
|
288
292
|
|
|
289
293
|
/** @type {jasmine.Fetch.RequestStub} */
|
|
290
294
|
let actual = jasmine.Fetch.requests.mostRecent();
|
|
@@ -326,7 +330,8 @@ function httpPluginTests(usingFetch) {
|
|
|
326
330
|
|
|
327
331
|
let request = shaka.net.NetworkingEngine.makeRequest(
|
|
328
332
|
['https://foo.bar/'], retryParameters);
|
|
329
|
-
operation = plugin(
|
|
333
|
+
operation = plugin(
|
|
334
|
+
request.uris[0], request, requestType, progressUpdated);
|
|
330
335
|
requestPromise = operation.promise;
|
|
331
336
|
}
|
|
332
337
|
|
|
@@ -359,7 +364,7 @@ function httpPluginTests(usingFetch) {
|
|
|
359
364
|
function testSucceeds(uri, done, overrideUri) {
|
|
360
365
|
let request = shaka.net.NetworkingEngine.makeRequest(
|
|
361
366
|
[uri], retryParameters);
|
|
362
|
-
plugin(uri, request, requestType).promise
|
|
367
|
+
plugin(uri, request, requestType, progressUpdated).promise
|
|
363
368
|
.catch(fail)
|
|
364
369
|
.then(function(response) {
|
|
365
370
|
expect(mostRecentRequest().url).toBe(uri);
|
|
@@ -385,7 +390,7 @@ function httpPluginTests(usingFetch) {
|
|
|
385
390
|
function testFails(uri, done, severity, code, errorData) {
|
|
386
391
|
let request = shaka.net.NetworkingEngine.makeRequest(
|
|
387
392
|
[uri], retryParameters);
|
|
388
|
-
plugin(uri, request, requestType).promise
|
|
393
|
+
plugin(uri, request, requestType, progressUpdated).promise
|
|
389
394
|
.then(fail)
|
|
390
395
|
.catch(function(error) {
|
|
391
396
|
expect(error).toBeTruthy();
|
|
@@ -414,7 +419,7 @@ function httpPluginTests(usingFetch) {
|
|
|
414
419
|
function testSucceedsWithEmptyLine(uri, done, overrideUri) {
|
|
415
420
|
let request = shaka.net.NetworkingEngine.makeRequest(
|
|
416
421
|
[uri], retryParameters);
|
|
417
|
-
plugin(uri, request, requestType).promise
|
|
422
|
+
plugin(uri, request, requestType, progressUpdated).promise
|
|
418
423
|
.catch(fail)
|
|
419
424
|
.then(function(response) {
|
|
420
425
|
expect(mostRecentRequest().url).toBe(uri);
|
|
@@ -124,7 +124,7 @@ describe('NetworkingEngine', /** @suppress {accessControls} */ function() {
|
|
|
124
124
|
});
|
|
125
125
|
});
|
|
126
126
|
|
|
127
|
-
it('will fail overall',
|
|
127
|
+
it('will fail overall', async () => {
|
|
128
128
|
let request = createRequest('reject://foo', {
|
|
129
129
|
maxAttempts: 3,
|
|
130
130
|
baseDelay: 0,
|
|
@@ -132,13 +132,22 @@ describe('NetworkingEngine', /** @suppress {accessControls} */ function() {
|
|
|
132
132
|
fuzzFactor: 0,
|
|
133
133
|
timeout: 0,
|
|
134
134
|
});
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
135
|
+
|
|
136
|
+
// It is expected to fail with the most recent error, but at a CRITICAL
|
|
137
|
+
// severity, even though the original is at RECOVERABLE.
|
|
138
|
+
|
|
139
|
+
// Check our expectations.
|
|
140
|
+
expect(error.severity).toEqual(shaka.util.Error.Severity.RECOVERABLE);
|
|
141
|
+
|
|
142
|
+
// Modify the expected error. Note that |expected| here is a wrapper
|
|
143
|
+
// created by jasmine, and |expected.sample| is the Object containing the
|
|
144
|
+
// expected values.
|
|
145
|
+
const expected = Util.jasmineError(error);
|
|
146
|
+
expected.sample.severity = shaka.util.Error.Severity.CRITICAL;
|
|
147
|
+
|
|
148
|
+
await expectAsync(networkingEngine.request(requestType, request).promise)
|
|
149
|
+
.toBeRejectedWith(expected);
|
|
150
|
+
expect(rejectScheme.calls.count()).toBe(3);
|
|
142
151
|
});
|
|
143
152
|
|
|
144
153
|
describe('backoff', function() {
|
|
@@ -15,8 +15,14 @@
|
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
describe('OfflineScheme',
|
|
19
|
-
|
|
18
|
+
describe('OfflineScheme', () => {
|
|
19
|
+
// An arbitrary request type.
|
|
20
|
+
const requestType = shaka.net.NetworkingEngine.RequestType.MANIFEST;
|
|
21
|
+
|
|
22
|
+
// A dummy progress callback.
|
|
23
|
+
const progressUpdated = (elapsedMs, bytes, bytesRemaining) => {};
|
|
24
|
+
|
|
25
|
+
beforeEach(checkAndRun(async () => {
|
|
20
26
|
// Make sure we start with a clean slate.
|
|
21
27
|
await clearStorage();
|
|
22
28
|
}));
|
|
@@ -35,8 +41,8 @@ describe('OfflineScheme', function() {
|
|
|
35
41
|
'mechanism', 'cell', 1024);
|
|
36
42
|
|
|
37
43
|
// eslint-disable-next-line new-cap
|
|
38
|
-
|
|
39
|
-
uri.toString(), request).promise;
|
|
44
|
+
const response = await shaka.offline.OfflineScheme(
|
|
45
|
+
uri.toString(), request, requestType, progressUpdated).promise;
|
|
40
46
|
|
|
41
47
|
expect(response).toBeTruthy();
|
|
42
48
|
expect(response.uri).toBe(uri.toString());
|
|
@@ -64,8 +70,8 @@ describe('OfflineScheme', function() {
|
|
|
64
70
|
}
|
|
65
71
|
|
|
66
72
|
// eslint-disable-next-line new-cap
|
|
67
|
-
|
|
68
|
-
uri.toString(), request).promise;
|
|
73
|
+
const response = await shaka.offline.OfflineScheme(
|
|
74
|
+
uri.toString(), request, requestType, progressUpdated).promise;
|
|
69
75
|
|
|
70
76
|
expect(response).toBeTruthy();
|
|
71
77
|
expect(response.data.byteLength).toBe(segment.data.byteLength);
|
|
@@ -95,7 +101,9 @@ describe('OfflineScheme', function() {
|
|
|
95
101
|
|
|
96
102
|
try {
|
|
97
103
|
// eslint-disable-next-line new-cap
|
|
98
|
-
|
|
104
|
+
const op = shaka.offline.OfflineScheme(
|
|
105
|
+
uri.toString(), request, requestType, progressUpdated);
|
|
106
|
+
await op.promise;
|
|
99
107
|
fail();
|
|
100
108
|
} catch (e) {
|
|
101
109
|
expect(e.code).toBe(shaka.util.Error.Code.KEY_NOT_FOUND);
|
|
@@ -108,7 +116,9 @@ describe('OfflineScheme', function() {
|
|
|
108
116
|
|
|
109
117
|
try {
|
|
110
118
|
// eslint-disable-next-line new-cap
|
|
111
|
-
|
|
119
|
+
const op = shaka.offline.OfflineScheme(
|
|
120
|
+
uri, request, requestType, progressUpdated);
|
|
121
|
+
await op.promise;
|
|
112
122
|
fail();
|
|
113
123
|
} catch (e) {
|
|
114
124
|
expect(e.code).toBe(shaka.util.Error.Code.MALFORMED_OFFLINE_URI);
|
package/test/player_external.js
CHANGED
|
@@ -89,7 +89,7 @@ describe('Player', () => {
|
|
|
89
89
|
|
|
90
90
|
let wit = asset.focus ? fit : it;
|
|
91
91
|
wit(testName, async () => {
|
|
92
|
-
if (asset.
|
|
92
|
+
if (!asset.isClear() &&
|
|
93
93
|
!asset.drm.some((keySystem) => support.drm[keySystem])) {
|
|
94
94
|
pending('None of the required key systems are supported.');
|
|
95
95
|
}
|
|
@@ -102,7 +102,8 @@ describe('Player', () => {
|
|
|
102
102
|
if (asset.features.includes(Feature.MP4)) {
|
|
103
103
|
mimeTypes.push('video/mp4');
|
|
104
104
|
}
|
|
105
|
-
if (
|
|
105
|
+
if (mimeTypes.length &&
|
|
106
|
+
!mimeTypes.some((type) => support.media[type])) {
|
|
106
107
|
pending('None of the required MIME types are supported.');
|
|
107
108
|
}
|
|
108
109
|
}
|
|
@@ -137,11 +137,11 @@ describe('Player', function() {
|
|
|
137
137
|
// This should not be null initially.
|
|
138
138
|
expect(textTrack.cues).not.toBe(null);
|
|
139
139
|
|
|
140
|
-
player.setTextTrackVisibility(true);
|
|
140
|
+
await player.setTextTrackVisibility(true);
|
|
141
141
|
// This should definitely not be null when visible.
|
|
142
142
|
expect(textTrack.cues).not.toBe(null);
|
|
143
143
|
|
|
144
|
-
player.setTextTrackVisibility(false);
|
|
144
|
+
await player.setTextTrackVisibility(false);
|
|
145
145
|
// This should not transition to null when invisible.
|
|
146
146
|
expect(textTrack.cues).not.toBe(null);
|
|
147
147
|
}
|
|
@@ -281,7 +281,6 @@ describe('Player', function() {
|
|
|
281
281
|
expect(textTracks[0].language).toEqual('en');
|
|
282
282
|
});
|
|
283
283
|
|
|
284
|
-
|
|
285
284
|
it('while changing languages with short Periods', async () => {
|
|
286
285
|
// See: https://github.com/google/shaka-player/issues/797
|
|
287
286
|
player.configure({preferredAudioLanguage: 'en'});
|
|
@@ -308,6 +307,23 @@ describe('Player', function() {
|
|
|
308
307
|
expect(getActiveLanguage()).toBe('es');
|
|
309
308
|
});
|
|
310
309
|
|
|
310
|
+
it('at higher playback rates', async () => {
|
|
311
|
+
await player.load('test:sintel_compiled');
|
|
312
|
+
video.play();
|
|
313
|
+
await waitUntilPlayheadReaches(eventManager, video, 1, 10);
|
|
314
|
+
|
|
315
|
+
// Enabling trick play should change our playback rate to the same rate.
|
|
316
|
+
player.trickPlay(2);
|
|
317
|
+
expect(video.playbackRate).toBe(2);
|
|
318
|
+
|
|
319
|
+
// Let playback continue playing for a bit longer.
|
|
320
|
+
await shaka.test.Util.delay(2);
|
|
321
|
+
|
|
322
|
+
// Cancelling trick play should return our playback rate to normal.
|
|
323
|
+
player.cancelTrickPlay();
|
|
324
|
+
expect(video.playbackRate).toBe(1);
|
|
325
|
+
});
|
|
326
|
+
|
|
311
327
|
/**
|
|
312
328
|
* Gets the language of the active Variant.
|
|
313
329
|
* @return {string}
|
|
@@ -448,6 +464,81 @@ describe('Player', function() {
|
|
|
448
464
|
}).catch(fail).then(done);
|
|
449
465
|
});
|
|
450
466
|
});
|
|
467
|
+
|
|
468
|
+
describe('tracks', () => {
|
|
469
|
+
// This is a regression test for b/138941217, in which tracks briefly
|
|
470
|
+
// vanished during the loading process. On Chromecast devices, where the
|
|
471
|
+
// timing is very different from on desktop, this could occur such that
|
|
472
|
+
// there were no tracks after load() is resolved.
|
|
473
|
+
// This is an integration test so that we can check the behavior of the
|
|
474
|
+
// Player against actual platform behavior on all supported platforms.
|
|
475
|
+
it('remain available at every stage of loading', async () => {
|
|
476
|
+
let tracksFound = false;
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* @param {string} when When the check takes place.
|
|
480
|
+
*
|
|
481
|
+
* Will fail the test if tracks disappear after they first become
|
|
482
|
+
* available.
|
|
483
|
+
*/
|
|
484
|
+
const checkTracks = (when) => {
|
|
485
|
+
// If tracks have already been found, expect them to still be found.
|
|
486
|
+
const tracksNow = player.getVariantTracks().length != 0;
|
|
487
|
+
if (tracksFound) {
|
|
488
|
+
expect(tracksNow).toBe(true);
|
|
489
|
+
} else {
|
|
490
|
+
// If tracks are now found, they should not, at any point during
|
|
491
|
+
// the loading process, disappear again.
|
|
492
|
+
if (tracksNow) {
|
|
493
|
+
tracksFound = true;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
shaka.log.debug(
|
|
497
|
+
'checkTracks', when,
|
|
498
|
+
'tracksFound=', tracksFound,
|
|
499
|
+
'tracksNow=', tracksNow);
|
|
500
|
+
};
|
|
501
|
+
|
|
502
|
+
/** @param {Event} event */
|
|
503
|
+
const checkOnEvent = (event) => {
|
|
504
|
+
checkTracks(event.type + ' event');
|
|
505
|
+
};
|
|
506
|
+
|
|
507
|
+
// On each of these events, we will notice when tracks first appear, and
|
|
508
|
+
// verify that they never disappear at any point in the loading sequence.
|
|
509
|
+
eventManager.listen(video, 'canplay', checkOnEvent);
|
|
510
|
+
eventManager.listen(video, 'canplaythrough', checkOnEvent);
|
|
511
|
+
eventManager.listen(video, 'durationchange', checkOnEvent);
|
|
512
|
+
eventManager.listen(video, 'emptied', checkOnEvent);
|
|
513
|
+
eventManager.listen(video, 'loadeddata', checkOnEvent);
|
|
514
|
+
eventManager.listen(video, 'loadedmetadata', checkOnEvent);
|
|
515
|
+
eventManager.listen(video, 'loadstart', checkOnEvent);
|
|
516
|
+
eventManager.listen(video, 'pause', checkOnEvent);
|
|
517
|
+
eventManager.listen(video, 'play', checkOnEvent);
|
|
518
|
+
eventManager.listen(video, 'playing', checkOnEvent);
|
|
519
|
+
eventManager.listen(video, 'seeked', checkOnEvent);
|
|
520
|
+
eventManager.listen(video, 'seeking', checkOnEvent);
|
|
521
|
+
eventManager.listen(video, 'stalled', checkOnEvent);
|
|
522
|
+
eventManager.listen(video, 'waiting', checkOnEvent);
|
|
523
|
+
eventManager.listen(player, 'trackschanged', checkOnEvent);
|
|
524
|
+
|
|
525
|
+
const waiter = (new shaka.test.Waiter(eventManager)).timeoutAfter(10);
|
|
526
|
+
const canPlayThrough = waiter.waitForEvent(video, 'canplaythrough');
|
|
527
|
+
|
|
528
|
+
// Important: use a stream that starts somewhere other than zero, so that
|
|
529
|
+
// the video element's time is initially different from the start time of
|
|
530
|
+
// playback, and there is no content at time zero.
|
|
531
|
+
await player.load('test:sintel_start_at_3_compiled', 5);
|
|
532
|
+
shaka.log.debug('load resolved');
|
|
533
|
+
|
|
534
|
+
// When load is resolved(), tracks should definitely exist.
|
|
535
|
+
expect(tracksFound).toBe(true);
|
|
536
|
+
|
|
537
|
+
// Let the test keep running until we can play through. In the original
|
|
538
|
+
// bug, tracks would disappear _after_ load() on some platforms.
|
|
539
|
+
await canPlayThrough;
|
|
540
|
+
});
|
|
541
|
+
});
|
|
451
542
|
});
|
|
452
543
|
|
|
453
544
|
// TODO(vaage): Try to group the stat tests together.
|
|
@@ -278,10 +278,10 @@ describe('Player Src Equals', () => {
|
|
|
278
278
|
|
|
279
279
|
expect(player.isTextTrackVisible()).toBe(false);
|
|
280
280
|
|
|
281
|
-
player.setTextTrackVisibility(true);
|
|
281
|
+
await player.setTextTrackVisibility(true);
|
|
282
282
|
expect(player.isTextTrackVisible()).toBe(true);
|
|
283
283
|
|
|
284
|
-
player.setTextTrackVisibility(false);
|
|
284
|
+
await player.setTextTrackVisibility(false);
|
|
285
285
|
expect(player.isTextTrackVisible()).toBe(false);
|
|
286
286
|
});
|
|
287
287
|
|
package/test/player_unit.js
CHANGED
|
@@ -308,30 +308,30 @@ describe('Player', function() {
|
|
|
308
308
|
|
|
309
309
|
it('load text stream if caption is visible', async () => {
|
|
310
310
|
await player.load(fakeManifestUri, 0, returnManifest(manifest));
|
|
311
|
-
player.setTextTrackVisibility(true);
|
|
311
|
+
await player.setTextTrackVisibility(true);
|
|
312
312
|
expect(streamingEngine.loadNewTextStream).toHaveBeenCalled();
|
|
313
313
|
expect(streamingEngine.getBufferingText()).not.toBe(null);
|
|
314
314
|
});
|
|
315
315
|
|
|
316
316
|
it('does not load text stream if caption is invisible', async () => {
|
|
317
317
|
await player.load(fakeManifestUri, 0, returnManifest(manifest));
|
|
318
|
-
player.setTextTrackVisibility(false);
|
|
318
|
+
await player.setTextTrackVisibility(false);
|
|
319
319
|
expect(streamingEngine.loadNewTextStream).not.toHaveBeenCalled();
|
|
320
320
|
expect(streamingEngine.getBufferingText()).toBe(null);
|
|
321
321
|
});
|
|
322
322
|
|
|
323
323
|
it('loads text stream if alwaysStreamText is set', async () => {
|
|
324
|
-
player.setTextTrackVisibility(false);
|
|
324
|
+
await player.setTextTrackVisibility(false);
|
|
325
325
|
player.configure({streaming: {alwaysStreamText: true}});
|
|
326
326
|
|
|
327
327
|
await player.load(fakeManifestUri, 0, returnManifest(manifest));
|
|
328
328
|
expect(streamingEngine.getBufferingText()).not.toBe(null);
|
|
329
329
|
|
|
330
|
-
player.setTextTrackVisibility(true);
|
|
330
|
+
await player.setTextTrackVisibility(true);
|
|
331
331
|
expect(streamingEngine.loadNewTextStream).not.toHaveBeenCalled();
|
|
332
332
|
expect(streamingEngine.unloadTextStream).not.toHaveBeenCalled();
|
|
333
333
|
|
|
334
|
-
player.setTextTrackVisibility(false);
|
|
334
|
+
await player.setTextTrackVisibility(false);
|
|
335
335
|
expect(streamingEngine.loadNewTextStream).not.toHaveBeenCalled();
|
|
336
336
|
expect(streamingEngine.unloadTextStream).not.toHaveBeenCalled();
|
|
337
337
|
});
|
|
@@ -1569,6 +1569,19 @@ describe('Player', function() {
|
|
|
1569
1569
|
expect(getActiveTextTrack().language).toBe('en');
|
|
1570
1570
|
});
|
|
1571
1571
|
|
|
1572
|
+
// https://github.com/google/shaka-player/issues/2010
|
|
1573
|
+
it('changing text lang changes active stream when not streaming', () => {
|
|
1574
|
+
streamingEngine.onCanSwitch();
|
|
1575
|
+
player.setTextTrackVisibility(false);
|
|
1576
|
+
|
|
1577
|
+
expect(getActiveTextTrack().language).not.toBe('en');
|
|
1578
|
+
expect(streamingEngine.switchTextStream).not.toHaveBeenCalled();
|
|
1579
|
+
player.selectTextLanguage('en');
|
|
1580
|
+
|
|
1581
|
+
expect(streamingEngine.switchTextStream).not.toHaveBeenCalled();
|
|
1582
|
+
expect(getActiveTextTrack().language).toBe('en');
|
|
1583
|
+
});
|
|
1584
|
+
|
|
1572
1585
|
it('remembers the channel count when ABR is reenabled', () => {
|
|
1573
1586
|
streamingEngine.onCanSwitch();
|
|
1574
1587
|
|
|
@@ -1701,7 +1714,7 @@ describe('Player', function() {
|
|
|
1701
1714
|
expect(player.isTextTrackVisible()).toBe(true);
|
|
1702
1715
|
|
|
1703
1716
|
// Turn text back off.
|
|
1704
|
-
player.setTextTrackVisibility(false);
|
|
1717
|
+
await player.setTextTrackVisibility(false);
|
|
1705
1718
|
expect(player.isTextTrackVisible()).toBe(false);
|
|
1706
1719
|
|
|
1707
1720
|
// Change text languages after startup.
|
|
@@ -2817,8 +2830,8 @@ describe('Player', function() {
|
|
|
2817
2830
|
});
|
|
2818
2831
|
|
|
2819
2832
|
describe('setTextTrackVisibility', function() {
|
|
2820
|
-
it('does not throw before load', function() {
|
|
2821
|
-
player.setTextTrackVisibility(true);
|
|
2833
|
+
it('does not throw before load', async function() {
|
|
2834
|
+
await player.setTextTrackVisibility(true);
|
|
2822
2835
|
});
|
|
2823
2836
|
});
|
|
2824
2837
|
|
package/test/test/boot.js
CHANGED
|
@@ -102,8 +102,10 @@ function getClientArg(name) {
|
|
|
102
102
|
// the first time it needs to schedule something.
|
|
103
103
|
Promise.resolve().then(function() {});
|
|
104
104
|
|
|
105
|
-
|
|
106
|
-
|
|
105
|
+
const timeout = getClientArg('testTimeout');
|
|
106
|
+
if (timeout) {
|
|
107
|
+
jasmine.DEFAULT_TIMEOUT_INTERVAL = Number(timeout);
|
|
108
|
+
}
|
|
107
109
|
|
|
108
110
|
let logLevel = getClientArg('logLevel');
|
|
109
111
|
if (logLevel) {
|
|
@@ -199,9 +201,12 @@ function getClientArg(name) {
|
|
|
199
201
|
// Load required AMD modules, then proceed with tests.
|
|
200
202
|
require(['promise-mock', 'sprintf-js', 'less'],
|
|
201
203
|
(PromiseMock, sprintfJs, less) => {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
204
|
+
// These external interfaces are declared as "const" in the externs.
|
|
205
|
+
// Avoid "const"-ness complaints from the compiler by assigning these
|
|
206
|
+
// using bracket notation.
|
|
207
|
+
window['PromiseMock'] = PromiseMock;
|
|
208
|
+
window['sprintf'] = sprintfJs.sprintf;
|
|
209
|
+
window['less'] = less;
|
|
205
210
|
|
|
206
211
|
// Patch a new convenience method into PromiseMock.
|
|
207
212
|
// See https://github.com/taylorhakes/promise-mock/issues/7
|
|
@@ -231,4 +236,14 @@ function getClientArg(name) {
|
|
|
231
236
|
originalSetTimeout(done, 100 /* ms */);
|
|
232
237
|
});
|
|
233
238
|
}
|
|
239
|
+
|
|
240
|
+
// Code in karma-jasmine's adapter will malform test failures when the
|
|
241
|
+
// expectation message contains a stack trace, losing the failure message and
|
|
242
|
+
// mixing up the stack trace of the failure. To avoid this, we modify
|
|
243
|
+
// shaka.util.Error not to create a stack trace. This trace is not available
|
|
244
|
+
// in production, and there is never any need for it in the tests.
|
|
245
|
+
// Shimming shaka.util.Error proved too complicated because of a combination
|
|
246
|
+
// of compiler restrictions and ES6 language features, so this is by far the
|
|
247
|
+
// simpler answer.
|
|
248
|
+
shaka.util.Error.createStack = false;
|
|
234
249
|
})();
|
|
@@ -65,6 +65,13 @@ jasmine.Spec.prototype.getFullName = function() {};
|
|
|
65
65
|
jasmine.Matchers = function() {};
|
|
66
66
|
|
|
67
67
|
|
|
68
|
+
/**
|
|
69
|
+
* @constructor
|
|
70
|
+
* @struct
|
|
71
|
+
*/
|
|
72
|
+
jasmine.MatchersAsync = function() {};
|
|
73
|
+
|
|
74
|
+
|
|
68
75
|
/**
|
|
69
76
|
* @param {*} value
|
|
70
77
|
* @return {!jasmine.Matchers}
|
|
@@ -72,6 +79,13 @@ jasmine.Matchers = function() {};
|
|
|
72
79
|
var expect = function(value) {};
|
|
73
80
|
|
|
74
81
|
|
|
82
|
+
/**
|
|
83
|
+
* @param {!Promise} value
|
|
84
|
+
* @return {!jasmine.MatchersAsync}
|
|
85
|
+
*/
|
|
86
|
+
var expectAsync = function(value) {};
|
|
87
|
+
|
|
88
|
+
|
|
75
89
|
/** @param {string=} message */
|
|
76
90
|
var pending = function(message) {};
|
|
77
91
|
|
|
@@ -173,6 +187,40 @@ jasmine.Matchers.prototype.toHaveBeenCalledOnceMore = function() {};
|
|
|
173
187
|
*/
|
|
174
188
|
jasmine.Matchers.prototype.toHaveBeenCalledOnceMoreWith = function(args) {};
|
|
175
189
|
|
|
190
|
+
/**
|
|
191
|
+
* @param {string} message
|
|
192
|
+
* @return {!jasmine.Matchers}
|
|
193
|
+
*/
|
|
194
|
+
jasmine.Matchers.prototype.withContext = function(message) {};
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
/** @type {!jasmine.MatchersAsync} */
|
|
198
|
+
jasmine.MatchersAsync.prototype.not;
|
|
199
|
+
|
|
200
|
+
/** @return {!Promise} */
|
|
201
|
+
jasmine.MatchersAsync.prototype.toBeRejected = function() {};
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* @param {*} expected
|
|
205
|
+
* @return {!Promise}
|
|
206
|
+
*/
|
|
207
|
+
jasmine.MatchersAsync.prototype.toBeRejectedWith = function(expected) {};
|
|
208
|
+
|
|
209
|
+
/** @return {!Promise} */
|
|
210
|
+
jasmine.MatchersAsync.prototype.toBeResolved = function() {};
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* @param {*} expected
|
|
214
|
+
* @return {!Promise}
|
|
215
|
+
*/
|
|
216
|
+
jasmine.MatchersAsync.prototype.toBeResolvedTo = function(expected) {};
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* @param {string} message
|
|
220
|
+
* @return {!jasmine.MatchersAsync}
|
|
221
|
+
*/
|
|
222
|
+
jasmine.MatchersAsync.prototype.withContext = function(message) {};
|
|
223
|
+
|
|
176
224
|
|
|
177
225
|
/**
|
|
178
226
|
* @constructor
|