shaka-player 3.3.1 → 3.3.4

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 (336) hide show
  1. package/.csslintrc +11 -1
  2. package/.github/ISSUE_TEMPLATE/bug_report.md +1 -1
  3. package/.github/pull_request_template.md +6 -34
  4. package/.github/workflows/build-and-test.yaml +130 -0
  5. package/.github/workflows/custom-actions/prep-for-appspot/action.yaml +56 -0
  6. package/.github/workflows/custom-actions/set-commit-status/action.yaml +41 -0
  7. package/.github/workflows/demo-version-index.yaml +29 -0
  8. package/.github/workflows/nightly-demo.yaml +42 -0
  9. package/.github/workflows/release-please.yaml +147 -0
  10. package/.github/workflows/safari-homedir-launcher.sh +18 -0
  11. package/.github/workflows/selenium-lab-tests.yaml +93 -0
  12. package/AUTHORS +2 -0
  13. package/CHANGELOG.md +1707 -1670
  14. package/CONTRIBUTING.md +2 -2
  15. package/CONTRIBUTORS +2 -0
  16. package/README.md +7 -7
  17. package/app-engine/README.md +9 -0
  18. package/app-engine/demo-version-index/README.md +14 -0
  19. package/app-engine/demo-version-index/app.yaml +2 -0
  20. package/app-engine/demo-version-index/main.py +162 -0
  21. package/app-engine/demo-version-index/requirements.txt +6 -0
  22. package/app-engine/demo-version-index/templates/index.html +114 -0
  23. package/app-engine/shaka-player-demo/README.md +18 -0
  24. package/app-engine/shaka-player-demo/app.yaml +61 -0
  25. package/app-engine/shaka-player-demo/main.py +95 -0
  26. package/app-engine/shaka-player-demo/posters/10yo.png +0 -0
  27. package/app-engine/shaka-player-demo/posters/10yo.xcf +0 -0
  28. package/app-engine/shaka-player-demo/posters/1yo.jpg +0 -0
  29. package/app-engine/shaka-player-demo/posters/2yo.png +0 -0
  30. package/app-engine/shaka-player-demo/posters/2yo.xcf +0 -0
  31. package/app-engine/shaka-player-demo/posters/3yo.png +0 -0
  32. package/app-engine/shaka-player-demo/posters/3yo.xcf +0 -0
  33. package/app-engine/shaka-player-demo/posters/4yo.png +0 -0
  34. package/app-engine/shaka-player-demo/posters/4yo.xcf +0 -0
  35. package/app-engine/shaka-player-demo/posters/5yo.png +0 -0
  36. package/app-engine/shaka-player-demo/posters/5yo.xcf +0 -0
  37. package/app-engine/shaka-player-demo/posters/6yo.png +0 -0
  38. package/app-engine/shaka-player-demo/posters/6yo.xcf +0 -0
  39. package/app-engine/shaka-player-demo/posters/7yo.png +0 -0
  40. package/app-engine/shaka-player-demo/posters/7yo.xcf +0 -0
  41. package/app-engine/shaka-player-demo/posters/8yo.png +0 -0
  42. package/app-engine/shaka-player-demo/posters/8yo.xcf +0 -0
  43. package/app-engine/shaka-player-demo/posters/9yo.png +0 -0
  44. package/app-engine/shaka-player-demo/posters/9yo.xcf +0 -0
  45. package/app-engine/shaka-player-demo/posters/audioOnly.gif +0 -0
  46. package/app-engine/shaka-player-demo/posters/audioRickRoll.gif +0 -0
  47. package/app-engine/shaka-player-demo/posters/colorbars.gif +0 -0
  48. package/app-engine/shaka-player-demo/posters/fireworks.jpg +0 -0
  49. package/app-engine/shaka-player-demo/posters/party-hat.png +0 -0
  50. package/app-engine/shaka-player-demo/posters/sources.txt +46 -0
  51. package/app-engine/shaka-player-demo/posters/standard.png +0 -0
  52. package/app-engine/shaka-player-demo/posters/trek.jpg +0 -0
  53. package/app-engine/shaka-player-demo/posters/valentines.png +0 -0
  54. package/app-engine/shaka-player-demo/posters/zombie.jpg +0 -0
  55. package/app-engine/shaka-player-demo/posters.py +110 -0
  56. package/app-engine/shaka-player-demo/requirements.txt +5 -0
  57. package/app-engine/shaka-player-demo/time.txt +1 -0
  58. package/build/README.md +1 -1
  59. package/build/checkversion.py +1 -1
  60. package/build/conformance.textproto +13 -0
  61. package/build/docker/Dockerfile +20 -0
  62. package/build/docker/docker-compose.yml +10 -0
  63. package/build/gendeps.py +18 -15
  64. package/build/generateTsDefs.py +2 -0
  65. package/build/shaka-lab.yaml +163 -0
  66. package/build/shakaBuildHelpers.py +4 -29
  67. package/build/test.py +93 -28
  68. package/build/types/polyfill +1 -0
  69. package/build/wrapper.template.js +2 -2
  70. package/demo/TengwarTelcontar.woff2 +0 -0
  71. package/demo/asset_card.js +1 -2
  72. package/demo/cast_receiver/index.html +1 -1
  73. package/demo/cast_receiver/receiver_app.css +14 -14
  74. package/demo/common/assets.js +2 -0
  75. package/demo/config.js +0 -1
  76. package/demo/custom.js +0 -1
  77. package/demo/customWarning.txt +2 -2
  78. package/demo/demo.less +29 -18
  79. package/demo/demo_uncompiled.js +1 -13
  80. package/demo/index.html +1 -1
  81. package/demo/main.js +3 -3
  82. package/dist/controls.css +3 -3
  83. package/dist/controls.css.map +1 -1
  84. package/dist/demo.compiled.debug.js +191 -194
  85. package/dist/demo.compiled.debug.map +4 -4
  86. package/dist/demo.compiled.js +191 -194
  87. package/dist/demo.compiled.map +4 -4
  88. package/dist/demo.css +1 -1
  89. package/dist/demo.css.map +1 -1
  90. package/dist/deps.js +233 -226
  91. package/dist/locales.js +32 -32
  92. package/dist/receiver.compiled.debug.js +43 -45
  93. package/dist/receiver.compiled.debug.map +4 -4
  94. package/dist/receiver.compiled.js +43 -45
  95. package/dist/receiver.compiled.map +4 -4
  96. package/dist/shaka-player.compiled.d.ts +250 -237
  97. package/dist/shaka-player.compiled.debug.d.ts +250 -237
  98. package/dist/shaka-player.compiled.debug.externs.js +31 -15
  99. package/dist/shaka-player.compiled.debug.js +252 -257
  100. package/dist/shaka-player.compiled.debug.map +4 -4
  101. package/dist/shaka-player.compiled.externs.js +31 -15
  102. package/dist/shaka-player.compiled.js +844 -849
  103. package/dist/shaka-player.compiled.map +4 -4
  104. package/dist/shaka-player.ui.d.ts +296 -292
  105. package/dist/shaka-player.ui.debug.d.ts +296 -292
  106. package/dist/shaka-player.ui.debug.externs.js +33 -26
  107. package/dist/shaka-player.ui.debug.js +345 -351
  108. package/dist/shaka-player.ui.debug.map +4 -4
  109. package/dist/shaka-player.ui.externs.js +33 -26
  110. package/dist/shaka-player.ui.js +1002 -1008
  111. package/dist/shaka-player.ui.map +4 -4
  112. package/docs/design/REDESIGN.md +33 -33
  113. package/docs/design/bg-fetch.md +2 -2
  114. package/docs/design/codec_preferences.md +1 -1
  115. package/docs/design/dash-audio-channels.md +3 -3
  116. package/docs/design/dash-manifests.md +1 -1
  117. package/docs/design/gap-jumping.md +3 -3
  118. package/docs/design/preload.md +2 -2
  119. package/docs/tutorials/faq.md +8 -8
  120. package/docs/tutorials/index.json +1 -0
  121. package/docs/tutorials/plugins.md +3 -3
  122. package/docs/tutorials/selenium-grid-config.md +122 -0
  123. package/docs/tutorials/welcome.md +10 -2
  124. package/externs/cmcd.js +1 -1
  125. package/karma.conf.js +156 -45
  126. package/lib/abr/simple_abr_manager.js +12 -6
  127. package/lib/ads/ad_manager.js +1 -0
  128. package/lib/cast/cast_proxy.js +6 -4
  129. package/lib/cast/cast_receiver.js +3 -0
  130. package/lib/cea/cea608_data_channel.js +2 -2
  131. package/lib/cea/cea708_service.js +5 -4
  132. package/lib/cea/mp4_cea_parser.js +11 -5
  133. package/lib/cea/sei_processor.js +6 -3
  134. package/lib/dash/dash_parser.js +40 -30
  135. package/lib/dash/mpd_utils.js +4 -5
  136. package/lib/dash/segment_list.js +1 -2
  137. package/lib/dash/segment_template.js +3 -3
  138. package/lib/hls/hls_parser.js +11 -9
  139. package/lib/hls/manifest_text_parser.js +4 -3
  140. package/lib/media/adaptation_set.js +1 -2
  141. package/lib/media/content_workarounds.js +2 -2
  142. package/lib/media/drm_engine.js +3 -2
  143. package/lib/media/media_source_engine.js +3 -2
  144. package/lib/media/mp4_segment_index_parser.js +1 -4
  145. package/lib/media/playhead.js +2 -2
  146. package/lib/media/presentation_timeline.js +18 -8
  147. package/lib/media/quality_observer.js +17 -34
  148. package/lib/media/region_observer.js +39 -33
  149. package/lib/media/region_timeline.js +17 -19
  150. package/lib/media/streaming_engine.js +7 -7
  151. package/lib/media/time_ranges_utils.js +1 -3
  152. package/lib/media/video_wrapper.js +1 -1
  153. package/lib/net/networking_engine.js +5 -1
  154. package/lib/offline/storage.js +12 -13
  155. package/lib/player.js +65 -25
  156. package/lib/polyfill/all.js +2 -3
  157. package/lib/polyfill/encryption_scheme.js +1 -1
  158. package/lib/polyfill/media_capabilities.js +3 -3
  159. package/lib/polyfill/mediasource.js +1 -1
  160. package/lib/polyfill/symbol.js +46 -0
  161. package/lib/text/cue.js +1 -1
  162. package/lib/text/simple_text_displayer.js +2 -1
  163. package/lib/text/ttml_text_parser.js +8 -5
  164. package/lib/text/ui_text_displayer.js +1 -1
  165. package/lib/util/buffer_utils.js +1 -3
  166. package/lib/util/ebml_parser.js +3 -3
  167. package/lib/util/error.js +1 -1
  168. package/lib/util/fake_event_target.js +21 -1
  169. package/lib/util/iterables.js +0 -46
  170. package/lib/util/mp4_box_parsers.js +1 -4
  171. package/lib/util/mp4_parser.js +5 -7
  172. package/lib/util/periods.js +10 -11
  173. package/lib/util/platform.js +3 -3
  174. package/lib/util/pssh.js +1 -4
  175. package/lib/util/stream_utils.js +4 -3
  176. package/lib/util/string_utils.js +3 -5
  177. package/lib/util/uint8array_utils.js +3 -5
  178. package/lib/util/xml_utils.js +15 -7
  179. package/package.json +62 -40
  180. package/roadmap.md +17 -17
  181. package/shaka-player.uncompiled.js +1 -0
  182. package/test/abr/simple_abr_manager_unit.js +3 -8
  183. package/test/ads/ad_manager_unit.js +0 -6
  184. package/test/cast/cast_proxy_unit.js +0 -8
  185. package/test/cast/cast_receiver_integration.js +1 -18
  186. package/test/cast/cast_receiver_unit.js +1 -9
  187. package/test/cast/cast_sender_unit.js +0 -6
  188. package/test/cast/cast_utils_unit.js +0 -13
  189. package/test/cea/cea608_memory_unit.js +0 -5
  190. package/test/cea/cea708_service_unit.js +0 -7
  191. package/test/cea/cea708_window_unit.js +0 -5
  192. package/test/cea/cea_decoder_unit.js +0 -6
  193. package/test/cea/dtvcc_packet_builder_unit.js +0 -3
  194. package/test/cea/dtvcc_packet_unit.js +0 -5
  195. package/test/cea/mp4_cea_parser_unit.js +0 -4
  196. package/test/dash/dash_parser_content_protection_unit.js +1 -10
  197. package/test/dash/dash_parser_live_unit.js +45 -15
  198. package/test/dash/dash_parser_manifest_unit.js +4 -17
  199. package/test/dash/dash_parser_segment_base_unit.js +1 -8
  200. package/test/dash/dash_parser_segment_list_unit.js +1 -7
  201. package/test/dash/dash_parser_segment_template_unit.js +0 -9
  202. package/test/dash/mpd_utils_unit.js +3 -11
  203. package/test/demo/demo_unit.js +0 -5
  204. package/test/deprecate/enforcer_unit.js +0 -4
  205. package/test/deprecate/version_unit.js +0 -2
  206. package/test/hls/hls_live_unit.js +2 -14
  207. package/test/hls/hls_parser_unit.js +76 -15
  208. package/test/hls/manifest_text_parser_unit.js +0 -10
  209. package/test/media/adaptation_set_criteria_unit.js +3 -7
  210. package/test/media/adaptation_set_unit.js +0 -2
  211. package/test/media/buffering_observer_unit.js +1 -4
  212. package/test/media/closed_caption_parser_unit.js +0 -3
  213. package/test/media/drm_engine_integration.js +2 -15
  214. package/test/media/drm_engine_unit.js +4 -24
  215. package/test/media/manifest_parser_unit.js +0 -4
  216. package/test/media/media_source_engine_integration.js +0 -7
  217. package/test/media/media_source_engine_unit.js +1 -14
  218. package/test/media/mp4_segment_index_parser_unit.js +0 -4
  219. package/test/media/play_rate_controller_unit.js +0 -4
  220. package/test/media/playhead_unit.js +8 -16
  221. package/test/media/presentation_timeline_unit.js +4 -7
  222. package/test/media/quality_observer_unit.js +4 -5
  223. package/test/media/region_observer_unit.js +40 -10
  224. package/test/media/region_timeline_unit.js +40 -25
  225. package/test/media/segment_index_unit.js +0 -6
  226. package/test/media/segment_reference_unit.js +0 -3
  227. package/test/media/stall_detector_unit.js +0 -5
  228. package/test/media/streaming_engine_integration.js +9 -36
  229. package/test/media/streaming_engine_unit.js +11 -35
  230. package/test/media/time_ranges_utils_unit.js +0 -2
  231. package/test/media/transmuxer_integration.js +0 -6
  232. package/test/media/webm_segment_index_parser_unit.js +0 -4
  233. package/test/net/data_uri_plugin_unit.js +0 -7
  234. package/test/net/http_plugin_unit.js +0 -9
  235. package/test/net/networking_engine_unit.js +0 -11
  236. package/test/offline/download_progress_estimator_unit.js +0 -2
  237. package/test/offline/indexeddb_storage_unit.js +0 -6
  238. package/test/offline/manifest_convert_unit.js +0 -8
  239. package/test/offline/offline_integration.js +1 -10
  240. package/test/offline/offline_manifest_parser_unit.js +0 -6
  241. package/test/offline/offline_scheme_unit.js +0 -8
  242. package/test/offline/offline_uri_unit.js +0 -2
  243. package/test/offline/storage_compatibility_unit.js +1 -14
  244. package/test/offline/storage_integration.js +1 -27
  245. package/test/player_external.js +2 -10
  246. package/test/player_integration.js +22 -28
  247. package/test/player_load_graph_integration.js +1 -6
  248. package/test/player_src_equals_external.js +3 -9
  249. package/test/player_src_equals_integration.js +0 -7
  250. package/test/player_unit.js +52 -37
  251. package/test/routing/walker_unit.js +0 -8
  252. package/test/test/assets/large_file.mpd +1 -1
  253. package/test/test/boot.js +75 -22
  254. package/test/test/externs/jasmine.js +2 -2
  255. package/test/test/externs/karma.js +4 -0
  256. package/test/test/namespace.js +10 -0
  257. package/test/test/util/canned_idb.js +0 -8
  258. package/test/test/util/cea_utils.js +0 -6
  259. package/test/test/util/dash_parser_util.js +0 -13
  260. package/test/test/util/fake_ad.js +0 -3
  261. package/test/test/util/fake_ad_manager.js +0 -9
  262. package/test/test/util/fake_demo_main.js +0 -5
  263. package/test/test/util/fake_drm_engine.js +0 -6
  264. package/test/test/util/fake_media_source_engine.js +0 -7
  265. package/test/test/util/fake_networking_engine.js +0 -5
  266. package/test/test/util/fake_text_displayer.js +0 -5
  267. package/test/test/util/indexeddb_utils.js +1 -10
  268. package/test/test/util/jasmine_fetch.js +0 -1
  269. package/test/test/util/loader.js +0 -18
  270. package/test/test/util/manifest_generator.js +9 -14
  271. package/test/test/util/manifest_parser_util.js +0 -6
  272. package/test/test/util/offline_utils.js +0 -5
  273. package/test/test/util/simple_fakes.js +9 -26
  274. package/test/test/util/stream_generator.js +0 -14
  275. package/test/test/util/streaming_engine_util.js +0 -15
  276. package/test/test/util/test_scheme.js +1 -19
  277. package/test/test/util/ttml_utils.js +0 -2
  278. package/test/test/util/ui_utils.js +0 -9
  279. package/test/test/util/util.js +15 -26
  280. package/test/test/util/waiter.js +84 -43
  281. package/test/text/cue_integration.js +0 -4
  282. package/test/text/lrc_text_parser_unit.js +0 -4
  283. package/test/text/mp4_ttml_parser_unit.js +0 -6
  284. package/test/text/mp4_vtt_parser_unit.js +1 -7
  285. package/test/text/sbv_text_parser_unit.js +0 -4
  286. package/test/text/simple_text_displayer_unit.js +1 -8
  287. package/test/text/srt_text_parser_unit.js +0 -4
  288. package/test/text/ssa_text_parser_unit.js +0 -5
  289. package/test/text/text_engine_unit.js +2 -7
  290. package/test/text/text_track_integration.js +0 -2
  291. package/test/text/ttml_text_parser_unit.js +2 -11
  292. package/test/text/ui_text_displayer_unit.js +44 -41
  293. package/test/text/vtt_text_parser_unit.js +0 -9
  294. package/test/text/web_vtt_generator_unit.js +0 -3
  295. package/test/ui/ad_ui_unit.js +0 -11
  296. package/test/ui/localization_unit.js +0 -3
  297. package/test/ui/text_displayer_layout_unit.js +9 -19
  298. package/test/ui/ui_customization_unit.js +0 -6
  299. package/test/ui/ui_integration.js +0 -16
  300. package/test/ui/ui_unit.js +1 -17
  301. package/test/util/abortable_operation_unit.js +4 -9
  302. package/test/util/array_utils_unit.js +0 -2
  303. package/test/util/buffer_utils_unit.js +0 -2
  304. package/test/util/cmcd_manager_unit.js +0 -3
  305. package/test/util/data_view_reader_unit.js +0 -4
  306. package/test/util/ebml_parser_unit.js +0 -4
  307. package/test/util/event_manager_unit.js +0 -3
  308. package/test/util/fake_event_target_unit.js +0 -5
  309. package/test/util/functional_unit.js +1 -1
  310. package/test/util/iterables_unit.js +0 -64
  311. package/test/util/language_utils_unit.js +0 -3
  312. package/test/util/manifest_parser_utils_unit.js +0 -2
  313. package/test/util/mp4_box_parsers_unit.js +0 -5
  314. package/test/util/mp4_parser_unit.js +0 -4
  315. package/test/util/multi_map_unit.js +0 -3
  316. package/test/util/object_utils_unit.js +0 -2
  317. package/test/util/periods_unit.js +14 -7
  318. package/test/util/pssh_unit.js +0 -5
  319. package/test/util/state_history_unit.js +0 -2
  320. package/test/util/stream_utils_unit.js +3 -8
  321. package/test/util/string_utils_unit.js +0 -6
  322. package/test/util/text_parser_unit.js +0 -2
  323. package/test/util/xml_utils_unit.js +0 -4
  324. package/ui/controls.js +3 -0
  325. package/ui/less/ad_controls.less +6 -6
  326. package/ui/less/buttons.less +6 -6
  327. package/ui/less/containers.less +13 -15
  328. package/ui/less/overflow_menu.less +4 -4
  329. package/ui/less/range_elements.less +7 -2
  330. package/ui/less/tooltip.less +4 -4
  331. package/ui/locales/sjn-translations.yaml +257 -0
  332. package/ui/locales/sjn.json +42 -0
  333. package/ui/localization.js +12 -36
  334. package/ui/seek_bar.js +2 -1
  335. package/externs/svgelement.js +0 -18
  336. package/externs/webcrypto.js +0 -18
