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
|
@@ -21,10 +21,8 @@ import {
|
|
|
21
21
|
import config from "../../../../config";
|
|
22
22
|
import log from "../../../../log";
|
|
23
23
|
import { getLoggableSegmentId } from "../../../../manifest";
|
|
24
|
-
import areArraysOfNumbersEqual from "../../../../utils/are_arrays_of_numbers_equal";
|
|
25
24
|
import assertUnreachable from "../../../../utils/assert_unreachable";
|
|
26
|
-
import
|
|
27
|
-
import hashBuffer from "../../../../utils/hash_buffer";
|
|
25
|
+
import createCancellablePromise from "../../../../utils/create_cancellable_promise";
|
|
28
26
|
import noop from "../../../../utils/noop";
|
|
29
27
|
import objectAssign from "../../../../utils/object_assign";
|
|
30
28
|
import TaskCanceller, {
|
|
@@ -138,20 +136,26 @@ export default class AudioVideoSegmentBuffer extends SegmentBuffer {
|
|
|
138
136
|
private _pendingTask : IAVSBPendingTask | null;
|
|
139
137
|
|
|
140
138
|
/**
|
|
141
|
-
* Keep track of the of the latest init segment
|
|
142
|
-
* SourceBuffer.
|
|
139
|
+
* Keep track of the unique identifier of the of the latest init segment
|
|
140
|
+
* pushed to the linked SourceBuffer.
|
|
143
141
|
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
142
|
+
* Such identifiers are first declared through the `declareInitSegment`
|
|
143
|
+
* method and the corresponding initialization segment is then pushed through
|
|
144
|
+
* the `pushChunk` method.
|
|
145
|
+
*
|
|
146
|
+
* Keeping track of this allows to be sure the right initialization segment is
|
|
147
|
+
* pushed before any chunk is.
|
|
146
148
|
*
|
|
147
149
|
* `null` if no initialization segment have been pushed to the
|
|
148
150
|
* `AudioVideoSegmentBuffer` yet.
|
|
149
151
|
*/
|
|
150
|
-
private
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
152
|
+
private _lastInitSegmentUniqueId : string | null;
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Link unique identifiers for initialization segments (as communicated by
|
|
156
|
+
* `declareInitSegment`) to the corresponding initialization data.
|
|
157
|
+
*/
|
|
158
|
+
private _initSegmentsMap : Map<string, BufferSource>;
|
|
155
159
|
|
|
156
160
|
/**
|
|
157
161
|
* @constructor
|
|
@@ -173,8 +177,9 @@ export default class AudioVideoSegmentBuffer extends SegmentBuffer {
|
|
|
173
177
|
this._sourceBuffer = sourceBuffer;
|
|
174
178
|
this._queue = [];
|
|
175
179
|
this._pendingTask = null;
|
|
176
|
-
this.
|
|
180
|
+
this._lastInitSegmentUniqueId = null;
|
|
177
181
|
this.codec = codec;
|
|
182
|
+
this._initSegmentsMap = new Map();
|
|
178
183
|
|
|
179
184
|
const onError = this._onPendingTaskError.bind(this);
|
|
180
185
|
const reCheck = this._flush.bind(this);
|
|
@@ -197,6 +202,20 @@ export default class AudioVideoSegmentBuffer extends SegmentBuffer {
|
|
|
197
202
|
});
|
|
198
203
|
}
|
|
199
204
|
|
|
205
|
+
public declareInitSegment(
|
|
206
|
+
uniqueId : string,
|
|
207
|
+
initSegmentData : unknown
|
|
208
|
+
) : void {
|
|
209
|
+
assertDataIsBufferSource(initSegmentData);
|
|
210
|
+
this._initSegmentsMap.set(uniqueId, initSegmentData);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
public freeInitSegment(
|
|
214
|
+
uniqueId : string
|
|
215
|
+
) : void {
|
|
216
|
+
this._initSegmentsMap.delete(uniqueId);
|
|
217
|
+
}
|
|
218
|
+
|
|
200
219
|
/**
|
|
201
220
|
* Push a chunk of the media segment given to the attached SourceBuffer, in a
|
|
202
221
|
* FIFO queue.
|
|
@@ -228,12 +247,12 @@ export default class AudioVideoSegmentBuffer extends SegmentBuffer {
|
|
|
228
247
|
infos : IPushChunkInfos<unknown>,
|
|
229
248
|
cancellationSignal : CancellationSignal
|
|
230
249
|
) : Promise<void> {
|
|
231
|
-
|
|
250
|
+
assertDataIsBufferSource(infos.data.chunk);
|
|
232
251
|
log.debug("AVSB: receiving order to push data to the SourceBuffer",
|
|
233
252
|
this.bufferType,
|
|
234
253
|
getLoggableSegmentId(infos.inventoryInfos));
|
|
235
254
|
return this._addToQueue({ type: SegmentBufferOperation.Push,
|
|
236
|
-
value: infos },
|
|
255
|
+
value: infos as IPushChunkInfos<BufferSource> },
|
|
237
256
|
cancellationSignal);
|
|
238
257
|
}
|
|
239
258
|
|
|
@@ -349,7 +368,7 @@ export default class AudioVideoSegmentBuffer extends SegmentBuffer {
|
|
|
349
368
|
* @param {Event} err
|
|
350
369
|
*/
|
|
351
370
|
private _onPendingTaskError(err : unknown) : void {
|
|
352
|
-
this.
|
|
371
|
+
this._lastInitSegmentUniqueId = null; // initialize init segment as a security
|
|
353
372
|
if (this._pendingTask !== null) {
|
|
354
373
|
const error = err instanceof Error ?
|
|
355
374
|
err :
|
|
@@ -369,15 +388,15 @@ export default class AudioVideoSegmentBuffer extends SegmentBuffer {
|
|
|
369
388
|
operation : ISBOperation<BufferSource>,
|
|
370
389
|
cancellationSignal : CancellationSignal
|
|
371
390
|
) : Promise<void> {
|
|
372
|
-
return
|
|
373
|
-
if (cancellationSignal.cancellationError !== null) {
|
|
374
|
-
return reject(cancellationSignal.cancellationError);
|
|
375
|
-
}
|
|
391
|
+
return createCancellablePromise(cancellationSignal, (resolve, reject) => {
|
|
376
392
|
const shouldRestartQueue = this._queue.length === 0 &&
|
|
377
393
|
this._pendingTask === null;
|
|
378
394
|
const queueItem = objectAssign({ resolve, reject }, operation);
|
|
379
395
|
this._queue.push(queueItem);
|
|
380
|
-
|
|
396
|
+
if (shouldRestartQueue) {
|
|
397
|
+
this._flush();
|
|
398
|
+
}
|
|
399
|
+
return () => {
|
|
381
400
|
// Remove the corresponding element from the AudioVideoSegmentBuffer's
|
|
382
401
|
// queue.
|
|
383
402
|
// If the operation was a pending task, it should still continue to not
|
|
@@ -388,12 +407,7 @@ export default class AudioVideoSegmentBuffer extends SegmentBuffer {
|
|
|
388
407
|
}
|
|
389
408
|
queueItem.resolve = noop;
|
|
390
409
|
queueItem.reject = noop;
|
|
391
|
-
|
|
392
|
-
});
|
|
393
|
-
|
|
394
|
-
if (shouldRestartQueue) {
|
|
395
|
-
this._flush();
|
|
396
|
-
}
|
|
410
|
+
};
|
|
397
411
|
});
|
|
398
412
|
}
|
|
399
413
|
|
|
@@ -451,7 +465,7 @@ export default class AudioVideoSegmentBuffer extends SegmentBuffer {
|
|
|
451
465
|
const error = e instanceof Error ?
|
|
452
466
|
e :
|
|
453
467
|
new Error("An unknown error occured when preparing a push operation");
|
|
454
|
-
this.
|
|
468
|
+
this._lastInitSegmentUniqueId = null; // initialize init segment as a security
|
|
455
469
|
nextItem.reject(error);
|
|
456
470
|
return;
|
|
457
471
|
}
|
|
@@ -561,15 +575,17 @@ export default class AudioVideoSegmentBuffer extends SegmentBuffer {
|
|
|
561
575
|
this._sourceBuffer.appendWindowEnd = appendWindow[1];
|
|
562
576
|
}
|
|
563
577
|
|
|
564
|
-
if (data.
|
|
565
|
-
(hasUpdatedSourceBufferType ||
|
|
578
|
+
if (data.initSegmentUniqueId !== null &&
|
|
579
|
+
(hasUpdatedSourceBufferType ||
|
|
580
|
+
!this._isLastInitSegment(data.initSegmentUniqueId)))
|
|
566
581
|
{
|
|
567
582
|
// Push initialization segment before the media segment
|
|
568
|
-
const segmentData = data.
|
|
583
|
+
const segmentData = this._initSegmentsMap.get(data.initSegmentUniqueId);
|
|
584
|
+
if (segmentData === undefined) {
|
|
585
|
+
throw new Error("Invalid initialization segment uniqueId");
|
|
586
|
+
}
|
|
569
587
|
dataToPush.push(segmentData);
|
|
570
|
-
|
|
571
|
-
this._lastInitSegment = { data: initU8,
|
|
572
|
-
hash: hashBuffer(initU8) };
|
|
588
|
+
this._lastInitSegmentUniqueId = data.initSegmentUniqueId;
|
|
573
589
|
}
|
|
574
590
|
|
|
575
591
|
if (data.chunk !== null) {
|
|
@@ -580,28 +596,16 @@ export default class AudioVideoSegmentBuffer extends SegmentBuffer {
|
|
|
580
596
|
}
|
|
581
597
|
|
|
582
598
|
/**
|
|
583
|
-
* Return `true` if the given `
|
|
599
|
+
* Return `true` if the given `uniqueId` is the identifier of the last
|
|
584
600
|
* initialization segment pushed to the `AudioVideoSegmentBuffer`.
|
|
585
|
-
* @param {
|
|
601
|
+
* @param {string} uniqueId
|
|
586
602
|
* @returns {boolean}
|
|
587
603
|
*/
|
|
588
|
-
private _isLastInitSegment(
|
|
589
|
-
if (this.
|
|
604
|
+
private _isLastInitSegment(uniqueId : string) : boolean {
|
|
605
|
+
if (this._lastInitSegmentUniqueId === null) {
|
|
590
606
|
return false;
|
|
591
607
|
}
|
|
592
|
-
|
|
593
|
-
return true;
|
|
594
|
-
}
|
|
595
|
-
const oldInit = this._lastInitSegment.data;
|
|
596
|
-
if (oldInit.byteLength === segmentData.byteLength) {
|
|
597
|
-
const newInitU8 = toUint8Array(segmentData);
|
|
598
|
-
if (hashBuffer(newInitU8) === this._lastInitSegment.hash &&
|
|
599
|
-
areArraysOfNumbersEqual(oldInit, newInitU8))
|
|
600
|
-
{
|
|
601
|
-
return true;
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
return false;
|
|
608
|
+
return this._lastInitSegmentUniqueId === uniqueId;
|
|
605
609
|
}
|
|
606
610
|
}
|
|
607
611
|
|
|
@@ -609,27 +613,20 @@ export default class AudioVideoSegmentBuffer extends SegmentBuffer {
|
|
|
609
613
|
* Throw if the given input is not in the expected format.
|
|
610
614
|
* Allows to enforce runtime type-checking as compile-time type-checking here is
|
|
611
615
|
* difficult to enforce.
|
|
612
|
-
* @param {Object}
|
|
616
|
+
* @param {Object} data
|
|
613
617
|
*/
|
|
614
|
-
function
|
|
615
|
-
|
|
616
|
-
) : asserts
|
|
618
|
+
function assertDataIsBufferSource(
|
|
619
|
+
data : unknown
|
|
620
|
+
) : asserts data is BufferSource {
|
|
617
621
|
if (__ENVIRONMENT__.CURRENT_ENV === __ENVIRONMENT__.PRODUCTION as number) {
|
|
618
622
|
return;
|
|
619
623
|
}
|
|
620
|
-
const { chunk, initSegment } = pushedData.data;
|
|
621
624
|
if (
|
|
622
|
-
typeof
|
|
623
|
-
typeof initSegment !== "object" ||
|
|
624
|
-
(
|
|
625
|
-
chunk !== null &&
|
|
626
|
-
!(chunk instanceof ArrayBuffer) &&
|
|
627
|
-
!((chunk as ArrayBufferView).buffer instanceof ArrayBuffer)
|
|
628
|
-
) ||
|
|
625
|
+
typeof data !== "object" ||
|
|
629
626
|
(
|
|
630
|
-
|
|
631
|
-
!(
|
|
632
|
-
!((
|
|
627
|
+
data !== null &&
|
|
628
|
+
!(data instanceof ArrayBuffer) &&
|
|
629
|
+
!((data as ArrayBufferView).buffer instanceof ArrayBuffer)
|
|
633
630
|
)
|
|
634
631
|
) {
|
|
635
632
|
throw new Error("Invalid data given to the AudioVideoSegmentBuffer");
|
|
@@ -137,6 +137,22 @@ export default class HTMLTextSegmentBuffer extends SegmentBuffer {
|
|
|
137
137
|
this.autoRefreshSubtitles(this._canceller.signal);
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
+
/**
|
|
141
|
+
* @param {string} uniqueId
|
|
142
|
+
*/
|
|
143
|
+
public declareInitSegment(uniqueId : string): void {
|
|
144
|
+
log.warn("ISB: Declaring initialization segment for image SegmentBuffer",
|
|
145
|
+
uniqueId);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* @param {string} uniqueId
|
|
150
|
+
*/
|
|
151
|
+
public freeInitSegment(uniqueId : string): void {
|
|
152
|
+
log.warn("ISB: Freeing initialization segment for image SegmentBuffer",
|
|
153
|
+
uniqueId);
|
|
154
|
+
}
|
|
155
|
+
|
|
140
156
|
/**
|
|
141
157
|
* Push text segment to the HTMLTextSegmentBuffer.
|
|
142
158
|
* @param {Object} infos
|
|
@@ -353,7 +369,8 @@ export default class HTMLTextSegmentBuffer extends SegmentBuffer {
|
|
|
353
369
|
element : HTMLElement; } => cue.resolution !== null);
|
|
354
370
|
|
|
355
371
|
if (proportionalCues.length > 0) {
|
|
356
|
-
this._sizeUpdateCanceller = new TaskCanceller(
|
|
372
|
+
this._sizeUpdateCanceller = new TaskCanceller();
|
|
373
|
+
this._sizeUpdateCanceller.linkToSignal(this._canceller.signal);
|
|
357
374
|
const { TEXT_TRACK_SIZE_CHECKS_INTERVAL } = config.getCurrent();
|
|
358
375
|
// update propertionally-sized elements periodically
|
|
359
376
|
const heightWidthRef = onHeightWidthChange(this._textTrackElement,
|
|
@@ -382,7 +399,8 @@ export default class HTMLTextSegmentBuffer extends SegmentBuffer {
|
|
|
382
399
|
|
|
383
400
|
const startAutoRefresh = () => {
|
|
384
401
|
stopAutoRefresh();
|
|
385
|
-
autoRefreshCanceller = new TaskCanceller(
|
|
402
|
+
autoRefreshCanceller = new TaskCanceller();
|
|
403
|
+
autoRefreshCanceller.linkToSignal(cancellationSignal);
|
|
386
404
|
const intervalId = setInterval(() => this.refreshSubtitles(),
|
|
387
405
|
MAXIMUM_HTML_TEXT_TRACK_UPDATE_INTERVAL);
|
|
388
406
|
autoRefreshCanceller.signal.register(() => {
|
|
@@ -61,6 +61,22 @@ export default class NativeTextSegmentBuffer extends SegmentBuffer {
|
|
|
61
61
|
this._trackElement = trackElement;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
/**
|
|
65
|
+
* @param {string} uniqueId
|
|
66
|
+
*/
|
|
67
|
+
public declareInitSegment(uniqueId : string): void {
|
|
68
|
+
log.warn("ISB: Declaring initialization segment for image SegmentBuffer",
|
|
69
|
+
uniqueId);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* @param {string} uniqueId
|
|
74
|
+
*/
|
|
75
|
+
public freeInitSegment(uniqueId : string): void {
|
|
76
|
+
log.warn("ISB: Freeing initialization segment for image SegmentBuffer",
|
|
77
|
+
uniqueId);
|
|
78
|
+
}
|
|
79
|
+
|
|
64
80
|
/**
|
|
65
81
|
* @param {Object} infos
|
|
66
82
|
* @returns {Promise}
|
|
@@ -87,6 +87,13 @@ export abstract class SegmentBuffer {
|
|
|
87
87
|
this._segmentInventory = new SegmentInventory();
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
+
public abstract declareInitSegment(
|
|
91
|
+
uniqueId : string,
|
|
92
|
+
initSegmentData : unknown
|
|
93
|
+
) : void;
|
|
94
|
+
|
|
95
|
+
public abstract freeInitSegment(uniqueId : string) : void;
|
|
96
|
+
|
|
90
97
|
/**
|
|
91
98
|
* Push a chunk of the media segment given to the attached buffer, in a
|
|
92
99
|
* FIFO queue.
|
|
@@ -96,7 +103,8 @@ export abstract class SegmentBuffer {
|
|
|
96
103
|
* pushed.
|
|
97
104
|
*
|
|
98
105
|
* Depending on the type of data appended, the pushed chunk might rely on an
|
|
99
|
-
* initialization segment,
|
|
106
|
+
* initialization segment, which had to be previously declared through the
|
|
107
|
+
* `declareInitSegment` method.
|
|
100
108
|
*
|
|
101
109
|
* Such initialization segment will be first pushed to the buffer if the
|
|
102
110
|
* last pushed segment was associated to another initialization segment.
|
|
@@ -106,7 +114,7 @@ export abstract class SegmentBuffer {
|
|
|
106
114
|
* reference).
|
|
107
115
|
*
|
|
108
116
|
* If you don't need any initialization segment to push the wanted chunk, you
|
|
109
|
-
* can just set
|
|
117
|
+
* can just set the corresponding property to `null`.
|
|
110
118
|
*
|
|
111
119
|
* You can also only push an initialization segment by setting the
|
|
112
120
|
* `data.chunk` argument to null.
|
|
@@ -229,12 +237,16 @@ export type IBufferType = "audio" |
|
|
|
229
237
|
*/
|
|
230
238
|
export interface IPushedChunkData<T> {
|
|
231
239
|
/**
|
|
232
|
-
* The
|
|
240
|
+
* The `uniqueId` of the initialization segment linked to the data you want to
|
|
233
241
|
* push.
|
|
242
|
+
*
|
|
243
|
+
* That identifier should previously have been declared through the
|
|
244
|
+
* `declareInitSegment` method and not freed.
|
|
245
|
+
*
|
|
234
246
|
* To set to `null` either if no initialization data is needed, or if you are
|
|
235
247
|
* confident that the last pushed one is compatible.
|
|
236
248
|
*/
|
|
237
|
-
|
|
249
|
+
initSegmentUniqueId : string | null;
|
|
238
250
|
/**
|
|
239
251
|
* Chunk you want to push.
|
|
240
252
|
* This can be the whole decodable segment's data or just a decodable sub-part
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
import {
|
|
31
31
|
IBufferedChunk,
|
|
32
32
|
IChunkContext,
|
|
33
|
+
IInsertedChunkInfos,
|
|
33
34
|
getFirstSegmentAfterPeriod,
|
|
34
35
|
getLastSegmentBeforePeriod,
|
|
35
36
|
} from "./inventory";
|
|
@@ -51,6 +52,7 @@ export {
|
|
|
51
52
|
|
|
52
53
|
IBufferedChunk,
|
|
53
54
|
IChunkContext,
|
|
55
|
+
IInsertedChunkInfos,
|
|
54
56
|
|
|
55
57
|
IPushChunkInfos,
|
|
56
58
|
IPushedChunkData,
|
|
@@ -17,10 +17,8 @@
|
|
|
17
17
|
import { MediaError } from "../../errors";
|
|
18
18
|
import features from "../../features";
|
|
19
19
|
import log from "../../log";
|
|
20
|
-
import
|
|
21
|
-
|
|
22
|
-
CancellationSignal,
|
|
23
|
-
} from "../../utils/task_canceller";
|
|
20
|
+
import createCancellablePromise from "../../utils/create_cancellable_promise";
|
|
21
|
+
import { CancellationSignal } from "../../utils/task_canceller";
|
|
24
22
|
import {
|
|
25
23
|
AudioVideoSegmentBuffer,
|
|
26
24
|
IBufferType,
|
|
@@ -189,21 +187,26 @@ export default class SegmentBuffersStore {
|
|
|
189
187
|
if (this._areNativeBuffersUsable()) {
|
|
190
188
|
return Promise.resolve();
|
|
191
189
|
}
|
|
192
|
-
return
|
|
193
|
-
|
|
190
|
+
return createCancellablePromise(cancelWaitSignal, (res) => {
|
|
191
|
+
/* eslint-disable-next-line prefer-const */
|
|
192
|
+
let onAddedOrDisabled : () => void;
|
|
193
|
+
|
|
194
|
+
const removeCallback = () => {
|
|
195
|
+
const indexOf = this._onNativeBufferAddedOrDisabled.indexOf(onAddedOrDisabled);
|
|
196
|
+
if (indexOf >= 0) {
|
|
197
|
+
this._onNativeBufferAddedOrDisabled.splice(indexOf, 1);
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
onAddedOrDisabled = () => {
|
|
194
202
|
if (this._areNativeBuffersUsable()) {
|
|
203
|
+
removeCallback();
|
|
195
204
|
res();
|
|
196
205
|
}
|
|
197
206
|
};
|
|
198
207
|
this._onNativeBufferAddedOrDisabled.push(onAddedOrDisabled);
|
|
199
208
|
|
|
200
|
-
|
|
201
|
-
const indexOf = this._onNativeBufferAddedOrDisabled.indexOf(onAddedOrDisabled);
|
|
202
|
-
if (indexOf >= 0) {
|
|
203
|
-
this._onNativeBufferAddedOrDisabled.splice(indexOf, 1);
|
|
204
|
-
}
|
|
205
|
-
rej(error);
|
|
206
|
-
});
|
|
209
|
+
return removeCallback;
|
|
207
210
|
});
|
|
208
211
|
}
|
|
209
212
|
|
|
@@ -3,6 +3,8 @@ import { formatError } from "../../../errors";
|
|
|
3
3
|
import log from "../../../log";
|
|
4
4
|
import { Representation } from "../../../manifest";
|
|
5
5
|
import assertUnreachable from "../../../utils/assert_unreachable";
|
|
6
|
+
import cancellableSleep from "../../../utils/cancellable_sleep";
|
|
7
|
+
import noop from "../../../utils/noop";
|
|
6
8
|
import objectAssign from "../../../utils/object_assign";
|
|
7
9
|
import {
|
|
8
10
|
createMappedReference,
|
|
@@ -69,7 +71,8 @@ export default function AdaptationStream<T>(
|
|
|
69
71
|
const { manifest, period, adaptation } = content;
|
|
70
72
|
|
|
71
73
|
/** Allows to cancel everything the `AdaptationStream` is doing. */
|
|
72
|
-
const adapStreamCanceller = new TaskCanceller(
|
|
74
|
+
const adapStreamCanceller = new TaskCanceller();
|
|
75
|
+
adapStreamCanceller.linkToSignal(parentCancelSignal);
|
|
73
76
|
|
|
74
77
|
/**
|
|
75
78
|
* The buffer goal ratio base itself on the value given by `wantedBufferAhead`
|
|
@@ -144,9 +147,10 @@ export default function AdaptationStream<T>(
|
|
|
144
147
|
cancelCurrentStreams.cancel();
|
|
145
148
|
}
|
|
146
149
|
representationsList.setValueIfChanged(val.representations);
|
|
147
|
-
cancelCurrentStreams = new TaskCanceller(
|
|
150
|
+
cancelCurrentStreams = new TaskCanceller();
|
|
151
|
+
cancelCurrentStreams.linkToSignal(adapStreamCanceller.signal);
|
|
148
152
|
onRepresentationsChoiceChange(val, cancelCurrentStreams.signal).catch((err) => {
|
|
149
|
-
if (cancelCurrentStreams?.isUsed === true &&
|
|
153
|
+
if (cancelCurrentStreams?.isUsed() === true &&
|
|
150
154
|
TaskCanceller.isCancellationError(err))
|
|
151
155
|
{
|
|
152
156
|
return;
|
|
@@ -195,13 +199,13 @@ export default function AdaptationStream<T>(
|
|
|
195
199
|
case "clean-buffer": // Just clean
|
|
196
200
|
for (const range of switchStrat.value) {
|
|
197
201
|
await segmentBuffer.removeBuffer(range.start, range.end, fnCancelSignal);
|
|
198
|
-
if (fnCancelSignal.isCancelled) {
|
|
202
|
+
if (fnCancelSignal.isCancelled()) {
|
|
199
203
|
return;
|
|
200
204
|
}
|
|
201
205
|
}
|
|
202
206
|
if (switchStrat.type === "flush-buffer") {
|
|
203
207
|
callbacks.needsBufferFlush();
|
|
204
|
-
if (fnCancelSignal.isCancelled) {
|
|
208
|
+
if (fnCancelSignal.isCancelled()) {
|
|
205
209
|
return;
|
|
206
210
|
}
|
|
207
211
|
}
|
|
@@ -229,7 +233,8 @@ export default function AdaptationStream<T>(
|
|
|
229
233
|
* terminating and as such the next one might be immediately created
|
|
230
234
|
* recursively.
|
|
231
235
|
*/
|
|
232
|
-
const repStreamTerminatingCanceller = new TaskCanceller(
|
|
236
|
+
const repStreamTerminatingCanceller = new TaskCanceller();
|
|
237
|
+
repStreamTerminatingCanceller.linkToSignal(fnCancelSignal);
|
|
233
238
|
const { representation } = estimateRef.getValue();
|
|
234
239
|
if (representation === null) {
|
|
235
240
|
return;
|
|
@@ -263,11 +268,11 @@ export default function AdaptationStream<T>(
|
|
|
263
268
|
|
|
264
269
|
const repInfo = { type: adaptation.type, period, representation };
|
|
265
270
|
currentRepresentation.setValue(representation);
|
|
266
|
-
if (adapStreamCanceller.isUsed) {
|
|
271
|
+
if (adapStreamCanceller.isUsed()) {
|
|
267
272
|
return ; // previous callback has stopped everything by side-effect
|
|
268
273
|
}
|
|
269
274
|
callbacks.representationChange(repInfo);
|
|
270
|
-
if (adapStreamCanceller.isUsed) {
|
|
275
|
+
if (adapStreamCanceller.isUsed()) {
|
|
271
276
|
return ; // previous callback has stopped everything by side-effect
|
|
272
277
|
}
|
|
273
278
|
|
|
@@ -284,13 +289,13 @@ export default function AdaptationStream<T>(
|
|
|
284
289
|
},
|
|
285
290
|
addedSegment(segmentInfo) {
|
|
286
291
|
abrCallbacks.addedSegment(segmentInfo);
|
|
287
|
-
if (adapStreamCanceller.isUsed) {
|
|
292
|
+
if (adapStreamCanceller.isUsed()) {
|
|
288
293
|
return;
|
|
289
294
|
}
|
|
290
295
|
callbacks.addedSegment(segmentInfo);
|
|
291
296
|
},
|
|
292
297
|
terminating() {
|
|
293
|
-
if (repStreamTerminatingCanceller.isUsed) {
|
|
298
|
+
if (repStreamTerminatingCanceller.isUsed()) {
|
|
294
299
|
return; // Already handled
|
|
295
300
|
}
|
|
296
301
|
repStreamTerminatingCanceller.cancel();
|
|
@@ -322,7 +327,8 @@ export default function AdaptationStream<T>(
|
|
|
322
327
|
representationStreamCallbacks : IRepresentationStreamCallbacks<T>,
|
|
323
328
|
fnCancelSignal : CancellationSignal
|
|
324
329
|
) : void {
|
|
325
|
-
const bufferGoalCanceller = new TaskCanceller(
|
|
330
|
+
const bufferGoalCanceller = new TaskCanceller();
|
|
331
|
+
bufferGoalCanceller.linkToSignal(fnCancelSignal);
|
|
326
332
|
const bufferGoal = createMappedReference(wantedBufferAhead, prev => {
|
|
327
333
|
return prev * getBufferGoalRatio(representation);
|
|
328
334
|
}, bufferGoalCanceller.signal);
|
|
@@ -339,19 +345,27 @@ export default function AdaptationStream<T>(
|
|
|
339
345
|
defaultCode: "NONE",
|
|
340
346
|
defaultReason: "Unknown `RepresentationStream` error",
|
|
341
347
|
});
|
|
342
|
-
if (formattedError.code
|
|
348
|
+
if (formattedError.code !== "BUFFER_FULL_ERROR") {
|
|
349
|
+
representationStreamCallbacks.error(err);
|
|
350
|
+
} else {
|
|
343
351
|
const wba = wantedBufferAhead.getValue();
|
|
344
352
|
const lastBufferGoalRatio = bufferGoalRatioMap.get(representation.id) ?? 1;
|
|
345
|
-
|
|
353
|
+
// 70%, 49%, 34.3%, 24%, 16.81%, 11.76%, 8.24% and 5.76%
|
|
354
|
+
const newBufferGoalRatio = lastBufferGoalRatio * 0.7;
|
|
355
|
+
if (newBufferGoalRatio <= 0.05 || wba * newBufferGoalRatio <= 2) {
|
|
346
356
|
throw formattedError;
|
|
347
357
|
}
|
|
348
|
-
bufferGoalRatioMap.set(representation.id,
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
358
|
+
bufferGoalRatioMap.set(representation.id, newBufferGoalRatio);
|
|
359
|
+
|
|
360
|
+
// We wait 4 seconds to let the situation evolve by itself before
|
|
361
|
+
// retrying loading segments with a lower buffer goal
|
|
362
|
+
cancellableSleep(4000, adapStreamCanceller.signal).then(() => {
|
|
363
|
+
return createRepresentationStream(representation,
|
|
364
|
+
terminateCurrentStream,
|
|
365
|
+
representationStreamCallbacks,
|
|
366
|
+
fnCancelSignal);
|
|
367
|
+
}).catch(noop);
|
|
353
368
|
}
|
|
354
|
-
representationStreamCallbacks.error(err);
|
|
355
369
|
},
|
|
356
370
|
terminating() {
|
|
357
371
|
bufferGoalCanceller.cancel();
|
|
@@ -0,0 +1,114 @@
|
|
|
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 { MediaError } from "../../../../errors";
|
|
18
|
+
import Manifest, {
|
|
19
|
+
Adaptation,
|
|
20
|
+
Period,
|
|
21
|
+
Representation,
|
|
22
|
+
} from "../../../../manifest";
|
|
23
|
+
import { IPlayerError } from "../../../../public_types";
|
|
24
|
+
import createSharedReference, {
|
|
25
|
+
IReadOnlySharedReference,
|
|
26
|
+
} from "../../../../utils/reference";
|
|
27
|
+
import { CancellationSignal } from "../../../../utils/task_canceller";
|
|
28
|
+
import {
|
|
29
|
+
IABREstimate,
|
|
30
|
+
IRepresentationEstimatorPlaybackObservation,
|
|
31
|
+
IRepresentationEstimator,
|
|
32
|
+
IRepresentationEstimatorCallbacks,
|
|
33
|
+
} from "../../../adaptive";
|
|
34
|
+
import { IReadOnlyPlaybackObserver } from "../../../api";
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Produce estimates to know which Representation should be played.
|
|
38
|
+
* @param {Object} content - The Manifest, Period and Adaptation wanted.
|
|
39
|
+
* @param {Object} representationEstimator - `IRepresentationEstimator` which
|
|
40
|
+
* will produce Representation estimates.
|
|
41
|
+
* @param {Object} currentRepresentation - Reference emitting the
|
|
42
|
+
* currently-loaded Representation.
|
|
43
|
+
* @param {Object} playbackObserver - Allows to observe the current playback
|
|
44
|
+
* conditions.
|
|
45
|
+
* @param {Function} onFatalError - Callback called when a fatal error was
|
|
46
|
+
* thrown. Once this callback is called, no estimate will be produced.
|
|
47
|
+
* @param {Object} cancellationSignal - `CancellationSignal` allowing to abort
|
|
48
|
+
* the production of estimates (and clean-up all linked resources).
|
|
49
|
+
* @returns {Object} - Returns an object with the following properties:
|
|
50
|
+
* - `estimateRef`: Reference emitting the last estimate
|
|
51
|
+
* - `abrCallbacks`: Callbacks allowing to report back network and playback
|
|
52
|
+
* activities to improve the estimates given.
|
|
53
|
+
*/
|
|
54
|
+
export default function getRepresentationEstimate(
|
|
55
|
+
content : { manifest : Manifest;
|
|
56
|
+
period : Period;
|
|
57
|
+
adaptation : Adaptation; },
|
|
58
|
+
representationEstimator : IRepresentationEstimator,
|
|
59
|
+
currentRepresentation : IReadOnlySharedReference<Representation | null>,
|
|
60
|
+
playbackObserver : IReadOnlyPlaybackObserver<
|
|
61
|
+
IRepresentationEstimatorPlaybackObservation
|
|
62
|
+
>,
|
|
63
|
+
onFatalError: (err : IPlayerError) => void,
|
|
64
|
+
cancellationSignal : CancellationSignal
|
|
65
|
+
) : { estimateRef : IReadOnlySharedReference<IABREstimate>;
|
|
66
|
+
abrCallbacks : IRepresentationEstimatorCallbacks; }
|
|
67
|
+
{
|
|
68
|
+
const { manifest, adaptation } = content;
|
|
69
|
+
const representations = createSharedReference<Representation[]>(
|
|
70
|
+
[],
|
|
71
|
+
cancellationSignal);
|
|
72
|
+
updateRepresentationsReference();
|
|
73
|
+
manifest.addEventListener("decipherabilityUpdate", updateRepresentationsReference);
|
|
74
|
+
const unregisterCleanUp = cancellationSignal.register(cleanUp);
|
|
75
|
+
const { estimates: estimateRef,
|
|
76
|
+
callbacks: abrCallbacks } = representationEstimator(content,
|
|
77
|
+
currentRepresentation,
|
|
78
|
+
representations,
|
|
79
|
+
playbackObserver,
|
|
80
|
+
cancellationSignal);
|
|
81
|
+
return { abrCallbacks, estimateRef };
|
|
82
|
+
|
|
83
|
+
function updateRepresentationsReference() : void {
|
|
84
|
+
/** Representations for which a `RepresentationStream` can be created. */
|
|
85
|
+
const newRepr = adaptation.getPlayableRepresentations();
|
|
86
|
+
if (newRepr.length === 0) {
|
|
87
|
+
const noRepErr = new MediaError("NO_PLAYABLE_REPRESENTATION",
|
|
88
|
+
"No Representation in the chosen " +
|
|
89
|
+
adaptation.type + " Adaptation can be played",
|
|
90
|
+
{ adaptation });
|
|
91
|
+
cleanUp();
|
|
92
|
+
onFatalError(noRepErr);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const prevRepr = representations.getValue();
|
|
97
|
+
if (prevRepr.length === newRepr.length) {
|
|
98
|
+
if (prevRepr.every((r, idx) => r.id === newRepr[idx].id)) {
|
|
99
|
+
return ;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
representations.setValue(newRepr);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** Clean-up all resources taken here. */
|
|
106
|
+
function cleanUp() : void {
|
|
107
|
+
manifest.removeEventListener("decipherabilityUpdate", updateRepresentationsReference);
|
|
108
|
+
|
|
109
|
+
// check to protect against the case where it is not yet defined.
|
|
110
|
+
if (typeof unregisterCleanUp !== "undefined") {
|
|
111
|
+
unregisterCleanUp();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|