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.
Files changed (261) hide show
  1. package/AUTHORS +1 -0
  2. package/CONTRIBUTORS +4 -0
  3. package/README.md +22 -21
  4. package/cspell.config.yaml +18 -0
  5. package/dist/controls.css +1 -1
  6. package/dist/controls.css.map +1 -1
  7. package/dist/deps.js +29 -24
  8. package/dist/locales.js +33 -33
  9. package/dist/shaka-player.compiled.d.ts +138 -36
  10. package/dist/shaka-player.compiled.debug.d.ts +138 -36
  11. package/dist/shaka-player.compiled.debug.externs.js +367 -107
  12. package/dist/shaka-player.compiled.debug.js +828 -765
  13. package/dist/shaka-player.compiled.debug.map +4 -4
  14. package/dist/shaka-player.compiled.externs.js +367 -107
  15. package/dist/shaka-player.compiled.js +1451 -1416
  16. package/dist/shaka-player.compiled.map +4 -4
  17. package/dist/shaka-player.ui.d.ts +172 -38
  18. package/dist/shaka-player.ui.debug.d.ts +172 -38
  19. package/dist/shaka-player.ui.debug.externs.js +406 -113
  20. package/dist/shaka-player.ui.debug.js +842 -766
  21. package/dist/shaka-player.ui.debug.map +4 -4
  22. package/dist/shaka-player.ui.externs.js +406 -113
  23. package/dist/shaka-player.ui.js +1670 -1628
  24. package/dist/shaka-player.ui.map +4 -4
  25. package/eslint.config.mjs +343 -0
  26. package/externs/airplay.js +1 -1
  27. package/externs/audiotrack.js +1 -1
  28. package/externs/awesomplete.js +1 -1
  29. package/externs/cast-sdk-v2.js +2 -2
  30. package/externs/cmcd.js +16 -1
  31. package/externs/device_sensor_event.js +1 -1
  32. package/externs/ima.js +8 -8
  33. package/externs/isoboxer.js +31 -31
  34. package/externs/jwk_set.js +1 -1
  35. package/externs/lcevc.js +8 -8
  36. package/externs/mediakeys.js +1 -1
  37. package/externs/mediasession.js +3 -2
  38. package/externs/mediatailor.js +18 -18
  39. package/externs/pictureinpicture.js +41 -1
  40. package/externs/playstation.js +2 -2
  41. package/externs/prefixed_eme.js +1 -1
  42. package/externs/shaka/abortable.js +4 -4
  43. package/externs/shaka/abr_manager.js +1 -1
  44. package/externs/shaka/ads.js +45 -6
  45. package/externs/shaka/cea.js +2 -2
  46. package/externs/shaka/codecs.js +4 -4
  47. package/externs/shaka/drm_info.js +6 -6
  48. package/externs/shaka/error.js +5 -5
  49. package/externs/shaka/manifest.js +51 -56
  50. package/externs/shaka/manifest_parser.js +3 -9
  51. package/externs/shaka/net.js +23 -20
  52. package/externs/shaka/offline.js +37 -37
  53. package/externs/shaka/offline_compat_v1.js +10 -10
  54. package/externs/shaka/offline_compat_v2.js +10 -10
  55. package/externs/shaka/player.js +139 -109
  56. package/externs/shaka/text.js +10 -3
  57. package/externs/shaka/transmuxer.js +1 -1
  58. package/externs/videotrack.js +1 -1
  59. package/lib/abr/ewma.js +1 -1
  60. package/lib/abr/simple_abr_manager.js +70 -22
  61. package/lib/ads/ad_manager.js +43 -18
  62. package/lib/ads/ad_utils.js +160 -58
  63. package/lib/ads/ads_stats.js +1 -1
  64. package/lib/ads/client_side_ad_manager.js +2 -2
  65. package/lib/ads/interstitial_ad.js +16 -11
  66. package/lib/ads/interstitial_ad_manager.js +419 -72
  67. package/lib/ads/interstitial_static_ad.js +299 -0
  68. package/lib/ads/media_tailor_ad.js +1 -0
  69. package/lib/ads/media_tailor_ad_manager.js +37 -36
  70. package/lib/ads/server_side_ad_manager.js +7 -6
  71. package/lib/cast/cast_receiver.js +5 -3
  72. package/lib/cast/cast_sender.js +2 -2
  73. package/lib/cast/cast_utils.js +20 -13
  74. package/lib/cea/cea608_data_channel.js +53 -53
  75. package/lib/cea/cea708_service.js +42 -40
  76. package/lib/cea/cea708_window.js +5 -2
  77. package/lib/cea/cea_decoder.js +5 -7
  78. package/lib/cea/mp4_cea_parser.js +1 -1
  79. package/lib/cea/sei_processor.js +1 -1
  80. package/lib/dash/content_protection.js +62 -192
  81. package/lib/dash/dash_parser.js +119 -119
  82. package/lib/dash/mpd_utils.js +14 -13
  83. package/lib/dash/segment_base.js +5 -5
  84. package/lib/dash/segment_list.js +10 -10
  85. package/lib/dash/segment_template.js +55 -53
  86. package/lib/debug/log.js +2 -2
  87. package/lib/dependencies/all.js +2 -1
  88. package/lib/{media → drm}/drm_engine.js +274 -143
  89. package/lib/{util → drm}/drm_utils.js +20 -11
  90. package/lib/drm/playready.js +233 -0
  91. package/lib/hls/hls_classes.js +14 -14
  92. package/lib/hls/hls_parser.js +257 -196
  93. package/lib/hls/hls_utils.js +14 -14
  94. package/lib/hls/manifest_text_parser.js +10 -10
  95. package/lib/media/adaptation_set.js +6 -5
  96. package/lib/media/adaptation_set_criteria.js +51 -379
  97. package/lib/media/buffering_observer.js +5 -4
  98. package/lib/media/closed_caption_parser.js +2 -2
  99. package/lib/media/content_workarounds.js +2 -2
  100. package/lib/media/example_based_criteria.js +69 -0
  101. package/lib/media/gap_jumping_controller.js +14 -1
  102. package/lib/media/manifest_filterer.js +8 -8
  103. package/lib/media/manifest_parser.js +2 -2
  104. package/lib/media/media_source_capabilities.js +20 -1
  105. package/lib/media/media_source_engine.js +84 -35
  106. package/lib/media/mp4_segment_index_parser.js +5 -5
  107. package/lib/media/playhead.js +2 -8
  108. package/lib/media/playhead_observer.js +1 -1
  109. package/lib/media/preference_based_criteria.js +333 -0
  110. package/lib/media/preload_manager.js +53 -37
  111. package/lib/media/presentation_timeline.js +2 -2
  112. package/lib/media/quality_observer.js +35 -35
  113. package/lib/media/region_observer.js +2 -2
  114. package/lib/media/region_timeline.js +3 -3
  115. package/lib/media/segment_index.js +14 -14
  116. package/lib/media/segment_prefetch.js +17 -13
  117. package/lib/media/segment_reference.js +7 -7
  118. package/lib/media/segment_utils.js +9 -9
  119. package/lib/media/streaming_engine.js +77 -38
  120. package/lib/media/time_ranges_utils.js +1 -1
  121. package/lib/media/video_wrapper.js +1 -1
  122. package/lib/media/webm_segment_index_parser.js +4 -4
  123. package/lib/mss/content_protection.js +17 -222
  124. package/lib/mss/mss_parser.js +23 -24
  125. package/lib/net/data_uri_plugin.js +1 -0
  126. package/lib/net/http_fetch_plugin.js +8 -7
  127. package/lib/net/http_plugin_utils.js +5 -2
  128. package/lib/net/http_xhr_plugin.js +4 -3
  129. package/lib/net/networking_engine.js +72 -17
  130. package/lib/net/networking_utils.js +5 -2
  131. package/lib/offline/download_info.js +5 -1
  132. package/lib/offline/download_manager.js +15 -4
  133. package/lib/offline/download_progress_estimator.js +1 -1
  134. package/lib/offline/indexeddb/base_storage_cell.js +9 -9
  135. package/lib/offline/indexeddb/db_connection.js +1 -1
  136. package/lib/offline/indexeddb/db_operation.js +2 -2
  137. package/lib/offline/indexeddb/eme_session_storage_cell.js +1 -1
  138. package/lib/offline/indexeddb/storage_mechanism.js +1 -1
  139. package/lib/offline/indexeddb/v1_storage_cell.js +3 -3
  140. package/lib/offline/indexeddb/v2_storage_cell.js +2 -2
  141. package/lib/offline/manifest_converter.js +11 -12
  142. package/lib/offline/offline_scheme.js +8 -4
  143. package/lib/offline/session_deleter.js +11 -11
  144. package/lib/offline/storage.js +137 -88
  145. package/lib/offline/storage_muxer.js +8 -8
  146. package/lib/offline/stored_content_utils.js +3 -3
  147. package/lib/offline/stream_bandwidth_estimator.js +1 -1
  148. package/lib/player.js +291 -207
  149. package/lib/polyfill/all.js +1 -1
  150. package/lib/polyfill/media_capabilities.js +5 -5
  151. package/lib/polyfill/patchedmediakeys_apple.js +6 -6
  152. package/lib/polyfill/patchedmediakeys_webkit.js +8 -8
  153. package/lib/polyfill/video_play_promise.js +0 -1
  154. package/lib/text/cue.js +3 -2
  155. package/lib/text/lrc_text_parser.js +1 -1
  156. package/lib/text/mp4_ttml_parser.js +1 -1
  157. package/lib/text/mp4_vtt_parser.js +3 -3
  158. package/lib/text/sbv_text_parser.js +1 -1
  159. package/lib/text/simple_text_displayer.js +37 -10
  160. package/lib/text/ssa_text_parser.js +3 -1
  161. package/lib/text/stub_text_displayer.js +12 -5
  162. package/lib/text/text_engine.js +5 -4
  163. package/lib/text/text_utils.js +4 -4
  164. package/lib/text/ttml_text_parser.js +21 -20
  165. package/lib/text/ui_text_displayer.js +20 -13
  166. package/lib/text/vtt_text_parser.js +10 -10
  167. package/lib/text/web_vtt_generator.js +2 -2
  168. package/lib/transmuxer/aac_transmuxer.js +2 -2
  169. package/lib/transmuxer/ac3_transmuxer.js +2 -2
  170. package/lib/transmuxer/adts.js +2 -0
  171. package/lib/transmuxer/ec3.js +3 -3
  172. package/lib/transmuxer/ec3_transmuxer.js +2 -2
  173. package/lib/transmuxer/h264.js +5 -5
  174. package/lib/transmuxer/h265.js +3 -3
  175. package/lib/transmuxer/mp3_transmuxer.js +2 -2
  176. package/lib/transmuxer/mpeg_audio.js +6 -6
  177. package/lib/transmuxer/mss_transmuxer.js +2 -0
  178. package/lib/transmuxer/transmuxer_engine.js +1 -1
  179. package/lib/transmuxer/ts_transmuxer.js +10 -10
  180. package/lib/util/abortable_operation.js +10 -10
  181. package/lib/util/array_utils.js +6 -6
  182. package/lib/util/cmcd_manager.js +149 -18
  183. package/lib/util/cmsd_manager.js +11 -11
  184. package/lib/util/config_utils.js +3 -3
  185. package/lib/util/content_steering_manager.js +17 -17
  186. package/lib/util/data_view_reader.js +3 -3
  187. package/lib/util/ebml_parser.js +1 -1
  188. package/lib/util/error.js +11 -6
  189. package/lib/util/event_manager.js +1 -1
  190. package/lib/util/exp_golomb.js +1 -1
  191. package/lib/util/fairplay_utils.js +6 -1
  192. package/lib/util/fake_event.js +3 -2
  193. package/lib/util/fake_event_target.js +1 -1
  194. package/lib/util/functional.js +8 -8
  195. package/lib/util/id3_utils.js +1 -1
  196. package/lib/util/iterables.js +6 -6
  197. package/lib/util/language_utils.js +17 -17
  198. package/lib/util/manifest_parser_utils.js +13 -13
  199. package/lib/util/map_utils.js +6 -6
  200. package/lib/util/media_ready_state_utils.js +1 -1
  201. package/lib/util/mime_utils.js +15 -4
  202. package/lib/util/mp4_box_parsers.js +5 -5
  203. package/lib/util/mp4_generator.js +31 -30
  204. package/lib/util/mp4_parser.js +2 -2
  205. package/lib/util/multi_map.js +5 -5
  206. package/lib/util/mutex.js +1 -1
  207. package/lib/util/networking.js +1 -1
  208. package/lib/util/object_utils.js +5 -1
  209. package/lib/util/operation_manager.js +1 -1
  210. package/lib/util/periods.js +24 -24
  211. package/lib/util/platform.js +8 -4
  212. package/lib/util/player_configuration.js +50 -17
  213. package/lib/util/pssh.js +34 -6
  214. package/lib/util/public_promise.js +2 -2
  215. package/lib/util/state_history.js +2 -2
  216. package/lib/util/stream_utils.js +138 -120
  217. package/lib/util/string_utils.js +4 -3
  218. package/lib/util/switch_history.js +2 -2
  219. package/lib/util/tXml.js +22 -17
  220. package/lib/util/text_parser.js +2 -2
  221. package/lib/util/timer.js +1 -1
  222. package/lib/util/ts_parser.js +22 -22
  223. package/lib/util/xml_utils.js +1 -0
  224. package/package.json +7 -4
  225. package/project-words.txt +485 -0
  226. package/shaka-player.uncompiled.js +1 -1
  227. package/third_party/closure-uri/uri.js +2 -2
  228. package/third_party/closure-uri/utils.js +2 -2
  229. package/third_party/language-mapping-list/language-mapping-list.js +1 -1
  230. package/ui/ad_statistics_button.js +9 -5
  231. package/ui/airplay_button.js +1 -0
  232. package/ui/audio_language_selection.js +2 -1
  233. package/ui/context_menu.js +2 -2
  234. package/ui/controls.js +7 -7
  235. package/ui/externs/ui.js +29 -21
  236. package/ui/externs/watermark.js +64 -0
  237. package/ui/fast_forward_button.js +1 -1
  238. package/ui/gl_matrix/matrix_4x4.js +11 -5
  239. package/ui/hidden_fast_forward_button.js +1 -1
  240. package/ui/hidden_seek_button.js +1 -1
  241. package/ui/language_utils.js +27 -26
  242. package/ui/less/buttons.less +2 -2
  243. package/ui/localization.js +21 -21
  244. package/ui/loop_button.js +2 -2
  245. package/ui/overflow_menu.js +2 -2
  246. package/ui/playback_rate_selection.js +1 -1
  247. package/ui/presentation_time.js +4 -1
  248. package/ui/range_element.js +2 -2
  249. package/ui/resolution_selection.js +42 -6
  250. package/ui/rewind_button.js +1 -1
  251. package/ui/seek_bar.js +5 -5
  252. package/ui/statistics_button.js +8 -4
  253. package/ui/text_selection.js +3 -2
  254. package/ui/ui.js +32 -2
  255. package/ui/vr_manager.js +3 -3
  256. package/ui/vr_utils.js +14 -14
  257. package/ui/vr_webgl.js +5 -5
  258. package/ui/watermark.js +313 -0
  259. package/.eslintignore +0 -4
  260. package/.eslintrc.js +0 -310
  261. package/lib/polyfill/patchedmediakeys_nop.js +0 -148
