rx-player 3.27.0-dev.2022032100 → 3.27.0
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 -2
- package/VERSION +1 -1
- package/dist/_esm5.processed/compat/eme/custom_media_keys/old_webkit_media_keys.js +15 -11
- package/dist/_esm5.processed/compat/eme/custom_media_keys/webkit_media_keys.js +22 -6
- package/dist/_esm5.processed/compat/eme/generate_key_request.d.ts +4 -6
- package/dist/_esm5.processed/compat/eme/generate_key_request.js +4 -6
- package/dist/_esm5.processed/compat/get_start_date.d.ts +30 -0
- package/dist/_esm5.processed/compat/get_start_date.js +44 -0
- package/dist/_esm5.processed/compat/index.d.ts +2 -1
- package/dist/_esm5.processed/compat/index.js +2 -1
- package/dist/_esm5.processed/config.d.ts +1 -5
- package/dist/_esm5.processed/core/api/public_api.js +25 -25
- package/dist/_esm5.processed/core/decrypt/content_decryptor.js +11 -3
- package/dist/_esm5.processed/core/decrypt/create_or_load_session.js +1 -1
- package/dist/_esm5.processed/core/decrypt/create_session.d.ts +3 -1
- package/dist/_esm5.processed/core/decrypt/create_session.js +15 -5
- package/dist/_esm5.processed/core/decrypt/utils/loaded_sessions_store.d.ts +94 -1
- package/dist/_esm5.processed/core/decrypt/utils/loaded_sessions_store.js +237 -96
- package/dist/_esm5.processed/core/segment_buffers/garbage_collector.js +4 -1
- package/dist/_esm5.processed/core/stream/orchestrator/stream_orchestrator.js +2 -1
- package/dist/_esm5.processed/core/stream/period/period_stream.js +9 -3
- package/dist/_esm5.processed/core/stream/representation/append_segment_to_buffer.js +4 -3
- package/dist/_esm5.processed/core/stream/representation/force_garbage_collection.js +3 -2
- package/dist/_esm5.processed/core/stream/representation/get_buffer_status.d.ts +2 -2
- package/dist/_esm5.processed/core/stream/representation/get_buffer_status.js +9 -3
- package/dist/_esm5.processed/core/stream/representation/get_needed_segments.d.ts +11 -1
- package/dist/_esm5.processed/core/stream/representation/get_needed_segments.js +27 -45
- package/dist/_esm5.processed/core/stream/representation/representation_stream.js +6 -4
- package/dist/_esm5.processed/default_config.d.ts +2 -35
- package/dist/_esm5.processed/default_config.js +2 -35
- package/dist/_esm5.processed/transports/dash/add_segment_integrity_checks_to_loader.js +39 -38
- package/dist/_esm5.processed/utils/reference.js +0 -2
- package/dist/_esm5.processed/utils/task_canceller.d.ts +8 -1
- package/dist/_esm5.processed/utils/task_canceller.js +9 -1
- package/dist/rx-player.js +927 -587
- package/dist/rx-player.min.js +1 -1
- package/package.json +1 -1
- package/sonar-project.properties +1 -1
- package/src/compat/eme/custom_media_keys/old_webkit_media_keys.ts +16 -12
- package/src/compat/eme/custom_media_keys/webkit_media_keys.ts +21 -8
- package/src/compat/eme/generate_key_request.ts +4 -6
- package/src/compat/get_start_date.ts +48 -0
- package/src/compat/index.ts +2 -0
- package/src/core/api/public_api.ts +23 -27
- package/src/core/decrypt/content_decryptor.ts +15 -4
- package/src/core/decrypt/create_or_load_session.ts +4 -1
- package/src/core/decrypt/create_session.ts +23 -9
- package/src/core/decrypt/utils/loaded_sessions_store.ts +254 -102
- package/src/core/segment_buffers/garbage_collector.ts +4 -0
- package/src/core/stream/orchestrator/stream_orchestrator.ts +2 -1
- package/src/core/stream/period/period_stream.ts +9 -4
- package/src/core/stream/representation/append_segment_to_buffer.ts +17 -13
- package/src/core/stream/representation/force_garbage_collection.ts +4 -1
- package/src/core/stream/representation/get_buffer_status.ts +21 -13
- package/src/core/stream/representation/get_needed_segments.ts +40 -55
- package/src/core/stream/representation/representation_stream.ts +6 -4
- package/src/default_config.ts +20 -57
- package/src/transports/dash/add_segment_integrity_checks_to_loader.ts +41 -44
- package/src/utils/reference.ts +0 -2
- package/src/utils/task_canceller.ts +16 -1
|
@@ -84,7 +84,17 @@ export interface IGetNeededSegmentsArguments {
|
|
|
84
84
|
|
|
85
85
|
|
|
86
86
|
interface INeededSegments {
|
|
87
|
-
|
|
87
|
+
/** Segments that should be loaded right now, by chronological order. */
|
|
88
|
+
segmentsToLoad: ISegment[];
|
|
89
|
+
/**
|
|
90
|
+
* Segments that should be loaded, but not right now, due to some other
|
|
91
|
+
* constraints, such as memory limitations.
|
|
92
|
+
*/
|
|
93
|
+
segmentsOnHold : ISegment[];
|
|
94
|
+
/**
|
|
95
|
+
* If `true` the buffer is currently full according to the given limits.
|
|
96
|
+
* Memory should be freed if possible, for example by cleaning the buffers.
|
|
97
|
+
*/
|
|
88
98
|
isBufferFull: boolean;
|
|
89
99
|
}
|
|
90
100
|
/**
|
|
@@ -112,8 +122,6 @@ export default function getNeededSegments({
|
|
|
112
122
|
segmentsBeingPushed,
|
|
113
123
|
maxBufferSize);
|
|
114
124
|
|
|
115
|
-
// Current buffer length in seconds
|
|
116
|
-
let bufferLength = getBufferLength(bufferedSegments, segmentsBeingPushed);
|
|
117
125
|
const availableSegmentsForRange = representation.index
|
|
118
126
|
.getSegments(neededRange.start, neededRange.end - neededRange.start);
|
|
119
127
|
|
|
@@ -151,16 +159,16 @@ export default function getNeededSegments({
|
|
|
151
159
|
return true;
|
|
152
160
|
});
|
|
153
161
|
const { MINIMUM_SEGMENT_SIZE,
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
let isMemorySaturated = false;
|
|
162
|
+
MIN_BUFFER_AHEAD } = config.getCurrent();
|
|
163
|
+
let shouldStopLoadingSegments = false;
|
|
157
164
|
/**
|
|
158
165
|
* Epsilon compensating for rounding errors when comparing the start and end
|
|
159
166
|
* time of multiple segments.
|
|
160
167
|
*/
|
|
161
168
|
const ROUNDING_ERROR = Math.min(1 / 60, MINIMUM_SEGMENT_SIZE);
|
|
162
169
|
let isBufferFull = false;
|
|
163
|
-
const
|
|
170
|
+
const segmentsOnHold : ISegment[] = [];
|
|
171
|
+
const segmentsToLoad = availableSegmentsForRange.filter(segment => {
|
|
164
172
|
const contentObject = objectAssign({ segment }, content);
|
|
165
173
|
|
|
166
174
|
// First, check that the segment is not already being pushed
|
|
@@ -176,21 +184,10 @@ export default function getNeededSegments({
|
|
|
176
184
|
if (segment.isInit) {
|
|
177
185
|
return true; // never skip initialization segments
|
|
178
186
|
}
|
|
179
|
-
if (
|
|
180
|
-
|
|
181
|
-
// That we cannot download atleast till
|
|
182
|
-
// NeededRange.Start ( current position ) + a CONST
|
|
183
|
-
// Then the buffer is full
|
|
184
|
-
if (time < neededRange.start + MIN_BUFFER_DISTANCE_BEFORE_CLEAN_UP) {
|
|
185
|
-
isBufferFull = true;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
if (isMemorySaturated &&
|
|
189
|
-
bufferLength > MIN_BUFFER_LENGTH) {
|
|
190
|
-
|
|
187
|
+
if (shouldStopLoadingSegments) {
|
|
188
|
+
segmentsOnHold.push(segment);
|
|
191
189
|
return false;
|
|
192
190
|
}
|
|
193
|
-
|
|
194
191
|
if (segment.complete && duration < MINIMUM_SEGMENT_SIZE) {
|
|
195
192
|
return false; // too small, don't download
|
|
196
193
|
}
|
|
@@ -239,29 +236,36 @@ export default function getNeededSegments({
|
|
|
239
236
|
}
|
|
240
237
|
}
|
|
241
238
|
|
|
239
|
+
const estimatedSegmentSize = (duration * content.representation.bitrate) / 8000;
|
|
240
|
+
if (availableBufferSize - estimatedSegmentSize < 0) {
|
|
241
|
+
isBufferFull = true;
|
|
242
|
+
if (time > neededRange.start + MIN_BUFFER_AHEAD) {
|
|
243
|
+
shouldStopLoadingSegments = true;
|
|
244
|
+
segmentsOnHold.push(segment);
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
242
249
|
// check if there is an hole in place of the segment currently
|
|
243
250
|
for (let i = 0; i < segmentsToKeep.length; i++) {
|
|
244
251
|
const completeSeg = segmentsToKeep[i];
|
|
245
|
-
if (completeSeg.end > time) {
|
|
246
|
-
// `true` if `completeSeg` starts too far after `time`
|
|
247
|
-
return completeSeg.start > time + ROUNDING_ERROR ||
|
|
248
|
-
// `true` if `completeSeg` ends too soon before `end`
|
|
249
|
-
getLastContiguousSegment(segmentsToKeep, i).end < end - ROUNDING_ERROR;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
252
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
253
|
+
// For the first already-loaded segment, take the first one ending after
|
|
254
|
+
// this one' s start
|
|
255
|
+
if ((completeSeg.end + ROUNDING_ERROR) > time) {
|
|
256
|
+
const shouldLoad = completeSeg.start > time + ROUNDING_ERROR ||
|
|
257
|
+
getLastContiguousSegment(segmentsToKeep, i).end <
|
|
258
|
+
end - ROUNDING_ERROR;
|
|
259
|
+
if (shouldLoad) {
|
|
260
|
+
availableBufferSize -= estimatedSegmentSize;
|
|
261
|
+
}
|
|
262
|
+
return shouldLoad;
|
|
263
|
+
}
|
|
258
264
|
}
|
|
259
265
|
availableBufferSize -= estimatedSegmentSize;
|
|
260
|
-
bufferLength += duration;
|
|
261
|
-
|
|
262
266
|
return true;
|
|
263
267
|
});
|
|
264
|
-
return {
|
|
268
|
+
return { segmentsToLoad, segmentsOnHold, isBufferFull };
|
|
265
269
|
|
|
266
270
|
}
|
|
267
271
|
/**
|
|
@@ -286,7 +290,7 @@ function getAvailableBufferSize(
|
|
|
286
290
|
}, 0);
|
|
287
291
|
return bufferedSegments.reduce((size, chunk) => {
|
|
288
292
|
if (chunk.chunkSize !== undefined) {
|
|
289
|
-
return size - (chunk.chunkSize /
|
|
293
|
+
return size - (chunk.chunkSize / 1000);
|
|
290
294
|
} else {
|
|
291
295
|
return size;
|
|
292
296
|
}
|
|
@@ -294,25 +298,6 @@ function getAvailableBufferSize(
|
|
|
294
298
|
} , availableBufferSize);
|
|
295
299
|
}
|
|
296
300
|
|
|
297
|
-
/**
|
|
298
|
-
* Compute the length of the buffer in seconds
|
|
299
|
-
* @param bufferedSegments
|
|
300
|
-
* @param segmentsBeingPushed
|
|
301
|
-
* @returns bufferLength in seconds
|
|
302
|
-
*/
|
|
303
|
-
function getBufferLength(
|
|
304
|
-
bufferedSegments: IBufferedChunk[],
|
|
305
|
-
segmentsBeingPushed: IEndOfSegmentInfos[]
|
|
306
|
-
) : number {
|
|
307
|
-
const bufferLength = bufferedSegments.reduce((length, segment) => {
|
|
308
|
-
return length + (segment.end - segment.start);
|
|
309
|
-
}, 0);
|
|
310
|
-
const bufferBeingPushed = segmentsBeingPushed.reduce((length, segment) => {
|
|
311
|
-
return length + segment.segment.duration;
|
|
312
|
-
}, 0);
|
|
313
|
-
return bufferLength + bufferBeingPushed;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
301
|
/**
|
|
317
302
|
* From the given array of buffered chunks (`bufferedSegments`) returns the last
|
|
318
303
|
* buffered chunk contiguous with the one at the `startIndex` index given.
|
|
@@ -384,10 +384,12 @@ export default function RepresentationStream<TSegmentDataType>({
|
|
|
384
384
|
const gcedPosition = Math.max(
|
|
385
385
|
0,
|
|
386
386
|
wantedStartPosition - UPTO_CURRENT_POSITION_CLEANUP);
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
387
|
+
if (gcedPosition > 0) {
|
|
388
|
+
bufferRemoval = segmentBuffer
|
|
389
|
+
.removeBuffer(0, gcedPosition)
|
|
390
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
391
|
+
.pipe(ignoreElements());
|
|
392
|
+
}
|
|
391
393
|
}
|
|
392
394
|
return status.shouldRefreshManifest ?
|
|
393
395
|
observableConcat(observableOf(EVENTS.needsManifestRefresh()),
|
package/src/default_config.ts
CHANGED
|
@@ -1057,36 +1057,6 @@ const DEFAULT_CONFIG = {
|
|
|
1057
1057
|
*/
|
|
1058
1058
|
EME_MAX_STORED_PERSISTENT_SESSION_INFORMATION: 1000,
|
|
1059
1059
|
|
|
1060
|
-
/**
|
|
1061
|
-
* Attempts to closing a MediaKeySession can fail, most likely because the
|
|
1062
|
-
* MediaKeySession was not initialized yet.
|
|
1063
|
-
* When we consider that we're in one of these case, we will retry to close it.
|
|
1064
|
-
*
|
|
1065
|
-
* To avoid going into an infinite loop of retry, this number indicates a
|
|
1066
|
-
* maximum number of attemps we're going to make (`0` meaning no retry at all,
|
|
1067
|
-
* `1` only one retry and so on).
|
|
1068
|
-
*/
|
|
1069
|
-
EME_SESSION_CLOSING_MAX_RETRY: 5,
|
|
1070
|
-
|
|
1071
|
-
/**
|
|
1072
|
-
* When closing a MediaKeySession failed due to the reasons explained for the
|
|
1073
|
-
* `EME_SESSION_CLOSING_MAX_RETRY` config property, we may (among other
|
|
1074
|
-
* triggers) choose to wait a delay raising exponentially at each retry before
|
|
1075
|
-
* that new attempt.
|
|
1076
|
-
* This value indicates the initial value for this delay, in milliseconds.
|
|
1077
|
-
*/
|
|
1078
|
-
EME_SESSION_CLOSING_INITIAL_DELAY: 100,
|
|
1079
|
-
|
|
1080
|
-
/**
|
|
1081
|
-
* When closing a MediaKeySession failed due to the reasons explained for the
|
|
1082
|
-
* `EME_SESSION_CLOSING_MAX_RETRY` config property, we may (among other
|
|
1083
|
-
* triggers) choose to wait a delay raising exponentially at each retry before
|
|
1084
|
-
* that new attempt.
|
|
1085
|
-
* This value indicates the maximum possible value for this delay, in
|
|
1086
|
-
* milliseconds.
|
|
1087
|
-
*/
|
|
1088
|
-
EME_SESSION_CLOSING_MAX_DELAY: 1000,
|
|
1089
|
-
|
|
1090
1060
|
/**
|
|
1091
1061
|
* After loading a persistent MediaKeySession, the RxPlayer needs to ensure
|
|
1092
1062
|
* that its keys still allow to decrypt a content.
|
|
@@ -1194,40 +1164,33 @@ const DEFAULT_CONFIG = {
|
|
|
1194
1164
|
*/
|
|
1195
1165
|
DEFAULT_MAXIMUM_TIME_ROUNDING_ERROR: 1 / 1000,
|
|
1196
1166
|
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1167
|
+
/**
|
|
1168
|
+
* RxPlayer's media buffers have a linked history registering recent events
|
|
1169
|
+
* that happened on those.
|
|
1170
|
+
* The reason is to implement various heuristics in case of weird browser
|
|
1171
|
+
* behavior.
|
|
1172
|
+
*
|
|
1173
|
+
* The `BUFFERED_HISTORY_RETENTION_TIME` is the minimum age an entry of
|
|
1174
|
+
* that history can have before being removed from the history.
|
|
1175
|
+
*/
|
|
1206
1176
|
BUFFERED_HISTORY_RETENTION_TIME: 60000,
|
|
1207
1177
|
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1178
|
+
/**
|
|
1179
|
+
* RxPlayer's media buffers have a linked history registering recent events
|
|
1180
|
+
* that happened on those.
|
|
1181
|
+
* The reason is to implement various heuristics in case of weird browser
|
|
1182
|
+
* behavior.
|
|
1183
|
+
*
|
|
1184
|
+
* The `BUFFERED_HISTORY_RETENTION_TIME` is the maximum number of entries
|
|
1185
|
+
* there can be in that history.
|
|
1186
|
+
*/
|
|
1217
1187
|
BUFFERED_HISTORY_MAXIMUM_ENTRIES: 200,
|
|
1218
1188
|
|
|
1219
|
-
/**
|
|
1220
|
-
* Minimum buffer (in seconds) we should have, regardless of memory
|
|
1221
|
-
* constraints
|
|
1222
|
-
*/
|
|
1223
|
-
MIN_BUFFER_LENGTH : 5,
|
|
1224
|
-
|
|
1225
1189
|
/**
|
|
1226
1190
|
* Minimum buffer in seconds ahead relative to current time
|
|
1227
|
-
* we should be able to download
|
|
1228
|
-
* Before trying to agressively free up memory
|
|
1191
|
+
* we should be able to download, even in cases of saturated memory.
|
|
1229
1192
|
*/
|
|
1230
|
-
|
|
1193
|
+
MIN_BUFFER_AHEAD: 5,
|
|
1231
1194
|
|
|
1232
1195
|
/**
|
|
1233
1196
|
* Distance in seconds behind the current position
|
|
@@ -14,9 +14,7 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import TaskCanceller
|
|
18
|
-
CancellationError,
|
|
19
|
-
} from "../../utils/task_canceller";
|
|
17
|
+
import TaskCanceller from "../../utils/task_canceller";
|
|
20
18
|
import { ISegmentLoader } from "../types";
|
|
21
19
|
import checkISOBMFFIntegrity from "../utils/check_isobmff_integrity";
|
|
22
20
|
import inferSegmentContainer from "../utils/infer_segment_container";
|
|
@@ -32,61 +30,60 @@ export default function addSegmentIntegrityChecks<T>(
|
|
|
32
30
|
segmentLoader : ISegmentLoader<T>
|
|
33
31
|
) : ISegmentLoader<T> {
|
|
34
32
|
return (url, content, initialCancelSignal, callbacks) => {
|
|
35
|
-
return new Promise((
|
|
36
|
-
const
|
|
37
|
-
const unregisterCancelLstnr = initialCancelSignal
|
|
38
|
-
.register(function onCheckCancellation(err : CancellationError) {
|
|
39
|
-
canceller.cancel();
|
|
40
|
-
rej(err);
|
|
41
|
-
});
|
|
33
|
+
return new Promise((resolve, reject) => {
|
|
34
|
+
const requestCanceller = new TaskCanceller({ cancelOn: initialCancelSignal });
|
|
42
35
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
* @param {*} data
|
|
47
|
-
*/
|
|
48
|
-
function cancelAndRejectOnBadIntegrity(data : T) : void {
|
|
49
|
-
if (!(data instanceof Array) && !(data instanceof Uint8Array) ||
|
|
50
|
-
inferSegmentContainer(content.adaptation.type,
|
|
51
|
-
content.representation) !== "mp4")
|
|
52
|
-
{
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
try {
|
|
56
|
-
checkISOBMFFIntegrity(new Uint8Array(data), content.segment.isInit);
|
|
57
|
-
} catch (err) {
|
|
58
|
-
unregisterCancelLstnr();
|
|
59
|
-
canceller.cancel();
|
|
60
|
-
rej(err);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
36
|
+
// Reject the `CancellationError` when `requestCanceller`'s signal emits
|
|
37
|
+
// `stopRejectingOnCancel` here is a function allowing to stop this mechanism
|
|
38
|
+
const stopRejectingOnCancel = requestCanceller.signal.register(reject);
|
|
63
39
|
|
|
64
|
-
segmentLoader(url, content,
|
|
40
|
+
segmentLoader(url, content, requestCanceller.signal, {
|
|
65
41
|
...callbacks,
|
|
66
42
|
onNewChunk(data) {
|
|
67
|
-
|
|
68
|
-
|
|
43
|
+
try {
|
|
44
|
+
trowOnIntegrityError(data);
|
|
69
45
|
callbacks.onNewChunk(data);
|
|
46
|
+
} catch (err) {
|
|
47
|
+
// Do not reject with a `CancellationError` after cancelling the request
|
|
48
|
+
stopRejectingOnCancel();
|
|
49
|
+
// Cancel the request
|
|
50
|
+
requestCanceller.cancel();
|
|
51
|
+
// Reject with thrown error
|
|
52
|
+
reject(err);
|
|
70
53
|
}
|
|
71
54
|
},
|
|
72
55
|
}).then((info) => {
|
|
73
|
-
if (
|
|
56
|
+
if (requestCanceller.isUsed) {
|
|
74
57
|
return;
|
|
75
58
|
}
|
|
76
|
-
|
|
77
|
-
|
|
59
|
+
stopRejectingOnCancel();
|
|
78
60
|
if (info.resultType === "segment-loaded") {
|
|
79
|
-
|
|
61
|
+
try {
|
|
62
|
+
trowOnIntegrityError(info.resultData.responseData);
|
|
63
|
+
} catch (err) {
|
|
64
|
+
reject(err);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
80
67
|
}
|
|
81
|
-
|
|
82
|
-
|
|
68
|
+
resolve(info);
|
|
83
69
|
}, (error : unknown) => {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
unregisterCancelLstnr();
|
|
87
|
-
rej(error);
|
|
88
|
-
}
|
|
70
|
+
stopRejectingOnCancel();
|
|
71
|
+
reject(error);
|
|
89
72
|
});
|
|
90
73
|
});
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* If the data's seems to be corrupted, throws an `INTEGRITY_ERROR` error.
|
|
77
|
+
* @param {*} data
|
|
78
|
+
*/
|
|
79
|
+
function trowOnIntegrityError(data : T) : void {
|
|
80
|
+
if (!(data instanceof ArrayBuffer) && !(data instanceof Uint8Array) ||
|
|
81
|
+
inferSegmentContainer(content.adaptation.type,
|
|
82
|
+
content.representation) !== "mp4")
|
|
83
|
+
{
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
checkISOBMFFIntegrity(new Uint8Array(data), content.segment.isInit);
|
|
87
|
+
}
|
|
91
88
|
};
|
|
92
89
|
}
|
package/src/utils/reference.ts
CHANGED
|
@@ -18,7 +18,6 @@ import {
|
|
|
18
18
|
Observable,
|
|
19
19
|
Subscriber,
|
|
20
20
|
} from "rxjs";
|
|
21
|
-
import log from "../log";
|
|
22
21
|
import { CancellationSignal } from "./task_canceller";
|
|
23
22
|
|
|
24
23
|
/**
|
|
@@ -194,7 +193,6 @@ export function createSharedReference<T>(initialValue : T) : ISharedReference<T>
|
|
|
194
193
|
if (__ENVIRONMENT__.CURRENT_ENV === __ENVIRONMENT__.DEV as number) {
|
|
195
194
|
throw new Error("Finished shared references cannot be updated");
|
|
196
195
|
} else {
|
|
197
|
-
log.error("Finished shared references cannot be updated");
|
|
198
196
|
return;
|
|
199
197
|
}
|
|
200
198
|
}
|
|
@@ -136,14 +136,29 @@ export default class TaskCanceller {
|
|
|
136
136
|
* Creates a new `TaskCanceller`, with its own `CancellationSignal` created
|
|
137
137
|
* as its `signal` provide.
|
|
138
138
|
* You can then pass this property to async task you wish to be cancellable.
|
|
139
|
+
* @param {Object|undefined} options
|
|
139
140
|
*/
|
|
140
|
-
constructor(
|
|
141
|
+
constructor(options? : {
|
|
142
|
+
/**
|
|
143
|
+
* If set the TaskCanceller created here will automatically be triggered
|
|
144
|
+
* when that signal emits.
|
|
145
|
+
*/
|
|
146
|
+
cancelOn? : CancellationSignal | undefined;
|
|
147
|
+
} | undefined) {
|
|
141
148
|
const [trigger, register] = createCancellationFunctions();
|
|
142
149
|
this.isUsed = false;
|
|
143
150
|
this._trigger = trigger;
|
|
144
151
|
this.signal = new CancellationSignal(register);
|
|
152
|
+
|
|
153
|
+
if (options?.cancelOn !== undefined) {
|
|
154
|
+
const unregisterParent = options.cancelOn.register(() => {
|
|
155
|
+
this.cancel();
|
|
156
|
+
});
|
|
157
|
+
this.signal.register(unregisterParent);
|
|
158
|
+
}
|
|
145
159
|
}
|
|
146
160
|
|
|
161
|
+
|
|
147
162
|
/**
|
|
148
163
|
* "Trigger" the `TaskCanceller`, notify through its associated
|
|
149
164
|
* `CancellationSignal` (its `signal` property) that a task should be aborted.
|