rx-player 3.27.0-dev.2022032800 → 3.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +3 -2
  2. package/VERSION +1 -1
  3. package/dist/_esm5.processed/compat/get_start_date.d.ts +30 -0
  4. package/dist/_esm5.processed/compat/get_start_date.js +44 -0
  5. package/dist/_esm5.processed/compat/index.d.ts +2 -1
  6. package/dist/_esm5.processed/compat/index.js +2 -1
  7. package/dist/_esm5.processed/config.d.ts +1 -2
  8. package/dist/_esm5.processed/core/api/public_api.js +25 -25
  9. package/dist/_esm5.processed/core/segment_buffers/garbage_collector.js +4 -1
  10. package/dist/_esm5.processed/core/stream/orchestrator/stream_orchestrator.js +2 -1
  11. package/dist/_esm5.processed/core/stream/period/period_stream.js +9 -3
  12. package/dist/_esm5.processed/core/stream/representation/force_garbage_collection.js +3 -2
  13. package/dist/_esm5.processed/core/stream/representation/get_buffer_status.d.ts +2 -2
  14. package/dist/_esm5.processed/core/stream/representation/get_buffer_status.js +9 -3
  15. package/dist/_esm5.processed/core/stream/representation/get_needed_segments.d.ts +11 -1
  16. package/dist/_esm5.processed/core/stream/representation/get_needed_segments.js +27 -45
  17. package/dist/_esm5.processed/core/stream/representation/representation_stream.js +6 -4
  18. package/dist/_esm5.processed/default_config.d.ts +2 -8
  19. package/dist/_esm5.processed/default_config.js +2 -8
  20. package/dist/_esm5.processed/transports/dash/add_segment_integrity_checks_to_loader.js +39 -38
  21. package/dist/_esm5.processed/utils/reference.js +0 -2
  22. package/dist/_esm5.processed/utils/task_canceller.d.ts +8 -1
  23. package/dist/_esm5.processed/utils/task_canceller.js +9 -1
  24. package/dist/rx-player.js +198 -145
  25. package/dist/rx-player.min.js +1 -1
  26. package/package.json +1 -1
  27. package/sonar-project.properties +1 -1
  28. package/src/compat/get_start_date.ts +48 -0
  29. package/src/compat/index.ts +2 -0
  30. package/src/core/api/public_api.ts +23 -27
  31. package/src/core/segment_buffers/garbage_collector.ts +4 -0
  32. package/src/core/stream/orchestrator/stream_orchestrator.ts +2 -1
  33. package/src/core/stream/period/period_stream.ts +9 -4
  34. package/src/core/stream/representation/force_garbage_collection.ts +4 -1
  35. package/src/core/stream/representation/get_buffer_status.ts +21 -13
  36. package/src/core/stream/representation/get_needed_segments.ts +40 -55
  37. package/src/core/stream/representation/representation_stream.ts +6 -4
  38. package/src/default_config.ts +20 -27
  39. package/src/transports/dash/add_segment_integrity_checks_to_loader.ts +41 -44
  40. package/src/utils/reference.ts +0 -2
  41. package/src/utils/task_canceller.ts +16 -1
