rx-player 3.26.1 → 3.26.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/.github/workflows/checks.yml +99 -0
- package/.github/workflows/sonarcloud_analysis.yml +20 -0
- package/CHANGELOG.md +99 -71
- package/README.md +19 -18
- package/VERSION +1 -1
- package/dist/_esm5.processed/compat/clear_element_src.js +8 -6
- package/dist/_esm5.processed/compat/eme/close_session.js +1 -2
- package/dist/_esm5.processed/compat/eme/custom_media_keys/ie11_media_keys.js +1 -2
- package/dist/_esm5.processed/compat/eme/custom_media_keys/index.d.ts +3 -1
- package/dist/_esm5.processed/compat/eme/custom_media_keys/old_webkit_media_keys.js +6 -4
- package/dist/_esm5.processed/compat/eme/custom_media_keys/webkit_media_keys.js +1 -2
- package/dist/_esm5.processed/compat/eme/generate_key_request.js +1 -2
- package/dist/_esm5.processed/compat/eme/load_session.js +2 -3
- package/dist/_esm5.processed/compat/event_listeners.d.ts +3 -2
- package/dist/_esm5.processed/compat/event_listeners.js +8 -14
- package/dist/_esm5.processed/compat/make_vtt_cue.js +1 -1
- package/dist/_esm5.processed/compat/on_height_width_change.js +1 -2
- package/dist/_esm5.processed/compat/set_element_src.js +1 -1
- package/dist/_esm5.processed/compat/when_loaded_metadata.js +1 -2
- package/dist/_esm5.processed/compat/when_media_source_open.js +1 -2
- package/dist/_esm5.processed/config.d.ts +3 -8
- package/dist/_esm5.processed/config.js +4 -9
- package/dist/_esm5.processed/core/abr/abr_manager.d.ts +11 -10
- package/dist/_esm5.processed/core/abr/abr_manager.js +47 -8
- package/dist/_esm5.processed/core/abr/bandwidth_estimator.js +1 -1
- package/dist/_esm5.processed/core/abr/buffer_based_chooser.d.ts +2 -2
- package/dist/_esm5.processed/core/abr/buffer_based_chooser.js +3 -3
- package/dist/_esm5.processed/core/abr/get_buffer_levels.js +3 -0
- package/dist/_esm5.processed/core/abr/get_estimate_from_buffer_levels.d.ts +3 -3
- package/dist/_esm5.processed/core/abr/get_estimate_from_buffer_levels.js +3 -3
- package/dist/_esm5.processed/core/abr/guess_based_chooser.d.ts +95 -0
- package/dist/_esm5.processed/core/abr/guess_based_chooser.js +242 -0
- package/dist/_esm5.processed/core/abr/index.d.ts +3 -3
- package/dist/_esm5.processed/core/abr/last_estimate_storage.d.ts +61 -0
- package/dist/_esm5.processed/core/abr/last_estimate_storage.js +37 -0
- package/dist/_esm5.processed/core/abr/network_analyzer.d.ts +25 -7
- package/dist/_esm5.processed/core/abr/network_analyzer.js +68 -31
- package/dist/_esm5.processed/core/abr/pending_requests_store.d.ts +56 -28
- package/dist/_esm5.processed/core/abr/pending_requests_store.js +9 -7
- package/dist/_esm5.processed/core/abr/representation_estimator.d.ts +34 -51
- package/dist/_esm5.processed/core/abr/representation_estimator.js +111 -52
- package/dist/_esm5.processed/core/abr/representation_score_calculator.d.ts +5 -8
- package/dist/_esm5.processed/core/abr/representation_score_calculator.js +20 -23
- package/dist/_esm5.processed/core/abr/{ewma.d.ts → utils/ewma.d.ts} +0 -0
- package/dist/_esm5.processed/core/abr/{ewma.js → utils/ewma.js} +0 -0
- package/dist/_esm5.processed/core/abr/{filter_by_bitrate.d.ts → utils/filter_by_bitrate.d.ts} +1 -1
- package/dist/_esm5.processed/core/abr/{filter_by_bitrate.js → utils/filter_by_bitrate.js} +1 -1
- package/dist/_esm5.processed/core/abr/{filter_by_width.d.ts → utils/filter_by_width.d.ts} +1 -1
- package/dist/_esm5.processed/core/abr/{filter_by_width.js → utils/filter_by_width.js} +2 -2
- package/dist/_esm5.processed/core/abr/{select_optimal_representation.d.ts → utils/select_optimal_representation.d.ts} +1 -1
- package/dist/_esm5.processed/core/abr/{select_optimal_representation.js → utils/select_optimal_representation.js} +1 -1
- package/dist/_esm5.processed/core/api/emit_seek_events.d.ts +4 -4
- package/dist/_esm5.processed/core/api/emit_seek_events.js +12 -10
- package/dist/_esm5.processed/core/api/index.d.ts +3 -1
- package/dist/_esm5.processed/core/api/index.js +2 -0
- package/dist/_esm5.processed/core/api/option_utils.js +4 -4
- package/dist/_esm5.processed/core/api/playback_observer.d.ts +280 -0
- package/dist/_esm5.processed/core/api/playback_observer.js +461 -0
- package/dist/_esm5.processed/core/api/public_api.d.ts +8 -7
- package/dist/_esm5.processed/core/api/public_api.js +98 -94
- package/dist/_esm5.processed/core/api/track_choice_manager.js +3 -3
- package/dist/_esm5.processed/core/eme/__tests__/__global__/utils.js +1 -0
- package/dist/_esm5.processed/core/eme/attach_media_keys.js +1 -2
- package/dist/_esm5.processed/core/eme/check_key_statuses.js +4 -5
- package/dist/_esm5.processed/core/eme/clean_old_loaded_sessions.js +1 -2
- package/dist/_esm5.processed/core/eme/clear_eme_session.js +6 -2
- package/dist/_esm5.processed/core/eme/create_session.js +1 -2
- package/dist/_esm5.processed/core/eme/dispose_media_keys.js +2 -3
- package/dist/_esm5.processed/core/eme/eme_manager.js +4 -5
- package/dist/_esm5.processed/core/eme/find_key_system.js +4 -5
- package/dist/_esm5.processed/core/eme/get_media_keys.js +2 -3
- package/dist/_esm5.processed/core/eme/get_session.js +1 -2
- package/dist/_esm5.processed/core/eme/init_media_keys.js +5 -5
- package/dist/_esm5.processed/core/eme/session_events_listener.js +6 -7
- package/dist/_esm5.processed/core/eme/set_server_certificate.js +8 -3
- package/dist/_esm5.processed/core/eme/types.d.ts +12 -4
- package/dist/_esm5.processed/core/eme/utils/close_session.js +2 -3
- package/dist/_esm5.processed/core/eme/utils/is_session_usable.js +1 -1
- package/dist/_esm5.processed/core/eme/utils/loaded_sessions_store.js +3 -4
- package/dist/_esm5.processed/core/eme/utils/persistent_sessions_store.js +3 -3
- package/dist/_esm5.processed/core/fetchers/index.d.ts +2 -2
- package/dist/_esm5.processed/core/fetchers/manifest/manifest_fetcher.js +2 -2
- package/dist/_esm5.processed/core/fetchers/segment/index.d.ts +2 -2
- package/dist/_esm5.processed/core/fetchers/segment/prioritized_segment_fetcher.d.ts +12 -29
- package/dist/_esm5.processed/core/fetchers/segment/prioritized_segment_fetcher.js +3 -7
- package/dist/_esm5.processed/core/fetchers/segment/prioritizer.d.ts +53 -53
- package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher.d.ts +42 -11
- package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher.js +118 -46
- package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher_creator.d.ts +21 -20
- package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher_creator.js +9 -8
- package/dist/_esm5.processed/core/init/create_eme_manager.js +1 -2
- package/dist/_esm5.processed/core/init/create_media_source.js +3 -4
- package/dist/_esm5.processed/core/init/create_stream_playback_observer.d.ts +39 -0
- package/dist/_esm5.processed/core/init/create_stream_playback_observer.js +50 -0
- package/dist/_esm5.processed/core/init/duration_updater.js +16 -7
- package/dist/_esm5.processed/core/init/emit_loaded_event.d.ts +4 -3
- package/dist/_esm5.processed/core/init/emit_loaded_event.js +8 -8
- package/dist/_esm5.processed/core/init/end_of_stream.js +1 -2
- package/dist/_esm5.processed/core/init/get_initial_time.js +2 -3
- package/dist/_esm5.processed/core/init/initial_seek_and_play.d.ts +32 -31
- package/dist/_esm5.processed/core/init/initial_seek_and_play.js +25 -32
- package/dist/_esm5.processed/core/init/initialize_directfile.d.ts +6 -5
- package/dist/_esm5.processed/core/init/initialize_directfile.js +16 -12
- package/dist/_esm5.processed/core/init/initialize_media_source.d.ts +10 -10
- package/dist/_esm5.processed/core/init/initialize_media_source.js +18 -12
- package/dist/_esm5.processed/core/init/load_on_media_source.d.ts +8 -11
- package/dist/_esm5.processed/core/init/load_on_media_source.js +16 -19
- package/dist/_esm5.processed/core/init/manifest_update_scheduler.js +8 -7
- package/dist/_esm5.processed/core/init/stall_avoider.d.ts +4 -6
- package/dist/_esm5.processed/core/init/stall_avoider.js +56 -42
- package/dist/_esm5.processed/core/init/stream_events_emitter/stream_events_emitter.d.ts +2 -2
- package/dist/_esm5.processed/core/init/stream_events_emitter/stream_events_emitter.js +20 -15
- package/dist/_esm5.processed/core/init/throw_on_media_error.js +1 -2
- package/dist/_esm5.processed/core/init/types.d.ts +0 -20
- package/dist/_esm5.processed/core/init/update_playback_rate.d.ts +5 -4
- package/dist/_esm5.processed/core/init/update_playback_rate.js +10 -11
- package/dist/_esm5.processed/core/segment_buffers/garbage_collector.d.ts +4 -4
- package/dist/_esm5.processed/core/segment_buffers/garbage_collector.js +12 -7
- package/dist/_esm5.processed/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.js +8 -7
- package/dist/_esm5.processed/core/segment_buffers/implementations/text/html/html_text_segment_buffer.js +9 -10
- package/dist/_esm5.processed/core/segment_buffers/implementations/text/html/text_track_cues_store.js +1 -1
- package/dist/_esm5.processed/core/segment_buffers/implementations/text/native/native_text_segment_buffer.js +4 -4
- package/dist/_esm5.processed/core/segment_buffers/implementations/utils/manual_time_ranges.js +2 -2
- package/dist/_esm5.processed/core/segment_buffers/inventory/buffered_history.js +2 -2
- package/dist/_esm5.processed/core/segment_buffers/inventory/segment_inventory.d.ts +1 -12
- package/dist/_esm5.processed/core/segment_buffers/inventory/segment_inventory.js +10 -10
- package/dist/_esm5.processed/core/segment_buffers/segment_buffers_store.js +1 -1
- package/dist/_esm5.processed/core/stream/adaptation/adaptation_stream.d.ts +15 -13
- package/dist/_esm5.processed/core/stream/adaptation/adaptation_stream.js +36 -23
- package/dist/_esm5.processed/core/stream/adaptation/create_representation_estimator.d.ts +9 -17
- package/dist/_esm5.processed/core/stream/adaptation/create_representation_estimator.js +11 -20
- package/dist/_esm5.processed/core/stream/adaptation/index.d.ts +2 -2
- package/dist/_esm5.processed/core/stream/index.d.ts +2 -2
- package/dist/_esm5.processed/core/stream/orchestrator/active_period_emitter.js +5 -6
- package/dist/_esm5.processed/core/stream/orchestrator/are_streams_complete.js +1 -2
- package/dist/_esm5.processed/core/stream/orchestrator/index.d.ts +2 -2
- package/dist/_esm5.processed/core/stream/orchestrator/stream_orchestrator.d.ts +10 -8
- package/dist/_esm5.processed/core/stream/orchestrator/stream_orchestrator.js +22 -21
- package/dist/_esm5.processed/core/stream/period/create_empty_adaptation_stream.d.ts +6 -4
- package/dist/_esm5.processed/core/stream/period/create_empty_adaptation_stream.js +11 -10
- package/dist/_esm5.processed/core/stream/period/index.d.ts +2 -2
- package/dist/_esm5.processed/core/stream/period/period_stream.d.ts +23 -7
- package/dist/_esm5.processed/core/stream/period/period_stream.js +38 -24
- package/dist/_esm5.processed/core/stream/reload_after_switch.d.ts +5 -4
- package/dist/_esm5.processed/core/stream/reload_after_switch.js +8 -7
- package/dist/_esm5.processed/core/stream/representation/append_segment_to_buffer.d.ts +4 -2
- package/dist/_esm5.processed/core/stream/representation/append_segment_to_buffer.js +10 -8
- package/dist/_esm5.processed/core/stream/representation/downloading_queue.d.ts +9 -9
- package/dist/_esm5.processed/core/stream/representation/downloading_queue.js +10 -12
- package/dist/_esm5.processed/core/stream/representation/force_garbage_collection.d.ts +1 -3
- package/dist/_esm5.processed/core/stream/representation/force_garbage_collection.js +6 -8
- package/dist/_esm5.processed/core/stream/representation/get_buffer_status.d.ts +3 -7
- package/dist/_esm5.processed/core/stream/representation/get_buffer_status.js +7 -8
- package/dist/_esm5.processed/core/stream/representation/get_needed_segments.js +1 -1
- package/dist/_esm5.processed/core/stream/representation/get_segment_priority.d.ts +6 -9
- package/dist/_esm5.processed/core/stream/representation/get_segment_priority.js +7 -8
- package/dist/_esm5.processed/core/stream/representation/index.d.ts +2 -2
- package/dist/_esm5.processed/core/stream/representation/push_init_segment.d.ts +4 -2
- package/dist/_esm5.processed/core/stream/representation/push_init_segment.js +3 -5
- package/dist/_esm5.processed/core/stream/representation/push_media_segment.d.ts +6 -4
- package/dist/_esm5.processed/core/stream/representation/push_media_segment.js +3 -5
- package/dist/_esm5.processed/core/stream/representation/representation_stream.d.ts +9 -12
- package/dist/_esm5.processed/core/stream/representation/representation_stream.js +30 -21
- package/dist/_esm5.processed/errors/error_message.js +1 -1
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/create_request.d.ts +5 -3
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/create_request.js +21 -8
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/get_initialized_source_buffer.js +2 -3
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/load_segments.d.ts +2 -2
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/load_segments.js +4 -0
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/prepare_source_buffer.js +1 -1
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/push_data.d.ts +2 -2
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/thumbnail_loader.js +17 -6
- package/dist/_esm5.processed/experimental/tools/createMetaplaylist/get_duration_from_manifest.js +1 -2
- package/dist/_esm5.processed/experimental/tools/createMetaplaylist/index.js +1 -2
- package/dist/_esm5.processed/experimental/tools/mediaCapabilitiesProber/probers/mediaDisplayInfos.js +1 -1
- package/dist/_esm5.processed/features/initialize_features.js +47 -44
- package/dist/_esm5.processed/index.js +2 -2
- package/dist/_esm5.processed/manifest/index.d.ts +2 -2
- package/dist/_esm5.processed/manifest/index.js +2 -2
- package/dist/_esm5.processed/manifest/representation.js +1 -1
- package/dist/_esm5.processed/manifest/representation_index/static.js +1 -0
- package/dist/_esm5.processed/manifest/representation_index/types.d.ts +24 -3
- package/dist/_esm5.processed/manifest/update_period_in_place.js +1 -1
- package/dist/_esm5.processed/manifest/{are_same_content.d.ts → utils.d.ts} +9 -7
- package/dist/_esm5.processed/manifest/{are_same_content.js → utils.js} +18 -1
- package/dist/_esm5.processed/minimal.js +2 -2
- package/dist/_esm5.processed/parsers/containers/isobmff/get_box.d.ts +18 -9
- package/dist/_esm5.processed/parsers/containers/isobmff/get_box.js +32 -9
- package/dist/_esm5.processed/parsers/containers/isobmff/read.d.ts +18 -5
- package/dist/_esm5.processed/parsers/containers/isobmff/read.js +28 -6
- package/dist/_esm5.processed/parsers/containers/isobmff/utils.js +52 -47
- package/dist/_esm5.processed/parsers/images/bif.js +1 -1
- package/dist/_esm5.processed/parsers/manifest/dash/common/flatten_overlapping_periods.js +2 -2
- package/dist/_esm5.processed/parsers/manifest/dash/common/get_http_utc-timing_url.js +2 -2
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/base.d.ts +2 -1
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/base.js +3 -2
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/get_init_segment.js +2 -1
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/get_segments_from_timeline.d.ts +1 -0
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/get_segments_from_timeline.js +7 -9
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/list.d.ts +2 -1
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/list.js +4 -2
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/template.d.ts +2 -1
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/template.js +11 -5
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/timeline/convert_element_to_index_segment.js +10 -9
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/timeline/parse_s_element.js +3 -3
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/timeline/timeline_representation_index.d.ts +6 -1
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/timeline/timeline_representation_index.js +5 -4
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/tokens.d.ts +1 -1
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/tokens.js +4 -4
- package/dist/_esm5.processed/parsers/manifest/dash/common/parse_adaptation_sets.d.ts +3 -1
- package/dist/_esm5.processed/parsers/manifest/dash/common/parse_adaptation_sets.js +19 -18
- package/dist/_esm5.processed/parsers/manifest/dash/common/parse_mpd.d.ts +2 -1
- package/dist/_esm5.processed/parsers/manifest/dash/common/parse_mpd.js +14 -8
- package/dist/_esm5.processed/parsers/manifest/dash/common/parse_periods.d.ts +2 -2
- package/dist/_esm5.processed/parsers/manifest/dash/common/parse_periods.js +7 -8
- package/dist/_esm5.processed/parsers/manifest/dash/common/parse_representation_index.d.ts +3 -1
- package/dist/_esm5.processed/parsers/manifest/dash/common/parse_representation_index.js +5 -10
- package/dist/_esm5.processed/parsers/manifest/dash/common/parse_representations.d.ts +3 -1
- package/dist/_esm5.processed/parsers/manifest/dash/common/parse_representations.js +17 -8
- package/dist/_esm5.processed/parsers/manifest/dash/common/resolve_base_urls.d.ts +7 -2
- package/dist/_esm5.processed/parsers/manifest/dash/common/resolve_base_urls.js +22 -21
- package/dist/_esm5.processed/parsers/manifest/dash/js-parser/node_parsers/AdaptationSet.js +10 -0
- package/dist/_esm5.processed/parsers/manifest/dash/js-parser/node_parsers/BaseURL.js +9 -9
- package/dist/_esm5.processed/parsers/manifest/dash/js-parser/node_parsers/Representation.js +24 -0
- package/dist/_esm5.processed/parsers/manifest/dash/js-parser/node_parsers/SegmentTemplate.js +7 -5
- package/dist/_esm5.processed/parsers/manifest/dash/js-parser/node_parsers/utils.js +12 -9
- package/dist/_esm5.processed/parsers/manifest/dash/js-parser/parse_from_document.js +5 -2
- package/dist/_esm5.processed/parsers/manifest/dash/node_parser_types.d.ts +8 -0
- package/dist/_esm5.processed/parsers/manifest/dash/parsers_types.d.ts +11 -2
- package/dist/_esm5.processed/parsers/manifest/dash/wasm-parser/ts/dash-wasm-parser.js +7 -4
- package/dist/_esm5.processed/parsers/manifest/dash/wasm-parser/ts/generators/AdaptationSet.js +11 -0
- package/dist/_esm5.processed/parsers/manifest/dash/wasm-parser/ts/generators/BaseURL.js +7 -1
- package/dist/_esm5.processed/parsers/manifest/dash/wasm-parser/ts/generators/EventStream.js +5 -0
- package/dist/_esm5.processed/parsers/manifest/dash/wasm-parser/ts/generators/MPD.js +5 -0
- package/dist/_esm5.processed/parsers/manifest/dash/wasm-parser/ts/generators/Period.js +13 -0
- package/dist/_esm5.processed/parsers/manifest/dash/wasm-parser/ts/generators/Representation.js +23 -0
- package/dist/_esm5.processed/parsers/manifest/dash/wasm-parser/ts/generators/SegmentList.js +5 -0
- package/dist/_esm5.processed/parsers/manifest/dash/wasm-parser/ts/generators/XLink.js +6 -0
- package/dist/_esm5.processed/parsers/manifest/dash/wasm-parser/ts/generators/root.js +6 -0
- package/dist/_esm5.processed/parsers/manifest/local/parse_local_manifest.js +1 -1
- package/dist/_esm5.processed/parsers/manifest/local/representation_index.js +4 -2
- package/dist/_esm5.processed/parsers/manifest/smooth/create_parser.js +1 -1
- package/dist/_esm5.processed/parsers/manifest/smooth/get_codecs.js +1 -1
- package/dist/_esm5.processed/parsers/manifest/smooth/representation_index.js +3 -1
- package/dist/_esm5.processed/parsers/manifest/utils/check_manifest_ids.js +1 -1
- package/dist/_esm5.processed/parsers/manifest/utils/clear_timeline_from_position.js +1 -1
- package/dist/_esm5.processed/parsers/manifest/utils/index_helpers.d.ts +11 -3
- package/dist/_esm5.processed/parsers/manifest/utils/index_helpers.js +5 -5
- package/dist/_esm5.processed/parsers/manifest/utils/is_segment_still_available.js +3 -6
- package/dist/_esm5.processed/parsers/texttracks/sami/html.js +2 -2
- package/dist/_esm5.processed/parsers/texttracks/sami/native.js +2 -2
- package/dist/_esm5.processed/parsers/texttracks/ttml/html/apply_font_size.js +13 -1
- package/dist/_esm5.processed/parsers/texttracks/ttml/html/generate_css_test_outline.js +4 -4
- package/dist/_esm5.processed/parsers/texttracks/webvtt/html/create_default_style_elements.js +2 -2
- package/dist/_esm5.processed/parsers/texttracks/webvtt/html/create_style_attribute.js +5 -5
- package/dist/_esm5.processed/transports/dash/image_pipelines.d.ts +2 -2
- package/dist/_esm5.processed/transports/dash/init_segment_loader.js +1 -1
- package/dist/_esm5.processed/transports/dash/manifest_parser.js +89 -20
- package/dist/_esm5.processed/transports/dash/segment_loader.js +1 -1
- package/dist/_esm5.processed/transports/local/segment_loader.js +2 -2
- package/dist/_esm5.processed/transports/local/segment_parser.d.ts +2 -2
- package/dist/_esm5.processed/transports/local/text_parser.d.ts +2 -2
- package/dist/_esm5.processed/transports/metaplaylist/pipelines.js +1 -1
- package/dist/_esm5.processed/transports/smooth/extract_timings_infos.js +1 -1
- package/dist/_esm5.processed/transports/smooth/pipelines.js +2 -2
- package/dist/_esm5.processed/transports/smooth/segment_loader.js +3 -3
- package/dist/_esm5.processed/transports/types.d.ts +29 -15
- package/dist/_esm5.processed/transports/utils/byte_range.js +2 -2
- package/dist/_esm5.processed/transports/utils/call_custom_manifest_loader.js +1 -1
- package/dist/_esm5.processed/transports/utils/get_isobmff_timing_infos.js +6 -1
- package/dist/_esm5.processed/transports/utils/parse_text_track.js +6 -4
- package/dist/_esm5.processed/utils/assert.js +3 -3
- package/dist/_esm5.processed/utils/concat_map_latest.js +1 -2
- package/dist/_esm5.processed/utils/defer_subscriptions.js +1 -2
- package/dist/_esm5.processed/utils/filter_map.js +1 -2
- package/dist/_esm5.processed/utils/reference.d.ts +108 -0
- package/dist/_esm5.processed/utils/reference.js +137 -0
- package/dist/_esm5.processed/utils/request/fetch.d.ts +1 -1
- package/dist/_esm5.processed/utils/request/fetch.js +3 -3
- package/dist/_esm5.processed/utils/request/xhr.d.ts +1 -1
- package/dist/_esm5.processed/utils/request/xhr.js +1 -1
- package/dist/_esm5.processed/utils/rx-retry_with_backoff.js +1 -2
- package/dist/mpd-parser.wasm +0 -0
- package/dist/rx-player.d.ts +1 -15
- package/dist/rx-player.js +3666 -2470
- package/dist/rx-player.min.d.ts +1 -15
- package/dist/rx-player.min.js +1 -1
- package/jest.config.js +28 -1
- package/package.json +43 -43
- package/scripts/build/constants.d.ts +50 -0
- package/scripts/build/generate_build.js +1 -189
- package/scripts/doc-generator/construct_table_of_contents.js +31 -24
- package/scripts/doc-generator/convert_MD_to_HMTL.js +4 -8
- package/scripts/doc-generator/create_documentation.js +331 -0
- package/scripts/doc-generator/create_documentation_page.js +209 -0
- package/scripts/doc-generator/create_page.js +117 -35
- package/scripts/doc-generator/generate_header_html.js +148 -0
- package/scripts/doc-generator/generate_page_html.js +116 -0
- package/scripts/doc-generator/generate_page_list_html.js +93 -0
- package/scripts/doc-generator/generate_sidebar_html.js +88 -0
- package/scripts/doc-generator/get_search_data_for_content.js +137 -0
- package/scripts/doc-generator/index.js +14 -15
- package/scripts/doc-generator/parse_doc_configs.js +327 -0
- package/scripts/doc-generator/scripts/lunr.js +10 -0
- package/scripts/doc-generator/scripts/script.js +451 -0
- package/scripts/doc-generator/styles/style.css +712 -144
- package/scripts/doc-generator/utils.js +85 -0
- package/scripts/fast_demo_build.js +143 -0
- package/scripts/generate_documentation_list.js +6 -2
- package/scripts/generate_full_demo.js +26 -49
- package/scripts/start_demo_web_server.js +14 -4
- package/scripts/update-version +1 -1
- package/sonar-project.properties +2 -1
- package/src/compat/__tests__/add_text_track.test.ts +1 -0
- package/src/compat/__tests__/clear_element_src.test.ts +55 -28
- package/src/compat/__tests__/set_element_src.test.ts +2 -2
- package/src/compat/__tests__/when_loaded_metadata.test.ts +4 -5
- package/src/compat/__tests__/when_media_source_open.test.ts +4 -5
- package/src/compat/clear_element_src.ts +8 -6
- package/src/compat/eme/close_session.ts +3 -5
- package/src/compat/eme/custom_media_keys/ie11_media_keys.ts +1 -1
- package/src/compat/eme/custom_media_keys/index.ts +6 -6
- package/src/compat/eme/custom_media_keys/old_webkit_media_keys.ts +6 -3
- package/src/compat/eme/custom_media_keys/webkit_media_keys.ts +1 -1
- package/src/compat/eme/generate_key_request.ts +1 -1
- package/src/compat/eme/load_session.ts +4 -6
- package/src/compat/event_listeners.ts +12 -21
- package/src/compat/on_height_width_change.ts +3 -5
- package/src/compat/set_element_src.ts +1 -1
- package/src/compat/when_loaded_metadata.ts +1 -1
- package/src/compat/when_media_source_open.ts +1 -1
- package/src/config.ts +4 -9
- package/src/core/abr/README.md +7 -7
- package/src/core/abr/abr_manager.ts +62 -21
- package/src/core/abr/bandwidth_estimator.ts +1 -1
- package/src/core/abr/buffer_based_chooser.ts +8 -6
- package/src/core/abr/get_buffer_levels.ts +3 -0
- package/src/core/abr/get_estimate_from_buffer_levels.ts +4 -4
- package/src/core/abr/guess_based_chooser.ts +308 -0
- package/src/core/abr/index.ts +7 -3
- package/src/core/abr/last_estimate_storage.ts +79 -0
- package/src/core/abr/network_analyzer.ts +74 -31
- package/src/core/abr/pending_requests_store.ts +76 -42
- package/src/core/abr/representation_estimator.ts +200 -125
- package/src/core/abr/representation_score_calculator.ts +33 -26
- package/src/core/abr/{__tests__ → utils/__tests__}/ewma.test.ts +0 -0
- package/src/core/abr/{__tests__ → utils/__tests__}/filter_by_bitrate.test.ts +1 -1
- package/src/core/abr/{__tests__ → utils/__tests__}/filter_by_width.test.ts +1 -1
- package/src/core/abr/{__tests__ → utils/__tests__}/select_optimal_representation.test.ts +1 -1
- package/src/core/abr/{ewma.ts → utils/ewma.ts} +0 -0
- package/src/core/abr/{filter_by_bitrate.ts → utils/filter_by_bitrate.ts} +2 -2
- package/src/core/abr/{filter_by_width.ts → utils/filter_by_width.ts} +3 -3
- package/src/core/abr/{select_optimal_representation.ts → utils/select_optimal_representation.ts} +2 -2
- package/src/core/api/README.md +4 -3
- package/src/core/api/__tests__/option_utils.test.ts +1 -0
- package/src/core/api/emit_seek_events.ts +21 -20
- package/src/core/api/index.ts +6 -2
- package/src/core/api/playback_observer.ts +768 -0
- package/src/core/api/public_api.ts +111 -111
- package/src/core/api/track_choice_manager.ts +6 -3
- package/src/core/eme/__tests__/__global__/get_license.test.ts +5 -3
- package/src/core/eme/__tests__/__global__/init_data.test.ts +11 -12
- package/src/core/eme/__tests__/__global__/media_key_system_access.test.ts +2 -1
- package/src/core/eme/__tests__/__global__/media_keys.test.ts +5 -8
- package/src/core/eme/__tests__/__global__/server_certificate.test.ts +8 -6
- package/src/core/eme/__tests__/__global__/utils.ts +1 -0
- package/src/core/eme/__tests__/init_media_keys.test.ts +6 -65
- package/src/core/eme/attach_media_keys.ts +2 -1
- package/src/core/eme/check_key_statuses.ts +10 -8
- package/src/core/eme/clean_old_loaded_sessions.ts +2 -4
- package/src/core/eme/clear_eme_session.ts +6 -1
- package/src/core/eme/create_session.ts +3 -5
- package/src/core/eme/dispose_media_keys.ts +2 -2
- package/src/core/eme/eme_manager.ts +10 -12
- package/src/core/eme/find_key_system.ts +3 -5
- package/src/core/eme/get_media_keys.ts +4 -6
- package/src/core/eme/get_session.ts +2 -4
- package/src/core/eme/init_media_keys.ts +9 -9
- package/src/core/eme/session_events_listener.ts +14 -15
- package/src/core/eme/set_server_certificate.ts +9 -5
- package/src/core/eme/types.ts +15 -4
- package/src/core/eme/utils/close_session.ts +7 -7
- package/src/core/eme/utils/is_session_usable.ts +1 -1
- package/src/core/eme/utils/loaded_sessions_store.ts +2 -2
- package/src/core/eme/utils/persistent_sessions_store.ts +2 -2
- package/src/core/fetchers/index.ts +2 -2
- package/src/core/fetchers/manifest/manifest_fetcher.ts +1 -1
- package/src/core/fetchers/segment/__tests__/prioritizer.test.ts +3 -4
- package/src/core/fetchers/segment/index.ts +2 -2
- package/src/core/fetchers/segment/prioritized_segment_fetcher.ts +37 -45
- package/src/core/fetchers/segment/prioritizer.ts +82 -82
- package/src/core/fetchers/segment/segment_fetcher.ts +178 -80
- package/src/core/fetchers/segment/segment_fetcher_creator.ts +23 -31
- package/src/core/init/create_eme_manager.ts +1 -1
- package/src/core/init/create_media_source.ts +5 -7
- package/src/core/init/create_stream_playback_observer.ts +88 -0
- package/src/core/init/duration_updater.ts +20 -17
- package/src/core/init/emit_loaded_event.ts +11 -15
- package/src/core/init/end_of_stream.ts +2 -4
- package/src/core/init/get_initial_time.ts +0 -1
- package/src/core/init/initial_seek_and_play.ts +67 -51
- package/src/core/init/initialize_directfile.ts +26 -35
- package/src/core/init/initialize_media_source.ts +28 -28
- package/src/core/init/load_on_media_source.ts +51 -58
- package/src/core/init/manifest_update_scheduler.ts +11 -12
- package/src/core/init/stall_avoider.ts +64 -47
- package/src/core/init/stream_events_emitter/stream_events_emitter.ts +24 -21
- package/src/core/init/throw_on_media_error.ts +1 -1
- package/src/core/init/types.ts +0 -24
- package/src/core/init/update_playback_rate.ts +15 -16
- package/src/core/segment_buffers/README.md +3 -3
- package/src/core/segment_buffers/garbage_collector.ts +15 -11
- package/src/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.ts +10 -7
- package/src/core/segment_buffers/implementations/text/html/html_text_segment_buffer.ts +14 -16
- package/src/core/segment_buffers/implementations/text/html/text_track_cues_store.ts +1 -1
- package/src/core/segment_buffers/implementations/text/native/native_text_segment_buffer.ts +4 -4
- package/src/core/segment_buffers/implementations/utils/manual_time_ranges.ts +2 -2
- package/src/core/segment_buffers/inventory/buffered_history.ts +2 -2
- package/src/core/segment_buffers/inventory/segment_inventory.ts +1 -13
- package/src/core/stream/adaptation/adaptation_stream.ts +78 -56
- package/src/core/stream/adaptation/create_representation_estimator.ts +19 -45
- package/src/core/stream/adaptation/index.ts +2 -2
- package/src/core/stream/index.ts +2 -2
- package/src/core/stream/orchestrator/active_period_emitter.ts +6 -8
- package/src/core/stream/orchestrator/are_streams_complete.ts +2 -4
- package/src/core/stream/orchestrator/index.ts +2 -2
- package/src/core/stream/orchestrator/stream_orchestrator.ts +58 -49
- package/src/core/stream/period/create_empty_adaptation_stream.ts +14 -10
- package/src/core/stream/period/index.ts +2 -2
- package/src/core/stream/period/period_stream.ts +118 -75
- package/src/core/stream/reload_after_switch.ts +13 -10
- package/src/core/stream/representation/append_segment_to_buffer.ts +20 -16
- package/src/core/stream/representation/downloading_queue.ts +21 -24
- package/src/core/stream/representation/force_garbage_collection.ts +16 -23
- package/src/core/stream/representation/get_buffer_status.ts +9 -11
- package/src/core/stream/representation/get_needed_segments.ts +1 -1
- package/src/core/stream/representation/get_segment_priority.ts +8 -10
- package/src/core/stream/representation/index.ts +2 -2
- package/src/core/stream/representation/push_init_segment.ts +19 -16
- package/src/core/stream/representation/push_media_segment.ts +21 -17
- package/src/core/stream/representation/representation_stream.ts +50 -47
- package/src/experimental/features/__tests__/dash_wasm.test.ts +1 -0
- package/src/experimental/tools/VideoThumbnailLoader/create_request.ts +32 -17
- package/src/experimental/tools/VideoThumbnailLoader/get_initialized_source_buffer.ts +6 -9
- package/src/experimental/tools/VideoThumbnailLoader/load_segments.ts +12 -6
- package/src/experimental/tools/VideoThumbnailLoader/prepare_source_buffer.ts +4 -2
- package/src/experimental/tools/VideoThumbnailLoader/push_data.ts +2 -2
- package/src/experimental/tools/VideoThumbnailLoader/thumbnail_loader.ts +21 -12
- package/src/experimental/tools/createMetaplaylist/get_duration_from_manifest.ts +1 -1
- package/src/experimental/tools/createMetaplaylist/index.ts +1 -1
- package/src/experimental/tools/mediaCapabilitiesProber/__tests__/probers/DRMInfos.test.ts +4 -2
- package/src/features/__tests__/initialize_features.test.ts +191 -101
- package/src/features/initialize_features.ts +40 -37
- package/src/features/list/__tests__/bif_parser.test.ts +1 -0
- package/src/features/list/__tests__/dash.test.ts +1 -0
- package/src/features/list/__tests__/directfile.test.ts +1 -0
- package/src/features/list/__tests__/eme.test.ts +1 -0
- package/src/features/list/__tests__/html_sami_parser.test.ts +1 -0
- package/src/features/list/__tests__/html_srt_parser.test.ts +1 -0
- package/src/features/list/__tests__/html_text_buffer.test.ts +1 -0
- package/src/features/list/__tests__/html_ttml_parser.test.ts +1 -0
- package/src/features/list/__tests__/html_vtt_parser.test.ts +1 -0
- package/src/features/list/__tests__/image_buffer.test.ts +1 -0
- package/src/features/list/__tests__/native_sami_parser.test.ts +1 -0
- package/src/features/list/__tests__/native_srt_parser.test.ts +1 -0
- package/src/features/list/__tests__/native_text_buffer.test.ts +1 -0
- package/src/features/list/__tests__/native_ttml_parser.test.ts +1 -0
- package/src/features/list/__tests__/native_vtt_parser.test.ts +1 -0
- package/src/features/list/__tests__/smooth.test.ts +1 -0
- package/src/index.ts +2 -2
- package/src/manifest/__tests__/manifest.test.ts +1 -0
- package/src/manifest/index.ts +7 -1
- package/src/manifest/representation_index/__tests__/static.test.ts +1 -0
- package/src/manifest/representation_index/static.ts +1 -0
- package/src/manifest/representation_index/types.ts +25 -3
- package/src/manifest/{are_same_content.ts → utils.ts} +26 -9
- package/src/minimal.ts +3 -2
- package/src/parsers/containers/isobmff/get_box.ts +35 -8
- package/src/parsers/containers/isobmff/read.ts +32 -5
- package/src/parsers/containers/isobmff/utils.ts +52 -47
- package/src/parsers/manifest/dash/common/__tests__/flatten_overlapping_period.test.ts +4 -4
- package/src/parsers/manifest/dash/common/flatten_overlapping_periods.ts +4 -2
- package/src/parsers/manifest/dash/common/get_clock_offset.ts +3 -3
- package/src/parsers/manifest/dash/common/get_http_utc-timing_url.ts +15 -6
- package/src/parsers/manifest/dash/common/indexes/base.ts +5 -3
- package/src/parsers/manifest/dash/common/indexes/get_init_segment.ts +1 -0
- package/src/parsers/manifest/dash/common/indexes/get_segments_from_timeline.ts +9 -9
- package/src/parsers/manifest/dash/common/indexes/list.ts +6 -3
- package/src/parsers/manifest/dash/common/indexes/template.ts +13 -6
- package/src/parsers/manifest/dash/common/indexes/timeline/convert_element_to_index_segment.ts +10 -9
- package/src/parsers/manifest/dash/common/indexes/timeline/timeline_representation_index.ts +13 -5
- package/src/parsers/manifest/dash/common/indexes/tokens.ts +4 -4
- package/src/parsers/manifest/dash/common/parse_adaptation_sets.ts +10 -4
- package/src/parsers/manifest/dash/common/parse_mpd.ts +21 -13
- package/src/parsers/manifest/dash/common/parse_periods.ts +7 -8
- package/src/parsers/manifest/dash/common/parse_representation_index.ts +12 -12
- package/src/parsers/manifest/dash/common/parse_representations.ts +23 -4
- package/src/parsers/manifest/dash/common/resolve_base_urls.ts +33 -24
- package/src/parsers/manifest/dash/js-parser/node_parsers/AdaptationSet.ts +12 -0
- package/src/parsers/manifest/dash/js-parser/node_parsers/BaseURL.ts +13 -9
- package/src/parsers/manifest/dash/js-parser/node_parsers/Representation.ts +28 -0
- package/src/parsers/manifest/dash/js-parser/node_parsers/SegmentTemplate.ts +8 -5
- package/src/parsers/manifest/dash/js-parser/node_parsers/utils.ts +3 -0
- package/src/parsers/manifest/dash/js-parser/parse_from_document.ts +5 -2
- package/src/parsers/manifest/dash/node_parser_types.ts +8 -0
- package/src/parsers/manifest/dash/parsers_types.ts +8 -2
- package/src/parsers/manifest/dash/wasm-parser/rs/lib.rs +1 -8
- package/src/parsers/manifest/dash/wasm-parser/rs/processor/attributes.rs +26 -5
- package/src/parsers/manifest/dash/wasm-parser/rs/processor/mod.rs +75 -521
- package/src/parsers/manifest/dash/wasm-parser/ts/dash-wasm-parser.ts +7 -4
- package/src/parsers/manifest/dash/wasm-parser/ts/generators/AdaptationSet.ts +13 -0
- package/src/parsers/manifest/dash/wasm-parser/ts/generators/BaseURL.ts +8 -1
- package/src/parsers/manifest/dash/wasm-parser/ts/generators/EventStream.ts +6 -0
- package/src/parsers/manifest/dash/wasm-parser/ts/generators/MPD.ts +6 -0
- package/src/parsers/manifest/dash/wasm-parser/ts/generators/Period.ts +14 -0
- package/src/parsers/manifest/dash/wasm-parser/ts/generators/Representation.ts +26 -0
- package/src/parsers/manifest/dash/wasm-parser/ts/generators/SegmentList.ts +6 -0
- package/src/parsers/manifest/dash/wasm-parser/ts/generators/XLink.ts +7 -0
- package/src/parsers/manifest/dash/wasm-parser/ts/generators/root.ts +7 -0
- package/src/parsers/manifest/dash/wasm-parser/ts/types.ts +1 -1
- package/src/parsers/manifest/local/representation_index.ts +2 -0
- package/src/parsers/manifest/smooth/create_parser.ts +1 -1
- package/src/parsers/manifest/smooth/representation_index.ts +3 -1
- package/src/parsers/manifest/utils/clear_timeline_from_position.ts +1 -1
- package/src/parsers/manifest/utils/index_helpers.ts +21 -11
- package/src/parsers/manifest/utils/is_segment_still_available.ts +4 -6
- package/src/parsers/texttracks/sami/html.ts +1 -1
- package/src/parsers/texttracks/sami/native.ts +1 -1
- package/src/parsers/texttracks/ttml/html/apply_font_size.ts +11 -1
- package/src/transports/dash/image_pipelines.ts +4 -4
- package/src/transports/dash/init_segment_loader.ts +1 -1
- package/src/transports/dash/manifest_parser.ts +99 -25
- package/src/transports/dash/segment_loader.ts +1 -1
- package/src/transports/dash/segment_parser.ts +4 -4
- package/src/transports/dash/text_parser.ts +8 -8
- package/src/transports/local/segment_loader.ts +2 -2
- package/src/transports/local/segment_parser.ts +4 -4
- package/src/transports/local/text_parser.ts +8 -8
- package/src/transports/metaplaylist/pipelines.ts +11 -11
- package/src/transports/smooth/extract_timings_infos.ts +1 -1
- package/src/transports/smooth/pipelines.ts +8 -8
- package/src/transports/smooth/segment_loader.ts +3 -3
- package/src/transports/types.ts +31 -17
- package/src/transports/utils/call_custom_manifest_loader.ts +1 -1
- package/src/transports/utils/get_isobmff_timing_infos.ts +6 -1
- package/src/transports/utils/parse_text_track.ts +4 -2
- package/src/typings/globals.d.ts +57 -40
- package/src/utils/__tests__/concat_map_latest.test.ts +7 -9
- package/src/utils/__tests__/defer_subscriptions.test.ts +4 -4
- package/src/utils/__tests__/event_emitter.test.ts +1 -1
- package/src/utils/__tests__/initialization_segment_cache.test.ts +7 -0
- package/src/utils/assert.ts +1 -1
- package/src/utils/concat_map_latest.ts +2 -4
- package/src/utils/defer_subscriptions.ts +1 -1
- package/src/utils/filter_map.ts +2 -4
- package/src/utils/reference.ts +234 -0
- package/src/utils/request/fetch.ts +3 -3
- package/src/utils/request/xhr.ts +2 -2
- package/src/utils/rx-retry_with_backoff.ts +2 -4
- package/tsconfig.json +4 -1
- package/tsconfig.modules.json +8 -3
- package/dist/_esm5.processed/core/abr/create_filters.d.ts +0 -27
- package/dist/_esm5.processed/core/abr/create_filters.js +0 -56
- package/dist/_esm5.processed/core/api/clock.d.ts +0 -157
- package/dist/_esm5.processed/core/api/clock.js +0 -363
- package/dist/_esm5.processed/core/init/create_stream_clock.d.ts +0 -34
- package/dist/_esm5.processed/core/init/create_stream_clock.js +0 -55
- package/dist/_esm5.processed/parsers/manifest/dash/common/extract_minimum_availability_time_offset.d.ts +0 -31
- package/dist/_esm5.processed/parsers/manifest/dash/common/extract_minimum_availability_time_offset.js +0 -37
- package/scripts/doc-generator/construct_html.js +0 -135
- package/scripts/doc-generator/construct_page_list.js +0 -120
- package/scripts/doc-generator/create_for_dir.js +0 -151
- package/scripts/doc-generator/get_files_to_convert.js +0 -71
- package/scripts/doc-generator/mkdir_parent.js +0 -21
- package/scripts/doc-generator/read_title_from_md.js +0 -22
- package/scripts/doc-generator/remove_toc_from_md.js +0 -20
- package/src/core/abr/create_filters.ts +0 -59
- package/src/core/api/clock.ts +0 -573
- package/src/core/init/create_stream_clock.ts +0 -93
- package/src/parsers/manifest/dash/common/extract_minimum_availability_time_offset.ts +0 -41
|
@@ -0,0 +1,768 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2015 CANAL+ Group
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import {
|
|
18
|
+
defer as observableDefer,
|
|
19
|
+
fromEvent as observableFromEvent,
|
|
20
|
+
interval as observableInterval,
|
|
21
|
+
map,
|
|
22
|
+
merge as observableMerge,
|
|
23
|
+
Observable,
|
|
24
|
+
share,
|
|
25
|
+
shareReplay,
|
|
26
|
+
skip,
|
|
27
|
+
startWith,
|
|
28
|
+
} from "rxjs";
|
|
29
|
+
import config from "../../config";
|
|
30
|
+
import log from "../../log";
|
|
31
|
+
import objectAssign from "../../utils/object_assign";
|
|
32
|
+
import { getRange } from "../../utils/ranges";
|
|
33
|
+
|
|
34
|
+
const { SAMPLING_INTERVAL_MEDIASOURCE,
|
|
35
|
+
SAMPLING_INTERVAL_LOW_LATENCY,
|
|
36
|
+
SAMPLING_INTERVAL_NO_MEDIASOURCE,
|
|
37
|
+
RESUME_GAP_AFTER_SEEKING,
|
|
38
|
+
RESUME_GAP_AFTER_NOT_ENOUGH_DATA,
|
|
39
|
+
RESUME_GAP_AFTER_BUFFERING,
|
|
40
|
+
REBUFFERING_GAP,
|
|
41
|
+
MINIMUM_BUFFER_AMOUNT_BEFORE_FREEZING } = config;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* HTMLMediaElement Events for which playback observations are calculated and
|
|
45
|
+
* emitted.
|
|
46
|
+
* @type {Array.<string>}
|
|
47
|
+
*/
|
|
48
|
+
const SCANNED_MEDIA_ELEMENTS_EVENTS : IPlaybackObserverEventType[] = [ "canplay",
|
|
49
|
+
"play",
|
|
50
|
+
"seeking",
|
|
51
|
+
"seeked",
|
|
52
|
+
"loadedmetadata",
|
|
53
|
+
"ratechange" ];
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Class allowing to "observe" current playback conditions so the RxPlayer is
|
|
57
|
+
* then able to react upon them.
|
|
58
|
+
*
|
|
59
|
+
* This is a central class of the RxPlayer as many modules rely on the
|
|
60
|
+
* `PlaybackObserver` to know the current state of the media being played.
|
|
61
|
+
*
|
|
62
|
+
* You can use the PlaybackObserver to either get the last observation
|
|
63
|
+
* performed, get the current media state or subscribe to an Observable emitting
|
|
64
|
+
* regularly media conditions.
|
|
65
|
+
*
|
|
66
|
+
* @class {PlaybackObserver}
|
|
67
|
+
*/
|
|
68
|
+
export default class PlaybackObserver {
|
|
69
|
+
|
|
70
|
+
/** HTMLMediaElement which we want to observe. */
|
|
71
|
+
private _mediaElement : HTMLMediaElement;
|
|
72
|
+
|
|
73
|
+
/** If `true`, a `MediaSource` object is linked to `_mediaElement`. */
|
|
74
|
+
private _withMediaSource : boolean;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* If `true`, we're playing in a low-latency mode, which might have an
|
|
78
|
+
* influence on some chosen interval values here.
|
|
79
|
+
*/
|
|
80
|
+
private _lowLatencyMode : boolean;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* The RxPlayer usually wants to differientate when a seek was sourced from
|
|
84
|
+
* the RxPlayer's internal logic vs when it was sourced from an outside
|
|
85
|
+
* application code.
|
|
86
|
+
*
|
|
87
|
+
* To implement this in the PlaybackObserver, we maintain this counter
|
|
88
|
+
* allowing to know when a "seeking" event received from a `HTMLMediaElement`
|
|
89
|
+
* was due to an "internal seek" or an external seek:
|
|
90
|
+
* - This counter is incremented each time an "internal seek" (seek from the
|
|
91
|
+
* inside of the RxPlayer has been performed.
|
|
92
|
+
* - This counter is decremented each time we received a "seeking" event.
|
|
93
|
+
*
|
|
94
|
+
* This allows us to correctly characterize seeking events: if the counter is
|
|
95
|
+
* superior to `0`, it is probably due to an internal "seek".
|
|
96
|
+
*/
|
|
97
|
+
private _internalSeekingEventsIncomingCounter : number;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Last playback observation made by the `PlaybackObserver`.
|
|
101
|
+
*
|
|
102
|
+
* `null` if no observation has been made yet.
|
|
103
|
+
*/
|
|
104
|
+
private _lastObservation : IPlaybackObservation | null;
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Lazily-created shared Observable that will emit playback observations.
|
|
108
|
+
* Set to `null` until the first time it is generated.
|
|
109
|
+
*/
|
|
110
|
+
private _observation$ : Observable<IPlaybackObservation> | null;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* @param {HTMLMediaElement} mediaElement
|
|
114
|
+
* @param {Object} options
|
|
115
|
+
*/
|
|
116
|
+
constructor(mediaElement : HTMLMediaElement, options : IPlaybackObserverOptions) {
|
|
117
|
+
this._internalSeekingEventsIncomingCounter = 0;
|
|
118
|
+
this._mediaElement = mediaElement;
|
|
119
|
+
this._withMediaSource = options.withMediaSource;
|
|
120
|
+
this._lowLatencyMode = options.lowLatencyMode;
|
|
121
|
+
this._lastObservation = null;
|
|
122
|
+
this._observation$ = null;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Returns the current position advertised by the `HTMLMediaElement`, in
|
|
127
|
+
* seconds.
|
|
128
|
+
* @returns {number}
|
|
129
|
+
*/
|
|
130
|
+
public getCurrentTime() : number {
|
|
131
|
+
return this._mediaElement.currentTime;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Update the current position (seek) on the `HTMLMediaElement`, by giving a
|
|
136
|
+
* new position in seconds.
|
|
137
|
+
*
|
|
138
|
+
* Note that seeks performed through this method are caracherized as
|
|
139
|
+
* "internal" seeks. They don't result into the exact same playback
|
|
140
|
+
* observation than regular seeks (which most likely comes from the outside,
|
|
141
|
+
* e.g. the user).
|
|
142
|
+
* @param {number}
|
|
143
|
+
*/
|
|
144
|
+
public setCurrentTime(time: number) : void {
|
|
145
|
+
this._internalSeekingEventsIncomingCounter += 1;
|
|
146
|
+
this._mediaElement.currentTime = time;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Returns the current `readyState` advertised by the `HTMLMediaElement`.
|
|
151
|
+
* @returns {number}
|
|
152
|
+
*/
|
|
153
|
+
public getReadyState() : number {
|
|
154
|
+
return this._mediaElement.readyState;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Returns an Observable regularly emitting playback observation, optionally
|
|
159
|
+
* starting with the last one.
|
|
160
|
+
*
|
|
161
|
+
* Note that this Observable is shared and unique, so that multiple `observe`
|
|
162
|
+
* call will return the exact same Observable and multiple concurrent
|
|
163
|
+
* `subscribe` will receive the same events at the same time.
|
|
164
|
+
* This was done for performance and simplicity reasons.
|
|
165
|
+
*
|
|
166
|
+
* @param {boolean} includeLastObservation
|
|
167
|
+
* @returns {Observable}
|
|
168
|
+
*/
|
|
169
|
+
public observe(includeLastObservation : boolean) : Observable<IPlaybackObservation> {
|
|
170
|
+
return observableDefer(() : Observable<IPlaybackObservation> => {
|
|
171
|
+
if (this._observation$ === null || this._lastObservation === null) {
|
|
172
|
+
this._lastObservation = this._generateInitialObservation();
|
|
173
|
+
this._observation$ = this._createInnerObservable().pipe(share());
|
|
174
|
+
return this.observe(includeLastObservation);
|
|
175
|
+
} else {
|
|
176
|
+
return includeLastObservation ?
|
|
177
|
+
this._observation$.pipe(startWith(this._lastObservation)) :
|
|
178
|
+
this._observation$;
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Generate a new playback observer which can listen to other
|
|
185
|
+
* properties and which can only be accessed to read observations (e.g.
|
|
186
|
+
* it cannot ask to perform a seek).
|
|
187
|
+
*
|
|
188
|
+
* The object returned will respect the `IReadOnlyPlaybackObserver` interface
|
|
189
|
+
* and will inherit this `PlaybackObserver`'s lifecycle: it will emit when
|
|
190
|
+
* the latter emits.
|
|
191
|
+
*
|
|
192
|
+
* As argument, this method takes a function which will allow to produce
|
|
193
|
+
* the new set of properties to be present on each observation.
|
|
194
|
+
* @param {Function} mapObservable
|
|
195
|
+
* @returns {Object}
|
|
196
|
+
*/
|
|
197
|
+
public deriveReadOnlyObserver<TDest>(
|
|
198
|
+
mapObservable : (
|
|
199
|
+
observation$ : Observable<IPlaybackObservation>
|
|
200
|
+
) => Observable<TDest>
|
|
201
|
+
) : IReadOnlyPlaybackObserver<TDest> {
|
|
202
|
+
return generateReadOnlyObserver(this, mapObservable);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Creates the observable that will generate playback observations.
|
|
207
|
+
* @returns {Observable}
|
|
208
|
+
*/
|
|
209
|
+
private _createInnerObservable() : Observable<IPlaybackObservation> {
|
|
210
|
+
return observableDefer(() : Observable<IPlaybackObservation> => {
|
|
211
|
+
const getCurrentObservation = (
|
|
212
|
+
event : IPlaybackObserverEventType
|
|
213
|
+
) : IPlaybackObservation => {
|
|
214
|
+
let tmpEvt: IPlaybackObserverEventType = event;
|
|
215
|
+
if (tmpEvt === "seeking" && this._internalSeekingEventsIncomingCounter > 0) {
|
|
216
|
+
tmpEvt = "internal-seeking";
|
|
217
|
+
this._internalSeekingEventsIncomingCounter -= 1;
|
|
218
|
+
}
|
|
219
|
+
const lastObservation = this._lastObservation ??
|
|
220
|
+
this._generateInitialObservation();
|
|
221
|
+
const mediaTimings = getMediaInfos(this._mediaElement, tmpEvt);
|
|
222
|
+
const internalSeeking = mediaTimings.seeking &&
|
|
223
|
+
// We've just received the event for internally seeking
|
|
224
|
+
(tmpEvt === "internal-seeking" ||
|
|
225
|
+
// or We're still waiting on the previous internal-seek
|
|
226
|
+
(lastObservation.internalSeeking && tmpEvt !== "seeking"));
|
|
227
|
+
const rebufferingStatus = getRebufferingStatus(
|
|
228
|
+
lastObservation,
|
|
229
|
+
mediaTimings,
|
|
230
|
+
{ lowLatencyMode: this._lowLatencyMode,
|
|
231
|
+
withMediaSource: this._withMediaSource });
|
|
232
|
+
|
|
233
|
+
const freezingStatus = getFreezingStatus(lastObservation, mediaTimings);
|
|
234
|
+
const timings = objectAssign(
|
|
235
|
+
{},
|
|
236
|
+
{ rebuffering: rebufferingStatus,
|
|
237
|
+
freezing: freezingStatus,
|
|
238
|
+
internalSeeking },
|
|
239
|
+
mediaTimings);
|
|
240
|
+
log.debug("API: current media element state", timings);
|
|
241
|
+
return timings;
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
const eventObs : Array< Observable< IPlaybackObserverEventType > > =
|
|
245
|
+
SCANNED_MEDIA_ELEMENTS_EVENTS.map((eventName) =>
|
|
246
|
+
observableFromEvent(this._mediaElement, eventName)
|
|
247
|
+
.pipe(map(() => eventName)));
|
|
248
|
+
|
|
249
|
+
const interval = this._lowLatencyMode ? SAMPLING_INTERVAL_LOW_LATENCY :
|
|
250
|
+
this._withMediaSource ? SAMPLING_INTERVAL_MEDIASOURCE :
|
|
251
|
+
SAMPLING_INTERVAL_NO_MEDIASOURCE;
|
|
252
|
+
|
|
253
|
+
const interval$ : Observable<"timeupdate"> =
|
|
254
|
+
observableInterval(interval)
|
|
255
|
+
.pipe(map(() => "timeupdate"));
|
|
256
|
+
|
|
257
|
+
return observableMerge(interval$, ...eventObs).pipe(
|
|
258
|
+
map((event : IPlaybackObserverEventType) => {
|
|
259
|
+
const newObservation = getCurrentObservation(event);
|
|
260
|
+
if (log.getLevel() === "DEBUG") {
|
|
261
|
+
log.debug("API: current playback timeline:\n" +
|
|
262
|
+
prettyPrintBuffered(newObservation.buffered,
|
|
263
|
+
newObservation.position),
|
|
264
|
+
`\n${event}`);
|
|
265
|
+
}
|
|
266
|
+
this._lastObservation = newObservation;
|
|
267
|
+
return newObservation;
|
|
268
|
+
}));
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
private _generateInitialObservation() : IPlaybackObservation {
|
|
273
|
+
return objectAssign(getMediaInfos(this._mediaElement, "init"),
|
|
274
|
+
{ rebuffering: null,
|
|
275
|
+
freezing: null,
|
|
276
|
+
internalSeeking: false });
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/** "Event" that triggered the playback observation. */
|
|
281
|
+
export type IPlaybackObserverEventType =
|
|
282
|
+
/** First playback observation automatically emitted. */
|
|
283
|
+
"init" | // set once on first emit
|
|
284
|
+
/** Regularly emitted playback observation when no event happened in a long time. */
|
|
285
|
+
"timeupdate" |
|
|
286
|
+
/** On the HTML5 event with the same name */
|
|
287
|
+
"canplay" |
|
|
288
|
+
/** On the HTML5 event with the same name */
|
|
289
|
+
"canplaythrough" | // HTML5 Event
|
|
290
|
+
/** On the HTML5 event with the same name */
|
|
291
|
+
"play" |
|
|
292
|
+
/** On the HTML5 event with the same name */
|
|
293
|
+
"seeking" |
|
|
294
|
+
/** On the HTML5 event with the same name */
|
|
295
|
+
"seeked" |
|
|
296
|
+
/** On the HTML5 event with the same name */
|
|
297
|
+
"stalled" |
|
|
298
|
+
/** On the HTML5 event with the same name */
|
|
299
|
+
"loadedmetadata" |
|
|
300
|
+
/** On the HTML5 event with the same name */
|
|
301
|
+
"ratechange" |
|
|
302
|
+
/** An internal seek happens */
|
|
303
|
+
"internal-seeking";
|
|
304
|
+
|
|
305
|
+
/** Information recuperated on the media element on each playback observation. */
|
|
306
|
+
interface IMediaInfos {
|
|
307
|
+
/** Gap between `currentTime` and the next position with un-buffered data. */
|
|
308
|
+
bufferGap : number;
|
|
309
|
+
/** Value of `buffered` (buffered ranges) for the media element. */
|
|
310
|
+
buffered : TimeRanges;
|
|
311
|
+
/** The buffered range we are currently playing. */
|
|
312
|
+
currentRange : { start : number;
|
|
313
|
+
end : number; } |
|
|
314
|
+
null;
|
|
315
|
+
/**
|
|
316
|
+
* `currentTime` (position) set on the media element at the time of the
|
|
317
|
+
* PlaybackObserver's measure.
|
|
318
|
+
*/
|
|
319
|
+
position : number;
|
|
320
|
+
/** Current `duration` set on the media element. */
|
|
321
|
+
duration : number;
|
|
322
|
+
/** Current `ended` set on the media element. */
|
|
323
|
+
ended: boolean;
|
|
324
|
+
/** Current `paused` set on the media element. */
|
|
325
|
+
paused : boolean;
|
|
326
|
+
/** Current `playbackRate` set on the media element. */
|
|
327
|
+
playbackRate : number;
|
|
328
|
+
/** Current `readyState` value on the media element. */
|
|
329
|
+
readyState : number;
|
|
330
|
+
/** Current `seeking` value on the mediaElement. */
|
|
331
|
+
seeking : boolean;
|
|
332
|
+
/** Event that triggered this playback observation. */
|
|
333
|
+
event : IPlaybackObserverEventType;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Describes when the player is "rebuffering" and what event started that
|
|
338
|
+
* status.
|
|
339
|
+
* "Rebuffering" is a status where the player has not enough buffer ahead to
|
|
340
|
+
* play reliably.
|
|
341
|
+
* The RxPlayer should pause playback when a playback observation indicates the
|
|
342
|
+
* rebuffering status.
|
|
343
|
+
*/
|
|
344
|
+
export interface IRebufferingStatus {
|
|
345
|
+
/** What started the player to rebuffer. */
|
|
346
|
+
reason : "seeking" | // Building buffer after seeking
|
|
347
|
+
"not-ready" | // Building buffer after low readyState
|
|
348
|
+
"buffering"; // Other cases
|
|
349
|
+
/** `performance.now` at the time the rebuffering happened. */
|
|
350
|
+
timestamp : number;
|
|
351
|
+
/**
|
|
352
|
+
* Position, in seconds, at which data is awaited.
|
|
353
|
+
* If `null` the player is rebuffering but not because it is awaiting future data.
|
|
354
|
+
*/
|
|
355
|
+
position : number | null;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Describes when the player is "frozen".
|
|
360
|
+
* This status is reserved for when the player is stuck at the same position for
|
|
361
|
+
* an unknown reason.
|
|
362
|
+
*/
|
|
363
|
+
export interface IFreezingStatus {
|
|
364
|
+
/** `performance.now` at the time the freezing started to be detected. */
|
|
365
|
+
timestamp : number;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/** Information emitted on each playback observation. */
|
|
369
|
+
export interface IPlaybackObservation extends IMediaInfos {
|
|
370
|
+
/**
|
|
371
|
+
* Set if the player is short on audio and/or video media data and is a such,
|
|
372
|
+
* rebuffering.
|
|
373
|
+
* `null` if not.
|
|
374
|
+
*/
|
|
375
|
+
rebuffering : IRebufferingStatus | null;
|
|
376
|
+
/**
|
|
377
|
+
* Set if the player is frozen, that is, stuck in place for unknown reason.
|
|
378
|
+
* Note that this reason can be a valid one, such as a necessary license not
|
|
379
|
+
* being obtained yet.
|
|
380
|
+
*
|
|
381
|
+
* `null` if the player is not frozen.
|
|
382
|
+
*/
|
|
383
|
+
freezing : IFreezingStatus | null;
|
|
384
|
+
/**
|
|
385
|
+
* If `true`, an "internal seek" (a seeking operation triggered by the
|
|
386
|
+
* RxPlayer code) is currently pending.
|
|
387
|
+
*/
|
|
388
|
+
internalSeeking : boolean;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Interface providing a generic and read-only version of a `PlaybackObserver`.
|
|
393
|
+
*
|
|
394
|
+
* This interface allows to provide regular and specific playback information
|
|
395
|
+
* without allowing any effect on playback like seeking.
|
|
396
|
+
*
|
|
397
|
+
* This can be very useful to give specific playback information to modules you
|
|
398
|
+
* don't want to be able to update playback.
|
|
399
|
+
*
|
|
400
|
+
* Note that a `PlaybackObserver` is compatible and can thus be upcasted to a
|
|
401
|
+
* `IReadOnlyPlaybackObserver` to "remove" its right to update playback.
|
|
402
|
+
*/
|
|
403
|
+
export interface IReadOnlyPlaybackObserver<TObservationType> {
|
|
404
|
+
/** Get the current playing position, in seconds. */
|
|
405
|
+
getCurrentTime() : number;
|
|
406
|
+
/** Get the HTMLMediaElement's current `readyState`. */
|
|
407
|
+
getReadyState() : number;
|
|
408
|
+
/**
|
|
409
|
+
* Returns an Observable regularly emitting playback observation, optionally
|
|
410
|
+
* starting with the last one.
|
|
411
|
+
*
|
|
412
|
+
* Note that this Observable is shared and unique, so that multiple `observe`
|
|
413
|
+
* call will return the exact same Observable and multiple concurrent
|
|
414
|
+
* `subscribe` will receive the same events at the same time.
|
|
415
|
+
* This was done for performance and simplicity reasons.
|
|
416
|
+
*
|
|
417
|
+
* @param {boolean} includeLastObservation
|
|
418
|
+
* @returns {Observable}
|
|
419
|
+
*/
|
|
420
|
+
observe(includeLastObservation : boolean) : Observable<TObservationType>;
|
|
421
|
+
/**
|
|
422
|
+
* Generate a new `IReadOnlyPlaybackObserver` from this one.
|
|
423
|
+
*
|
|
424
|
+
* As argument, this method takes a function which will allow to produce
|
|
425
|
+
* the new set of properties to be present on each observation.
|
|
426
|
+
* @param {Function} mapObservable
|
|
427
|
+
* @returns {Object}
|
|
428
|
+
*/
|
|
429
|
+
deriveReadOnlyObserver<TDest>(
|
|
430
|
+
mapObservable : (observation$ : Observable<TObservationType>) => Observable<TDest>,
|
|
431
|
+
mapObservation : (observation : TObservationType) => TDest
|
|
432
|
+
) : IReadOnlyPlaybackObserver<TDest>;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Returns the amount of time in seconds the buffer should have ahead of the
|
|
437
|
+
* current position before resuming playback. Based on the infos of the
|
|
438
|
+
* rebuffering status.
|
|
439
|
+
*
|
|
440
|
+
* Waiting time differs between a rebuffering happening after a "seek" or one
|
|
441
|
+
* happening after a buffer starvation occured.
|
|
442
|
+
* @param {Object|null} rebufferingStatus
|
|
443
|
+
* @param {Boolean} lowLatencyMode
|
|
444
|
+
* @returns {Number}
|
|
445
|
+
*/
|
|
446
|
+
function getRebufferingEndGap(
|
|
447
|
+
rebufferingStatus : IRebufferingStatus,
|
|
448
|
+
lowLatencyMode : boolean
|
|
449
|
+
) : number {
|
|
450
|
+
if (rebufferingStatus === null) {
|
|
451
|
+
return 0;
|
|
452
|
+
}
|
|
453
|
+
const suffix : "LOW_LATENCY" | "DEFAULT" = lowLatencyMode ? "LOW_LATENCY" :
|
|
454
|
+
"DEFAULT";
|
|
455
|
+
|
|
456
|
+
switch (rebufferingStatus.reason) {
|
|
457
|
+
case "seeking":
|
|
458
|
+
return RESUME_GAP_AFTER_SEEKING[suffix];
|
|
459
|
+
case "not-ready":
|
|
460
|
+
return RESUME_GAP_AFTER_NOT_ENOUGH_DATA[suffix];
|
|
461
|
+
case "buffering":
|
|
462
|
+
return RESUME_GAP_AFTER_BUFFERING[suffix];
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* @param {Object} currentRange
|
|
468
|
+
* @param {Number} duration
|
|
469
|
+
* @param {Boolean} lowLatencyMode
|
|
470
|
+
* @returns {Boolean}
|
|
471
|
+
*/
|
|
472
|
+
function hasLoadedUntilTheEnd(
|
|
473
|
+
currentRange : { start : number; end : number }|null,
|
|
474
|
+
duration : number,
|
|
475
|
+
lowLatencyMode : boolean
|
|
476
|
+
) : boolean {
|
|
477
|
+
const suffix : "LOW_LATENCY" | "DEFAULT" = lowLatencyMode ? "LOW_LATENCY" :
|
|
478
|
+
"DEFAULT";
|
|
479
|
+
return currentRange !== null &&
|
|
480
|
+
(duration - currentRange.end) <= REBUFFERING_GAP[suffix];
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* Get basic playback information.
|
|
485
|
+
* @param {HTMLMediaElement} mediaElement
|
|
486
|
+
* @param {string} event
|
|
487
|
+
* @returns {Object}
|
|
488
|
+
*/
|
|
489
|
+
function getMediaInfos(
|
|
490
|
+
mediaElement : HTMLMediaElement,
|
|
491
|
+
event : IPlaybackObserverEventType
|
|
492
|
+
) : IMediaInfos {
|
|
493
|
+
const { buffered,
|
|
494
|
+
currentTime,
|
|
495
|
+
duration,
|
|
496
|
+
ended,
|
|
497
|
+
paused,
|
|
498
|
+
playbackRate,
|
|
499
|
+
readyState,
|
|
500
|
+
seeking } = mediaElement;
|
|
501
|
+
|
|
502
|
+
const currentRange = getRange(buffered, currentTime);
|
|
503
|
+
return { bufferGap: currentRange !== null ? currentRange.end - currentTime :
|
|
504
|
+
// TODO null/0 would probably be
|
|
505
|
+
// more appropriate
|
|
506
|
+
Infinity,
|
|
507
|
+
buffered,
|
|
508
|
+
currentRange,
|
|
509
|
+
position: currentTime,
|
|
510
|
+
duration,
|
|
511
|
+
ended,
|
|
512
|
+
paused,
|
|
513
|
+
playbackRate,
|
|
514
|
+
readyState,
|
|
515
|
+
seeking,
|
|
516
|
+
event };
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
/**
|
|
520
|
+
* Infer rebuffering status of the media based on:
|
|
521
|
+
* - the return of the function getMediaInfos
|
|
522
|
+
* - the previous observation object.
|
|
523
|
+
*
|
|
524
|
+
* @param {Object} prevObservation - Previous playback observation object.
|
|
525
|
+
* @param {Object} currentInfo - Current set of basic information on the
|
|
526
|
+
* `HTMLMediaElement`. This does not need every single property from a regular
|
|
527
|
+
* playback observation.
|
|
528
|
+
* @param {Object} options
|
|
529
|
+
* @returns {Object|null}
|
|
530
|
+
*/
|
|
531
|
+
function getRebufferingStatus(
|
|
532
|
+
prevObservation : IPlaybackObservation,
|
|
533
|
+
currentInfo : IMediaInfos,
|
|
534
|
+
{ withMediaSource, lowLatencyMode } : IPlaybackObserverOptions
|
|
535
|
+
) : IRebufferingStatus | null {
|
|
536
|
+
const { event: currentEvt,
|
|
537
|
+
position: currentTime,
|
|
538
|
+
bufferGap,
|
|
539
|
+
currentRange,
|
|
540
|
+
duration,
|
|
541
|
+
paused,
|
|
542
|
+
readyState,
|
|
543
|
+
ended } = currentInfo;
|
|
544
|
+
|
|
545
|
+
const { rebuffering: prevRebuffering,
|
|
546
|
+
event: prevEvt,
|
|
547
|
+
position: prevTime } = prevObservation;
|
|
548
|
+
|
|
549
|
+
const fullyLoaded = hasLoadedUntilTheEnd(currentRange, duration, lowLatencyMode);
|
|
550
|
+
|
|
551
|
+
const canSwitchToRebuffering = (readyState >= 1 &&
|
|
552
|
+
currentEvt !== "loadedmetadata" &&
|
|
553
|
+
prevRebuffering === null &&
|
|
554
|
+
!(fullyLoaded || ended));
|
|
555
|
+
|
|
556
|
+
let rebufferEndPosition : number | null = null;
|
|
557
|
+
let shouldRebuffer : boolean | undefined;
|
|
558
|
+
let shouldStopRebuffer : boolean | undefined;
|
|
559
|
+
|
|
560
|
+
const rebufferGap = lowLatencyMode ? REBUFFERING_GAP.LOW_LATENCY :
|
|
561
|
+
REBUFFERING_GAP.DEFAULT;
|
|
562
|
+
|
|
563
|
+
if (withMediaSource) {
|
|
564
|
+
if (canSwitchToRebuffering) {
|
|
565
|
+
if (bufferGap <= rebufferGap) {
|
|
566
|
+
shouldRebuffer = true;
|
|
567
|
+
rebufferEndPosition = currentTime + bufferGap;
|
|
568
|
+
} else if (bufferGap === Infinity) {
|
|
569
|
+
shouldRebuffer = true;
|
|
570
|
+
rebufferEndPosition = currentTime;
|
|
571
|
+
}
|
|
572
|
+
} else if (prevRebuffering !== null) {
|
|
573
|
+
const resumeGap = getRebufferingEndGap(prevRebuffering, lowLatencyMode);
|
|
574
|
+
if (shouldRebuffer !== true && prevRebuffering !== null && readyState > 1 &&
|
|
575
|
+
(fullyLoaded || ended || (bufferGap < Infinity && bufferGap > resumeGap)))
|
|
576
|
+
{
|
|
577
|
+
shouldStopRebuffer = true;
|
|
578
|
+
} else if (bufferGap === Infinity || bufferGap <= resumeGap) {
|
|
579
|
+
rebufferEndPosition = bufferGap === Infinity ? currentTime :
|
|
580
|
+
currentTime + bufferGap;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
// when using a direct file, the media will stall and unstall on its
|
|
586
|
+
// own, so we only try to detect when the media timestamp has not changed
|
|
587
|
+
// between two consecutive timeupdates
|
|
588
|
+
else {
|
|
589
|
+
if (canSwitchToRebuffering &&
|
|
590
|
+
(!paused && currentEvt === "timeupdate" &&
|
|
591
|
+
prevEvt === "timeupdate" && currentTime === prevTime ||
|
|
592
|
+
currentEvt === "seeking" && bufferGap === Infinity)
|
|
593
|
+
) {
|
|
594
|
+
shouldRebuffer = true;
|
|
595
|
+
} else if (prevRebuffering !== null &&
|
|
596
|
+
(currentEvt !== "seeking" && currentTime !== prevTime ||
|
|
597
|
+
currentEvt === "canplay" ||
|
|
598
|
+
bufferGap < Infinity &&
|
|
599
|
+
(bufferGap > getRebufferingEndGap(prevRebuffering, lowLatencyMode) ||
|
|
600
|
+
fullyLoaded || ended))
|
|
601
|
+
) {
|
|
602
|
+
shouldStopRebuffer = true;
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
if (shouldStopRebuffer === true) {
|
|
607
|
+
return null;
|
|
608
|
+
} else if (shouldRebuffer === true || prevRebuffering !== null) {
|
|
609
|
+
let reason : "seeking" | "not-ready" | "buffering" | "internal-seek";
|
|
610
|
+
if (currentEvt === "seeking" ||
|
|
611
|
+
prevRebuffering !== null && prevRebuffering.reason === "seeking") {
|
|
612
|
+
reason = "seeking";
|
|
613
|
+
} else if (currentInfo.seeking) {
|
|
614
|
+
reason = "seeking";
|
|
615
|
+
} else if (readyState === 1) {
|
|
616
|
+
reason = "not-ready";
|
|
617
|
+
} else {
|
|
618
|
+
reason = "buffering";
|
|
619
|
+
}
|
|
620
|
+
if (prevRebuffering !== null && prevRebuffering.reason === reason) {
|
|
621
|
+
return { reason: prevRebuffering.reason,
|
|
622
|
+
timestamp: prevRebuffering.timestamp,
|
|
623
|
+
position: rebufferEndPosition };
|
|
624
|
+
}
|
|
625
|
+
return { reason,
|
|
626
|
+
timestamp: performance.now(),
|
|
627
|
+
position: rebufferEndPosition };
|
|
628
|
+
}
|
|
629
|
+
return null;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
/**
|
|
633
|
+
* Detect if the current media can be considered as "freezing" (i.e. not
|
|
634
|
+
* advancing for unknown reasons).
|
|
635
|
+
*
|
|
636
|
+
* Returns a corresponding `IFreezingStatus` object if that's the case and
|
|
637
|
+
* `null` if not.
|
|
638
|
+
* @param {Object} prevObservation
|
|
639
|
+
* @param {Object} currentInfo
|
|
640
|
+
* @returns {Object|null}
|
|
641
|
+
*/
|
|
642
|
+
function getFreezingStatus(
|
|
643
|
+
prevObservation : IPlaybackObservation,
|
|
644
|
+
currentInfo : IMediaInfos
|
|
645
|
+
) : IFreezingStatus | null {
|
|
646
|
+
if (prevObservation.freezing) {
|
|
647
|
+
if (currentInfo.ended ||
|
|
648
|
+
currentInfo.paused ||
|
|
649
|
+
currentInfo.readyState === 0 ||
|
|
650
|
+
currentInfo.playbackRate === 0 ||
|
|
651
|
+
prevObservation.position !== currentInfo.position)
|
|
652
|
+
{
|
|
653
|
+
return null; // Quit freezing status
|
|
654
|
+
}
|
|
655
|
+
return prevObservation.freezing; // Stay in it
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
return currentInfo.event === "timeupdate" &&
|
|
659
|
+
currentInfo.bufferGap > MINIMUM_BUFFER_AMOUNT_BEFORE_FREEZING &&
|
|
660
|
+
!currentInfo.ended &&
|
|
661
|
+
!currentInfo.paused &&
|
|
662
|
+
currentInfo.readyState >= 1 &&
|
|
663
|
+
currentInfo.playbackRate !== 0 &&
|
|
664
|
+
currentInfo.position === prevObservation.position ?
|
|
665
|
+
{ timestamp: performance.now() } :
|
|
666
|
+
null;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
export interface IPlaybackObserverOptions {
|
|
670
|
+
withMediaSource : boolean;
|
|
671
|
+
lowLatencyMode : boolean;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
/**
|
|
675
|
+
* Pretty print a TimeRanges Object, to see the current content of it in a
|
|
676
|
+
* one-liner string.
|
|
677
|
+
*
|
|
678
|
+
* @example
|
|
679
|
+
* This function is called by giving it directly the TimeRanges, such as:
|
|
680
|
+
* ```js
|
|
681
|
+
* prettyPrintBuffered(document.getElementsByTagName("video")[0].buffered);
|
|
682
|
+
* ```
|
|
683
|
+
*
|
|
684
|
+
* Let's consider this possible return:
|
|
685
|
+
*
|
|
686
|
+
* ```
|
|
687
|
+
* 0.00|==29.95==|29.95 ~30.05~ 60.00|==29.86==|89.86
|
|
688
|
+
* ^14
|
|
689
|
+
* ```
|
|
690
|
+
* This means that our video element has 29.95 seconds of buffer between 0 and
|
|
691
|
+
* 29.95 seconds.
|
|
692
|
+
* Then 30.05 seconds where no buffer is found.
|
|
693
|
+
* Then 29.86 seconds of buffer between 60.00 and 89.86 seconds.
|
|
694
|
+
*
|
|
695
|
+
* A caret on the second line indicates the current time we're at.
|
|
696
|
+
* The number coming after it is the current time.
|
|
697
|
+
* @param {TimeRanges} buffered
|
|
698
|
+
* @param {number} currentTime
|
|
699
|
+
* @returns {string}
|
|
700
|
+
*/
|
|
701
|
+
function prettyPrintBuffered(
|
|
702
|
+
buffered : TimeRanges,
|
|
703
|
+
currentTime : number
|
|
704
|
+
) : string {
|
|
705
|
+
let str = "";
|
|
706
|
+
let currentTimeStr = "";
|
|
707
|
+
|
|
708
|
+
for (let i = 0; i < buffered.length; i++) {
|
|
709
|
+
const start = buffered.start(i);
|
|
710
|
+
const end = buffered.end(i);
|
|
711
|
+
const fixedStart = start.toFixed(2);
|
|
712
|
+
const fixedEnd = end.toFixed(2);
|
|
713
|
+
const fixedDuration = (end - start).toFixed(2);
|
|
714
|
+
const newIntervalStr = `${fixedStart}|==${fixedDuration}==|${fixedEnd}`;
|
|
715
|
+
str += newIntervalStr;
|
|
716
|
+
if (currentTimeStr.length === 0 && end > currentTime) {
|
|
717
|
+
const padBefore = str.length - Math.floor(newIntervalStr.length / 2);
|
|
718
|
+
currentTimeStr = " ".repeat(padBefore) + `^${currentTime}`;
|
|
719
|
+
}
|
|
720
|
+
if (i < buffered.length - 1) {
|
|
721
|
+
const nextStart = buffered.start(i + 1);
|
|
722
|
+
const fixedDiff = (nextStart - end).toFixed(2);
|
|
723
|
+
const holeStr = ` ~${fixedDiff}~ `;
|
|
724
|
+
str += holeStr;
|
|
725
|
+
if (currentTimeStr.length === 0 && currentTime < nextStart) {
|
|
726
|
+
const padBefore = str.length - Math.floor(holeStr.length / 2);
|
|
727
|
+
currentTimeStr = " ".repeat(padBefore) + `^${currentTime}`;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
if (currentTimeStr.length === 0) {
|
|
732
|
+
currentTimeStr = " ".repeat(str.length) + `^${currentTime}`;
|
|
733
|
+
}
|
|
734
|
+
return str + "\n" + currentTimeStr;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
/**
|
|
738
|
+
* Create `IReadOnlyPlaybackObserver` from a source `IReadOnlyPlaybackObserver`
|
|
739
|
+
* and a mapping function.
|
|
740
|
+
* @param {Object} src
|
|
741
|
+
* @param {Function} mapObservable
|
|
742
|
+
* @returns {Object}
|
|
743
|
+
*/
|
|
744
|
+
function generateReadOnlyObserver<TSource, TDest>(
|
|
745
|
+
src : IReadOnlyPlaybackObserver<TSource>,
|
|
746
|
+
mapObservable : (observation$ : Observable<TSource>) => Observable<TDest>
|
|
747
|
+
) : IReadOnlyPlaybackObserver<TDest> {
|
|
748
|
+
const newObs = observableDefer(() =>
|
|
749
|
+
mapObservable(src.observe(true))
|
|
750
|
+
).pipe(shareReplay({ bufferSize: 1, refCount: true }));
|
|
751
|
+
return {
|
|
752
|
+
getCurrentTime() {
|
|
753
|
+
return src.getCurrentTime();
|
|
754
|
+
},
|
|
755
|
+
getReadyState() {
|
|
756
|
+
return src.getReadyState();
|
|
757
|
+
},
|
|
758
|
+
observe(includeLastObservation : boolean) : Observable<TDest> {
|
|
759
|
+
return includeLastObservation ? newObs :
|
|
760
|
+
newObs.pipe(skip(1));
|
|
761
|
+
},
|
|
762
|
+
deriveReadOnlyObserver<TNext>(
|
|
763
|
+
newUdateObserver : (observation$ : Observable<TDest>) => Observable<TNext>
|
|
764
|
+
) : IReadOnlyPlaybackObserver<TNext> {
|
|
765
|
+
return generateReadOnlyObserver(this, newUdateObserver);
|
|
766
|
+
},
|
|
767
|
+
};
|
|
768
|
+
}
|