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.
Files changed (42) hide show
  1. package/CHANGELOG.md +2 -1
  2. package/VERSION +1 -1
  3. package/dist/_esm5.processed/core/adaptive/adaptive_representation_selector.js +1 -6
  4. package/dist/_esm5.processed/core/api/playback_observer.d.ts +47 -35
  5. package/dist/_esm5.processed/core/api/playback_observer.js +120 -117
  6. package/dist/_esm5.processed/core/api/public_api.d.ts +4 -1
  7. package/dist/_esm5.processed/core/api/public_api.js +10 -5
  8. package/dist/_esm5.processed/core/init/content_time_boundaries_observer.js +1 -1
  9. package/dist/_esm5.processed/core/init/create_stream_playback_observer.d.ts +1 -1
  10. package/dist/_esm5.processed/core/init/create_stream_playback_observer.js +23 -6
  11. package/dist/_esm5.processed/core/init/initial_seek_and_play.js +3 -3
  12. package/dist/_esm5.processed/core/init/initialize_directfile.js +1 -1
  13. package/dist/_esm5.processed/core/init/load_on_media_source.js +1 -1
  14. package/dist/_esm5.processed/core/init/stall_avoider.js +12 -8
  15. package/dist/_esm5.processed/core/stream/orchestrator/stream_orchestrator.js +5 -4
  16. package/dist/_esm5.processed/core/stream/period/create_empty_adaptation_stream.js +1 -1
  17. package/dist/_esm5.processed/core/stream/period/period_stream.js +21 -5
  18. package/dist/_esm5.processed/core/stream/reload_after_switch.js +1 -1
  19. package/dist/_esm5.processed/core/stream/representation/append_segment_to_buffer.js +1 -1
  20. package/dist/_esm5.processed/core/stream/representation/representation_stream.js +1 -1
  21. package/dist/_esm5.processed/utils/reference.d.ts +2 -2
  22. package/dist/_esm5.processed/utils/reference.js +5 -4
  23. package/dist/rx-player.js +241 -179
  24. package/dist/rx-player.min.js +1 -1
  25. package/package.json +2 -2
  26. package/sonar-project.properties +1 -1
  27. package/src/core/adaptive/adaptive_representation_selector.ts +1 -7
  28. package/src/core/api/playback_observer.ts +185 -173
  29. package/src/core/api/public_api.ts +15 -6
  30. package/src/core/init/content_time_boundaries_observer.ts +1 -1
  31. package/src/core/init/create_stream_playback_observer.ts +69 -47
  32. package/src/core/init/initial_seek_and_play.ts +3 -3
  33. package/src/core/init/initialize_directfile.ts +1 -1
  34. package/src/core/init/load_on_media_source.ts +1 -1
  35. package/src/core/init/stall_avoider.ts +12 -9
  36. package/src/core/stream/orchestrator/stream_orchestrator.ts +5 -4
  37. package/src/core/stream/period/create_empty_adaptation_stream.ts +1 -1
  38. package/src/core/stream/period/period_stream.ts +33 -14
  39. package/src/core/stream/reload_after_switch.ts +1 -1
  40. package/src/core/stream/representation/append_segment_to_buffer.ts +1 -1
  41. package/src/core/stream/representation/representation_stream.ts +1 -1
  42. 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 { combineLatest as observableCombineLatest, map, } from "rxjs";
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 {Observable}
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 mapObservable(observation$) {
27
- return observableCombineLatest([observation$, speed.asObservable()]).pipe(map(function (_a) {
28
- var observation = _a[0], lastSpeed = _a[1];
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} - mediaElement
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.observe(true));
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.observe(true))
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.observe(true);
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.observe(true);
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.observe(true)), scan(function (discontinuitiesStore, _a) {
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.observe(true)), tap(function (_a) {
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.observe(true).pipe(withLatestFrom(discontinuitiesStore$), map(function (_a) {
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
- observation.position < lastSeekingPosition &&
160
- now - ignoredStallTimeStamp < FORCE_DISCONTINUITY_SEEK_DELAY) {
161
- return { type: "stalled",
162
- value: stalledReason };
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.observe(true)
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 restartStreamsWhenOutOfBounds$ = playbackObserver.observe(true).pipe(filterMap(function (_a) {
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.observe(true).pipe(take(1), mergeMap(function (observation) {
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.observe(true)
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.observe(true);
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 (observation$) { return observation$.pipe(map(mapObservation)); }, mapObservation);
185
- function mapObservation(baseObservation) {
186
- var buffered = segmentBuffer.getBufferedRanges();
187
- return objectAssign({}, baseObservation, { bufferGap: getLeftSizeOfRange(buffered, baseObservation.position.last) });
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.observe(true); }), map(function (observation) {
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.observe(true).pipe(take(1), mergeMap(function (observation) {
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.observe(true),
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
- throw new Error("Finished shared references cannot be updated");
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
  }