rx-player 3.30.0-dev.2023020100 → 3.30.0-dev.2023030200
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 +5 -1
- package/VERSION +1 -1
- package/dist/_esm5.processed/compat/browser_detection.d.ts +23 -12
- package/dist/_esm5.processed/compat/browser_detection.js +80 -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/event_listeners.js +1 -1
- package/dist/_esm5.processed/config.d.ts +2 -0
- package/dist/_esm5.processed/core/adaptive/adaptive_representation_selector.js +4 -2
- 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 +199 -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 +3 -2
- package/dist/_esm5.processed/core/api/public_api.d.ts +3 -0
- package/dist/_esm5.processed/core/api/public_api.js +25 -14
- package/dist/_esm5.processed/core/api/utils.js +3 -3
- package/dist/_esm5.processed/core/decrypt/__tests__/__global__/utils.d.ts +32 -13
- 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 +33 -24
- package/dist/_esm5.processed/core/decrypt/session_events_listener.js +54 -50
- package/dist/_esm5.processed/core/decrypt/utils/check_key_statuses.js +4 -0
- 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 +1 -1
- package/dist/_esm5.processed/core/init/media_source_content_initializer.js +27 -31
- package/dist/_esm5.processed/core/init/utils/content_time_boundaries_observer.js +2 -2
- 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_duration_updater.js +23 -19
- package/dist/_esm5.processed/core/init/utils/rebuffering_controller.js +1 -1
- 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.js +7 -10
- package/dist/_esm5.processed/core/segment_buffers/implementations/text/html/html_text_segment_buffer.js +4 -2
- package/dist/_esm5.processed/core/segment_buffers/segment_buffers_store.js +13 -9
- package/dist/_esm5.processed/core/stream/adaptation/adaptation_stream.js +25 -16
- package/dist/_esm5.processed/core/stream/orchestrator/stream_orchestrator.js +26 -12
- package/dist/_esm5.processed/core/stream/period/period_stream.js +11 -10
- package/dist/_esm5.processed/core/stream/representation/representation_stream.js +15 -15
- package/dist/_esm5.processed/core/stream/representation/utils/append_segment_to_buffer.js +1 -1
- package/dist/_esm5.processed/core/stream/representation/utils/downloading_queue.js +16 -6
- package/dist/_esm5.processed/default_config.d.ts +16 -0
- package/dist/_esm5.processed/default_config.js +19 -0
- 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/prepare_source_buffer.js +7 -4
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.js +8 -4
- 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.js +4 -0
- package/dist/_esm5.processed/manifest/manifest.js +2 -0
- package/dist/_esm5.processed/manifest/representation.js +11 -4
- 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/public_types.d.ts +1 -0
- 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/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/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/rx-player.js +880 -677
- package/dist/rx-player.min.js +1 -1
- package/jest.config.js +1 -0
- package/package.json +19 -18
- package/scripts/build/constants.d.ts +1 -0
- package/scripts/report_build_sizes +4 -0
- package/sonar-project.properties +1 -1
- package/src/compat/browser_detection.ts +99 -52
- package/src/compat/can_reuse_media_keys.ts +5 -2
- package/src/compat/eme/close_session.ts +2 -2
- package/src/compat/event_listeners.ts +1 -1
- package/src/core/adaptive/adaptive_representation_selector.ts +4 -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 +204 -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 +4 -2
- package/src/core/api/public_api.ts +28 -14
- package/src/core/api/utils.ts +3 -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 +36 -35
- package/src/core/decrypt/session_events_listener.ts +57 -56
- package/src/core/decrypt/utils/check_key_statuses.ts +6 -0
- 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 +1 -1
- package/src/core/init/media_source_content_initializer.ts +37 -41
- package/src/core/init/utils/content_time_boundaries_observer.ts +2 -2
- 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 +25 -20
- package/src/core/init/utils/rebuffering_controller.ts +1 -1
- 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 +7 -11
- package/src/core/segment_buffers/implementations/text/html/html_text_segment_buffer.ts +4 -2
- package/src/core/segment_buffers/segment_buffers_store.ts +16 -13
- package/src/core/stream/adaptation/adaptation_stream.ts +28 -19
- package/src/core/stream/orchestrator/stream_orchestrator.ts +26 -12
- package/src/core/stream/period/period_stream.ts +11 -10
- package/src/core/stream/representation/representation_stream.ts +15 -15
- package/src/core/stream/representation/utils/append_segment_to_buffer.ts +1 -1
- package/src/core/stream/representation/utils/downloading_queue.ts +16 -4
- package/src/default_config.ts +30 -9
- 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/prepare_source_buffer.ts +7 -4
- package/src/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.ts +8 -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/adaptation.ts +7 -0
- package/src/manifest/manifest.ts +4 -0
- package/src/manifest/representation.ts +10 -4
- 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/public_types.ts +1 -0
- 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/segment_loader.ts +4 -4
- package/src/transports/utils/call_custom_manifest_loader.ts +3 -3
- package/src/typings/globals.d.ts +2 -0
- package/src/utils/cancellable_sleep.ts +5 -14
- package/src/utils/create_cancellable_promise.ts +69 -0
- package/src/utils/reference.ts +6 -0
- package/src/utils/request/xhr.ts +1 -1
- package/src/utils/task_canceller.ts +63 -34
|
@@ -16,19 +16,22 @@
|
|
|
16
16
|
|
|
17
17
|
import config from "../../config";
|
|
18
18
|
import { ICdnMetadata } from "../../parsers/manifest";
|
|
19
|
-
import { IPlayerError } from "../../public_types";
|
|
20
19
|
import arrayFindIndex from "../../utils/array_find_index";
|
|
21
20
|
import EventEmitter from "../../utils/event_emitter";
|
|
22
21
|
import { CancellationSignal } from "../../utils/task_canceller";
|
|
23
22
|
|
|
24
23
|
/**
|
|
25
|
-
* Class signaling the priority between multiple CDN available for
|
|
26
|
-
* resource.
|
|
24
|
+
* Class storing and signaling the priority between multiple CDN available for
|
|
25
|
+
* any given resource.
|
|
27
26
|
*
|
|
28
|
-
* This class
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
27
|
+
* This class was first created to implement the complexities behind
|
|
28
|
+
* Content Steering features, though its handling hasn't been added yet as we
|
|
29
|
+
* wait for its specification to be both standardized and relied on in the wild.
|
|
30
|
+
* In the meantime, it acts as an abstraction for the simple concept of
|
|
31
|
+
* avoiding to request a CDN for any segment when an issue is encountered with
|
|
32
|
+
* one (e.g. HTTP 500 statuses) and several CDN exist for a given resource. It
|
|
33
|
+
* should be noted that this is also one of the planified features of the
|
|
34
|
+
* Content Steering specification.
|
|
32
35
|
*
|
|
33
36
|
* @class CdnPrioritizer
|
|
34
37
|
*/
|
|
@@ -41,7 +44,7 @@ export default class CdnPrioritizer extends EventEmitter<ICdnPrioritizerEvents>
|
|
|
41
44
|
private _downgradedCdnList : {
|
|
42
45
|
/**
|
|
43
46
|
* Metadata of downgraded CDN, sorted by the time at which they have
|
|
44
|
-
* been downgraded.
|
|
47
|
+
* been downgraded ascending.
|
|
45
48
|
*/
|
|
46
49
|
metadata : ICdnMetadata[];
|
|
47
50
|
/**
|
|
@@ -174,8 +177,14 @@ export default class CdnPrioritizer extends EventEmitter<ICdnPrioritizerEvents>
|
|
|
174
177
|
}
|
|
175
178
|
}
|
|
176
179
|
|
|
180
|
+
/** Events sent by a `CdnPrioritizer` */
|
|
177
181
|
export interface ICdnPrioritizerEvents {
|
|
178
|
-
|
|
182
|
+
/**
|
|
183
|
+
* The priority of one or several CDN changed.
|
|
184
|
+
*
|
|
185
|
+
* You might want to re-check if a CDN should still be used when this event
|
|
186
|
+
* is triggered.
|
|
187
|
+
*/
|
|
179
188
|
priorityChange : null;
|
|
180
189
|
}
|
|
181
190
|
|
|
@@ -155,7 +155,7 @@ export default class ManifestFetcher extends EventEmitter<IManifestFetcherEvent>
|
|
|
155
155
|
manifestProm
|
|
156
156
|
.then((val : IManifestFetcherParsedResult) => {
|
|
157
157
|
this.trigger("manifestReady", val.manifest);
|
|
158
|
-
if (!this._canceller.isUsed) {
|
|
158
|
+
if (!this._canceller.isUsed()) {
|
|
159
159
|
this._recursivelyRefreshManifest(val.manifest, val);
|
|
160
160
|
}
|
|
161
161
|
})
|
|
@@ -362,7 +362,7 @@ export default class ManifestFetcher extends EventEmitter<IManifestFetcherEvent>
|
|
|
362
362
|
*/
|
|
363
363
|
function onWarnings(warnings : Error[]) : void {
|
|
364
364
|
for (const warning of warnings) {
|
|
365
|
-
if (cancelSignal.isCancelled) {
|
|
365
|
+
if (cancelSignal.isCancelled()) {
|
|
366
366
|
return;
|
|
367
367
|
}
|
|
368
368
|
const formattedError = formatError(warning, {
|
|
@@ -470,7 +470,8 @@ export default class ManifestFetcher extends EventEmitter<IManifestFetcherEvent>
|
|
|
470
470
|
* be effectively considered.
|
|
471
471
|
* `nextRefreshCanceller` will allow to cancel every other when one is triggered.
|
|
472
472
|
*/
|
|
473
|
-
const nextRefreshCanceller = new TaskCanceller(
|
|
473
|
+
const nextRefreshCanceller = new TaskCanceller();
|
|
474
|
+
nextRefreshCanceller.linkToSignal(this._canceller.signal);
|
|
474
475
|
|
|
475
476
|
/* Function to manually schedule a Manifest refresh */
|
|
476
477
|
this.scheduleManualRefresh = (settings : IManifestRefreshSettings) => {
|
|
@@ -669,7 +670,7 @@ export default class ManifestFetcher extends EventEmitter<IManifestFetcherEvent>
|
|
|
669
670
|
}
|
|
670
671
|
|
|
671
672
|
private _onFatalError(err : unknown) : void {
|
|
672
|
-
if (this._canceller.isUsed) {
|
|
673
|
+
if (this._canceller.isUsed()) {
|
|
673
674
|
return;
|
|
674
675
|
}
|
|
675
676
|
this.trigger("error", err);
|
|
@@ -64,10 +64,22 @@ const generateRequestID = idGenerator();
|
|
|
64
64
|
* An `ISegmentFetcher` also implements a retry mechanism, based on the given
|
|
65
65
|
* `options` argument, which may retry a segment request when it fails.
|
|
66
66
|
*
|
|
67
|
-
* @param {string} bufferType
|
|
68
|
-
*
|
|
69
|
-
* @param {Object}
|
|
70
|
-
*
|
|
67
|
+
* @param {string} bufferType - Type of buffer concerned (e.g. `"audio"`,
|
|
68
|
+
* `"video"`, `"text" etc.)
|
|
69
|
+
* @param {Object} pipeline - The transport-specific logic allowing to load
|
|
70
|
+
* segments of the given buffer type and transport protocol (e.g. DASH).
|
|
71
|
+
* @param {Object|null} cdnPrioritizer - Abstraction allowing to synchronize,
|
|
72
|
+
* update and keep track of the priorization of the CDN to use to load any given
|
|
73
|
+
* segment, in cases where multiple ones are available.
|
|
74
|
+
*
|
|
75
|
+
* Can be set to `null` in which case a minimal priorization logic will be used
|
|
76
|
+
* instead.
|
|
77
|
+
* @param {Object} lifecycleCallbacks - Callbacks that can be registered to be
|
|
78
|
+
* informed when new requests are made, ended, new metrics are available etc.
|
|
79
|
+
* This should be mainly useful to implement an adaptive logic relying on those
|
|
80
|
+
* metrics and events.
|
|
81
|
+
* @param {Object} options - Various tweaking options allowing to configure the
|
|
82
|
+
* behavior of the returned `ISegmentFetcher`.
|
|
71
83
|
* @returns {Function}
|
|
72
84
|
*/
|
|
73
85
|
export default function createSegmentFetcher<TLoadedFormat, TSegmentDataType>(
|
|
@@ -184,14 +196,7 @@ export default function createSegmentFetcher<TLoadedFormat, TSegmentDataType>(
|
|
|
184
196
|
id: requestId,
|
|
185
197
|
content });
|
|
186
198
|
|
|
187
|
-
cancellationSignal.register(
|
|
188
|
-
if (requestInfo !== undefined) {
|
|
189
|
-
return; // Request already terminated
|
|
190
|
-
}
|
|
191
|
-
log.debug("SF: Segment request cancelled", segmentIdString);
|
|
192
|
-
requestInfo = null;
|
|
193
|
-
lifecycleCallbacks.onRequestEnd?.({ id: requestId });
|
|
194
|
-
});
|
|
199
|
+
cancellationSignal.register(onCancellation);
|
|
195
200
|
|
|
196
201
|
try {
|
|
197
202
|
const res = await scheduleRequestWithCdns(content.representation.cdnMetadata,
|
|
@@ -220,22 +225,34 @@ export default function createSegmentFetcher<TLoadedFormat, TSegmentDataType>(
|
|
|
220
225
|
requestInfo = null;
|
|
221
226
|
}
|
|
222
227
|
|
|
223
|
-
if (!cancellationSignal.isCancelled) {
|
|
228
|
+
if (!cancellationSignal.isCancelled()) {
|
|
224
229
|
// The current task could have been canceled as a result of one
|
|
225
230
|
// of the previous callbacks call. In that case, we don't want to send
|
|
226
231
|
// a "requestEnd" again as it has already been sent on cancellation.
|
|
227
232
|
lifecycleCallbacks.onRequestEnd?.({ id: requestId });
|
|
228
233
|
}
|
|
234
|
+
cancellationSignal.deregister(onCancellation);
|
|
229
235
|
} catch (err) {
|
|
236
|
+
cancellationSignal.deregister(onCancellation);
|
|
230
237
|
requestInfo = null;
|
|
231
238
|
if (err instanceof CancellationError) {
|
|
232
239
|
log.debug("SF: Segment request aborted", segmentIdString);
|
|
233
240
|
throw err;
|
|
234
241
|
}
|
|
235
242
|
log.debug("SF: Segment request failed", segmentIdString);
|
|
243
|
+
lifecycleCallbacks.onRequestEnd?.({ id: requestId });
|
|
236
244
|
throw errorSelector(err);
|
|
237
245
|
}
|
|
238
246
|
|
|
247
|
+
function onCancellation() {
|
|
248
|
+
if (requestInfo !== undefined) {
|
|
249
|
+
return; // Request already terminated
|
|
250
|
+
}
|
|
251
|
+
log.debug("SF: Segment request cancelled", segmentIdString);
|
|
252
|
+
requestInfo = null;
|
|
253
|
+
lifecycleCallbacks.onRequestEnd?.({ id: requestId });
|
|
254
|
+
}
|
|
255
|
+
|
|
239
256
|
/**
|
|
240
257
|
* Call a segment loader for the given URL with the right arguments.
|
|
241
258
|
* @param {Object|null} cdnMetadata
|
|
@@ -360,11 +377,16 @@ export interface ISegmentFetcherCallbacks<TSegmentDataType> {
|
|
|
360
377
|
/**
|
|
361
378
|
* Callback called when all decodable chunks of the loaded segment have been
|
|
362
379
|
* communicated through the `onChunk` callback.
|
|
380
|
+
*
|
|
381
|
+
* This callback is called before the corresponding `ISegmentFetcher`'s
|
|
382
|
+
* returned Promise is resolved.
|
|
363
383
|
*/
|
|
364
384
|
onAllChunksReceived() : void;
|
|
365
385
|
|
|
366
386
|
/**
|
|
367
|
-
* Callback called when the segment request has to restart from scratch.
|
|
387
|
+
* Callback called when the segment request has to restart from scratch, e.g.
|
|
388
|
+
* due to a request error.
|
|
389
|
+
*/
|
|
368
390
|
onRetry(error : IPlayerError) : void;
|
|
369
391
|
}
|
|
370
392
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import log from "../../../log";
|
|
2
2
|
import arrayFindIndex from "../../../utils/array_find_index";
|
|
3
|
+
import createCancellablePromise from "../../../utils/create_cancellable_promise";
|
|
3
4
|
import TaskCanceller, {
|
|
4
5
|
CancellationError,
|
|
5
6
|
CancellationSignal,
|
|
@@ -64,19 +65,34 @@ export default class TaskPrioritizer<T> {
|
|
|
64
65
|
cancelSignal: CancellationSignal
|
|
65
66
|
): Promise<T> {
|
|
66
67
|
let newTask: IPrioritizerTask<T>;
|
|
67
|
-
|
|
68
|
-
return new Promise<T>((resolve, reject) => {
|
|
68
|
+
return createCancellablePromise<T>(cancelSignal, (resolve, reject) => {
|
|
69
69
|
/** Function allowing to start the underlying Promise. */
|
|
70
70
|
const trigger = () => {
|
|
71
71
|
if (newTask.hasEnded) {
|
|
72
|
-
unregisterCancelSignal();
|
|
73
72
|
return;
|
|
74
73
|
}
|
|
75
|
-
const
|
|
74
|
+
const finishTask = () => {
|
|
75
|
+
unlinkInterrupter();
|
|
76
|
+
this._endTask(newTask);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const onResolve = (value: T) => {
|
|
80
|
+
callbacks.beforeEnded();
|
|
81
|
+
finishTask();
|
|
82
|
+
resolve(value);
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const onReject = (err: unknown) => {
|
|
86
|
+
finishTask();
|
|
87
|
+
reject(err);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const interrupter = new TaskCanceller();
|
|
91
|
+
const unlinkInterrupter = interrupter.linkToSignal(cancelSignal);
|
|
76
92
|
newTask.interrupter = interrupter;
|
|
77
93
|
interrupter.signal.register(() => {
|
|
78
94
|
newTask.interrupter = null;
|
|
79
|
-
if (!cancelSignal.isCancelled) {
|
|
95
|
+
if (!cancelSignal.isCancelled()) {
|
|
80
96
|
callbacks.beforeInterrupted();
|
|
81
97
|
}
|
|
82
98
|
});
|
|
@@ -89,8 +105,8 @@ export default class TaskPrioritizer<T> {
|
|
|
89
105
|
newTask.taskFn(interrupter.signal)
|
|
90
106
|
.then(onResolve)
|
|
91
107
|
.catch((err) => {
|
|
92
|
-
if (!cancelSignal.isCancelled &&
|
|
93
|
-
interrupter.isUsed &&
|
|
108
|
+
if (!cancelSignal.isCancelled() &&
|
|
109
|
+
interrupter.isUsed() &&
|
|
94
110
|
err instanceof CancellationError)
|
|
95
111
|
{
|
|
96
112
|
return;
|
|
@@ -99,29 +115,6 @@ export default class TaskPrioritizer<T> {
|
|
|
99
115
|
});
|
|
100
116
|
};
|
|
101
117
|
|
|
102
|
-
const unregisterCancelSignal = cancelSignal.register(
|
|
103
|
-
(cancellationError: CancellationError) => {
|
|
104
|
-
this._endTask(newTask);
|
|
105
|
-
reject(cancellationError);
|
|
106
|
-
}
|
|
107
|
-
);
|
|
108
|
-
|
|
109
|
-
const finishTask = () => {
|
|
110
|
-
unregisterCancelSignal();
|
|
111
|
-
this._endTask(newTask);
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
const onResolve = (value: T) => {
|
|
115
|
-
callbacks.beforeEnded();
|
|
116
|
-
finishTask();
|
|
117
|
-
resolve(value);
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
const onReject = (err: unknown) => {
|
|
121
|
-
finishTask();
|
|
122
|
-
reject(err);
|
|
123
|
-
};
|
|
124
|
-
|
|
125
118
|
newTask = {
|
|
126
119
|
hasEnded: false,
|
|
127
120
|
priority,
|
|
@@ -146,6 +139,8 @@ export default class TaskPrioritizer<T> {
|
|
|
146
139
|
this._interruptCancellableTasks();
|
|
147
140
|
}
|
|
148
141
|
}
|
|
142
|
+
|
|
143
|
+
return () => this._endTask(newTask);
|
|
149
144
|
});
|
|
150
145
|
}
|
|
151
146
|
|
|
@@ -315,7 +315,7 @@ export async function scheduleRequestWithCdns<T>(
|
|
|
315
315
|
async function retryWithNextCdn(prevRequestError : unknown) : Promise<T> {
|
|
316
316
|
const nextCdn = getCdnToRequest();
|
|
317
317
|
|
|
318
|
-
if (cancellationSignal.isCancelled) {
|
|
318
|
+
if (cancellationSignal.isCancelled()) {
|
|
319
319
|
throw cancellationSignal.cancellationError;
|
|
320
320
|
}
|
|
321
321
|
|
|
@@ -324,7 +324,7 @@ export async function scheduleRequestWithCdns<T>(
|
|
|
324
324
|
}
|
|
325
325
|
|
|
326
326
|
onRetry(prevRequestError);
|
|
327
|
-
if (cancellationSignal.isCancelled) {
|
|
327
|
+
if (cancellationSignal.isCancelled()) {
|
|
328
328
|
throw cancellationSignal.cancellationError;
|
|
329
329
|
}
|
|
330
330
|
|
|
@@ -358,26 +358,37 @@ export async function scheduleRequestWithCdns<T>(
|
|
|
358
358
|
return requestCdn(nextWantedCdn);
|
|
359
359
|
}
|
|
360
360
|
|
|
361
|
-
const canceller = new TaskCanceller(
|
|
361
|
+
const canceller = new TaskCanceller();
|
|
362
|
+
const unlinkCanceller = canceller.linkToSignal(cancellationSignal);
|
|
362
363
|
return new Promise<T>((res, rej) => {
|
|
363
364
|
/* eslint-disable-next-line @typescript-eslint/no-misused-promises */
|
|
364
365
|
cdnPrioritizer?.addEventListener("priorityChange", () => {
|
|
365
366
|
const updatedPrioritaryCdn = getCdnToRequest();
|
|
366
|
-
if (cancellationSignal.isCancelled) {
|
|
367
|
+
if (cancellationSignal.isCancelled()) {
|
|
367
368
|
throw cancellationSignal.cancellationError;
|
|
368
369
|
}
|
|
369
370
|
if (updatedPrioritaryCdn === undefined) {
|
|
370
|
-
return
|
|
371
|
+
return cleanAndReject(prevRequestError);
|
|
371
372
|
}
|
|
372
373
|
if (updatedPrioritaryCdn !== nextWantedCdn) {
|
|
373
374
|
canceller.cancel();
|
|
374
375
|
waitPotentialBackoffAndRequest(updatedPrioritaryCdn, prevRequestError)
|
|
375
|
-
.then(
|
|
376
|
+
.then(cleanAndResolve, cleanAndReject);
|
|
376
377
|
}
|
|
377
378
|
}, canceller.signal);
|
|
378
379
|
|
|
379
380
|
cancellableSleep(blockedFor, canceller.signal)
|
|
380
|
-
.then(() => requestCdn(nextWantedCdn)
|
|
381
|
+
.then(() => requestCdn(nextWantedCdn)
|
|
382
|
+
.then(cleanAndResolve, cleanAndReject), noop);
|
|
383
|
+
|
|
384
|
+
function cleanAndResolve(response : T) {
|
|
385
|
+
unlinkCanceller();
|
|
386
|
+
res(response);
|
|
387
|
+
}
|
|
388
|
+
function cleanAndReject(err : unknown) {
|
|
389
|
+
unlinkCanceller();
|
|
390
|
+
rej(err);
|
|
391
|
+
}
|
|
381
392
|
});
|
|
382
393
|
}
|
|
383
394
|
|
|
@@ -167,7 +167,7 @@ export default class DirectFileContentInitializer extends ContentInitializer {
|
|
|
167
167
|
}
|
|
168
168
|
}, { emitCurrentValue: true, clearSignal: cancelSignal }))
|
|
169
169
|
.catch((err) => {
|
|
170
|
-
if (!cancelSignal.isCancelled) {
|
|
170
|
+
if (!cancelSignal.isCancelled()) {
|
|
171
171
|
this._onFatalError(err);
|
|
172
172
|
}
|
|
173
173
|
});
|
|
@@ -25,13 +25,13 @@ import {
|
|
|
25
25
|
} from "../../public_types";
|
|
26
26
|
import { ITransportPipelines } from "../../transports";
|
|
27
27
|
import assert from "../../utils/assert";
|
|
28
|
+
import createCancellablePromise from "../../utils/create_cancellable_promise";
|
|
28
29
|
import objectAssign from "../../utils/object_assign";
|
|
29
30
|
import createSharedReference, {
|
|
30
31
|
IReadOnlySharedReference,
|
|
31
32
|
ISharedReference,
|
|
32
33
|
} from "../../utils/reference";
|
|
33
34
|
import TaskCanceller, {
|
|
34
|
-
CancellationError,
|
|
35
35
|
CancellationSignal,
|
|
36
36
|
} from "../../utils/task_canceller";
|
|
37
37
|
import AdaptiveRepresentationSelector, {
|
|
@@ -125,21 +125,22 @@ export default class MediaSourceContentInitializer extends ContentInitializer {
|
|
|
125
125
|
if (this._initialManifestProm !== null) {
|
|
126
126
|
return;
|
|
127
127
|
}
|
|
128
|
-
this._initialManifestProm =
|
|
129
|
-
this._initCanceller.signal
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
res(manifest);
|
|
128
|
+
this._initialManifestProm = createCancellablePromise(
|
|
129
|
+
this._initCanceller.signal,
|
|
130
|
+
(res, rej) => {
|
|
131
|
+
this._manifestFetcher.addEventListener("warning", (err : IPlayerError) =>
|
|
132
|
+
this.trigger("warning", err));
|
|
133
|
+
this._manifestFetcher.addEventListener("error", (err : unknown) => {
|
|
134
|
+
this.trigger("error", err);
|
|
135
|
+
rej(err);
|
|
136
|
+
});
|
|
137
|
+
this._manifestFetcher.addEventListener("manifestReady", (manifest) => {
|
|
138
|
+
res(manifest);
|
|
139
|
+
});
|
|
141
140
|
});
|
|
142
|
-
|
|
141
|
+
this._manifestFetcher.start();
|
|
142
|
+
this._initCanceller.signal.register(() => {
|
|
143
|
+
this._manifestFetcher.dispose();
|
|
143
144
|
});
|
|
144
145
|
}
|
|
145
146
|
|
|
@@ -192,7 +193,7 @@ export default class MediaSourceContentInitializer extends ContentInitializer {
|
|
|
192
193
|
}
|
|
193
194
|
|
|
194
195
|
private _onFatalError(err : unknown) {
|
|
195
|
-
if (this._initCanceller.isUsed) {
|
|
196
|
+
if (this._initCanceller.isUsed()) {
|
|
196
197
|
return;
|
|
197
198
|
}
|
|
198
199
|
this._initCanceller.cancel();
|
|
@@ -206,13 +207,9 @@ export default class MediaSourceContentInitializer extends ContentInitializer {
|
|
|
206
207
|
drmSystemId : string | undefined;
|
|
207
208
|
unlinkMediaSource : TaskCanceller; }>
|
|
208
209
|
{
|
|
209
|
-
|
|
210
|
+
const initCanceller = this._initCanceller;
|
|
211
|
+
return createCancellablePromise(initCanceller.signal, (resolve) => {
|
|
210
212
|
const { keySystems } = this._settings;
|
|
211
|
-
const initCanceller = this._initCanceller;
|
|
212
|
-
|
|
213
|
-
const unregisterReject = initCanceller.signal.register((err) => {
|
|
214
|
-
reject(err);
|
|
215
|
-
});
|
|
216
213
|
|
|
217
214
|
/** Initialize decryption capabilities. */
|
|
218
215
|
const drmInitRef =
|
|
@@ -227,9 +224,8 @@ export default class MediaSourceContentInitializer extends ContentInitializer {
|
|
|
227
224
|
}
|
|
228
225
|
stopListeningToDrmUpdates();
|
|
229
226
|
|
|
230
|
-
const mediaSourceCanceller = new TaskCanceller(
|
|
231
|
-
|
|
232
|
-
});
|
|
227
|
+
const mediaSourceCanceller = new TaskCanceller();
|
|
228
|
+
mediaSourceCanceller.linkToSignal(initCanceller.signal);
|
|
233
229
|
openMediaSource(mediaElement, mediaSourceCanceller.signal)
|
|
234
230
|
.then((mediaSource) => {
|
|
235
231
|
const lastDrmStatus = drmInitRef.getValue();
|
|
@@ -238,7 +234,6 @@ export default class MediaSourceContentInitializer extends ContentInitializer {
|
|
|
238
234
|
drmInitRef.onUpdate((newDrmStatus, stopListeningToDrmUpdatesAgain) => {
|
|
239
235
|
if (newDrmStatus.initializationState.type === "initialized") {
|
|
240
236
|
stopListeningToDrmUpdatesAgain();
|
|
241
|
-
unregisterReject();
|
|
242
237
|
resolve({ mediaSource,
|
|
243
238
|
drmSystemId: newDrmStatus.drmSystemId,
|
|
244
239
|
unlinkMediaSource: mediaSourceCanceller });
|
|
@@ -246,7 +241,6 @@ export default class MediaSourceContentInitializer extends ContentInitializer {
|
|
|
246
241
|
}
|
|
247
242
|
}, { emitCurrentValue: true, clearSignal: initCanceller.signal });
|
|
248
243
|
} else if (drmStatus.initializationState.type === "initialized") {
|
|
249
|
-
unregisterReject();
|
|
250
244
|
resolve({ mediaSource,
|
|
251
245
|
drmSystemId: drmStatus.drmSystemId,
|
|
252
246
|
unlinkMediaSource: mediaSourceCanceller });
|
|
@@ -254,7 +248,7 @@ export default class MediaSourceContentInitializer extends ContentInitializer {
|
|
|
254
248
|
}
|
|
255
249
|
})
|
|
256
250
|
.catch((err) => {
|
|
257
|
-
if (mediaSourceCanceller.isUsed) {
|
|
251
|
+
if (mediaSourceCanceller.isUsed()) {
|
|
258
252
|
return;
|
|
259
253
|
}
|
|
260
254
|
this._onFatalError(err);
|
|
@@ -311,7 +305,7 @@ export default class MediaSourceContentInitializer extends ContentInitializer {
|
|
|
311
305
|
initCanceller.signal);
|
|
312
306
|
|
|
313
307
|
this.trigger("manifestReady", manifest);
|
|
314
|
-
if (initCanceller.isUsed) {
|
|
308
|
+
if (initCanceller.isUsed()) {
|
|
315
309
|
return ;
|
|
316
310
|
}
|
|
317
311
|
|
|
@@ -359,15 +353,16 @@ export default class MediaSourceContentInitializer extends ContentInitializer {
|
|
|
359
353
|
autoPlay : boolean; }
|
|
360
354
|
) : void {
|
|
361
355
|
currentCanceller.cancel();
|
|
362
|
-
if (initCanceller.isUsed) {
|
|
356
|
+
if (initCanceller.isUsed()) {
|
|
363
357
|
return;
|
|
364
358
|
}
|
|
365
359
|
triggerEvent("reloadingMediaSource", null);
|
|
366
|
-
if (initCanceller.isUsed) {
|
|
360
|
+
if (initCanceller.isUsed()) {
|
|
367
361
|
return;
|
|
368
362
|
}
|
|
369
363
|
|
|
370
|
-
const newCanceller = new TaskCanceller(
|
|
364
|
+
const newCanceller = new TaskCanceller();
|
|
365
|
+
newCanceller.linkToSignal(initCanceller.signal);
|
|
371
366
|
openMediaSource(mediaElement, newCanceller.signal)
|
|
372
367
|
.then(newMediaSource => {
|
|
373
368
|
recursivelyLoadOnMediaSource(newMediaSource,
|
|
@@ -376,7 +371,7 @@ export default class MediaSourceContentInitializer extends ContentInitializer {
|
|
|
376
371
|
newCanceller);
|
|
377
372
|
})
|
|
378
373
|
.catch((err) => {
|
|
379
|
-
if (newCanceller.isUsed) {
|
|
374
|
+
if (newCanceller.isUsed()) {
|
|
380
375
|
return;
|
|
381
376
|
}
|
|
382
377
|
onFatalError(err);
|
|
@@ -431,7 +426,7 @@ export default class MediaSourceContentInitializer extends ContentInitializer {
|
|
|
431
426
|
(err) => this.trigger("warning", err),
|
|
432
427
|
cancelSignal);
|
|
433
428
|
|
|
434
|
-
if (cancelSignal.isCancelled) {
|
|
429
|
+
if (cancelSignal.isCancelled()) {
|
|
435
430
|
return;
|
|
436
431
|
}
|
|
437
432
|
|
|
@@ -483,7 +478,7 @@ export default class MediaSourceContentInitializer extends ContentInitializer {
|
|
|
483
478
|
}, { emitCurrentValue: true, clearSignal: cancelSignal });
|
|
484
479
|
})
|
|
485
480
|
.catch((err) => {
|
|
486
|
-
if (cancelSignal.isCancelled) {
|
|
481
|
+
if (cancelSignal.isCancelled()) {
|
|
487
482
|
return; // Current loading cancelled, no need to trigger the error
|
|
488
483
|
}
|
|
489
484
|
this._onFatalError(err);
|
|
@@ -519,7 +514,7 @@ export default class MediaSourceContentInitializer extends ContentInitializer {
|
|
|
519
514
|
discontinuity: imminentDiscontinuity,
|
|
520
515
|
position,
|
|
521
516
|
});
|
|
522
|
-
if (cancelSignal.isCancelled) {
|
|
517
|
+
if (cancelSignal.isCancelled()) {
|
|
523
518
|
return; // Previous call has stopped streams due to a side-effect
|
|
524
519
|
}
|
|
525
520
|
|
|
@@ -560,7 +555,7 @@ export default class MediaSourceContentInitializer extends ContentInitializer {
|
|
|
560
555
|
|
|
561
556
|
adaptationChange: (value) => {
|
|
562
557
|
self.trigger("adaptationChange", value);
|
|
563
|
-
if (cancelSignal.isCancelled) {
|
|
558
|
+
if (cancelSignal.isCancelled()) {
|
|
564
559
|
return; // Previous call has stopped streams due to a side-effect
|
|
565
560
|
}
|
|
566
561
|
contentTimeBoundariesObserver.onAdaptationChange(value.type,
|
|
@@ -570,7 +565,7 @@ export default class MediaSourceContentInitializer extends ContentInitializer {
|
|
|
570
565
|
|
|
571
566
|
representationChange: (value) => {
|
|
572
567
|
self.trigger("representationChange", value);
|
|
573
|
-
if (cancelSignal.isCancelled) {
|
|
568
|
+
if (cancelSignal.isCancelled()) {
|
|
574
569
|
return; // Previous call has stopped streams due to a side-effect
|
|
575
570
|
}
|
|
576
571
|
contentTimeBoundariesObserver.onRepresentationChange(value.type, value.period);
|
|
@@ -584,7 +579,7 @@ export default class MediaSourceContentInitializer extends ContentInitializer {
|
|
|
584
579
|
|
|
585
580
|
periodStreamCleared: (value) => {
|
|
586
581
|
contentTimeBoundariesObserver.onPeriodCleared(value.type, value.period);
|
|
587
|
-
if (cancelSignal.isCancelled) {
|
|
582
|
+
if (cancelSignal.isCancelled()) {
|
|
588
583
|
return; // Previous call has stopped streams due to a side-effect
|
|
589
584
|
}
|
|
590
585
|
self.trigger("periodStreamCleared", value);
|
|
@@ -615,7 +610,7 @@ export default class MediaSourceContentInitializer extends ContentInitializer {
|
|
|
615
610
|
encryptionDataEncountered: (value) => {
|
|
616
611
|
for (const protectionData of value) {
|
|
617
612
|
protectionRef.setValue(protectionData);
|
|
618
|
-
if (cancelSignal.isCancelled) {
|
|
613
|
+
if (cancelSignal.isCancelled()) {
|
|
619
614
|
return; // Previous call has stopped streams due to a side-effect
|
|
620
615
|
}
|
|
621
616
|
}
|
|
@@ -674,7 +669,8 @@ export default class MediaSourceContentInitializer extends ContentInitializer {
|
|
|
674
669
|
});
|
|
675
670
|
contentTimeBoundariesObserver.addEventListener("endOfStream", () => {
|
|
676
671
|
if (endOfStreamCanceller === null) {
|
|
677
|
-
endOfStreamCanceller = new TaskCanceller(
|
|
672
|
+
endOfStreamCanceller = new TaskCanceller();
|
|
673
|
+
endOfStreamCanceller.linkToSignal(cancelSignal);
|
|
678
674
|
log.debug("Init: end-of-stream order received.");
|
|
679
675
|
maintainEndOfStream(mediaSource, endOfStreamCanceller.signal);
|
|
680
676
|
}
|
|
@@ -112,7 +112,7 @@ export default class ContentTimeBoundariesObserver
|
|
|
112
112
|
|
|
113
113
|
manifest.addEventListener("manifestUpdate", () => {
|
|
114
114
|
this.trigger("durationUpdate", getManifestDuration());
|
|
115
|
-
if (cancelSignal.isCancelled) {
|
|
115
|
+
if (cancelSignal.isCancelled()) {
|
|
116
116
|
return;
|
|
117
117
|
}
|
|
118
118
|
this._checkEndOfStream();
|
|
@@ -161,7 +161,7 @@ export default class ContentTimeBoundariesObserver
|
|
|
161
161
|
}
|
|
162
162
|
}
|
|
163
163
|
}
|
|
164
|
-
if (this._canceller.isUsed) {
|
|
164
|
+
if (this._canceller.isUsed()) {
|
|
165
165
|
return;
|
|
166
166
|
}
|
|
167
167
|
if (adaptation === null) {
|
|
@@ -21,10 +21,9 @@ import {
|
|
|
21
21
|
} from "../../../compat";
|
|
22
22
|
import { MediaError } from "../../../errors";
|
|
23
23
|
import log from "../../../log";
|
|
24
|
+
import createCancellablePromise from "../../../utils/create_cancellable_promise";
|
|
24
25
|
import isNonEmptyString from "../../../utils/is_non_empty_string";
|
|
25
|
-
import
|
|
26
|
-
CancellationSignal,
|
|
27
|
-
} from "../../../utils/task_canceller";
|
|
26
|
+
import { CancellationSignal } from "../../../utils/task_canceller";
|
|
28
27
|
|
|
29
28
|
/**
|
|
30
29
|
* Dispose of ressources taken by the MediaSource:
|
|
@@ -128,21 +127,10 @@ export default function openMediaSource(
|
|
|
128
127
|
mediaElement : HTMLMediaElement,
|
|
129
128
|
unlinkSignal : CancellationSignal
|
|
130
129
|
) : Promise<MediaSource> {
|
|
131
|
-
return
|
|
132
|
-
let hasResolved = false;
|
|
130
|
+
return createCancellablePromise(unlinkSignal, (resolve) => {
|
|
133
131
|
const mediaSource = createMediaSource(mediaElement, unlinkSignal);
|
|
134
|
-
const eventListenerCanceller = new TaskCanceller({ cancelOn: unlinkSignal });
|
|
135
|
-
|
|
136
132
|
events.onSourceOpen(mediaSource, () => {
|
|
137
|
-
eventListenerCanceller.cancel();
|
|
138
|
-
hasResolved = true;
|
|
139
133
|
resolve(mediaSource);
|
|
140
|
-
},
|
|
141
|
-
|
|
142
|
-
unlinkSignal.register((error) => {
|
|
143
|
-
if (!hasResolved) {
|
|
144
|
-
reject(error);
|
|
145
|
-
}
|
|
146
|
-
});
|
|
134
|
+
}, unlinkSignal);
|
|
147
135
|
});
|
|
148
136
|
}
|
|
@@ -70,7 +70,8 @@ export default function triggerEndOfStream(
|
|
|
70
70
|
|
|
71
71
|
log.debug("Init: Waiting SourceBuffers to be updated before calling endOfStream.");
|
|
72
72
|
|
|
73
|
-
const innerCanceller = new TaskCanceller(
|
|
73
|
+
const innerCanceller = new TaskCanceller();
|
|
74
|
+
innerCanceller.linkToSignal(cancelSignal);
|
|
74
75
|
for (const sourceBuffer of updatingSourceBuffers) {
|
|
75
76
|
onSourceBufferUpdate(sourceBuffer, () => {
|
|
76
77
|
innerCanceller.cancel();
|
|
@@ -94,10 +95,12 @@ export function maintainEndOfStream(
|
|
|
94
95
|
mediaSource : MediaSource,
|
|
95
96
|
cancelSignal : CancellationSignal
|
|
96
97
|
) : void {
|
|
97
|
-
let endOfStreamCanceller = new TaskCanceller(
|
|
98
|
+
let endOfStreamCanceller = new TaskCanceller();
|
|
99
|
+
endOfStreamCanceller.linkToSignal(cancelSignal);
|
|
98
100
|
onSourceOpen(mediaSource, () => {
|
|
99
101
|
endOfStreamCanceller.cancel();
|
|
100
|
-
endOfStreamCanceller = new TaskCanceller(
|
|
102
|
+
endOfStreamCanceller = new TaskCanceller();
|
|
103
|
+
endOfStreamCanceller.linkToSignal(cancelSignal);
|
|
101
104
|
triggerEndOfStream(mediaSource, endOfStreamCanceller.signal);
|
|
102
105
|
}, cancelSignal);
|
|
103
106
|
triggerEndOfStream(mediaSource, endOfStreamCanceller.signal);
|
|
@@ -43,7 +43,8 @@ export default function getLoadedReference(
|
|
|
43
43
|
isDirectfile : boolean,
|
|
44
44
|
cancelSignal : CancellationSignal
|
|
45
45
|
) : IReadOnlySharedReference<boolean> {
|
|
46
|
-
const listenCanceller = new TaskCanceller(
|
|
46
|
+
const listenCanceller = new TaskCanceller();
|
|
47
|
+
listenCanceller.linkToSignal(cancelSignal);
|
|
47
48
|
const isLoaded = createSharedReference(false, listenCanceller.signal);
|
|
48
49
|
playbackObserver.listen((observation) => {
|
|
49
50
|
if (observation.rebuffering !== null ||
|