@@ -22,7 +22,6 @@ goog.require('shaka.text.TextEngine');
22
22
  goog.require('shaka.util.CmcdManager');
23
23
  goog.require('shaka.util.Error');
24
24
  goog.require('shaka.util.Functional');
25
- goog.require('shaka.util.Iterables');
26
25
  goog.require('shaka.util.LanguageUtils');
27
26
  goog.require('shaka.util.ManifestParserUtils');
28
27
  goog.require('shaka.util.MimeUtils');
@@ -104,7 +103,7 @@ shaka.dash.DashParser = class {
104
103
 
105
104
  /**
106
105
  * Period IDs seen in previous manifest.
107
- * @private {!Array.<number>}
106
+ * @private {!Array.<string>}
108
107
  */
109
108
  this.lastManifestUpdatePeriodIds_ = [];
110
109
 
@@ -383,7 +382,7 @@ shaka.dash.DashParser = class {
383
382
  // This gives us confidence that our state is maintained correctly, and
384
383
  // that the complex logic of multi-Period eviction and period-flattening
385
384
  // is correct. See also:
386
- // https://github.com/google/shaka-player/issues/3169#issuecomment-823580634
385
+ // https://github.com/shaka-project/shaka-player/issues/3169#issuecomment-823580634
387
386
  for (const stream of Object.values(this.streamMap_)) {
388
387
  if (stream.segmentIndex) {
389
388
  stream.segmentIndex.evict(
@@ -410,6 +409,24 @@ shaka.dash.DashParser = class {
410
409
  this.config_.dash.autoCorrectDrift);
411
410
  }
412
411
 
412
+ presentationTimeline.setStatic(mpdType == 'static');
413
+
414
+ const isLive = presentationTimeline.isLive();
415
+
416
+ // If it's live, we check for an override.
417
+ if (isLive && !isNaN(this.config_.availabilityWindowOverride)) {
418
+ segmentAvailabilityDuration = this.config_.availabilityWindowOverride;
419
+ }
420
+
421
+ // If it's null, that means segments are always available. This is always
422
+ // the case for VOD, and sometimes the case for live.
423
+ if (segmentAvailabilityDuration == null) {
424
+ segmentAvailabilityDuration = Infinity;
425
+ }
426
+
427
+ presentationTimeline.setSegmentAvailabilityDuration(
428
+ segmentAvailabilityDuration);
429
+
413
430
  const profiles = mpd.getAttribute('profiles') || '';
414
431
 
415
432
  /** @type {shaka.dash.DashParser.Context} */
@@ -432,7 +449,6 @@ shaka.dash.DashParser = class {
432
449
  const duration = periodsAndDuration.duration;
433
450
  const periods = periodsAndDuration.periods;
434
451
 
435
- presentationTimeline.setStatic(mpdType == 'static');
436
452
  if (mpdType == 'static' ||
437
453
  !periodsAndDuration.durationDerivedFromPeriods) {
438
454
  // Ignore duration calculated from Period lengths if this is dynamic.
@@ -451,6 +467,7 @@ shaka.dash.DashParser = class {
451
467
  this.lowLatencyMode_ = this.playerInterface_.isLowLatencyMode();
452
468
  }
453
469
  }
470
+
454
471
  if (this.lowLatencyMode_) {
455
472
  presentationTimeline.setAvailabilityTimeOffset(
456
473
  this.minTotalAvailabilityTimeOffset_);
@@ -464,22 +481,6 @@ shaka.dash.DashParser = class {
464
481
  'https://bit.ly/3clctcj for details.');
465
482
  }
466
483
 
467
- const isLive = presentationTimeline.isLive();
468
-
469
- // If it's live, we check for an override.
470
- if (isLive && !isNaN(this.config_.availabilityWindowOverride)) {
471
- segmentAvailabilityDuration = this.config_.availabilityWindowOverride;
472
- }
473
-
474
- // If it's null, that means segments are always available. This is always
475
- // the case for VOD, and sometimes the case for live.
476
- if (segmentAvailabilityDuration == null) {
477
- segmentAvailabilityDuration = Infinity;
478
- }
479
-
480
- presentationTimeline.setSegmentAvailabilityDuration(
481
- segmentAvailabilityDuration);
482
-
483
484
  // Use @maxSegmentDuration to override smaller, derived values.
484
485
  presentationTimeline.notifyMaxSegmentDuration(maxSegmentDuration || 1);
485
486
  if (goog.DEBUG) {
@@ -553,10 +554,9 @@ shaka.dash.DashParser = class {
553
554
  const periods = [];
554
555
  let prevEnd = 0;
555
556
  const periodNodes = XmlUtils.findChildren(mpd, 'Period');
556
- // This uses a for-loop rather than a for-of loop because this needs to look
557
- // ahead to the next element.
558
- const enumerate = (it) => shaka.util.Iterables.enumerate(it);
559
- for (const {i, item: elem, next} of enumerate(periodNodes)) {
557
+ for (let i = 0; i < periodNodes.length; i++) {
558
+ const elem = periodNodes[i];
559
+ const next = periodNodes[i + 1];
560
560
  const start = /** @type {number} */ (
561
561
  XmlUtils.parseAttr(elem, 'start', XmlUtils.parseDuration, prevEnd));
562
562
  const periodId = elem.id;
@@ -714,8 +714,12 @@ shaka.dash.DashParser = class {
714
714
 
715
715
  const eventStreamNodes =
716
716
  XmlUtils.findChildren(periodInfo.node, 'EventStream');
717
+ const availabilityStart =
718
+ context.presentationTimeline.getSegmentAvailabilityStart();
719
+
717
720
  for (const node of eventStreamNodes) {
718
- this.parseEventStream_(periodInfo.start, periodInfo.duration, node);
721
+ this.parseEventStream_(
722
+ periodInfo.start, periodInfo.duration, node, availabilityStart);
719
723
  }
720
724
 
721
725
  const adaptationSetNodes =
@@ -758,7 +762,7 @@ shaka.dash.DashParser = class {
758
762
  for (const stream of normalSet.streams) {
759
763
  // There may be multiple trick mode streams, but we do not
760
764
  // currently support that. Just choose one.
761
- // TODO: https://github.com/google/shaka-player/issues/1528
765
+ // TODO: https://github.com/shaka-project/shaka-player/issues/1528
762
766
  stream.trickModeVideo = trickModeSet.streams.find((trickStream) =>
763
767
  shaka.util.MimeUtils.getCodecBase(stream.codecs) ==
764
768
  shaka.util.MimeUtils.getCodecBase(trickStream.codecs));
@@ -1151,7 +1155,7 @@ shaka.dash.DashParser = class {
1151
1155
  // does not make sense in the DASH spec's bandwidth formulas.
1152
1156
  // In some content, however, the attribute is missing or zero.
1153
1157
  // To avoid NaN at the variant level on broken content, fall back to zero.
1154
- // https://github.com/google/shaka-player/issues/938#issuecomment-317278180
1158
+ // https://github.com/shaka-project/shaka-player/issues/938#issuecomment-317278180
1155
1159
  context.bandwidth =
1156
1160
  XmlUtils.parseAttr(node, 'bandwidth', XmlUtils.parsePositiveInt) || 0;
1157
1161
 
@@ -1230,7 +1234,7 @@ shaka.dash.DashParser = class {
1230
1234
 
1231
1235
  let forced = false;
1232
1236
  if (isText) {
1233
- // See: https://github.com/google/shaka-player/issues/2122 and
1237
+ // See: https://github.com/shaka-project/shaka-player/issues/2122 and
1234
1238
  // https://github.com/Dash-Industry-Forum/DASH-IF-IOP/issues/165
1235
1239
  forced = roles.includes('forced_subtitle') ||
1236
1240
  roles.includes('forced-subtitle');
@@ -1378,7 +1382,7 @@ shaka.dash.DashParser = class {
1378
1382
  // NOTE: An updatePeriod_ of -1 means the attribute was missing.
1379
1383
  // An attribute which is present and set to 0 should still result in
1380
1384
  // periodic updates. For more, see:
1381
- // https://github.com/google/shaka-player/issues/331
1385
+ // https://github.com/shaka-project/shaka-player/issues/331
1382
1386
  if (this.updatePeriod_ < 0) {
1383
1387
  return;
1384
1388
  }
@@ -1769,9 +1773,10 @@ shaka.dash.DashParser = class {
1769
1773
  * @param {number} periodStart
1770
1774
  * @param {?number} periodDuration
1771
1775
  * @param {!Element} elem
1776
+ * @param {number} availabilityStart
1772
1777
  * @private
1773
1778
  */
1774
- parseEventStream_(periodStart, periodDuration, elem) {
1779
+ parseEventStream_(periodStart, periodDuration, elem, availabilityStart) {
1775
1780
  const XmlUtils = shaka.util.XmlUtils;
1776
1781
  const parseNumber = XmlUtils.parseNonNegativeInt;
1777
1782
 
@@ -1794,6 +1799,11 @@ shaka.dash.DashParser = class {
1794
1799
  endTime = Math.min(endTime, periodStart + periodDuration);
1795
1800
  }
1796
1801
 
1802
+ // Don't add unavailable regions to the timeline.
1803
+ if (endTime < availabilityStart) {
1804
+ continue;
1805
+ }
1806
+
1797
1807
  /** @type {shaka.extern.TimelineRegionInfo} */
1798
1808
  const region = {
1799
1809
  schemeIdUri: schemeIdUri,
@@ -12,7 +12,6 @@ goog.require('shaka.net.NetworkingEngine');
12
12
  goog.require('shaka.util.AbortableOperation');
13
13
  goog.require('shaka.util.Error');
14
14
  goog.require('shaka.util.Functional');
15
- goog.require('shaka.util.Iterables');
16
15
  goog.require('shaka.util.ManifestParserUtils');
17
16
  goog.require('shaka.util.XmlUtils');
18
17
  goog.requireType('shaka.dash.DashParser');
@@ -142,8 +141,9 @@ shaka.dash.MpdUtils = class {
142
141
  const timeline = [];
143
142
  let lastEndTime = -unscaledPresentationTimeOffset;
144
143
 
145
- const enumerate = (it) => shaka.util.Iterables.enumerate(it);
146
- for (const {item: timePoint, next} of enumerate(timePoints)) {
144
+ for (let i = 0; i < timePoints.length; ++i) {
145
+ const timePoint = timePoints[i];
146
+ const next = timePoints[i + 1];
147
147
  let t = XmlUtils.parseAttr(timePoint, 't', XmlUtils.parseNonNegativeInt);
148
148
  const d =
149
149
  XmlUtils.parseAttr(timePoint, 'd', XmlUtils.parseNonNegativeInt);
@@ -225,8 +225,7 @@ shaka.dash.MpdUtils = class {
225
225
  timeline[timeline.length - 1].end = startTime / timescale;
226
226
  }
227
227
 
228
- for (const _ of shaka.util.Iterables.range(repeat + 1)) {
229
- shaka.util.Functional.ignored(_);
228
+ for (let j = 0; j <= repeat; ++j) {
230
229
  const endTime = startTime + d;
231
230
  const item = {
232
231
  start: startTime / timescale,
@@ -15,7 +15,6 @@ goog.require('shaka.media.SegmentIndex');
15
15
  goog.require('shaka.media.SegmentReference');
16
16
  goog.require('shaka.util.Error');
17
17
  goog.require('shaka.util.Functional');
18
- goog.require('shaka.util.Iterables');
19
18
  goog.require('shaka.util.ManifestParserUtils');
20
19
  goog.require('shaka.util.XmlUtils');
21
20
  goog.requireType('shaka.dash.DashParser');
@@ -222,7 +221,7 @@ shaka.dash.SegmentList = class {
222
221
  /** @type {!Array.<!shaka.media.SegmentReference>} */
223
222
  const references = [];
224
223
  let prevEndTime = info.startTime;
225
- for (const i of shaka.util.Iterables.range(max)) {
224
+ for (let i = 0; i < max; i++) {
226
225
  const segment = info.mediaSegments[i];
227
226
  const mediaUri = ManifestParserUtils.resolveUris(
228
227
  baseUris, [segment.mediaUri]);
@@ -14,7 +14,6 @@ goog.require('shaka.media.InitSegmentReference');
14
14
  goog.require('shaka.media.SegmentIndex');
15
15
  goog.require('shaka.media.SegmentReference');
16
16
  goog.require('shaka.util.Error');
17
- goog.require('shaka.util.Iterables');
18
17
  goog.require('shaka.util.ManifestParserUtils');
19
18
  goog.require('shaka.util.ObjectUtils');
20
19
  goog.requireType('shaka.dash.DashParser');
@@ -504,8 +503,9 @@ shaka.dash.SegmentTemplate = class {
504
503
 
505
504
  /** @type {!Array.<!shaka.media.SegmentReference>} */
506
505
  const references = [];
507
- const enum_ = (it) => shaka.util.Iterables.enumerate(it);
508
- for (const {i, item: {start, unscaledStart, end}} of enum_(info.timeline)) {
506
+ for (let i = 0; i < info.timeline.length; i++) {
507
+ const {start, unscaledStart, end} = info.timeline[i];
508
+
509
509
  // Note: i = k - 1, where k indicates the k'th segment listed in the MPD.
510
510
  // (See section 5.3.9.5.3 of the DASH spec.)
511
511
  const segmentReplacement = i + info.startNumber;
@@ -30,7 +30,6 @@ goog.require('shaka.util.DataViewReader');
30
30
  goog.require('shaka.util.Error');
31
31
  goog.require('shaka.util.FakeEvent');
32
32
  goog.require('shaka.util.Functional');
33
- goog.require('shaka.util.Iterables');
34
33
  goog.require('shaka.util.LanguageUtils');
35
34
  goog.require('shaka.util.ManifestParserUtils');
36
35
  goog.require('shaka.util.MimeUtils');
@@ -919,7 +918,7 @@ shaka.hls.HlsParser = class {
919
918
  // the content. This means that if the content changes profiles, it should
920
919
  // include both. Since all known browsers support changing profiles
921
920
  // without any other work, just ignore them. See also:
922
- // https://github.com/google/shaka-player/issues/1817
921
+ // https://github.com/shaka-project/shaka-player/issues/1817
923
922
  const shortCodec = shaka.util.MimeUtils.getCodecBase(codec);
924
923
  if (!seen.has(shortCodec)) {
925
924
  ret.push(codec);
@@ -1760,8 +1759,8 @@ shaka.hls.HlsParser = class {
1760
1759
  // Create SegmentReferences for the partial segments.
1761
1760
  const partialSegmentRefs = [];
1762
1761
  if (this.lowLatencyMode_ && hlsSegment.partialSegments.length) {
1763
- const enumerate = (it) => shaka.util.Iterables.enumerate(it);
1764
- for (const {i, item} of enumerate(hlsSegment.partialSegments)) {
1762
+ for (let i = 0; i < hlsSegment.partialSegments.length; i++) {
1763
+ const item = hlsSegment.partialSegments[i];
1765
1764
  const pPreviousReference = i == 0 ?
1766
1765
  previousReference : partialSegmentRefs[partialSegmentRefs.length - 1];
1767
1766
  const pStartTime = (i == 0) ? startTime : pPreviousReference.endTime;
@@ -1782,6 +1781,9 @@ shaka.hls.HlsParser = class {
1782
1781
  this.parseByteRange_(pPreviousReference, pByterange);
1783
1782
  }
1784
1783
  const pUri = item.getAttributeValue('URI');
1784
+ if (!pUri) {
1785
+ continue;
1786
+ }
1785
1787
  const pAbsoluteUri = shaka.hls.Utils.constructAbsoluteUri(
1786
1788
  absoluteMediaPlaylistUri, pUri);
1787
1789
 
@@ -1989,9 +1991,9 @@ shaka.hls.HlsParser = class {
1989
1991
  // With delta updates, the DISCONTINUITY may be skipped. Check if
1990
1992
  // the discontintuity Sequence Number based on the media sequence
1991
1993
  // number.
1992
- while (discontinuityToMediaSequence.has(discontintuitySequenceNum + 1)
1993
- && discontinuityToMediaSequence.get(discontintuitySequenceNum + 1) <
1994
- position) {
1994
+ const disconMap = discontinuityToMediaSequence;
1995
+ while (disconMap.has(discontintuitySequenceNum + 1) &&
1996
+ disconMap.get(discontintuitySequenceNum + 1) < position) {
1995
1997
  discontintuitySequenceNum++;
1996
1998
  }
1997
1999
  }
@@ -2002,8 +2004,8 @@ shaka.hls.HlsParser = class {
2002
2004
  /** @type {!Array.<!shaka.media.SegmentReference>} */
2003
2005
  const references = [];
2004
2006
 
2005
- const enumerate = (it) => shaka.util.Iterables.enumerate(it);
2006
- for (const {i, item} of enumerate(hlsSegments)) {
2007
+ for (let i = 0; i < hlsSegments.length; i++) {
2008
+ const item = hlsSegments[i];
2007
2009
  const previousReference = references[references.length - 1];
2008
2010
  const startTime = (i == 0) ? firstStartTime :
2009
2011
  previousReference.endTime;
@@ -13,7 +13,6 @@ goog.require('shaka.hls.Segment');
13
13
  goog.require('shaka.hls.Tag');
14
14
  goog.require('shaka.hls.Utils');
15
15
  goog.require('shaka.util.Error');
16
- goog.require('shaka.util.Iterables');
17
16
  goog.require('shaka.util.StringUtils');
18
17
  goog.require('shaka.util.TextParser');
19
18
 
@@ -82,8 +81,9 @@ shaka.hls.ManifestTextParser = class {
82
81
  const tags = [];
83
82
  // Initialize to "true" to skip the first element.
84
83
  skip = true;
85
- const enumerate = (it) => shaka.util.Iterables.enumerate(it);
86
- for (const {i, item: line, next} of enumerate(lines)) {
84
+ for (let i = 0; i < lines.length; i++) {
85
+ const line = lines[i];
86
+ const next = lines[i + 1];
87
87
  // Skip comments
88
88
  if (shaka.hls.Utils.isComment(line) || skip) {
89
89
  skip = false;
@@ -277,6 +277,7 @@ shaka.hls.ManifestTextParser = class {
277
277
  const attrValue = blockAttrs[2] || blockAttrs[3];
278
278
  const attribute = new shaka.hls.Attribute(attrName, attrValue);
279
279
  attributes.push(attribute);
280
+ parser.skipWhitespace();
280
281
  }
281
282
  }
282
283
 
@@ -8,7 +8,6 @@ goog.provide('shaka.media.AdaptationSet');
8
8
 
9
9
  goog.require('goog.asserts');
10
10
  goog.require('shaka.log');
11
- goog.require('shaka.util.Iterables');
12
11
  goog.require('shaka.util.MimeUtils');
13
12
 
14
13
 
@@ -215,7 +214,7 @@ shaka.media.AdaptationSet = class {
215
214
  codecsA.sort();
216
215
  codecsB.sort();
217
216
 
218
- for (const i of shaka.util.Iterables.range(codecsA.length)) {
217
+ for (let i = 0; i < codecsA.length; i++) {
219
218
  if (codecsA[i] != codecsB[i]) {
220
219
  return false;
221
220
  }
@@ -31,7 +31,7 @@ shaka.media.ContentWorkarounds = class {
31
31
  *
32
32
  * @param {!BufferSource} initSegmentBuffer
33
33
  * @return {!Uint8Array}
34
- * @see https://github.com/google/shaka-player/issues/2759
34
+ * @see https://github.com/shaka-project/shaka-player/issues/2759
35
35
  */
36
36
  static fakeEncryption(initSegmentBuffer) {
37
37
  const ContentWorkarounds = shaka.media.ContentWorkarounds;
@@ -283,7 +283,7 @@ shaka.media.ContentWorkarounds = class {
283
283
  *
284
284
  * @const {!shaka.util.Lazy.<!Uint8Array>}
285
285
  * @private
286
- * @see https://github.com/google/shaka-player/issues/2759
286
+ * @see https://github.com/shaka-project/shaka-player/issues/2759
287
287
  */
288
288
  shaka.media.ContentWorkarounds.CANNED_SINF_BOX_ =
289
289
  new shaka.util.Lazy(() => new Uint8Array([
@@ -655,7 +655,7 @@ shaka.media.DrmEngine = class {
655
655
  // first MIME type even if the others are supported. To work around this,
656
656
  // we say that Edge supports everything.
657
657
  //
658
- // See https://github.com/google/shaka-player/issues/1495 for details.
658
+ // See https://github.com/shaka-project/shaka-player/issues/1495 for details.
659
659
  if (shaka.util.Platform.isLegacyEdge()) {
660
660
  return true;
661
661
  }
@@ -667,7 +667,8 @@ shaka.media.DrmEngine = class {
667
667
  // Some Tizen devices seem to misreport AC-3 support. This works around
668
668
  // the issue, by falling back to EC-3, which seems to be supported on the
669
669
  // same devices and be correctly reported in all cases we have observed.
670
- // See https://github.com/google/shaka-player/issues/2989 for details.
670
+ // See https://github.com/shaka-project/shaka-player/issues/2989 for
671
+ // details.
671
672
  const fallback = contentType.replace('ac-3', 'ec-3');
672
673
  return this.supportedTypes_.has(contentType) ||
673
674
  this.supportedTypes_.has(fallback);
@@ -830,7 +830,8 @@ shaka.media.MediaSourceEngine = class {
830
830
  * @private
831
831
  */
832
832
  setTimestampOffset_(contentType, timestampOffset) {
833
- // Work around for https://github.com/google/shaka-player/issues/1281:
833
+ // Work around for
834
+ // https://github.com/shaka-project/shaka-player/issues/1281:
834
835
  // TODO(https://bit.ly/2ttKiBU): follow up when this is fixed in Edge
835
836
  if (timestampOffset < 0) {
836
837
  // Try to prevent rounding errors in Edge from removing the first
@@ -1100,7 +1101,7 @@ shaka.media.MediaSourceEngine = class {
1100
1101
  // then insert fake encryption metadata for init segments that lack it.
1101
1102
  // The MP4 requirement is because we can currently only do this
1102
1103
  // transformation on MP4 containers.
1103
- // See: https://github.com/google/shaka-player/issues/2759
1104
+ // See: https://github.com/shaka-project/shaka-player/issues/2759
1104
1105
  if (isInitSegment &&
1105
1106
  encryptionExpected &&
1106
1107
  shaka.util.Platform.requiresEncryptionInfoInAllInitSegments() &&
@@ -11,8 +11,6 @@ goog.require('shaka.log');
11
11
  goog.require('shaka.media.InitSegmentReference');
12
12
  goog.require('shaka.media.SegmentReference');
13
13
  goog.require('shaka.util.Error');
14
- goog.require('shaka.util.Functional');
15
- goog.require('shaka.util.Iterables');
16
14
  goog.require('shaka.util.Mp4Parser');
17
15
 
18
16
 
@@ -123,8 +121,7 @@ shaka.media.Mp4SegmentIndexParser = class {
123
121
  let unscaledStartTime = earliestPresentationTime;
124
122
  let startByte = sidxOffset + box.size + firstOffset;
125
123
 
126
- for (const _ of shaka.util.Iterables.range(referenceCount)) {
127
- shaka.util.Functional.ignored(_);
124
+ for (let i = 0; i < referenceCount; i++) {
128
125
  // |chunk| is 1 bit for |referenceType|, and 31 bits for |referenceSize|.
129
126
  const chunk = box.reader.readUint32();
130
127
  const referenceType = (chunk & 0x80000000) >>> 31;
@@ -256,7 +256,7 @@ shaka.media.MediaSourcePlayhead = class {
256
256
  // We don't buffer when the livestream video is paused and the playhead time
257
257
  // is out of the seek range; thus, we do not clamp the current time when the
258
258
  // video is paused.
259
- // https://github.com/google/shaka-player/issues/1121
259
+ // https://github.com/shaka-project/shaka-player/issues/1121
260
260
  if (this.mediaElement_.readyState > 0 && !this.mediaElement_.paused) {
261
261
  return this.clampTime_(time);
262
262
  }
@@ -362,7 +362,7 @@ shaka.media.MediaSourcePlayhead = class {
362
362
  * presentation duration. Seeking to or starting at duration does not work
363
363
  * consistently across browsers.
364
364
  *
365
- * @see https://github.com/google/shaka-player/issues/979
365
+ * @see https://github.com/shaka-project/shaka-player/issues/979
366
366
  * @param {number} time
367
367
  * @return {number} The adjusted seek time.
368
368
  * @private
@@ -355,14 +355,23 @@ shaka.media.PresentationTimeline = class {
355
355
  * starting after this time should be assumed to be unavailable.
356
356
  *
357
357
  * @return {number} The current segment availability end time, in seconds,
358
- * relative to the start of the presentation. Always returns the
359
- * presentation's duration for video-on-demand.
358
+ * relative to the start of the presentation. For VOD, the availability
359
+ * end time is the content's duration. If the Player's playRangeEnd
360
+ * configuration is used, this can override the duration.
360
361
  * @export
361
362
  */
362
363
  getSegmentAvailabilityEnd() {
363
364
  if (!this.isLive() && !this.isInProgress()) {
364
365
  // It's a static manifest (can also be a dynamic->static conversion)
365
- return this.maxSegmentEndTime_ || this.duration_;
366
+ if (this.maxSegmentEndTime_) {
367
+ // If we know segment times, use the min of that and duration.
368
+ // Note that the playRangeEnd configuration changes this.duration_.
369
+ // See https://github.com/shaka-project/shaka-player/issues/4026
370
+ return Math.min(this.maxSegmentEndTime_, this.duration_);
371
+ } else {
372
+ // If we don't have segment times, use duration.
373
+ return this.duration_;
374
+ }
366
375
  }
367
376
  // Can be either live or "in-progress recording" (live with known duration)
368
377
  return Math.min(this.getLiveEdge_() + this.availabilityTimeOffset_,
@@ -389,10 +398,11 @@ shaka.media.PresentationTimeline = class {
389
398
  // For VOD, the offset and end time are ignored, and we just return the
390
399
  // earliest segment time. All segments are "safe" in VOD. However, we
391
400
  // should round up to the nearest millisecond to avoid issues like
392
- // https://github.com/google/shaka-player/issues/2831, in which we tried to
393
- // seek repeatedly to catch up to the seek range, and never actually
394
- // "arrived" within it. The video's currentTime is not as accurate as the
395
- // JS number representing the earliest segment time for some content.
401
+ // https://github.com/shaka-project/shaka-player/issues/2831, in which we
402
+ // tried to seek repeatedly to catch up to the seek range, and never
403
+ // actually "arrived" within it. The video's currentTime is not as
404
+ // accurate as the JS number representing the earliest segment time for
405
+ // some content.
396
406
  if (this.segmentAvailabilityDuration_ == Infinity) {
397
407
  return Math.ceil(earliestSegmentTime * 1e3) / 1e3;
398
408
  }
@@ -407,7 +417,7 @@ shaka.media.PresentationTimeline = class {
407
417
  // Add the offset to the availability start to ensure that we don't fall
408
418
  // outside the availability window while we buffer; we don't need to add the
409
419
  // offset to earliestSegmentTime since that won't change over time.
410
- // Also see: https://github.com/google/shaka-player/issues/692
420
+ // Also see: https://github.com/shaka-project/shaka-player/issues/692
411
421
  const desiredStart =
412
422
  Math.min(availabilityStart + offset, this.getSeekRangeEnd());
413
423
  return Math.max(earliestSegmentTime, desiredStart);
@@ -8,48 +8,40 @@ goog.provide('shaka.media.QualityObserver');
8
8
 
9
9
  goog.require('shaka.media.IPlayheadObserver');
10
10
  goog.require('shaka.log');
11
+ goog.require('shaka.util.FakeEvent');
12
+ goog.require('shaka.util.FakeEventTarget');
11
13
 
12
14
  /**
13
- * Monitors the quality of content being appended to the source
14
- * buffers and fires onQualityChange events when the media quality
15
- * at the playhead changes.
15
+ * Monitors the quality of content being appended to the source buffers and
16
+ * fires 'qualitychange' events when the media quality at the playhead changes.
16
17
  *
17
18
  * @implements {shaka.media.IPlayheadObserver}
18
19
  * @final
19
20
  */
20
- shaka.media.QualityObserver = class {
21
+ shaka.media.QualityObserver = class extends shaka.util.FakeEventTarget {
21
22
  /**
22
23
  * Creates a new QualityObserver.
23
24
  *
24
25
  * @param {!function():!shaka.extern.BufferedInfo} getBufferedInfo
25
- * Buffered info is needed to purge QualityChanges that are no
26
- * longer relevant.
26
+ * Buffered info is needed to purge QualityChanges that are no
27
+ * longer relevant.
27
28
  */
28
29
  constructor(getBufferedInfo) {
30
+ super();
31
+
29
32
  /**
30
33
  * @private {!Map.<string,!shaka.media.QualityObserver.ContentTypeState>}
31
34
  */
32
35
  this.contentTypeStates_ = new Map();
33
36
 
34
- /** @private {shaka.media.QualityObserver.EventListener} */
35
- this.onQualityChange_ = (mediaQuality, position) => {};
36
-
37
37
  /** @private function():!shaka.extern.BufferedInfo */
38
38
  this.getBufferedInfo_ = getBufferedInfo;
39
39
  }
40
40
 
41
- /**
42
- * Set all the listeners. This overrides any previous calls to |setListeners|.
43
- *
44
- * @param {shaka.media.QualityObserver.EventListener} onQualityChange
45
- */
46
- setListeners(onQualityChange) {
47
- this.onQualityChange_ = onQualityChange;
48
- }
49
-
50
41
  /** @override */
51
42
  release() {
52
43
  this.contentTypeStates_.clear();
44
+ super.release();
53
45
  }
54
46
 
55
47
  /**
@@ -169,10 +161,15 @@ shaka.media.QualityObserver = class {
169
161
  if (this.positionIsBuffered_(
170
162
  positionInSeconds, qualityAtPosition.contentType)) {
171
163
  contentTypeState.currentQuality = qualityAtPosition;
164
+
172
165
  shaka.log.debug('Media quality changed at position ' +
173
166
  positionInSeconds + ' ' + JSON.stringify(qualityAtPosition));
174
- this.onQualityChange_(
175
- qualityAtPosition, positionInSeconds);
167
+
168
+ const event = new shaka.util.FakeEvent('qualitychange', new Map([
169
+ ['quality', qualityAtPosition],
170
+ ['position', positionInSeconds],
171
+ ]));
172
+ this.dispatchEvent(event);
176
173
  }
177
174
  }
178
175
  }
@@ -237,20 +234,6 @@ shaka.media.QualityObserver = class {
237
234
  }
238
235
  };
239
236
 
240
- /**
241
- * @typedef {function(shaka.extern.MediaQualityInfo, number)}
242
- *
243
- * @description
244
- * A callback function used to notify the player when media quality changes
245
- * are detected at the playhead.
246
- *
247
- * The first argument is information about media quality at the playhead
248
- * position.
249
- *
250
- * The second argument is the playhead position in seconds.
251
- */
252
- shaka.media.QualityObserver.EventListener;
253
-
254
237
  /**
255
238
  * @typedef {{
256
239
  * mediaQuality: !shaka.extern.MediaQualityInfo,