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
package/lib/player.js
CHANGED
|
@@ -590,7 +590,8 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
590
590
|
new shaka.media.PreferenceBasedCriteria(
|
|
591
591
|
this.config_.preferredAudioLanguage,
|
|
592
592
|
this.config_.preferredVariantRole,
|
|
593
|
-
this.config_.preferredAudioChannelCount
|
|
593
|
+
this.config_.preferredAudioChannelCount,
|
|
594
|
+
this.config_.preferredVideoHdrLevel);
|
|
594
595
|
|
|
595
596
|
/** @private {string} */
|
|
596
597
|
this.currentTextLanguage_ = this.config_.preferredTextLanguage;
|
|
@@ -617,6 +618,10 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
617
618
|
dependencyInjector(this);
|
|
618
619
|
}
|
|
619
620
|
|
|
621
|
+
|
|
622
|
+
// Create the CMCD manager so client data can be attached to all requests
|
|
623
|
+
this.cmcdManager_ = this.createCmcd_();
|
|
624
|
+
|
|
620
625
|
this.networkingEngine_ = this.createNetworkingEngine();
|
|
621
626
|
this.networkingEngine_.setForceHTTPS(this.config_.streaming.forceHTTPS);
|
|
622
627
|
|
|
@@ -630,6 +635,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
630
635
|
// If the browser comes back online after being offline, then try to play
|
|
631
636
|
// again.
|
|
632
637
|
this.globalEventManager_.listen(window, 'online', () => {
|
|
638
|
+
this.restoreDisabledVariants_();
|
|
633
639
|
this.retryStreaming();
|
|
634
640
|
});
|
|
635
641
|
|
|
@@ -799,13 +805,13 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
799
805
|
const edge = shaka.util.Platform.isEdge() ||
|
|
800
806
|
shaka.util.Platform.isLegacyEdge();
|
|
801
807
|
if (edge) {
|
|
802
|
-
if (!config.
|
|
808
|
+
if (!config.mediaSource.forceTransmux) {
|
|
803
809
|
// If forceTransmux is disabled for Microsoft Edge, LCEVC data
|
|
804
810
|
// is stripped out in case of a MPEG-2 TS container.
|
|
805
811
|
// Hence the warning for Microsoft Edge when playing content with
|
|
806
812
|
// MPEG-2 TS container.
|
|
807
813
|
shaka.log.alwaysWarn('LCEVC Warning: For MPEG-2 TS decoding '+
|
|
808
|
-
'the config.
|
|
814
|
+
'the config.mediaSource.forceTransmux must be enabled.');
|
|
809
815
|
}
|
|
810
816
|
}
|
|
811
817
|
}
|
|
@@ -1310,9 +1316,6 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
1310
1316
|
// before we allow calls to |updateStateHistory|.
|
|
1311
1317
|
this.stats_ = new shaka.util.Stats();
|
|
1312
1318
|
|
|
1313
|
-
// Create the CMCD manager so client data can be attached to all requests
|
|
1314
|
-
this.cmcdManager_ = this.createCmcd_();
|
|
1315
|
-
|
|
1316
1319
|
// Load's request is a little different, so we can't use our normal
|
|
1317
1320
|
// listeners-to-promise method. It is the only request where we may skip the
|
|
1318
1321
|
// request, so we need to set the on skip callback to reject with a specific
|
|
@@ -1870,12 +1873,6 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
1870
1873
|
|
|
1871
1874
|
const playerInterface = {
|
|
1872
1875
|
networkingEngine: networkingEngine,
|
|
1873
|
-
modifyManifestRequest: (request, manifestInfo) => {
|
|
1874
|
-
this.cmcdManager_.applyManifestData(request, manifestInfo);
|
|
1875
|
-
},
|
|
1876
|
-
modifySegmentRequest: (request, segmentInfo) => {
|
|
1877
|
-
this.cmcdManager_.applySegmentData(request, segmentInfo);
|
|
1878
|
-
},
|
|
1879
1876
|
filter: (manifest) => this.filterManifest_(manifest),
|
|
1880
1877
|
makeTextStreamsForClosedCaptions: (manifest) => {
|
|
1881
1878
|
return this.makeTextStreamsForClosedCaptions_(manifest);
|
|
@@ -2113,7 +2110,9 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
2113
2110
|
new shaka.media.PreferenceBasedCriteria(
|
|
2114
2111
|
this.config_.preferredAudioLanguage,
|
|
2115
2112
|
this.config_.preferredVariantRole,
|
|
2116
|
-
this.config_.preferredAudioChannelCount
|
|
2113
|
+
this.config_.preferredAudioChannelCount,
|
|
2114
|
+
this.config_.preferredVideoHdrLevel,
|
|
2115
|
+
this.config_.preferredAudioLabel);
|
|
2117
2116
|
|
|
2118
2117
|
this.currentTextLanguage_ = this.config_.preferredTextLanguage;
|
|
2119
2118
|
this.currentTextRole_ = this.config_.preferredTextRole;
|
|
@@ -2281,6 +2280,12 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
2281
2280
|
'arbitrary language initially');
|
|
2282
2281
|
}
|
|
2283
2282
|
|
|
2283
|
+
if (this.isLive() && (this.config_.streaming.liveSync ||
|
|
2284
|
+
this.manifest_.serviceDescription)) {
|
|
2285
|
+
const onTimeUpdate = () => this.onTimeUpdate_();
|
|
2286
|
+
this.loadEventManager_.listen(mediaElement, 'timeupdate', onTimeUpdate);
|
|
2287
|
+
}
|
|
2288
|
+
|
|
2284
2289
|
this.fullyLoaded_ = true;
|
|
2285
2290
|
|
|
2286
2291
|
// Wait for the 'loadedmetadata' event to measure load() latency.
|
|
@@ -2379,6 +2384,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
2379
2384
|
drmInfos: [], // Filled in by DrmEngine config.
|
|
2380
2385
|
keyIds: new Set(),
|
|
2381
2386
|
language: 'und',
|
|
2387
|
+
originalLanguage: null,
|
|
2382
2388
|
label: null,
|
|
2383
2389
|
type: ContentType.VIDEO,
|
|
2384
2390
|
primary: false,
|
|
@@ -2390,6 +2396,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
2390
2396
|
audioSamplingRate: null,
|
|
2391
2397
|
spatialAudio: false,
|
|
2392
2398
|
closedCaptions: null,
|
|
2399
|
+
accessibilityPurpose: null,
|
|
2393
2400
|
external: false,
|
|
2394
2401
|
},
|
|
2395
2402
|
bandwidth: 100,
|
|
@@ -2633,6 +2640,11 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
2633
2640
|
fullyLoaded.reject(abortedError);
|
|
2634
2641
|
return Promise.resolve(); // Abort complete.
|
|
2635
2642
|
}).chain(() => {
|
|
2643
|
+
if (this.isLive() && this.config_.streaming.liveSync) {
|
|
2644
|
+
const onTimeUpdate = () => this.onTimeUpdate_();
|
|
2645
|
+
this.loadEventManager_.listen(mediaElement, 'timeupdate', onTimeUpdate);
|
|
2646
|
+
}
|
|
2647
|
+
|
|
2636
2648
|
this.fullyLoaded_ = true;
|
|
2637
2649
|
});
|
|
2638
2650
|
}
|
|
@@ -2894,9 +2906,13 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
2894
2906
|
.set('aborted', aborted);
|
|
2895
2907
|
this.dispatchEvent(this.makeEvent_(name, data));
|
|
2896
2908
|
};
|
|
2909
|
+
/** @type {shaka.net.NetworkingEngine.OnRequest} */
|
|
2910
|
+
const onRequest_ = (type, request, context) => {
|
|
2911
|
+
this.cmcdManager_.applyData(type, request, context);
|
|
2912
|
+
};
|
|
2897
2913
|
|
|
2898
2914
|
return new shaka.net.NetworkingEngine(
|
|
2899
|
-
onProgressUpdated_, onHeadersReceived_, onDownloadFailed_);
|
|
2915
|
+
onProgressUpdated_, onHeadersReceived_, onDownloadFailed_, onRequest_);
|
|
2900
2916
|
}
|
|
2901
2917
|
|
|
2902
2918
|
/**
|
|
@@ -3102,8 +3118,9 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
3102
3118
|
this.abrManager_.getBandwidthEstimate() : NaN,
|
|
3103
3119
|
getBufferedInfo: () => this.getBufferedInfo(),
|
|
3104
3120
|
getCurrentTime: () => this.video_ ? this.video_.currentTime : 0,
|
|
3105
|
-
getVariantTracks: () => this.getVariantTracks(),
|
|
3106
3121
|
getPlaybackRate: () => this.getPlaybackRate(),
|
|
3122
|
+
getNetworkingEngine: () => this.getNetworkingEngine(),
|
|
3123
|
+
getVariantTracks: () => this.getVariantTracks(),
|
|
3107
3124
|
isLive: () => this.isLive(),
|
|
3108
3125
|
};
|
|
3109
3126
|
|
|
@@ -3118,17 +3135,13 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
3118
3135
|
*/
|
|
3119
3136
|
createStreamingEngine() {
|
|
3120
3137
|
goog.asserts.assert(
|
|
3121
|
-
this.abrManager_ && this.mediaSourceEngine_ &&
|
|
3122
|
-
this.cmcdManager_ && this.manifest_,
|
|
3138
|
+
this.abrManager_ && this.mediaSourceEngine_ && this.manifest_,
|
|
3123
3139
|
'Must not be destroyed');
|
|
3124
3140
|
|
|
3125
3141
|
/** @type {shaka.media.StreamingEngine.PlayerInterface} */
|
|
3126
3142
|
const playerInterface = {
|
|
3127
3143
|
getPresentationTime: () => this.playhead_ ? this.playhead_.getTime() : 0,
|
|
3128
3144
|
getBandwidthEstimate: () => this.abrManager_.getBandwidthEstimate(),
|
|
3129
|
-
modifySegmentRequest: (request, segmentInfo) => {
|
|
3130
|
-
this.cmcdManager_.applySegmentData(request, segmentInfo);
|
|
3131
|
-
},
|
|
3132
3145
|
mediaSourceEngine: this.mediaSourceEngine_,
|
|
3133
3146
|
netEngine: this.networkingEngine_,
|
|
3134
3147
|
onError: (error) => this.onError_(error),
|
|
@@ -3149,6 +3162,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
3149
3162
|
onMetadata: (metadata, offset, endTime) => {
|
|
3150
3163
|
this.processTimedMetadataMediaSrc_(metadata, offset, endTime);
|
|
3151
3164
|
},
|
|
3165
|
+
disableStream: (stream, time) => this.disableStream(stream, time),
|
|
3152
3166
|
};
|
|
3153
3167
|
|
|
3154
3168
|
return new shaka.media.StreamingEngine(this.manifest_, playerInterface);
|
|
@@ -3196,15 +3210,26 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
3196
3210
|
if (config['streaming'] && 'forceTransmuxTS' in config['streaming']) {
|
|
3197
3211
|
shaka.Deprecate.deprecateFeature(5,
|
|
3198
3212
|
'streaming.forceTransmuxTS configuration',
|
|
3199
|
-
'Please Use
|
|
3200
|
-
config['
|
|
3213
|
+
'Please Use mediaSource.forceTransmux instead.');
|
|
3214
|
+
config['mediaSource']['mediaSource'] =
|
|
3201
3215
|
config['streaming']['forceTransmuxTS'];
|
|
3202
3216
|
delete config['streaming']['forceTransmuxTS'];
|
|
3203
3217
|
}
|
|
3204
3218
|
|
|
3219
|
+
// Deprecate 'streaming.forceTransmux' configuration.
|
|
3220
|
+
if (config['streaming'] && 'forceTransmux' in config['streaming']) {
|
|
3221
|
+
shaka.Deprecate.deprecateFeature(5,
|
|
3222
|
+
'streaming.forceTransmux configuration',
|
|
3223
|
+
'Please Use mediaSource.forceTransmux instead.');
|
|
3224
|
+
config['mediaSource']['mediaSource'] =
|
|
3225
|
+
config['streaming']['forceTransmux'];
|
|
3226
|
+
delete config['streaming']['forceTransmux'];
|
|
3227
|
+
}
|
|
3228
|
+
|
|
3205
3229
|
// If lowLatencyMode is enabled, and inaccurateManifestTolerance and
|
|
3206
|
-
// rebufferingGoal are not specified, set
|
|
3207
|
-
// and rebufferingGoal to 0.01
|
|
3230
|
+
// rebufferingGoal and segmentPrefetchLimit are not specified, set
|
|
3231
|
+
// inaccurateManifestTolerance to 0 and rebufferingGoal to 0.01 and
|
|
3232
|
+
// segmentPrefetchLimit to 2 by default for low latency streaming.
|
|
3208
3233
|
if (config['streaming'] && config['streaming']['lowLatencyMode']) {
|
|
3209
3234
|
if (config['streaming']['inaccurateManifestTolerance'] == undefined) {
|
|
3210
3235
|
config['streaming']['inaccurateManifestTolerance'] = 0;
|
|
@@ -3212,6 +3237,9 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
3212
3237
|
if (config['streaming']['rebufferingGoal'] == undefined) {
|
|
3213
3238
|
config['streaming']['rebufferingGoal'] = 0.01;
|
|
3214
3239
|
}
|
|
3240
|
+
if (config['streaming']['segmentPrefetchLimit'] == undefined) {
|
|
3241
|
+
config['streaming']['segmentPrefetchLimit'] = 2;
|
|
3242
|
+
}
|
|
3215
3243
|
}
|
|
3216
3244
|
const ret = shaka.util.PlayerConfiguration.mergeConfigObjects(
|
|
3217
3245
|
this.config_, config, this.defaultConfig_());
|
|
@@ -3311,6 +3339,12 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
3311
3339
|
this.config_.playRangeStart,
|
|
3312
3340
|
this.config_.playRangeEnd);
|
|
3313
3341
|
}
|
|
3342
|
+
if (this.adManager_) {
|
|
3343
|
+
this.adManager_.configure(this.config_.ads);
|
|
3344
|
+
}
|
|
3345
|
+
if (this.cmcdManager_) {
|
|
3346
|
+
this.cmcdManager_.configure(this.config_.cmcd);
|
|
3347
|
+
}
|
|
3314
3348
|
}
|
|
3315
3349
|
|
|
3316
3350
|
/**
|
|
@@ -3397,6 +3431,19 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
3397
3431
|
return this.loadMode_;
|
|
3398
3432
|
}
|
|
3399
3433
|
|
|
3434
|
+
/**
|
|
3435
|
+
* Get the current manifest type.
|
|
3436
|
+
*
|
|
3437
|
+
* @return {?string}
|
|
3438
|
+
* @export
|
|
3439
|
+
*/
|
|
3440
|
+
getManifestType() {
|
|
3441
|
+
if (!this.manifest_) {
|
|
3442
|
+
return null;
|
|
3443
|
+
}
|
|
3444
|
+
return this.manifest_.type;
|
|
3445
|
+
}
|
|
3446
|
+
|
|
3400
3447
|
/**
|
|
3401
3448
|
* Get the media element that the player is currently using to play loaded
|
|
3402
3449
|
* content. If the player has not loaded content, this will return
|
|
@@ -3647,6 +3694,16 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
3647
3694
|
return this.drmEngine_ ? this.drmEngine_.getExpiration() : Infinity;
|
|
3648
3695
|
}
|
|
3649
3696
|
|
|
3697
|
+
/**
|
|
3698
|
+
* Returns the active sessions metadata
|
|
3699
|
+
*
|
|
3700
|
+
* @return {!Array.<shaka.extern.DrmSessionMetadata>}
|
|
3701
|
+
* @export
|
|
3702
|
+
*/
|
|
3703
|
+
getActiveSessionsMetadata() {
|
|
3704
|
+
return this.drmEngine_ ? this.drmEngine_.getActiveSessionsMetadata() : [];
|
|
3705
|
+
}
|
|
3706
|
+
|
|
3650
3707
|
/**
|
|
3651
3708
|
* Gets a map of EME key ID to the current key status.
|
|
3652
3709
|
*
|
|
@@ -4138,15 +4195,16 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
4138
4195
|
* @param {string} language
|
|
4139
4196
|
* @param {string=} role
|
|
4140
4197
|
* @param {number=} channelsCount
|
|
4198
|
+
* @param {number=} safeMargin
|
|
4141
4199
|
* @export
|
|
4142
4200
|
*/
|
|
4143
|
-
selectAudioLanguage(language, role, channelsCount = 0) {
|
|
4201
|
+
selectAudioLanguage(language, role, channelsCount = 0, safeMargin = 0) {
|
|
4144
4202
|
const LanguageUtils = shaka.util.LanguageUtils;
|
|
4145
4203
|
|
|
4146
4204
|
if (this.manifest_ && this.playhead_) {
|
|
4147
4205
|
this.currentAdaptationSetCriteria_ =
|
|
4148
4206
|
new shaka.media.PreferenceBasedCriteria(language, role || '',
|
|
4149
|
-
channelsCount, /* label= */ '');
|
|
4207
|
+
channelsCount, /* hdrLevel= */ '', /* label= */ '');
|
|
4150
4208
|
|
|
4151
4209
|
const diff = (a, b) => {
|
|
4152
4210
|
if (!a.video && !b.video) {
|
|
@@ -4173,7 +4231,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
4173
4231
|
}
|
|
4174
4232
|
if (bestVariant) {
|
|
4175
4233
|
const track = shaka.util.StreamUtils.variantToTrack(bestVariant);
|
|
4176
|
-
this.selectVariantTrack(track, /* clearBuffer= */ true);
|
|
4234
|
+
this.selectVariantTrack(track, /* clearBuffer= */ true, safeMargin);
|
|
4177
4235
|
return;
|
|
4178
4236
|
}
|
|
4179
4237
|
|
|
@@ -4263,9 +4321,15 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
4263
4321
|
* are expected to have the same variant.audio.
|
|
4264
4322
|
*
|
|
4265
4323
|
* @param {string} label
|
|
4324
|
+
* @param {boolean=} clearBuffer Optional clear buffer or not when
|
|
4325
|
+
* switch to new variant
|
|
4326
|
+
* Defaults to true if not provided
|
|
4327
|
+
* @param {number=} safeMargin Optional amount of buffer (in seconds) to
|
|
4328
|
+
* retain when clearing the buffer.
|
|
4329
|
+
* Defaults to 0 if not provided. Ignored if clearBuffer is false.
|
|
4266
4330
|
* @export
|
|
4267
4331
|
*/
|
|
4268
|
-
selectVariantsByLabel(label) {
|
|
4332
|
+
selectVariantsByLabel(label, clearBuffer = true, safeMargin = 0) {
|
|
4269
4333
|
if (this.manifest_ && this.playhead_) {
|
|
4270
4334
|
let firstVariantWithLabel = null;
|
|
4271
4335
|
for (const variant of this.manifest_.variants) {
|
|
@@ -4287,9 +4351,9 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
4287
4351
|
// label have the same language.
|
|
4288
4352
|
this.currentAdaptationSetCriteria_ =
|
|
4289
4353
|
new shaka.media.PreferenceBasedCriteria(
|
|
4290
|
-
firstVariantWithLabel.language, '', 0, label);
|
|
4354
|
+
firstVariantWithLabel.language, '', 0, '', label);
|
|
4291
4355
|
|
|
4292
|
-
this.chooseVariantAndSwitch_();
|
|
4356
|
+
this.chooseVariantAndSwitch_(clearBuffer, safeMargin);
|
|
4293
4357
|
} else if (this.video_ && this.video_.audioTracks) {
|
|
4294
4358
|
const audioTracks = Array.from(this.video_.audioTracks);
|
|
4295
4359
|
|
|
@@ -4813,6 +4877,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
4813
4877
|
drmInfos: [],
|
|
4814
4878
|
keyIds: new Set(),
|
|
4815
4879
|
language: language,
|
|
4880
|
+
originalLanguage: language,
|
|
4816
4881
|
label: label || null,
|
|
4817
4882
|
type: ContentType.TEXT,
|
|
4818
4883
|
primary: false,
|
|
@@ -4824,6 +4889,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
4824
4889
|
audioSamplingRate: null,
|
|
4825
4890
|
spatialAudio: false,
|
|
4826
4891
|
closedCaptions: null,
|
|
4892
|
+
accessibilityPurpose: null,
|
|
4827
4893
|
external: true,
|
|
4828
4894
|
};
|
|
4829
4895
|
|
|
@@ -4964,6 +5030,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
4964
5030
|
drmInfos: [],
|
|
4965
5031
|
keyIds: new Set(),
|
|
4966
5032
|
language: 'und',
|
|
5033
|
+
originalLanguage: null,
|
|
4967
5034
|
label: null,
|
|
4968
5035
|
type: ContentType.IMAGE,
|
|
4969
5036
|
primary: false,
|
|
@@ -4976,6 +5043,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
4976
5043
|
spatialAudio: false,
|
|
4977
5044
|
closedCaptions: null,
|
|
4978
5045
|
tilesLayout: '1x1',
|
|
5046
|
+
accessibilityPurpose: null,
|
|
4979
5047
|
external: true,
|
|
4980
5048
|
};
|
|
4981
5049
|
|
|
@@ -5373,6 +5441,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
5373
5441
|
// Add an empty segmentIndex, for the benefit of the period combiner
|
|
5374
5442
|
// in our builtin DASH parser.
|
|
5375
5443
|
const segmentIndex = new shaka.media.MetaSegmentIndex();
|
|
5444
|
+
const language = video.closedCaptions.get(id);
|
|
5376
5445
|
const textStream = {
|
|
5377
5446
|
id: this.nextExternalStreamId_++, // A globally unique ID.
|
|
5378
5447
|
originalId: id, // The CC ID string, like 'CC1', 'CC3', etc.
|
|
@@ -5384,7 +5453,8 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
5384
5453
|
encrypted: false,
|
|
5385
5454
|
drmInfos: [],
|
|
5386
5455
|
keyIds: new Set(),
|
|
5387
|
-
language
|
|
5456
|
+
language,
|
|
5457
|
+
originalLanguage: language,
|
|
5388
5458
|
label: null,
|
|
5389
5459
|
type: ContentType.TEXT,
|
|
5390
5460
|
primary: false,
|
|
@@ -5396,6 +5466,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
5396
5466
|
audioSamplingRate: null,
|
|
5397
5467
|
spatialAudio: false,
|
|
5398
5468
|
closedCaptions: null,
|
|
5469
|
+
accessibilityPurpose: null,
|
|
5399
5470
|
external: false,
|
|
5400
5471
|
};
|
|
5401
5472
|
manifest.textStreams.push(textStream);
|
|
@@ -5650,6 +5721,71 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
5650
5721
|
}
|
|
5651
5722
|
}
|
|
5652
5723
|
|
|
5724
|
+
/**
|
|
5725
|
+
* Callback for liveSync
|
|
5726
|
+
*
|
|
5727
|
+
* @private
|
|
5728
|
+
*/
|
|
5729
|
+
onTimeUpdate_() {
|
|
5730
|
+
// If the live stream has reached its end, do not sync.
|
|
5731
|
+
if (!this.isLive()) {
|
|
5732
|
+
return;
|
|
5733
|
+
}
|
|
5734
|
+
const seekRange = this.seekRange();
|
|
5735
|
+
if (!Number.isFinite(seekRange.end)) {
|
|
5736
|
+
return;
|
|
5737
|
+
}
|
|
5738
|
+
const currentTime = this.video_.currentTime;
|
|
5739
|
+
if (currentTime < seekRange.start) {
|
|
5740
|
+
// Bad stream?
|
|
5741
|
+
return;
|
|
5742
|
+
}
|
|
5743
|
+
|
|
5744
|
+
let liveSyncMaxLatency;
|
|
5745
|
+
let liveSyncPlaybackRate;
|
|
5746
|
+
if (this.config_.streaming.liveSync) {
|
|
5747
|
+
liveSyncMaxLatency = this.config_.streaming.liveSyncMaxLatency;
|
|
5748
|
+
liveSyncPlaybackRate = this.config_.streaming.liveSyncPlaybackRate;
|
|
5749
|
+
} else {
|
|
5750
|
+
// serviceDescription must override if it is defined in the MPD and
|
|
5751
|
+
// liveSync configuration is not set.
|
|
5752
|
+
if (this.manifest_ && this.manifest_.serviceDescription) {
|
|
5753
|
+
liveSyncMaxLatency = this.manifest_.serviceDescription.maxLatency ||
|
|
5754
|
+
this.config_.streaming.liveSyncMaxLatency;
|
|
5755
|
+
liveSyncPlaybackRate =
|
|
5756
|
+
this.manifest_.serviceDescription.maxPlaybackRate ||
|
|
5757
|
+
this.config_.streaming.liveSyncPlaybackRate;
|
|
5758
|
+
}
|
|
5759
|
+
}
|
|
5760
|
+
|
|
5761
|
+
const playbackRate = this.video_.playbackRate;
|
|
5762
|
+
const latency = seekRange.end - this.video_.currentTime;
|
|
5763
|
+
let offset = 0;
|
|
5764
|
+
// In src= mode, the seek range isn't updated frequently enough, so we need
|
|
5765
|
+
// to fudge the latency number with an offset. The playback rate is used
|
|
5766
|
+
// as an offset, since that is the amount we catch up 1 second of
|
|
5767
|
+
// accelerated playback.
|
|
5768
|
+
if (this.loadMode_ == shaka.Player.LoadMode.SRC_EQUALS) {
|
|
5769
|
+
const buffered = this.video_.buffered;
|
|
5770
|
+
if (buffered.length > 0) {
|
|
5771
|
+
const bufferedEnd = buffered.end(buffered.length - 1);
|
|
5772
|
+
offset = Math.max(liveSyncPlaybackRate, bufferedEnd - seekRange.end);
|
|
5773
|
+
}
|
|
5774
|
+
}
|
|
5775
|
+
|
|
5776
|
+
if (liveSyncMaxLatency && liveSyncPlaybackRate &&
|
|
5777
|
+
(latency - offset) > liveSyncMaxLatency) {
|
|
5778
|
+
if (playbackRate != liveSyncPlaybackRate) {
|
|
5779
|
+
shaka.log.debug('Latency (' + latency + 's) ' +
|
|
5780
|
+
'is greater than liveSyncMaxLatency (' + liveSyncMaxLatency + 's). ' +
|
|
5781
|
+
'Updating playbackRate to ' + liveSyncPlaybackRate);
|
|
5782
|
+
this.trickPlay(liveSyncPlaybackRate);
|
|
5783
|
+
}
|
|
5784
|
+
} else if (playbackRate !== 1 && playbackRate !== 0) {
|
|
5785
|
+
this.cancelTrickPlay();
|
|
5786
|
+
}
|
|
5787
|
+
}
|
|
5788
|
+
|
|
5653
5789
|
/**
|
|
5654
5790
|
* Callback from Playhead.
|
|
5655
5791
|
*
|
|
@@ -5688,9 +5824,8 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
5688
5824
|
return false;
|
|
5689
5825
|
}
|
|
5690
5826
|
|
|
5691
|
-
const playableVariants =
|
|
5692
|
-
|
|
5693
|
-
});
|
|
5827
|
+
const playableVariants = shaka.util.StreamUtils.getPlayableVariants(
|
|
5828
|
+
this.manifest_.variants);
|
|
5694
5829
|
|
|
5695
5830
|
// Update the abr manager with newly filtered variants.
|
|
5696
5831
|
const adaptationSet = this.currentAdaptationSetCriteria_.create(
|
|
@@ -5717,17 +5852,55 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
5717
5852
|
}
|
|
5718
5853
|
|
|
5719
5854
|
/**
|
|
5720
|
-
*
|
|
5721
|
-
*
|
|
5722
|
-
*
|
|
5723
|
-
* playback.
|
|
5855
|
+
* Checks to re-enable variants that were temporarily disabled due to network
|
|
5856
|
+
* errors. If any variants are enabled this way, a new variant may be chosen
|
|
5857
|
+
* for playback.
|
|
5724
5858
|
* @private
|
|
5725
5859
|
*/
|
|
5726
5860
|
checkVariants_() {
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5861
|
+
goog.asserts.assert(this.manifest_, 'Should have manifest!');
|
|
5862
|
+
|
|
5863
|
+
const now = Date.now() / 1000;
|
|
5864
|
+
let hasVariantUpdate = false;
|
|
5865
|
+
|
|
5866
|
+
/** @type {function(shaka.extern.Variant):string} */
|
|
5867
|
+
const streamsAsString = (variant) => {
|
|
5868
|
+
let str = '';
|
|
5869
|
+
if (variant.video) {
|
|
5870
|
+
str += 'video:' + variant.video.id;
|
|
5871
|
+
}
|
|
5872
|
+
if (variant.audio) {
|
|
5873
|
+
str += str ? '&' : '';
|
|
5874
|
+
str += 'audio:' + variant.audio.id;
|
|
5875
|
+
}
|
|
5876
|
+
return str;
|
|
5877
|
+
};
|
|
5878
|
+
|
|
5879
|
+
for (const variant of this.manifest_.variants) {
|
|
5880
|
+
if (variant.disabledUntilTime > 0 && variant.disabledUntilTime <= now) {
|
|
5881
|
+
variant.disabledUntilTime = 0;
|
|
5882
|
+
hasVariantUpdate = true;
|
|
5883
|
+
|
|
5884
|
+
shaka.log.v2('Re-enabled variant with ' + streamsAsString(variant));
|
|
5885
|
+
}
|
|
5886
|
+
}
|
|
5887
|
+
|
|
5888
|
+
const shouldStopTimer = this.manifest_.variants.every((variant) => {
|
|
5889
|
+
goog.asserts.assert(
|
|
5890
|
+
variant.disabledUntilTime >= 0,
|
|
5891
|
+
'|variant.disableTimeUntilTime| must always be >= 0');
|
|
5892
|
+
return variant.disabledUntilTime === 0;
|
|
5893
|
+
});
|
|
5894
|
+
|
|
5895
|
+
if (shouldStopTimer) {
|
|
5896
|
+
this.checkVariantsTimer_.stop();
|
|
5897
|
+
}
|
|
5898
|
+
|
|
5899
|
+
if (hasVariantUpdate) {
|
|
5900
|
+
// Reconsider re-enabled variant for ABR switching.
|
|
5901
|
+
this.chooseVariantAndSwitch_(
|
|
5902
|
+
/* clearBuffer= */ true, /* safeMargin= */ undefined,
|
|
5903
|
+
/* force= */ false, /* fromAdaptation= */ false);
|
|
5731
5904
|
}
|
|
5732
5905
|
}
|
|
5733
5906
|
|
|
@@ -5754,9 +5927,16 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
5754
5927
|
* Called after a config change, a key status event, or an explicit language
|
|
5755
5928
|
* change.
|
|
5756
5929
|
*
|
|
5930
|
+
* @param {boolean=} clearBuffer Optional clear buffer or not when
|
|
5931
|
+
* switch to new variant
|
|
5932
|
+
* Defaults to true if not provided
|
|
5933
|
+
* @param {number=} safeMargin Optional amount of buffer (in seconds) to
|
|
5934
|
+
* retain when clearing the buffer.
|
|
5935
|
+
* Defaults to 0 if not provided. Ignored if clearBuffer is false.
|
|
5757
5936
|
* @private
|
|
5758
5937
|
*/
|
|
5759
|
-
chooseVariantAndSwitch_(
|
|
5938
|
+
chooseVariantAndSwitch_(clearBuffer = true, safeMargin = 0, force = false,
|
|
5939
|
+
fromAdaptation = true) {
|
|
5760
5940
|
goog.asserts.assert(this.config_, 'Must not be destroyed');
|
|
5761
5941
|
|
|
5762
5942
|
// Because we're running this after a config change (manual language
|
|
@@ -5764,8 +5944,8 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
5764
5944
|
// here.
|
|
5765
5945
|
const chosenVariant = this.chooseVariant_();
|
|
5766
5946
|
if (chosenVariant) {
|
|
5767
|
-
this.switchVariant_(chosenVariant,
|
|
5768
|
-
|
|
5947
|
+
this.switchVariant_(chosenVariant, fromAdaptation,
|
|
5948
|
+
clearBuffer, safeMargin, force);
|
|
5769
5949
|
}
|
|
5770
5950
|
}
|
|
5771
5951
|
|
|
@@ -5774,9 +5954,11 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
5774
5954
|
* @param {boolean} fromAdaptation
|
|
5775
5955
|
* @param {boolean} clearBuffer
|
|
5776
5956
|
* @param {number} safeMargin
|
|
5957
|
+
* @param {boolean=} force
|
|
5777
5958
|
* @private
|
|
5778
5959
|
*/
|
|
5779
|
-
switchVariant_(variant, fromAdaptation, clearBuffer, safeMargin
|
|
5960
|
+
switchVariant_(variant, fromAdaptation, clearBuffer, safeMargin,
|
|
5961
|
+
force = false) {
|
|
5780
5962
|
const currentVariant = this.streamingEngine_.getCurrentVariant();
|
|
5781
5963
|
if (variant == currentVariant) {
|
|
5782
5964
|
shaka.log.debug('Variant already selected.');
|
|
@@ -5793,7 +5975,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
5793
5975
|
// Add entries to the history.
|
|
5794
5976
|
this.addVariantToSwitchHistory_(variant, fromAdaptation);
|
|
5795
5977
|
this.streamingEngine_.switchVariant(
|
|
5796
|
-
variant, clearBuffer, safeMargin,
|
|
5978
|
+
variant, clearBuffer, safeMargin, force,
|
|
5797
5979
|
/* adaptation= */ fromAdaptation);
|
|
5798
5980
|
let oldTrack = null;
|
|
5799
5981
|
if (currentVariant) {
|
|
@@ -6059,85 +6241,108 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
6059
6241
|
|
|
6060
6242
|
/** @private */
|
|
6061
6243
|
onAbrStatusChanged_() {
|
|
6244
|
+
// Restore disabled variants if abr get disabled
|
|
6245
|
+
if (!this.config_.abr.enabled) {
|
|
6246
|
+
this.restoreDisabledVariants_();
|
|
6247
|
+
}
|
|
6248
|
+
|
|
6062
6249
|
const data = (new Map()).set('newStatus', this.config_.abr.enabled);
|
|
6063
6250
|
this.delayDispatchEvent_(this.makeEvent_(
|
|
6064
6251
|
shaka.util.FakeEvent.EventName.AbrStatusChanged, data));
|
|
6065
6252
|
}
|
|
6066
6253
|
|
|
6067
6254
|
/**
|
|
6068
|
-
*
|
|
6069
|
-
* problematic variant.
|
|
6070
|
-
* @param {!shaka.util.Error} error
|
|
6071
|
-
* @return {boolean}
|
|
6255
|
+
* @param {boolean} updateAbrManager
|
|
6072
6256
|
* @private
|
|
6073
6257
|
*/
|
|
6074
|
-
|
|
6075
|
-
if ((error.code != shaka.util.Error.Code.HTTP_ERROR &&
|
|
6076
|
-
error.code != shaka.util.Error.Code.SEGMENT_MISSING) ||
|
|
6077
|
-
error.category != shaka.util.Error.Category.NETWORK) {
|
|
6078
|
-
return false;
|
|
6079
|
-
}
|
|
6258
|
+
restoreDisabledVariants_(updateAbrManager=true) {
|
|
6080
6259
|
if (this.loadMode_ != shaka.Player.LoadMode.MEDIA_SOURCE) {
|
|
6081
|
-
return
|
|
6260
|
+
return;
|
|
6082
6261
|
}
|
|
6083
6262
|
goog.asserts.assert(this.manifest_, 'Should have manifest!');
|
|
6084
6263
|
|
|
6264
|
+
shaka.log.v2('Restoring all disabled streams...');
|
|
6265
|
+
|
|
6266
|
+
this.checkVariantsTimer_.stop();
|
|
6267
|
+
|
|
6268
|
+
for (const variant of this.manifest_.variants) {
|
|
6269
|
+
variant.disabledUntilTime = 0;
|
|
6270
|
+
}
|
|
6271
|
+
|
|
6272
|
+
if (updateAbrManager) {
|
|
6273
|
+
this.updateAbrManagerVariants_();
|
|
6274
|
+
}
|
|
6275
|
+
}
|
|
6276
|
+
|
|
6277
|
+
/**
|
|
6278
|
+
* Temporarily disable all variants containing |stream|
|
|
6279
|
+
* @param {shaka.extern.Stream} stream
|
|
6280
|
+
* @param {number} disableTime
|
|
6281
|
+
* @return {boolean}
|
|
6282
|
+
*/
|
|
6283
|
+
disableStream(stream, disableTime) {
|
|
6284
|
+
if (!this.config_.abr.enabled ||
|
|
6285
|
+
this.loadMode_ === shaka.Player.LoadMode.DESTROYED) {
|
|
6286
|
+
return false;
|
|
6287
|
+
}
|
|
6288
|
+
|
|
6085
6289
|
if (!navigator.onLine) {
|
|
6086
|
-
// Don't
|
|
6290
|
+
// Don't disable variants if we're completely offline, or else we end up
|
|
6087
6291
|
// rapidly restricting all of them.
|
|
6088
6292
|
return false;
|
|
6089
6293
|
}
|
|
6090
6294
|
|
|
6091
|
-
|
|
6092
|
-
|
|
6093
|
-
|
|
6094
|
-
|
|
6095
|
-
|
|
6096
|
-
|
|
6097
|
-
|
|
6098
|
-
|
|
6099
|
-
|
|
6100
|
-
|
|
6101
|
-
} else {
|
|
6102
|
-
return false;
|
|
6295
|
+
// It only makes sense to disable a stream if we have an alternative else we
|
|
6296
|
+
// end up disabling all variants.
|
|
6297
|
+
const hasAltStream = this.manifest_.variants.some((variant) => {
|
|
6298
|
+
const altStream = variant[stream.type];
|
|
6299
|
+
|
|
6300
|
+
if (altStream && altStream.id !== stream.id) {
|
|
6301
|
+
if (shaka.util.StreamUtils.isAudio(stream)) {
|
|
6302
|
+
return stream.language === altStream.language;
|
|
6303
|
+
}
|
|
6304
|
+
return true;
|
|
6103
6305
|
}
|
|
6104
|
-
|
|
6306
|
+
return false;
|
|
6307
|
+
});
|
|
6105
6308
|
|
|
6106
|
-
if (
|
|
6107
|
-
|
|
6108
|
-
}
|
|
6309
|
+
if (hasAltStream) {
|
|
6310
|
+
let didDisableStream = false;
|
|
6109
6311
|
|
|
6110
|
-
|
|
6111
|
-
|
|
6112
|
-
|
|
6113
|
-
|
|
6114
|
-
|
|
6115
|
-
|
|
6116
|
-
|
|
6312
|
+
for (const variant of this.manifest_.variants) {
|
|
6313
|
+
const candidate = variant[stream.type];
|
|
6314
|
+
|
|
6315
|
+
if (candidate && candidate.id === stream.id) {
|
|
6316
|
+
variant.disabledUntilTime = (Date.now() / 1000) + disableTime;
|
|
6317
|
+
didDisableStream = true;
|
|
6318
|
+
|
|
6319
|
+
shaka.log.v2(
|
|
6320
|
+
'Disabled stream ' + stream.type + ':' + stream.id +
|
|
6321
|
+
' for ' + disableTime + ' seconds...');
|
|
6322
|
+
}
|
|
6117
6323
|
}
|
|
6118
|
-
}
|
|
6119
6324
|
|
|
6120
|
-
|
|
6121
|
-
shaka.util.StreamUtils.applyRestrictions(
|
|
6122
|
-
manifest.variants, this.config_.restrictions, this.maxHwRes_);
|
|
6325
|
+
goog.asserts.assert(didDisableStream, 'Must have disabled stream');
|
|
6123
6326
|
|
|
6124
|
-
|
|
6125
|
-
const chosenVariant = this.chooseVariant_();
|
|
6126
|
-
if (!chosenVariant) {
|
|
6127
|
-
shaka.log.warning('Not enough variants to recover from error');
|
|
6128
|
-
return false;
|
|
6129
|
-
}
|
|
6327
|
+
this.checkVariantsTimer_.tickEvery(1);
|
|
6130
6328
|
|
|
6131
|
-
|
|
6132
|
-
|
|
6133
|
-
|
|
6134
|
-
|
|
6329
|
+
// Get the safeMargin to ensure a seamless playback
|
|
6330
|
+
const {video} = this.getBufferedInfo();
|
|
6331
|
+
const safeMargin =
|
|
6332
|
+
video.reduce((size, {start, end}) => size + end - start, 0);
|
|
6135
6333
|
|
|
6136
|
-
|
|
6137
|
-
|
|
6334
|
+
// Update abr manager variants and switch to recover playback
|
|
6335
|
+
this.chooseVariantAndSwitch_(
|
|
6336
|
+
/* clearBuffer= */ true, /* safeMargin= */ safeMargin,
|
|
6337
|
+
/* force= */ true, /* fromAdaptation= */ false);
|
|
6338
|
+
return true;
|
|
6339
|
+
}
|
|
6138
6340
|
|
|
6139
|
-
|
|
6140
|
-
|
|
6341
|
+
shaka.log.warning(
|
|
6342
|
+
'No alternate stream found for active ' + stream.type + ' stream. ' +
|
|
6343
|
+
'Will ignore request to disable stream...');
|
|
6344
|
+
|
|
6345
|
+
return false;
|
|
6141
6346
|
}
|
|
6142
6347
|
|
|
6143
6348
|
/**
|
|
@@ -6153,10 +6358,9 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
6153
6358
|
return;
|
|
6154
6359
|
}
|
|
6155
6360
|
|
|
6156
|
-
|
|
6157
|
-
if (
|
|
6158
|
-
|
|
6159
|
-
return;
|
|
6361
|
+
// Restore disabled variant if the player experienced a critical error.
|
|
6362
|
+
if (error.severity === shaka.util.Error.Severity.CRITICAL) {
|
|
6363
|
+
this.restoreDisabledVariants_(/* updateAbrManager= */ false);
|
|
6160
6364
|
}
|
|
6161
6365
|
|
|
6162
6366
|
const eventName = shaka.util.FakeEvent.EventName.Error;
|
|
@@ -7020,7 +7224,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
|
|
|
7020
7224
|
* @define {string} A version number taken from git at compile time.
|
|
7021
7225
|
* @export
|
|
7022
7226
|
*/
|
|
7023
|
-
shaka.Player.version = 'v4.
|
|
7227
|
+
shaka.Player.version = 'v4.4.0-uncompiled';
|
|
7024
7228
|
|
|
7025
7229
|
// Initialize the deprecation system using the version string we just set
|
|
7026
7230
|
// on the player.
|