Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Handle audio only audio track change correctly #1100

Merged
merged 23 commits into from
Apr 6, 2021

Conversation

brandonocasey
Copy link
Contributor

@brandonocasey brandonocasey commented Mar 15, 2021

Allows audio only playlists to change audio tracks. IE an audio only playlist can change from english to spanish correctly now. Would be good to get videojs/mpd-parser#123 in with this.

@brandonocasey brandonocasey force-pushed the fix/audio-only-groups branch 2 times, most recently from 161c9cc to b92f5e2 Compare March 17, 2021 19:59
Copy link
Member

@gkatsev gkatsev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dont really have much to add. I think it's worth having @gesinger look over this.

package.json Outdated Show resolved Hide resolved
src/playlist-selectors.js Outdated Show resolved Hide resolved
Comment on lines 175 to 179
// if playlist is audio only, select between currently active audio group playlists.
if (Playlist.isAudioOnly(master)) {
playlists = masterPlaylistController.getAudioTrackPlaylists_();
options.audioOnly = true;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏻

Copy link
Contributor

@gesinger gesinger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably add some audio only related tests.

src/playlist-selectors.js Show resolved Hide resolved
src/master-playlist-controller.js Outdated Show resolved Hide resolved
src/master-playlist-controller.js Outdated Show resolved Hide resolved
src/media-groups.js Outdated Show resolved Hide resolved
mediaType.logger_(`track change. Switching master audio from ${lastTrack.id} to ${activeTrack.id}`);
masterPlaylistLoader.pause();
mainSegmentLoader.resetEverything();
mpc.fastQualityChange_();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fastQualityChange should reset everything unless the media is the same. And if the media is the same, would we ever resume playback (the loader would pause but fastQualityChange would return early)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will only get in here if the track id changed. which will cause us to select from a new set of playlists in fastQualityChange which will mean that the playlists should never be the same.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated the code to check that the playlist will actually change.

src/media-groups.js Outdated Show resolved Hide resolved
src/playlist-selectors.js Show resolved Hide resolved
src/master-playlist-controller.js Outdated Show resolved Hide resolved
if (sourceType === 'vhs-json' && properties.playlists) {
if (audioOnlyMaster) {
logger_(`AUDIO group '${groupId}' label '${variantLabel}' is a master playlist`);
properties.masterPlaylist = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When reading from the top I was a bit confused until I saw that masterPlaylist was a boolean. Maybe isMasterPlaylist?

src/media-groups.js Outdated Show resolved Hide resolved
src/playlist.js Show resolved Hide resolved
test/rendition-mixin.test.js Outdated Show resolved Hide resolved
Copy link
Contributor

@gesinger gesinger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. I think some of the new and modified functions may need some new tests.

@codecov
Copy link

codecov bot commented Apr 5, 2021

Codecov Report

Merging #1100 (a9bfc51) into main (9b116ce) will increase coverage by 0.15%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1100      +/-   ##
==========================================
+ Coverage   86.13%   86.29%   +0.15%     
==========================================
  Files          38       38              
  Lines        8966     9068     +102     
  Branches     2017     2052      +35     
==========================================
+ Hits         7723     7825     +102     
  Misses       1243     1243              
Impacted Files Coverage Δ
src/master-playlist-controller.js 94.31% <100.00%> (+0.18%) ⬆️
src/media-groups.js 98.90% <100.00%> (+0.15%) ⬆️
src/playlist-selectors.js 85.23% <100.00%> (+0.40%) ⬆️
src/playlist.js 94.50% <100.00%> (+1.29%) ⬆️
src/rendition-mixin.js 94.87% <100.00%> (+0.42%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 9b116ce...a9bfc51. Read the comment docs.

);
};

QUnit.module('MediaGroups', function() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

made all media groups tests live under the same base module.

const tracks = settings.mediaTypes[type].tracks;
const activeTrack = MediaGroups.activeTrack[type](type, settings);
const activeGroup = MediaGroups.activeGroup(type, settings);
['AUDIO', 'SUBTITLES'].forEach(function(groupType) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move all activeGroup tests to here and added a few for cases we were missing.

'sets the correct active playlist loader'
);

mediaType.lastGroup_ = null;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add tests to onGroupChanged for isMasterPlaylist type group changes.

if (!master && !master.mediaGroups && !master.mediaGroups.AUDIO) {
return [];
if (!master || !master.mediaGroups || !master.mediaGroups.AUDIO) {
return master && master.playlists;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there's no master, is it OK that this returns undefined? Would it be better to return []?

The comment above may need to be changed too otherwise. And would returning master.playlists end up returning non audio only tracks?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will make it return an empty array without a master. It will could end up returning non-audio playlists but if we don't have audio groups and this function is called, which should only happen if we detect that the playlist is audio only, Then we should just return the main playlists.

src/playlist.js Outdated
Comment on lines 631 to 657
if (AUDIO) {
let audioGroupFound = false;

for (const groupName in AUDIO) {
if (audioGroupFound) {
break;
}
for (const label in AUDIO[groupName]) {
const variant = AUDIO[groupName][label];

// playlist is in an audio group it is audio only
if (playlistMatch(playlist, variant)) {
audioGroupFound = true;
break;
}
}
}

if (audioGroupFound) {
continue;
}
}

// if we make it here this playlist isn't audio and we
// are not audio only
return false;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we can, since this ends up in a nesting of three for loops, it may be better to move this to a separate function to check if there's an audio playlist match for a given playlist.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added as someAudioVariant a function similar to Array.some.

'no resync changing to group with no playlist loader'
);

mediaType.lastGroup_ = null;
Copy link
Contributor Author

@brandonocasey brandonocasey Apr 6, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For most of this test we have to add this line before calling onGroupChanged to mimic previous behavior, where we didn't care about group changes.

'sets the correct active playlist loader'
);

tracks.fr.enabled = false;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test previously relied on weird logic to change tracks, now we actually change the tracks around before each step.

});
};

QUnit.test('onTrackChanged with isMasterPlaylist', function(assert) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous onTrackChanged test was very brittle, so I didn't want to add anything else to it. I instead added the this test here that tests the new isMasterPlaylist functionality.

gkatsev
gkatsev previously approved these changes Apr 6, 2021
test/media-groups.test.js Outdated Show resolved Hide resolved
Comment on lines 1336 to 1341
a.resolvedUri += '?nope';
assert.equal(Playlist.playlistMatch(a, b), true, 'uri match');

a.uri += '?nope';

assert.equal(Playlist.playlistMatch(a, b), false, 'no match');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should query parameters result in a uri match?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, resolveUri query param succeeds because the uri still matches but if both have a query param it fails.

@@ -1317,4 +1317,95 @@ QUnit.module('Playlist', function() {
'no segments, live delay can\'t be calculated'
);
});

QUnit.test('playlistMatch', function(assert) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if playlistMatch returns a boolean, might be better to use assert.true and assert.false. Same for isAudioOnly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'll switch to that.

Co-authored-by: Gary Katsevman <gary.katsevman@gmail.com>
@brandonocasey brandonocasey merged commit 6d83de3 into main Apr 6, 2021
@brandonocasey brandonocasey deleted the fix/audio-only-groups branch April 6, 2021 19:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants