shaka-player 4.12.8 → 4.13.0
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/AUTHORS +1 -0
- package/CONTRIBUTORS +4 -0
- package/README.md +22 -21
- package/cspell.config.yaml +18 -0
- package/dist/controls.css +1 -1
- package/dist/controls.css.map +1 -1
- package/dist/deps.js +29 -24
- package/dist/locales.js +33 -33
- package/dist/shaka-player.compiled.d.ts +138 -36
- package/dist/shaka-player.compiled.debug.d.ts +138 -36
- package/dist/shaka-player.compiled.debug.externs.js +367 -107
- package/dist/shaka-player.compiled.debug.js +828 -765
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +367 -107
- package/dist/shaka-player.compiled.js +1451 -1416
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +172 -38
- package/dist/shaka-player.ui.debug.d.ts +172 -38
- package/dist/shaka-player.ui.debug.externs.js +406 -113
- package/dist/shaka-player.ui.debug.js +842 -766
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +406 -113
- package/dist/shaka-player.ui.js +1670 -1628
- package/dist/shaka-player.ui.map +4 -4
- package/eslint.config.mjs +343 -0
- package/externs/airplay.js +1 -1
- package/externs/audiotrack.js +1 -1
- package/externs/awesomplete.js +1 -1
- package/externs/cast-sdk-v2.js +2 -2
- package/externs/cmcd.js +16 -1
- package/externs/device_sensor_event.js +1 -1
- package/externs/ima.js +8 -8
- package/externs/isoboxer.js +31 -31
- package/externs/jwk_set.js +1 -1
- package/externs/lcevc.js +8 -8
- package/externs/mediakeys.js +1 -1
- package/externs/mediasession.js +3 -2
- package/externs/mediatailor.js +18 -18
- package/externs/pictureinpicture.js +41 -1
- package/externs/playstation.js +2 -2
- package/externs/prefixed_eme.js +1 -1
- package/externs/shaka/abortable.js +4 -4
- package/externs/shaka/abr_manager.js +1 -1
- package/externs/shaka/ads.js +45 -6
- package/externs/shaka/cea.js +2 -2
- package/externs/shaka/codecs.js +4 -4
- package/externs/shaka/drm_info.js +6 -6
- package/externs/shaka/error.js +5 -5
- package/externs/shaka/manifest.js +51 -56
- package/externs/shaka/manifest_parser.js +3 -9
- package/externs/shaka/net.js +23 -20
- package/externs/shaka/offline.js +37 -37
- package/externs/shaka/offline_compat_v1.js +10 -10
- package/externs/shaka/offline_compat_v2.js +10 -10
- package/externs/shaka/player.js +139 -109
- package/externs/shaka/text.js +10 -3
- package/externs/shaka/transmuxer.js +1 -1
- package/externs/videotrack.js +1 -1
- package/lib/abr/ewma.js +1 -1
- package/lib/abr/simple_abr_manager.js +70 -22
- package/lib/ads/ad_manager.js +43 -18
- package/lib/ads/ad_utils.js +160 -58
- package/lib/ads/ads_stats.js +1 -1
- package/lib/ads/client_side_ad_manager.js +2 -2
- package/lib/ads/interstitial_ad.js +16 -11
- package/lib/ads/interstitial_ad_manager.js +419 -72
- package/lib/ads/interstitial_static_ad.js +299 -0
- package/lib/ads/media_tailor_ad.js +1 -0
- package/lib/ads/media_tailor_ad_manager.js +37 -36
- package/lib/ads/server_side_ad_manager.js +7 -6
- package/lib/cast/cast_receiver.js +5 -3
- package/lib/cast/cast_sender.js +2 -2
- package/lib/cast/cast_utils.js +20 -13
- package/lib/cea/cea608_data_channel.js +53 -53
- package/lib/cea/cea708_service.js +42 -40
- package/lib/cea/cea708_window.js +5 -2
- package/lib/cea/cea_decoder.js +5 -7
- package/lib/cea/mp4_cea_parser.js +1 -1
- package/lib/cea/sei_processor.js +1 -1
- package/lib/dash/content_protection.js +62 -192
- package/lib/dash/dash_parser.js +119 -119
- package/lib/dash/mpd_utils.js +14 -13
- package/lib/dash/segment_base.js +5 -5
- package/lib/dash/segment_list.js +10 -10
- package/lib/dash/segment_template.js +55 -53
- package/lib/debug/log.js +2 -2
- package/lib/dependencies/all.js +2 -1
- package/lib/{media → drm}/drm_engine.js +274 -143
- package/lib/{util → drm}/drm_utils.js +20 -11
- package/lib/drm/playready.js +233 -0
- package/lib/hls/hls_classes.js +14 -14
- package/lib/hls/hls_parser.js +257 -196
- package/lib/hls/hls_utils.js +14 -14
- package/lib/hls/manifest_text_parser.js +10 -10
- package/lib/media/adaptation_set.js +6 -5
- package/lib/media/adaptation_set_criteria.js +51 -379
- package/lib/media/buffering_observer.js +5 -4
- package/lib/media/closed_caption_parser.js +2 -2
- package/lib/media/content_workarounds.js +2 -2
- package/lib/media/example_based_criteria.js +69 -0
- package/lib/media/gap_jumping_controller.js +14 -1
- package/lib/media/manifest_filterer.js +8 -8
- package/lib/media/manifest_parser.js +2 -2
- package/lib/media/media_source_capabilities.js +20 -1
- package/lib/media/media_source_engine.js +84 -35
- package/lib/media/mp4_segment_index_parser.js +5 -5
- package/lib/media/playhead.js +2 -8
- package/lib/media/playhead_observer.js +1 -1
- package/lib/media/preference_based_criteria.js +333 -0
- package/lib/media/preload_manager.js +53 -37
- package/lib/media/presentation_timeline.js +2 -2
- package/lib/media/quality_observer.js +35 -35
- package/lib/media/region_observer.js +2 -2
- package/lib/media/region_timeline.js +3 -3
- package/lib/media/segment_index.js +14 -14
- package/lib/media/segment_prefetch.js +17 -13
- package/lib/media/segment_reference.js +7 -7
- package/lib/media/segment_utils.js +9 -9
- package/lib/media/streaming_engine.js +77 -38
- package/lib/media/time_ranges_utils.js +1 -1
- package/lib/media/video_wrapper.js +1 -1
- package/lib/media/webm_segment_index_parser.js +4 -4
- package/lib/mss/content_protection.js +17 -222
- package/lib/mss/mss_parser.js +23 -24
- package/lib/net/data_uri_plugin.js +1 -0
- package/lib/net/http_fetch_plugin.js +8 -7
- package/lib/net/http_plugin_utils.js +5 -2
- package/lib/net/http_xhr_plugin.js +4 -3
- package/lib/net/networking_engine.js +72 -17
- package/lib/net/networking_utils.js +5 -2
- package/lib/offline/download_info.js +5 -1
- package/lib/offline/download_manager.js +15 -4
- package/lib/offline/download_progress_estimator.js +1 -1
- package/lib/offline/indexeddb/base_storage_cell.js +9 -9
- package/lib/offline/indexeddb/db_connection.js +1 -1
- package/lib/offline/indexeddb/db_operation.js +2 -2
- package/lib/offline/indexeddb/eme_session_storage_cell.js +1 -1
- package/lib/offline/indexeddb/storage_mechanism.js +1 -1
- package/lib/offline/indexeddb/v1_storage_cell.js +3 -3
- package/lib/offline/indexeddb/v2_storage_cell.js +2 -2
- package/lib/offline/manifest_converter.js +11 -12
- package/lib/offline/offline_scheme.js +8 -4
- package/lib/offline/session_deleter.js +11 -11
- package/lib/offline/storage.js +137 -88
- package/lib/offline/storage_muxer.js +8 -8
- package/lib/offline/stored_content_utils.js +3 -3
- package/lib/offline/stream_bandwidth_estimator.js +1 -1
- package/lib/player.js +291 -207
- package/lib/polyfill/all.js +1 -1
- package/lib/polyfill/media_capabilities.js +5 -5
- package/lib/polyfill/patchedmediakeys_apple.js +6 -6
- package/lib/polyfill/patchedmediakeys_webkit.js +8 -8
- package/lib/polyfill/video_play_promise.js +0 -1
- package/lib/text/cue.js +3 -2
- package/lib/text/lrc_text_parser.js +1 -1
- package/lib/text/mp4_ttml_parser.js +1 -1
- package/lib/text/mp4_vtt_parser.js +3 -3
- package/lib/text/sbv_text_parser.js +1 -1
- package/lib/text/simple_text_displayer.js +37 -10
- package/lib/text/ssa_text_parser.js +3 -1
- package/lib/text/stub_text_displayer.js +12 -5
- package/lib/text/text_engine.js +5 -4
- package/lib/text/text_utils.js +4 -4
- package/lib/text/ttml_text_parser.js +21 -20
- package/lib/text/ui_text_displayer.js +20 -13
- package/lib/text/vtt_text_parser.js +10 -10
- package/lib/text/web_vtt_generator.js +2 -2
- package/lib/transmuxer/aac_transmuxer.js +2 -2
- package/lib/transmuxer/ac3_transmuxer.js +2 -2
- package/lib/transmuxer/adts.js +2 -0
- package/lib/transmuxer/ec3.js +3 -3
- package/lib/transmuxer/ec3_transmuxer.js +2 -2
- package/lib/transmuxer/h264.js +5 -5
- package/lib/transmuxer/h265.js +3 -3
- package/lib/transmuxer/mp3_transmuxer.js +2 -2
- package/lib/transmuxer/mpeg_audio.js +6 -6
- package/lib/transmuxer/mss_transmuxer.js +2 -0
- package/lib/transmuxer/transmuxer_engine.js +1 -1
- package/lib/transmuxer/ts_transmuxer.js +10 -10
- package/lib/util/abortable_operation.js +10 -10
- package/lib/util/array_utils.js +6 -6
- package/lib/util/cmcd_manager.js +149 -18
- package/lib/util/cmsd_manager.js +11 -11
- package/lib/util/config_utils.js +3 -3
- package/lib/util/content_steering_manager.js +17 -17
- package/lib/util/data_view_reader.js +3 -3
- package/lib/util/ebml_parser.js +1 -1
- package/lib/util/error.js +11 -6
- package/lib/util/event_manager.js +1 -1
- package/lib/util/exp_golomb.js +1 -1
- package/lib/util/fairplay_utils.js +6 -1
- package/lib/util/fake_event.js +3 -2
- package/lib/util/fake_event_target.js +1 -1
- package/lib/util/functional.js +8 -8
- package/lib/util/id3_utils.js +1 -1
- package/lib/util/iterables.js +6 -6
- package/lib/util/language_utils.js +17 -17
- package/lib/util/manifest_parser_utils.js +13 -13
- package/lib/util/map_utils.js +6 -6
- package/lib/util/media_ready_state_utils.js +1 -1
- package/lib/util/mime_utils.js +15 -4
- package/lib/util/mp4_box_parsers.js +5 -5
- package/lib/util/mp4_generator.js +31 -30
- package/lib/util/mp4_parser.js +2 -2
- package/lib/util/multi_map.js +5 -5
- package/lib/util/mutex.js +1 -1
- package/lib/util/networking.js +1 -1
- package/lib/util/object_utils.js +5 -1
- package/lib/util/operation_manager.js +1 -1
- package/lib/util/periods.js +24 -24
- package/lib/util/platform.js +8 -4
- package/lib/util/player_configuration.js +50 -17
- package/lib/util/pssh.js +34 -6
- package/lib/util/public_promise.js +2 -2
- package/lib/util/state_history.js +2 -2
- package/lib/util/stream_utils.js +138 -120
- package/lib/util/string_utils.js +4 -3
- package/lib/util/switch_history.js +2 -2
- package/lib/util/tXml.js +22 -17
- package/lib/util/text_parser.js +2 -2
- package/lib/util/timer.js +1 -1
- package/lib/util/ts_parser.js +22 -22
- package/lib/util/xml_utils.js +1 -0
- package/package.json +7 -4
- package/project-words.txt +485 -0
- package/shaka-player.uncompiled.js +1 -1
- package/third_party/closure-uri/uri.js +2 -2
- package/third_party/closure-uri/utils.js +2 -2
- package/third_party/language-mapping-list/language-mapping-list.js +1 -1
- package/ui/ad_statistics_button.js +9 -5
- package/ui/airplay_button.js +1 -0
- package/ui/audio_language_selection.js +2 -1
- package/ui/context_menu.js +2 -2
- package/ui/controls.js +7 -7
- package/ui/externs/ui.js +29 -21
- package/ui/externs/watermark.js +64 -0
- package/ui/fast_forward_button.js +1 -1
- package/ui/gl_matrix/matrix_4x4.js +11 -5
- package/ui/hidden_fast_forward_button.js +1 -1
- package/ui/hidden_seek_button.js +1 -1
- package/ui/language_utils.js +27 -26
- package/ui/less/buttons.less +2 -2
- package/ui/localization.js +21 -21
- package/ui/loop_button.js +2 -2
- package/ui/overflow_menu.js +2 -2
- package/ui/playback_rate_selection.js +1 -1
- package/ui/presentation_time.js +4 -1
- package/ui/range_element.js +2 -2
- package/ui/resolution_selection.js +42 -6
- package/ui/rewind_button.js +1 -1
- package/ui/seek_bar.js +5 -5
- package/ui/statistics_button.js +8 -4
- package/ui/text_selection.js +3 -2
- package/ui/ui.js +32 -2
- package/ui/vr_manager.js +3 -3
- package/ui/vr_utils.js +14 -14
- package/ui/vr_webgl.js +5 -5
- package/ui/watermark.js +313 -0
- package/.eslintignore +0 -4
- package/.eslintrc.js +0 -310
- package/lib/polyfill/patchedmediakeys_nop.js +0 -148
package/lib/util/multi_map.js
CHANGED
|
@@ -14,7 +14,7 @@ goog.provide('shaka.util.MultiMap');
|
|
|
14
14
|
shaka.util.MultiMap = class {
|
|
15
15
|
/** */
|
|
16
16
|
constructor() {
|
|
17
|
-
/** @private {!Object
|
|
17
|
+
/** @private {!Object<string, !Array<T>>} */
|
|
18
18
|
this.map_ = {};
|
|
19
19
|
}
|
|
20
20
|
|
|
@@ -37,7 +37,7 @@ shaka.util.MultiMap = class {
|
|
|
37
37
|
/**
|
|
38
38
|
* Get a list of values by key.
|
|
39
39
|
* @param {string} key
|
|
40
|
-
* @return {Array
|
|
40
|
+
* @return {Array<T>} or null if no such key exists.
|
|
41
41
|
*/
|
|
42
42
|
get(key) {
|
|
43
43
|
const list = this.map_[key];
|
|
@@ -49,7 +49,7 @@ shaka.util.MultiMap = class {
|
|
|
49
49
|
|
|
50
50
|
/**
|
|
51
51
|
* Get a list of all values.
|
|
52
|
-
* @return {!Array
|
|
52
|
+
* @return {!Array<T>}
|
|
53
53
|
*/
|
|
54
54
|
getAll() {
|
|
55
55
|
const list = [];
|
|
@@ -87,7 +87,7 @@ shaka.util.MultiMap = class {
|
|
|
87
87
|
|
|
88
88
|
|
|
89
89
|
/**
|
|
90
|
-
* @param {function(string, !Array
|
|
90
|
+
* @param {function(string, !Array<T>)} callback
|
|
91
91
|
*/
|
|
92
92
|
forEach(callback) {
|
|
93
93
|
for (const key in this.map_) {
|
|
@@ -105,7 +105,7 @@ shaka.util.MultiMap = class {
|
|
|
105
105
|
|
|
106
106
|
/**
|
|
107
107
|
* Get a list of all the keys.
|
|
108
|
-
* @return {!Array
|
|
108
|
+
* @return {!Array<string>}
|
|
109
109
|
*/
|
|
110
110
|
keys() {
|
|
111
111
|
return Object.keys(this.map_);
|
package/lib/util/mutex.js
CHANGED
package/lib/util/networking.js
CHANGED
|
@@ -22,7 +22,7 @@ shaka.util.Networking = class {
|
|
|
22
22
|
* will set the byte range. A non-zero start must be provided for |end| to
|
|
23
23
|
* be used.
|
|
24
24
|
*
|
|
25
|
-
* @param {!Array
|
|
25
|
+
* @param {!Array<string>} uris
|
|
26
26
|
* @param {?number} start
|
|
27
27
|
* @param {?number} end
|
|
28
28
|
* @param {shaka.extern.RetryParameters} retryParameters
|
package/lib/util/object_utils.js
CHANGED
|
@@ -22,7 +22,11 @@ shaka.util.ObjectUtils = class {
|
|
|
22
22
|
const seenObjects = new WeakSet();
|
|
23
23
|
// This recursively clones the value |val|, using the captured variable
|
|
24
24
|
// |seenObjects| to track the objects we have already cloned.
|
|
25
|
-
/**
|
|
25
|
+
/**
|
|
26
|
+
* @param {*} val
|
|
27
|
+
* @return {*}
|
|
28
|
+
* @suppress {strictMissingProperties}
|
|
29
|
+
*/
|
|
26
30
|
const clone = (val) => {
|
|
27
31
|
switch (typeof val) {
|
|
28
32
|
case 'undefined':
|
|
@@ -18,7 +18,7 @@ goog.require('shaka.util.IDestroyable');
|
|
|
18
18
|
shaka.util.OperationManager = class {
|
|
19
19
|
/** */
|
|
20
20
|
constructor() {
|
|
21
|
-
/** @private {!Array
|
|
21
|
+
/** @private {!Array<!shaka.extern.IAbortableOperation>} */
|
|
22
22
|
this.operations_ = [];
|
|
23
23
|
}
|
|
24
24
|
|
package/lib/util/periods.js
CHANGED
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
goog.provide('shaka.util.PeriodCombiner');
|
|
8
8
|
|
|
9
9
|
goog.require('goog.asserts');
|
|
10
|
+
goog.require('shaka.drm.DrmUtils');
|
|
10
11
|
goog.require('shaka.log');
|
|
11
12
|
goog.require('shaka.media.MetaSegmentIndex');
|
|
12
13
|
goog.require('shaka.media.SegmentIndex');
|
|
13
|
-
goog.require('shaka.util.DrmUtils');
|
|
14
14
|
goog.require('shaka.util.Error');
|
|
15
15
|
goog.require('shaka.util.IReleasable');
|
|
16
16
|
goog.require('shaka.util.LanguageUtils');
|
|
@@ -27,19 +27,19 @@ goog.require('shaka.util.MimeUtils');
|
|
|
27
27
|
shaka.util.PeriodCombiner = class {
|
|
28
28
|
/** */
|
|
29
29
|
constructor() {
|
|
30
|
-
/** @private {!Array
|
|
30
|
+
/** @private {!Array<shaka.extern.Variant>} */
|
|
31
31
|
this.variants_ = [];
|
|
32
32
|
|
|
33
|
-
/** @private {!Array
|
|
33
|
+
/** @private {!Array<shaka.extern.Stream>} */
|
|
34
34
|
this.audioStreams_ = [];
|
|
35
35
|
|
|
36
|
-
/** @private {!Array
|
|
36
|
+
/** @private {!Array<shaka.extern.Stream>} */
|
|
37
37
|
this.videoStreams_ = [];
|
|
38
38
|
|
|
39
|
-
/** @private {!Array
|
|
39
|
+
/** @private {!Array<shaka.extern.Stream>} */
|
|
40
40
|
this.textStreams_ = [];
|
|
41
41
|
|
|
42
|
-
/** @private {!Array
|
|
42
|
+
/** @private {!Array<shaka.extern.Stream>} */
|
|
43
43
|
this.imageStreams_ = [];
|
|
44
44
|
|
|
45
45
|
/** @private {boolean} */
|
|
@@ -53,7 +53,7 @@ shaka.util.PeriodCombiner = class {
|
|
|
53
53
|
* This helps us identify the periods which have been added when a live
|
|
54
54
|
* stream is updated.
|
|
55
55
|
*
|
|
56
|
-
* @private {!Set
|
|
56
|
+
* @private {!Set<string>}
|
|
57
57
|
*/
|
|
58
58
|
this.usedPeriodIds_ = new Set();
|
|
59
59
|
}
|
|
@@ -81,7 +81,7 @@ shaka.util.PeriodCombiner = class {
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
/**
|
|
84
|
-
* @return {!Array
|
|
84
|
+
* @return {!Array<shaka.extern.Variant>}
|
|
85
85
|
*
|
|
86
86
|
* @export
|
|
87
87
|
*/
|
|
@@ -90,10 +90,10 @@ shaka.util.PeriodCombiner = class {
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
/**
|
|
93
|
-
* @return {!Array
|
|
93
|
+
* @return {!Array<shaka.extern.Stream>}
|
|
94
94
|
*
|
|
95
95
|
* @export
|
|
96
|
-
|
|
96
|
+
*/
|
|
97
97
|
getTextStreams() {
|
|
98
98
|
// Return a copy of the array because makeTextStreamsForClosedCaptions
|
|
99
99
|
// may make changes to the contents of the array. Those changes should not
|
|
@@ -102,7 +102,7 @@ shaka.util.PeriodCombiner = class {
|
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
/**
|
|
105
|
-
* @return {!Array
|
|
105
|
+
* @return {!Array<shaka.extern.Stream>}
|
|
106
106
|
*
|
|
107
107
|
* @export
|
|
108
108
|
*/
|
|
@@ -217,7 +217,7 @@ shaka.util.PeriodCombiner = class {
|
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
/**
|
|
220
|
-
* @param {!Array
|
|
220
|
+
* @param {!Array<shaka.extern.Period>} periods
|
|
221
221
|
* @param {boolean} isDynamic
|
|
222
222
|
* @param {boolean=} isPatchUpdate
|
|
223
223
|
* @return {!Promise}
|
|
@@ -335,7 +335,7 @@ shaka.util.PeriodCombiner = class {
|
|
|
335
335
|
} else {
|
|
336
336
|
for (const audio of this.audioStreams_) {
|
|
337
337
|
for (const video of this.videoStreams_) {
|
|
338
|
-
const commonDrmInfos = shaka.
|
|
338
|
+
const commonDrmInfos = shaka.drm.DrmUtils.getCommonDrmInfos(
|
|
339
339
|
audio.drmInfos, video.drmInfos);
|
|
340
340
|
|
|
341
341
|
if (audio.drmInfos.length && video.drmInfos.length &&
|
|
@@ -375,8 +375,8 @@ shaka.util.PeriodCombiner = class {
|
|
|
375
375
|
* Unlike the DASH case, this does not need to maintain any state for manifest
|
|
376
376
|
* updates.
|
|
377
377
|
*
|
|
378
|
-
* @param {!Array
|
|
379
|
-
* @return {!Promise
|
|
378
|
+
* @param {!Array<!Array<shaka.extern.StreamDB>>} streamDbsPerPeriod
|
|
379
|
+
* @return {!Promise<!Array<shaka.extern.StreamDB>>}
|
|
380
380
|
*/
|
|
381
381
|
static async combineDbStreams(streamDbsPerPeriod) {
|
|
382
382
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
@@ -490,7 +490,7 @@ shaka.util.PeriodCombiner = class {
|
|
|
490
490
|
* Combine input Streams per period into flat output Streams.
|
|
491
491
|
* Templatized to handle both DASH Streams and offline StreamDBs.
|
|
492
492
|
*
|
|
493
|
-
* @param {!Array
|
|
493
|
+
* @param {!Array<T>} outputStreams A list of existing output streams, to
|
|
494
494
|
* facilitate updates for live DASH content. Will be modified and returned.
|
|
495
495
|
* @param {!Array<!Map<string, T>>} streamsPerPeriod A list of maps of Streams
|
|
496
496
|
* from each period.
|
|
@@ -501,7 +501,7 @@ shaka.util.PeriodCombiner = class {
|
|
|
501
501
|
* of the first.
|
|
502
502
|
* @param {number} periodsMissing The number of periods missing
|
|
503
503
|
*
|
|
504
|
-
* @return {!Promise
|
|
504
|
+
* @return {!Promise<!Array<T>>} The same array passed to outputStreams,
|
|
505
505
|
* modified to include any newly-created streams.
|
|
506
506
|
*
|
|
507
507
|
* @template T
|
|
@@ -598,11 +598,11 @@ shaka.util.PeriodCombiner = class {
|
|
|
598
598
|
* represents the first new period that hasn't been processed yet.
|
|
599
599
|
* @param {function(T, T)} concat Concatenate the second stream onto the end
|
|
600
600
|
* of the first.
|
|
601
|
-
* @param {!Array
|
|
601
|
+
* @param {!Array<!Set<T>>} unusedStreamsPerPeriod An array of sets of
|
|
602
602
|
* unused streams from each period.
|
|
603
603
|
* @param {number} periodsMissing How many periods are missing in this update.
|
|
604
604
|
*
|
|
605
|
-
* @return {!Promise
|
|
605
|
+
* @return {!Promise<boolean>}
|
|
606
606
|
*
|
|
607
607
|
* @template T
|
|
608
608
|
* Should only be called with a Stream type in practice, but has call sites
|
|
@@ -691,7 +691,7 @@ shaka.util.PeriodCombiner = class {
|
|
|
691
691
|
* @param {function(T):T} clone Make a clone of an input stream.
|
|
692
692
|
* @param {function(T, T)} concat Concatenate the second stream onto the end
|
|
693
693
|
* of the first.
|
|
694
|
-
* @param {!Array
|
|
694
|
+
* @param {!Array<!Set<T>>} unusedStreamsPerPeriod An array of sets of
|
|
695
695
|
* unused streams from each period.
|
|
696
696
|
*
|
|
697
697
|
* @return {?T} A newly-created output Stream, or null if matches
|
|
@@ -748,7 +748,7 @@ shaka.util.PeriodCombiner = class {
|
|
|
748
748
|
* represents the first new period that hasn't been processed yet.
|
|
749
749
|
* @param {function(T, T)} concat Concatenate the second stream onto the end
|
|
750
750
|
* of the first.
|
|
751
|
-
* @param {!Array
|
|
751
|
+
* @param {!Array<!Set<T>>} unusedStreamsPerPeriod An array of sets of
|
|
752
752
|
* unused streams from each period.
|
|
753
753
|
* @param {number} periodsMissing How many periods are missing in this update
|
|
754
754
|
*
|
|
@@ -914,7 +914,7 @@ shaka.util.PeriodCombiner = class {
|
|
|
914
914
|
}
|
|
915
915
|
}
|
|
916
916
|
|
|
917
|
-
const commonDrmInfos = shaka.
|
|
917
|
+
const commonDrmInfos = shaka.drm.DrmUtils.getCommonDrmInfos(
|
|
918
918
|
output.drmInfos, input.drmInfos);
|
|
919
919
|
if (input.drmInfos.length && output.drmInfos.length &&
|
|
920
920
|
!commonDrmInfos.length) {
|
|
@@ -1143,7 +1143,7 @@ shaka.util.PeriodCombiner = class {
|
|
|
1143
1143
|
|
|
1144
1144
|
/**
|
|
1145
1145
|
* @param {boolean} useOnce if true, stream will be used only once in period
|
|
1146
|
-
* flattening
|
|
1146
|
+
* flattening algorithm.
|
|
1147
1147
|
* @export
|
|
1148
1148
|
*/
|
|
1149
1149
|
setUseStreamOnce(useOnce) {
|
|
@@ -1176,7 +1176,7 @@ shaka.util.PeriodCombiner = class {
|
|
|
1176
1176
|
if (outputStream.drmInfos) {
|
|
1177
1177
|
// Check for compatible DRM systems. Note that clear streams are
|
|
1178
1178
|
// implicitly compatible with any DRM and with each other.
|
|
1179
|
-
if (!shaka.
|
|
1179
|
+
if (!shaka.drm.DrmUtils.areDrmCompatible(outputStream.drmInfos,
|
|
1180
1180
|
candidate.drmInfos)) {
|
|
1181
1181
|
return false;
|
|
1182
1182
|
}
|
package/lib/util/platform.js
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
goog.provide('shaka.util.Platform');
|
|
8
8
|
|
|
9
|
+
goog.require('shaka.drm.DrmUtils');
|
|
9
10
|
goog.require('shaka.log');
|
|
10
|
-
goog.require('shaka.util.DrmUtils');
|
|
11
11
|
goog.require('shaka.util.Timer');
|
|
12
12
|
|
|
13
13
|
|
|
@@ -331,6 +331,7 @@ shaka.util.Platform = class {
|
|
|
331
331
|
|
|
332
332
|
/**
|
|
333
333
|
* Check if the current platform is Playstation 4.
|
|
334
|
+
* @return {boolean}
|
|
334
335
|
*/
|
|
335
336
|
static isPS4() {
|
|
336
337
|
return shaka.util.Platform.userAgentContains_('PlayStation 4');
|
|
@@ -338,6 +339,7 @@ shaka.util.Platform = class {
|
|
|
338
339
|
|
|
339
340
|
/**
|
|
340
341
|
* Check if the current platform is Hisense.
|
|
342
|
+
* @return {boolean}
|
|
341
343
|
*/
|
|
342
344
|
static isHisense() {
|
|
343
345
|
return shaka.util.Platform.userAgentContains_('Hisense') ||
|
|
@@ -346,6 +348,7 @@ shaka.util.Platform = class {
|
|
|
346
348
|
|
|
347
349
|
/**
|
|
348
350
|
* Check if the current platform is Virgin Media device.
|
|
351
|
+
* @return {boolean}
|
|
349
352
|
*/
|
|
350
353
|
static isVirginMedia() {
|
|
351
354
|
return shaka.util.Platform.userAgentContains_('VirginMedia');
|
|
@@ -353,6 +356,7 @@ shaka.util.Platform = class {
|
|
|
353
356
|
|
|
354
357
|
/**
|
|
355
358
|
* Check if the current platform is Orange.
|
|
359
|
+
* @return {boolean}
|
|
356
360
|
*/
|
|
357
361
|
static isOrange() {
|
|
358
362
|
return shaka.util.Platform.userAgentContains_('SOPOpenBrowser');
|
|
@@ -360,6 +364,7 @@ shaka.util.Platform = class {
|
|
|
360
364
|
|
|
361
365
|
/**
|
|
362
366
|
* Check if the current platform is SkyQ STB.
|
|
367
|
+
* @return {boolean}
|
|
363
368
|
*/
|
|
364
369
|
static isSkyQ() {
|
|
365
370
|
return shaka.util.Platform.userAgentContains_('Sky_STB');
|
|
@@ -631,7 +636,7 @@ shaka.util.Platform = class {
|
|
|
631
636
|
*/
|
|
632
637
|
static requiresEncryptionInfoInAllInitSegments(keySystem) {
|
|
633
638
|
const Platform = shaka.util.Platform;
|
|
634
|
-
const isPlayReady = shaka.
|
|
639
|
+
const isPlayReady = shaka.drm.DrmUtils.isPlayReadyKeySystem(keySystem);
|
|
635
640
|
return Platform.isTizen() || Platform.isXboxOne() || Platform.isOrange() ||
|
|
636
641
|
(Platform.isEdge() && Platform.isWindows() && isPlayReady);
|
|
637
642
|
}
|
|
@@ -716,7 +721,7 @@ shaka.util.Platform = class {
|
|
|
716
721
|
/**
|
|
717
722
|
* Detect the maximum resolution that the platform's hardware can handle.
|
|
718
723
|
*
|
|
719
|
-
* @return {!Promise
|
|
724
|
+
* @return {!Promise<shaka.extern.Resolution>}
|
|
720
725
|
*/
|
|
721
726
|
static async detectMaxHardwareResolution() {
|
|
722
727
|
const Platform = shaka.util.Platform;
|
|
@@ -795,7 +800,6 @@ shaka.util.Platform = class {
|
|
|
795
800
|
maxResolution.height = 1080;
|
|
796
801
|
}
|
|
797
802
|
} else if (Platform.isHisense()) {
|
|
798
|
-
// eslint-disable-next-line new-cap
|
|
799
803
|
if (window.Hisense_Get4KSupportState &&
|
|
800
804
|
// eslint-disable-next-line new-cap
|
|
801
805
|
window.Hisense_Get4KSupportState()) {
|
|
@@ -12,6 +12,7 @@ goog.require('shaka.config.AutoShowText');
|
|
|
12
12
|
goog.require('shaka.config.CodecSwitchingStrategy');
|
|
13
13
|
goog.require('shaka.log');
|
|
14
14
|
goog.require('shaka.media.Capabilities');
|
|
15
|
+
goog.require('shaka.media.PreferenceBasedCriteria');
|
|
15
16
|
goog.require('shaka.net.NetworkingEngine');
|
|
16
17
|
goog.require('shaka.util.ConfigUtils');
|
|
17
18
|
goog.require('shaka.util.FairPlayUtils');
|
|
@@ -94,6 +95,8 @@ shaka.util.PlayerConfiguration = class {
|
|
|
94
95
|
parseInbandPsshEnabled: shaka.util.Platform.isXboxOne(),
|
|
95
96
|
minHdcpVersion: '',
|
|
96
97
|
ignoreDuplicateInitData: !shaka.util.Platform.isTizen2(),
|
|
98
|
+
defaultAudioRobustnessForWidevine: 'SW_SECURE_CRYPTO',
|
|
99
|
+
defaultVideoRobustnessForWidevine: 'SW_SECURE_DECODE',
|
|
97
100
|
};
|
|
98
101
|
|
|
99
102
|
// The Xbox One and PS4 only support the Playready DRM, so they should
|
|
@@ -147,6 +150,8 @@ shaka.util.PlayerConfiguration = class {
|
|
|
147
150
|
'com.microsoft.playready',
|
|
148
151
|
'urn:uuid:94ce86fb-07ff-4f43-adb8-93d2fa968ca2':
|
|
149
152
|
'com.apple.fps',
|
|
153
|
+
'urn:uuid:3d5e6d35-9b9a-41e8-b843-dd3c6e72c42c':
|
|
154
|
+
'com.huawei.wiseplay',
|
|
150
155
|
},
|
|
151
156
|
manifestPreprocessor:
|
|
152
157
|
shaka.util.PlayerConfiguration.defaultManifestPreprocessor,
|
|
@@ -157,6 +162,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
157
162
|
useStreamOnceInPeriodFlattening: false,
|
|
158
163
|
updatePeriod: -1,
|
|
159
164
|
enableFastSwitching: true,
|
|
165
|
+
ignoreSupplementalCodecs: false,
|
|
160
166
|
},
|
|
161
167
|
hls: {
|
|
162
168
|
ignoreTextStreamFailures: false,
|
|
@@ -174,6 +180,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
174
180
|
disableClosedCaptionsDetection: false,
|
|
175
181
|
updatePeriod: -1,
|
|
176
182
|
allowLowLatencyByteRangeOptimization: true,
|
|
183
|
+
ignoreSupplementalCodecs: false,
|
|
177
184
|
},
|
|
178
185
|
mss: {
|
|
179
186
|
manifestPreprocessor:
|
|
@@ -201,9 +208,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
201
208
|
[error],
|
|
202
209
|
undefined);
|
|
203
210
|
},
|
|
204
|
-
|
|
205
|
-
// 0.01 if not specified.
|
|
206
|
-
rebufferingGoal: 2,
|
|
211
|
+
rebufferingGoal: 0,
|
|
207
212
|
bufferingGoal: 10,
|
|
208
213
|
bufferBehind: 30,
|
|
209
214
|
evictionGoal: 1,
|
|
@@ -229,10 +234,10 @@ shaka.util.PlayerConfiguration = class {
|
|
|
229
234
|
// will default to 0 if not specified.
|
|
230
235
|
inaccurateManifestTolerance: 2,
|
|
231
236
|
lowLatencyMode: false,
|
|
232
|
-
autoLowLatencyMode: false,
|
|
233
237
|
forceHTTP: false,
|
|
234
238
|
forceHTTPS: false,
|
|
235
239
|
minBytesForProgressEvents: minBytes,
|
|
240
|
+
preferNativeDash: false,
|
|
236
241
|
preferNativeHls: false,
|
|
237
242
|
updateIntervalSeconds: 1,
|
|
238
243
|
observeQualityChanges: false,
|
|
@@ -266,7 +271,6 @@ shaka.util.PlayerConfiguration = class {
|
|
|
266
271
|
vodDynamicPlaybackRate: false,
|
|
267
272
|
vodDynamicPlaybackRateLowBufferRate: 0.95,
|
|
268
273
|
vodDynamicPlaybackRateBufferRatio: 0.5,
|
|
269
|
-
infiniteLiveStreamDuration: false,
|
|
270
274
|
preloadNextUrlWindow: 30,
|
|
271
275
|
loadTimeout: 30,
|
|
272
276
|
clearDecodingCache: shaka.util.Platform.isPS4() ||
|
|
@@ -276,11 +280,6 @@ shaka.util.PlayerConfiguration = class {
|
|
|
276
280
|
shaka.util.Platform.isTizen(),
|
|
277
281
|
};
|
|
278
282
|
|
|
279
|
-
const safariVersion = shaka.util.Platform.safariVersion();
|
|
280
|
-
if (safariVersion && safariVersion >= 17) {
|
|
281
|
-
streaming.infiniteLiveStreamDuration = true;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
283
|
// WebOS, Tizen, Chromecast and Hisense have long hardware pipelines
|
|
285
284
|
// that respond slowly to seeking.
|
|
286
285
|
// Therefore we should not seek when we detect a stall
|
|
@@ -377,6 +376,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
377
376
|
rtpSafetyFactor: 5,
|
|
378
377
|
useHeaders: false,
|
|
379
378
|
includeKeys: [],
|
|
379
|
+
version: 1,
|
|
380
380
|
};
|
|
381
381
|
|
|
382
382
|
const cmsd = {
|
|
@@ -440,6 +440,8 @@ shaka.util.PlayerConfiguration = class {
|
|
|
440
440
|
mediaSource: mediaSource,
|
|
441
441
|
offline: offline,
|
|
442
442
|
abrFactory: () => new shaka.abr.SimpleAbrManager(),
|
|
443
|
+
adaptationSetCriteriaFactory:
|
|
444
|
+
(...args) => new shaka.media.PreferenceBasedCriteria(...args),
|
|
443
445
|
abr: abr,
|
|
444
446
|
autoShowText: AutoShowText.IF_SUBTITLES_MAY_BE_NEEDED,
|
|
445
447
|
preferredAudioLanguage: '',
|
|
@@ -495,6 +497,37 @@ shaka.util.PlayerConfiguration = class {
|
|
|
495
497
|
return config;
|
|
496
498
|
}
|
|
497
499
|
|
|
500
|
+
/**
|
|
501
|
+
* @return {!Object}
|
|
502
|
+
* @export
|
|
503
|
+
*/
|
|
504
|
+
static createDefaultForLL() {
|
|
505
|
+
return {
|
|
506
|
+
streaming: {
|
|
507
|
+
inaccurateManifestTolerance: 0,
|
|
508
|
+
segmentPrefetchLimit: 2,
|
|
509
|
+
updateIntervalSeconds: 0.1,
|
|
510
|
+
maxDisabledTime: 1,
|
|
511
|
+
retryParameters: {
|
|
512
|
+
baseDelay: 100,
|
|
513
|
+
},
|
|
514
|
+
},
|
|
515
|
+
manifest: {
|
|
516
|
+
dash: {
|
|
517
|
+
autoCorrectDrift: false,
|
|
518
|
+
},
|
|
519
|
+
retryParameters: {
|
|
520
|
+
baseDelay: 100,
|
|
521
|
+
},
|
|
522
|
+
},
|
|
523
|
+
drm: {
|
|
524
|
+
retryParameters: {
|
|
525
|
+
baseDelay: 100,
|
|
526
|
+
},
|
|
527
|
+
},
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
|
|
498
531
|
/**
|
|
499
532
|
* Merges the given configuration changes into the given destination. This
|
|
500
533
|
* uses the default Player configurations as the template.
|
|
@@ -513,8 +546,8 @@ shaka.util.PlayerConfiguration = class {
|
|
|
513
546
|
'.drm.advanced': {
|
|
514
547
|
distinctiveIdentifierRequired: false,
|
|
515
548
|
persistentStateRequired: false,
|
|
516
|
-
videoRobustness:
|
|
517
|
-
audioRobustness:
|
|
549
|
+
videoRobustness: [],
|
|
550
|
+
audioRobustness: [],
|
|
518
551
|
sessionType: '',
|
|
519
552
|
serverCertificate: new Uint8Array(0),
|
|
520
553
|
serverCertificateUri: '',
|
|
@@ -529,10 +562,10 @@ shaka.util.PlayerConfiguration = class {
|
|
|
529
562
|
}
|
|
530
563
|
|
|
531
564
|
/**
|
|
532
|
-
* @param {!Array
|
|
565
|
+
* @param {!Array<shaka.extern.Track>} tracks
|
|
533
566
|
* @param {string} preferredAudioLanguage
|
|
534
567
|
* @param {string} preferredVideoHdrLevel
|
|
535
|
-
* @return {!Array
|
|
568
|
+
* @return {!Array<shaka.extern.Track>}
|
|
536
569
|
*/
|
|
537
570
|
static defaultTrackSelect(
|
|
538
571
|
tracks, preferredAudioLanguage, preferredVideoHdrLevel) {
|
|
@@ -555,7 +588,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
555
588
|
}
|
|
556
589
|
}
|
|
557
590
|
|
|
558
|
-
/** @type {!Array
|
|
591
|
+
/** @type {!Array<shaka.extern.Track>} */
|
|
559
592
|
const allVariants = tracks.filter((track) => {
|
|
560
593
|
if (track.type != 'variant') {
|
|
561
594
|
return false;
|
|
@@ -566,7 +599,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
566
599
|
return true;
|
|
567
600
|
});
|
|
568
601
|
|
|
569
|
-
/** @type {!Array
|
|
602
|
+
/** @type {!Array<shaka.extern.Track>} */
|
|
570
603
|
let selectedVariants = [];
|
|
571
604
|
|
|
572
605
|
// Find the locale that best matches our preferred audio locale.
|
|
@@ -632,7 +665,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
632
665
|
});
|
|
633
666
|
}
|
|
634
667
|
|
|
635
|
-
/** @type {!Array
|
|
668
|
+
/** @type {!Array<shaka.extern.Track>} */
|
|
636
669
|
const selectedTracks = [];
|
|
637
670
|
|
|
638
671
|
// If there are multiple matches at different audio bitrates, select the
|
package/lib/util/pssh.js
CHANGED
|
@@ -24,19 +24,19 @@ shaka.util.Pssh = class {
|
|
|
24
24
|
constructor(psshBox) {
|
|
25
25
|
/**
|
|
26
26
|
* In hex.
|
|
27
|
-
* @type {!Array
|
|
27
|
+
* @type {!Array<string>}
|
|
28
28
|
*/
|
|
29
29
|
this.systemIds = [];
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
32
|
* In hex.
|
|
33
|
-
* @type {!Array
|
|
33
|
+
* @type {!Array<string>}
|
|
34
34
|
*/
|
|
35
35
|
this.cencKeyIds = [];
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
38
|
* Array with the pssh boxes found.
|
|
39
|
-
* @type {!Array
|
|
39
|
+
* @type {!Array<!Uint8Array>}
|
|
40
40
|
*/
|
|
41
41
|
this.data = [];
|
|
42
42
|
|
|
@@ -95,7 +95,7 @@ shaka.util.Pssh = class {
|
|
|
95
95
|
*
|
|
96
96
|
* @param {!Uint8Array} data
|
|
97
97
|
* @param {!Uint8Array} systemId
|
|
98
|
-
* @param {!Set
|
|
98
|
+
* @param {!Set<string>} keyIds
|
|
99
99
|
* @param {number} version
|
|
100
100
|
* @return {!Uint8Array}
|
|
101
101
|
*/
|
|
@@ -144,10 +144,38 @@ shaka.util.Pssh = class {
|
|
|
144
144
|
return psshBox;
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
+
/**
|
|
148
|
+
* Returns just the data portion of a single PSSH
|
|
149
|
+
*
|
|
150
|
+
* @param {!Uint8Array} pssh
|
|
151
|
+
* @return {!Uint8Array}
|
|
152
|
+
*/
|
|
153
|
+
static getPsshData(pssh) {
|
|
154
|
+
let offset = 8; // Box size and type fields
|
|
155
|
+
|
|
156
|
+
/** @type {!DataView} */
|
|
157
|
+
const view = shaka.util.BufferUtils.toDataView(pssh);
|
|
158
|
+
|
|
159
|
+
// Read version
|
|
160
|
+
const version = view.getUint8(offset);
|
|
161
|
+
|
|
162
|
+
// Version (1), flags (3), system ID (16)
|
|
163
|
+
offset += 20;
|
|
164
|
+
|
|
165
|
+
if (version > 0) {
|
|
166
|
+
// Key ID count (4) and All key IDs (16*count)
|
|
167
|
+
offset += 4 + (16 * view.getUint32(offset));
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Data size
|
|
171
|
+
offset += 4;
|
|
172
|
+
|
|
173
|
+
return shaka.util.BufferUtils.toUint8(view, offset);
|
|
174
|
+
}
|
|
147
175
|
|
|
148
176
|
/**
|
|
149
177
|
* Normalise the initData array. This is to apply browser specific
|
|
150
|
-
*
|
|
178
|
+
* workarounds, e.g. removing duplicates which appears to occur
|
|
151
179
|
* intermittently when the native msneedkey event fires (i.e. event.initData
|
|
152
180
|
* contains dupes).
|
|
153
181
|
*
|
|
@@ -167,7 +195,7 @@ shaka.util.Pssh = class {
|
|
|
167
195
|
}
|
|
168
196
|
|
|
169
197
|
// Dedupe psshData.
|
|
170
|
-
/** @type {!Array
|
|
198
|
+
/** @type {!Array<!Uint8Array>} */
|
|
171
199
|
const dedupedInitDatas = [];
|
|
172
200
|
for (const initData of pssh.data) {
|
|
173
201
|
const found = dedupedInitDatas.some((x) => {
|
|
@@ -12,12 +12,12 @@ goog.provide('shaka.util.PublicPromise');
|
|
|
12
12
|
* A utility to create Promises with convenient public resolve and reject
|
|
13
13
|
* methods.
|
|
14
14
|
*
|
|
15
|
-
* @extends {Promise
|
|
15
|
+
* @extends {Promise<T>}
|
|
16
16
|
* @template T
|
|
17
17
|
*/
|
|
18
18
|
shaka.util.PublicPromise = class {
|
|
19
19
|
/**
|
|
20
|
-
* @return {!Promise
|
|
20
|
+
* @return {!Promise<T>}
|
|
21
21
|
*/
|
|
22
22
|
constructor() {
|
|
23
23
|
let resolvePromise;
|
|
@@ -33,7 +33,7 @@ shaka.util.StateHistory = class {
|
|
|
33
33
|
* The stats that are "closed" for updating. The "open" state becomes closed
|
|
34
34
|
* once we move to a new state.
|
|
35
35
|
*
|
|
36
|
-
* @private {!Array
|
|
36
|
+
* @private {!Array<shaka.extern.StateChange>}
|
|
37
37
|
*/
|
|
38
38
|
this.closed_ = [];
|
|
39
39
|
}
|
|
@@ -77,7 +77,7 @@ shaka.util.StateHistory = class {
|
|
|
77
77
|
* Get a copy of each state change entry in the history. A copy of each entry
|
|
78
78
|
* is created to break the reference to the internal data.
|
|
79
79
|
*
|
|
80
|
-
* @return {!Array
|
|
80
|
+
* @return {!Array<shaka.extern.StateChange>}
|
|
81
81
|
*/
|
|
82
82
|
getCopy() {
|
|
83
83
|
const clone = (entry) => {
|