hls.js 1.6.0-beta.1.0.canary.10764 → 1.6.0-beta.1.0.canary.10765

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/package.json CHANGED
@@ -130,5 +130,5 @@
130
130
  "url-toolkit": "2.2.5",
131
131
  "wrangler": "3.87.0"
132
132
  },
133
- "version": "1.6.0-beta.1.0.canary.10764"
133
+ "version": "1.6.0-beta.1.0.canary.10765"
134
134
  }
@@ -795,14 +795,15 @@ class AbrController extends Logger implements AbrComponentAPI {
795
795
  | undefined;
796
796
  if (
797
797
  typeof mediaCapabilities?.decodingInfo === 'function' &&
798
- requiresMediaCapabilitiesDecodingInfo(
798
+ (requiresMediaCapabilitiesDecodingInfo(
799
799
  levelInfo,
800
800
  audioTracksByGroup,
801
801
  currentVideoRange,
802
802
  currentFrameRate,
803
803
  currentBw,
804
804
  audioPreference,
805
- )
805
+ ) ||
806
+ levelInfo.videoCodec?.substring(0, 4) === 'hvc1') // Force media capabilities check for HEVC to avoid failure on Windows
806
807
  ) {
807
808
  levelInfo.supportedPromise = getMediaDecodingInfoPromise(
808
809
  levelInfo,
@@ -831,6 +832,9 @@ class AbrController extends Logger implements AbrComponentAPI {
831
832
  if (index > -1 && levels.length > 1) {
832
833
  this.log(`Removing unsupported level ${index}`);
833
834
  this.hls.removeLevel(index);
835
+ if (this.hls.loadLevel === -1) {
836
+ this.hls.nextLoadLevel = 0;
837
+ }
834
838
  }
835
839
  }
836
840
  });
@@ -434,6 +434,7 @@ class AudioTrackController extends BasePlaylistController {
434
434
  id,
435
435
  groupId,
436
436
  deliveryDirectives: hlsUrlParameters || null,
437
+ track: audioTrack,
437
438
  });
438
439
  }
439
440
  }
