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
package/lib/util/fake_event.js
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
goog.provide('shaka.util.FakeEvent');
|
|
8
8
|
|
|
9
|
+
goog.require('goog.asserts');
|
|
10
|
+
|
|
9
11
|
|
|
10
12
|
/**
|
|
11
13
|
* @summary Create an Event work-alike object based on the provided dictionary.
|
|
@@ -16,18 +18,62 @@ goog.provide('shaka.util.FakeEvent');
|
|
|
16
18
|
*/
|
|
17
19
|
shaka.util.FakeEvent = class {
|
|
18
20
|
/**
|
|
19
|
-
* @param {
|
|
20
|
-
* @
|
|
21
|
+
* @param {!Event} event
|
|
22
|
+
* @return {!shaka.util.FakeEvent}
|
|
21
23
|
*/
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
for (const key in
|
|
25
|
-
Object.defineProperty(
|
|
26
|
-
value:
|
|
24
|
+
static fromRealEvent(event) {
|
|
25
|
+
const fakeEvent = new shaka.util.FakeEvent(event.type);
|
|
26
|
+
for (const key in event) {
|
|
27
|
+
Object.defineProperty(fakeEvent, key, {
|
|
28
|
+
value: event[key],
|
|
27
29
|
writable: true,
|
|
28
30
|
enumerable: true,
|
|
29
31
|
});
|
|
30
32
|
}
|
|
33
|
+
return fakeEvent;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Allows us to tell the compiler that the dictionary "map" is actually a
|
|
38
|
+
* generic object, for backwards compatibility.
|
|
39
|
+
* @param {!Map.<string, Object>} dict
|
|
40
|
+
* @return {!Object}
|
|
41
|
+
* @suppress {invalidCasts}
|
|
42
|
+
* @private
|
|
43
|
+
*/
|
|
44
|
+
static recastDictAsObject_(dict) {
|
|
45
|
+
goog.asserts.assert(!(dict instanceof Map), 'dict should not be a map');
|
|
46
|
+
return /** @type {!Object} */ (dict);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @param {string} type
|
|
51
|
+
* @param {Map.<string, Object>=} dict
|
|
52
|
+
*/
|
|
53
|
+
constructor(type, dict) {
|
|
54
|
+
if (dict) {
|
|
55
|
+
if (dict instanceof Map) {
|
|
56
|
+
// Take properties from dict if present.
|
|
57
|
+
for (const key of dict.keys()) {
|
|
58
|
+
Object.defineProperty(this, key, {
|
|
59
|
+
value: dict.get(key),
|
|
60
|
+
writable: true,
|
|
61
|
+
enumerable: true,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
// For backwards compatibility with external apps that may make use of
|
|
66
|
+
// this public constructor, this should still accept generic objects.
|
|
67
|
+
const obj = shaka.util.FakeEvent.recastDictAsObject_(dict);
|
|
68
|
+
for (const key in obj) {
|
|
69
|
+
Object.defineProperty(this, key, {
|
|
70
|
+
value: obj[key],
|
|
71
|
+
writable: true,
|
|
72
|
+
enumerable: true,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
31
77
|
|
|
32
78
|
// The properties below cannot be set by the dict. They are all provided
|
|
33
79
|
// for compatibility with native events.
|
|
@@ -13,6 +13,7 @@ goog.require('shaka.util.ManifestParserUtils');
|
|
|
13
13
|
/**
|
|
14
14
|
* @summary A set of language utility functions.
|
|
15
15
|
* @final
|
|
16
|
+
* @export
|
|
16
17
|
*/
|
|
17
18
|
shaka.util.LanguageUtils = class {
|
|
18
19
|
/**
|
|
@@ -32,6 +33,7 @@ shaka.util.LanguageUtils = class {
|
|
|
32
33
|
* @param {string} locale1
|
|
33
34
|
* @param {string} locale2
|
|
34
35
|
* @return {boolean}
|
|
36
|
+
* @export
|
|
35
37
|
*/
|
|
36
38
|
static areLocaleCompatible(locale1, locale2) {
|
|
37
39
|
const LanguageUtils = shaka.util.LanguageUtils;
|
|
@@ -62,6 +64,7 @@ shaka.util.LanguageUtils = class {
|
|
|
62
64
|
* @param {string} locale1
|
|
63
65
|
* @param {string} locale2
|
|
64
66
|
* @return {boolean}
|
|
67
|
+
* @export
|
|
65
68
|
*/
|
|
66
69
|
static areLanguageCompatible(locale1, locale2) {
|
|
67
70
|
const LanguageUtils = shaka.util.LanguageUtils;
|
|
@@ -102,6 +105,7 @@ shaka.util.LanguageUtils = class {
|
|
|
102
105
|
* @param {string} possibleParent
|
|
103
106
|
* @param {string} possibleChild
|
|
104
107
|
* @return {boolean}
|
|
108
|
+
* @export
|
|
105
109
|
*/
|
|
106
110
|
static isParentOf(possibleParent, possibleChild) {
|
|
107
111
|
const LanguageUtils = shaka.util.LanguageUtils;
|
|
@@ -146,6 +150,7 @@ shaka.util.LanguageUtils = class {
|
|
|
146
150
|
* @param {string} localeA
|
|
147
151
|
* @param {string} localeB
|
|
148
152
|
* @return {boolean}
|
|
153
|
+
* @export
|
|
149
154
|
*/
|
|
150
155
|
static isSiblingOf(localeA, localeB) {
|
|
151
156
|
const LanguageUtils = shaka.util.LanguageUtils;
|
|
@@ -181,6 +186,7 @@ shaka.util.LanguageUtils = class {
|
|
|
181
186
|
*
|
|
182
187
|
* @param {string} locale
|
|
183
188
|
* @return {string}
|
|
189
|
+
* @export
|
|
184
190
|
*/
|
|
185
191
|
static normalize(locale) {
|
|
186
192
|
const LanguageUtils = shaka.util.LanguageUtils;
|
|
@@ -217,6 +223,7 @@ shaka.util.LanguageUtils = class {
|
|
|
217
223
|
* @param {string} a
|
|
218
224
|
* @param {string} b
|
|
219
225
|
* @return {boolean}
|
|
226
|
+
* @export
|
|
220
227
|
*/
|
|
221
228
|
static areSiblings(a, b) {
|
|
222
229
|
const LanguageUtils = shaka.util.LanguageUtils;
|
|
@@ -235,6 +242,7 @@ shaka.util.LanguageUtils = class {
|
|
|
235
242
|
* @param {string} target
|
|
236
243
|
* @param {string} candidate
|
|
237
244
|
* @return {number}
|
|
245
|
+
* @export
|
|
238
246
|
*/
|
|
239
247
|
static relatedness(target, candidate) {
|
|
240
248
|
const LanguageUtils = shaka.util.LanguageUtils;
|
|
@@ -271,6 +279,7 @@ shaka.util.LanguageUtils = class {
|
|
|
271
279
|
*
|
|
272
280
|
* @param {string} lang
|
|
273
281
|
* @return {string}
|
|
282
|
+
* @export
|
|
274
283
|
*/
|
|
275
284
|
static getBase(lang) {
|
|
276
285
|
const LanguageUtils = shaka.util.LanguageUtils;
|
|
@@ -300,6 +309,7 @@ shaka.util.LanguageUtils = class {
|
|
|
300
309
|
*
|
|
301
310
|
* @param {shaka.extern.Stream} stream
|
|
302
311
|
* @return {string}
|
|
312
|
+
* @export
|
|
303
313
|
*/
|
|
304
314
|
static getLocaleForText(stream) {
|
|
305
315
|
const LanguageUtils = shaka.util.LanguageUtils;
|
|
@@ -322,6 +332,7 @@ shaka.util.LanguageUtils = class {
|
|
|
322
332
|
*
|
|
323
333
|
* @param {shaka.extern.Variant} variant
|
|
324
334
|
* @return {string}
|
|
335
|
+
* @export
|
|
325
336
|
*/
|
|
326
337
|
static getLocaleForVariant(variant) {
|
|
327
338
|
const LanguageUtils = shaka.util.LanguageUtils;
|
|
@@ -356,6 +367,7 @@ shaka.util.LanguageUtils = class {
|
|
|
356
367
|
* @param {string} target
|
|
357
368
|
* @param {!Iterable.<string>} searchSpace
|
|
358
369
|
* @return {?string}
|
|
370
|
+
* @export
|
|
359
371
|
*/
|
|
360
372
|
static findClosestLocale(target, searchSpace) {
|
|
361
373
|
const LanguageUtils = shaka.util.LanguageUtils;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/*! @license
|
|
2
|
+
* Shaka Player
|
|
3
|
+
* Copyright 2016 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
goog.provide('shaka.util.Mutex');
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @summary A simple mutex.
|
|
12
|
+
*/
|
|
13
|
+
shaka.util.Mutex = class {
|
|
14
|
+
/** Creates the mutex. */
|
|
15
|
+
constructor() {
|
|
16
|
+
/** @private {!Array.<function()>} */
|
|
17
|
+
this.waiting_ = [];
|
|
18
|
+
|
|
19
|
+
/** @private {number} */
|
|
20
|
+
this.nextMutexId_ = 0;
|
|
21
|
+
|
|
22
|
+
/** @private {number} */
|
|
23
|
+
this.acquiredMutexId_ = 0;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** @return {!Promise.<number>} mutexId */
|
|
27
|
+
async acquire() {
|
|
28
|
+
const mutexId = ++this.nextMutexId_;
|
|
29
|
+
if (!this.acquiredMutexId_) {
|
|
30
|
+
this.acquiredMutexId_ = mutexId;
|
|
31
|
+
} else {
|
|
32
|
+
await (new Promise((resolve, reject) => {
|
|
33
|
+
this.waiting_.push(() => {
|
|
34
|
+
this.acquiredMutexId_ = mutexId;
|
|
35
|
+
resolve();
|
|
36
|
+
});
|
|
37
|
+
}));
|
|
38
|
+
}
|
|
39
|
+
return mutexId;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** @param {number} mutexId */
|
|
43
|
+
release(mutexId) {
|
|
44
|
+
if (mutexId == this.acquiredMutexId_) {
|
|
45
|
+
this.acquiredMutexId_ = 0;
|
|
46
|
+
if (this.waiting_.length > 0) {
|
|
47
|
+
const callback = this.waiting_.shift();
|
|
48
|
+
callback();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
};
|
package/lib/util/periods.js
CHANGED
|
@@ -80,7 +80,10 @@ shaka.util.PeriodCombiner = class {
|
|
|
80
80
|
|
|
81
81
|
/** @return {!Array.<shaka.extern.Stream>} */
|
|
82
82
|
getTextStreams() {
|
|
83
|
-
|
|
83
|
+
// Return a copy of the array because makeTextStreamsForClosedCaptions
|
|
84
|
+
// may make changes to the contents of the array. Those changes should not
|
|
85
|
+
// propagate back to the PeriodCombiner.
|
|
86
|
+
return this.textStreams_.slice();
|
|
84
87
|
}
|
|
85
88
|
|
|
86
89
|
/** @return {!Array.<shaka.extern.Stream>} */
|
|
@@ -544,8 +547,7 @@ shaka.util.PeriodCombiner = class {
|
|
|
544
547
|
for (const stream of unusedStreams) {
|
|
545
548
|
// Create a new output stream which includes this input stream.
|
|
546
549
|
const outputStream =
|
|
547
|
-
|
|
548
|
-
await shaka.util.PeriodCombiner.createNewOutputStream_(
|
|
550
|
+
shaka.util.PeriodCombiner.createNewOutputStream_(
|
|
549
551
|
stream, streamsPerPeriod, clone, concat,
|
|
550
552
|
unusedStreamsPerPeriod);
|
|
551
553
|
if (outputStream) {
|
|
@@ -616,52 +618,69 @@ shaka.util.PeriodCombiner = class {
|
|
|
616
618
|
static async extendExistingOutputStream_(
|
|
617
619
|
outputStream, streamsPerPeriod, firstNewPeriodIndex, concat,
|
|
618
620
|
unusedStreamsPerPeriod) {
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
if (!matches) {
|
|
623
|
-
// We were unable to extend this output stream.
|
|
624
|
-
shaka.log.error('No matches extending output stream!',
|
|
625
|
-
outputStream, streamsPerPeriod);
|
|
626
|
-
return false;
|
|
627
|
-
}
|
|
621
|
+
shaka.util.PeriodCombiner.findMatchesInAllPeriods_(streamsPerPeriod,
|
|
622
|
+
outputStream);
|
|
628
623
|
|
|
629
624
|
// This only exists where T == Stream, and this should only ever be called
|
|
630
625
|
// on Stream types. StreamDB should not have pre-existing output streams.
|
|
631
626
|
goog.asserts.assert(outputStream.createSegmentIndex,
|
|
632
627
|
'outputStream should be a Stream type!');
|
|
633
628
|
|
|
629
|
+
if (!outputStream.matchedStreams) {
|
|
630
|
+
// We were unable to extend this output stream.
|
|
631
|
+
shaka.log.error('No matches extending output stream!',
|
|
632
|
+
outputStream, streamsPerPeriod);
|
|
633
|
+
return false;
|
|
634
|
+
}
|
|
634
635
|
// We need to create all the per-period segment indexes and append them to
|
|
635
636
|
// the output's MetaSegmentIndex.
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
goog.asserts.assert(matches, 'Matches should be non-null');
|
|
637
|
+
if (outputStream.segmentIndex) {
|
|
638
|
+
await shaka.util.PeriodCombiner.extendOutputSegmentIndex_(outputStream,
|
|
639
|
+
firstNewPeriodIndex);
|
|
640
|
+
}
|
|
641
641
|
|
|
642
|
-
shaka.util.PeriodCombiner.extendOutputStream_(
|
|
643
|
-
|
|
644
|
-
unusedStreamsPerPeriod);
|
|
642
|
+
shaka.util.PeriodCombiner.extendOutputStream_(outputStream,
|
|
643
|
+
firstNewPeriodIndex, concat, unusedStreamsPerPeriod);
|
|
645
644
|
return true;
|
|
646
645
|
}
|
|
647
646
|
|
|
648
647
|
/**
|
|
649
|
-
* Creates
|
|
650
|
-
* segment index
|
|
648
|
+
* Creates the segment indexes for an array of input streams, and append them
|
|
649
|
+
* to the output stream's segment index.
|
|
651
650
|
*
|
|
652
|
-
* @param {
|
|
653
|
-
* @
|
|
651
|
+
* @param {shaka.extern.Stream} outputStream
|
|
652
|
+
* @param {number} firstNewPeriodIndex An index into streamsPerPeriod which
|
|
653
|
+
* represents the first new period that hasn't been processed yet.
|
|
654
654
|
* @private
|
|
655
655
|
*/
|
|
656
|
-
static
|
|
656
|
+
static async extendOutputSegmentIndex_(outputStream, firstNewPeriodIndex) {
|
|
657
657
|
const operations = [];
|
|
658
|
+
const streams = outputStream.matchedStreams;
|
|
659
|
+
goog.asserts.assert(streams, 'matched streams should be valid');
|
|
660
|
+
|
|
658
661
|
for (const stream of streams) {
|
|
659
662
|
operations.push(stream.createSegmentIndex());
|
|
660
663
|
if (stream.trickModeVideo && !stream.trickModeVideo.segmentIndex) {
|
|
661
664
|
operations.push(stream.trickModeVideo.createSegmentIndex());
|
|
662
665
|
}
|
|
663
666
|
}
|
|
664
|
-
|
|
667
|
+
await Promise.all(operations);
|
|
668
|
+
|
|
669
|
+
// Concatenate the new matches onto the stream, starting at the first new
|
|
670
|
+
// period.
|
|
671
|
+
const Iterables = shaka.util.Iterables;
|
|
672
|
+
// Satisfy the compiler about the type.
|
|
673
|
+
// Also checks if the segmentIndex is still valid after the async
|
|
674
|
+
// operations, to make sure we stop if the active stream has changed.
|
|
675
|
+
if (outputStream.segmentIndex instanceof shaka.media.MetaSegmentIndex) {
|
|
676
|
+
for (const {i, item: match} of Iterables.enumerate(streams)) {
|
|
677
|
+
if (match.segmentIndex && i >= firstNewPeriodIndex) {
|
|
678
|
+
goog.asserts.assert(match.segmentIndex,
|
|
679
|
+
'stream should have a segmentIndex.');
|
|
680
|
+
outputStream.segmentIndex.appendSegmentIndex(match.segmentIndex);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
}
|
|
665
684
|
}
|
|
666
685
|
|
|
667
686
|
/**
|
|
@@ -679,7 +698,7 @@ shaka.util.PeriodCombiner = class {
|
|
|
679
698
|
* @param {!Array.<!Set.<T>>} unusedStreamsPerPeriod An array of sets of
|
|
680
699
|
* unused streams from each period.
|
|
681
700
|
*
|
|
682
|
-
* @return {
|
|
701
|
+
* @return {?T} A newly-created output Stream, or null if matches
|
|
683
702
|
* could not be found.`
|
|
684
703
|
*
|
|
685
704
|
* @template T
|
|
@@ -687,35 +706,36 @@ shaka.util.PeriodCombiner = class {
|
|
|
687
706
|
*
|
|
688
707
|
* @private
|
|
689
708
|
*/
|
|
690
|
-
static
|
|
709
|
+
static createNewOutputStream_(
|
|
691
710
|
stream, streamsPerPeriod, clone, concat, unusedStreamsPerPeriod) {
|
|
692
711
|
// Start by cloning the stream without segments, key IDs, etc.
|
|
693
712
|
const outputStream = clone(stream);
|
|
694
713
|
|
|
695
714
|
// Find best-matching streams in all periods.
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
if (!matches) {
|
|
700
|
-
// This is not a stream we can build output from, but it may become part
|
|
701
|
-
// of another output based on another period's stream.
|
|
702
|
-
return null;
|
|
703
|
-
}
|
|
715
|
+
shaka.util.PeriodCombiner.findMatchesInAllPeriods_(streamsPerPeriod,
|
|
716
|
+
outputStream);
|
|
704
717
|
|
|
705
718
|
// This only exists where T == Stream.
|
|
706
719
|
if (outputStream.createSegmentIndex) {
|
|
720
|
+
// Override the createSegmentIndex function of the outputStream.
|
|
721
|
+
outputStream.createSegmentIndex = async () => {
|
|
722
|
+
if (!outputStream.segmentIndex) {
|
|
723
|
+
outputStream.segmentIndex = new shaka.media.MetaSegmentIndex();
|
|
724
|
+
await shaka.util.PeriodCombiner.extendOutputSegmentIndex_(
|
|
725
|
+
outputStream, /* firstNewPeriodIndex= */ 0);
|
|
726
|
+
}
|
|
727
|
+
};
|
|
707
728
|
// For T == Stream, we need to create all the per-period segment indexes
|
|
708
729
|
// in advance. concat() will add them to the output's MetaSegmentIndex.
|
|
709
|
-
await shaka.util.PeriodCombiner.createSegmentIndexes_(matches);
|
|
710
730
|
}
|
|
711
731
|
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
unusedStreamsPerPeriod);
|
|
732
|
+
if (!outputStream.matchedStreams) {
|
|
733
|
+
// This is not a stream we can build output from, but it may become part
|
|
734
|
+
// of another output based on another period's stream.
|
|
735
|
+
return null;
|
|
736
|
+
}
|
|
737
|
+
shaka.util.PeriodCombiner.extendOutputStream_(outputStream,
|
|
738
|
+
/* firstNewPeriodIndex= */ 0, concat, unusedStreamsPerPeriod);
|
|
719
739
|
|
|
720
740
|
return outputStream;
|
|
721
741
|
}
|
|
@@ -723,7 +743,6 @@ shaka.util.PeriodCombiner = class {
|
|
|
723
743
|
/**
|
|
724
744
|
* @param {T} outputStream An existing output stream which needs to be
|
|
725
745
|
* extended into new periods.
|
|
726
|
-
* @param {!Array.<T>} matches A list of matching Streams from each period.
|
|
727
746
|
* @param {number} firstNewPeriodIndex An index into streamsPerPeriod which
|
|
728
747
|
* represents the first new period that hasn't been processed yet.
|
|
729
748
|
* @param {function(T, T)} concat Concatenate the second stream onto the end
|
|
@@ -737,10 +756,15 @@ shaka.util.PeriodCombiner = class {
|
|
|
737
756
|
* @private
|
|
738
757
|
*/
|
|
739
758
|
static extendOutputStream_(
|
|
740
|
-
outputStream,
|
|
741
|
-
unusedStreamsPerPeriod) {
|
|
759
|
+
outputStream, firstNewPeriodIndex, concat, unusedStreamsPerPeriod) {
|
|
742
760
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
743
761
|
const LanguageUtils = shaka.util.LanguageUtils;
|
|
762
|
+
const matches = outputStream.matchedStreams;
|
|
763
|
+
|
|
764
|
+
// Assure the compiler that matches didn't become null during the async
|
|
765
|
+
// operation before.
|
|
766
|
+
goog.asserts.assert(outputStream.matchedStreams,
|
|
767
|
+
'matchedStreams should be non-null');
|
|
744
768
|
|
|
745
769
|
// Concatenate the new matches onto the stream, starting at the first new
|
|
746
770
|
// period.
|
|
@@ -784,7 +808,23 @@ shaka.util.PeriodCombiner = class {
|
|
|
784
808
|
// streams that match this output.
|
|
785
809
|
clone.originalId = null;
|
|
786
810
|
clone.createSegmentIndex = () => Promise.resolve();
|
|
787
|
-
clone.
|
|
811
|
+
clone.closeSegmentIndex = () => {
|
|
812
|
+
if (clone.segmentIndex) {
|
|
813
|
+
clone.segmentIndex.release();
|
|
814
|
+
clone.segmentIndex = null;
|
|
815
|
+
}
|
|
816
|
+
// Close the segment index of the matched streams.
|
|
817
|
+
if (clone.matchedStreams) {
|
|
818
|
+
for (const match of clone.matchedStreams) {
|
|
819
|
+
if (match.segmentIndex) {
|
|
820
|
+
match.segmentIndex.release();
|
|
821
|
+
match.segmentIndex = null;
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
};
|
|
826
|
+
|
|
827
|
+
clone.segmentIndex = null;
|
|
788
828
|
clone.emsgSchemeIdUris = [];
|
|
789
829
|
clone.keyIds = new Set();
|
|
790
830
|
clone.closedCaptions = null;
|
|
@@ -870,26 +910,24 @@ shaka.util.PeriodCombiner = class {
|
|
|
870
910
|
}
|
|
871
911
|
}
|
|
872
912
|
|
|
873
|
-
// Satisfy the compiler about the type.
|
|
874
|
-
goog.asserts.assert(
|
|
875
|
-
output.segmentIndex instanceof shaka.media.MetaSegmentIndex,
|
|
876
|
-
'Output streams should have a MetaSegmentIndex!');
|
|
877
|
-
// Satisfy the compiler that the input index has been created.
|
|
878
|
-
goog.asserts.assert(
|
|
879
|
-
input.segmentIndex,
|
|
880
|
-
'Input segment index should have been created by now!');
|
|
881
|
-
|
|
882
|
-
output.segmentIndex.appendSegmentIndex(input.segmentIndex);
|
|
883
|
-
|
|
884
913
|
// Combine trick-play video streams, if present.
|
|
885
914
|
if (input.trickModeVideo) {
|
|
886
915
|
if (!output.trickModeVideo) {
|
|
887
916
|
// Create a fresh output stream for trick-mode playback.
|
|
888
917
|
output.trickModeVideo = shaka.util.PeriodCombiner.cloneStream_(
|
|
889
918
|
input.trickModeVideo);
|
|
890
|
-
//
|
|
891
|
-
//
|
|
892
|
-
|
|
919
|
+
// TODO: fix the createSegmentIndex function for trickModeVideo.
|
|
920
|
+
// The trick-mode tracks in multi-period content should have trick-mode
|
|
921
|
+
// segment indexes whenever available, rather than only regular-mode
|
|
922
|
+
// segment indexes.
|
|
923
|
+
output.trickModeVideo.createSegmentIndex = () => {
|
|
924
|
+
// Satisfy the compiler about the type.
|
|
925
|
+
goog.asserts.assert(
|
|
926
|
+
output.segmentIndex instanceof shaka.media.MetaSegmentIndex,
|
|
927
|
+
'The stream should have a MetaSegmentIndex.');
|
|
928
|
+
output.trickModeVideo.segmentIndex = output.segmentIndex.clone();
|
|
929
|
+
return Promise.resolve();
|
|
930
|
+
};
|
|
893
931
|
}
|
|
894
932
|
|
|
895
933
|
// Concatenate the trick mode input onto the trick mode output.
|
|
@@ -940,7 +978,6 @@ shaka.util.PeriodCombiner = class {
|
|
|
940
978
|
*
|
|
941
979
|
* @param {!Array.<!Array.<T>>} streamsPerPeriod
|
|
942
980
|
* @param {T} outputStream
|
|
943
|
-
* @return {Array.<T>}
|
|
944
981
|
*
|
|
945
982
|
* @template T
|
|
946
983
|
* Accepts either a StreamDB or Stream type.
|
|
@@ -953,11 +990,11 @@ shaka.util.PeriodCombiner = class {
|
|
|
953
990
|
const match = shaka.util.PeriodCombiner.findBestMatchInPeriod_(
|
|
954
991
|
streams, outputStream);
|
|
955
992
|
if (!match) {
|
|
956
|
-
return
|
|
993
|
+
return;
|
|
957
994
|
}
|
|
958
995
|
matches.push(match);
|
|
959
996
|
}
|
|
960
|
-
|
|
997
|
+
outputStream.matchedStreams = matches;
|
|
961
998
|
}
|
|
962
999
|
|
|
963
1000
|
/**
|
package/lib/util/platform.js
CHANGED
|
@@ -163,7 +163,6 @@ shaka.util.Platform = class {
|
|
|
163
163
|
!shaka.util.Platform.isEdge();
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
-
|
|
167
166
|
/**
|
|
168
167
|
* Check if the current platform is from Apple.
|
|
169
168
|
*
|
|
@@ -179,6 +178,19 @@ shaka.util.Platform = class {
|
|
|
179
178
|
&& !shaka.util.Platform.isTizen();
|
|
180
179
|
}
|
|
181
180
|
|
|
181
|
+
/**
|
|
182
|
+
* Check if the current platform is Playstation 5.
|
|
183
|
+
*
|
|
184
|
+
* Returns true on Playstation 5 browsers.
|
|
185
|
+
*
|
|
186
|
+
* Returns false for Playstation 5 browsers
|
|
187
|
+
*
|
|
188
|
+
* @return {boolean}
|
|
189
|
+
*/
|
|
190
|
+
static isPS5() {
|
|
191
|
+
return shaka.util.Platform.userAgentContains_('PlayStation 5');
|
|
192
|
+
}
|
|
193
|
+
|
|
182
194
|
/**
|
|
183
195
|
* Returns a major version number for Safari, or Safari-based iOS browsers.
|
|
184
196
|
*
|
|
@@ -120,6 +120,8 @@ shaka.util.PlayerConfiguration = class {
|
|
|
120
120
|
ignoreTextStreamFailures: false,
|
|
121
121
|
ignoreImageStreamFailures: false,
|
|
122
122
|
useFullSegmentsForStartTime: false,
|
|
123
|
+
defaultAudioCodec: 'mp4a.40.2',
|
|
124
|
+
defaultVideoCodec: 'avc1.42E01E',
|
|
123
125
|
},
|
|
124
126
|
};
|
|
125
127
|
|
|
@@ -163,6 +165,8 @@ shaka.util.PlayerConfiguration = class {
|
|
|
163
165
|
forceHTTPS: false,
|
|
164
166
|
preferNativeHls: false,
|
|
165
167
|
updateIntervalSeconds: 1,
|
|
168
|
+
dispatchAllEmsgBoxes: false,
|
|
169
|
+
observeQualityChanges: false,
|
|
166
170
|
};
|
|
167
171
|
|
|
168
172
|
// Some browsers will stop earlier than others before a gap (e.g., Edge
|
|
@@ -235,6 +239,19 @@ shaka.util.PlayerConfiguration = class {
|
|
|
235
239
|
minBandwidth: 0,
|
|
236
240
|
maxBandwidth: Infinity,
|
|
237
241
|
},
|
|
242
|
+
advanced: {
|
|
243
|
+
minTotalBytes: 128e3,
|
|
244
|
+
minBytes: 16e3,
|
|
245
|
+
fastHalfLife: 2,
|
|
246
|
+
slowHalfLife: 5,
|
|
247
|
+
},
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
const cmcd = {
|
|
251
|
+
enabled: false,
|
|
252
|
+
sessionId: '',
|
|
253
|
+
contentId: '',
|
|
254
|
+
useHeaders: false,
|
|
238
255
|
};
|
|
239
256
|
|
|
240
257
|
/** @type {shaka.extern.PlayerConfiguration} */
|
|
@@ -269,6 +286,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
269
286
|
playRangeStart: 0,
|
|
270
287
|
playRangeEnd: Infinity,
|
|
271
288
|
textDisplayFactory: () => null,
|
|
289
|
+
cmcd: cmcd,
|
|
272
290
|
};
|
|
273
291
|
|
|
274
292
|
// Add this callback so that we can reference the preferred audio language
|