rx-player 3.28.0-dev.2022061700 → 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 (49) hide show
  1. package/CHANGELOG.md +5 -3
  2. package/VERSION +1 -1
  3. package/appveyor.yml +1 -1
  4. package/dist/_esm5.processed/core/adaptive/adaptive_representation_selector.d.ts +32 -11
  5. package/dist/_esm5.processed/core/adaptive/adaptive_representation_selector.js +19 -26
  6. package/dist/_esm5.processed/core/api/playback_observer.d.ts +47 -35
  7. package/dist/_esm5.processed/core/api/playback_observer.js +120 -117
  8. package/dist/_esm5.processed/core/api/public_api.d.ts +4 -6
  9. package/dist/_esm5.processed/core/api/public_api.js +18 -18
  10. package/dist/_esm5.processed/core/decrypt/content_decryptor.js +60 -31
  11. package/dist/_esm5.processed/core/init/content_time_boundaries_observer.js +1 -1
  12. package/dist/_esm5.processed/core/init/create_stream_playback_observer.d.ts +1 -1
  13. package/dist/_esm5.processed/core/init/create_stream_playback_observer.js +23 -6
  14. package/dist/_esm5.processed/core/init/initial_seek_and_play.js +3 -3
  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.js +12 -8
  18. package/dist/_esm5.processed/core/stream/adaptation/create_representation_estimator.js +1 -1
  19. package/dist/_esm5.processed/core/stream/orchestrator/stream_orchestrator.js +5 -4
  20. package/dist/_esm5.processed/core/stream/period/create_empty_adaptation_stream.js +1 -1
  21. package/dist/_esm5.processed/core/stream/period/period_stream.js +21 -5
  22. package/dist/_esm5.processed/core/stream/reload_after_switch.js +1 -1
  23. package/dist/_esm5.processed/core/stream/representation/append_segment_to_buffer.js +1 -1
  24. package/dist/_esm5.processed/core/stream/representation/representation_stream.js +1 -1
  25. package/dist/_esm5.processed/utils/reference.d.ts +29 -19
  26. package/dist/_esm5.processed/utils/reference.js +21 -5
  27. package/dist/rx-player.js +366 -257
  28. package/dist/rx-player.min.js +1 -1
  29. package/package.json +2 -2
  30. package/sonar-project.properties +1 -1
  31. package/src/README.md +84 -68
  32. package/src/core/adaptive/adaptive_representation_selector.ts +47 -40
  33. package/src/core/api/playback_observer.ts +185 -173
  34. package/src/core/api/public_api.ts +23 -21
  35. package/src/core/decrypt/content_decryptor.ts +57 -23
  36. package/src/core/init/content_time_boundaries_observer.ts +1 -1
  37. package/src/core/init/create_stream_playback_observer.ts +69 -47
  38. package/src/core/init/initial_seek_and_play.ts +3 -3
  39. package/src/core/init/initialize_directfile.ts +1 -1
  40. package/src/core/init/load_on_media_source.ts +1 -1
  41. package/src/core/init/stall_avoider.ts +12 -9
  42. package/src/core/stream/adaptation/create_representation_estimator.ts +6 -6
  43. package/src/core/stream/orchestrator/stream_orchestrator.ts +5 -4
  44. package/src/core/stream/period/create_empty_adaptation_stream.ts +1 -1
  45. package/src/core/stream/period/period_stream.ts +33 -14
  46. package/src/core/stream/reload_after_switch.ts +1 -1
  47. package/src/core/stream/representation/append_segment_to_buffer.ts +1 -1
  48. package/src/core/stream/representation/representation_stream.ts +1 -1
  49. package/src/utils/reference.ts +40 -28
package/dist/rx-player.js CHANGED
@@ -9919,23 +9919,9 @@ var ContentDecryptor = /*#__PURE__*/function (_EventEmitter) {
9919
9919
  return;
9920
9920
  }
9921
9921
 
9922
- var linkedKeys;
9923
-
9924
- if (sessionInfo.source === "created-session"
9922
+ var linkedKeys = getKeyIdsLinkedToSession(initializationData, sessionInfo.record, options.singleLicensePer, sessionInfo.source === "created-session"
9925
9923
  /* MediaKeySessionLoadingType.Created */
9926
- ) {
9927
- // When the license has been fetched, there might be implicit key ids
9928
- // linked to the session depending on the `singleLicensePer` option.
9929
- linkedKeys = getFetchedLicenseKeysInfo(initializationData, options.singleLicensePer, evt.value.whitelistedKeyIds, evt.value.blacklistedKeyIDs);
9930
- } else {
9931
- // When the MediaKeySession is just a cached/persisted one, we don't
9932
- // have any concept of "implicit key id".
9933
- linkedKeys = {
9934
- whitelisted: evt.value.whitelistedKeyIds,
9935
- blacklisted: evt.value.blacklistedKeyIDs
9936
- };
9937
- }
9938
-
9924
+ , evt.value.whitelistedKeyIds, evt.value.blacklistedKeyIDs);
9939
9925
  sessionInfo.record.associateKeyIds(linkedKeys.whitelisted);
9940
9926
  sessionInfo.record.associateKeyIds(linkedKeys.blacklisted);
9941
9927
  sessionInfo.keyStatuses = {
@@ -10336,22 +10322,44 @@ var ContentDecryptorState;
10336
10322
  ContentDecryptorState[ContentDecryptorState["Disposed"] = 4] = "Disposed";
10337
10323
  })(ContentDecryptorState || (ContentDecryptorState = {}));
10338
10324
  /**
10339
- * Returns information on all keys - explicit or implicit - that are linked to
10340
- * a loaded license.
10325
+ * Returns set of all usable and unusable keys - explicit or implicit - that are
10326
+ * linked to a `MediaKeySession`.
10341
10327
  *
10342
10328
  * In the RxPlayer, there is a concept of "explicit" key ids, which are key ids
10343
10329
  * found in a license whose status can be known through the `keyStatuses`
10344
10330
  * property from a `MediaKeySession`, and of "implicit" key ids, which are key
10345
10331
  * ids which were expected to be in a fetched license, but apparently weren't.
10346
- * @param {Object} initializationData
10347
- * @param {string|undefined} singleLicensePer
10348
- * @param {Array.<Uint8Array>} usableKeyIds
10349
- * @param {Array.<Uint8Array>} unusableKeyIds
10350
- * @returns {Object}
10332
+ *
10333
+ * @param {Object} initializationData - Initialization data object used to make
10334
+ * the request for the current license.
10335
+ * @param {Object} keySessionRecord - The `KeySessionRecord` associated with the
10336
+ * session that has been loaded. It might give supplementary information on
10337
+ * keys implicitly linked to the license.
10338
+ * @param {string|undefined} singleLicensePer - Setting allowing to indicate the
10339
+ * scope a given license should have.
10340
+ * @param {boolean} isCurrentLicense - If `true` the license has been fetched
10341
+ * especially for the current content.
10342
+ *
10343
+ * Knowing this allows to determine that if decryption keys that should have
10344
+ * been referenced in the fetched license (according to the `singleLicensePer`
10345
+ * setting) are missing, then the keys surely must have been voluntarly
10346
+ * removed from the license.
10347
+ *
10348
+ * If it is however set to `false`, it means that the license is an older
10349
+ * license that might have been linked to another content, thus we cannot make
10350
+ * that assumption.
10351
+ * @param {Array.<Uint8Array>} usableKeyIds - Key ids that are present in the
10352
+ * license and can be used.
10353
+ * @param {Array.<Uint8Array>} unusableKeyIds - Key ids that are present in the
10354
+ * license yet cannot be used.
10355
+ * @returns {Object} - Returns an object with the following properties:
10356
+ * - `whitelisted`: Array of key ids for keys that are known to be usable
10357
+ * - `blacklisted`: Array of key ids for keys that are considered unusable.
10358
+ * The qualities linked to those keys should not be played.
10351
10359
  */
10352
10360
 
10353
10361
 
