shaka-player 4.12.9 → 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 +36 -36
- package/dist/shaka-player.compiled.d.ts +131 -36
- package/dist/shaka-player.compiled.debug.d.ts +131 -36
- package/dist/shaka-player.compiled.debug.externs.js +355 -107
- package/dist/shaka-player.compiled.debug.js +799 -742
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +355 -107
- package/dist/shaka-player.compiled.js +1456 -1423
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +165 -38
- package/dist/shaka-player.ui.debug.d.ts +165 -38
- package/dist/shaka-player.ui.debug.externs.js +394 -113
- package/dist/shaka-player.ui.debug.js +808 -738
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +394 -113
- package/dist/shaka-player.ui.js +1671 -1632
- 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 +137 -108
- package/externs/shaka/text.js +3 -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 +34 -24
- 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 +98 -108
- 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 +14 -14
- 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/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 +71 -26
- 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 +270 -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/ssa_text_parser.js +3 -1
- package/lib/text/stub_text_displayer.js +5 -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 +13 -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/cmcd_manager.js
CHANGED
|
@@ -10,6 +10,7 @@ goog.require('goog.Uri');
|
|
|
10
10
|
goog.require('shaka.log');
|
|
11
11
|
goog.require('shaka.net.NetworkingEngine');
|
|
12
12
|
goog.require('shaka.util.ArrayUtils');
|
|
13
|
+
goog.require('shaka.util.EventManager');
|
|
13
14
|
|
|
14
15
|
goog.requireType('shaka.media.SegmentReference');
|
|
15
16
|
|
|
@@ -43,8 +44,8 @@ shaka.util.CmcdManager = class {
|
|
|
43
44
|
this.playbackStarted_ = false;
|
|
44
45
|
|
|
45
46
|
/**
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
* @private {boolean}
|
|
48
|
+
*/
|
|
48
49
|
this.buffering_ = true;
|
|
49
50
|
|
|
50
51
|
/**
|
|
@@ -56,6 +57,44 @@ shaka.util.CmcdManager = class {
|
|
|
56
57
|
* @private {boolean}
|
|
57
58
|
*/
|
|
58
59
|
this.lowLatency_ = false;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @private {number|undefined}
|
|
63
|
+
*/
|
|
64
|
+
this.playbackPlayTime_ = undefined;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @private {number|undefined}
|
|
68
|
+
*/
|
|
69
|
+
this.playbackPlayingTime_ = undefined;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @private {number}
|
|
73
|
+
*/
|
|
74
|
+
this.startTimeOfLoad_ = 0;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @private {boolean}
|
|
78
|
+
*/
|
|
79
|
+
this.msdSent_ = false;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @private {shaka.util.EventManager}
|
|
83
|
+
*/
|
|
84
|
+
this.eventManager_ = new shaka.util.EventManager();
|
|
85
|
+
|
|
86
|
+
/** @private {HTMLMediaElement} */
|
|
87
|
+
this.video_ = null;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Set media element and setup event listeners
|
|
93
|
+
* @param {HTMLMediaElement} mediaElement The video element
|
|
94
|
+
*/
|
|
95
|
+
setMediaElement(mediaElement) {
|
|
96
|
+
this.video_ = mediaElement;
|
|
97
|
+
this.setupMSDEventListeners_();
|
|
59
98
|
}
|
|
60
99
|
|
|
61
100
|
/**
|
|
@@ -77,6 +116,12 @@ shaka.util.CmcdManager = class {
|
|
|
77
116
|
this.buffering_ = true;
|
|
78
117
|
this.starved_ = false;
|
|
79
118
|
this.lowLatency_ = false;
|
|
119
|
+
this.playbackPlayTime_ = 0;
|
|
120
|
+
this.playbackPlayingTime_ = 0;
|
|
121
|
+
this.startTimeOfLoad_ = 0;
|
|
122
|
+
this.msdSent_ = false;
|
|
123
|
+
this.video_ = null;
|
|
124
|
+
this.eventManager_.removeAll();
|
|
80
125
|
}
|
|
81
126
|
|
|
82
127
|
/**
|
|
@@ -120,6 +165,24 @@ shaka.util.CmcdManager = class {
|
|
|
120
165
|
}
|
|
121
166
|
}
|
|
122
167
|
|
|
168
|
+
/**
|
|
169
|
+
* Set start time of load if autoplay is enabled
|
|
170
|
+
*
|
|
171
|
+
* @param {number} startTimeOfLoad
|
|
172
|
+
*/
|
|
173
|
+
setStartTimeOfLoad(startTimeOfLoad) {
|
|
174
|
+
if (this.video_) {
|
|
175
|
+
const playResult = this.video_.play();
|
|
176
|
+
if (playResult) {
|
|
177
|
+
playResult.then(() => {
|
|
178
|
+
this.startTimeOfLoad_ = startTimeOfLoad;
|
|
179
|
+
}).catch((e) => {
|
|
180
|
+
this.startTimeOfLoad_ = 0;
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
123
186
|
/**
|
|
124
187
|
* Apply CMCD data to a request.
|
|
125
188
|
*
|
|
@@ -248,7 +311,7 @@ shaka.util.CmcdManager = class {
|
|
|
248
311
|
if (stream.segmentIndex && segment) {
|
|
249
312
|
const reverse = playbackRate < 0;
|
|
250
313
|
const iterator = stream.segmentIndex.getIteratorForTime(
|
|
251
|
-
segment.endTime, /*
|
|
314
|
+
segment.endTime, /* allowNonIndependent= */ true, reverse);
|
|
252
315
|
if (iterator) {
|
|
253
316
|
const nextSegment = iterator.next().value;
|
|
254
317
|
if (nextSegment && nextSegment != segment) {
|
|
@@ -360,6 +423,40 @@ shaka.util.CmcdManager = class {
|
|
|
360
423
|
}
|
|
361
424
|
}
|
|
362
425
|
|
|
426
|
+
/**
|
|
427
|
+
* Set playbackPlayTime_ when the play event is triggered
|
|
428
|
+
* @private
|
|
429
|
+
*/
|
|
430
|
+
onPlaybackPlay_() {
|
|
431
|
+
if (!this.playbackPlayTime_) {
|
|
432
|
+
this.playbackPlayTime_ = Date.now();
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Set playbackPlayingTime_
|
|
438
|
+
* @private
|
|
439
|
+
*/
|
|
440
|
+
onPlaybackPlaying_() {
|
|
441
|
+
if (!this.playbackPlayingTime_) {
|
|
442
|
+
this.playbackPlayingTime_ = Date.now();
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Setup event listeners for msd calculation
|
|
448
|
+
* @private
|
|
449
|
+
*/
|
|
450
|
+
setupMSDEventListeners_() {
|
|
451
|
+
const onPlaybackPlay = () => this.onPlaybackPlay_();
|
|
452
|
+
this.eventManager_.listenOnce(
|
|
453
|
+
this.video_, 'play', onPlaybackPlay);
|
|
454
|
+
|
|
455
|
+
const onPlaybackPlaying = () => this.onPlaybackPlaying_();
|
|
456
|
+
this.eventManager_.listenOnce(
|
|
457
|
+
this.video_, 'playing', onPlaybackPlaying);
|
|
458
|
+
}
|
|
459
|
+
|
|
363
460
|
/**
|
|
364
461
|
* Create baseline CMCD data
|
|
365
462
|
*
|
|
@@ -371,7 +468,7 @@ shaka.util.CmcdManager = class {
|
|
|
371
468
|
this.config_.sessionId = window.crypto.randomUUID();
|
|
372
469
|
}
|
|
373
470
|
return {
|
|
374
|
-
v:
|
|
471
|
+
v: this.config_.version,
|
|
375
472
|
sf: this.sf_,
|
|
376
473
|
sid: this.config_.sessionId,
|
|
377
474
|
cid: this.config_.contentId,
|
|
@@ -410,6 +507,18 @@ shaka.util.CmcdManager = class {
|
|
|
410
507
|
data.su = this.buffering_;
|
|
411
508
|
}
|
|
412
509
|
|
|
510
|
+
if (data.v === shaka.util.CmcdManager.Version.VERSION_2) {
|
|
511
|
+
if (this.playerInterface_.isLive()) {
|
|
512
|
+
data.ltc = this.playerInterface_.getLiveLatency();
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
const msd = this.calculateMSD_();
|
|
516
|
+
if (msd != undefined) {
|
|
517
|
+
data.msd = msd;
|
|
518
|
+
this.msdSent_ = true;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
413
522
|
const output = this.filterKeys_(data);
|
|
414
523
|
|
|
415
524
|
if (useHeaders) {
|
|
@@ -459,6 +568,7 @@ shaka.util.CmcdManager = class {
|
|
|
459
568
|
*
|
|
460
569
|
* @param {shaka.extern.RequestContext} context
|
|
461
570
|
* The request context
|
|
571
|
+
* @return {shaka.util.CmcdManager.ObjectType|undefined}
|
|
462
572
|
* @private
|
|
463
573
|
*/
|
|
464
574
|
getObjectType_(context) {
|
|
@@ -615,7 +725,24 @@ shaka.util.CmcdManager = class {
|
|
|
615
725
|
}
|
|
616
726
|
|
|
617
727
|
/**
|
|
618
|
-
* Calculate
|
|
728
|
+
* Calculate measured start delay
|
|
729
|
+
*
|
|
730
|
+
* @return {number|undefined}
|
|
731
|
+
* @private
|
|
732
|
+
*/
|
|
733
|
+
calculateMSD_() {
|
|
734
|
+
if (!this.msdSent_ &&
|
|
735
|
+
this.playbackPlayingTime_ &&
|
|
736
|
+
this.playbackPlayTime_) {
|
|
737
|
+
const startTime = this.startTimeOfLoad_ || this.playbackPlayTime_;
|
|
738
|
+
return this.playbackPlayingTime_ - startTime;
|
|
739
|
+
}
|
|
740
|
+
return undefined;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
|
|
744
|
+
/**
|
|
745
|
+
* Calculate requested maximum throughput
|
|
619
746
|
*
|
|
620
747
|
* @param {shaka.extern.Stream} stream
|
|
621
748
|
* @param {shaka.media.SegmentReference} segment
|
|
@@ -691,7 +818,7 @@ shaka.util.CmcdManager = class {
|
|
|
691
818
|
/**
|
|
692
819
|
* Get the highest bandwidth for a given type.
|
|
693
820
|
*
|
|
694
|
-
* @param {
|
|
821
|
+
* @param {shaka.util.CmcdManager.ObjectType|undefined} type
|
|
695
822
|
* @return {number}
|
|
696
823
|
* @private
|
|
697
824
|
*/
|
|
@@ -810,8 +937,8 @@ shaka.util.CmcdManager = class {
|
|
|
810
937
|
const headerGroups = [{}, {}, {}, {}];
|
|
811
938
|
const headerMap = {
|
|
812
939
|
br: 0, d: 0, ot: 0, tb: 0,
|
|
813
|
-
bl: 1, dl: 1, mtp: 1, nor: 1, nrr: 1, su: 1,
|
|
814
|
-
cid: 2, pr: 2, sf: 2, sid: 2, st: 2, v: 2,
|
|
940
|
+
bl: 1, dl: 1, mtp: 1, nor: 1, nrr: 1, su: 1, ltc: 1,
|
|
941
|
+
cid: 2, pr: 2, sf: 2, sid: 2, st: 2, v: 2, msd: 2,
|
|
815
942
|
bs: 3, rtp: 3,
|
|
816
943
|
};
|
|
817
944
|
|
|
@@ -872,8 +999,9 @@ shaka.util.CmcdManager = class {
|
|
|
872
999
|
* getBufferedInfo: function():shaka.extern.BufferedInfo,
|
|
873
1000
|
* getCurrentTime: function():number,
|
|
874
1001
|
* getPlaybackRate: function():number,
|
|
875
|
-
* getVariantTracks: function():Array
|
|
876
|
-
* isLive: function():boolean
|
|
1002
|
+
* getVariantTracks: function():Array<shaka.extern.Track>,
|
|
1003
|
+
* isLive: function():boolean,
|
|
1004
|
+
* getLiveLatency: function():number
|
|
877
1005
|
* }}
|
|
878
1006
|
*
|
|
879
1007
|
* @property {function():number} getBandwidthEstimate
|
|
@@ -884,10 +1012,13 @@ shaka.util.CmcdManager = class {
|
|
|
884
1012
|
* Get the current time
|
|
885
1013
|
* @property {function():number} getPlaybackRate
|
|
886
1014
|
* Get the playback rate
|
|
887
|
-
* @property {function():Array
|
|
1015
|
+
* @property {function():Array<shaka.extern.Track>} getVariantTracks
|
|
888
1016
|
* Get the variant tracks
|
|
889
1017
|
* @property {function():boolean} isLive
|
|
890
1018
|
* Get if the player is playing live content.
|
|
1019
|
+
* @property {function():number} getLiveLatency
|
|
1020
|
+
* Get latency in milliseconds between the live edge and what's currently
|
|
1021
|
+
* playing.
|
|
891
1022
|
*/
|
|
892
1023
|
shaka.util.CmcdManager.PlayerInterface;
|
|
893
1024
|
|
|
@@ -907,6 +1038,13 @@ shaka.util.CmcdManager.ObjectType = {
|
|
|
907
1038
|
OTHER: 'o',
|
|
908
1039
|
};
|
|
909
1040
|
|
|
1041
|
+
/**
|
|
1042
|
+
* @enum {number}
|
|
1043
|
+
*/
|
|
1044
|
+
shaka.util.CmcdManager.Version = {
|
|
1045
|
+
VERSION_1: 1,
|
|
1046
|
+
VERSION_2: 2,
|
|
1047
|
+
};
|
|
910
1048
|
|
|
911
1049
|
/**
|
|
912
1050
|
* @enum {string}
|
|
@@ -929,10 +1067,3 @@ shaka.util.CmcdManager.StreamingFormat = {
|
|
|
929
1067
|
SMOOTH: 's',
|
|
930
1068
|
OTHER: 'o',
|
|
931
1069
|
};
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
/**
|
|
935
|
-
* The CMCD spec version
|
|
936
|
-
* @const {number}
|
|
937
|
-
*/
|
|
938
|
-
shaka.util.CmcdManager.Version = 1;
|
package/lib/util/cmsd_manager.js
CHANGED
|
@@ -23,10 +23,10 @@ shaka.util.CmsdManager = class {
|
|
|
23
23
|
/** @private {shaka.extern.CmsdConfiguration} */
|
|
24
24
|
this.config_ = config;
|
|
25
25
|
|
|
26
|
-
/** @private {?Map
|
|
26
|
+
/** @private {?Map<string, (boolean | number | string)>} */
|
|
27
27
|
this.staticParams_ = null;
|
|
28
28
|
|
|
29
|
-
/** @private {?Map
|
|
29
|
+
/** @private {?Map<string, (boolean | number | string)>} */
|
|
30
30
|
this.dynamicParams_ = null;
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -52,7 +52,7 @@ shaka.util.CmsdManager = class {
|
|
|
52
52
|
/**
|
|
53
53
|
* Called by the Player to provide the headers of the latest request.
|
|
54
54
|
*
|
|
55
|
-
* @param {!Object
|
|
55
|
+
* @param {!Object<string, string>} headers
|
|
56
56
|
*/
|
|
57
57
|
processHeaders(headers) {
|
|
58
58
|
if (!this.config_.enabled) {
|
|
@@ -161,7 +161,7 @@ shaka.util.CmsdManager = class {
|
|
|
161
161
|
|
|
162
162
|
/**
|
|
163
163
|
* @param {string} headerValue
|
|
164
|
-
* @return {?Map
|
|
164
|
+
* @return {?Map<string, (boolean | number | string)>}
|
|
165
165
|
* @private
|
|
166
166
|
*/
|
|
167
167
|
parseCMSDStatic_(headerValue) {
|
|
@@ -170,9 +170,9 @@ shaka.util.CmsdManager = class {
|
|
|
170
170
|
const items = headerValue.split(',');
|
|
171
171
|
for (let i = 0; i < items.length; i++) {
|
|
172
172
|
// <key>=<value>
|
|
173
|
-
const
|
|
174
|
-
const key =
|
|
175
|
-
const value = this.parseParameterValue_(
|
|
173
|
+
const substrings = items[i].split('=');
|
|
174
|
+
const key = substrings[0];
|
|
175
|
+
const value = this.parseParameterValue_(substrings[1]);
|
|
176
176
|
params.set(key, value);
|
|
177
177
|
}
|
|
178
178
|
return params;
|
|
@@ -185,7 +185,7 @@ shaka.util.CmsdManager = class {
|
|
|
185
185
|
|
|
186
186
|
/**
|
|
187
187
|
* @param {string} headerValue
|
|
188
|
-
* @return {?Map
|
|
188
|
+
* @return {?Map<string, (boolean | number | string)>}
|
|
189
189
|
* @private
|
|
190
190
|
*/
|
|
191
191
|
parseCMSDDynamic_(headerValue) {
|
|
@@ -195,9 +195,9 @@ shaka.util.CmsdManager = class {
|
|
|
195
195
|
// Server identifier as 1st item
|
|
196
196
|
for (let i = 1; i < items.length; i++) {
|
|
197
197
|
// <key>=<value>
|
|
198
|
-
const
|
|
199
|
-
const key =
|
|
200
|
-
const value = this.parseParameterValue_(
|
|
198
|
+
const substrings = items[i].split('=');
|
|
199
|
+
const key = substrings[0];
|
|
200
|
+
const value = this.parseParameterValue_(substrings[1]);
|
|
201
201
|
params.set(key, value);
|
|
202
202
|
}
|
|
203
203
|
return params;
|
package/lib/util/config_utils.js
CHANGED
|
@@ -86,7 +86,7 @@ shaka.util.ConfigUtils = class {
|
|
|
86
86
|
isValid = isValid && subMergeValid;
|
|
87
87
|
} else if (typeof source[k] != typeof subTemplate ||
|
|
88
88
|
source[k] == null ||
|
|
89
|
-
// Function
|
|
89
|
+
// Function constructors are not informative, and differ
|
|
90
90
|
// between sync and async functions. So don't look at
|
|
91
91
|
// constructor for function types.
|
|
92
92
|
(typeof source[k] != 'function' &&
|
|
@@ -125,7 +125,7 @@ shaka.util.ConfigUtils = class {
|
|
|
125
125
|
let last = configObject;
|
|
126
126
|
let searchIndex = 0;
|
|
127
127
|
let nameStart = 0;
|
|
128
|
-
while (true) {
|
|
128
|
+
while (true) {
|
|
129
129
|
const idx = fieldName.indexOf('.', searchIndex);
|
|
130
130
|
if (idx < 0) {
|
|
131
131
|
break;
|
|
@@ -158,7 +158,7 @@ shaka.util.ConfigUtils = class {
|
|
|
158
158
|
a); // Can be anything, doesn't need to be one of the parameters
|
|
159
159
|
* };
|
|
160
160
|
*
|
|
161
|
-
* @param {!Array
|
|
161
|
+
* @param {!Array<?>} parameters
|
|
162
162
|
* @param {T} returnValue
|
|
163
163
|
* @return {T}
|
|
164
164
|
* @template T
|
|
@@ -36,19 +36,19 @@ shaka.util.ContentSteeringManager = class {
|
|
|
36
36
|
/** @private {!shaka.util.OperationManager} */
|
|
37
37
|
this.operationManager_ = new shaka.util.OperationManager();
|
|
38
38
|
|
|
39
|
-
/** @private {!Array
|
|
39
|
+
/** @private {!Array<string>} */
|
|
40
40
|
this.baseUris_ = [];
|
|
41
41
|
|
|
42
42
|
/** @private {?string} */
|
|
43
43
|
this.defaultPathwayId_ = null;
|
|
44
44
|
|
|
45
|
-
/** @private {!Array
|
|
45
|
+
/** @private {!Array<string>} */
|
|
46
46
|
this.pathwayPriority_ = [];
|
|
47
47
|
|
|
48
48
|
/** @private {?string} */
|
|
49
49
|
this.lastPathwayUsed_ = null;
|
|
50
50
|
|
|
51
|
-
/** @private {!Array
|
|
51
|
+
/** @private {!Array<shaka.util.ContentSteeringManager.PathwayClone>} */
|
|
52
52
|
this.pathwayClones_ = [];
|
|
53
53
|
|
|
54
54
|
/**
|
|
@@ -58,10 +58,10 @@ shaka.util.ContentSteeringManager = class {
|
|
|
58
58
|
*/
|
|
59
59
|
this.lastTTL_ = 300;
|
|
60
60
|
|
|
61
|
-
/** @private {!Map
|
|
61
|
+
/** @private {!Map<(string | number), !Map<string, string>>} */
|
|
62
62
|
this.locations_ = new Map();
|
|
63
63
|
|
|
64
|
-
/** @private {!Map
|
|
64
|
+
/** @private {!Map<string, number>} */
|
|
65
65
|
this.bannedLocations_ = new Map();
|
|
66
66
|
|
|
67
67
|
/** @private {?shaka.util.Timer} */
|
|
@@ -105,7 +105,7 @@ shaka.util.ContentSteeringManager = class {
|
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
/**
|
|
108
|
-
* @param {!Array
|
|
108
|
+
* @param {!Array<string>} baseUris
|
|
109
109
|
*/
|
|
110
110
|
setBaseUris(baseUris) {
|
|
111
111
|
this.baseUris_ = baseUris;
|
|
@@ -237,11 +237,11 @@ shaka.util.ContentSteeringManager = class {
|
|
|
237
237
|
*
|
|
238
238
|
* @param {string|number} streamId
|
|
239
239
|
* @param {boolean=} ignoreBaseUrls
|
|
240
|
-
* @return {!Array
|
|
240
|
+
* @return {!Array<string>}
|
|
241
241
|
*/
|
|
242
242
|
getLocations(streamId, ignoreBaseUrls = false) {
|
|
243
243
|
const streamLocations = this.locations_.get(streamId) || new Map();
|
|
244
|
-
/** @type {!Array
|
|
244
|
+
/** @type {!Array<!{pathwayId: string, location: string}>} */
|
|
245
245
|
let locationsPathwayIdMap = [];
|
|
246
246
|
for (const pathwayId of this.pathwayPriority_) {
|
|
247
247
|
const location = streamLocations.get(pathwayId);
|
|
@@ -320,8 +320,8 @@ shaka.util.ContentSteeringManager = class {
|
|
|
320
320
|
* VERSION: number,
|
|
321
321
|
* TTL: number,
|
|
322
322
|
* RELOAD-URI: string,
|
|
323
|
-
* PATHWAY-PRIORITY: !Array
|
|
324
|
-
* PATHWAY-CLONES: !Array
|
|
323
|
+
* PATHWAY-PRIORITY: !Array<string>,
|
|
324
|
+
* PATHWAY-CLONES: !Array<shaka.util.ContentSteeringManager.PathwayClone>
|
|
325
325
|
* }}
|
|
326
326
|
*
|
|
327
327
|
* @description
|
|
@@ -329,10 +329,10 @@ shaka.util.ContentSteeringManager = class {
|
|
|
329
329
|
*
|
|
330
330
|
* @property {string} VERSION
|
|
331
331
|
* @property {number} TTL
|
|
332
|
-
* @property {string RELOAD-URI
|
|
333
|
-
* @property {!Array
|
|
334
|
-
* @property {!Array
|
|
335
|
-
* shaka.util.ContentSteeringManager.
|
|
332
|
+
* @property {string} RELOAD-URI
|
|
333
|
+
* @property {!Array<string>} PATHWAY-PRIORITY
|
|
334
|
+
* @property {!Array<
|
|
335
|
+
* shaka.util.ContentSteeringManager.PathwayClone>} PATHWAY-CLONES
|
|
336
336
|
*/
|
|
337
337
|
shaka.util.ContentSteeringManager.SteeringManifest;
|
|
338
338
|
|
|
@@ -341,15 +341,15 @@ shaka.util.ContentSteeringManager.SteeringManifest;
|
|
|
341
341
|
* @typedef {{
|
|
342
342
|
* BASE-ID: string,
|
|
343
343
|
* ID: string,
|
|
344
|
-
* URI-REPLACEMENT: !Array
|
|
344
|
+
* URI-REPLACEMENT: !Array<shaka.util.ContentSteeringManager.UriReplacement>
|
|
345
345
|
* }}
|
|
346
346
|
*
|
|
347
347
|
* @property {string} BASE-ID
|
|
348
348
|
* @property {string} ID
|
|
349
|
-
* @property {!Array
|
|
349
|
+
* @property {!Array<
|
|
350
350
|
* shaka.util.ContentSteeringManager.UriReplacement>} URI-REPLACEMENT
|
|
351
351
|
*/
|
|
352
|
-
shaka.util.ContentSteeringManager.
|
|
352
|
+
shaka.util.ContentSteeringManager.PathwayClone;
|
|
353
353
|
|
|
354
354
|
|
|
355
355
|
/**
|
|
@@ -13,9 +13,9 @@ goog.require('shaka.util.StringUtils');
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
* @summary DataViewReader abstracts a DataView object.
|
|
17
|
+
* @export
|
|
18
|
+
*/
|
|
19
19
|
shaka.util.DataViewReader = class {
|
|
20
20
|
/**
|
|
21
21
|
* @param {BufferSource} data
|
package/lib/util/ebml_parser.js
CHANGED
package/lib/util/error.js
CHANGED
|
@@ -208,7 +208,7 @@ shaka.util.Error.Code = {
|
|
|
208
208
|
* <br> error.data[0] is the URI.
|
|
209
209
|
* <br> error.data[1] is the status code.
|
|
210
210
|
* <br> error.data[2] is the response text, or null if the response could not
|
|
211
|
-
* be
|
|
211
|
+
* be interpreted as text.
|
|
212
212
|
* <br> error.data[3] is the map of response headers.
|
|
213
213
|
* <br> error.data[4] is the NetworkingEngine.RequestType of the request,
|
|
214
214
|
* if one was provided.
|
|
@@ -509,7 +509,7 @@ shaka.util.Error.Code = {
|
|
|
509
509
|
// RETIRED: 'MSS_TRANSMUXING_CODEC_UNKNOWN': 3021,
|
|
510
510
|
|
|
511
511
|
/**
|
|
512
|
-
* MSS
|
|
512
|
+
* MSS transmuxing failed for unknown reason.
|
|
513
513
|
* <br> error.data[0] is the segment URI that triggered the error, if any.
|
|
514
514
|
*/
|
|
515
515
|
'MSS_TRANSMUXING_FAILED': 3022,
|
|
@@ -600,7 +600,7 @@ shaka.util.Error.Code = {
|
|
|
600
600
|
// RETIRED: 'NO_PERIODS': 4014,
|
|
601
601
|
|
|
602
602
|
/**
|
|
603
|
-
* HLS playlist doesn't start with a
|
|
603
|
+
* HLS playlist doesn't start with a mandatory #EXTM3U tag.
|
|
604
604
|
*/
|
|
605
605
|
'HLS_PLAYLIST_HEADER_MISSING': 4015,
|
|
606
606
|
|
|
@@ -681,8 +681,8 @@ shaka.util.Error.Code = {
|
|
|
681
681
|
* example, this could happen if the content is WebM, but your browser does
|
|
682
682
|
* not support the WebM container, or if the content uses HEVC, but your
|
|
683
683
|
* browser does not support the HEVC codec. This can also occur for
|
|
684
|
-
*
|
|
685
|
-
* are supported by the browser.
|
|
684
|
+
* multi codec or multi container manifests if none of the codecs
|
|
685
|
+
* or containers are supported by the browser.
|
|
686
686
|
*
|
|
687
687
|
* To see what your browser supports, you can check the JSON data dumped by
|
|
688
688
|
* http://support.shaka-player-demo.appspot.com/
|
|
@@ -702,7 +702,7 @@ shaka.util.Error.Code = {
|
|
|
702
702
|
|
|
703
703
|
/**
|
|
704
704
|
* We failed to find matching streams across DASH Periods, and the
|
|
705
|
-
* period-flattening
|
|
705
|
+
* period-flattening algorithm introduced in v3.0 has failed.
|
|
706
706
|
*/
|
|
707
707
|
'PERIOD_FLATTENING_FAILED': 4037,
|
|
708
708
|
|
|
@@ -935,6 +935,11 @@ shaka.util.Error.Code = {
|
|
|
935
935
|
*/
|
|
936
936
|
'ERROR_CHECKING_HDCP_VERSION': 6019,
|
|
937
937
|
|
|
938
|
+
/**
|
|
939
|
+
* The browser does not support EME APIs, so DRM content cannot be played.
|
|
940
|
+
*/
|
|
941
|
+
'MISSING_EME_SUPPORT': 6020,
|
|
942
|
+
|
|
938
943
|
|
|
939
944
|
/**
|
|
940
945
|
* The call to Player.load() was interrupted by a call to Player.unload()
|
|
@@ -24,7 +24,7 @@ shaka.util.EventManager = class {
|
|
|
24
24
|
constructor() {
|
|
25
25
|
/**
|
|
26
26
|
* Maps an event type to an array of event bindings.
|
|
27
|
-
* @private {shaka.util.MultiMap
|
|
27
|
+
* @private {shaka.util.MultiMap<!shaka.util.EventManager.Binding_>}
|
|
28
28
|
*/
|
|
29
29
|
this.bindingMap_ = new shaka.util.MultiMap();
|
|
30
30
|
}
|
package/lib/util/exp_golomb.js
CHANGED
|
@@ -23,7 +23,7 @@ goog.require('shaka.util.DataViewReader');
|
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* @summary
|
|
26
|
-
* Parser for exponential Golomb codes, a variable-
|
|
26
|
+
* Parser for exponential Golomb codes, a variable-bit width number encoding
|
|
27
27
|
* scheme used by h264.
|
|
28
28
|
* Based on https://github.com/videojs/mux.js/blob/main/lib/utils/exp-golomb.js
|
|
29
29
|
*
|
|
@@ -23,7 +23,7 @@ shaka.util.FairPlayUtils = class {
|
|
|
23
23
|
/**
|
|
24
24
|
* Check if FairPlay is supported.
|
|
25
25
|
*
|
|
26
|
-
* @return {!Promise
|
|
26
|
+
* @return {!Promise<boolean>}
|
|
27
27
|
* @export
|
|
28
28
|
*/
|
|
29
29
|
static async isFairPlaySupported() {
|
|
@@ -138,6 +138,7 @@ shaka.util.FairPlayUtils = class {
|
|
|
138
138
|
* @param {!Uint8Array} initData
|
|
139
139
|
* @param {string} initDataType
|
|
140
140
|
* @param {?shaka.extern.DrmInfo} drmInfo
|
|
141
|
+
* @return {!Uint8Array}
|
|
141
142
|
* @private
|
|
142
143
|
*/
|
|
143
144
|
static basicInitDataTransform_(initData, initDataType, drmInfo) {
|
|
@@ -158,6 +159,7 @@ shaka.util.FairPlayUtils = class {
|
|
|
158
159
|
* @param {!Uint8Array} initData
|
|
159
160
|
* @param {string} initDataType
|
|
160
161
|
* @param {?shaka.extern.DrmInfo} drmInfo
|
|
162
|
+
* @return {!Uint8Array}
|
|
161
163
|
* @export
|
|
162
164
|
*/
|
|
163
165
|
static verimatrixInitDataTransform(initData, initDataType, drmInfo) {
|
|
@@ -171,6 +173,7 @@ shaka.util.FairPlayUtils = class {
|
|
|
171
173
|
* @param {!Uint8Array} initData
|
|
172
174
|
* @param {string} initDataType
|
|
173
175
|
* @param {?shaka.extern.DrmInfo} drmInfo
|
|
176
|
+
* @return {!Uint8Array}
|
|
174
177
|
* @export
|
|
175
178
|
*/
|
|
176
179
|
static ezdrmInitDataTransform(initData, initDataType, drmInfo) {
|
|
@@ -191,6 +194,7 @@ shaka.util.FairPlayUtils = class {
|
|
|
191
194
|
* @param {!Uint8Array} initData
|
|
192
195
|
* @param {string} initDataType
|
|
193
196
|
* @param {?shaka.extern.DrmInfo} drmInfo
|
|
197
|
+
* @return {!Uint8Array}
|
|
194
198
|
* @export
|
|
195
199
|
*/
|
|
196
200
|
static conaxInitDataTransform(initData, initDataType, drmInfo) {
|
|
@@ -221,6 +225,7 @@ shaka.util.FairPlayUtils = class {
|
|
|
221
225
|
* @param {!Uint8Array} initData
|
|
222
226
|
* @param {string} initDataType
|
|
223
227
|
* @param {?shaka.extern.DrmInfo} drmInfo
|
|
228
|
+
* @return {!Uint8Array}
|
|
224
229
|
* @export
|
|
225
230
|
*/
|
|
226
231
|
static expressplayInitDataTransform(initData, initDataType, drmInfo) {
|
package/lib/util/fake_event.js
CHANGED
|
@@ -36,7 +36,7 @@ shaka.util.FakeEvent = class {
|
|
|
36
36
|
/**
|
|
37
37
|
* Allows us to tell the compiler that the dictionary "map" is actually a
|
|
38
38
|
* generic object, for backwards compatibility.
|
|
39
|
-
* @param {!Map
|
|
39
|
+
* @param {!Map<string, Object>} dict
|
|
40
40
|
* @return {!Object}
|
|
41
41
|
* @suppress {invalidCasts}
|
|
42
42
|
* @private
|
|
@@ -48,7 +48,7 @@ shaka.util.FakeEvent = class {
|
|
|
48
48
|
|
|
49
49
|
/**
|
|
50
50
|
* @param {string} type
|
|
51
|
-
* @param {Map
|
|
51
|
+
* @param {Map<string, Object>=} dict
|
|
52
52
|
*/
|
|
53
53
|
constructor(type, dict) {
|
|
54
54
|
if (dict) {
|
|
@@ -158,6 +158,7 @@ shaka.util.FakeEvent.EventName = {
|
|
|
158
158
|
AudioTrackChanged: 'audiotrackchanged',
|
|
159
159
|
Buffering: 'buffering',
|
|
160
160
|
Complete: 'complete',
|
|
161
|
+
DownloadCompleted: 'downloadcompleted',
|
|
161
162
|
DownloadFailed: 'downloadfailed',
|
|
162
163
|
DownloadHeadersReceived: 'downloadheadersreceived',
|
|
163
164
|
DrmSessionUpdate: 'drmsessionupdate',
|
|
@@ -26,7 +26,7 @@ shaka.util.FakeEventTarget = class {
|
|
|
26
26
|
/** */
|
|
27
27
|
constructor() {
|
|
28
28
|
/**
|
|
29
|
-
* @private {shaka.util.MultiMap
|
|
29
|
+
* @private {shaka.util.MultiMap<shaka.util.FakeEventTarget.ListenerType>}
|
|
30
30
|
*/
|
|
31
31
|
this.listeners_ = new shaka.util.MultiMap();
|
|
32
32
|
|