rx-player 3.30.1-dev.2023032300 → 3.30.1-dev.2023032800

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 (40) hide show
  1. package/CHANGELOG.md +8 -2
  2. package/VERSION +1 -1
  3. package/dist/_esm5.processed/compat/eme/load_session.js +1 -1
  4. package/dist/_esm5.processed/config.d.ts +2 -0
  5. package/dist/_esm5.processed/core/adaptive/adaptive_representation_selector.js +4 -2
  6. package/dist/_esm5.processed/core/adaptive/buffer_based_chooser.js +4 -4
  7. package/dist/_esm5.processed/core/adaptive/network_analyzer.js +8 -5
  8. package/dist/_esm5.processed/core/api/playback_observer.js +1 -0
  9. package/dist/_esm5.processed/core/api/public_api.js +3 -2
  10. package/dist/_esm5.processed/core/decrypt/utils/clean_old_loaded_sessions.js +2 -0
  11. package/dist/_esm5.processed/core/decrypt/utils/loaded_sessions_store.js +5 -1
  12. package/dist/_esm5.processed/core/init/media_source_content_initializer.js +6 -5
  13. package/dist/_esm5.processed/core/init/utils/content_time_boundaries_observer.d.ts +28 -1
  14. package/dist/_esm5.processed/core/init/utils/content_time_boundaries_observer.js +22 -9
  15. package/dist/_esm5.processed/core/init/utils/media_source_duration_updater.d.ts +58 -0
  16. package/dist/_esm5.processed/core/init/utils/{media_duration_updater.js → media_source_duration_updater.js} +71 -85
  17. package/dist/_esm5.processed/core/stream/orchestrator/stream_orchestrator.js +3 -3
  18. package/dist/_esm5.processed/default_config.d.ts +25 -0
  19. package/dist/_esm5.processed/default_config.js +27 -2
  20. package/dist/_esm5.processed/utils/is_null_or_undefined.d.ts +1 -1
  21. package/dist/_esm5.processed/utils/is_null_or_undefined.js +1 -1
  22. package/dist/rx-player.js +168 -120
  23. package/dist/rx-player.min.js +1 -1
  24. package/package.json +1 -1
  25. package/sonar-project.properties +1 -1
  26. package/src/compat/eme/load_session.ts +1 -1
  27. package/src/core/adaptive/adaptive_representation_selector.ts +6 -2
  28. package/src/core/adaptive/buffer_based_chooser.ts +4 -4
  29. package/src/core/adaptive/network_analyzer.ts +9 -4
  30. package/src/core/api/playback_observer.ts +1 -0
  31. package/src/core/api/public_api.ts +3 -2
  32. package/src/core/decrypt/utils/clean_old_loaded_sessions.ts +2 -1
  33. package/src/core/decrypt/utils/loaded_sessions_store.ts +8 -1
  34. package/src/core/init/media_source_content_initializer.ts +7 -5
  35. package/src/core/init/utils/content_time_boundaries_observer.ts +46 -10
  36. package/src/core/init/utils/{media_duration_updater.ts → media_source_duration_updater.ts} +87 -111
  37. package/src/core/stream/orchestrator/stream_orchestrator.ts +4 -4
  38. package/src/default_config.ts +29 -2
  39. package/src/utils/is_null_or_undefined.ts +1 -1
  40. package/dist/_esm5.processed/core/init/utils/media_duration_updater.d.ts +0 -56
package/CHANGELOG.md CHANGED
@@ -1,10 +1,16 @@
1
1
  # Changelog
2
2
 
3
- ## v3.30.1 (2023-03-23)
3
+ ## v3.30.1-dev.2023032800 (2023-03-28)
4
4
 
5
5
  ### Bug fixes
6
6
 
