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.
@@ -512,7 +512,7 @@ function enableLogs(debugConfig, context, id) {
512
512
  // Some browsers don't allow to use bind on console object anyway
513
513
  // fallback to default if needed
514
514
  try {
515
- newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.5.5-0.canary.9984"}`);
515
+ newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.5.5-0.canary.9986"}`);
516
516
  } catch (e) {
517
517
  /* log fn threw an exception. All logger methods are no-ops. */
518
518
  return createLogger();
@@ -5713,7 +5713,12 @@ class BasePlaylistController extends Logger {
5713
5713
  const cdnAge = lastAdvanced + details.ageHeader;
5714
5714
  let currentGoal = Math.min(cdnAge - details.partTarget, details.targetduration * 1.5);
5715
5715
  if (currentGoal > 0) {
5716
- if (previousDetails && currentGoal > previousDetails.tuneInGoal) {
5716
+ if (cdnAge > details.targetduration * 3) {
5717
+ // Omit segment and part directives when the last response was more than 3 target durations ago,
5718
+ this.log(`Playlist last advanced ${lastAdvanced.toFixed(2)}s ago. Omitting segment and part directives.`);
5719
+ msn = undefined;
5720
+ part = undefined;
5721
+ } else if (previousDetails != null && previousDetails.tuneInGoal && cdnAge - details.partTarget > previousDetails.tuneInGoal) {
5717
5722
  // If we attempted to get the next or latest playlist update, but currentGoal increased,
5718
5723
  // then we either can't catchup, or the "age" header cannot be trusted.
5719
5724
  this.warn(`CDN Tune-in goal increased from: ${previousDetails.tuneInGoal} to: ${currentGoal} with playlist age: ${details.age}`);
@@ -10059,7 +10064,12 @@ class LevelController extends BasePlaylistController {
10059
10064
  if (curLevel.fragmentError === 0) {
10060
10065
  curLevel.loadError = 0;
10061
10066
  }
10062
- this.playlistLoaded(level, data, curLevel.details);
10067
+ // Ignore matching details populated by loading a Media Playlist directly
10068
+ let previousDetails = curLevel.details;
10069
+ if (previousDetails === data.details && previousDetails.advanced) {
10070
+ previousDetails = undefined;
10071
+ }
10072
+ this.playlistLoaded(level, data, previousDetails);
10063
10073
  } else if ((_data$deliveryDirecti2 = data.deliveryDirectives) != null && _data$deliveryDirecti2.skip) {
10064
10074
  // received a delta playlist update that cannot be merged
10065
10075
  details.deltaUpdateFailed = true;
@@ -11956,6 +11966,7 @@ class BaseStreamController extends TaskLoop {
11956
11966
  this.decrypter = void 0;
11957
11967
  this.initPTS = [];
11958
11968
  this.buffering = true;
11969
+ this.loadingParts = false;
11959
11970
  this.onMediaSeeking = () => {
11960
11971
  const {
11961
11972
  config,
@@ -11992,6 +12003,14 @@ class BaseStreamController extends TaskLoop {
11992
12003
  // Remove gap fragments
11993
12004
  this.fragmentTracker.removeFragmentsInRange(currentTime, Infinity, this.playlistType, true);
11994
12005
  this.lastCurrentTime = currentTime;
12006
+ if (!this.loadingParts) {
12007
+ const bufferEnd = Math.max(bufferInfo.end, currentTime);
12008
+ const shouldLoadParts = this.shouldLoadParts(this.getLevelDetails(), bufferEnd);
12009
+ if (shouldLoadParts) {
12010
+ this.log(`LL-Part loading ON after seeking to ${currentTime.toFixed(2)} with buffer @${bufferEnd.toFixed(2)}`);
12011
+ this.loadingParts = shouldLoadParts;
12012
+ }
12013
+ }
11995
12014
  }
11996
12015
 
11997
12016
  // in case seeking occurs although no media buffered, adjust startPosition and nextLoadPosition to seek target
@@ -12402,8 +12421,16 @@ class BaseStreamController extends TaskLoop {
12402
12421
  } else if (!frag.encrypted && details.encryptedFragments.length) {
12403
12422
  this.keyLoader.loadClear(frag, details.encryptedFragments);
12404
12423
  }
12424
+ const fragPrevious = this.fragPrevious;
12425
+ if (frag.sn !== 'initSegment' && (!fragPrevious || frag.sn !== fragPrevious.sn)) {
12426
+ const shouldLoadParts = this.shouldLoadParts(level.details, frag.end);
12427
+ if (shouldLoadParts !== this.loadingParts) {
12428
+ this.log(`LL-Part loading ${shouldLoadParts ? 'ON' : 'OFF'} loading sn ${fragPrevious == null ? void 0 : fragPrevious.sn}->${frag.sn}`);
12429
+ this.loadingParts = shouldLoadParts;
12430
+ }
12431
+ }
12405
12432
  targetBufferTime = Math.max(frag.start, targetBufferTime || 0);
12406
- if (this.config.lowLatencyMode && frag.sn !== 'initSegment') {
12433
+ if (this.loadingParts && frag.sn !== 'initSegment') {
12407
12434
  const partList = details.partList;
12408
12435
  if (partList && progressCallback) {
12409
12436
  if (targetBufferTime > frag.end && details.fragmentHint) {
@@ -12441,6 +12468,13 @@ class BaseStreamController extends TaskLoop {
12441
12468
  }
12442
12469
  }
12443
12470
  }
12471
+ if (frag.sn !== 'initSegment' && this.loadingParts) {
12472
+ this.log(`LL-Part loading OFF after next part miss @${targetBufferTime.toFixed(2)}`);
12473
+ this.loadingParts = false;
12474
+ } else if (!frag.url) {
12475
+ // Selected fragment hint for part but not loading parts
12476
+ return Promise.resolve(null);
12477
+ }
12444
12478
  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))}`);
12445
12479
  // Don't update nextLoadPosition for fragments which are not buffered
12446
12480
  if (isFiniteNumber(frag.sn) && !this.bitrateTest) {
@@ -12539,8 +12573,36 @@ class BaseStreamController extends TaskLoop {
12539
12573
  if (part) {
12540
12574
  part.stats.parsing.end = now;
12541
12575
  }
12576
+ // See if part loading should be disabled/enabled based on buffer and playback position.
12577
+ if (frag.sn !== 'initSegment') {
12578
+ const levelDetails = this.getLevelDetails();
12579
+ const loadingPartsAtEdge = levelDetails && frag.sn > levelDetails.endSN;
12580
+ const shouldLoadParts = loadingPartsAtEdge || this.shouldLoadParts(levelDetails, frag.end);
12581
+ if (shouldLoadParts !== this.loadingParts) {
12582
+ this.log(`LL-Part loading ${shouldLoadParts ? 'ON' : 'OFF'} after parsing segment ending @${frag.end.toFixed(2)}`);
12583
+ this.loadingParts = shouldLoadParts;
12584
+ }
12585
+ }
12542
12586
  this.updateLevelTiming(frag, part, level, chunkMeta.partial);
12543
12587
  }
12588
+ shouldLoadParts(details, bufferEnd) {
12589
+ if (this.config.lowLatencyMode) {
12590
+ if (!details) {
12591
+ return this.loadingParts;
12592
+ }
12593
+ if (details != null && details.partList) {
12594
+ var _details$fragmentHint;
12595
+ // Buffer must be ahead of first part + duration of parts after last segment
12596
+ // and playback must be at or past segment adjacent to part list
12597
+ const firstPart = details.partList[0];
12598
+ const safePartStart = firstPart.end + (((_details$fragmentHint = details.fragmentHint) == null ? void 0 : _details$fragmentHint.duration) || 0);
12599
+ if (bufferEnd >= safePartStart && this.lastCurrentTime > firstPart.start - firstPart.fragment.duration) {
12600
+ return true;
12601
+ }
12602
+ }
12603
+ }
12604
+ return false;
12605
+ }
12544
12606
  getCurrentContext(chunkMeta) {
12545
12607
  const {
12546
12608
  levels,
@@ -12689,7 +12751,8 @@ class BaseStreamController extends TaskLoop {
12689
12751
  config
12690
12752
  } = this;
12691
12753
  const start = fragments[0].start;
12692
- let frag;
12754
+ const canLoadParts = config.lowLatencyMode && !!levelDetails.partList;
12755
+ let frag = null;
12693
12756
  if (levelDetails.live) {
12694
12757
  const initialLiveManifestSize = config.initialLiveManifestSize;
12695
12758
  if (fragLen < initialLiveManifestSize) {
@@ -12701,6 +12764,10 @@ class BaseStreamController extends TaskLoop {
12701
12764
  // Do not load using live logic if the starting frag is requested - we want to use getFragmentAtPosition() so that
12702
12765
  // we get the fragment matching that start time
12703
12766
  if (!levelDetails.PTSKnown && !this.startFragRequested && this.startPosition === -1 || pos < start) {
12767
+ if (canLoadParts && !this.loadingParts) {
12768
+ this.log(`LL-Part loading ON for initial live fragment`);
12769
+ this.loadingParts = true;
12770
+ }
12704
12771
  frag = this.getInitialLiveFragment(levelDetails, fragments);
12705
12772
  this.startPosition = this.nextLoadPosition = frag ? this.hls.liveSyncPosition || frag.start : pos;
12706
12773
  }
@@ -12711,7 +12778,7 @@ class BaseStreamController extends TaskLoop {
12711
12778
 
12712
12779
  // If we haven't run into any special cases already, just load the fragment most closely matching the requested position
12713
12780
  if (!frag) {
12714
- const end = config.lowLatencyMode ? levelDetails.partEnd : levelDetails.fragmentEnd;
12781
+ const end = this.loadingParts ? levelDetails.partEnd : levelDetails.fragmentEnd;
12715
12782
  frag = this.getFragmentAtPosition(pos, end, levelDetails);
12716
12783
  }
12717
12784
  return this.mapToInitFragWhenRequired(frag);
@@ -12833,7 +12900,7 @@ class BaseStreamController extends TaskLoop {
12833
12900
  } = levelDetails;
12834
12901
  const tolerance = config.maxFragLookUpTolerance;
12835
12902
  const partList = levelDetails.partList;
12836
- const loadingParts = !!(config.lowLatencyMode && partList != null && partList.length && fragmentHint);
12903
+ const loadingParts = !!(this.loadingParts && partList != null && partList.length && fragmentHint);
12837
12904
  if (loadingParts && fragmentHint && !this.bitrateTest) {
12838
12905
  // Include incomplete fragment with parts at end
12839
12906
  fragments = fragments.concat(fragmentHint);
@@ -19924,7 +19991,7 @@ class Hls {
19924
19991
  * Get the video-dev/hls.js package version.
19925
19992
  */
19926
19993
  static get version() {
19927
- return "1.5.5-0.canary.9984";
19994
+ return "1.5.5-0.canary.9986";
19928
19995
  }
19929
19996
 
19930
19997
  /**