rx-player 3.28.1-dev.2022083000 → 3.29.0-dev.2022090500

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 (139) hide show
  1. package/CHANGELOG.md +11 -1
  2. package/VERSION +1 -1
  3. package/dist/_esm5.processed/compat/event_listeners.d.ts +18 -2
  4. package/dist/_esm5.processed/compat/event_listeners.js +64 -2
  5. package/dist/_esm5.processed/compat/on_height_width_change.d.ts +5 -4
  6. package/dist/_esm5.processed/compat/on_height_width_change.js +43 -34
  7. package/dist/_esm5.processed/core/api/playback_observer.d.ts +12 -2
  8. package/dist/_esm5.processed/core/api/playback_observer.js +27 -12
  9. package/dist/_esm5.processed/core/api/public_api.js +14 -14
  10. package/dist/_esm5.processed/core/fetchers/manifest/manifest_fetcher.d.ts +7 -0
  11. package/dist/_esm5.processed/core/fetchers/manifest/manifest_fetcher.js +10 -2
  12. package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher.d.ts +8 -1
  13. package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher.js +10 -4
  14. package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher_creator.d.ts +7 -0
  15. package/dist/_esm5.processed/core/init/initialize_directfile.js +1 -1
  16. package/dist/_esm5.processed/core/init/load_on_media_source.js +1 -1
  17. package/dist/_esm5.processed/core/init/stall_avoider.d.ts +4 -2
  18. package/dist/_esm5.processed/core/init/stall_avoider.js +32 -26
  19. package/dist/_esm5.processed/core/segment_buffers/garbage_collector.d.ts +12 -6
  20. package/dist/_esm5.processed/core/segment_buffers/garbage_collector.js +142 -78
  21. package/dist/_esm5.processed/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.d.ts +18 -16
  22. package/dist/_esm5.processed/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.js +53 -41
  23. package/dist/_esm5.processed/core/segment_buffers/implementations/image/image_segment_buffer.d.ts +6 -5
  24. package/dist/_esm5.processed/core/segment_buffers/implementations/image/image_segment_buffer.js +37 -39
  25. package/dist/_esm5.processed/core/segment_buffers/implementations/text/html/html_text_segment_buffer.d.ts +23 -22
  26. package/dist/_esm5.processed/core/segment_buffers/implementations/text/html/html_text_segment_buffer.js +84 -72
  27. package/dist/_esm5.processed/core/segment_buffers/implementations/text/native/native_text_segment_buffer.d.ts +6 -12
  28. package/dist/_esm5.processed/core/segment_buffers/implementations/text/native/native_text_segment_buffer.js +33 -43
  29. package/dist/_esm5.processed/core/segment_buffers/implementations/types.d.ts +12 -9
  30. package/dist/_esm5.processed/core/segment_buffers/segment_buffers_store.d.ts +7 -6
  31. package/dist/_esm5.processed/core/segment_buffers/segment_buffers_store.js +17 -10
  32. package/dist/_esm5.processed/core/stream/orchestrator/stream_orchestrator.js +20 -9
  33. package/dist/_esm5.processed/core/stream/period/period_stream.js +25 -14
  34. package/dist/_esm5.processed/core/stream/representation/append_segment_to_buffer.d.ts +4 -7
  35. package/dist/_esm5.processed/core/stream/representation/append_segment_to_buffer.js +80 -23
  36. package/dist/_esm5.processed/core/stream/representation/force_garbage_collection.d.ts +5 -4
  37. package/dist/_esm5.processed/core/stream/representation/force_garbage_collection.js +78 -26
  38. package/dist/_esm5.processed/core/stream/representation/get_buffer_status.js +7 -3
  39. package/dist/_esm5.processed/core/stream/representation/push_init_segment.js +7 -1
  40. package/dist/_esm5.processed/core/stream/representation/push_media_segment.js +7 -1
  41. package/dist/_esm5.processed/core/stream/representation/representation_stream.js +15 -8
  42. package/dist/_esm5.processed/default_config.js +1 -1
  43. package/dist/_esm5.processed/errors/custom_loader_error.d.ts +3 -2
  44. package/dist/_esm5.processed/errors/custom_loader_error.js +3 -2
  45. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/get_initialized_source_buffer.js +5 -2
  46. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/push_data.js +5 -2
  47. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/remove_buffer_around_time.js +9 -2
  48. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/thumbnail_loader.js +3 -1
  49. package/dist/_esm5.processed/experimental/tools/createMetaplaylist/get_duration_from_manifest.js +4 -3
  50. package/dist/_esm5.processed/public_types.d.ts +22 -3
  51. package/dist/_esm5.processed/transports/dash/add_segment_integrity_checks_to_loader.js +2 -2
  52. package/dist/_esm5.processed/transports/dash/image_pipelines.d.ts +3 -2
  53. package/dist/_esm5.processed/transports/dash/image_pipelines.js +3 -1
  54. package/dist/_esm5.processed/transports/dash/init_segment_loader.d.ts +3 -2
  55. package/dist/_esm5.processed/transports/dash/init_segment_loader.js +12 -6
  56. package/dist/_esm5.processed/transports/dash/low_latency_segment_loader.d.ts +3 -2
  57. package/dist/_esm5.processed/transports/dash/low_latency_segment_loader.js +3 -2
  58. package/dist/_esm5.processed/transports/dash/manifest_parser.js +6 -2
  59. package/dist/_esm5.processed/transports/dash/segment_loader.d.ts +3 -2
  60. package/dist/_esm5.processed/transports/dash/segment_loader.js +12 -9
  61. package/dist/_esm5.processed/transports/dash/text_loader.js +6 -3
  62. package/dist/_esm5.processed/transports/local/pipelines.d.ts +2 -2
  63. package/dist/_esm5.processed/transports/local/pipelines.js +6 -6
  64. package/dist/_esm5.processed/transports/local/segment_loader.d.ts +3 -2
  65. package/dist/_esm5.processed/transports/local/segment_loader.js +4 -3
  66. package/dist/_esm5.processed/transports/metaplaylist/manifest_loader.d.ts +2 -2
  67. package/dist/_esm5.processed/transports/metaplaylist/manifest_loader.js +5 -2
  68. package/dist/_esm5.processed/transports/metaplaylist/pipelines.js +15 -10
  69. package/dist/_esm5.processed/transports/smooth/pipelines.d.ts +1 -1
  70. package/dist/_esm5.processed/transports/smooth/pipelines.js +18 -14
  71. package/dist/_esm5.processed/transports/smooth/segment_loader.d.ts +2 -2
  72. package/dist/_esm5.processed/transports/smooth/segment_loader.js +8 -6
  73. package/dist/_esm5.processed/transports/types.d.ts +25 -2
  74. package/dist/_esm5.processed/transports/utils/call_custom_manifest_loader.d.ts +2 -2
  75. package/dist/_esm5.processed/transports/utils/call_custom_manifest_loader.js +3 -3
  76. package/dist/_esm5.processed/transports/utils/generate_manifest_loader.d.ts +2 -2
  77. package/dist/_esm5.processed/transports/utils/generate_manifest_loader.js +9 -6
  78. package/dist/_esm5.processed/utils/request/fetch.js +7 -8
  79. package/dist/_esm5.processed/utils/request/xhr.d.ts +1 -1
  80. package/dist/_esm5.processed/utils/request/xhr.js +28 -14
  81. package/dist/_esm5.processed/utils/task_canceller.d.ts +1 -2
  82. package/dist/_esm5.processed/utils/task_canceller.js +1 -2
  83. package/dist/mpd-parser.wasm +0 -0
  84. package/dist/rx-player.js +1116 -695
  85. package/dist/rx-player.min.js +1 -1
  86. package/package.json +7 -7
  87. package/sonar-project.properties +1 -1
  88. package/src/compat/event_listeners.ts +86 -1
  89. package/src/compat/on_height_width_change.ts +48 -49
  90. package/src/core/api/playback_observer.ts +34 -14
  91. package/src/core/api/public_api.ts +23 -18
  92. package/src/core/fetchers/manifest/manifest_fetcher.ts +20 -2
  93. package/src/core/fetchers/segment/segment_fetcher.ts +23 -3
  94. package/src/core/fetchers/segment/segment_fetcher_creator.ts +7 -0
  95. package/src/core/init/initialize_directfile.ts +1 -1
  96. package/src/core/init/load_on_media_source.ts +1 -0
  97. package/src/core/init/stall_avoider.ts +40 -26
  98. package/src/core/segment_buffers/garbage_collector.ts +55 -47
  99. package/src/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.ts +92 -70
  100. package/src/core/segment_buffers/implementations/image/image_segment_buffer.ts +37 -42
  101. package/src/core/segment_buffers/implementations/text/html/html_text_segment_buffer.ts +103 -105
  102. package/src/core/segment_buffers/implementations/text/native/native_text_segment_buffer.ts +35 -46
  103. package/src/core/segment_buffers/implementations/types.ts +22 -9
  104. package/src/core/segment_buffers/segment_buffers_store.ts +23 -14
  105. package/src/core/stream/orchestrator/stream_orchestrator.ts +31 -12
  106. package/src/core/stream/period/period_stream.ts +31 -18
  107. package/src/core/stream/representation/append_segment_to_buffer.ts +27 -42
  108. package/src/core/stream/representation/force_garbage_collection.ts +28 -32
  109. package/src/core/stream/representation/get_buffer_status.ts +7 -3
  110. package/src/core/stream/representation/push_init_segment.ts +12 -6
  111. package/src/core/stream/representation/push_media_segment.ts +12 -6
  112. package/src/core/stream/representation/representation_stream.ts +11 -5
  113. package/src/default_config.ts +17 -17
  114. package/src/errors/custom_loader_error.ts +3 -2
  115. package/src/experimental/tools/VideoThumbnailLoader/get_initialized_source_buffer.ts +7 -2
  116. package/src/experimental/tools/VideoThumbnailLoader/push_data.ts +6 -2
  117. package/src/experimental/tools/VideoThumbnailLoader/remove_buffer_around_time.ts +10 -2
  118. package/src/experimental/tools/VideoThumbnailLoader/thumbnail_loader.ts +3 -1
  119. package/src/experimental/tools/createMetaplaylist/get_duration_from_manifest.ts +4 -3
  120. package/src/public_types.ts +28 -4
  121. package/src/transports/dash/add_segment_integrity_checks_to_loader.ts +2 -2
  122. package/src/transports/dash/image_pipelines.ts +4 -0
  123. package/src/transports/dash/init_segment_loader.ts +8 -0
  124. package/src/transports/dash/low_latency_segment_loader.ts +4 -0
  125. package/src/transports/dash/manifest_parser.ts +4 -0
  126. package/src/transports/dash/segment_loader.ts +21 -5
  127. package/src/transports/dash/text_loader.ts +7 -2
  128. package/src/transports/local/pipelines.ts +7 -5
  129. package/src/transports/local/segment_loader.ts +4 -2
  130. package/src/transports/metaplaylist/manifest_loader.ts +9 -2
  131. package/src/transports/metaplaylist/pipelines.ts +16 -6
  132. package/src/transports/smooth/pipelines.ts +17 -9
  133. package/src/transports/smooth/segment_loader.ts +8 -0
  134. package/src/transports/types.ts +27 -0
  135. package/src/transports/utils/call_custom_manifest_loader.ts +8 -2
  136. package/src/transports/utils/generate_manifest_loader.ts +18 -5
  137. package/src/utils/request/fetch.ts +7 -8
  138. package/src/utils/request/xhr.ts +31 -15
  139. package/src/utils/task_canceller.ts +1 -2
