shaka-player 3.2.1 → 3.3.1
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 +1 -1
- package/.github/ISSUE_TEMPLATE/feature_request.md +1 -1
- package/.github/ISSUE_TEMPLATE/question.md +1 -1
- package/AUTHORS +9 -5
- package/CHANGELOG.md +358 -0
- package/CONTRIBUTORS +7 -2
- package/build/conformance.textproto +183 -169
- package/build/generateExterns.js +1 -1
- package/build/types/core +3 -0
- package/build/types/offline +1 -0
- package/build/types/polyfill +1 -0
- package/build/types/ui +2 -0
- package/demo/common/assets.js +19 -1
- package/demo/common/message_ids.js +13 -1
- package/demo/config.js +31 -1
- package/demo/index.html +1 -1
- package/demo/locales/en.json +12 -0
- package/demo/locales/source.json +48 -0
- package/dist/controls.css +26 -2
- package/dist/controls.css.map +1 -1
- package/dist/demo.compiled.debug.js +20 -17
- package/dist/demo.compiled.debug.map +3 -3
- package/dist/demo.compiled.js +20 -17
- package/dist/demo.compiled.map +3 -3
- package/dist/deps.js +19 -12
- package/dist/locales.js +39 -37
- package/dist/receiver.compiled.debug.js +12 -10
- package/dist/receiver.compiled.debug.map +3 -3
- package/dist/receiver.compiled.js +12 -10
- package/dist/receiver.compiled.map +3 -3
- package/dist/shaka-player.compiled.d.ts +231 -18
- package/dist/shaka-player.compiled.debug.d.ts +231 -18
- package/dist/shaka-player.compiled.debug.externs.js +279 -8
- package/dist/shaka-player.compiled.debug.js +512 -449
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +279 -8
- package/dist/shaka-player.compiled.js +854 -821
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +247 -19
- package/dist/shaka-player.ui.debug.d.ts +247 -19
- package/dist/shaka-player.ui.debug.externs.js +307 -9
- package/dist/shaka-player.ui.debug.js +662 -580
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +307 -9
- package/dist/shaka-player.ui.js +1047 -1000
- package/dist/shaka-player.ui.map +4 -4
- package/docs/design/bg-fetch-after.gv +29 -0
- package/docs/design/bg-fetch-after.gv.png +0 -0
- package/docs/design/bg-fetch-before.gv +18 -0
- package/docs/design/bg-fetch-before.gv.png +0 -0
- package/docs/design/bg-fetch.md +134 -0
- package/docs/tutorials/blob-url.md +15 -0
- package/docs/tutorials/fairplay.md +1 -1
- package/docs/tutorials/index.json +1 -0
- package/docs/tutorials/ui-customization.md +66 -0
- package/docs/tutorials/ui.md +5 -5
- package/externs/cmcd.js +186 -0
- package/externs/ima.js +3 -0
- package/externs/shaka/ads.js +5 -0
- package/externs/shaka/manifest.js +12 -1
- package/externs/shaka/manifest_parser.js +10 -1
- package/externs/shaka/net.js +20 -4
- package/externs/shaka/offline.js +31 -2
- package/externs/shaka/player.js +138 -5
- package/externs/shaka/text.js +24 -0
- package/externs/webcrypto.js +18 -0
- package/karma.conf.js +1 -0
- package/lib/abr/ewma.js +14 -0
- package/lib/abr/ewma_bandwidth_estimator.js +16 -2
- package/lib/abr/simple_abr_manager.js +6 -0
- package/lib/ads/client_side_ad.js +8 -0
- package/lib/ads/client_side_ad_manager.js +54 -90
- package/lib/ads/server_side_ad.js +7 -0
- package/lib/ads/server_side_ad_manager.js +7 -10
- package/lib/cast/cast_proxy.js +3 -2
- package/lib/cast/cast_receiver.js +2 -1
- package/lib/cast/cast_sender.js +2 -2
- package/lib/cast/cast_utils.js +1 -0
- package/lib/dash/dash_parser.js +141 -16
- package/lib/dash/segment_base.js +25 -1
- package/lib/dash/segment_list.js +19 -10
- package/lib/dash/segment_template.js +24 -11
- package/lib/hls/hls_parser.js +146 -40
- package/lib/media/drm_engine.js +7 -0
- package/lib/media/gap_jumping_controller.js +4 -2
- package/lib/media/media_source_engine.js +1 -2
- package/lib/media/quality_observer.js +291 -0
- package/lib/media/segment_index.js +8 -1
- package/lib/media/segment_reference.js +37 -4
- package/lib/media/streaming_engine.js +49 -7
- package/lib/net/http_fetch_plugin.js +31 -11
- package/lib/net/http_plugin_utils.js +1 -0
- package/lib/net/http_xhr_plugin.js +40 -14
- package/lib/net/networking_engine.js +83 -19
- package/lib/offline/download_info.js +68 -0
- package/lib/offline/download_manager.js +13 -5
- package/lib/offline/indexeddb/base_storage_cell.js +35 -0
- package/lib/offline/indexeddb/storage_mechanism.js +1 -1
- package/lib/offline/indexeddb/v5_storage_cell.js +5 -0
- package/lib/offline/storage.js +393 -284
- package/lib/offline/stored_content_utils.js +2 -0
- package/lib/player.js +249 -43
- package/lib/polyfill/media_capabilities.js +36 -15
- package/lib/polyfill/mediasource.js +6 -0
- package/lib/polyfill/orientation.js +1 -1
- package/lib/polyfill/patchedmediakeys_apple.js +4 -4
- package/lib/polyfill/patchedmediakeys_ms.js +4 -4
- package/lib/polyfill/patchedmediakeys_webkit.js +4 -4
- package/lib/polyfill/random_uuid.js +52 -0
- package/lib/text/cue.js +18 -0
- package/lib/text/mp4_ttml_parser.js +3 -0
- package/lib/text/text_engine.js +14 -2
- package/lib/text/ttml_text_parser.js +114 -60
- package/lib/text/ui_text_displayer.js +95 -41
- package/lib/util/cmcd_manager.js +672 -0
- package/lib/util/error.js +6 -0
- package/lib/util/fake_event.js +53 -7
- package/lib/util/language_utils.js +12 -0
- package/lib/util/mutex.js +52 -0
- package/lib/util/periods.js +102 -65
- package/lib/util/platform.js +13 -1
- package/lib/util/player_configuration.js +18 -0
- package/lib/util/stream_utils.js +99 -10
- package/lib/util/xml_utils.js +19 -0
- package/package.json +2 -2
- package/shaka-player.uncompiled.js +3 -0
- package/test/cast/cast_proxy_unit.js +12 -6
- package/test/cast/cast_utils_unit.js +1 -1
- package/test/dash/dash_parser_content_protection_unit.js +2 -0
- package/test/dash/dash_parser_live_unit.js +101 -1
- package/test/dash/dash_parser_manifest_unit.js +222 -2
- package/test/dash/dash_parser_segment_base_unit.js +2 -0
- package/test/dash/dash_parser_segment_list_unit.js +2 -1
- package/test/dash/dash_parser_segment_template_unit.js +2 -1
- package/test/hls/hls_live_unit.js +2 -0
- package/test/hls/hls_parser_unit.js +7 -1
- package/test/media/closed_caption_parser_unit.js +6 -1
- package/test/media/drm_engine_unit.js +47 -3
- package/test/media/quality_observer_unit.js +139 -0
- package/test/media/segment_reference_unit.js +16 -1
- package/test/media/streaming_engine_integration.js +4 -2
- package/test/media/streaming_engine_unit.js +147 -0
- package/test/net/http_plugin_unit.js +20 -15
- package/test/offline/storage_integration.js +108 -4
- package/test/player_integration.js +178 -8
- package/test/player_src_equals_integration.js +41 -8
- package/test/player_unit.js +19 -9
- package/test/test/assets/3675/chunk-stream0-00001.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00002.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00003.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00004.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00005.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00006.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00007.m4s +0 -0
- package/test/test/assets/3675/dash_0.mpd +30 -0
- package/test/test/assets/3675/dash_1.mpd +30 -0
- package/test/test/assets/3675/dash_2.mpd +30 -0
- package/test/test/assets/3675/dash_3.mpd +30 -0
- package/test/test/assets/3675/dash_4.mpd +30 -0
- package/test/test/assets/3675/dash_5.mpd +26 -0
- package/test/test/assets/3675/init-stream0.m4s +0 -0
- package/test/test/assets/chapters.vtt +2 -2
- package/test/test/assets/chapters2.vtt +10 -0
- package/test/test/util/dash_parser_util.js +4 -0
- package/test/test/util/fake_ad.js +7 -0
- package/test/test/util/fake_ad_manager.js +1 -1
- package/test/test/util/fake_drm_engine.js +9 -2
- package/test/test/util/manifest_generator.js +3 -2
- package/test/test/util/test_scheme.js +14 -1
- package/test/test/util/ttml_utils.js +81 -0
- package/test/text/mp4_ttml_parser_unit.js +11 -18
- package/test/text/ttml_text_parser_unit.js +552 -227
- package/test/text/ui_text_displayer_unit.js +29 -17
- package/test/ui/localization_unit.js +15 -14
- package/test/ui/text_displayer_layout_unit.js +13 -1
- package/test/ui/ui_unit.js +250 -0
- package/test/util/cmcd_manager_unit.js +291 -0
- package/test/util/stream_utils_unit.js +45 -4
- package/third_party/closure-uri/uri.js +21 -0
- package/ui/airplay_button.js +1 -0
- package/ui/audio_language_selection.js +7 -0
- package/ui/cast_button.js +3 -3
- package/ui/context_menu.js +109 -0
- package/ui/controls.js +45 -13
- package/ui/controls.less +1 -0
- package/ui/enums.js +4 -0
- package/ui/externs/ui.js +28 -1
- package/ui/fast_forward_button.js +14 -5
- package/ui/fullscreen_button.js +1 -0
- package/ui/less/buttons.less +0 -4
- package/ui/less/containers.less +77 -7
- package/ui/less/overflow_menu.less +0 -10
- package/ui/less/tooltip.less +97 -0
- package/ui/locales/en.json +1 -0
- package/ui/locales/ru.json +6 -6
- package/ui/locales/source.json +4 -0
- package/ui/localization.js +28 -51
- package/ui/loop_button.js +5 -0
- package/ui/mute_button.js +2 -1
- package/ui/overflow_menu.js +5 -25
- package/ui/pip_button.js +7 -3
- package/ui/play_button.js +2 -2
- package/ui/playback_rate_selection.js +8 -9
- package/ui/resolution_selection.js +7 -0
- package/ui/rewind_button.js +15 -6
- package/ui/seek_bar.js +4 -2
- package/ui/settings_menu.js +36 -4
- package/ui/small_play_button.js +1 -0
- package/ui/statistics_button.js +253 -0
- package/ui/text_selection.js +12 -4
- package/ui/ui.js +30 -0
- package/ui/volume_bar.js +1 -1
- package/externs/media_capabilities.js +0 -16
|
@@ -567,10 +567,10 @@ class extends shaka.util.FakeEventTarget {
|
|
|
567
567
|
|
|
568
568
|
const isNew = this.keyStatuses.getStatus() == undefined;
|
|
569
569
|
|
|
570
|
-
const
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
570
|
+
const data = new Map()
|
|
571
|
+
.set('messageType', isNew ? 'license-request' : 'license-renewal')
|
|
572
|
+
.set('message', shaka.util.BufferUtils.toArrayBuffer(event.message));
|
|
573
|
+
const event2 = new shaka.util.FakeEvent('message', data);
|
|
574
574
|
|
|
575
575
|
this.dispatchEvent(event2);
|
|
576
576
|
}
|
|
@@ -512,10 +512,10 @@ class extends shaka.util.FakeEventTarget {
|
|
|
512
512
|
|
|
513
513
|
const isNew = this.keyStatuses.getStatus() == undefined;
|
|
514
514
|
|
|
515
|
-
const
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
515
|
+
const data = new Map()
|
|
516
|
+
.set('messageType', isNew ? 'license-request' : 'license-renewal')
|
|
517
|
+
.set('message', shaka.util.BufferUtils.toArrayBuffer(event.message));
|
|
518
|
+
const event2 = new shaka.util.FakeEvent('message', data);
|
|
519
519
|
|
|
520
520
|
this.dispatchEvent(event2);
|
|
521
521
|
}
|
|
@@ -451,10 +451,10 @@ shaka.polyfill.PatchedMediaKeysWebkit.MediaKeys = class {
|
|
|
451
451
|
|
|
452
452
|
const isNew = session.keyStatuses.getStatus() == undefined;
|
|
453
453
|
|
|
454
|
-
const
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
454
|
+
const data = new Map()
|
|
455
|
+
.set('messageType', isNew ? 'licenserequest' : 'licenserenewal')
|
|
456
|
+
.set('message', event.message);
|
|
457
|
+
const event2 = new shaka.util.FakeEvent('message', data);
|
|
458
458
|
|
|
459
459
|
session.generated();
|
|
460
460
|
session.dispatchEvent(event2);
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/*! @license
|
|
2
|
+
* Shaka Player
|
|
3
|
+
* Copyright 2016 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
goog.provide('shaka.polyfill.RandomUUID');
|
|
7
|
+
|
|
8
|
+
goog.require('shaka.log');
|
|
9
|
+
goog.require('shaka.polyfill');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @summary A polyfill to provide window.crypto.randomUUID in all browsers.
|
|
13
|
+
* @export
|
|
14
|
+
*/
|
|
15
|
+
shaka.polyfill.RandomUUID = class {
|
|
16
|
+
/**
|
|
17
|
+
* Install the polyfill if needed.
|
|
18
|
+
* @export
|
|
19
|
+
*/
|
|
20
|
+
static install() {
|
|
21
|
+
shaka.log.debug('randomUUID.install');
|
|
22
|
+
|
|
23
|
+
if (!window.crypto) {
|
|
24
|
+
// See: https://caniuse.com/cryptography
|
|
25
|
+
shaka.log.debug(
|
|
26
|
+
'window.crypto must be available to install randomUUID polyfill.');
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if ('randomUUID' in window.crypto) {
|
|
31
|
+
shaka.log.debug(
|
|
32
|
+
'RandomUUID: Native window.crypto.randomUUID() support found.');
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
window.crypto.randomUUID = shaka.polyfill.RandomUUID.randomUUID_;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @return {string}
|
|
41
|
+
* @private
|
|
42
|
+
*/
|
|
43
|
+
static randomUUID_() {
|
|
44
|
+
const url = URL.createObjectURL(new Blob());
|
|
45
|
+
const uuid = url.toString();
|
|
46
|
+
URL.revokeObjectURL(url);
|
|
47
|
+
return uuid.substr(uuid.lastIndexOf('/') + 1);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
shaka.polyfill.register(shaka.polyfill.RandomUUID.install);
|
package/lib/text/cue.js
CHANGED
|
@@ -144,6 +144,18 @@ shaka.text.Cue = class {
|
|
|
144
144
|
*/
|
|
145
145
|
this.border = '';
|
|
146
146
|
|
|
147
|
+
/**
|
|
148
|
+
* @override
|
|
149
|
+
* @exportInterface
|
|
150
|
+
*/
|
|
151
|
+
this.textStrokeColor = '';
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* @override
|
|
155
|
+
* @exportInterface
|
|
156
|
+
*/
|
|
157
|
+
this.textStrokeWidth = '';
|
|
158
|
+
|
|
147
159
|
/**
|
|
148
160
|
* @override
|
|
149
161
|
* @exportInterface
|
|
@@ -210,6 +222,12 @@ shaka.text.Cue = class {
|
|
|
210
222
|
*/
|
|
211
223
|
this.nestedCues = [];
|
|
212
224
|
|
|
225
|
+
/**
|
|
226
|
+
* @override
|
|
227
|
+
* @exportInterface
|
|
228
|
+
*/
|
|
229
|
+
this.isContainer = false;
|
|
230
|
+
|
|
213
231
|
/**
|
|
214
232
|
* @override
|
|
215
233
|
* @exportInterface
|
|
@@ -88,6 +88,9 @@ shaka.text.Mp4TtmlParser = class {
|
|
|
88
88
|
|
|
89
89
|
shaka.text.TextEngine.registerParser(
|
|
90
90
|
'application/mp4; codecs="stpp"', () => new shaka.text.Mp4TtmlParser());
|
|
91
|
+
shaka.text.TextEngine.registerParser(
|
|
92
|
+
'application/mp4; codecs="stpp.ttml"',
|
|
93
|
+
() => new shaka.text.Mp4TtmlParser());
|
|
91
94
|
shaka.text.TextEngine.registerParser(
|
|
92
95
|
'application/mp4; codecs="stpp.ttml.im1t"',
|
|
93
96
|
() => new shaka.text.Mp4TtmlParser());
|
package/lib/text/text_engine.js
CHANGED
|
@@ -345,6 +345,19 @@ shaka.text.TextEngine = class {
|
|
|
345
345
|
return cues;
|
|
346
346
|
}
|
|
347
347
|
|
|
348
|
+
/**
|
|
349
|
+
* @param {!shaka.text.Cue} cue the cue to apply the timestamp to recursively
|
|
350
|
+
* @param {number} videoTimestampOffset the timestamp offset of the video
|
|
351
|
+
* @private
|
|
352
|
+
*/
|
|
353
|
+
applyVideoTimestampOffsetRecursive_(cue, videoTimestampOffset) {
|
|
354
|
+
cue.startTime += videoTimestampOffset;
|
|
355
|
+
cue.endTime += videoTimestampOffset;
|
|
356
|
+
for (const nested of cue.nestedCues) {
|
|
357
|
+
this.applyVideoTimestampOffsetRecursive_(nested, videoTimestampOffset);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
348
361
|
/**
|
|
349
362
|
* Store the closed captions in the text engine, and append the cues to the
|
|
350
363
|
* text displayer. This is a side-channel used for embedded text only.
|
|
@@ -373,8 +386,7 @@ shaka.text.TextEngine = class {
|
|
|
373
386
|
|
|
374
387
|
// Adjust CEA captions with respect to the timestamp offset of the video
|
|
375
388
|
// stream in which they were embedded.
|
|
376
|
-
cue
|
|
377
|
-
cue.endTime += videoTimestampOffset;
|
|
389
|
+
this.applyVideoTimestampOffsetRecursive_(cue, videoTimestampOffset);
|
|
378
390
|
|
|
379
391
|
const keepThisCue =
|
|
380
392
|
cue.startTime >= this.appendWindowStart_ &&
|
|
@@ -86,16 +86,17 @@ shaka.text.TtmlTextParser = class {
|
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
// Get the framerate, subFrameRate and frameRateMultiplier if applicable.
|
|
89
|
-
const frameRate = XmlUtils.
|
|
90
|
-
const subFrameRate = XmlUtils.
|
|
89
|
+
const frameRate = XmlUtils.getAttributeNSList(tt, ttpNs, 'frameRate');
|
|
90
|
+
const subFrameRate = XmlUtils.getAttributeNSList(
|
|
91
|
+
tt, ttpNs, 'subFrameRate');
|
|
91
92
|
const frameRateMultiplier =
|
|
92
|
-
XmlUtils.
|
|
93
|
-
const tickRate = XmlUtils.
|
|
93
|
+
XmlUtils.getAttributeNSList(tt, ttpNs, 'frameRateMultiplier');
|
|
94
|
+
const tickRate = XmlUtils.getAttributeNSList(tt, ttpNs, 'tickRate');
|
|
94
95
|
|
|
95
|
-
const cellResolution = XmlUtils.
|
|
96
|
+
const cellResolution = XmlUtils.getAttributeNSList(
|
|
96
97
|
tt, ttpNs, 'cellResolution');
|
|
97
98
|
const spaceStyle = tt.getAttribute('xml:space') || 'default';
|
|
98
|
-
const extent = XmlUtils.
|
|
99
|
+
const extent = XmlUtils.getAttributeNSList(tt, ttsNs, 'extent');
|
|
99
100
|
|
|
100
101
|
if (spaceStyle != 'default' && spaceStyle != 'preserve') {
|
|
101
102
|
throw new shaka.util.Error(
|
|
@@ -147,28 +148,15 @@ shaka.text.TtmlTextParser = class {
|
|
|
147
148
|
shaka.util.Error.Code.INVALID_TEXT_CUE,
|
|
148
149
|
'<span> can only be inside <p> in TTML');
|
|
149
150
|
}
|
|
151
|
+
}
|
|
150
152
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
if (cue) {
|
|
159
|
-
cues.push(cue);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
} else {
|
|
163
|
-
// Only used for parsing the background image
|
|
164
|
-
const cue = TtmlTextParser.parseCue_(
|
|
165
|
-
div, time.periodStart, rateInfo, metadataElements, styles,
|
|
166
|
-
regionElements, cueRegions, whitespaceTrim,
|
|
167
|
-
/* isNested= */ false, cellResolutionInfo);
|
|
168
|
-
if (cue) {
|
|
169
|
-
cues.push(cue);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
153
|
+
const cue = TtmlTextParser.parseCue_(
|
|
154
|
+
body, time.periodStart, rateInfo, metadataElements, styles,
|
|
155
|
+
regionElements, cueRegions, whitespaceTrim,
|
|
156
|
+
cellResolutionInfo, /* parentCueElement= */ null,
|
|
157
|
+
/* isContent= */ false);
|
|
158
|
+
if (cue) {
|
|
159
|
+
cues.push(cue);
|
|
172
160
|
}
|
|
173
161
|
}
|
|
174
162
|
|
|
@@ -186,20 +174,32 @@ shaka.text.TtmlTextParser = class {
|
|
|
186
174
|
* @param {!Array.<!Element>} regionElements
|
|
187
175
|
* @param {!Array.<!shaka.text.CueRegion>} cueRegions
|
|
188
176
|
* @param {boolean} whitespaceTrim
|
|
189
|
-
* @param {boolean} isNested
|
|
190
177
|
* @param {?{columns: number, rows: number}} cellResolution
|
|
178
|
+
* @param {?Element} parentCueElement
|
|
179
|
+
* @param {boolean} isContent
|
|
191
180
|
* @return {shaka.text.Cue}
|
|
192
181
|
* @private
|
|
193
182
|
*/
|
|
194
183
|
static parseCue_(
|
|
195
184
|
cueNode, offset, rateInfo, metadataElements, styles, regionElements,
|
|
196
|
-
cueRegions, whitespaceTrim,
|
|
185
|
+
cueRegions, whitespaceTrim, cellResolution, parentCueElement, isContent) {
|
|
197
186
|
/** @type {Element} */
|
|
198
187
|
let cueElement;
|
|
199
188
|
/** @type {Element} */
|
|
200
|
-
let parentElement = /** @type {Element} */(cueNode.parentNode);
|
|
189
|
+
let parentElement = /** @type {Element} */ (cueNode.parentNode);
|
|
190
|
+
|
|
191
|
+
if (cueNode.nodeType == Node.COMMENT_NODE) {
|
|
192
|
+
// The comments do not contain information that interests us here.
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
201
195
|
|
|
202
196
|
if (cueNode.nodeType == Node.TEXT_NODE) {
|
|
197
|
+
if (!isContent) {
|
|
198
|
+
// Ignore text elements outside the content. For example, whitespace
|
|
199
|
+
// on the same lexical level as the <p> elements, in a document with
|
|
200
|
+
// xml:space="preserve", should not be renderer.
|
|
201
|
+
return null;
|
|
202
|
+
}
|
|
203
203
|
// This should generate an "anonymous span" according to the TTML spec.
|
|
204
204
|
// So pretend the element was a <span>. parentElement was set above, so
|
|
205
205
|
// we should still be able to correctly traverse up for timing
|
|
@@ -214,6 +214,21 @@ shaka.text.TtmlTextParser = class {
|
|
|
214
214
|
}
|
|
215
215
|
goog.asserts.assert(cueElement, 'cueElement should be non-null!');
|
|
216
216
|
|
|
217
|
+
let imageElement = null;
|
|
218
|
+
for (const nameSpace of shaka.text.TtmlTextParser.smpteNsList_) {
|
|
219
|
+
imageElement = shaka.text.TtmlTextParser.getElementsFromCollection_(
|
|
220
|
+
cueElement, 'backgroundImage', metadataElements, '#',
|
|
221
|
+
nameSpace)[0];
|
|
222
|
+
if (imageElement) {
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const parentIsContent = isContent;
|
|
228
|
+
if (cueNode.nodeName == 'p' || imageElement) {
|
|
229
|
+
isContent = true;
|
|
230
|
+
}
|
|
231
|
+
|
|
217
232
|
const spaceStyle = cueElement.getAttribute('xml:space') ||
|
|
218
233
|
(whitespaceTrim ? 'default' : 'preserve');
|
|
219
234
|
|
|
@@ -238,8 +253,9 @@ shaka.text.TtmlTextParser = class {
|
|
|
238
253
|
regionElements,
|
|
239
254
|
cueRegions,
|
|
240
255
|
localWhitespaceTrim,
|
|
241
|
-
/* isNested= */ true,
|
|
242
256
|
cellResolution,
|
|
257
|
+
cueElement,
|
|
258
|
+
isContent,
|
|
243
259
|
);
|
|
244
260
|
|
|
245
261
|
// This node may or may not generate a nested cue.
|
|
@@ -249,6 +265,8 @@ shaka.text.TtmlTextParser = class {
|
|
|
249
265
|
}
|
|
250
266
|
}
|
|
251
267
|
|
|
268
|
+
const isNested = /** @type {boolean} */ (parentCueElement != null);
|
|
269
|
+
|
|
252
270
|
// In this regex, "\S" means "non-whitespace character".
|
|
253
271
|
const hasTextContent = /\S/.test(cueElement.textContent);
|
|
254
272
|
const hasTimeAttributes =
|
|
@@ -329,6 +347,13 @@ shaka.text.TtmlTextParser = class {
|
|
|
329
347
|
const cue = new shaka.text.Cue(start, end, payload);
|
|
330
348
|
cue.nestedCues = nestedCues;
|
|
331
349
|
|
|
350
|
+
if (!isContent) {
|
|
351
|
+
// If this is not a <p> element or a <div> with images, and it has no
|
|
352
|
+
// parent that was a <p> element, then it's part of the outer containers
|
|
353
|
+
// (e.g. the <body> or a normal <div> element within it).
|
|
354
|
+
cue.isContainer = true;
|
|
355
|
+
}
|
|
356
|
+
|
|
332
357
|
if (cellResolution) {
|
|
333
358
|
cue.cellResolution = cellResolution;
|
|
334
359
|
}
|
|
@@ -336,31 +361,32 @@ shaka.text.TtmlTextParser = class {
|
|
|
336
361
|
// Get other properties if available.
|
|
337
362
|
const regionElement = shaka.text.TtmlTextParser.getElementsFromCollection_(
|
|
338
363
|
cueElement, 'region', regionElements, /* prefix= */ '')[0];
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
imageElement = shaka.text.TtmlTextParser.getElementsFromCollection_(
|
|
347
|
-
cueElement, 'backgroundImage', metadataElements, '#',
|
|
348
|
-
nameSpace)[0];
|
|
349
|
-
if (imageElement) {
|
|
350
|
-
break;
|
|
364
|
+
// Do not actually apply that region unless it is non-inherited, though.
|
|
365
|
+
// This makes it so that, if a parent element has a region, the children
|
|
366
|
+
// don't also all independently apply the positioning of that region.
|
|
367
|
+
if (cueElement.hasAttribute('region')) {
|
|
368
|
+
if (regionElement && regionElement.getAttribute('xml:id')) {
|
|
369
|
+
const regionId = regionElement.getAttribute('xml:id');
|
|
370
|
+
cue.region = cueRegions.filter((region) => region.id == regionId)[0];
|
|
351
371
|
}
|
|
352
372
|
}
|
|
353
373
|
|
|
354
|
-
|
|
374
|
+
let regionElementForStyle = regionElement;
|
|
375
|
+
if (parentCueElement && isNested && !cueElement.getAttribute('region') &&
|
|
376
|
+
!cueElement.getAttribute('style')) {
|
|
377
|
+
regionElementForStyle =
|
|
378
|
+
shaka.text.TtmlTextParser.getElementsFromCollection_(
|
|
379
|
+
parentCueElement, 'region', regionElements, /* prefix= */ '')[0];
|
|
380
|
+
}
|
|
355
381
|
|
|
356
382
|
shaka.text.TtmlTextParser.addStyle_(
|
|
357
383
|
cue,
|
|
358
384
|
cueElement,
|
|
359
|
-
|
|
385
|
+
regionElementForStyle,
|
|
360
386
|
imageElement,
|
|
361
387
|
styles,
|
|
362
|
-
isNested,
|
|
363
|
-
isLeaf);
|
|
388
|
+
/** isNested= */ parentIsContent, // "nested in a <div>" doesn't count.
|
|
389
|
+
/** isLeaf= */ (nestedCues.length == 0));
|
|
364
390
|
|
|
365
391
|
return cue;
|
|
366
392
|
}
|
|
@@ -500,14 +526,13 @@ shaka.text.TtmlTextParser = class {
|
|
|
500
526
|
}
|
|
501
527
|
|
|
502
528
|
const align = TtmlTextParser.getStyleAttribute_(
|
|
503
|
-
cueElement, region, styles, 'textAlign',
|
|
529
|
+
cueElement, region, styles, 'textAlign', true);
|
|
504
530
|
if (align) {
|
|
505
531
|
cue.positionAlign = TtmlTextParser.textAlignToPositionAlign_[align];
|
|
506
532
|
cue.lineAlign = TtmlTextParser.textAlignToLineAlign_[align];
|
|
507
533
|
|
|
508
534
|
goog.asserts.assert(align.toUpperCase() in Cue.textAlign,
|
|
509
|
-
align.toUpperCase() +
|
|
510
|
-
' Should be in Cue.textAlign values!');
|
|
535
|
+
align.toUpperCase() + ' Should be in Cue.textAlign values!');
|
|
511
536
|
|
|
512
537
|
cue.textAlign = Cue.textAlign[align.toUpperCase()];
|
|
513
538
|
} else {
|
|
@@ -516,7 +541,7 @@ shaka.text.TtmlTextParser = class {
|
|
|
516
541
|
}
|
|
517
542
|
|
|
518
543
|
const displayAlign = TtmlTextParser.getStyleAttribute_(
|
|
519
|
-
cueElement, region, styles, 'displayAlign',
|
|
544
|
+
cueElement, region, styles, 'displayAlign', true);
|
|
520
545
|
if (displayAlign) {
|
|
521
546
|
goog.asserts.assert(displayAlign.toUpperCase() in Cue.displayAlign,
|
|
522
547
|
displayAlign.toUpperCase() +
|
|
@@ -526,7 +551,6 @@ shaka.text.TtmlTextParser = class {
|
|
|
526
551
|
|
|
527
552
|
const color = TtmlTextParser.getStyleAttribute_(
|
|
528
553
|
cueElement, region, styles, 'color', shouldInheritRegionStyles);
|
|
529
|
-
|
|
530
554
|
if (color) {
|
|
531
555
|
cue.color = color;
|
|
532
556
|
}
|
|
@@ -579,7 +603,6 @@ shaka.text.TtmlTextParser = class {
|
|
|
579
603
|
|
|
580
604
|
const fontSize = TtmlTextParser.getStyleAttribute_(
|
|
581
605
|
cueElement, region, styles, 'fontSize', shouldInheritRegionStyles);
|
|
582
|
-
|
|
583
606
|
if (fontSize) {
|
|
584
607
|
const isValidFontSizeUnit =
|
|
585
608
|
fontSize.match(TtmlTextParser.unitValues_) ||
|
|
@@ -617,6 +640,31 @@ shaka.text.TtmlTextParser = class {
|
|
|
617
640
|
}
|
|
618
641
|
}
|
|
619
642
|
|
|
643
|
+
const textOutline = TtmlTextParser.getStyleAttribute_(
|
|
644
|
+
cueElement, region, styles, 'textOutline', shouldInheritRegionStyles);
|
|
645
|
+
if (textOutline) {
|
|
646
|
+
// tts:textOutline isn't natively supported by browsers, but it can be
|
|
647
|
+
// mostly replicated using the non-standard -webkit-text-stroke-width and
|
|
648
|
+
// -webkit-text-stroke-color properties.
|
|
649
|
+
const split = textOutline.split(' ');
|
|
650
|
+
if (split[0].match(TtmlTextParser.unitValues_)) {
|
|
651
|
+
// There is no defined color, so default to the text color.
|
|
652
|
+
cue.textStrokeColor = cue.color;
|
|
653
|
+
} else {
|
|
654
|
+
cue.textStrokeColor = split[0];
|
|
655
|
+
split.shift();
|
|
656
|
+
}
|
|
657
|
+
if (split[0] && split[0].match(TtmlTextParser.unitValues_)) {
|
|
658
|
+
cue.textStrokeWidth = split[0];
|
|
659
|
+
} else {
|
|
660
|
+
// If there is no width, or the width is not a number, don't draw a
|
|
661
|
+
// border.
|
|
662
|
+
cue.textStrokeColor = '';
|
|
663
|
+
}
|
|
664
|
+
// There is an optional blur radius also, but we have no way of
|
|
665
|
+
// replicating that, so ignore it.
|
|
666
|
+
}
|
|
667
|
+
|
|
620
668
|
const letterSpacing = TtmlTextParser.getStyleAttribute_(
|
|
621
669
|
cueElement, region, styles, 'letterSpacing', shouldInheritRegionStyles);
|
|
622
670
|
if (letterSpacing && letterSpacing.match(TtmlTextParser.unitValues_)) {
|
|
@@ -748,7 +796,7 @@ shaka.text.TtmlTextParser = class {
|
|
|
748
796
|
return null;
|
|
749
797
|
}
|
|
750
798
|
|
|
751
|
-
const attr = XmlUtils.
|
|
799
|
+
const attr = XmlUtils.getAttributeNSList(region, ttsNs, attribute);
|
|
752
800
|
if (attr) {
|
|
753
801
|
return attr;
|
|
754
802
|
}
|
|
@@ -773,7 +821,7 @@ shaka.text.TtmlTextParser = class {
|
|
|
773
821
|
|
|
774
822
|
// Styling on elements should take precedence
|
|
775
823
|
// over the main styling attributes
|
|
776
|
-
const elementAttribute = XmlUtils.
|
|
824
|
+
const elementAttribute = XmlUtils.getAttributeNSList(
|
|
777
825
|
cueElement,
|
|
778
826
|
ttsNs,
|
|
779
827
|
attribute);
|
|
@@ -816,7 +864,7 @@ shaka.text.TtmlTextParser = class {
|
|
|
816
864
|
|
|
817
865
|
if (!styleAttributeValue) {
|
|
818
866
|
// Fall back to tts namespace.
|
|
819
|
-
styleAttributeValue = XmlUtils.
|
|
867
|
+
styleAttributeValue = XmlUtils.getAttributeNSList(
|
|
820
868
|
inheritedStyles[i],
|
|
821
869
|
ttsNs,
|
|
822
870
|
attribute);
|
|
@@ -1271,20 +1319,26 @@ shaka.text.TtmlTextParser.textAlignToPositionAlign_ = {
|
|
|
1271
1319
|
* document, not just "ttp:", so we use this with getAttributeNS() to ensure
|
|
1272
1320
|
* that we support arbitrary namespace names.
|
|
1273
1321
|
*
|
|
1274
|
-
* @const {string}
|
|
1322
|
+
* @const {!Array.<string>}
|
|
1275
1323
|
* @private
|
|
1276
1324
|
*/
|
|
1277
|
-
shaka.text.TtmlTextParser.parameterNs_ =
|
|
1325
|
+
shaka.text.TtmlTextParser.parameterNs_ = [
|
|
1326
|
+
'http://www.w3.org/ns/ttml#parameter',
|
|
1327
|
+
'http://www.w3.org/2006/10/ttaf1#parameter',
|
|
1328
|
+
];
|
|
1278
1329
|
|
|
1279
1330
|
/**
|
|
1280
1331
|
* The namespace URL for TTML styles. Can be assigned any name in the TTML
|
|
1281
1332
|
* document, not just "tts:", so we use this with getAttributeNS() to ensure
|
|
1282
1333
|
* that we support arbitrary namespace names.
|
|
1283
1334
|
*
|
|
1284
|
-
* @const {string}
|
|
1335
|
+
* @const {!Array.<string>}
|
|
1285
1336
|
* @private
|
|
1286
1337
|
*/
|
|
1287
|
-
shaka.text.TtmlTextParser.styleNs_ =
|
|
1338
|
+
shaka.text.TtmlTextParser.styleNs_ = [
|
|
1339
|
+
'http://www.w3.org/ns/ttml#styling',
|
|
1340
|
+
'http://www.w3.org/2006/10/ttaf1#styling',
|
|
1341
|
+
];
|
|
1288
1342
|
|
|
1289
1343
|
/**
|
|
1290
1344
|
* The namespace URL for EBU TTML styles. Can be assigned any name in the TTML
|