shaka-player 4.3.9 → 4.4.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 (321) hide show
  1. package/.github/workflows/build-and-test.yaml +11 -18
  2. package/.github/workflows/compute-incremental-coverage.py +3 -0
  3. package/.github/workflows/release-please.yaml +7 -0
  4. package/.github/workflows/selenium-lab-tests.yaml +45 -10
  5. package/AUTHORS +9 -0
  6. package/CHANGELOG.md +295 -190
  7. package/CONTRIBUTORS +8 -0
  8. package/LICENSE +32 -0
  9. package/README.md +63 -10
  10. package/demo/autoTemplate.txt +40 -5
  11. package/demo/close_button.js +11 -0
  12. package/demo/common/asset.js +13 -1
  13. package/demo/common/assets.js +112 -28
  14. package/demo/common/message_ids.js +25 -1
  15. package/demo/config.js +69 -10
  16. package/demo/customWarning.txt +2 -2
  17. package/demo/index.html +3 -1
  18. package/demo/locales/en.json +26 -2
  19. package/demo/locales/source.json +105 -9
  20. package/demo/main.js +57 -9
  21. package/demo/search.js +3 -1
  22. package/demo/service_worker.js +3 -0
  23. package/dist/controls.css +1 -1
  24. package/dist/controls.css.map +1 -1
  25. package/dist/demo.compiled.debug.js +132 -118
  26. package/dist/demo.compiled.debug.map +3 -3
  27. package/dist/demo.compiled.js +132 -118
  28. package/dist/demo.compiled.map +3 -3
  29. package/dist/deps.js +46 -28
  30. package/dist/locales.js +31 -31
  31. package/dist/receiver.compiled.debug.js +60 -52
  32. package/dist/receiver.compiled.debug.map +3 -3
  33. package/dist/receiver.compiled.js +60 -52
  34. package/dist/receiver.compiled.map +3 -3
  35. package/dist/shaka-player.compiled.d.ts +676 -391
  36. package/dist/shaka-player.compiled.debug.d.ts +676 -391
  37. package/dist/shaka-player.compiled.debug.externs.js +1188 -616
  38. package/dist/shaka-player.compiled.debug.js +1046 -700
  39. package/dist/shaka-player.compiled.debug.map +4 -4
  40. package/dist/shaka-player.compiled.externs.js +1188 -616
  41. package/dist/shaka-player.compiled.js +1094 -933
  42. package/dist/shaka-player.compiled.map +4 -4
  43. package/dist/shaka-player.ui.d.ts +677 -392
  44. package/dist/shaka-player.ui.debug.d.ts +677 -392
  45. package/dist/shaka-player.ui.debug.externs.js +1023 -451
  46. package/dist/shaka-player.ui.debug.js +1101 -738
  47. package/dist/shaka-player.ui.debug.map +4 -4
  48. package/dist/shaka-player.ui.externs.js +1023 -451
  49. package/dist/shaka-player.ui.js +1244 -1071
  50. package/dist/shaka-player.ui.map +4 -4
  51. package/docs/tutorials/ad_monetization.md +15 -1
  52. package/docs/tutorials/application-level-redirects.md +1 -1
  53. package/docs/tutorials/config.md +9 -5
  54. package/docs/tutorials/drm-config.md +61 -0
  55. package/docs/tutorials/fairplay.md +19 -4
  56. package/docs/tutorials/license-server-auth.md +4 -4
  57. package/docs/tutorials/license-wrapping.md +2 -2
  58. package/docs/tutorials/ui-customization.md +7 -3
  59. package/docs/tutorials/ui.md +7 -7
  60. package/docs/tutorials/upgrade.md +3 -0
  61. package/externs/ima.js +123 -2
  62. package/externs/isoboxer.js +217 -0
  63. package/externs/mediakeys.js +18 -0
  64. package/externs/mux.js +1 -105
  65. package/externs/pictureinpicture.js +48 -0
  66. package/externs/shaka/ads.js +61 -1
  67. package/externs/shaka/cea.js +110 -0
  68. package/externs/shaka/codecs.js +32 -0
  69. package/externs/shaka/manifest.js +101 -1
  70. package/externs/shaka/manifest_parser.js +0 -10
  71. package/externs/shaka/net.js +36 -7
  72. package/externs/shaka/offline.js +8 -1
  73. package/externs/shaka/player.js +220 -21
  74. package/externs/shaka/text.js +1 -382
  75. package/externs/shaka/transmuxer.js +59 -0
  76. package/karma.conf.js +15 -0
  77. package/lib/abr/simple_abr_manager.js +6 -3
  78. package/lib/ads/ad_manager.js +60 -2
  79. package/lib/ads/client_side_ad.js +86 -0
  80. package/lib/ads/client_side_ad_manager.js +93 -5
  81. package/lib/ads/server_side_ad.js +86 -0
  82. package/lib/ads/server_side_ad_manager.js +13 -0
  83. package/lib/cast/cast_utils.js +1 -0
  84. package/lib/cea/cea608_data_channel.js +24 -14
  85. package/lib/cea/cea608_memory.js +5 -2
  86. package/lib/cea/cea708_service.js +8 -9
  87. package/lib/cea/cea708_window.js +1 -2
  88. package/lib/cea/cea_decoder.js +23 -6
  89. package/lib/cea/cea_utils.js +25 -2
  90. package/lib/cea/dummy_caption_decoder.js +21 -0
  91. package/lib/cea/dummy_cea_parser.js +1 -3
  92. package/lib/cea/mp4_cea_parser.js +15 -10
  93. package/lib/cea/ts_cea_parser.js +69 -0
  94. package/lib/dash/content_protection.js +32 -2
  95. package/lib/dash/dash_parser.js +93 -31
  96. package/lib/dash/mpd_utils.js +6 -25
  97. package/lib/dash/segment_base.js +12 -14
  98. package/lib/dash/segment_list.js +10 -6
  99. package/lib/dash/segment_template.js +349 -32
  100. package/lib/dependencies/all.js +8 -0
  101. package/lib/hls/hls_classes.js +33 -8
  102. package/lib/hls/hls_parser.js +805 -191
  103. package/lib/hls/manifest_text_parser.js +4 -14
  104. package/lib/media/adaptation_set_criteria.js +43 -3
  105. package/lib/media/closed_caption_parser.js +74 -12
  106. package/lib/media/drm_engine.js +189 -49
  107. package/lib/media/gap_jumping_controller.js +1 -1
  108. package/lib/media/manifest_parser.js +34 -0
  109. package/lib/media/media_source_capabilities.js +10 -0
  110. package/lib/media/media_source_engine.js +475 -231
  111. package/lib/media/playhead.js +1 -1
  112. package/lib/media/presentation_timeline.js +62 -0
  113. package/lib/media/segment_index.js +50 -14
  114. package/lib/media/segment_prefetch.js +277 -0
  115. package/lib/media/segment_reference.js +70 -4
  116. package/lib/media/streaming_engine.js +258 -81
  117. package/lib/media/video_wrapper.js +15 -7
  118. package/lib/mss/content_protection.js +353 -0
  119. package/lib/mss/mss_parser.js +1081 -0
  120. package/lib/net/networking_engine.js +60 -10
  121. package/lib/offline/indexeddb/v1_storage_cell.js +1 -0
  122. package/lib/offline/indexeddb/v2_storage_cell.js +1 -0
  123. package/lib/offline/manifest_converter.js +6 -0
  124. package/lib/offline/storage.js +2 -4
  125. package/lib/player.js +309 -105
  126. package/lib/polyfill/media_capabilities.js +43 -3
  127. package/lib/polyfill/patchedmediakeys_apple.js +5 -0
  128. package/lib/polyfill/patchedmediakeys_nop.js +5 -0
  129. package/lib/polyfill/patchedmediakeys_webkit.js +5 -0
  130. package/lib/text/cue.js +208 -130
  131. package/lib/text/lrc_text_parser.js +2 -2
  132. package/lib/text/mp4_vtt_parser.js +2 -2
  133. package/lib/text/sbv_text_parser.js +1 -1
  134. package/lib/text/simple_text_displayer.js +2 -1
  135. package/lib/text/srt_text_parser.js +9 -1
  136. package/lib/text/ssa_text_parser.js +2 -2
  137. package/lib/text/text_engine.js +3 -21
  138. package/lib/text/text_utils.js +71 -20
  139. package/lib/text/ui_text_displayer.js +14 -14
  140. package/lib/text/vtt_text_parser.js +22 -14
  141. package/lib/transmuxer/aac_transmuxer.js +224 -0
  142. package/lib/transmuxer/ac3.js +142 -0
  143. package/lib/transmuxer/ac3_transmuxer.js +212 -0
  144. package/lib/transmuxer/adts.js +232 -0
  145. package/lib/transmuxer/ec3.js +103 -0
  146. package/lib/transmuxer/ec3_transmuxer.js +212 -0
  147. package/lib/transmuxer/h264.js +324 -0
  148. package/lib/transmuxer/mp3_transmuxer.js +204 -0
  149. package/lib/transmuxer/mpeg_audio.js +196 -0
  150. package/lib/transmuxer/mpeg_ts_transmuxer.js +182 -0
  151. package/lib/transmuxer/mss_transmuxer.js +389 -0
  152. package/lib/{media/transmuxer.js → transmuxer/muxjs_transmuxer.js} +34 -80
  153. package/lib/transmuxer/transmuxer_engine.js +161 -0
  154. package/lib/transmuxer/ts_transmuxer.js +738 -0
  155. package/lib/util/cmcd_manager.js +131 -71
  156. package/lib/util/error.js +62 -26
  157. package/lib/util/exp_golomb.js +220 -0
  158. package/lib/util/fairplay_utils.js +64 -13
  159. package/lib/util/id3_utils.js +56 -3
  160. package/lib/util/language_utils.js +11 -8
  161. package/lib/util/manifest_parser_utils.js +3 -0
  162. package/lib/util/mime_utils.js +44 -7
  163. package/lib/util/mp4_box_parsers.js +233 -5
  164. package/lib/util/mp4_generator.js +1381 -0
  165. package/lib/util/periods.js +40 -34
  166. package/lib/util/platform.js +25 -3
  167. package/lib/util/player_configuration.js +38 -1
  168. package/lib/util/stream_utils.js +138 -27
  169. package/lib/util/text_parser.js +1 -1
  170. package/lib/util/ts_parser.js +470 -47
  171. package/lib/util/xml_utils.js +16 -3
  172. package/maintained-branches.md +2 -2
  173. package/package.json +4 -2
  174. package/roadmap.md +21 -6
  175. package/shaka-player.uncompiled.js +18 -0
  176. package/test/abr/simple_abr_manager_unit.js +32 -4
  177. package/test/ads/ad_manager_unit.js +18 -2
  178. package/test/cast/cast_utils_unit.js +7 -2
  179. package/test/cea/cea608_memory_unit.js +24 -0
  180. package/test/cea/cea_decoder_unit.js +33 -0
  181. package/test/dash/dash_parser_content_protection_unit.js +93 -3
  182. package/test/dash/dash_parser_live_unit.js +56 -13
  183. package/test/dash/dash_parser_manifest_unit.js +70 -2
  184. package/test/dash/dash_parser_segment_base_unit.js +14 -9
  185. package/test/dash/dash_parser_segment_template_unit.js +286 -6
  186. package/test/demo/demo_unit.js +5 -1
  187. package/test/hls/hls_live_unit.js +188 -28
  188. package/test/hls/hls_parser_unit.js +250 -109
  189. package/test/hls/manifest_text_parser_unit.js +18 -13
  190. package/test/media/adaptation_set_criteria_unit.js +46 -14
  191. package/test/media/adaptation_set_unit.js +2 -0
  192. package/test/media/drm_engine_integration.js +11 -8
  193. package/test/media/drm_engine_unit.js +220 -7
  194. package/test/media/media_source_engine_integration.js +122 -38
  195. package/test/media/media_source_engine_unit.js +133 -153
  196. package/test/media/playhead_unit.js +3 -0
  197. package/test/media/presentation_timeline_unit.js +51 -0
  198. package/test/media/segment_index_unit.js +52 -0
  199. package/test/media/segment_prefetch_unit.js +243 -0
  200. package/test/media/streaming_engine_integration.js +9 -3
  201. package/test/media/streaming_engine_unit.js +440 -59
  202. package/test/mss/mss_parser_content_protection_unit.js +49 -0
  203. package/test/mss/mss_parser_unit.js +472 -0
  204. package/test/mss/mss_player_integration.js +123 -0
  205. package/test/offline/manifest_convert_unit.js +9 -0
  206. package/test/offline/storage_integration.js +6 -1
  207. package/test/player_integration.js +4 -1
  208. package/test/player_unit.js +386 -133
  209. package/test/polyfill/media_capabilities_unit.js +18 -0
  210. package/test/test/assets/hls-raw-aac/fileSequence0.aac +0 -0
  211. package/test/test/assets/hls-raw-aac/fileSequence1.aac +0 -0
  212. package/test/test/assets/hls-raw-aac/fileSequence2.aac +0 -0
  213. package/test/test/assets/hls-raw-aac/fileSequence3.aac +0 -0
  214. package/test/test/assets/hls-raw-aac/manifest.m3u8 +4 -0
  215. package/test/test/assets/hls-raw-aac/stream.m4a.m3u8 +14 -0
  216. package/test/test/assets/hls-raw-ac3/fileSequence0.ac3 +0 -0
  217. package/test/test/assets/hls-raw-ac3/fileSequence1.ac3 +0 -0
  218. package/test/test/assets/hls-raw-ac3/fileSequence2.ac3 +0 -0
  219. package/test/test/assets/hls-raw-ac3/fileSequence3.ac3 +0 -0
  220. package/test/test/assets/hls-raw-ac3/fileSequence4.ac3 +0 -0
  221. package/test/test/assets/hls-raw-ac3/fileSequence5.ac3 +0 -0
  222. package/test/test/assets/hls-raw-ac3/fileSequence6.ac3 +0 -0
  223. package/test/test/assets/hls-raw-ac3/fileSequence7.ac3 +0 -0
  224. package/test/test/assets/hls-raw-ac3/prog_index.m3u8 +31 -0
  225. package/test/test/assets/hls-raw-ec3/fileSequence0.ec3 +0 -0
  226. package/test/test/assets/hls-raw-ec3/fileSequence1.ec3 +0 -0
  227. package/test/test/assets/hls-raw-ec3/fileSequence2.ec3 +0 -0
  228. package/test/test/assets/hls-raw-ec3/fileSequence3.ec3 +0 -0
  229. package/test/test/assets/hls-raw-ec3/fileSequence4.ec3 +0 -0
  230. package/test/test/assets/hls-raw-ec3/fileSequence5.ec3 +0 -0
  231. package/test/test/assets/hls-raw-ec3/fileSequence6.ec3 +0 -0
  232. package/test/test/assets/hls-raw-ec3/fileSequence7.ec3 +0 -0
  233. package/test/test/assets/hls-raw-ec3/prog_index.m3u8 +31 -0
  234. package/test/test/assets/hls-raw-mp3/chunklist_w905519204.m3u8 +13 -0
  235. package/test/test/assets/hls-raw-mp3/media_w905519204_0.mp3 +0 -0
  236. package/test/test/assets/hls-raw-mp3/media_w905519204_1.mp3 +0 -0
  237. package/test/test/assets/hls-raw-mp3/media_w905519204_2.mp3 +0 -0
  238. package/test/test/assets/hls-raw-mp3/media_w905519204_3.mp3 +0 -0
  239. package/test/test/assets/hls-raw-mp3/playlist.m3u8 +4 -0
  240. package/test/test/assets/hls-ts-aac/playlist.m3u8 +23 -0
  241. package/test/test/assets/hls-ts-aac/segment_0.ts +0 -0
  242. package/test/test/assets/hls-ts-aac/segment_1.ts +0 -0
  243. package/test/test/assets/hls-ts-aac/segment_2.ts +0 -0
  244. package/test/test/assets/hls-ts-aac/segment_3.ts +0 -0
  245. package/test/test/assets/hls-ts-aac/segment_4.ts +0 -0
  246. package/test/test/assets/hls-ts-aac/segment_5.ts +0 -0
  247. package/test/test/assets/hls-ts-aac/segment_6.ts +0 -0
  248. package/test/test/assets/hls-ts-aac/segment_7.ts +0 -0
  249. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0000.ts +0 -0
  250. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0001.ts +0 -0
  251. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0002.ts +0 -0
  252. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0003.ts +0 -0
  253. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0004.ts +0 -0
  254. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0005.ts +0 -0
  255. package/test/test/assets/hls-ts-ac3/prog_index.m3u8 +19 -0
  256. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0000.ts +0 -0
  257. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0001.ts +0 -0
  258. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0002.ts +0 -0
  259. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0003.ts +0 -0
  260. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0004.ts +0 -0
  261. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0005.ts +0 -0
  262. package/test/test/assets/hls-ts-ec3/prog_index.m3u8 +19 -0
  263. package/test/test/assets/hls-ts-h264/fileSequence0.ts +0 -0
  264. package/test/test/assets/hls-ts-h264/fileSequence1.ts +0 -0
  265. package/test/test/assets/hls-ts-h264/fileSequence2.ts +0 -0
  266. package/test/test/assets/hls-ts-h264/fileSequence3.ts +0 -0
  267. package/test/test/assets/hls-ts-h264/fileSequence4.ts +0 -0
  268. package/test/test/assets/hls-ts-h264/fileSequence5.ts +0 -0
  269. package/test/test/assets/hls-ts-h264/prog_index.m3u8 +25 -0
  270. package/test/test/assets/hls-ts-mp3/manifest.m3u8 +13 -0
  271. package/test/test/assets/hls-ts-mp3/media_w239891843_0.ts +0 -0
  272. package/test/test/assets/hls-ts-mp3/media_w239891843_1.ts +0 -0
  273. package/test/test/assets/hls-ts-mp3/media_w239891843_2.ts +0 -0
  274. package/test/test/assets/hls-ts-mp3/media_w239891843_3.ts +0 -0
  275. package/test/test/assets/hls-ts-muxed-aac-h264/chunk.m3u8 +17 -0
  276. package/test/test/assets/hls-ts-muxed-aac-h264/n_0_0_0.ts +0 -0
  277. package/test/test/assets/hls-ts-muxed-aac-h264/n_1_0_0.ts +0 -0
  278. package/test/test/assets/hls-ts-muxed-aac-h264/n_2_0_0.ts +0 -0
  279. package/test/test/assets/hls-ts-muxed-aac-h264/n_3_0_0.ts +0 -0
  280. package/test/test/assets/hls-ts-muxed-aac-h264/n_4_0_0.ts +0 -0
  281. package/test/test/assets/hls-ts-muxed-aac-h264/n_5_0_0.ts +0 -0
  282. package/test/test/assets/hls-ts-muxed-aac-h264/playlist.m3u8 +4 -0
  283. package/test/test/boot.js +7 -2
  284. package/test/test/util/fake_ad.js +99 -0
  285. package/test/test/util/fake_ad_manager.js +7 -1
  286. package/test/test/util/fake_networking_engine.js +41 -14
  287. package/test/test/util/fake_segment_prefetch.js +81 -0
  288. package/test/test/util/manifest_generator.js +19 -5
  289. package/test/test/util/mss_parser_util.js +115 -0
  290. package/test/test/util/offline_utils.js +1 -0
  291. package/test/test/util/simple_fakes.js +12 -3
  292. package/test/test/util/streaming_engine_util.js +14 -4
  293. package/test/test/util/ttml_utils.js +2 -2
  294. package/test/test/util/ui_utils.js +5 -1
  295. package/test/text/cue_integration.js +1 -1
  296. package/test/text/srt_text_parser_unit.js +78 -0
  297. package/test/text/text_engine_unit.js +17 -8
  298. package/test/text/ui_text_displayer_unit.js +4 -4
  299. package/test/text/vtt_text_parser_unit.js +59 -40
  300. package/test/text/web_vtt_generator_unit.js +9 -3
  301. package/test/{media/transmuxer_integration.js → transmuxer/muxjs_transmuxer_integration.js} +30 -33
  302. package/test/transmuxer/transmuxer_engine_integration.js +60 -0
  303. package/test/transmuxer/transmuxer_integration.js +296 -0
  304. package/test/util/cmcd_manager_unit.js +162 -13
  305. package/test/util/language_utils_unit.js +9 -2
  306. package/test/util/mp4_box_parsers_unit.js +39 -4
  307. package/test/util/periods_unit.js +34 -26
  308. package/test/util/stream_utils_unit.js +60 -107
  309. package/ui/controls.js +19 -1
  310. package/ui/controls.less +1 -0
  311. package/ui/externs/ui.js +13 -3
  312. package/ui/language_utils.js +15 -0
  313. package/ui/less/thumbnails.less +26 -0
  314. package/ui/locales/oc.json +42 -0
  315. package/ui/pip_button.js +83 -2
  316. package/ui/range_element.js +15 -0
  317. package/ui/resolution_selection.js +9 -2
  318. package/ui/seek_bar.js +230 -1
  319. package/ui/ui.js +5 -0
  320. package/lib/cea/i_caption_decoder.js +0 -51
  321. package/lib/cea/i_cea_parser.js +0 -68
