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
@@ -46,18 +46,21 @@ goog.require('shaka.util.Timer');
46
46
  */
47
47
  shaka.net.NetworkingEngine = class extends shaka.util.FakeEventTarget {
48
48
  /**
49
- * @param {function(number, number)=} onProgressUpdated Called when a progress
50
- * event is triggered. Passed the duration, in milliseconds, that the
51
- * request took, and the number of bytes transferred.
49
+ * @param {function(number, number, boolean)=} onProgressUpdated Called when
50
+ * a progress event is triggered. Passed the duration, in milliseconds,
51
+ * that the request took, the number of bytes transferred, and the boolean
52
+ * of whether the switching is allowed.
52
53
  * @param {shaka.net.NetworkingEngine.OnHeadersReceived=} onHeadersReceived
53
54
  * Called when the headers are received for a download.
54
55
  * @param {shaka.net.NetworkingEngine.OnDownloadFailed=} onDownloadFailed
55
56
  * Called when a download fails, for any reason.
56
57
  * @param {shaka.net.NetworkingEngine.OnRequest=} onRequest
57
58
  * Called when a request is made
59
+ * @param {shaka.net.NetworkingEngine.OnRetry=} onRetry
60
+ * Called when a request retry is made
58
61
  */
59
62
  constructor(onProgressUpdated, onHeadersReceived, onDownloadFailed,
60
- onRequest) {
63
+ onRequest, onRetry) {
61
64
  super();
62
65
 
63
66
  /** @private {boolean} */
@@ -72,7 +75,7 @@ shaka.net.NetworkingEngine = class extends shaka.util.FakeEventTarget {
72
75
  /** @private {!Set.<shaka.extern.ResponseFilter>} */
73
76
  this.responseFilters_ = new Set();
74
77
 
75
- /** @private {?function(number, number)} */
78
+ /** @private {?function(number, number, boolean)} */
76
79
  this.onProgressUpdated_ = onProgressUpdated || null;
77
80
 
78
81
  /** @private {?shaka.net.NetworkingEngine.OnHeadersReceived} */
@@ -84,6 +87,9 @@ shaka.net.NetworkingEngine = class extends shaka.util.FakeEventTarget {
84
87
  /** @private {?shaka.net.NetworkingEngine.OnRequest} */
85
88
  this.onRequest_ = onRequest || null;
86
89
 
90
+ /** @private {?shaka.net.NetworkingEngine.OnRetry} */
91
+ this.onRetry_ = onRetry || null;
92
+
87
93
  /** @private {boolean} */
88
94
  this.forceHTTPS_ = false;
89
95
  }
@@ -295,7 +301,8 @@ shaka.net.NetworkingEngine = class extends shaka.util.FakeEventTarget {
295
301
  // Apply the registered filters to the request.
296
302
  const requestFilterOperation = this.filterRequest_(type, request, context);
297
303
  const requestOperation = requestFilterOperation.chain(
298
- () => this.makeRequestWithRetry_(type, request, numBytesRemainingObj));
304
+ () => this.makeRequestWithRetry_(type, request, context,
305
+ numBytesRemainingObj));
299
306
  const responseFilterOperation = requestOperation.chain(
300
307
  (responseAndGotProgress) =>
301
308
  this.filterResponse_(type, responseAndGotProgress, context));
@@ -322,7 +329,9 @@ shaka.net.NetworkingEngine = class extends shaka.util.FakeEventTarget {
322
329
  !response.fromCache &&
323
330
  request.method != 'HEAD' &&
324
331
  type == shaka.net.NetworkingEngine.RequestType.SEGMENT) {
325
- this.onProgressUpdated_(response.timeMs, response.data.byteLength);
332
+ const allowSwitch = this.allowSwitch_(context);
333
+ this.onProgressUpdated_(
334
+ response.timeMs, response.data.byteLength, allowSwitch);
326
335
  }
327
336
  return response;
328
337
  }, (e) => {
@@ -399,18 +408,19 @@ shaka.net.NetworkingEngine = class extends shaka.util.FakeEventTarget {
399
408
  /**
400
409
  * @param {shaka.net.NetworkingEngine.RequestType} type
401
410
  * @param {shaka.extern.Request} request
411
+ * @param {(shaka.extern.RequestContext|undefined)} context
402
412
  * @param {shaka.net.NetworkingEngine.NumBytesRemainingClass}
403
413
  * numBytesRemainingObj
404
414
  * @return {!shaka.extern.IAbortableOperation.<
405
415
  * shaka.net.NetworkingEngine.ResponseAndGotProgress>}
406
416
  * @private
407
417
  */
408
- makeRequestWithRetry_(type, request, numBytesRemainingObj) {
418
+ makeRequestWithRetry_(type, request, context, numBytesRemainingObj) {
409
419
  const backoff = new shaka.net.Backoff(
410
420
  request.retryParameters, /* autoReset= */ false);
411
421
  const index = 0;
412
422
  return this.send_(
413
- type, request, backoff, index, /* lastError= */ null,
423
+ type, request, context, backoff, index, /* lastError= */ null,
414
424
  numBytesRemainingObj);
415
425
  }
416
426
 
@@ -419,6 +429,7 @@ shaka.net.NetworkingEngine = class extends shaka.util.FakeEventTarget {
419
429
  *
420
430
  * @param {shaka.net.NetworkingEngine.RequestType} type
421
431
  * @param {shaka.extern.Request} request
432
+ * @param {(shaka.extern.RequestContext|undefined)} context
422
433
  * @param {!shaka.net.Backoff} backoff
423
434
  * @param {number} index
424
435
  * @param {?shaka.util.Error} lastError
@@ -428,11 +439,18 @@ shaka.net.NetworkingEngine = class extends shaka.util.FakeEventTarget {
428
439
  * shaka.net.NetworkingEngine.ResponseAndGotProgress>}
429
440
  * @private
430
441
  */
431
- send_(type, request, backoff, index, lastError, numBytesRemainingObj) {
442
+ send_(type, request, context, backoff, index, lastError,
443
+ numBytesRemainingObj) {
432
444
  if (this.forceHTTPS_) {
433
445
  request.uris[index] = request.uris[index].replace('http://', 'https://');
434
446
  }
435
447
 
448
+ if (index > 0 && this.onRetry_) {
449
+ const newUri = request.uris[index];
450
+ const oldUri = request.uris[index - 1];
451
+ this.onRetry_(type, context, newUri, oldUri);
452
+ }
453
+
436
454
  const uri = new goog.Uri(request.uris[index]);
437
455
  let scheme = uri.getScheme();
438
456
  // Whether it got a progress event.
@@ -501,7 +519,8 @@ shaka.net.NetworkingEngine = class extends shaka.util.FakeEventTarget {
501
519
  stallTimer.tickAfter(stallTimeoutMs / 1000);
502
520
  }
503
521
  if (this.onProgressUpdated_ && type == segment) {
504
- this.onProgressUpdated_(time, bytes);
522
+ const allowSwitch = this.allowSwitch_(context);
523
+ this.onProgressUpdated_(time, bytes, allowSwitch);
505
524
  gotProgress = true;
506
525
  numBytesRemainingObj.setBytes(numBytesRemaining);
507
526
  }
@@ -610,7 +629,8 @@ shaka.net.NetworkingEngine = class extends shaka.util.FakeEventTarget {
610
629
  // Move to the next URI.
611
630
  index = (index + 1) % request.uris.length;
612
631
  return this.send_(
613
- type, request, backoff, index, error, numBytesRemainingObj);
632
+ type, request, context, backoff, index, error,
633
+ numBytesRemainingObj);
614
634
  }
615
635
  }
616
636
 
@@ -670,6 +690,24 @@ shaka.net.NetworkingEngine = class extends shaka.util.FakeEventTarget {
670
690
  });
671
691
  }
672
692
 
693
+ /**
694
+ * @param {(shaka.extern.RequestContext|undefined)} context
695
+ * @return {boolean}
696
+ * @private
697
+ */
698
+ allowSwitch_(context) {
699
+ if (context) {
700
+ const segment = context.segment;
701
+ const stream = context.stream;
702
+ if (segment && stream && stream.fastSwitching) {
703
+ if (segment.isPartial() && !segment.isLastPartial()) {
704
+ return false;
705
+ }
706
+ }
707
+ }
708
+ return true;
709
+ }
710
+
673
711
  /**
674
712
  * This is here only for testability. We can't mock location in our tests on
675
713
  * all browsers, so instead we mock this.
@@ -769,6 +807,8 @@ shaka.net.NetworkingEngine.RequestType = {
769
807
  'TIMING': 4,
770
808
  'SERVER_CERTIFICATE': 5,
771
809
  'KEY': 6,
810
+ 'ADS': 7,
811
+ 'CONTENT_STEERING': 8,
772
812
  };
773
813
 
774
814
  /**
@@ -886,3 +926,18 @@ shaka.net.NetworkingEngine.OnDownloadFailed;
886
926
  * @export
887
927
  */
888
928
  shaka.net.NetworkingEngine.OnRequest;
929
+
930
+
931
+ /**
932
+ * @typedef {function(
933
+ * !shaka.net.NetworkingEngine.RequestType,
934
+ * (shaka.extern.RequestContext|undefined),
935
+ * string,
936
+ * string)}
937
+ *
938
+ * @description
939
+ * A callback function called on every request retry. The first string is the
940
+ * new URI and the second string is the old URI.
941
+ * @export
942
+ */
943
+ shaka.net.NetworkingEngine.OnRetry;
@@ -0,0 +1,95 @@
1
+ /*! @license
2
+ * Shaka Player
3
+ * Copyright 2016 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ goog.provide('shaka.net.NetworkingUtils');
8
+
9
+ goog.require('goog.Uri');
10
+ goog.require('shaka.net.NetworkingEngine');
11
+
12
+
13
+ /**
14
+ * @summary Networking utility functions.
15
+ */
16
+ shaka.net.NetworkingUtils = class {
17
+ /**
18
+ * @param {string} uri
19
+ * @param {!shaka.net.NetworkingEngine} netEngine
20
+ * @param {shaka.extern.RetryParameters} retryParams
21
+ * @return {!Promise.<string>}
22
+ */
23
+ static async getMimeType(uri, netEngine, retryParams) {
24
+ const extension = shaka.net.NetworkingUtils.getExtension_(uri);
25
+ let mimeType =
26
+ shaka.net.NetworkingUtils.EXTENSIONS_TO_MIME_TYPES_[extension];
27
+ if (mimeType) {
28
+ return mimeType;
29
+ }
30
+ const type = shaka.net.NetworkingEngine.RequestType.MANIFEST;
31
+
32
+ const request = shaka.net.NetworkingEngine.makeRequest([uri], retryParams);
33
+ request.method = 'HEAD';
34
+
35
+ const response = await netEngine.request(type, request).promise;
36
+
37
+ // https://bit.ly/2K9s9kf says this header should always be available,
38
+ // but just to be safe:
39
+ mimeType = response.headers['content-type'];
40
+ return mimeType ? mimeType.toLowerCase().split(';').shift() : '';
41
+ }
42
+
43
+
44
+ /**
45
+ * @param {string} uri
46
+ * @return {string}
47
+ * @private
48
+ */
49
+ static getExtension_(uri) {
50
+ const uriObj = new goog.Uri(uri);
51
+ const uriPieces = uriObj.getPath().split('/');
52
+ const uriFilename = uriPieces.pop();
53
+ const filenamePieces = uriFilename.split('.');
54
+
55
+ // Only one piece means there is no extension.
56
+ if (filenamePieces.length == 1) {
57
+ return '';
58
+ }
59
+
60
+ return filenamePieces.pop().toLowerCase();
61
+ }
62
+ };
63
+
64
+ /**
65
+ * @const {!Object.<string, string>}
66
+ * @private
67
+ */
68
+ shaka.net.NetworkingUtils.EXTENSIONS_TO_MIME_TYPES_ = {
69
+ 'mp4': 'video/mp4',
70
+ 'm4v': 'video/mp4',
71
+ 'm4a': 'audio/mp4',
72
+ 'webm': 'video/webm',
73
+ 'weba': 'audio/webm',
74
+ 'mkv': 'video/webm', // Chromium browsers supports it.
75
+ 'ts': 'video/mp2t',
76
+ 'ogv': 'video/ogg',
77
+ 'ogg': 'audio/ogg',
78
+ 'mpg': 'video/mpeg',
79
+ 'mpeg': 'video/mpeg',
80
+ 'm3u8': 'application/x-mpegurl',
81
+ 'mpd': 'application/dash+xml',
82
+ 'ism': 'application/vnd.ms-sstr+xml',
83
+ 'mp3': 'audio/mpeg',
84
+ 'aac': 'audio/aac',
85
+ 'flac': 'audio/flac',
86
+ 'wav': 'audio/wav',
87
+ 'sbv': 'text/x-subviewer',
88
+ 'srt': 'text/srt',
89
+ 'vtt': 'text/vtt',
90
+ 'webvtt': 'text/vtt',
91
+ 'ttml': 'application/ttml+xml',
92
+ 'lrc': 'application/x-subtitle-lrc',
93
+ 'ssa': 'text/x-ssa',
94
+ 'ass': 'text/x-ssa',
95
+ };
@@ -150,6 +150,7 @@ shaka.offline.indexeddb.V1StorageCell = class
150
150
  return {
151
151
  id: old.id,
152
152
  originalId: null,
153
+ groupId: null,
153
154
  primary: old.primary,
154
155
  type: old.contentType,
155
156
  mimeType: old.mimeType,
@@ -157,6 +158,7 @@ shaka.offline.indexeddb.V1StorageCell = class
157
158
  frameRate: old.frameRate,
158
159
  pixelAspectRatio: undefined,
159
160
  hdr: undefined,
161
+ videoLayout: undefined,
160
162
  kind: old.kind,
161
163
  language: old.language,
162
164
  originalLanguage: old.language || null,
@@ -178,6 +180,7 @@ shaka.offline.indexeddb.V1StorageCell = class
178
180
  closedCaptions: null,
179
181
  tilesLayout: undefined,
180
182
  external: false,
183
+ fastSwitching: false,
181
184
  };
182
185
  }
183
186
 
@@ -99,6 +99,7 @@ shaka.offline.indexeddb.V2StorageCell = class
99
99
  return {
100
100
  id: old.id,
101
101
  originalId: old.originalId,
102
+ groupId: null,
102
103
  primary: old.primary,
103
104
  type: old.contentType,
104
105
  mimeType: old.mimeType,
@@ -106,6 +107,7 @@ shaka.offline.indexeddb.V2StorageCell = class
106
107
  frameRate: old.frameRate,
107
108
  pixelAspectRatio: old.pixelAspectRatio,
108
109
  hdr: undefined,
110
+ videoLayout: undefined,
109
111
  kind: old.kind,
110
112
  language: old.language,
111
113
  originalLanguage: old.language || null,
@@ -127,6 +129,7 @@ shaka.offline.indexeddb.V2StorageCell = class
127
129
  closedCaptions: null,
128
130
  tilesLayout: undefined,
129
131
  external: false,
132
+ fastSwitching: false,
130
133
  };
131
134
  }
132
135
 
@@ -180,6 +180,7 @@ shaka.offline.ManifestConverter = class {
180
180
  const stream = {
181
181
  id: streamDB.id,
182
182
  originalId: streamDB.originalId,
183
+ groupId: streamDB.groupId,
183
184
  createSegmentIndex: () => Promise.resolve(),
184
185
  segmentIndex,
185
186
  mimeType: streamDB.mimeType,
@@ -189,6 +190,7 @@ shaka.offline.ManifestConverter = class {
189
190
  frameRate: streamDB.frameRate,
190
191
  pixelAspectRatio: streamDB.pixelAspectRatio,
191
192
  hdr: streamDB.hdr,
193
+ videoLayout: streamDB.videoLayout,
192
194
  kind: streamDB.kind,
193
195
  encrypted: streamDB.encrypted,
194
196
  drmInfos: [],
@@ -209,6 +211,7 @@ shaka.offline.ManifestConverter = class {
209
211
  tilesLayout: streamDB.tilesLayout,
210
212
  accessibilityPurpose: null,
211
213
  external: streamDB.external,
214
+ fastSwitching: streamDB.fastSwitching,
212
215
  };
213
216
 
214
217
  return stream;
@@ -112,6 +112,16 @@ shaka.offline.OfflineManifestParser = class {
112
112
  await muxer.destroy();
113
113
  }
114
114
  }
115
+
116
+ /** @override */
117
+ onInitialVariantChosen(variant) {
118
+ // No-op
119
+ }
120
+
121
+ /** @override */
122
+ banLocation(uri) {
123
+ // No-op
124
+ }
115
125
  };
116
126
 
117
127
 
@@ -12,6 +12,7 @@ goog.require('shaka.log');
12
12
  goog.require('shaka.media.DrmEngine');
13
13
  goog.require('shaka.media.ManifestParser');
14
14
  goog.require('shaka.net.NetworkingEngine');
15
+ goog.require('shaka.net.NetworkingUtils');
15
16
  goog.require('shaka.offline.DownloadInfo');
16
17
  goog.require('shaka.offline.DownloadManager');
17
18
  goog.require('shaka.offline.OfflineUri');
@@ -271,10 +272,13 @@ shaka.offline.Storage = class {
271
272
  goog.asserts.assert(
272
273
  this.networkingEngine_, 'Should not call |store| after |destroy|');
273
274
 
274
- const factory = await shaka.media.ManifestParser.getFactory(
275
+ if (!mimeType) {
276
+ mimeType = await shaka.net.NetworkingUtils.getMimeType(
277
+ uri, this.networkingEngine_, config.manifest.retryParameters);
278
+ }
279
+
280
+ const factory = shaka.media.ManifestParser.getFactory(
275
281
  uri,
276
- this.networkingEngine_,
277
- config.manifest.retryParameters,
278
282
  mimeType || null);
279
283
 
280
284
  return factory();
@@ -656,20 +660,19 @@ shaka.offline.Storage = class {
656
660
  // Filter the manifest based on what we know MediaCapabilities will be able
657
661
  // to play later (no point storing something we can't play).
658
662
  await shaka.util.StreamUtils.filterManifestByMediaCapabilities(
659
- manifest, config.offline.usePersistentLicense);
663
+ drmEngine, manifest, config.offline.usePersistentLicense);
660
664
 
661
665
  // Gather all tracks.
662
666
  const allTracks = [];
663
667
 
664
668
  // Choose the codec that has the lowest average bandwidth.
665
- const preferredAudioChannelCount = config.preferredAudioChannelCount;
666
669
  const preferredDecodingAttributes = config.preferredDecodingAttributes;
667
670
  const preferredVideoCodecs = config.preferredVideoCodecs;
668
671
  const preferredAudioCodecs = config.preferredAudioCodecs;
669
672
 
670
673
  shaka.util.StreamUtils.chooseCodecsAndFilterManifest(
671
674
  manifest, preferredVideoCodecs, preferredAudioCodecs,
672
- preferredAudioChannelCount, preferredDecodingAttributes);
675
+ preferredDecodingAttributes);
673
676
 
674
677
  for (const variant of manifest.variants) {
675
678
  goog.asserts.assert(
@@ -1168,6 +1171,8 @@ shaka.offline.Storage = class {
1168
1171
  enableLowLatencyMode: () => {},
1169
1172
  updateDuration: () => {},
1170
1173
  newDrmInfo: (stream) => {},
1174
+ onManifestUpdated: () => {},
1175
+ getBandwidthEstimate: () => config.abr.defaultBandwidthEstimate,
1171
1176
  };
1172
1177
 
1173
1178
  parser.configure(config.manifest);
@@ -1228,7 +1233,6 @@ shaka.offline.Storage = class {
1228
1233
  drmEngine.configure(config.drm);
1229
1234
  await drmEngine.initForStorage(
1230
1235
  manifest.variants, config.offline.usePersistentLicense);
1231
- await drmEngine.setServerCertificate();
1232
1236
  await drmEngine.createOrLoad();
1233
1237
 
1234
1238
  return drmEngine;
@@ -1299,6 +1303,7 @@ shaka.offline.Storage = class {
1299
1303
  const streamDb = {
1300
1304
  id: stream.id,
1301
1305
  originalId: stream.originalId,
1306
+ groupId: stream.groupId,
1302
1307
  primary: stream.primary,
1303
1308
  type: stream.type,
1304
1309
  mimeType: stream.mimeType,
@@ -1306,6 +1311,7 @@ shaka.offline.Storage = class {
1306
1311
  frameRate: stream.frameRate,
1307
1312
  pixelAspectRatio: stream.pixelAspectRatio,
1308
1313
  hdr: stream.hdr,
1314
+ videoLayout: stream.videoLayout,
1309
1315
  kind: stream.kind,
1310
1316
  language: stream.language,
1311
1317
  originalLanguage: stream.originalLanguage,
@@ -1324,6 +1330,7 @@ shaka.offline.Storage = class {
1324
1330
  closedCaptions: stream.closedCaptions,
1325
1331
  tilesLayout: stream.tilesLayout,
1326
1332
  external: stream.external,
1333
+ fastSwitching: stream.fastSwitching,
1327
1334
  };
1328
1335
 
1329
1336
  const startTime =