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.
Files changed (142) hide show
  1. package/CHANGELOG.md +5 -1
  2. package/VERSION +1 -1
  3. package/dist/_esm5.processed/core/api/option_utils.js +7 -11
  4. package/dist/_esm5.processed/core/api/public_api.d.ts +4 -4
  5. package/dist/_esm5.processed/core/api/public_api.js +18 -19
  6. package/dist/_esm5.processed/core/api/{media_element_track_choice_manager.d.ts → tracks_management/media_element_track_choice_manager.d.ts} +2 -2
  7. package/dist/_esm5.processed/core/api/{media_element_track_choice_manager.js → tracks_management/media_element_track_choice_manager.js} +7 -4
  8. package/dist/_esm5.processed/core/api/{track_choice_manager.d.ts → tracks_management/track_choice_manager.d.ts} +2 -2
  9. package/dist/_esm5.processed/core/api/{track_choice_manager.js → tracks_management/track_choice_manager.js} +7 -7
  10. package/dist/_esm5.processed/core/api/{emit_seek_events.d.ts → utils.d.ts} +24 -1
  11. package/dist/_esm5.processed/core/api/{emit_seek_events.js → utils.js} +32 -1
  12. package/dist/_esm5.processed/core/decrypt/content_decryptor.d.ts +26 -0
  13. package/dist/_esm5.processed/core/decrypt/content_decryptor.js +101 -9
  14. package/dist/_esm5.processed/core/decrypt/session_events_listener.d.ts +15 -18
  15. package/dist/_esm5.processed/core/decrypt/session_events_listener.js +9 -7
  16. package/dist/_esm5.processed/core/decrypt/utils/check_key_statuses.d.ts +19 -22
  17. package/dist/_esm5.processed/core/decrypt/utils/check_key_statuses.js +87 -16
  18. package/dist/_esm5.processed/core/decrypt/utils/persistent_sessions_store.d.ts +1 -2
  19. package/dist/_esm5.processed/core/decrypt/utils/persistent_sessions_store.js +1 -2
  20. package/dist/_esm5.processed/core/fetchers/index.d.ts +2 -2
  21. package/dist/_esm5.processed/core/fetchers/segment/index.d.ts +2 -3
  22. package/dist/_esm5.processed/core/fetchers/segment/prioritized_segment_fetcher.d.ts +9 -9
  23. package/dist/_esm5.processed/core/fetchers/segment/prioritized_segment_fetcher.js +17 -15
  24. package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher.d.ts +33 -40
  25. package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher.js +156 -153
  26. package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher_creator.d.ts +3 -3
  27. package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher_creator.js +2 -2
  28. package/dist/_esm5.processed/core/fetchers/segment/task_prioritizer.d.ts +145 -0
  29. package/dist/_esm5.processed/core/fetchers/segment/task_prioritizer.js +325 -0
  30. package/dist/_esm5.processed/core/fetchers/utils/try_urls_with_backoff.d.ts +2 -2
  31. package/dist/_esm5.processed/core/fetchers/utils/try_urls_with_backoff.js +3 -3
  32. package/dist/_esm5.processed/core/init/create_media_source.d.ts +10 -0
  33. package/dist/_esm5.processed/core/init/create_media_source.js +1 -1
  34. package/dist/_esm5.processed/core/init/stall_avoider.d.ts +2 -1
  35. package/dist/_esm5.processed/core/init/stall_avoider.js +2 -1
  36. package/dist/_esm5.processed/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.js +1 -1
  37. package/dist/_esm5.processed/core/segment_buffers/implementations/text/html/html_text_segment_buffer.js +3 -3
  38. package/dist/_esm5.processed/core/segment_buffers/implementations/types.d.ts +6 -2
  39. package/dist/_esm5.processed/core/stream/orchestrator/{get_blacklisted_ranges.d.ts → get_time_ranges_for_content.d.ts} +1 -1
  40. package/dist/_esm5.processed/core/stream/orchestrator/{get_blacklisted_ranges.js → get_time_ranges_for_content.js} +1 -1
  41. package/dist/_esm5.processed/core/stream/orchestrator/stream_orchestrator.js +61 -19
  42. package/dist/_esm5.processed/core/stream/representation/downloading_queue.d.ts +8 -4
  43. package/dist/_esm5.processed/core/stream/representation/downloading_queue.js +200 -83
  44. package/dist/_esm5.processed/core/stream/types.d.ts +3 -1
  45. package/dist/_esm5.processed/errors/encrypted_media_error.d.ts +6 -1
  46. package/dist/_esm5.processed/errors/encrypted_media_error.js +4 -5
  47. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/index.d.ts +1 -1
  48. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/index.js +1 -1
  49. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/load_and_push_segment.d.ts +26 -0
  50. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/load_and_push_segment.js +60 -0
  51. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/prepare_source_buffer.d.ts +6 -5
  52. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/prepare_source_buffer.js +40 -9
  53. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/remove_buffer_around_time.d.ts +3 -2
  54. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/remove_buffer_around_time.js +7 -14
  55. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/types.d.ts +1 -1
  56. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/{thumbnail_loader.d.ts → video_thumbnail_loader.d.ts} +1 -13
  57. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.js +331 -0
  58. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader_error.d.ts +1 -2
  59. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader_error.js +1 -2
  60. package/dist/_esm5.processed/features/initialize_features.js +2 -1
  61. package/dist/_esm5.processed/features/list/directfile.js +1 -1
  62. package/dist/_esm5.processed/features/types.d.ts +1 -1
  63. package/dist/_esm5.processed/manifest/index.d.ts +2 -2
  64. package/dist/_esm5.processed/public_types.d.ts +47 -0
  65. package/dist/_esm5.processed/utils/reference.d.ts +23 -3
  66. package/dist/_esm5.processed/utils/reference.js +23 -2
  67. package/dist/rx-player.js +1253 -1014
  68. package/dist/rx-player.min.js +1 -1
  69. package/package.json +1 -1
  70. package/sonar-project.properties +1 -1
  71. package/src/core/api/README.md +1 -1
  72. package/src/core/api/__tests__/{get_player_state.test.ts → utils.test.ts} +1 -1
  73. package/src/core/api/option_utils.ts +1 -5
  74. package/src/core/api/public_api.ts +15 -13
  75. package/src/core/api/{__tests__ → tracks_management/__tests__}/media_element_track_choice_manager.test.ts +0 -0
  76. package/src/core/api/{media_element_track_choice_manager.ts → tracks_management/media_element_track_choice_manager.ts} +10 -7
  77. package/src/core/api/{track_choice_manager.ts → tracks_management/track_choice_manager.ts} +9 -9
  78. package/src/core/api/{get_player_state.ts → utils.ts} +62 -11
  79. package/src/core/decrypt/content_decryptor.ts +112 -13
  80. package/src/core/decrypt/session_events_listener.ts +34 -30
  81. package/src/core/decrypt/utils/check_key_statuses.ts +89 -45
  82. package/src/core/decrypt/utils/persistent_sessions_store.ts +1 -2
  83. package/src/core/fetchers/index.ts +0 -12
  84. package/src/core/fetchers/segment/__tests__/task_prioritizer.test.ts +763 -0
  85. package/src/core/fetchers/segment/index.ts +0 -12
  86. package/src/core/fetchers/segment/prioritized_segment_fetcher.ts +40 -47
  87. package/src/core/fetchers/segment/segment_fetcher.ts +249 -268
  88. package/src/core/fetchers/segment/segment_fetcher_creator.ts +6 -7
  89. package/src/core/fetchers/segment/task_prioritizer.ts +460 -0
  90. package/src/core/fetchers/utils/try_urls_with_backoff.ts +3 -3
  91. package/src/core/init/create_media_source.ts +1 -1
  92. package/src/core/init/stall_avoider.ts +2 -1
  93. package/src/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.ts +1 -1
  94. package/src/core/segment_buffers/implementations/text/html/html_text_segment_buffer.ts +3 -3
  95. package/src/core/segment_buffers/implementations/types.ts +6 -2
  96. package/src/core/stream/orchestrator/{get_blacklisted_ranges.ts → get_time_ranges_for_content.ts} +1 -1
  97. package/src/core/stream/orchestrator/stream_orchestrator.ts +115 -56
  98. package/src/core/stream/representation/downloading_queue.ts +269 -142
  99. package/src/core/stream/types.ts +3 -1
  100. package/src/errors/encrypted_media_error.ts +20 -1
  101. package/src/experimental/tools/VideoThumbnailLoader/index.ts +1 -1
  102. package/src/experimental/tools/VideoThumbnailLoader/load_and_push_segment.ts +74 -0
  103. package/src/experimental/tools/VideoThumbnailLoader/prepare_source_buffer.ts +50 -16
  104. package/src/experimental/tools/VideoThumbnailLoader/remove_buffer_around_time.ts +14 -21
  105. package/src/experimental/tools/VideoThumbnailLoader/types.ts +7 -4
  106. package/src/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.ts +407 -0
  107. package/src/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader_error.ts +1 -2
  108. package/src/features/__tests__/initialize_features.test.ts +3 -1
  109. package/src/features/initialize_features.ts +2 -1
  110. package/src/features/list/__tests__/directfile.test.ts +1 -1
  111. package/src/features/list/directfile.ts +1 -1
  112. package/src/features/types.ts +1 -1
  113. package/src/manifest/index.ts +2 -0
  114. package/src/public_types.ts +53 -0
  115. package/src/utils/reference.ts +58 -4
  116. package/dist/_esm5.processed/core/api/get_player_state.d.ts +0 -28
  117. package/dist/_esm5.processed/core/api/get_player_state.js +0 -56
  118. package/dist/_esm5.processed/core/fetchers/segment/prioritizer.d.ts +0 -232
  119. package/dist/_esm5.processed/core/fetchers/segment/prioritizer.js +0 -422
  120. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/create_request.d.ts +0 -29
  121. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/create_request.js +0 -68
  122. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/get_complete_segment_id.d.ts +0 -24
  123. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/get_complete_segment_id.js +0 -29
  124. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/get_content_infos.d.ts +0 -25
  125. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/get_content_infos.js +0 -40
  126. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/get_initialized_source_buffer.d.ts +0 -33
  127. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/get_initialized_source_buffer.js +0 -124
  128. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/load_segments.d.ts +0 -17
  129. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/load_segments.js +0 -41
  130. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/push_data.d.ts +0 -22
  131. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/push_data.js +0 -21
  132. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/thumbnail_loader.js +0 -212
  133. package/src/core/api/emit_seek_events.ts +0 -66
  134. package/src/core/fetchers/segment/__tests__/prioritizer.test.ts +0 -962
  135. package/src/core/fetchers/segment/prioritizer.ts +0 -558
  136. package/src/experimental/tools/VideoThumbnailLoader/create_request.ts +0 -113
  137. package/src/experimental/tools/VideoThumbnailLoader/get_complete_segment_id.ts +0 -34
  138. package/src/experimental/tools/VideoThumbnailLoader/get_content_infos.ts +0 -48
  139. package/src/experimental/tools/VideoThumbnailLoader/get_initialized_source_buffer.ts +0 -171
  140. package/src/experimental/tools/VideoThumbnailLoader/load_segments.ts +0 -69
  141. package/src/experimental/tools/VideoThumbnailLoader/push_data.ts +0 -48
  142. 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} request$
81
+ * @param {Function} performRequest
82
82
  * @param {Object} options
83
- * @returns {Observable}
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 {Observable}
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} request$
257
+ * @param {Function} performRequest
258
258
  * @param {Object} options
259
- * @returns {Observable}
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 (videoElt.paused || videoElt.playbackRate <= 0) {
329
- time = videoElt.currentTime;
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 none.
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 getBlacklistedRanges(segmentBuffer: SegmentBuffer, contents: Array<{
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 getBlacklistedRanges(segmentBuffer, contents) {
24
+ export default function getTimeRangesForContent(segmentBuffer, contents) {
25
25
  if (contents.length === 0) {
26
26
  return [];
27
27
  }