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
|
@@ -54,6 +54,8 @@ describe('DashParser Manifest', () => {
|
|
|
54
54
|
enableLowLatencyMode: () => {},
|
|
55
55
|
updateDuration: () => {},
|
|
56
56
|
newDrmInfo: (stream) => {},
|
|
57
|
+
onManifestUpdated: () => {},
|
|
58
|
+
getBandwidthEstimate: () => 1e6,
|
|
57
59
|
};
|
|
58
60
|
});
|
|
59
61
|
|
|
@@ -1180,6 +1182,46 @@ describe('DashParser Manifest', () => {
|
|
|
1180
1182
|
expect(trickModeVideo).toBe(null);
|
|
1181
1183
|
});
|
|
1182
1184
|
|
|
1185
|
+
it('populates groupId if configuration enabled', async () => {
|
|
1186
|
+
const manifestText = [
|
|
1187
|
+
'<MPD minBufferTime="PT75S">',
|
|
1188
|
+
' <Period id="1" duration="PT30S">',
|
|
1189
|
+
' <AdaptationSet id="1" contentType="text">',
|
|
1190
|
+
' <Representation id="text-en" mimeType="text/webvtt">',
|
|
1191
|
+
' <BaseURL>t-en.vtt</BaseURL>',
|
|
1192
|
+
' </Representation>',
|
|
1193
|
+
' </AdaptationSet>',
|
|
1194
|
+
' <AdaptationSet id="2" mimeType="video/mp4">',
|
|
1195
|
+
' <Representation id="video-sd" width="640" height="480">',
|
|
1196
|
+
' <BaseURL>v-sd.mp4</BaseURL>',
|
|
1197
|
+
' <SegmentBase indexRange="100-200" />',
|
|
1198
|
+
' </Representation>',
|
|
1199
|
+
' </AdaptationSet>',
|
|
1200
|
+
' <AdaptationSet id="3" mimeType="audio/mp4">',
|
|
1201
|
+
' <Representation id="audio-en">',
|
|
1202
|
+
' <BaseURL>a-en.mp4</BaseURL>',
|
|
1203
|
+
' <SegmentBase indexRange="100-200" />',
|
|
1204
|
+
' </Representation>',
|
|
1205
|
+
' </AdaptationSet>',
|
|
1206
|
+
' </Period>',
|
|
1207
|
+
'</MPD>',
|
|
1208
|
+
].join('\n');
|
|
1209
|
+
|
|
1210
|
+
fakeNetEngine.setResponseText('dummy://foo', manifestText);
|
|
1211
|
+
|
|
1212
|
+
const config = shaka.util.PlayerConfiguration.createDefault().manifest;
|
|
1213
|
+
config.dash.enableAudioGroups = true;
|
|
1214
|
+
parser.configure(config);
|
|
1215
|
+
|
|
1216
|
+
/** @type {shaka.extern.Manifest} */
|
|
1217
|
+
const manifest = await parser.start('dummy://foo', playerInterface);
|
|
1218
|
+
|
|
1219
|
+
|
|
1220
|
+
expect(manifest.variants.length).toBe(1);
|
|
1221
|
+
const variant = manifest.variants[0];
|
|
1222
|
+
expect(variant.audio.groupId).toBe('3');
|
|
1223
|
+
});
|
|
1224
|
+
|
|
1183
1225
|
it('sets contentType to text for embedded text mime types', async () => {
|
|
1184
1226
|
// One MIME type for embedded TTML, one for embedded WebVTT.
|
|
1185
1227
|
// One MIME type specified on AdaptationSet, on one Representation.
|
|
@@ -2569,8 +2611,8 @@ describe('DashParser Manifest', () => {
|
|
|
2569
2611
|
'<MPD minBufferTime="PT75S" type="dynamic"',
|
|
2570
2612
|
' availabilityStartTime="1970-01-01T00:00:00Z">',
|
|
2571
2613
|
' <ServiceDescription id="0">',
|
|
2572
|
-
' <Latency max="2000" min="
|
|
2573
|
-
' <PlaybackRate max="1.10" min="0.
|
|
2614
|
+
' <Latency max="2000" min="1000" referenceId="0" target="4000" />',
|
|
2615
|
+
' <PlaybackRate max="1.10" min="0.95" />',
|
|
2574
2616
|
' </ServiceDescription>',
|
|
2575
2617
|
'</MPD>',
|
|
2576
2618
|
].join('\n');
|
|
@@ -2582,6 +2624,498 @@ describe('DashParser Manifest', () => {
|
|
|
2582
2624
|
|
|
2583
2625
|
expect(manifest.serviceDescription.maxLatency).toBe(2);
|
|
2584
2626
|
expect(manifest.serviceDescription.maxPlaybackRate).toBe(1.1);
|
|
2627
|
+
expect(manifest.serviceDescription.minLatency).toBe(1);
|
|
2628
|
+
expect(manifest.serviceDescription.minPlaybackRate).toBe(0.95);
|
|
2629
|
+
});
|
|
2630
|
+
});
|
|
2631
|
+
|
|
2632
|
+
it('parses urn:mpeg:dash:ssr:2023', async () => { // eslint-disable-line max-len
|
|
2633
|
+
const manifestText = [
|
|
2634
|
+
'<MPD minBufferTime="PT75S">',
|
|
2635
|
+
' <Period id="1" duration="PT30S">',
|
|
2636
|
+
' <AdaptationSet id="1" mimeType="video/mp4">',
|
|
2637
|
+
' <Representation bandwidth="2" codecs="avc1.4d401f"',
|
|
2638
|
+
' height="1080" width="1920">',
|
|
2639
|
+
' <SegmentTemplate startNumber="1" media="l2-$Number$.mp4"',
|
|
2640
|
+
' initialization="init.mp4" timescale="50" duration="100">',
|
|
2641
|
+
' <SegmentTimeline>',
|
|
2642
|
+
' <S t="0" d="100"/>',
|
|
2643
|
+
' <S d="100"/>',
|
|
2644
|
+
' </SegmentTimeline>',
|
|
2645
|
+
' </SegmentTemplate>',
|
|
2646
|
+
' </Representation>',
|
|
2647
|
+
' </AdaptationSet>',
|
|
2648
|
+
' <AdaptationSet id="2" mimeType="video/mp4">',
|
|
2649
|
+
' <EssentialProperty value="video_primary" ',
|
|
2650
|
+
' schemeIdUri="urn:mpeg:dash:ssr:2023" />',
|
|
2651
|
+
' <Representation bandwidth="1" codecs="avc1.4d401f"',
|
|
2652
|
+
' height="720" width="1280">',
|
|
2653
|
+
' <SegmentTemplate startNumber="1"',
|
|
2654
|
+
' media="l-$Number$-p$SubNumber$.mp4"',
|
|
2655
|
+
' initialization="init.mp4" timescale="50" duration="100">',
|
|
2656
|
+
' <SegmentTimeline>',
|
|
2657
|
+
' <S t="0" d="100" k="4"/>',
|
|
2658
|
+
' <S d="100" k="4"/>',
|
|
2659
|
+
' </SegmentTimeline>',
|
|
2660
|
+
' </SegmentTemplate>',
|
|
2661
|
+
' </Representation>',
|
|
2662
|
+
' </AdaptationSet>',
|
|
2663
|
+
' </Period>',
|
|
2664
|
+
'</MPD>',
|
|
2665
|
+
].join('\n');
|
|
2666
|
+
|
|
2667
|
+
fakeNetEngine.setResponseText('dummy://foo', manifestText);
|
|
2668
|
+
/** @type {shaka.extern.Manifest} */
|
|
2669
|
+
const manifest = await parser.start('dummy://foo', playerInterface);
|
|
2670
|
+
expect(manifest.variants.length).toBe(2);
|
|
2671
|
+
|
|
2672
|
+
const normalStream = manifest.variants[0].video;
|
|
2673
|
+
expect(normalStream.width).toBe(1920);
|
|
2674
|
+
expect(normalStream.height).toBe(1080);
|
|
2675
|
+
expect(normalStream.fastSwitching).toBe(false);
|
|
2676
|
+
await normalStream.createSegmentIndex();
|
|
2677
|
+
goog.asserts.assert(normalStream.segmentIndex != null,
|
|
2678
|
+
'Null segmentIndex!');
|
|
2679
|
+
|
|
2680
|
+
const firstNormalReference = normalStream.segmentIndex.get(0);
|
|
2681
|
+
expect(firstNormalReference.partialReferences.length).toBe(0);
|
|
2682
|
+
|
|
2683
|
+
const stream = manifest.variants[1].video;
|
|
2684
|
+
expect(stream.width).toBe(1280);
|
|
2685
|
+
expect(stream.height).toBe(720);
|
|
2686
|
+
expect(stream.fastSwitching).toBe(true);
|
|
2687
|
+
await stream.createSegmentIndex();
|
|
2688
|
+
goog.asserts.assert(stream.segmentIndex != null,
|
|
2689
|
+
'Null segmentIndex!');
|
|
2690
|
+
|
|
2691
|
+
const firstReference = stream.segmentIndex.get(0);
|
|
2692
|
+
expect(firstReference.partialReferences.length).toBe(4);
|
|
2693
|
+
});
|
|
2694
|
+
|
|
2695
|
+
describe('parses partial segments correctly', () => {
|
|
2696
|
+
it('whitout cadence', async () => {
|
|
2697
|
+
const manifestText = [
|
|
2698
|
+
'<MPD minBufferTime="PT75S">',
|
|
2699
|
+
' <Period id="1" duration="PT30S">',
|
|
2700
|
+
' <AdaptationSet id="1" mimeType="video/mp4">',
|
|
2701
|
+
' <Representation bandwidth="1" codecs="avc1.4d401f">',
|
|
2702
|
+
' <SegmentTemplate startNumber="1"',
|
|
2703
|
+
' media="l-$Number$-p$SubNumber$.mp4"',
|
|
2704
|
+
' initialization="init.mp4" timescale="50" duration="100">',
|
|
2705
|
+
' <SegmentTimeline>',
|
|
2706
|
+
' <S t="0" d="100" k="4"/>',
|
|
2707
|
+
' <S d="100" k="4"/>',
|
|
2708
|
+
' </SegmentTimeline>',
|
|
2709
|
+
' </SegmentTemplate>',
|
|
2710
|
+
' </Representation>',
|
|
2711
|
+
' </AdaptationSet>',
|
|
2712
|
+
' </Period>',
|
|
2713
|
+
'</MPD>',
|
|
2714
|
+
].join('\n');
|
|
2715
|
+
|
|
2716
|
+
fakeNetEngine.setResponseText('dummy://foo', manifestText);
|
|
2717
|
+
/** @type {shaka.extern.Manifest} */
|
|
2718
|
+
const manifest = await parser.start('dummy://foo', playerInterface);
|
|
2719
|
+
const stream = manifest.variants[0].video;
|
|
2720
|
+
await stream.createSegmentIndex();
|
|
2721
|
+
goog.asserts.assert(stream.segmentIndex != null, 'Null segmentIndex!');
|
|
2722
|
+
|
|
2723
|
+
const firstReference = stream.segmentIndex.get(0);
|
|
2724
|
+
expect(firstReference.startTime).toBe(0);
|
|
2725
|
+
expect(firstReference.endTime).toBe(2);
|
|
2726
|
+
expect(firstReference.getUris()).toEqual([]);
|
|
2727
|
+
expect(firstReference.partialReferences.length).toBe(4);
|
|
2728
|
+
const firstPartialReference = firstReference.partialReferences[0];
|
|
2729
|
+
expect(firstPartialReference.startTime).toBe(0);
|
|
2730
|
+
expect(firstPartialReference.endTime).toBe(0.5);
|
|
2731
|
+
expect(firstPartialReference.getUris())
|
|
2732
|
+
.toEqual(['dummy://foo/l-1-p1.mp4']);
|
|
2733
|
+
const secondPartialReference = firstReference.partialReferences[1];
|
|
2734
|
+
expect(secondPartialReference.startTime).toBe(0.5);
|
|
2735
|
+
expect(secondPartialReference.endTime).toBe(1);
|
|
2736
|
+
expect(secondPartialReference.getUris())
|
|
2737
|
+
.toEqual(['dummy://foo/l-1-p2.mp4']);
|
|
2738
|
+
const thirdPartialReference = firstReference.partialReferences[2];
|
|
2739
|
+
expect(thirdPartialReference.startTime).toBe(1);
|
|
2740
|
+
expect(thirdPartialReference.endTime).toBe(1.5);
|
|
2741
|
+
expect(thirdPartialReference.getUris())
|
|
2742
|
+
.toEqual(['dummy://foo/l-1-p3.mp4']);
|
|
2743
|
+
const fourthPartialReference = firstReference.partialReferences[3];
|
|
2744
|
+
expect(fourthPartialReference.startTime).toBe(1.5);
|
|
2745
|
+
expect(fourthPartialReference.endTime).toBe(2);
|
|
2746
|
+
expect(fourthPartialReference.getUris())
|
|
2747
|
+
.toEqual(['dummy://foo/l-1-p4.mp4']);
|
|
2748
|
+
});
|
|
2749
|
+
|
|
2750
|
+
it('with cadence equal to 1', async () => {
|
|
2751
|
+
const manifestText = [
|
|
2752
|
+
'<MPD minBufferTime="PT75S">',
|
|
2753
|
+
' <Period id="1" duration="PT30S">',
|
|
2754
|
+
' <AdaptationSet id="1" mimeType="video/mp4">',
|
|
2755
|
+
' <Representation bandwidth="1" codecs="avc1.4d401f">',
|
|
2756
|
+
' <SegmentTemplate startNumber="1"',
|
|
2757
|
+
' media="l-$Number$-p$SubNumber$.mp4"',
|
|
2758
|
+
' initialization="init.mp4" timescale="50" duration="100">',
|
|
2759
|
+
' <SegmentTimeline>',
|
|
2760
|
+
' <S t="0" d="100" k="4"/>',
|
|
2761
|
+
' <S d="100" k="4"/>',
|
|
2762
|
+
' </SegmentTimeline>',
|
|
2763
|
+
' </SegmentTemplate>',
|
|
2764
|
+
' <SegmentSequenceProperties>',
|
|
2765
|
+
' <SAP type="1" cadence="1" />',
|
|
2766
|
+
' </SegmentSequenceProperties>',
|
|
2767
|
+
' </Representation>',
|
|
2768
|
+
' </AdaptationSet>',
|
|
2769
|
+
' </Period>',
|
|
2770
|
+
'</MPD>',
|
|
2771
|
+
].join('\n');
|
|
2772
|
+
|
|
2773
|
+
fakeNetEngine.setResponseText('dummy://foo', manifestText);
|
|
2774
|
+
/** @type {shaka.extern.Manifest} */
|
|
2775
|
+
const manifest = await parser.start('dummy://foo', playerInterface);
|
|
2776
|
+
const stream = manifest.variants[0].video;
|
|
2777
|
+
await stream.createSegmentIndex();
|
|
2778
|
+
goog.asserts.assert(stream.segmentIndex != null, 'Null segmentIndex!');
|
|
2779
|
+
|
|
2780
|
+
const firstReference = stream.segmentIndex.get(0);
|
|
2781
|
+
const firstPartialReference = firstReference.partialReferences[0];
|
|
2782
|
+
expect(firstPartialReference.isIndependent()).toBeTruthy();
|
|
2783
|
+
const secondPartialReference = firstReference.partialReferences[1];
|
|
2784
|
+
expect(secondPartialReference.isIndependent()).toBeTruthy();
|
|
2785
|
+
const thirdPartialReference = firstReference.partialReferences[2];
|
|
2786
|
+
expect(thirdPartialReference.isIndependent()).toBeTruthy();
|
|
2787
|
+
const fourthPartialReference = firstReference.partialReferences[3];
|
|
2788
|
+
expect(fourthPartialReference.isIndependent()).toBeTruthy();
|
|
2789
|
+
});
|
|
2790
|
+
|
|
2791
|
+
it('with cadence equal to 2', async () => {
|
|
2792
|
+
const manifestText = [
|
|
2793
|
+
'<MPD minBufferTime="PT75S">',
|
|
2794
|
+
' <Period id="1" duration="PT30S">',
|
|
2795
|
+
' <AdaptationSet id="1" mimeType="video/mp4">',
|
|
2796
|
+
' <Representation bandwidth="1" codecs="avc1.4d401f">',
|
|
2797
|
+
' <SegmentTemplate startNumber="1"',
|
|
2798
|
+
' media="l-$Number$-p$SubNumber$.mp4"',
|
|
2799
|
+
' initialization="init.mp4" timescale="50" duration="100">',
|
|
2800
|
+
' <SegmentTimeline>',
|
|
2801
|
+
' <S t="0" d="100" k="4"/>',
|
|
2802
|
+
' <S d="100" k="4"/>',
|
|
2803
|
+
' </SegmentTimeline>',
|
|
2804
|
+
' </SegmentTemplate>',
|
|
2805
|
+
' <SegmentSequenceProperties>',
|
|
2806
|
+
' <SAP type="1" cadence="2" />',
|
|
2807
|
+
' </SegmentSequenceProperties>',
|
|
2808
|
+
' </Representation>',
|
|
2809
|
+
' </AdaptationSet>',
|
|
2810
|
+
' </Period>',
|
|
2811
|
+
'</MPD>',
|
|
2812
|
+
].join('\n');
|
|
2813
|
+
|
|
2814
|
+
fakeNetEngine.setResponseText('dummy://foo', manifestText);
|
|
2815
|
+
/** @type {shaka.extern.Manifest} */
|
|
2816
|
+
const manifest = await parser.start('dummy://foo', playerInterface);
|
|
2817
|
+
const stream = manifest.variants[0].video;
|
|
2818
|
+
await stream.createSegmentIndex();
|
|
2819
|
+
goog.asserts.assert(stream.segmentIndex != null, 'Null segmentIndex!');
|
|
2820
|
+
|
|
2821
|
+
const firstReference = stream.segmentIndex.get(0);
|
|
2822
|
+
const firstPartialReference = firstReference.partialReferences[0];
|
|
2823
|
+
expect(firstPartialReference.isIndependent()).toBeTruthy();
|
|
2824
|
+
const secondPartialReference = firstReference.partialReferences[1];
|
|
2825
|
+
expect(secondPartialReference.isIndependent()).toBeFalsy();
|
|
2826
|
+
const thirdPartialReference = firstReference.partialReferences[2];
|
|
2827
|
+
expect(thirdPartialReference.isIndependent()).toBeTruthy();
|
|
2828
|
+
const fourthPartialReference = firstReference.partialReferences[3];
|
|
2829
|
+
expect(fourthPartialReference.isIndependent()).toBeFalsy();
|
|
2830
|
+
});
|
|
2831
|
+
});
|
|
2832
|
+
|
|
2833
|
+
describe('supports ContentSteering', () => {
|
|
2834
|
+
it('with defaultServiceLocation', async () => {
|
|
2835
|
+
const manifestText = [
|
|
2836
|
+
'<MPD type="static">',
|
|
2837
|
+
' <BaseURL serviceLocation="a">http://example.com/r0/</BaseURL>',
|
|
2838
|
+
' <BaseURL serviceLocation="b">http://example.com/r1/</BaseURL>',
|
|
2839
|
+
' <ContentSteering defaultServiceLocation="a,b" ',
|
|
2840
|
+
'queryBeforeStart="true">http://contentsteering</ContentSteering>',
|
|
2841
|
+
' <Period id="1" duration="PT30S">',
|
|
2842
|
+
' <AdaptationSet id="2" mimeType="video/mp4">',
|
|
2843
|
+
' <SegmentTemplate media="$Number$.mp4" startNumber="1">',
|
|
2844
|
+
' <SegmentTimeline>',
|
|
2845
|
+
' <S t="0" d="30" />',
|
|
2846
|
+
' </SegmentTimeline>',
|
|
2847
|
+
' </SegmentTemplate>',
|
|
2848
|
+
' <Representation id="video-sd" width="640" height="480">',
|
|
2849
|
+
' </Representation>',
|
|
2850
|
+
' </AdaptationSet>',
|
|
2851
|
+
' </Period>',
|
|
2852
|
+
'</MPD>',
|
|
2853
|
+
].join('\n');
|
|
2854
|
+
|
|
2855
|
+
fakeNetEngine.setResponseText('dummy://foo', manifestText);
|
|
2856
|
+
|
|
2857
|
+
const contentSteering = JSON.stringify({
|
|
2858
|
+
'VERSION': 1,
|
|
2859
|
+
'TTL': 1,
|
|
2860
|
+
'RELOAD-URI': 'http://contentsteering/update',
|
|
2861
|
+
'PATHWAY-PRIORITY': [],
|
|
2862
|
+
});
|
|
2863
|
+
|
|
2864
|
+
fakeNetEngine.setResponseText('http://contentsteering', contentSteering);
|
|
2865
|
+
|
|
2866
|
+
/** @type {shaka.extern.Manifest} */
|
|
2867
|
+
const manifest = await parser.start('dummy://foo', playerInterface);
|
|
2868
|
+
|
|
2869
|
+
const video0 = manifest.variants[0].video;
|
|
2870
|
+
await video0.createSegmentIndex();
|
|
2871
|
+
goog.asserts.assert(video0.segmentIndex, 'Null segmentIndex!');
|
|
2872
|
+
const segment0 = Array.from(video0.segmentIndex)[0];
|
|
2873
|
+
const uri0 = segment0.getUris()[0];
|
|
2874
|
+
const uri1 = segment0.getUris()[1];
|
|
2875
|
+
|
|
2876
|
+
expect(uri0).toBe('http://example.com/r0/1.mp4');
|
|
2877
|
+
expect(uri1).toBe('http://example.com/r1/1.mp4');
|
|
2878
|
+
});
|
|
2879
|
+
|
|
2880
|
+
it('without defaultServiceLocation', async () => {
|
|
2881
|
+
const manifestText = [
|
|
2882
|
+
'<MPD type="static">',
|
|
2883
|
+
' <BaseURL serviceLocation="a">http://example.com/r0/</BaseURL>',
|
|
2884
|
+
' <BaseURL serviceLocation="b">http://example.com/r1/</BaseURL>',
|
|
2885
|
+
' <ContentSteering',
|
|
2886
|
+
'queryBeforeStart="true">http://contentsteering</ContentSteering>',
|
|
2887
|
+
' <Period id="1" duration="PT30S">',
|
|
2888
|
+
' <AdaptationSet id="2" mimeType="video/mp4">',
|
|
2889
|
+
' <SegmentTemplate media="$Number$.mp4" startNumber="1">',
|
|
2890
|
+
' <SegmentTimeline>',
|
|
2891
|
+
' <S t="0" d="30" />',
|
|
2892
|
+
' </SegmentTimeline>',
|
|
2893
|
+
' </SegmentTemplate>',
|
|
2894
|
+
' <Representation id="video-sd" width="640" height="480">',
|
|
2895
|
+
' </Representation>',
|
|
2896
|
+
' </AdaptationSet>',
|
|
2897
|
+
' </Period>',
|
|
2898
|
+
'</MPD>',
|
|
2899
|
+
].join('\n');
|
|
2900
|
+
|
|
2901
|
+
fakeNetEngine.setResponseText('dummy://foo', manifestText);
|
|
2902
|
+
|
|
2903
|
+
const contentSteering = JSON.stringify({
|
|
2904
|
+
'VERSION': 1,
|
|
2905
|
+
'TTL': 1,
|
|
2906
|
+
'RELOAD-URI': 'http://contentsteering/update',
|
|
2907
|
+
'PATHWAY-PRIORITY': [
|
|
2908
|
+
'b',
|
|
2909
|
+
'a',
|
|
2910
|
+
],
|
|
2911
|
+
});
|
|
2912
|
+
|
|
2913
|
+
fakeNetEngine.setResponseText('http://contentsteering', contentSteering);
|
|
2914
|
+
|
|
2915
|
+
/** @type {shaka.extern.Manifest} */
|
|
2916
|
+
const manifest = await parser.start('dummy://foo', playerInterface);
|
|
2917
|
+
|
|
2918
|
+
const video0 = manifest.variants[0].video;
|
|
2919
|
+
await video0.createSegmentIndex();
|
|
2920
|
+
goog.asserts.assert(video0.segmentIndex, 'Null segmentIndex!');
|
|
2921
|
+
const segment0 = Array.from(video0.segmentIndex)[0];
|
|
2922
|
+
const uri0 = segment0.getUris()[0];
|
|
2923
|
+
const uri1 = segment0.getUris()[1];
|
|
2924
|
+
|
|
2925
|
+
expect(uri0).toBe('http://example.com/r1/1.mp4');
|
|
2926
|
+
expect(uri1).toBe('http://example.com/r0/1.mp4');
|
|
2927
|
+
});
|
|
2928
|
+
|
|
2929
|
+
it('with queryBeforeStart', async () => {
|
|
2930
|
+
const manifestText = [
|
|
2931
|
+
'<MPD type="static">',
|
|
2932
|
+
' <BaseURL serviceLocation="a">http://example.com/r0/</BaseURL>',
|
|
2933
|
+
' <BaseURL serviceLocation="b">http://example.com/r1/</BaseURL>',
|
|
2934
|
+
' <ContentSteering defaultServiceLocation="b" ',
|
|
2935
|
+
'queryBeforeStart="true">http://contentsteering</ContentSteering>',
|
|
2936
|
+
' <Period id="1" duration="PT30S">',
|
|
2937
|
+
' <AdaptationSet id="2" mimeType="video/mp4">',
|
|
2938
|
+
' <SegmentTemplate media="$Number$.mp4" startNumber="1">',
|
|
2939
|
+
' <SegmentTimeline>',
|
|
2940
|
+
' <S t="0" d="30" />',
|
|
2941
|
+
' </SegmentTimeline>',
|
|
2942
|
+
' </SegmentTemplate>',
|
|
2943
|
+
' <Representation id="video-sd" width="640" height="480">',
|
|
2944
|
+
' </Representation>',
|
|
2945
|
+
' </AdaptationSet>',
|
|
2946
|
+
' </Period>',
|
|
2947
|
+
'</MPD>',
|
|
2948
|
+
].join('\n');
|
|
2949
|
+
|
|
2950
|
+
fakeNetEngine.setResponseText('dummy://foo', manifestText);
|
|
2951
|
+
|
|
2952
|
+
const contentSteering = JSON.stringify({
|
|
2953
|
+
'VERSION': 1,
|
|
2954
|
+
'TTL': 1,
|
|
2955
|
+
'RELOAD-URI': 'http://contentsteering/update',
|
|
2956
|
+
'PATHWAY-PRIORITY': [
|
|
2957
|
+
'a',
|
|
2958
|
+
],
|
|
2959
|
+
});
|
|
2960
|
+
|
|
2961
|
+
fakeNetEngine.setResponseText('http://contentsteering', contentSteering);
|
|
2962
|
+
|
|
2963
|
+
/** @type {shaka.extern.Manifest} */
|
|
2964
|
+
const manifest = await parser.start('dummy://foo', playerInterface);
|
|
2965
|
+
|
|
2966
|
+
const video0 = manifest.variants[0].video;
|
|
2967
|
+
await video0.createSegmentIndex();
|
|
2968
|
+
goog.asserts.assert(video0.segmentIndex, 'Null segmentIndex!');
|
|
2969
|
+
const segment0 = Array.from(video0.segmentIndex)[0];
|
|
2970
|
+
expect(segment0.getUris().length).toBe(1);
|
|
2971
|
+
const uri0 = segment0.getUris()[0];
|
|
2972
|
+
|
|
2973
|
+
expect(uri0).toBe('http://example.com/r0/1.mp4');
|
|
2974
|
+
});
|
|
2975
|
+
|
|
2976
|
+
it('without queryBeforeStart', async () => {
|
|
2977
|
+
const manifestText = [
|
|
2978
|
+
'<MPD type="static">',
|
|
2979
|
+
' <BaseURL serviceLocation="a">http://example.com/r0/</BaseURL>',
|
|
2980
|
+
' <BaseURL serviceLocation="b">http://example.com/r1/</BaseURL>',
|
|
2981
|
+
' <ContentSteering defaultServiceLocation="b">',
|
|
2982
|
+
'http://contentsteering</ContentSteering>',
|
|
2983
|
+
' <Period id="1" duration="PT30S">',
|
|
2984
|
+
' <AdaptationSet id="2" mimeType="video/mp4">',
|
|
2985
|
+
' <SegmentTemplate media="$Number$.mp4" startNumber="1">',
|
|
2986
|
+
' <SegmentTimeline>',
|
|
2987
|
+
' <S t="0" d="30" />',
|
|
2988
|
+
' </SegmentTimeline>',
|
|
2989
|
+
' </SegmentTemplate>',
|
|
2990
|
+
' <Representation id="video-sd" width="640" height="480">',
|
|
2991
|
+
' </Representation>',
|
|
2992
|
+
' </AdaptationSet>',
|
|
2993
|
+
' </Period>',
|
|
2994
|
+
'</MPD>',
|
|
2995
|
+
].join('\n');
|
|
2996
|
+
|
|
2997
|
+
fakeNetEngine.setResponseText('dummy://foo', manifestText);
|
|
2998
|
+
|
|
2999
|
+
fakeNetEngine.setResponseText('http://contentsteering', 'foo');
|
|
3000
|
+
|
|
3001
|
+
/** @type {shaka.extern.Manifest} */
|
|
3002
|
+
const manifest = await parser.start('dummy://foo', playerInterface);
|
|
3003
|
+
|
|
3004
|
+
const video0 = manifest.variants[0].video;
|
|
3005
|
+
await video0.createSegmentIndex();
|
|
3006
|
+
goog.asserts.assert(video0.segmentIndex, 'Null segmentIndex!');
|
|
3007
|
+
const segment0 = Array.from(video0.segmentIndex)[0];
|
|
3008
|
+
expect(segment0.getUris().length).toBe(1);
|
|
3009
|
+
const uri0 = segment0.getUris()[0];
|
|
3010
|
+
|
|
3011
|
+
expect(uri0).toBe('http://example.com/r1/1.mp4');
|
|
3012
|
+
});
|
|
3013
|
+
|
|
3014
|
+
it('without serviceLocation in BaseURL', async () => {
|
|
3015
|
+
const manifestText = [
|
|
3016
|
+
'<MPD type="static">',
|
|
3017
|
+
' <BaseURL>http://example.com/r0/</BaseURL>',
|
|
3018
|
+
' <BaseURL>http://example.com/r1/</BaseURL>',
|
|
3019
|
+
' <ContentSteering',
|
|
3020
|
+
'queryBeforeStart="true">http://contentsteering</ContentSteering>',
|
|
3021
|
+
' <Period id="1" duration="PT30S">',
|
|
3022
|
+
' <AdaptationSet id="2" mimeType="video/mp4">',
|
|
3023
|
+
' <SegmentTemplate media="$Number$.mp4" startNumber="1">',
|
|
3024
|
+
' <SegmentTimeline>',
|
|
3025
|
+
' <S t="0" d="30" />',
|
|
3026
|
+
' </SegmentTimeline>',
|
|
3027
|
+
' </SegmentTemplate>',
|
|
3028
|
+
' <Representation id="video-sd" width="640" height="480">',
|
|
3029
|
+
' </Representation>',
|
|
3030
|
+
' </AdaptationSet>',
|
|
3031
|
+
' </Period>',
|
|
3032
|
+
'</MPD>',
|
|
3033
|
+
].join('\n');
|
|
3034
|
+
|
|
3035
|
+
fakeNetEngine.setResponseText('dummy://foo', manifestText);
|
|
3036
|
+
|
|
3037
|
+
fakeNetEngine.setResponseText('http://contentsteering', 'foo');
|
|
3038
|
+
|
|
3039
|
+
/** @type {shaka.extern.Manifest} */
|
|
3040
|
+
const manifest = await parser.start('dummy://foo', playerInterface);
|
|
3041
|
+
|
|
3042
|
+
const video0 = manifest.variants[0].video;
|
|
3043
|
+
await video0.createSegmentIndex();
|
|
3044
|
+
goog.asserts.assert(video0.segmentIndex, 'Null segmentIndex!');
|
|
3045
|
+
const segment0 = Array.from(video0.segmentIndex)[0];
|
|
3046
|
+
const uri0 = segment0.getUris()[0];
|
|
3047
|
+
const uri1 = segment0.getUris()[1];
|
|
3048
|
+
|
|
3049
|
+
expect(uri0).toBe('http://example.com/r0/1.mp4');
|
|
3050
|
+
expect(uri1).toBe('http://example.com/r1/1.mp4');
|
|
3051
|
+
});
|
|
3052
|
+
|
|
3053
|
+
it('specify MPD BaseURL and AdaptationSet BaseURL', async () => {
|
|
3054
|
+
const manifestText = [
|
|
3055
|
+
'<MPD type="static">',
|
|
3056
|
+
' <BaseURL serviceLocation="a">http://example.com/r0/</BaseURL>',
|
|
3057
|
+
' <BaseURL serviceLocation="b">http://example.com/r1/</BaseURL>',
|
|
3058
|
+
' <ContentSteering defaultServiceLocation="a,b" ',
|
|
3059
|
+
'queryBeforeStart="true">http://contentsteering</ContentSteering>',
|
|
3060
|
+
' <Period id="1" duration="PT30S">',
|
|
3061
|
+
' <AdaptationSet id="2" mimeType="video/mp4">',
|
|
3062
|
+
' <SegmentTemplate media="$Number$.mp4" startNumber="1">',
|
|
3063
|
+
' <SegmentTimeline>',
|
|
3064
|
+
' <S t="0" d="30" />',
|
|
3065
|
+
' </SegmentTimeline>',
|
|
3066
|
+
' </SegmentTemplate>',
|
|
3067
|
+
' <Representation id="video-sd" width="640" height="480">',
|
|
3068
|
+
' </Representation>',
|
|
3069
|
+
' </AdaptationSet>',
|
|
3070
|
+
' <AdaptationSet id="3" mimeType="audio/mp4">',
|
|
3071
|
+
' <BaseURL serviceLocation="c">http://example.foo/r0/</BaseURL>',
|
|
3072
|
+
' <BaseURL serviceLocation="d">http://example.foo/r1/</BaseURL>',
|
|
3073
|
+
' <SegmentTemplate media="$Number$.mp4" startNumber="1">',
|
|
3074
|
+
' <SegmentTimeline>',
|
|
3075
|
+
' <S t="0" d="30" />',
|
|
3076
|
+
' </SegmentTimeline>',
|
|
3077
|
+
' </SegmentTemplate>',
|
|
3078
|
+
' <Representation id="audio">',
|
|
3079
|
+
' </Representation>',
|
|
3080
|
+
' </AdaptationSet>',
|
|
3081
|
+
' </Period>',
|
|
3082
|
+
'</MPD>',
|
|
3083
|
+
].join('\n');
|
|
3084
|
+
|
|
3085
|
+
fakeNetEngine.setResponseText('dummy://foo', manifestText);
|
|
3086
|
+
|
|
3087
|
+
const contentSteering = JSON.stringify({
|
|
3088
|
+
'VERSION': 1,
|
|
3089
|
+
'TTL': 1,
|
|
3090
|
+
'RELOAD-URI': 'http://contentsteering/update',
|
|
3091
|
+
'PATHWAY-PRIORITY': [
|
|
3092
|
+
'a',
|
|
3093
|
+
'c',
|
|
3094
|
+
],
|
|
3095
|
+
});
|
|
3096
|
+
|
|
3097
|
+
fakeNetEngine.setResponseText('http://contentsteering', contentSteering);
|
|
3098
|
+
|
|
3099
|
+
/** @type {shaka.extern.Manifest} */
|
|
3100
|
+
const manifest = await parser.start('dummy://foo', playerInterface);
|
|
3101
|
+
|
|
3102
|
+
const video0 = manifest.variants[0].video;
|
|
3103
|
+
await video0.createSegmentIndex();
|
|
3104
|
+
goog.asserts.assert(video0.segmentIndex, 'Null segmentIndex!');
|
|
3105
|
+
const videoSegment0 = Array.from(video0.segmentIndex)[0];
|
|
3106
|
+
expect(videoSegment0.getUris().length).toBe(1);
|
|
3107
|
+
const videoUri0 = videoSegment0.getUris()[0];
|
|
3108
|
+
|
|
3109
|
+
expect(videoUri0).toBe('http://example.com/r0/1.mp4');
|
|
3110
|
+
|
|
3111
|
+
const audio0 = manifest.variants[0].audio;
|
|
3112
|
+
await audio0.createSegmentIndex();
|
|
3113
|
+
goog.asserts.assert(audio0.segmentIndex, 'Null segmentIndex!');
|
|
3114
|
+
const audioSegment0 = Array.from(audio0.segmentIndex)[0];
|
|
3115
|
+
expect(audioSegment0.getUris().length).toBe(1);
|
|
3116
|
+
const audioUri0 = audioSegment0.getUris()[0];
|
|
3117
|
+
|
|
3118
|
+
expect(audioUri0).toBe('http://example.foo/r0/1.mp4');
|
|
2585
3119
|
});
|
|
2586
3120
|
});
|
|
2587
3121
|
});
|
|
@@ -350,6 +350,8 @@ describe('DashParser SegmentList', () => {
|
|
|
350
350
|
enableLowLatencyMode: () => {},
|
|
351
351
|
updateDuration: () => {},
|
|
352
352
|
newDrmInfo: (stream) => {},
|
|
353
|
+
onManifestUpdated: () => {},
|
|
354
|
+
getBandwidthEstimate: () => 1e6,
|
|
353
355
|
};
|
|
354
356
|
try {
|
|
355
357
|
const manifest = await dashParser.start('dummy://foo', playerInterface);
|