@@ -55,7 +55,7 @@ shaka.media.ContentWorkarounds = class {
55
55
  // Multiplexed content could have multiple boxes that we need to modify.
56
56
  // Add to this array in order of box offset. This will be important later,
57
57
  // when we process the boxes.
58
- /** @type {!Array.<{box: shaka.extern.ParsedBox, newType: number}>} */
58
+ /** @type {!Array<{box: shaka.extern.ParsedBox, newType: number}>} */
59
59
  const boxesToModify = [];
60
60
 
61
61
  new shaka.util.Mp4Parser()
@@ -208,7 +208,7 @@ shaka.media.ContentWorkarounds = class {
208
208
  * @param {!Uint8Array} initSegment
209
209
  * @param {shaka.extern.ParsedBox} stsdBox
210
210
  * @param {shaka.extern.ParsedBox} sourceBox
211
- * @param {!Array.<shaka.extern.ParsedBox>} ancestorBoxes
211
+ * @param {!Array<shaka.extern.ParsedBox>} ancestorBoxes
212
212
  * @param {number} metadataBoxType
213
213
  * @return {!Uint8Array}
214
214
  * @private
@@ -0,0 +1,69 @@
1
+ /*! @license
2
+ * Shaka Player
3
+ * Copyright 2016 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ goog.provide('shaka.media.ExampleBasedCriteria');
8
+
9
+ goog.require('shaka.media.AdaptationSetCriteria');
10
+ goog.requireType('shaka.config.CodecSwitchingStrategy');
11
+
12
+
13
+ /**
14
+ * @implements {shaka.media.AdaptationSetCriteria}
15
+ * @final
16
+ */
17
+ shaka.media.ExampleBasedCriteria = class {
18
+ /**
19
+ * @param {shaka.extern.Variant} example
20
+ * @param {shaka.config.CodecSwitchingStrategy} codecSwitchingStrategy
21
+ * @param {shaka.media.AdaptationSetCriteria.Factory
22
+ * } adaptationSetCriteriaFactory
23
+ */
24
+ constructor(example, codecSwitchingStrategy, adaptationSetCriteriaFactory) {
25
+ // We can't know if role and label are really important, so we don't use
26
+ // role and label for this.
27
+ const role = '';
28
+ const audioLabel = '';
29
+ const videoLabel = '';
30
+ const hdrLevel = example.video && example.video.hdr ?
31
+ example.video.hdr : '';
32
+ const spatialAudio = example.audio && example.audio.spatialAudio ?
33
+ example.audio.spatialAudio : false;
34
+ const videoLayout = example.video && example.video.videoLayout ?
35
+ example.video.videoLayout : '';
36
+ const channelCount = example.audio && example.audio.channelsCount ?
37
+ example.audio.channelsCount : 0;
38
+ const audioCodec = example.audio && example.audio.codecs ?
39
+ example.audio.codecs : '';
40
+
41
+ /** @private {!shaka.media.AdaptationSetCriteria} */
42
+ this.preferenceBasedCriteria_ = adaptationSetCriteriaFactory();
43
+ this.preferenceBasedCriteria_.configure({
44
+ language: example.language,
45
+ role,
46
+ channelCount,
47
+ hdrLevel,
48
+ spatialAudio,
49
+ videoLayout,
50
+ audioLabel,
51
+ videoLabel,
52
+ codecSwitchingStrategy,
53
+ audioCodec,
54
+ });
55
+ }
56
+
57
+ /**
58
+ * @override
59
+ */
60
+ create(variants) {
61
+ return this.preferenceBasedCriteria_.create(variants);
62
+ }
63
+
64
+ /**
65
+ * @override
66
+ */
67
+ configure() {
68
+ }
69
+ };
@@ -53,6 +53,9 @@ shaka.media.GapJumpingController = class {
53
53
  /** @private {shaka.util.EventManager} */
54
54
  this.eventManager_ = new shaka.util.EventManager();
55
55
 
56
+ /** @private {boolean} */
57
+ this.started_ = false;
58
+
56
59
  /** @private {boolean} */
57
60
  this.seekingEventReceived_ = false;
58
61
 
@@ -90,7 +93,7 @@ shaka.media.GapJumpingController = class {
90
93
  */
91
94
  this.gapJumpTimer_ = new shaka.util.Timer(() => {
92
95
  this.onPollGapJump_();
93
- }).tickEvery(this.config_.gapJumpTimerTime);
96
+ });
94
97
  }
95
98
 
96
99
 
@@ -134,16 +137,22 @@ shaka.media.GapJumpingController = class {
134
137
  * @param {number} startTime
135
138
  */
136
139
  onStarted(startTime) {
140
+ this.started_ = true;
137
141
  if (this.video_.seeking && !this.seekingEventReceived_) {
138
142
  this.seekingEventReceived_ = true;
139
143
  this.startTime_ = startTime;
140
144
  }
145
+ if (this.gapJumpTimer_) {
146
+ this.gapJumpTimer_.tickEvery(this.config_.gapJumpTimerTime);
147
+ }
148
+ this.onPollGapJump_();
141
149
  }
142
150
 
143
151
  /** Called when a seek has started. */
144
152
  onSeeking() {
145
153
  this.seekingEventReceived_ = true;
146
154
  this.hadSegmentAppended_ = false;
155
+ this.onPollGapJump_();
147
156
  }
148
157
 
149
158
 
@@ -167,6 +176,10 @@ shaka.media.GapJumpingController = class {
167
176
  if (this.video_.readyState == 0) {
168
177
  return;
169
178
  }
179
+ // Don't gap jump before playback started
180
+ if (!this.started_) {
181
+ return;
182
+ }
170
183
  // Do not gap jump if seeking has begun, but the seeking event has not
171
184
  // yet fired for this particular seek.
172
185
  if (this.video_.seeking) {
@@ -7,8 +7,8 @@
7
7
  goog.provide('shaka.media.ManifestFilterer');
8
8
 
9
9
  goog.require('goog.asserts');
10
+ goog.require('shaka.drm.DrmEngine');
10
11
  goog.require('shaka.util.StreamUtils');
11
- goog.require('shaka.media.DrmEngine');
12
12
  goog.require('shaka.util.Error');
13
13
 
14
14
  /**
@@ -20,7 +20,7 @@ shaka.media.ManifestFilterer = class {
20
20
  /**
21
21
  * @param {?shaka.extern.PlayerConfiguration} config
22
22
  * @param {shaka.extern.Resolution} maxHwRes
23
- * @param {?shaka.media.DrmEngine} drmEngine
23
+ * @param {?shaka.drm.DrmEngine} drmEngine
24
24
  */
25
25
  constructor(config, maxHwRes, drmEngine) {
26
26
  goog.asserts.assert(config, 'Must have config');
@@ -31,11 +31,11 @@ shaka.media.ManifestFilterer = class {
31
31
  /** @private {shaka.extern.Resolution} */
32
32
  this.maxHwRes_ = maxHwRes;
33
33
 
34
- /** @private {?shaka.media.DrmEngine} drmEngine */
34
+ /** @private {?shaka.drm.DrmEngine} drmEngine */
35
35
  this.drmEngine_ = drmEngine;
36
36
  }
37
37
 
38
- /** @param {!shaka.media.DrmEngine} drmEngine */
38
+ /** @param {!shaka.drm.DrmEngine} drmEngine */
39
39
  setDrmEngine(drmEngine) {
40
40
  this.drmEngine_ = drmEngine;
41
41
  }
@@ -45,7 +45,7 @@ shaka.media.ManifestFilterer = class {
45
45
  * the codecs.
46
46
  *
47
47
  * @param {?shaka.extern.Manifest} manifest
48
- * @return {!Promise.<boolean>} tracksChanged
48
+ * @return {!Promise<boolean>} tracksChanged
49
49
  */
50
50
  async filterManifest(manifest) {
51
51
  goog.asserts.assert(manifest, 'Manifest should exist!');
@@ -156,10 +156,10 @@ shaka.media.ManifestFilterer = class {
156
156
  let hasPlayable = false;
157
157
  let hasAppRestrictions = false;
158
158
 
159
- /** @type {!Set.<string>} */
159
+ /** @type {!Set<string>} */
160
160
  const missingKeys = new Set();
161
161
 
162
- /** @type {!Set.<string>} */
162
+ /** @type {!Set<string>} */
163
163
  const badKeyStatuses = new Set();
164
164
 
165
165
  for (const variant of manifest.variants) {
@@ -214,7 +214,7 @@ shaka.media.ManifestFilterer = class {
214
214
  * of the usable keys. 'expired' status is being handled separately in
215
215
  * DrmEngine.
216
216
  *
217
- * @const {!Array.<string>}
217
+ * @const {!Array<string>}
218
218
  */
219
219
  shaka.media.ManifestFilterer.restrictedStatuses =
220
220
  ['output-restricted', 'internal-error'];
@@ -59,7 +59,7 @@ shaka.media.ManifestParser = class {
59
59
  /**
60
60
  * Returns a map of manifest support for well-known types.
61
61
  *
62
- * @return {!Object.<string, boolean>}
62
+ * @return {!Object<string, boolean>}
63
63
  */
64
64
  static probeSupport() {
65
65
  const ManifestParser = shaka.media.ManifestParser;
@@ -191,7 +191,7 @@ shaka.media.ManifestParser.AccessibilityPurpose = {
191
191
  /**
192
192
  * Contains the parser factory functions indexed by MIME type.
193
193
  *
194
- * @type {!Object.<string, shaka.extern.ManifestParser.Factory>}
194
+ * @type {!Object<string, shaka.extern.ManifestParser.Factory>}
195
195
  */
196
196
  shaka.media.ManifestParser.parsersByMime = {};
197
197
 
@@ -42,10 +42,29 @@ shaka.media.Capabilities = class {
42
42
  // eslint-disable-next-line no-restricted-syntax
43
43
  !!sourceBuffer.prototype && !!sourceBuffer.prototype.changeType;
44
44
  }
45
+
46
+ /**
47
+ * Determine support for MediaSource.setLiveSeekableRange and
48
+ * MediaSource.clearLiveSeekableRange, which can allow for a media element
49
+ * duration of Infinite by providing a non-infinite seekable range.
50
+ *
51
+ * @return {boolean}
52
+ */
53
+ static isInfiniteLiveStreamDurationSupported() {
54
+ const mediaSource = window.ManagedMediaSource || window.MediaSource;
55
+ // eslint-disable-next-line no-restricted-syntax
56
+ if (mediaSource && mediaSource.prototype) {
57
+ // eslint-disable-next-line no-restricted-syntax
58
+ return !!mediaSource.prototype.setLiveSeekableRange &&
59
+ // eslint-disable-next-line no-restricted-syntax
60
+ !!mediaSource.prototype.clearLiveSeekableRange;
61
+ }
62
+ return false;
63
+ }
45
64
  };
46
65
 
47
66
  /**
48
67
  * Public it for unit test, and developer could also check the support map.
49
- * @type {!Map.<string, boolean>}
68
+ * @type {!Map<string, boolean>}
50
69
  */
51
70
  shaka.media.Capabilities.MediaSourceTypeSupportMap = new Map();
@@ -72,17 +72,23 @@ shaka.media.MediaSourceEngine = class {
72
72
  /** @private {shaka.extern.TextDisplayer} */
73
73
  this.textDisplayer_ = textDisplayer;
74
74
 
75
- /** @private {!Object.<shaka.util.ManifestParserUtils.ContentType,
76
- SourceBuffer>} */
75
+ /**
76
+ * @private {!Object<shaka.util.ManifestParserUtils.ContentType,
77
+ * SourceBuffer>}
78
+ */
77
79
  this.sourceBuffers_ = {};
78
80
 
79
- /** @private {!Object.<shaka.util.ManifestParserUtils.ContentType,
80
- string>} */
81
+ /**
82
+ * @private {!Object<shaka.util.ManifestParserUtils.ContentType,
83
+ * string>}
84
+ */
81
85
  this.sourceBufferTypes_ = {};
82
86
 
83
87
 
84
- /** @private {!Object.<shaka.util.ManifestParserUtils.ContentType,
85
- boolean>} */
88
+ /**
89
+ * @private {!Object<shaka.util.ManifestParserUtils.ContentType,
90
+ * boolean>}
91
+ */
86
92
  this.expectedEncryption_ = {};
87
93
 
88
94
  /** @private {shaka.text.TextEngine} */
@@ -95,15 +101,15 @@ shaka.media.MediaSourceEngine = class {
95
101
  this.lcevcDec_ = lcevcDec || null;
96
102
 
97
103
  /**
98
- * @private {!Object.<string,
99
- * !Array.<shaka.media.MediaSourceEngine.Operation>>}
104
+ * @private {!Object<string,
105
+ * !Array<shaka.media.MediaSourceEngine.Operation>>}
100
106
  */
101
107
  this.queues_ = {};
102
108
 
103
109
  /** @private {shaka.util.EventManager} */
104
110
  this.eventManager_ = new shaka.util.EventManager();
105
111
 
106
- /** @private {!Object.<string, !shaka.extern.Transmuxer>} */
112
+ /** @private {!Object<string, !shaka.extern.Transmuxer>} */
107
113
  this.transmuxers_ = {};
108
114
 
109
115
  /** @private {?shaka.media.IClosedCaptionParser} */
@@ -155,7 +161,7 @@ shaka.media.MediaSourceEngine = class {
155
161
  /** @private {boolean} */
156
162
  this.attemptTimestampOffsetCalculation_ = false;
157
163
 
158
- /** @private {!shaka.util.PublicPromise.<number>} */
164
+ /** @private {!shaka.util.PublicPromise<number>} */
159
165
  this.textSequenceModeOffset_ = new shaka.util.PublicPromise();
160
166
 
161
167
  /** @private {boolean} */
@@ -164,8 +170,10 @@ shaka.media.MediaSourceEngine = class {
164
170
  /** @private {?number} */
165
171
  this.lastDuration_ = null;
166
172
 
167
- /** @private {!Object.<shaka.util.ManifestParserUtils.ContentType,
168
- !shaka.util.TsParser>} */
173
+ /**
174
+ * @private {!Object<shaka.util.ManifestParserUtils.ContentType,
175
+ * !shaka.util.TsParser>}
176
+ */
169
177
  this.tsParsers_ = {};
170
178
 
171
179
  /** @private {?number} */
@@ -180,7 +188,7 @@ shaka.media.MediaSourceEngine = class {
180
188
  /** @private {?number} */
181
189
  this.firstAudioReferenceStartTime_ = null;
182
190
 
183
- /** @private {!shaka.util.PublicPromise.<number>} */
191
+ /** @private {!shaka.util.PublicPromise<number>} */
184
192
  this.audioCompensation_ = new shaka.util.PublicPromise();
185
193
 
186
194
  if (this.video_.remote) {
@@ -307,7 +315,7 @@ shaka.media.MediaSourceEngine = class {
307
315
  *
308
316
  * @param {shaka.extern.Stream} stream
309
317
  * @param {shaka.util.ManifestParserUtils.ContentType} contentType
310
- * @return {!Promise.<boolean>}
318
+ * @return {!Promise<boolean>}
311
319
  */
312
320
  static async isStreamSupported(stream, contentType) {
313
321
  if (stream.createSegmentIndex) {
@@ -371,7 +379,7 @@ shaka.media.MediaSourceEngine = class {
371
379
  /**
372
380
  * Returns a map of MediaSource support for well-known types.
373
381
  *
374
- * @return {!Object.<string, boolean>}
382
+ * @return {!Object<string, boolean>}
375
383
  */
376
384
  static probeSupport() {
377
385
  const testMimeTypes = [
@@ -532,7 +540,7 @@ shaka.media.MediaSourceEngine = class {
532
540
  * Note that it is not valid to call this multiple times, except to add or
533
541
  * reinitialize text streams.
534
542
  *
535
- * @param {!Map.<shaka.util.ManifestParserUtils.ContentType,
543
+ * @param {!Map<shaka.util.ManifestParserUtils.ContentType,
536
544
  * shaka.extern.Stream>} streamsByType
537
545
  * A map of content types to streams. All streams must be supported
538
546
  * according to MediaSourceEngine.isStreamSupported.
@@ -699,7 +707,7 @@ shaka.media.MediaSourceEngine = class {
699
707
 
700
708
  /**
701
709
  * Indicate if the streaming is allowed by MediaSourceEngine.
702
- * If we using MediaSource we allways returns true.
710
+ * If we using MediaSource we always returns true.
703
711
  *
704
712
  * @return {boolean}
705
713
  */
@@ -891,7 +899,7 @@ shaka.media.MediaSourceEngine = class {
891
899
  * we are appending
892
900
  * @param {shaka.extern.Stream} stream
893
901
  * @param {!string} mimeType
894
- * @return {{timestamp: ?number, metadata: !Array.<shaka.extern.ID3Metadata>}}
902
+ * @return {{timestamp: ?number, metadata: !Array<shaka.extern.ID3Metadata>}}
895
903
  */
896
904
  getTimestampAndDispatchMetadata(contentType, data, reference, stream,
897
905
  mimeType) {
@@ -980,7 +988,7 @@ shaka.media.MediaSourceEngine = class {
980
988
  * Parse the EMSG box from a MP4 container.
981
989
  *
982
990
  * @param {!shaka.media.SegmentReference} reference
983
- * @param {?Array.<string>} emsgSchemeIdUris Array of emsg
991
+ * @param {?Array<string>} emsgSchemeIdUris Array of emsg
984
992
  * scheme_id_uri for which emsg boxes should be parsed.
985
993
  * @param {!shaka.extern.ParsedBox} box
986
994
  * @private
@@ -1506,7 +1514,7 @@ shaka.media.MediaSourceEngine = class {
1506
1514
  * not be applied in this step.
1507
1515
  * @param {string} mimeType
1508
1516
  * @param {string} codecs
1509
- * @param {!Map.<shaka.util.ManifestParserUtils.ContentType,
1517
+ * @param {!Map<shaka.util.ManifestParserUtils.ContentType,
1510
1518
  * shaka.extern.Stream>} streamsByType
1511
1519
  * A map of content types to streams. All streams must be supported
1512
1520
  * according to MediaSourceEngine.isStreamSupported.
@@ -1562,20 +1570,24 @@ shaka.media.MediaSourceEngine = class {
1562
1570
  null));
1563
1571
  }
1564
1572
  }
1565
- operations.push(this.enqueueOperation_(
1566
- contentType,
1567
- () => this.setAppendWindow_(
1568
- contentType, appendWindowStart, appendWindowEnd),
1569
- null));
1570
- if (this.needSplitMuxedContent_) {
1573
+ if (appendWindowStart != 0 || appendWindowEnd != Infinity) {
1571
1574
  operations.push(this.enqueueOperation_(
1572
- ContentType.AUDIO,
1575
+ contentType,
1573
1576
  () => this.setAppendWindow_(
1574
- ContentType.AUDIO, appendWindowStart, appendWindowEnd),
1577
+ contentType, appendWindowStart, appendWindowEnd),
1575
1578
  null));
1579
+ if (this.needSplitMuxedContent_) {
1580
+ operations.push(this.enqueueOperation_(
1581
+ ContentType.AUDIO,
1582
+ () => this.setAppendWindow_(
1583
+ ContentType.AUDIO, appendWindowStart, appendWindowEnd),
1584
+ null));
1585
+ }
1576
1586
  }
1577
1587
 
1578
- await Promise.all(operations);
1588
+ if (operations.length) {
1589
+ await Promise.all(operations);
1590
+ }
1579
1591
  }
1580
1592
 
1581
1593
  /**
@@ -1699,6 +1711,43 @@ shaka.media.MediaSourceEngine = class {
1699
1711
  return this.mediaSource_.duration;
1700
1712
  }
1701
1713
 
1714
+ /**
1715
+ * Updates the live seekable range.
1716
+ *
1717
+ * @param {number} startTime
1718
+ * @param {number} endTime
1719
+ */
1720
+ async setLiveSeekableRange(startTime, endTime) {
1721
+ goog.asserts.assert('setLiveSeekableRange' in this.mediaSource_,
1722
+ 'Using setLiveSeekableRange on not supported platform');
1723
+ if (this.ended() || this.closed()) {
1724
+ return;
1725
+ }
1726
+ await this.enqueueBlockingOperation_(() => {
1727
+ if (this.ended() || this.closed()) {
1728
+ return;
1729
+ }
1730
+ this.mediaSource_.setLiveSeekableRange(startTime, endTime);
1731
+ });
1732
+ }
1733
+
1734
+ /**
1735
+ * Clear the current live seekable range.
1736
+ */
1737
+ async clearLiveSeekableRange() {
1738
+ goog.asserts.assert('clearLiveSeekableRange' in this.mediaSource_,
1739
+ 'Using clearLiveSeekableRange on not supported platform');
1740
+ if (this.ended() || this.closed()) {
1741
+ return;
1742
+ }
1743
+ await this.enqueueBlockingOperation_(() => {
1744
+ if (this.ended() || this.closed()) {
1745
+ return;
1746
+ }
1747
+ this.mediaSource_.clearLiveSeekableRange();
1748
+ });
1749
+ }
1750
+
1702
1751
  /**
1703
1752
  * Append data to the SourceBuffer.
1704
1753
  * @param {shaka.util.ManifestParserUtils.ContentType} contentType
@@ -1901,9 +1950,9 @@ shaka.media.MediaSourceEngine = class {
1901
1950
  async enqueueBlockingOperation_(run) {
1902
1951
  this.destroyer_.ensureNotDestroyed();
1903
1952
 
1904
- /** @type {!Array.<!shaka.util.PublicPromise>} */
1953
+ /** @type {!Array<!shaka.util.PublicPromise>} */
1905
1954
  const allWaiters = [];
1906
- /** @type {!Array.<!shaka.util.ManifestParserUtils.ContentType>} */
1955
+ /** @type {!Array<!shaka.util.ManifestParserUtils.ContentType>} */
1907
1956
  const contentTypes = Object.keys(this.sourceBuffers_);
1908
1957
 
1909
1958
  // Enqueue a 'wait' operation onto each queue.
@@ -2149,7 +2198,7 @@ shaka.media.MediaSourceEngine = class {
2149
2198
  /**
2150
2199
  * Resets the MediaSource and re-adds source buffers due to codec mismatch
2151
2200
  *
2152
- * @param {!Map.<shaka.util.ManifestParserUtils.ContentType,
2201
+ * @param {!Map<shaka.util.ManifestParserUtils.ContentType,
2153
2202
  * shaka.extern.Stream>} streamsByType
2154
2203
  * @private
2155
2204
  */
@@ -2257,7 +2306,7 @@ shaka.media.MediaSourceEngine = class {
2257
2306
 
2258
2307
  /**
2259
2308
  * Resets the Media Source
2260
- * @param {!Map.<shaka.util.ManifestParserUtils.ContentType,
2309
+ * @param {!Map<shaka.util.ManifestParserUtils.ContentType,
2261
2310
  * shaka.extern.Stream>} streamsByType
2262
2311
  * @return {!Promise}
2263
2312
  */
@@ -2333,9 +2382,9 @@ shaka.media.MediaSourceEngine = class {
2333
2382
  * @param {shaka.util.ManifestParserUtils.ContentType} contentType
2334
2383
  * @param {string} mimeType
2335
2384
  * @param {string} codecs
2336
- * @param {!Map.<shaka.util.ManifestParserUtils.ContentType,
2385
+ * @param {!Map<shaka.util.ManifestParserUtils.ContentType,
2337
2386
  * shaka.extern.Stream>} streamsByType
2338
- * @return {!Promise.<boolean>} true if there was a codec switch,
2387
+ * @return {!Promise<boolean>} true if there was a codec switch,
2339
2388
  * false otherwise.
2340
2389
  * @private
2341
2390
  */
@@ -20,13 +20,13 @@ shaka.media.Mp4SegmentIndexParser = class {
20
20
  * @param {BufferSource} sidxData The MP4's container's SIDX.
21
21
  * @param {number} sidxOffset The SIDX's offset, in bytes, from the start of
22
22
  * the MP4 container.
23
- * @param {!Array.<string>} uris The possible locations of the MP4 file that
23
+ * @param {!Array<string>} uris The possible locations of the MP4 file that
24
24
  * contains the segments.
25
25
  * @param {shaka.media.InitSegmentReference} initSegmentReference
26
26
  * @param {number} timestampOffset
27
27
  * @param {number} appendWindowStart
28
28
  * @param {number} appendWindowEnd
29
- * @return {!Array.<!shaka.media.SegmentReference>}
29
+ * @return {!Array<!shaka.media.SegmentReference>}
30
30
  */
31
31
  static parse(
32
32
  sidxData, sidxOffset, uris, initSegmentReference, timestampOffset,
@@ -71,10 +71,10 @@ shaka.media.Mp4SegmentIndexParser = class {
71
71
  * @param {number} timestampOffset
72
72
  * @param {number} appendWindowStart
73
73
  * @param {number} appendWindowEnd
74
- * @param {!Array.<string>} uris The possible locations of the MP4 file that
74
+ * @param {!Array<string>} uris The possible locations of the MP4 file that
75
75
  * contains the segments.
76
76
  * @param {!shaka.extern.ParsedBox} box
77
- * @return {!Array.<!shaka.media.SegmentReference>}
77
+ * @return {!Array<!shaka.media.SegmentReference>}
78
78
  * @private
79
79
  */
80
80
  static parseSIDX_(
@@ -136,7 +136,7 @@ shaka.media.Mp4SegmentIndexParser = class {
136
136
  // If |referenceType| is 1 then the reference is to another SIDX.
137
137
  // We do not support this.
138
138
  if (referenceType == 1) {
139
- shaka.log.error('Heirarchical SIDXs are not supported.');
139
+ shaka.log.error('Hierarchical SIDXs are not supported.');
140
140
  throw new shaka.util.Error(
141
141
  shaka.util.Error.Severity.CRITICAL,
142
142
  shaka.util.Error.Category.MEDIA,
@@ -231,9 +231,6 @@ shaka.media.MediaSourcePlayhead = class {
231
231
  /** @private {shaka.media.PresentationTimeline} */
232
232
  this.timeline_ = manifest.presentationTimeline;
233
233
 
234
- /** @private {number} */
235
- this.minBufferTime_ = manifest.minBufferTime || 0;
236
-
237
234
  /** @private {?shaka.extern.StreamingConfiguration} */
238
235
  this.config_ = config;
239
236
 
@@ -476,16 +473,13 @@ shaka.media.MediaSourcePlayhead = class {
476
473
  reposition_(currentTime) {
477
474
  goog.asserts.assert(
478
475
  this.config_,
479
- 'Cannot reposition playhead when it has beeen destroyed');
476
+ 'Cannot reposition playhead when it has been destroyed');
480
477
 
481
478
  /** @type {function(number)} */
482
479
  const isBuffered = (playheadTime) => shaka.media.TimeRangesUtils.isBuffered(
483
480
  this.mediaElement_.buffered, playheadTime);
484
481
 
485
- const rebufferingGoal = Math.max(
486
- this.minBufferTime_,
487
- this.config_.rebufferingGoal);
488
-
482
+ const rebufferingGoal = this.config_.rebufferingGoal;
489
483
  const safeSeekOffset = this.config_.safeSeekOffset;
490
484
 
491
485
  let start = this.timeline_.getSeekRangeStart();
@@ -52,7 +52,7 @@ shaka.media.PlayheadObserverManager = class {
52
52
  * We are using a set to ensure that we don't double update an observer if
53
53
  * it is accidentally added twice.
54
54
  *
55
- * @private {!Set.<shaka.media.IPlayheadObserver>}
55
+ * @private {!Set<shaka.media.IPlayheadObserver>}
56
56
  */
57
57
  this.observers_ = new Set();
58
58