hls.js 1.6.0-beta.1.0.canary.10714 → 1.6.0-beta.1.0.canary.10717

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.
@@ -397,7 +397,7 @@ function enableLogs(debugConfig, context, id) {
397
397
  // Some browsers don't allow to use bind on console object anyway
398
398
  // fallback to default if needed
399
399
  try {
400
- newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.6.0-beta.1.0.canary.10714"}`);
400
+ newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.6.0-beta.1.0.canary.10717"}`);
401
401
  } catch (e) {
402
402
  /* log fn threw an exception. All logger methods are no-ops. */
403
403
  return createLogger();
@@ -1078,6 +1078,7 @@ class AbrController extends Logger {
1078
1078
  quickly enough to prevent underbuffering
1079
1079
  */
1080
1080
  this._abandonRulesCheck = () => {
1081
+ var _this$hls$latestLevel;
1081
1082
  const {
1082
1083
  fragCurrent: frag,
1083
1084
  partCurrent: part,
@@ -1132,12 +1133,15 @@ class AbrController extends Logger {
1132
1133
  }
1133
1134
  const loadRate = loadedFirstByte ? stats.loaded * 1000 / timeStreaming : 0;
1134
1135
  // fragLoadDelay is an estimate of the time (in seconds) it will take to buffer the remainder of the fragment
1135
- const fragLoadedDelay = loadRate ? (expectedLen - stats.loaded) / loadRate : expectedLen * 8 / bwEstimate + ttfbEstimate / 1000;
1136
+ const ttfbSeconds = ttfbEstimate / 1000;
1137
+ const fragLoadedDelay = loadRate ? (expectedLen - stats.loaded) / loadRate : expectedLen * 8 / bwEstimate + ttfbSeconds;
1136
1138
  // Only downswitch if the time to finish loading the current fragment is greater than the amount of buffer left
1137
1139
  if (fragLoadedDelay <= bufferStarvationDelay) {
1138
1140
  return;
1139
1141
  }
1140
1142
  const bwe = loadRate ? loadRate * 8 : bwEstimate;
1143
+ const live = ((_this$hls$latestLevel = this.hls.latestLevelDetails) == null ? void 0 : _this$hls$latestLevel.live) === true;
1144
+ const abrBandWidthUpFactor = this.hls.config.abrBandWidthUpFactor;
1141
1145
  let fragLevelNextLoadedDelay = Number.POSITIVE_INFINITY;
1142
1146
  let nextLoadLevel;
1143
1147
  // Iterate through lower level and try to find the largest one that avoids rebuffering
@@ -1145,8 +1149,9 @@ class AbrController extends Logger {
1145
1149
  // compute time to load next fragment at lower level
1146
1150
  // 8 = bits per byte (bps/Bps)
1147
1151
  const levelNextBitrate = levels[nextLoadLevel].maxBitrate;
1148
- fragLevelNextLoadedDelay = this.getTimeToLoadFrag(ttfbEstimate / 1000, bwe, duration * levelNextBitrate, !levels[nextLoadLevel].details);
1149
- if (fragLevelNextLoadedDelay < bufferStarvationDelay) {
1152
+ const requiresLevelLoad = !levels[nextLoadLevel].details || live;
1153
+ fragLevelNextLoadedDelay = this.getTimeToLoadFrag(ttfbSeconds, bwe, duration * levelNextBitrate, requiresLevelLoad);
1154
+ if (fragLevelNextLoadedDelay < Math.min(bufferStarvationDelay, duration + ttfbSeconds)) {
1150
1155
  break;
1151
1156
  }
1152
1157
  }
@@ -1160,7 +1165,6 @@ class AbrController extends Logger {
1160
1165
  if (fragLevelNextLoadedDelay > duration * 10) {
1161
1166
  return;
1162
1167
  }
1163
- hls.nextLoadLevel = hls.nextAutoLevel = nextLoadLevel;
1164
1168
  if (loadedFirstByte) {
1165
1169
  // If there has been loading progress, sample bandwidth using loading time offset by minimum TTFB time
1166
1170
  this.bwEstimator.sample(timeLoading - Math.min(ttfbEstimate, ttfb), stats.loaded);
@@ -1169,11 +1173,15 @@ class AbrController extends Logger {
1169
1173
  this.bwEstimator.sampleTTFB(timeLoading);
1170
1174
  }
1171
1175
  const nextLoadLevelBitrate = levels[nextLoadLevel].maxBitrate;
1172
- if (this.getBwEstimate() * this.hls.config.abrBandWidthUpFactor > nextLoadLevelBitrate) {
1176
+ if (this.getBwEstimate() * abrBandWidthUpFactor > nextLoadLevelBitrate) {
1173
1177
  this.resetEstimator(nextLoadLevelBitrate);
1174
1178
  }
1175
- this.clearTimer();
1179
+ const bestSwitchLevel = this.findBestLevel(nextLoadLevelBitrate, minAutoLevel, nextLoadLevel, 0, bufferStarvationDelay, 1, 1);
1180
+ if (bestSwitchLevel > -1) {
1181
+ nextLoadLevel = bestSwitchLevel;
1182
+ }
1176
1183
  this.warn(`Fragment ${frag.sn}${part ? ' part ' + part.index : ''} of level ${frag.level} is loading too slowly;
1184
+ Fragment duration: ${frag.duration.toFixed(3)}
1177
1185
  Time to underbuffer: ${bufferStarvationDelay.toFixed(3)} s
1178
1186
  Estimated load time for current fragment: ${fragLoadedDelay.toFixed(3)} s
1179
1187
  Estimated load time for down switch fragment: ${fragLevelNextLoadedDelay.toFixed(3)} s
@@ -1181,6 +1189,28 @@ class AbrController extends Logger {
1181
1189
  Current BW estimate: ${isFiniteNumber(bwEstimate) ? bwEstimate | 0 : 'Unknown'} bps
1182
1190
  New BW estimate: ${this.getBwEstimate() | 0} bps
1183
1191
  Switching to level ${nextLoadLevel} @ ${nextLoadLevelBitrate | 0} bps`);
1192
+ hls.nextLoadLevel = hls.nextAutoLevel = nextLoadLevel;
1193
+ this.clearTimer();
1194
+ this.timer = self.setInterval(() => {
1195
+ // Are nextLoadLevel details available or is stream-controller still in "WAITING_LEVEL" state?
1196
+ this.clearTimer();
1197
+ if (this.fragCurrent === frag && this.hls.loadLevel === nextLoadLevel && nextLoadLevel > 0) {
1198
+ const bufferStarvationDelay = this.getStarvationDelay();
1199
+ this.warn(`Aborting inflight request ${nextLoadLevel > 0 ? 'and switching down' : ''}
1200
+ Fragment duration: ${frag.duration.toFixed(3)} s
1201
+ Time to underbuffer: ${bufferStarvationDelay.toFixed(3)} s`);
1202
+ frag.abortRequests();
1203
+ this.fragCurrent = this.partCurrent = null;
1204
+ if (nextLoadLevel > minAutoLevel) {
1205
+ let lowestSwitchLevel = this.findBestLevel(this.hls.levels[minAutoLevel].bitrate, minAutoLevel, nextLoadLevel, 0, bufferStarvationDelay, 1, 1);
1206
+ if (lowestSwitchLevel === -1) {
1207
+ lowestSwitchLevel = minAutoLevel;
1208
+ }
1209
+ this.hls.nextLoadLevel = this.hls.nextAutoLevel = lowestSwitchLevel;
1210
+ this.resetEstimator(this.hls.levels[lowestSwitchLevel].bitrate);
1211
+ }
1212
+ }
1213
+ }, fragLevelNextLoadedDelay * 1000);
1184
1214
  hls.trigger(Events.FRAG_LOAD_EMERGENCY_ABORTED, {
1185
1215
  frag,
1186
1216
  part,
@@ -1541,7 +1571,7 @@ class AbrController extends Logger {
1541
1571
  return this.bwEstimator.canEstimate() ? this.bwEstimator.getEstimate() : this.hls.config.abrEwmaDefaultEstimate;
1542
1572
  }
1543
1573
  findBestLevel(currentBw, minAutoLevel, maxAutoLevel, bufferStarvationDelay, maxStarvationDelay, bwFactor, bwUpFactor) {
1544
- var _level$details;
1574
+ var _this$hls$latestLevel2;
1545
1575
  const maxFetchDuration = bufferStarvationDelay + maxStarvationDelay;
1546
1576
  const lastLoadedFragLevel = this.lastLoadedFragLevel;
1547
1577
  const selectionBaseLevel = lastLoadedFragLevel === -1 ? this.hls.firstLevel : lastLoadedFragLevel;
@@ -1559,7 +1589,7 @@ class AbrController extends Logger {
1559
1589
  return 0;
1560
1590
  }
1561
1591
  const level = levels[selectionBaseLevel];
1562
- const live = !!(level != null && (_level$details = level.details) != null && _level$details.live);
1592
+ const live = !!((_this$hls$latestLevel2 = this.hls.latestLevelDetails) != null && _this$hls$latestLevel2.live);
1563
1593
  const firstSelection = loadLevel === -1 || lastLoadedFragLevel === -1;
1564
1594
  let currentCodecSet;
1565
1595
  let currentVideoRange = 'SDR';
@@ -18333,8 +18363,10 @@ class LevelController extends BasePlaylistController {
18333
18363
  const pathwayId = level.attrs['PATHWAY-ID'];
18334
18364
  this.currentLevelIndex = newLevel;
18335
18365
  this.currentLevel = level;
18336
- if (lastLevelIndex === newLevel && level.details && lastLevel && lastPathwayId === pathwayId) {
18337
- return;
18366
+ if (lastLevelIndex === newLevel && lastLevel && lastPathwayId === pathwayId) {
18367
+ if (level.details || this.requestScheduled !== -1) {
18368
+ return;
18369
+ }
18338
18370
  }
18339
18371
  this.log(`Switching to level ${newLevel} (${level.height ? level.height + 'p ' : ''}${level.videoRange ? level.videoRange + ' ' : ''}${level.codecSet ? level.codecSet + ' ' : ''}@${level.bitrate})${pathwayId ? ' with Pathway ' + pathwayId : ''} from level ${lastLevelIndex}${lastPathwayId ? ' with Pathway ' + lastPathwayId : ''}`);
18340
18372
  const levelSwitchingData = {
@@ -18428,7 +18460,10 @@ class LevelController extends BasePlaylistController {
18428
18460
  return;
18429
18461
  }
18430
18462
  if (data.context.type === PlaylistContextType.LEVEL && data.context.level === this.level) {
18431
- this.checkRetry(data);
18463
+ const retry = this.checkRetry(data);
18464
+ if (!retry) {
18465
+ this.requestScheduled = -1;
18466
+ }
18432
18467
  }
18433
18468
  }
18434
18469
 
@@ -18927,7 +18962,7 @@ class GapController extends Logger {
18927
18962
  }
18928
18963
  }
18929
18964
 
18930
- const version = "1.6.0-beta.1.0.canary.10714";
18965
+ const version = "1.6.0-beta.1.0.canary.10717";
18931
18966
 
18932
18967
  // ensure the worker ends up in the bundle
18933
18968
  // If the worker should not be included this gets aliased to empty.js