package/dist/rx-player.js CHANGED
@@ -3367,18 +3367,11 @@ var DEFAULT_CONFIG = {
3367
3367
  */
3368
3368
  BUFFERED_HISTORY_MAXIMUM_ENTRIES: 200,
3369
3369
 
3370
- /**
3371
- * Minimum buffer (in seconds) we should have, regardless of memory
3372
- * constraints
3373
- */
3374
- MIN_BUFFER_LENGTH: 5,
3375
-
3376
3370
  /**
3377
3371
  * Minimum buffer in seconds ahead relative to current time
3378
- * we should be able to download
3379
- * Before trying to agressively free up memory
3372
+ * we should be able to download, even in cases of saturated memory.
3380
3373
  */
3381
- MIN_BUFFER_DISTANCE_BEFORE_CLEAN_UP: 10,
3374
+ MIN_BUFFER_AHEAD: 5,
3382
3375
 
3383
3376
  /**
3384
3377
  * Distance in seconds behind the current position
@@ -31907,60 +31900,61 @@ var check_isobmff_integrity = __webpack_require__(4460);
31907
31900
 
31908
31901
  function addSegmentIntegrityChecks(segmentLoader) {
31909
31902
  return function (url, content, initialCancelSignal, callbacks) {
31910
- return new Promise(function (res, rej) {
31911
- var canceller = new task_canceller/* default */.ZP();
31912
- var unregisterCancelLstnr = initialCancelSignal.register(function onCheckCancellation(err) {
31913
- canceller.cancel();
31914
- rej(err);
31915
- });
31916
- /**
31917
- * If the data's seems to be corrupted, cancel the loading task and reject
31918
- * with an `INTEGRITY_ERROR` error.
31919
- * @param {*} data
31920
- */
31921
-
31922
- function cancelAndRejectOnBadIntegrity(data) {
31923
- if (!(data instanceof Array) && !(data instanceof Uint8Array) || inferSegmentContainer(content.adaptation.type, content.representation) !== "mp4") {
31924
- return;
31925
- }
31926
-
31927
- try {
31928
- (0,check_isobmff_integrity/* default */.Z)(new Uint8Array(data), content.segment.isInit);
31929
- } catch (err) {
31930
- unregisterCancelLstnr();
31931
- canceller.cancel();
31932
- rej(err);
31933
- }
31934
- }
31903
+ return new Promise(function (resolve, reject) {
31904
+ var requestCanceller = new task_canceller/* default */.ZP({
31905
+ cancelOn: initialCancelSignal
31906
+ }); // Reject the `CancellationError` when `requestCanceller`'s signal emits
31907
+ // `stopRejectingOnCancel` here is a function allowing to stop this mechanism
31935
31908
 
31936
- segmentLoader(url, content, canceller.signal, Object.assign(Object.assign({}, callbacks), {
31909
+ var stopRejectingOnCancel = requestCanceller.signal.register(reject);
31910
+ segmentLoader(url, content, requestCanceller.signal, Object.assign(Object.assign({}, callbacks), {
31937
31911
  onNewChunk: function onNewChunk(data) {
31938
- cancelAndRejectOnBadIntegrity(data);
31939
-
31940
- if (!canceller.isUsed) {
31912
+ try {
31913
+ trowOnIntegrityError(data);
31941
31914
  callbacks.onNewChunk(data);
31915
+ } catch (err) {
31916
+ // Do not reject with a `CancellationError` after cancelling the request
31917
+ stopRejectingOnCancel(); // Cancel the request
31918
+
31919
+ requestCanceller.cancel(); // Reject with thrown error
31920
+
31921
+ reject(err);
31942
31922
  }
31943
31923
  }
31944
31924
  })).then(function (info) {
31945
- if (canceller.isUsed) {
31925
+ if (requestCanceller.isUsed) {
31946
31926
  return;
31947
31927
  }
31948
31928
 
31949
- unregisterCancelLstnr();
31929
+ stopRejectingOnCancel();
31950
31930
 
31951
31931
  if (info.resultType === "segment-loaded") {
31952
- cancelAndRejectOnBadIntegrity(info.resultData.responseData);
31932
+ try {
31933
+ trowOnIntegrityError(info.resultData.responseData);
31934
+ } catch (err) {
31935
+ reject(err);
31936
+ return;
31937
+ }
31953
31938
  }
31954
31939
 
31955
- res(info);
31940
+ resolve(info);
31956
31941
  }, function (error) {
31957
- // The segmentLoader's cancellations cases are all handled here
31958
- if (!task_canceller/* default.isCancellationError */.ZP.isCancellationError(error)) {
31959
- unregisterCancelLstnr();
31960
- rej(error);
31961
- }
31942
+ stopRejectingOnCancel();
31943
+ reject(error);
31962
31944
  });
31963
31945
  });
31946
+ /**
31947
+ * If the data's seems to be corrupted, throws an `INTEGRITY_ERROR` error.
31948
+ * @param {*} data
31949
+ */
31950
+
31951
+ function trowOnIntegrityError(data) {
31952
+ if (!(data instanceof ArrayBuffer) && !(data instanceof Uint8Array) || inferSegmentContainer(content.adaptation.type, content.representation) !== "mp4") {
31953
+ return;
31954
+ }
31955
+
31956
+ (0,check_isobmff_integrity/* default */.Z)(new Uint8Array(data), content.segment.isInit);
31957
+ }
31964
31958
  };
31965
31959
  }
31966
31960
  // EXTERNAL MODULE: ./src/utils/byte_parsing.ts
@@ -40477,8 +40471,7 @@ function isTimeInTimeRanges(ranges, time) {
40477
40471
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
40478
40472
  /* harmony export */ "$": function() { return /* binding */ createSharedReference; }
40479
40473
  /* harmony export */ });
40480
- /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(1480);
40481
- /* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3887);
40474
+ /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1480);
40482
40475
  function _createForOfIteratorHelperLoose(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (it) return (it = it.call(o)).next.bind(it); if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; return function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
40483
40476
 
40484
40477
  function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
@@ -40501,7 +40494,6 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
40501
40494
  * limitations under the License.
40502
40495
  */
40503
40496
 
40504
-
40505
40497
  /**
40506
40498
  * Create an `ISharedReference` object encapsulating the mutable `initialValue`
40507
40499
  * value of type T.
@@ -40548,7 +40540,6 @@ function createSharedReference(initialValue) {
40548
40540
  setValue: function setValue(newVal) {
40549
40541
  if (isFinished) {
40550
40542
  if (false) {} else {
40551
- _log__WEBPACK_IMPORTED_MODULE_0__/* ["default"].error */ .Z.error("Finished shared references cannot be updated");
40552
40543
  return;
40553
40544
  }
40554
40545
  }
@@ -40587,7 +40578,7 @@ function createSharedReference(initialValue) {
40587
40578
  * @returns {Observable}
40588
40579
  */
40589
40580
  asObservable: function asObservable(skipCurrentValue) {
40590
- return new rxjs__WEBPACK_IMPORTED_MODULE_1__/* .Observable */ .y(function (obs) {
40581
+ return new rxjs__WEBPACK_IMPORTED_MODULE_0__/* .Observable */ .y(function (obs) {
40591
40582
  if (skipCurrentValue !== true) {
40592
40583
  obs.next(value);
40593
40584
  }
@@ -41751,8 +41742,11 @@ var TaskCanceller = /*#__PURE__*/function () {
41751
41742
  * Creates a new `TaskCanceller`, with its own `CancellationSignal` created
41752
41743
  * as its `signal` provide.
41753
41744
  * You can then pass this property to async task you wish to be cancellable.
41745
+ * @param {Object|undefined} options
41754
41746
  */
41755
- function TaskCanceller() {
41747
+ function TaskCanceller(options) {
41748
+ var _this = this;
41749
+
41756
41750
  var _createCancellationFu = createCancellationFunctions(),
41757
41751
  trigger = _createCancellationFu[0],
41758
41752
  register = _createCancellationFu[1];
@@ -41760,6 +41754,13 @@ var TaskCanceller = /*#__PURE__*/function () {
41760
41754
  this.isUsed = false;
41761
41755
  this._trigger = trigger;
41762
41756
  this.signal = new CancellationSignal(register);
41757
+
41758
+ if ((options === null || options === void 0 ? void 0 : options.cancelOn) !== undefined) {
41759
+ var unregisterParent = options.cancelOn.register(function () {
41760
+ _this.cancel();
41761
+ });
41762
+ this.signal.register(unregisterParent);
41763
+ }
41763
41764
  }
41764
41765
  /**
41765
41766
  * "Trigger" the `TaskCanceller`, notify through its associated
@@ -41817,17 +41818,17 @@ var CancellationSignal = /*#__PURE__*/function () {
41817
41818
  * cancelled.
41818
41819
  */
41819
41820
  function CancellationSignal(registerToSource) {
41820
- var _this = this;
41821
+ var _this2 = this;
41821
41822
 
41822
41823
  this.isCancelled = false;
41823
41824
  this.cancellationError = null;
41824
41825
  this._listeners = [];
41825
41826
  registerToSource(function (cancellationError) {
41826
- _this.cancellationError = cancellationError;
41827
- _this.isCancelled = true;
41827
+ _this2.cancellationError = cancellationError;
41828
+ _this2.isCancelled = true;
41828
41829
 
41829
- while (_this._listeners.length > 0) {
41830
- var listener = _this._listeners.splice(_this._listeners.length - 1, 1)[0];
41830
+ while (_this2._listeners.length > 0) {
41831
+ var listener = _this2._listeners.splice(_this2._listeners.length - 1, 1)[0];
41831
41832
 
41832
41833
  listener(cancellationError);
41833
41834
  }
@@ -41859,7 +41860,7 @@ var CancellationSignal = /*#__PURE__*/function () {
41859
41860
  var _proto2 = CancellationSignal.prototype;
41860
41861
 
41861
41862
  _proto2.register = function register(fn) {
41862
- var _this2 = this;
41863
+ var _this3 = this;
41863
41864
 
41864
41865
  if (this.isCancelled) {
41865
41866
  (0,_assert__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(this.cancellationError !== null);
@@ -41869,7 +41870,7 @@ var CancellationSignal = /*#__PURE__*/function () {
41869
41870
  this._listeners.push(fn);
41870
41871
 
41871
41872
  return function () {
41872
- return _this2.deregister(fn);
41873
+ return _this3.deregister(fn);
41873
41874
  };
41874
41875
  }
41875
41876
  /**
@@ -41912,14 +41913,14 @@ var CancellationError = /*#__PURE__*/function (_Error) {
41912
41913
  * @param {string} message
41913
41914
  */
41914
41915
  function CancellationError() {
41915
- var _this3;
41916
+ var _this4;
41916
41917
 
41917
- _this3 = _Error.call(this) || this; // @see https://stackoverflow.com/questions/41102060/typescript-extending-error-class
41918
+ _this4 = _Error.call(this) || this; // @see https://stackoverflow.com/questions/41102060/typescript-extending-error-class
41918
41919
 
41919
- Object.setPrototypeOf((0,_babel_runtime_helpers_assertThisInitialized__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)(_this3), CancellationError.prototype);
41920
- _this3.name = "CancellationError";
41921
- _this3.message = "This task was cancelled.";
41922
- return _this3;
41920
+ Object.setPrototypeOf((0,_babel_runtime_helpers_assertThisInitialized__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)(_this4), CancellationError.prototype);
41921
+ _this4.name = "CancellationError";
41922
+ _this4.message = "This task was cancelled.";
41923
+ return _this4;
41923
41924
  }
41924
41925
 
41925
41926
  return CancellationError;
@@ -46564,6 +46565,54 @@ function skipWhile(predicate) {
46564
46565
  var take = __webpack_require__(4727);
46565
46566
  // EXTERNAL MODULE: ./src/compat/event_listeners.ts + 6 modules
46566
46567
  var event_listeners = __webpack_require__(4804);
46568
+ ;// CONCATENATED MODULE: ./src/compat/get_start_date.ts
46569
+ /**
46570
+ * Copyright 2015 CANAL+ Group
46571
+ *
46572
+ * Licensed under the Apache License, Version 2.0 (the "License");
46573
+ * you may not use this file except in compliance with the License.
46574
+ * You may obtain a copy of the License at
46575
+ *
46576
+ * http://www.apache.org/licenses/LICENSE-2.0
46577
+ *
46578
+ * Unless required by applicable law or agreed to in writing, software
46579
+ * distributed under the License is distributed on an "AS IS" BASIS,
46580
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
46581
+ * See the License for the specific language governing permissions and
46582
+ * limitations under the License.
46583
+ */
46584
+
46585
+ /**
46586
+ * Calculating a live-offseted media position necessitate to obtain first an
46587
+ * offset, and then adding that offset to the wanted position.
46588
+ *
46589
+ * That offset is in most case present inside the Manifest file, yet in cases
46590
+ * without it or without a Manifest, such as the "directfile" mode, the RxPlayer
46591
+ * won't know that offset.
46592
+ *
46593
+ * Thankfully Safari declares a `getStartDate` method allowing to obtain that
46594
+ * offset when available. This logic is mainly useful when playing HLS contents
46595
+ * in directfile mode on Safari.
46596
+ * @param {HTMLMediaElement} mediaElement
46597
+ * @returns {number|undefined}
46598
+ */
46599
+ function getStartDate(mediaElement) {
46600
+ var _mediaElement = mediaElement;
46601
+
46602
+ if (typeof _mediaElement.getStartDate === "function") {
46603
+ var startDate = _mediaElement.getStartDate();
46604
+
46605
+ if (typeof startDate === "object" && startDate !== null) {
46606
+ var startDateNum = +startDate;
46607
+
46608
+ if (!isNaN(startDateNum)) {
46609
+ return startDateNum / 1000;
46610
+ }
46611
+ } else if (typeof startDate === "number" && !isNaN(startDate)) {
46612
+ return startDate;
46613
+ }
46614
+ }
46615
+ }
46567
46616
  ;// CONCATENATED MODULE: ./src/compat/fullscreen.ts
46568
46617
  /**
46569
46618
  * Copyright 2015 CANAL+ Group
@@ -52605,6 +52654,11 @@ function clearBuffer(segmentBuffer, position, maxBufferBehind, maxBufferAhead) {
52605
52654
  collectBufferAhead();
52606
52655
  var clean$ = (0,from/* from */.D)(cleanedupRanges.map(function (range) {
52607
52656
  log/* default.debug */.Z.debug("GC: cleaning range from SegmentBuffer", range);
52657
+
52658
+ if (range.start >= range.end) {
52659
+ return (0,of.of)(null);
52660
+ }
52661
+
52608
52662
  return segmentBuffer.removeBuffer(range.start, range.end);
52609
52663
  })).pipe((0,concatAll/* concatAll */.u)(), // NOTE As of now (RxJS 7.4.0), RxJS defines `ignoreElements` default
52610
52664
  // first type parameter as `any` instead of the perfectly fine `unknown`,
@@ -53339,9 +53393,7 @@ function getNeededSegments(_ref) {
53339
53393
  segmentsBeingPushed = _ref.segmentsBeingPushed,
53340
53394
  maxBufferSize = _ref.maxBufferSize;
53341
53395
  var representation = content.representation;
53342
- var availableBufferSize = getAvailableBufferSize(bufferedSegments, segmentsBeingPushed, maxBufferSize); // Current buffer length in seconds
53343
-
53344
- var bufferLength = getBufferLength(bufferedSegments, segmentsBeingPushed);
53396
+ var availableBufferSize = getAvailableBufferSize(bufferedSegments, segmentsBeingPushed, maxBufferSize);
53345
53397
  var availableSegmentsForRange = representation.index.getSegments(neededRange.start, neededRange.end - neededRange.start); // Remove from `bufferedSegments` any segments we would prefer to replace:
53346
53398
  // - segments in the wrong track / bad quality
53347
53399
  // - garbage-collected segments
@@ -53378,10 +53430,9 @@ function getNeededSegments(_ref) {
53378
53430
 
53379
53431
  var _config$getCurrent = config/* default.getCurrent */.Z.getCurrent(),
53380
53432
  MINIMUM_SEGMENT_SIZE = _config$getCurrent.MINIMUM_SEGMENT_SIZE,
53381
- MIN_BUFFER_LENGTH = _config$getCurrent.MIN_BUFFER_LENGTH,
53382
- MIN_BUFFER_DISTANCE_BEFORE_CLEAN_UP = _config$getCurrent.MIN_BUFFER_DISTANCE_BEFORE_CLEAN_UP;
53433
+ MIN_BUFFER_AHEAD = _config$getCurrent.MIN_BUFFER_AHEAD;
53383
53434
 
53384
- var isMemorySaturated = false;
53435
+ var shouldStopLoadingSegments = false;
53385
53436
  /**
53386
53437
  * Epsilon compensating for rounding errors when comparing the start and end
53387
53438
  * time of multiple segments.
@@ -53389,7 +53440,8 @@ function getNeededSegments(_ref) {
53389
53440
 
53390
53441
  var ROUNDING_ERROR = Math.min(1 / 60, MINIMUM_SEGMENT_SIZE);
53391
53442
  var isBufferFull = false;
53392
- var neededSegments = availableSegmentsForRange.filter(function (segment) {
53443
+ var segmentsOnHold = [];
53444
+ var segmentsToLoad = availableSegmentsForRange.filter(function (segment) {
53393
53445
  var contentObject = (0,object_assign/* default */.Z)({
53394
53446
  segment: segment
53395
53447
  }, content); // First, check that the segment is not already being pushed
@@ -53412,17 +53464,8 @@ function getNeededSegments(_ref) {
53412
53464
  return true; // never skip initialization segments
53413
53465
  }
53414
53466
 
53415
- if (isMemorySaturated) {
53416
- // If we are so saturated in memory
53417
- // That we cannot download atleast till
53418
- // NeededRange.Start ( current position ) + a CONST
53419
- // Then the buffer is full
53420
- if (time < neededRange.start + MIN_BUFFER_DISTANCE_BEFORE_CLEAN_UP) {
53421
- isBufferFull = true;
53422
- }
53423
- }
53424
-
53425
- if (isMemorySaturated && bufferLength > MIN_BUFFER_LENGTH) {
53467
+ if (shouldStopLoadingSegments) {
53468
+ segmentsOnHold.push(segment);
53426
53469
  return false;
53427
53470
  }
53428
53471
 
@@ -53471,32 +53514,42 @@ function getNeededSegments(_ref) {
53471
53514
  return false; // already downloaded
53472
53515
  }
53473
53516
  }
53517
+ }
53518
+
53519
+ var estimatedSegmentSize = duration * content.representation.bitrate / 8000;
53520
+
53521
+ if (availableBufferSize - estimatedSegmentSize < 0) {
53522
+ isBufferFull = true;
53523
+
53524
+ if (time > neededRange.start + MIN_BUFFER_AHEAD) {
53525
+ shouldStopLoadingSegments = true;
53526
+ segmentsOnHold.push(segment);
53527
+ return false;
53528
+ }
53474
53529
  } // check if there is an hole in place of the segment currently
53475
53530
 
53476
53531
 
53477
53532
  for (var _i = 0; _i < segmentsToKeep.length; _i++) {
53478
- var _completeSeg = segmentsToKeep[_i];
53533
+ var _completeSeg = segmentsToKeep[_i]; // For the first already-loaded segment, take the first one ending after
53534
+ // this one' s start
53479
53535
 
53480
- if (_completeSeg.end > time) {
53481
- // `true` if `completeSeg` starts too far after `time`
53482
- return _completeSeg.start > time + ROUNDING_ERROR || // `true` if `completeSeg` ends too soon before `end`
53483
- getLastContiguousSegment(segmentsToKeep, _i).end < end - ROUNDING_ERROR;
53484
- }
53485
- }
53536
+ if (_completeSeg.end + ROUNDING_ERROR > time) {
53537
+ var shouldLoad = _completeSeg.start > time + ROUNDING_ERROR || getLastContiguousSegment(segmentsToKeep, _i).end < end - ROUNDING_ERROR;
53486
53538
 
53487
- var estimatedSegmentSize = duration * content.representation.bitrate / 8000;
53539
+ if (shouldLoad) {
53540
+ availableBufferSize -= estimatedSegmentSize;
53541
+ }
53488
53542
 
53489
- if (availableBufferSize - estimatedSegmentSize < 0 && bufferLength > MIN_BUFFER_LENGTH) {
53490
- isMemorySaturated = true;
53491
- return false;
53543
+ return shouldLoad;
53544
+ }
53492
53545
  }
53493
53546
 
53494
53547
  availableBufferSize -= estimatedSegmentSize;
53495
- bufferLength += duration;
53496
53548
  return true;
53497
53549
  });
53498
53550
  return {
53499
- neededSegments: neededSegments,
53551
+ segmentsToLoad: segmentsToLoad,
53552
+ segmentsOnHold: segmentsOnHold,
53500
53553
  isBufferFull: isBufferFull
53501
53554
  };
53502
53555
  }
@@ -53519,29 +53572,12 @@ function getAvailableBufferSize(bufferedSegments, segmentsBeingPushed, maxVideoB
53519
53572
  }, 0);
53520
53573
  return bufferedSegments.reduce(function (size, chunk) {
53521
53574
  if (chunk.chunkSize !== undefined) {
53522
- return size - chunk.chunkSize / 8000;
53575
+ return size - chunk.chunkSize / 1000;
53523
53576
  } else {
53524
53577
  return size;
53525
53578
  }
53526
53579
  }, availableBufferSize);
53527
53580
  }
53528
- /**
53529
- * Compute the length of the buffer in seconds
53530
- * @param bufferedSegments
53531
- * @param segmentsBeingPushed
53532
- * @returns bufferLength in seconds
53533
- */
53534
-
53535
-
53536
- function getBufferLength(bufferedSegments, segmentsBeingPushed) {
53537
- var bufferLength = bufferedSegments.reduce(function (length, segment) {
53538
- return length + (segment.end - segment.start);
53539
- }, 0);
53540
- var bufferBeingPushed = segmentsBeingPushed.reduce(function (length, segment) {
53541
- return length + segment.segment.duration;
53542
- }, 0);
53543
- return bufferLength + bufferBeingPushed;
53544
- }
53545
53581
  /**
53546
53582
  * From the given array of buffered chunks (`bufferedSegments`) returns the last
53547
53583
  * buffered chunk contiguous with the one at the `startIndex` index given.
@@ -53915,10 +53951,11 @@ function getBufferStatus(content, wantedStartPosition, playbackObserver, fastSwi
53915
53951
  segmentsBeingPushed: segmentsBeingPushed,
53916
53952
  maxBufferSize: maxBufferSize
53917
53953
  }),
53918
- neededSegments = _getNeededSegments.neededSegments,
53954
+ segmentsToLoad = _getNeededSegments.segmentsToLoad,
53955
+ segmentsOnHold = _getNeededSegments.segmentsOnHold,
53919
53956
  isBufferFull = _getNeededSegments.isBufferFull;
53920
53957
 
53921
- var prioritizedNeededSegments = neededSegments.map(function (segment) {
53958
+ var prioritizedNeededSegments = segmentsToLoad.map(function (segment) {
53922
53959
  return {
53923
53960
  priority: getSegmentPriority(segment.time, wantedStartPosition),
53924
53961
  segment: segment
@@ -53932,7 +53969,7 @@ function getBufferStatus(content, wantedStartPosition, playbackObserver, fastSwi
53932
53969
  var hasFinishedLoading;
53933
53970
  var lastPosition = representation.index.getLastPosition();
53934
53971
 
53935
- if (!representation.index.isInitialized() || period.end === undefined || prioritizedNeededSegments.length > 0) {
53972
+ if (!representation.index.isInitialized() || period.end === undefined || prioritizedNeededSegments.length > 0 || segmentsOnHold.length > 0) {
53936
53973
  hasFinishedLoading = false;
53937
53974
  } else {
53938
53975
  if (lastPosition === undefined) {
@@ -53973,6 +54010,10 @@ function getBufferStatus(content, wantedStartPosition, playbackObserver, fastSwi
53973
54010
  }));
53974
54011
  }
53975
54012
 
54013
+ if (segmentsOnHold.length > 0) {
54014
+ nextSegmentStart = nextSegmentStart !== null ? Math.min(nextSegmentStart, segmentsOnHold[0].time) : segmentsOnHold[0].time;
54015
+ }
54016
+
53976
54017
  if (prioritizedNeededSegments.length > 0) {
53977
54018
  nextSegmentStart = nextSegmentStart !== null ? Math.min(nextSegmentStart, prioritizedNeededSegments[0].segment.time) : prioritizedNeededSegments[0].segment.time;
53978
54019
  }
@@ -54070,7 +54111,7 @@ function forceGarbageCollection(currentPosition, bufferingQueue) {
54070
54111
  return (0,from/* from */.D)(cleanedupRanges.map(function (_ref) {
54071
54112
  var start = _ref.start,
54072
54113
  end = _ref.end;
54073
- return bufferingQueue.removeBuffer(start, end);
54114
+ return start >= end ? (0,of.of)(null) : bufferingQueue.removeBuffer(start, end);
54074
54115
  })).pipe((0,concatAll/* concatAll */.u)());
54075
54116
  });
54076
54117
  }
@@ -54528,8 +54569,11 @@ function RepresentationStream(_ref) {
54528
54569
 
54529
54570
  if (status.isBufferFull) {
54530
54571
  var gcedPosition = Math.max(0, wantedStartPosition - UPTO_CURRENT_POSITION_CLEANUP);
54531
- bufferRemoval = segmentBuffer.removeBuffer(0, gcedPosition) // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
54532
- .pipe((0,ignoreElements/* ignoreElements */.l)());
54572
+
54573
+ if (gcedPosition > 0) {
54574
+ bufferRemoval = segmentBuffer.removeBuffer(0, gcedPosition) // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
54575
+ .pipe((0,ignoreElements/* ignoreElements */.l)());
54576
+ }
54533
54577
  }
54534
54578
 
54535
54579
  return status.shouldRefreshManifest ? (0,concat/* concat */.z)((0,of.of)(stream_events_generators/* default.needsManifestRefresh */.Z.needsManifestRefresh()), bufferStatusEvt, bufferRemoval) : (0,concat/* concat */.z)(bufferStatusEvt, bufferRemoval);
@@ -55513,7 +55557,13 @@ function PeriodStream(_ref) {
55513
55557
  return reloadAfterSwitch(period, bufferType, playbackObserver, 0);
55514
55558
  }
55515
55559
 
55516
- cleanBuffer$ = segmentBufferStatus.value.removeBuffer(period.start, period.end == null ? Infinity : period.end);
55560
+ if (period.end === undefined) {
55561
+ cleanBuffer$ = segmentBufferStatus.value.removeBuffer(period.start, Infinity);
55562
+ } else if (period.end <= period.start) {
55563
+ cleanBuffer$ = (0,of.of)(null);
55564
+ } else {
55565
+ cleanBuffer$ = segmentBufferStatus.value.removeBuffer(period.start, period.end);
55566
+ }
55517
55567
  } else {
55518
55568
  if (segmentBufferStatus.type === "uninitialized") {
55519
55569
  segmentBuffersStore.disableSegmentBuffer(bufferType);
@@ -56236,7 +56286,7 @@ function StreamOrchestrator(content, playbackObserver, abrManager, segmentBuffer
56236
56286
  return concat/* concat.apply */.z.apply(void 0, rangesToClean.map(function (_ref4) {
56237
56287
  var start = _ref4.start,
56238
56288
  end = _ref4.end;
56239
- return segmentBuffer.removeBuffer(start, end).pipe((0,ignoreElements/* ignoreElements */.l)());
56289
+ return start >= end ? empty/* EMPTY */.E : segmentBuffer.removeBuffer(start, end).pipe((0,ignoreElements/* ignoreElements */.l)());
56240
56290
  }).concat([playbackObserver.observe(true).pipe((0,take/* take */.q)(1), (0,mergeMap/* mergeMap */.z)(function (observation) {
56241
56291
  return (0,concat/* concat */.z)((0,of.of)(stream_events_generators/* default.needsDecipherabilityFlush */.Z.needsDecipherabilityFlush(observation.position, !observation.isPaused, observation.duration)), (0,defer/* defer */.P)(function () {
56242
56292
  var lastPosition = observation.position + observation.wantedTimeOffset;
@@ -60440,7 +60490,7 @@ var Player = /*#__PURE__*/function (_EventEmitter) {
60440
60490
  videoElement.preload = "auto";
60441
60491
  _this.version =
60442
60492
  /* PLAYER_VERSION */
60443
- "3.27.0-dev.2022032800";
60493
+ "3.27.0";
60444
60494
  _this.log = log/* default */.Z;
60445
60495
  _this.state = "STOPPED";
60446
60496
  _this.videoElement = videoElement;
@@ -61332,25 +61382,8 @@ var Player = /*#__PURE__*/function (_EventEmitter) {
61332
61382
  manifest = _this$_priv_contentIn4.manifest;
61333
61383
 
61334
61384
  if (isDirectFile) {
61335
- // Calculating the "wall-clock time" necessitate to obtain first an offset,
61336
- // and then adding that offset to the HTMLMediaElement's current position.
61337
- // That offset is in most case present inside the Manifest file, yet in
61338
- // directfile mode, the RxPlayer won't parse that file, the browser does it.
61339
- //
61340
- // Thankfully Safari declares a `getStartDate` method allowing to obtain
61341
- // that offset when available. This logic is thus mainly useful when
61342
- // playing HLS contents in directfile mode on Safari.
61343
- var mediaElement = this.videoElement;
61344
-
61345
- if (typeof mediaElement.getStartDate === "function") {
61346
- var startDate = mediaElement.getStartDate();
61347
-
61348
- if (typeof startDate === "number" && !isNaN(startDate)) {
61349
- return startDate + mediaElement.currentTime;
61350
- }
61351
- }
61352
-
61353
- return mediaElement.currentTime;
61385
+ var startDate = getStartDate(this.videoElement);
61386
+ return (startDate !== null && startDate !== void 0 ? startDate : 0) + this.videoElement.currentTime;
61354
61387
  }
61355
61388
 
61356
61389
  if (manifest !== null) {
@@ -61658,6 +61691,8 @@ var Player = /*#__PURE__*/function (_EventEmitter) {
61658
61691
  ;
61659
61692
 
61660
61693
  _proto.seekTo = function seekTo(time) {
61694
+ var _a;
61695
+
61661
61696
  if (this.videoElement === null) {
61662
61697
  throw new Error("Disposed player");
61663
61698
  }
@@ -61687,7 +61722,19 @@ var Player = /*#__PURE__*/function (_EventEmitter) {
61687
61722
  } else if (!(0,is_null_or_undefined/* default */.Z)(timeObj.position)) {
61688
61723
  positionWanted = timeObj.position;
61689
61724
  } else if (!(0,is_null_or_undefined/* default */.Z)(timeObj.wallClockTime)) {
61690
- positionWanted = isDirectFile || manifest === null ? timeObj.wallClockTime : timeObj.wallClockTime - (manifest.availabilityStartTime !== undefined ? manifest.availabilityStartTime : 0);
61725
+ if (manifest !== null) {
61726
+ positionWanted = timeObj.wallClockTime - ((_a = manifest.availabilityStartTime) !== null && _a !== void 0 ? _a : 0);
61727
+ } else if (isDirectFile && this.videoElement !== null) {
61728
+ var startDate = getStartDate(this.videoElement);
61729
+
61730
+ if (startDate !== undefined) {
61731
+ positionWanted = timeObj.wallClockTime - startDate;
61732
+ }
61733
+ }
61734
+
61735
+ if (positionWanted === undefined) {
61736
+ positionWanted = timeObj.wallClockTime;
61737
+ }
61691
61738
  } else {
61692
61739
  throw new Error("invalid time object. You must set one of the " + "following properties: \"relative\", \"position\" or " + "\"wallClockTime\"");
61693
61740
  }
@@ -63179,6 +63226,12 @@ var Player = /*#__PURE__*/function (_EventEmitter) {
63179
63226
  var ast = (_a = manifest.availabilityStartTime) !== null && _a !== void 0 ? _a : 0;
63180
63227
  positionData.wallClockTime = observation.position + ast;
63181
63228
  positionData.liveGap = maximumPosition - observation.position;
63229
+ } else if (isDirectFile && this.videoElement !== null) {
63230
+ var startDate = getStartDate(this.videoElement);
63231
+
63232
+ if (startDate !== undefined) {
63233
+ positionData.wallClockTime = startDate + observation.position;
63234
+ }
63182
63235
  }
63183
63236
 
63184
63237
  this.trigger("positionUpdate", positionData);
@@ -63269,7 +63322,7 @@ var Player = /*#__PURE__*/function (_EventEmitter) {
63269
63322
 
63270
63323
  Player.version =
63271
63324
  /* PLAYER_VERSION */
63272
- "3.27.0-dev.2022032800";
63325
+ "3.27.0";
63273
63326
  /* harmony default export */ var public_api = (Player);
63274
63327
  ;// CONCATENATED MODULE: ./src/core/api/index.ts
63275
63328
  /**