shaka-player 4.4.3 → 4.6.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 (307) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +1 -1
  2. package/.github/workflows/release-please.yaml +2 -27
  3. package/AUTHORS +2 -0
  4. package/CHANGELOG.md +156 -39
  5. package/CODE_OF_CONDUCT.md +1 -1
  6. package/CONTRIBUTORS +2 -0
  7. package/README.md +54 -42
  8. package/demo/asset_card.js +18 -21
  9. package/demo/cast_receiver/index.html +0 -1
  10. package/demo/close_button.js +0 -3
  11. package/demo/common/asset.js +33 -22
  12. package/demo/common/assets.js +249 -60
  13. package/demo/config.js +219 -253
  14. package/demo/custom.js +88 -133
  15. package/demo/front.js +7 -10
  16. package/demo/index.html +19 -22
  17. package/demo/input.js +6 -11
  18. package/demo/input_container.js +8 -9
  19. package/demo/main.js +62 -126
  20. package/demo/search.js +29 -34
  21. package/demo/service_worker.js +0 -3
  22. package/demo/tooltip.js +3 -5
  23. package/demo/visualizer.js +3 -5
  24. package/demo/visualizer_button.js +1 -20
  25. package/dist/controls.css +1 -1
  26. package/dist/controls.css.map +1 -1
  27. package/dist/demo.compiled.debug.js +211 -228
  28. package/dist/demo.compiled.debug.map +4 -4
  29. package/dist/demo.compiled.js +211 -228
  30. package/dist/demo.compiled.map +4 -4
  31. package/dist/deps.js +42 -37
  32. package/dist/locales.js +34 -30
  33. package/dist/receiver.compiled.debug.js +64 -77
  34. package/dist/receiver.compiled.debug.map +4 -4
  35. package/dist/receiver.compiled.js +64 -77
  36. package/dist/receiver.compiled.map +4 -4
  37. package/dist/shaka-player.compiled.d.ts +343 -151
  38. package/dist/shaka-player.compiled.debug.d.ts +343 -151
  39. package/dist/shaka-player.compiled.debug.externs.js +356 -117
  40. package/dist/shaka-player.compiled.debug.js +952 -811
  41. package/dist/shaka-player.compiled.debug.map +4 -4
  42. package/dist/shaka-player.compiled.externs.js +356 -117
  43. package/dist/shaka-player.compiled.js +1165 -1078
  44. package/dist/shaka-player.compiled.map +4 -4
  45. package/dist/shaka-player.ui.d.ts +359 -153
  46. package/dist/shaka-player.ui.debug.d.ts +359 -153
  47. package/dist/shaka-player.ui.debug.externs.js +382 -117
  48. package/dist/shaka-player.ui.debug.js +1084 -918
  49. package/dist/shaka-player.ui.debug.map +4 -4
  50. package/dist/shaka-player.ui.externs.js +382 -117
  51. package/dist/shaka-player.ui.js +1377 -1274
  52. package/dist/shaka-player.ui.map +4 -4
  53. package/docs/design/lcevc-integration.md +14 -14
  54. package/docs/tutorials/ad_monetization.md +54 -0
  55. package/docs/tutorials/basic-usage.md +2 -1
  56. package/docs/tutorials/errors.md +2 -1
  57. package/docs/tutorials/faq.md +27 -55
  58. package/docs/tutorials/index.json +2 -1
  59. package/docs/tutorials/lcevc.md +118 -0
  60. package/docs/tutorials/offline.md +10 -8
  61. package/docs/tutorials/plugins.md +5 -0
  62. package/docs/tutorials/ui-customization.md +17 -0
  63. package/docs/tutorials/ui.md +2 -1
  64. package/docs/tutorials/upgrade.md +3 -0
  65. package/externs/css_style_declaration.js +19 -0
  66. package/externs/lcevc.js +37 -13
  67. package/externs/managedmediasource.js +24 -0
  68. package/externs/media_remote.js +68 -0
  69. package/externs/mediatailor.js +193 -0
  70. package/externs/pictureinpicture.js +11 -0
  71. package/externs/shaka/abr_manager.js +6 -2
  72. package/externs/shaka/ads.js +27 -0
  73. package/externs/shaka/cea.js +7 -0
  74. package/externs/shaka/codecs.js +5 -3
  75. package/externs/shaka/manifest.js +31 -10
  76. package/externs/shaka/manifest_parser.js +24 -1
  77. package/externs/shaka/net.js +2 -2
  78. package/externs/shaka/offline.js +13 -2
  79. package/externs/shaka/player.js +65 -8
  80. package/externs/shaka/text.js +3 -1
  81. package/externs/shaka/transmuxer.js +1 -1
  82. package/karma.conf.js +7 -3
  83. package/lib/abr/simple_abr_manager.js +66 -9
  84. package/lib/ads/ad_manager.js +104 -50
  85. package/lib/ads/media_tailor_ad.js +297 -0
  86. package/lib/ads/media_tailor_ad_manager.js +839 -0
  87. package/lib/cast/cast_receiver.js +1 -1
  88. package/lib/cea/cea_decoder.js +28 -0
  89. package/lib/cea/dummy_caption_decoder.js +5 -0
  90. package/lib/cea/ts_cea_parser.js +15 -2
  91. package/lib/config/codec_switching_strategy.js +24 -0
  92. package/lib/dash/content_protection.js +120 -2
  93. package/lib/dash/dash_parser.js +322 -93
  94. package/lib/dash/mpd_utils.js +62 -37
  95. package/lib/dash/segment_base.js +17 -10
  96. package/lib/dash/segment_list.js +18 -9
  97. package/lib/dash/segment_template.js +122 -107
  98. package/lib/dependencies/all.js +8 -7
  99. package/lib/hls/hls_classes.js +28 -43
  100. package/lib/hls/hls_parser.js +798 -658
  101. package/lib/hls/hls_utils.js +64 -5
  102. package/lib/hls/manifest_text_parser.js +7 -11
  103. package/lib/lcevc/lcevc_dec.js +220 -0
  104. package/lib/media/adaptation_set.js +32 -14
  105. package/lib/media/adaptation_set_criteria.js +86 -16
  106. package/lib/media/closed_caption_parser.js +13 -0
  107. package/lib/media/content_workarounds.js +6 -0
  108. package/lib/media/drm_engine.js +8 -13
  109. package/lib/media/manifest_parser.js +8 -113
  110. package/lib/media/media_source_capabilities.js +10 -3
  111. package/lib/media/media_source_engine.js +286 -44
  112. package/lib/media/play_rate_controller.js +8 -38
  113. package/lib/media/presentation_timeline.js +7 -1
  114. package/lib/media/quality_observer.js +1 -1
  115. package/lib/media/segment_index.js +6 -6
  116. package/lib/media/segment_prefetch.js +92 -24
  117. package/lib/media/segment_reference.js +73 -7
  118. package/lib/media/segment_utils.js +343 -0
  119. package/lib/media/stall_detector.js +0 -3
  120. package/lib/media/streaming_engine.js +73 -38
  121. package/lib/mss/mss_parser.js +19 -2
  122. package/lib/net/networking_engine.js +67 -12
  123. package/lib/net/networking_utils.js +95 -0
  124. package/lib/offline/indexeddb/v1_storage_cell.js +3 -0
  125. package/lib/offline/indexeddb/v2_storage_cell.js +3 -0
  126. package/lib/offline/manifest_converter.js +3 -0
  127. package/lib/offline/offline_manifest_parser.js +10 -0
  128. package/lib/offline/storage.js +14 -7
  129. package/lib/player.js +1098 -1537
  130. package/lib/polyfill/mediasource.js +22 -1
  131. package/lib/text/cue.js +15 -0
  132. package/lib/text/mp4_ttml_parser.js +2 -2
  133. package/lib/text/srt_text_parser.js +2 -2
  134. package/lib/text/stub_text_displayer.js +51 -0
  135. package/lib/text/text_engine.js +3 -2
  136. package/lib/text/ttml_text_parser.js +45 -5
  137. package/lib/text/ui_text_displayer.js +8 -0
  138. package/lib/text/vtt_text_parser.js +40 -22
  139. package/lib/transmuxer/aac_transmuxer.js +1 -1
  140. package/lib/transmuxer/ac3_transmuxer.js +1 -1
  141. package/lib/transmuxer/ec3_transmuxer.js +1 -1
  142. package/lib/transmuxer/h264.js +5 -4
  143. package/lib/transmuxer/h265.js +863 -0
  144. package/lib/transmuxer/mp3_transmuxer.js +1 -1
  145. package/lib/transmuxer/mpeg_ts_transmuxer.js +4 -3
  146. package/lib/transmuxer/mss_transmuxer.js +1 -1
  147. package/lib/transmuxer/ts_transmuxer.js +187 -22
  148. package/lib/util/buffer_utils.js +26 -4
  149. package/lib/util/content_steering_manager.js +358 -0
  150. package/lib/util/error.js +30 -15
  151. package/lib/util/exp_golomb.js +30 -2
  152. package/lib/util/fairplay_utils.js +1 -1
  153. package/lib/util/fake_event.js +8 -1
  154. package/lib/util/id3_utils.js +50 -1
  155. package/lib/util/manifest_parser_utils.js +12 -8
  156. package/lib/util/mp4_generator.js +6 -8
  157. package/lib/util/mutex.js +59 -0
  158. package/lib/util/object_utils.js +1 -1
  159. package/lib/util/periods.js +156 -179
  160. package/lib/util/platform.js +44 -3
  161. package/lib/util/player_configuration.js +43 -6
  162. package/lib/util/state_history.js +6 -2
  163. package/lib/util/stream_utils.js +206 -283
  164. package/lib/util/ts_parser.js +335 -98
  165. package/lib/util/uint8array_utils.js +5 -1
  166. package/lib/util/xml_utils.js +5 -0
  167. package/maintained-branches.md +3 -2
  168. package/package.json +4 -6
  169. package/roadmap.md +25 -5
  170. package/shaka-player.uncompiled.js +2 -2
  171. package/support.html +0 -1
  172. package/test/abr/simple_abr_manager_unit.js +33 -33
  173. package/test/ads/ad_manager_unit.js +3 -2
  174. package/test/cast/cast_receiver_integration.js +50 -4
  175. package/test/cast/cast_utils_unit.js +2 -0
  176. package/test/cea/cea_decoder_unit.js +7 -0
  177. package/test/codec_switching/codec_switching_integration.js +182 -0
  178. package/test/dash/dash_parser_content_protection_unit.js +2 -0
  179. package/test/dash/dash_parser_integration.js +74 -0
  180. package/test/dash/dash_parser_live_unit.js +2 -19
  181. package/test/dash/dash_parser_manifest_unit.js +536 -2
  182. package/test/dash/dash_parser_segment_base_unit.js +2 -0
  183. package/test/dash/dash_parser_segment_list_unit.js +2 -0
  184. package/test/dash/dash_parser_segment_template_unit.js +2 -0
  185. package/test/dash/mpd_utils_unit.js +61 -30
  186. package/test/demo/demo_unit.js +0 -16
  187. package/test/hls/hls_live_unit.js +14 -3
  188. package/test/hls/hls_parser_unit.js +385 -33
  189. package/test/hls/manifest_text_parser_unit.js +32 -99
  190. package/test/media/adaptation_set_criteria_unit.js +284 -15
  191. package/test/media/adaptation_set_unit.js +2 -0
  192. package/test/media/content_workarounds_unit.js +1 -1
  193. package/test/media/drm_engine_unit.js +3 -3
  194. package/test/media/media_source_engine_unit.js +166 -2
  195. package/test/media/play_rate_controller_unit.js +0 -48
  196. package/test/media/segment_index_unit.js +5 -4
  197. package/test/media/segment_prefetch_unit.js +1 -1
  198. package/test/media/streaming_engine_unit.js +17 -17
  199. package/test/mss/mss_parser_unit.js +2 -0
  200. package/test/mss/mss_player_integration.js +3 -2
  201. package/test/net/networking_engine_unit.js +3 -3
  202. package/test/{media/manifest_parser_unit.js → net/networking_utils_unit.js} +2 -2
  203. package/test/offline/manifest_convert_unit.js +14 -0
  204. package/test/offline/offline_integration.js +2 -1
  205. package/test/offline/storage_integration.js +22 -13
  206. package/test/player_external.js +4 -2
  207. package/test/player_integration.js +15 -4
  208. package/test/player_load_graph_integration.js +47 -151
  209. package/test/player_src_equals_external.js +1 -0
  210. package/test/player_src_equals_integration.js +71 -4
  211. package/test/player_unit.js +182 -158
  212. package/test/test/assets/dash-aes-128/Fragments(video=0,format=mpd-time-csf) +0 -0
  213. package/test/test/assets/dash-aes-128/Fragments(video=20000000,format=mpd-time-csf) +0 -0
  214. package/test/test/assets/dash-aes-128/Fragments(video=40000000,format=mpd-time-csf) +0 -0
  215. package/test/test/assets/dash-aes-128/Fragments(video=60000000,format=mpd-time-csf) +0 -0
  216. package/test/test/assets/dash-aes-128/Fragments(video=i,format=mpd-time-csf) +0 -0
  217. package/test/test/assets/dash-aes-128/dash.mpd +18 -0
  218. package/test/test/assets/dash-aes-128/license +1 -0
  219. package/test/test/assets/dash-multi-codec/audio_en_2c_128k_aac.mp4 +0 -0
  220. package/test/test/assets/dash-multi-codec/audio_es_2c_64k_opus.webm +0 -0
  221. package/test/test/assets/dash-multi-codec/dash.mpd +32 -0
  222. package/test/test/assets/dash-multi-codec/video_144p_108k_h264.mp4 +0 -0
  223. package/test/test/assets/hls-ts-h265/0.ts +0 -0
  224. package/test/test/assets/hls-ts-h265/hevc.m3u8 +6 -0
  225. package/test/test/assets/hls-ts-h265/index.m3u8 +7 -0
  226. package/test/test/assets/hls-ts-muxed-aac-h265/0.ts +0 -0
  227. package/test/test/assets/hls-ts-muxed-aac-h265/1.ts +0 -0
  228. package/test/test/assets/hls-ts-muxed-aac-h265/media.m3u8 +9 -0
  229. package/test/test/assets/hls-ts-muxed-ac3-h264/media.m3u8 +24 -0
  230. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00000.ts +0 -0
  231. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00001.ts +0 -0
  232. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00002.ts +0 -0
  233. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00003.ts +0 -0
  234. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00004.ts +0 -0
  235. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00005.ts +0 -0
  236. package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0000.ts +0 -0
  237. package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0001.ts +0 -0
  238. package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0002.ts +0 -0
  239. package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0003.ts +0 -0
  240. package/test/test/assets/hls-ts-muxed-ec3-h264/prog_index.m3u8 +14 -0
  241. package/test/test/assets/hls-ts-muxed-mp3-h264/index.m3u8 +23 -0
  242. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-1-v1-a1.ts +0 -0
  243. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-2-v1-a1.ts +0 -0
  244. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-3-v1-a1.ts +0 -0
  245. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-4-v1-a1.ts +0 -0
  246. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-5-v1-a1.ts +0 -0
  247. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-6-v1-a1.ts +0 -0
  248. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-7-v1-a1.ts +0 -0
  249. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-8-v1-a1.ts +0 -0
  250. package/test/test/util/dash_parser_util.js +4 -0
  251. package/test/test/util/fake_ad_manager.js +20 -0
  252. package/test/test/util/fake_media_source_engine.js +13 -2
  253. package/test/test/util/fake_networking_engine.js +9 -1
  254. package/test/test/util/fake_segment_prefetch.js +3 -0
  255. package/test/test/util/manifest_generator.js +11 -3
  256. package/test/test/util/manifest_parser_util.js +14 -2
  257. package/test/test/util/mss_parser_util.js +4 -0
  258. package/test/test/util/offline_utils.js +2 -0
  259. package/test/test/util/simple_fakes.js +2 -2
  260. package/test/test/util/streaming_engine_util.js +10 -4
  261. package/test/test/util/test_scheme.js +6 -0
  262. package/test/test/util/ui_utils.js +4 -3
  263. package/test/text/mp4_ttml_parser_unit.js +4 -4
  264. package/test/text/srt_text_parser_unit.js +1 -1
  265. package/test/text/text_displayer_layout_unit.js +1 -1
  266. package/test/text/text_engine_unit.js +6 -0
  267. package/test/text/ttml_text_parser_unit.js +85 -2
  268. package/test/text/vtt_text_parser_unit.js +103 -31
  269. package/test/transmuxer/transmuxer_engine_integration.js +9 -0
  270. package/test/transmuxer/transmuxer_integration.js +150 -3
  271. package/test/ui/ad_ui_unit.js +2 -2
  272. package/test/ui/ui_customization_unit.js +17 -16
  273. package/test/ui/ui_integration.js +30 -20
  274. package/test/ui/ui_unit.js +28 -29
  275. package/test/util/buffer_utils_unit.js +1 -1
  276. package/test/util/content_steering_manager_unit.js +427 -0
  277. package/test/util/id3_utils_unit.js +52 -0
  278. package/test/util/stream_utils_unit.js +207 -169
  279. package/test/util/ts_parser_unit.js +3 -3
  280. package/third_party/closure-uri/uri.js +13 -1
  281. package/ui/audio_language_selection.js +9 -2
  282. package/ui/controls.js +125 -0
  283. package/ui/externs/ui.js +24 -2
  284. package/ui/language_utils.js +43 -8
  285. package/ui/less/range_elements.less +33 -0
  286. package/ui/locales/en.json +1 -0
  287. package/ui/locales/es-419.json +1 -0
  288. package/ui/locales/es.json +1 -0
  289. package/ui/locales/source.json +4 -0
  290. package/ui/localization.js +10 -0
  291. package/ui/pip_button.js +22 -120
  292. package/ui/remote_button.js +203 -0
  293. package/ui/resolution_selection.js +47 -10
  294. package/ui/seek_bar.js +296 -3
  295. package/ui/text_selection.js +2 -1
  296. package/ui/ui.js +11 -4
  297. package/demo/common/message_ids.js +0 -309
  298. package/demo/locales/en.json +0 -288
  299. package/demo/locales/source.json +0 -1146
  300. package/externs/mux.js +0 -69
  301. package/lib/lcevc/lcevc_dil.js +0 -152
  302. package/lib/routing/node.js +0 -23
  303. package/lib/routing/payload.js +0 -43
  304. package/lib/routing/walker.js +0 -587
  305. package/lib/transmuxer/muxjs_transmuxer.js +0 -242
  306. package/test/routing/walker_unit.js +0 -504
  307. package/test/transmuxer/muxjs_transmuxer_integration.js +0 -177
