rx-player 4.0.0-beta.0 → 4.0.0-beta.2
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/.eslintrc.js +8 -0
- package/CHANGELOG.md +93 -0
- package/CONTRIBUTING.md +48 -168
- package/FILES.md +40 -92
- package/VERSION +1 -1
- package/dist/_esm5.processed/compat/browser_detection.d.ts +25 -12
- package/dist/_esm5.processed/compat/browser_detection.js +85 -38
- package/dist/_esm5.processed/compat/can_reuse_media_keys.js +2 -2
- package/dist/_esm5.processed/compat/eme/close_session.js +2 -2
- package/dist/_esm5.processed/compat/eme/load_session.js +1 -1
- package/dist/_esm5.processed/compat/event_listeners.js +1 -1
- package/dist/_esm5.processed/compat/has_issues_with_high_media_source_duration.d.ts +21 -0
- package/dist/_esm5.processed/compat/has_issues_with_high_media_source_duration.js +26 -0
- package/dist/_esm5.processed/config.d.ts +4 -0
- package/dist/_esm5.processed/core/adaptive/adaptive_representation_selector.js +9 -6
- package/dist/_esm5.processed/core/adaptive/buffer_based_chooser.d.ts +18 -1
- package/dist/_esm5.processed/core/adaptive/buffer_based_chooser.js +106 -25
- package/dist/_esm5.processed/core/adaptive/guess_based_chooser.js +6 -6
- package/dist/_esm5.processed/core/adaptive/network_analyzer.js +8 -5
- package/dist/_esm5.processed/core/adaptive/utils/representation_score_calculator.d.ts +19 -1
- package/dist/_esm5.processed/core/adaptive/utils/representation_score_calculator.js +1 -1
- package/dist/_esm5.processed/core/api/debug/buffer_graph.d.ts +28 -0
- package/dist/_esm5.processed/core/api/debug/buffer_graph.js +175 -0
- package/dist/_esm5.processed/core/api/debug/buffer_size_graph.d.ts +10 -0
- package/dist/_esm5.processed/core/api/debug/buffer_size_graph.js +104 -0
- package/dist/_esm5.processed/core/api/debug/constants.d.ts +2 -0
- package/dist/_esm5.processed/core/api/debug/constants.js +2 -0
- package/dist/_esm5.processed/core/api/debug/index.d.ts +2 -0
- package/dist/_esm5.processed/core/api/debug/index.js +2 -0
- package/dist/_esm5.processed/core/api/debug/modules/general_info.d.ts +3 -0
- package/dist/_esm5.processed/core/api/debug/modules/general_info.js +180 -0
- package/dist/_esm5.processed/core/api/debug/modules/segment_buffer_content.d.ts +4 -0
- package/dist/_esm5.processed/core/api/debug/modules/segment_buffer_content.js +121 -0
- package/dist/_esm5.processed/core/api/debug/modules/segment_buffer_size.d.ts +3 -0
- package/dist/_esm5.processed/core/api/debug/modules/segment_buffer_size.js +35 -0
- package/dist/_esm5.processed/core/api/debug/render.d.ts +3 -0
- package/dist/_esm5.processed/core/api/debug/render.js +32 -0
- package/dist/_esm5.processed/core/api/debug/utils.d.ts +39 -0
- package/dist/_esm5.processed/core/api/debug/utils.js +57 -0
- package/dist/_esm5.processed/core/api/playback_observer.js +4 -2
- package/dist/_esm5.processed/core/api/public_api.d.ts +60 -3
- package/dist/_esm5.processed/core/api/public_api.js +280 -60
- package/dist/_esm5.processed/core/api/track_management/media_element_tracks_store.js +10 -1
- package/dist/_esm5.processed/core/api/track_management/track_dispatcher.d.ts +13 -1
- package/dist/_esm5.processed/core/api/track_management/track_dispatcher.js +30 -15
- package/dist/_esm5.processed/core/api/track_management/tracks_store.d.ts +3 -1
- package/dist/_esm5.processed/core/api/track_management/tracks_store.js +67 -152
- package/dist/_esm5.processed/core/api/utils.d.ts +10 -0
- package/dist/_esm5.processed/core/api/utils.js +23 -3
- package/dist/_esm5.processed/core/decrypt/__tests__/__global__/utils.d.ts +27 -8
- package/dist/_esm5.processed/core/decrypt/__tests__/__global__/utils.js +28 -7
- package/dist/_esm5.processed/core/decrypt/attach_media_keys.js +1 -1
- package/dist/_esm5.processed/core/decrypt/content_decryptor.js +1 -1
- package/dist/_esm5.processed/core/decrypt/find_key_system.js +29 -6
- package/dist/_esm5.processed/core/decrypt/session_events_listener.js +42 -32
- package/dist/_esm5.processed/core/decrypt/utils/check_key_statuses.js +4 -0
- package/dist/_esm5.processed/core/decrypt/utils/clean_old_loaded_sessions.js +2 -0
- package/dist/_esm5.processed/core/decrypt/utils/loaded_sessions_store.js +5 -1
- package/dist/_esm5.processed/core/fetchers/cdn_prioritizer.d.ts +17 -8
- package/dist/_esm5.processed/core/fetchers/cdn_prioritizer.js +10 -6
- package/dist/_esm5.processed/core/fetchers/manifest/manifest_fetcher.js +5 -4
- package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher.d.ts +22 -5
- package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher.js +37 -21
- package/dist/_esm5.processed/core/fetchers/segment/task_prioritizer.js +21 -23
- package/dist/_esm5.processed/core/fetchers/utils/schedule_request.js +17 -7
- package/dist/_esm5.processed/core/init/directfile_content_initializer.js +2 -2
- package/dist/_esm5.processed/core/init/media_source_content_initializer.js +74 -41
- package/dist/_esm5.processed/core/init/types.d.ts +9 -1
- package/dist/_esm5.processed/core/init/utils/content_time_boundaries_observer.d.ts +28 -1
- package/dist/_esm5.processed/core/init/utils/content_time_boundaries_observer.js +24 -11
- package/dist/_esm5.processed/core/init/utils/create_media_source.js +3 -12
- package/dist/_esm5.processed/core/init/utils/end_of_stream.js +6 -3
- package/dist/_esm5.processed/core/init/utils/get_loaded_reference.js +2 -1
- package/dist/_esm5.processed/core/init/utils/initial_seek_and_play.js +9 -5
- package/dist/_esm5.processed/core/init/utils/initialize_content_decryption.js +2 -1
- package/dist/_esm5.processed/core/init/utils/media_source_duration_updater.d.ts +58 -0
- package/dist/_esm5.processed/core/init/utils/{media_duration_updater.js → media_source_duration_updater.js} +87 -86
- package/dist/_esm5.processed/core/init/utils/rebuffering_controller.d.ts +36 -2
- package/dist/_esm5.processed/core/init/utils/rebuffering_controller.js +83 -3
- package/dist/_esm5.processed/core/init/utils/stream_events_emitter/stream_events_emitter.js +6 -4
- package/dist/_esm5.processed/core/init/utils/throw_on_media_error.js +1 -1
- package/dist/_esm5.processed/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.d.ts +18 -7
- package/dist/_esm5.processed/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.js +38 -50
- package/dist/_esm5.processed/core/segment_buffers/implementations/text/html/html_text_segment_buffer.d.ts +8 -0
- package/dist/_esm5.processed/core/segment_buffers/implementations/text/html/html_text_segment_buffer.js +16 -2
- package/dist/_esm5.processed/core/segment_buffers/implementations/text/native/native_text_segment_buffer.d.ts +8 -0
- package/dist/_esm5.processed/core/segment_buffers/implementations/text/native/native_text_segment_buffer.js +12 -0
- package/dist/_esm5.processed/core/segment_buffers/implementations/types.d.ts +11 -4
- package/dist/_esm5.processed/core/segment_buffers/index.d.ts +2 -2
- package/dist/_esm5.processed/core/segment_buffers/segment_buffers_store.js +13 -9
- package/dist/_esm5.processed/core/stream/adaptation/adaptation_stream.js +30 -16
- package/dist/_esm5.processed/core/stream/adaptation/utils/create_representation_estimator.d.ts +47 -0
- package/dist/_esm5.processed/core/stream/adaptation/utils/create_representation_estimator.js +70 -0
- package/dist/_esm5.processed/core/stream/orchestrator/stream_orchestrator.js +41 -20
- package/dist/_esm5.processed/core/stream/period/period_stream.js +12 -11
- package/dist/_esm5.processed/core/stream/representation/representation_stream.js +37 -28
- package/dist/_esm5.processed/core/stream/representation/utils/append_segment_to_buffer.d.ts +4 -2
- package/dist/_esm5.processed/core/stream/representation/utils/append_segment_to_buffer.js +3 -3
- package/dist/_esm5.processed/core/stream/representation/utils/downloading_queue.js +16 -6
- package/dist/_esm5.processed/core/stream/representation/utils/push_init_segment.d.ts +3 -2
- package/dist/_esm5.processed/core/stream/representation/utils/push_init_segment.js +8 -8
- package/dist/_esm5.processed/core/stream/representation/utils/push_media_segment.d.ts +2 -2
- package/dist/_esm5.processed/core/stream/representation/utils/push_media_segment.js +2 -3
- package/dist/_esm5.processed/core/stream/utils/create_reload_request.js +1 -1
- package/dist/_esm5.processed/default_config.d.ts +41 -0
- package/dist/_esm5.processed/default_config.js +46 -2
- package/dist/_esm5.processed/errors/index.d.ts +2 -2
- package/dist/_esm5.processed/errors/media_error.d.ts +23 -1
- package/dist/_esm5.processed/errors/media_error.js +18 -5
- package/dist/_esm5.processed/experimental/features/debug_element.d.ts +8 -0
- package/dist/_esm5.processed/experimental/features/debug_element.js +10 -0
- package/dist/_esm5.processed/experimental/features/index.d.ts +1 -0
- package/dist/_esm5.processed/experimental/features/index.js +1 -0
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/load_and_push_segment.d.ts +1 -1
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/load_and_push_segment.js +8 -7
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/prepare_source_buffer.js +7 -4
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.js +24 -12
- package/dist/_esm5.processed/experimental/tools/mediaCapabilitiesProber/index.js +0 -2
- package/dist/_esm5.processed/features/features_object.js +1 -0
- package/dist/_esm5.processed/features/initialize_features.js +13 -10
- package/dist/_esm5.processed/features/types.d.ts +3 -0
- package/dist/_esm5.processed/manifest/adaptation.d.ts +21 -2
- package/dist/_esm5.processed/manifest/adaptation.js +80 -1
- package/dist/_esm5.processed/manifest/manifest.js +2 -0
- package/dist/_esm5.processed/manifest/period.js +2 -2
- package/dist/_esm5.processed/manifest/representation.d.ts +33 -2
- package/dist/_esm5.processed/manifest/representation.js +32 -4
- package/dist/_esm5.processed/manifest/utils.js +1 -3
- package/dist/_esm5.processed/parsers/manifest/dash/common/parse_adaptation_sets.js +105 -137
- package/dist/_esm5.processed/parsers/manifest/dash/common/parse_representations.js +25 -5
- package/dist/_esm5.processed/parsers/manifest/dash/js-parser/parse_from_document.d.ts +1 -1
- package/dist/_esm5.processed/parsers/manifest/dash/js-parser/parse_from_document.js +1 -1
- package/dist/_esm5.processed/parsers/manifest/dash/wasm-parser/ts/dash-wasm-parser.js +1 -0
- package/dist/_esm5.processed/public_types.d.ts +13 -3
- package/dist/_esm5.processed/tools/TextTrackRenderer/text_track_renderer.js +1 -1
- package/dist/_esm5.processed/transports/dash/add_segment_integrity_checks_to_loader.js +15 -11
- package/dist/_esm5.processed/transports/dash/low_latency_segment_loader.js +2 -2
- package/dist/_esm5.processed/transports/dash/manifest_parser.js +1 -1
- package/dist/_esm5.processed/transports/dash/segment_loader.js +4 -4
- package/dist/_esm5.processed/transports/local/segment_loader.js +13 -26
- package/dist/_esm5.processed/transports/smooth/isobmff/create_boxes.d.ts +4 -6
- package/dist/_esm5.processed/transports/smooth/isobmff/create_boxes.js +4 -6
- package/dist/_esm5.processed/transports/smooth/segment_loader.js +4 -4
- package/dist/_esm5.processed/transports/utils/call_custom_manifest_loader.js +3 -3
- package/dist/_esm5.processed/utils/cancellable_sleep.js +4 -10
- package/dist/_esm5.processed/utils/create_cancellable_promise.d.ts +26 -0
- package/dist/_esm5.processed/utils/create_cancellable_promise.js +52 -0
- package/dist/_esm5.processed/utils/is_null_or_undefined.d.ts +1 -1
- package/dist/_esm5.processed/utils/is_null_or_undefined.js +1 -1
- package/dist/_esm5.processed/utils/reference.js +6 -0
- package/dist/_esm5.processed/utils/request/xhr.js +1 -1
- package/dist/_esm5.processed/utils/task_canceller.d.ts +34 -15
- package/dist/_esm5.processed/utils/task_canceller.js +55 -22
- package/dist/mpd-parser.wasm +0 -0
- package/dist/rx-player.js +5424 -4712
- package/dist/rx-player.min.js +1 -1
- package/jest.config.js +1 -5
- package/package.json +44 -40
- package/scripts/build/constants.d.ts +1 -0
- package/scripts/build/generate_build.js +1 -1
- package/scripts/fast_demo_build.js +40 -40
- package/scripts/generate_full_demo.js +1 -1
- package/sonar-project.properties +1 -1
- package/src/compat/browser_detection.ts +105 -52
- package/src/compat/can_reuse_media_keys.ts +5 -2
- package/src/compat/eme/close_session.ts +2 -2
- package/src/compat/eme/load_session.ts +1 -1
- package/src/compat/event_listeners.ts +1 -1
- package/src/compat/has_issues_with_high_media_source_duration.ts +27 -0
- package/src/core/adaptive/__tests__/buffer_based_chooser.test.ts +147 -48
- package/src/core/adaptive/adaptive_representation_selector.ts +11 -6
- package/src/core/adaptive/buffer_based_chooser.ts +144 -26
- package/src/core/adaptive/guess_based_chooser.ts +9 -8
- package/src/core/adaptive/network_analyzer.ts +9 -4
- package/src/core/adaptive/utils/representation_score_calculator.ts +22 -2
- package/src/core/api/debug/buffer_graph.ts +247 -0
- package/src/core/api/debug/buffer_size_graph.ts +130 -0
- package/src/core/api/debug/constants.ts +2 -0
- package/src/core/api/debug/index.ts +3 -0
- package/src/core/api/debug/modules/general_info.ts +184 -0
- package/src/core/api/debug/modules/segment_buffer_content.ts +155 -0
- package/src/core/api/debug/modules/segment_buffer_size.ts +48 -0
- package/src/core/api/debug/render.ts +40 -0
- package/src/core/api/debug/utils.ts +103 -0
- package/src/core/api/playback_observer.ts +5 -2
- package/src/core/api/public_api.ts +334 -73
- package/src/core/api/track_management/media_element_tracks_store.ts +17 -8
- package/src/core/api/track_management/track_dispatcher.ts +37 -14
- package/src/core/api/track_management/tracks_store.ts +77 -167
- package/src/core/api/utils.ts +29 -3
- package/src/core/decrypt/__tests__/__global__/utils.ts +61 -40
- package/src/core/decrypt/attach_media_keys.ts +1 -1
- package/src/core/decrypt/content_decryptor.ts +1 -1
- package/src/core/decrypt/find_key_system.ts +25 -11
- package/src/core/decrypt/session_events_listener.ts +45 -39
- package/src/core/decrypt/utils/check_key_statuses.ts +6 -0
- package/src/core/decrypt/utils/clean_old_loaded_sessions.ts +2 -1
- package/src/core/decrypt/utils/loaded_sessions_store.ts +8 -1
- package/src/core/fetchers/cdn_prioritizer.ts +18 -9
- package/src/core/fetchers/manifest/manifest_fetcher.ts +5 -4
- package/src/core/fetchers/segment/segment_fetcher.ts +36 -14
- package/src/core/fetchers/segment/task_prioritizer.ts +25 -30
- package/src/core/fetchers/utils/schedule_request.ts +18 -7
- package/src/core/init/directfile_content_initializer.ts +2 -1
- package/src/core/init/media_source_content_initializer.ts +89 -50
- package/src/core/init/types.ts +9 -1
- package/src/core/init/utils/content_time_boundaries_observer.ts +48 -12
- package/src/core/init/utils/create_media_source.ts +4 -16
- package/src/core/init/utils/end_of_stream.ts +6 -3
- package/src/core/init/utils/get_loaded_reference.ts +2 -1
- package/src/core/init/utils/initial_seek_and_play.ts +9 -5
- package/src/core/init/utils/initialize_content_decryption.ts +2 -1
- package/src/core/init/utils/{media_duration_updater.ts → media_source_duration_updater.ts} +103 -110
- package/src/core/init/utils/rebuffering_controller.ts +115 -4
- package/src/core/init/utils/stream_events_emitter/stream_events_emitter.ts +6 -4
- package/src/core/init/utils/throw_on_media_error.ts +1 -1
- package/src/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.ts +63 -66
- package/src/core/segment_buffers/implementations/text/html/html_text_segment_buffer.ts +20 -2
- package/src/core/segment_buffers/implementations/text/native/native_text_segment_buffer.ts +16 -0
- package/src/core/segment_buffers/implementations/types.ts +16 -4
- package/src/core/segment_buffers/index.ts +2 -0
- package/src/core/segment_buffers/segment_buffers_store.ts +16 -13
- package/src/core/stream/adaptation/adaptation_stream.ts +33 -19
- package/src/core/stream/adaptation/utils/create_representation_estimator.ts +114 -0
- package/src/core/stream/orchestrator/stream_orchestrator.ts +42 -20
- package/src/core/stream/period/period_stream.ts +13 -11
- package/src/core/stream/representation/representation_stream.ts +49 -37
- package/src/core/stream/representation/utils/append_segment_to_buffer.ts +9 -4
- package/src/core/stream/representation/utils/downloading_queue.ts +16 -4
- package/src/core/stream/representation/utils/push_init_segment.ts +11 -6
- package/src/core/stream/representation/utils/push_media_segment.ts +3 -3
- package/src/core/stream/utils/create_reload_request.ts +1 -1
- package/src/default_config.ts +59 -11
- package/src/errors/__tests__/media_error.test.ts +6 -6
- package/src/errors/index.ts +4 -1
- package/src/errors/media_error.ts +67 -1
- package/src/experimental/features/__tests__/debug_element.test.ts +26 -0
- package/src/experimental/features/debug_element.ts +13 -0
- package/src/experimental/features/index.ts +1 -0
- package/src/experimental/tools/VideoThumbnailLoader/load_and_push_segment.ts +10 -7
- package/src/experimental/tools/VideoThumbnailLoader/prepare_source_buffer.ts +7 -4
- package/src/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.ts +25 -10
- package/src/experimental/tools/mediaCapabilitiesProber/index.ts +0 -4
- package/src/features/__tests__/initialize_features.test.ts +11 -0
- package/src/features/features_object.ts +1 -0
- package/src/features/initialize_features.ts +15 -10
- package/src/features/types.ts +9 -0
- package/src/manifest/__tests__/manifest.test.ts +7 -7
- package/src/manifest/__tests__/period.test.ts +90 -45
- package/src/manifest/adaptation.ts +96 -1
- package/src/manifest/manifest.ts +4 -0
- package/src/manifest/period.ts +4 -2
- package/src/manifest/representation.ts +77 -5
- package/src/manifest/utils.ts +1 -3
- package/src/parsers/manifest/dash/common/parse_adaptation_sets.ts +116 -151
- package/src/parsers/manifest/dash/common/parse_representations.ts +21 -4
- package/src/parsers/manifest/dash/js-parser/parse_from_document.ts +1 -1
- package/src/parsers/manifest/dash/wasm-parser/ts/dash-wasm-parser.ts +1 -0
- package/src/parsers/texttracks/ttml/parse_ttml.ts +1 -1
- package/src/public_types.ts +16 -1
- package/src/tools/TextTrackRenderer/text_track_renderer.ts +1 -1
- package/src/transports/dash/add_segment_integrity_checks_to_loader.ts +31 -22
- package/src/transports/dash/low_latency_segment_loader.ts +2 -2
- package/src/transports/dash/manifest_parser.ts +1 -1
- package/src/transports/dash/segment_loader.ts +4 -4
- package/src/transports/local/segment_loader.ts +14 -30
- package/src/transports/smooth/isobmff/create_boxes.ts +4 -6
- package/src/transports/smooth/segment_loader.ts +4 -4
- package/src/transports/utils/call_custom_manifest_loader.ts +3 -3
- package/src/typings/globals.d.ts +21 -19
- package/src/utils/cancellable_sleep.ts +5 -14
- package/src/utils/create_cancellable_promise.ts +69 -0
- package/src/utils/is_null_or_undefined.ts +1 -1
- package/src/utils/reference.ts +6 -0
- package/src/utils/request/xhr.ts +1 -1
- package/src/utils/task_canceller.ts +63 -34
- package/tsconfig.json +1 -1
- package/tsconfig.modules.json +1 -1
- package/dist/_esm5.processed/core/init/utils/media_duration_updater.d.ts +0 -56
- package/locked_reps.js +0 -46
- package/scripts/doc-generator/construct_table_of_contents.js +0 -76
- package/scripts/doc-generator/convert_MD_to_HMTL.js +0 -26
- package/scripts/doc-generator/create_documentation.js +0 -331
- package/scripts/doc-generator/create_documentation_page.js +0 -209
- package/scripts/doc-generator/create_page.js +0 -210
- package/scripts/doc-generator/generate_header_html.js +0 -147
- package/scripts/doc-generator/generate_page_html.js +0 -115
- package/scripts/doc-generator/generate_page_list_html.js +0 -92
- package/scripts/doc-generator/generate_sidebar_html.js +0 -85
- package/scripts/doc-generator/get_search_data_for_content.js +0 -137
- package/scripts/doc-generator/index.js +0 -34
- package/scripts/doc-generator/parse_doc_configs.js +0 -327
- package/scripts/doc-generator/scripts/lunr.js +0 -10
- package/scripts/doc-generator/scripts/script.js +0 -451
- package/scripts/doc-generator/styles/code.css +0 -99
- package/scripts/doc-generator/styles/style.css +0 -835
- package/scripts/doc-generator/utils.js +0 -74
|
@@ -57,6 +57,7 @@ import {
|
|
|
57
57
|
ILockedAudioRepresentationsSettings,
|
|
58
58
|
ILockedVideoRepresentationsSettings,
|
|
59
59
|
ITrackUpdateEventPayload,
|
|
60
|
+
IRepresentationListUpdateContext,
|
|
60
61
|
IPeriod,
|
|
61
62
|
IPeriodChangeEvent,
|
|
62
63
|
IPlayerError,
|
|
@@ -70,7 +71,10 @@ import {
|
|
|
70
71
|
IVideoTrack,
|
|
71
72
|
IVideoTrackSetting,
|
|
72
73
|
IVideoTrackSwitchingMode,
|
|
74
|
+
ITrackType,
|
|
73
75
|
} from "../../public_types";
|
|
76
|
+
import arrayFind from "../../utils/array_find";
|
|
77
|
+
import arrayIncludes from "../../utils/array_includes";
|
|
74
78
|
import assert from "../../utils/assert";
|
|
75
79
|
import assertUnreachable from "../../utils/assert_unreachable";
|
|
76
80
|
import EventEmitter, {
|
|
@@ -123,9 +127,9 @@ import TracksStore, {
|
|
|
123
127
|
} from "./track_management/tracks_store";
|
|
124
128
|
import {
|
|
125
129
|
constructPlayerStateReference,
|
|
130
|
+
emitPlayPauseEvents,
|
|
126
131
|
emitSeekEvents,
|
|
127
132
|
isLoadedState,
|
|
128
|
-
// emitSeekEvents,
|
|
129
133
|
PLAYER_STATES,
|
|
130
134
|
} from "./utils";
|
|
131
135
|
|
|
@@ -280,6 +284,11 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
280
284
|
reloadPosition?: number;
|
|
281
285
|
};
|
|
282
286
|
|
|
287
|
+
/**
|
|
288
|
+
* Store last value of autoPlay, from the last load or reload.
|
|
289
|
+
*/
|
|
290
|
+
private _priv_lastAutoPlay: boolean;
|
|
291
|
+
|
|
283
292
|
/** All possible Error types emitted by the RxPlayer. */
|
|
284
293
|
static get ErrorTypes() : Record<IErrorType, IErrorType> {
|
|
285
294
|
return ErrorTypes;
|
|
@@ -327,7 +336,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
327
336
|
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=1194624
|
|
328
337
|
videoElement.preload = "auto";
|
|
329
338
|
|
|
330
|
-
this.version = /* PLAYER_VERSION */"4.0.0-beta.
|
|
339
|
+
this.version = /* PLAYER_VERSION */"4.0.0-beta.2";
|
|
331
340
|
this.log = log;
|
|
332
341
|
this.state = "STOPPED";
|
|
333
342
|
this.videoElement = videoElement;
|
|
@@ -372,6 +381,8 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
372
381
|
this._priv_setPlayerState(PLAYER_STATES.STOPPED);
|
|
373
382
|
|
|
374
383
|
this._priv_reloadingMetadata = {};
|
|
384
|
+
|
|
385
|
+
this._priv_lastAutoPlay = false;
|
|
375
386
|
}
|
|
376
387
|
|
|
377
388
|
/**
|
|
@@ -442,6 +453,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
442
453
|
log.info("API: Calling loadvideo", options.url, options.transport);
|
|
443
454
|
this._priv_reloadingMetadata = { options };
|
|
444
455
|
this._priv_initializeContentPlayback(options);
|
|
456
|
+
this._priv_lastAutoPlay = options.autoPlay;
|
|
445
457
|
}
|
|
446
458
|
|
|
447
459
|
/**
|
|
@@ -493,6 +505,21 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
493
505
|
this._priv_initializeContentPlayback(newOptions);
|
|
494
506
|
}
|
|
495
507
|
|
|
508
|
+
public createDebugElement(element : HTMLElement) : {
|
|
509
|
+
dispose() : void;
|
|
510
|
+
} {
|
|
511
|
+
if (features.createDebugElement === null) {
|
|
512
|
+
throw new Error("Feature `DEBUG_ELEMENT` not added to the RxPlayer");
|
|
513
|
+
}
|
|
514
|
+
const canceller = new TaskCanceller() ;
|
|
515
|
+
features.createDebugElement(element, this, canceller.signal);
|
|
516
|
+
return {
|
|
517
|
+
dispose() {
|
|
518
|
+
canceller.cancel();
|
|
519
|
+
},
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
|
|
496
523
|
/**
|
|
497
524
|
* From given options, initialize content playback.
|
|
498
525
|
* @param {Object} options
|
|
@@ -639,7 +666,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
639
666
|
}
|
|
640
667
|
mediaElementTracksStore =
|
|
641
668
|
this._priv_initializeMediaElementTracksStore(currentContentCanceller.signal);
|
|
642
|
-
if (currentContentCanceller.isUsed) {
|
|
669
|
+
if (currentContentCanceller.isUsed()) {
|
|
643
670
|
return;
|
|
644
671
|
}
|
|
645
672
|
initializer = new features.directfile.initDirectFile({ autoPlay,
|
|
@@ -668,26 +695,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
668
695
|
|
|
669
696
|
// Bind events
|
|
670
697
|
initializer.addEventListener("error", (error) => {
|
|
671
|
-
|
|
672
|
-
defaultCode: "NONE",
|
|
673
|
-
defaultReason: "An unknown error stopped content playback.",
|
|
674
|
-
});
|
|
675
|
-
formattedError.fatal = true;
|
|
676
|
-
|
|
677
|
-
contentInfos.currentContentCanceller.cancel();
|
|
678
|
-
this._priv_cleanUpCurrentContentState();
|
|
679
|
-
this._priv_currentError = formattedError;
|
|
680
|
-
log.error("API: The player stopped because of an error",
|
|
681
|
-
error instanceof Error ? error : "");
|
|
682
|
-
this._priv_setPlayerState(PLAYER_STATES.STOPPED);
|
|
683
|
-
|
|
684
|
-
// TODO This condition is here because the eventual callback called when the
|
|
685
|
-
// player state is updated can launch a new content, thus the error will not
|
|
686
|
-
// be here anymore, in which case triggering the "error" event is unwanted.
|
|
687
|
-
// This is very ugly though, and we should probable have a better solution
|
|
688
|
-
if (this._priv_currentError === formattedError) {
|
|
689
|
-
this.trigger("error", formattedError);
|
|
690
|
-
}
|
|
698
|
+
this._priv_onFatalError(error, contentInfos);
|
|
691
699
|
});
|
|
692
700
|
initializer.addEventListener("warning", (error) => {
|
|
693
701
|
const formattedError = formatError(error, {
|
|
@@ -697,11 +705,12 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
697
705
|
log.warn("API: Sending warning:", formattedError);
|
|
698
706
|
this.trigger("warning", formattedError);
|
|
699
707
|
});
|
|
700
|
-
initializer.addEventListener("reloadingMediaSource", () => {
|
|
708
|
+
initializer.addEventListener("reloadingMediaSource", (payload) => {
|
|
701
709
|
contentInfos.segmentBuffersStore = null;
|
|
702
710
|
if (contentInfos.tracksStore !== null) {
|
|
703
711
|
contentInfos.tracksStore.resetPeriodObjects();
|
|
704
712
|
}
|
|
713
|
+
this._priv_lastAutoPlay = payload.autoPlay;
|
|
705
714
|
});
|
|
706
715
|
initializer.addEventListener("inbandEvents", (inbandEvents) =>
|
|
707
716
|
this.trigger("inbandEvents", inbandEvents));
|
|
@@ -785,6 +794,53 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
785
794
|
}
|
|
786
795
|
};
|
|
787
796
|
|
|
797
|
+
/**
|
|
798
|
+
* `TaskCanceller` allowing to stop emitting `"play"` and `"pause"`
|
|
799
|
+
* events.
|
|
800
|
+
* `null` when such events are not emitted currently.
|
|
801
|
+
*/
|
|
802
|
+
let playPauseEventsCanceller : TaskCanceller | null = null;
|
|
803
|
+
|
|
804
|
+
/**
|
|
805
|
+
* Callback emitting `"play"` and `"pause`" events once the content is
|
|
806
|
+
* loaded, starting from the state indicated in argument.
|
|
807
|
+
* @param {boolean} willAutoPlay - If `false`, we're currently paused.
|
|
808
|
+
*/
|
|
809
|
+
const triggerPlayPauseEventsWhenReady = (willAutoPlay: boolean) => {
|
|
810
|
+
if (playPauseEventsCanceller !== null) {
|
|
811
|
+
playPauseEventsCanceller.cancel(); // cancel previous logic
|
|
812
|
+
playPauseEventsCanceller = null;
|
|
813
|
+
}
|
|
814
|
+
playerStateRef.onUpdate((val, stopListeningToStateUpdates) => {
|
|
815
|
+
if (!isLoadedState(val)) {
|
|
816
|
+
return; // content not loaded yet: no event
|
|
817
|
+
}
|
|
818
|
+
stopListeningToStateUpdates();
|
|
819
|
+
if (playPauseEventsCanceller !== null) {
|
|
820
|
+
playPauseEventsCanceller.cancel();
|
|
821
|
+
}
|
|
822
|
+
playPauseEventsCanceller = new TaskCanceller();
|
|
823
|
+
playPauseEventsCanceller.linkToSignal(currentContentCanceller.signal);
|
|
824
|
+
if (willAutoPlay !== !videoElement.paused) {
|
|
825
|
+
// paused status is not at the expected value on load: emit event
|
|
826
|
+
if (videoElement.paused) {
|
|
827
|
+
this.trigger("pause", null);
|
|
828
|
+
} else {
|
|
829
|
+
this.trigger("play", null);
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
emitPlayPauseEvents(videoElement,
|
|
833
|
+
() => this.trigger("play", null),
|
|
834
|
+
() => this.trigger("pause", null),
|
|
835
|
+
currentContentCanceller.signal);
|
|
836
|
+
}, { emitCurrentValue: false, clearSignal: currentContentCanceller.signal });
|
|
837
|
+
};
|
|
838
|
+
|
|
839
|
+
triggerPlayPauseEventsWhenReady(autoPlay);
|
|
840
|
+
initializer.addEventListener("reloadingMediaSource", (payload) => {
|
|
841
|
+
triggerPlayPauseEventsWhenReady(payload.autoPlay);
|
|
842
|
+
});
|
|
843
|
+
|
|
788
844
|
/**
|
|
789
845
|
* `TaskCanceller` allowing to stop emitting `"seeking"` and `"seeked"`
|
|
790
846
|
* events.
|
|
@@ -797,7 +853,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
797
853
|
updateReloadingMetadata(newState);
|
|
798
854
|
this._priv_setPlayerState(newState);
|
|
799
855
|
|
|
800
|
-
if (currentContentCanceller.isUsed) {
|
|
856
|
+
if (currentContentCanceller.isUsed()) {
|
|
801
857
|
return;
|
|
802
858
|
}
|
|
803
859
|
|
|
@@ -807,9 +863,8 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
807
863
|
seekEventsCanceller = null;
|
|
808
864
|
}
|
|
809
865
|
} else if (isLoadedState(this.state)) {
|
|
810
|
-
seekEventsCanceller = new TaskCanceller(
|
|
811
|
-
|
|
812
|
-
});
|
|
866
|
+
seekEventsCanceller = new TaskCanceller();
|
|
867
|
+
seekEventsCanceller.linkToSignal(currentContentCanceller.signal);
|
|
813
868
|
emitSeekEvents(videoElement,
|
|
814
869
|
playbackObserver,
|
|
815
870
|
() => this.trigger("seeking", null),
|
|
@@ -870,6 +925,42 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
870
925
|
return this.state;
|
|
871
926
|
}
|
|
872
927
|
|
|
928
|
+
/**
|
|
929
|
+
* Returns true if a content is loaded.
|
|
930
|
+
* @returns {Boolean} - `true` if a content is loaded, `false` otherwise.
|
|
931
|
+
*/
|
|
932
|
+
isContentLoaded() : boolean {
|
|
933
|
+
return !arrayIncludes(["LOADING", "RELOADING", "STOPPED"], this.state);
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
/**
|
|
937
|
+
* Returns true if the player is buffering.
|
|
938
|
+
* @returns {Boolean} - `true` if the player is buffering, `false` otherwise.
|
|
939
|
+
*/
|
|
940
|
+
isBuffering() : boolean {
|
|
941
|
+
return arrayIncludes(["BUFFERING", "SEEKING", "LOADING", "RELOADING"], this.state);
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
/**
|
|
945
|
+
* Returns the play/pause status of the player :
|
|
946
|
+
* - when `LOADING` or `RELOADING`, returns the scheduled play/pause condition
|
|
947
|
+
* for when loading is over,
|
|
948
|
+
* - in other states, returns the `<video>` element .paused value,
|
|
949
|
+
* - if the player is disposed, returns `true`.
|
|
950
|
+
* @returns {Boolean} - `true` if the player is paused or will be after loading,
|
|
951
|
+
* `false` otherwise.
|
|
952
|
+
*/
|
|
953
|
+
isPaused() : boolean {
|
|
954
|
+
if (this.videoElement) {
|
|
955
|
+
if (arrayIncludes(["LOADING", "RELOADING"], this.state)) {
|
|
956
|
+
return !this._priv_lastAutoPlay;
|
|
957
|
+
} else {
|
|
958
|
+
return this.videoElement.paused;
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
return true;
|
|
962
|
+
}
|
|
963
|
+
|
|
873
964
|
/**
|
|
874
965
|
* Returns true if both:
|
|
875
966
|
* - a content is loaded
|
|
@@ -1022,6 +1113,15 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
1022
1113
|
return this.videoElement.currentTime;
|
|
1023
1114
|
}
|
|
1024
1115
|
|
|
1116
|
+
/**
|
|
1117
|
+
* Returns the last stored content position, in seconds.
|
|
1118
|
+
*
|
|
1119
|
+
* @returns {number|undefined}
|
|
1120
|
+
*/
|
|
1121
|
+
getLastStoredContentPosition() : number|undefined {
|
|
1122
|
+
return this._priv_reloadingMetadata.reloadPosition;
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1025
1125
|
/**
|
|
1026
1126
|
* Returns the current playback rate at which the video plays.
|
|
1027
1127
|
* @returns {Number}
|
|
@@ -1119,7 +1219,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
1119
1219
|
* @returns {Object|null|undefined}
|
|
1120
1220
|
*/
|
|
1121
1221
|
getVideoRepresentation() : IVideoRepresentation | null | undefined {
|
|
1122
|
-
const representations = this.
|
|
1222
|
+
const representations = this.__priv_getCurrentRepresentations();
|
|
1123
1223
|
if (representations === null) {
|
|
1124
1224
|
return undefined;
|
|
1125
1225
|
}
|
|
@@ -1136,7 +1236,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
1136
1236
|
* @returns {Object|null|undefined}
|
|
1137
1237
|
*/
|
|
1138
1238
|
getAudioRepresentation() : IAudioRepresentation | null | undefined {
|
|
1139
|
-
const representations = this.
|
|
1239
|
+
const representations = this.__priv_getCurrentRepresentations();
|
|
1140
1240
|
if (representations === null) {
|
|
1141
1241
|
return undefined;
|
|
1142
1242
|
}
|
|
@@ -1237,6 +1337,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
1237
1337
|
if (positionWanted === undefined) {
|
|
1238
1338
|
throw new Error("invalid time given");
|
|
1239
1339
|
}
|
|
1340
|
+
log.info("API: API Seek to", positionWanted);
|
|
1240
1341
|
this.videoElement.currentTime = positionWanted;
|
|
1241
1342
|
return positionWanted;
|
|
1242
1343
|
}
|
|
@@ -1891,6 +1992,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
1891
1992
|
* null if the player is STOPPED.
|
|
1892
1993
|
* @returns {Manifest|null} - The current Manifest (`null` when not known).
|
|
1893
1994
|
*/
|
|
1995
|
+
// TODO remove the need for that public method
|
|
1894
1996
|
__priv_getManifest() : Manifest|null {
|
|
1895
1997
|
if (this._priv_contentInfos === null) {
|
|
1896
1998
|
return null;
|
|
@@ -1898,6 +2000,38 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
1898
2000
|
return this._priv_contentInfos.manifest;
|
|
1899
2001
|
}
|
|
1900
2002
|
|
|
2003
|
+
// TODO remove the need for that public method
|
|
2004
|
+
__priv_getCurrentAdaptation(
|
|
2005
|
+
) : Partial<Record<IBufferType, Adaptation|null>> | null {
|
|
2006
|
+
if (this._priv_contentInfos === null) {
|
|
2007
|
+
return null;
|
|
2008
|
+
}
|
|
2009
|
+
const { currentPeriod, activeAdaptations } = this._priv_contentInfos;
|
|
2010
|
+
if (currentPeriod === null ||
|
|
2011
|
+
activeAdaptations === null ||
|
|
2012
|
+
isNullOrUndefined(activeAdaptations[currentPeriod.id]))
|
|
2013
|
+
{
|
|
2014
|
+
return null;
|
|
2015
|
+
}
|
|
2016
|
+
return activeAdaptations[currentPeriod.id];
|
|
2017
|
+
}
|
|
2018
|
+
|
|
2019
|
+
// TODO remove the need for that public method
|
|
2020
|
+
__priv_getCurrentRepresentations(
|
|
2021
|
+
) : Partial<Record<IBufferType, Representation|null>> | null {
|
|
2022
|
+
if (this._priv_contentInfos === null) {
|
|
2023
|
+
return null;
|
|
2024
|
+
}
|
|
2025
|
+
const { currentPeriod, activeRepresentations } = this._priv_contentInfos;
|
|
2026
|
+
if (currentPeriod === null ||
|
|
2027
|
+
activeRepresentations === null ||
|
|
2028
|
+
isNullOrUndefined(activeRepresentations[currentPeriod.id]))
|
|
2029
|
+
{
|
|
2030
|
+
return null;
|
|
2031
|
+
}
|
|
2032
|
+
return activeRepresentations[currentPeriod.id];
|
|
2033
|
+
}
|
|
2034
|
+
|
|
1901
2035
|
// ---- Private methods ----
|
|
1902
2036
|
|
|
1903
2037
|
/**
|
|
@@ -1954,21 +2088,34 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
1954
2088
|
return; // Event for another content
|
|
1955
2089
|
}
|
|
1956
2090
|
contentInfos.manifest = manifest;
|
|
1957
|
-
const cancelSignal = contentInfos.currentContentCanceller.signal;
|
|
1958
2091
|
this._priv_reloadingMetadata.manifest = manifest;
|
|
1959
2092
|
|
|
1960
|
-
|
|
2093
|
+
const tracksStore = new TracksStore({
|
|
1961
2094
|
preferTrickModeTracks: this._priv_preferTrickModeTracks,
|
|
1962
2095
|
defaultAudioTrackSwitchingMode: contentInfos.defaultAudioTrackSwitchingMode,
|
|
1963
2096
|
});
|
|
1964
|
-
contentInfos.tracksStore
|
|
2097
|
+
contentInfos.tracksStore = tracksStore;
|
|
2098
|
+
tracksStore.addEventListener("newAvailablePeriods", (p) => {
|
|
1965
2099
|
this.trigger("newAvailablePeriods", p);
|
|
1966
2100
|
});
|
|
1967
|
-
|
|
2101
|
+
tracksStore.addEventListener("brokenRepresentationsLock", (e) => {
|
|
1968
2102
|
this.trigger("brokenRepresentationsLock", e);
|
|
1969
2103
|
});
|
|
1970
|
-
|
|
2104
|
+
tracksStore.addEventListener("trackUpdate", (e) => {
|
|
1971
2105
|
this.trigger("trackUpdate", e);
|
|
2106
|
+
|
|
2107
|
+
const currentPeriod = this._priv_contentInfos?.currentPeriod ?? undefined;
|
|
2108
|
+
if (e.reason === "no-playable-representation" &&
|
|
2109
|
+
e.period.id === currentPeriod?.id)
|
|
2110
|
+
{
|
|
2111
|
+
this._priv_onAvailableTracksMayHaveChanged(e.trackType);
|
|
2112
|
+
}
|
|
2113
|
+
});
|
|
2114
|
+
contentInfos.tracksStore.addEventListener("warning", (err) => {
|
|
2115
|
+
this.trigger("warning", err);
|
|
2116
|
+
});
|
|
2117
|
+
contentInfos.tracksStore.addEventListener("error", (err) => {
|
|
2118
|
+
this._priv_onFatalError(err, contentInfos);
|
|
1972
2119
|
});
|
|
1973
2120
|
|
|
1974
2121
|
contentInfos.tracksStore.updatePeriodList(manifest);
|
|
@@ -1979,8 +2126,8 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
1979
2126
|
contentInfos.tracksStore.updatePeriodList(manifest);
|
|
1980
2127
|
}
|
|
1981
2128
|
const currentPeriod = this._priv_contentInfos?.currentPeriod ?? undefined;
|
|
1982
|
-
const
|
|
1983
|
-
if (currentPeriod === undefined || isNullOrUndefined(
|
|
2129
|
+
const currTracksStore = this._priv_contentInfos?.tracksStore;
|
|
2130
|
+
if (currentPeriod === undefined || isNullOrUndefined(currTracksStore)) {
|
|
1984
2131
|
return;
|
|
1985
2132
|
}
|
|
1986
2133
|
for (const update of updates.updatedPeriods) {
|
|
@@ -1989,27 +2136,72 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
1989
2136
|
update.result.removedAdaptations.length > 0)
|
|
1990
2137
|
{
|
|
1991
2138
|
// We might have new (or less) tracks, send events just to be sure
|
|
1992
|
-
const periodRef =
|
|
2139
|
+
const periodRef = currTracksStore.getPeriodObjectFromPeriod(currentPeriod);
|
|
1993
2140
|
if (periodRef === undefined) {
|
|
1994
2141
|
return;
|
|
1995
2142
|
}
|
|
1996
|
-
|
|
1997
|
-
this.
|
|
1998
|
-
|
|
1999
|
-
cancelSignal);
|
|
2000
|
-
const textTracks = tracksStore.getAvailableTextTracks(periodRef);
|
|
2001
|
-
this._priv_triggerEventIfNotStopped("availableTextTracksChange",
|
|
2002
|
-
textTracks ?? [],
|
|
2003
|
-
cancelSignal);
|
|
2004
|
-
const videoTracks = tracksStore.getAvailableVideoTracks(periodRef);
|
|
2005
|
-
this._priv_triggerEventIfNotStopped("availableVideoTracksChange",
|
|
2006
|
-
videoTracks ?? [],
|
|
2007
|
-
cancelSignal);
|
|
2143
|
+
this._priv_onAvailableTracksMayHaveChanged("audio");
|
|
2144
|
+
this._priv_onAvailableTracksMayHaveChanged("text");
|
|
2145
|
+
this._priv_onAvailableTracksMayHaveChanged("video");
|
|
2008
2146
|
}
|
|
2009
2147
|
}
|
|
2010
2148
|
return;
|
|
2011
2149
|
}
|
|
2012
2150
|
}, contentInfos.currentContentCanceller.signal);
|
|
2151
|
+
|
|
2152
|
+
manifest.addEventListener("decipherabilityUpdate", (elts) => {
|
|
2153
|
+
/**
|
|
2154
|
+
* Array of tuples only including once the Period/Track combination, and
|
|
2155
|
+
* only when it concerns the currently-selected track.
|
|
2156
|
+
*/
|
|
2157
|
+
const periodsAndTrackTypes = elts.reduce(
|
|
2158
|
+
(acc: Array<[Period, ITrackType]>, elt) => {
|
|
2159
|
+
const isFound = arrayFind(
|
|
2160
|
+
acc,
|
|
2161
|
+
(x) => x[0].id === elt.period.id &&
|
|
2162
|
+
x[1] === elt.adaptation.type
|
|
2163
|
+
) === undefined;
|
|
2164
|
+
|
|
2165
|
+
if (!isFound) {
|
|
2166
|
+
// Only consider the currently-selected tracks.
|
|
2167
|
+
// NOTE: Maybe there's room for optimizations? Unclear.
|
|
2168
|
+
const tStore = contentInfos.tracksStore;
|
|
2169
|
+
if (tStore === null) {
|
|
2170
|
+
return acc;
|
|
2171
|
+
}
|
|
2172
|
+
let isCurrent = false;
|
|
2173
|
+
const periodRef = tStore.getPeriodObjectFromPeriod(elt.period);
|
|
2174
|
+
if (periodRef === undefined) {
|
|
2175
|
+
return acc;
|
|
2176
|
+
}
|
|
2177
|
+
switch (elt.adaptation.type) {
|
|
2178
|
+
case "audio":
|
|
2179
|
+
isCurrent = tStore
|
|
2180
|
+
.getChosenAudioTrack(periodRef)?.id === elt.adaptation.id;
|
|
2181
|
+
break;
|
|
2182
|
+
case "video":
|
|
2183
|
+
isCurrent = tStore
|
|
2184
|
+
.getChosenVideoTrack(periodRef)?.id === elt.adaptation.id;
|
|
2185
|
+
break;
|
|
2186
|
+
case "text":
|
|
2187
|
+
isCurrent = tStore
|
|
2188
|
+
.getChosenTextTrack(periodRef)?.id === elt.adaptation.id;
|
|
2189
|
+
break;
|
|
2190
|
+
}
|
|
2191
|
+
if (isCurrent) {
|
|
2192
|
+
acc.push([elt.period, elt.adaptation.type]);
|
|
2193
|
+
}
|
|
2194
|
+
}
|
|
2195
|
+
return acc;
|
|
2196
|
+
}, []);
|
|
2197
|
+
for (const [period, trackType] of periodsAndTrackTypes) {
|
|
2198
|
+
this._priv_triggerEventIfNotStopped(
|
|
2199
|
+
"representationListUpdate",
|
|
2200
|
+
{ period, trackType, reason: "decipherability-update" },
|
|
2201
|
+
contentInfos.currentContentCanceller.signal
|
|
2202
|
+
);
|
|
2203
|
+
}
|
|
2204
|
+
}, contentInfos.currentContentCanceller.signal);
|
|
2013
2205
|
}
|
|
2014
2206
|
|
|
2015
2207
|
/**
|
|
@@ -2073,15 +2265,11 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
2073
2265
|
this._priv_triggerEventIfNotStopped("videoTrackChange", null, cancelSignal);
|
|
2074
2266
|
}
|
|
2075
2267
|
|
|
2076
|
-
const audioRepresentation = this.
|
|
2268
|
+
const audioRepresentation = this.__priv_getCurrentRepresentations()?.audio ?? null;
|
|
2077
2269
|
this._priv_triggerEventIfNotStopped("audioRepresentationChange",
|
|
2078
2270
|
audioRepresentation,
|
|
2079
2271
|
cancelSignal);
|
|
2080
|
-
|
|
2081
|
-
return;
|
|
2082
|
-
}
|
|
2083
|
-
|
|
2084
|
-
const videoRepresentation = this._priv_getCurrentRepresentations()?.video ?? null;
|
|
2272
|
+
const videoRepresentation = this.__priv_getCurrentRepresentations()?.video ?? null;
|
|
2085
2273
|
this._priv_triggerEventIfNotStopped("videoRepresentationChange",
|
|
2086
2274
|
videoRepresentation,
|
|
2087
2275
|
cancelSignal);
|
|
@@ -2377,21 +2565,6 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
2377
2565
|
this.trigger("positionUpdate", positionData);
|
|
2378
2566
|
}
|
|
2379
2567
|
|
|
2380
|
-
private _priv_getCurrentRepresentations(
|
|
2381
|
-
) : Partial<Record<IBufferType, Representation|null>> | null {
|
|
2382
|
-
if (this._priv_contentInfos === null) {
|
|
2383
|
-
return null;
|
|
2384
|
-
}
|
|
2385
|
-
const { currentPeriod, activeRepresentations } = this._priv_contentInfos;
|
|
2386
|
-
if (currentPeriod === null ||
|
|
2387
|
-
activeRepresentations === null ||
|
|
2388
|
-
isNullOrUndefined(activeRepresentations[currentPeriod.id]))
|
|
2389
|
-
{
|
|
2390
|
-
return null;
|
|
2391
|
-
}
|
|
2392
|
-
return activeRepresentations[currentPeriod.id];
|
|
2393
|
-
}
|
|
2394
|
-
|
|
2395
2568
|
/**
|
|
2396
2569
|
* @param {string} evt
|
|
2397
2570
|
* @param {*} arg
|
|
@@ -2402,7 +2575,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
2402
2575
|
arg : IEventPayload<IPublicAPIEvent, TEventName>,
|
|
2403
2576
|
currentContentCancelSignal : CancellationSignal
|
|
2404
2577
|
) {
|
|
2405
|
-
if (!currentContentCancelSignal.isCancelled) {
|
|
2578
|
+
if (!currentContentCancelSignal.isCancelled()) {
|
|
2406
2579
|
this.trigger(evt, arg);
|
|
2407
2580
|
}
|
|
2408
2581
|
}
|
|
@@ -2497,8 +2670,93 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
2497
2670
|
}
|
|
2498
2671
|
return cb(tracksStore, periodRef);
|
|
2499
2672
|
}
|
|
2673
|
+
|
|
2674
|
+
/**
|
|
2675
|
+
* Method to call when some event lead to a high for possibility that the
|
|
2676
|
+
* available tracks for the given type have changed.
|
|
2677
|
+
* Send the corresponding `available*Tracks` change event with the last
|
|
2678
|
+
* available tracks.
|
|
2679
|
+
*
|
|
2680
|
+
* @param {string} trackType
|
|
2681
|
+
* @param {Object|undefined} [oPeriodRef] - optional period object used by the
|
|
2682
|
+
* `tracksStore` API, allows to optimize the method by bypassing this step.
|
|
2683
|
+
*/
|
|
2684
|
+
private _priv_onAvailableTracksMayHaveChanged(
|
|
2685
|
+
trackType : IBufferType,
|
|
2686
|
+
oPeriodRef? : ITMPeriodObject
|
|
2687
|
+
): void {
|
|
2688
|
+
const contentInfos = this._priv_contentInfos;
|
|
2689
|
+
if (contentInfos === null) {
|
|
2690
|
+
return;
|
|
2691
|
+
}
|
|
2692
|
+
const { currentPeriod,
|
|
2693
|
+
tracksStore,
|
|
2694
|
+
currentContentCanceller } = contentInfos;
|
|
2695
|
+
const cancelSignal = currentContentCanceller.signal;
|
|
2696
|
+
if (isNullOrUndefined(currentPeriod) || tracksStore === null) {
|
|
2697
|
+
return;
|
|
2698
|
+
}
|
|
2699
|
+
const periodRef = oPeriodRef ?? tracksStore.getPeriodObjectFromPeriod(currentPeriod);
|
|
2700
|
+
if (periodRef === undefined) {
|
|
2701
|
+
return;
|
|
2702
|
+
}
|
|
2703
|
+
switch (trackType) {
|
|
2704
|
+
case "video":
|
|
2705
|
+
const videoTracks = tracksStore.getAvailableVideoTracks(periodRef);
|
|
2706
|
+
this._priv_triggerEventIfNotStopped("availableVideoTracksChange",
|
|
2707
|
+
videoTracks ?? [],
|
|
2708
|
+
cancelSignal);
|
|
2709
|
+
break;
|
|
2710
|
+
case "audio":
|
|
2711
|
+
const audioTracks = tracksStore.getAvailableAudioTracks(periodRef);
|
|
2712
|
+
this._priv_triggerEventIfNotStopped("availableAudioTracksChange",
|
|
2713
|
+
audioTracks ?? [],
|
|
2714
|
+
cancelSignal);
|
|
2715
|
+
break;
|
|
2716
|
+
case "text":
|
|
2717
|
+
const textTracks = tracksStore.getAvailableTextTracks(periodRef);
|
|
2718
|
+
this._priv_triggerEventIfNotStopped("availableTextTracksChange",
|
|
2719
|
+
textTracks ?? [],
|
|
2720
|
+
cancelSignal);
|
|
2721
|
+
break;
|
|
2722
|
+
default:
|
|
2723
|
+
assertUnreachable(trackType);
|
|
2724
|
+
}
|
|
2725
|
+
}
|
|
2726
|
+
|
|
2727
|
+
/**
|
|
2728
|
+
* Method to call when a fatal error lead to the stopping of the current
|
|
2729
|
+
* content.
|
|
2730
|
+
*
|
|
2731
|
+
* @param {*} err - The error encountered.
|
|
2732
|
+
* @param {Object} contentInfos - The `IPublicApiContentInfos` object linked
|
|
2733
|
+
* to the content for which the error was received.
|
|
2734
|
+
*/
|
|
2735
|
+
private _priv_onFatalError(
|
|
2736
|
+
err : unknown,
|
|
2737
|
+
contentInfos : IPublicApiContentInfos
|
|
2738
|
+
): void {
|
|
2739
|
+
const formattedError = formatError(err, {
|
|
2740
|
+
defaultCode: "NONE",
|
|
2741
|
+
defaultReason: "An unknown error stopped content playback.",
|
|
2742
|
+
});
|
|
2743
|
+
formattedError.fatal = true;
|
|
2744
|
+
contentInfos.currentContentCanceller.cancel();
|
|
2745
|
+
this._priv_cleanUpCurrentContentState();
|
|
2746
|
+
this._priv_currentError = formattedError;
|
|
2747
|
+
log.error("API: The player stopped because of an error", formattedError);
|
|
2748
|
+
this._priv_setPlayerState(PLAYER_STATES.STOPPED);
|
|
2749
|
+
|
|
2750
|
+
// TODO This condition is here because the eventual callback called when the
|
|
2751
|
+
// player state is updated can launch a new content, thus the error will not
|
|
2752
|
+
// be here anymore, in which case triggering the "error" event is unwanted.
|
|
2753
|
+
// This is very ugly though, and we should probable have a better solution
|
|
2754
|
+
if (this._priv_currentError === formattedError) {
|
|
2755
|
+
this.trigger("error", formattedError);
|
|
2756
|
+
}
|
|
2757
|
+
}
|
|
2500
2758
|
}
|
|
2501
|
-
Player.version = /* PLAYER_VERSION */"4.0.0-beta.
|
|
2759
|
+
Player.version = /* PLAYER_VERSION */"4.0.0-beta.2";
|
|
2502
2760
|
|
|
2503
2761
|
/** Every events sent by the RxPlayer's public API. */
|
|
2504
2762
|
interface IPublicAPIEvent {
|
|
@@ -2516,9 +2774,12 @@ interface IPublicAPIEvent {
|
|
|
2516
2774
|
availableAudioTracksChange : IAvailableAudioTrack[];
|
|
2517
2775
|
availableTextTracksChange : IAvailableTextTrack[];
|
|
2518
2776
|
availableVideoTracksChange : IAvailableVideoTrack[];
|
|
2777
|
+
play: null;
|
|
2778
|
+
pause: null;
|
|
2519
2779
|
newAvailablePeriods : IPeriod[];
|
|
2520
2780
|
brokenRepresentationsLock : IBrokenRepresentationsLockContext;
|
|
2521
2781
|
trackUpdate : ITrackUpdateEventPayload;
|
|
2782
|
+
representationListUpdate : IRepresentationListUpdateContext;
|
|
2522
2783
|
seeking : null;
|
|
2523
2784
|
seeked : null;
|
|
2524
2785
|
streamEvent : IStreamEvent;
|
|
@@ -118,10 +118,7 @@ function createAudioTracks(
|
|
|
118
118
|
*/
|
|
119
119
|
function createTextTracks(
|
|
120
120
|
textTracks: ICompatTextTrackList
|
|
121
|
-
): Array<{ track:
|
|
122
|
-
normalized: string;
|
|
123
|
-
language: string;
|
|
124
|
-
closedCaption: boolean; };
|
|
121
|
+
): Array<{ track: ITextTrack;
|
|
125
122
|
nativeTrack: TextTrack; }> {
|
|
126
123
|
const newTextTracks = [];
|
|
127
124
|
const languagesOccurences: Partial<Record<string, number>> = {};
|
|
@@ -135,10 +132,20 @@ function createTextTracks(
|
|
|
135
132
|
"_" +
|
|
136
133
|
occurences.toString();
|
|
137
134
|
languagesOccurences[language] = occurences + 1;
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
135
|
+
|
|
136
|
+
// Safari seems to be indicating that the subtitles track is a forced
|
|
137
|
+
// subtitles track by setting the `kind` attribute to `"forced"`.
|
|
138
|
+
// As of now (2023-04-04), this is not standard.
|
|
139
|
+
// @see https://github.com/whatwg/html/issues/4472
|
|
140
|
+
const forced = (textTrack.kind as string) === "forced" ?
|
|
141
|
+
true :
|
|
142
|
+
undefined;
|
|
143
|
+
const track = { language: textTrack.language,
|
|
144
|
+
forced,
|
|
145
|
+
label: textTrack.label,
|
|
146
|
+
id,
|
|
147
|
+
normalized: normalizeLanguage(textTrack.language),
|
|
148
|
+
closedCaption: textTrack.kind === "captions" };
|
|
142
149
|
newTextTracks.push({ track,
|
|
143
150
|
nativeTrack: textTrack });
|
|
144
151
|
}
|
|
@@ -393,6 +400,8 @@ export default class MediaElementTracksStore
|
|
|
393
400
|
public getAvailableTextTracks(): IAvailableTextTrack[] {
|
|
394
401
|
return this._textTracks.map(({ track, nativeTrack }) => {
|
|
395
402
|
return { id: track.id,
|
|
403
|
+
label: track.label,
|
|
404
|
+
forced: track.forced,
|
|
396
405
|
language: track.language,
|
|
397
406
|
normalized: track.normalized,
|
|
398
407
|
closedCaption: track.closedCaption,
|