Skip to content

Commit

Permalink
fix: set audio status on loaders when setting up media groups (#1126)
Browse files Browse the repository at this point in the history
Although the audio status is set in onTrackChanged for media groups, and
the function is called when the media groups are first set up, the track
is not always considered changed. This means that for demuxed audio, the
main loader may still think it should be using its own audio itself,
leading to issues when crossing discontinuities (i.e., the main loader
will cross the discontinuity before waiting for the audio loader to be
ready, leading to audio timestamps that aren't correct).

This change ensures that the audio status is set on setup, regardless of
whether the track is considered changed. Subsequent changes are handled
in onTrackChanged.
  • Loading branch information
gesinger authored May 19, 2021
1 parent a4af004 commit a44f984
Show file tree
Hide file tree
Showing 2 changed files with 151 additions and 3 deletions.
20 changes: 19 additions & 1 deletion src/media-groups.js
Original file line number Diff line number Diff line change
Expand Up @@ -838,7 +838,11 @@ export const setupMediaGroups = (settings) => {
mediaTypes,
masterPlaylistLoader,
tech,
vhs
vhs,
segmentLoaders: {
['AUDIO']: audioSegmentLoader,
main: mainSegmentLoader
}
} = settings;

// setup active group and track getters and change event handlers
Expand All @@ -861,6 +865,20 @@ export const setupMediaGroups = (settings) => {
mediaTypes.AUDIO.tracks[groupId].enabled = true;
mediaTypes.AUDIO.onGroupChanged();
mediaTypes.AUDIO.onTrackChanged();

const activeAudioGroup = mediaTypes.AUDIO.getActiveGroup();

// a similar check for handling setAudio on each loader is run again each time the
// track is changed, but needs to be handled here since the track may not be considered
// changed on the first call to onTrackChanged
if (!activeAudioGroup.playlistLoader) {
// either audio is muxed with video or the stream is audio only
mainSegmentLoader.setAudio(true);
} else {
// audio is demuxed
mainSegmentLoader.setAudio(false);
audioSegmentLoader.setAudio(true);
}
}

masterPlaylistLoader.on('mediachange', () => {
Expand Down
134 changes: 132 additions & 2 deletions test/media-groups.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1058,6 +1058,13 @@ QUnit.module('MediaGroups', function() {
QUnit.module('initialize', {
beforeEach(assert) {
this.mediaTypes = MediaGroups.createMediaTypes();
this.mainLoader = {
setAudio() {}
};
this.audioLoader = {
on() {},
setAudio() {}
};
this.master = {
mediaGroups: {
'AUDIO': {},
Expand All @@ -1076,8 +1083,9 @@ QUnit.module('MediaGroups', function() {
}
},
segmentLoaders: {
AUDIO: { on() {} },
SUBTITLES: { on() {} }
AUDIO: this.audioLoader,
SUBTITLES: { on() {} },
main: this.mainLoader
},
requestOptions: { withCredentials: false, timeout: 10 },
master: this.master,
Expand Down Expand Up @@ -1512,4 +1520,126 @@ QUnit.module('MediaGroups', function() {
'passed the subtitles playlist'
);
});

QUnit.module('setupMediaGroups', {
beforeEach(assert) {
this.mediaTypes = MediaGroups.createMediaTypes();
this.mainLoader = {
audioDisabled_: false,
setAudio(enable) {
this.audioDisabled_ = !enable;
},
on() {},
abort() {},
pause() {}
};
this.audioLoader = {
audioDisabled_: false,
setAudio(enable) {
this.audioDisabled_ = !enable;
},
on() {},
abort() {},
pause() {},
resyncLoader() {}
};
this.master = {
mediaGroups: {
'AUDIO': {},
'SUBTITLES': {},
'CLOSED-CAPTIONS': {}
}
};
this.media = null;
this.settings = {
mode: 'html5',
masterPlaylistLoader: {
master: this.master,
media: () => this.media,
on() {}
},
vhs: {
on() {},
xhr() {}
},
tech: {
addRemoteTextTrack(track) {
return { track };
},
audioTracks() {
return {
addEventListener() {},
addTrack() {}
};
},
remoteTextTracks() {
return {
addEventListener() {}
};
},
clearTracks() {}
},
segmentLoaders: {
AUDIO: this.audioLoader,
SUBTITLES: { on() {} },
main: this.mainLoader
},
requestOptions: { withCredentials: false, timeout: 10 },
master: this.master,
mediaTypes: this.mediaTypes,
blacklistCurrentPlaylist() {},
sourceType: 'hls'
};
}
});

QUnit.test('audio true for main loader if no audio loader', function(assert) {
this.media = {attributes: {}, resolvedUri: 'main.m3u8'};
this.master.playlists = [this.media];

MediaGroups.setupMediaGroups(this.settings);

assert.notOk(
this.mainLoader.audioDisabled_,
'main loader: audio enabled'
);

// audio loader remains unchanged as there's no need for an audio loader
});

QUnit.test('audio false for main loader if audio loader', function(assert) {
this.media = {resolvedUri: 'video/en.m3u8', attributes: {AUDIO: 'aud1'}};
this.master.playlists = [this.media];
this.master.mediaGroups.AUDIO.aud1 = {
en: { default: true, language: 'en', resolvedUri: 'aud1/en.m3u8' }
};

MediaGroups.setupMediaGroups(this.settings);

assert.ok(
this.mainLoader.audioDisabled_,
'main loader: audio disabled'
);
assert.notOk(
this.audioLoader.audioDisabled_,
'audio loader: audio enabled'
);
});

QUnit.test('audio true for main loader if alternate tracks with main stream as URI attribute', function(assert) {
this.media = {resolvedUri: 'en.m3u8', attributes: {AUDIO: 'aud1'}};
this.master.playlists = [this.media];
this.master.mediaGroups.AUDIO.aud1 = {
en: { default: true, language: 'en', resolvedUri: 'en.m3u8' }
};

MediaGroups.setupMediaGroups(this.settings);

assert.notOk(
this.mainLoader.audioDisabled_,
'main loader: audio enabled'
);

// audio loader remains unchanged as there's no need for an audio loader
});
});

0 comments on commit a44f984

Please sign in to comment.