hls.js 1.5.17 → 1.5.18

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.mjs CHANGED
@@ -411,7 +411,7 @@ function enableLogs(debugConfig, id) {
411
411
  // Some browsers don't allow to use bind on console object anyway
412
412
  // fallback to default if needed
413
413
  try {
414
- exportedLogger.log(`Debug logs enabled for "${id}" in hls.js version ${"1.5.17"}`);
414
+ exportedLogger.log(`Debug logs enabled for "${id}" in hls.js version ${"1.5.18"}`);
415
415
  } catch (e) {
416
416
  exportedLogger = fakeLogger;
417
417
  }
@@ -9168,6 +9168,7 @@ class BaseStreamController extends TaskLoop {
9168
9168
  this.startFragRequested = false;
9169
9169
  this.decrypter = void 0;
9170
9170
  this.initPTS = [];
9171
+ this.buffering = true;
9171
9172
  this.onvseeking = null;
9172
9173
  this.onvended = null;
9173
9174
  this.logPrefix = '';
@@ -9207,6 +9208,12 @@ class BaseStreamController extends TaskLoop {
9207
9208
  this.clearNextTick();
9208
9209
  this.state = State.STOPPED;
9209
9210
  }
9211
+ pauseBuffering() {
9212
+ this.buffering = false;
9213
+ }
9214
+ resumeBuffering() {
9215
+ this.buffering = true;
9216
+ }
9210
9217
  _streamEnded(bufferInfo, levelDetails) {
9211
9218
  // If playlist is live, there is another buffered range after the current range, nothing buffered, media is detached,
9212
9219
  // of nothing loading/loaded return false
@@ -13624,19 +13631,23 @@ class MP4Remuxer {
13624
13631
  this.videoTrackConfig = undefined;
13625
13632
  }
13626
13633
  getVideoStartPts(videoSamples) {
13634
+ // Get the minimum PTS value relative to the first sample's PTS, normalized for 33-bit wrapping
13627
13635
  let rolloverDetected = false;
13636
+ const firstPts = videoSamples[0].pts;
13628
13637
  const startPTS = videoSamples.reduce((minPTS, sample) => {
13629
- const delta = sample.pts - minPTS;
13638
+ let pts = sample.pts;
13639
+ let delta = pts - minPTS;
13630
13640
  if (delta < -4294967296) {
13631
13641
  // 2^32, see PTSNormalize for reasoning, but we're hitting a rollover here, and we don't want that to impact the timeOffset calculation
13632
13642
  rolloverDetected = true;
13633
- return normalizePts(minPTS, sample.pts);
13634
- } else if (delta > 0) {
13643
+ pts = normalizePts(pts, firstPts);
13644
+ delta = pts - minPTS;
13645
+ }
13646
+ if (delta > 0) {
13635
13647
  return minPTS;
13636
- } else {
13637
- return sample.pts;
13638
13648
  }
13639
- }, videoSamples[0].pts);
13649
+ return pts;
13650
+ }, firstPts);
13640
13651
  if (rolloverDetected) {
13641
13652
  logger.debug('PTS rollover detected');
13642
13653
  }
@@ -15934,12 +15945,13 @@ class AudioStreamController extends BaseStreamController {
15934
15945
  } = this;
15935
15946
  const config = hls.config;
15936
15947
 
15937
- // 1. if video not attached AND
15948
+ // 1. if buffering is suspended
15949
+ // 2. if video not attached AND
15938
15950
  // start fragment already requested OR start frag prefetch not enabled
15939
- // 2. if tracks or track not loaded and selected
15951
+ // 3. if tracks or track not loaded and selected
15940
15952
  // then exit loop
15941
15953
  // => if media not attached but start frag prefetch is enabled and start frag not requested yet, we will not exit loop
15942
- if (!media && (this.startFragRequested || !config.startFragPrefetch) || !(levels != null && levels[trackId])) {
15954
+ if (!this.buffering || !media && (this.startFragRequested || !config.startFragPrefetch) || !(levels != null && levels[trackId])) {
15943
15955
  return;
15944
15956
  }
15945
15957
  const levelInfo = levels[trackId];
@@ -17993,6 +18005,7 @@ class BufferController {
17993
18005
  this.resetBuffer(type);
17994
18006
  });
17995
18007
  this._initSourceBuffer();
18008
+ this.hls.resumeBuffering();
17996
18009
  }
17997
18010
  resetBuffer(type) {
17998
18011
  const sb = this.sourceBuffer[type];
@@ -24704,47 +24717,51 @@ class XhrLoader {
24704
24717
  xhr.onprogress = null;
24705
24718
  const status = xhr.status;
24706
24719
  // http status between 200 to 299 are all successful
24707
- const useResponse = xhr.responseType !== 'text';
24708
- if (status >= 200 && status < 300 && (useResponse && xhr.response || xhr.responseText !== null)) {
24709
- stats.loading.end = Math.max(self.performance.now(), stats.loading.first);
24710
- const data = useResponse ? xhr.response : xhr.responseText;
24711
- const len = xhr.responseType === 'arraybuffer' ? data.byteLength : data.length;
24712
- stats.loaded = stats.total = len;
24713
- stats.bwEstimate = stats.total * 8000 / (stats.loading.end - stats.loading.first);
24714
- if (!this.callbacks) {
24715
- return;
24716
- }
24717
- const onProgress = this.callbacks.onProgress;
24718
- if (onProgress) {
24719
- onProgress(stats, context, data, xhr);
24720
- }
24721
- if (!this.callbacks) {
24720
+ const useResponseText = xhr.responseType === 'text' ? xhr.responseText : null;
24721
+ if (status >= 200 && status < 300) {
24722
+ const data = useResponseText != null ? useResponseText : xhr.response;
24723
+ if (data != null) {
24724
+ stats.loading.end = Math.max(self.performance.now(), stats.loading.first);
24725
+ const len = xhr.responseType === 'arraybuffer' ? data.byteLength : data.length;
24726
+ stats.loaded = stats.total = len;
24727
+ stats.bwEstimate = stats.total * 8000 / (stats.loading.end - stats.loading.first);
24728
+ if (!this.callbacks) {
24729
+ return;
24730
+ }
24731
+ const onProgress = this.callbacks.onProgress;
24732
+ if (onProgress) {
24733
+ onProgress(stats, context, data, xhr);
24734
+ }
24735
+ if (!this.callbacks) {
24736
+ return;
24737
+ }
24738
+ const _response = {
24739
+ url: xhr.responseURL,
24740
+ data: data,
24741
+ code: status
24742
+ };
24743
+ this.callbacks.onSuccess(_response, stats, context, xhr);
24722
24744
  return;
24723
24745
  }
24724
- const response = {
24725
- url: xhr.responseURL,
24726
- data: data,
24727
- code: status
24728
- };
24729
- this.callbacks.onSuccess(response, stats, context, xhr);
24746
+ }
24747
+
24748
+ // Handle bad status or nullish response
24749
+ const retryConfig = config.loadPolicy.errorRetry;
24750
+ const retryCount = stats.retry;
24751
+ // if max nb of retries reached or if http status between 400 and 499 (such error cannot be recovered, retrying is useless), return error
24752
+ const response = {
24753
+ url: context.url,
24754
+ data: undefined,
24755
+ code: status
24756
+ };
24757
+ if (shouldRetry(retryConfig, retryCount, false, response)) {
24758
+ this.retry(retryConfig);
24730
24759
  } else {
24731
- const retryConfig = config.loadPolicy.errorRetry;
24732
- const retryCount = stats.retry;
24733
- // if max nb of retries reached or if http status between 400 and 499 (such error cannot be recovered, retrying is useless), return error
24734
- const response = {
24735
- url: context.url,
24736
- data: undefined,
24737
- code: status
24738
- };
24739
- if (shouldRetry(retryConfig, retryCount, false, response)) {
24740
- this.retry(retryConfig);
24741
- } else {
24742
- logger.error(`${status} while loading ${context.url}`);
24743
- this.callbacks.onError({
24744
- code: status,
24745
- text: xhr.statusText
24746
- }, context, xhr, stats);
24747
- }
24760
+ logger.error(`${status} while loading ${context.url}`);
24761
+ this.callbacks.onError({
24762
+ code: status,
24763
+ text: xhr.statusText
24764
+ }, context, xhr, stats);
24748
24765
  }
24749
24766
  }
24750
24767
  }
@@ -26797,7 +26814,7 @@ class StreamController extends BaseStreamController {
26797
26814
  if (this.altAudio && this.audioOnly) {
26798
26815
  return;
26799
26816
  }
26800
- const level = hls.nextLoadLevel;
26817
+ const level = this.buffering ? hls.nextLoadLevel : hls.loadLevel;
26801
26818
  if (!(levels != null && levels[level])) {
26802
26819
  return;
26803
26820
  }
@@ -26819,6 +26836,9 @@ class StreamController extends BaseStreamController {
26819
26836
  this.state = State.ENDED;
26820
26837
  return;
26821
26838
  }
26839
+ if (!this.buffering) {
26840
+ return;
26841
+ }
26822
26842
 
26823
26843
  // set next load level : this will trigger a playlist load if needed
26824
26844
  if (hls.loadLevel !== level && hls.manualLevel === -1) {
@@ -27781,7 +27801,7 @@ class Hls {
27781
27801
  * Get the video-dev/hls.js package version.
27782
27802
  */
27783
27803
  static get version() {
27784
- return "1.5.17";
27804
+ return "1.5.18";
27785
27805
  }
27786
27806
 
27787
27807
  /**
@@ -28062,9 +28082,13 @@ class Hls {
28062
28082
  startLoad(startPosition = -1) {
28063
28083
  logger.log(`startLoad(${startPosition})`);
28064
28084
  this.started = true;
28065
- this.networkControllers.forEach(controller => {
28066
- controller.startLoad(startPosition);
28067
- });
28085
+ this.resumeBuffering();
28086
+ for (let i = 0; i < this.networkControllers.length; i++) {
28087
+ this.networkControllers[i].startLoad(startPosition);
28088
+ if (!this.started || !this.networkControllers) {
28089
+ break;
28090
+ }
28091
+ }
28068
28092
  }
28069
28093
 
28070
28094
  /**
@@ -28073,32 +28097,35 @@ class Hls {
28073
28097
  stopLoad() {
28074
28098
  logger.log('stopLoad');
28075
28099
  this.started = false;
28076
- this.networkControllers.forEach(controller => {
28077
- controller.stopLoad();
28078
- });
28100
+ for (let i = 0; i < this.networkControllers.length; i++) {
28101
+ this.networkControllers[i].stopLoad();
28102
+ if (this.started || !this.networkControllers) {
28103
+ break;
28104
+ }
28105
+ }
28079
28106
  }
28080
28107
 
28081
28108
  /**
28082
- * Resumes stream controller segment loading if previously started.
28109
+ * Resumes stream controller segment loading after `pauseBuffering` has been called.
28083
28110
  */
28084
28111
  resumeBuffering() {
28085
- if (this.started) {
28086
- this.networkControllers.forEach(controller => {
28087
- if ('fragmentLoader' in controller) {
28088
- controller.startLoad(-1);
28089
- }
28090
- });
28091
- }
28112
+ logger.log(`resume buffering`);
28113
+ this.networkControllers.forEach(controller => {
28114
+ if (controller.resumeBuffering) {
28115
+ controller.resumeBuffering();
28116
+ }
28117
+ });
28092
28118
  }
28093
28119
 
28094
28120
  /**
28095
- * Stops stream controller segment loading without changing 'started' state like stopLoad().
28121
+ * Prevents stream controller from loading new segments until `resumeBuffering` is called.
28096
28122
  * This allows for media buffering to be paused without interupting playlist loading.
28097
28123
  */
28098
28124
  pauseBuffering() {
28125
+ logger.log(`pause buffering`);
28099
28126
  this.networkControllers.forEach(controller => {
28100
- if ('fragmentLoader' in controller) {
28101
- controller.stopLoad();
28127
+ if (controller.pauseBuffering) {
28128
+ controller.pauseBuffering();
28102
28129
  }
28103
28130
  });
28104
28131
  }