@@ -601,7 +601,7 @@ export default class LevelController extends BasePlaylistController {
601
601
 
602
602
  protected onLevelLoaded(event: Events.LEVEL_LOADED, data: LevelLoadedData) {
603
603
  const { level, details } = data;
604
- const curLevel = this._levels[level];
604
+ const curLevel = data.levelInfo;
605
605
 
606
606
  if (!curLevel) {
607
607
  this.warn(`Invalid level index ${level}`);
@@ -612,7 +612,7 @@ export default class LevelController extends BasePlaylistController {
612
612
  }
613
613
 
614
614
  // only process level loaded events matching with expected level
615
- if (level === this.currentLevelIndex) {
615
+ if (curLevel === this.currentLevel) {
616
616
  // reset level load error counter on successful level loaded only if there is no issues with fragments
617
617
  if (curLevel.fragmentError === 0) {
618
618
  curLevel.loadError = 0;
@@ -665,6 +665,7 @@ export default class LevelController extends BasePlaylistController {
665
665
  this.hls.trigger(Events.LEVEL_LOADING, {
666
666
  url,
667
667
  level: currentLevelIndex,
668
+ levelInfo: currentLevel,
668
669
  pathwayId: currentLevel.attrs['PATHWAY-ID'],
669
670
  id: 0, // Deprecated Level urlId
670
671
  deliveryDirectives: hlsUrlParameters || null,
@@ -646,7 +646,7 @@ export default class StreamController
646
646
  if (!levels || this.state !== State.IDLE) {
647
647
  return;
648
648
  }
649
- const level = levels[data.level];
649
+ const level = data.levelInfo;
650
650
  if (
651
651
  !level.details ||
652
652
  (level.details.live && this.levelLastLoaded !== level) ||
@@ -674,7 +674,7 @@ export default class StreamController
674
674
  }, cc [${newDetails.startCC}, ${newDetails.endCC}] duration:${duration}`,
675
675
  );
676
676
 
677
- const curLevel = levels[newLevelId];
677
+ const curLevel = data.levelInfo;
678
678
  const fragCurrent = this.fragCurrent;
679
679
  if (
680
680
  fragCurrent &&
@@ -453,6 +453,7 @@ class SubtitleTrackController extends BasePlaylistController {
453
453
  id,
454
454
  groupId,
455
455
  deliveryDirectives: hlsUrlParameters || null,
456
+ track: currentTrack,
456
457
  });
457
458
  }
458
459
  }
@@ -18,10 +18,11 @@ import type { NetworkComponentAPI } from '../types/component-api';
18
18
  import type {
19
19
  ErrorData,
20
20
  LevelLoadingData,
21
+ LevelsUpdatedData,
21
22
  ManifestLoadingData,
22
23
  TrackLoadingData,
23
24
  } from '../types/events';
24
- import type { LevelParsed, VariableMap } from '../types/level';
25
+ import type { Level, LevelParsed, VariableMap } from '../types/level';
25
26
  import type {
26
27
  Loader,
27
28
  LoaderCallbacks,
@@ -31,7 +32,7 @@ import type {
31
32
  LoaderStats,
32
33
  PlaylistLoaderContext,
33
34
  } from '../types/loader';
34
- import type { MediaAttributes } from '../types/media-playlist';
35
+ import type { MediaAttributes, MediaPlaylist } from '../types/media-playlist';
35
36
 
36
37
  function mapContextToLevelType(
37
38
  context: PlaylistLoaderContext,
@@ -86,6 +87,7 @@ class PlaylistLoader implements NetworkComponentAPI {
86
87
  hls.on(Events.LEVEL_LOADING, this.onLevelLoading, this);
87
88
  hls.on(Events.AUDIO_TRACK_LOADING, this.onAudioTrackLoading, this);
88
89
  hls.on(Events.SUBTITLE_TRACK_LOADING, this.onSubtitleTrackLoading, this);
90
+ hls.on(Events.LEVELS_UPDATED, this.onLevelsUpdated, this);
89
91
  }
90
92
 
91
93
  private unregisterListeners() {
@@ -94,6 +96,7 @@ class PlaylistLoader implements NetworkComponentAPI {
94
96
  hls.off(Events.LEVEL_LOADING, this.onLevelLoading, this);
95
97
  hls.off(Events.AUDIO_TRACK_LOADING, this.onAudioTrackLoading, this);
96
98
  hls.off(Events.SUBTITLE_TRACK_LOADING, this.onSubtitleTrackLoading, this);
99
+ hls.off(Events.LEVELS_UPDATED, this.onLevelsUpdated, this);
97
100
  }
98
101
 
99
102
  /**
@@ -118,7 +121,7 @@ class PlaylistLoader implements NetworkComponentAPI {
118
121
  return this.loaders[context.type];
119
122
  }
120
123
 
121
- private resetInternalLoader(contextType): void {
124
+ private resetInternalLoader(contextType: PlaylistContextType): void {
122
125
  if (this.loaders[contextType]) {
123
126
  delete this.loaders[contextType];
124
127
  }
@@ -134,7 +137,7 @@ class PlaylistLoader implements NetworkComponentAPI {
134
137
  loader.destroy();
135
138
  }
136
139
 
137
- this.resetInternalLoader(contextType);
140
+ this.resetInternalLoader(contextType as PlaylistContextType);
138
141
  }
139
142
  }
140
143
 
@@ -157,11 +160,12 @@ class PlaylistLoader implements NetworkComponentAPI {
157
160
  type: PlaylistContextType.MANIFEST,
158
161
  url,
159
162
  deliveryDirectives: null,
163
+ levelOrTrack: null,
160
164
  });
161
165
  }
162
166
 
163
167
  private onLevelLoading(event: Events.LEVEL_LOADING, data: LevelLoadingData) {
164
- const { id, level, pathwayId, url, deliveryDirectives } = data;
168
+ const { id, level, pathwayId, url, deliveryDirectives, levelInfo } = data;
165
169
  this.load({
166
170
  id,
167
171
  level,
@@ -170,6 +174,7 @@ class PlaylistLoader implements NetworkComponentAPI {
170
174
  type: PlaylistContextType.LEVEL,
171
175
  url,
172
176
  deliveryDirectives,
177
+ levelOrTrack: levelInfo,
173
178
  });
174
179
  }
175
180
 
@@ -177,7 +182,7 @@ class PlaylistLoader implements NetworkComponentAPI {
177
182
  event: Events.AUDIO_TRACK_LOADING,
178
183
  data: TrackLoadingData,
179
184
  ) {
180
- const { id, groupId, url, deliveryDirectives } = data;
185
+ const { id, groupId, url, deliveryDirectives, track } = data;
181
186
  this.load({
182
187
  id,
183
188
  groupId,
@@ -186,6 +191,7 @@ class PlaylistLoader implements NetworkComponentAPI {
186
191
  type: PlaylistContextType.AUDIO_TRACK,
187
192
  url,
188
193
  deliveryDirectives,
194
+ levelOrTrack: track,
189
195
  });
190
196
  }
191
197
 
@@ -193,7 +199,7 @@ class PlaylistLoader implements NetworkComponentAPI {
193
199
  event: Events.SUBTITLE_TRACK_LOADING,
194
200
  data: TrackLoadingData,
195
201
  ) {
196
- const { id, groupId, url, deliveryDirectives } = data;
202
+ const { id, groupId, url, deliveryDirectives, track } = data;
197
203
  this.load({
198
204
  id,
199
205
  groupId,
@@ -202,9 +208,30 @@ class PlaylistLoader implements NetworkComponentAPI {
202
208
  type: PlaylistContextType.SUBTITLE_TRACK,
203
209
  url,
204
210
  deliveryDirectives,
211
+ levelOrTrack: track,
205
212
  });
206
213
  }
207
214
 
215
+ private onLevelsUpdated(
216
+ event: Events.LEVELS_UPDATED,
217
+ data: LevelsUpdatedData,
218
+ ) {
219
+ // abort and delete loader of removed levels
220
+ const loader = this.loaders[PlaylistContextType.LEVEL];
221
+ if (loader) {
222
+ const context = loader.context;
223
+ if (
224
+ context &&
225
+ !data.levels.some(
226
+ (lvl) => lvl === (context as PlaylistLoaderContext).levelOrTrack,
227
+ )
228
+ ) {
229
+ loader.abort();
230
+ delete this.loaders[PlaylistContextType.LEVEL];
231
+ }
232
+ }
233
+ }
234
+
208
235
  private load(context: PlaylistLoaderContext): void {
209
236
  const config = this.hls.config;
210
237
 
@@ -217,7 +244,7 @@ class PlaylistLoader implements NetworkComponentAPI {
217
244
  if (
218
245
  loaderContext &&
219
246
  loaderContext.url === context.url &&
220
- loaderContext.level === context.level
247
+ loaderContext.levelOrTrack === context.levelOrTrack
221
248
  ) {
222
249
  // same URL can't overlap
223
250
  this.hls.logger.trace('[playlist-loader]: playlist request ongoing');
@@ -680,6 +707,7 @@ class PlaylistLoader implements NetworkComponentAPI {
680
707
  case PlaylistContextType.LEVEL:
681
708
  hls.trigger(Events.LEVEL_LOADED, {
682
709
  details: levelDetails,
710
+ levelInfo: (context.levelOrTrack as Level) || hls.levels[0],
683
711
  level: levelIndex || 0,
684
712
  id: id || 0,
685
713
  stats,
@@ -690,6 +718,7 @@ class PlaylistLoader implements NetworkComponentAPI {
690
718
  case PlaylistContextType.AUDIO_TRACK:
691
719
  hls.trigger(Events.AUDIO_TRACK_LOADED, {
692
720
  details: levelDetails,
721
+ track: context.levelOrTrack as MediaPlaylist,
693
722
  id: id || 0,
694
723
  groupId: groupId || '',
695
724
  stats,
@@ -700,6 +729,7 @@ class PlaylistLoader implements NetworkComponentAPI {
700
729
  case PlaylistContextType.SUBTITLE_TRACK:
701
730
  hls.trigger(Events.SUBTITLE_TRACK_LOADED, {
702
731
  details: levelDetails,
732
+ track: context.levelOrTrack as MediaPlaylist,
703
733
  id: id || 0,
704
734
  groupId: groupId || '',
705
735
  stats,
@@ -188,6 +188,7 @@ export interface LevelSwitchedData {
188
188
  export interface TrackLoadingData {
189
189
  id: number;
190
190
  groupId: string;
191
+ track: MediaPlaylist;
191
192
  url: string;
192
193
  deliveryDirectives: HlsUrlParameters | null;
193
194
  }
@@ -195,6 +196,7 @@ export interface TrackLoadingData {
195
196
  export interface LevelLoadingData {
196
197
  id: number;
197
198
  level: number;
199
+ levelInfo: Level;
198
200
  pathwayId: string | undefined;
199
201
  url: string;
200
202
  deliveryDirectives: HlsUrlParameters | null;
@@ -207,12 +209,14 @@ export interface TrackLoadedData {
207
209
  networkDetails: any;
208
210
  stats: LoaderStats;
209
211
  deliveryDirectives: HlsUrlParameters | null;
212
+ track: MediaPlaylist;
210
213
  }
211
214
 
212
215
  export interface LevelLoadedData {
213
216
  details: LevelDetails;
214
217
  id: number;
215
218
  level: number;
219
+ levelInfo: Level;
216
220
  networkDetails: any;
217
221
  stats: LoaderStats;
218
222
  deliveryDirectives: HlsUrlParameters | null;
@@ -1,5 +1,6 @@
1
1
  import type { LoaderConfig } from '../config';
2
- import type { HlsUrlParameters } from './level';
2
+ import type { HlsUrlParameters, Level } from './level';
3
+ import type { MediaPlaylist } from './media-playlist';
3
4
  import type { Fragment } from '../loader/fragment';
4
5
  import type { Part } from '../loader/fragment';
5
6
  import type { KeyLoaderInfo } from '../loader/key-loader';
@@ -191,4 +192,6 @@ export interface PlaylistLoaderContext extends LoaderContext {
191
192
  levelDetails?: LevelDetails;
192
193
  // Blocking playlist request delivery directives (or null id none were added to playlist url
193
194
  deliveryDirectives: HlsUrlParameters | null;
195
+ // Reference to level or track object in hls.levels, hls.allAudioTracks, or hls.allSubtitleTracks (null when loading MVP)
196
+ levelOrTrack: Level | MediaPlaylist | null;
194
197
  }