@@ -6,7 +6,6 @@
6
6
 
7
7
  goog.provide('shaka.media.PlayRateController');
8
8
 
9
- goog.require('goog.asserts');
10
9
  goog.require('shaka.log');
11
10
  goog.require('shaka.util.IReleasable');
12
11
  goog.require('shaka.util.Timer');
@@ -17,8 +16,6 @@ goog.require('shaka.util.Timer');
17
16
  * the playback rate on the media element can change outside of the controller,
18
17
  * the playback controller will need to be updated to stay in-sync.
19
18
  *
20
- * TODO: Try not to manage buffering above the browser with playbackRate=0.
21
- *
22
19
  * @implements {shaka.util.IReleasable}
23
20
  * @final
24
21
  */
@@ -30,9 +27,6 @@ shaka.media.PlayRateController = class {
30
27
  /** @private {?shaka.media.PlayRateController.Harness} */
31
28
  this.harness_ = harness;
32
29
 
33
- /** @private {boolean} */
34
- this.isBuffering_ = false;
35
-
36
30
  /** @private {number} */
37
31
  this.rate_ = this.harness_.getRate();
38
32
 
@@ -56,25 +50,15 @@ shaka.media.PlayRateController = class {
56
50
  }
57
51
 
58
52
  /**
59
- * Sets the buffering flag, which controls the effective playback rate.
60
- *
61
- * @param {boolean} isBuffering If true, forces playback rate to 0 internally.
62
- */
63
- setBuffering(isBuffering) {
64
- this.isBuffering_ = isBuffering;
65
- this.apply_();
66
- }
67
-
68
- /**
69
- * Set the playback rate. This rate will only be used as provided when the
70
- * player is not buffering. You should never set the rate to 0.
53
+ * Set the playback rate.
71
54
  *
72
55
  * @param {number} rate
73
56
  */
74
57
  set(rate) {
75
- goog.asserts.assert(rate != 0, 'Should never set rate of 0 explicitly!');
76
- this.rate_ = rate;
77
- this.apply_();
58
+ if (this.rate_ != rate) {
59
+ this.rate_ = rate;
60
+ this.apply_();
61
+ }
78
62
  }
79
63
 
80
64
  /**
@@ -108,14 +92,11 @@ shaka.media.PlayRateController = class {
108
92
  // Always stop the timer. We may not start it again.
109
93
  this.timer_.stop();
110
94
 
111
- /** @type {number} */
112
- const rate = this.calculateCurrentRate_();
95
+ shaka.log.v1('Changing effective playback rate to', this.rate_);
113
96
 
114
- shaka.log.v1('Changing effective playback rate to', rate);
115
-
116
- if (rate >= 0) {
97
+ if (this.rate_ >= 0) {
117
98
  try {
118
- this.applyRate_(rate);
99
+ this.applyRate_(this.rate_);
119
100
  return;
120
101
  } catch (e) {
121
102
  // Fall through to the next clause.
@@ -135,17 +116,6 @@ shaka.media.PlayRateController = class {
135
116
  this.applyRate_(0);
136
117
  }
137
118
 
138
- /**
139
- * Calculate the rate that the controller wants the media element to have
140
- * based on the current state of the controller.
141
- *
142
- * @return {number}
143
- * @private
144
- */
145
- calculateCurrentRate_() {
146
- return this.isBuffering_ ? 0 : this.rate_;
147
- }
148
-
149
119
  /**
150
120
  * If the new rate is different than the media element's playback rate, this
151
121
  * will change the playback rate. If the rate does not need to change, it will
@@ -619,7 +619,9 @@ shaka.media.PresentationTimeline = class {
619
619
  * @typedef {{
620
620
  * start: number,
621
621
  * unscaledStart: number,
622
- * end: number
622
+ * end: number,
623
+ * partialSegments: number,
624
+ * segmentPosition: number
623
625
  * }}
624
626
  *
625
627
  * @description
@@ -631,6 +633,10 @@ shaka.media.PresentationTimeline = class {
631
633
  * The start time of the range in representation timescale units.
632
634
  * @property {number} end
633
635
  * The end time (exclusive) of the range.
636
+ * @property {number} partialSegments
637
+ * The number of partial segments
638
+ * @property {number} segmentPosition
639
+ * The segment position of the timeline entry as it appears in the manifest
634
640
  *
635
641
  * @export
636
642
  */
@@ -261,7 +261,7 @@ shaka.media.QualityObserver.QualityChangePosition;
261
261
  *
262
262
  * @description
263
263
  * Contains media quality information for a specific content type
264
- * e.g video or audio.
264
+ * e.g. video or audio.
265
265
  *
266
266
  * @property {!Array.<shaka.media.QualityObserver.QualityChangePosition>}
267
267
  * qualityChangePositions
@@ -379,7 +379,7 @@ shaka.media.SegmentIndex = class {
379
379
  lastReference.tileDuration,
380
380
  lastReference.syncTime,
381
381
  lastReference.status,
382
- lastReference.hlsAes128Key,
382
+ lastReference.aes128Key,
383
383
  );
384
384
  this.references[this.references.length - 1].discontinuitySequence =
385
385
  lastReference.discontinuitySequence;
@@ -582,7 +582,7 @@ shaka.media.SegmentIterator = class {
582
582
  // new references in merge(), the pointers may not make sense any more.
583
583
  // This adjusts the invalid pointer values to point to the next newly added
584
584
  // segment or partial segment.
585
- if (ref && ref.hasPartialSegments() && ref.getUris().length &&
585
+ if (ref && ref.hasPartialSegments() && ref.hasAllPartialSegments() &&
586
586
  this.currentPartialPosition_ >= ref.partialReferences.length) {
587
587
  this.currentPosition_++;
588
588
  this.currentPartialPosition_ = 0;
@@ -609,12 +609,12 @@ shaka.media.SegmentIterator = class {
609
609
  // If the regular segment contains partial segments, move to the next
610
610
  // partial SegmentReference.
611
611
  this.currentPartialPosition_++;
612
- // If the current regular segment has been published completely (has a
613
- // valid Uri), and we've reached the end of its partial segments list,
614
- // move to the next regular segment.
612
+ // If the current regular segment has been published completely, and
613
+ // we've reached the end of its partial segments list, move to the next
614
+ // regular segment.
615
615
  // If the Partial Segments list is still on the fly, do not move to
616
616
  // the next regular segment.
617
- if (ref.getUris().length &&
617
+ if (ref.hasAllPartialSegments() &&
618
618
  this.currentPartialPosition_ == ref.partialReferences.length) {
619
619
  this.currentPosition_++;
620
620
  this.currentPartialPosition_ = 0;
@@ -4,12 +4,15 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
+ goog.provide('shaka.media.SegmentPrefetch');
8
+
7
9
  goog.require('goog.asserts');
8
- goog.require('shaka.net.NetworkingEngine');
10
+ goog.require('shaka.log');
9
11
  goog.require('shaka.media.InitSegmentReference');
10
12
  goog.require('shaka.media.SegmentReference');
11
- goog.provide('shaka.media.SegmentPrefetch');
12
- goog.require('shaka.log');
13
+ goog.require('shaka.net.NetworkingEngine');
14
+ goog.require('shaka.util.Uint8ArrayUtils');
15
+
13
16
 
14
17
  /**
15
18
  * @summary
@@ -37,8 +40,9 @@ shaka.media.SegmentPrefetch = class {
37
40
  this.fetchDispatcher_ = fetchDispatcher;
38
41
 
39
42
  /**
40
- * @private {!Map.<shaka.media.SegmentReference,
41
- * !shaka.media.SegmentPrefetchOperation>}
43
+ * @private {!Map.<
44
+ * !(shaka.media.SegmentReference|shaka.media.InitSegmentReference),
45
+ * !shaka.media.SegmentPrefetchOperation>}
42
46
  */
43
47
  this.segmentPrefetchMap_ = new Map();
44
48
  }
@@ -47,9 +51,10 @@ shaka.media.SegmentPrefetch = class {
47
51
  * Fetch next segments ahead of current segment.
48
52
  *
49
53
  * @param {(!shaka.media.SegmentReference)} startReference
54
+ * @param {boolean=} skipFirst
50
55
  * @public
51
56
  */
52
- prefetchSegments(startReference) {
57
+ prefetchSegments(startReference, skipFirst = false) {
53
58
  goog.asserts.assert(this.prefetchLimit_ > 0,
54
59
  'SegmentPrefetch can not be used when prefetchLimit <= 0.');
55
60
 
@@ -65,6 +70,14 @@ shaka.media.SegmentPrefetch = class {
65
70
  return;
66
71
  }
67
72
  let reference = startReference;
73
+ if (skipFirst) {
74
+ reference = iterator.next().value;
75
+ if (reference &&
76
+ reference.startTime == startReference.startTime &&
77
+ reference.endTime == startReference.endTime) {
78
+ reference = null;
79
+ }
80
+ }
68
81
  while (this.segmentPrefetchMap_.size < this.prefetchLimit_ &&
69
82
  reference != null) {
70
83
  // By default doesn't prefech preload partial segments when using
@@ -88,9 +101,38 @@ shaka.media.SegmentPrefetch = class {
88
101
  }
89
102
  }
90
103
 
104
+ /**
105
+ * Fetch init segment.
106
+ *
107
+ * @param {!shaka.media.InitSegmentReference} initSegmentReference
108
+ * @public
109
+ */
110
+ prefetchInitSegment(initSegmentReference) {
111
+ goog.asserts.assert(this.prefetchLimit_ > 0,
112
+ 'SegmentPrefetch can not be used when prefetchLimit <= 0.');
113
+
114
+ const logPrefix = shaka.media.SegmentPrefetch.logPrefix_(this.stream_);
115
+ if (!this.stream_.segmentIndex) {
116
+ shaka.log.info(logPrefix, 'missing segmentIndex');
117
+ return;
118
+ }
119
+
120
+ if (this.segmentPrefetchMap_.size < this.prefetchLimit_) {
121
+ if (!this.segmentPrefetchMap_.has(initSegmentReference)) {
122
+ const segmentPrefetchOperation =
123
+ new shaka.media.SegmentPrefetchOperation(this.fetchDispatcher_);
124
+ segmentPrefetchOperation.dispatchFetch(
125
+ initSegmentReference, this.stream_);
126
+ this.segmentPrefetchMap_.set(
127
+ initSegmentReference, segmentPrefetchOperation);
128
+ }
129
+ }
130
+ }
131
+
91
132
  /**
92
133
  * Get the result of prefetched segment if already exists.
93
- * @param {(!shaka.media.SegmentReference)} reference
134
+ * @param {!(shaka.media.SegmentReference|shaka.media.InitSegmentReference)}
135
+ * reference
94
136
  * @param {?function(BufferSource):!Promise=} streamDataCallback
95
137
  * @return {?shaka.net.NetworkingEngine.PendingRequest} op
96
138
  * @public
@@ -98,8 +140,6 @@ shaka.media.SegmentPrefetch = class {
98
140
  getPrefetchedSegment(reference, streamDataCallback) {
99
141
  goog.asserts.assert(this.prefetchLimit_ > 0,
100
142
  'SegmentPrefetch can not be used when prefetchLimit <= 0.');
101
- goog.asserts.assert(reference instanceof shaka.media.SegmentReference,
102
- 'getPrefetchedSegment is only used for shaka.media.SegmentReference.');
103
143
 
104
144
  const logPrefix = shaka.media.SegmentPrefetch.logPrefix_(this.stream_);
105
145
 
@@ -109,16 +149,30 @@ shaka.media.SegmentPrefetch = class {
109
149
  segmentPrefetchOperation.setStreamDataCallback(streamDataCallback);
110
150
  }
111
151
  this.segmentPrefetchMap_.delete(reference);
112
- shaka.log.debug(
113
- logPrefix,
114
- 'reused prefetched segment at time:', reference.startTime,
115
- 'mapSize', this.segmentPrefetchMap_.size);
152
+ if (reference instanceof shaka.media.SegmentReference) {
153
+ shaka.log.debug(
154
+ logPrefix,
155
+ 'reused prefetched segment at time:', reference.startTime,
156
+ 'mapSize', this.segmentPrefetchMap_.size);
157
+ } else {
158
+ shaka.log.debug(
159
+ logPrefix,
160
+ 'reused prefetched init segment at time, mapSize',
161
+ this.segmentPrefetchMap_.size);
162
+ }
116
163
  return segmentPrefetchOperation.getOperation();
117
164
  } else {
118
- shaka.log.debug(
119
- logPrefix,
120
- 'missed segment at time:', reference.startTime,
121
- 'mapSize', this.segmentPrefetchMap_.size);
165
+ if (reference instanceof shaka.media.SegmentReference) {
166
+ shaka.log.debug(
167
+ logPrefix,
168
+ 'reused prefetched segment at time:', reference.startTime,
169
+ 'mapSize', this.segmentPrefetchMap_.size);
170
+ } else {
171
+ shaka.log.debug(
172
+ logPrefix,
173
+ 'reused prefetched init segment at time, mapSize',
174
+ this.segmentPrefetchMap_.size);
175
+ }
122
176
  return null;
123
177
  }
124
178
  }
@@ -174,7 +228,8 @@ shaka.media.SegmentPrefetch = class {
174
228
 
175
229
  /**
176
230
  * Remove a segment from prefetch map and abort it.
177
- * @param {(!shaka.media.SegmentReference)} reference
231
+ * @param {!(shaka.media.SegmentReference|shaka.media.InitSegmentReference)}
232
+ * reference
178
233
  * @private
179
234
  */
180
235
  abortPrefetchedSegment_(reference) {
@@ -183,9 +238,13 @@ shaka.media.SegmentPrefetch = class {
183
238
  this.segmentPrefetchMap_.delete(reference);
184
239
  if (segmentPrefetchOperation) {
185
240
  segmentPrefetchOperation.abort();
186
- shaka.log.info(
187
- logPrefix,
188
- 'pop and abort prefetched segment at time:', reference.startTime);
241
+ if (reference instanceof shaka.media.SegmentReference) {
242
+ shaka.log.info(
243
+ logPrefix,
244
+ 'pop and abort prefetched segment at time:', reference.startTime);
245
+ } else {
246
+ shaka.log.info(logPrefix, 'pop and abort prefetched init segment');
247
+ }
189
248
  }
190
249
  }
191
250
 
@@ -221,16 +280,25 @@ shaka.media.SegmentPrefetchOperation = class {
221
280
  /**
222
281
  * Fetch a segments
223
282
  *
224
- * @param {!shaka.media.SegmentReference}
225
- * reference
283
+ * @param {!(shaka.media.SegmentReference|shaka.media.InitSegmentReference)}
284
+ * reference
226
285
  * @param {!shaka.extern.Stream} stream
227
286
  * @public
228
287
  */
229
288
  dispatchFetch(reference, stream) {
289
+ // We need to store the data, because streamDataCallback_ might not be
290
+ // available when you start getting the first data.
291
+ let buffered = new Uint8Array(0);
230
292
  this.operation_ = this.fetchDispatcher_(
231
293
  reference, stream, async (data) => {
294
+ if (buffered.byteLength > 0) {
295
+ buffered = shaka.util.Uint8ArrayUtils.concat(buffered, data);
296
+ } else {
297
+ buffered = data;
298
+ }
232
299
  if (this.streamDataCallback_) {
233
- await this.streamDataCallback_(data);
300
+ await this.streamDataCallback_(buffered);
301
+ buffered = new Uint8Array(0);
234
302
  }
235
303
  });
236
304
  }
@@ -32,7 +32,7 @@ shaka.media.InitSegmentReference = class {
32
32
  * the quality of the media associated with this init segment.
33
33
  * @param {(null|number)=} timescale
34
34
  * @param {(null|BufferSource)=} segmentData
35
- * @param {?shaka.extern.HlsAes128Key=} aes128Key
35
+ * @param {?shaka.extern.aes128Key=} aes128Key
36
36
  * The segment's AES-128-CBC full segment encryption key and iv.
37
37
  */
38
38
  constructor(uris, startByte, endByte, mediaQuality = null, timescale = null,
@@ -55,8 +55,8 @@ shaka.media.InitSegmentReference = class {
55
55
  /** @type {BufferSource|null} */
56
56
  this.segmentData = segmentData;
57
57
 
58
- /** @type {?shaka.extern.HlsAes128Key} */
59
- this.hlsAes128Key = aes128Key;
58
+ /** @type {?shaka.extern.aes128Key} */
59
+ this.aes128Key = aes128Key;
60
60
  }
61
61
 
62
62
  /**
@@ -196,15 +196,17 @@ shaka.media.SegmentReference = class {
196
196
  * @param {shaka.media.SegmentReference.Status=} status
197
197
  * The segment status is used to indicate that a segment does not exist or is
198
198
  * not available.
199
- * @param {?shaka.extern.HlsAes128Key=} hlsAes128Key
199
+ * @param {?shaka.extern.aes128Key=} aes128Key
200
200
  * The segment's AES-128-CBC full segment encryption key and iv.
201
+ * @param {boolean=} allPartialSegments
202
+ * Indicate if the segment has all partial segments
201
203
  */
202
204
  constructor(
203
205
  startTime, endTime, uris, startByte, endByte, initSegmentReference,
204
206
  timestampOffset, appendWindowStart, appendWindowEnd,
205
207
  partialReferences = [], tilesLayout = '', tileDuration = null,
206
208
  syncTime = null, status = shaka.media.SegmentReference.Status.AVAILABLE,
207
- hlsAes128Key = null) {
209
+ aes128Key = null, allPartialSegments = false) {
208
210
  // A preload hinted Partial Segment has the same startTime and endTime.
209
211
  goog.asserts.assert(startTime <= endTime,
210
212
  'startTime must be less than or equal to endTime');
@@ -276,14 +278,32 @@ shaka.media.SegmentReference = class {
276
278
  /** @type {boolean} */
277
279
  this.byterangeOptimization = false;
278
280
 
279
- /** @type {?shaka.extern.HlsAes128Key} */
280
- this.hlsAes128Key = hlsAes128Key;
281
+ /** @type {?shaka.extern.aes128Key} */
282
+ this.aes128Key = aes128Key;
281
283
 
282
284
  /** @type {?shaka.media.SegmentReference.ThumbnailSprite} */
283
285
  this.thumbnailSprite = null;
284
286
 
285
287
  /** @type {number} */
286
288
  this.discontinuitySequence = 0;
289
+
290
+ /** @type {boolean} */
291
+ this.allPartialSegments = allPartialSegments;
292
+
293
+ /** @type {boolean} */
294
+ this.partial = false;
295
+
296
+ /** @type {boolean} */
297
+ this.lastPartial = false;
298
+
299
+ for (const partial of this.partialReferences) {
300
+ partial.markAsPartial();
301
+ }
302
+ if (this.allPartialSegments && this.partialReferences.length) {
303
+ const lastPartial =
304
+ this.partialReferences[this.partialReferences.length - 1];
305
+ lastPartial.markAsLastPartial();
306
+ }
287
307
  }
288
308
 
289
309
  /**
@@ -359,6 +379,14 @@ shaka.media.SegmentReference = class {
359
379
  return this.partialReferences.length > 0;
360
380
  }
361
381
 
382
+ /**
383
+ * Returns true if it contains all partial SegmentReferences.
384
+ * @return {boolean}
385
+ */
386
+ hasAllPartialSegments() {
387
+ return this.allPartialSegments;
388
+ }
389
+
362
390
  /**
363
391
  * Returns the segment's tiles layout. Only defined in image segments.
364
392
  *
@@ -437,6 +465,44 @@ shaka.media.SegmentReference = class {
437
465
  return this.independent;
438
466
  }
439
467
 
468
+ /**
469
+ * Mark the reference as partial.
470
+ *
471
+ * @export
472
+ */
473
+ markAsPartial() {
474
+ this.partial = true;
475
+ }
476
+
477
+ /**
478
+ * Returns true if the segment is partial.
479
+ *
480
+ * @return {boolean}
481
+ * @export
482
+ */
483
+ isPartial() {
484
+ return this.partial;
485
+ }
486
+
487
+ /**
488
+ * Mark the reference as being the last part of the full segment
489
+ *
490
+ * @export
491
+ */
492
+ markAsLastPartial() {
493
+ this.lastPartial = true;
494
+ }
495
+
496
+ /**
497
+ * Returns true if reference as being the last part of the full segment.
498
+ *
499
+ * @return {boolean}
500
+ * @export
501
+ */
502
+ isLastPartial() {
503
+ return this.lastPartial;
504
+ }
505
+
440
506
  /**
441
507
  * Mark the reference as byterange optimization.
442
508
  *