hls.js 1.5.14-0.canary.10427 → 1.5.14-0.canary.10431

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.
@@ -442,7 +442,9 @@ export default class BaseStreamController
442
442
  }
443
443
 
444
444
  if ('payload' in data) {
445
- this.log(`Loaded fragment ${frag.sn} of level ${frag.level}`);
445
+ this.log(
446
+ `Loaded ${frag.type} sn: ${frag.sn} of ${this.playlistLabel()} ${frag.level}`,
447
+ );
446
448
  this.hls.trigger(Events.FRAG_LOADED, data);
447
449
  }
448
450
 
@@ -629,11 +631,7 @@ export default class BaseStreamController
629
631
  this.log(
630
632
  `Buffered ${frag.type} sn: ${frag.sn}${
631
633
  part ? ' part: ' + part.index : ''
632
- } of ${
633
- this.playlistType === PlaylistLevelType.MAIN ? 'level' : 'track'
634
- } ${frag.level} (frag:[${(frag.startPTS ?? NaN).toFixed(3)}-${(
635
- frag.endPTS ?? NaN
636
- ).toFixed(3)}] > buffer:${
634
+ } of ${this.fragInfo(frag)} > buffer:${
637
635
  media
638
636
  ? TimeRanges.toString(BufferHelper.getBuffered(media))
639
637
  : '(detached)'
@@ -718,9 +716,7 @@ export default class BaseStreamController
718
716
  let keyLoadingPromise: Promise<KeyLoadedData | void> | null = null;
719
717
  if (frag.encrypted && !frag.decryptdata?.key) {
720
718
  this.log(
721
- `Loading key for ${frag.sn} of [${details.startSN}-${details.endSN}], ${
722
- this.playlistType === PlaylistLevelType.MAIN ? 'level' : 'track'
723
- } ${frag.level}`,
719
+ `Loading key for ${frag.sn} of [${details.startSN}-${details.endSN}], ${this.playlistLabel()} ${frag.level}`,
724
720
  );
725
721
  this.state = State.KEY_LOADING;
726
722
  this.fragCurrent = frag;
@@ -773,9 +769,7 @@ export default class BaseStreamController
773
769
  frag.cc
774
770
  } of playlist [${details.startSN}-${
775
771
  details.endSN
776
- }] parts [0-${partIndex}-${partList.length - 1}] ${
777
- this.playlistType === PlaylistLevelType.MAIN ? 'level' : 'track'
778
- }: ${frag.level}, target: ${parseFloat(
772
+ }] parts [0-${partIndex}-${partList.length - 1}] ${this.playlistLabel()}: ${frag.level}, target: ${parseFloat(
779
773
  targetBufferTime.toFixed(3),
780
774
  )}`,
781
775
  );
@@ -843,10 +837,8 @@ export default class BaseStreamController
843
837
  }
844
838
 
