rx-player 3.29.0-dev.2022090500 → 3.29.0-dev.2022091600
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/CHANGELOG.md +5 -1
- package/VERSION +1 -1
- package/dist/_esm5.processed/core/api/option_utils.js +7 -11
- package/dist/_esm5.processed/core/api/public_api.d.ts +4 -4
- package/dist/_esm5.processed/core/api/public_api.js +18 -19
- package/dist/_esm5.processed/core/api/{media_element_track_choice_manager.d.ts → tracks_management/media_element_track_choice_manager.d.ts} +2 -2
- package/dist/_esm5.processed/core/api/{media_element_track_choice_manager.js → tracks_management/media_element_track_choice_manager.js} +7 -4
- package/dist/_esm5.processed/core/api/{track_choice_manager.d.ts → tracks_management/track_choice_manager.d.ts} +2 -2
- package/dist/_esm5.processed/core/api/{track_choice_manager.js → tracks_management/track_choice_manager.js} +7 -7
- package/dist/_esm5.processed/core/api/{emit_seek_events.d.ts → utils.d.ts} +24 -1
- package/dist/_esm5.processed/core/api/{emit_seek_events.js → utils.js} +32 -1
- package/dist/_esm5.processed/core/decrypt/content_decryptor.d.ts +26 -0
- package/dist/_esm5.processed/core/decrypt/content_decryptor.js +101 -9
- package/dist/_esm5.processed/core/decrypt/session_events_listener.d.ts +15 -18
- package/dist/_esm5.processed/core/decrypt/session_events_listener.js +9 -7
- package/dist/_esm5.processed/core/decrypt/utils/check_key_statuses.d.ts +19 -22
- package/dist/_esm5.processed/core/decrypt/utils/check_key_statuses.js +87 -16
- package/dist/_esm5.processed/core/decrypt/utils/persistent_sessions_store.d.ts +1 -2
- package/dist/_esm5.processed/core/decrypt/utils/persistent_sessions_store.js +1 -2
- package/dist/_esm5.processed/core/fetchers/index.d.ts +2 -2
- package/dist/_esm5.processed/core/fetchers/segment/index.d.ts +2 -3
- package/dist/_esm5.processed/core/fetchers/segment/prioritized_segment_fetcher.d.ts +9 -9
- package/dist/_esm5.processed/core/fetchers/segment/prioritized_segment_fetcher.js +17 -15
- package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher.d.ts +33 -40
- package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher.js +156 -153
- package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher_creator.d.ts +3 -3
- package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher_creator.js +2 -2
- package/dist/_esm5.processed/core/fetchers/segment/task_prioritizer.d.ts +145 -0
- package/dist/_esm5.processed/core/fetchers/segment/task_prioritizer.js +325 -0
- package/dist/_esm5.processed/core/fetchers/utils/try_urls_with_backoff.d.ts +2 -2
- package/dist/_esm5.processed/core/fetchers/utils/try_urls_with_backoff.js +3 -3
- package/dist/_esm5.processed/core/init/create_media_source.d.ts +10 -0
- package/dist/_esm5.processed/core/init/create_media_source.js +1 -1
- package/dist/_esm5.processed/core/init/stall_avoider.d.ts +2 -1
- package/dist/_esm5.processed/core/init/stall_avoider.js +2 -1
- package/dist/_esm5.processed/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.js +1 -1
- package/dist/_esm5.processed/core/segment_buffers/implementations/text/html/html_text_segment_buffer.js +3 -3
- package/dist/_esm5.processed/core/segment_buffers/implementations/types.d.ts +6 -2
- package/dist/_esm5.processed/core/stream/orchestrator/{get_blacklisted_ranges.d.ts → get_time_ranges_for_content.d.ts} +1 -1
- package/dist/_esm5.processed/core/stream/orchestrator/{get_blacklisted_ranges.js → get_time_ranges_for_content.js} +1 -1
- package/dist/_esm5.processed/core/stream/orchestrator/stream_orchestrator.js +61 -19
- package/dist/_esm5.processed/core/stream/representation/downloading_queue.d.ts +8 -4
- package/dist/_esm5.processed/core/stream/representation/downloading_queue.js +200 -83
- package/dist/_esm5.processed/core/stream/types.d.ts +3 -1
- package/dist/_esm5.processed/errors/encrypted_media_error.d.ts +6 -1
- package/dist/_esm5.processed/errors/encrypted_media_error.js +4 -5
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/index.d.ts +1 -1
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/index.js +1 -1
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/load_and_push_segment.d.ts +26 -0
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/load_and_push_segment.js +60 -0
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/prepare_source_buffer.d.ts +6 -5
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/prepare_source_buffer.js +40 -9
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/remove_buffer_around_time.d.ts +3 -2
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/remove_buffer_around_time.js +7 -14
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/types.d.ts +1 -1
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/{thumbnail_loader.d.ts → video_thumbnail_loader.d.ts} +1 -13
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.js +331 -0
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader_error.d.ts +1 -2
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader_error.js +1 -2
- package/dist/_esm5.processed/features/initialize_features.js +2 -1
- package/dist/_esm5.processed/features/list/directfile.js +1 -1
- package/dist/_esm5.processed/features/types.d.ts +1 -1
- package/dist/_esm5.processed/manifest/index.d.ts +2 -2
- package/dist/_esm5.processed/public_types.d.ts +47 -0
- package/dist/_esm5.processed/utils/reference.d.ts +23 -3
- package/dist/_esm5.processed/utils/reference.js +23 -2
- package/dist/rx-player.js +1253 -1014
- package/dist/rx-player.min.js +1 -1
- package/package.json +1 -1
- package/sonar-project.properties +1 -1
- package/src/core/api/README.md +1 -1
- package/src/core/api/__tests__/{get_player_state.test.ts → utils.test.ts} +1 -1
- package/src/core/api/option_utils.ts +1 -5
- package/src/core/api/public_api.ts +15 -13
- package/src/core/api/{__tests__ → tracks_management/__tests__}/media_element_track_choice_manager.test.ts +0 -0
- package/src/core/api/{media_element_track_choice_manager.ts → tracks_management/media_element_track_choice_manager.ts} +10 -7
- package/src/core/api/{track_choice_manager.ts → tracks_management/track_choice_manager.ts} +9 -9
- package/src/core/api/{get_player_state.ts → utils.ts} +62 -11
- package/src/core/decrypt/content_decryptor.ts +112 -13
- package/src/core/decrypt/session_events_listener.ts +34 -30
- package/src/core/decrypt/utils/check_key_statuses.ts +89 -45
- package/src/core/decrypt/utils/persistent_sessions_store.ts +1 -2
- package/src/core/fetchers/index.ts +0 -12
- package/src/core/fetchers/segment/__tests__/task_prioritizer.test.ts +763 -0
- package/src/core/fetchers/segment/index.ts +0 -12
- package/src/core/fetchers/segment/prioritized_segment_fetcher.ts +40 -47
- package/src/core/fetchers/segment/segment_fetcher.ts +249 -268
- package/src/core/fetchers/segment/segment_fetcher_creator.ts +6 -7
- package/src/core/fetchers/segment/task_prioritizer.ts +460 -0
- package/src/core/fetchers/utils/try_urls_with_backoff.ts +3 -3
- package/src/core/init/create_media_source.ts +1 -1
- package/src/core/init/stall_avoider.ts +2 -1
- package/src/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.ts +1 -1
- package/src/core/segment_buffers/implementations/text/html/html_text_segment_buffer.ts +3 -3
- package/src/core/segment_buffers/implementations/types.ts +6 -2
- package/src/core/stream/orchestrator/{get_blacklisted_ranges.ts → get_time_ranges_for_content.ts} +1 -1
- package/src/core/stream/orchestrator/stream_orchestrator.ts +115 -56
- package/src/core/stream/representation/downloading_queue.ts +269 -142
- package/src/core/stream/types.ts +3 -1
- package/src/errors/encrypted_media_error.ts +20 -1
- package/src/experimental/tools/VideoThumbnailLoader/index.ts +1 -1
- package/src/experimental/tools/VideoThumbnailLoader/load_and_push_segment.ts +74 -0
- package/src/experimental/tools/VideoThumbnailLoader/prepare_source_buffer.ts +50 -16
- package/src/experimental/tools/VideoThumbnailLoader/remove_buffer_around_time.ts +14 -21
- package/src/experimental/tools/VideoThumbnailLoader/types.ts +7 -4
- package/src/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.ts +407 -0
- package/src/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader_error.ts +1 -2
- package/src/features/__tests__/initialize_features.test.ts +3 -1
- package/src/features/initialize_features.ts +2 -1
- package/src/features/list/__tests__/directfile.test.ts +1 -1
- package/src/features/list/directfile.ts +1 -1
- package/src/features/types.ts +1 -1
- package/src/manifest/index.ts +2 -0
- package/src/public_types.ts +53 -0
- package/src/utils/reference.ts +58 -4
- package/dist/_esm5.processed/core/api/get_player_state.d.ts +0 -28
- package/dist/_esm5.processed/core/api/get_player_state.js +0 -56
- package/dist/_esm5.processed/core/fetchers/segment/prioritizer.d.ts +0 -232
- package/dist/_esm5.processed/core/fetchers/segment/prioritizer.js +0 -422
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/create_request.d.ts +0 -29
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/create_request.js +0 -68
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/get_complete_segment_id.d.ts +0 -24
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/get_complete_segment_id.js +0 -29
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/get_content_infos.d.ts +0 -25
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/get_content_infos.js +0 -40
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/get_initialized_source_buffer.d.ts +0 -33
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/get_initialized_source_buffer.js +0 -124
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/load_segments.d.ts +0 -17
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/load_segments.js +0 -41
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/push_data.d.ts +0 -22
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/push_data.js +0 -21
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/thumbnail_loader.js +0 -212
- package/src/core/api/emit_seek_events.ts +0 -66
- package/src/core/fetchers/segment/__tests__/prioritizer.test.ts +0 -962
- package/src/core/fetchers/segment/prioritizer.ts +0 -558
- package/src/experimental/tools/VideoThumbnailLoader/create_request.ts +0 -113
- package/src/experimental/tools/VideoThumbnailLoader/get_complete_segment_id.ts +0 -34
- package/src/experimental/tools/VideoThumbnailLoader/get_content_infos.ts +0 -48
- package/src/experimental/tools/VideoThumbnailLoader/get_initialized_source_buffer.ts +0 -171
- package/src/experimental/tools/VideoThumbnailLoader/load_segments.ts +0 -69
- package/src/experimental/tools/VideoThumbnailLoader/push_data.ts +0 -48
- package/src/experimental/tools/VideoThumbnailLoader/thumbnail_loader.ts +0 -311
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { CancellationSignal } from "../../../utils/task_canceller";
|
|
2
|
+
export default class TaskPrioritizer<T> {
|
|
3
|
+
/**
|
|
4
|
+
* Priority of the most prioritary task currently running.
|
|
5
|
+
* `null` if no task is currently running.
|
|
6
|
+
*/
|
|
7
|
+
private _minPendingPriority;
|
|
8
|
+
/** Queue of tasks currently waiting for more prioritary ones to finish. */
|
|
9
|
+
private _waitingQueue;
|
|
10
|
+
/** Tasks currently pending. */
|
|
11
|
+
private _pendingTasks;
|
|
12
|
+
/** @see IPrioritizerPrioritySteps */
|
|
13
|
+
private _prioritySteps;
|
|
14
|
+
/**
|
|
15
|
+
* @param {Options} prioritizerOptions
|
|
16
|
+
*/
|
|
17
|
+
constructor({ prioritySteps }: IPrioritizerOptions);
|
|
18
|
+
/**
|
|
19
|
+
* Create a priorized Promise from a base task.
|
|
20
|
+
*
|
|
21
|
+
* This task will immediately have its priority compared to all the
|
|
22
|
+
* already-running ones created from this class.
|
|
23
|
+
*
|
|
24
|
+
* Only if this number is inferior or equal to the priority of the
|
|
25
|
+
* minimum priority number of all currently-running tasks will it be
|
|
26
|
+
* immediately started.
|
|
27
|
+
* In the opposite case, we will wait for higher-priority tasks to
|
|
28
|
+
* finish before starting it.
|
|
29
|
+
*
|
|
30
|
+
* Note that while this task is waiting for its turn, it is possible
|
|
31
|
+
* to update its property through the updatePriority method, by providing
|
|
32
|
+
* the task again and its new priority number.
|
|
33
|
+
*
|
|
34
|
+
* @param {Function} taskFn
|
|
35
|
+
* @param {number} priority
|
|
36
|
+
* @param {Object} callbacks
|
|
37
|
+
* @param {Object} cancelSignal
|
|
38
|
+
* @returns {Promise}
|
|
39
|
+
*/
|
|
40
|
+
create(taskFn: ITaskFn<T>, priority: number, callbacks: ITaskPrioritizerCallbacks, cancelSignal: CancellationSignal): Promise<T>;
|
|
41
|
+
private _endTask;
|
|
42
|
+
/**
|
|
43
|
+
* Update the priority of a promise given to the TaskPrioritizer.
|
|
44
|
+
* @param {Object} promise
|
|
45
|
+
* @param {number} priority
|
|
46
|
+
*/
|
|
47
|
+
updatePriority(promise: ITaskFn<T>, priority: number): void;
|
|
48
|
+
/**
|
|
49
|
+
* Browse the current waiting queue and start all task in it that needs to be
|
|
50
|
+
* started: start the ones with the lowest priority value below
|
|
51
|
+
* `_minPendingPriority`.
|
|
52
|
+
*
|
|
53
|
+
* Private properties, such as `_minPendingPriority` are updated accordingly
|
|
54
|
+
* while this method is called.
|
|
55
|
+
*/
|
|
56
|
+
private _loopThroughWaitingQueue;
|
|
57
|
+
/**
|
|
58
|
+
* Interrupt and move back to the waiting queue all pending tasks that are
|
|
59
|
+
* low priority (having a higher priority number than
|
|
60
|
+
* `this._prioritySteps.low`).
|
|
61
|
+
*/
|
|
62
|
+
private _interruptCancellableTasks;
|
|
63
|
+
/**
|
|
64
|
+
* Start task which is at the given index in the waiting queue.
|
|
65
|
+
* The task will be removed from the waiting queue in the process.
|
|
66
|
+
* @param {number} index
|
|
67
|
+
*/
|
|
68
|
+
private _findAndRunWaitingQueueTask;
|
|
69
|
+
/**
|
|
70
|
+
* Move back pending task to the waiting queue and interrupt it.
|
|
71
|
+
* @param {object} task
|
|
72
|
+
*/
|
|
73
|
+
private _interruptPendingTask;
|
|
74
|
+
/**
|
|
75
|
+
* Return `true` if the given task can be started immediately based on its
|
|
76
|
+
* priority.
|
|
77
|
+
* @param {Object} task
|
|
78
|
+
* @returns {boolean}
|
|
79
|
+
*/
|
|
80
|
+
private _canBeStartedNow;
|
|
81
|
+
/**
|
|
82
|
+
* Returns `true` if any running task is considered "high priority".
|
|
83
|
+
* returns `false` otherwise.
|
|
84
|
+
* @returns {boolean}
|
|
85
|
+
*/
|
|
86
|
+
private _isRunningHighPriorityTasks;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Task function as given to the TaskPrioritizer.
|
|
90
|
+
* The `CancellationSignal` given as argument should be used to directly
|
|
91
|
+
* interrupt the task.
|
|
92
|
+
*
|
|
93
|
+
* A same task might be re-run multiple times.
|
|
94
|
+
*/
|
|
95
|
+
export declare type ITaskFn<T> = (cancellationSignal: CancellationSignal) => Promise<T>;
|
|
96
|
+
/** Options to give to the `TaskPrioritizer`. */
|
|
97
|
+
export interface IPrioritizerOptions {
|
|
98
|
+
/** @see IPrioritizerPrioritySteps */
|
|
99
|
+
prioritySteps: IPrioritizerPrioritySteps;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Define both the `low` and `high` priority steps:
|
|
103
|
+
*
|
|
104
|
+
* - Any task with a priority number that is lower or equal to the
|
|
105
|
+
* `high` value will be a task with high priority.
|
|
106
|
+
*
|
|
107
|
+
* When tasks with high priorities are scheduled, they immediately
|
|
108
|
+
* abort pending tasks with low priorities (which will have then to
|
|
109
|
+
* wait until all higher-priority task have ended before re-starting).
|
|
110
|
+
*
|
|
111
|
+
* - Any task with a priority number that is higher or equal to the
|
|
112
|
+
* `low` value will be a task with low priority.
|
|
113
|
+
*
|
|
114
|
+
* Pending tasks with low priorities have the added particularity*
|
|
115
|
+
* of being aborted as soon as a high priority task is scheduled.
|
|
116
|
+
*
|
|
117
|
+
* * Other pending tasks are not aborted when a higher-priority
|
|
118
|
+
* task is scheduled, as their priorities only affect them before
|
|
119
|
+
* they are started (to know when to start them).
|
|
120
|
+
*/
|
|
121
|
+
export interface IPrioritizerPrioritySteps {
|
|
122
|
+
low: number;
|
|
123
|
+
high: number;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Callbacks called by the `TaskPrioritizer` on various events associated to a
|
|
127
|
+
* single task.
|
|
128
|
+
*/
|
|
129
|
+
export interface ITaskPrioritizerCallbacks {
|
|
130
|
+
/**
|
|
131
|
+
* Callback called just before the `TaskPrioritizer` temporarily cancels
|
|
132
|
+
* a task, to prioritize higher-priority tasks.
|
|
133
|
+
*
|
|
134
|
+
* Interrupted tasks are restarted from scratch at a later time.
|
|
135
|
+
*/
|
|
136
|
+
beforeInterrupted(): void;
|
|
137
|
+
/**
|
|
138
|
+
* Callback called when the task ended just before the `TaskPrioritizer`
|
|
139
|
+
* chooses the next task(s) to run.
|
|
140
|
+
*
|
|
141
|
+
* You can use this callback to add yet other tasks just in time before the
|
|
142
|
+
* `TaskPrioritizer` chooses the next one.
|
|
143
|
+
*/
|
|
144
|
+
beforeEnded(): void;
|
|
145
|
+
}
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
import log from "../../../log";
|
|
2
|
+
import arrayFindIndex from "../../../utils/array_find_index";
|
|
3
|
+
import TaskCanceller, { CancellationError, } from "../../../utils/task_canceller";
|
|
4
|
+
var TaskPrioritizer = /** @class */ (function () {
|
|
5
|
+
/**
|
|
6
|
+
* @param {Options} prioritizerOptions
|
|
7
|
+
*/
|
|
8
|
+
function TaskPrioritizer(_a) {
|
|
9
|
+
var prioritySteps = _a.prioritySteps;
|
|
10
|
+
this._minPendingPriority = null;
|
|
11
|
+
this._waitingQueue = [];
|
|
12
|
+
this._pendingTasks = [];
|
|
13
|
+
this._prioritySteps = prioritySteps;
|
|
14
|
+
if (this._prioritySteps.high >= this._prioritySteps.low) {
|
|
15
|
+
throw new Error("TP: the max high level priority should be given a lower" +
|
|
16
|
+
"priority number than the min low priority.");
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Create a priorized Promise from a base task.
|
|
21
|
+
*
|
|
22
|
+
* This task will immediately have its priority compared to all the
|
|
23
|
+
* already-running ones created from this class.
|
|
24
|
+
*
|
|
25
|
+
* Only if this number is inferior or equal to the priority of the
|
|
26
|
+
* minimum priority number of all currently-running tasks will it be
|
|
27
|
+
* immediately started.
|
|
28
|
+
* In the opposite case, we will wait for higher-priority tasks to
|
|
29
|
+
* finish before starting it.
|
|
30
|
+
*
|
|
31
|
+
* Note that while this task is waiting for its turn, it is possible
|
|
32
|
+
* to update its property through the updatePriority method, by providing
|
|
33
|
+
* the task again and its new priority number.
|
|
34
|
+
*
|
|
35
|
+
* @param {Function} taskFn
|
|
36
|
+
* @param {number} priority
|
|
37
|
+
* @param {Object} callbacks
|
|
38
|
+
* @param {Object} cancelSignal
|
|
39
|
+
* @returns {Promise}
|
|
40
|
+
*/
|
|
41
|
+
TaskPrioritizer.prototype.create = function (taskFn, priority, callbacks, cancelSignal) {
|
|
42
|
+
var _this = this;
|
|
43
|
+
var newTask;
|
|
44
|
+
return new Promise(function (resolve, reject) {
|
|
45
|
+
/** Function allowing to start the underlying Promise. */
|
|
46
|
+
var trigger = function () {
|
|
47
|
+
if (newTask.hasEnded) {
|
|
48
|
+
unregisterCancelSignal();
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
var interrupter = new TaskCanceller({ cancelOn: cancelSignal });
|
|
52
|
+
newTask.interrupter = interrupter;
|
|
53
|
+
interrupter.signal.register(function () {
|
|
54
|
+
newTask.interrupter = null;
|
|
55
|
+
if (!cancelSignal.isCancelled) {
|
|
56
|
+
callbacks.beforeInterrupted();
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
_this._minPendingPriority = _this._minPendingPriority === null ?
|
|
60
|
+
newTask.priority :
|
|
61
|
+
Math.min(_this._minPendingPriority, newTask.priority);
|
|
62
|
+
_this._pendingTasks.push(newTask);
|
|
63
|
+
newTask.taskFn(interrupter.signal)
|
|
64
|
+
.then(onResolve)
|
|
65
|
+
.catch(function (err) {
|
|
66
|
+
if (!cancelSignal.isCancelled &&
|
|
67
|
+
interrupter.isUsed &&
|
|
68
|
+
err instanceof CancellationError) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
onReject(err);
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
var unregisterCancelSignal = cancelSignal.register(function (cancellationError) {
|
|
75
|
+
_this._endTask(newTask);
|
|
76
|
+
reject(cancellationError);
|
|
77
|
+
});
|
|
78
|
+
var finishTask = function () {
|
|
79
|
+
unregisterCancelSignal();
|
|
80
|
+
_this._endTask(newTask);
|
|
81
|
+
};
|
|
82
|
+
var onResolve = function (value) {
|
|
83
|
+
callbacks.beforeEnded();
|
|
84
|
+
finishTask();
|
|
85
|
+
resolve(value);
|
|
86
|
+
};
|
|
87
|
+
var onReject = function (err) {
|
|
88
|
+
finishTask();
|
|
89
|
+
reject(err);
|
|
90
|
+
};
|
|
91
|
+
newTask = {
|
|
92
|
+
hasEnded: false,
|
|
93
|
+
priority: priority,
|
|
94
|
+
trigger: trigger,
|
|
95
|
+
taskFn: taskFn,
|
|
96
|
+
interrupter: null,
|
|
97
|
+
};
|
|
98
|
+
if (!_this._canBeStartedNow(newTask)) {
|
|
99
|
+
_this._waitingQueue.push(newTask);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
// We can start the task right away
|
|
103
|
+
newTask.trigger();
|
|
104
|
+
if (_this._isRunningHighPriorityTasks()) {
|
|
105
|
+
// Note: we want to begin interrupting low-priority tasks just
|
|
106
|
+
// after starting the current one because the interrupting
|
|
107
|
+
// logic can call external code.
|
|
108
|
+
// This would mean re-entrancy, itself meaning that some weird
|
|
109
|
+
// half-state could be reached unless we're very careful.
|
|
110
|
+
// To be sure no harm is done, we put that code at the last
|
|
111
|
+
// possible position.
|
|
112
|
+
_this._interruptCancellableTasks();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
};
|
|
117
|
+
TaskPrioritizer.prototype._endTask = function (task) {
|
|
118
|
+
task.hasEnded = true;
|
|
119
|
+
var waitingQueueIndex = _findTaskIndex(task.taskFn, this._waitingQueue);
|
|
120
|
+
if (waitingQueueIndex >= 0) {
|
|
121
|
+
// If it was still waiting for its turn
|
|
122
|
+
this._waitingQueue.splice(waitingQueueIndex, 1);
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
// remove it from pending queue if in it
|
|
126
|
+
var pendingTasksIndex = _findTaskIndex(task.taskFn, this._pendingTasks);
|
|
127
|
+
if (pendingTasksIndex < 0) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
this._pendingTasks.splice(pendingTasksIndex, 1);
|
|
131
|
+
if (this._pendingTasks.length > 0) {
|
|
132
|
+
if (this._minPendingPriority === task.priority) {
|
|
133
|
+
this._minPendingPriority = Math.min.apply(Math, this._pendingTasks.map(function (t) { return t.priority; }));
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
this._minPendingPriority = null;
|
|
138
|
+
}
|
|
139
|
+
this._loopThroughWaitingQueue();
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
/**
|
|
143
|
+
* Update the priority of a promise given to the TaskPrioritizer.
|
|
144
|
+
* @param {Object} promise
|
|
145
|
+
* @param {number} priority
|
|
146
|
+
*/
|
|
147
|
+
TaskPrioritizer.prototype.updatePriority = function (promise, priority) {
|
|
148
|
+
var waitingQueueIndex = _findTaskIndex(promise, this._waitingQueue);
|
|
149
|
+
if (waitingQueueIndex >= 0) { // If it was still waiting for its turn
|
|
150
|
+
var waitingQueueElt = this._waitingQueue[waitingQueueIndex];
|
|
151
|
+
if (waitingQueueElt.priority === priority) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
waitingQueueElt.priority = priority;
|
|
155
|
+
if (!this._canBeStartedNow(waitingQueueElt)) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
this._findAndRunWaitingQueueTask(waitingQueueIndex);
|
|
159
|
+
if (this._isRunningHighPriorityTasks()) {
|
|
160
|
+
// Re-check to cancel every "cancellable" pending task
|
|
161
|
+
//
|
|
162
|
+
// Note: We start the task before interrupting cancellable tasks on
|
|
163
|
+
// purpose.
|
|
164
|
+
// Because both `_findAndRunWaitingQueueTask` and
|
|
165
|
+
// `_interruptCancellableTasks` can emit events and thus call external
|
|
166
|
+
// code, we could retrieve ourselves in a very weird state at this point
|
|
167
|
+
//
|
|
168
|
+
// By starting the task first, we ensure that this is manageable:
|
|
169
|
+
// `_getMinPendingPriority()` has already been updated to the right value at
|
|
170
|
+
// the time we reached external code, the priority of the current
|
|
171
|
+
// Task has just been updated, and `_interruptCancellableTasks`
|
|
172
|
+
// will ensure that we're basing ourselves on the last `priority` value
|
|
173
|
+
// each time.
|
|
174
|
+
// Doing it in the reverse order is an order of magnitude more difficult
|
|
175
|
+
// to write and to reason about.
|
|
176
|
+
this._interruptCancellableTasks();
|
|
177
|
+
}
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
var pendingTasksIndex = _findTaskIndex(promise, this._pendingTasks);
|
|
181
|
+
if (pendingTasksIndex < 0) {
|
|
182
|
+
log.warn("TP: request to update the priority of a non-existent task");
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
var task = this._pendingTasks[pendingTasksIndex];
|
|
186
|
+
if (task.priority === priority) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
var prevPriority = task.priority;
|
|
190
|
+
task.priority = priority;
|
|
191
|
+
if (this._minPendingPriority === null || priority < this._minPendingPriority) {
|
|
192
|
+
this._minPendingPriority = priority;
|
|
193
|
+
}
|
|
194
|
+
else if (this._minPendingPriority === prevPriority) { // was highest priority
|
|
195
|
+
if (this._pendingTasks.length === 1) {
|
|
196
|
+
this._minPendingPriority = priority;
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
this._minPendingPriority = Math.min.apply(Math, this._pendingTasks.map(function (t) { return t.priority; }));
|
|
200
|
+
}
|
|
201
|
+
this._loopThroughWaitingQueue();
|
|
202
|
+
}
|
|
203
|
+
if (this._isRunningHighPriorityTasks()) {
|
|
204
|
+
// Always interrupt cancellable tasks after all other side-effects, to
|
|
205
|
+
// avoid re-entrancy issues
|
|
206
|
+
this._interruptCancellableTasks();
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
/**
|
|
210
|
+
* Browse the current waiting queue and start all task in it that needs to be
|
|
211
|
+
* started: start the ones with the lowest priority value below
|
|
212
|
+
* `_minPendingPriority`.
|
|
213
|
+
*
|
|
214
|
+
* Private properties, such as `_minPendingPriority` are updated accordingly
|
|
215
|
+
* while this method is called.
|
|
216
|
+
*/
|
|
217
|
+
TaskPrioritizer.prototype._loopThroughWaitingQueue = function () {
|
|
218
|
+
var minWaitingPriority = this._waitingQueue.reduce(function (acc, elt) {
|
|
219
|
+
return acc === null || acc > elt.priority ? elt.priority :
|
|
220
|
+
acc;
|
|
221
|
+
}, null);
|
|
222
|
+
if (minWaitingPriority === null ||
|
|
223
|
+
(this._minPendingPriority !== null &&
|
|
224
|
+
this._minPendingPriority < minWaitingPriority)) {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
for (var i = 0; i < this._waitingQueue.length; i++) {
|
|
228
|
+
var priorityToCheck = this._minPendingPriority === null ?
|
|
229
|
+
minWaitingPriority :
|
|
230
|
+
Math.min(this._minPendingPriority, minWaitingPriority);
|
|
231
|
+
var elt = this._waitingQueue[i];
|
|
232
|
+
if (elt.priority <= priorityToCheck) {
|
|
233
|
+
this._findAndRunWaitingQueueTask(i);
|
|
234
|
+
i--; // previous operation should have removed that element from the
|
|
235
|
+
// the waiting queue
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
/**
|
|
240
|
+
* Interrupt and move back to the waiting queue all pending tasks that are
|
|
241
|
+
* low priority (having a higher priority number than
|
|
242
|
+
* `this._prioritySteps.low`).
|
|
243
|
+
*/
|
|
244
|
+
TaskPrioritizer.prototype._interruptCancellableTasks = function () {
|
|
245
|
+
for (var i = 0; i < this._pendingTasks.length; i++) {
|
|
246
|
+
var pendingObj = this._pendingTasks[i];
|
|
247
|
+
if (pendingObj.priority >= this._prioritySteps.low) {
|
|
248
|
+
this._interruptPendingTask(pendingObj);
|
|
249
|
+
// The previous call could have a lot of potential side-effects.
|
|
250
|
+
// It is safer to re-start the function to not miss any pending
|
|
251
|
+
// task that needs to be cancelled.
|
|
252
|
+
return this._interruptCancellableTasks();
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
/**
|
|
257
|
+
* Start task which is at the given index in the waiting queue.
|
|
258
|
+
* The task will be removed from the waiting queue in the process.
|
|
259
|
+
* @param {number} index
|
|
260
|
+
*/
|
|
261
|
+
TaskPrioritizer.prototype._findAndRunWaitingQueueTask = function (index) {
|
|
262
|
+
if (index >= this._waitingQueue.length || index < 0) {
|
|
263
|
+
log.warn("TP : Tried to start a non existing task");
|
|
264
|
+
return false;
|
|
265
|
+
}
|
|
266
|
+
var task = this._waitingQueue.splice(index, 1)[0];
|
|
267
|
+
task.trigger();
|
|
268
|
+
return true;
|
|
269
|
+
};
|
|
270
|
+
/**
|
|
271
|
+
* Move back pending task to the waiting queue and interrupt it.
|
|
272
|
+
* @param {object} task
|
|
273
|
+
*/
|
|
274
|
+
TaskPrioritizer.prototype._interruptPendingTask = function (task) {
|
|
275
|
+
var _a;
|
|
276
|
+
var pendingTasksIndex = _findTaskIndex(task.taskFn, this._pendingTasks);
|
|
277
|
+
if (pendingTasksIndex < 0) {
|
|
278
|
+
log.warn("TP: Interrupting a non-existent pending task. Aborting...");
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
// Stop task and put it back in the waiting queue
|
|
282
|
+
this._pendingTasks.splice(pendingTasksIndex, 1);
|
|
283
|
+
this._waitingQueue.push(task);
|
|
284
|
+
if (this._pendingTasks.length === 0) {
|
|
285
|
+
this._minPendingPriority = null;
|
|
286
|
+
}
|
|
287
|
+
else if (this._minPendingPriority === task.priority) {
|
|
288
|
+
this._minPendingPriority = Math.min.apply(Math, this._pendingTasks.map(function (t) { return t.priority; }));
|
|
289
|
+
}
|
|
290
|
+
(_a = task.interrupter) === null || _a === void 0 ? void 0 : _a.cancel(); // Interrupt at last step because it calls external code
|
|
291
|
+
};
|
|
292
|
+
/**
|
|
293
|
+
* Return `true` if the given task can be started immediately based on its
|
|
294
|
+
* priority.
|
|
295
|
+
* @param {Object} task
|
|
296
|
+
* @returns {boolean}
|
|
297
|
+
*/
|
|
298
|
+
TaskPrioritizer.prototype._canBeStartedNow = function (task) {
|
|
299
|
+
return this._minPendingPriority === null ||
|
|
300
|
+
task.priority <= this._minPendingPriority;
|
|
301
|
+
};
|
|
302
|
+
/**
|
|
303
|
+
* Returns `true` if any running task is considered "high priority".
|
|
304
|
+
* returns `false` otherwise.
|
|
305
|
+
* @returns {boolean}
|
|
306
|
+
*/
|
|
307
|
+
TaskPrioritizer.prototype._isRunningHighPriorityTasks = function () {
|
|
308
|
+
return this._minPendingPriority !== null &&
|
|
309
|
+
this._minPendingPriority <= this._prioritySteps.high;
|
|
310
|
+
};
|
|
311
|
+
return TaskPrioritizer;
|
|
312
|
+
}());
|
|
313
|
+
export default TaskPrioritizer;
|
|
314
|
+
/**
|
|
315
|
+
* Simple utils function allowing to find a given task function in the given
|
|
316
|
+
* `queue`.
|
|
317
|
+
*
|
|
318
|
+
* Returns `-1` if `taskFn` is not found.
|
|
319
|
+
* @param {Function} taskFn
|
|
320
|
+
* @param {Array.<Object>} queue
|
|
321
|
+
* @returns {number}
|
|
322
|
+
*/
|
|
323
|
+
function _findTaskIndex(taskFn, queue) {
|
|
324
|
+
return arrayFindIndex(queue, function (elt) { return elt.taskFn === taskFn; });
|
|
325
|
+
}
|
|
@@ -78,8 +78,8 @@ export declare function tryURLsWithBackoff<T>(urls: Array<string | null>, perfor
|
|
|
78
78
|
/**
|
|
79
79
|
* Lightweight version of the request algorithm, this time with only a simple
|
|
80
80
|
* Promise given.
|
|
81
|
-
* @param {Function}
|
|
81
|
+
* @param {Function} performRequest
|
|
82
82
|
* @param {Object} options
|
|
83
|
-
* @returns {
|
|
83
|
+
* @returns {Promise}
|
|
84
84
|
*/
|
|
85
85
|
export declare function tryRequestPromiseWithBackoff<T>(performRequest: () => Promise<T>, options: IBackoffSettings, cancellationSignal: CancellationSignal): Promise<T>;
|
|
@@ -180,7 +180,7 @@ export function tryURLsWithBackoff(urls, performRequest, options, cancellationSi
|
|
|
180
180
|
*
|
|
181
181
|
* @param {string|null} url
|
|
182
182
|
* @param {number} index
|
|
183
|
-
* @returns {
|
|
183
|
+
* @returns {Promise}
|
|
184
184
|
*/
|
|
185
185
|
function tryURLsRecursively(url, index) {
|
|
186
186
|
return __awaiter(this, void 0, void 0, function () {
|
|
@@ -254,9 +254,9 @@ export function tryURLsWithBackoff(urls, performRequest, options, cancellationSi
|
|
|
254
254
|
/**
|
|
255
255
|
* Lightweight version of the request algorithm, this time with only a simple
|
|
256
256
|
* Promise given.
|
|
257
|
-
* @param {Function}
|
|
257
|
+
* @param {Function} performRequest
|
|
258
258
|
* @param {Object} options
|
|
259
|
-
* @returns {
|
|
259
|
+
* @returns {Promise}
|
|
260
260
|
*/
|
|
261
261
|
export function tryRequestPromiseWithBackoff(performRequest, options, cancellationSignal) {
|
|
262
262
|
// same than for a single unknown URL
|
|
@@ -14,6 +14,16 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
import { Observable } from "rxjs";
|
|
17
|
+
/**
|
|
18
|
+
* Dispose of ressources taken by the MediaSource:
|
|
19
|
+
* - Clear the MediaSource' SourceBuffers
|
|
20
|
+
* - Clear the mediaElement's src (stop the mediaElement)
|
|
21
|
+
* - Revoke MediaSource' URL
|
|
22
|
+
* @param {HTMLMediaElement} mediaElement
|
|
23
|
+
* @param {MediaSource|null} mediaSource
|
|
24
|
+
* @param {string|null} mediaSourceURL
|
|
25
|
+
*/
|
|
26
|
+
export declare function resetMediaSource(mediaElement: HTMLMediaElement, mediaSource: MediaSource | null, mediaSourceURL: string | null): void;
|
|
17
27
|
/**
|
|
18
28
|
* Create and open a new MediaSource object on the given media element.
|
|
19
29
|
* Emit the MediaSource when done.
|
|
@@ -28,7 +28,7 @@ var onSourceOpen$ = events.onSourceOpen$;
|
|
|
28
28
|
* @param {MediaSource|null} mediaSource
|
|
29
29
|
* @param {string|null} mediaSourceURL
|
|
30
30
|
*/
|
|
31
|
-
function resetMediaSource(mediaElement, mediaSource, mediaSourceURL) {
|
|
31
|
+
export function resetMediaSource(mediaElement, mediaSource, mediaSourceURL) {
|
|
32
32
|
if (mediaSource !== null && mediaSource.readyState !== "closed") {
|
|
33
33
|
var readyState = mediaSource.readyState, sourceBuffers = mediaSource.sourceBuffers;
|
|
34
34
|
for (var i = sourceBuffers.length - 1; i >= 0; i--) {
|
|
@@ -69,7 +69,8 @@ export interface IDiscontinuityTimeInfo {
|
|
|
69
69
|
* @param {object} playbackObserver - emit the current playback conditions.
|
|
70
70
|
* @param {Object} manifest - The Manifest of the currently-played content.
|
|
71
71
|
* @param {Object} speed - The last speed set by the user
|
|
72
|
-
* @param {Observable} lockedStream$
|
|
72
|
+
* @param {Observable} lockedStream$ - Emit information on currently "locked"
|
|
73
|
+
* streams.
|
|
73
74
|
* @param {Observable} discontinuityUpdate$ - Observable emitting encountered
|
|
74
75
|
* discontinuities for loaded Period and buffer types.
|
|
75
76
|
* @returns {Observable}
|
|
@@ -32,7 +32,8 @@ var EPSILON = 1 / 60;
|
|
|
32
32
|
* @param {object} playbackObserver - emit the current playback conditions.
|
|
33
33
|
* @param {Object} manifest - The Manifest of the currently-played content.
|
|
34
34
|
* @param {Object} speed - The last speed set by the user
|
|
35
|
-
* @param {Observable} lockedStream$
|
|
35
|
+
* @param {Observable} lockedStream$ - Emit information on currently "locked"
|
|
36
|
+
* streams.
|
|
36
37
|
* @param {Observable} discontinuityUpdate$ - Observable emitting encountered
|
|
37
38
|
* discontinuities for loaded Period and buffer types.
|
|
38
39
|
* @returns {Observable}
|
|
@@ -366,7 +366,7 @@ var AudioVideoSegmentBuffer = /** @class */ (function (_super) {
|
|
|
366
366
|
var dataToPush = [];
|
|
367
367
|
var codec = data.codec, timestampOffset = data.timestampOffset, appendWindow = data.appendWindow;
|
|
368
368
|
var hasUpdatedSourceBufferType = false;
|
|
369
|
-
if (codec !== this.codec) {
|
|
369
|
+
if (codec !== undefined && codec !== this.codec) {
|
|
370
370
|
log.debug("AVSB: updating codec", codec);
|
|
371
371
|
hasUpdatedSourceBufferType = tryToChangeSourceBufferType(this._sourceBuffer, codec);
|
|
372
372
|
if (hasUpdatedSourceBufferType) {
|
|
@@ -310,6 +310,7 @@ var HTMLTextSegmentBuffer = /** @class */ (function (_super) {
|
|
|
310
310
|
}, cancellationSignal);
|
|
311
311
|
onSeeked(this._videoElement, startAutoRefresh, cancellationSignal);
|
|
312
312
|
onEnded(this._videoElement, startAutoRefresh, cancellationSignal);
|
|
313
|
+
startAutoRefresh();
|
|
313
314
|
function stopAutoRefresh() {
|
|
314
315
|
if (autoRefreshCanceller !== null) {
|
|
315
316
|
autoRefreshCanceller.cancel();
|
|
@@ -322,11 +323,10 @@ var HTMLTextSegmentBuffer = /** @class */ (function (_super) {
|
|
|
322
323
|
* position.
|
|
323
324
|
*/
|
|
324
325
|
HTMLTextSegmentBuffer.prototype.refreshSubtitles = function () {
|
|
325
|
-
var videoElt = this._videoElement;
|
|
326
326
|
var MAXIMUM_HTML_TEXT_TRACK_UPDATE_INTERVAL = config.getCurrent().MAXIMUM_HTML_TEXT_TRACK_UPDATE_INTERVAL;
|
|
327
327
|
var time;
|
|
328
|
-
if (
|
|
329
|
-
time =
|
|
328
|
+
if (this._videoElement.paused || this._videoElement.playbackRate <= 0) {
|
|
329
|
+
time = this._videoElement.currentTime;
|
|
330
330
|
}
|
|
331
331
|
else {
|
|
332
332
|
// to spread the time error, we divide the regular chosen interval.
|
|
@@ -179,7 +179,8 @@ export interface IPushedChunkData<T> {
|
|
|
179
179
|
/**
|
|
180
180
|
* The whole initialization segment's data related to the chunk you want to
|
|
181
181
|
* push.
|
|
182
|
-
* `null` if
|
|
182
|
+
* To set to `null` either if no initialization data is needed, or if you are
|
|
183
|
+
* confident that the last pushed one is compatible.
|
|
183
184
|
*/
|
|
184
185
|
initSegment: T | null;
|
|
185
186
|
/**
|
|
@@ -192,8 +193,11 @@ export interface IPushedChunkData<T> {
|
|
|
192
193
|
/**
|
|
193
194
|
* String corresponding to the mime-type + codec of the last segment pushed.
|
|
194
195
|
* This might then be used by a SourceBuffer to infer the right codec to use.
|
|
196
|
+
*
|
|
197
|
+
* If set to `undefined`, the SegmentBuffer implementation will just rely on
|
|
198
|
+
* a default codec it is linked to, if one.
|
|
195
199
|
*/
|
|
196
|
-
codec: string;
|
|
200
|
+
codec: string | undefined;
|
|
197
201
|
/**
|
|
198
202
|
* Time offset in seconds to apply to this segment.
|
|
199
203
|
* A `timestampOffset` set to `5` will mean that the segment will be decoded
|
|
@@ -23,7 +23,7 @@ import { SegmentBuffer } from "../../segment_buffers";
|
|
|
23
23
|
* @param {Array.<Object>} contents
|
|
24
24
|
* @returns {Array.<Object>}
|
|
25
25
|
*/
|
|
26
|
-
export default function
|
|
26
|
+
export default function getTimeRangesForContent(segmentBuffer: SegmentBuffer, contents: Array<{
|
|
27
27
|
adaptation: Adaptation;
|
|
28
28
|
period: Period;
|
|
29
29
|
representation: Representation;
|
|
@@ -21,7 +21,7 @@ import log from "../../../log";
|
|
|
21
21
|
* @param {Array.<Object>} contents
|
|
22
22
|
* @returns {Array.<Object>}
|
|
23
23
|
*/
|
|
24
|
-
export default function
|
|
24
|
+
export default function getTimeRangesForContent(segmentBuffer, contents) {
|
|
25
25
|
if (contents.length === 0) {
|
|
26
26
|
return [];
|
|
27
27
|
}
|