shaka-player 4.6.5 → 4.7.1
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/README.md +1 -0
- package/dist/controls.css +1 -1
- package/dist/controls.css.map +1 -1
- package/dist/deps.js +9 -5
- package/dist/locales.js +30 -30
- package/dist/shaka-player.compiled.d.ts +46 -3
- package/dist/shaka-player.compiled.debug.d.ts +46 -3
- package/dist/shaka-player.compiled.debug.externs.js +45 -0
- package/dist/shaka-player.compiled.debug.js +382 -351
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +45 -0
- package/dist/shaka-player.compiled.js +1127 -1113
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +68 -4
- package/dist/shaka-player.ui.debug.d.ts +68 -4
- package/dist/shaka-player.ui.debug.externs.js +77 -0
- package/dist/shaka-player.ui.debug.js +428 -392
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +77 -0
- package/dist/shaka-player.ui.js +1304 -1290
- package/dist/shaka-player.ui.map +4 -4
- package/externs/mediasession.js +7 -0
- package/externs/shaka/abr_manager.js +8 -0
- package/externs/shaka/manifest.js +3 -3
- package/externs/shaka/player.js +59 -4
- package/lib/abr/simple_abr_manager.js +41 -15
- package/lib/cea/cea708_service.js +1 -1
- package/lib/cea/cea708_window.js +95 -7
- package/lib/dash/dash_parser.js +55 -11
- package/lib/media/adaptation_set_criteria.js +76 -10
- package/lib/media/media_source_engine.js +42 -18
- package/lib/media/segment_reference.js +12 -0
- package/lib/media/streaming_engine.js +55 -3
- package/lib/player.js +92 -6
- package/lib/util/cmsd_manager.js +269 -0
- package/lib/util/content_steering_manager.js +5 -1
- package/lib/util/mime_utils.js +6 -2
- package/lib/util/periods.js +108 -39
- package/lib/util/player_configuration.js +19 -5
- package/lib/util/stream_utils.js +82 -13
- package/package.json +1 -1
- package/ui/audio_language_selection.js +3 -0
- package/ui/controls.js +60 -0
- package/ui/externs/ui.js +12 -1
- package/ui/hidden_fast_forward_button.js +32 -0
- package/ui/hidden_rewind_button.js +32 -0
- package/ui/hidden_seek_button.js +121 -0
- package/ui/less/buttons.less +50 -0
- package/ui/less/containers.less +18 -0
- package/ui/resolution_selection.js +2 -0
- package/ui/ui.js +2 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -75
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -26
- package/.github/ISSUE_TEMPLATE/question.md +0 -26
- package/.github/config.yml +0 -1
- package/.github/workflows/appspot.yaml +0 -39
- package/.github/workflows/build-and-test.yaml +0 -222
- package/.github/workflows/compute-incremental-coverage.py +0 -265
- package/.github/workflows/custom-actions/prep-for-appspot/action.yaml +0 -56
- package/.github/workflows/custom-actions/set-commit-status/action.yaml +0 -37
- package/.github/workflows/deflake.yaml +0 -31
- package/.github/workflows/demo-version-index.yaml +0 -43
- package/.github/workflows/nightly-demo.yaml +0 -42
- package/.github/workflows/release-please.yaml +0 -193
- package/.github/workflows/report-incremental-coverage.yaml +0 -39
- package/.github/workflows/safari-homedir-launcher.sh +0 -18
- package/.github/workflows/selenium-lab-tests.yaml +0 -370
- package/.github/workflows/shaka-bot-commands/command-help.sh +0 -27
- package/.github/workflows/shaka-bot-commands/command-test.sh +0 -56
- package/.github/workflows/shaka-bot-commands/lib.sh +0 -83
- package/.github/workflows/shaka-bot-commands/main.sh +0 -51
- package/.github/workflows/sync-labels.yaml +0 -33
- package/.github/workflows/talk-to-shaka-bot.yaml +0 -29
- package/.github/workflows/update-issues.yaml +0 -31
- package/.github/workflows/update-screenshots.yaml +0 -142
- package/.github/workflows/validate-pr-title.yaml +0 -27
- package/CHANGELOG.md +0 -5785
- package/CODE_OF_CONDUCT.md +0 -93
- package/CONTRIBUTING.md +0 -76
- package/demo/TengwarTelcontar.woff2 +0 -0
- package/demo/app_logo_144.png +0 -0
- package/demo/app_logo_192.png +0 -0
- package/demo/app_logo_256.png +0 -0
- package/demo/app_logo_384.png +0 -0
- package/demo/app_logo_512.png +0 -0
- package/demo/app_manifest.json +0 -29
- package/demo/asset_card.js +0 -410
- package/demo/autoTemplate.txt +0 -61
- package/demo/cast_receiver/idle1.jpg +0 -0
- package/demo/cast_receiver/idle2.jpg +0 -0
- package/demo/cast_receiver/idle3.jpg +0 -0
- package/demo/cast_receiver/index.html +0 -75
- package/demo/cast_receiver/receiver_app.css +0 -111
- package/demo/cast_receiver/receiver_app.js +0 -158
- package/demo/close_button.js +0 -60
- package/demo/common/asset.js +0 -510
- package/demo/common/assets.js +0 -1634
- package/demo/config.js +0 -859
- package/demo/custom.js +0 -907
- package/demo/customWarning.txt +0 -8
- package/demo/demo.less +0 -591
- package/demo/demo_uncompiled.js +0 -11
- package/demo/demo_utils.js +0 -113
- package/demo/favicon.ico +0 -0
- package/demo/front.js +0 -156
- package/demo/icons/README.md +0 -4
- package/demo/icons/baseline-audiotrack-24px.svg +0 -1
- package/demo/icons/baseline-closed_caption-24px.svg +0 -1
- package/demo/icons/baseline-fast_forward-24px.svg +0 -1
- package/demo/icons/baseline-language-24px.svg +0 -1
- package/demo/icons/baseline-live_tv-24px.svg +0 -1
- package/demo/icons/baseline-subtitles-24px.svg +0 -1
- package/demo/icons/baseline-surround_sound-24px.svg +0 -1
- package/demo/icons/custom_ad.svg +0 -1
- package/demo/icons/custom_box_with_text.svg +0 -1
- package/demo/icons/custom_clear_key.svg +0 -1
- package/demo/icons/custom_high_definition.svg +0 -1
- package/demo/icons/custom_playready.svg +0 -1
- package/demo/icons/custom_ultra_high_definition.svg +0 -1
- package/demo/icons/custom_widevine.svg +0 -1
- package/demo/index.html +0 -173
- package/demo/input.js +0 -270
- package/demo/input_container.js +0 -218
- package/demo/load.js +0 -156
- package/demo/main.js +0 -1854
- package/demo/search.js +0 -452
- package/demo/service_worker.js +0 -355
- package/demo/shaka_logo_trans.png +0 -0
- package/demo/tooltip.js +0 -29
- package/demo/visualizer.js +0 -335
- package/demo/visualizer_button.js +0 -84
- package/dist/demo.compiled.debug.js +0 -340
- package/dist/demo.compiled.debug.map +0 -8
- package/dist/demo.compiled.js +0 -340
- package/dist/demo.compiled.map +0 -8
- package/dist/demo.css +0 -6
- package/dist/demo.css.map +0 -1
- package/dist/receiver.compiled.debug.js +0 -187
- package/dist/receiver.compiled.debug.map +0 -8
- package/dist/receiver.compiled.js +0 -187
- package/dist/receiver.compiled.map +0 -8
- package/docs/announcement-list-join-group.png +0 -0
- package/docs/api-mainpage.md +0 -28
- package/docs/design/REDESIGN.md +0 -283
- package/docs/design/architecture.md +0 -13
- package/docs/design/bg-fetch-after.gv +0 -29
- package/docs/design/bg-fetch-after.gv.png +0 -0
- package/docs/design/bg-fetch-before.gv +0 -18
- package/docs/design/bg-fetch-before.gv.png +0 -0
- package/docs/design/bg-fetch.md +0 -134
- package/docs/design/cast.gv +0 -35
- package/docs/design/cast.gv.png +0 -0
- package/docs/design/chromecast.md +0 -151
- package/docs/design/codec_preferences.md +0 -158
- package/docs/design/dash-audio-channels.md +0 -123
- package/docs/design/dash-manifests.md +0 -248
- package/docs/design/dash-timeline.svg +0 -4
- package/docs/design/dataflow.gv +0 -66
- package/docs/design/dataflow.gv.png +0 -0
- package/docs/design/export.md +0 -70
- package/docs/design/fuzzy-locale-matching.md +0 -40
- package/docs/design/gap-jumping.md +0 -151
- package/docs/design/lcevc-architecture.png +0 -0
- package/docs/design/lcevc-demo.png +0 -0
- package/docs/design/lcevc-integration.md +0 -72
- package/docs/design/locale_compatibility.svg +0 -1
- package/docs/design/locales_tree.svg +0 -1
- package/docs/design/localization-design-principles.md +0 -158
- package/docs/design/newdemo.gv +0 -83
- package/docs/design/newdemo.gv.png +0 -0
- package/docs/design/offline.gv +0 -43
- package/docs/design/offline.gv.png +0 -0
- package/docs/design/offline.md +0 -153
- package/docs/design/ownership.gv +0 -76
- package/docs/design/ownership.gv.png +0 -0
- package/docs/design/preload.md +0 -299
- package/docs/design/preload.png +0 -0
- package/docs/design/talking-about-languages.md +0 -46
- package/docs/design/timeline.svg +0 -152
- package/docs/design/ui.md +0 -31
- package/docs/design/ui_player_relationships.svg +0 -1
- package/docs/jsdoc-plugin.js +0 -74
- package/docs/jsdoc-template/README.md +0 -1
- package/docs/jsdoc-template/publish.js +0 -879
- package/docs/jsdoc-template/static/fonts/OpenSans-Bold-webfont.eot +0 -0
- package/docs/jsdoc-template/static/fonts/OpenSans-Bold-webfont.svg +0 -1830
- package/docs/jsdoc-template/static/fonts/OpenSans-Bold-webfont.woff +0 -0
- package/docs/jsdoc-template/static/fonts/OpenSans-BoldItalic-webfont.eot +0 -0
- package/docs/jsdoc-template/static/fonts/OpenSans-BoldItalic-webfont.svg +0 -1830
- package/docs/jsdoc-template/static/fonts/OpenSans-BoldItalic-webfont.woff +0 -0
- package/docs/jsdoc-template/static/fonts/OpenSans-Italic-webfont.eot +0 -0
- package/docs/jsdoc-template/static/fonts/OpenSans-Italic-webfont.svg +0 -1830
- package/docs/jsdoc-template/static/fonts/OpenSans-Italic-webfont.woff +0 -0
- package/docs/jsdoc-template/static/fonts/OpenSans-Light-webfont.eot +0 -0
- package/docs/jsdoc-template/static/fonts/OpenSans-Light-webfont.svg +0 -1831
- package/docs/jsdoc-template/static/fonts/OpenSans-Light-webfont.woff +0 -0
- package/docs/jsdoc-template/static/fonts/OpenSans-LightItalic-webfont.eot +0 -0
- package/docs/jsdoc-template/static/fonts/OpenSans-LightItalic-webfont.svg +0 -1835
- package/docs/jsdoc-template/static/fonts/OpenSans-LightItalic-webfont.woff +0 -0
- package/docs/jsdoc-template/static/fonts/OpenSans-Regular-webfont.eot +0 -0
- package/docs/jsdoc-template/static/fonts/OpenSans-Regular-webfont.svg +0 -1831
- package/docs/jsdoc-template/static/fonts/OpenSans-Regular-webfont.woff +0 -0
- package/docs/jsdoc-template/static/scripts/linenumber.js +0 -44
- package/docs/jsdoc-template/static/scripts/show-widget.js +0 -55
- package/docs/jsdoc-template/static/styles/jsdoc-default.css +0 -438
- package/docs/jsdoc-template/tmpl/augments.tmpl +0 -10
- package/docs/jsdoc-template/tmpl/container.tmpl +0 -205
- package/docs/jsdoc-template/tmpl/details.tmpl +0 -152
- package/docs/jsdoc-template/tmpl/example.tmpl +0 -2
- package/docs/jsdoc-template/tmpl/examples.tmpl +0 -13
- package/docs/jsdoc-template/tmpl/exceptions.tmpl +0 -32
- package/docs/jsdoc-template/tmpl/layout.tmpl +0 -50
- package/docs/jsdoc-template/tmpl/mainpage.tmpl +0 -14
- package/docs/jsdoc-template/tmpl/members.tmpl +0 -47
- package/docs/jsdoc-template/tmpl/method.tmpl +0 -140
- package/docs/jsdoc-template/tmpl/modifies.tmpl +0 -14
- package/docs/jsdoc-template/tmpl/params.tmpl +0 -131
- package/docs/jsdoc-template/tmpl/properties.tmpl +0 -125
- package/docs/jsdoc-template/tmpl/returns.tmpl +0 -19
- package/docs/jsdoc-template/tmpl/source.tmpl +0 -8
- package/docs/jsdoc-template/tmpl/tutorial.tmpl +0 -21
- package/docs/jsdoc-template/tmpl/type.tmpl +0 -7
- package/docs/jsdoc.conf.json +0 -38
- package/docs/shaka-player-logo.png +0 -0
- package/docs/style.md +0 -174
- package/docs/tutorials/a11y.md +0 -64
- package/docs/tutorials/ad_monetization.md +0 -292
- package/docs/tutorials/application-level-redirects.md +0 -94
- package/docs/tutorials/architecture.md +0 -32
- package/docs/tutorials/basic-usage.md +0 -89
- package/docs/tutorials/blob-url.md +0 -15
- package/docs/tutorials/config.md +0 -148
- package/docs/tutorials/debugging.md +0 -189
- package/docs/tutorials/drm-config.md +0 -274
- package/docs/tutorials/errors.md +0 -95
- package/docs/tutorials/fairplay.md +0 -242
- package/docs/tutorials/faq.md +0 -252
- package/docs/tutorials/index.json +0 -29
- package/docs/tutorials/lcevc.md +0 -118
- package/docs/tutorials/license-server-auth.md +0 -248
- package/docs/tutorials/license-wrapping.md +0 -168
- package/docs/tutorials/manifest-parser.md +0 -365
- package/docs/tutorials/network-and-buffering-config.md +0 -119
- package/docs/tutorials/offline.md +0 -683
- package/docs/tutorials/plugins.md +0 -184
- package/docs/tutorials/selenium-grid-config.md +0 -174
- package/docs/tutorials/service-worker.md +0 -106
- package/docs/tutorials/ui-customization.md +0 -288
- package/docs/tutorials/ui.md +0 -232
- package/docs/tutorials/upgrade-manifest.md +0 -281
- package/docs/tutorials/upgrade.md +0 -104
- package/docs/tutorials/welcome.md +0 -108
- package/docs/tutorials/widevine-service-certs.md +0 -45
- package/karma.conf.js +0 -879
- package/maintained-branches.md +0 -15
- package/roadmap.md +0 -186
- package/test/abr/simple_abr_manager_unit.js +0 -398
- package/test/ads/ad_manager_unit.js +0 -260
- package/test/assumptions/uint8_array_unit.js +0 -22
- package/test/cast/cast_proxy_unit.js +0 -736
- package/test/cast/cast_receiver_integration.js +0 -488
- package/test/cast/cast_receiver_unit.js +0 -1183
- package/test/cast/cast_sender_unit.js +0 -973
- package/test/cast/cast_utils_unit.js +0 -311
- package/test/cea/cea608_memory_unit.js +0 -411
- package/test/cea/cea708_service_unit.js +0 -674
- package/test/cea/cea708_window_unit.js +0 -373
- package/test/cea/cea_decoder_unit.js +0 -615
- package/test/cea/dtvcc_packet_builder_unit.js +0 -158
- package/test/cea/dtvcc_packet_unit.js +0 -60
- package/test/cea/mp4_cea_parser_unit.js +0 -127
- package/test/codec_switching/codec_switching_integration.js +0 -182
- package/test/dash/dash_parser_content_protection_unit.js +0 -998
- package/test/dash/dash_parser_integration.js +0 -74
- package/test/dash/dash_parser_live_unit.js +0 -1542
- package/test/dash/dash_parser_manifest_unit.js +0 -3121
- package/test/dash/dash_parser_segment_base_unit.js +0 -421
- package/test/dash/dash_parser_segment_list_unit.js +0 -380
- package/test/dash/dash_parser_segment_template_unit.js +0 -910
- package/test/dash/mpd_utils_unit.js +0 -794
- package/test/demo/demo_unit.js +0 -108
- package/test/deprecate/enforcer_unit.js +0 -74
- package/test/deprecate/version_unit.js +0 -57
- package/test/hls/hls_live_unit.js +0 -1330
- package/test/hls/hls_parser_unit.js +0 -5276
- package/test/hls/manifest_text_parser_unit.js +0 -545
- package/test/media/adaptation_set_criteria_unit.js +0 -806
- package/test/media/adaptation_set_unit.js +0 -229
- package/test/media/buffering_observer_unit.js +0 -143
- package/test/media/closed_caption_parser_unit.js +0 -18
- package/test/media/content_workarounds_unit.js +0 -43
- package/test/media/drm_engine_integration.js +0 -356
- package/test/media/drm_engine_unit.js +0 -2805
- package/test/media/media_source_engine_integration.js +0 -691
- package/test/media/media_source_engine_unit.js +0 -1512
- package/test/media/mp4_segment_index_parser_unit.js +0 -80
- package/test/media/play_rate_controller_unit.js +0 -69
- package/test/media/playhead_unit.js +0 -1394
- package/test/media/presentation_timeline_unit.js +0 -477
- package/test/media/quality_observer_unit.js +0 -138
- package/test/media/region_observer_unit.js +0 -374
- package/test/media/region_timeline_unit.js +0 -139
- package/test/media/segment_index_unit.js +0 -1080
- package/test/media/segment_prefetch_unit.js +0 -243
- package/test/media/segment_reference_unit.js +0 -63
- package/test/media/stall_detector_unit.js +0 -184
- package/test/media/streaming_engine_integration.js +0 -632
- package/test/media/streaming_engine_unit.js +0 -4211
- package/test/media/time_ranges_utils_unit.js +0 -123
- package/test/media/webm_segment_index_parser_unit.js +0 -90
- package/test/mss/mss_parser_content_protection_unit.js +0 -49
- package/test/mss/mss_parser_unit.js +0 -474
- package/test/mss/mss_player_integration.js +0 -124
- package/test/net/data_uri_plugin_unit.js +0 -105
- package/test/net/http_plugin_unit.js +0 -439
- package/test/net/networking_engine_unit.js +0 -1236
- package/test/net/networking_utils_unit.js +0 -37
- package/test/offline/download_progress_estimator_unit.js +0 -90
- package/test/offline/indexeddb_storage_unit.js +0 -192
- package/test/offline/manifest_convert_unit.js +0 -622
- package/test/offline/offline_integration.js +0 -168
- package/test/offline/offline_manifest_parser_unit.js +0 -231
- package/test/offline/offline_scheme_unit.js +0 -154
- package/test/offline/offline_uri_unit.js +0 -59
- package/test/offline/storage_compatibility_unit.js +0 -344
- package/test/offline/storage_integration.js +0 -1858
- package/test/player_external.js +0 -237
- package/test/player_integration.js +0 -1371
- package/test/player_load_graph_integration.js +0 -865
- package/test/player_src_equals_external.js +0 -154
- package/test/player_src_equals_integration.js +0 -527
- package/test/player_unit.js +0 -4465
- package/test/polyfill/media_capabilities_unit.js +0 -277
- package/test/polyfill/patchedmediakeys_apple_unit.js +0 -130
- package/test/test/assets/3675/chunk-stream0-00001.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00002.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00003.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00004.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00005.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00006.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00007.m4s +0 -0
- package/test/test/assets/3675/dash_0.mpd +0 -30
- package/test/test/assets/3675/dash_1.mpd +0 -30
- package/test/test/assets/3675/dash_2.mpd +0 -30
- package/test/test/assets/3675/dash_3.mpd +0 -30
- package/test/test/assets/3675/dash_4.mpd +0 -30
- package/test/test/assets/3675/dash_5.mpd +0 -26
- package/test/test/assets/3675/init-stream0.m4s +0 -0
- package/test/test/assets/audio-xhe-aac.mp4 +0 -0
- package/test/test/assets/audio.ts +0 -0
- package/test/test/assets/captions-test.ts +0 -0
- package/test/test/assets/cea-init.mp4 +0 -0
- package/test/test/assets/cea-segment.mp4 +0 -0
- package/test/test/assets/chapters.srt +0 -11
- package/test/test/assets/chapters.vtt +0 -10
- package/test/test/assets/chapters2.vtt +0 -10
- package/test/test/assets/dash-aes-128/Fragments(video=0,format=mpd-time-csf) +0 -0
- package/test/test/assets/dash-aes-128/Fragments(video=20000000,format=mpd-time-csf) +0 -0
- package/test/test/assets/dash-aes-128/Fragments(video=40000000,format=mpd-time-csf) +0 -0
- package/test/test/assets/dash-aes-128/Fragments(video=60000000,format=mpd-time-csf) +0 -0
- package/test/test/assets/dash-aes-128/Fragments(video=i,format=mpd-time-csf) +0 -0
- package/test/test/assets/dash-aes-128/dash.mpd +0 -18
- package/test/test/assets/dash-aes-128/license +0 -1
- package/test/test/assets/dash-multi-codec/audio_en_2c_128k_aac.mp4 +0 -0
- package/test/test/assets/dash-multi-codec/audio_es_2c_64k_opus.webm +0 -0
- package/test/test/assets/dash-multi-codec/dash.mpd +0 -32
- package/test/test/assets/dash-multi-codec/video_144p_108k_h264.mp4 +0 -0
- package/test/test/assets/db-dump-v1.json +0 -1
- package/test/test/assets/db-dump-v2-broken.json +0 -1
- package/test/test/assets/db-dump-v2-clean.json +0 -1
- package/test/test/assets/db-dump-v3.json +0 -1
- package/test/test/assets/db-dump-v4-broken.json +0 -1
- package/test/test/assets/db-dump-v5.json +0 -1
- package/test/test/assets/empty_caption_video_init.mp4 +0 -0
- package/test/test/assets/empty_caption_video_segment.mp4 +0 -0
- package/test/test/assets/encrypted-sintel-audio-init.mp4 +0 -0
- package/test/test/assets/encrypted-sintel-audio-segment.mp4 +0 -0
- package/test/test/assets/encrypted-sintel-video-init.mp4 +0 -0
- package/test/test/assets/encrypted-sintel-video-segment.mp4 +0 -0
- package/test/test/assets/green-pixel.mp4 +0 -0
- package/test/test/assets/green-pixel.txt +0 -15
- package/test/test/assets/h265-cea-init.mp4 +0 -0
- package/test/test/assets/h265-cea-segment.mp4 +0 -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 +0 -4
- package/test/test/assets/hls-raw-aac/stream.m4a.m3u8 +0 -14
- 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 +0 -31
- 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 +0 -31
- package/test/test/assets/hls-raw-mp3/chunklist_w905519204.m3u8 +0 -13
- 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 +0 -4
- package/test/test/assets/hls-ts-aac/playlist.m3u8 +0 -23
- 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 +0 -19
- 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 +0 -19
- 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 +0 -25
- package/test/test/assets/hls-ts-h265/0.ts +0 -0
- package/test/test/assets/hls-ts-h265/hevc.m3u8 +0 -6
- package/test/test/assets/hls-ts-h265/index.m3u8 +0 -7
- package/test/test/assets/hls-ts-mp3/manifest.m3u8 +0 -13
- 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 +0 -17
- 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 +0 -4
- package/test/test/assets/hls-ts-muxed-aac-h265/0.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h265/1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h265/media.m3u8 +0 -9
- package/test/test/assets/hls-ts-muxed-ac3-h264/media.m3u8 +0 -24
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00000.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00001.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00002.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00003.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00004.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00005.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0000.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0001.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0002.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0003.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ec3-h264/prog_index.m3u8 +0 -14
- package/test/test/assets/hls-ts-muxed-mp3-h264/index.m3u8 +0 -23
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-1-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-2-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-3-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-4-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-5-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-6-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-7-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-8-v1-a1.ts +0 -0
- package/test/test/assets/id3-metadata.aac +0 -0
- package/test/test/assets/id3-metadata.ts +0 -0
- package/test/test/assets/index-segment.mp4 +0 -0
- package/test/test/assets/index-segment.webm +0 -0
- package/test/test/assets/init-segment.webm +0 -0
- package/test/test/assets/large_file.mpd +0 -4930
- package/test/test/assets/multidrm-audio-init.mp4 +0 -0
- package/test/test/assets/multidrm-audio-segment.mp4 +0 -0
- package/test/test/assets/multidrm-video-init.mp4 +0 -0
- package/test/test/assets/multidrm-video-segment.mp4 +0 -0
- package/test/test/assets/multiple-trun-init.mp4 +0 -0
- package/test/test/assets/multiple-trun-segment.mp4 +0 -0
- package/test/test/assets/sintel-audio-init.mp4 +0 -0
- package/test/test/assets/sintel-audio-segment.mp4 +0 -0
- package/test/test/assets/sintel-video-init.mp4 +0 -0
- package/test/test/assets/sintel-video-segment.mp4 +0 -0
- package/test/test/assets/small.mp4 +0 -0
- package/test/test/assets/text-clip-alt.vtt +0 -63
- package/test/test/assets/text-clip.vtt +0 -63
- package/test/test/assets/thumbnails-sprites.vtt +0 -10
- package/test/test/assets/thumbnails.vtt +0 -10
- package/test/test/assets/ttml-init.mp4 +0 -0
- package/test/test/assets/ttml-segment-multiplemdat.mp4 +0 -0
- package/test/test/assets/ttml-segment.mp4 +0 -0
- package/test/test/assets/video.ts +0 -0
- package/test/test/assets/vtt-init.mp4 +0 -0
- package/test/test/assets/vtt-segment-multi-payload.mp4 +0 -0
- package/test/test/assets/vtt-segment-no-duration.mp4 +0 -0
- package/test/test/assets/vtt-segment-settings.mp4 +0 -0
- package/test/test/assets/vtt-segment.mp4 +0 -0
- package/test/test/boot.js +0 -495
- package/test/test/externs/filters.js +0 -44
- package/test/test/externs/fontfaceonload.js +0 -29
- package/test/test/externs/jasmine.js +0 -670
- package/test/test/externs/karma.js +0 -26
- package/test/test/externs/require.js +0 -21
- package/test/test/externs/sprintf.js +0 -18
- package/test/test/namespace.js +0 -10
- package/test/test/util/canned_idb.js +0 -379
- package/test/test/util/cea_utils.js +0 -60
- package/test/test/util/dash_parser_util.js +0 -329
- package/test/test/util/fake_ad.js +0 -321
- package/test/test/util/fake_ad_manager.js +0 -122
- package/test/test/util/fake_demo_main.js +0 -144
- package/test/test/util/fake_drm_engine.js +0 -103
- package/test/test/util/fake_media_source_engine.js +0 -464
- package/test/test/util/fake_networking_engine.js +0 -381
- package/test/test/util/fake_segment_prefetch.js +0 -84
- package/test/test/util/fake_text_displayer.js +0 -60
- package/test/test/util/id3_generator.js +0 -100
- package/test/test/util/indexeddb_utils.js +0 -124
- package/test/test/util/jasmine_fetch.js +0 -382
- package/test/test/util/layout_tests.js +0 -435
- package/test/test/util/loader.js +0 -88
- package/test/test/util/manifest_generator.js +0 -705
- package/test/test/util/manifest_parser_util.js +0 -101
- package/test/test/util/mss_parser_util.js +0 -119
- package/test/test/util/offline_utils.js +0 -105
- package/test/test/util/simple_fakes.js +0 -535
- package/test/test/util/stream_generator.js +0 -676
- package/test/test/util/streaming_engine_util.js +0 -506
- package/test/test/util/test_scheme.js +0 -778
- package/test/test/util/ttml_utils.js +0 -77
- package/test/test/util/ui_utils.js +0 -183
- package/test/test/util/util.js +0 -374
- package/test/test/util/waiter.js +0 -406
- package/test/text/cue_integration.js +0 -51
- package/test/text/lrc_text_parser_unit.js +0 -98
- package/test/text/mp4_ttml_parser_unit.js +0 -171
- package/test/text/mp4_vtt_parser_unit.js +0 -195
- package/test/text/sbv_text_parser_unit.js +0 -81
- package/test/text/simple_text_displayer_unit.js +0 -468
- package/test/text/srt_text_parser_unit.js +0 -163
- package/test/text/ssa_text_parser_unit.js +0 -382
- package/test/text/text_displayer_layout_unit.js +0 -323
- package/test/text/text_engine_unit.js +0 -500
- package/test/text/text_track_integration.js +0 -186
- package/test/text/ttml_text_parser_unit.js +0 -2176
- package/test/text/ui_text_displayer_unit.js +0 -608
- package/test/text/vtt_text_parser_unit.js +0 -1363
- package/test/text/web_vtt_generator_unit.js +0 -144
- package/test/text/web_vtt_layout_integration.js +0 -524
- package/test/transmuxer/transmuxer_engine_integration.js +0 -69
- package/test/transmuxer/transmuxer_integration.js +0 -443
- package/test/ui/ad_ui_unit.js +0 -369
- package/test/ui/localization_unit.js +0 -508
- package/test/ui/ui_customization_unit.js +0 -208
- package/test/ui/ui_integration.js +0 -669
- package/test/ui/ui_unit.js +0 -902
- package/test/util/abortable_operation_unit.js +0 -624
- package/test/util/array_utils_unit.js +0 -58
- package/test/util/buffer_utils_unit.js +0 -185
- package/test/util/cmcd_manager_unit.js +0 -440
- package/test/util/content_steering_manager_unit.js +0 -427
- package/test/util/data_view_reader_unit.js +0 -254
- package/test/util/ebml_parser_unit.js +0 -297
- package/test/util/event_manager_unit.js +0 -185
- package/test/util/fake_event_target_unit.js +0 -123
- package/test/util/id3_utils_unit.js +0 -168
- package/test/util/iterables_unit.js +0 -68
- package/test/util/language_utils_unit.js +0 -240
- package/test/util/manifest_parser_utils_unit.js +0 -55
- package/test/util/mime_utils_unit.js +0 -64
- package/test/util/mp4_box_parsers_unit.js +0 -246
- package/test/util/mp4_parser_unit.js +0 -373
- package/test/util/multi_map_unit.js +0 -94
- package/test/util/object_utils_unit.js +0 -79
- package/test/util/periods_unit.js +0 -1623
- package/test/util/pssh_unit.js +0 -226
- package/test/util/state_history_unit.js +0 -101
- package/test/util/stream_utils_unit.js +0 -1068
- package/test/util/string_utils_unit.js +0 -166
- package/test/util/text_parser_unit.js +0 -165
- package/test/util/ts_parser_unit.js +0 -77
- package/test/util/xml_utils_unit.js +0 -444
package/demo/main.js
DELETED
|
@@ -1,1854 +0,0 @@
|
|
|
1
|
-
/*! @license
|
|
2
|
-
* Shaka Player
|
|
3
|
-
* Copyright 2016 Google LLC
|
|
4
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
goog.provide('shakaDemo.Main');
|
|
9
|
-
|
|
10
|
-
goog.require('ShakaDemoAssetInfo');
|
|
11
|
-
goog.require('goog.asserts');
|
|
12
|
-
goog.require('shakaDemo.CloseButton');
|
|
13
|
-
goog.require('shakaDemo.Utils');
|
|
14
|
-
goog.require('shakaDemo.Visualizer');
|
|
15
|
-
goog.require('shakaDemo.VisualizerButton');
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Shaka Player demo, main section.
|
|
19
|
-
* This controls the header and the footer, and contains all methods that should
|
|
20
|
-
* be shared by multiple page layouts (loading assets, setting/checking
|
|
21
|
-
* configuration, etc).
|
|
22
|
-
*/
|
|
23
|
-
shakaDemo.Main = class {
|
|
24
|
-
/** */
|
|
25
|
-
constructor() {
|
|
26
|
-
/** @private {HTMLVideoElement} */
|
|
27
|
-
this.video_ = null;
|
|
28
|
-
|
|
29
|
-
/** @private {HTMLElement} */
|
|
30
|
-
this.container_ = null;
|
|
31
|
-
|
|
32
|
-
/** @private {shaka.Player} */
|
|
33
|
-
this.player_ = null;
|
|
34
|
-
|
|
35
|
-
/** @type {?ShakaDemoAssetInfo} */
|
|
36
|
-
this.selectedAsset = null;
|
|
37
|
-
|
|
38
|
-
/** @type {shaka.ui.Localization} */
|
|
39
|
-
this.localization_ = null;
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* The configuration asked for by the user. I.e., not from the asset.
|
|
43
|
-
* @private {shaka.extern.PlayerConfiguration}
|
|
44
|
-
*/
|
|
45
|
-
this.desiredConfig_;
|
|
46
|
-
|
|
47
|
-
/** @private {shaka.extern.PlayerConfiguration} */
|
|
48
|
-
this.defaultConfig_;
|
|
49
|
-
|
|
50
|
-
/** @private {boolean} */
|
|
51
|
-
this.fullyLoaded_ = false;
|
|
52
|
-
|
|
53
|
-
/** @private {?shaka.ui.Controls} */
|
|
54
|
-
this.controls_ = null;
|
|
55
|
-
|
|
56
|
-
/** @private {?Array.<shaka.extern.StoredContent>} */
|
|
57
|
-
this.initialStoredList_;
|
|
58
|
-
|
|
59
|
-
/** @private {boolean} */
|
|
60
|
-
this.trickPlayControlsEnabled_ = false;
|
|
61
|
-
|
|
62
|
-
/** @private {boolean} */
|
|
63
|
-
this.nativeControlsEnabled_ = false;
|
|
64
|
-
|
|
65
|
-
/** @private {shaka.extern.SupportType} */
|
|
66
|
-
this.support_;
|
|
67
|
-
|
|
68
|
-
/** @private {string} */
|
|
69
|
-
this.uiLocale_ = '';
|
|
70
|
-
|
|
71
|
-
/** @private {boolean} */
|
|
72
|
-
this.noInput_ = false;
|
|
73
|
-
|
|
74
|
-
/** @private {!HTMLAnchorElement} */
|
|
75
|
-
this.errorDisplayLink_ = /** @type {!HTMLAnchorElement} */(
|
|
76
|
-
document.getElementById('error-display-link'));
|
|
77
|
-
|
|
78
|
-
/** @private {?number} */
|
|
79
|
-
this.currentErrorSeverity_ = null;
|
|
80
|
-
|
|
81
|
-
// Override the icon for the MDL library's menu button.
|
|
82
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
83
|
-
MaterialLayout.prototype.Constant_.MENU_ICON = 'settings';
|
|
84
|
-
|
|
85
|
-
/** @private {?shakaDemo.Visualizer} */
|
|
86
|
-
this.visualizer_ = null;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* This function contains the steps of initialization that should be followed
|
|
91
|
-
* whether or not the demo successfully set up.
|
|
92
|
-
* @private
|
|
93
|
-
*/
|
|
94
|
-
initCommon_() {
|
|
95
|
-
// Display uncaught exceptions. Note that this doesn't seem to work in IE.
|
|
96
|
-
// See shakaDemo.Main.initWrapper for a failsafe that works for init-time
|
|
97
|
-
// errors on IE.
|
|
98
|
-
window.addEventListener('error', (event) => {
|
|
99
|
-
const errorEvent = /** @type {!ErrorEvent} */(event);
|
|
100
|
-
|
|
101
|
-
// Exception to the exceptions we catch: ChromeVox (screenreader) always
|
|
102
|
-
// throws an error as of Chrome 73. Screen these out since they are
|
|
103
|
-
// unrelated to our application and we can't control them.
|
|
104
|
-
if (errorEvent.message.includes('cvox.Api')) {
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
this.onError_(/** @type {!shaka.util.Error} */ (errorEvent.error));
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
// Set up event listeners.
|
|
112
|
-
document.getElementById('error-display-close-button').addEventListener(
|
|
113
|
-
'click', (event) => this.closeError_());
|
|
114
|
-
|
|
115
|
-
// Set up version strings in the appropriate divs.
|
|
116
|
-
this.setUpVersionStrings_();
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Set up the application with errors to show that load failed.
|
|
121
|
-
* This does not dispatch the shaka-main-loaded event, so it will not cause
|
|
122
|
-
* the nav bar buttons to be set up.
|
|
123
|
-
* @param {!shaka.ui.Overlay.FailReasonCode} reasonCode
|
|
124
|
-
*/
|
|
125
|
-
initFailed(reasonCode) {
|
|
126
|
-
this.initCommon_();
|
|
127
|
-
|
|
128
|
-
// Set up version links, so the user can switch to compiled mode if
|
|
129
|
-
// necessary.
|
|
130
|
-
this.makeVersionLinks_();
|
|
131
|
-
|
|
132
|
-
const errorCloseButton =
|
|
133
|
-
document.getElementById('error-display-close-button');
|
|
134
|
-
errorCloseButton.style.display = 'none';
|
|
135
|
-
|
|
136
|
-
// Update the componentHandler, to account for any new MDL elements added.
|
|
137
|
-
componentHandler.upgradeDom();
|
|
138
|
-
|
|
139
|
-
// Disable elements that should not be used.
|
|
140
|
-
const elementsToDisable = [];
|
|
141
|
-
const disableClass = 'should-disable-on-fail';
|
|
142
|
-
for (const element of document.getElementsByClassName(disableClass)) {
|
|
143
|
-
elementsToDisable.push(element);
|
|
144
|
-
}
|
|
145
|
-
// The hamburger menu close button is added programmatically by MDL, and
|
|
146
|
-
// thus isn't given our 'disableonfail' class.
|
|
147
|
-
for (const element of document.getElementsByClassName(
|
|
148
|
-
'mdl-layout__drawer-button')) {
|
|
149
|
-
elementsToDisable.push(element);
|
|
150
|
-
}
|
|
151
|
-
for (const element of elementsToDisable) {
|
|
152
|
-
element.tabIndex = -1;
|
|
153
|
-
element.classList.add('disabled-by-fail');
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// Process a synthetic error about lack of browser support.
|
|
157
|
-
const severity = shaka.util.Error.Severity.CRITICAL;
|
|
158
|
-
let href = '';
|
|
159
|
-
let message = '';
|
|
160
|
-
switch (reasonCode) {
|
|
161
|
-
case shaka.ui.Overlay.FailReasonCode.NO_BROWSER_SUPPORT:
|
|
162
|
-
message = 'Your browser is not supported!';
|
|
163
|
-
href = 'https://github.com/shaka-project/shaka-player#' +
|
|
164
|
-
'platform-and-browser-support-matrix';
|
|
165
|
-
break;
|
|
166
|
-
case shaka.ui.Overlay.FailReasonCode.PLAYER_FAILED_TO_LOAD:
|
|
167
|
-
message = 'Shaka Player failed to load! If you are using an adblocker' +
|
|
168
|
-
', try switching to compiled mode at the bottom of the page.';
|
|
169
|
-
break;
|
|
170
|
-
}
|
|
171
|
-
this.handleError_(severity, message, href);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* Initialize the application.
|
|
176
|
-
*/
|
|
177
|
-
async init() {
|
|
178
|
-
this.initCommon_();
|
|
179
|
-
|
|
180
|
-
this.support_ = await shaka.Player.probeSupport();
|
|
181
|
-
|
|
182
|
-
this.video_ =
|
|
183
|
-
/** @type {!HTMLVideoElement} */ (document.getElementById('video'));
|
|
184
|
-
this.video_.poster = shakaDemo.Main.mainPoster_;
|
|
185
|
-
|
|
186
|
-
this.container_ = /** @type {!HTMLElement} */(
|
|
187
|
-
document.getElementsByClassName('video-container')[0]);
|
|
188
|
-
|
|
189
|
-
if (navigator.serviceWorker) {
|
|
190
|
-
console.debug('Registering service worker.');
|
|
191
|
-
// NOTE: This can sometimes hang on iOS 12, so let's not wait for it to
|
|
192
|
-
// complete before setting up the app. We don't even use the Promise
|
|
193
|
-
// result or react to the registration failure except to log it.
|
|
194
|
-
navigator.serviceWorker.register('service_worker.js');
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
// Optionally enter noinput mode. This has to happen before setting up the
|
|
198
|
-
// player.
|
|
199
|
-
this.noInput_ = 'noinput' in this.getParams_();
|
|
200
|
-
this.setupPlayer_();
|
|
201
|
-
this.readHash_();
|
|
202
|
-
window.addEventListener('hashchange', () => this.hashChanged_());
|
|
203
|
-
|
|
204
|
-
await this.setupStorage_();
|
|
205
|
-
|
|
206
|
-
this.setupBugButton_();
|
|
207
|
-
|
|
208
|
-
if (this.noInput_) {
|
|
209
|
-
// Set the page to noInput mode, disabling the header and footer.
|
|
210
|
-
const hideClass = 'should-hide-in-no-input-mode';
|
|
211
|
-
for (const element of document.getElementsByClassName(hideClass)) {
|
|
212
|
-
this.hideElement_(element);
|
|
213
|
-
}
|
|
214
|
-
const showClass = 'should-show-in-no-input-mode';
|
|
215
|
-
for (const element of document.getElementsByClassName(showClass)) {
|
|
216
|
-
this.showElement_(element);
|
|
217
|
-
}
|
|
218
|
-
// Also fullscreen the container.
|
|
219
|
-
this.container_.classList.add('no-input-sized');
|
|
220
|
-
document.getElementById('video-bar').classList.add('no-input-sized');
|
|
221
|
-
} else {
|
|
222
|
-
goog.asserts.assert(this.player_, 'Player should exist by now.');
|
|
223
|
-
|
|
224
|
-
// Make the visualizer element.
|
|
225
|
-
const vCanvas = /** @type {!HTMLCanvasElement} */ (
|
|
226
|
-
document.getElementById('visualizer-canvas'));
|
|
227
|
-
const vDiv = /** @type {!HTMLElement} */ (
|
|
228
|
-
document.getElementById('visualizer-div'));
|
|
229
|
-
const vControlsDiv = /** @type {!HTMLElement} */ (
|
|
230
|
-
document.getElementById('visualizer-controls-div'));
|
|
231
|
-
const vScreenshotDiv = /** @type {!HTMLElement} */ (
|
|
232
|
-
document.getElementById('visualizer-screenshot-div'));
|
|
233
|
-
/** @private {?shakaDemo.Visualizer} */
|
|
234
|
-
this.visualizer_ = new shakaDemo.Visualizer(
|
|
235
|
-
vCanvas, vDiv, vScreenshotDiv, vControlsDiv, this.video_,
|
|
236
|
-
this.player_);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
// The main page is loaded. Dispatch an event, so the various
|
|
240
|
-
// configurations will load themselves.
|
|
241
|
-
this.dispatchEventWithName_('shaka-main-loaded');
|
|
242
|
-
|
|
243
|
-
// Wait for one interruptor cycle, so that the tabs have time to load.
|
|
244
|
-
// This ensures that, for example, if there is an asset playing at page
|
|
245
|
-
// load time, the video will scroll into view second, and the page won't
|
|
246
|
-
// scroll away from the video.
|
|
247
|
-
await Promise.resolve();
|
|
248
|
-
|
|
249
|
-
// Update the componentHandler, to account for any new MDL elements added.
|
|
250
|
-
componentHandler.upgradeDom();
|
|
251
|
-
|
|
252
|
-
const asset = this.getLastAssetFromHash_();
|
|
253
|
-
|
|
254
|
-
this.fullyLoaded_ = true;
|
|
255
|
-
this.remakeHash();
|
|
256
|
-
|
|
257
|
-
if (asset && !this.selectedAsset) {
|
|
258
|
-
// If an asset has begun loading in the meantime (for example, due to
|
|
259
|
-
// re-joining an existing cast session), don't play this.
|
|
260
|
-
this.loadAsset(asset);
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
/**
|
|
265
|
-
* @param {string} url
|
|
266
|
-
* @return {!Promise.<string>}
|
|
267
|
-
* @private
|
|
268
|
-
*/
|
|
269
|
-
async loadText_(url) {
|
|
270
|
-
const netEngine = new shaka.net.NetworkingEngine();
|
|
271
|
-
const retryParams = shaka.net.NetworkingEngine.defaultRetryParameters();
|
|
272
|
-
const request = shaka.net.NetworkingEngine.makeRequest([url], retryParams);
|
|
273
|
-
const requestType = shaka.net.NetworkingEngine.RequestType.APP;
|
|
274
|
-
const operation = netEngine.request(requestType, request);
|
|
275
|
-
const response = await operation.promise;
|
|
276
|
-
const text = shaka.util.StringUtils.fromUTF8(response.data);
|
|
277
|
-
await netEngine.destroy();
|
|
278
|
-
return text;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
/** @private */
|
|
282
|
-
async reportBug_() {
|
|
283
|
-
// Fetch the special bug template.
|
|
284
|
-
let text = await this.loadText_('autoTemplate.txt');
|
|
285
|
-
|
|
286
|
-
// Fill in what parts of the template we can.
|
|
287
|
-
const fillInTemplate = (replaceString, value) => {
|
|
288
|
-
text = text.replace(replaceString, value);
|
|
289
|
-
};
|
|
290
|
-
fillInTemplate('RE:player', shaka.Player.version);
|
|
291
|
-
if (this.selectedAsset) {
|
|
292
|
-
const uriLines = [];
|
|
293
|
-
const addLine = (key, value) => {
|
|
294
|
-
uriLines.push(key + '= `' + value + '`');
|
|
295
|
-
};
|
|
296
|
-
addLine('uri', this.selectedAsset.manifestUri);
|
|
297
|
-
if (this.selectedAsset.adTagUri) {
|
|
298
|
-
addLine('ad tag uri', this.selectedAsset.adTagUri);
|
|
299
|
-
}
|
|
300
|
-
if (this.selectedAsset.licenseServers.size) {
|
|
301
|
-
const uri = this.selectedAsset.licenseServers.values().next().value;
|
|
302
|
-
addLine('license server', uri);
|
|
303
|
-
for (const drmSystem of this.selectedAsset.licenseServers.keys()) {
|
|
304
|
-
if (!shakaDemo.Main.commonDrmSystems.includes(drmSystem)) {
|
|
305
|
-
addLine('drm system', drmSystem);
|
|
306
|
-
break;
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
if (this.selectedAsset.certificateUri) {
|
|
311
|
-
addLine('certificate', this.selectedAsset.certificateUri);
|
|
312
|
-
}
|
|
313
|
-
fillInTemplate('RE:uris', uriLines.join('\n'));
|
|
314
|
-
} else {
|
|
315
|
-
fillInTemplate('RE:uris', 'No asset');
|
|
316
|
-
}
|
|
317
|
-
fillInTemplate('RE:browser', navigator.userAgent);
|
|
318
|
-
if (this.selectedAsset &&
|
|
319
|
-
this.selectedAsset.source == shakaAssets.Source.CUSTOM) {
|
|
320
|
-
// This is a custom asset, so add a comment warning about custom assets.
|
|
321
|
-
const warning = await this.loadText_('customWarning.txt');
|
|
322
|
-
fillInTemplate('RE:customwarning', warning);
|
|
323
|
-
} else {
|
|
324
|
-
// No need for any warnings. So remove it (and the newline after it).
|
|
325
|
-
fillInTemplate('RE:customwarning\n', '');
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
const urlTerms = [];
|
|
329
|
-
urlTerms.push('labels=type%3A+bug');
|
|
330
|
-
urlTerms.push('body=' + encodeURIComponent(text));
|
|
331
|
-
const url = 'https://github.com/shaka-project/shaka-player/issues/new?' +
|
|
332
|
-
urlTerms.join('&');
|
|
333
|
-
|
|
334
|
-
// Navigate to the github issue opening interface, with the
|
|
335
|
-
// partially-filled template as a preset body, opening in another tab.
|
|
336
|
-
window.open(url, '_blank');
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
/** @private */
|
|
340
|
-
setupBugButton_() {
|
|
341
|
-
const bugButton = document.getElementById('bug-button');
|
|
342
|
-
bugButton.addEventListener('click', () => this.reportBug_());
|
|
343
|
-
|
|
344
|
-
// The button should be disabled when offline, as we can't report bugs in
|
|
345
|
-
// that state.
|
|
346
|
-
if (!navigator.onLine) {
|
|
347
|
-
bugButton.setAttribute('disabled', '');
|
|
348
|
-
}
|
|
349
|
-
window.addEventListener('online', () => {
|
|
350
|
-
bugButton.removeAttribute('disabled');
|
|
351
|
-
});
|
|
352
|
-
window.addEventListener('offline', () => {
|
|
353
|
-
bugButton.setAttribute('disabled', '');
|
|
354
|
-
});
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
/** @private */
|
|
358
|
-
configureUI_() {
|
|
359
|
-
const video = /** @type {!HTMLVideoElement} */ (this.video_);
|
|
360
|
-
const ui = video['ui'];
|
|
361
|
-
|
|
362
|
-
const uiConfig = ui.getConfiguration();
|
|
363
|
-
// Remove any trick play configurations from a previous config.
|
|
364
|
-
uiConfig.addSeekBar = true;
|
|
365
|
-
uiConfig.controlPanelElements =
|
|
366
|
-
uiConfig.controlPanelElements.filter((element) => {
|
|
367
|
-
return element != 'rewind' && element != 'fast_forward';
|
|
368
|
-
});
|
|
369
|
-
if (this.trickPlayControlsEnabled_) {
|
|
370
|
-
// Trick mode controls don't have a seek bar.
|
|
371
|
-
uiConfig.addSeekBar = false;
|
|
372
|
-
// Replace the position the play_pause button was at with a full suite of
|
|
373
|
-
// trick play controls, including rewind and fast-forward.
|
|
374
|
-
const index = uiConfig.controlPanelElements.indexOf('play_pause');
|
|
375
|
-
uiConfig.controlPanelElements.splice(
|
|
376
|
-
index, 1, 'rewind', 'play_pause', 'fast_forward');
|
|
377
|
-
}
|
|
378
|
-
if (!uiConfig.controlPanelElements.includes('close')) {
|
|
379
|
-
uiConfig.controlPanelElements.push('close');
|
|
380
|
-
}
|
|
381
|
-
if (!uiConfig.overflowMenuButtons.includes('visualizer')) {
|
|
382
|
-
uiConfig.overflowMenuButtons.push('visualizer');
|
|
383
|
-
}
|
|
384
|
-
ui.configure(uiConfig);
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
/** @private */
|
|
388
|
-
setupPlayer_() {
|
|
389
|
-
const video = /** @type {!HTMLVideoElement} */ (this.video_);
|
|
390
|
-
const ui = video['ui'];
|
|
391
|
-
this.player_ = ui.getControls().getPlayer();
|
|
392
|
-
|
|
393
|
-
if (!this.noInput_) {
|
|
394
|
-
// Don't add the close button if in noInput mode; it doesn't make much
|
|
395
|
-
// sense to stop playing a video if you can't start playing other videos.
|
|
396
|
-
|
|
397
|
-
// Register custom controls to the UI.
|
|
398
|
-
const closeFactory = new shakaDemo.CloseButton.Factory();
|
|
399
|
-
shaka.ui.Controls.registerElement('close', closeFactory);
|
|
400
|
-
const visualizerFactory = new shakaDemo.VisualizerButton.Factory();
|
|
401
|
-
shaka.ui.OverflowMenu.registerElement('visualizer', visualizerFactory);
|
|
402
|
-
|
|
403
|
-
// Configure UI.
|
|
404
|
-
this.configureUI_();
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
// Add application-level default configs here. These are not the library
|
|
408
|
-
// defaults, but they are the application defaults. This will affect the
|
|
409
|
-
// default values assigned to UI config elements as well as the decision
|
|
410
|
-
// about what values to place in the URL hash.
|
|
411
|
-
this.player_.configure(
|
|
412
|
-
'manifest.dash.clockSyncUri',
|
|
413
|
-
'https://shaka-player-demo.appspot.com/time.txt');
|
|
414
|
-
|
|
415
|
-
// Get default config.
|
|
416
|
-
this.defaultConfig_ = this.player_.getConfiguration();
|
|
417
|
-
this.desiredConfig_ = this.player_.getConfiguration();
|
|
418
|
-
const languages = navigator.languages || ['en-us'];
|
|
419
|
-
this.configure('preferredAudioLanguage', languages[0]);
|
|
420
|
-
this.configure('preferredTextLanguage', languages[0]);
|
|
421
|
-
this.uiLocale_ = languages[0];
|
|
422
|
-
// TODO(#1591): Support multiple language preferences
|
|
423
|
-
|
|
424
|
-
const onErrorEvent = (event) => this.onErrorEvent_(event);
|
|
425
|
-
this.player_.addEventListener('error', onErrorEvent);
|
|
426
|
-
|
|
427
|
-
// Listen to events on controls.
|
|
428
|
-
this.controls_ = ui.getControls();
|
|
429
|
-
this.controls_.addEventListener('error', onErrorEvent);
|
|
430
|
-
this.controls_.addEventListener('caststatuschanged', (event) => {
|
|
431
|
-
this.onCastStatusChange_(event['newStatus']);
|
|
432
|
-
});
|
|
433
|
-
|
|
434
|
-
this.localization_ = this.controls_.getLocalization();
|
|
435
|
-
|
|
436
|
-
const drawerCloseButton = document.getElementById('drawer-close-button');
|
|
437
|
-
drawerCloseButton.addEventListener('click', () => {
|
|
438
|
-
const layout = document.getElementById('main-layout');
|
|
439
|
-
layout.MaterialLayout.toggleDrawer();
|
|
440
|
-
this.dispatchEventWithName_('shaka-main-drawer-state-change');
|
|
441
|
-
this.hideElement_(drawerCloseButton);
|
|
442
|
-
});
|
|
443
|
-
// Dispatch drawer state change events when the drawer button or obfuscator
|
|
444
|
-
// are pressed also.
|
|
445
|
-
const drawerButton = document.querySelector('.mdl-layout__drawer-button');
|
|
446
|
-
goog.asserts.assert(drawerButton, 'There should be a drawer button.');
|
|
447
|
-
const openDrawer = () => {
|
|
448
|
-
this.dispatchEventWithName_('shaka-main-drawer-state-change');
|
|
449
|
-
this.showElement_(drawerCloseButton);
|
|
450
|
-
};
|
|
451
|
-
// Listen to both the "click" and "keydown" events on the drawer button,
|
|
452
|
-
// since the element is actually a div rather than a button, which means
|
|
453
|
-
// that it doesn't fire "click" events when activated by keyboard input.
|
|
454
|
-
drawerButton.addEventListener('click', openDrawer);
|
|
455
|
-
drawerButton.addEventListener('keydown', (event) => {
|
|
456
|
-
const key = (/** @type {!KeyboardEvent} */ (event)).key;
|
|
457
|
-
// Ignore "keydown" input for keys that won't trigger the button (i.e.
|
|
458
|
-
// anything besides spacebar or enter).
|
|
459
|
-
if (key == ' ' || key == 'Spacebar' || key == 'Enter') {
|
|
460
|
-
openDrawer();
|
|
461
|
-
}
|
|
462
|
-
});
|
|
463
|
-
const obfuscator = document.querySelector('.mdl-layout__obfuscator');
|
|
464
|
-
goog.asserts.assert(obfuscator, 'There should be an obfuscator.');
|
|
465
|
-
obfuscator.addEventListener('click', () => {
|
|
466
|
-
this.dispatchEventWithName_('shaka-main-drawer-state-change');
|
|
467
|
-
this.hideElement_(drawerCloseButton);
|
|
468
|
-
});
|
|
469
|
-
this.hideElement_(drawerCloseButton);
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
/** @return {boolean} */
|
|
473
|
-
getIsDrawerOpen() {
|
|
474
|
-
const drawer = document.querySelector('.mdl-layout__drawer');
|
|
475
|
-
goog.asserts.assert(drawer, 'There should be a drawer.');
|
|
476
|
-
return drawer.classList.contains('is-visible');
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
/**
|
|
480
|
-
* Gets a unique storage identifier for an asset.
|
|
481
|
-
* @param {!ShakaDemoAssetInfo} asset
|
|
482
|
-
* @return {string}
|
|
483
|
-
* @private
|
|
484
|
-
*/
|
|
485
|
-
getIdentifierFromAsset_(asset) {
|
|
486
|
-
// Custom assets can't have special characters like [ or ] in their name,
|
|
487
|
-
// and none of the default assets will have that in their name, so we can
|
|
488
|
-
// be sure that no asset will have [CUSTOM] in its name.
|
|
489
|
-
return asset.name +
|
|
490
|
-
(asset.source == shakaAssets.Source.CUSTOM ? ' [CUSTOM]' : '');
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
/**
|
|
494
|
-
* Creates a storage instance.
|
|
495
|
-
* If and only if storage is not available, this will return null.
|
|
496
|
-
* These storage instances are meant to be used once and then destroyed, using
|
|
497
|
-
* the |Storage.destroy| method.
|
|
498
|
-
* @return {?shaka.offline.Storage}
|
|
499
|
-
* @private
|
|
500
|
-
*/
|
|
501
|
-
makeStorageInstance_() {
|
|
502
|
-
if (!shaka.offline.Storage.support()) {
|
|
503
|
-
return null;
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
const storage = new shaka.offline.Storage();
|
|
507
|
-
|
|
508
|
-
// Configure the storage instance.
|
|
509
|
-
/**
|
|
510
|
-
* @param {string} identifier
|
|
511
|
-
* @return {?ShakaDemoAssetInfo}
|
|
512
|
-
*/
|
|
513
|
-
const getAssetWithIdentifier = (identifier) => {
|
|
514
|
-
for (const asset of shakaAssets.testAssets) {
|
|
515
|
-
if (this.getIdentifierFromAsset_(asset) == identifier) {
|
|
516
|
-
return asset;
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
if (shakaDemoCustom) {
|
|
520
|
-
for (const asset of shakaDemoCustom.assets()) {
|
|
521
|
-
if (this.getIdentifierFromAsset_(asset) == identifier) {
|
|
522
|
-
return asset;
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
return null;
|
|
527
|
-
};
|
|
528
|
-
/**
|
|
529
|
-
* @param {shaka.extern.StoredContent} content
|
|
530
|
-
* @param {number} progress
|
|
531
|
-
*/
|
|
532
|
-
const progressCallback = (content, progress) => {
|
|
533
|
-
const identifier = content.appMetadata['identifier'];
|
|
534
|
-
const asset = getAssetWithIdentifier(identifier);
|
|
535
|
-
if (asset) {
|
|
536
|
-
asset.storedProgress = progress;
|
|
537
|
-
this.dispatchEventWithName_('shaka-main-offline-progress');
|
|
538
|
-
}
|
|
539
|
-
};
|
|
540
|
-
storage.configure(this.desiredConfig_);
|
|
541
|
-
storage.configure('offline.progressCallback', progressCallback);
|
|
542
|
-
|
|
543
|
-
return storage;
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
/**
|
|
547
|
-
* Attaches callbacks to an asset so that it can be downloaded online.
|
|
548
|
-
* This method does not verify whether storage is or is not possible.
|
|
549
|
-
* Also, if an asset has an associated offline version, load it with that
|
|
550
|
-
* info.
|
|
551
|
-
* @param {!ShakaDemoAssetInfo} asset
|
|
552
|
-
*/
|
|
553
|
-
setupOfflineSupport(asset) {
|
|
554
|
-
if (!this.initialStoredList_) {
|
|
555
|
-
// Storage failed to set up, so nothing happened.
|
|
556
|
-
return;
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
// If the list of stored content does not contain this asset, then make sure
|
|
560
|
-
// that the asset's |storedContent| value is null. Custom assets that were
|
|
561
|
-
// once stored might have that object serialized with their other data.
|
|
562
|
-
asset.storedContent = null;
|
|
563
|
-
for (const storedContent of this.initialStoredList_) {
|
|
564
|
-
const identifier = storedContent.appMetadata['identifier'];
|
|
565
|
-
if (this.getIdentifierFromAsset_(asset) == identifier) {
|
|
566
|
-
asset.storedContent = storedContent;
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
asset.storeCallback = async () => {
|
|
571
|
-
const storage = this.makeStorageInstance_();
|
|
572
|
-
if (!storage) {
|
|
573
|
-
return;
|
|
574
|
-
}
|
|
575
|
-
try {
|
|
576
|
-
await this.drmConfiguration_(asset, storage);
|
|
577
|
-
const metadata = {
|
|
578
|
-
'identifier': this.getIdentifierFromAsset_(asset),
|
|
579
|
-
'downloaded': new Date(),
|
|
580
|
-
};
|
|
581
|
-
asset.storedProgress = 0;
|
|
582
|
-
this.dispatchEventWithName_('shaka-main-offline-progress');
|
|
583
|
-
const start = Date.now();
|
|
584
|
-
const stored = await storage.store(asset.manifestUri, metadata).promise;
|
|
585
|
-
const end = Date.now();
|
|
586
|
-
console.log('Download time:', end - start);
|
|
587
|
-
asset.storedContent = stored;
|
|
588
|
-
} catch (error) {
|
|
589
|
-
this.onError_(/** @type {!shaka.util.Error} */ (error));
|
|
590
|
-
asset.storedContent = null;
|
|
591
|
-
}
|
|
592
|
-
storage.destroy();
|
|
593
|
-
asset.storedProgress = 1;
|
|
594
|
-
this.dispatchEventWithName_('shaka-main-offline-progress');
|
|
595
|
-
};
|
|
596
|
-
|
|
597
|
-
asset.unstoreCallback = async () => {
|
|
598
|
-
if (asset == this.selectedAsset) {
|
|
599
|
-
this.unload();
|
|
600
|
-
}
|
|
601
|
-
if (asset.storedContent && asset.storedContent.offlineUri) {
|
|
602
|
-
const storage = this.makeStorageInstance_();
|
|
603
|
-
if (!storage) {
|
|
604
|
-
return;
|
|
605
|
-
}
|
|
606
|
-
try {
|
|
607
|
-
asset.storedProgress = 0;
|
|
608
|
-
this.dispatchEventWithName_('shaka-main-offline-progress');
|
|
609
|
-
await storage.remove(asset.storedContent.offlineUri);
|
|
610
|
-
asset.storedContent = null;
|
|
611
|
-
} catch (error) {
|
|
612
|
-
this.onError_(/** @type {!shaka.util.Error} */ (error));
|
|
613
|
-
// Presumably, if deleting the asset fails, it still exists?
|
|
614
|
-
}
|
|
615
|
-
storage.destroy();
|
|
616
|
-
asset.storedProgress = 1;
|
|
617
|
-
this.dispatchEventWithName_('shaka-main-offline-progress');
|
|
618
|
-
}
|
|
619
|
-
};
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
/**
|
|
623
|
-
* @return {!Promise}
|
|
624
|
-
* @private
|
|
625
|
-
*/
|
|
626
|
-
async setupStorage_() {
|
|
627
|
-
// Load stored asset infos.
|
|
628
|
-
const storage = this.makeStorageInstance_();
|
|
629
|
-
if (!storage) {
|
|
630
|
-
return;
|
|
631
|
-
}
|
|
632
|
-
try {
|
|
633
|
-
this.initialStoredList_ = await storage.list();
|
|
634
|
-
} catch (error) {
|
|
635
|
-
// If this operation errors, it means that storage (while supported) is
|
|
636
|
-
// being held up by some kind of error.
|
|
637
|
-
// Log that error, and then pretend that storage is unsupported.
|
|
638
|
-
console.error(error);
|
|
639
|
-
this.initialStoredList_ = null;
|
|
640
|
-
} finally {
|
|
641
|
-
storage.destroy();
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
// Setup asset callbacks for storage, for the test assets.
|
|
645
|
-
for (const asset of shakaAssets.testAssets) {
|
|
646
|
-
if (this.getAssetUnsupportedReason(asset, /* needOffline= */ true)) {
|
|
647
|
-
// Don't bother setting up the callbacks.
|
|
648
|
-
continue;
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
this.setupOfflineSupport(asset);
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
/** @private */
|
|
656
|
-
hashChanged_() {
|
|
657
|
-
this.readHash_();
|
|
658
|
-
this.dispatchEventWithName_('shaka-main-config-change');
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
/**
|
|
662
|
-
* Get why the asset is unplayable, if it is unplayable.
|
|
663
|
-
*
|
|
664
|
-
* @param {!ShakaDemoAssetInfo} asset
|
|
665
|
-
* @param {boolean} needOffline True if offline support is required.
|
|
666
|
-
* @return {?string} unsupportedReason
|
|
667
|
-
* Null if asset is supported.
|
|
668
|
-
*/
|
|
669
|
-
getAssetUnsupportedReason(asset, needOffline) {
|
|
670
|
-
if (needOffline &&
|
|
671
|
-
(!shaka.offline.Storage.support() || !this.initialStoredList_)) {
|
|
672
|
-
return 'Your browser does not support offline storage.';
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
if (asset.source == shakaAssets.Source.CUSTOM) {
|
|
676
|
-
// We can't be sure if custom assets are supported or not. Just assume
|
|
677
|
-
// they are.
|
|
678
|
-
return null;
|
|
679
|
-
}
|
|
680
|
-
|
|
681
|
-
// Is the asset disabled?
|
|
682
|
-
if (asset.disabled) {
|
|
683
|
-
return 'This asset is disabled.';
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
if (needOffline && !asset.features.includes(shakaAssets.Feature.OFFLINE)) {
|
|
687
|
-
return 'This asset cannot be downloaded.';
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
if (!asset.isClear() && !asset.isAes128()) {
|
|
691
|
-
const hasSupportedDRM = asset.drm.some((drm) => {
|
|
692
|
-
return this.support_.drm[shakaAssets.identifierForKeySystem(drm)];
|
|
693
|
-
});
|
|
694
|
-
if (!hasSupportedDRM) {
|
|
695
|
-
return 'Your browser does not support the required key systems.';
|
|
696
|
-
}
|
|
697
|
-
if (needOffline) {
|
|
698
|
-
const hasSupportedOfflineDRM = asset.drm.some((drm) => {
|
|
699
|
-
const identifier = shakaAssets.identifierForKeySystem(drm);
|
|
700
|
-
return this.support_.drm[identifier] &&
|
|
701
|
-
this.support_.drm[identifier].persistentState;
|
|
702
|
-
});
|
|
703
|
-
if (!hasSupportedOfflineDRM) {
|
|
704
|
-
return 'Your browser does not support offline licenses for the ' +
|
|
705
|
-
'required key systems.';
|
|
706
|
-
}
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
// Does the browser support the asset's manifest type?
|
|
711
|
-
if (asset.features.includes(shakaAssets.Feature.DASH) &&
|
|
712
|
-
!this.support_.manifest['application/dash+xml']) {
|
|
713
|
-
return 'Your browser does not support MPEG-DASH manifests.';
|
|
714
|
-
}
|
|
715
|
-
if (asset.features.includes(shakaAssets.Feature.HLS) &&
|
|
716
|
-
!this.support_.manifest['application/x-mpegurl']) {
|
|
717
|
-
return 'Your browser does not support HLS manifests.';
|
|
718
|
-
}
|
|
719
|
-
if (asset.features.includes(shakaAssets.Feature.MSS) &&
|
|
720
|
-
!this.support_.manifest['application/vnd.ms-sstr+xml']) {
|
|
721
|
-
return 'Your browser does not support MSS manifests.';
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
// Does the asset contain a playable mime type?
|
|
725
|
-
const mimeTypes = [];
|
|
726
|
-
if (asset.features.includes(shakaAssets.Feature.WEBM)) {
|
|
727
|
-
mimeTypes.push('video/webm');
|
|
728
|
-
}
|
|
729
|
-
if (asset.features.includes(shakaAssets.Feature.MP4)) {
|
|
730
|
-
mimeTypes.push('video/mp4');
|
|
731
|
-
}
|
|
732
|
-
if (asset.features.includes(shakaAssets.Feature.MP2TS)) {
|
|
733
|
-
mimeTypes.push('video/mp2t');
|
|
734
|
-
}
|
|
735
|
-
if (asset.features.includes(shakaAssets.Feature.CONTAINERLESS)) {
|
|
736
|
-
mimeTypes.push('audio/aac');
|
|
737
|
-
}
|
|
738
|
-
if (asset.features.includes(shakaAssets.Feature.DOLBY_VISION_3D)) {
|
|
739
|
-
mimeTypes.push('video/mp4; codecs="dvh1.20.01"');
|
|
740
|
-
}
|
|
741
|
-
const hasSupportedMimeType = mimeTypes.some((type) => {
|
|
742
|
-
return this.support_.media[type];
|
|
743
|
-
});
|
|
744
|
-
if (!hasSupportedMimeType) {
|
|
745
|
-
return 'Your browser does not support the required video format.';
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
return null;
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
/**
|
|
752
|
-
* Enable or disable the UI's trick play controls.
|
|
753
|
-
*
|
|
754
|
-
* @param {boolean} enabled
|
|
755
|
-
*/
|
|
756
|
-
setTrickPlayControlsEnabled(enabled) {
|
|
757
|
-
this.trickPlayControlsEnabled_ = enabled;
|
|
758
|
-
// Configure the UI, to add or remove the controls.
|
|
759
|
-
this.configureUI_();
|
|
760
|
-
this.remakeHash();
|
|
761
|
-
}
|
|
762
|
-
|
|
763
|
-
/**
|
|
764
|
-
* Get if the trick play controls are enabled.
|
|
765
|
-
*
|
|
766
|
-
* @return {boolean} enabled
|
|
767
|
-
*/
|
|
768
|
-
getTrickPlayControlsEnabled() {
|
|
769
|
-
return this.trickPlayControlsEnabled_;
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
/**
|
|
773
|
-
* Enable or disable the native controls.
|
|
774
|
-
* Goes into effect during the next load.
|
|
775
|
-
*
|
|
776
|
-
* @param {boolean} enabled
|
|
777
|
-
*/
|
|
778
|
-
setNativeControlsEnabled(enabled) {
|
|
779
|
-
this.nativeControlsEnabled_ = enabled;
|
|
780
|
-
this.remakeHash();
|
|
781
|
-
}
|
|
782
|
-
|
|
783
|
-
/**
|
|
784
|
-
* Get if the native controls are enabled.
|
|
785
|
-
*
|
|
786
|
-
* @return {boolean} enabled
|
|
787
|
-
*/
|
|
788
|
-
getNativeControlsEnabled() {
|
|
789
|
-
return this.nativeControlsEnabled_;
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
/** @param {string} locale */
|
|
793
|
-
setUILocale(locale) {
|
|
794
|
-
this.uiLocale_ = locale;
|
|
795
|
-
|
|
796
|
-
// Fall back to browser languages after the demo page setting.
|
|
797
|
-
const preferredLocales = [locale].concat(navigator.languages);
|
|
798
|
-
|
|
799
|
-
this.localization_.changeLocale(preferredLocales);
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
/** @return {string} */
|
|
803
|
-
getUILocale() {
|
|
804
|
-
return this.uiLocale_;
|
|
805
|
-
}
|
|
806
|
-
|
|
807
|
-
/**
|
|
808
|
-
* @return {?ShakaDemoAssetInfo}
|
|
809
|
-
* @private
|
|
810
|
-
*/
|
|
811
|
-
getLastAssetFromHash_() {
|
|
812
|
-
const params = this.getParams_();
|
|
813
|
-
|
|
814
|
-
const manifest = params['asset'];
|
|
815
|
-
const adTagUri = params['adTagUri'];
|
|
816
|
-
if (manifest) {
|
|
817
|
-
// See if it's a default asset.
|
|
818
|
-
for (const asset of shakaAssets.testAssets) {
|
|
819
|
-
if (asset.manifestUri == manifest && asset.adTagUri == adTagUri) {
|
|
820
|
-
return asset;
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
// See if it's a custom asset saved here.
|
|
825
|
-
for (const asset of shakaDemoCustom.assets()) {
|
|
826
|
-
if (asset.manifestUri == manifest) {
|
|
827
|
-
return asset;
|
|
828
|
-
}
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
// Construct a new asset.
|
|
832
|
-
const asset = new ShakaDemoAssetInfo(
|
|
833
|
-
/* name= */ 'loaded asset',
|
|
834
|
-
/* iconUri= */ '',
|
|
835
|
-
/* manifestUri= */ manifest,
|
|
836
|
-
/* source= */ shakaAssets.Source.CUSTOM);
|
|
837
|
-
if ('license' in params) {
|
|
838
|
-
let drmSystems = shakaDemo.Main.commonDrmSystems;
|
|
839
|
-
if ('drmSystem' in params) {
|
|
840
|
-
drmSystems = [params['drmSystem']];
|
|
841
|
-
}
|
|
842
|
-
for (const drmSystem of drmSystems) {
|
|
843
|
-
asset.addLicenseServer(drmSystem, params['license']);
|
|
844
|
-
}
|
|
845
|
-
}
|
|
846
|
-
if ('certificate' in params) {
|
|
847
|
-
asset.addCertificateUri(params['certificate']);
|
|
848
|
-
}
|
|
849
|
-
return asset;
|
|
850
|
-
}
|
|
851
|
-
return null;
|
|
852
|
-
}
|
|
853
|
-
|
|
854
|
-
/** @private */
|
|
855
|
-
readHash_() {
|
|
856
|
-
const params = this.getParams_();
|
|
857
|
-
|
|
858
|
-
if (this.player_) {
|
|
859
|
-
const readParam = (hashName, configName) => {
|
|
860
|
-
if (hashName in params) {
|
|
861
|
-
const existing = this.getCurrentConfigValue(configName);
|
|
862
|
-
|
|
863
|
-
// Translate the param string into a non-string value if appropriate.
|
|
864
|
-
// Determine what type the parsed value should be based on the current
|
|
865
|
-
// value.
|
|
866
|
-
let value = params[hashName];
|
|
867
|
-
if (typeof existing == 'boolean') {
|
|
868
|
-
value = value == 'true';
|
|
869
|
-
} else if (typeof existing == 'number') {
|
|
870
|
-
value = parseFloat(value);
|
|
871
|
-
}
|
|
872
|
-
|
|
873
|
-
this.configure(configName, value);
|
|
874
|
-
}
|
|
875
|
-
};
|
|
876
|
-
const config = this.player_.getConfiguration();
|
|
877
|
-
shakaDemo.Utils.runThroughHashParams(readParam, config);
|
|
878
|
-
const advanced = this.getCurrentConfigValue('drm.advanced');
|
|
879
|
-
if (advanced) {
|
|
880
|
-
for (const drmSystem of shakaDemo.Main.commonDrmSystems) {
|
|
881
|
-
if (!advanced[drmSystem]) {
|
|
882
|
-
advanced[drmSystem] = shakaDemo.Main.defaultAdvancedDrmConfig();
|
|
883
|
-
}
|
|
884
|
-
if ('videoRobustness' in params) {
|
|
885
|
-
advanced[drmSystem].videoRobustness = params['videoRobustness'];
|
|
886
|
-
}
|
|
887
|
-
if ('audioRobustness' in params) {
|
|
888
|
-
advanced[drmSystem].audioRobustness = params['audioRobustness'];
|
|
889
|
-
}
|
|
890
|
-
}
|
|
891
|
-
}
|
|
892
|
-
}
|
|
893
|
-
if ('lang' in params) {
|
|
894
|
-
// Load the legacy 'lang' hash value.
|
|
895
|
-
const lang = params['lang'];
|
|
896
|
-
this.configure('preferredAudioLanguage', lang);
|
|
897
|
-
this.configure('preferredTextLanguage', lang);
|
|
898
|
-
this.setUILocale(lang);
|
|
899
|
-
}
|
|
900
|
-
if ('uilang' in params) {
|
|
901
|
-
this.setUILocale(params['uilang']);
|
|
902
|
-
// TODO(#1591): Support multiple language preferences
|
|
903
|
-
}
|
|
904
|
-
if ('noadaptation' in params) {
|
|
905
|
-
this.configure('abr.enabled', false);
|
|
906
|
-
}
|
|
907
|
-
|
|
908
|
-
// Add compiled/uncompiled links.
|
|
909
|
-
this.makeVersionLinks_();
|
|
910
|
-
|
|
911
|
-
// Disable custom controls.
|
|
912
|
-
this.nativeControlsEnabled_ = 'nativecontrols' in params;
|
|
913
|
-
|
|
914
|
-
// Enable trick play.
|
|
915
|
-
if ('trickplay' in params) {
|
|
916
|
-
this.trickPlayControlsEnabled_ = true;
|
|
917
|
-
this.configureUI_();
|
|
918
|
-
}
|
|
919
|
-
|
|
920
|
-
// Check if uncompiled mode is supported.
|
|
921
|
-
if (!shakaDemo.Utils.browserSupportsUncompiledMode()) {
|
|
922
|
-
const uncompiledLink = document.getElementById('uncompiled-link');
|
|
923
|
-
goog.asserts.assert(
|
|
924
|
-
uncompiledLink instanceof HTMLAnchorElement, 'Wrong element type!');
|
|
925
|
-
uncompiledLink.setAttribute('disabled', '');
|
|
926
|
-
uncompiledLink.removeAttribute('href');
|
|
927
|
-
uncompiledLink.title = 'requires a newer browser';
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
if (shaka.log) {
|
|
931
|
-
if ('vv' in params) {
|
|
932
|
-
shaka.log.setLevel(shaka.log.Level.V2);
|
|
933
|
-
} else if ('v' in params) {
|
|
934
|
-
shaka.log.setLevel(shaka.log.Level.V1);
|
|
935
|
-
} else if ('debug' in params) {
|
|
936
|
-
shaka.log.setLevel(shaka.log.Level.DEBUG);
|
|
937
|
-
} else if ('info' in params) {
|
|
938
|
-
shaka.log.setLevel(shaka.log.Level.INFO);
|
|
939
|
-
}
|
|
940
|
-
}
|
|
941
|
-
}
|
|
942
|
-
|
|
943
|
-
/** @private */
|
|
944
|
-
makeVersionLinks_() {
|
|
945
|
-
const params = this.getParams_();
|
|
946
|
-
let buildType = 'uncompiled';
|
|
947
|
-
if ('build' in params) {
|
|
948
|
-
buildType = params['build'];
|
|
949
|
-
} else if ('compiled' in params) {
|
|
950
|
-
buildType = 'compiled';
|
|
951
|
-
}
|
|
952
|
-
for (const type of ['compiled', 'debug_compiled', 'uncompiled']) {
|
|
953
|
-
const elem = document.getElementById(type.split('_').join('-') + '-link');
|
|
954
|
-
goog.asserts.assert(
|
|
955
|
-
elem instanceof HTMLAnchorElement, 'Wrong element type!');
|
|
956
|
-
if (buildType == type) {
|
|
957
|
-
elem.setAttribute('disabled', '');
|
|
958
|
-
elem.removeAttribute('href');
|
|
959
|
-
elem.title = 'currently selected';
|
|
960
|
-
} else {
|
|
961
|
-
elem.removeAttribute('disabled');
|
|
962
|
-
elem.addEventListener('click', () => {
|
|
963
|
-
const rawParams = location.hash.substr(1).split(';');
|
|
964
|
-
const newParams = rawParams.filter((param) => {
|
|
965
|
-
// Remove current build type param(s).
|
|
966
|
-
return param != 'compiled' && param.split('=')[0] != 'build';
|
|
967
|
-
});
|
|
968
|
-
newParams.push('build=' + type);
|
|
969
|
-
this.setNewHashSilent_(newParams.join(';'));
|
|
970
|
-
location.reload();
|
|
971
|
-
return false;
|
|
972
|
-
});
|
|
973
|
-
}
|
|
974
|
-
}
|
|
975
|
-
}
|
|
976
|
-
|
|
977
|
-
/**
|
|
978
|
-
* @return {!Object.<string, string>} params
|
|
979
|
-
* @private
|
|
980
|
-
*/
|
|
981
|
-
getParams_() {
|
|
982
|
-
// Read URL parameters.
|
|
983
|
-
let fields = location.search.substr(1);
|
|
984
|
-
fields = fields ? fields.split(';') : [];
|
|
985
|
-
let fragments = location.hash.substr(1);
|
|
986
|
-
fragments = fragments ? fragments.split(';') : [];
|
|
987
|
-
|
|
988
|
-
// Because they are being concatenated in this order, if both an
|
|
989
|
-
// URL fragment and an URL parameter of the same type are present
|
|
990
|
-
// the URL fragment takes precendence.
|
|
991
|
-
/** @type {!Array.<string>} */
|
|
992
|
-
const combined = fields.concat(fragments);
|
|
993
|
-
const params = {};
|
|
994
|
-
for (const line of combined) {
|
|
995
|
-
const kv = line.split('=');
|
|
996
|
-
params[kv[0]] = kv.slice(1).join('=');
|
|
997
|
-
}
|
|
998
|
-
return params;
|
|
999
|
-
}
|
|
1000
|
-
|
|
1001
|
-
/**
|
|
1002
|
-
* Recovers the value from the given config field, from an arbitrary config
|
|
1003
|
-
* object.
|
|
1004
|
-
* This uses the same syntax as setting a single configuration field.
|
|
1005
|
-
* @param {string} valueName
|
|
1006
|
-
* @param {?shaka.extern.PlayerConfiguration} configObject
|
|
1007
|
-
* @return {*}
|
|
1008
|
-
* @private
|
|
1009
|
-
*/
|
|
1010
|
-
getValueFromGivenConfig_(valueName, configObject) {
|
|
1011
|
-
let objOn = configObject;
|
|
1012
|
-
let valueNameOn = valueName;
|
|
1013
|
-
while (valueNameOn) {
|
|
1014
|
-
// Split using a regex that only matches the first period.
|
|
1015
|
-
const split = valueNameOn.split(/\.(.+)/);
|
|
1016
|
-
if (split.length == 3) {
|
|
1017
|
-
valueNameOn = split[1];
|
|
1018
|
-
objOn = objOn[split[0]];
|
|
1019
|
-
} else {
|
|
1020
|
-
return objOn[split[0]];
|
|
1021
|
-
}
|
|
1022
|
-
}
|
|
1023
|
-
return undefined;
|
|
1024
|
-
}
|
|
1025
|
-
|
|
1026
|
-
/**
|
|
1027
|
-
* Recovers the value from the given config field.
|
|
1028
|
-
* This uses the same syntax as setting a single configuration field.
|
|
1029
|
-
* @example getCurrentConfigValue('abr.bandwidthDowngradeTarget')
|
|
1030
|
-
* @param {string} valueName
|
|
1031
|
-
* @return {*}
|
|
1032
|
-
*/
|
|
1033
|
-
getCurrentConfigValue(valueName) {
|
|
1034
|
-
const config = this.desiredConfig_;
|
|
1035
|
-
return this.getValueFromGivenConfig_(valueName, config);
|
|
1036
|
-
}
|
|
1037
|
-
|
|
1038
|
-
/**
|
|
1039
|
-
* @param {string} valueName
|
|
1040
|
-
*/
|
|
1041
|
-
resetConfiguration(valueName) {
|
|
1042
|
-
this.configure(valueName, undefined);
|
|
1043
|
-
}
|
|
1044
|
-
|
|
1045
|
-
/**
|
|
1046
|
-
* @param {string|!Object} config
|
|
1047
|
-
* @param {*=} value
|
|
1048
|
-
*/
|
|
1049
|
-
configure(config, value) {
|
|
1050
|
-
if (arguments.length == 2 && typeof(config) == 'string') {
|
|
1051
|
-
config = shaka.util.ConfigUtils.convertToConfigObject(config, value);
|
|
1052
|
-
}
|
|
1053
|
-
const asObj = /** @type {!Object} */ (config);
|
|
1054
|
-
shaka.util.PlayerConfiguration.mergeConfigObjects(
|
|
1055
|
-
this.desiredConfig_, asObj, this.defaultConfig_);
|
|
1056
|
-
this.player_.configure(config, value);
|
|
1057
|
-
}
|
|
1058
|
-
|
|
1059
|
-
/** @return {!shaka.extern.PlayerConfiguration} */
|
|
1060
|
-
getConfiguration() {
|
|
1061
|
-
return this.desiredConfig_;
|
|
1062
|
-
}
|
|
1063
|
-
|
|
1064
|
-
/**
|
|
1065
|
-
* @param {string} uri
|
|
1066
|
-
* @param {!shaka.net.NetworkingEngine} netEngine
|
|
1067
|
-
* @return {!Promise.<!ArrayBuffer>}
|
|
1068
|
-
* @private
|
|
1069
|
-
*/
|
|
1070
|
-
async requestCertificate_(uri, netEngine) {
|
|
1071
|
-
const requestType = shaka.net.NetworkingEngine.RequestType.APP;
|
|
1072
|
-
const request = /** @type {shaka.extern.Request} */ ({uris: [uri]});
|
|
1073
|
-
const response = await netEngine.request(requestType, request).promise;
|
|
1074
|
-
return response.data;
|
|
1075
|
-
}
|
|
1076
|
-
|
|
1077
|
-
/** @return {boolean} */
|
|
1078
|
-
getIsVisualizerActive() {
|
|
1079
|
-
if (this.visualizer_) {
|
|
1080
|
-
return this.visualizer_.active;
|
|
1081
|
-
}
|
|
1082
|
-
return false;
|
|
1083
|
-
}
|
|
1084
|
-
|
|
1085
|
-
/** @param {boolean} active */
|
|
1086
|
-
setIsVisualizerActive(active) {
|
|
1087
|
-
if (this.visualizer_) {
|
|
1088
|
-
const wasActive = this.visualizer_.active;
|
|
1089
|
-
this.visualizer_.active = active;
|
|
1090
|
-
if (wasActive != active) {
|
|
1091
|
-
if (active) {
|
|
1092
|
-
this.visualizer_.start();
|
|
1093
|
-
} else {
|
|
1094
|
-
this.visualizer_.stop();
|
|
1095
|
-
}
|
|
1096
|
-
}
|
|
1097
|
-
}
|
|
1098
|
-
}
|
|
1099
|
-
|
|
1100
|
-
/** Unload the currently-playing asset. */
|
|
1101
|
-
unload() {
|
|
1102
|
-
if (this.visualizer_) {
|
|
1103
|
-
this.visualizer_.stop();
|
|
1104
|
-
}
|
|
1105
|
-
this.selectedAsset = null;
|
|
1106
|
-
const videoBar = document.getElementById('video-bar');
|
|
1107
|
-
this.hideElement_(videoBar);
|
|
1108
|
-
this.video_.poster = shakaDemo.Main.mainPoster_;
|
|
1109
|
-
|
|
1110
|
-
if (document.fullscreenElement) {
|
|
1111
|
-
document.exitFullscreen();
|
|
1112
|
-
}
|
|
1113
|
-
if (this.video_.webkitDisplayingFullscreen) {
|
|
1114
|
-
this.video_.webkitExitFullscreen();
|
|
1115
|
-
}
|
|
1116
|
-
if (document.pictureInPictureElement) {
|
|
1117
|
-
document.exitPictureInPicture();
|
|
1118
|
-
}
|
|
1119
|
-
if (window.documentPictureInPicture &&
|
|
1120
|
-
window.documentPictureInPicture.window) {
|
|
1121
|
-
window.documentPictureInPicture.window.close();
|
|
1122
|
-
}
|
|
1123
|
-
this.player_.unload();
|
|
1124
|
-
|
|
1125
|
-
// The currently-selected asset changed, so update asset cards.
|
|
1126
|
-
this.dispatchEventWithName_('shaka-main-selected-asset-changed');
|
|
1127
|
-
|
|
1128
|
-
// Unset media session title, but only if the browser supports that API.
|
|
1129
|
-
if (navigator.mediaSession) {
|
|
1130
|
-
navigator.mediaSession.metadata = null;
|
|
1131
|
-
}
|
|
1132
|
-
|
|
1133
|
-
// Remake hash, to change the current asset.
|
|
1134
|
-
this.remakeHash();
|
|
1135
|
-
}
|
|
1136
|
-
|
|
1137
|
-
/**
|
|
1138
|
-
* @param {ShakaDemoAssetInfo} asset
|
|
1139
|
-
* @param {shaka.offline.Storage=} storage
|
|
1140
|
-
* @return {!Promise}
|
|
1141
|
-
* @private
|
|
1142
|
-
*/
|
|
1143
|
-
async drmConfiguration_(asset, storage) {
|
|
1144
|
-
const netEngine = storage ?
|
|
1145
|
-
storage.getNetworkingEngine() :
|
|
1146
|
-
this.player_.getNetworkingEngine();
|
|
1147
|
-
goog.asserts.assert(netEngine, 'There should be a net engine.');
|
|
1148
|
-
asset.applyFilters(netEngine);
|
|
1149
|
-
|
|
1150
|
-
const assetConfig = asset.getConfiguration();
|
|
1151
|
-
if (storage) {
|
|
1152
|
-
storage.configure(assetConfig);
|
|
1153
|
-
} else {
|
|
1154
|
-
// Remove all not-player-applied configurations, by resetting the
|
|
1155
|
-
// configuration then re-applying the desired configuration.
|
|
1156
|
-
this.player_.resetConfiguration();
|
|
1157
|
-
this.readHash_();
|
|
1158
|
-
this.player_.configure(assetConfig);
|
|
1159
|
-
}
|
|
1160
|
-
|
|
1161
|
-
const config = storage ?
|
|
1162
|
-
storage.getConfiguration() :
|
|
1163
|
-
this.player_.getConfiguration();
|
|
1164
|
-
|
|
1165
|
-
// Change the config's serverCertificate fields based on
|
|
1166
|
-
// asset.certificateUri.
|
|
1167
|
-
if (asset.certificateUri) {
|
|
1168
|
-
// Fetch the certificate, and apply it to the configuration.
|
|
1169
|
-
const certificate = await this.requestCertificate_(
|
|
1170
|
-
asset.certificateUri, netEngine);
|
|
1171
|
-
const certArray = shaka.util.BufferUtils.toUint8(certificate);
|
|
1172
|
-
for (const drmSystem of asset.licenseServers.keys()) {
|
|
1173
|
-
config.drm.advanced[drmSystem] = config.drm.advanced[drmSystem] || {};
|
|
1174
|
-
config.drm.advanced[drmSystem].serverCertificate = certArray;
|
|
1175
|
-
}
|
|
1176
|
-
} else {
|
|
1177
|
-
// Remove any server certificates.
|
|
1178
|
-
for (const drmSystem of asset.licenseServers.keys()) {
|
|
1179
|
-
if (config.drm.advanced[drmSystem]) {
|
|
1180
|
-
delete config.drm.advanced[drmSystem].serverCertificate;
|
|
1181
|
-
}
|
|
1182
|
-
}
|
|
1183
|
-
}
|
|
1184
|
-
|
|
1185
|
-
if (storage) {
|
|
1186
|
-
storage.configure(config);
|
|
1187
|
-
} else {
|
|
1188
|
-
this.player_.configure('drm.advanced', config.drm.advanced);
|
|
1189
|
-
}
|
|
1190
|
-
this.remakeHash();
|
|
1191
|
-
}
|
|
1192
|
-
|
|
1193
|
-
/**
|
|
1194
|
-
* Performs all visual operations that should be performed when a new asset
|
|
1195
|
-
* begins playing. The video bar is un-hidden, the screen is scrolled, and so
|
|
1196
|
-
* on.
|
|
1197
|
-
*
|
|
1198
|
-
* @private
|
|
1199
|
-
*/
|
|
1200
|
-
showPlayer_() {
|
|
1201
|
-
const videoBar = document.getElementById('video-bar');
|
|
1202
|
-
this.showElement_(videoBar);
|
|
1203
|
-
this.closeError_();
|
|
1204
|
-
this.video_.poster = shakaDemo.Main.mainPoster_;
|
|
1205
|
-
|
|
1206
|
-
// Scroll to the top of the page, so that if the page is scrolled down,
|
|
1207
|
-
// the user won't need to manually scroll up to see the video.
|
|
1208
|
-
videoBar.scrollIntoView({behavior: 'smooth', block: 'start'});
|
|
1209
|
-
}
|
|
1210
|
-
|
|
1211
|
-
/**
|
|
1212
|
-
* @param {ShakaDemoAssetInfo} asset
|
|
1213
|
-
*/
|
|
1214
|
-
async loadAsset(asset) {
|
|
1215
|
-
try {
|
|
1216
|
-
this.selectedAsset = asset;
|
|
1217
|
-
this.showPlayer_();
|
|
1218
|
-
|
|
1219
|
-
// The currently-selected asset changed, so update asset cards.
|
|
1220
|
-
this.dispatchEventWithName_('shaka-main-selected-asset-changed');
|
|
1221
|
-
|
|
1222
|
-
// Enable the correct set of controls before loading.
|
|
1223
|
-
// The video container influences the TextDisplayer used.
|
|
1224
|
-
if (this.nativeControlsEnabled_) {
|
|
1225
|
-
this.controls_.setEnabledShakaControls(false);
|
|
1226
|
-
this.controls_.setEnabledNativeControls(true);
|
|
1227
|
-
// This will force the player to use SimpleTextDisplayer.
|
|
1228
|
-
this.player_.setVideoContainer(null);
|
|
1229
|
-
} else {
|
|
1230
|
-
this.controls_.setEnabledShakaControls(true);
|
|
1231
|
-
this.controls_.setEnabledNativeControls(false);
|
|
1232
|
-
// This will force the player to use UITextDisplayer.
|
|
1233
|
-
this.player_.setVideoContainer(this.container_);
|
|
1234
|
-
}
|
|
1235
|
-
|
|
1236
|
-
await this.drmConfiguration_(asset);
|
|
1237
|
-
this.controls_.getCastProxy().setAppData({'asset': asset});
|
|
1238
|
-
|
|
1239
|
-
// Finally, the asset can be loaded.
|
|
1240
|
-
let manifestUri = asset.manifestUri;
|
|
1241
|
-
// If we have an offline copy, use that. If the offlineUri field is null,
|
|
1242
|
-
// we are still downloading it.
|
|
1243
|
-
if (asset.storedContent && asset.storedContent.offlineUri) {
|
|
1244
|
-
manifestUri = asset.storedContent.offlineUri;
|
|
1245
|
-
}
|
|
1246
|
-
// If it's a server side dai asset, request ad-containing manifest
|
|
1247
|
-
// from the ad manager.
|
|
1248
|
-
if (asset.imaAssetKey || (asset.imaContentSrcId && asset.imaVideoId)) {
|
|
1249
|
-
manifestUri = await this.getManifestUriFromAdManager_(asset);
|
|
1250
|
-
}
|
|
1251
|
-
// If it's a MediaTailor asset, request ad-containing manifest
|
|
1252
|
-
// from the ad manager.
|
|
1253
|
-
if (asset.mediaTailorUrl) {
|
|
1254
|
-
manifestUri = await this.getManifestUriFromMediaTailorAdManager_(asset);
|
|
1255
|
-
}
|
|
1256
|
-
await this.player_.load(
|
|
1257
|
-
manifestUri,
|
|
1258
|
-
/* startTime= */ null,
|
|
1259
|
-
asset.mimeType || undefined);
|
|
1260
|
-
|
|
1261
|
-
if (this.player_.isAudioOnly()) {
|
|
1262
|
-
this.video_.poster = shakaDemo.Main.audioOnlyPoster_;
|
|
1263
|
-
}
|
|
1264
|
-
|
|
1265
|
-
for (const extraText of asset.extraText) {
|
|
1266
|
-
this.player_.addTextTrackAsync(extraText.uri, extraText.language,
|
|
1267
|
-
extraText.kind, extraText.mime, extraText.codecs);
|
|
1268
|
-
}
|
|
1269
|
-
|
|
1270
|
-
for (const extraThumbnail of asset.extraThumbnail) {
|
|
1271
|
-
this.player_.addThumbnailsTrack(extraThumbnail);
|
|
1272
|
-
}
|
|
1273
|
-
|
|
1274
|
-
for (const extraChapter of asset.extraChapter) {
|
|
1275
|
-
this.player_.addChaptersTrack(extraChapter.uri, extraChapter.language,
|
|
1276
|
-
extraChapter.mime);
|
|
1277
|
-
}
|
|
1278
|
-
|
|
1279
|
-
// If the asset has an ad tag attached to it, load the ads
|
|
1280
|
-
const adManager = this.player_.getAdManager();
|
|
1281
|
-
if (adManager && asset.adTagUri) {
|
|
1282
|
-
try {
|
|
1283
|
-
// If IMA is blocked by an AdBlocker, init() will throw.
|
|
1284
|
-
// If that happens, just proceed to load.
|
|
1285
|
-
goog.asserts.assert(this.video_ != null, 'this.video should exist!');
|
|
1286
|
-
adManager.initClientSide(
|
|
1287
|
-
this.controls_.getClientSideAdContainer(), this.video_,
|
|
1288
|
-
/** adsRenderingSettings= **/ null);
|
|
1289
|
-
const adRequest = new google.ima.AdsRequest();
|
|
1290
|
-
adRequest.adTagUrl = asset.adTagUri;
|
|
1291
|
-
adManager.requestClientSideAds(adRequest);
|
|
1292
|
-
} catch (error) {
|
|
1293
|
-
console.log(error);
|
|
1294
|
-
console.warn('Ads code has been prevented from running. ' +
|
|
1295
|
-
'Proceeding without ads.');
|
|
1296
|
-
}
|
|
1297
|
-
}
|
|
1298
|
-
|
|
1299
|
-
// Set media session title, but only if the browser supports that API.
|
|
1300
|
-
if (navigator.mediaSession) {
|
|
1301
|
-
const metadata = {
|
|
1302
|
-
title: asset.name,
|
|
1303
|
-
artwork: [{src: asset.iconUri}],
|
|
1304
|
-
};
|
|
1305
|
-
metadata.artist = asset.source;
|
|
1306
|
-
navigator.mediaSession.metadata = new MediaMetadata(metadata);
|
|
1307
|
-
}
|
|
1308
|
-
|
|
1309
|
-
if (this.visualizer_ && this.visualizer_.active) {
|
|
1310
|
-
this.visualizer_.start();
|
|
1311
|
-
}
|
|
1312
|
-
} catch (reason) {
|
|
1313
|
-
const error = /** @type {!shaka.util.Error} */ (reason);
|
|
1314
|
-
if (error.code == shaka.util.Error.Code.LOAD_INTERRUPTED) {
|
|
1315
|
-
// Don't use shaka.log, which is not present in compiled builds.
|
|
1316
|
-
console.debug('load() interrupted');
|
|
1317
|
-
} else {
|
|
1318
|
-
this.onError_(error);
|
|
1319
|
-
}
|
|
1320
|
-
}
|
|
1321
|
-
|
|
1322
|
-
// Remake hash, to change the current asset.
|
|
1323
|
-
this.remakeHash();
|
|
1324
|
-
}
|
|
1325
|
-
|
|
1326
|
-
/** Remakes the location's hash. */
|
|
1327
|
-
remakeHash() {
|
|
1328
|
-
if (!this.fullyLoaded_) {
|
|
1329
|
-
// Don't remake the hash until the demo page is fully loaded.
|
|
1330
|
-
return;
|
|
1331
|
-
}
|
|
1332
|
-
|
|
1333
|
-
const params = [];
|
|
1334
|
-
|
|
1335
|
-
if (this.player_) {
|
|
1336
|
-
const setParam = (hashName, configName) => {
|
|
1337
|
-
const currentValue = this.getCurrentConfigValue(configName);
|
|
1338
|
-
const defaultConfig = this.defaultConfig_;
|
|
1339
|
-
const defaultValue =
|
|
1340
|
-
this.getValueFromGivenConfig_(configName, defaultConfig);
|
|
1341
|
-
// NaN != NaN, so there has to be a special check for it to prevent
|
|
1342
|
-
// false positives.
|
|
1343
|
-
const bothAreNaN = isNaN(currentValue) && isNaN(defaultValue);
|
|
1344
|
-
// Strings count as NaN too, so check for them specifically.
|
|
1345
|
-
const bothAreStrings = (typeof currentValue) == 'string' &&
|
|
1346
|
-
(typeof defaultValue) == 'string';
|
|
1347
|
-
if (currentValue != defaultValue && (!bothAreNaN || bothAreStrings)) {
|
|
1348
|
-
// Don't bother saving in the hash unless it's a non-default value.
|
|
1349
|
-
params.push(hashName + '=' + currentValue);
|
|
1350
|
-
}
|
|
1351
|
-
};
|
|
1352
|
-
const config = this.player_.getConfiguration();
|
|
1353
|
-
shakaDemo.Utils.runThroughHashParams(setParam, config);
|
|
1354
|
-
const advanced = this.getCurrentConfigValue('drm.advanced');
|
|
1355
|
-
if (advanced) {
|
|
1356
|
-
for (const drmSystem of shakaDemo.Main.commonDrmSystems) {
|
|
1357
|
-
const advancedFor = advanced[drmSystem];
|
|
1358
|
-
if (advancedFor) {
|
|
1359
|
-
if (advancedFor.videoRobustness) {
|
|
1360
|
-
params.push('videoRobustness=' + advancedFor.videoRobustness);
|
|
1361
|
-
}
|
|
1362
|
-
if (advancedFor.audioRobustness) {
|
|
1363
|
-
params.push('audioRobustness=' + advancedFor.audioRobustness);
|
|
1364
|
-
}
|
|
1365
|
-
break;
|
|
1366
|
-
}
|
|
1367
|
-
}
|
|
1368
|
-
}
|
|
1369
|
-
}
|
|
1370
|
-
if (!this.getCurrentConfigValue('abr.enabled')) {
|
|
1371
|
-
params.push('noadaptation');
|
|
1372
|
-
}
|
|
1373
|
-
params.push('uilang=' + this.getUILocale());
|
|
1374
|
-
|
|
1375
|
-
if (this.selectedAsset) {
|
|
1376
|
-
const isDefault = shakaAssets.testAssets.includes(this.selectedAsset);
|
|
1377
|
-
params.push('asset=' + this.selectedAsset.manifestUri);
|
|
1378
|
-
if (this.selectedAsset.adTagUri) {
|
|
1379
|
-
params.push('adTagUri=' + this.selectedAsset.adTagUri);
|
|
1380
|
-
}
|
|
1381
|
-
if (!isDefault && this.selectedAsset.licenseServers.size) {
|
|
1382
|
-
const uri = this.selectedAsset.licenseServers.values().next().value;
|
|
1383
|
-
params.push('license=' + uri);
|
|
1384
|
-
for (const drmSystem of this.selectedAsset.licenseServers.keys()) {
|
|
1385
|
-
if (!shakaDemo.Main.commonDrmSystems.includes(drmSystem)) {
|
|
1386
|
-
params.push('drmSystem=' + drmSystem);
|
|
1387
|
-
break;
|
|
1388
|
-
}
|
|
1389
|
-
}
|
|
1390
|
-
}
|
|
1391
|
-
if (!isDefault && this.selectedAsset.certificateUri) {
|
|
1392
|
-
params.push('certificate=' + this.selectedAsset.certificateUri);
|
|
1393
|
-
}
|
|
1394
|
-
}
|
|
1395
|
-
|
|
1396
|
-
const navButtons = document.getElementById('nav-button-container');
|
|
1397
|
-
for (const button of navButtons.childNodes) {
|
|
1398
|
-
if (button.nodeType == Node.ELEMENT_NODE) {
|
|
1399
|
-
goog.asserts.assert( button instanceof HTMLElement, 'Wrong node type!');
|
|
1400
|
-
if (button.classList.contains('mdl-button--accent')) {
|
|
1401
|
-
params.push('panel=' + button.getAttribute('tab-identifier'));
|
|
1402
|
-
const hashValues = button.getAttribute('tab-hash');
|
|
1403
|
-
if (hashValues) {
|
|
1404
|
-
params.push('panelData=' + hashValues);
|
|
1405
|
-
}
|
|
1406
|
-
break;
|
|
1407
|
-
}
|
|
1408
|
-
}
|
|
1409
|
-
}
|
|
1410
|
-
|
|
1411
|
-
for (const type of ['compiled', 'debug_compiled', 'uncompiled']) {
|
|
1412
|
-
const elem = document.getElementById(type.split('_').join('-') + '-link');
|
|
1413
|
-
if (elem.hasAttribute('disabled')) {
|
|
1414
|
-
params.push('build=' + type);
|
|
1415
|
-
}
|
|
1416
|
-
}
|
|
1417
|
-
|
|
1418
|
-
if (this.noInput_) {
|
|
1419
|
-
params.push('noinput');
|
|
1420
|
-
}
|
|
1421
|
-
|
|
1422
|
-
if (this.nativeControlsEnabled_) {
|
|
1423
|
-
params.push('nativecontrols');
|
|
1424
|
-
}
|
|
1425
|
-
|
|
1426
|
-
if (this.trickPlayControlsEnabled_) {
|
|
1427
|
-
params.push('trickplay');
|
|
1428
|
-
}
|
|
1429
|
-
|
|
1430
|
-
// MAX_LOG_LEVEL is the default starting log level. Only save the log level
|
|
1431
|
-
// if it's different from this default.
|
|
1432
|
-
if (shaka.log && shaka.log.currentLevel != shaka.log.MAX_LOG_LEVEL) {
|
|
1433
|
-
switch (shaka.log.currentLevel) {
|
|
1434
|
-
case shaka.log.Level.INFO:
|
|
1435
|
-
params.push('info');
|
|
1436
|
-
break;
|
|
1437
|
-
case shaka.log.Level.DEBUG:
|
|
1438
|
-
params.push('debug');
|
|
1439
|
-
break;
|
|
1440
|
-
case shaka.log.Level.V2:
|
|
1441
|
-
params.push('vv');
|
|
1442
|
-
break;
|
|
1443
|
-
case shaka.log.Level.V1:
|
|
1444
|
-
params.push('v');
|
|
1445
|
-
break;
|
|
1446
|
-
}
|
|
1447
|
-
}
|
|
1448
|
-
|
|
1449
|
-
this.setNewHashSilent_(params.join(';'));
|
|
1450
|
-
}
|
|
1451
|
-
|
|
1452
|
-
/**
|
|
1453
|
-
* Sets the hash to a given value WITHOUT triggering a |hashchange| event.
|
|
1454
|
-
* @param {string} hash
|
|
1455
|
-
* @private
|
|
1456
|
-
*/
|
|
1457
|
-
setNewHashSilent_(hash) {
|
|
1458
|
-
const state = null;
|
|
1459
|
-
const title = ''; // Unused; just needed to make Closure happy.
|
|
1460
|
-
const newURL = document.location.pathname + '#' + hash;
|
|
1461
|
-
// Calling history.replaceState can change the URL or hash of the page
|
|
1462
|
-
// without actually triggering any changes; it won't make the page navigate,
|
|
1463
|
-
// or trigger a |hashchange| event.
|
|
1464
|
-
history.replaceState(state, title, newURL);
|
|
1465
|
-
}
|
|
1466
|
-
|
|
1467
|
-
/**
|
|
1468
|
-
* Gets the hamburger menu's content div, so that the caller to add elements
|
|
1469
|
-
* to it.
|
|
1470
|
-
* There is no guarantee that the caller is the only entity that has added
|
|
1471
|
-
* contents to the hamburger menu.
|
|
1472
|
-
* @return {!HTMLDivElement} The container for the hamburger menu.
|
|
1473
|
-
*/
|
|
1474
|
-
getHamburgerMenu() {
|
|
1475
|
-
const menu = document.getElementById('hamburger-menu-contents');
|
|
1476
|
-
return /** @type {!HTMLDivElement} */ (menu);
|
|
1477
|
-
}
|
|
1478
|
-
|
|
1479
|
-
/**
|
|
1480
|
-
* @param {Element} element
|
|
1481
|
-
* @private
|
|
1482
|
-
*/
|
|
1483
|
-
hideElement_(element) {
|
|
1484
|
-
element.classList.add('hidden');
|
|
1485
|
-
}
|
|
1486
|
-
|
|
1487
|
-
/**
|
|
1488
|
-
* @param {Element} element
|
|
1489
|
-
* @private
|
|
1490
|
-
*/
|
|
1491
|
-
showElement_(element) {
|
|
1492
|
-
element.classList.remove('hidden');
|
|
1493
|
-
}
|
|
1494
|
-
|
|
1495
|
-
/**
|
|
1496
|
-
* @param {ShakaDemoAssetInfo} asset
|
|
1497
|
-
* @return {!Promise.<string>}
|
|
1498
|
-
* @private
|
|
1499
|
-
*/
|
|
1500
|
-
async getManifestUriFromAdManager_(asset) {
|
|
1501
|
-
const adManager = this.player_.getAdManager();
|
|
1502
|
-
const container = this.controls_.getServerSideAdContainer();
|
|
1503
|
-
try {
|
|
1504
|
-
// If IMA is blocked by an AdBlocker, init() will throw.
|
|
1505
|
-
// If that happens, return our backup uri.
|
|
1506
|
-
goog.asserts.assert(this.video_ != null, 'Video should not be null!');
|
|
1507
|
-
adManager.initServerSide(container, this.video_);
|
|
1508
|
-
let request;
|
|
1509
|
-
if (asset.imaAssetKey != null) {
|
|
1510
|
-
// LIVE stream
|
|
1511
|
-
request = new google.ima.dai.api.LiveStreamRequest();
|
|
1512
|
-
request.assetKey = asset.imaAssetKey;
|
|
1513
|
-
} else {
|
|
1514
|
-
goog.asserts.assert(asset.imaContentSrcId != null &&
|
|
1515
|
-
asset.imaVideoId != null, 'Asset should have ima ids!');
|
|
1516
|
-
// VOD
|
|
1517
|
-
request = new google.ima.dai.api.VODStreamRequest();
|
|
1518
|
-
request.contentSourceId = asset.imaContentSrcId;
|
|
1519
|
-
request.videoId = asset.imaVideoId;
|
|
1520
|
-
}
|
|
1521
|
-
switch (asset.imaManifestType) {
|
|
1522
|
-
case 'DASH':
|
|
1523
|
-
case 'dash':
|
|
1524
|
-
case 'MPD':
|
|
1525
|
-
case 'mpd':
|
|
1526
|
-
request.format = google.ima.dai.api.StreamRequest.StreamFormat.DASH;
|
|
1527
|
-
break;
|
|
1528
|
-
case 'HLS':
|
|
1529
|
-
case 'hls':
|
|
1530
|
-
case 'M3U8':
|
|
1531
|
-
case 'm3u8':
|
|
1532
|
-
request.format = google.ima.dai.api.StreamRequest.StreamFormat.HLS;
|
|
1533
|
-
break;
|
|
1534
|
-
}
|
|
1535
|
-
|
|
1536
|
-
const uri = await adManager.requestServerSideStream(
|
|
1537
|
-
request, /* backupUri= */ asset.manifestUri);
|
|
1538
|
-
return uri;
|
|
1539
|
-
} catch (error) {
|
|
1540
|
-
console.log(error);
|
|
1541
|
-
console.warn('Ads code has been prevented from running ' +
|
|
1542
|
-
'or returned an error. Proceeding without ads.');
|
|
1543
|
-
|
|
1544
|
-
return asset.manifestUri;
|
|
1545
|
-
}
|
|
1546
|
-
}
|
|
1547
|
-
|
|
1548
|
-
/**
|
|
1549
|
-
* @param {ShakaDemoAssetInfo} asset
|
|
1550
|
-
* @return {!Promise.<string>}
|
|
1551
|
-
* @private
|
|
1552
|
-
*/
|
|
1553
|
-
async getManifestUriFromMediaTailorAdManager_(asset) {
|
|
1554
|
-
const adManager = this.player_.getAdManager();
|
|
1555
|
-
const container = this.controls_.getServerSideAdContainer();
|
|
1556
|
-
try {
|
|
1557
|
-
goog.asserts.assert(this.video_ != null, 'Video should not be null!');
|
|
1558
|
-
goog.asserts.assert(asset.mediaTailorUrl != null,
|
|
1559
|
-
'Media Tailor info not be null!');
|
|
1560
|
-
const netEngine = this.player_.getNetworkingEngine();
|
|
1561
|
-
goog.asserts.assert(netEngine, 'There should be a net engine.');
|
|
1562
|
-
adManager.initMediaTailor(container, netEngine, this.video_);
|
|
1563
|
-
const uri = await adManager.requestMediaTailorStream(
|
|
1564
|
-
asset.mediaTailorUrl, asset.mediaTailorAdsParams,
|
|
1565
|
-
/* backupUri= */ asset.manifestUri);
|
|
1566
|
-
return uri;
|
|
1567
|
-
} catch (error) {
|
|
1568
|
-
console.log(error);
|
|
1569
|
-
console.warn('Ads code has been prevented from running ' +
|
|
1570
|
-
'or returned an error. Proceeding without ads.');
|
|
1571
|
-
|
|
1572
|
-
return asset.manifestUri;
|
|
1573
|
-
}
|
|
1574
|
-
}
|
|
1575
|
-
|
|
1576
|
-
/**
|
|
1577
|
-
* Sets up a nav button, and an associated tab.
|
|
1578
|
-
* This method is meant to be called by the various tabs, as part of their
|
|
1579
|
-
* setup process.
|
|
1580
|
-
* @param {string} containerName Used to determine the id of the button this
|
|
1581
|
-
* is looking for. Also used as the className of the container, for CSS.
|
|
1582
|
-
* @return {{
|
|
1583
|
-
* container: !HTMLDivElement,
|
|
1584
|
-
* button: !HTMLButtonElement,
|
|
1585
|
-
* }} The container for the tab, and the button element that activates it.
|
|
1586
|
-
*/
|
|
1587
|
-
addNavButton(containerName) {
|
|
1588
|
-
const navButtons = document.getElementById('nav-button-container');
|
|
1589
|
-
const contents = document.getElementById('contents');
|
|
1590
|
-
const button = document.getElementById('nav-button-' + containerName);
|
|
1591
|
-
|
|
1592
|
-
// TODO: Switch to using MDL tabs.
|
|
1593
|
-
|
|
1594
|
-
// Determine if the element is selected.
|
|
1595
|
-
const params = this.getParams_();
|
|
1596
|
-
let selected =
|
|
1597
|
-
params['panel'] == encodeURI(button.getAttribute('tab-identifier'));
|
|
1598
|
-
if (selected) {
|
|
1599
|
-
// Re-apply any saved data from hash.
|
|
1600
|
-
const hashValues = params['panelData'];
|
|
1601
|
-
if (hashValues) {
|
|
1602
|
-
button.setAttribute('tab-hash', hashValues);
|
|
1603
|
-
}
|
|
1604
|
-
} else if (!params['panel']) {
|
|
1605
|
-
// Check if it's selected by default.
|
|
1606
|
-
selected = button.getAttribute('defaultselected') != null;
|
|
1607
|
-
}
|
|
1608
|
-
|
|
1609
|
-
// Create the div for this nav button's container within the contents.
|
|
1610
|
-
const container = document.createElement('div');
|
|
1611
|
-
this.hideElement_(container);
|
|
1612
|
-
contents.appendChild(container);
|
|
1613
|
-
|
|
1614
|
-
// Add a click listener to display this container, and hide the others.
|
|
1615
|
-
const switchPage = () => {
|
|
1616
|
-
// This element should be the selected one.
|
|
1617
|
-
for (const child of navButtons.childNodes) {
|
|
1618
|
-
if (child.nodeType == Node.ELEMENT_NODE) {
|
|
1619
|
-
goog.asserts.assert(child instanceof Element, 'Wrong node type!');
|
|
1620
|
-
child.classList.remove('mdl-button--accent');
|
|
1621
|
-
}
|
|
1622
|
-
}
|
|
1623
|
-
for (const child of contents.childNodes) {
|
|
1624
|
-
if (child.nodeType == Node.ELEMENT_NODE) {
|
|
1625
|
-
goog.asserts.assert(child instanceof Element, 'Wrong node type!');
|
|
1626
|
-
this.hideElement_(child);
|
|
1627
|
-
}
|
|
1628
|
-
}
|
|
1629
|
-
button.classList.add('mdl-button--accent');
|
|
1630
|
-
this.showElement_(container);
|
|
1631
|
-
this.remakeHash();
|
|
1632
|
-
|
|
1633
|
-
// Dispatch an event so that a page can load any deferred content.
|
|
1634
|
-
this.dispatchEventWithName_('shaka-main-page-changed');
|
|
1635
|
-
|
|
1636
|
-
// Scroll so that the top of the tab is in view.
|
|
1637
|
-
container.scrollIntoView({behavior: 'smooth', block: 'start'});
|
|
1638
|
-
};
|
|
1639
|
-
|
|
1640
|
-
button.addEventListener('click', switchPage);
|
|
1641
|
-
if (selected) {
|
|
1642
|
-
// Defer this call to switchPage until the container is fully set up.
|
|
1643
|
-
Promise.resolve().then(switchPage);
|
|
1644
|
-
}
|
|
1645
|
-
|
|
1646
|
-
return {
|
|
1647
|
-
container: /** @type {!HTMLDivElement} */ (container),
|
|
1648
|
-
button: /** @type {!HTMLButtonElement} */ (button),
|
|
1649
|
-
};
|
|
1650
|
-
}
|
|
1651
|
-
|
|
1652
|
-
/**
|
|
1653
|
-
* Dispatches a custom event to document.
|
|
1654
|
-
* @param {string} name
|
|
1655
|
-
* @private
|
|
1656
|
-
*/
|
|
1657
|
-
dispatchEventWithName_(name) {
|
|
1658
|
-
const event =
|
|
1659
|
-
/** @type {!CustomEvent} */(document.createEvent('CustomEvent'));
|
|
1660
|
-
event.initCustomEvent(name,
|
|
1661
|
-
/* canBubble= */ false,
|
|
1662
|
-
/* cancelable= */ false,
|
|
1663
|
-
/* detail= */ null);
|
|
1664
|
-
document.dispatchEvent(event);
|
|
1665
|
-
}
|
|
1666
|
-
|
|
1667
|
-
/**
|
|
1668
|
-
* Sets the "version-string" divs to a version string.
|
|
1669
|
-
* For example, "v2.5.4-main (uncompiled)".
|
|
1670
|
-
* @private
|
|
1671
|
-
*/
|
|
1672
|
-
setUpVersionStrings_() {
|
|
1673
|
-
const version = shaka.Player.version;
|
|
1674
|
-
let split = version.split('-');
|
|
1675
|
-
const inParen = [];
|
|
1676
|
-
|
|
1677
|
-
// Separate out some special terms into parentheses after the rest of the
|
|
1678
|
-
// version, to make them stand out visually.
|
|
1679
|
-
for (const whitelisted of ['debug', 'uncompiled']) {
|
|
1680
|
-
if (split.includes(whitelisted)) {
|
|
1681
|
-
inParen.push(whitelisted);
|
|
1682
|
-
split = split.filter((term) => term != whitelisted);
|
|
1683
|
-
}
|
|
1684
|
-
}
|
|
1685
|
-
|
|
1686
|
-
// Put the version into the version string div.
|
|
1687
|
-
const versionStringDivs = document.getElementsByClassName('version-string');
|
|
1688
|
-
for (const div of versionStringDivs) {
|
|
1689
|
-
div.textContent = split.join('-');
|
|
1690
|
-
if (inParen.length > 0) {
|
|
1691
|
-
div.textContent += ' (' + inParen.join(', ') + ')';
|
|
1692
|
-
}
|
|
1693
|
-
}
|
|
1694
|
-
}
|
|
1695
|
-
|
|
1696
|
-
/**
|
|
1697
|
-
* Closes the error bar.
|
|
1698
|
-
* @private
|
|
1699
|
-
*/
|
|
1700
|
-
closeError_() {
|
|
1701
|
-
document.getElementById('error-display').classList.add('hidden');
|
|
1702
|
-
this.errorDisplayLink_.href = '';
|
|
1703
|
-
this.errorDisplayLink_.textContent = '';
|
|
1704
|
-
this.currentErrorSeverity_ = null;
|
|
1705
|
-
}
|
|
1706
|
-
|
|
1707
|
-
/**
|
|
1708
|
-
* @param {!Event} event
|
|
1709
|
-
* @private
|
|
1710
|
-
*/
|
|
1711
|
-
onErrorEvent_(event) {
|
|
1712
|
-
// TODO: generate externs automatically from @event types
|
|
1713
|
-
// This event should be shaka.Player.ErrorEvent
|
|
1714
|
-
this.onError_(event['detail']);
|
|
1715
|
-
}
|
|
1716
|
-
|
|
1717
|
-
/**
|
|
1718
|
-
* @param {!shaka.util.Error} error
|
|
1719
|
-
* @private
|
|
1720
|
-
*/
|
|
1721
|
-
onError_(error) {
|
|
1722
|
-
let severity = error.severity;
|
|
1723
|
-
if (severity == null || error.severity == undefined) {
|
|
1724
|
-
// It's not a shaka.util.Error. Treat it as very severe, since those
|
|
1725
|
-
// should not be happening.
|
|
1726
|
-
severity = shaka.util.Error.Severity.CRITICAL;
|
|
1727
|
-
}
|
|
1728
|
-
|
|
1729
|
-
const message = error.message || ('Error code ' + error.code);
|
|
1730
|
-
|
|
1731
|
-
let href = '';
|
|
1732
|
-
if (error.code) {
|
|
1733
|
-
href = '../docs/api/shaka.util.Error.html#value:' + error.code;
|
|
1734
|
-
}
|
|
1735
|
-
|
|
1736
|
-
console.error(error);
|
|
1737
|
-
this.handleError_(severity, message, href);
|
|
1738
|
-
}
|
|
1739
|
-
|
|
1740
|
-
/**
|
|
1741
|
-
* @param {!shaka.util.Error.Severity} severity
|
|
1742
|
-
* @param {string} message
|
|
1743
|
-
* @param {string} href
|
|
1744
|
-
* @private
|
|
1745
|
-
*/
|
|
1746
|
-
handleError_(severity, message, href) {
|
|
1747
|
-
// Always show the new error if:
|
|
1748
|
-
// 1. there is no error showing currently
|
|
1749
|
-
// 2. the new error is more severe than the old one
|
|
1750
|
-
if (this.currentErrorSeverity_ == null ||
|
|
1751
|
-
severity > this.currentErrorSeverity_) {
|
|
1752
|
-
this.errorDisplayLink_.href = href;
|
|
1753
|
-
// IE8 and other very old browsers don't have textContent.
|
|
1754
|
-
if (this.errorDisplayLink_.textContent === undefined) {
|
|
1755
|
-
this.errorDisplayLink_.innerText = message;
|
|
1756
|
-
} else {
|
|
1757
|
-
this.errorDisplayLink_.textContent = message;
|
|
1758
|
-
}
|
|
1759
|
-
this.currentErrorSeverity_ = severity;
|
|
1760
|
-
if (this.errorDisplayLink_.href) {
|
|
1761
|
-
this.errorDisplayLink_.classList.remove('input-disabled');
|
|
1762
|
-
} else {
|
|
1763
|
-
this.errorDisplayLink_.classList.add('input-disabled');
|
|
1764
|
-
}
|
|
1765
|
-
document.getElementById('error-display').classList.remove('hidden');
|
|
1766
|
-
}
|
|
1767
|
-
}
|
|
1768
|
-
|
|
1769
|
-
/**
|
|
1770
|
-
* @param {boolean} connected
|
|
1771
|
-
* @private
|
|
1772
|
-
*/
|
|
1773
|
-
onCastStatusChange_(connected) {
|
|
1774
|
-
if (connected && !this.selectedAsset) {
|
|
1775
|
-
// You joined an existing session.
|
|
1776
|
-
// The exact asset playing is unknown. Just have a selectedAsset, to show
|
|
1777
|
-
// that this is playing something.
|
|
1778
|
-
this.selectedAsset = ShakaDemoAssetInfo.makeBlankAsset();
|
|
1779
|
-
this.showPlayer_();
|
|
1780
|
-
}
|
|
1781
|
-
}
|
|
1782
|
-
|
|
1783
|
-
/** @return {!shaka.extern.AdvancedDrmConfiguration} */
|
|
1784
|
-
static defaultAdvancedDrmConfig() {
|
|
1785
|
-
return {
|
|
1786
|
-
distinctiveIdentifierRequired: false,
|
|
1787
|
-
persistentStateRequired: false,
|
|
1788
|
-
videoRobustness: '',
|
|
1789
|
-
audioRobustness: '',
|
|
1790
|
-
sessionType: '',
|
|
1791
|
-
serverCertificate: new Uint8Array(0),
|
|
1792
|
-
serverCertificateUri: '',
|
|
1793
|
-
individualizationServer: '',
|
|
1794
|
-
};
|
|
1795
|
-
}
|
|
1796
|
-
};
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
/** @type {!Array.<string>} */
|
|
1800
|
-
shakaDemo.Main.commonDrmSystems = [
|
|
1801
|
-
'com.widevine.alpha',
|
|
1802
|
-
'com.microsoft.playready',
|
|
1803
|
-
'com.apple.fps',
|
|
1804
|
-
'com.adobe.primetime',
|
|
1805
|
-
'org.w3.clearkey',
|
|
1806
|
-
];
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
const shakaDemoMain = new shakaDemo.Main();
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
/**
|
|
1813
|
-
* @private
|
|
1814
|
-
* @const {string}
|
|
1815
|
-
*/
|
|
1816
|
-
shakaDemo.Main.mainPoster_ =
|
|
1817
|
-
'https://shaka-player-demo.appspot.com/assets/poster.jpg';
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
/**
|
|
1821
|
-
* @private
|
|
1822
|
-
* @const {string}
|
|
1823
|
-
*/
|
|
1824
|
-
shakaDemo.Main.audioOnlyPoster_ =
|
|
1825
|
-
'https://shaka-player-demo.appspot.com/assets/audioOnly.gif';
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
// If setup fails and the global error handler does, too, (as happened on IE
|
|
1829
|
-
// right before the launch of this demo), at least log that error to the console
|
|
1830
|
-
// for debugging. Wrap init functions in an async function with a try/catch to
|
|
1831
|
-
// make sure no error goes unseen when debugging.
|
|
1832
|
-
/**
|
|
1833
|
-
* @param {function()} initFn
|
|
1834
|
-
* @return {!Promise}
|
|
1835
|
-
* @suppress {accessControls}
|
|
1836
|
-
*/
|
|
1837
|
-
shakaDemo.Main.initWrapper = async (initFn) => {
|
|
1838
|
-
try {
|
|
1839
|
-
await initFn();
|
|
1840
|
-
} catch (error) {
|
|
1841
|
-
shakaDemoMain.onError_(error);
|
|
1842
|
-
console.error(error);
|
|
1843
|
-
}
|
|
1844
|
-
};
|
|
1845
|
-
document.addEventListener('shaka-ui-loaded', () => {
|
|
1846
|
-
shakaDemo.Main.initWrapper(() => shakaDemoMain.init());
|
|
1847
|
-
});
|
|
1848
|
-
document.addEventListener('shaka-ui-load-failed', (event) => {
|
|
1849
|
-
shakaDemo.Main.initWrapper(() => {
|
|
1850
|
-
const reasonCode = /** @type {!shaka.ui.Overlay.FailReasonCode} */ (
|
|
1851
|
-
event['detail']['reasonCode']);
|
|
1852
|
-
shakaDemoMain.initFailed(reasonCode);
|
|
1853
|
-
});
|
|
1854
|
-
});
|