Skip to content
This repository has been archived by the owner on Jan 12, 2019. It is now read-only.

MediaGroups: various bug fixes and refactor #1243

Merged
merged 12 commits into from
Sep 18, 2017
Merged

Conversation

mjneil
Copy link
Contributor

@mjneil mjneil commented Aug 25, 2017

Description

This PR is a WIP. Tests still need to be written.

There are some issues with the way we currently handle media groups. A big issue is that when switching to a new track, the PlaylistLoader is disposed of and a fresh one is created. The problem there is that the PlaylistLoader also holds onto the playlist object reference. When we dispose of the loader, we lose any sync information we have learned about that stream, so returning to it is basically starting fresh.
Alternate audio was also using incorrect sync information causing delayed switches, and sometimes desync of audio and video.
This also removes the Firefox 48 check for for supporting a change in audio info

Specific Changes proposed

  • Pull setup of MediaGroups out of MasterPlaylistController and into its own module.
  • Fix delayed switching between audio tracks and intermittent desync.
  • removes the Firefox 48 check for for supporting a change in audio info

@mjneil mjneil changed the title [WIP] MediaGroups: various bug fixes and refactor MediaGroups: various bug fixes and refactor Sep 1, 2017
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.

Still have to look at the tests, but wanted to submit an initial review. The refactor looks much cleaner and more straightforward than the old code 👍

@@ -381,14 +349,25 @@ export class MasterPlaylistController extends videojs.EventTarget {
this.mainSegmentLoader_.load();
}

this.fillAudioTracks_();
this.setupAudio();
const mediaGroupSettings = {
Copy link
Contributor

Choose a reason for hiding this comment

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

Since it's only used in one place, probably can get rid of the var

this.audioSegmentLoader_.load();
}
if (this.subtitlePlaylistLoader_) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this load no longer necessary?

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'm not sure what you are asking. load is still called on the subtitleSegmentLoader_ it's just that the check for the playlist loader was changed to a different reference

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Maybe there is confusion because git diff is matching the load call with one much lower from another function that was removed? (line 1159 for this file, line 636 in the new file)?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yup, it was the diff 👍

};

/**
* Start loading for provided segment loader and playlist loader
Copy link
Contributor

Choose a reason for hiding this comment

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

s/for//

if (!masterGroups[type] ||
Object.keys(masterGroups[type]).length === 0 ||
mode !== 'html5') {
masterGroups[type] = { main: { default: { defualt: true } } };
Copy link
Contributor

Choose a reason for hiding this comment

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

default

AUDIO: (type, settings) => () => {
const { mediaGroups: { [type]: { tracks } } } = settings;

for (let id in tracks) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Preference, but this can probably be return tracks.filter((track) => track.enabled)[0] || 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.

Object :/

};

/**
* Returns a function used to get the active group of type provided
Copy link
Contributor

Choose a reason for hiding this comment

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

the provided type

* Object containing required information for media groups
* @return {Function}
* Function that returns the active media group for the provided type. Takes an
* optional paramter {TextTrack} track. If no track is provided, a list of all
Copy link
Contributor

Choose a reason for hiding this comment

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

parameter

return null;
}

let result = null;
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe this should be called variants?

return null;
}

return result.reduce((final, props) => props.id === track.id ? props : final, null);
Copy link
Contributor

Choose a reason for hiding this comment

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

Preference, but might be clearer as result.filter((props) => props.id === track.id)[0] || null

} = settings;

// setup active group and track getters and change event handlers

Copy link
Contributor

Choose a reason for hiding this comment

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

Extra space?

@@ -573,8 +577,8 @@ QUnit.test('updates the enabled track when switching audio groups', function(ass
'0.ts\n' +
'#EXT-X-ENDLIST\n');

assert.ok(mpc.activeAudioGroup().filter((track) => track.enabled)[0],
'enabled a track in the new audio group');
assert.notOk(mpc.mediaTypes_.AUDIO.activePlaylistLoader,
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't this still have an activePlaylistLoader?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is switching from unmuxed to muxed audio. When we are in the muxed audio case, there is no active audio playlist loader because the audio content is coming from the video stream

@@ -863,40 +867,6 @@ function(assert) {
assert.equal(this.player.tech_.hls.stats.bandwidth, 1, 'bandwidth we set above');
});

QUnit.test('blacklists the current playlist when audio changes in Firefox 48 & below',
Copy link
Contributor

Choose a reason for hiding this comment

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

Are we foregoing this?

'no active subtitle group');

// media
this.standardXHRResponse(this.requests.shift());

assert.ok(masterPlaylistController.activeSubtitleGroup_(), 'active subtitle group');
assert.ok(masterPlaylistController.mediaTypes_.SUBTITLES.activeGroup(),
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this test make sense in this file?

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 left these tests in here as integration tests. I'm in favor of (re?)moving them if you think they would be better placed in the media-groups.test.js or if they are already covered by another test

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm in favor of either of those, since this test won't directly touch the segment loader.

@@ -2296,7 +2272,7 @@ QUnit.test('can get active subtitle track', function(assert) {

const masterPlaylistController = this.player.tech_.hls.masterPlaylistController_;

assert.notOk(masterPlaylistController.activeSubtitleTrack_(),
assert.notOk(masterPlaylistController.mediaTypes_.SUBTITLES.activeTrack(),
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this test belong in this file?

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 left these tests in here as integration tests. I'm in favor of (re?)moving them if you think they would be better placed in the media-groups.test.js or if they are already covered by another test

Copy link
Contributor

Choose a reason for hiding this comment

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

Any of those options sound good 👍

const result = MediaGroups.createMediaTypes();

assert.ok(result.AUDIO, 'created AUDIO media group object');
assert.equal(JSON.stringify(result.AUDIO.groups), '{}',
Copy link
Contributor

Choose a reason for hiding this comment

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

Will deep equal not work for empty objects?

Copy link
Contributor Author

@mjneil mjneil Sep 11, 2017

Choose a reason for hiding this comment

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

It might, I didn't think to try that for some reason. I was trying strictEqual but that was not working
edit: it does :)

assert.equal(mainSegmentLoaderResetCalls, 1,
'no main reset changing to group with playlist loader');
assert.equal(segmentLoaderResetCalls, 0,
'no reset when active group hasnt changed');
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice try, but we need the \'

onError();

assert.equal(blacklistCurrentPlaylistCalls, 0, 'did not blacklist current playlist');
assert.equal(onTrackChangedCalls, 1, 'called onTrackChanged after chaging to default');
Copy link
Contributor

Choose a reason for hiding this comment

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

changing

this.env.log.warn.callCount = 0;
});

QUnit.test('setupListeners adds correct playlist loader listeners', function(assert) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm surprised this test passes

{ main: { default: { default: true } } }, 'forced default audio group');
assert.deepEqual(this.mediaTypes[type].groups,
{ main: [ { id: 'default', playlistLoader: null, default: true } ] },
'creates group properites and no playlist loader');
Copy link
Contributor

Choose a reason for hiding this comment

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

properties

assert.ok(this.mediaTypes[type].tracks.fr, 'created text track');
});

QUnit.test('initialize closed-captions correctly generates tracks and NO laoders',
Copy link
Contributor

Choose a reason for hiding this comment

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

loaders

@videojs videojs deleted a comment from shahlabs Sep 13, 2017
@mjneil mjneil merged commit 24894e6 into videojs:master Sep 18, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants