shaka-player 4.3.9 → 4.4.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/workflows/build-and-test.yaml +11 -18
- package/.github/workflows/compute-incremental-coverage.py +3 -0
- package/.github/workflows/release-please.yaml +7 -0
- package/.github/workflows/selenium-lab-tests.yaml +45 -10
- package/AUTHORS +9 -0
- package/CHANGELOG.md +295 -190
- package/CONTRIBUTORS +8 -0
- package/LICENSE +32 -0
- package/README.md +63 -10
- package/demo/autoTemplate.txt +40 -5
- package/demo/close_button.js +11 -0
- package/demo/common/asset.js +13 -1
- package/demo/common/assets.js +112 -28
- package/demo/common/message_ids.js +25 -1
- package/demo/config.js +69 -10
- package/demo/customWarning.txt +2 -2
- package/demo/index.html +3 -1
- package/demo/locales/en.json +26 -2
- package/demo/locales/source.json +105 -9
- package/demo/main.js +57 -9
- package/demo/search.js +3 -1
- package/demo/service_worker.js +3 -0
- package/dist/controls.css +1 -1
- package/dist/controls.css.map +1 -1
- package/dist/demo.compiled.debug.js +132 -118
- package/dist/demo.compiled.debug.map +3 -3
- package/dist/demo.compiled.js +132 -118
- package/dist/demo.compiled.map +3 -3
- package/dist/deps.js +46 -28
- package/dist/locales.js +31 -31
- package/dist/receiver.compiled.debug.js +60 -52
- package/dist/receiver.compiled.debug.map +3 -3
- package/dist/receiver.compiled.js +60 -52
- package/dist/receiver.compiled.map +3 -3
- package/dist/shaka-player.compiled.d.ts +676 -391
- package/dist/shaka-player.compiled.debug.d.ts +676 -391
- package/dist/shaka-player.compiled.debug.externs.js +1188 -616
- package/dist/shaka-player.compiled.debug.js +1046 -700
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +1188 -616
- package/dist/shaka-player.compiled.js +1094 -933
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +677 -392
- package/dist/shaka-player.ui.debug.d.ts +677 -392
- package/dist/shaka-player.ui.debug.externs.js +1023 -451
- package/dist/shaka-player.ui.debug.js +1101 -738
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +1023 -451
- package/dist/shaka-player.ui.js +1244 -1071
- package/dist/shaka-player.ui.map +4 -4
- package/docs/tutorials/ad_monetization.md +15 -1
- package/docs/tutorials/application-level-redirects.md +1 -1
- package/docs/tutorials/config.md +9 -5
- package/docs/tutorials/drm-config.md +61 -0
- package/docs/tutorials/fairplay.md +19 -4
- package/docs/tutorials/license-server-auth.md +4 -4
- package/docs/tutorials/license-wrapping.md +2 -2
- package/docs/tutorials/ui-customization.md +7 -3
- package/docs/tutorials/ui.md +7 -7
- package/docs/tutorials/upgrade.md +3 -0
- package/externs/ima.js +123 -2
- package/externs/isoboxer.js +217 -0
- package/externs/mediakeys.js +18 -0
- package/externs/mux.js +1 -105
- package/externs/pictureinpicture.js +48 -0
- package/externs/shaka/ads.js +61 -1
- package/externs/shaka/cea.js +110 -0
- package/externs/shaka/codecs.js +32 -0
- package/externs/shaka/manifest.js +101 -1
- package/externs/shaka/manifest_parser.js +0 -10
- package/externs/shaka/net.js +36 -7
- package/externs/shaka/offline.js +8 -1
- package/externs/shaka/player.js +220 -21
- package/externs/shaka/text.js +1 -382
- package/externs/shaka/transmuxer.js +59 -0
- package/karma.conf.js +15 -0
- package/lib/abr/simple_abr_manager.js +6 -3
- package/lib/ads/ad_manager.js +60 -2
- package/lib/ads/client_side_ad.js +86 -0
- package/lib/ads/client_side_ad_manager.js +93 -5
- package/lib/ads/server_side_ad.js +86 -0
- package/lib/ads/server_side_ad_manager.js +13 -0
- package/lib/cast/cast_utils.js +1 -0
- package/lib/cea/cea608_data_channel.js +24 -14
- package/lib/cea/cea608_memory.js +5 -2
- package/lib/cea/cea708_service.js +8 -9
- package/lib/cea/cea708_window.js +1 -2
- package/lib/cea/cea_decoder.js +23 -6
- package/lib/cea/cea_utils.js +25 -2
- package/lib/cea/dummy_caption_decoder.js +21 -0
- package/lib/cea/dummy_cea_parser.js +1 -3
- package/lib/cea/mp4_cea_parser.js +15 -10
- package/lib/cea/ts_cea_parser.js +69 -0
- package/lib/dash/content_protection.js +32 -2
- package/lib/dash/dash_parser.js +93 -31
- package/lib/dash/mpd_utils.js +6 -25
- package/lib/dash/segment_base.js +12 -14
- package/lib/dash/segment_list.js +10 -6
- package/lib/dash/segment_template.js +349 -32
- package/lib/dependencies/all.js +8 -0
- package/lib/hls/hls_classes.js +33 -8
- package/lib/hls/hls_parser.js +805 -191
- package/lib/hls/manifest_text_parser.js +4 -14
- package/lib/media/adaptation_set_criteria.js +43 -3
- package/lib/media/closed_caption_parser.js +74 -12
- package/lib/media/drm_engine.js +189 -49
- package/lib/media/gap_jumping_controller.js +1 -1
- package/lib/media/manifest_parser.js +34 -0
- package/lib/media/media_source_capabilities.js +10 -0
- package/lib/media/media_source_engine.js +475 -231
- package/lib/media/playhead.js +1 -1
- package/lib/media/presentation_timeline.js +62 -0
- package/lib/media/segment_index.js +50 -14
- package/lib/media/segment_prefetch.js +277 -0
- package/lib/media/segment_reference.js +70 -4
- package/lib/media/streaming_engine.js +258 -81
- package/lib/media/video_wrapper.js +15 -7
- package/lib/mss/content_protection.js +353 -0
- package/lib/mss/mss_parser.js +1081 -0
- package/lib/net/networking_engine.js +60 -10
- package/lib/offline/indexeddb/v1_storage_cell.js +1 -0
- package/lib/offline/indexeddb/v2_storage_cell.js +1 -0
- package/lib/offline/manifest_converter.js +6 -0
- package/lib/offline/storage.js +2 -4
- package/lib/player.js +309 -105
- package/lib/polyfill/media_capabilities.js +43 -3
- package/lib/polyfill/patchedmediakeys_apple.js +5 -0
- package/lib/polyfill/patchedmediakeys_nop.js +5 -0
- package/lib/polyfill/patchedmediakeys_webkit.js +5 -0
- package/lib/text/cue.js +208 -130
- package/lib/text/lrc_text_parser.js +2 -2
- package/lib/text/mp4_vtt_parser.js +2 -2
- package/lib/text/sbv_text_parser.js +1 -1
- package/lib/text/simple_text_displayer.js +2 -1
- package/lib/text/srt_text_parser.js +9 -1
- package/lib/text/ssa_text_parser.js +2 -2
- package/lib/text/text_engine.js +3 -21
- package/lib/text/text_utils.js +71 -20
- package/lib/text/ui_text_displayer.js +14 -14
- package/lib/text/vtt_text_parser.js +22 -14
- package/lib/transmuxer/aac_transmuxer.js +224 -0
- package/lib/transmuxer/ac3.js +142 -0
- package/lib/transmuxer/ac3_transmuxer.js +212 -0
- package/lib/transmuxer/adts.js +232 -0
- package/lib/transmuxer/ec3.js +103 -0
- package/lib/transmuxer/ec3_transmuxer.js +212 -0
- package/lib/transmuxer/h264.js +324 -0
- package/lib/transmuxer/mp3_transmuxer.js +204 -0
- package/lib/transmuxer/mpeg_audio.js +196 -0
- package/lib/transmuxer/mpeg_ts_transmuxer.js +182 -0
- package/lib/transmuxer/mss_transmuxer.js +389 -0
- package/lib/{media/transmuxer.js → transmuxer/muxjs_transmuxer.js} +34 -80
- package/lib/transmuxer/transmuxer_engine.js +161 -0
- package/lib/transmuxer/ts_transmuxer.js +738 -0
- package/lib/util/cmcd_manager.js +131 -71
- package/lib/util/error.js +62 -26
- package/lib/util/exp_golomb.js +220 -0
- package/lib/util/fairplay_utils.js +64 -13
- package/lib/util/id3_utils.js +56 -3
- package/lib/util/language_utils.js +11 -8
- package/lib/util/manifest_parser_utils.js +3 -0
- package/lib/util/mime_utils.js +44 -7
- package/lib/util/mp4_box_parsers.js +233 -5
- package/lib/util/mp4_generator.js +1381 -0
- package/lib/util/periods.js +40 -34
- package/lib/util/platform.js +25 -3
- package/lib/util/player_configuration.js +38 -1
- package/lib/util/stream_utils.js +138 -27
- package/lib/util/text_parser.js +1 -1
- package/lib/util/ts_parser.js +470 -47
- package/lib/util/xml_utils.js +16 -3
- package/maintained-branches.md +2 -2
- package/package.json +4 -2
- package/roadmap.md +21 -6
- package/shaka-player.uncompiled.js +18 -0
- package/test/abr/simple_abr_manager_unit.js +32 -4
- package/test/ads/ad_manager_unit.js +18 -2
- package/test/cast/cast_utils_unit.js +7 -2
- package/test/cea/cea608_memory_unit.js +24 -0
- package/test/cea/cea_decoder_unit.js +33 -0
- package/test/dash/dash_parser_content_protection_unit.js +93 -3
- package/test/dash/dash_parser_live_unit.js +56 -13
- package/test/dash/dash_parser_manifest_unit.js +70 -2
- package/test/dash/dash_parser_segment_base_unit.js +14 -9
- package/test/dash/dash_parser_segment_template_unit.js +286 -6
- package/test/demo/demo_unit.js +5 -1
- package/test/hls/hls_live_unit.js +188 -28
- package/test/hls/hls_parser_unit.js +250 -109
- package/test/hls/manifest_text_parser_unit.js +18 -13
- package/test/media/adaptation_set_criteria_unit.js +46 -14
- package/test/media/adaptation_set_unit.js +2 -0
- package/test/media/drm_engine_integration.js +11 -8
- package/test/media/drm_engine_unit.js +220 -7
- package/test/media/media_source_engine_integration.js +122 -38
- package/test/media/media_source_engine_unit.js +133 -153
- package/test/media/playhead_unit.js +3 -0
- package/test/media/presentation_timeline_unit.js +51 -0
- package/test/media/segment_index_unit.js +52 -0
- package/test/media/segment_prefetch_unit.js +243 -0
- package/test/media/streaming_engine_integration.js +9 -3
- package/test/media/streaming_engine_unit.js +440 -59
- package/test/mss/mss_parser_content_protection_unit.js +49 -0
- package/test/mss/mss_parser_unit.js +472 -0
- package/test/mss/mss_player_integration.js +123 -0
- package/test/offline/manifest_convert_unit.js +9 -0
- package/test/offline/storage_integration.js +6 -1
- package/test/player_integration.js +4 -1
- package/test/player_unit.js +386 -133
- package/test/polyfill/media_capabilities_unit.js +18 -0
- package/test/test/assets/hls-raw-aac/fileSequence0.aac +0 -0
- package/test/test/assets/hls-raw-aac/fileSequence1.aac +0 -0
- package/test/test/assets/hls-raw-aac/fileSequence2.aac +0 -0
- package/test/test/assets/hls-raw-aac/fileSequence3.aac +0 -0
- package/test/test/assets/hls-raw-aac/manifest.m3u8 +4 -0
- package/test/test/assets/hls-raw-aac/stream.m4a.m3u8 +14 -0
- package/test/test/assets/hls-raw-ac3/fileSequence0.ac3 +0 -0
- package/test/test/assets/hls-raw-ac3/fileSequence1.ac3 +0 -0
- package/test/test/assets/hls-raw-ac3/fileSequence2.ac3 +0 -0
- package/test/test/assets/hls-raw-ac3/fileSequence3.ac3 +0 -0
- package/test/test/assets/hls-raw-ac3/fileSequence4.ac3 +0 -0
- package/test/test/assets/hls-raw-ac3/fileSequence5.ac3 +0 -0
- package/test/test/assets/hls-raw-ac3/fileSequence6.ac3 +0 -0
- package/test/test/assets/hls-raw-ac3/fileSequence7.ac3 +0 -0
- package/test/test/assets/hls-raw-ac3/prog_index.m3u8 +31 -0
- package/test/test/assets/hls-raw-ec3/fileSequence0.ec3 +0 -0
- package/test/test/assets/hls-raw-ec3/fileSequence1.ec3 +0 -0
- package/test/test/assets/hls-raw-ec3/fileSequence2.ec3 +0 -0
- package/test/test/assets/hls-raw-ec3/fileSequence3.ec3 +0 -0
- package/test/test/assets/hls-raw-ec3/fileSequence4.ec3 +0 -0
- package/test/test/assets/hls-raw-ec3/fileSequence5.ec3 +0 -0
- package/test/test/assets/hls-raw-ec3/fileSequence6.ec3 +0 -0
- package/test/test/assets/hls-raw-ec3/fileSequence7.ec3 +0 -0
- package/test/test/assets/hls-raw-ec3/prog_index.m3u8 +31 -0
- package/test/test/assets/hls-raw-mp3/chunklist_w905519204.m3u8 +13 -0
- package/test/test/assets/hls-raw-mp3/media_w905519204_0.mp3 +0 -0
- package/test/test/assets/hls-raw-mp3/media_w905519204_1.mp3 +0 -0
- package/test/test/assets/hls-raw-mp3/media_w905519204_2.mp3 +0 -0
- package/test/test/assets/hls-raw-mp3/media_w905519204_3.mp3 +0 -0
- package/test/test/assets/hls-raw-mp3/playlist.m3u8 +4 -0
- package/test/test/assets/hls-ts-aac/playlist.m3u8 +23 -0
- package/test/test/assets/hls-ts-aac/segment_0.ts +0 -0
- package/test/test/assets/hls-ts-aac/segment_1.ts +0 -0
- package/test/test/assets/hls-ts-aac/segment_2.ts +0 -0
- package/test/test/assets/hls-ts-aac/segment_3.ts +0 -0
- package/test/test/assets/hls-ts-aac/segment_4.ts +0 -0
- package/test/test/assets/hls-ts-aac/segment_5.ts +0 -0
- package/test/test/assets/hls-ts-aac/segment_6.ts +0 -0
- package/test/test/assets/hls-ts-aac/segment_7.ts +0 -0
- package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0000.ts +0 -0
- package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0001.ts +0 -0
- package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0002.ts +0 -0
- package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0003.ts +0 -0
- package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0004.ts +0 -0
- package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0005.ts +0 -0
- package/test/test/assets/hls-ts-ac3/prog_index.m3u8 +19 -0
- package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0000.ts +0 -0
- package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0001.ts +0 -0
- package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0002.ts +0 -0
- package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0003.ts +0 -0
- package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0004.ts +0 -0
- package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0005.ts +0 -0
- package/test/test/assets/hls-ts-ec3/prog_index.m3u8 +19 -0
- package/test/test/assets/hls-ts-h264/fileSequence0.ts +0 -0
- package/test/test/assets/hls-ts-h264/fileSequence1.ts +0 -0
- package/test/test/assets/hls-ts-h264/fileSequence2.ts +0 -0
- package/test/test/assets/hls-ts-h264/fileSequence3.ts +0 -0
- package/test/test/assets/hls-ts-h264/fileSequence4.ts +0 -0
- package/test/test/assets/hls-ts-h264/fileSequence5.ts +0 -0
- package/test/test/assets/hls-ts-h264/prog_index.m3u8 +25 -0
- package/test/test/assets/hls-ts-mp3/manifest.m3u8 +13 -0
- package/test/test/assets/hls-ts-mp3/media_w239891843_0.ts +0 -0
- package/test/test/assets/hls-ts-mp3/media_w239891843_1.ts +0 -0
- package/test/test/assets/hls-ts-mp3/media_w239891843_2.ts +0 -0
- package/test/test/assets/hls-ts-mp3/media_w239891843_3.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h264/chunk.m3u8 +17 -0
- package/test/test/assets/hls-ts-muxed-aac-h264/n_0_0_0.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h264/n_1_0_0.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h264/n_2_0_0.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h264/n_3_0_0.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h264/n_4_0_0.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h264/n_5_0_0.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h264/playlist.m3u8 +4 -0
- package/test/test/boot.js +7 -2
- package/test/test/util/fake_ad.js +99 -0
- package/test/test/util/fake_ad_manager.js +7 -1
- package/test/test/util/fake_networking_engine.js +41 -14
- package/test/test/util/fake_segment_prefetch.js +81 -0
- package/test/test/util/manifest_generator.js +19 -5
- package/test/test/util/mss_parser_util.js +115 -0
- package/test/test/util/offline_utils.js +1 -0
- package/test/test/util/simple_fakes.js +12 -3
- package/test/test/util/streaming_engine_util.js +14 -4
- package/test/test/util/ttml_utils.js +2 -2
- package/test/test/util/ui_utils.js +5 -1
- package/test/text/cue_integration.js +1 -1
- package/test/text/srt_text_parser_unit.js +78 -0
- package/test/text/text_engine_unit.js +17 -8
- package/test/text/ui_text_displayer_unit.js +4 -4
- package/test/text/vtt_text_parser_unit.js +59 -40
- package/test/text/web_vtt_generator_unit.js +9 -3
- package/test/{media/transmuxer_integration.js → transmuxer/muxjs_transmuxer_integration.js} +30 -33
- package/test/transmuxer/transmuxer_engine_integration.js +60 -0
- package/test/transmuxer/transmuxer_integration.js +296 -0
- package/test/util/cmcd_manager_unit.js +162 -13
- package/test/util/language_utils_unit.js +9 -2
- package/test/util/mp4_box_parsers_unit.js +39 -4
- package/test/util/periods_unit.js +34 -26
- package/test/util/stream_utils_unit.js +60 -107
- package/ui/controls.js +19 -1
- package/ui/controls.less +1 -0
- package/ui/externs/ui.js +13 -3
- package/ui/language_utils.js +15 -0
- package/ui/less/thumbnails.less +26 -0
- package/ui/locales/oc.json +42 -0
- package/ui/pip_button.js +83 -2
- package/ui/range_element.js +15 -0
- package/ui/resolution_selection.js +9 -2
- package/ui/seek_bar.js +230 -1
- package/ui/ui.js +5 -0
- package/lib/cea/i_caption_decoder.js +0 -51
- package/lib/cea/i_cea_parser.js +0 -68
|
@@ -26,8 +26,6 @@ describe('DashParser Live', () => {
|
|
|
26
26
|
parser.configure(shaka.util.PlayerConfiguration.createDefault().manifest);
|
|
27
27
|
playerInterface = {
|
|
28
28
|
networkingEngine: fakeNetEngine,
|
|
29
|
-
modifyManifestRequest: (request, manifestInfo) => {},
|
|
30
|
-
modifySegmentRequest: (request, segmentInfo) => {},
|
|
31
29
|
filter: (manifest) => Promise.resolve(),
|
|
32
30
|
makeTextStreamsForClosedCaptions: (manifest) => {},
|
|
33
31
|
onTimelineRegionAdded: fail, // Should not have any EventStream elements.
|
|
@@ -591,6 +589,8 @@ describe('DashParser Live', () => {
|
|
|
591
589
|
const onError = jasmine.createSpy('onError');
|
|
592
590
|
playerInterface.onError = Util.spyFunc(onError);
|
|
593
591
|
|
|
592
|
+
const updateTick = updateTickSpy();
|
|
593
|
+
|
|
594
594
|
fakeNetEngine.setResponseText('dummy://foo', manifestText);
|
|
595
595
|
await parser.start('dummy://foo', playerInterface);
|
|
596
596
|
|
|
@@ -605,6 +605,39 @@ describe('DashParser Live', () => {
|
|
|
605
605
|
|
|
606
606
|
await updateManifest();
|
|
607
607
|
expect(onError).toHaveBeenCalledTimes(1);
|
|
608
|
+
expect(updateTick).toHaveBeenCalledTimes(2);
|
|
609
|
+
});
|
|
610
|
+
|
|
611
|
+
it('fatal error on manifest update request failure when ' +
|
|
612
|
+
'raiseFatalErrorOnManifestUpdateRequestFailure is true', async () => {
|
|
613
|
+
const manifestConfig =
|
|
614
|
+
shaka.util.PlayerConfiguration.createDefault().manifest;
|
|
615
|
+
manifestConfig.raiseFatalErrorOnManifestUpdateRequestFailure = true;
|
|
616
|
+
parser.configure(manifestConfig);
|
|
617
|
+
|
|
618
|
+
const updateTick = updateTickSpy();
|
|
619
|
+
|
|
620
|
+
const lines = [
|
|
621
|
+
'<SegmentTemplate startNumber="1" media="s$Number$.mp4" duration="2"/>',
|
|
622
|
+
];
|
|
623
|
+
const manifestText = makeSimpleLiveManifestText(lines, updateTime);
|
|
624
|
+
/** @type {!jasmine.Spy} */
|
|
625
|
+
const onError = jasmine.createSpy('onError');
|
|
626
|
+
playerInterface.onError = Util.spyFunc(onError);
|
|
627
|
+
|
|
628
|
+
fakeNetEngine.setResponseText('dummy://foo', manifestText);
|
|
629
|
+
await parser.start('dummy://foo', playerInterface);
|
|
630
|
+
|
|
631
|
+
const error = new shaka.util.Error(
|
|
632
|
+
shaka.util.Error.Severity.CRITICAL,
|
|
633
|
+
shaka.util.Error.Category.NETWORK,
|
|
634
|
+
shaka.util.Error.Code.BAD_HTTP_STATUS);
|
|
635
|
+
const operation = shaka.util.AbortableOperation.failed(error);
|
|
636
|
+
fakeNetEngine.request.and.returnValue(operation);
|
|
637
|
+
|
|
638
|
+
await updateManifest();
|
|
639
|
+
expect(onError).toHaveBeenCalledWith(error);
|
|
640
|
+
expect(updateTick).toHaveBeenCalledTimes(1);
|
|
608
641
|
});
|
|
609
642
|
|
|
610
643
|
it('uses @minimumUpdatePeriod', async () => {
|
|
@@ -640,10 +673,9 @@ describe('DashParser Live', () => {
|
|
|
640
673
|
fakeNetEngine.setResponseText('dummy://foo', manifestText);
|
|
641
674
|
await parser.start('dummy://foo', playerInterface);
|
|
642
675
|
|
|
643
|
-
const waitTime = shaka.dash.DashParser['MIN_UPDATE_PERIOD_'];
|
|
644
676
|
expect(tickAfter).toHaveBeenCalledTimes(1);
|
|
645
677
|
const delay = tickAfter.calls.mostRecent().args[0];
|
|
646
|
-
expect(delay).toBe(
|
|
678
|
+
expect(delay).toBe(0);
|
|
647
679
|
});
|
|
648
680
|
|
|
649
681
|
it('does not update when @minimumUpdatePeriod is missing', async () => {
|
|
@@ -668,8 +700,7 @@ describe('DashParser Live', () => {
|
|
|
668
700
|
'<SegmentTemplate startNumber="1" media="s$Number$.mp4" duration="2" />',
|
|
669
701
|
];
|
|
670
702
|
const extraWaitTime = 15.0;
|
|
671
|
-
const
|
|
672
|
-
const manifestText = makeSimpleLiveManifestText(lines, idealUpdateTime);
|
|
703
|
+
const manifestText = makeSimpleLiveManifestText(lines, 3);
|
|
673
704
|
|
|
674
705
|
let now = 0;
|
|
675
706
|
Date.now = () => now;
|
|
@@ -709,17 +740,21 @@ describe('DashParser Live', () => {
|
|
|
709
740
|
fakeNetEngine.setResponseText('dummy://foo', manifestText);
|
|
710
741
|
|
|
711
742
|
const manifestRequest = shaka.net.NetworkingEngine.RequestType.MANIFEST;
|
|
743
|
+
const manifestContext = {
|
|
744
|
+
type: shaka.net.NetworkingEngine.AdvancedRequestType.MPD,
|
|
745
|
+
};
|
|
712
746
|
await parser.start('dummy://foo', playerInterface);
|
|
713
747
|
|
|
714
748
|
expect(fakeNetEngine.request).toHaveBeenCalledTimes(1);
|
|
715
|
-
fakeNetEngine.expectRequest('dummy://foo', manifestRequest);
|
|
749
|
+
fakeNetEngine.expectRequest('dummy://foo', manifestRequest, manifestContext);
|
|
716
750
|
fakeNetEngine.request.calls.reset();
|
|
717
751
|
|
|
718
752
|
// Create a mock so we can verify it gives two URIs.
|
|
719
753
|
// The third location is a relative url, and should be resolved as an
|
|
720
754
|
// absolute url.
|
|
721
|
-
fakeNetEngine.request.and.callFake((type, request) => {
|
|
755
|
+
fakeNetEngine.request.and.callFake((type, request, context) => {
|
|
722
756
|
expect(type).toBe(manifestRequest);
|
|
757
|
+
expect(context).toEqual(manifestContext);
|
|
723
758
|
expect(request.uris).toEqual(
|
|
724
759
|
['http://foobar', 'http://foobar2', 'dummy://foo/foobar3']);
|
|
725
760
|
const data = shaka.util.StringUtils.toUTF8(manifestText);
|
|
@@ -952,6 +987,9 @@ describe('DashParser Live', () => {
|
|
|
952
987
|
|
|
953
988
|
describe('stop', () => {
|
|
954
989
|
const manifestRequestType = shaka.net.NetworkingEngine.RequestType.MANIFEST;
|
|
990
|
+
const manifestContext = {
|
|
991
|
+
type: shaka.net.NetworkingEngine.AdvancedRequestType.MPD,
|
|
992
|
+
};
|
|
955
993
|
const dateRequestType = shaka.net.NetworkingEngine.RequestType.TIMING;
|
|
956
994
|
const manifestUri = 'dummy://foo';
|
|
957
995
|
const dateUri = 'http://foo.bar/date';
|
|
@@ -983,7 +1021,8 @@ describe('DashParser Live', () => {
|
|
|
983
1021
|
it('stops updates', async () => {
|
|
984
1022
|
await parser.start(manifestUri, playerInterface);
|
|
985
1023
|
|
|
986
|
-
fakeNetEngine.expectRequest(
|
|
1024
|
+
fakeNetEngine.expectRequest(
|
|
1025
|
+
manifestUri, manifestRequestType, manifestContext);
|
|
987
1026
|
fakeNetEngine.request.calls.reset();
|
|
988
1027
|
|
|
989
1028
|
parser.stop();
|
|
@@ -1001,7 +1040,8 @@ describe('DashParser Live', () => {
|
|
|
1001
1040
|
parser.stop();
|
|
1002
1041
|
await expectation;
|
|
1003
1042
|
|
|
1004
|
-
fakeNetEngine.expectRequest(
|
|
1043
|
+
fakeNetEngine.expectRequest(
|
|
1044
|
+
manifestUri, manifestRequestType, manifestContext);
|
|
1005
1045
|
fakeNetEngine.request.calls.reset();
|
|
1006
1046
|
await updateManifest();
|
|
1007
1047
|
// An update should not occur.
|
|
@@ -1012,7 +1052,8 @@ describe('DashParser Live', () => {
|
|
|
1012
1052
|
const manifest = await parser.start('dummy://foo', playerInterface);
|
|
1013
1053
|
|
|
1014
1054
|
expect(manifest).toBeTruthy();
|
|
1015
|
-
fakeNetEngine.expectRequest(
|
|
1055
|
+
fakeNetEngine.expectRequest(
|
|
1056
|
+
manifestUri, manifestRequestType, manifestContext);
|
|
1016
1057
|
fakeNetEngine.request.calls.reset();
|
|
1017
1058
|
/** @type {!shaka.util.PublicPromise} */
|
|
1018
1059
|
const delay = fakeNetEngine.delayNextRequest();
|
|
@@ -1020,7 +1061,8 @@ describe('DashParser Live', () => {
|
|
|
1020
1061
|
await updateManifest();
|
|
1021
1062
|
// The request was made but should not be resolved yet.
|
|
1022
1063
|
expect(fakeNetEngine.request).toHaveBeenCalledTimes(1);
|
|
1023
|
-
fakeNetEngine.expectRequest(
|
|
1064
|
+
fakeNetEngine.expectRequest(
|
|
1065
|
+
manifestUri, manifestRequestType, manifestContext);
|
|
1024
1066
|
fakeNetEngine.request.calls.reset();
|
|
1025
1067
|
parser.stop();
|
|
1026
1068
|
delay.resolve();
|
|
@@ -1041,7 +1083,8 @@ describe('DashParser Live', () => {
|
|
|
1041
1083
|
await Util.shortDelay();
|
|
1042
1084
|
// This is the initial manifest request.
|
|
1043
1085
|
expect(fakeNetEngine.request).toHaveBeenCalledTimes(1);
|
|
1044
|
-
fakeNetEngine.expectRequest(
|
|
1086
|
+
fakeNetEngine.expectRequest(
|
|
1087
|
+
manifestUri, manifestRequestType, manifestContext);
|
|
1045
1088
|
fakeNetEngine.request.calls.reset();
|
|
1046
1089
|
// Resolve the manifest request and wait on the UTCTiming request.
|
|
1047
1090
|
delay.resolve();
|
|
@@ -140,7 +140,7 @@ describe('DashParser Manifest', () => {
|
|
|
140
140
|
' <Representation bandwidth="50" width="576" height="432" />',
|
|
141
141
|
' </AdaptationSet>',
|
|
142
142
|
' <AdaptationSet mimeType="text/vtt"',
|
|
143
|
-
' lang="
|
|
143
|
+
' lang="spa" label="spanish">',
|
|
144
144
|
' <Role value="caption" />',
|
|
145
145
|
' <Role value="main" />',
|
|
146
146
|
' <Representation bandwidth="100" />',
|
|
@@ -155,6 +155,7 @@ describe('DashParser Manifest', () => {
|
|
|
155
155
|
],
|
|
156
156
|
shaka.test.ManifestGenerator.generate((manifest) => {
|
|
157
157
|
manifest.sequenceMode = true;
|
|
158
|
+
manifest.type = shaka.media.ManifestParser.DASH;
|
|
158
159
|
manifest.anyTimeline();
|
|
159
160
|
manifest.minBufferTime = 75;
|
|
160
161
|
manifest.addPartialVariant((variant) => {
|
|
@@ -193,6 +194,7 @@ describe('DashParser Manifest', () => {
|
|
|
193
194
|
});
|
|
194
195
|
manifest.addPartialTextStream((stream) => {
|
|
195
196
|
stream.language = 'es';
|
|
197
|
+
stream.originalLanguage = 'spa';
|
|
196
198
|
stream.label = 'spanish';
|
|
197
199
|
stream.primary = true;
|
|
198
200
|
stream.mimeType = 'text/vtt';
|
|
@@ -239,6 +241,7 @@ describe('DashParser Manifest', () => {
|
|
|
239
241
|
],
|
|
240
242
|
shaka.test.ManifestGenerator.generate((manifest) => {
|
|
241
243
|
manifest.sequenceMode = false;
|
|
244
|
+
manifest.type = shaka.media.ManifestParser.DASH;
|
|
242
245
|
manifest.anyTimeline();
|
|
243
246
|
manifest.minBufferTime = 75;
|
|
244
247
|
manifest.addPartialVariant((variant) => {
|
|
@@ -725,7 +728,7 @@ describe('DashParser Manifest', () => {
|
|
|
725
728
|
' value="http://foo.bar/date" />',
|
|
726
729
|
]);
|
|
727
730
|
|
|
728
|
-
fakeNetEngine.request.and.callFake((type, request) => {
|
|
731
|
+
fakeNetEngine.request.and.callFake((type, request, context) => {
|
|
729
732
|
if (request.uris[0] == 'http://foo.bar/manifest') {
|
|
730
733
|
const data = shaka.util.StringUtils.toUTF8(source);
|
|
731
734
|
return shaka.util.AbortableOperation.completed({
|
|
@@ -1862,6 +1865,49 @@ describe('DashParser Manifest', () => {
|
|
|
1862
1865
|
expect(stream).toBeUndefined();
|
|
1863
1866
|
});
|
|
1864
1867
|
|
|
1868
|
+
it('reads accessibility purpose elements', async () => {
|
|
1869
|
+
const manifestText = [
|
|
1870
|
+
'<MPD minBufferTime="PT75S">',
|
|
1871
|
+
' <Period id="1" duration="PT30S">',
|
|
1872
|
+
' <AdaptationSet id="1" contentType="text">',
|
|
1873
|
+
' <Accessibility ',
|
|
1874
|
+
' schemeIdUri="urn:tva:metadata:cs:AudioPurposeCS:2007"',
|
|
1875
|
+
' value="2" />',
|
|
1876
|
+
' <Representation id="text-en" mimeType="text/webvtt">',
|
|
1877
|
+
' <BaseURL>t-en.vtt</BaseURL>',
|
|
1878
|
+
' </Representation>',
|
|
1879
|
+
' </AdaptationSet>',
|
|
1880
|
+
' <AdaptationSet id="1" mimeType="video/mp4">',
|
|
1881
|
+
' <Representation id="video-sd" width="640" height="480">',
|
|
1882
|
+
' <BaseURL>v-sd.mp4</BaseURL>',
|
|
1883
|
+
' <SegmentBase indexRange="100-200" />',
|
|
1884
|
+
' </Representation>',
|
|
1885
|
+
' </AdaptationSet>',
|
|
1886
|
+
' <AdaptationSet id="1" mimeType="audio/mp4">',
|
|
1887
|
+
' <Accessibility ',
|
|
1888
|
+
' schemeIdUri="urn:tva:metadata:cs:AudioPurposeCS:2007"',
|
|
1889
|
+
' value="1" />',
|
|
1890
|
+
' <Representation id="audio-sd" width="640" height="480">',
|
|
1891
|
+
' <BaseURL>v-sd.mp4</BaseURL>',
|
|
1892
|
+
' <SegmentBase indexRange="100-200" />',
|
|
1893
|
+
' </Representation>',
|
|
1894
|
+
' </AdaptationSet>',
|
|
1895
|
+
' </Period>',
|
|
1896
|
+
'</MPD>',
|
|
1897
|
+
].join('\n');
|
|
1898
|
+
|
|
1899
|
+
fakeNetEngine.setResponseText('dummy://foo', manifestText);
|
|
1900
|
+
/** @type {shaka.extern.Manifest} */
|
|
1901
|
+
const manifest = await parser.start('dummy://foo', playerInterface);
|
|
1902
|
+
const textStream = manifest.textStreams[0];
|
|
1903
|
+
expect(textStream.accessibilityPurpose).toBe(
|
|
1904
|
+
shaka.media.ManifestParser.AccessibilityPurpose.HARD_OF_HEARING);
|
|
1905
|
+
const variant = manifest.variants[0];
|
|
1906
|
+
expect(variant.video.accessibilityPurpose).toBeUndefined();
|
|
1907
|
+
expect(variant.audio.accessibilityPurpose).toBe(
|
|
1908
|
+
shaka.media.ManifestParser.AccessibilityPurpose.VISUALLY_IMPAIRED);
|
|
1909
|
+
});
|
|
1910
|
+
|
|
1865
1911
|
it('converts Accessibility element to "kind"', async () => {
|
|
1866
1912
|
const manifestText = [
|
|
1867
1913
|
'<MPD minBufferTime="PT75S">',
|
|
@@ -2511,4 +2557,26 @@ describe('DashParser Manifest', () => {
|
|
|
2511
2557
|
expect(segments[0][1].startTime).toBe(15);
|
|
2512
2558
|
expect(segments[1][1].startTime).toBe(15);
|
|
2513
2559
|
});
|
|
2560
|
+
|
|
2561
|
+
describe('Parses ServiceDescription', () => {
|
|
2562
|
+
it('with PlaybackRate and Latency', async () => {
|
|
2563
|
+
const source = [
|
|
2564
|
+
'<MPD minBufferTime="PT75S" type="dynamic"',
|
|
2565
|
+
' availabilityStartTime="1970-01-01T00:00:00Z">',
|
|
2566
|
+
' <ServiceDescription id="0">',
|
|
2567
|
+
' <Latency max="2000" min="2000" referenceId="0" target="4000" />',
|
|
2568
|
+
' <PlaybackRate max="1.10" min="0.96" />',
|
|
2569
|
+
' </ServiceDescription>',
|
|
2570
|
+
'</MPD>',
|
|
2571
|
+
].join('\n');
|
|
2572
|
+
|
|
2573
|
+
fakeNetEngine.setResponseText('dummy://foo', source);
|
|
2574
|
+
|
|
2575
|
+
/** @type {shaka.extern.Manifest} */
|
|
2576
|
+
const manifest = await parser.start('dummy://foo', playerInterface);
|
|
2577
|
+
|
|
2578
|
+
expect(manifest.serviceDescription.maxLatency).toBe(2);
|
|
2579
|
+
expect(manifest.serviceDescription.maxPlaybackRate).toBe(1.1);
|
|
2580
|
+
});
|
|
2581
|
+
});
|
|
2514
2582
|
});
|
|
@@ -87,13 +87,13 @@ describe('DashParser SegmentBase', () => {
|
|
|
87
87
|
|
|
88
88
|
// Expect calls to fetch part of the media and init segments of each stream.
|
|
89
89
|
fakeNetEngine.expectRangeRequest(
|
|
90
|
-
'http://example.com/media-1.webm', 100, 200);
|
|
90
|
+
'http://example.com/media-1.webm', 100, 200, /* isInit= */ false);
|
|
91
91
|
fakeNetEngine.expectRangeRequest(
|
|
92
|
-
'http://example.com/init-1.webm', 201, 300);
|
|
92
|
+
'http://example.com/init-1.webm', 201, 300, /* isInit= */ true);
|
|
93
93
|
fakeNetEngine.expectRangeRequest(
|
|
94
|
-
'http://example.com/media-2.webm', 1100, 1200);
|
|
94
|
+
'http://example.com/media-2.webm', 1100, 1200, /* isInit= */ false);
|
|
95
95
|
fakeNetEngine.expectRangeRequest(
|
|
96
|
-
'http://example.com/init-2.webm', 1201, 1300);
|
|
96
|
+
'http://example.com/init-2.webm', 1201, 1300, /* isInit= */ true);
|
|
97
97
|
});
|
|
98
98
|
|
|
99
99
|
it('inherits from Period', async () => {
|
|
@@ -125,7 +125,8 @@ describe('DashParser SegmentBase', () => {
|
|
|
125
125
|
expect(initSegmentReference.getEndByte()).toBe(300);
|
|
126
126
|
|
|
127
127
|
expect(fakeNetEngine.request).toHaveBeenCalledTimes(2);
|
|
128
|
-
fakeNetEngine.expectRangeRequest(
|
|
128
|
+
fakeNetEngine.expectRangeRequest(
|
|
129
|
+
'http://example.com', 100, 200, /* isInit= */ false);
|
|
129
130
|
});
|
|
130
131
|
|
|
131
132
|
it('inherits from AdaptationSet', async () => {
|
|
@@ -157,7 +158,8 @@ describe('DashParser SegmentBase', () => {
|
|
|
157
158
|
expect(initSegmentReference.getEndByte()).toBe(300);
|
|
158
159
|
|
|
159
160
|
expect(fakeNetEngine.request).toHaveBeenCalledTimes(2);
|
|
160
|
-
fakeNetEngine.expectRangeRequest(
|
|
161
|
+
fakeNetEngine.expectRangeRequest(
|
|
162
|
+
'http://example.com', 100, 200, /* isInit= */ false);
|
|
161
163
|
});
|
|
162
164
|
|
|
163
165
|
it('does not require sourceURL in Initialization', async () => {
|
|
@@ -190,7 +192,8 @@ describe('DashParser SegmentBase', () => {
|
|
|
190
192
|
expect(initSegmentReference.getEndByte()).toBe(300);
|
|
191
193
|
|
|
192
194
|
expect(fakeNetEngine.request).toHaveBeenCalledTimes(2);
|
|
193
|
-
fakeNetEngine.expectRangeRequest(
|
|
195
|
+
fakeNetEngine.expectRangeRequest(
|
|
196
|
+
'http://example.com/stream.mp4', 100, 200, /* isInit= */ false);
|
|
194
197
|
});
|
|
195
198
|
|
|
196
199
|
it('merges across levels', async () => {
|
|
@@ -230,7 +233,8 @@ describe('DashParser SegmentBase', () => {
|
|
|
230
233
|
expect(segmentReference.timestampOffset).toBe(-10);
|
|
231
234
|
|
|
232
235
|
expect(fakeNetEngine.request).toHaveBeenCalledTimes(2);
|
|
233
|
-
fakeNetEngine.expectRangeRequest(
|
|
236
|
+
fakeNetEngine.expectRangeRequest(
|
|
237
|
+
'http://example.com/index.mp4', 5, 2000, /* isInit= */ false);
|
|
234
238
|
});
|
|
235
239
|
|
|
236
240
|
it('merges and overrides across levels', async () => {
|
|
@@ -269,7 +273,8 @@ describe('DashParser SegmentBase', () => {
|
|
|
269
273
|
expect(segmentReference.timestampOffset).toBe(-20);
|
|
270
274
|
|
|
271
275
|
expect(fakeNetEngine.request).toHaveBeenCalledTimes(2);
|
|
272
|
-
fakeNetEngine.expectRangeRequest(
|
|
276
|
+
fakeNetEngine.expectRangeRequest(
|
|
277
|
+
'http://example.com', 30, 900, /* isInit= */ false);
|
|
273
278
|
});
|
|
274
279
|
|
|
275
280
|
it('does not assume the same timescale as media', async () => {
|
|
@@ -198,7 +198,7 @@ describe('DashParser SegmentTemplate', () => {
|
|
|
198
198
|
|
|
199
199
|
expect(fakeNetEngine.request).toHaveBeenCalledTimes(2);
|
|
200
200
|
fakeNetEngine.expectRangeRequest(
|
|
201
|
-
'http://example.com/index-500.mp4', 0, null);
|
|
201
|
+
'http://example.com/index-500.mp4', 0, null, /* isInit= */ false);
|
|
202
202
|
});
|
|
203
203
|
|
|
204
204
|
it('defaults to index with multiple segment sources', async () => {
|
|
@@ -226,7 +226,7 @@ describe('DashParser SegmentTemplate', () => {
|
|
|
226
226
|
|
|
227
227
|
expect(fakeNetEngine.request).toHaveBeenCalledTimes(2);
|
|
228
228
|
fakeNetEngine.expectRangeRequest(
|
|
229
|
-
'http://example.com/index-500.mp4', 0, null);
|
|
229
|
+
'http://example.com/index-500.mp4', 0, null, /* isInit= */ false);
|
|
230
230
|
});
|
|
231
231
|
|
|
232
232
|
it('requests init data for WebM', async () => {
|
|
@@ -261,9 +261,9 @@ describe('DashParser SegmentTemplate', () => {
|
|
|
261
261
|
|
|
262
262
|
expect(fakeNetEngine.request).toHaveBeenCalledTimes(3);
|
|
263
263
|
fakeNetEngine.expectRangeRequest(
|
|
264
|
-
'http://example.com/init-500.webm', 0, null);
|
|
264
|
+
'http://example.com/init-500.webm', 0, null, /* isInit= */ true);
|
|
265
265
|
fakeNetEngine.expectRangeRequest(
|
|
266
|
-
'http://example.com/index-500.webm', 0, null);
|
|
266
|
+
'http://example.com/index-500.webm', 0, null, /* isInit= */ false);
|
|
267
267
|
});
|
|
268
268
|
|
|
269
269
|
it('inherits from Period', async () => {
|
|
@@ -295,7 +295,7 @@ describe('DashParser SegmentTemplate', () => {
|
|
|
295
295
|
|
|
296
296
|
expect(fakeNetEngine.request).toHaveBeenCalledTimes(2);
|
|
297
297
|
fakeNetEngine.expectRangeRequest(
|
|
298
|
-
'http://example.com/index-500.mp4', 0, null);
|
|
298
|
+
'http://example.com/index-500.mp4', 0, null, /* isInit= */ false);
|
|
299
299
|
});
|
|
300
300
|
|
|
301
301
|
it('inherits from AdaptationSet', async () => {
|
|
@@ -327,7 +327,7 @@ describe('DashParser SegmentTemplate', () => {
|
|
|
327
327
|
|
|
328
328
|
expect(fakeNetEngine.request).toHaveBeenCalledTimes(2);
|
|
329
329
|
fakeNetEngine.expectRangeRequest(
|
|
330
|
-
'http://example.com/index-500.mp4', 0, null);
|
|
330
|
+
'http://example.com/index-500.mp4', 0, null, /* isInit= */ false);
|
|
331
331
|
});
|
|
332
332
|
});
|
|
333
333
|
|
|
@@ -578,4 +578,284 @@ describe('DashParser SegmentTemplate', () => {
|
|
|
578
578
|
await Dash.testFails(source, error);
|
|
579
579
|
});
|
|
580
580
|
});
|
|
581
|
+
|
|
582
|
+
describe('TimelineSegmentIndex', () => {
|
|
583
|
+
describe('find', () => {
|
|
584
|
+
it('finds the correct references', async () => {
|
|
585
|
+
const info = makeTemplateInfo(makeRanges(0, 2.0, 10));
|
|
586
|
+
const infoClone = shaka.util.ObjectUtils.cloneObject(info);
|
|
587
|
+
const index = await makeTimelineSegmentIndex(infoClone,
|
|
588
|
+
/* delayPeriodEnd= */ true,
|
|
589
|
+
/* shouldFit= */ true);
|
|
590
|
+
|
|
591
|
+
const pos1 = index.find(1.0);
|
|
592
|
+
expect(pos1).toBe(0);
|
|
593
|
+
const pos2 = index.find(2.0);
|
|
594
|
+
expect(pos2).toBe(1);
|
|
595
|
+
|
|
596
|
+
// After the end of the last reference but before the end of the period
|
|
597
|
+
// should return index of the last reference
|
|
598
|
+
const lastRef = info.timeline[info.timeline.length - 1];
|
|
599
|
+
const pos3 = index.find(lastRef.end + 0.5);
|
|
600
|
+
expect(pos3).toBe(info.timeline.length - 1);
|
|
601
|
+
|
|
602
|
+
const pos4 = index.find(123.45);
|
|
603
|
+
expect(pos4).toBeNull();
|
|
604
|
+
});
|
|
605
|
+
|
|
606
|
+
it('finds correct position if time is in gap', async () => {
|
|
607
|
+
const ranges = [
|
|
608
|
+
{
|
|
609
|
+
start: 0,
|
|
610
|
+
end: 2,
|
|
611
|
+
unscaledStart: 0,
|
|
612
|
+
},
|
|
613
|
+
{
|
|
614
|
+
start: 3,
|
|
615
|
+
end: 5,
|
|
616
|
+
unscaledStart: 3 * 90000,
|
|
617
|
+
},
|
|
618
|
+
];
|
|
619
|
+
const info = makeTemplateInfo(ranges);
|
|
620
|
+
const index = await makeTimelineSegmentIndex(info);
|
|
621
|
+
const pos = index.find(2.5);
|
|
622
|
+
expect(pos).toBe(0);
|
|
623
|
+
});
|
|
624
|
+
|
|
625
|
+
it('finds correct position if time === first start time', async () => {
|
|
626
|
+
const info = makeTemplateInfo(makeRanges(0, 2.0, 10));
|
|
627
|
+
const index = await makeTimelineSegmentIndex(info);
|
|
628
|
+
|
|
629
|
+
const pos = index.find(0);
|
|
630
|
+
expect(pos).toBe(0);
|
|
631
|
+
});
|
|
632
|
+
|
|
633
|
+
it('finds correct position if time === first end time', async () => {
|
|
634
|
+
const ranges = [
|
|
635
|
+
{
|
|
636
|
+
start: 0,
|
|
637
|
+
end: 2,
|
|
638
|
+
unscaledStart: 0,
|
|
639
|
+
},
|
|
640
|
+
{
|
|
641
|
+
start: 2.1,
|
|
642
|
+
end: 5,
|
|
643
|
+
unscaledStart: 3 * 90000,
|
|
644
|
+
},
|
|
645
|
+
];
|
|
646
|
+
const info = makeTemplateInfo(ranges);
|
|
647
|
+
const index = await makeTimelineSegmentIndex(info);
|
|
648
|
+
|
|
649
|
+
const pos = index.find(2.0);
|
|
650
|
+
expect(pos).toBe(0);
|
|
651
|
+
});
|
|
652
|
+
|
|
653
|
+
it('finds correct position if time === second start time', async () => {
|
|
654
|
+
const ranges = [
|
|
655
|
+
{
|
|
656
|
+
start: 0,
|
|
657
|
+
end: 2,
|
|
658
|
+
unscaledStart: 0,
|
|
659
|
+
},
|
|
660
|
+
{
|
|
661
|
+
start: 2.1,
|
|
662
|
+
end: 5,
|
|
663
|
+
unscaledStart: 3 * 90000,
|
|
664
|
+
},
|
|
665
|
+
];
|
|
666
|
+
const info = makeTemplateInfo(ranges);
|
|
667
|
+
const index = await makeTimelineSegmentIndex(info);
|
|
668
|
+
|
|
669
|
+
const pos = index.find(2.1);
|
|
670
|
+
expect(pos).toBe(1);
|
|
671
|
+
});
|
|
672
|
+
|
|
673
|
+
|
|
674
|
+
it('returns null if time === last end time', async () => {
|
|
675
|
+
const info = makeTemplateInfo(makeRanges(0, 2.0, 2));
|
|
676
|
+
const index = await makeTimelineSegmentIndex(info, false);
|
|
677
|
+
|
|
678
|
+
const pos = index.find(4.0);
|
|
679
|
+
expect(pos).toBeNull();
|
|
680
|
+
});
|
|
681
|
+
|
|
682
|
+
it('returns null if time > last end time', async () => {
|
|
683
|
+
const info = makeTemplateInfo(makeRanges(0, 2.0, 2));
|
|
684
|
+
const index = await makeTimelineSegmentIndex(info, false);
|
|
685
|
+
|
|
686
|
+
const pos = index.find(6.0);
|
|
687
|
+
expect(pos).toBeNull();
|
|
688
|
+
});
|
|
689
|
+
});
|
|
690
|
+
describe('get', () => {
|
|
691
|
+
it('creates a segment reference for a given position', async () => {
|
|
692
|
+
const info = makeTemplateInfo(makeRanges(0, 2.0, 10));
|
|
693
|
+
const index = await makeTimelineSegmentIndex(info);
|
|
694
|
+
const pos = index.find(2.0);
|
|
695
|
+
goog.asserts.assert(pos != null, 'Null position!');
|
|
696
|
+
const ref = index.get(pos);
|
|
697
|
+
expect(ref).toEqual(jasmine.objectContaining({
|
|
698
|
+
'startTime': 2,
|
|
699
|
+
'endTime': 4,
|
|
700
|
+
'trueEndTime': 4,
|
|
701
|
+
'startByte': 0,
|
|
702
|
+
'endByte': null,
|
|
703
|
+
'timestampOffset': 0,
|
|
704
|
+
'appendWindowStart': 0,
|
|
705
|
+
'appendWindowEnd': 21,
|
|
706
|
+
'partialReferences': [],
|
|
707
|
+
'tilesLayout': '',
|
|
708
|
+
'tileDuration': null,
|
|
709
|
+
}));
|
|
710
|
+
});
|
|
711
|
+
|
|
712
|
+
it('returns null if a position is unknown', async () => {
|
|
713
|
+
const info = makeTemplateInfo(makeRanges(0, 2.0, 10));
|
|
714
|
+
const index = await makeTimelineSegmentIndex(info);
|
|
715
|
+
const ref = index.get(12345);
|
|
716
|
+
expect(ref).toBeNull();
|
|
717
|
+
});
|
|
718
|
+
|
|
719
|
+
it('returns null if a position < 0', async () => {
|
|
720
|
+
const info = makeTemplateInfo(makeRanges(0, 2.0, 10));
|
|
721
|
+
const index = await makeTimelineSegmentIndex(info);
|
|
722
|
+
const ref = index.get(-12);
|
|
723
|
+
expect(ref).toBeNull();
|
|
724
|
+
});
|
|
725
|
+
});
|
|
726
|
+
|
|
727
|
+
describe('appendTemplateInfo', () => {
|
|
728
|
+
it('appends new timeline to existing', async () => {
|
|
729
|
+
const initialRanges = makeRanges(0, 2.0, 10);
|
|
730
|
+
const info = makeTemplateInfo(initialRanges);
|
|
731
|
+
const index = await makeTimelineSegmentIndex(info, false);
|
|
732
|
+
|
|
733
|
+
const newStart = initialRanges[initialRanges.length - 1].end;
|
|
734
|
+
expect(index.find(newStart)).toBeNull();
|
|
735
|
+
|
|
736
|
+
const newRanges = makeRanges(newStart, 2.0, 10);
|
|
737
|
+
const newTemplateInfo = makeTemplateInfo(newRanges);
|
|
738
|
+
|
|
739
|
+
const newEnd = newRanges[newRanges.length - 1].end;
|
|
740
|
+
index.appendTemplateInfo(newTemplateInfo, newEnd);
|
|
741
|
+
expect(index.find(newStart)).toBe(10);
|
|
742
|
+
expect(index.find(newEnd - 1.0)).toBe(19);
|
|
743
|
+
});
|
|
744
|
+
});
|
|
745
|
+
|
|
746
|
+
describe('evict', () => {
|
|
747
|
+
it('evicts old entries and maintains position', async () => {
|
|
748
|
+
const initialRanges = makeRanges(0, 2.0, 10);
|
|
749
|
+
const info = makeTemplateInfo(initialRanges);
|
|
750
|
+
const index = await makeTimelineSegmentIndex(info, false);
|
|
751
|
+
|
|
752
|
+
index.evict(4.0);
|
|
753
|
+
expect(index.find(2.0)).toBe(2);
|
|
754
|
+
expect(index.find(6.0)).toBe(3);
|
|
755
|
+
});
|
|
756
|
+
});
|
|
757
|
+
});
|
|
758
|
+
|
|
759
|
+
/**
|
|
760
|
+
*
|
|
761
|
+
* @param {shaka.dash.SegmentTemplate.SegmentTemplateInfo} info
|
|
762
|
+
* @param {boolean} delayPeriodEnd
|
|
763
|
+
* @param {boolean} shouldFit
|
|
764
|
+
* @return {?}
|
|
765
|
+
*/
|
|
766
|
+
async function makeTimelineSegmentIndex(info, delayPeriodEnd = true,
|
|
767
|
+
shouldFit = false) {
|
|
768
|
+
// Period end may be a bit after the last timeline entry
|
|
769
|
+
let periodEnd = info.timeline[info.timeline.length - 1].end;
|
|
770
|
+
if (delayPeriodEnd) {
|
|
771
|
+
periodEnd += 1.0;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
const dummySource = Dash.makeSimpleManifestText([
|
|
775
|
+
'<SegmentTemplate startNumber="0" duration="10"',
|
|
776
|
+
' media="$Number$-$Time$-$Bandwidth$.mp4">',
|
|
777
|
+
' <SegmentTimeline>',
|
|
778
|
+
' <S t="0" d="15" r="2" />',
|
|
779
|
+
' </SegmentTimeline>',
|
|
780
|
+
'</SegmentTemplate>',
|
|
781
|
+
], /* duration= */ 45);
|
|
782
|
+
|
|
783
|
+
fakeNetEngine.setResponseText('dummy://foo', dummySource);
|
|
784
|
+
const manifest = await parser.start('dummy://foo', playerInterface);
|
|
785
|
+
|
|
786
|
+
expect(manifest.variants.length).toBe(1);
|
|
787
|
+
|
|
788
|
+
const stream = manifest.variants[0].video;
|
|
789
|
+
expect(stream).toBeTruthy();
|
|
790
|
+
await stream.createSegmentIndex();
|
|
791
|
+
|
|
792
|
+
/** @type {?} */
|
|
793
|
+
const index = stream.segmentIndex;
|
|
794
|
+
index.release();
|
|
795
|
+
index.appendTemplateInfo(info, info.timeline[0].start,
|
|
796
|
+
periodEnd, shouldFit);
|
|
797
|
+
|
|
798
|
+
return index;
|
|
799
|
+
}
|
|
581
800
|
});
|
|
801
|
+
|
|
802
|
+
/**
|
|
803
|
+
* Creates a URI string.
|
|
804
|
+
*
|
|
805
|
+
* @param {number} x
|
|
806
|
+
* @return {string}
|
|
807
|
+
*/
|
|
808
|
+
function uri(x) {
|
|
809
|
+
return 'http://example.com/video_' + x + '.m4s';
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
/**
|
|
813
|
+
*
|
|
814
|
+
* @return {shaka.media.InitSegmentReference}
|
|
815
|
+
*/
|
|
816
|
+
function makeInitSegmentReference() {
|
|
817
|
+
return new shaka.media.InitSegmentReference(() => [], 0, null);
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
/**
|
|
821
|
+
* Create a list of continuous time ranges
|
|
822
|
+
* @param {number} start
|
|
823
|
+
* @param {number} duration
|
|
824
|
+
* @param {number} num
|
|
825
|
+
* @return {Array<shaka.media.PresentationTimeline.TimeRange>}
|
|
826
|
+
*/
|
|
827
|
+
function makeRanges(start, duration, num) {
|
|
828
|
+
const ranges = [];
|
|
829
|
+
let currentPos = start;
|
|
830
|
+
for (let i = 0; i < num; i += 1) {
|
|
831
|
+
ranges.push({
|
|
832
|
+
start: currentPos,
|
|
833
|
+
end: currentPos + duration,
|
|
834
|
+
unscaledStart: currentPos * 90000,
|
|
835
|
+
});
|
|
836
|
+
currentPos += duration;
|
|
837
|
+
}
|
|
838
|
+
return ranges;
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
/**
|
|
842
|
+
* Creates a real SegmentReference. This is distinct from the fake ones used
|
|
843
|
+
* in ManifestParser tests because it can be on the left-hand side of an
|
|
844
|
+
* expect(). You can't expect jasmine.any(Number) to equal
|
|
845
|
+
* jasmine.any(Number). :-(
|
|
846
|
+
*
|
|
847
|
+
* @param {Array<shaka.media.PresentationTimeline.TimeRange>} timeline
|
|
848
|
+
* @return {shaka.dash.SegmentTemplate.SegmentTemplateInfo}
|
|
849
|
+
*/
|
|
850
|
+
function makeTemplateInfo(timeline) {
|
|
851
|
+
return {
|
|
852
|
+
'segmentDuration': null,
|
|
853
|
+
'timescale': 90000,
|
|
854
|
+
'startNumber': 1,
|
|
855
|
+
'scaledPresentationTimeOffset': 0,
|
|
856
|
+
'unscaledPresentationTimeOffset': 0,
|
|
857
|
+
'timeline': timeline,
|
|
858
|
+
'mediaTemplate': 'master_540_2997_$Number%09d$.cmfv',
|
|
859
|
+
'indexTemplate': null,
|
|
860
|
+
};
|
|
861
|
+
}
|
package/test/demo/demo_unit.js
CHANGED
|
@@ -95,8 +95,12 @@ describe('Demo', () => {
|
|
|
95
95
|
.add('playRangeEnd')
|
|
96
96
|
.add('manifest.dash.keySystemsByURI')
|
|
97
97
|
.add('manifest.hls.mediaPlaylistFullMimeType')
|
|
98
|
+
.add('manifest.mss.keySystemsBySystemId')
|
|
98
99
|
.add('drm.keySystemsMapping')
|
|
99
|
-
.add('streaming.parsePrftBox')
|
|
100
|
+
.add('streaming.parsePrftBox')
|
|
101
|
+
.add('manifest.raiseFatalErrorOnManifestUpdateRequestFailure')
|
|
102
|
+
.add('drm.persistentSessionOnlinePlayback')
|
|
103
|
+
.add('drm.persistentSessionsMetadata');
|
|
100
104
|
|
|
101
105
|
/**
|
|
102
106
|
* @param {!Object} section
|