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
package/lib/util/string_utils.js
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
goog.provide('shaka.util.StringUtils');
|
|
19
19
|
|
|
20
|
+
goog.require('goog.asserts');
|
|
20
21
|
goog.require('shaka.log');
|
|
21
22
|
goog.require('shaka.util.Error');
|
|
22
23
|
|
|
@@ -212,12 +213,47 @@ shaka.util.StringUtils.toUTF16 = function(str, littleEndian) {
|
|
|
212
213
|
* @return {string}
|
|
213
214
|
*/
|
|
214
215
|
shaka.util.StringUtils.fromCharCode = function(array) {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
216
|
+
// Check the browser for what chunk sizes it supports. Cache the result
|
|
217
|
+
// in an impl method to avoid checking several times.
|
|
218
|
+
if (!shaka.util.StringUtils.fromCharCodeImpl_) {
|
|
219
|
+
const supportsChunkSize = (size) => {
|
|
220
|
+
try {
|
|
221
|
+
const buffer = new Uint8Array(size);
|
|
222
|
+
// The compiler will complain about suspicious value if this isn't
|
|
223
|
+
// stored in a variable and used.
|
|
224
|
+
const foo = String.fromCharCode(...buffer);
|
|
225
|
+
goog.asserts.assert(foo, 'Should get value');
|
|
226
|
+
return true;
|
|
227
|
+
} catch (error) {
|
|
228
|
+
return false;
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
// Different browsers support different chunk sizes; find out the largest
|
|
233
|
+
// this browser supports so we can use larger chunks on supported browsers
|
|
234
|
+
// but still support lower-end devices that require small chunks.
|
|
235
|
+
// 64k is supported on all major desktop browsers.
|
|
236
|
+
for (let size = 64 * 1024; size > 0; size /= 2) {
|
|
237
|
+
if (supportsChunkSize(size)) {
|
|
238
|
+
shaka.util.StringUtils.fromCharCodeImpl_ = (buffer) => {
|
|
239
|
+
let ret = '';
|
|
240
|
+
for (let i = 0; i < buffer.length; i += size) {
|
|
241
|
+
const subArray = buffer.subarray(i, i + size);
|
|
242
|
+
ret += String.fromCharCode(...subArray);
|
|
243
|
+
}
|
|
244
|
+
return ret;
|
|
245
|
+
};
|
|
246
|
+
break;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
220
249
|
}
|
|
221
250
|
|
|
222
|
-
|
|
251
|
+
goog.asserts.assert(
|
|
252
|
+
shaka.util.StringUtils.fromCharCodeImpl_,
|
|
253
|
+
'Unable to create a fromCharCode method');
|
|
254
|
+
return shaka.util.StringUtils.fromCharCodeImpl_(array);
|
|
223
255
|
};
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
/** @private {?function(!TypedArray):string} */
|
|
259
|
+
shaka.util.StringUtils.fromCharCodeImpl_ = null;
|
package/lib/util/timer.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shaka-player",
|
|
3
3
|
"description": "DASH/EME video player library",
|
|
4
|
-
"version": "2.5.
|
|
4
|
+
"version": "2.5.5",
|
|
5
5
|
"homepage": "https://github.com/google/shaka-player",
|
|
6
6
|
"author": "Google",
|
|
7
7
|
"maintainers": [
|
|
@@ -11,47 +11,47 @@
|
|
|
11
11
|
}
|
|
12
12
|
],
|
|
13
13
|
"devDependencies": {
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"babel-
|
|
14
|
+
"awesomplete": "^1.1.4",
|
|
15
|
+
"babel-core": "^6.26.3",
|
|
16
|
+
"babel-plugin-istanbul": "^4.1.6",
|
|
17
17
|
"babel-polyfill": "^6.26.0",
|
|
18
|
-
"babel-preset-env": "^1.
|
|
18
|
+
"babel-preset-env": "^1.7.0",
|
|
19
19
|
"cajon": "^0.4.4",
|
|
20
|
-
"dialog-polyfill": "^0.
|
|
20
|
+
"dialog-polyfill": "^0.5.0",
|
|
21
21
|
"es6-promise-polyfill": "^1.2.0",
|
|
22
|
-
"
|
|
23
|
-
"eslint": "^4.14.0",
|
|
22
|
+
"eslint": "^5.16.0",
|
|
24
23
|
"eslint-config-google": "^0.9.1",
|
|
25
|
-
"esprima": "^4.0.
|
|
26
|
-
"htmlhint": "
|
|
27
|
-
"
|
|
28
|
-
"jasmine-ajax": "~3.3.1",
|
|
24
|
+
"esprima": "^4.0.1",
|
|
25
|
+
"htmlhint": "^0.11.0",
|
|
26
|
+
"jasmine-ajax": "^3.3.1",
|
|
29
27
|
"jasmine-core": "^2.8.0",
|
|
30
|
-
"jsdoc": "joeyparrish/jsdoc#
|
|
31
|
-
"karma": "
|
|
28
|
+
"jsdoc": "github:joeyparrish/jsdoc#45c271fa",
|
|
29
|
+
"karma": "^4.1.0",
|
|
32
30
|
"karma-babel-preprocessor": "^7.0.0",
|
|
33
|
-
"karma-chrome-launcher": "
|
|
34
|
-
"karma-coverage": "
|
|
35
|
-
"karma-edge-launcher": "
|
|
36
|
-
"karma-firefox-launcher": "
|
|
37
|
-
"karma-ie-launcher": "
|
|
38
|
-
"karma-jasmine": "
|
|
39
|
-
"karma-jasmine-ajax": "
|
|
40
|
-
"karma-opera-launcher": "
|
|
41
|
-
"karma-safari-launcher": "
|
|
42
|
-
"karma-
|
|
43
|
-
"karma-spec-reporter": "
|
|
44
|
-
"karma-webdriver-launcher": "
|
|
45
|
-
"less": "^3.
|
|
31
|
+
"karma-chrome-launcher": "^2.2.0",
|
|
32
|
+
"karma-coverage": "^1.1.2",
|
|
33
|
+
"karma-edge-launcher": "^0.4.2",
|
|
34
|
+
"karma-firefox-launcher": "^1.1.0",
|
|
35
|
+
"karma-ie-launcher": "^1.0.0",
|
|
36
|
+
"karma-jasmine": "^1.1.0",
|
|
37
|
+
"karma-jasmine-ajax": "^0.1.13",
|
|
38
|
+
"karma-opera-launcher": "^1.0.0",
|
|
39
|
+
"karma-safari-launcher": "^1.0.0",
|
|
40
|
+
"karma-sourcemap-loader": "^0.3.7",
|
|
41
|
+
"karma-spec-reporter": "0.0.32",
|
|
42
|
+
"karma-webdriver-launcher": "^1.0.7",
|
|
43
|
+
"less": "^3.9.0",
|
|
46
44
|
"less-plugin-clean-css": "^1.5.1",
|
|
47
45
|
"material-design-lite": "^1.3.0",
|
|
48
46
|
"mux.js": "^5.1.3",
|
|
49
47
|
"promise-mock": "^2.1.0",
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
48
|
+
"promise-polyfill": "<8.1.1",
|
|
49
|
+
"rimraf": "^2.6.3",
|
|
50
|
+
"sprintf-js": "^1.1.2",
|
|
51
|
+
"stylelint": "github:theodab/stylelint",
|
|
52
|
+
"stylelint-config-standard": "^18.3.0",
|
|
53
|
+
"tippy.js": "^4.3.1",
|
|
54
|
+
"which": "^1.3.1"
|
|
55
55
|
},
|
|
56
56
|
"main": "dist/shaka-player.compiled.js",
|
|
57
57
|
"repository": {
|
|
@@ -63,6 +63,6 @@
|
|
|
63
63
|
},
|
|
64
64
|
"license": "Apache-2.0",
|
|
65
65
|
"scripts": {
|
|
66
|
-
"
|
|
66
|
+
"prepublishOnly": "python build/checkversion.py && python build/all.py --force"
|
|
67
67
|
}
|
|
68
68
|
}
|
package/roadmap.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Shaka Player Roadmap
|
|
2
|
+
|
|
3
|
+
This doc shows all past and planned future milestones for Shaka Player, with
|
|
4
|
+
brief details about the goals and rough dates of each milestone. This is not a
|
|
5
|
+
comprehensive list of features or fixes for each release. For that, see
|
|
6
|
+
CHANGELOG.md.
|
|
7
|
+
|
|
8
|
+
The goals of future milestones are fluid until we begin that development cycle,
|
|
9
|
+
so the exact milestone for future features is not pre-determined.
|
|
10
|
+
|
|
11
|
+
Candidate features for future release cycles
|
|
12
|
+
- HLS discontinuity support
|
|
13
|
+
- Low-latency live (LHLS, equivalent for DASH)
|
|
14
|
+
- MediaCapabilities to make performance-based decisions
|
|
15
|
+
- Codec-switching
|
|
16
|
+
- Background fetch for offline storage
|
|
17
|
+
- Preload API
|
|
18
|
+
- Thumbnail tracks
|
|
19
|
+
- Own CEA parser, use mux.js only for TS
|
|
20
|
+
- Smaller, more modular binary
|
|
21
|
+
- IMA SDK ad integration demo
|
|
22
|
+
- Ad controls in the UI
|
|
23
|
+
|
|
24
|
+
v2.6 - 2019 Q3 (estimated)
|
|
25
|
+
- Code health release
|
|
26
|
+
- Finish conversion to ES6
|
|
27
|
+
- Isolate DASH periods to the DASH parser
|
|
28
|
+
|
|
29
|
+
=====
|
|
30
|
+
|
|
31
|
+
v2.5 - 2019 Q2
|
|
32
|
+
- Video controls UI API
|
|
33
|
+
- FairPlay & iOS support
|
|
34
|
+
- CEA captions in HLS/CMAF and DASH w/ mux.js
|
|
35
|
+
- Single-file playback
|
|
36
|
+
- DASH drift tolerance
|
|
37
|
+
|
|
38
|
+
v2.4 - 2018 Q2
|
|
39
|
+
- TTML and VTT regions
|
|
40
|
+
- CEA captions in HLS/TS
|
|
41
|
+
- Attach/detach API
|
|
42
|
+
|
|
43
|
+
v2.3 - 2017 Q4
|
|
44
|
+
- HLS live
|
|
45
|
+
- Transmux TS w/ mux.js
|
|
46
|
+
- NetworkInformation API to improve bandwidth estimates
|
|
47
|
+
- ES6 transition begins
|
|
48
|
+
|
|
49
|
+
v2.2 - 2017 Q3
|
|
50
|
+
- HLS event-type playlists
|
|
51
|
+
- TextDisplayer interface
|
|
52
|
+
- DASH xlink support
|
|
53
|
+
|
|
54
|
+
v2.1 - 2017 Q2
|
|
55
|
+
- HLS VOD, clear & Widevine only, no CEA
|
|
56
|
+
- DASH trick mode tracks
|
|
57
|
+
- Async network filters
|
|
58
|
+
|
|
59
|
+
v2.0 - 2016 Q3
|
|
60
|
+
- Multi-period DASH
|
|
61
|
+
- Chromecast API
|
|
62
|
+
- TTML, VTT-in-MP4, and TTML-in-MP4
|
|
63
|
+
- Safari, Firefox, & Opera support
|
|
64
|
+
- Plugin system (manifest parsers, network filters, text parsers)
|
|
65
|
+
- DASH emsg box support
|
|
66
|
+
- DASH IPR support
|
|
67
|
+
|
|
68
|
+
v1.6 - 2015 Q4
|
|
69
|
+
- IE11, Edge, & PlayReady support
|
|
70
|
+
- Chromecast added to demo app
|
|
71
|
+
|
|
72
|
+
v1.5 - 2015 Q3
|
|
73
|
+
- Unified configuration system
|
|
74
|
+
- Multiple DASH BaseURL elements for failover
|
|
75
|
+
- Side-loaded text streams
|
|
76
|
+
|
|
77
|
+
v1.4 - 2015 Q3
|
|
78
|
+
- Code health release
|
|
79
|
+
- DASH Location element support
|
|
80
|
+
- Buffering config API
|
|
81
|
+
- License preprocessing API
|
|
82
|
+
|
|
83
|
+
v1.3 - 2015 Q2
|
|
84
|
+
- DASH live
|
|
85
|
+
- Offline playback
|
|
86
|
+
|
|
87
|
+
v1.2 - 2015 Q1
|
|
88
|
+
- DASH Role element support
|
|
89
|
+
|
|
90
|
+
v1.1 - 2015 Q1
|
|
91
|
+
- EME API updates
|
|
92
|
+
|
|
93
|
+
v1.0 - 2014 Q4
|
|
94
|
+
- DASH VOD (MP4 & WebM)
|
|
95
|
+
- VTT subtitles, rendered by the browser
|
|
96
|
+
- Widevine support
|
|
@@ -64,8 +64,11 @@ goog.require('shaka.text.TextEngine');
|
|
|
64
64
|
goog.require('shaka.text.TtmlTextParser');
|
|
65
65
|
goog.require('shaka.text.VttTextParser');
|
|
66
66
|
goog.require('shaka.ui.Controls');
|
|
67
|
+
goog.require('shaka.ui.PlayButton');
|
|
68
|
+
goog.require('shaka.ui.SettingsMenu');
|
|
67
69
|
goog.require('shaka.ui.OverflowMenu');
|
|
68
70
|
goog.require('shaka.ui.AudioLanguageSelection');
|
|
71
|
+
goog.require('shaka.ui.BigPlayButton');
|
|
69
72
|
goog.require('shaka.ui.CastButton');
|
|
70
73
|
goog.require('shaka.ui.Element');
|
|
71
74
|
goog.require('shaka.ui.FastForwardButton');
|
|
@@ -74,7 +77,7 @@ goog.require('shaka.ui.Localization');
|
|
|
74
77
|
goog.require('shaka.ui.MuteButton');
|
|
75
78
|
goog.require('shaka.ui.Overlay');
|
|
76
79
|
goog.require('shaka.ui.PipButton');
|
|
77
|
-
goog.require('shaka.ui.
|
|
80
|
+
goog.require('shaka.ui.SmallPlayButton');
|
|
78
81
|
goog.require('shaka.ui.PresentationTimeTracker');
|
|
79
82
|
goog.require('shaka.ui.ResolutionSelection');
|
|
80
83
|
goog.require('shaka.ui.RewindButton');
|
|
@@ -83,4 +86,5 @@ goog.require('shaka.ui.TextSelection');
|
|
|
83
86
|
goog.require('shaka.ui.VolumeBar');
|
|
84
87
|
goog.require('shaka.util.Dom');
|
|
85
88
|
goog.require('shaka.util.Error');
|
|
89
|
+
goog.require('shaka.util.FairPlayUtils');
|
|
86
90
|
goog.require('shaka.util.Iterables');
|
|
@@ -68,7 +68,8 @@ describe('DashParser ContentProtection', function() {
|
|
|
68
68
|
adaptationSetLines, representation1Lines, representation2Lines) {
|
|
69
69
|
let template = [
|
|
70
70
|
'<MPD xmlns="urn:mpeg:DASH:schema:MPD:2011"',
|
|
71
|
-
' xmlns:cenc="urn:mpeg:cenc:2013"
|
|
71
|
+
' xmlns:cenc="urn:mpeg:cenc:2013"',
|
|
72
|
+
' xmlns:mspr="urn:microsoft:playready">',
|
|
72
73
|
' <Period duration="PT30S">',
|
|
73
74
|
' <SegmentTemplate media="s.mp4" duration="2" />',
|
|
74
75
|
' <AdaptationSet mimeType="video/mp4" codecs="avc1.4d401f">',
|
|
@@ -298,6 +299,39 @@ describe('DashParser ContentProtection', function() {
|
|
|
298
299
|
await testDashParser(source, expected);
|
|
299
300
|
});
|
|
300
301
|
|
|
302
|
+
it('extracts embedded PSSHs with mspr:pro', async () => {
|
|
303
|
+
const source = buildManifestText([
|
|
304
|
+
// AdaptationSet lines
|
|
305
|
+
'<ContentProtection',
|
|
306
|
+
' schemeIdUri="urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95">',
|
|
307
|
+
' <mspr:pro>UGxheXJlYWR5</mspr:pro>',
|
|
308
|
+
'</ContentProtection>',
|
|
309
|
+
], [], []);
|
|
310
|
+
const expected = buildExpectedManifest([
|
|
311
|
+
buildDrmInfo('com.microsoft.playready', [], [
|
|
312
|
+
'AAAAKXBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAAlQbGF5cmVhZHk=',
|
|
313
|
+
]),
|
|
314
|
+
]);
|
|
315
|
+
await testDashParser(source, expected);
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
it('extracts embedded PSSHs and prefer cenc:pssh over mspr:pro', async () => {
|
|
319
|
+
const source = buildManifestText([
|
|
320
|
+
// AdaptationSet lines
|
|
321
|
+
'<ContentProtection',
|
|
322
|
+
' schemeIdUri="urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95">',
|
|
323
|
+
' <cenc:pssh>bm8gaHVtYW4gY2FuIHJlYWQgYmFzZTY0IGRpcmVjdGx5</cenc:pssh>',
|
|
324
|
+
' <mspr:pro>ZmFrZSBQbGF5cmVhZHkgUFJP</mspr:pro>',
|
|
325
|
+
'</ContentProtection>',
|
|
326
|
+
], [], []);
|
|
327
|
+
const expected = buildExpectedManifest([
|
|
328
|
+
buildDrmInfo('com.microsoft.playready', [], [
|
|
329
|
+
'bm8gaHVtYW4gY2FuIHJlYWQgYmFzZTY0IGRpcmVjdGx5',
|
|
330
|
+
]),
|
|
331
|
+
]);
|
|
332
|
+
await testDashParser(source, expected);
|
|
333
|
+
});
|
|
334
|
+
|
|
301
335
|
it('assumes all known key systems for generic CENC', async () => {
|
|
302
336
|
let source = buildManifestText([
|
|
303
337
|
// AdaptationSet lines
|
|
@@ -1215,4 +1215,64 @@ describe('DashParser Manifest', function() {
|
|
|
1215
1215
|
const minBufferTime = manifest.minBufferTime;
|
|
1216
1216
|
expect(minBufferTime).toEqual(75);
|
|
1217
1217
|
});
|
|
1218
|
+
|
|
1219
|
+
it('does not set presentationDelay to NaN', async () => {
|
|
1220
|
+
// NOTE: This is a regression test for #2015. It ensures that, if
|
|
1221
|
+
// ignoreMinBufferTime is true and there is no suggestedPresentationDelay,
|
|
1222
|
+
// we do not erroneously set presentationDelay to NaN.
|
|
1223
|
+
const manifestText = [
|
|
1224
|
+
'<MPD minBufferTime="PT75S">',
|
|
1225
|
+
' <Period id="1" duration="PT30S">',
|
|
1226
|
+
' <AdaptationSet id="1" mimeType="video/mp4">',
|
|
1227
|
+
' <Representation id="video-sd" width="640" height="480">',
|
|
1228
|
+
' <BaseURL>v-sd.mp4</BaseURL>',
|
|
1229
|
+
' <SegmentBase indexRange="100-200" />',
|
|
1230
|
+
' </Representation>',
|
|
1231
|
+
' </AdaptationSet>',
|
|
1232
|
+
' </Period>',
|
|
1233
|
+
'</MPD>',
|
|
1234
|
+
].join('\n');
|
|
1235
|
+
|
|
1236
|
+
fakeNetEngine.setResponseText('dummy://foo', manifestText);
|
|
1237
|
+
const config = shaka.util.PlayerConfiguration.createDefault().manifest;
|
|
1238
|
+
config.dash.ignoreMinBufferTime = true;
|
|
1239
|
+
parser.configure(config);
|
|
1240
|
+
|
|
1241
|
+
const manifest = await parser.start('dummy://foo', playerInterface);
|
|
1242
|
+
const presentationTimeline = manifest.presentationTimeline;
|
|
1243
|
+
const presentationDelay = presentationTimeline.getDelay();
|
|
1244
|
+
expect(presentationDelay).not.toBeNaN();
|
|
1245
|
+
expect(presentationDelay).toBe(config.dash.defaultPresentationDelay);
|
|
1246
|
+
});
|
|
1247
|
+
|
|
1248
|
+
it('converts Accessibility element to "kind"', async () => {
|
|
1249
|
+
const manifestText = [
|
|
1250
|
+
'<MPD minBufferTime="PT75S">',
|
|
1251
|
+
' <Period id="1" duration="PT30S">',
|
|
1252
|
+
' <AdaptationSet id="1" contentType="text">',
|
|
1253
|
+
' <Accessibility schemeIdUri="urn:mpeg:dash:role:2011" ',
|
|
1254
|
+
' value="captions" />',
|
|
1255
|
+
' <Accessibility schemeIdUri="urn:mpeg:dash:role:2011" ',
|
|
1256
|
+
' value="foo" />',
|
|
1257
|
+
' <Accessibility schemeIdUri="foobar" value="bar" />',
|
|
1258
|
+
' <Representation id="text-en" mimeType="text/webvtt">',
|
|
1259
|
+
' <BaseURL>t-en.vtt</BaseURL>',
|
|
1260
|
+
' </Representation>',
|
|
1261
|
+
' </AdaptationSet>',
|
|
1262
|
+
' <AdaptationSet id="1" mimeType="video/mp4">',
|
|
1263
|
+
' <Representation id="video-sd" width="640" height="480">',
|
|
1264
|
+
' <BaseURL>v-sd.mp4</BaseURL>',
|
|
1265
|
+
' <SegmentBase indexRange="100-200" />',
|
|
1266
|
+
' </Representation>',
|
|
1267
|
+
' </AdaptationSet>',
|
|
1268
|
+
' </Period>',
|
|
1269
|
+
'</MPD>',
|
|
1270
|
+
].join('\n');
|
|
1271
|
+
|
|
1272
|
+
fakeNetEngine.setResponseText('dummy://foo', manifestText);
|
|
1273
|
+
const manifest = await parser.start('dummy://foo', playerInterface);
|
|
1274
|
+
const textStream = manifest.periods[0].textStreams[0];
|
|
1275
|
+
expect(textStream.roles).toEqual(['captions', 'foo']);
|
|
1276
|
+
expect(textStream.kind).toBe('caption');
|
|
1277
|
+
});
|
|
1218
1278
|
});
|
|
@@ -273,12 +273,18 @@ describe('HlsParser live', function() {
|
|
|
273
273
|
});
|
|
274
274
|
|
|
275
275
|
it('updates all streams', function(done) {
|
|
276
|
+
const masterlist = [
|
|
277
|
+
'#EXTM3U\n',
|
|
278
|
+
'#EXT-X-STREAM-INF:BANDWIDTH=200,CODECS="avc1",AUDIO="aud1",',
|
|
279
|
+
'RESOLUTION=960x540,FRAME-RATE=60\n',
|
|
280
|
+
'video\n',
|
|
281
|
+
].join('');
|
|
276
282
|
const audio = [
|
|
277
283
|
'#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aud1",LANGUAGE="eng",',
|
|
278
284
|
'URI="audio"\n',
|
|
279
285
|
].join('');
|
|
280
286
|
|
|
281
|
-
let masterWithAudio =
|
|
287
|
+
let masterWithAudio = masterlist + audio;
|
|
282
288
|
let ref1 = ManifestParser.makeReference('test:/main.mp4',
|
|
283
289
|
0, 2, 4);
|
|
284
290
|
let ref2 = ManifestParser.makeReference('test:/main2.mp4',
|
|
@@ -1107,6 +1107,56 @@ describe('HlsParser', function() {
|
|
|
1107
1107
|
.catch(fail).then(done);
|
|
1108
1108
|
});
|
|
1109
1109
|
|
|
1110
|
+
it('drops failed text streams when configured to', async () => {
|
|
1111
|
+
const master = [
|
|
1112
|
+
'#EXTM3U\n',
|
|
1113
|
+
'#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="sub1",LANGUAGE="eng",',
|
|
1114
|
+
'URI="text"\n',
|
|
1115
|
+
'#EXT-X-STREAM-INF:BANDWIDTH=200,CODECS="avc1,vtt",',
|
|
1116
|
+
'RESOLUTION=960x540,FRAME-RATE=60,SUBTITLES="sub1"\n',
|
|
1117
|
+
'video\n',
|
|
1118
|
+
].join('');
|
|
1119
|
+
|
|
1120
|
+
const media = [
|
|
1121
|
+
'#EXTM3U\n',
|
|
1122
|
+
'#EXT-X-PLAYLIST-TYPE:VOD\n',
|
|
1123
|
+
'#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
|
|
1124
|
+
'#EXTINF:5,\n',
|
|
1125
|
+
'#EXT-X-BYTERANGE:121090@616\n',
|
|
1126
|
+
'main.mp4',
|
|
1127
|
+
].join('');
|
|
1128
|
+
|
|
1129
|
+
const textMedia = [
|
|
1130
|
+
'#EXTM3U\n',
|
|
1131
|
+
'#EXT-X-PLAYLIST-TYPE:VOD\n',
|
|
1132
|
+
'#EXTINF:5,\n',
|
|
1133
|
+
'#EXT-X-BYTERANGE:121090@616\n',
|
|
1134
|
+
'main.foo',
|
|
1135
|
+
].join('');
|
|
1136
|
+
|
|
1137
|
+
/* eslint-disable indent */
|
|
1138
|
+
const manifest = new shaka.test.ManifestGenerator()
|
|
1139
|
+
.anyTimeline()
|
|
1140
|
+
.addPeriod(0)
|
|
1141
|
+
.addPartialVariant()
|
|
1142
|
+
.addPartialStream(ContentType.VIDEO)
|
|
1143
|
+
.build();
|
|
1144
|
+
/* eslint-enable indent */
|
|
1145
|
+
|
|
1146
|
+
fakeNetEngine
|
|
1147
|
+
.setResponseText('test:/master', master)
|
|
1148
|
+
.setResponseText('test:/audio', media)
|
|
1149
|
+
.setResponseText('test:/video', media)
|
|
1150
|
+
.setResponseText('test:/text', textMedia)
|
|
1151
|
+
.setResponseText('test:/main.foo', '')
|
|
1152
|
+
.setResponseValue('test:/init.mp4', initSegmentData)
|
|
1153
|
+
.setResponseValue('test:/main.mp4', segmentData);
|
|
1154
|
+
|
|
1155
|
+
config.hls.ignoreTextStreamFailures = true;
|
|
1156
|
+
const actual = await parser.start('test:/master', playerInterface);
|
|
1157
|
+
expect(actual).toEqual(manifest);
|
|
1158
|
+
});
|
|
1159
|
+
|
|
1110
1160
|
it('parses video described by a media tag', async () => {
|
|
1111
1161
|
const master = [
|
|
1112
1162
|
'#EXTM3U\n',
|
|
@@ -829,7 +829,7 @@ describe('DrmEngine', function() {
|
|
|
829
829
|
it('is listened for', async () => {
|
|
830
830
|
await initAndAttach();
|
|
831
831
|
expect(mockVideo.addEventListener).toHaveBeenCalledWith(
|
|
832
|
-
'encrypted', jasmine.any(Function),
|
|
832
|
+
'encrypted', jasmine.any(Function), jasmine.anything());
|
|
833
833
|
});
|
|
834
834
|
|
|
835
835
|
it('triggers the creation of a session', async () => {
|
|
@@ -924,7 +924,7 @@ describe('DrmEngine', function() {
|
|
|
924
924
|
{initDataType: 'webm', initData: initData, keyId: null});
|
|
925
925
|
|
|
926
926
|
expect(session1.addEventListener).toHaveBeenCalledWith(
|
|
927
|
-
'message', jasmine.any(Function),
|
|
927
|
+
'message', jasmine.any(Function), jasmine.anything());
|
|
928
928
|
});
|
|
929
929
|
|
|
930
930
|
it('triggers a license request', async () => {
|
|
@@ -1027,7 +1027,7 @@ describe('DrmEngine', function() {
|
|
|
1027
1027
|
{initDataType: 'webm', initData: initData, keyId: null});
|
|
1028
1028
|
|
|
1029
1029
|
expect(session1.addEventListener).toHaveBeenCalledWith(
|
|
1030
|
-
'keystatuseschange', jasmine.any(Function),
|
|
1030
|
+
'keystatuseschange', jasmine.any(Function), jasmine.anything());
|
|
1031
1031
|
});
|
|
1032
1032
|
|
|
1033
1033
|
it('triggers callback', function(done) {
|
|
@@ -1262,8 +1262,14 @@ describe('DrmEngine', function() {
|
|
|
1262
1262
|
// Not mocked. Run data through real data URI parser to ensure that it is
|
|
1263
1263
|
// correctly formatted.
|
|
1264
1264
|
fakeNetEngine.request.and.callFake(function(type, request) {
|
|
1265
|
+
const requestType = shaka.net.NetworkingEngine.RequestType.LICENSE;
|
|
1266
|
+
|
|
1267
|
+
// A dummy progress callback.
|
|
1268
|
+
const progressUpdated = (elapsedMs, bytes, bytesRemaining) => {};
|
|
1269
|
+
|
|
1265
1270
|
// eslint-disable-next-line new-cap
|
|
1266
|
-
return shaka.net.DataUriPlugin(
|
|
1271
|
+
return shaka.net.DataUriPlugin(
|
|
1272
|
+
request.uris[0], request, requestType, progressUpdated);
|
|
1267
1273
|
});
|
|
1268
1274
|
|
|
1269
1275
|
await initAndAttach();
|
|
@@ -193,6 +193,18 @@ describe('MediaSourceEngine', function() {
|
|
|
193
193
|
expect(mediaSource.duration).toBeCloseTo(30);
|
|
194
194
|
});
|
|
195
195
|
|
|
196
|
+
it('does not throw if endOfStrem called more than once', async () => {
|
|
197
|
+
const initObject = new Map();
|
|
198
|
+
initObject.set(ContentType.VIDEO, getFakeStream(metadata.video));
|
|
199
|
+
await mediaSourceEngine.init(initObject, false);
|
|
200
|
+
await mediaSourceEngine.setDuration(presentationDuration);
|
|
201
|
+
await appendInit(ContentType.VIDEO);
|
|
202
|
+
await append(ContentType.VIDEO, 1);
|
|
203
|
+
// Call endOfStream twice. There should be no exception.
|
|
204
|
+
await mediaSourceEngine.endOfStream();
|
|
205
|
+
await mediaSourceEngine.endOfStream();
|
|
206
|
+
});
|
|
207
|
+
|
|
196
208
|
it('queues operations', function(done) {
|
|
197
209
|
let resolutionOrder = [];
|
|
198
210
|
let requests = [];
|
|
@@ -1066,6 +1066,8 @@ describe('MediaSourceEngine', function() {
|
|
|
1066
1066
|
new shaka.test.StatusPromise(mediaSourceEngine.appendBuffer(
|
|
1067
1067
|
ContentType.AUDIO, buffer2, null, null,
|
|
1068
1068
|
/* hasClosedCaptions */ false));
|
|
1069
|
+
// Create the expectation first so we don't get unhandled rejection errors
|
|
1070
|
+
const expected = expectAsync(rejected).toBeRejected();
|
|
1069
1071
|
|
|
1070
1072
|
expect(audioSourceBuffer.appendBuffer).toHaveBeenCalledWith(buffer);
|
|
1071
1073
|
expect(audioSourceBuffer.appendBuffer).not.toHaveBeenCalledWith(buffer2);
|
|
@@ -1076,7 +1078,7 @@ describe('MediaSourceEngine', function() {
|
|
|
1076
1078
|
expect(p.status).toBe('pending');
|
|
1077
1079
|
await Util.delay(0.1);
|
|
1078
1080
|
expect(p.status).toBe('pending');
|
|
1079
|
-
|
|
1081
|
+
await expected;
|
|
1080
1082
|
expect(audioSourceBuffer.appendBuffer).toHaveBeenCalledWith(buffer);
|
|
1081
1083
|
expect(audioSourceBuffer.appendBuffer).not.toHaveBeenCalledWith(buffer2);
|
|
1082
1084
|
audioSourceBuffer.updateend();
|
|
@@ -200,9 +200,9 @@ describe('Playhead', function() {
|
|
|
200
200
|
Util.spyFunc(onEvent));
|
|
201
201
|
|
|
202
202
|
expect(video.addEventListener).toHaveBeenCalledWith(
|
|
203
|
-
'loadedmetadata', jasmine.any(Function),
|
|
203
|
+
'loadedmetadata', jasmine.any(Function), jasmine.anything());
|
|
204
204
|
expect(video.addEventListener).not.toHaveBeenCalledWith(
|
|
205
|
-
'seeking', jasmine.any(Function), jasmine.
|
|
205
|
+
'seeking', jasmine.any(Function), jasmine.anything());
|
|
206
206
|
|
|
207
207
|
expect(playhead.getTime()).toBe(5);
|
|
208
208
|
expect(video.currentTime).toBe(0);
|
|
@@ -211,7 +211,8 @@ describe('Playhead', function() {
|
|
|
211
211
|
video.on['loadedmetadata']();
|
|
212
212
|
|
|
213
213
|
expect(video.addEventListener).toHaveBeenCalledWith(
|
|
214
|
-
'seeking', jasmine.any(Function),
|
|
214
|
+
'seeking', jasmine.any(Function), jasmine.anything());
|
|
215
|
+
video.on['seeking']();
|
|
215
216
|
|
|
216
217
|
expect(playhead.getTime()).toBe(5);
|
|
217
218
|
expect(video.currentTime).toBe(5);
|
|
@@ -239,6 +240,7 @@ describe('Playhead', function() {
|
|
|
239
240
|
Util.spyFunc(onSeek),
|
|
240
241
|
Util.spyFunc(onEvent));
|
|
241
242
|
|
|
243
|
+
video.on['seeking']();
|
|
242
244
|
expect(playhead.getTime()).toBe(5);
|
|
243
245
|
expect(video.currentTime).toBe(5);
|
|
244
246
|
|
|
@@ -314,7 +316,7 @@ describe('Playhead', function() {
|
|
|
314
316
|
Util.spyFunc(onEvent));
|
|
315
317
|
|
|
316
318
|
expect(video.addEventListener).toHaveBeenCalledWith(
|
|
317
|
-
'loadedmetadata', jasmine.any(Function),
|
|
319
|
+
'loadedmetadata', jasmine.any(Function), jasmine.anything());
|
|
318
320
|
|
|
319
321
|
expect(playhead.getTime()).toBe(5);
|
|
320
322
|
expect(video.currentTime).toBe(0);
|
|
@@ -347,7 +349,7 @@ describe('Playhead', function() {
|
|
|
347
349
|
Util.spyFunc(onEvent));
|
|
348
350
|
|
|
349
351
|
expect(video.addEventListener).toHaveBeenCalledWith(
|
|
350
|
-
'loadedmetadata', jasmine.any(Function),
|
|
352
|
+
'loadedmetadata', jasmine.any(Function), jasmine.anything());
|
|
351
353
|
|
|
352
354
|
expect(playhead.getTime()).toBe(60);
|
|
353
355
|
expect(video.currentTime).toBe(0);
|