7
- - DASH: Fix issue which could lead to infinite rebuffering when switching between multiple Periods
7
+ - DASH: Fix issue which could lead to infinite rebuffering when switching between multiple Periods [#1232]
8
+ - Return actual ending duration through the `getVideoDuration` method when playing dynamic contents whose future end is already known [#1235]
9
+
10
+ ### Other improvements
11
+
12
+ - adaptive: Perform various adaptive tweaks to avoid switching too much between qualities in some conditions
13
+
8
14
 
9
15
  ## v3.30.0 (2023-03-07)
10
16
 
package/VERSION CHANGED
@@ -1 +1 @@
1
- 3.30.1-dev.2023032300
1
+ 3.30.1-dev.2023032800
@@ -70,7 +70,7 @@ export default function loadSession(session, sessionId) {
70
70
  return __generator(this, function (_a) {
71
71
  switch (_a.label) {
72
72
  case 0:
73
- log.info("Compat/DRM: Load persisted session", sessionId);
73
+ log.info("DRM: Load persisted session", sessionId);
74
74
  return [4 /*yield*/, session.load(sessionId)];
75
75
  case 1:
76
76
  isLoaded = _a.sent();
@@ -77,6 +77,8 @@ declare class ConfigHandler {
77
77
  SAMPLING_INTERVAL_MEDIASOURCE: number;
78
78
  SAMPLING_INTERVAL_LOW_LATENCY: number;
79
79
  SAMPLING_INTERVAL_NO_MEDIASOURCE: number;
80
+ ABR_ENTER_BUFFER_BASED_ALGO: number;
81
+ ABR_EXIT_BUFFER_BASED_ALGO: number;
80
82
  ABR_MINIMUM_TOTAL_BYTES: number;
81
83
  ABR_MINIMUM_CHUNK_SIZE: number;
82
84
  ABR_STARVATION_FACTOR: {
@@ -13,6 +13,7 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
+ import config from "../../config";
16
17
  import log from "../../log";
17
18
  import noop from "../../utils/noop";
18
19
  import { getLeftSizeOfRange } from "../../utils/ranges";
@@ -242,12 +243,13 @@ function getEstimateReference(_a, stopAllEstimates) {
242
243
  stableRepresentation.bitrate / (lastPlaybackObservation.speed > 0 ?
243
244
  lastPlaybackObservation.speed :
244
245
  1);
245
- if (allowBufferBasedEstimates && bufferGap <= 5) {
246
+ var _b = config.getCurrent(), ABR_ENTER_BUFFER_BASED_ALGO = _b.ABR_ENTER_BUFFER_BASED_ALGO, ABR_EXIT_BUFFER_BASED_ALGO = _b.ABR_EXIT_BUFFER_BASED_ALGO;
247
+ if (allowBufferBasedEstimates && bufferGap <= ABR_EXIT_BUFFER_BASED_ALGO) {
246
248
  allowBufferBasedEstimates = false;
247
249
  }
248
250
  else if (!allowBufferBasedEstimates &&
249
251
  isFinite(bufferGap) &&
250
- bufferGap > 10) {
252
+ bufferGap >= ABR_ENTER_BUFFER_BASED_ALGO) {
251
253
  allowBufferBasedEstimates = true;
252
254
  }
253
255
  /**
@@ -56,10 +56,10 @@ var BufferBasedChooser = /** @class */ (function () {
56
56
  return bitrates[0];
57
57
  }
58
58
  var scaledScore;
59
- if (currentScore != null) {
59
+ if (currentScore !== undefined) {
60
60
  scaledScore = speed === 0 ? currentScore : (currentScore / speed);
61
61
  }
62
- if (scaledScore != null && scaledScore > 1) {
62
+ if (scaledScore !== undefined && scaledScore > 1) {
63
63
  var currentBufferLevel_1 = bufferLevels[currentBitrateIndex];
64
64
  var nextIndex = (function () {
65
65
  for (var i = currentBitrateIndex + 1; i < bufferLevels.length; i++) {
@@ -68,14 +68,14 @@ var BufferBasedChooser = /** @class */ (function () {
68
68
  }
69
69
  }
70
70
  })();
71
- if (nextIndex != null) {
71
+ if (nextIndex !== undefined) {
72
72
  var nextBufferLevel = bufferLevels[nextIndex];
73
73
  if (bufferGap >= nextBufferLevel) {
74
74
  return bitrates[nextIndex];
75
75
  }
76
76
  }
77
77
  }
78
- if (scaledScore == null || scaledScore < 1.15) {
78
+ if (scaledScore === undefined || scaledScore < 1.15) {
79
79
  var currentBufferLevel = bufferLevels[currentBitrateIndex];
80
80
  if (bufferGap < currentBufferLevel) {
81
81
  for (var i = currentBitrateIndex - 1; i >= 0; i--) {
@@ -126,6 +126,12 @@ function estimateStarvationModeBitrate(pendingRequests, playbackInfo, currentRep
126
126
  }
127
127
  var concernedRequest = concernedRequests[0];
128
128
  var now = performance.now();
129
+ var minimumRequestTime = concernedRequest.content.segment.duration * 1.5;
130
+ minimumRequestTime = Math.min(minimumRequestTime, 3000);
131
+ minimumRequestTime = Math.max(minimumRequestTime, 12000);
132
+ if (now - concernedRequest.requestTimestamp < minimumRequestTime) {
133
+ return undefined;
134
+ }
129
135
  var lastProgressEvent = concernedRequest.progress.length > 0 ?
130
136
  concernedRequest.progress[concernedRequest.progress.length - 1] :
131
137
  undefined;
@@ -138,7 +144,7 @@ function estimateStarvationModeBitrate(pendingRequests, playbackInfo, currentRep
138
144
  // Calculate estimated time spent rebuffering if we continue doing that request.
139
145
  var expectedRebufferingTime = remainingTime -
140
146
  (realBufferGap / speed);
141
- if (expectedRebufferingTime > 2000) {
147
+ if (expectedRebufferingTime > 2500) {
142
148
  return bandwidthEstimate;
143
149
  }
144
150
  }
@@ -320,12 +326,9 @@ var NetworkAnalyzer = /** @class */ (function () {
320
326
  if (currentRepresentation === null) {
321
327
  return true;
322
328
  }
323
- else if (bitrate === currentRepresentation.bitrate) {
329
+ else if (bitrate >= currentRepresentation.bitrate) {
324
330
  return false;
325
331
  }
326
- else if (bitrate > currentRepresentation.bitrate) {
327
- return !this._inStarvationMode;
328
- }
329
332
  return shouldDirectlySwitchToLowBitrate(playbackInfo, currentRequests, this._lowLatencyMode);
330
333
  };
331
334
  return NetworkAnalyzer;
@@ -114,6 +114,7 @@ var PlaybackObserver = /** @class */ (function () {
114
114
  */
115
115
  PlaybackObserver.prototype.setCurrentTime = function (time) {
116
116
  this._internalSeeksIncoming.push(time);
117
+ log.info("API: Seeking internally", time);
117
118
  this._mediaElement.currentTime = time;
118
119
  };
119
120
  /**
@@ -89,7 +89,7 @@ var Player = /** @class */ (function (_super) {
89
89
  // Workaround to support Firefox autoplay on FF 42.
90
90
  // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1194624
91
91
  videoElement.preload = "auto";
92
- _this.version = /* PLAYER_VERSION */ "3.30.1-dev.2023032300";
92
+ _this.version = /* PLAYER_VERSION */ "3.30.1-dev.2023032800";
93
93
  _this.log = log;
94
94
  _this.state = "STOPPED";
95
95
  _this.videoElement = videoElement;
@@ -1165,6 +1165,7 @@ var Player = /** @class */ (function (_super) {
1165
1165
  if (positionWanted === undefined) {
1166
1166
  throw new Error("invalid time given");
1167
1167
  }
1168
+ log.info("API: API Seek to", positionWanted);
1168
1169
  this.videoElement.currentTime = positionWanted;
1169
1170
  return positionWanted;
1170
1171
  };
@@ -2339,5 +2340,5 @@ var Player = /** @class */ (function (_super) {
2339
2340
  };
2340
2341
  return Player;
2341
2342
  }(EventEmitter));
2342
- Player.version = /* PLAYER_VERSION */ "3.30.1-dev.2023032300";
2343
+ Player.version = /* PLAYER_VERSION */ "3.30.1-dev.2023032800";
2343
2344
  export default Player;
@@ -49,6 +49,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
49
49
  if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
50
50
  }
51
51
  };
52
+ import log from "../../../log";
52
53
  /**
53
54
  * Close sessions from the loadedSessionsStore to allow at maximum `limit`
54
55
  * stored MediaKeySessions in it.
@@ -67,6 +68,7 @@ export default function cleanOldLoadedSessions(loadedSessionsStore, limit) {
67
68
  if (limit < 0 || limit >= loadedSessionsStore.getLength()) {
68
69
  return [2 /*return*/];
69
70
  }
71
+ log.info("DRM: LSS cache limit exceeded", limit, loadedSessionsStore.getLength());
70
72
  proms = [];
71
73
  entries = loadedSessionsStore.getAll().slice();
72
74
  toDelete = entries.length - limit;
@@ -92,6 +92,7 @@ var LoadedSessionsStore = /** @class */ (function () {
92
92
  LoadedSessionsStore.prototype.createSession = function (initData, sessionType) {
93
93
  var _this = this;
94
94
  var keySessionRecord = new KeySessionRecord(initData);
95
+ log.debug("DRM-LSS: calling `createSession`", sessionType);
95
96
  var mediaKeySession = this._mediaKeys.createSession(sessionType);
96
97
  var entry = { mediaKeySession: mediaKeySession, sessionType: sessionType, keySessionRecord: keySessionRecord, isGeneratingRequest: false,
97
98
  isLoadingPersistentSession: false,
@@ -99,6 +100,7 @@ var LoadedSessionsStore = /** @class */ (function () {
99
100
  if (!isNullOrUndefined(mediaKeySession.closed)) {
100
101
  mediaKeySession.closed
101
102
  .then(function () {
103
+ log.info("DRM-LSS: session was closed, removing it.", mediaKeySession.sessionId);
102
104
  var index = _this.getIndex(keySessionRecord);
103
105
  if (index >= 0 &&
104
106
  _this._storage[index].mediaKeySession === mediaKeySession) {
@@ -110,8 +112,8 @@ var LoadedSessionsStore = /** @class */ (function () {
110
112
  log.warn("DRM-LSS: MediaKeySession.closed rejected: ".concat(e));
111
113
  });
112
114
  }
113
- log.debug("DRM-LSS: Add MediaKeySession", entry.sessionType);
114
115
  this._storage.push(__assign({}, entry));
116
+ log.debug("DRM-LSS: MediaKeySession added", entry.sessionType, this._storage.length);
115
117
  return entry;
116
118
  };
117
119
  /**
@@ -132,6 +134,7 @@ var LoadedSessionsStore = /** @class */ (function () {
132
134
  if (stored.keySessionRecord.isCompatibleWith(initializationData)) {
133
135
  this._storage.splice(i, 1);
134
136
  this._storage.push(stored);
137
+ log.debug("DRM-LSS: Reusing session:", stored.mediaKeySession.sessionId, stored.sessionType);
135
138
  return __assign({}, stored);
136
139
  }
137
140
  }
@@ -365,6 +368,7 @@ var LoadedSessionsStore = /** @class */ (function () {
365
368
  for (var i = this._storage.length - 1; i >= 0; i--) {
366
369
  var stored = this._storage[i];
367
370
  if (stored.mediaKeySession === mediaKeySession) {
371
+ log.debug("DRM-LSS: Removing session without closing it", mediaKeySession.sessionId);
368
372
  this._storage.splice(i, 1);
369
373
  return true;
370
374
  }
@@ -87,7 +87,7 @@ import getInitialTime from "./utils/get_initial_time";
87
87
  import getLoadedReference from "./utils/get_loaded_reference";
88
88
  import performInitialSeekAndPlay from "./utils/initial_seek_and_play";
89
89
  import initializeContentDecryption from "./utils/initialize_content_decryption";
90
- import MediaDurationUpdater from "./utils/media_duration_updater";
90
+ import MediaSourceDurationUpdater from "./utils/media_source_duration_updater";
91
91
  import RebufferingController from "./utils/rebuffering_controller";
92
92
  import streamEventsEmitter from "./utils/stream_events_emitter";
93
93
  import listenToMediaError from "./utils/throw_on_media_error";
@@ -501,9 +501,9 @@ var MediaSourceContentInitializer = /** @class */ (function (_super) {
501
501
  MediaSourceContentInitializer.prototype._createContentTimeBoundariesObserver = function (manifest, mediaSource, streamObserver, segmentBuffersStore, cancelSignal) {
502
502
  var _this = this;
503
503
  /** Maintains the MediaSource's duration up-to-date with the Manifest */
504
- var mediaDurationUpdater = new MediaDurationUpdater(manifest, mediaSource);
504
+ var mediaSourceDurationUpdater = new MediaSourceDurationUpdater(mediaSource);
505
505
  cancelSignal.register(function () {
506
- mediaDurationUpdater.stop();
506
+ mediaSourceDurationUpdater.stopUpdating();
507
507
  });
508
508
  /** Allows to cancel a pending `end-of-stream` operation. */
509
509
  var endOfStreamCanceller = null;
@@ -518,8 +518,7 @@ var MediaSourceContentInitializer = /** @class */ (function (_super) {
518
518
  _this.trigger("activePeriodChanged", { period: period });
519
519
  });
520
520
  contentTimeBoundariesObserver.addEventListener("durationUpdate", function (newDuration) {
521
- log.debug("Init: Duration has to be updated.", newDuration);
522
- mediaDurationUpdater.updateKnownDuration(newDuration);
521
+ mediaSourceDurationUpdater.updateDuration(newDuration.duration, !newDuration.isEnd);
523
522
  });
524
523
  contentTimeBoundariesObserver.addEventListener("endOfStream", function () {
525
524
  if (endOfStreamCanceller === null) {
@@ -536,6 +535,8 @@ var MediaSourceContentInitializer = /** @class */ (function (_super) {
536
535
  endOfStreamCanceller = null;
537
536
  }
538
537
  });
538
+ var currentDuration = contentTimeBoundariesObserver.getCurrentDuration();
539
+ mediaSourceDurationUpdater.updateDuration(currentDuration.duration, !currentDuration.isEnd);
539
540
  return contentTimeBoundariesObserver;
540
541
  };
541
542
  /**
@@ -55,6 +55,11 @@ export default class ContentTimeBoundariesObserver extends EventEmitter<IContent
55
55
  * @param {Object} playbackObserver
56
56
  */
57
57
  constructor(manifest: Manifest, playbackObserver: IReadOnlyPlaybackObserver<IStreamOrchestratorPlaybackObservation>, bufferTypes: IBufferType[]);
58
+ /**
59
+ * Returns an estimate of the current duration of the content.
60
+ * @returns {Object}
61
+ */
62
+ getCurrentDuration(): IDurationItem;
58
63
  /**
59
64
  * Method to call any time an Adaptation has been selected.
60
65
  *
@@ -121,9 +126,31 @@ export default class ContentTimeBoundariesObserver extends EventEmitter<IContent
121
126
  private _addActivelyLoadedPeriod;
122
127
  private _removeActivelyLoadedPeriod;
123
128
  private _checkCurrentPeriod;
129
+ private _getManifestDuration;
124
130
  private _lazilyCreateActiveStreamInfo;
125
131
  private _checkEndOfStream;
126
132
  }
133
+ export interface IDurationItem {
134
+ /**
135
+ * The new maximum known position (note that this is the ending position
136
+ * currently known of the current content, it might be superior to the last
137
+ * position at which segments are available and it might also evolve over
138
+ * time), in seconds.
139
+ */
140
+ duration: number;
141
+ /**
142
+ * If `true`, the communicated `duration` is the actual end of the content.
143
+ * It may still be updated due to a track change or to add precision, but it
144
+ * is still a (rough) estimate of the maximum position that content should
145
+ * have.
146
+ *
147
+ * If `false`, this is the currently known maximum position associated to
148
+ * the content, but the content is still evolving (typically, new media
149
+ * segments are still being generated) and as such it can still have a
150
+ * longer duration in the future.
151
+ */
152
+ isEnd: boolean;
153
+ }
127
154
  /**
128
155
  * Events triggered by a `ContentTimeBoundariesObserver` where the keys are the
129
156
  * event names and the value is the payload of those events.
@@ -137,7 +164,7 @@ export interface IContentTimeBoundariesObserverEvent {
137
164
  * Triggered when the duration of the currently-playing content became known
138
165
  * or changed.
139
166
  */
140
- durationUpdate: number | undefined;
167
+ durationUpdate: IDurationItem;
141
168
  /**
142
169
  * Triggered when the last possible chronological segment for all types of
143
170
  * buffers has either been pushed or is being pushed to the corresponding
@@ -82,19 +82,21 @@ var ContentTimeBoundariesObserver = /** @class */ (function (_super) {
82
82
  }
83
83
  }, { includeLastObservation: true, clearSignal: cancelSignal });
84
84
  manifest.addEventListener("manifestUpdate", function () {
85
- _this.trigger("durationUpdate", getManifestDuration());
85
+ _this.trigger("durationUpdate", _this._getManifestDuration());
86
86
  if (cancelSignal.isCancelled()) {
87
87
  return;
88
88
  }
89
89
  _this._checkEndOfStream();
90
90
  }, cancelSignal);
91
- function getManifestDuration() {
92
- return manifest.isDynamic ?
93
- maximumPositionCalculator.getMaximumAvailablePosition() :
94
- maximumPositionCalculator.getEndingPosition();
95
- }
96
91
  return _this;
97
92
  }
93
+ /**
94
+ * Returns an estimate of the current duration of the content.
95
+ * @returns {Object}
96
+ */
97
+ ContentTimeBoundariesObserver.prototype.getCurrentDuration = function () {
98
+ return this._getManifestDuration();
99
+ };
98
100
  /**
99
101
  * Method to call any time an Adaptation has been selected.
100
102
  *
@@ -121,9 +123,12 @@ var ContentTimeBoundariesObserver = /** @class */ (function (_super) {
121
123
  this._maximumPositionCalculator
122
124
  .updateLastVideoAdaptation(adaptation);
123
125
  }
124
- var newDuration = this._manifest.isDynamic ?
125
- this._maximumPositionCalculator.getMaximumAvailablePosition() :
126
- this._maximumPositionCalculator.getEndingPosition();
126
+ var endingPosition = this._maximumPositionCalculator.getEndingPosition();
127
+ var newDuration = endingPosition !== undefined ?
128
+ { isEnd: true,
129
+ duration: endingPosition } :
130
+ { isEnd: false,
131
+ duration: this._maximumPositionCalculator.getMaximumAvailablePosition() };
127
132
  this.trigger("durationUpdate", newDuration);
128
133
  }
129
134
  }
@@ -258,6 +263,14 @@ var ContentTimeBoundariesObserver = /** @class */ (function (_super) {
258
263
  return state_1.value;
259
264
  }
260
265
  };
266
+ ContentTimeBoundariesObserver.prototype._getManifestDuration = function () {
267
+ var endingPosition = this._maximumPositionCalculator.getEndingPosition();
268
+ return endingPosition !== undefined ?
269
+ { isEnd: true,
270
+ duration: endingPosition } :
271
+ { isEnd: false,
272
+ duration: this._maximumPositionCalculator.getMaximumAvailablePosition() };
273
+ };
261
274
  ContentTimeBoundariesObserver.prototype._lazilyCreateActiveStreamInfo = function (bufferType) {
262
275
  var streamInfo = this._activeStreams.get(bufferType);
263
276
  if (streamInfo === undefined) {
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Copyright 2015 CANAL+ Group
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ /**
17
+ * Keep the MediaSource's `duration` attribute up-to-date with the duration of
18
+ * the content played on it.
19
+ * @class MediaSourceDurationUpdater
20
+ */
21
+ export default class MediaSourceDurationUpdater {
22
+ /**
23
+ * `MediaSource` on which we're going to update the `duration` attribute.
24
+ */
25
+ private _mediaSource;
26
+ /**
27
+ * Abort the current duration-setting logic.
28
+ * `null` if no such logic is pending.
29
+ */
30
+ private _currentMediaSourceDurationUpdateCanceller;
31
+ /**
32
+ * Create a new `MediaSourceDurationUpdater`,
33
+ * @param {MediaSource} mediaSource - The MediaSource on which the content is
34
+ * played.
35
+ */
36
+ constructor(mediaSource: MediaSource);
37
+ /**
38
+ * Indicate to the `MediaSourceDurationUpdater` the currently known duration
39
+ * of the content.
40
+ *
41
+ * The `MediaSourceDurationUpdater` will then use that value to determine
42
+ * which `duration` attribute should be set on the `MediaSource` associated
43
+ *
44
+ * @param {number} newDuration
45
+ * @param {boolean} addTimeMargin - If set to `true`, the current content is
46
+ * a dynamic content (it might evolve in the future) and the `newDuration`
47
+ * communicated might be greater still. In effect the
48
+ * `MediaSourceDurationUpdater` will actually set a much higher value to the
49
+ * `MediaSource`'s duration to prevent being annoyed by the HTML-related
50
+ * side-effects of having a too low duration (such as the impossibility to
51
+ * seek over that value).
52
+ */
53
+ updateDuration(newDuration: number, addTimeMargin: boolean): void;
54
+ /**
55
+ * Abort the last duration-setting operation and free its resources.
56
+ */
57
+ stopUpdating(): void;
58
+ }