diff --git a/api-extractor/report/hls.js.api.md b/api-extractor/report/hls.js.api.md index 0ea2ac7acf9..fa7a9884fba 100644 --- a/api-extractor/report/hls.js.api.md +++ b/api-extractor/report/hls.js.api.md @@ -1215,6 +1215,8 @@ export enum Events { // (undocumented) MANIFEST_PARSED = "hlsManifestParsed", // (undocumented) + MAX_AUTO_LEVEL_UPDATED = "hlsMaxAutoLevelUpdated", + // (undocumented) MEDIA_ATTACHED = "hlsMediaAttached", // (undocumented) MEDIA_ATTACHING = "hlsMediaAttaching", @@ -1802,6 +1804,10 @@ export interface HlsListeners { [Events.MANIFEST_LOADING]: (event: Events.MANIFEST_LOADING, data: ManifestLoadingData) => void; // (undocumented) [Events.MANIFEST_PARSED]: (event: Events.MANIFEST_PARSED, data: ManifestParsedData) => void; + // Warning: (ae-forgotten-export) The symbol "MaxAutoLevelUpdatedData" needs to be exported by the entry point hls.d.ts + // + // (undocumented) + [Events.MAX_AUTO_LEVEL_UPDATED]: (event: Events.MAX_AUTO_LEVEL_UPDATED, data: MaxAutoLevelUpdatedData) => void; // (undocumented) [Events.MEDIA_ATTACHED]: (event: Events.MEDIA_ATTACHED, data: MediaAttachedData) => void; // (undocumented) diff --git a/src/controller/level-controller.ts b/src/controller/level-controller.ts index 83919b71398..e665cf549c7 100644 --- a/src/controller/level-controller.ts +++ b/src/controller/level-controller.ts @@ -40,6 +40,7 @@ let chromeOrFirefox: boolean; export default class LevelController extends BasePlaylistController { private _levels: Level[] = []; private _firstLevel: number = -1; + private _maxAutoLevel: number = -1; private _startLevel?: number; private currentLevel: Level | null = null; private currentLevelIndex: number = -1; @@ -104,6 +105,7 @@ export default class LevelController extends BasePlaylistController { this.currentLevelIndex = -1; this.currentLevel = null; this._levels = []; + this._maxAutoLevel = -1; } private onManifestLoading( @@ -680,6 +682,20 @@ export default class LevelController extends BasePlaylistController { ) { this._levels = levels; } + + public checkMaxAutoUpdated() { + const { autoLevelCapping, maxAutoLevel, maxHdcpLevel } = this.hls; + if (this._maxAutoLevel !== maxAutoLevel) { + this._maxAutoLevel = maxAutoLevel; + this.hls.trigger(Events.MAX_AUTO_LEVEL_UPDATED, { + autoLevelCapping, + levels: this.levels, + maxAutoLevel, + minAutoLevel: this.hls.minAutoLevel, + maxHdcpLevel, + }); + } + } } function assignTrackIdsByGroup(tracks: MediaPlaylist[]): void { diff --git a/src/events.ts b/src/events.ts index 45367bab18e..8196cea76f8 100644 --- a/src/events.ts +++ b/src/events.ts @@ -35,6 +35,7 @@ import { BufferFlushingData, BufferEOSData, LevelSwitchingData, + MaxAutoLevelUpdatedData, FPSDropLevelCappingData, FPSDropData, BufferCreatedData, @@ -151,6 +152,8 @@ export enum Events { FPS_DROP = 'hlsFpsDrop', // triggered when FPS drop triggers auto level capping - data: { level, droppedLevel } FPS_DROP_LEVEL_CAPPING = 'hlsFpsDropLevelCapping', + // triggered when maxAutoLevel changes - data { autoLevelCapping, levels, maxAutoLevel, minAutoLevel, maxHdcpLevel } + MAX_AUTO_LEVEL_UPDATED = 'hlsMaxAutoLevelUpdated', // Identifier for an error event - data: { type : error type, details : error details, fatal : if true, hls.js cannot/will not try to recover, if false, hls.js will try to recover,other error specific data } ERROR = 'hlsError', // fired when hls.js instance starts destroying. Different from MEDIA_DETACHED as one could want to detach and reattach a media to the instance of hls.js to handle mid-rolls for example - data: { } @@ -349,6 +352,10 @@ export interface HlsListeners { event: Events.FPS_DROP_LEVEL_CAPPING, data: FPSDropLevelCappingData, ) => void; + [Events.MAX_AUTO_LEVEL_UPDATED]: ( + event: Events.MAX_AUTO_LEVEL_UPDATED, + data: MaxAutoLevelUpdatedData, + ) => void; [Events.ERROR]: (event: Events.ERROR, data: ErrorData) => void; [Events.DESTROYING]: (event: Events.DESTROYING) => void; [Events.KEY_LOADING]: ( diff --git a/src/hls.ts b/src/hls.ts index 0f99328c5ab..f2749b93104 100644 --- a/src/hls.ts +++ b/src/hls.ts @@ -53,7 +53,7 @@ export default class Hls implements HlsEventEmitter { private networkControllers: NetworkComponentAPI[]; private started: boolean = false; private _emitter: HlsEventEmitter = new EventEmitter(); - private _autoLevelCapping: number; + private _autoLevelCapping: number = -1; private _maxHdcpLevel: HdcpLevel = null; private abrController: AbrController; private bufferController: BufferController; @@ -122,8 +122,6 @@ export default class Hls implements HlsEventEmitter { const config = (this.config = mergeConfig(Hls.DefaultConfig, userConfig)); this.userConfig = userConfig; - this._autoLevelCapping = -1; - if (config.progressive) { enableStreamingMode(config); } @@ -383,6 +381,8 @@ export default class Hls implements HlsEventEmitter { alwaysNormalize: true, }, )); + this._autoLevelCapping = -1; + this._maxHdcpLevel = null; logger.log(`loadSource:${loadingSource}`); if ( media && @@ -665,6 +665,7 @@ export default class Hls implements HlsEventEmitter { if (this._autoLevelCapping !== newLevel) { logger.log(`set autoLevelCapping:${newLevel}`); this._autoLevelCapping = newLevel; + this.levelController.checkMaxAutoUpdated(); } } @@ -673,8 +674,9 @@ export default class Hls implements HlsEventEmitter { } set maxHdcpLevel(value: HdcpLevel) { - if (isHdcpLevel(value)) { + if (isHdcpLevel(value) && this._maxHdcpLevel !== value) { this._maxHdcpLevel = value; + this.levelController.checkMaxAutoUpdated(); } } diff --git a/src/types/events.ts b/src/types/events.ts index bebb30241b3..c38dd595fc9 100644 --- a/src/types/events.ts +++ b/src/types/events.ts @@ -4,6 +4,7 @@ import type { Fragment } from '../loader/fragment'; import type { Part } from '../loader/fragment'; import type { LevelDetails } from '../loader/level-details'; import type { + HdcpLevel, HlsUrlParameters, Level, LevelParsed, @@ -222,6 +223,14 @@ export interface FPSDropLevelCappingData { level: number; } +export interface MaxAutoLevelUpdatedData { + autoLevelCapping: number; + levels: Level[] | null; + maxAutoLevel: number; + minAutoLevel: number; + maxHdcpLevel: HdcpLevel; +} + export interface ErrorData { type: ErrorTypes; details: ErrorDetails;