rx-player 3.28.0-dev.2022062300 → 3.28.0-dev.2022062700
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 +2 -1
- package/VERSION +1 -1
- package/dist/_esm5.processed/core/adaptive/adaptive_representation_selector.js +1 -6
- package/dist/_esm5.processed/core/api/playback_observer.d.ts +47 -35
- package/dist/_esm5.processed/core/api/playback_observer.js +120 -117
- package/dist/_esm5.processed/core/api/public_api.d.ts +4 -1
- package/dist/_esm5.processed/core/api/public_api.js +10 -5
- package/dist/_esm5.processed/core/init/content_time_boundaries_observer.js +1 -1
- package/dist/_esm5.processed/core/init/create_stream_playback_observer.d.ts +1 -1
- package/dist/_esm5.processed/core/init/create_stream_playback_observer.js +23 -6
- package/dist/_esm5.processed/core/init/initial_seek_and_play.js +3 -3
- package/dist/_esm5.processed/core/init/initialize_directfile.js +1 -1
- package/dist/_esm5.processed/core/init/load_on_media_source.js +1 -1
- package/dist/_esm5.processed/core/init/stall_avoider.js +12 -8
- package/dist/_esm5.processed/core/stream/orchestrator/stream_orchestrator.js +5 -4
- package/dist/_esm5.processed/core/stream/period/create_empty_adaptation_stream.js +1 -1
- package/dist/_esm5.processed/core/stream/period/period_stream.js +21 -5
- package/dist/_esm5.processed/core/stream/reload_after_switch.js +1 -1
- package/dist/_esm5.processed/core/stream/representation/append_segment_to_buffer.js +1 -1
- package/dist/_esm5.processed/core/stream/representation/representation_stream.js +1 -1
- package/dist/_esm5.processed/utils/reference.d.ts +2 -2
- package/dist/_esm5.processed/utils/reference.js +5 -4
- package/dist/rx-player.js +241 -179
- package/dist/rx-player.min.js +1 -1
- package/package.json +2 -2
- package/sonar-project.properties +1 -1
- package/src/core/adaptive/adaptive_representation_selector.ts +1 -7
- package/src/core/api/playback_observer.ts +185 -173
- package/src/core/api/public_api.ts +15 -6
- package/src/core/init/content_time_boundaries_observer.ts +1 -1
- package/src/core/init/create_stream_playback_observer.ts +69 -47
- package/src/core/init/initial_seek_and_play.ts +3 -3
- package/src/core/init/initialize_directfile.ts +1 -1
- package/src/core/init/load_on_media_source.ts +1 -1
- package/src/core/init/stall_avoider.ts +12 -9
- package/src/core/stream/orchestrator/stream_orchestrator.ts +5 -4
- package/src/core/stream/period/create_empty_adaptation_stream.ts +1 -1
- package/src/core/stream/period/period_stream.ts +33 -14
- package/src/core/stream/reload_after_switch.ts +1 -1
- package/src/core/stream/representation/append_segment_to_buffer.ts +1 -1
- package/src/core/stream/representation/representation_stream.ts +1 -1
- package/src/utils/reference.ts +7 -5
|
@@ -13,19 +13,33 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
-
import
|
|
16
|
+
import createSharedReference from "../../utils/reference";
|
|
17
17
|
/**
|
|
18
18
|
* Create PlaybackObserver for the `Stream` part of the code.
|
|
19
19
|
* @param {Object} manifest
|
|
20
20
|
* @param {Object} playbackObserver
|
|
21
21
|
* @param {Object} args
|
|
22
|
-
* @returns {
|
|
22
|
+
* @returns {Object}
|
|
23
23
|
*/
|
|
24
24
|
export default function createStreamPlaybackObserver(manifest, playbackObserver, _a) {
|
|
25
25
|
var autoPlay = _a.autoPlay, initialPlayPerformed = _a.initialPlayPerformed, initialSeekPerformed = _a.initialSeekPerformed, speed = _a.speed, startTime = _a.startTime;
|
|
26
|
-
return playbackObserver.deriveReadOnlyObserver(function
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
return playbackObserver.deriveReadOnlyObserver(function transform(observationRef, cancellationSignal) {
|
|
27
|
+
var newRef = createSharedReference(constructStreamPlaybackObservation());
|
|
28
|
+
speed.onUpdate(emitStreamPlaybackObservation, {
|
|
29
|
+
clearSignal: cancellationSignal,
|
|
30
|
+
emitCurrentValue: false,
|
|
31
|
+
});
|
|
32
|
+
observationRef.onUpdate(emitStreamPlaybackObservation, {
|
|
33
|
+
clearSignal: cancellationSignal,
|
|
34
|
+
emitCurrentValue: false,
|
|
35
|
+
});
|
|
36
|
+
cancellationSignal.register(function () {
|
|
37
|
+
newRef.finish();
|
|
38
|
+
});
|
|
39
|
+
return newRef;
|
|
40
|
+
function constructStreamPlaybackObservation() {
|
|
41
|
+
var observation = observationRef.getValue();
|
|
42
|
+
var lastSpeed = speed.getValue();
|
|
29
43
|
var pendingPosition;
|
|
30
44
|
if (!initialSeekPerformed.getValue()) {
|
|
31
45
|
pendingPosition = startTime;
|
|
@@ -61,6 +75,9 @@ export default function createStreamPlaybackObserver(manifest, playbackObserver,
|
|
|
61
75
|
readyState: observation.readyState,
|
|
62
76
|
speed: lastSpeed,
|
|
63
77
|
};
|
|
64
|
-
}
|
|
78
|
+
}
|
|
79
|
+
function emitStreamPlaybackObservation() {
|
|
80
|
+
newRef.setValue(constructStreamPlaybackObservation());
|
|
81
|
+
}
|
|
65
82
|
});
|
|
66
83
|
}
|
|
@@ -39,7 +39,7 @@ export function waitUntilPlayable(observation$) {
|
|
|
39
39
|
}
|
|
40
40
|
/**
|
|
41
41
|
* Try to play content then handle autoplay errors.
|
|
42
|
-
* @param {HTMLMediaElement}
|
|
42
|
+
* @param {HTMLMediaElement} mediaElement
|
|
43
43
|
* @returns {Observable}
|
|
44
44
|
*/
|
|
45
45
|
function autoPlay(mediaElement) {
|
|
@@ -75,12 +75,12 @@ export default function initialSeekAndPlay(_a) {
|
|
|
75
75
|
}), shareReplay({ refCount: true }));
|
|
76
76
|
var seekAndPlay$ = seek$.pipe(mergeMap(function () {
|
|
77
77
|
if (!shouldValidateMetadata() || mediaElement.duration > 0) {
|
|
78
|
-
return waitUntilPlayable(playbackObserver.
|
|
78
|
+
return waitUntilPlayable(playbackObserver.getReference().asObservable());
|
|
79
79
|
}
|
|
80
80
|
else {
|
|
81
81
|
var error = new MediaError("MEDIA_ERR_NOT_LOADED_METADATA", "Cannot load automatically: your browser " +
|
|
82
82
|
"falsely announced having loaded the content.");
|
|
83
|
-
return waitUntilPlayable(playbackObserver.
|
|
83
|
+
return waitUntilPlayable(playbackObserver.getReference().asObservable())
|
|
84
84
|
.pipe(startWith(EVENTS.warning(error)));
|
|
85
85
|
}
|
|
86
86
|
}), mergeMap(function (evt) {
|
|
@@ -99,7 +99,7 @@ export default function initializeDirectfileContent(_a) {
|
|
|
99
99
|
// Translate errors coming from the media element into RxPlayer errors
|
|
100
100
|
// through a throwing Observable.
|
|
101
101
|
var mediaError$ = throwOnMediaError(mediaElement);
|
|
102
|
-
var observation$ = playbackObserver.
|
|
102
|
+
var observation$ = playbackObserver.getReference().asObservable();
|
|
103
103
|
// Set the speed set by the user on the media element while pausing a
|
|
104
104
|
// little longer while the buffer is empty.
|
|
105
105
|
var playbackRate$ = updatePlaybackRate(mediaElement, speed, observation$)
|
|
@@ -54,7 +54,7 @@ export default function createMediaSourceLoader(_a) {
|
|
|
54
54
|
var segmentBuffersStore = new SegmentBuffersStore(mediaElement, mediaSource);
|
|
55
55
|
var _b = initialSeekAndPlay({ mediaElement: mediaElement, playbackObserver: playbackObserver, startTime: initialTime,
|
|
56
56
|
mustAutoPlay: autoPlay }), seekAndPlay$ = _b.seekAndPlay$, initialPlayPerformed = _b.initialPlayPerformed, initialSeekPerformed = _b.initialSeekPerformed;
|
|
57
|
-
var observation$ = playbackObserver.
|
|
57
|
+
var observation$ = playbackObserver.getReference().asObservable();
|
|
58
58
|
var streamEvents$ = initialPlayPerformed.asObservable().pipe(filter(function (hasPlayed) { return hasPlayed; }), mergeMap(function () { return streamEventsEmitter(manifest, mediaElement, observation$); }));
|
|
59
59
|
var streamObserver = createStreamPlaybackObserver(manifest, playbackObserver, { autoPlay: autoPlay, initialPlayPerformed: initialPlayPerformed, initialSeekPerformed: initialSeekPerformed, speed: speed, startTime: initialTime });
|
|
60
60
|
/** Cancel endOfStream calls when streams become active again. */
|
|
@@ -42,7 +42,7 @@ export default function StallAvoider(playbackObserver, manifest, lockedStream$,
|
|
|
42
42
|
* Emit every known audio and video buffer discontinuities in chronological
|
|
43
43
|
* order (first ordered by Period's start, then by bufferType in any order.
|
|
44
44
|
*/
|
|
45
|
-
var discontinuitiesStore$ = discontinuityUpdate$.pipe(withLatestFrom(playbackObserver.
|
|
45
|
+
var discontinuitiesStore$ = discontinuityUpdate$.pipe(withLatestFrom(playbackObserver.getReference().asObservable()), scan(function (discontinuitiesStore, _a) {
|
|
46
46
|
var evt = _a[0], observation = _a[1];
|
|
47
47
|
return updateDiscontinuitiesStore(discontinuitiesStore, evt, observation);
|
|
48
48
|
}, initialDiscontinuitiesStore));
|
|
@@ -76,7 +76,7 @@ export default function StallAvoider(playbackObserver, manifest, lockedStream$,
|
|
|
76
76
|
* If we're rebuffering waiting on data of a "locked stream", seek into the
|
|
77
77
|
* Period handled by that stream to unlock the situation.
|
|
78
78
|
*/
|
|
79
|
-
var unlock$ = lockedStream$.pipe(withLatestFrom(playbackObserver.
|
|
79
|
+
var unlock$ = lockedStream$.pipe(withLatestFrom(playbackObserver.getReference().asObservable()), tap(function (_a) {
|
|
80
80
|
var _b;
|
|
81
81
|
var lockedStreamEvt = _a[0], observation = _a[1];
|
|
82
82
|
// TODO(PaulB) also skip when the user's wanted speed is set to `0`, as we
|
|
@@ -102,7 +102,7 @@ export default function StallAvoider(playbackObserver, manifest, lockedStream$,
|
|
|
102
102
|
// This is why we're disabling the eslint rule.
|
|
103
103
|
/* eslint-disable-next-line @typescript-eslint/no-unsafe-argument */
|
|
104
104
|
ignoreElements());
|
|
105
|
-
var stall$ = playbackObserver.
|
|
105
|
+
var stall$ = playbackObserver.getReference().asObservable().pipe(withLatestFrom(discontinuitiesStore$), map(function (_a) {
|
|
106
106
|
var observation = _a[0], discontinuitiesStore = _a[1];
|
|
107
107
|
var buffered = observation.buffered, position = observation.position, readyState = observation.readyState, rebuffering = observation.rebuffering, freezing = observation.freezing;
|
|
108
108
|
var _b = config.getCurrent(), BUFFER_DISCONTINUITY_THRESHOLD = _b.BUFFER_DISCONTINUITY_THRESHOLD, FORCE_DISCONTINUITY_SEEK_DELAY = _b.FORCE_DISCONTINUITY_SEEK_DELAY, FREEZING_STALLED_DELAY = _b.FREEZING_STALLED_DELAY, UNFREEZING_SEEK_DELAY = _b.UNFREEZING_SEEK_DELAY, UNFREEZING_DELTA_POSITION = _b.UNFREEZING_DELTA_POSITION;
|
|
@@ -155,11 +155,15 @@ export default function StallAvoider(playbackObserver, manifest, lockedStream$,
|
|
|
155
155
|
if (ignoredStallTimeStamp === null) {
|
|
156
156
|
ignoredStallTimeStamp = now;
|
|
157
157
|
}
|
|
158
|
-
if (isSeekingApproximate &&
|
|
159
|
-
|
|
160
|
-
now - ignoredStallTimeStamp < FORCE_DISCONTINUITY_SEEK_DELAY) {
|
|
161
|
-
|
|
162
|
-
|
|
158
|
+
if (isSeekingApproximate && observation.position < lastSeekingPosition) {
|
|
159
|
+
log.debug("Init: the device appeared to have seeked back by itself.");
|
|
160
|
+
if (now - ignoredStallTimeStamp < FORCE_DISCONTINUITY_SEEK_DELAY) {
|
|
161
|
+
return { type: "stalled",
|
|
162
|
+
value: stalledReason };
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
log.warn("Init: ignored stall for too long, checking discontinuity", now - ignoredStallTimeStamp);
|
|
166
|
+
}
|
|
163
167
|
}
|
|
164
168
|
lastSeekingPosition = null;
|
|
165
169
|
}
|
|
@@ -79,7 +79,7 @@ export default function StreamOrchestrator(content, playbackObserver, representa
|
|
|
79
79
|
Infinity;
|
|
80
80
|
return BufferGarbageCollector({
|
|
81
81
|
segmentBuffer: segmentBuffer,
|
|
82
|
-
currentTime$: playbackObserver.
|
|
82
|
+
currentTime$: playbackObserver.getReference().asObservable()
|
|
83
83
|
.pipe(map(function (o) { var _a; return (_a = o.position.pending) !== null && _a !== void 0 ? _a : o.position.last; })),
|
|
84
84
|
maxBufferBehind$: maxBufferBehind.asObservable().pipe(map(function (val) { return Math.min(val, defaultMaxBehind); })),
|
|
85
85
|
maxBufferAhead$: maxBufferAhead.asObservable().pipe(map(function (val) { return Math.min(val, defaultMaxAhead); })),
|
|
@@ -175,7 +175,8 @@ export default function StreamOrchestrator(content, playbackObserver, representa
|
|
|
175
175
|
}
|
|
176
176
|
// Restart the current Stream when the wanted time is in another period
|
|
177
177
|
// than the ones already considered
|
|
178
|
-
var
|
|
178
|
+
var observation$ = playbackObserver.getReference().asObservable();
|
|
179
|
+
var restartStreamsWhenOutOfBounds$ = observation$.pipe(filterMap(function (_a) {
|
|
179
180
|
var _b, _c;
|
|
180
181
|
var position = _a.position;
|
|
181
182
|
var time = (_b = position.pending) !== null && _b !== void 0 ? _b : position.last;
|
|
@@ -228,7 +229,7 @@ export default function StreamOrchestrator(content, playbackObserver, representa
|
|
|
228
229
|
// to reduce the risk of race conditions where the next observation
|
|
229
230
|
// was going to be emitted synchronously.
|
|
230
231
|
nextTickObs().pipe(ignoreElements()),
|
|
231
|
-
playbackObserver.
|
|
232
|
+
playbackObserver.getReference().asObservable().pipe(take(1), mergeMap(function (observation) {
|
|
232
233
|
var _a;
|
|
233
234
|
var shouldAutoPlay = !((_a = observation.paused.pending) !== null && _a !== void 0 ? _a : playbackObserver.getIsPaused());
|
|
234
235
|
return observableConcat(observableOf(EVENTS.needsDecipherabilityFlush(observation.position.last, shouldAutoPlay, observation.duration)), observableDefer(function () {
|
|
@@ -279,7 +280,7 @@ export default function StreamOrchestrator(content, playbackObserver, representa
|
|
|
279
280
|
// created.
|
|
280
281
|
var destroyNextStreams$ = new Subject();
|
|
281
282
|
// Emits when the current position goes over the end of the current Stream.
|
|
282
|
-
var endOfCurrentStream$ = playbackObserver.
|
|
283
|
+
var endOfCurrentStream$ = playbackObserver.getReference().asObservable()
|
|
283
284
|
.pipe(filter(function (_a) {
|
|
284
285
|
var _b;
|
|
285
286
|
var position = _a.position;
|
|
@@ -30,7 +30,7 @@ export default function createEmptyAdaptationStream(playbackObserver, wantedBuff
|
|
|
30
30
|
var period = content.period;
|
|
31
31
|
var hasFinishedLoading = false;
|
|
32
32
|
var wantedBufferAhead$ = wantedBufferAhead.asObservable();
|
|
33
|
-
var observation$ = playbackObserver.
|
|
33
|
+
var observation$ = playbackObserver.getReference().asObservable();
|
|
34
34
|
return observableCombineLatest([observation$,
|
|
35
35
|
wantedBufferAhead$]).pipe(mergeMap(function (_a) {
|
|
36
36
|
var observation = _a[0], wba = _a[1];
|
|
@@ -19,6 +19,7 @@ import { formatError, MediaError, } from "../../../errors";
|
|
|
19
19
|
import log from "../../../log";
|
|
20
20
|
import objectAssign from "../../../utils/object_assign";
|
|
21
21
|
import { getLeftSizeOfRange } from "../../../utils/ranges";
|
|
22
|
+
import createSharedReference from "../../../utils/reference";
|
|
22
23
|
import SegmentBuffersStore from "../../segment_buffers";
|
|
23
24
|
import AdaptationStream from "../adaptation";
|
|
24
25
|
import EVENTS from "../events_generators";
|
|
@@ -181,9 +182,24 @@ function getFirstDeclaredMimeType(adaptation) {
|
|
|
181
182
|
* @returns {Object}
|
|
182
183
|
*/
|
|
183
184
|
function createAdaptationStreamPlaybackObserver(initialPlaybackObserver, segmentBuffer) {
|
|
184
|
-
return initialPlaybackObserver.deriveReadOnlyObserver(function (
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
185
|
+
return initialPlaybackObserver.deriveReadOnlyObserver(function transform(observationRef, cancellationSignal) {
|
|
186
|
+
var newRef = createSharedReference(constructAdaptationStreamPlaybackObservation());
|
|
187
|
+
observationRef.onUpdate(emitAdaptationStreamPlaybackObservation, {
|
|
188
|
+
clearSignal: cancellationSignal,
|
|
189
|
+
emitCurrentValue: false,
|
|
190
|
+
});
|
|
191
|
+
cancellationSignal.register(function () {
|
|
192
|
+
newRef.finish();
|
|
193
|
+
});
|
|
194
|
+
return newRef;
|
|
195
|
+
function constructAdaptationStreamPlaybackObservation() {
|
|
196
|
+
var baseObservation = observationRef.getValue();
|
|
197
|
+
var buffered = segmentBuffer.getBufferedRanges();
|
|
198
|
+
var bufferGap = getLeftSizeOfRange(buffered, baseObservation.position.last);
|
|
199
|
+
return objectAssign({}, baseObservation, { bufferGap: bufferGap });
|
|
200
|
+
}
|
|
201
|
+
function emitAdaptationStreamPlaybackObservation() {
|
|
202
|
+
newRef.setValue(constructAdaptationStreamPlaybackObservation());
|
|
203
|
+
}
|
|
204
|
+
});
|
|
189
205
|
}
|
|
@@ -44,7 +44,7 @@ export default function reloadAfterSwitch(period, bufferType, playbackObserver,
|
|
|
44
44
|
// is actually received.
|
|
45
45
|
// It can happen when `reloadAfterSwitch` is called as a side-effect of the
|
|
46
46
|
// same event that triggers the playback observation to be emitted.
|
|
47
|
-
return nextTickObs().pipe(mergeMap(function () { return playbackObserver.
|
|
47
|
+
return nextTickObs().pipe(mergeMap(function () { return playbackObserver.getReference().asObservable(); }), map(function (observation) {
|
|
48
48
|
var _a, _b;
|
|
49
49
|
var currentTime = playbackObserver.getCurrentTime();
|
|
50
50
|
var pos = currentTime + deltaPos;
|
|
@@ -38,7 +38,7 @@ export default function appendSegmentToBuffer(playbackObserver, segmentBuffer, d
|
|
|
38
38
|
"An unknown error happened when pushing content";
|
|
39
39
|
throw new MediaError("BUFFER_APPEND_ERROR", reason);
|
|
40
40
|
}
|
|
41
|
-
return playbackObserver.
|
|
41
|
+
return playbackObserver.getReference().asObservable().pipe(take(1), mergeMap(function (observation) {
|
|
42
42
|
var _a;
|
|
43
43
|
var currentPos = (_a = observation.position.pending) !== null && _a !== void 0 ? _a : observation.position.last;
|
|
44
44
|
return observableConcat(forceGarbageCollection(currentPos, segmentBuffer).pipe(ignoreElements()), append$).pipe(catchError(function (forcedGCError) {
|
|
@@ -97,7 +97,7 @@ export default function RepresentationStream(_a) {
|
|
|
97
97
|
.pipe(mergeMap(onQueueEvent));
|
|
98
98
|
/** Observable emitting the stream "status" and filling `lastSegmentQueue`. */
|
|
99
99
|
var status$ = observableCombineLatest([
|
|
100
|
-
playbackObserver.
|
|
100
|
+
playbackObserver.getReference().asObservable(),
|
|
101
101
|
bufferGoal$,
|
|
102
102
|
maxBufferSize$,
|
|
103
103
|
terminate$.pipe(take(1), startWith(null)),
|
|
@@ -91,8 +91,8 @@ export interface ISharedReference<T> {
|
|
|
91
91
|
* also be immediately called with the current value.
|
|
92
92
|
*/
|
|
93
93
|
onUpdate(cb: (val: T) => void, options?: {
|
|
94
|
-
clearSignal?: CancellationSignal;
|
|
95
|
-
emitCurrentValue?: boolean;
|
|
94
|
+
clearSignal?: CancellationSignal | undefined;
|
|
95
|
+
emitCurrentValue?: boolean | undefined;
|
|
96
96
|
}): void;
|
|
97
97
|
/**
|
|
98
98
|
* Indicate that no new values will be emitted.
|
|
@@ -58,11 +58,10 @@ export function createSharedReference(initialValue) {
|
|
|
58
58
|
setValue: function (newVal) {
|
|
59
59
|
if (isFinished) {
|
|
60
60
|
if (0 /* __ENVIRONMENT__.CURRENT_ENV */ === 1 /* __ENVIRONMENT__.DEV */) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
else {
|
|
64
|
-
return;
|
|
61
|
+
/* eslint-disable-next-line no-console */
|
|
62
|
+
console.error("Finished shared references cannot be updated");
|
|
65
63
|
}
|
|
64
|
+
return;
|
|
66
65
|
}
|
|
67
66
|
value = newVal;
|
|
68
67
|
if (cbs.length === 0) {
|
|
@@ -177,11 +176,13 @@ export function createSharedReference(initialValue) {
|
|
|
177
176
|
if (!cbObj.hasBeenCleared) {
|
|
178
177
|
cbObj.complete();
|
|
179
178
|
}
|
|
179
|
+
cbObj.hasBeenCleared = true;
|
|
180
180
|
}
|
|
181
181
|
catch (_) {
|
|
182
182
|
/* nothing */
|
|
183
183
|
}
|
|
184
184
|
}
|
|
185
|
+
cbs.length = 0;
|
|
185
186
|
},
|
|
186
187
|
};
|
|
187
188
|
}
|