Skip to content

Commit

Permalink
Do not group levels with different audio or subtitle options in their…
Browse files Browse the repository at this point in the history
… respective groups

#5302
  • Loading branch information
robwalch committed Sep 26, 2023
1 parent 8b0c47d commit 02859ca
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 11 deletions.
1 change: 0 additions & 1 deletion src/controller/audio-stream-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,6 @@ class AudioStreamController
event: Events.AUDIO_TRACKS_UPDATED,
{ audioTracks }: AudioTracksUpdatedData,
) {
this.resetTransmuxer();
this.levels = audioTracks.map((mediaPlaylist) => new Level(mediaPlaylist));
}

Expand Down
15 changes: 9 additions & 6 deletions src/controller/audio-track-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,19 +195,22 @@ class AudioTrackController extends BasePlaylistController {
// stopping live reloading timer if any
this.clearTimer();

this.selectDefaultTrack = false;
const lastTrack = this.currentTrack;
tracks[this.trackId];
const track = tracks[newId];
const trackLoaded = track.details && !track.details.live;
if (newId === this.trackId && track === lastTrack && trackLoaded) {
return;
}
const { groupId, name } = track;
this.log(
`Switching to audio-track ${newId} "${name}" lang:${track.lang} group:${groupId}`,
);
this.trackId = newId;
this.currentTrack = track;
this.selectDefaultTrack = false;
this.hls.trigger(Events.AUDIO_TRACK_SWITCHING, { ...track });
// Do not reload track unless live
if (track.details && !track.details.live) {
if (trackLoaded) {
return;
}
const hlsUrlParameters = this.switchParams(track.url, lastTrack?.details);
Expand Down Expand Up @@ -266,9 +269,9 @@ class AudioTrackController extends BasePlaylistController {
}

protected loadPlaylist(hlsUrlParameters?: HlsUrlParameters): void {
super.loadPlaylist();
const audioTrack = this.tracksInGroup[this.trackId];
if (this.shouldLoadPlaylist(audioTrack)) {
const audioTrack = this.currentTrack;
if (this.shouldLoadPlaylist(audioTrack) && audioTrack) {
super.loadPlaylist();
const id = audioTrack.id;
const groupId = audioTrack.groupId as string;
let url = audioTrack.url;
Expand Down
24 changes: 22 additions & 2 deletions src/controller/level-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
import BasePlaylistController from './base-playlist-controller';
import { PlaylistContextType, PlaylistLevelType } from '../types/loader';
import ContentSteeringController from './content-steering-controller';
import { getSelectionOptionsByGroup } from '../utils/rendition-helper';
import { reassignFragmentLevelIndexes } from '../utils/level-helper';
import { hlsDefaultConfig } from '../config';
import type Hls from '../hls';
Expand Down Expand Up @@ -123,6 +124,12 @@ export default class LevelController extends BasePlaylistController {
const levelSet: { [key: string]: Level } = {};
let levelFromSet: Level;

const { audioTracks, subtitles } = data;
const audioOptionsByGroup = getSelectionOptionsByGroup(audioTracks);
const subtitleOptionsByGroup = subtitles
? getSelectionOptionsByGroup(subtitles)
: null;

// regroup redundant levels together
data.levels.forEach((levelParsed: LevelParsed) => {
const attributes = levelParsed.attrs;
Expand Down Expand Up @@ -154,9 +161,22 @@ export default class LevelController extends BasePlaylistController {
const contentSteeringPrefix = __USE_CONTENT_STEERING__
? `${PATHWAY || '.'}-`
: '';
const levelKey = `${contentSteeringPrefix}${levelParsed.bitrate}-${RESOLUTION}-${FRAMERATE}-${CODECS}`;
levelFromSet = levelSet[levelKey];
let levelKey = `${contentSteeringPrefix}${levelParsed.bitrate}-${RESOLUTION}-${FRAMERATE}-${CODECS}`;

// Do not group levels with different audio or subtitle options in their respective groups (#5302)
const audioOptions = AUDIO ? audioOptionsByGroup[AUDIO] : null;
if (audioOptions) {
levelKey += `-${audioOptions.join(',')}`;
}
const subtitleOptions =
SUBTITLES && subtitleOptionsByGroup
? subtitleOptionsByGroup[SUBTITLES]
: null;
if (subtitleOptions) {
levelKey += `-${subtitleOptions.join(',')}`;
}

levelFromSet = levelSet[levelKey];
if (!levelFromSet) {
levelFromSet = new Level(levelParsed);
levelSet[levelKey] = levelFromSet;
Expand Down
3 changes: 1 addition & 2 deletions src/hls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -494,8 +494,7 @@ export default class Hls implements HlsEventEmitter {
*/
set currentLevel(newLevel: number) {
logger.log(`set currentLevel:${newLevel}`);
this.loadLevel = newLevel;
this.abrController.clearTimer();
this.levelController.manualLevel = newLevel;
this.streamController.immediateLevelSwitch();
}

Expand Down
17 changes: 17 additions & 0 deletions src/utils/rendition-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,23 @@ export function getAudioTracksByGroup(allAudioTracks: MediaPlaylist[]) {
);
}

export function getSelectionOptionsByGroup(
tracks: MediaPlaylist[],
): Record<string, string[]> {
return tracks.reduce((options, track) => {
const characteristics = track.attrs.CHARACTERISTICS;
const trackKey = `${track.name}-${track.lang}-${
characteristics ? '-' + characteristics : ''
}`;
let option = options[track.groupId];
if (!option) {
options[track.groupId] = option = [];
}
option.push(trackKey);
return options;
}, {});
}

export function getCodecTiers(
levels: Level[],
audioTracksByGroup: AudioTracksByGroup,
Expand Down
3 changes: 3 additions & 0 deletions tests/unit/controller/level-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ http://bar.example.com/audio-only/prog_index.m3u8`,
expect(parsedLevels).to.have.lengthOf(6, 'MANIFEST_LOADED levels');
levelController.onManifestLoaded(Events.MANIFEST_LOADED, {
levels: parsedLevels,
audioTracks: [],
});
const {
name,
Expand Down Expand Up @@ -657,6 +658,7 @@ http://bar.example.com/md/prog_index.m3u8`,
expect(parsedLevels).to.have.lengthOf(4, 'MANIFEST_LOADED levels');
levelController.onManifestLoaded(Events.MANIFEST_LOADED, {
levels: parsedLevels,
audioTracks: [],
});
const {
name,
Expand Down Expand Up @@ -716,6 +718,7 @@ http://bar.example.com/md/prog_index.m3u8`;
expect(parsedSubs).to.be.undefined;
levelController.onManifestLoaded(Events.MANIFEST_LOADED, {
levels: parsedLevels,
audioTracks: parsedAudio,
});
const {
name,
Expand Down

0 comments on commit 02859ca

Please sign in to comment.