@@ -14,9 +14,11 @@ 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.IReleasable');
17
18
  goog.require('shaka.util.ManifestParserUtils');
18
19
  goog.require('shaka.util.ObjectUtils');
19
20
  goog.requireType('shaka.dash.DashParser');
21
+ goog.requireType('shaka.media.PresentationTimeline');
20
22
 
21
23
 
22
24
  /**
@@ -28,8 +30,7 @@ shaka.dash.SegmentTemplate = class {
28
30
  * Updates the existing SegmentIndex, if any.
29
31
  *
30
32
  * @param {shaka.dash.DashParser.Context} context
31
- * @param {shaka.dash.DashParser.RequestInitSegmentCallback}
32
- * requestInitSegment
33
+ * @param {shaka.dash.DashParser.RequestSegmentCallback} requestSegment
33
34
  * @param {!Object.<string, !shaka.extern.Stream>} streamMap
34
35
  * @param {boolean} isUpdate True if the manifest is being updated.
35
36
  * @param {number} segmentLimit The maximum number of segments to generate for
@@ -38,13 +39,16 @@ shaka.dash.SegmentTemplate = class {
38
39
  * @return {shaka.dash.DashParser.StreamInfo}
39
40
  */
40
41
  static createStreamInfo(
41
- context, requestInitSegment, streamMap, isUpdate, segmentLimit,
42
+ context, requestSegment, streamMap, isUpdate, segmentLimit,
42
43
  periodDurationMap) {
43
44
  goog.asserts.assert(context.representation.segmentTemplate,
44
45
  'Should only be called with SegmentTemplate');
45
46
  const SegmentTemplate = shaka.dash.SegmentTemplate;
47
+ const TimelineSegmentIndex = shaka.dash.TimelineSegmentIndex;
46
48
 
47
49
  const initSegmentReference = SegmentTemplate.createInitSegment_(context);
50
+
51
+ /** @type {shaka.dash.SegmentTemplate.SegmentTemplateInfo} */
48
52
  const info = SegmentTemplate.parseSegmentTemplateInfo_(context);
49
53
 
50
54
  SegmentTemplate.checkSegmentTemplateInfo_(context, info);
@@ -62,7 +66,7 @@ shaka.dash.SegmentTemplate = class {
62
66
  return {
63
67
  generateSegmentIndex: () => {
64
68
  return SegmentTemplate.generateSegmentIndexFromIndexTemplate_(
65
- shallowCopyOfContext, requestInitSegment, initSegmentReference,
69
+ shallowCopyOfContext, requestSegment, initSegmentReference,
66
70
  info);
67
71
  },
68
72
  };
@@ -95,12 +99,11 @@ shaka.dash.SegmentTemplate = class {
95
99
  }
96
100
  }
97
101
 
98
- const references = SegmentTemplate.createFromTimeline_(
99
- shallowCopyOfContext, info, initSegmentReference);
100
-
101
102
  const periodStart = context.periodInfo.start;
102
- const periodEnd = context.periodInfo.duration ?
103
- context.periodInfo.start + context.periodInfo.duration : Infinity;
103
+ const periodEnd = context.periodInfo.duration ? periodStart +
104
+ context.periodInfo.duration : Infinity;
105
+
106
+ shaka.log.debug(`New manifest ${periodStart} - ${periodEnd}`);
104
107
 
105
108
  /* When to fit segments. All refactors should honor/update this table:
106
109
  *
@@ -120,23 +123,32 @@ shaka.dash.SegmentTemplate = class {
120
123
  // most recent segment to the end of the presentation).
121
124
  const shouldFit = !(context.dynamic && context.periodInfo.isLastPeriod);
122
125
 
123
- if (segmentIndex) {
124
- if (shouldFit) {
125
- // Fit the new references before merging them, so that the merge
126
- // algorithm has a more accurate view of their start and end times.
127
- const wrapper = new shaka.media.SegmentIndex(references);
128
- wrapper.fit(periodStart, periodEnd, /* isNew= */ true);
129
- }
130
-
131
- segmentIndex.mergeAndEvict(references,
132
- context.presentationTimeline.getSegmentAvailabilityStart());
126
+ if (!segmentIndex) {
127
+ shaka.log.debug(`Creating TSI with end ${periodEnd}`);
128
+ segmentIndex = new TimelineSegmentIndex(
129
+ info,
130
+ context.representation.id,
131
+ context.bandwidth,
132
+ context.representation.baseUris,
133
+ periodStart,
134
+ periodEnd,
135
+ initSegmentReference,
136
+ shouldFit,
137
+ );
133
138
  } else {
134
- segmentIndex = new shaka.media.SegmentIndex(references);
139
+ const tsi = /** @type {!TimelineSegmentIndex} */(segmentIndex);
140
+ tsi.appendTemplateInfo(info, periodStart, periodEnd, shouldFit);
141
+
142
+ const availabilityStart =
143
+ context.presentationTimeline.getSegmentAvailabilityStart();
144
+ tsi.evict(availabilityStart);
135
145
  }
