hls.js 1.5.5-0.canary.9984 → 1.5.5-0.canary.9986

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/hls.light.js CHANGED
@@ -613,7 +613,7 @@
613
613
  // Some browsers don't allow to use bind on console object anyway
614
614
  // fallback to default if needed
615
615
  try {
616
- newLogger.log("Debug logs enabled for \"" + context + "\" in hls.js version " + "1.5.5-0.canary.9984");
616
+ newLogger.log("Debug logs enabled for \"" + context + "\" in hls.js version " + "1.5.5-0.canary.9986");
617
617
  } catch (e) {
618
618
  /* log fn threw an exception. All logger methods are no-ops. */
619
619
  return createLogger();
@@ -5976,7 +5976,12 @@
5976
5976
  var cdnAge = lastAdvanced + details.ageHeader;
5977
5977
  var currentGoal = Math.min(cdnAge - details.partTarget, details.targetduration * 1.5);
5978
5978
  if (currentGoal > 0) {
5979
- if (previousDetails && currentGoal > previousDetails.tuneInGoal) {
5979
+ if (cdnAge > details.targetduration * 3) {
5980
+ // Omit segment and part directives when the last response was more than 3 target durations ago,
5981
+ this.log("Playlist last advanced " + lastAdvanced.toFixed(2) + "s ago. Omitting segment and part directives.");
5982
+ msn = undefined;
5983
+ part = undefined;
5984
+ } else if (previousDetails != null && previousDetails.tuneInGoal && cdnAge - details.partTarget > previousDetails.tuneInGoal) {
5980
5985
  // If we attempted to get the next or latest playlist update, but currentGoal increased,
5981
5986
  // then we either can't catchup, or the "age" header cannot be trusted.
5982
5987
  this.warn("CDN Tune-in goal increased from: " + previousDetails.tuneInGoal + " to: " + currentGoal + " with playlist age: " + details.age);
@@ -10240,7 +10245,12 @@
10240
10245
  if (curLevel.fragmentError === 0) {
10241
10246
  curLevel.loadError = 0;
10242
10247
  }
10243
- this.playlistLoaded(level, data, curLevel.details);
10248
+ // Ignore matching details populated by loading a Media Playlist directly
10249
+ var previousDetails = curLevel.details;
10250
+ if (previousDetails === data.details && previousDetails.advanced) {
10251
+ previousDetails = undefined;
10252
+ }
10253
+ this.playlistLoaded(level, data, previousDetails);
10244
10254
  } else if ((_data$deliveryDirecti2 = data.deliveryDirectives) != null && _data$deliveryDirecti2.skip) {
10245
10255
  // received a delta playlist update that cannot be merged
10246
10256
  details.deltaUpdateFailed = true;
@@ -12297,6 +12307,7 @@
12297
12307
  _this.decrypter = void 0;
12298
12308
  _this.initPTS = [];
12299
12309
  _this.buffering = true;
12310
+ _this.loadingParts = false;
12300
12311
  _this.onMediaSeeking = function () {
12301
12312
  var _assertThisInitialize = _assertThisInitialized(_this),
12302
12313
  config = _assertThisInitialize.config,
@@ -12332,6 +12343,14 @@
12332
12343
  // Remove gap fragments
12333
12344
  _this.fragmentTracker.removeFragmentsInRange(currentTime, Infinity, _this.playlistType, true);
12334
12345
  _this.lastCurrentTime = currentTime;
12346
+ if (!_this.loadingParts) {
12347
+ var bufferEnd = Math.max(bufferInfo.end, currentTime);
12348
+ var shouldLoadParts = _this.shouldLoadParts(_this.getLevelDetails(), bufferEnd);
12349
+ if (shouldLoadParts) {
12350
+ _this.log("LL-Part loading ON after seeking to " + currentTime.toFixed(2) + " with buffer @" + bufferEnd.toFixed(2));
12351
+ _this.loadingParts = shouldLoadParts;
12352
+ }
12353
+ }
12335
12354
  }
12336
12355
 
12337
12356
  // in case seeking occurs although no media buffered, adjust startPosition and nextLoadPosition to seek target
@@ -12741,8 +12760,16 @@
12741
12760
  } else if (!frag.encrypted && details.encryptedFragments.length) {
12742
12761
  this.keyLoader.loadClear(frag, details.encryptedFragments);
12743
12762
  }
12763
+ var fragPrevious = this.fragPrevious;
12764
+ if (frag.sn !== 'initSegment' && (!fragPrevious || frag.sn !== fragPrevious.sn)) {
12765
+ var shouldLoadParts = this.shouldLoadParts(level.details, frag.end);
12766
+ if (shouldLoadParts !== this.loadingParts) {
12767
+ this.log("LL-Part loading " + (shouldLoadParts ? 'ON' : 'OFF') + " loading sn " + (fragPrevious == null ? void 0 : fragPrevious.sn) + "->" + frag.sn);
12768
+ this.loadingParts = shouldLoadParts;
12769
+ }
12770
+ }
12744
12771
  targetBufferTime = Math.max(frag.start, targetBufferTime || 0);
12745
- if (this.config.lowLatencyMode && frag.sn !== 'initSegment') {
12772
+ if (this.loadingParts && frag.sn !== 'initSegment') {
12746
12773
  var partList = details.partList;
12747
12774
  if (partList && progressCallback) {
12748
12775
  if (targetBufferTime > frag.end && details.fragmentHint) {
@@ -12784,6 +12811,13 @@
12784
12811
  }
12785
12812
  }
12786
12813
  }
12814
+ if (frag.sn !== 'initSegment' && this.loadingParts) {
12815
+ this.log("LL-Part loading OFF after next part miss @" + targetBufferTime.toFixed(2));
12816
+ this.loadingParts = false;
12817
+ } else if (!frag.url) {
12818
+ // Selected fragment hint for part but not loading parts
12819
+ return Promise.resolve(null);
12820
+ }
12787
12821
  this.log("Loading fragment " + frag.sn + " cc: " + frag.cc + " " + (details ? 'of [' + details.startSN + '-' + details.endSN + '] ' : '') + (this.playlistType === PlaylistLevelType.MAIN ? 'level' : 'track') + ": " + frag.level + ", target: " + parseFloat(targetBufferTime.toFixed(3)));
12788
12822
  // Don't update nextLoadPosition for fragments which are not buffered
12789
12823
  if (isFiniteNumber(frag.sn) && !this.bitrateTest) {
@@ -12886,8 +12920,36 @@
12886
12920
  if (part) {
12887
12921
  part.stats.parsing.end = now;
12888
12922
  }
12923
+ // See if part loading should be disabled/enabled based on buffer and playback position.
12924
+ if (frag.sn !== 'initSegment') {
12925
+ var levelDetails = this.getLevelDetails();
12926
+ var loadingPartsAtEdge = levelDetails && frag.sn > levelDetails.endSN;
12927
+ var shouldLoadParts = loadingPartsAtEdge || this.shouldLoadParts(levelDetails, frag.end);
12928
+ if (shouldLoadParts !== this.loadingParts) {
12929
+ this.log("LL-Part loading " + (shouldLoadParts ? 'ON' : 'OFF') + " after parsing segment ending @" + frag.end.toFixed(2));
12930
+ this.loadingParts = shouldLoadParts;
12931
+ }
12932
+ }
12889
12933
  this.updateLevelTiming(frag, part, level, chunkMeta.partial);
12890
12934
  };
12935
+ _proto.shouldLoadParts = function shouldLoadParts(details, bufferEnd) {
12936
+ if (this.config.lowLatencyMode) {
12937
+ if (!details) {
12938
+ return this.loadingParts;
12939
+ }
12940
+ if (details != null && details.partList) {
12941
+ var _details$fragmentHint;
12942
+ // Buffer must be ahead of first part + duration of parts after last segment
12943
+ // and playback must be at or past segment adjacent to part list
12944
+ var firstPart = details.partList[0];
12945
+ var safePartStart = firstPart.end + (((_details$fragmentHint = details.fragmentHint) == null ? void 0 : _details$fragmentHint.duration) || 0);
12946
+ if (bufferEnd >= safePartStart && this.lastCurrentTime > firstPart.start - firstPart.fragment.duration) {
12947
+ return true;
12948
+ }
12949
+ }
12950
+ }
12951
+ return false;
12952
+ };
12891
12953
  _proto.getCurrentContext = function getCurrentContext(chunkMeta) {
12892
12954
  var levels = this.levels,
12893
12955
  fragCurrent = this.fragCurrent;
@@ -13022,7 +13084,8 @@
13022
13084
  // find fragment index, contiguous with end of buffer position
13023
13085
  var config = this.config;
13024
13086
  var start = fragments[0].start;
13025
- var frag;
13087
+ var canLoadParts = config.lowLatencyMode && !!levelDetails.partList;
13088
+ var frag = null;
13026
13089
  if (levelDetails.live) {
13027
13090
  var initialLiveManifestSize = config.initialLiveManifestSize;
13028
13091
  if (fragLen < initialLiveManifestSize) {
@@ -13034,6 +13097,10 @@
13034
13097
  // Do not load using live logic if the starting frag is requested - we want to use getFragmentAtPosition() so that
13035
13098
  // we get the fragment matching that start time
13036
13099
  if (!levelDetails.PTSKnown && !this.startFragRequested && this.startPosition === -1 || pos < start) {
13100
+ if (canLoadParts && !this.loadingParts) {
13101
+ this.log("LL-Part loading ON for initial live fragment");
13102
+ this.loadingParts = true;
13103
+ }
13037
13104
  frag = this.getInitialLiveFragment(levelDetails, fragments);
13038
13105
  this.startPosition = this.nextLoadPosition = frag ? this.hls.liveSyncPosition || frag.start : pos;
13039
13106
  }
@@ -13044,7 +13111,7 @@
13044
13111
 
13045
13112
  // If we haven't run into any special cases already, just load the fragment most closely matching the requested position
13046
13113
  if (!frag) {
13047
- var end = config.lowLatencyMode ? levelDetails.partEnd : levelDetails.fragmentEnd;
13114
+ var end = this.loadingParts ? levelDetails.partEnd : levelDetails.fragmentEnd;
13048
13115
  frag = this.getFragmentAtPosition(pos, end, levelDetails);
13049
13116
  }
13050
13117
  return this.mapToInitFragWhenRequired(frag);
@@ -13158,7 +13225,7 @@
13158
13225
  var fragmentHint = levelDetails.fragmentHint;
13159
13226
  var tolerance = config.maxFragLookUpTolerance;
13160
13227
  var partList = levelDetails.partList;
13161
- var loadingParts = !!(config.lowLatencyMode && partList != null && partList.length && fragmentHint);
13228
+ var loadingParts = !!(this.loadingParts && partList != null && partList.length && fragmentHint);
13162
13229
  if (loadingParts && fragmentHint && !this.bitrateTest) {
13163
13230
  // Include incomplete fragment with parts at end
13164
13231
  fragments = fragments.concat(fragmentHint);
@@ -21258,7 +21325,7 @@
21258
21325
  * Get the video-dev/hls.js package version.
21259
21326
  */
21260
21327
  function get() {
21261
- return "1.5.5-0.canary.9984";
21328
+ return "1.5.5-0.canary.9986";
21262
21329
  }
21263
21330
  }, {
21264
21331
  key: "Events",