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.
- package/.github/ISSUE_TEMPLATE/bug_report.md +1 -1
- package/.github/workflows/release-please.yaml +2 -27
- package/AUTHORS +2 -0
- package/CHANGELOG.md +156 -39
- package/CODE_OF_CONDUCT.md +1 -1
- package/CONTRIBUTORS +2 -0
- package/README.md +54 -42
- package/demo/asset_card.js +18 -21
- package/demo/cast_receiver/index.html +0 -1
- package/demo/close_button.js +0 -3
- package/demo/common/asset.js +33 -22
- package/demo/common/assets.js +249 -60
- package/demo/config.js +219 -253
- package/demo/custom.js +88 -133
- package/demo/front.js +7 -10
- package/demo/index.html +19 -22
- package/demo/input.js +6 -11
- package/demo/input_container.js +8 -9
- package/demo/main.js +62 -126
- package/demo/search.js +29 -34
- package/demo/service_worker.js +0 -3
- package/demo/tooltip.js +3 -5
- package/demo/visualizer.js +3 -5
- package/demo/visualizer_button.js +1 -20
- package/dist/controls.css +1 -1
- package/dist/controls.css.map +1 -1
- package/dist/demo.compiled.debug.js +211 -228
- package/dist/demo.compiled.debug.map +4 -4
- package/dist/demo.compiled.js +211 -228
- package/dist/demo.compiled.map +4 -4
- package/dist/deps.js +42 -37
- package/dist/locales.js +34 -30
- package/dist/receiver.compiled.debug.js +64 -77
- package/dist/receiver.compiled.debug.map +4 -4
- package/dist/receiver.compiled.js +64 -77
- package/dist/receiver.compiled.map +4 -4
- package/dist/shaka-player.compiled.d.ts +343 -151
- package/dist/shaka-player.compiled.debug.d.ts +343 -151
- package/dist/shaka-player.compiled.debug.externs.js +356 -117
- package/dist/shaka-player.compiled.debug.js +952 -811
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +356 -117
- package/dist/shaka-player.compiled.js +1165 -1078
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +359 -153
- package/dist/shaka-player.ui.debug.d.ts +359 -153
- package/dist/shaka-player.ui.debug.externs.js +382 -117
- package/dist/shaka-player.ui.debug.js +1084 -918
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +382 -117
- package/dist/shaka-player.ui.js +1377 -1274
- package/dist/shaka-player.ui.map +4 -4
- package/docs/design/lcevc-integration.md +14 -14
- package/docs/tutorials/ad_monetization.md +54 -0
- package/docs/tutorials/basic-usage.md +2 -1
- package/docs/tutorials/errors.md +2 -1
- package/docs/tutorials/faq.md +27 -55
- package/docs/tutorials/index.json +2 -1
- package/docs/tutorials/lcevc.md +118 -0
- package/docs/tutorials/offline.md +10 -8
- package/docs/tutorials/plugins.md +5 -0
- package/docs/tutorials/ui-customization.md +17 -0
- package/docs/tutorials/ui.md +2 -1
- package/docs/tutorials/upgrade.md +3 -0
- package/externs/css_style_declaration.js +19 -0
- package/externs/lcevc.js +37 -13
- package/externs/managedmediasource.js +24 -0
- package/externs/media_remote.js +68 -0
- package/externs/mediatailor.js +193 -0
- package/externs/pictureinpicture.js +11 -0
- package/externs/shaka/abr_manager.js +6 -2
- package/externs/shaka/ads.js +27 -0
- package/externs/shaka/cea.js +7 -0
- package/externs/shaka/codecs.js +5 -3
- package/externs/shaka/manifest.js +31 -10
- package/externs/shaka/manifest_parser.js +24 -1
- package/externs/shaka/net.js +2 -2
- package/externs/shaka/offline.js +13 -2
- package/externs/shaka/player.js +65 -8
- package/externs/shaka/text.js +3 -1
- package/externs/shaka/transmuxer.js +1 -1
- package/karma.conf.js +7 -3
- package/lib/abr/simple_abr_manager.js +66 -9
- package/lib/ads/ad_manager.js +104 -50
- package/lib/ads/media_tailor_ad.js +297 -0
- package/lib/ads/media_tailor_ad_manager.js +839 -0
- package/lib/cast/cast_receiver.js +1 -1
- package/lib/cea/cea_decoder.js +28 -0
- package/lib/cea/dummy_caption_decoder.js +5 -0
- package/lib/cea/ts_cea_parser.js +15 -2
- package/lib/config/codec_switching_strategy.js +24 -0
- package/lib/dash/content_protection.js +120 -2
- package/lib/dash/dash_parser.js +322 -93
- package/lib/dash/mpd_utils.js +62 -37
- package/lib/dash/segment_base.js +17 -10
- package/lib/dash/segment_list.js +18 -9
- package/lib/dash/segment_template.js +122 -107
- package/lib/dependencies/all.js +8 -7
- package/lib/hls/hls_classes.js +28 -43
- package/lib/hls/hls_parser.js +798 -658
- package/lib/hls/hls_utils.js +64 -5
- package/lib/hls/manifest_text_parser.js +7 -11
- package/lib/lcevc/lcevc_dec.js +220 -0
- package/lib/media/adaptation_set.js +32 -14
- package/lib/media/adaptation_set_criteria.js +86 -16
- package/lib/media/closed_caption_parser.js +13 -0
- package/lib/media/content_workarounds.js +6 -0
- package/lib/media/drm_engine.js +8 -13
- package/lib/media/manifest_parser.js +8 -113
- package/lib/media/media_source_capabilities.js +10 -3
- package/lib/media/media_source_engine.js +286 -44
- package/lib/media/play_rate_controller.js +8 -38
- package/lib/media/presentation_timeline.js +7 -1
- package/lib/media/quality_observer.js +1 -1
- package/lib/media/segment_index.js +6 -6
- package/lib/media/segment_prefetch.js +92 -24
- package/lib/media/segment_reference.js +73 -7
- package/lib/media/segment_utils.js +343 -0
- package/lib/media/stall_detector.js +0 -3
- package/lib/media/streaming_engine.js +73 -38
- package/lib/mss/mss_parser.js +19 -2
- package/lib/net/networking_engine.js +67 -12
- package/lib/net/networking_utils.js +95 -0
- package/lib/offline/indexeddb/v1_storage_cell.js +3 -0
- package/lib/offline/indexeddb/v2_storage_cell.js +3 -0
- package/lib/offline/manifest_converter.js +3 -0
- package/lib/offline/offline_manifest_parser.js +10 -0
- package/lib/offline/storage.js +14 -7
- package/lib/player.js +1098 -1537
- package/lib/polyfill/mediasource.js +22 -1
- package/lib/text/cue.js +15 -0
- package/lib/text/mp4_ttml_parser.js +2 -2
- package/lib/text/srt_text_parser.js +2 -2
- package/lib/text/stub_text_displayer.js +51 -0
- package/lib/text/text_engine.js +3 -2
- package/lib/text/ttml_text_parser.js +45 -5
- package/lib/text/ui_text_displayer.js +8 -0
- package/lib/text/vtt_text_parser.js +40 -22
- package/lib/transmuxer/aac_transmuxer.js +1 -1
- package/lib/transmuxer/ac3_transmuxer.js +1 -1
- package/lib/transmuxer/ec3_transmuxer.js +1 -1
- package/lib/transmuxer/h264.js +5 -4
- package/lib/transmuxer/h265.js +863 -0
- package/lib/transmuxer/mp3_transmuxer.js +1 -1
- package/lib/transmuxer/mpeg_ts_transmuxer.js +4 -3
- package/lib/transmuxer/mss_transmuxer.js +1 -1
- package/lib/transmuxer/ts_transmuxer.js +187 -22
- package/lib/util/buffer_utils.js +26 -4
- package/lib/util/content_steering_manager.js +358 -0
- package/lib/util/error.js +30 -15
- package/lib/util/exp_golomb.js +30 -2
- package/lib/util/fairplay_utils.js +1 -1
- package/lib/util/fake_event.js +8 -1
- package/lib/util/id3_utils.js +50 -1
- package/lib/util/manifest_parser_utils.js +12 -8
- package/lib/util/mp4_generator.js +6 -8
- package/lib/util/mutex.js +59 -0
- package/lib/util/object_utils.js +1 -1
- package/lib/util/periods.js +156 -179
- package/lib/util/platform.js +44 -3
- package/lib/util/player_configuration.js +43 -6
- package/lib/util/state_history.js +6 -2
- package/lib/util/stream_utils.js +206 -283
- package/lib/util/ts_parser.js +335 -98
- package/lib/util/uint8array_utils.js +5 -1
- package/lib/util/xml_utils.js +5 -0
- package/maintained-branches.md +3 -2
- package/package.json +4 -6
- package/roadmap.md +25 -5
- package/shaka-player.uncompiled.js +2 -2
- package/support.html +0 -1
- package/test/abr/simple_abr_manager_unit.js +33 -33
- package/test/ads/ad_manager_unit.js +3 -2
- package/test/cast/cast_receiver_integration.js +50 -4
- package/test/cast/cast_utils_unit.js +2 -0
- package/test/cea/cea_decoder_unit.js +7 -0
- package/test/codec_switching/codec_switching_integration.js +182 -0
- package/test/dash/dash_parser_content_protection_unit.js +2 -0
- package/test/dash/dash_parser_integration.js +74 -0
- package/test/dash/dash_parser_live_unit.js +2 -19
- package/test/dash/dash_parser_manifest_unit.js +536 -2
- package/test/dash/dash_parser_segment_base_unit.js +2 -0
- package/test/dash/dash_parser_segment_list_unit.js +2 -0
- package/test/dash/dash_parser_segment_template_unit.js +2 -0
- package/test/dash/mpd_utils_unit.js +61 -30
- package/test/demo/demo_unit.js +0 -16
- package/test/hls/hls_live_unit.js +14 -3
- package/test/hls/hls_parser_unit.js +385 -33
- package/test/hls/manifest_text_parser_unit.js +32 -99
- package/test/media/adaptation_set_criteria_unit.js +284 -15
- package/test/media/adaptation_set_unit.js +2 -0
- package/test/media/content_workarounds_unit.js +1 -1
- package/test/media/drm_engine_unit.js +3 -3
- package/test/media/media_source_engine_unit.js +166 -2
- package/test/media/play_rate_controller_unit.js +0 -48
- package/test/media/segment_index_unit.js +5 -4
- package/test/media/segment_prefetch_unit.js +1 -1
- package/test/media/streaming_engine_unit.js +17 -17
- package/test/mss/mss_parser_unit.js +2 -0
- package/test/mss/mss_player_integration.js +3 -2
- package/test/net/networking_engine_unit.js +3 -3
- package/test/{media/manifest_parser_unit.js → net/networking_utils_unit.js} +2 -2
- package/test/offline/manifest_convert_unit.js +14 -0
- package/test/offline/offline_integration.js +2 -1
- package/test/offline/storage_integration.js +22 -13
- package/test/player_external.js +4 -2
- package/test/player_integration.js +15 -4
- package/test/player_load_graph_integration.js +47 -151
- package/test/player_src_equals_external.js +1 -0
- package/test/player_src_equals_integration.js +71 -4
- package/test/player_unit.js +182 -158
- package/test/test/assets/dash-aes-128/Fragments(video=0,format=mpd-time-csf) +0 -0
- package/test/test/assets/dash-aes-128/Fragments(video=20000000,format=mpd-time-csf) +0 -0
- package/test/test/assets/dash-aes-128/Fragments(video=40000000,format=mpd-time-csf) +0 -0
- package/test/test/assets/dash-aes-128/Fragments(video=60000000,format=mpd-time-csf) +0 -0
- package/test/test/assets/dash-aes-128/Fragments(video=i,format=mpd-time-csf) +0 -0
- package/test/test/assets/dash-aes-128/dash.mpd +18 -0
- package/test/test/assets/dash-aes-128/license +1 -0
- package/test/test/assets/dash-multi-codec/audio_en_2c_128k_aac.mp4 +0 -0
- package/test/test/assets/dash-multi-codec/audio_es_2c_64k_opus.webm +0 -0
- package/test/test/assets/dash-multi-codec/dash.mpd +32 -0
- package/test/test/assets/dash-multi-codec/video_144p_108k_h264.mp4 +0 -0
- package/test/test/assets/hls-ts-h265/0.ts +0 -0
- package/test/test/assets/hls-ts-h265/hevc.m3u8 +6 -0
- package/test/test/assets/hls-ts-h265/index.m3u8 +7 -0
- package/test/test/assets/hls-ts-muxed-aac-h265/0.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h265/1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h265/media.m3u8 +9 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/media.m3u8 +24 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00000.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00001.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00002.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00003.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00004.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00005.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0000.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0001.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0002.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0003.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ec3-h264/prog_index.m3u8 +14 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/index.m3u8 +23 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-1-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-2-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-3-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-4-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-5-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-6-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-7-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-8-v1-a1.ts +0 -0
- package/test/test/util/dash_parser_util.js +4 -0
- package/test/test/util/fake_ad_manager.js +20 -0
- package/test/test/util/fake_media_source_engine.js +13 -2
- package/test/test/util/fake_networking_engine.js +9 -1
- package/test/test/util/fake_segment_prefetch.js +3 -0
- package/test/test/util/manifest_generator.js +11 -3
- package/test/test/util/manifest_parser_util.js +14 -2
- package/test/test/util/mss_parser_util.js +4 -0
- package/test/test/util/offline_utils.js +2 -0
- package/test/test/util/simple_fakes.js +2 -2
- package/test/test/util/streaming_engine_util.js +10 -4
- package/test/test/util/test_scheme.js +6 -0
- package/test/test/util/ui_utils.js +4 -3
- package/test/text/mp4_ttml_parser_unit.js +4 -4
- package/test/text/srt_text_parser_unit.js +1 -1
- package/test/text/text_displayer_layout_unit.js +1 -1
- package/test/text/text_engine_unit.js +6 -0
- package/test/text/ttml_text_parser_unit.js +85 -2
- package/test/text/vtt_text_parser_unit.js +103 -31
- package/test/transmuxer/transmuxer_engine_integration.js +9 -0
- package/test/transmuxer/transmuxer_integration.js +150 -3
- package/test/ui/ad_ui_unit.js +2 -2
- package/test/ui/ui_customization_unit.js +17 -16
- package/test/ui/ui_integration.js +30 -20
- package/test/ui/ui_unit.js +28 -29
- package/test/util/buffer_utils_unit.js +1 -1
- package/test/util/content_steering_manager_unit.js +427 -0
- package/test/util/id3_utils_unit.js +52 -0
- package/test/util/stream_utils_unit.js +207 -169
- package/test/util/ts_parser_unit.js +3 -3
- package/third_party/closure-uri/uri.js +13 -1
- package/ui/audio_language_selection.js +9 -2
- package/ui/controls.js +125 -0
- package/ui/externs/ui.js +24 -2
- package/ui/language_utils.js +43 -8
- package/ui/less/range_elements.less +33 -0
- package/ui/locales/en.json +1 -0
- package/ui/locales/es-419.json +1 -0
- package/ui/locales/es.json +1 -0
- package/ui/locales/source.json +4 -0
- package/ui/localization.js +10 -0
- package/ui/pip_button.js +22 -120
- package/ui/remote_button.js +203 -0
- package/ui/resolution_selection.js +47 -10
- package/ui/seek_bar.js +296 -3
- package/ui/text_selection.js +2 -1
- package/ui/ui.js +11 -4
- package/demo/common/message_ids.js +0 -309
- package/demo/locales/en.json +0 -288
- package/demo/locales/source.json +0 -1146
- package/externs/mux.js +0 -69
- package/lib/lcevc/lcevc_dil.js +0 -152
- package/lib/routing/node.js +0 -23
- package/lib/routing/payload.js +0 -43
- package/lib/routing/walker.js +0 -587
- package/lib/transmuxer/muxjs_transmuxer.js +0 -242
- package/test/routing/walker_unit.js +0 -504
- 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=
|
|
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
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
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-
|
|
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
|
|
3006
|
-
|
|
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=
|
|
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.
|
|
3128
|
-
expect(firstMp4Segment.initSegmentReference.
|
|
3404
|
+
expect(firstMp4Segment.aes128Key).toBeDefined();
|
|
3405
|
+
expect(firstMp4Segment.initSegmentReference.aes128Key).toBeDefined();
|
|
3129
3406
|
const secondMp4Segment = mp4AesEncryptionVideo.segmentIndex.get(1);
|
|
3130
|
-
expect(secondMp4Segment.
|
|
3131
|
-
expect(secondMp4Segment.initSegmentReference.
|
|
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.
|
|
3416
|
+
expect(firstTsSegment.aes128Key).toBeDefined();
|
|
3140
3417
|
const secondTsSegment = tsAesEncryptionVideo.segmentIndex.get(1);
|
|
3141
|
-
expect(secondTsSegment.
|
|
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="
|
|
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",
|
|
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
|
-
|
|
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="
|
|
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',
|
|
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
|
});
|