@@ -14,11 +14,6 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import {
18
- defer as observableDefer,
19
- Observable,
20
- of as observableOf,
21
- } from "rxjs";
22
17
  import log from "../../../../log";
23
18
  import { IBifThumbnail } from "../../../../parsers/images/bif";
24
19
  import {
@@ -45,55 +40,57 @@ export default class ImageSegmentBuffer extends SegmentBuffer {
45
40
 
46
41
  /**
47
42
  * @param {Object} data
43
+ * @returns {Promise}
48
44
  */
49
45
  public pushChunk(
50
46
  infos : IPushChunkInfos<unknown>
51
- ) : Observable<void> {
52
- return observableDefer(() => {
53
- log.debug("ISB: appending new data.");
54
- if (infos.data.chunk === null) {
55
- return observableOf(undefined);
56
- }
57
- const { appendWindow,
58
- chunk } = infos.data;
47
+ ) : Promise<void> {
48
+ log.debug("ISB: appending new data.");
49
+ if (infos.data.chunk === null) {
50
+ return Promise.resolve();
51
+ }
52
+ const { appendWindow,
53
+ chunk } = infos.data;
59
54
 
60
- // The following check is ugly. I don't care, the image buffer is there
61
- // due to an ugly deprecated API that will soon disappear
62
- const { start, end, timescale } = chunk as IImageTrackSegmentData;
63
- const appendWindowStart = appendWindow[0] ?? 0;
64
- const appendWindowEnd = appendWindow[1] ?? Infinity;
55
+ // The following check is ugly. I don't care, the image buffer is there
56
+ // due to an ugly deprecated API that will soon disappear
57
+ const { start, end, timescale } = chunk as IImageTrackSegmentData;
58
+ const appendWindowStart = appendWindow[0] ?? 0;
59
+ const appendWindowEnd = appendWindow[1] ?? Infinity;
65
60
 
66
- const timescaledStart = start / timescale;
67
- const timescaledEnd = end / timescale;
61
+ const timescaledStart = start / timescale;
62
+ const timescaledEnd = end / timescale;
68
63
 
69
- const startTime = Math.max(appendWindowStart, timescaledStart);
70
- const endTime = Math.min(appendWindowEnd, timescaledEnd);
64
+ const startTime = Math.max(appendWindowStart, timescaledStart);
65
+ const endTime = Math.min(appendWindowEnd, timescaledEnd);
71
66
 
67
+ try {
72
68
  this._buffered.insert(startTime, endTime);
73
69
  if (infos.inventoryInfos !== null) {
74
70
  this._segmentInventory.insertChunk(infos.inventoryInfos);
75
71
  }
76
- return observableOf(undefined);
77
- });
72
+ } catch (err) {
73
+ return Promise.reject(err);
74
+ }
75
+ return Promise.resolve();
78
76
  }
79
77
 
80
78
  /**
81
79
  * @param {Number} from
82
80
  * @param {Number} to
81
+ * @returns {Promise}
83
82
  */
84
- public removeBuffer(start : number, end : number) : Observable<void> {
85
- return observableDefer(() => {
86
- log.info("ISB: ignored image data remove order", start, end);
83
+ public removeBuffer(start : number, end : number) : Promise<void> {
84
+ log.info("ISB: ignored image data remove order", start, end);
87
85
 
88
- // Logic removed as it caused more problems than it resolved:
89
- // Image thumbnails are always downloaded as a single BIF file, meaning that
90
- // any removing might necessitate to re-load the whole file in the future
91
- // which seems pointless.
92
- // In any case, image handling through the regular RxPlayer APIs has been
93
- // completely deprecated now for several reasons, and should disappear in
94
- // the next major version.
95
- return observableOf(undefined);
96
- });
86
+ // Logic removed as it caused more problems than it resolved:
87
+ // Image thumbnails are always downloaded as a single BIF file, meaning that
88
+ // any removing might necessitate to re-load the whole file in the future
89
+ // which seems pointless.
90
+ // In any case, image handling through the regular RxPlayer APIs has been
91
+ // completely deprecated now for several reasons, and should disappear in
92
+ // the next major version.
93
+ return Promise.resolve();
97
94
  }
98
95
 
99
96
  /**
@@ -103,13 +100,11 @@ export default class ImageSegmentBuffer extends SegmentBuffer {
103
100
  * The returned Observable will emit and complete successively once the whole
104
101
  * segment has been pushed and this indication is acknowledged.
105
102
  * @param {Object} infos
106
- * @returns {Observable}
103
+ * @returns {Promise}
107
104
  */
108
- public endOfSegment(_infos : IEndOfSegmentInfos) : Observable<void> {
109
- return observableDefer(() => {
110
- this._segmentInventory.completeSegment(_infos, this._buffered);
111
- return observableOf(undefined);
112
- });
105
+ public endOfSegment(_infos : IEndOfSegmentInfos) : Promise<void> {
106
+ this._segmentInventory.completeSegment(_infos, this._buffered);
107
+ return Promise.resolve();
113
108
  }
114
109
 
115
110
  /**
@@ -14,19 +14,6 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import {
18
- concat as observableConcat,
19
- defer as observableDefer,
20
- interval as observableInterval,
21
- map,
22
- merge as observableMerge,
23
- Observable,
24
- of as observableOf,
25
- startWith,
26
- Subject,
27
- switchMap,
28
- takeUntil,
29
- } from "rxjs";
30
17
  import {
31
18
  events,
32
19
  onHeightWidthChange,
@@ -34,6 +21,9 @@ import {
34
21
  import config from "../../../../../config";
35
22
  import log from "../../../../../log";
36
23
  import { ITextTrackSegmentData } from "../../../../../transports";
24
+ import TaskCanceller, {
25
+ CancellationSignal,
26
+ } from "../../../../../utils/task_canceller";
37
27
  import {
38
28
  IEndOfSegmentInfos,
39
29
  IPushChunkInfos,
@@ -44,31 +34,7 @@ import parseTextTrackToElements from "./parsers";
44
34
  import TextTrackCuesStore from "./text_track_cues_store";
45
35
  import updateProportionalElements from "./update_proportional_elements";
46
36
 
47
- const { onEnded$,
48
- onSeeked$,
49
- onSeeking$ } = events;
50
-
51
-
52
- /**
53
- * Generate the interval at which TextTrack HTML Cues should be refreshed.
54
- * @param {HTMLMediaElement} videoElement
55
- * @returns {Observable}
56
- */
57
- function generateRefreshInterval(videoElement : HTMLMediaElement) : Observable<boolean> {
58
- const seeking$ = onSeeking$(videoElement);
59
- const seeked$ = onSeeked$(videoElement);
60
- const ended$ = onEnded$(videoElement);
61
- const { MAXIMUM_HTML_TEXT_TRACK_UPDATE_INTERVAL } = config.getCurrent();
62
- const manualRefresh$ = observableMerge(seeked$, ended$);
63
- const autoRefresh$ = observableInterval(MAXIMUM_HTML_TEXT_TRACK_UPDATE_INTERVAL)
64
- .pipe(startWith(null));
65
-
66
- return manualRefresh$.pipe(
67
- startWith(null),
68
- switchMap(() => observableConcat(autoRefresh$.pipe(map(() => true),
69
- takeUntil(seeking$)),
70
- observableOf(false))));
71
- }
37
+ const { onEnded, onSeeked, onSeeking } = events;
72
38
 
73
39
  /**
74
40
  * @param {Element} element
@@ -116,12 +82,8 @@ export default class HTMLTextSegmentBuffer extends SegmentBuffer {
116
82
  */
117
83
  private readonly _videoElement : HTMLMediaElement;
118
84
 
119
- /**
120
- * When "nexting" that subject, every Observable declared here will be
121
- * unsubscribed.
122
- * Used for clean-up
123
- */
124
- private readonly _destroy$ : Subject<void>;
85
+ /** Used for clean-up. */
86
+ private readonly _canceller : TaskCanceller;
125
87
 
126
88
  /** HTMLElement which will contain the cues */
127
89
  private readonly _textTrackElement : HTMLElement;
@@ -131,10 +93,10 @@ export default class HTMLTextSegmentBuffer extends SegmentBuffer {
131
93
 
132
94
  /**
133
95
  * We could need us to automatically update styling depending on
134
- * `_textTrackElement`'s size. This Subject allows to stop that
96
+ * `_textTrackElement`'s size. This TaskCanceller allows to stop that
135
97
  * regular check.
136
98
  */
137
- private _clearSizeUpdates$ : Subject<void>;
99
+ private _sizeUpdateCanceller : TaskCanceller;
138
100
 
139
101
  /** Information on cues currently displayed. */
140
102
  private _currentCues : Array<{
@@ -167,72 +129,46 @@ export default class HTMLTextSegmentBuffer extends SegmentBuffer {
167
129
 
168
130
  this._videoElement = videoElement;
169
131
  this._textTrackElement = textTrackElement;
170
- this._clearSizeUpdates$ = new Subject();
171
- this._destroy$ = new Subject();
132
+ this._sizeUpdateCanceller = new TaskCanceller();
133
+ this._canceller = new TaskCanceller();
172
134
  this._buffer = new TextTrackCuesStore();
173
135
  this._currentCues = [];
174
136
 
175
- // update text tracks
176
- generateRefreshInterval(this._videoElement)
177
- .pipe(takeUntil(this._destroy$))
178
- .subscribe((shouldDisplay) => {
179
- if (!shouldDisplay) {
180
- this._disableCurrentCues();
181
- return;
182
- }
183
- const { MAXIMUM_HTML_TEXT_TRACK_UPDATE_INTERVAL } = config.getCurrent();
184
- // to spread the time error, we divide the regular chosen interval.
185
- const time = Math.max(this._videoElement.currentTime +
186
- (MAXIMUM_HTML_TEXT_TRACK_UPDATE_INTERVAL / 1000) / 2,
187
- 0);
188
- const cues = this._buffer.get(time);
189
- if (cues.length === 0) {
190
- this._disableCurrentCues();
191
- } else {
192
- this._displayCues(cues);
193
- }
194
- });
137
+ this.autoRefreshSubtitles(this._canceller.signal);
195
138
  }
196
139
 
197
140
  /**
198
141
  * Push segment on Subscription.
199
142
  * @param {Object} infos
200
- * @returns {Observable}
143
+ * @returns {Promise}
201
144
  */
202
- public pushChunk(infos : IPushChunkInfos<unknown>) : Observable<void> {
203
- return observableDefer(() => {
145
+ public pushChunk(infos : IPushChunkInfos<unknown>) : Promise<void> {
146
+ try {
204
147
  this.pushChunkSync(infos);
205
- return observableOf(undefined);
206
- });
148
+ } catch (err) {
149
+ return Promise.reject(err);
150
+ }
151
+ return Promise.resolve();
207
152
  }
208
153
 
209
154
  /**
210
155
  * Remove buffered data.
211
156
  * @param {number} start - start position, in seconds
212
157
  * @param {number} end - end position, in seconds
213
- * @returns {Observable}
158
+ * @returns {Promise}
214
159
  */
215
- public removeBuffer(start : number, end : number) : Observable<void> {
216
- return observableDefer(() => {
217
- this.removeBufferSync(start, end);
218
- return observableOf(undefined);
219
- });
160
+ public removeBuffer(start : number, end : number) : Promise<void> {
161
+ this.removeBufferSync(start, end);
162
+ return Promise.resolve();
220
163
  }
221
164
 
222
165
  /**
223
- * Indicate that every chunks from a Segment has been given to pushChunk so
224
- * far.
225
- * This will update our internal Segment inventory accordingly.
226
- * The returned Observable will emit and complete successively once the whole
227
- * segment has been pushed and this indication is acknowledged.
228
166
  * @param {Object} infos
229
- * @returns {Observable}
167
+ * @returns {Promise}
230
168
  */
231
- public endOfSegment(_infos : IEndOfSegmentInfos) : Observable<void> {
232
- return observableDefer(() => {
233
- this._segmentInventory.completeSegment(_infos, this._buffered);
234
- return observableOf(undefined);
235
- });
169
+ public endOfSegment(infos : IEndOfSegmentInfos) : Promise<void> {
170
+ this._segmentInventory.completeSegment(infos, this._buffered);
171
+ return Promise.resolve();
236
172
  }
237
173
 
238
174
  /**
@@ -248,8 +184,7 @@ export default class HTMLTextSegmentBuffer extends SegmentBuffer {
248
184
  this._disableCurrentCues();
249
185
  this._buffer.remove(0, Infinity);
250
186
  this._buffered.remove(0, Infinity);
251
- this._destroy$.next();
252
- this._destroy$.complete();
187
+ this._canceller.cancel();
253
188
  }
254
189
 
255
190
  /**
@@ -264,7 +199,7 @@ export default class HTMLTextSegmentBuffer extends SegmentBuffer {
264
199
  *
265
200
  * /!\ This method won't add any data to the linked inventory.
266
201
  * Please use the `pushChunk` method for most use-cases.
267
- * @param {Object} data
202
+ * @param {Object} infos
268
203
  * @returns {boolean}
269
204
  */
270
205
  public pushChunkSync(infos : IPushChunkInfos<unknown>) : void {
@@ -375,7 +310,7 @@ export default class HTMLTextSegmentBuffer extends SegmentBuffer {
375
310
  * Remove the current cue from being displayed.
376
311
  */
377
312
  private _disableCurrentCues() : void {
378
- this._clearSizeUpdates$.next();
313
+ this._sizeUpdateCanceller.cancel();
379
314
  if (this._currentCues.length > 0) {
380
315
  for (let i = 0; i < this._currentCues.length; i++) {
381
316
  safelyRemoveChild(this._textTrackElement, this._currentCues[i].element);
@@ -386,7 +321,7 @@ export default class HTMLTextSegmentBuffer extends SegmentBuffer {
386
321
 
387
322
  /**
388
323
  * Display a new Cue. If one was already present, it will be replaced.
389
- * @param {HTMLElement} element
324
+ * @param {HTMLElement} elements
390
325
  */
391
326
  private _displayCues(elements : HTMLElement[]) : void {
392
327
  const nothingChanged = this._currentCues.length === elements.length &&
@@ -399,7 +334,7 @@ export default class HTMLTextSegmentBuffer extends SegmentBuffer {
399
334
  // Remove and re-display everything
400
335
  // TODO More intelligent handling
401
336
 
402
- this._clearSizeUpdates$.next();
337
+ this._sizeUpdateCanceller.cancel();
403
338
  for (let i = 0; i < this._currentCues.length; i++) {
404
339
  safelyRemoveChild(this._textTrackElement, this._currentCues[i].element);
405
340
  }
@@ -418,17 +353,80 @@ export default class HTMLTextSegmentBuffer extends SegmentBuffer {
418
353
  element : HTMLElement; } => cue.resolution !== null);
419
354
 
420
355
  if (proportionalCues.length > 0) {
356
+ this._sizeUpdateCanceller = new TaskCanceller({ cancelOn: this._canceller.signal });
421
357
  const { TEXT_TRACK_SIZE_CHECKS_INTERVAL } = config.getCurrent();
422
358
  // update propertionally-sized elements periodically
423
- onHeightWidthChange(this._textTrackElement, TEXT_TRACK_SIZE_CHECKS_INTERVAL)
424
- .pipe(takeUntil(this._clearSizeUpdates$),
425
- takeUntil(this._destroy$))
426
- .subscribe(({ height, width }) => {
427
- for (let i = 0; i < proportionalCues.length; i++) {
428
- const { resolution, element } = proportionalCues[i];
429
- updateProportionalElements(height, width, resolution, element);
430
- }
431
- });
359
+ const heightWidthRef = onHeightWidthChange(this._textTrackElement,
360
+ TEXT_TRACK_SIZE_CHECKS_INTERVAL,
361
+ this._sizeUpdateCanceller.signal);
362
+ heightWidthRef.onUpdate(({ height, width }) => {
363
+ for (let i = 0; i < proportionalCues.length; i++) {
364
+ const { resolution, element } = proportionalCues[i];
365
+ updateProportionalElements(height, width, resolution, element);
366
+ }
367
+ }, { clearSignal: this._sizeUpdateCanceller.signal,
368
+ emitCurrentValue: true });
369
+ }
370
+ }
371
+
372
+ /**
373
+ * Auto-refresh the display of subtitles according to the media element's
374
+ * position and events.
375
+ * @param {Object} cancellationSignal
376
+ */
377
+ private autoRefreshSubtitles(
378
+ cancellationSignal : CancellationSignal
379
+ ) : void {
380
+ let autoRefreshCanceller : TaskCanceller | null = null;
381
+ const { MAXIMUM_HTML_TEXT_TRACK_UPDATE_INTERVAL } = config.getCurrent();
382
+
383
+ const startAutoRefresh = () => {
384
+ stopAutoRefresh();
385
+ autoRefreshCanceller = new TaskCanceller({ cancelOn: cancellationSignal });
386
+ const intervalId = setInterval(() => this.refreshSubtitles(),
387
+ MAXIMUM_HTML_TEXT_TRACK_UPDATE_INTERVAL);
388
+ autoRefreshCanceller.signal.register(() => {
389
+ clearInterval(intervalId);
390
+ });
391
+ this.refreshSubtitles();
392
+ };
393
+
394
+ onSeeking(this._videoElement, () => {
395
+ stopAutoRefresh();
396
+ this._disableCurrentCues();
397
+ }, cancellationSignal);
398
+ onSeeked(this._videoElement, startAutoRefresh, cancellationSignal);
399
+ onEnded(this._videoElement, startAutoRefresh, cancellationSignal);
400
+
401
+ function stopAutoRefresh() {
402
+ if (autoRefreshCanceller !== null) {
403
+ autoRefreshCanceller.cancel();
404
+ autoRefreshCanceller = null;
405
+ }
406
+ }
407
+ }
408
+
409
+ /**
410
+ * Refresh current subtitles according to the current media element's
411
+ * position.
412
+ */
413
+ private refreshSubtitles() : void {
414
+ const videoElt = this._videoElement;
415
+ const { MAXIMUM_HTML_TEXT_TRACK_UPDATE_INTERVAL } = config.getCurrent();
416
+ let time;
417
+ if (videoElt.paused || videoElt.playbackRate <= 0) {
418
+ time = videoElt.currentTime;
419
+ } else {
420
+ // to spread the time error, we divide the regular chosen interval.
421
+ time = Math.max(this._videoElement.currentTime +
422
+ (MAXIMUM_HTML_TEXT_TRACK_UPDATE_INTERVAL / 1000) / 2,
423
+ 0);
424
+ }
425
+ const cues = this._buffer.get(time);
426
+ if (cues.length === 0) {
427
+ this._disableCurrentCues();
428
+ } else {
429
+ this._displayCues(cues);
432
430
  }
433
431
  }
434
432
  }
@@ -14,11 +14,6 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import {
18
- defer as observableDefer,
19
- Observable,
20
- of as observableOf,
21
- } from "rxjs";
22
17
  import {
23
18
  addTextTrack,
24
19
  ICompatTextTrack,
@@ -73,26 +68,26 @@ export default class NativeTextSegmentBuffer extends SegmentBuffer {
73
68
 
74
69
  /**
75
70
  * @param {Object} infos
76
- * @returns {Observable}
71
+ * @returns {Promise}
77
72
  */
78
- public pushChunk(infos : IPushChunkInfos<unknown>) : Observable<void> {
79
- return observableDefer(() => {
80
- log.debug("NTSB: Appending new native text tracks");
81
- if (infos.data.chunk === null) {
82
- return observableOf(undefined);
83
- }
84
- const { timestampOffset,
85
- appendWindow,
86
- chunk } = infos.data;
87
- assertChunkIsTextTrackSegmentData(chunk);
88
- const { start: startTime,
89
- end: endTime,
90
- data: dataString,
91
- type,
92
- language } = chunk;
93
- const appendWindowStart = appendWindow[0] ?? 0;
94
- const appendWindowEnd = appendWindow[1] ?? Infinity;
95
-
73
+ public pushChunk(infos : IPushChunkInfos<unknown>) : Promise<void> {
74
+ log.debug("NTSB: Appending new native text tracks");
75
+ if (infos.data.chunk === null) {
76
+ return Promise.resolve();
77
+ }
78
+ const { timestampOffset,
79
+ appendWindow,
80
+ chunk } = infos.data;
81
+ assertChunkIsTextTrackSegmentData(chunk);
82
+ const { start: startTime,
83
+ end: endTime,
84
+ data: dataString,
85
+ type,
86
+ language } = chunk;
87
+ const appendWindowStart = appendWindow[0] ?? 0;
88
+ const appendWindowEnd = appendWindow[1] ?? Infinity;
89
+
90
+ try {
96
91
  const cues = parseTextTrackToCues(type, dataString, timestampOffset, language);
97
92
 
98
93
  if (appendWindowStart !== 0 && appendWindowEnd !== Infinity) {
@@ -130,7 +125,7 @@ export default class NativeTextSegmentBuffer extends SegmentBuffer {
130
125
  } else {
131
126
  if (cues.length <= 0) {
132
127
  log.warn("NTSB: Current text tracks have no cues nor start time. Aborting");
133
- return observableOf(undefined);
128
+ return Promise.resolve();
134
129
  }
135
130
  log.warn("NTSB: No start time given. Guessing from cues.");
136
131
  start = cues[0].startTime;
@@ -142,7 +137,7 @@ export default class NativeTextSegmentBuffer extends SegmentBuffer {
142
137
  } else {
143
138
  if (cues.length <= 0) {
144
139
  log.warn("NTSB: Current text tracks have no cues nor end time. Aborting");
145
- return observableOf(undefined);
140
+ return Promise.resolve();
146
141
  }
147
142
  log.warn("NTSB: No end time given. Guessing from cues.");
148
143
  end = cues[cues.length - 1].endTime;
@@ -151,7 +146,7 @@ export default class NativeTextSegmentBuffer extends SegmentBuffer {
151
146
  if (end <= start) {
152
147
  log.warn("NTSB: Invalid text track appended: ",
153
148
  "the start time is inferior or equal to the end time.");
154
- return observableOf(undefined);
149
+ return Promise.resolve();
155
150
  }
156
151
 
157
152
  if (cues.length > 0) {
@@ -178,37 +173,31 @@ export default class NativeTextSegmentBuffer extends SegmentBuffer {
178
173
  if (infos.inventoryInfos !== null) {
179
174
  this._segmentInventory.insertChunk(infos.inventoryInfos);
180
175
  }
181
- return observableOf(undefined);
182
- });
176
+ } catch (err) {
177
+ return Promise.reject(err);
178
+ }
179
+
180
+ return Promise.resolve();
183
181
  }
184
182
 
185
183
  /**
186
184
  * Remove buffered data.
187
185
  * @param {number} start - start position, in seconds
188
186
  * @param {number} end - end position, in seconds
189
- * @returns {Observable}
187
+ * @returns {Promise}
190
188
  */
191
- public removeBuffer(start : number, end : number) : Observable<void> {
192
- return observableDefer(() => {
193
- this._removeData(start, end);
194
- return observableOf(undefined);
195
- });
189
+ public removeBuffer(start : number, end : number) : Promise<void> {
190
+ this._removeData(start, end);
191
+ return Promise.resolve();
196
192
  }
197
193
 
198
194
  /**
199
- * Indicate that every chunks from a Segment has been given to pushChunk so
200
- * far.
201
- * This will update our internal Segment inventory accordingly.
202
- * The returned Observable will emit and complete successively once the whole
203
- * segment has been pushed and this indication is acknowledged.
204
195
  * @param {Object} infos
205
- * @returns {Observable}
196
+ * @returns {Promise}
206
197
  */
207
- public endOfSegment(_infos : IEndOfSegmentInfos) : Observable<void> {
208
- return observableDefer(() => {
209
- this._segmentInventory.completeSegment(_infos, this._buffered);
210
- return observableOf(undefined);
211
- });
198
+ public endOfSegment(_infos : IEndOfSegmentInfos) : Promise<void> {
199
+ this._segmentInventory.completeSegment(_infos, this._buffered);
200
+ return Promise.resolve();
212
201
  }
213
202
 
214
203
  /**
@@ -14,13 +14,13 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import { Observable } from "rxjs";
18
17
  import {
19
18
  Adaptation,
20
19
  ISegment,
21
20
  Period,
22
21
  Representation,
23
22
  } from "../../../manifest";
23
+ import { CancellationSignal } from "../../../utils/task_canceller";
24
24
  import SegmentInventory, {
25
25
  IBufferedChunk,
26
26
  IBufferedHistoryEntry,
@@ -112,28 +112,41 @@ export abstract class SegmentBuffer {
112
112
  * `data.chunk` argument to null.
113
113
  *
114
114
  * @param {Object} infos
115
- * @returns {Observable}
115
+ * @param {Object} cancellationSignal
116
+ * @returns {Promise}
116
117
  */
117
- public abstract pushChunk(infos : IPushChunkInfos<unknown>) : Observable<void>;
118
+ public abstract pushChunk(
119
+ infos : IPushChunkInfos<unknown>,
120
+ cancellationSignal : CancellationSignal
121
+ ) : Promise<void>;
118
122
 
119
123
  /**
120
124
  * Remove buffered data (added to the same FIFO queue than `pushChunk`).
121
125
  * @param {number} start - start position, in seconds
122
126
  * @param {number} end - end position, in seconds
123
- * @returns {Observable}
127
+ * @param {Object} cancellationSignal
128
+ * @returns {Promise}
124
129
  */
125
- public abstract removeBuffer(start : number, end : number) : Observable<void>;
130
+ public abstract removeBuffer(
131
+ start : number,
132
+ end : number,
133
+ cancellationSignal : CancellationSignal
134
+ ) : Promise<void>;
126
135
 
127
136
  /**
128
137
  * Indicate that every chunks from a Segment has been given to pushChunk so
129
138
  * far.
130
139
  * This will update our internal Segment inventory accordingly.
131
- * The returned Observable will emit and complete successively once the whole
132
- * segment has been pushed and this indication is acknowledged.
140
+ * The returned Promise will resolve once the whole segment has been pushed
141
+ * and this indication is acknowledged.
133
142
  * @param {Object} infos
134
- * @returns {Observable}
143
+ * @param {Object} cancellationSignal
144
+ * @returns {Promise}
135
145
  */
136
- public abstract endOfSegment(infos : IEndOfSegmentInfos) : Observable<void>;
146
+ public abstract endOfSegment(
147
+ infos : IEndOfSegmentInfos,
148
+ cancellationSignal : CancellationSignal
149
+ ) : Promise<void>;
137
150
 
138
151
  /**
139
152
  * Returns the currently buffered data, in a TimeRanges object.