hls.js 1.6.0-beta.1.0.canary.10787 → 1.6.0-beta.1.0.canary.10789

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.
@@ -400,7 +400,7 @@ function enableLogs(debugConfig, context, id) {
400
400
  // Some browsers don't allow to use bind on console object anyway
401
401
  // fallback to default if needed
402
402
  try {
403
- newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.6.0-beta.1.0.canary.10787"}`);
403
+ newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.6.0-beta.1.0.canary.10789"}`);
404
404
  } catch (e) {
405
405
  /* log fn threw an exception. All logger methods are no-ops. */
406
406
  return createLogger();
@@ -3140,6 +3140,7 @@ class LevelDetails {
3140
3140
  this.dateRanges = void 0;
3141
3141
  this.dateRangeTagCount = 0;
3142
3142
  this.live = true;
3143
+ this.requestScheduled = -1;
3143
3144
  this.ageHeader = 0;
3144
3145
  this.advancedDateTime = void 0;
3145
3146
  this.updated = true;
@@ -5417,6 +5418,9 @@ function mergeDetails(oldDetails, newDetails) {
5417
5418
  newDetails.driftEnd = oldDetails.driftEnd;
5418
5419
  newDetails.advancedDateTime = oldDetails.advancedDateTime;
5419
5420
  }
5421
+ if (newDetails.requestScheduled === -1) {
5422
+ newDetails.requestScheduled = oldDetails.requestScheduled;
5423
+ }
5420
5424
  }
5421
5425
  function mergeDateRanges(oldDateRanges, newDetails) {
5422
5426
  const {
@@ -5487,12 +5491,14 @@ function adjustSliding(oldDetails, newDetails, matchingStableVariantOrRendition
5487
5491
  let sliding = 0;
5488
5492
  if (advancedOrStable && delta < oldFragments.length) {
5489
5493
  sliding = oldFragments[delta].start;
5494
+ } else if (advancedOrStable && newDetails.startSN === oldDetails.endSN + 1) {
5495
+ sliding = oldDetails.fragmentEnd;
5490
5496
  } else if (advancedOrStable && matchingStableVariantOrRendition) {
5491
- // align new start with old end (updated playlist start sequence is past end sequence of last update)
5492
- sliding = oldDetails.edge;
5493
- } else if (!newDetails.skippedSegments && newDetails.fragments[0].start === 0) {
5497
+ // align with expected position (updated playlist start sequence is past end sequence of last update)
5498
+ sliding = oldDetails.fragmentStart + delta * newDetails.levelTargetDuration;
5499
+ } else if (!newDetails.skippedSegments && newDetails.fragmentStart === 0) {
5494
5500
  // align new start with old (playlist switch has a sequence with no overlap and should not be used for alignment)
5495
- sliding = oldDetails.fragments[0].start;
5501
+ sliding = oldDetails.fragmentStart;
5496
5502
  } else {
5497
5503
  // new details already has a sliding offset or has skipped segments
5498
5504
  return;
@@ -5583,7 +5589,6 @@ class BasePlaylistController extends Logger {
5583
5589
  super(logPrefix, hls.logger);
5584
5590
  this.hls = void 0;
5585
5591
  this.timer = -1;
5586
- this.requestScheduled = -1;
5587
5592
  this.canLoad = false;
5588
5593
  this.hls = hls;
5589
5594
  }
@@ -5600,7 +5605,6 @@ class BasePlaylistController extends Logger {
5600
5605
  }
5601
5606
  startLoad() {
5602
5607
  this.canLoad = true;
5603
- this.requestScheduled = -1;
5604
5608
  this.loadPlaylist();
5605
5609
  }
5606
5610
  stopLoad() {
@@ -5645,16 +5649,25 @@ class BasePlaylistController extends Logger {
5645
5649
  }
5646
5650
  }
5647
5651
  loadPlaylist(hlsUrlParameters) {
5648
- if (this.requestScheduled === -1) {
5649
- this.requestScheduled = self.performance.now();
5650
- }
5651
5652
  // Loading is handled by the subclasses
5653
+ this.clearTimer();
5654
+ }
5655
+ loadingPlaylist(playlist, hlsUrlParameters) {
5656
+ // Loading is handled by the subclasses
5657
+ this.clearTimer();
5652
5658
  }
5653
5659
  shouldLoadPlaylist(playlist) {
5654
5660
  return this.canLoad && !!playlist && !!playlist.url && (!playlist.details || playlist.details.live);
5655
5661
  }
5656
- shouldReloadPlaylist(playlist) {
5657
- return this.timer === -1 && this.requestScheduled === -1 && this.shouldLoadPlaylist(playlist);
5662
+ getUrlWithDirectives(uri, hlsUrlParameters) {
5663
+ if (hlsUrlParameters) {
5664
+ try {
5665
+ return hlsUrlParameters.addDirectives(uri);
5666
+ } catch (error) {
5667
+ this.warn(`Could not construct new URL with HLS Delivery Directives: ${error}`);
5668
+ }
5669
+ }
5670
+ return uri;
5658
5671
  }
5659
5672
  playlistLoaded(index, data, previousDetails) {
5660
5673
  const {
@@ -5679,10 +5692,9 @@ class BasePlaylistController extends Logger {
5679
5692
 
5680
5693
  // if current playlist is a live playlist, arm a timer to reload it
5681
5694
  if (details.live || previousDetails != null && previousDetails.live) {
5695
+ const levelOrTrack = 'levelInfo' in data ? data.levelInfo : data.track;
5682
5696
  details.reloaded(previousDetails);
5683
- if (previousDetails) {
5684
- this.log(`live playlist ${index} ${details.advanced ? 'REFRESHED ' + details.lastPartSn + '-' + details.lastPartIndex : details.updated ? 'UPDATED' : 'MISSED'}`);
5685
- }
5697
+ this.log(`live playlist ${index} ${details.advanced ? 'REFRESHED ' + details.lastPartSn + '-' + details.lastPartIndex : details.updated ? 'UPDATED' : 'MISSED'}`);
5686
5698
  // Merge live playlists to adjust fragment starts and fill in delta playlist skipped segments
5687
5699
  if (previousDetails && details.fragments.length > 0) {
5688
5700
  mergeDetails(previousDetails, details);
@@ -5738,50 +5750,64 @@ class BasePlaylistController extends Logger {
5738
5750
  }
5739
5751
  deliveryDirectives = this.getDeliveryDirectives(details, data.deliveryDirectives, msn, part);
5740
5752
  if (lowLatencyMode || !lastPart) {
5741
- this.loadPlaylist(deliveryDirectives);
5753
+ this.loadingPlaylist(levelOrTrack, deliveryDirectives);
5742
5754
  return;
5743
5755
  }
5744
5756
  } else if (details.canBlockReload || details.canSkipUntil) {
5745
5757
  deliveryDirectives = this.getDeliveryDirectives(details, data.deliveryDirectives, msn, part);
5746
5758
  }
5759
+ if (details.requestScheduled === -1) {
5760
+ details.requestScheduled = stats.loading.start;
5761
+ }
5762
+ if (deliveryDirectives && msn !== undefined && details.canBlockReload) {
5763
+ details.requestScheduled -= details.partTarget * 1000 || 1000;
5764
+ }
5747
5765
  const bufferInfo = this.hls.mainForwardBufferInfo;
5748
5766
  const position = bufferInfo ? bufferInfo.end - bufferInfo.len : 0;
5749
5767
  const distanceToLiveEdgeMs = (details.edge - position) * 1000;
5750
5768
  const reloadInterval = computeReloadInterval(details, distanceToLiveEdgeMs);
5751
- if (details.updated && now > this.requestScheduled + reloadInterval) {
5752
- this.requestScheduled = stats.loading.start;
5753
- }
5754
- if (msn !== undefined && details.canBlockReload) {
5755
- this.requestScheduled = stats.loading.first + reloadInterval - (details.partTarget * 1000 || 1000);
5756
- } else if (this.requestScheduled === -1 || this.requestScheduled + reloadInterval < now) {
5757
- this.requestScheduled = now;
5758
- } else if (this.requestScheduled - now <= 0) {
5759
- this.requestScheduled += reloadInterval;
5760
- }
5761
- let estimatedTimeUntilUpdate = this.requestScheduled - now;
5762
- estimatedTimeUntilUpdate = Math.max(0, estimatedTimeUntilUpdate);
5763
- this.log(`reload live playlist ${index} in ${Math.round(estimatedTimeUntilUpdate)} ms`);
5764
- // this.log(
5765
- // `live reload ${details.updated ? 'REFRESHED' : 'MISSED'}
5766
- // reload in ${estimatedTimeUntilUpdate / 1000}
5767
- // round trip ${(stats.loading.end - stats.loading.start) / 1000}
5768
- // diff ${
5769
- // (reloadInterval -
5770
- // (estimatedTimeUntilUpdate +
5771
- // stats.loading.end -
5772
- // stats.loading.start)) /
5773
- // 1000
5774
- // }
5775
- // reload interval ${reloadInterval / 1000}
5776
- // target duration ${details.targetduration}
5777
- // distance to edge ${distanceToLiveEdgeMs / 1000}`
5778
- // );
5779
-
5780
- this.timer = self.setTimeout(() => this.loadPlaylist(deliveryDirectives), estimatedTimeUntilUpdate);
5769
+ if (details.requestScheduled + reloadInterval < now) {
5770
+ details.requestScheduled = now;
5771
+ } else {
5772
+ details.requestScheduled += reloadInterval;
5773
+ }
5774
+ this.scheduleLoading(levelOrTrack, deliveryDirectives);
5781
5775
  } else {
5782
5776
  this.clearTimer();
5783
5777
  }
5784
5778
  }
5779
+ scheduleLoading(levelOrTrack, deliveryDirectives) {
5780
+ const details = levelOrTrack.details;
5781
+ if (!details) {
5782
+ this.loadingPlaylist(levelOrTrack, deliveryDirectives);
5783
+ return;
5784
+ }
5785
+ const now = self.performance.now();
5786
+ const requestScheduled = details.requestScheduled;
5787
+ if (now >= requestScheduled) {
5788
+ this.loadingPlaylist(levelOrTrack, deliveryDirectives);
5789
+ return;
5790
+ }
5791
+ const estimatedTimeUntilUpdate = requestScheduled - now;
5792
+ this.log(`reload live playlist ${levelOrTrack.name || levelOrTrack.bitrate + 'bps'} in ${Math.round(estimatedTimeUntilUpdate)} ms`);
5793
+ // this.log(
5794
+ // `live reload ${details.updated ? 'REFRESHED' : 'MISSED'}
5795
+ // reload in ${estimatedTimeUntilUpdate / 1000}
5796
+ // round trip ${(stats.loading.end - stats.loading.start) / 1000}
5797
+ // diff ${
5798
+ // (reloadInterval -
5799
+ // (estimatedTimeUntilUpdate +
5800
+ // stats.loading.end -
5801
+ // stats.loading.start)) /
5802
+ // 1000
5803
+ // }
5804
+ // reload interval ${reloadInterval / 1000}
5805
+ // target duration ${details.targetduration}
5806
+ // distance to edge ${distanceToLiveEdgeMs / 1000}`
5807
+ // );
5808
+
5809
+ this.timer = self.setTimeout(() => this.loadingPlaylist(levelOrTrack, deliveryDirectives), estimatedTimeUntilUpdate);
5810
+ }
5785
5811
  getDeliveryDirectives(details, previousDeliveryDirectives, msn, part) {
5786
5812
  let skip = getSkipValue(details);
5787
5813
  if (previousDeliveryDirectives != null && previousDeliveryDirectives.skip && details.deltaUpdateFailed) {
@@ -5803,7 +5829,6 @@ class BasePlaylistController extends Logger {
5803
5829
  const retry = !!errorAction && !!retryConfig && (action === NetworkErrorAction.RetryRequest || !errorAction.resolved && action === NetworkErrorAction.SendAlternateToPenaltyBox);
5804
5830
  if (retry) {
5805
5831
  var _errorEvent$context;
5806
- this.requestScheduled = -1;
5807
5832
  if (retryCount >= retryConfig.maxNumRetry) {
5808
5833
  return false;
5809
5834
  }
@@ -8606,12 +8631,13 @@ class BaseStreamController extends TaskLoop {
8606
8631
  this.nextLoadPosition = startPosition;
8607
8632
  }
8608
8633
  getLoadPosition() {
8634
+ var _this$hls;
8609
8635
  const {
8610
8636
  media
8611
8637
  } = this;
8612
8638
  // if we have not yet loaded any fragment, start loading from start position
8613
8639
  let pos = 0;
8614
- if (this.hls.hasEnoughToStart && media) {
8640
+ if ((_this$hls = this.hls) != null && _this$hls.hasEnoughToStart && media) {
8615
8641
  pos = media.currentTime;
8616
8642
  } else if (this.nextLoadPosition >= 0) {
8617
8643
  pos = this.nextLoadPosition;
@@ -18516,9 +18542,7 @@ class LevelController extends BasePlaylistController {
18516
18542
  this.currentLevelIndex = newLevel;
18517
18543
  this.currentLevel = level;
18518
18544
  if (lastLevelIndex === newLevel && lastLevel && lastPathwayId === pathwayId) {
18519
- if (level.details || this.requestScheduled !== -1) {
18520
- return;
18521
- }
18545
+ return;
18522
18546
  }
18523
18547
  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 : ''}`);
18524
18548
  const levelSwitchingData = {
@@ -18612,10 +18636,7 @@ class LevelController extends BasePlaylistController {
18612
18636
  return;
18613
18637
  }
18614
18638
  if (data.context.type === PlaylistContextType.LEVEL && data.context.level === this.level) {
18615
- const retry = this.checkRetry(data);
18616
- if (!retry) {
18617
- this.requestScheduled = -1;
18618
- }
18639
+ this.checkRetry(data);
18619
18640
  }
18620
18641
  }
18621
18642
 
@@ -18670,36 +18691,28 @@ class LevelController extends BasePlaylistController {
18670
18691
  }
18671
18692
  loadPlaylist(hlsUrlParameters) {
18672
18693
  super.loadPlaylist();
18673
- const currentLevelIndex = this.currentLevelIndex;
18674
- const currentLevel = this.currentLevel;
18675
- if (currentLevel && this.shouldLoadPlaylist(currentLevel)) {
18676
- let url = currentLevel.uri;
18677
- if (hlsUrlParameters) {
18678
- try {
18679
- url = hlsUrlParameters.addDirectives(url);
18680
- } catch (error) {
18681
- this.warn(`Could not construct new URL with HLS Delivery Directives: ${error}`);
18682
- }
18683
- }
18684
- const pathwayId = currentLevel.attrs['PATHWAY-ID'];
18685
- const details = currentLevel.details;
18686
- const age = details == null ? void 0 : details.age;
18687
- this.log(`Loading level index ${currentLevelIndex}${(hlsUrlParameters == null ? void 0 : hlsUrlParameters.msn) !== undefined ? ' at sn ' + hlsUrlParameters.msn + ' part ' + hlsUrlParameters.part : ''}${pathwayId ? ' Pathway ' + pathwayId : ''}${age && details.live ? ' age ' + age.toFixed(1) + (details.type ? ' ' + details.type || '' : '') : ''} ${url}`);
18688
-
18689
- // console.log('Current audio track group ID:', this.hls.audioTracks[this.hls.audioTrack].groupId);
18690
- // console.log('New video quality level audio group id:', levelObject.attrs.AUDIO, level);
18691
- this.clearTimer();
18692
- this.hls.trigger(Events.LEVEL_LOADING, {
18693
- url,
18694
- level: currentLevelIndex,
18695
- levelInfo: currentLevel,
18696
- pathwayId: currentLevel.attrs['PATHWAY-ID'],
18697
- id: 0,
18698
- // Deprecated Level urlId
18699
- deliveryDirectives: hlsUrlParameters || null
18700
- });
18694
+ if (this.shouldLoadPlaylist(this.currentLevel)) {
18695
+ this.scheduleLoading(this.currentLevel, hlsUrlParameters);
18701
18696
  }
18702
18697
  }
18698
+ loadingPlaylist(currentLevel, hlsUrlParameters) {
18699
+ super.loadingPlaylist(currentLevel, hlsUrlParameters);
18700
+ const url = this.getUrlWithDirectives(currentLevel.uri, hlsUrlParameters);
18701
+ const currentLevelIndex = this.currentLevelIndex;
18702
+ const pathwayId = currentLevel.attrs['PATHWAY-ID'];
18703
+ const details = currentLevel.details;
18704
+ const age = details == null ? void 0 : details.age;
18705
+ this.log(`Loading level index ${currentLevelIndex}${(hlsUrlParameters == null ? void 0 : hlsUrlParameters.msn) !== undefined ? ' at sn ' + hlsUrlParameters.msn + ' part ' + hlsUrlParameters.part : ''}${pathwayId ? ' Pathway ' + pathwayId : ''}${age && details.live ? ' age ' + age.toFixed(1) + (details.type ? ' ' + details.type || '' : '') : ''} ${url}`);
18706
+ this.hls.trigger(Events.LEVEL_LOADING, {
18707
+ url,
18708
+ level: currentLevelIndex,
18709
+ levelInfo: currentLevel,
18710
+ pathwayId: currentLevel.attrs['PATHWAY-ID'],
18711
+ id: 0,
18712
+ // Deprecated Level urlId
18713
+ deliveryDirectives: hlsUrlParameters || null
18714
+ });
18715
+ }
18703
18716
  get nextLoadLevel() {
18704
18717
  if (this.manualLevelIndex !== -1) {
18705
18718
  return this.manualLevelIndex;
@@ -19117,7 +19130,7 @@ class GapController extends Logger {
19117
19130
  }
19118
19131
  }
19119
19132
 
19120
- const version = "1.6.0-beta.1.0.canary.10787";
19133
+ const version = "1.6.0-beta.1.0.canary.10789";
19121
19134
 
19122
19135
  // ensure the worker ends up in the bundle
19123
19136
  // If the worker should not be included this gets aliased to empty.js