77c25202 by Matthew Neil Committed by forbesjo

Add support for maat in Firefox 49 (#852)

* use window.isSecureContext to detect ff 49

* fix tests

* fix linting

* make supportsAudioInfoChange private

* forgot to save this file before commit

* detect firefox 49 by user agent parsing for version number
1 parent b0f43a65
......@@ -18,8 +18,6 @@ Maintenance Status: Stable
- [Manual Build](#manual-build)
- [Contributing](#contributing)
- [Getting Started](#getting-started)
- [Known Issues](#known-issues)
- [IE11](#ie11)
- [Documentation](#documentation)
- [Options](#options)
- [How to use](#how-to-use)
......@@ -43,6 +41,9 @@ Maintenance Status: Stable
- [mediachange](#mediachange)
- [In-Band Metadata](#in-band-metadata)
- [Hosting Considerations](#hosting-considerations)
- [Known Issues](#known-issues)
- [IE11](#ie11)
- [Fragmented MP4 Support](#fragmented-mp4-support)
- [Testing](#testing)
- [Release History](#release-history)
- [Building](#building)
......
......@@ -382,7 +382,7 @@ export class MasterPlaylistController extends videojs.EventTarget {
}
handleAudioinfoUpdate_(event) {
if (!videojs.browser.IS_FIREFOX ||
if (Hls.supportsAudioInfoChange_() ||
!this.audioInfo_ ||
!objectChanged(this.audioInfo_, event.info)) {
this.audioInfo_ = event.info;
......@@ -391,7 +391,7 @@ export class MasterPlaylistController extends videojs.EventTarget {
let error = 'had different audio properties (channels, sample rate, etc.) ' +
'or changed in some other way. This behavior is currently ' +
'unsupported in Firefox due to an issue: \n\n' +
'unsupported in Firefox 48 and below due to an issue: \n\n' +
'https://bugzilla.mozilla.org/show_bug.cgi?id=1247138\n\n';
let enabledIndex =
......
......@@ -244,6 +244,26 @@ Hls.isSupported = function() {
'your player\'s techOrder.');
};
const USER_AGENT = window.navigator && window.navigator.userAgent || '';
/**
* Determines whether the browser supports a change in the audio configuration
* during playback. Currently only Firefox 48 and below do not support this.
* window.isSecureContext is a propterty that was added to window in firefox 49,
* so we can use it to detect Firefox 49+.
*
* @return {Boolean} Whether the browser supports audio config change during playback
*/
Hls.supportsAudioInfoChange_ = function() {
if (videojs.browser.IS_FIREFOX) {
let firefoxVersionMap = (/Firefox\/([\d.]+)/i).exec(USER_AGENT);
let version = parseInt(firefoxVersionMap[1], 10);
return version >= 49;
}
return true;
};
const Component = videojs.getComponent('Component');
/**
......
......@@ -421,33 +421,39 @@ function() {
QUnit.equal(this.player.tech_.hls.stats.bandwidth, 1, 'bandwidth we set above');
});
QUnit.test('blacklists the current playlist when audio changes in Firefox', function() {
videojs.browser.IS_FIREFOX = true;
QUnit.test('blacklists the current playlist when audio changes in Firefox 48 & below',
function() {
videojs.browser.IS_FIREFOX = true;
// master
standardXHRResponse(this.requests.shift());
// media
standardXHRResponse(this.requests.shift());
let origSupportsAudioInfoChange_ = videojs.Hls.supportsAudioInfoChange_;
let media = this.masterPlaylistController.media();
videojs.Hls.supportsAudioInfoChange_ = () => false;
// initial audio config
this.masterPlaylistController.mediaSource.trigger({
type: 'audioinfo',
info: {}
});
// updated audio config
// master
standardXHRResponse(this.requests.shift());
// media
standardXHRResponse(this.requests.shift());
this.masterPlaylistController.mediaSource.trigger({
type: 'audioinfo',
info: {
different: true
}
let media = this.masterPlaylistController.media();
// initial audio config
this.masterPlaylistController.mediaSource.trigger({
type: 'audioinfo',
info: {}
});
// updated audio config
this.masterPlaylistController.mediaSource.trigger({
type: 'audioinfo',
info: {
different: true
}
});
QUnit.ok(media.excludeUntil > 0, 'blacklisted the old playlist');
QUnit.equal(this.env.log.warn.callCount, 2, 'logged two warnings');
this.env.log.warn.callCount = 0;
videojs.Hls.supportsAudioInfoChange_ = origSupportsAudioInfoChange_;
});
QUnit.ok(media.excludeUntil > 0, 'blacklisted the old playlist');
QUnit.equal(this.env.log.warn.callCount, 2, 'logged two warnings');
this.env.log.warn.callCount = 0;
});
QUnit.test('updates the combined segment loader on media changes', function() {
let updates = [];
......
......@@ -1792,11 +1792,15 @@ QUnit.test('adds audio tracks if we have parsed some from a playlist', function(
QUnit.equal(vjsAudioTracks[0].enabled, false, 'main track is disabled');
});
QUnit.test('when audioinfo changes on an independent audio track in Firefox, the enabled track is blacklisted and removed', function() {
QUnit.test('when audioinfo changes on an independent audio track in Firefox 48 & below, the enabled track is blacklisted and removed', function() {
let audioTracks = this.player.audioTracks();
let oldLabel;
videojs.browser.IS_FIREFOX = true;
let origSupportsAudioInfoChange_ = videojs.Hls.supportsAudioInfoChange_;
videojs.Hls.supportsAudioInfoChange_ = () => false;
this.player.src({
src: 'manifest/multipleAudioGroups.m3u8',
type: 'application/vnd.apple.mpegurl'
......@@ -1828,12 +1832,17 @@ QUnit.test('when audioinfo changes on an independent audio track in Firefox, the
QUnit.notEqual(audioTracks[1].label, oldLabel, 'audio track at index 1 is not the same');
QUnit.equal(defaultTrack.enabled, true, 'default track is enabled again');
QUnit.equal(this.env.log.warn.calls, 1, 'firefox issue warning logged');
videojs.Hls.supportsAudioInfoChange_ = origSupportsAudioInfoChange_;
});
QUnit.test('audioinfo changes with one track, blacklist playlist', function() {
QUnit.test('audioinfo changes with one track, blacklist playlist on Firefox 48 & below', function() {
let audioTracks = this.player.audioTracks();
videojs.browser.IS_FIREFOX = true;
let origSupportsAudioInfoChange_ = videojs.Hls.supportsAudioInfoChange_;
videojs.Hls.supportsAudioInfoChange_ = () => false;
this.player.src({
src: 'manifest/master.m3u8',
type: 'application/vnd.apple.mpegurl'
......@@ -1857,12 +1866,17 @@ QUnit.test('audioinfo changes with one track, blacklist playlist', function() {
QUnit.equal(audioTracks.length, 1, 'still have one audio track');
QUnit.ok(oldMedia.excludeUntil > 0, 'blacklisted old playlist');
QUnit.equal(this.env.log.warn.calls, 2, 'firefox issue warning logged');
videojs.Hls.supportsAudioInfoChange_ = origSupportsAudioInfoChange_;
});
QUnit.test('changing audioinfo for muxed audio blacklists the current playlist in Firefox', function() {
let audioTracks = this.player.audioTracks();
videojs.browser.IS_FIREFOX = true;
let origSupportsAudioInfoChange_ = videojs.Hls.supportsAudioInfoChange_;
videojs.Hls.supportsAudioInfoChange_ = () => false;
this.player.src({
src: 'manifest/multipleAudioGroupsCombinedMain.m3u8',
type: 'application/vnd.apple.mpegurl'
......@@ -1910,6 +1924,7 @@ QUnit.test('changing audioinfo for muxed audio blacklists the current playlist i
QUnit.equal(defaultTrack.enabled, true, 'default audio still enabled');
QUnit.ok(oldPlaylist.excludeUntil > 0, 'blacklisted the old playlist');
QUnit.equal(this.env.log.warn.calls, 2, 'firefox issue warning logged');
videojs.Hls.supportsAudioInfoChange_ = origSupportsAudioInfoChange_;
});
QUnit.test('cleans up the buffer when loading live segments', function() {
......