136
- context.presentationTimeline.notifySegments(references);
137
146
 
138
- if (shouldFit) {
139
- segmentIndex.fit(periodStart, periodEnd);
147
+ if (info.timeline && context.adaptationSet.contentType !== 'image') {
148
+ const timeline = info.timeline;
149
+ context.presentationTimeline.notifyTimeRange(
150
+ timeline,
151
+ periodStart);
140
152
  }
141
153
 
142
154
  if (stream && context.dynamic) {
@@ -148,8 +160,10 @@ shaka.dash.SegmentTemplate = class {
148
160
  // If segmentIndex is deleted, or segmentIndex's references are
149
161
  // released by closeSegmentIndex(), we should set the value of
150
162
  // segmentIndex again.
151
- if (!segmentIndex || segmentIndex.isEmpty()) {
152
- segmentIndex.merge(references);
163
+ if (segmentIndex instanceof shaka.dash.TimelineSegmentIndex &&
164
+ segmentIndex.isEmpty()) {
165
+ segmentIndex.appendTemplateInfo(info, periodStart,
166
+ periodEnd, shouldFit);
153
167
  }
154
168
  return Promise.resolve(segmentIndex);
155
169
  },
@@ -253,15 +267,14 @@ shaka.dash.SegmentTemplate = class {
253
267
  * Generates a SegmentIndex from an index URL template.
254
268
  *
255
269
  * @param {shaka.dash.DashParser.Context} context
256
- * @param {shaka.dash.DashParser.RequestInitSegmentCallback}
257
- * requestInitSegment
270
+ * @param {shaka.dash.DashParser.RequestSegmentCallback} requestSegment
258
271
  * @param {shaka.media.InitSegmentReference} init
259
272
  * @param {shaka.dash.SegmentTemplate.SegmentTemplateInfo} info
260
273
  * @return {!Promise.<shaka.media.SegmentIndex>}
261
274
  * @private
262
275
  */
263
276
  static generateSegmentIndexFromIndexTemplate_(
264
- context, requestInitSegment, init, info) {
277
+ context, requestSegment, init, info) {
265
278
  const MpdUtils = shaka.dash.MpdUtils;
266
279
  const ManifestParserUtils = shaka.util.ManifestParserUtils;
267
280
 
@@ -274,7 +287,7 @@ shaka.dash.SegmentTemplate = class {
274
287
  context.representation.baseUris, [filledTemplate]);
275
288
 
276
289
  return shaka.dash.SegmentBase.generateSegmentIndexFromUris(
277
- context, requestInitSegment, init, resolvedUris, 0, null,
290
+ context, requestSegment, init, resolvedUris, 0, null,
278
291
  info.scaledPresentationTimeOffset);
279
292
  }
280
293
 
@@ -599,6 +612,311 @@ shaka.dash.SegmentTemplate = class {
599
612
  }
600
613
  };
601
614
 
615
+
616
+ /**
617
+ * A SegmentIndex that returns segments references on demand from
618
+ * a segment timeline.
619
+ *
620
+ * @extends shaka.media.SegmentIndex
621
+ * @implements {shaka.util.IReleasable}
622
+ * @implements {Iterable.<!shaka.media.SegmentReference>}
623
+ *
624
+ * @private
625
+ *
626
+ */
627
+ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
628
+ /**
629
+ *
630
+ * @param {!shaka.dash.SegmentTemplate.SegmentTemplateInfo} templateInfo
631
+ * @param {?string} representationId
632
+ * @param {number} bandwidth
633
+ * @param {Array.<string>} baseUris
634
+ * @param {number} periodStart
635
+ * @param {number} periodEnd
636
+ * @param {shaka.media.InitSegmentReference} initSegmentReference
637
+ * @param {boolean} shouldFit
638
+ *
639
+ */
640
+ constructor(templateInfo, representationId, bandwidth, baseUris,
641
+ periodStart, periodEnd, initSegmentReference, shouldFit) {
642
+ super([]);
643
+
644
+ /** @private {?shaka.dash.SegmentTemplate.SegmentTemplateInfo} */
645
+ this.templateInfo_ = templateInfo;
646
+ /** @private {?string} */
647
+ this.representationId_ = representationId;
648
+ /** @private {number} */
649
+ this.bandwidth_ = bandwidth;
650
+ /** @private {Array.<string>} */
651
+ this.baseUris_ = baseUris;
652
+ /** @private {number} */
653
+ this.periodStart_ = periodStart;
654
+ /** @private {number} */
655
+ this.periodEnd_ = periodEnd;
656
+ /** @private {shaka.media.InitSegmentReference} */
657
+ this.initSegmentReference_ = initSegmentReference;
658
+
659
+
660
+ if (shouldFit) {
661
+ this.fitTimeline();
662
+ }
663
+ }
664
+
665
+ /**
666
+ * @override
667
+ */
668
+ getNumReferences() {
669
+ if (this.templateInfo_) {
670
+ return this.templateInfo_.timeline.length;
671
+ } else {
672
+ return 0;
673
+ }
674
+ }
675
+
676
+ /**
677
+ * @override
678
+ */
679
+ release() {
680
+ super.release();
681
+ this.templateInfo_ = null;
682
+ // We cannot release other fields, as segment index can
683
+ // be recreated using only template info.
684
+ }
685
+
686
+
687
+ /**
688
+ * @override
689
+ */
690
+ evict(time) {
691
+ if (!this.templateInfo_) {
692
+ return;
693
+ }
694
+ shaka.log.debug(`${this.representationId_} Evicting at ${time}`);
695
+ let numToEvict = 0;
696
+ const timeline = this.templateInfo_.timeline;
697
+
698
+ for (let i = 0; i < timeline.length; i += 1) {
699
+ const range = timeline[i];
700
+ const end = range.end + this.periodStart_;
701
+ const start = range.start + this.periodStart_;
702
+
703
+ if (end <= time) {
704
+ shaka.log.debug(`Evicting ${start} - ${end}`);
705
+ numToEvict += 1;
706
+ } else {
707
+ break;
708
+ }
709
+ }
710
+
711
+ if (numToEvict > 0) {
712
+ this.templateInfo_.timeline = timeline.slice(numToEvict);
713
+ if (this.references.length >= numToEvict) {
714
+ this.references = this.references.slice(numToEvict);
715
+ }
716
+
717
+ this.numEvicted_ += numToEvict;
718
+
719
+ if (this.getNumReferences() === 0) {
720
+ this.release();
721
+ }
722
+ }
723
+ }
724
+
725
+ /**
726
+ * Merge new template info
727
+ * @param {shaka.dash.SegmentTemplate.SegmentTemplateInfo} info
728
+ * @param {number} periodStart
729
+ * @param {number} periodEnd
730
+ * @param {boolean} shouldFit
731
+ */
732
+ appendTemplateInfo(info, periodStart, periodEnd, shouldFit) {
733
+ if (!this.templateInfo_) {
734
+ this.templateInfo_ = info;
735
+ this.periodStart_ = periodStart;
736
+ this.periodEnd_ = periodEnd;
737
+ } else {
738
+ const currentTimeline = this.templateInfo_.timeline;
739
+
740
+ // Append timeline
741
+ const lastCurrentEntry = currentTimeline[currentTimeline.length - 1];
742
+ const newEntries = info.timeline.filter((entry) => {
743
+ return entry.start >= lastCurrentEntry.end;
744
+ });
745
+
746
+ if (newEntries.length > 0) {
747
+ shaka.log.debug(`Appending ${newEntries.length} entries`);
748
+ this.templateInfo_.timeline.push(...newEntries);
749
+ }
750
+
751
+ if (this.periodEnd_ !== periodEnd) {
752
+ this.periodEnd_ = periodEnd;
753
+ }
754
+ }
755
+
756
+ if (shouldFit) {
757
+ this.fitTimeline();
758
+ }
759
+ }
760
+
761
+ /**
762
+ *
763
+ * @param {number} time
764
+ */
765
+ isBeforeFirstEntry(time) {
766
+ const hasTimeline = this.templateInfo_ &&
767
+ this.templateInfo_.timeline && this.templateInfo_.timeline.length;
768
+
769
+ if (hasTimeline) {
770
+ const timeline = this.templateInfo_.timeline;
771
+ return time < timeline[0].start + this.periodStart_;
772
+ } else {
773
+ return false;
774
+ }
775
+ }
776
+
777
+ /**
778
+ * Fit timeline entries to period boundaries
779
+ */
780
+ fitTimeline() {
781
+ if (this.getIsImmutable()) {
782
+ return;
783
+ }
784
+ const timeline = this.templateInfo_.timeline;
785
+ while (timeline.length) {
786
+ const lastTimePeriod = timeline[timeline.length - 1];
787
+ if (lastTimePeriod.start >= this.periodEnd_) {
788
+ timeline.pop();
789
+ } else {
790
+ break;
791
+ }
792
+ }
793
+
794
+ this.evict(this.periodStart_);
795
+
796
+ if (timeline.length === 0) {
797
+ return;
798
+ }
799
+
800
+ if (this.periodEnd_ !== Infinity) {
801
+ // Adjust the last timeline entry to match the period end
802
+ const lastTimePeriod = timeline[timeline.length - 1];
803
+ // NOTE: end should be relative to period start
804
+ lastTimePeriod.end = this.periodEnd_ - this.periodStart_;
805
+ }
806
+ }
807
+
808
+ /**
809
+ * @override
810
+ */
811
+ find(time) {
812
+ shaka.log.debug(`Find ${time}`);
813
+
814
+ if (this.isBeforeFirstEntry(time)) {
815
+ return this.numEvicted_;
816
+ }
817
+
818
+ if (!this.templateInfo_) {
819
+ return null;
820
+ }
821
+
822
+ const timeline = this.templateInfo_.timeline;
823
+
824
+ // Early exit if the time isn't within this period
825
+ if (time < this.periodStart_ || time > this.periodEnd_) {
826
+ return null;
827
+ }
828
+
829
+ const lastIndex = timeline.length - 1;
830
+
831
+ for (let i = 0; i < timeline.length; i++) {
832
+ const range = timeline[i];
833
+ const start = range.start + this.periodStart_;
834
+ // A rounding error can cause /time/ to equal e.endTime or fall in between
835
+ // the references by a fraction of a second. To account for this, we use
836
+ // the start of the next segment as /end/, unless this is the last
837
+ // reference, in which case we use the period end as the /end/
838
+ let end = range.end + this.periodStart_;
839
+
840
+ if (i < lastIndex) {
841
+ end = timeline[i + 1].start + this.periodStart_;
842
+ }
843
+
844
+ if ((time >= start) && (time < end)) {
845
+ return i + this.numEvicted_;
846
+ }
847
+ }
848
+
849
+ return null;
850
+ }
851
+
852
+ /**
853
+ * @override
854
+ */
855
+ get(position) {
856
+ const correctedPosition = position - this.numEvicted_;
857
+ if (correctedPosition < 0 ||
858
+ correctedPosition >= this.getNumReferences() || !this.templateInfo_) {
859
+ return null;
860
+ }
861
+
862
+ let ref = this.references[correctedPosition];
863
+
864
+ if (!ref) {
865
+ const range = this.templateInfo_.timeline[correctedPosition];
866
+ const segmentReplacement = position + this.templateInfo_.startNumber;
867
+ const timeReplacement = this.templateInfo_
868
+ .unscaledPresentationTimeOffset + range.unscaledStart;
869
+
870
+ const createUrisCb = () => {
871
+ return shaka.dash.TimelineSegmentIndex
872
+ .createUris_(
873
+ this.templateInfo_.mediaTemplate,
874
+ this.representationId_,
875
+ segmentReplacement,
876
+ this.bandwidth_,
877
+ timeReplacement,
878
+ this.baseUris_,
879
+ );
880
+ };
881
+
882
+ const timestampOffset = this.periodStart_ -
883
+ this.templateInfo_.scaledPresentationTimeOffset;
884
+
885
+ ref = new shaka.media.SegmentReference(
886
+ this.periodStart_ + range.start,
887
+ this.periodStart_ + range.end,
888
+ createUrisCb,
889
+ /* startByte= */ 0,
890
+ /* endByte= */ null,
891
+ this.initSegmentReference_,
892
+ timestampOffset,
893
+ this.periodStart_,
894
+ this.periodEnd_);
895
+ this.references[correctedPosition] = ref;
896
+ }
897
+
898
+ return ref;
899
+ }
900
+
901
+ /**
902
+ * Fill in a specific template with values to get the segment uris
903
+ *
904
+ * @return {!Array.<string>}
905
+ * @private
906
+ */
907
+ static createUris_(mediaTemplate, repId, segmentReplacement,
908
+ bandwidth, timeReplacement, baseUris) {
909
+ const mediaUri = shaka.dash.MpdUtils.fillUriTemplate(
910
+ mediaTemplate, repId,
911
+ segmentReplacement, bandwidth || null, timeReplacement);
912
+ return shaka.util.ManifestParserUtils
913
+ .resolveUris(baseUris, [mediaUri])
914
+ .map((g) => {
915
+ return g.toString();
916
+ });
917
+ }
918
+ };
919
+
602
920
  /**
603
921
  * @typedef {{
604
922
  * timescale: number,
@@ -606,11 +924,10 @@ shaka.dash.SegmentTemplate = class {
606
924
  * startNumber: number,
607
925
  * scaledPresentationTimeOffset: number,
608
926
  * unscaledPresentationTimeOffset: number,
609
- * timeline: Array.<shaka.dash.MpdUtils.TimeRange>,
927
+ * timeline: Array.<shaka.media.PresentationTimeline.TimeRange>,
610
928
  * mediaTemplate: ?string,
611
929
  * indexTemplate: ?string
612
930
  * }}
613
- * @private
614
931
  *
615
932
  * @description
616
933
  * Contains information about a SegmentTemplate.
@@ -625,7 +942,7 @@ shaka.dash.SegmentTemplate = class {
625
942
  * The presentation time offset of the representation, in seconds.
626
943
  * @property {number} unscaledPresentationTimeOffset
627
944
  * The presentation time offset of the representation, in timescale units.
628
- * @property {Array.<shaka.dash.MpdUtils.TimeRange>} timeline
945
+ * @property {Array.<shaka.media.PresentationTimeline.TimeRange>} timeline
629
946
  * The timeline of the representation, if given. Times in seconds.
630
947
  * @property {?string} mediaTemplate
631
948
  * The media URI template, if given.
@@ -41,6 +41,12 @@ shaka.dependencies = class {
41
41
  return /** @type {?muxjs} */ (shaka.dependencies.dependencies_.get(
42
42
  shaka.dependencies.Allowed.muxjs)());
43
43
  }
44
+
45
+ /** @return {?ISOBoxer} */
46
+ static isoBoxer() {
47
+ return /** @type {?ISOBoxer} */ (shaka.dependencies.dependencies_.get(
48
+ shaka.dependencies.Allowed.ISOBoxer)());
49
+ }
44
50
  };