845
839
  this.log(
846
- `Loading fragment ${frag.sn} cc: ${frag.cc} ${
847
- details ? 'of [' + details.startSN + '-' + details.endSN + '] ' : ''
848
- }${this.playlistType === PlaylistLevelType.MAIN ? 'level' : 'track'}: ${
849
- frag.level
840
+ `Loading ${frag.type} sn: ${frag.sn} of ${this.fragInfo(frag, false)}) cc: ${frag.cc} ${
841
+ details ? '[' + details.startSN + '-' + details.endSN + ']' : ''
850
842
  }, target: ${parseFloat(targetBufferTime.toFixed(3))}`,
851
843
  );
852
844
  // Don't update nextLoadPosition for fragments which are not buffered
@@ -1920,9 +1912,24 @@ export default class BaseStreamController
1920
1912
  // For this error fallthrough. Marking parsed will allow advancing to next fragment.
1921
1913
  }
1922
1914
  this.state = State.PARSED;
1915
+ this.log(
1916
+ `Parsed ${frag.type} sn: ${frag.sn}${
1917
+ part ? ' part: ' + part.index : ''
1918
+ } of ${this.fragInfo(frag)})`,
1919
+ );
1923
1920
  this.hls.trigger(Events.FRAG_PARSED, { frag, part });
1924
1921
  }
1925
1922
 
1923
+ private playlistLabel() {
1924
+ return this.playlistType === PlaylistLevelType.MAIN ? 'level' : 'track';
1925
+ }
1926
+
1927
+ private fragInfo(frag: Fragment, pts: boolean = true): string {
1928
+ return `${this.playlistLabel()} ${frag.level} (frag:[${((pts ? frag.startPTS : frag.start) ?? NaN).toFixed(3)}-${(
1929
+ (pts ? frag.endPTS : frag.end) ?? NaN
1930
+ ).toFixed(3)}]`;
1931
+ }
1932
+
1926
1933
  protected resetTransmuxer() {
1927
1934
  if (this.transmuxer) {
1928
1935
  this.transmuxer.destroy();
@@ -17,14 +17,13 @@ export function findFirstFragWithCC(
17
17
  }
18
18
 
19
19
  export function shouldAlignOnDiscontinuities(
20
- lastFrag: Fragment | null,
21
- switchDetails: LevelDetails | undefined,
20
+ refDetails: LevelDetails | undefined,
22
21
  details: LevelDetails,
23
- ): switchDetails is LevelDetails & boolean {
24
- if (switchDetails) {
22
+ ): refDetails is LevelDetails & boolean {
23
+ if (refDetails) {
25
24
  if (
26
- details.endCC > details.startCC ||
27
- (lastFrag && lastFrag.cc < details.startCC)
25
+ details.startCC < refDetails.endCC &&
26
+ details.endCC > refDetails.startCC
28
27
  ) {
29
28
  return true;
30
29
  }
@@ -32,29 +31,6 @@ export function shouldAlignOnDiscontinuities(
32
31
  return false;
33
32
  }
34
33
 
35
- // Find the first frag in the previous level which matches the CC of the first frag of the new level
36
- export function findDiscontinuousReferenceFrag(
37
- prevDetails: LevelDetails,
38
- curDetails: LevelDetails,
39
- ) {
40
- const prevFrags = prevDetails.fragments;
41
- const curFrags = curDetails.fragments;
42
-
43
- if (!curFrags.length || !prevFrags.length) {
44
- logger.log('No fragments to align');
45
- return;
46
- }
47
-
48
- const prevStartFrag = findFirstFragWithCC(prevFrags, curFrags[0].cc);
49
-
50
- if (!prevStartFrag || (prevStartFrag && !prevStartFrag.startPTS)) {
51
- logger.log('No frag in previous level to align on');
52
- return;
53
- }
54
-
55
- return prevStartFrag;
56
- }
57
-
58
34
  function adjustFragmentStart(frag: Fragment, sliding: number) {
59
35
  if (frag) {
60
36
  const start = frag.start + sliding;
@@ -94,7 +70,7 @@ export function alignStream(
94
70
  if (!switchDetails) {
95
71
  return;
96
72
  }
97
- alignDiscontinuities(lastFrag, details, switchDetails);
73
+ alignDiscontinuities(details, switchDetails);
98
74
  if (!details.alignedSliding && switchDetails) {
99
75
  // If the PTS wasn't figured out via discontinuity sequence that means there was no CC increase within the level.
100
76
  // Aligning via Program Date Time should therefore be reliable, since PDT should be the same within the same
@@ -110,29 +86,27 @@ export function alignStream(
110
86
  }
111
87
 
112
88
  /**
113
- * Computes the PTS if a new level's fragments using the PTS of a fragment in the last level which shares the same
114
- * discontinuity sequence.
115
- * @param lastFrag - The last Fragment which shares the same discontinuity sequence
89
+ * Ajust the start of fragments in `details` by the difference in time between fragments of the latest
90
+ * shared discontinuity sequence change.
116
91
  * @param lastLevel - The details of the last loaded level
117
92
  * @param details - The details of the new level
118
93
  */
119
- function alignDiscontinuities(
120
- lastFrag: Fragment | null,
94
+ export function alignDiscontinuities(
121
95
  details: LevelDetails,
122
- switchDetails: LevelDetails | undefined,
96
+ refDetails: LevelDetails | undefined,
123
97
  ) {
124
- if (shouldAlignOnDiscontinuities(lastFrag, switchDetails, details)) {
125
- const referenceFrag = findDiscontinuousReferenceFrag(
126
- switchDetails,
127
- details,
128
- );
129
- if (referenceFrag && Number.isFinite(referenceFrag.start)) {
130
- logger.log(
131
- `Adjusting PTS using last level due to CC increase within current level ${details.url}`,
132
- );
133
- adjustSlidingStart(referenceFrag.start, details);
134
- }
98
+ if (!shouldAlignOnDiscontinuities(refDetails, details)) {
99
+ return;
135
100
  }
101
+ const targetCC = Math.min(refDetails.endCC, details.endCC);
102
+ const refFrag = findFirstFragWithCC(refDetails.fragments, targetCC);
103
+ const frag = findFirstFragWithCC(details.fragments, targetCC);
104
+ if (!refFrag || !frag) {
105
+ return;
106
+ }
107
+ logger.log(`Aligning playlist at start of dicontinuity sequence ${targetCC}`);
108
+ const delta = refFrag.start - frag.start;
109
+ adjustSlidingStart(delta, details);
136
110
  }
137
111
 
138
112
  /**