10354
- function getFetchedLicenseKeysInfo(initializationData, singleLicensePer, usableKeyIds, unusableKeyIds) {
10362
+ function getKeyIdsLinkedToSession(initializationData, keySessionRecord, singleLicensePer, isCurrentLicense, usableKeyIds, unusableKeyIds) {
10355
10363
  var _a;
10356
10364
  /**
10357
10365
  * Every key id associated with the MediaKeySession, starting with
@@ -10359,7 +10367,28 @@ function getFetchedLicenseKeysInfo(initializationData, singleLicensePer, usableK
10359
10367
  */
10360
10368
 
10361
10369
 
10362
- var associatedKeyIds = [].concat(usableKeyIds, unusableKeyIds);
10370
+ var associatedKeyIds = [].concat(usableKeyIds, unusableKeyIds); // Add all key ids associated to the `KeySessionRecord` yet not in
10371
+ // `usableKeyIds` nor in `unusableKeyIds`
10372
+
10373
+ var allKnownKeyIds = keySessionRecord.getAssociatedKeyIds();
10374
+
10375
+ var _loop3 = function _loop3() {
10376
+ var kid = _step3.value;
10377
+
10378
+ if (!associatedKeyIds.some(function (ak) {
10379
+ return areKeyIdsEqual(ak, kid);
10380
+ })) {
10381
+ if (log/* default.hasLevel */.Z.hasLevel("DEBUG")) {
10382
+ log/* default.debug */.Z.debug("DRM: KeySessionRecord's key missing in the license, blacklisting it", (0,string_parsing/* bytesToHex */.ci)(kid));
10383
+ }
10384
+
10385
+ associatedKeyIds.push(kid);
10386
+ }
10387
+ };
10388
+
10389
+ for (var _iterator3 = content_decryptor_createForOfIteratorHelperLoose(allKnownKeyIds), _step3; !(_step3 = _iterator3()).done;) {
10390
+ _loop3();
10391
+ }
10363
10392
 
10364
10393
  if (singleLicensePer !== undefined && singleLicensePer !== "init-data") {
10365
10394
  // We want to add the current key ids in the blacklist if it is
@@ -10386,18 +10415,24 @@ function getFetchedLicenseKeysInfo(initializationData, singleLicensePer, usableK
10386
10415
  });
10387
10416
 
10388
10417
  if (missingKeyIds.length > 0) {
10418
+ if (log/* default.hasLevel */.Z.hasLevel("DEBUG")) {
10419
+ log/* default.debug */.Z.debug("DRM: init data keys missing in the license, blacklisting them", missingKeyIds.map(function (m) {
10420
+ return (0,string_parsing/* bytesToHex */.ci)(m);
10421
+ }).join(", "));
10422
+ }
10423
+
10389
10424
  associatedKeyIds.push.apply(associatedKeyIds, missingKeyIds);
10390
10425
  }
10391
10426
  }
10392
10427
 
10393
- if (content !== undefined) {
10428
+ if (isCurrentLicense && content !== undefined) {
10394
10429
  if (singleLicensePer === "content") {
10395
10430
  // Put it in a Set to automatically filter out duplicates (by ref)
10396
10431
  var contentKeys = new Set();
10397
10432
  var manifest = content.manifest;
10398
10433
 
10399
- for (var _iterator3 = content_decryptor_createForOfIteratorHelperLoose(manifest.periods), _step3; !(_step3 = _iterator3()).done;) {
10400
- var period = _step3.value;
10434
+ for (var _iterator4 = content_decryptor_createForOfIteratorHelperLoose(manifest.periods), _step4; !(_step4 = _iterator4()).done;) {
10435
+ var period = _step4.value;
10401
10436
  addKeyIdsFromPeriod(contentKeys, period);
10402
10437
  }
10403
10438
 
@@ -10405,8 +10440,8 @@ function getFetchedLicenseKeysInfo(initializationData, singleLicensePer, usableK
10405
10440
  } else if (singleLicensePer === "periods") {
10406
10441
  var _manifest = content.manifest;
10407
10442
 
10408
- for (var _iterator4 = content_decryptor_createForOfIteratorHelperLoose(_manifest.periods), _step4; !(_step4 = _iterator4()).done;) {
10409
- var _period = _step4.value;
10443
+ for (var _iterator5 = content_decryptor_createForOfIteratorHelperLoose(_manifest.periods), _step5; !(_step5 = _iterator5()).done;) {
10444
+ var _period = _step5.value;
10410
10445
  var periodKeys = new Set();
10411
10446
  addKeyIdsFromPeriod(periodKeys, _period);
10412
10447
 
@@ -10449,7 +10484,7 @@ function getFetchedLicenseKeysInfo(initializationData, singleLicensePer, usableK
10449
10484
  function mergeKeyIdSetIntoArray(set, arr) {
10450
10485
  var setArr = Array.from(set.values());
10451
10486
 
10452
- var _loop3 = function _loop3() {
10487
+ var _loop4 = function _loop4() {
10453
10488
  var kid = _setArr[_i3];
10454
10489
  var isFound = arr.some(function (k) {
10455
10490
  return areKeyIdsEqual(k, kid);
@@ -10461,20 +10496,20 @@ function mergeKeyIdSetIntoArray(set, arr) {
10461
10496
  };
10462
10497
 
10463
10498
  for (var _i3 = 0, _setArr = setArr; _i3 < _setArr.length; _i3++) {
10464
- _loop3();
10499
+ _loop4();
10465
10500
  }
10466
10501
  }
10467
10502
 
10468
10503
  function addKeyIdsFromPeriod(set, period) {
10469
- for (var _iterator5 = content_decryptor_createForOfIteratorHelperLoose(period.getAdaptations()), _step5; !(_step5 = _iterator5()).done;) {
10470
- var adaptation = _step5.value;
10504
+ for (var _iterator6 = content_decryptor_createForOfIteratorHelperLoose(period.getAdaptations()), _step6; !(_step6 = _iterator6()).done;) {
10505
+ var adaptation = _step6.value;
10471
10506
 
10472
- for (var _iterator6 = content_decryptor_createForOfIteratorHelperLoose(adaptation.representations), _step6; !(_step6 = _iterator6()).done;) {
10473
- var representation = _step6.value;
10507
+ for (var _iterator7 = content_decryptor_createForOfIteratorHelperLoose(adaptation.representations), _step7; !(_step7 = _iterator7()).done;) {
10508
+ var representation = _step7.value;
10474
10509
 
10475
10510
  if (representation.contentProtections !== undefined && representation.contentProtections.keyIds !== undefined) {
10476
- for (var _iterator7 = content_decryptor_createForOfIteratorHelperLoose(representation.contentProtections.keyIds), _step7; !(_step7 = _iterator7()).done;) {
10477
- var kidInf = _step7.value;
10511
+ for (var _iterator8 = content_decryptor_createForOfIteratorHelperLoose(representation.contentProtections.keyIds), _step8; !(_step8 = _iterator8()).done;) {
10512
+ var kidInf = _step8.value;
10478
10513
  set.add(kidInf.keyId);
10479
10514
  }
10480
10515
  }
@@ -11000,7 +11035,7 @@ function waitUntilPlayable(observation$) {
11000
11035
  }
11001
11036
  /**
11002
11037
  * Try to play content then handle autoplay errors.
11003
- * @param {HTMLMediaElement} - mediaElement
11038
+ * @param {HTMLMediaElement} mediaElement
11004
11039
  * @returns {Observable}
11005
11040
  */
11006
11041
 
@@ -11043,10 +11078,10 @@ function initialSeekAndPlay(_ref2) {
11043
11078
  }));
11044
11079
  var seekAndPlay$ = seek$.pipe((0,mergeMap/* mergeMap */.z)(function () {
11045
11080
  if (!(0,should_validate_metadata/* default */.Z)() || mediaElement.duration > 0) {
11046
- return waitUntilPlayable(playbackObserver.observe(true));
11081
+ return waitUntilPlayable(playbackObserver.getReference().asObservable());
11047
11082
  } else {
11048
11083
  var error = new media_error/* default */.Z("MEDIA_ERR_NOT_LOADED_METADATA", "Cannot load automatically: your browser " + "falsely announced having loaded the content.");
11049
- return waitUntilPlayable(playbackObserver.observe(true)).pipe((0,startWith/* startWith */.O)(events_generators/* default.warning */.Z.warning(error)));
11084
+ return waitUntilPlayable(playbackObserver.getReference().asObservable()).pipe((0,startWith/* startWith */.O)(events_generators/* default.warning */.Z.warning(error)));
11050
11085
  }
11051
11086
  }), (0,mergeMap/* mergeMap */.z)(function (evt) {
11052
11087
  if (evt !== undefined) {
@@ -11307,7 +11342,7 @@ function initializeDirectfileContent(_ref) {
11307
11342
  // through a throwing Observable.
11308
11343
 
11309
11344
  var mediaError$ = (0,throw_on_media_error/* default */.Z)(mediaElement);
11310
- var observation$ = playbackObserver.observe(true); // Set the speed set by the user on the media element while pausing a
11345
+ var observation$ = playbackObserver.getReference().asObservable(); // Set the speed set by the user on the media element while pausing a
11311
11346
  // little longer while the buffer is empty.
11312
11347
 
11313
11348
  var playbackRate$ = (0,update_playback_rate/* default */.Z)(mediaElement, speed, observation$).pipe((0,ignoreElements/* ignoreElements */.l)());
@@ -11632,7 +11667,7 @@ function StallAvoider(playbackObserver, manifest, lockedStream$, discontinuityUp
11632
11667
  * order (first ordered by Period's start, then by bufferType in any order.
11633
11668
  */
11634
11669
 
11635
- var discontinuitiesStore$ = discontinuityUpdate$.pipe((0,withLatestFrom/* withLatestFrom */.M)(playbackObserver.observe(true)), (0,scan/* scan */.R)(function (discontinuitiesStore, _ref) {
11670
+ var discontinuitiesStore$ = discontinuityUpdate$.pipe((0,withLatestFrom/* withLatestFrom */.M)(playbackObserver.getReference().asObservable()), (0,scan/* scan */.R)(function (discontinuitiesStore, _ref) {
11636
11671
  var evt = _ref[0],
11637
11672
  observation = _ref[1];
11638
11673
  return updateDiscontinuitiesStore(discontinuitiesStore, evt, observation);
@@ -11670,7 +11705,7 @@ function StallAvoider(playbackObserver, manifest, lockedStream$, discontinuityUp
11670
11705
  * Period handled by that stream to unlock the situation.
11671
11706
  */
11672
11707
 
11673
- var unlock$ = lockedStream$.pipe((0,withLatestFrom/* withLatestFrom */.M)(playbackObserver.observe(true)), (0,tap/* tap */.b)(function (_ref2) {
11708
+ var unlock$ = lockedStream$.pipe((0,withLatestFrom/* withLatestFrom */.M)(playbackObserver.getReference().asObservable()), (0,tap/* tap */.b)(function (_ref2) {
11674
11709
  var lockedStreamEvt = _ref2[0],
11675
11710
  observation = _ref2[1];
11676
11711
 
@@ -11697,7 +11732,7 @@ function StallAvoider(playbackObserver, manifest, lockedStream$, discontinuityUp
11697
11732
 
11698
11733
  /* eslint-disable-next-line @typescript-eslint/no-unsafe-argument */
11699
11734
  (0,ignoreElements/* ignoreElements */.l)());
11700
- var stall$ = playbackObserver.observe(true).pipe((0,withLatestFrom/* withLatestFrom */.M)(discontinuitiesStore$), (0,map/* map */.U)(function (_ref3) {
11735
+ var stall$ = playbackObserver.getReference().asObservable().pipe((0,withLatestFrom/* withLatestFrom */.M)(discontinuitiesStore$), (0,map/* map */.U)(function (_ref3) {
11701
11736
  var observation = _ref3[0],
11702
11737
  discontinuitiesStore = _ref3[1];
11703
11738
  var buffered = observation.buffered,
@@ -11772,11 +11807,17 @@ function StallAvoider(playbackObserver, manifest, lockedStream$, discontinuityUp
11772
11807
  ignoredStallTimeStamp = _now;
11773
11808
  }
11774
11809
 
11775
- if (is_seeking_approximate && observation.position < lastSeekingPosition && _now - ignoredStallTimeStamp < FORCE_DISCONTINUITY_SEEK_DELAY) {
11776
- return {
11777
- type: "stalled",
11778
- value: stalledReason
11779
- };
11810
+ if (is_seeking_approximate && observation.position < lastSeekingPosition) {
11811
+ log/* default.debug */.Z.debug("Init: the device appeared to have seeked back by itself.");
11812
+
11813
+ if (_now - ignoredStallTimeStamp < FORCE_DISCONTINUITY_SEEK_DELAY) {
11814
+ return {
11815
+ type: "stalled",
11816
+ value: stalledReason
11817
+ };
11818
+ } else {
11819
+ log/* default.warn */.Z.warn("Init: ignored stall for too long, checking discontinuity", _now - ignoredStallTimeStamp);
11820
+ }
11780
11821
  }
11781
11822
 
11782
11823
  lastSeekingPosition = null;
@@ -41379,13 +41420,13 @@ function createSharedReference(initialValue) {
41379
41420
 
41380
41421
  /**
41381
41422
  * Update the value of this shared reference.
41382
- * @param {*}
41423
+ * @param {*} newVal
41383
41424
  */
41384
41425
  setValue: function setValue(newVal) {
41385
41426
  if (isFinished) {
41386
- if (false) {} else {
41387
- return;
41388
- }
41427
+ if (false) {}
41428
+
41429
+ return;
41389
41430
  }
41390
41431
 
41391
41432
  value = newVal;
@@ -41408,6 +41449,11 @@ function createSharedReference(initialValue) {
41408
41449
  }
41409
41450
  }
41410
41451
  },
41452
+
41453
+ /**
41454
+ * Update the value of this shared reference only if it changed.
41455
+ * @param {*} newVal
41456
+ */
41411
41457
  setValueIfChanged: function setValueIfChanged(newVal) {
41412
41458
  if (newVal !== value) {
41413
41459
  this.setValue(newVal);
@@ -41518,13 +41564,29 @@ function createSharedReference(initialValue) {
41518
41564
  if (!cbObj.hasBeenCleared) {
41519
41565
  cbObj.complete();
41520
41566
  }
41567
+
41568
+ cbObj.hasBeenCleared = true;
41521
41569
  } catch (_) {
41522
41570
  /* nothing */
41523
41571
  }
41524
41572
  }
41573
+
41574
+ cbs.length = 0;
41525
41575
  }
41526
41576
  };
41527
41577
  }
41578
+ /**
41579
+ * Create a new `ISharedReference` based on another one by mapping over its
41580
+ * referenced value each time it is updated.
41581
+ * @param {Object} originalRef - The Original `ISharedReference` you wish to map
41582
+ * over.
41583
+ * @param {Function} mappingFn - The mapping function which will receives
41584
+ * `originalRef`'s value and outputs this new reference's value.
41585
+ * @param {Object | undefined} [cancellationSignal] - Optionally, a
41586
+ * `CancellationSignal` which will finish that reference when it emits.
41587
+ * @returns {Object} - The new, mapped, reference.
41588
+ */
41589
+
41528
41590
  function createMappedReference(originalRef, mappingFn, cancellationSignal) {
41529
41591
  var newRef = createSharedReference(mappingFn(originalRef.getValue()));
41530
41592
  originalRef.onUpdate(function mapOriginalReference(x) {
@@ -50557,8 +50619,10 @@ function selectOptimalRepresentation(representations, optimalBitrate, minBitrate
50557
50619
  /**
50558
50620
  * Select the most adapted Representation according to the network and buffer
50559
50621
  * metrics it receives.
50622
+ *
50560
50623
  * @param {Object} options - Initial configuration (see type definition)
50561
- * @returns {Object} - Interface allowing to select a Representation
50624
+ * @returns {Object} - Interface allowing to select a Representation.
50625
+ * @see IRepresentationEstimator
50562
50626
  */
50563
50627
 
50564
50628
  function createAdaptiveRepresentationSelector(options) {
@@ -50576,18 +50640,17 @@ function createAdaptiveRepresentationSelector(options) {
50576
50640
  /**
50577
50641
  * Returns Object emitting Representation estimates as well as callbacks
50578
50642
  * allowing to helping it produce them.
50643
+ *
50644
+ * @see IRepresentationEstimator
50579
50645
  * @param {Object} context
50580
- * @param {Object} currentRepresentation - Reference emitting the
50581
- * Representation currently loaded.
50582
- * @param {Object} representations - Reference emitting the list of available
50583
- * Representations to choose from.
50584
- * @param {Object} playbackObserver - Emits regularly playback conditions
50585
- * @param {Object} cancellationSignal - After this `CancellationSignal` emits,
50586
- * estimates will stop to be emitted.
50646
+ * @param {Object} currentRepresentation
50647
+ * @param {Object} representations
50648
+ * @param {Object} playbackObserver
50649
+ * @param {Object} stopAllEstimates
50587
50650
  * @returns {Array.<Object>}
50588
50651
  */
50589
50652
 
50590
- return function getEstimates(context, currentRepresentation, representations, playbackObserver, cancellationSignal) {
50653
+ return function getEstimates(context, currentRepresentation, representations, playbackObserver, stopAllEstimates) {
50591
50654
  var type = context.adaptation.type;
50592
50655
 
50593
50656
  var bandwidthEstimator = _getBandwidthEstimator(type);
@@ -50612,7 +50675,7 @@ function createAdaptiveRepresentationSelector(options) {
50612
50675
  playbackObserver: playbackObserver,
50613
50676
  representations: representations,
50614
50677
  lowLatencyMode: lowLatencyMode
50615
- }, cancellationSignal);
50678
+ }, stopAllEstimates);
50616
50679
  };
50617
50680
  /**
50618
50681
  * Returns interface allowing to estimate network throughtput for a given type.
@@ -50649,11 +50712,11 @@ function createAdaptiveRepresentationSelector(options) {
50649
50712
  * events to help it doing those estimates.
50650
50713
  *
50651
50714
  * @param {Object} args
50652
- * @param {Object} cancellationSignal
50715
+ * @param {Object} stopAllEstimates
50653
50716
  * @returns {Array.<Object>}
50654
50717
  */
50655
50718
 
50656
- function getEstimateReference(_ref, cancellationSignal) {
50719
+ function getEstimateReference(_ref, stopAllEstimates) {
50657
50720
  var bandwidthEstimator = _ref.bandwidthEstimator,
50658
50721
  context = _ref.context,
50659
50722
  currentRepresentation = _ref.currentRepresentation,
@@ -50684,19 +50747,21 @@ function getEstimateReference(_ref, cancellationSignal) {
50684
50747
  * configuration and to cancel them altogether.
50685
50748
  */
50686
50749
 
50687
- var currentEstimatesCanceller = new task_canceller/* default */.ZP();
50688
- cancellationSignal.register(function () {
50689
- currentEstimatesCanceller.cancel();
50750
+ var currentEstimatesCanceller = new task_canceller/* default */.ZP({
50751
+ cancelOn: stopAllEstimates
50690
50752
  }); // Create `ISharedReference` on which estimates will be emitted.
50691
50753
 
50692
50754
  var estimateRef = createEstimateReference(manualBitrate.getValue(), representationsRef.getValue(), currentEstimatesCanceller.signal);
50693
50755
  manualBitrate.onUpdate(restartEstimatesProductionFromCurrentConditions, {
50694
- clearSignal: currentEstimatesCanceller.signal
50756
+ clearSignal: stopAllEstimates
50695
50757
  });
50696
50758
  representationsRef.onUpdate(restartEstimatesProductionFromCurrentConditions, {
50697
- clearSignal: currentEstimatesCanceller.signal
50759
+ clearSignal: stopAllEstimates
50698
50760
  });
50699
- return [estimateRef, callbacks];
50761
+ return {
50762
+ estimates: estimateRef,
50763
+ callbacks: callbacks
50764
+ };
50700
50765
 
50701
50766
  function createEstimateReference(manualBitrateVal, representations, innerCancellationSignal) {
50702
50767
  if (manualBitrateVal >= 0) {
@@ -50751,17 +50816,9 @@ function getEstimateReference(_ref, cancellationSignal) {
50751
50816
  * Only used in very specific scenarios.
50752
50817
  */
50753
50818
 
50754
- var guessBasedChooser = new GuessBasedChooser(scoreCalculator, prevEstimate);
50755
- var lastPlaybackObservation; // get initial observation for initial estimate
50756
-
50757
- var unregisterInitial = playbackObserver.listen(function (obs) {
50758
- lastPlaybackObservation = obs;
50759
- }, {
50760
- includeLastObservation: true
50761
- });
50762
- unregisterInitial(); // The initial is emitted synchronously, we can now remove it
50763
- // TODO cleaner playbackObserver.getLast() or something?
50819
+ var guessBasedChooser = new GuessBasedChooser(scoreCalculator, prevEstimate); // get initial observation for initial estimate
50764
50820
 
50821
+ var lastPlaybackObservation = playbackObserver.getReference().getValue();
50765
50822
  /** Reference through which estimates are emitted. */
50766
50823
 
50767
50824
  var innerEstimateRef = (0,reference/* default */.ZP)(getCurrentEstimate()); // subscribe to subsequent playback observations
@@ -50942,7 +50999,9 @@ function getEstimateReference(_ref, cancellationSignal) {
50942
50999
  var manualBitrateVal = manualBitrate.getValue();
50943
51000
  var representations = representationsRef.getValue();
50944
51001
  currentEstimatesCanceller.cancel();
50945
- currentEstimatesCanceller = new task_canceller/* default */.ZP();
51002
+ currentEstimatesCanceller = new task_canceller/* default */.ZP({
51003
+ cancelOn: stopAllEstimates
51004
+ });
50946
51005
  var newRef = createEstimateReference(manualBitrateVal, representations, currentEstimatesCanceller.signal);
50947
51006
  newRef.onUpdate(function onNewEstimate(newEstimate) {
50948
51007
  estimateRef.setValue(newEstimate);
@@ -51280,7 +51339,7 @@ var link_drm_and_content = __webpack_require__(9607);
51280
51339
  // EXTERNAL MODULE: ./node_modules/rxjs/dist/esm5/internal/observable/throwError.js
51281
51340
  var throwError = __webpack_require__(3610);
51282
51341
  // EXTERNAL MODULE: ./node_modules/rxjs/dist/esm5/internal/observable/interval.js
51283
- var observable_interval = __webpack_require__(6697);
51342
+ var interval = __webpack_require__(6697);
51284
51343
  // EXTERNAL MODULE: ./node_modules/rxjs/dist/esm5/internal/operators/tap.js
51285
51344
  var tap = __webpack_require__(2006);
51286
51345
  // EXTERNAL MODULE: ./node_modules/rxjs/dist/esm5/internal/observable/fromEvent.js
@@ -51405,7 +51464,7 @@ var AudioVideoSegmentBuffer = /*#__PURE__*/function (_SegmentBuffer) {
51405
51464
  // SourceBuffer is currently updating.
51406
51465
 
51407
51466
 
51408
- (0,observable_interval/* interval */.F)(SOURCE_BUFFER_FLUSHING_INTERVAL).pipe((0,tap/* tap */.b)(function () {
51467
+ (0,interval/* interval */.F)(SOURCE_BUFFER_FLUSHING_INTERVAL).pipe((0,tap/* tap */.b)(function () {
51409
51468
  return _this._flush();
51410
51469
  }), (0,takeUntil/* takeUntil */.R)(_this._destroy$)).subscribe();
51411
51470
  (0,fromEvent/* fromEvent */.R)(_this._sourceBuffer, "error").pipe((0,tap/* tap */.b)(function (err) {
@@ -52875,7 +52934,7 @@ function reloadAfterSwitch(period, bufferType, playbackObserver, deltaPos) {
52875
52934
  // It can happen when `reloadAfterSwitch` is called as a side-effect of the
52876
52935
  // same event that triggers the playback observation to be emitted.
52877
52936
  return nextTickObs().pipe((0,mergeMap/* mergeMap */.z)(function () {
52878
- return playbackObserver.observe(true);
52937
+ return playbackObserver.getReference().asObservable();
52879
52938
  }), (0,map/* map */.U)(function (observation) {
52880
52939
  var _a, _b;
52881
52940
 
@@ -54460,7 +54519,7 @@ function appendSegmentToBuffer(playbackObserver, segmentBuffer, dataInfos) {
54460
54519
  throw new media_error/* default */.Z("BUFFER_APPEND_ERROR", reason);
54461
54520
  }
54462
54521
 
54463
- return playbackObserver.observe(true).pipe((0,take/* take */.q)(1), (0,mergeMap/* mergeMap */.z)(function (observation) {
54522
+ return playbackObserver.getReference().asObservable().pipe((0,take/* take */.q)(1), (0,mergeMap/* mergeMap */.z)(function (observation) {
54464
54523
  var _a;
54465
54524
 
54466
54525
  var currentPos = (_a = observation.position.pending) !== null && _a !== void 0 ? _a : observation.position.last;
@@ -54741,7 +54800,7 @@ function RepresentationStream(_ref) {
54741
54800
  var queue$ = downloadingQueue.start().pipe((0,mergeMap/* mergeMap */.z)(onQueueEvent));
54742
54801
  /** Observable emitting the stream "status" and filling `lastSegmentQueue`. */
54743
54802
 
54744
- var status$ = combineLatest([playbackObserver.observe(true), bufferGoal$, maxBufferSize$, terminate$.pipe((0,take/* take */.q)(1), (0,startWith/* startWith */.O)(null)), reCheckNeededSegments$.pipe((0,startWith/* startWith */.O)(undefined))]).pipe((0,withLatestFrom/* withLatestFrom */.M)(fastSwitchThreshold$), (0,mergeMap/* mergeMap */.z)(function (_ref2) {
54803
+ var status$ = combineLatest([playbackObserver.getReference().asObservable(), bufferGoal$, maxBufferSize$, terminate$.pipe((0,take/* take */.q)(1), (0,startWith/* startWith */.O)(null)), reCheckNeededSegments$.pipe((0,startWith/* startWith */.O)(undefined))]).pipe((0,withLatestFrom/* withLatestFrom */.M)(fastSwitchThreshold$), (0,mergeMap/* mergeMap */.z)(function (_ref2) {
54745
54804
  var _ref2$ = _ref2[0],
54746
54805
  observation = _ref2$[0],
54747
54806
  bufferGoal = _ref2$[1],
@@ -55013,8 +55072,8 @@ function getRepresentationEstimate(content, representationEstimator, currentRepr
55013
55072
  var unregisterCleanUp = cancellationSignal.register(cleanUp);
55014
55073
 
55015
55074
  var _representationEstima = representationEstimator(content, currentRepresentation, representations, playbackObserver, cancellationSignal),
55016
- estimateRef = _representationEstima[0],
55017
- abrCallbacks = _representationEstima[1];
55075
+ estimateRef = _representationEstima.estimates,
55076
+ abrCallbacks = _representationEstima.callbacks;
55018
55077
 
55019
55078
  return {
55020
55079
  abrCallbacks: abrCallbacks,
@@ -55393,7 +55452,7 @@ function createEmptyAdaptationStream(playbackObserver, wantedBufferAhead, buffer
55393
55452
  var period = content.period;
55394
55453
  var hasFinishedLoading = false;
55395
55454
  var wantedBufferAhead$ = wantedBufferAhead.asObservable();
55396
- var observation$ = playbackObserver.observe(true);
55455
+ var observation$ = playbackObserver.getReference().asObservable();
55397
55456
  return combineLatest([observation$, wantedBufferAhead$]).pipe((0,mergeMap/* mergeMap */.z)(function (_ref) {
55398
55457
  var observation = _ref[0],
55399
55458
  wba = _ref[1];
@@ -55783,6 +55842,7 @@ function getFirstSegmentAfterPeriod(inventory, period) {
55783
55842
 
55784
55843
 
55785
55844
 
55845
+
55786
55846
  /**
55787
55847
  * Create single PeriodStream Observable:
55788
55848
  * - Lazily create (or reuse) a SegmentBuffer for the given type.
@@ -55979,16 +56039,30 @@ function getFirstDeclaredMimeType(adaptation) {
55979
56039
 
55980
56040
 
55981
56041
  function createAdaptationStreamPlaybackObserver(initialPlaybackObserver, segmentBuffer) {
55982
- return initialPlaybackObserver.deriveReadOnlyObserver(function (observation$) {
55983
- return observation$.pipe((0,map/* map */.U)(mapObservation));
55984
- }, mapObservation);
55985
-
55986
- function mapObservation(baseObservation) {
55987
- var buffered = segmentBuffer.getBufferedRanges();
55988
- return (0,object_assign/* default */.Z)({}, baseObservation, {
55989
- bufferGap: (0,ranges/* getLeftSizeOfRange */.L7)(buffered, baseObservation.position.last)
56042
+ return initialPlaybackObserver.deriveReadOnlyObserver(function transform(observationRef, cancellationSignal) {
56043
+ var newRef = (0,reference/* default */.ZP)(constructAdaptationStreamPlaybackObservation());
56044
+ observationRef.onUpdate(emitAdaptationStreamPlaybackObservation, {
56045
+ clearSignal: cancellationSignal,
56046
+ emitCurrentValue: false
55990
56047
  });
55991
- }
56048
+ cancellationSignal.register(function () {
56049
+ newRef.finish();
56050
+ });
56051
+ return newRef;
56052
+
56053
+ function constructAdaptationStreamPlaybackObservation() {
56054
+ var baseObservation = observationRef.getValue();
56055
+ var buffered = segmentBuffer.getBufferedRanges();
56056
+ var bufferGap = (0,ranges/* getLeftSizeOfRange */.L7)(buffered, baseObservation.position.last);
56057
+ return (0,object_assign/* default */.Z)({}, baseObservation, {
56058
+ bufferGap: bufferGap
56059
+ });
56060
+ }
56061
+
56062
+ function emitAdaptationStreamPlaybackObservation() {
56063
+ newRef.setValue(constructAdaptationStreamPlaybackObservation());
56064
+ }
56065
+ });
55992
56066
  }
55993
56067
  ;// CONCATENATED MODULE: ./src/core/stream/period/index.ts
55994
56068
  /**
@@ -56369,7 +56443,7 @@ function StreamOrchestrator(content, playbackObserver, representationEstimator,
56369
56443
  var defaultMaxAhead = MAXIMUM_MAX_BUFFER_AHEAD[bufferType] != null ? MAXIMUM_MAX_BUFFER_AHEAD[bufferType] : Infinity;
56370
56444
  return BufferGarbageCollector({
56371
56445
  segmentBuffer: segmentBuffer,
56372
- currentTime$: playbackObserver.observe(true).pipe((0,map/* map */.U)(function (o) {
56446
+ currentTime$: playbackObserver.getReference().asObservable().pipe((0,map/* map */.U)(function (o) {
56373
56447
  var _a;
56374
56448
 
56375
56449
  return (_a = o.position.pending) !== null && _a !== void 0 ? _a : o.position.last;
@@ -56487,7 +56561,8 @@ function StreamOrchestrator(content, playbackObserver, representationEstimator,
56487
56561
  // than the ones already considered
56488
56562
 
56489
56563
 
56490
- var restartStreamsWhenOutOfBounds$ = playbackObserver.observe(true).pipe((0,filter_map/* default */.Z)(function (_ref2) {
56564
+ var observation$ = playbackObserver.getReference().asObservable();
56565
+ var restartStreamsWhenOutOfBounds$ = observation$.pipe((0,filter_map/* default */.Z)(function (_ref2) {
56491
56566
  var position = _ref2.position;
56492
56567
 
56493
56568
  var _a, _b;
@@ -56548,7 +56623,7 @@ function StreamOrchestrator(content, playbackObserver, representationEstimator,
56548
56623
  }).concat([// Schedule micro task before checking the last playback observation
56549
56624
  // to reduce the risk of race conditions where the next observation
56550
56625
  // was going to be emitted synchronously.
56551
- nextTickObs().pipe((0,ignoreElements/* ignoreElements */.l)()), playbackObserver.observe(true).pipe((0,take/* take */.q)(1), (0,mergeMap/* mergeMap */.z)(function (observation) {
56626
+ nextTickObs().pipe((0,ignoreElements/* ignoreElements */.l)()), playbackObserver.getReference().asObservable().pipe((0,take/* take */.q)(1), (0,mergeMap/* mergeMap */.z)(function (observation) {
56552
56627
  var _a;
56553
56628
 
56554
56629
  var shouldAutoPlay = !((_a = observation.paused.pending) !== null && _a !== void 0 ? _a : playbackObserver.getIsPaused());
@@ -56605,7 +56680,7 @@ function StreamOrchestrator(content, playbackObserver, representationEstimator,
56605
56680
 
56606
56681
  var destroyNextStreams$ = new Subject/* Subject */.x(); // Emits when the current position goes over the end of the current Stream.
56607
56682
 
56608
- var endOfCurrentStream$ = playbackObserver.observe(true).pipe((0,filter/* filter */.h)(function (_ref4) {
56683
+ var endOfCurrentStream$ = playbackObserver.getReference().asObservable().pipe((0,filter/* filter */.h)(function (_ref4) {
56609
56684
  var position = _ref4.position;
56610
56685
 
56611
56686
  var _a;
@@ -56757,7 +56832,7 @@ function ContentTimeBoundariesObserver(manifest, streams, playbackObserver) {
56757
56832
  var maximumPositionCalculator = new MaximumPositionCalculator(manifest); // trigger warnings when the wanted time is before or after the manifest's
56758
56833
  // segments
56759
56834
 
56760
- var outOfManifest$ = playbackObserver.observe(true).pipe((0,filter_map/* default */.Z)(function (_ref) {
56835
+ var outOfManifest$ = playbackObserver.getReference().asObservable().pipe((0,filter_map/* default */.Z)(function (_ref) {
56761
56836
  var position = _ref.position;
56762
56837
 
56763
56838
  var _a;
@@ -56985,7 +57060,7 @@ function getLastPositionFromAdaptation(adaptation) {
56985
57060
  * @param {Object} manifest
56986
57061
  * @param {Object} playbackObserver
56987
57062
  * @param {Object} args
56988
- * @returns {Observable}
57063
+ * @returns {Object}
56989
57064
  */
56990
57065
 
56991
57066
  function createStreamPlaybackObserver(manifest, playbackObserver, _ref) {
@@ -56994,10 +57069,24 @@ function createStreamPlaybackObserver(manifest, playbackObserver, _ref) {
56994
57069
  initialSeekPerformed = _ref.initialSeekPerformed,
56995
57070
  speed = _ref.speed,
56996
57071
  startTime = _ref.startTime;
56997
- return playbackObserver.deriveReadOnlyObserver(function mapObservable(observation$) {
56998
- return combineLatest([observation$, speed.asObservable()]).pipe((0,map/* map */.U)(function (_ref2) {
56999
- var observation = _ref2[0],
57000
- lastSpeed = _ref2[1];
57072
+ return playbackObserver.deriveReadOnlyObserver(function transform(observationRef, cancellationSignal) {
57073
+ var newRef = (0,reference/* default */.ZP)(constructStreamPlaybackObservation());
57074
+ speed.onUpdate(emitStreamPlaybackObservation, {
57075
+ clearSignal: cancellationSignal,
57076
+ emitCurrentValue: false
57077
+ });
57078
+ observationRef.onUpdate(emitStreamPlaybackObservation, {
57079
+ clearSignal: cancellationSignal,
57080
+ emitCurrentValue: false
57081
+ });
57082
+ cancellationSignal.register(function () {
57083
+ newRef.finish();
57084
+ });
57085
+ return newRef;
57086
+
57087
+ function constructStreamPlaybackObservation() {
57088
+ var observation = observationRef.getValue();
57089
+ var lastSpeed = speed.getValue();
57001
57090
  var pendingPosition;
57002
57091
 
57003
57092
  if (!initialSeekPerformed.getValue()) {
@@ -57031,7 +57120,11 @@ function createStreamPlaybackObserver(manifest, playbackObserver, _ref) {
57031
57120
  readyState: observation.readyState,
57032
57121
  speed: lastSpeed
57033
57122
  };
57034
- }));
57123
+ }
57124
+
57125
+ function emitStreamPlaybackObservation() {
57126
+ newRef.setValue(constructStreamPlaybackObservation());
57127
+ }
57035
57128
  });
57036
57129
  }
57037
57130
  // EXTERNAL MODULE: ./src/core/init/emit_loaded_event.ts + 1 modules
@@ -57421,7 +57514,7 @@ function areSourceBuffersUpdating$(sourceBuffers) {
57421
57514
  return true;
57422
57515
  })), (0,fromEvent/* fromEvent */.R)(sourceBuffer, "update").pipe((0,map/* map */.U)(function () {
57423
57516
  return false;
57424
- })), (0,observable_interval/* interval */.F)(500).pipe((0,map/* map */.U)(function () {
57517
+ })), (0,interval/* interval */.F)(500).pipe((0,map/* map */.U)(function () {
57425
57518
  return sourceBuffer.updating;
57426
57519
  }))).pipe((0,startWith/* startWith */.O)(sourceBuffer.updating), (0,distinctUntilChanged/* distinctUntilChanged */.x)()));
57427
57520
  };
@@ -57716,7 +57809,7 @@ function streamEventsEmitter(manifest, mediaElement, observation$) {
57716
57809
  var _config$getCurrent = config/* default.getCurrent */.Z.getCurrent(),
57717
57810
  STREAM_EVENT_EMITTER_POLL_INTERVAL = _config$getCurrent.STREAM_EVENT_EMITTER_POLL_INTERVAL;
57718
57811
 
57719
- return combineLatest([(0,observable_interval/* interval */.F)(STREAM_EVENT_EMITTER_POLL_INTERVAL).pipe((0,startWith/* startWith */.O)(null)), observation$]).pipe((0,map/* map */.U)(function (_ref) {
57812
+ return combineLatest([(0,interval/* interval */.F)(STREAM_EVENT_EMITTER_POLL_INTERVAL).pipe((0,startWith/* startWith */.O)(null)), observation$]).pipe((0,map/* map */.U)(function (_ref) {
57720
57813
  var _ = _ref[0],
57721
57814
  observation = _ref[1];
57722
57815
  var seeking = observation.seeking;
@@ -57834,7 +57927,7 @@ function createMediaSourceLoader(_ref) {
57834
57927
  initialPlayPerformed = _initialSeekAndPlay.initialPlayPerformed,
57835
57928
  initialSeekPerformed = _initialSeekAndPlay.initialSeekPerformed;
57836
57929
 
57837
- var observation$ = playbackObserver.observe(true);
57930
+ var observation$ = playbackObserver.getReference().asObservable();
57838
57931
  var streamEvents$ = initialPlayPerformed.asObservable().pipe((0,filter/* filter */.h)(function (hasPlayed) {
57839
57932
  return hasPlayed;
57840
57933
  }), (0,mergeMap/* mergeMap */.z)(function () {
@@ -59161,12 +59254,6 @@ function parseLoadVideoOptions(options) {
59161
59254
  }
59162
59255
 
59163
59256
 
59164
- ;// CONCATENATED MODULE: ./node_modules/rxjs/dist/esm5/internal/operators/skip.js
59165
-
59166
- function skip(count) {
59167
- return (0,filter/* filter */.h)(function (_, index) { return count <= index; });
59168
- }
59169
- //# sourceMappingURL=skip.js.map
59170
59257
  ;// CONCATENATED MODULE: ./src/core/api/playback_observer.ts
59171
59258
  /**
59172
59259
  * Copyright 2015 CANAL+ Group
@@ -59189,6 +59276,7 @@ function skip(count) {
59189
59276
 
59190
59277
 
59191
59278
 
59279
+
59192
59280
  /**
59193
59281
  * HTMLMediaElement Events for which playback observations are calculated and
59194
59282
  * emitted.
@@ -59212,6 +59300,12 @@ var SCANNED_MEDIA_ELEMENTS_EVENTS = ["canplay", "ended", "play", "pause", "seeki
59212
59300
 
59213
59301
  var PlaybackObserver = /*#__PURE__*/function () {
59214
59302
  /**
59303
+ * Create a new `PlaybackObserver`, which allows to produce new "playback
59304
+ * observations" on various media events and intervals.
59305
+ *
59306
+ * Note that creating a `PlaybackObserver` lead to the usage of resources,
59307
+ * such as event listeners which will only be freed once the `stop` method is
59308
+ * called.
59215
59309
  * @param {HTMLMediaElement} mediaElement
59216
59310
  * @param {Object} options
59217
59311
  */
@@ -59220,18 +59314,33 @@ var PlaybackObserver = /*#__PURE__*/function () {
59220
59314
  this._mediaElement = mediaElement;
59221
59315
  this._withMediaSource = options.withMediaSource;
59222
59316
  this._lowLatencyMode = options.lowLatencyMode;
59223
- this._lastObservation = null;
59224
- this._observation$ = null;
59317
+ this._canceller = new task_canceller/* default */.ZP();
59318
+ this._observationRef = this._createSharedReference();
59225
59319
  }
59226
59320
  /**
59227
- * Returns the current position advertised by the `HTMLMediaElement`, in
59228
- * seconds.
59229
- * @returns {number}
59321
+ * Stop the `PlaybackObserver` from emitting playback observations and free all
59322
+ * resources reserved to emitting them such as event listeners, intervals and
59323
+ * subscribing callbacks.
59324
+ *
59325
+ * Once `stop` is called, no new playback observation will ever be emitted.
59326
+ *
59327
+ * Note that it is important to call stop once the `PlaybackObserver` is no
59328
+ * more needed to avoid unnecessarily leaking resources.
59230
59329
  */
59231
59330
 
59232
59331
 
59233
59332
  var _proto = PlaybackObserver.prototype;
59234
59333
 
59334
+ _proto.stop = function stop() {
59335
+ this._canceller.cancel();
59336
+ }
59337
+ /**
59338
+ * Returns the current position advertised by the `HTMLMediaElement`, in
59339
+ * seconds.
59340
+ * @returns {number}
59341
+ */
59342
+ ;
59343
+
59235
59344
  _proto.getCurrentTime = function getCurrentTime() {
59236
59345
  return this._mediaElement.currentTime;
59237
59346
  }
@@ -59273,31 +59382,19 @@ var PlaybackObserver = /*#__PURE__*/function () {
59273
59382
  return this._mediaElement.readyState;
59274
59383
  }
59275
59384
  /**
59276
- * Returns an Observable regularly emitting playback observation, optionally
59277
- * starting with the last one.
59385
+ * Returns an `IReadOnlySharedReference` storing the last playback observation
59386
+ * produced by the `PlaybackObserver` and updated each time a new one is
59387
+ * produced.
59278
59388
  *
59279
- * Note that this Observable is shared and unique, so that multiple `observe`
59280
- * call will return the exact same Observable and multiple concurrent
59281
- * `subscribe` will receive the same events at the same time.
59282
- * This was done for performance and simplicity reasons.
59389
+ * This value can then be for example subscribed to to be notified of future
59390
+ * playback observations.
59283
59391
  *
59284
- * @param {boolean} includeLastObservation
59285
- * @returns {Observable}
59392
+ * @returns {Object}
59286
59393
  */
59287
59394
  ;
59288
59395
 
59289
- _proto.observe = function observe(includeLastObservation) {
59290
- var _this = this;
59291
-
59292
- return (0,defer/* defer */.P)(function () {
59293
- if (_this._observation$ === null || _this._lastObservation === null) {
59294
- _this._lastObservation = _this._generateInitialObservation();
59295
- _this._observation$ = _this._createInnerObservable().pipe((0,share/* share */.B)());
59296
- return _this.observe(includeLastObservation);
59297
- } else {
59298
- return includeLastObservation ? _this._observation$.pipe((0,startWith/* startWith */.O)(_this._lastObservation)) : _this._observation$;
59299
- }
59300
- });
59396
+ _proto.getReference = function getReference() {
59397
+ return this._observationRef;
59301
59398
  }
59302
59399
  /**
59303
59400
  * Register a callback so it regularly receives playback observations.
@@ -59307,25 +59404,20 @@ var PlaybackObserver = /*#__PURE__*/function () {
59307
59404
  * be first emitted synchronously.
59308
59405
  * - `clearSignal`: If set, the callback will be unregistered when this
59309
59406
  * CancellationSignal emits.
59310
- * @returns {Function} - Allows to easily unregister the callback
59311
59407
  */
59312
59408
  ;
59313
59409
 
59314
59410
  _proto.listen = function listen(cb, options) {
59315
- var _a, _b, _c, _d;
59411
+ var _a;
59316
59412
 
59317
- if (((_a = options === null || options === void 0 ? void 0 : options.clearSignal) === null || _a === void 0 ? void 0 : _a.isCancelled) === true) {
59413
+ if (this._canceller.isUsed || ((_a = options === null || options === void 0 ? void 0 : options.clearSignal) === null || _a === void 0 ? void 0 : _a.isCancelled) === true) {
59318
59414
  return noop/* default */.Z;
59319
59415
  }
59320
59416
 
59321
- var sub = this.observe((_b = options === null || options === void 0 ? void 0 : options.includeLastObservation) !== null && _b !== void 0 ? _b : false).subscribe(cb);
59322
- var unregister = (_d = (_c = options === null || options === void 0 ? void 0 : options.clearSignal) === null || _c === void 0 ? void 0 : _c.register(function () {
59323
- sub.unsubscribe();
59324
- })) !== null && _d !== void 0 ? _d : noop/* default */.Z;
59325
- return function () {
59326
- unregister();
59327
- sub.unsubscribe();
59328
- };
59417
+ this._observationRef.onUpdate(cb, {
59418
+ clearSignal: options === null || options === void 0 ? void 0 : options.clearSignal,
59419
+ emitCurrentValue: options === null || options === void 0 ? void 0 : options.includeLastObservation
59420
+ });
59329
59421
  }
59330
59422
  /**
59331
59423
  * Generate a new playback observer which can listen to other
@@ -59338,82 +59430,113 @@ var PlaybackObserver = /*#__PURE__*/function () {
59338
59430
  *
59339
59431
  * As argument, this method takes a function which will allow to produce
59340
59432
  * the new set of properties to be present on each observation.
59341
- * @param {Function} mapObservable
59433
+ * @param {Function} transform
59342
59434
  * @returns {Object}
59343
59435
  */
59344
59436
  ;
59345
59437
 
59346
- _proto.deriveReadOnlyObserver = function deriveReadOnlyObserver(mapObservable) {
59347
- return generateReadOnlyObserver(this, mapObservable);
59438
+ _proto.deriveReadOnlyObserver = function deriveReadOnlyObserver(transform) {
59439
+ return generateReadOnlyObserver(this, transform, this._canceller.signal);
59348
59440
  }
59349
59441
  /**
59350
- * Creates the observable that will generate playback observations.
59442
+ * Creates the `IReadOnlySharedReference` that will generate playback
59443
+ * observations.
59351
59444
  * @returns {Observable}
59352
59445
  */
59353
59446
  ;
59354
59447
 
59355
- _proto._createInnerObservable = function _createInnerObservable() {
59356
- var _this2 = this;
59448
+ _proto._createSharedReference = function _createSharedReference() {
59449
+ var _this = this;
59357
59450
 
59358
- return (0,defer/* defer */.P)(function () {
59359
- var _config$getCurrent = config/* default.getCurrent */.Z.getCurrent(),
59360
- SAMPLING_INTERVAL_MEDIASOURCE = _config$getCurrent.SAMPLING_INTERVAL_MEDIASOURCE,
59361
- SAMPLING_INTERVAL_LOW_LATENCY = _config$getCurrent.SAMPLING_INTERVAL_LOW_LATENCY,
59362
- SAMPLING_INTERVAL_NO_MEDIASOURCE = _config$getCurrent.SAMPLING_INTERVAL_NO_MEDIASOURCE;
59451
+ if (this._observationRef !== undefined) {
59452
+ return this._observationRef;
59453
+ }
59363
59454
 
59364
- var getCurrentObservation = function getCurrentObservation(event) {
59365
- var _a;
59455
+ var lastObservation;
59366
59456
 
59367
- var tmpEvt = event;
59457
+ var _config$getCurrent = config/* default.getCurrent */.Z.getCurrent(),
59458
+ SAMPLING_INTERVAL_MEDIASOURCE = _config$getCurrent.SAMPLING_INTERVAL_MEDIASOURCE,
59459
+ SAMPLING_INTERVAL_LOW_LATENCY = _config$getCurrent.SAMPLING_INTERVAL_LOW_LATENCY,
59460
+ SAMPLING_INTERVAL_NO_MEDIASOURCE = _config$getCurrent.SAMPLING_INTERVAL_NO_MEDIASOURCE;
59368
59461
 
59369
- if (tmpEvt === "seeking" && _this2._internalSeekingEventsIncomingCounter > 0) {
59370
- tmpEvt = "internal-seeking";
59371
- _this2._internalSeekingEventsIncomingCounter -= 1;
59372
- }
59462
+ var getCurrentObservation = function getCurrentObservation(event) {
59463
+ var tmpEvt = event;
59373
59464
 
59374
- var lastObservation = (_a = _this2._lastObservation) !== null && _a !== void 0 ? _a : _this2._generateInitialObservation();
59375
- var mediaTimings = getMediaInfos(_this2._mediaElement, tmpEvt);
59376
- var internalSeeking = mediaTimings.seeking && ( // We've just received the event for internally seeking
59377
- tmpEvt === "internal-seeking" || // or We're still waiting on the previous internal-seek
59378
- lastObservation.internalSeeking && tmpEvt !== "seeking");
59379
- var rebufferingStatus = getRebufferingStatus(lastObservation, mediaTimings, {
59380
- lowLatencyMode: _this2._lowLatencyMode,
59381
- withMediaSource: _this2._withMediaSource
59382
- });
59383
- var freezingStatus = getFreezingStatus(lastObservation, mediaTimings);
59384
- var timings = (0,object_assign/* default */.Z)({}, {
59385
- rebuffering: rebufferingStatus,
59386
- freezing: freezingStatus,
59387
- internalSeeking: internalSeeking
59388
- }, mediaTimings);
59465
+ if (tmpEvt === "seeking" && _this._internalSeekingEventsIncomingCounter > 0) {
59466
+ tmpEvt = "internal-seeking";
59467
+ _this._internalSeekingEventsIncomingCounter -= 1;
59468
+ }
59389
59469
 
59390
- if (log/* default.hasLevel */.Z.hasLevel("DEBUG")) {
59391
- log/* default.debug */.Z.debug("API: current media element state tick", "event", timings.event, "position", timings.position, "seeking", timings.seeking, "internalSeeking", timings.internalSeeking, "rebuffering", timings.rebuffering !== null, "freezing", timings.freezing !== null, "ended", timings.ended, "paused", timings.paused, "playbackRate", timings.playbackRate, "readyState", timings.readyState);
59392
- }
59470
+ var _lastObservation = lastObservation !== null && lastObservation !== void 0 ? lastObservation : _this._generateInitialObservation();
59471
+
59472
+ var mediaTimings = getMediaInfos(_this._mediaElement, tmpEvt);
59473
+ var internalSeeking = mediaTimings.seeking && ( // We've just received the event for internally seeking
59474
+ tmpEvt === "internal-seeking" || // or We're still waiting on the previous internal-seek
59475
+ _lastObservation.internalSeeking && tmpEvt !== "seeking");
59476
+ var rebufferingStatus = getRebufferingStatus(_lastObservation, mediaTimings, {
59477
+ lowLatencyMode: _this._lowLatencyMode,
59478
+ withMediaSource: _this._withMediaSource
59479
+ });
59480
+ var freezingStatus = getFreezingStatus(_lastObservation, mediaTimings);
59481
+ var timings = (0,object_assign/* default */.Z)({}, {
59482
+ rebuffering: rebufferingStatus,
59483
+ freezing: freezingStatus,
59484
+ internalSeeking: internalSeeking
59485
+ }, mediaTimings);
59486
+
59487
+ if (log/* default.hasLevel */.Z.hasLevel("DEBUG")) {
59488
+ log/* default.debug */.Z.debug("API: current media element state tick", "event", timings.event, "position", timings.position, "seeking", timings.seeking, "internalSeeking", timings.internalSeeking, "rebuffering", timings.rebuffering !== null, "freezing", timings.freezing !== null, "ended", timings.ended, "paused", timings.paused, "playbackRate", timings.playbackRate, "readyState", timings.readyState);
59489
+ }
59490
+
59491
+ return timings;
59492
+ };
59493
+
59494
+ var returnedSharedReference = (0,reference/* default */.ZP)(getCurrentObservation("init"));
59495
+
59496
+ var generateObservationForEvent = function generateObservationForEvent(event) {
59497
+ var newObservation = getCurrentObservation(event);
59393
59498
 
59394
- return timings;
59499
+ if (log/* default.hasLevel */.Z.hasLevel("DEBUG")) {
59500
+ log/* default.debug */.Z.debug("API: current playback timeline:\n" + prettyPrintBuffered(newObservation.buffered, newObservation.position), "\n" + event);
59501
+ }
59502
+
59503
+ lastObservation = newObservation;
59504
+ returnedSharedReference.setValue(newObservation);
59505
+ };
59506
+
59507
+ var interval = this._lowLatencyMode ? SAMPLING_INTERVAL_LOW_LATENCY : this._withMediaSource ? SAMPLING_INTERVAL_MEDIASOURCE : SAMPLING_INTERVAL_NO_MEDIASOURCE;
59508
+ var intervalId = setInterval(onInterval, interval);
59509
+ var removeEventListeners = SCANNED_MEDIA_ELEMENTS_EVENTS.map(function (eventName) {
59510
+ _this._mediaElement.addEventListener(eventName, onMediaEvent);
59511
+
59512
+ function onMediaEvent() {
59513
+ restartInterval();
59514
+ generateObservationForEvent(eventName);
59515
+ }
59516
+
59517
+ return function () {
59518
+ _this._mediaElement.removeEventListener(eventName, onMediaEvent);
59395
59519
  };
59520
+ });
59396
59521
 
59397
- var eventObs = SCANNED_MEDIA_ELEMENTS_EVENTS.map(function (eventName) {
59398
- return (0,fromEvent/* fromEvent */.R)(_this2._mediaElement, eventName).pipe((0,map/* map */.U)(function () {
59399
- return eventName;
59400
- }));
59522
+ this._canceller.signal.register(function () {
59523
+ clearInterval(intervalId);
59524
+ removeEventListeners.forEach(function (cb) {
59525
+ return cb();
59401
59526
  });
59402
- var interval = _this2._lowLatencyMode ? SAMPLING_INTERVAL_LOW_LATENCY : _this2._withMediaSource ? SAMPLING_INTERVAL_MEDIASOURCE : SAMPLING_INTERVAL_NO_MEDIASOURCE;
59403
- var interval$ = (0,observable_interval/* interval */.F)(interval).pipe((0,map/* map */.U)(function () {
59404
- return "timeupdate";
59405
- }));
59406
- return merge/* merge.apply */.T.apply(void 0, [interval$].concat(eventObs)).pipe((0,map/* map */.U)(function (event) {
59407
- var newObservation = getCurrentObservation(event);
59527
+ returnedSharedReference.finish();
59528
+ });
59408
59529
 
59409
- if (log/* default.hasLevel */.Z.hasLevel("DEBUG")) {
59410
- log/* default.debug */.Z.debug("API: current playback timeline:\n" + prettyPrintBuffered(newObservation.buffered, newObservation.position), "\n" + event);
59411
- }
59530
+ return returnedSharedReference;
59412
59531
 
59413
- _this2._lastObservation = newObservation;
59414
- return newObservation;
59415
- }));
59416
- });
59532
+ function onInterval() {
59533
+ generateObservationForEvent("timeupdate");
59534
+ }
59535
+
59536
+ function restartInterval() {
59537
+ clearInterval(intervalId);
59538
+ intervalId = setInterval(onInterval, interval);
59539
+ }
59417
59540
  };
59418
59541
 
59419
59542
  _proto._generateInitialObservation = function _generateInitialObservation() {
@@ -59712,18 +59835,13 @@ function prettyPrintBuffered(buffered, currentTime) {
59712
59835
  * Create `IReadOnlyPlaybackObserver` from a source `IReadOnlyPlaybackObserver`
59713
59836
  * and a mapping function.
59714
59837
  * @param {Object} src
59715
- * @param {Function} mapObservable
59838
+ * @param {Function} transform
59716
59839
  * @returns {Object}
59717
59840
  */
59718
59841
 
59719
59842
 
59720
- function generateReadOnlyObserver(src, mapObservable) {
59721
- var newObs = (0,defer/* defer */.P)(function () {
59722
- return mapObservable(src.observe(true));
59723
- }).pipe((0,shareReplay/* shareReplay */.d)({
59724
- bufferSize: 1,
59725
- refCount: true
59726
- }));
59843
+ function generateReadOnlyObserver(src, transform, cancellationSignal) {
59844
+ var mappedRef = transform(src.getReference(), cancellationSignal);
59727
59845
  return {
59728
59846
  getCurrentTime: function getCurrentTime() {
59729
59847
  return src.getCurrentTime();
@@ -59734,28 +59852,23 @@ function generateReadOnlyObserver(src, mapObservable) {
59734
59852
  getIsPaused: function getIsPaused() {
59735
59853
  return src.getIsPaused();
59736
59854
  },
59737
- observe: function observe(includeLastObservation) {
59738
- return includeLastObservation ? newObs : newObs.pipe(skip(1));
59855
+ getReference: function getReference() {
59856
+ return mappedRef;
59739
59857
  },
59740
59858
  listen: function listen(cb, options) {
59741
- var _a, _b, _c;
59859
+ var _a;
59742
59860
 
59743
- if (((_a = options === null || options === void 0 ? void 0 : options.clearSignal) === null || _a === void 0 ? void 0 : _a.isCancelled) === true) {
59744
- return noop/* default */.Z;
59861
+ if (cancellationSignal.isCancelled || ((_a = options === null || options === void 0 ? void 0 : options.clearSignal) === null || _a === void 0 ? void 0 : _a.isCancelled) === true) {
59862
+ return;
59745
59863
  }
59746
59864
 
59747
- var obs = (options === null || options === void 0 ? void 0 : options.includeLastObservation) === true ? newObs : newObs.pipe(skip(1));
59748
- var sub = obs.subscribe(cb);
59749
- var unregister = (_c = (_b = options === null || options === void 0 ? void 0 : options.clearSignal) === null || _b === void 0 ? void 0 : _b.register(function () {
59750
- sub.unsubscribe();
59751
- })) !== null && _c !== void 0 ? _c : noop/* default */.Z;
59752
- return function () {
59753
- unregister();
59754
- sub.unsubscribe();
59755
- };
59865
+ mappedRef.onUpdate(cb, {
59866
+ clearSignal: options === null || options === void 0 ? void 0 : options.clearSignal,
59867
+ emitCurrentValue: options === null || options === void 0 ? void 0 : options.includeLastObservation
59868
+ });
59756
59869
  },
59757
- deriveReadOnlyObserver: function deriveReadOnlyObserver(newUdateObserver) {
59758
- return generateReadOnlyObserver(this, newUdateObserver);
59870
+ deriveReadOnlyObserver: function deriveReadOnlyObserver(newTransformFn) {
59871
+ return generateReadOnlyObserver(this, newTransformFn, cancellationSignal);
59759
59872
  }
59760
59873
  };
59761
59874
  }
@@ -61183,7 +61296,7 @@ var Player = /*#__PURE__*/function (_EventEmitter) {
61183
61296
  videoElement.preload = "auto";
61184
61297
  _this.version =
61185
61298
  /* PLAYER_VERSION */
61186
- "3.28.0-dev.2022061700";
61299
+ "3.28.0-dev.2022062700";
61187
61300
  _this.log = log/* default */.Z;
61188
61301
  _this.state = "STOPPED";
61189
61302
  _this.videoElement = videoElement;
@@ -61502,6 +61615,9 @@ var Player = /*#__PURE__*/function (_EventEmitter) {
61502
61615
  withMediaSource: !isDirectFile,
61503
61616
  lowLatencyMode: lowLatencyMode
61504
61617
  });
61618
+ currentContentCanceller.signal.register(function () {
61619
+ playbackObserver.stop();
61620
+ });
61505
61621
  /** Emit playback events. */
61506
61622
 
61507
61623
  var playback$;
@@ -61747,7 +61863,7 @@ var Player = /*#__PURE__*/function (_EventEmitter) {
61747
61863
  }), (0,share/* share */.B)());
61748
61864
  /** Emit when the media element emits a "seeking" event. */
61749
61865
 
61750
- var observation$ = playbackObserver.observe(true);
61866
+ var observation$ = playbackObserver.getReference().asObservable();
61751
61867
  var stateChangingEvent$ = observation$.pipe((0,filter/* filter */.h)(function (o) {
61752
61868
  return o.event === "seeking" || o.event === "ended" || o.event === "play" || o.event === "pause";
61753
61869
  }));
@@ -61813,7 +61929,14 @@ var Player = /*#__PURE__*/function (_EventEmitter) {
61813
61929
  return _this2._priv_onPlaybackError(err);
61814
61930
  },
61815
61931
  complete: function complete() {
61816
- return _this2._priv_onPlaybackFinished();
61932
+ if (!contentInfos.currentContentCanceller.isUsed) {
61933
+ log/* default.info */.Z.info("API: Previous playback finished. Stopping and cleaning-up...");
61934
+ contentInfos.currentContentCanceller.cancel();
61935
+
61936
+ _this2._priv_cleanUpCurrentContentState();
61937
+
61938
+ _this2._priv_setPlayerState(PLAYER_STATES.STOPPED);
61939
+ }
61817
61940
  }
61818
61941
  }); // initialize the content only when the lock is inactive
61819
61942
 
@@ -63286,9 +63409,12 @@ var Player = /*#__PURE__*/function (_EventEmitter) {
63286
63409
  this._priv_contentEventsMemory = {}; // DRM-related clean-up
63287
63410
 
63288
63411
  var freeUpContentLock = function freeUpContentLock() {
63289
- log/* default.debug */.Z.debug("Unlocking `contentLock`. Next content can begin.");
63412
+ if (_this4.videoElement !== null) {
63413
+ // If not disposed
63414
+ log/* default.debug */.Z.debug("Unlocking `contentLock`. Next content can begin.");
63290
63415
 
63291
- _this4._priv_contentLock.setValue(false);
63416
+ _this4._priv_contentLock.setValue(false);
63417
+ }
63292
63418
  };
63293
63419
 
63294
63420
  if (!(0,is_null_or_undefined/* default */.Z)(this.videoElement)) {
@@ -63445,23 +63571,6 @@ var Player = /*#__PURE__*/function (_EventEmitter) {
63445
63571
  this.trigger("error", formattedError);
63446
63572
  }
63447
63573
  }
63448
- /**
63449
- * Triggered when the playback Observable completes.
63450
- * Clean-up ressources and signal that the content has ended.
63451
- */
63452
- ;
63453
-
63454
- _proto._priv_onPlaybackFinished = function _priv_onPlaybackFinished() {
63455
- log/* default.info */.Z.info("API: Previous playback finished. Stopping and cleaning-up...");
63456
-
63457
- if (this._priv_contentInfos !== null) {
63458
- this._priv_contentInfos.currentContentCanceller.cancel();
63459
- }
63460
-
63461
- this._priv_cleanUpCurrentContentState();
63462
-
63463
- this._priv_setPlayerState(PLAYER_STATES.ENDED);
63464
- }
63465
63574
  /**
63466
63575
  * Triggered when we received a warning event during playback.
63467
63576
  * Trigger the right API event.
@@ -64008,7 +64117,7 @@ var Player = /*#__PURE__*/function (_EventEmitter) {
64008
64117
 
64009
64118
  Player.version =
64010
64119
  /* PLAYER_VERSION */
64011
- "3.28.0-dev.2022061700";
64120
+ "3.28.0-dev.2022062700";
64012
64121
  /* harmony default export */ var public_api = (Player);
64013
64122
  ;// CONCATENATED MODULE: ./src/core/api/index.ts
64014
64123
  /**