45
51
 
46
52
  /**
@@ -49,6 +55,7 @@ shaka.dependencies = class {
49
55
  */
50
56
  shaka.dependencies.Allowed = {
51
57
  muxjs: 'muxjs',
58
+ ISOBoxer: 'ISOBoxer',
52
59
  };
53
60
 
54
61
  /**
@@ -59,4 +66,5 @@ shaka.dependencies.Allowed = {
59
66
  */
60
67
  shaka.dependencies.dependencies_ = new Map([
61
68
  [shaka.dependencies.Allowed.muxjs, () => window.muxjs],
69
+ [shaka.dependencies.Allowed.ISOBoxer, () => window.ISOBoxer],
62
70
  ]);
@@ -11,6 +11,7 @@ goog.provide('shaka.hls.Segment');
11
11
  goog.provide('shaka.hls.Tag');
12
12
 
13
13
  goog.require('goog.asserts');
14
+ goog.require('shaka.hls.Utils');
14
15
  goog.require('shaka.util.Error');
15
16
 
16
17
 
@@ -202,24 +203,48 @@ shaka.hls.Segment = class {
202
203
  /**
203
204
  * Creates an HLS segment object.
204
205
  *
205
- * @param {string} absoluteUri An absolute URI.
206
+ * @param {string} absoluteMediaPlaylistUri An absolute Media Playlist URI.
207
+ * @param {string} verbatimSegmentUri verbatim segment URI.
206
208
  * @param {!Array.<shaka.hls.Tag>} tags
207
209
  * @param {!Array.<shaka.hls.Tag>=} partialSegments
208
210
  */
209
- constructor(absoluteUri, tags, partialSegments=[]) {
211
+ constructor(absoluteMediaPlaylistUri, verbatimSegmentUri, tags,
212
+ partialSegments=[]) {
210
213
  /** @const {!Array.<shaka.hls.Tag>} */
211
214
  this.tags = tags;
212
215
 
213
- /**
214
- * An absolute URI.
215
- *
216
- * @const {string}
217
- */
218
- this.absoluteUri = absoluteUri;
216
+ /** @type {?string} */
217
+ this.absoluteUri_ = null;
218
+
219
+ /** @type {?string} */
220
+ this.absoluteMediaPlaylistUri_ = absoluteMediaPlaylistUri;
221
+
222
+ /** @type {?string} */
223
+ this.verbatimSegmentUri_ = verbatimSegmentUri;
219
224
 
220
225
  /** @type {!Array.<shaka.hls.Tag>} */
221
226
  this.partialSegments = partialSegments;
222
227
  }
228
+
229
+ /**
230
+ * Returns an absolute URI.
231
+ *
232
+ * @return {string}
233
+ */
234
+ get absoluteUri() {
235
+ if (!this.absoluteUri_ &&
236
+ this.absoluteMediaPlaylistUri_ && this.verbatimSegmentUri_) {
237
+ goog.asserts.assert(this.absoluteMediaPlaylistUri_,
238
+ 'An absolute Media Playlist URI should be defined!');
239
+ goog.asserts.assert(this.verbatimSegmentUri_,
240
+ 'An verbatim segment URI should be defined!');
241
+ this.absoluteUri_ = shaka.hls.Utils.constructAbsoluteUri(
242
+ this.absoluteMediaPlaylistUri_, this.verbatimSegmentUri_);
243
+ this.absoluteMediaPlaylistUri_ = null;
244
+ this.verbatimSegmentUri_ = null;
245
+ }
246
+ return this.absoluteUri_ || '';
247
+ }
223
248
  };
224
249
 
225
250