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
@@ -90,6 +90,8 @@ describe('HlsParser', () => {
90
90
  enableLowLatencyMode: () => {},
91
91
  updateDuration: () => {},
92
92
  newDrmInfo: shaka.test.Util.spyFunc(newDrmInfoSpy),
93
+ onManifestUpdated: () => {},
94
+ getBandwidthEstimate: () => 1e6,
93
95
  };
94
96
 
95
97
  parser = new shaka.hls.HlsParser();
@@ -922,7 +924,7 @@ describe('HlsParser', () => {
922
924
  '#EXT-X-STREAM-INF:BANDWIDTH=200,',
923
925
  'RESOLUTION=960x540,FRAME-RATE=60,AUDIO="aud1"\n',
924
926
  'video\n',
925
- '#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aud1",NAME="audio"\n',
927
+ '#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aud1",LANGUAGE="eng",NAME="audio"\n',
926
928
  ].join('');
927
929
 
928
930
  const media = [
@@ -939,6 +941,9 @@ describe('HlsParser', () => {
939
941
  manifest.addPartialVariant((variant) => {
940
942
  variant.addPartialStream(ContentType.VIDEO, (stream) => {
941
943
  stream.mime('video/mp4', /** @type {?} */ (jasmine.any(String)));
944
+ stream.language = 'en';
945
+ stream.originalLanguage = 'eng';
946
+ stream.label = 'audio';
942
947
  });
943
948
  });
944
949
  manifest.sequenceMode = sequenceMode;
@@ -1486,6 +1491,72 @@ describe('HlsParser', () => {
1486
1491
  expect(actual).toEqual(manifest);
1487
1492
  });
1488
1493
 
1494
+ it('parses manifest with video layout metadata', async () => {
1495
+ const master = [
1496
+ '#EXTM3U\n',
1497
+ '#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aud1",LANGUAGE="eng",',
1498
+ 'URI="audio"\n',
1499
+ '#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="sub1",LANGUAGE="eng",',
1500
+ 'FORCED=YES,URI="text"\n',
1501
+ '#EXT-X-STREAM-INF:BANDWIDTH=200,CODECS="avc1,mp4a",',
1502
+ 'REQ-VIDEO-LAYOUT=CH-STEREO,RESOLUTION=960x540,FRAME-RATE=60,',
1503
+ 'AUDIO="aud1",SUBTITLES="sub1"\n',
1504
+ 'video\n',
1505
+ ].join('');
1506
+
1507
+ const media = [
1508
+ '#EXTM3U\n',
1509
+ '#EXT-X-PLAYLIST-TYPE:VOD\n',
1510
+ '#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
1511
+ '#EXTINF:5,\n',
1512
+ '#EXT-X-BYTERANGE:121090@616\n',
1513
+ 'main.mp4',
1514
+ ].join('');
1515
+
1516
+ const textMedia = [
1517
+ '#EXTM3U\n',
1518
+ '#EXT-X-PLAYLIST-TYPE:VOD\n',
1519
+ '#EXTINF:5,\n',
1520
+ '#EXT-X-BYTERANGE:121090@616\n',
1521
+ 'main.vtt',
1522
+ ].join('');
1523
+
1524
+ const manifest = shaka.test.ManifestGenerator.generate((manifest) => {
1525
+ manifest.anyTimeline();
1526
+ manifest.addPartialVariant((variant) => {
1527
+ variant.addPartialStream(ContentType.VIDEO, (stream) => {
1528
+ stream.mime('video/mp4', 'avc1');
1529
+ stream.videoLayout = 'CH-STEREO';
1530
+ });
1531
+ variant.addPartialStream(ContentType.AUDIO, (stream) => {
1532
+ stream.mime('audio/mp4', 'mp4a');
1533
+ });
1534
+ });
1535
+ manifest.addPartialTextStream((stream) => {
1536
+ stream.language = 'en';
1537
+ stream.originalLanguage = 'eng';
1538
+ stream.forced = true;
1539
+ stream.kind = TextStreamKind.SUBTITLE;
1540
+ stream.mime('text/vtt', '');
1541
+ });
1542
+ manifest.sequenceMode = sequenceMode;
1543
+ manifest.type = shaka.media.ManifestParser.HLS;
1544
+ });
1545
+
1546
+ fakeNetEngine
1547
+ .setResponseText('test:/master', master)
1548
+ .setResponseText('test:/audio', media)
1549
+ .setResponseText('test:/video', media)
1550
+ .setResponseText('test:/text', textMedia)
1551
+ .setResponseText('test:/main.vtt', vttText)
1552
+ .setResponseValue('test:/init.mp4', initSegmentData)
1553
+ .setResponseValue('test:/main.mp4', segmentData);
1554
+
1555
+ const actual = await parser.start('test:/master', playerInterface);
1556
+ await loadAllStreamsFor(actual);
1557
+ expect(actual).toEqual(manifest);
1558
+ });
1559
+
1489
1560
  it('parses manifest with SUBTITLES', async () => {
1490
1561
  const master = [
1491
1562
  '#EXTM3U\n',
@@ -1499,7 +1570,7 @@ describe('HlsParser', () => {
1499
1570
  'RESOLUTION=960x540,FRAME-RATE=60,AUDIO="aud1",SUBTITLES="sub1"\n',
1500
1571
  'video\n',
1501
1572
  '#EXT-X-STREAM-INF:BANDWIDTH=200,CODECS="avc1,mp4a",',
1502
- 'RESOLUTION=960x540,FRAME-RATE=60,AUDIO="aud1",SUBTITLES="sub2"\n',
1573
+ 'RESOLUTION=960x540,FRAME-RATE=90,AUDIO="aud1",SUBTITLES="sub2"\n',
1503
1574
  'video\n',
1504
1575
  ].join('');
1505
1576
 
@@ -1919,6 +1990,100 @@ describe('HlsParser', () => {
1919
1990
  }
1920
1991
  });
1921
1992
 
1993
+ it('supports EXT-X-I-FRAME-STREAM-INF with mjpg codec', async () => {
1994
+ const master = [
1995
+ '#EXTM3U\n',
1996
+ '#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="sub1",LANGUAGE="eng",',
1997
+ 'URI="text"\n',
1998
+ '#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aud1",LANGUAGE="eng",',
1999
+ 'CHANNELS="2",URI="audio"\n',
2000
+ '#EXT-X-STREAM-INF:BANDWIDTH=200,CODECS="avc1,mp4a",',
2001
+ 'RESOLUTION=960x540,FRAME-RATE=60,AUDIO="aud1",SUBTITLES="sub1"\n',
2002
+ 'video\n',
2003
+ '#EXT-X-I-FRAME-STREAM-INF:RESOLUTION=240×135,CODECS="mjpg",',
2004
+ 'URI="iframe"\n',
2005
+ '#EXT-X-I-FRAME-STREAM-INF:RESOLUTION=240×135,CODECS="avc",',
2006
+ 'URI="iframeAvc"\n',
2007
+ ].join('');
2008
+
2009
+ const video = [
2010
+ '#EXTM3U\n',
2011
+ '#EXT-X-PLAYLIST-TYPE:VOD\n',
2012
+ '#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
2013
+ '#EXTINF:5,\n',
2014
+ 'main.mp4\n',
2015
+ '#EXTINF:5,\n',
2016
+ 'main.mp4\n',
2017
+ '#EXTINF:5,\n',
2018
+ 'main.mp4\n',
2019
+ ].join('');
2020
+
2021
+ const audio = [
2022
+ '#EXTM3U\n',
2023
+ '#EXT-X-PLAYLIST-TYPE:VOD\n',
2024
+ '#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
2025
+ '#EXTINF:5,\n',
2026
+ 'main.mp4\n',
2027
+ '#EXTINF:5,\n',
2028
+ 'main.mp4\n',
2029
+ '#EXTINF:5,\n',
2030
+ 'main.mp4\n',
2031
+ ].join('');
2032
+
2033
+ const text = [
2034
+ '#EXTM3U\n',
2035
+ '#EXT-X-PLAYLIST-TYPE:VOD\n',
2036
+ '#EXTINF:5,\n',
2037
+ '#EXT-X-BYTERANGE:121090@616\n',
2038
+ 'main.vtt',
2039
+ ].join('');
2040
+
2041
+ const iframe = [
2042
+ '#EXTM3U\n',
2043
+ '#EXT-X-PLAYLIST-TYPE:VOD\n',
2044
+ '#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
2045
+ '#EXTINF:5,\n',
2046
+ 'main.mp4\n',
2047
+ '#EXTINF:5,\n',
2048
+ 'main.mp4\n',
2049
+ '#EXTINF:5,\n',
2050
+ 'main.mp4\n',
2051
+ ].join('');
2052
+
2053
+ fakeNetEngine
2054
+ .setResponseText('test:/master', master)
2055
+ .setResponseText('test:/audio', audio)
2056
+ .setResponseText('test:/video', video)
2057
+ .setResponseText('test:/text', text)
2058
+ .setResponseText('test:/iframe', iframe)
2059
+ .setResponseText('test:/main.vtt', vttText)
2060
+ .setResponseValue('test:/init.mp4', initSegmentData)
2061
+ .setResponseValue('test:/main.mp4', segmentData);
2062
+
2063
+ const actual = await parser.start('test:/master', playerInterface);
2064
+ await loadAllStreamsFor(actual);
2065
+
2066
+ expect(actual.imageStreams.length).toBe(1);
2067
+ expect(actual.textStreams.length).toBe(1);
2068
+ expect(actual.variants.length).toBe(1);
2069
+
2070
+ const thumbnails = actual.imageStreams[0];
2071
+
2072
+ expect(thumbnails.mimeType).toBe('application/mp4');
2073
+ expect(thumbnails.codecs).toBe('mjpg');
2074
+
2075
+ await thumbnails.createSegmentIndex();
2076
+ goog.asserts.assert(thumbnails.segmentIndex != null, 'Null segmentIndex!');
2077
+
2078
+ const firstThumbnailReference = thumbnails.segmentIndex.get(0);
2079
+ const secondThumbnailReference = thumbnails.segmentIndex.get(1);
2080
+ const thirdThumbnailReference = thumbnails.segmentIndex.get(2);
2081
+
2082
+ expect(firstThumbnailReference).not.toBe(null);
2083
+ expect(secondThumbnailReference).not.toBe(null);
2084
+ expect(thirdThumbnailReference).not.toBe(null);
2085
+ });
2086
+
1922
2087
  it('parse EXT-X-GAP', async () => {
1923
2088
  const master = [
1924
2089
  '#EXTM3U\n',
@@ -2585,6 +2750,106 @@ describe('HlsParser', () => {
2585
2750
  expect(actual).toEqual(manifest);
2586
2751
  });
2587
2752
 
2753
+ describe('When config.hls.disableCodecGuessing is set to true', () => {
2754
+ beforeEach(() => {
2755
+ const config = shaka.util.PlayerConfiguration.createDefault().manifest;
2756
+ config.hls.disableCodecGuessing = true;
2757
+ parser.configure(config);
2758
+ });
2759
+
2760
+ it('gets codec info from media if omitted in playlist', async () => {
2761
+ const master = [
2762
+ '#EXTM3U\n',
2763
+ '#EXT-X-VERSION:3\n',
2764
+ '#EXT-X-STREAM-INF:BANDWIDTH=2000000\n',
2765
+ 'video\n',
2766
+ ].join('');
2767
+
2768
+ const media = [
2769
+ '#EXTM3U\n',
2770
+ '#EXT-X-VERSION:3\n',
2771
+ '#EXT-X-TARGETDURATION:5\n',
2772
+ '#EXT-X-MEDIA-SEQUENCE:0\n',
2773
+ '#EXTINF:5,\n',
2774
+ 'video-0.ts\n',
2775
+ ].join('');
2776
+
2777
+ fakeNetEngine
2778
+ .setResponseText('test:/master', master)
2779
+ .setResponseText('test:/video', media)
2780
+ .setResponseValue('test:/video-0.ts', tsSegmentData);
2781
+
2782
+ const actual = await parser.start('test:/master', playerInterface);
2783
+ const variant = actual.variants[0];
2784
+
2785
+ expect(variant.audio).toBe(null);
2786
+ expect(variant.video).toBeDefined();
2787
+ expect(variant.video.codecs).toBe('avc1.42C01E');
2788
+ });
2789
+
2790
+ it('gets codecs from playlist if CODECS attribute present', async () => {
2791
+ const master = [
2792
+ '#EXTM3U\n',
2793
+ '#EXT-X-VERSION:3\n',
2794
+ '#EXT-X-STREAM-INF:BANDWIDTH=2000000,CODECS="foo"\n',
2795
+ 'video\n',
2796
+ ].join('');
2797
+
2798
+ const media = [
2799
+ '#EXTM3U\n',
2800
+ '#EXT-X-VERSION:3\n',
2801
+ '#EXT-X-TARGETDURATION:5\n',
2802
+ '#EXT-X-MEDIA-SEQUENCE:0\n',
2803
+ '#EXTINF:5,\n',
2804
+ 'video-0.ts\n',
2805
+ ].join('');
2806
+
2807
+ fakeNetEngine
2808
+ .setResponseText('test:/master', master)
2809
+ .setResponseText('test:/video', media)
2810
+ .setResponseValue('test:/video-0.ts', tsSegmentData);
2811
+
2812
+ const actual = await parser.start('test:/master', playerInterface);
2813
+ const variant = actual.variants[0];
2814
+
2815
+ expect(variant.audio).toBe(null);
2816
+ expect(variant.video).toBeDefined();
2817
+ expect(variant.video.codecs).toBe('foo');
2818
+ });
2819
+
2820
+ it('falls back to default codecs if it could not find codec', async () => {
2821
+ const master = [
2822
+ '#EXTM3U\n',
2823
+ '#EXT-X-VERSION:3\n',
2824
+ '#EXT-X-STREAM-INF:BANDWIDTH=2000000\n',
2825
+ 'video\n',
2826
+ ].join('');
2827
+
2828
+ const media = [
2829
+ '#EXTM3U\n',
2830
+ '#EXT-X-VERSION:3\n',
2831
+ '#EXT-X-TARGETDURATION:5\n',
2832
+ '#EXT-X-MEDIA-SEQUENCE:0\n',
2833
+ '#EXTINF:5,\n',
2834
+ 'video-0.ts\n',
2835
+ ].join('');
2836
+
2837
+ fakeNetEngine
2838
+ .setResponseText('test:/master', master)
2839
+ .setResponseText('test:/video', media)
2840
+ .setResponseValue('test:/video-0.ts', new Uint8Array([]));
2841
+
2842
+ const actual = await parser.start('test:/master', playerInterface);
2843
+ const variant = actual.variants[0];
2844
+
2845
+ expect(variant.video).toBeDefined();
2846
+
2847
+ const codecs = variant.video.codecs.split(',').map((c) => c.trim());
2848
+
2849
+ expect(codecs).toEqual(['avc1.42E01E', 'mp4a.40.2']);
2850
+ });
2851
+ });
2852
+
2588
2853
  describe('produces syncTime', () => {
2589
2854
  // Corresponds to "2000-01-01T00:00:00.00Z".
2590
2855
  // All the PROGRAM-DATE-TIME values in the tests below are at or after this.
@@ -2751,10 +3016,14 @@ describe('HlsParser', () => {
2751
3016
  'main.mp4',
2752
3017
  ].join(''), [0, 5, 10, 15, 20, 25], syncTimeBase + 5, (reference) => {
2753
3018
  if (reference.startTime == 10) {
2754
- reference.partialReferences = [
2755
- makeReference(10, 12.5, syncTimeBase + 15),
2756
- makeReference(12.5, 15, syncTimeBase + 17.5),
2757
- ];
3019
+ const partialRef = makeReference(10, 12.5, syncTimeBase + 15);
3020
+ partialRef.partial = true;
3021
+ const partialRef2 = makeReference(12.5, 15, syncTimeBase + 17.5);
3022
+ partialRef2.partial = true;
3023
+ partialRef2.lastPartial = true;
3024
+
3025
+ reference.partialReferences = [partialRef, partialRef2];
3026
+ reference.allPartialSegments = true;
2758
3027
  }
2759
3028
  });
2760
3029
  });
@@ -2974,7 +3243,8 @@ describe('HlsParser', () => {
2974
3243
  const media = [
2975
3244
  '#EXTM3U\n',
2976
3245
  '#EXT-X-PLAYLIST-TYPE:VOD\n',
2977
- '#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
3246
+ '#EXT-X-BYTERANGE:616@0\n',
3247
+ '#EXT-X-MAP:URI="init.mp4"\n',
2978
3248
  '#EXTINF:5,\n',
2979
3249
  'main.mp4\n',
2980
3250
  '#EXT-X-MAP:URI="init2.mp4",BYTERANGE="616@0"\n',
@@ -3002,8 +3272,15 @@ describe('HlsParser', () => {
3002
3272
  // uri.
3003
3273
  const initSegments = Array.from(actualVideo.segmentIndex).map(
3004
3274
  (seg) => seg.initSegmentReference);
3005
- expect(initSegments[0].getUris()[0]).toBe('test:/init.mp4');
3006
- expect(initSegments[1].getUris()[0]).toBe('test:/init2.mp4');
3275
+ expect(initSegments.length).toBe(2);
3276
+ const firstInitSegment = initSegments[0];
3277
+ expect(firstInitSegment.getUris()[0]).toBe('test:/init.mp4');
3278
+ expect(firstInitSegment.startByte).toBe(0);
3279
+ expect(firstInitSegment.endByte).toBe(615);
3280
+ const secondInitSegment = initSegments[1];
3281
+ expect(secondInitSegment.getUris()[0]).toBe('test:/init2.mp4');
3282
+ expect(secondInitSegment.startByte).toBe(0);
3283
+ expect(secondInitSegment.endByte).toBe(615);
3007
3284
  });
3008
3285
 
3009
3286
  it('parses variants encrypted with AES-128', async () => {
@@ -3013,7 +3290,7 @@ describe('HlsParser', () => {
3013
3290
  'RESOLUTION=960x540,FRAME-RATE=60,AUDIO="aud1"\n',
3014
3291
  'video\n',
3015
3292
  '#EXT-X-STREAM-INF:BANDWIDTH=300,CODECS="avc1,mp4a",',
3016
- 'RESOLUTION=960x540,FRAME-RATE=120,AUDIO="aud2"\n',
3293
+ 'RESOLUTION=960x540,FRAME-RATE=90,AUDIO="aud2"\n',
3017
3294
  'video2\n',
3018
3295
  '#EXT-X-STREAM-INF:BANDWIDTH=300,CODECS="avc1,mp4a",',
3019
3296
  'RESOLUTION=960x540,FRAME-RATE=120,AUDIO="aud3"\n',
@@ -3124,11 +3401,11 @@ describe('HlsParser', () => {
3124
3401
  'Null segmentIndex!');
3125
3402
 
3126
3403
  const firstMp4Segment = mp4AesEncryptionVideo.segmentIndex.get(0);
3127
- expect(firstMp4Segment.hlsAes128Key).toBeDefined();
3128
- expect(firstMp4Segment.initSegmentReference.hlsAes128Key).toBeDefined();
3404
+ expect(firstMp4Segment.aes128Key).toBeDefined();
3405
+ expect(firstMp4Segment.initSegmentReference.aes128Key).toBeDefined();
3129
3406
  const secondMp4Segment = mp4AesEncryptionVideo.segmentIndex.get(1);
3130
- expect(secondMp4Segment.hlsAes128Key).toBeNull();
3131
- expect(secondMp4Segment.initSegmentReference.hlsAes128Key).toBeDefined();
3407
+ expect(secondMp4Segment.aes128Key).toBeNull();
3408
+ expect(secondMp4Segment.initSegmentReference.aes128Key).toBeDefined();
3132
3409
 
3133
3410
  const tsAesEncryptionVideo = actual.variants[2].video;
3134
3411
  await tsAesEncryptionVideo.createSegmentIndex();
@@ -3136,9 +3413,9 @@ describe('HlsParser', () => {
3136
3413
  'Null segmentIndex!');
3137
3414
 
3138
3415
  const firstTsSegment = tsAesEncryptionVideo.segmentIndex.get(0);
3139
- expect(firstTsSegment.hlsAes128Key).toBeDefined();
3416
+ expect(firstTsSegment.aes128Key).toBeDefined();
3140
3417
  const secondTsSegment = tsAesEncryptionVideo.segmentIndex.get(1);
3141
- expect(secondTsSegment.hlsAes128Key).toBeNull();
3418
+ expect(secondTsSegment.aes128Key).toBeNull();
3142
3419
  });
3143
3420
 
3144
3421
  it('fails on AES-128 if WebCrypto APIs are not available', async () => {
@@ -4181,11 +4458,14 @@ describe('HlsParser', () => {
4181
4458
  it('parse variables master playlist', async () => {
4182
4459
  const master = [
4183
4460
  '#EXTM3U\n',
4184
- '#EXT-X-DEFINE:NAME="auth",VALUE="?token=1"\n',
4461
+ '#EXT-X-DEFINE:NAME="auth",VALUE="token=1"\n',
4462
+ '#EXT-X-DEFINE:QUERYPARAM="a"\n',
4463
+ '#EXT-X-DEFINE:QUERYPARAM="b"\n',
4185
4464
  '#EXT-X-STREAM-INF:BANDWIDTH=200,CODECS="avc1,mp4a",',
4186
4465
  'RESOLUTION=960x540,FRAME-RATE=60,VIDEO="vid"\n',
4187
- 'audio.m3u8{$auth}\n',
4188
- '#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="vid",URI="video.m3u8{$auth}"',
4466
+ 'audio.m3u8?{$auth}&a={$a}&b={$b}\n',
4467
+ '#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="vid",',
4468
+ 'URI="video.m3u8?{$auth}&a={$a}&b={$b}"',
4189
4469
  ].join('');
4190
4470
 
4191
4471
  const media = [
@@ -4197,14 +4477,14 @@ describe('HlsParser', () => {
4197
4477
  ].join('');
4198
4478
 
4199
4479
  fakeNetEngine
4200
- .setResponseText('test:/host/master.m3u8', master)
4201
- .setResponseText('test:/host/audio.m3u8?token=1', media)
4202
- .setResponseText('test:/host/video.m3u8?token=1', media)
4480
+ .setResponseText('test:/host/master.m3u8?a=1&b=2', master)
4481
+ .setResponseText('test:/host/audio.m3u8?token=1&a=1&b=2', media)
4482
+ .setResponseText('test:/host/video.m3u8?token=1&a=1&b=2', media)
4203
4483
  .setResponseValue('test:/host/init.mp4', initSegmentData)
4204
4484
  .setResponseValue('test:/host/segment.mp4', segmentData);
4205
4485
 
4206
- const actual =
4207
- await parser.start('test:/host/master.m3u8', playerInterface);
4486
+ const actual = await parser.start(
4487
+ 'test:/host/master.m3u8?a=1&b=2', playerInterface);
4208
4488
  await loadAllStreamsFor(actual);
4209
4489
  const video = actual.variants[0].video;
4210
4490
  const audio = actual.variants[0].audio;
@@ -4230,26 +4510,28 @@ describe('HlsParser', () => {
4230
4510
  '#EXTM3U\n',
4231
4511
  '#EXT-X-STREAM-INF:BANDWIDTH=200,CODECS="avc1,mp4a",',
4232
4512
  'RESOLUTION=960x540,FRAME-RATE=60,VIDEO="vid"\n',
4233
- 'audio.m3u8\n',
4234
- '#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="vid",URI="video.m3u8"',
4513
+ 'audio.m3u8?fooParam=1\n',
4514
+ '#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="vid",URI="video.m3u8?fooParam=1"',
4235
4515
  ].join('');
4236
4516
 
4237
4517
  const media = [
4238
4518
  '#EXTM3U\n',
4239
- '#EXT-X-DEFINE:NAME="auth",VALUE="?token=1"\n',
4519
+ '#EXT-X-DEFINE:NAME="auth",VALUE="token=1"\n',
4240
4520
  '#EXT-X-DEFINE:NAME="path",VALUE="test/"\n',
4521
+ '#EXT-X-DEFINE:QUERYPARAM="fooParam"\n',
4241
4522
  '#EXT-X-PLAYLIST-TYPE:VOD\n',
4242
4523
  '#EXT-X-MAP:URI="{$path}init.mp4"\n',
4243
4524
  '#EXTINF:5,\n',
4244
- '{$path}segment.mp4{$auth}',
4525
+ '{$path}segment.mp4?{$auth}&fooParam={$fooParam}',
4245
4526
  ].join('');
4246
4527
 
4247
4528
  fakeNetEngine
4248
4529
  .setResponseText('test:/host/master.m3u8', master)
4249
- .setResponseText('test:/host/audio.m3u8', media)
4250
- .setResponseText('test:/host/video.m3u8', media)
4530
+ .setResponseText('test:/host/audio.m3u8?fooParam=1', media)
4531
+ .setResponseText('test:/host/video.m3u8?fooParam=1', media)
4251
4532
  .setResponseValue('test:/host/test/init.mp4', initSegmentData)
4252
- .setResponseValue('test:/host/test/segment.mp4?token=1', segmentData);
4533
+ .setResponseValue('test:/host/test/segment.mp4?token=1&fooParam=1',
4534
+ segmentData);
4253
4535
 
4254
4536
  const actual =
4255
4537
  await parser.start('test:/host/master.m3u8', playerInterface);
@@ -4266,11 +4548,11 @@ describe('HlsParser', () => {
4266
4548
  // flow has gone well.
4267
4549
  const videoReference = Array.from(video.segmentIndex)[0];
4268
4550
  expect(videoReference.getUris())
4269
- .toEqual(['test:/host/test/segment.mp4?token=1']);
4551
+ .toEqual(['test:/host/test/segment.mp4?token=1&fooParam=1']);
4270
4552
 
4271
4553
  const audioReference = Array.from(audio.segmentIndex)[0];
4272
4554
  expect(audioReference.getUris())
4273
- .toEqual(['test:/host/test/segment.mp4?token=1']);
4555
+ .toEqual(['test:/host/test/segment.mp4?token=1&fooParam=1']);
4274
4556
  });
4275
4557
 
4276
4558
  it('import variables in media from master playlist', async () => {
@@ -4881,4 +5163,74 @@ describe('HlsParser', () => {
4881
5163
  expect(video.width).toBe(256);
4882
5164
  expect(video.height).toBe(110);
4883
5165
  });
5166
+
5167
+ it('supports ContentSteering', async () => {
5168
+ const master = [
5169
+ '#EXTM3U\n',
5170
+ '#EXT-X-CONTENT-STEERING:SERVER-URI="http://contentsteering",',
5171
+ 'PATHWAY-ID="a"\n',
5172
+ '#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="a",LANGUAGE="eng",',
5173
+ 'URI="audio/a/media.m3u8"\n',
5174
+ '#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="b",LANGUAGE="eng",',
5175
+ 'URI="audio/b/media.m3u8"\n',
5176
+ '#EXT-X-STREAM-INF:BANDWIDTH=200,CODECS="avc,mp4a",',
5177
+ 'AUDIO="a",PATHWAY-ID="a"\n',
5178
+ 'a/media.m3u8\n',
5179
+ '#EXT-X-STREAM-INF:BANDWIDTH=200,CODECS="avc,mp4a",',
5180
+ 'AUDIO="b",PATHWAY-ID="b"\n',
5181
+ 'b/media.m3u8',
5182
+ ].join('');
5183
+
5184
+ const media = [
5185
+ '#EXTM3U\n',
5186
+ '#EXT-X-PLAYLIST-TYPE:VOD\n',
5187
+ '#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
5188
+ '#EXTINF:5,\n',
5189
+ '#EXT-X-BYTERANGE:121090@616\n',
5190
+ 'main.mp4',
5191
+ ].join('');
5192
+
5193
+ const contentSteering = JSON.stringify({
5194
+ 'VERSION': 1,
5195
+ 'TTL': 1,
5196
+ 'RELOAD-URI': 'http://contentsteering/update',
5197
+ 'PATHWAY-PRIORITY': [
5198
+ 'b',
5199
+ 'a',
5200
+ ],
5201
+ });
5202
+
5203
+ fakeNetEngine
5204
+ .setResponseText('http://master', master)
5205
+ .setResponseText('http://contentsteering', contentSteering)
5206
+ .setResponseText('http://master/a/media.m3u8', media)
5207
+ .setResponseText('http://master/b/media.m3u8', media)
5208
+ .setResponseText('http://master/audio/a/media.m3u8', media)
5209
+ .setResponseText('http://master/audio/b/media.m3u8', media)
5210
+ .setMaxUris(2);
5211
+
5212
+ /** @type {shaka.extern.Manifest} */
5213
+ const manifest = await parser.start('http://master', playerInterface);
5214
+ expect(manifest.variants.length).toBe(1);
5215
+
5216
+ const audio0 = manifest.variants[0].audio;
5217
+ await audio0.createSegmentIndex();
5218
+ goog.asserts.assert(audio0.segmentIndex, 'Null segmentIndex!');
5219
+ const audioSegment0 = Array.from(audio0.segmentIndex)[0];
5220
+ const audioUri0 = audioSegment0.getUris()[0];
5221
+ const audioUri1 = audioSegment0.getUris()[1];
5222
+
5223
+ expect(audioUri0).toBe('http://master/audio/b/main.mp4');
5224
+ expect(audioUri1).toBe('http://master/audio/a/main.mp4');
5225
+
5226
+ const video0 = manifest.variants[0].video;
5227
+ await video0.createSegmentIndex();
5228
+ goog.asserts.assert(video0.segmentIndex, 'Null segmentIndex!');
5229
+ const videoSegment0 = Array.from(video0.segmentIndex)[0];
5230
+ const videoUri0 = videoSegment0.getUris()[0];
5231
+ const videoUri1 = videoSegment0.getUris()[1];
5232
+
5233
+ expect(videoUri0).toBe('http://master/b/main.mp4');
5234
+ expect(videoUri1).toBe('http://master/a/main.mp4');
5235
+ });
4884
5236
  });