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 ...@@ -18,8 +18,6 @@ Maintenance Status: Stable
18 - [Manual Build](#manual-build) 18 - [Manual Build](#manual-build)
19 - [Contributing](#contributing) 19 - [Contributing](#contributing)
20 - [Getting Started](#getting-started) 20 - [Getting Started](#getting-started)
21 - [Known Issues](#known-issues)
22 - [IE11](#ie11)
23 - [Documentation](#documentation) 21 - [Documentation](#documentation)
24 - [Options](#options) 22 - [Options](#options)
25 - [How to use](#how-to-use) 23 - [How to use](#how-to-use)
...@@ -43,6 +41,9 @@ Maintenance Status: Stable ...@@ -43,6 +41,9 @@ Maintenance Status: Stable
43 - [mediachange](#mediachange) 41 - [mediachange](#mediachange)
44 - [In-Band Metadata](#in-band-metadata) 42 - [In-Band Metadata](#in-band-metadata)
45 - [Hosting Considerations](#hosting-considerations) 43 - [Hosting Considerations](#hosting-considerations)
44 - [Known Issues](#known-issues)
45 - [IE11](#ie11)
46 - [Fragmented MP4 Support](#fragmented-mp4-support)
46 - [Testing](#testing) 47 - [Testing](#testing)
47 - [Release History](#release-history) 48 - [Release History](#release-history)
48 - [Building](#building) 49 - [Building](#building)
......
...@@ -382,7 +382,7 @@ export class MasterPlaylistController extends videojs.EventTarget { ...@@ -382,7 +382,7 @@ export class MasterPlaylistController extends videojs.EventTarget {
382 } 382 }
383 383
384 handleAudioinfoUpdate_(event) { 384 handleAudioinfoUpdate_(event) {
385 if (!videojs.browser.IS_FIREFOX || 385 if (Hls.supportsAudioInfoChange_() ||
386 !this.audioInfo_ || 386 !this.audioInfo_ ||
387 !objectChanged(this.audioInfo_, event.info)) { 387 !objectChanged(this.audioInfo_, event.info)) {
388 this.audioInfo_ = event.info; 388 this.audioInfo_ = event.info;
...@@ -391,7 +391,7 @@ export class MasterPlaylistController extends videojs.EventTarget { ...@@ -391,7 +391,7 @@ export class MasterPlaylistController extends videojs.EventTarget {
391 391
392 let error = 'had different audio properties (channels, sample rate, etc.) ' + 392 let error = 'had different audio properties (channels, sample rate, etc.) ' +
393 'or changed in some other way. This behavior is currently ' + 393 'or changed in some other way. This behavior is currently ' +
394 'unsupported in Firefox due to an issue: \n\n' + 394 'unsupported in Firefox 48 and below due to an issue: \n\n' +
395 'https://bugzilla.mozilla.org/show_bug.cgi?id=1247138\n\n'; 395 'https://bugzilla.mozilla.org/show_bug.cgi?id=1247138\n\n';
396 396
397 let enabledIndex = 397 let enabledIndex =
......
...@@ -244,6 +244,26 @@ Hls.isSupported = function() { ...@@ -244,6 +244,26 @@ Hls.isSupported = function() {
244 'your player\'s techOrder.'); 244 'your player\'s techOrder.');
245 }; 245 };
246 246
247 const USER_AGENT = window.navigator && window.navigator.userAgent || '';
248
249 /**
250 * Determines whether the browser supports a change in the audio configuration
251 * during playback. Currently only Firefox 48 and below do not support this.
252 * window.isSecureContext is a propterty that was added to window in firefox 49,
253 * so we can use it to detect Firefox 49+.
254 *
255 * @return {Boolean} Whether the browser supports audio config change during playback
256 */
257 Hls.supportsAudioInfoChange_ = function() {
258 if (videojs.browser.IS_FIREFOX) {
259 let firefoxVersionMap = (/Firefox\/([\d.]+)/i).exec(USER_AGENT);
260 let version = parseInt(firefoxVersionMap[1], 10);
261
262 return version >= 49;
263 }
264 return true;
265 };
266
247 const Component = videojs.getComponent('Component'); 267 const Component = videojs.getComponent('Component');
248 268
249 /** 269 /**
......
...@@ -421,33 +421,39 @@ function() { ...@@ -421,33 +421,39 @@ function() {
421 QUnit.equal(this.player.tech_.hls.stats.bandwidth, 1, 'bandwidth we set above'); 421 QUnit.equal(this.player.tech_.hls.stats.bandwidth, 1, 'bandwidth we set above');
422 }); 422 });
423 423
424 QUnit.test('blacklists the current playlist when audio changes in Firefox', function() { 424 QUnit.test('blacklists the current playlist when audio changes in Firefox 48 & below',
425 videojs.browser.IS_FIREFOX = true; 425 function() {
426 videojs.browser.IS_FIREFOX = true;
426 427
427 // master 428 let origSupportsAudioInfoChange_ = videojs.Hls.supportsAudioInfoChange_;
428 standardXHRResponse(this.requests.shift());
429 // media
430 standardXHRResponse(this.requests.shift());
431 429
432 let media = this.masterPlaylistController.media(); 430 videojs.Hls.supportsAudioInfoChange_ = () => false;
433 431
434 // initial audio config 432 // master
435 this.masterPlaylistController.mediaSource.trigger({ 433 standardXHRResponse(this.requests.shift());
436 type: 'audioinfo', 434 // media
437 info: {} 435 standardXHRResponse(this.requests.shift());
438 });
439 // updated audio config
440 436
441 this.masterPlaylistController.mediaSource.trigger({ 437 let media = this.masterPlaylistController.media();
442 type: 'audioinfo', 438
443 info: { 439 // initial audio config
444 different: true 440 this.masterPlaylistController.mediaSource.trigger({
445 } 441 type: 'audioinfo',
442 info: {}
443 });
444 // updated audio config
445
446 this.masterPlaylistController.mediaSource.trigger({
447 type: 'audioinfo',
448 info: {
449 different: true
450 }
451 });
452 QUnit.ok(media.excludeUntil > 0, 'blacklisted the old playlist');
453 QUnit.equal(this.env.log.warn.callCount, 2, 'logged two warnings');
454 this.env.log.warn.callCount = 0;
455 videojs.Hls.supportsAudioInfoChange_ = origSupportsAudioInfoChange_;
446 }); 456 });
447 QUnit.ok(media.excludeUntil > 0, 'blacklisted the old playlist');
448 QUnit.equal(this.env.log.warn.callCount, 2, 'logged two warnings');
449 this.env.log.warn.callCount = 0;
450 });
451 457
452 QUnit.test('updates the combined segment loader on media changes', function() { 458 QUnit.test('updates the combined segment loader on media changes', function() {
453 let updates = []; 459 let updates = [];
......
...@@ -1792,11 +1792,15 @@ QUnit.test('adds audio tracks if we have parsed some from a playlist', function( ...@@ -1792,11 +1792,15 @@ QUnit.test('adds audio tracks if we have parsed some from a playlist', function(
1792 QUnit.equal(vjsAudioTracks[0].enabled, false, 'main track is disabled'); 1792 QUnit.equal(vjsAudioTracks[0].enabled, false, 'main track is disabled');
1793 }); 1793 });
1794 1794
1795 QUnit.test('when audioinfo changes on an independent audio track in Firefox, the enabled track is blacklisted and removed', function() { 1795 QUnit.test('when audioinfo changes on an independent audio track in Firefox 48 & below, the enabled track is blacklisted and removed', function() {
1796 let audioTracks = this.player.audioTracks(); 1796 let audioTracks = this.player.audioTracks();
1797 let oldLabel; 1797 let oldLabel;
1798 1798
1799 videojs.browser.IS_FIREFOX = true; 1799 videojs.browser.IS_FIREFOX = true;
1800 let origSupportsAudioInfoChange_ = videojs.Hls.supportsAudioInfoChange_;
1801
1802 videojs.Hls.supportsAudioInfoChange_ = () => false;
1803
1800 this.player.src({ 1804 this.player.src({
1801 src: 'manifest/multipleAudioGroups.m3u8', 1805 src: 'manifest/multipleAudioGroups.m3u8',
1802 type: 'application/vnd.apple.mpegurl' 1806 type: 'application/vnd.apple.mpegurl'
...@@ -1828,12 +1832,17 @@ QUnit.test('when audioinfo changes on an independent audio track in Firefox, the ...@@ -1828,12 +1832,17 @@ QUnit.test('when audioinfo changes on an independent audio track in Firefox, the
1828 QUnit.notEqual(audioTracks[1].label, oldLabel, 'audio track at index 1 is not the same'); 1832 QUnit.notEqual(audioTracks[1].label, oldLabel, 'audio track at index 1 is not the same');
1829 QUnit.equal(defaultTrack.enabled, true, 'default track is enabled again'); 1833 QUnit.equal(defaultTrack.enabled, true, 'default track is enabled again');
1830 QUnit.equal(this.env.log.warn.calls, 1, 'firefox issue warning logged'); 1834 QUnit.equal(this.env.log.warn.calls, 1, 'firefox issue warning logged');
1835 videojs.Hls.supportsAudioInfoChange_ = origSupportsAudioInfoChange_;
1831 }); 1836 });
1832 1837
1833 QUnit.test('audioinfo changes with one track, blacklist playlist', function() { 1838 QUnit.test('audioinfo changes with one track, blacklist playlist on Firefox 48 & below', function() {
1834 let audioTracks = this.player.audioTracks(); 1839 let audioTracks = this.player.audioTracks();
1835 1840
1836 videojs.browser.IS_FIREFOX = true; 1841 videojs.browser.IS_FIREFOX = true;
1842 let origSupportsAudioInfoChange_ = videojs.Hls.supportsAudioInfoChange_;
1843
1844 videojs.Hls.supportsAudioInfoChange_ = () => false;
1845
1837 this.player.src({ 1846 this.player.src({
1838 src: 'manifest/master.m3u8', 1847 src: 'manifest/master.m3u8',
1839 type: 'application/vnd.apple.mpegurl' 1848 type: 'application/vnd.apple.mpegurl'
...@@ -1857,12 +1866,17 @@ QUnit.test('audioinfo changes with one track, blacklist playlist', function() { ...@@ -1857,12 +1866,17 @@ QUnit.test('audioinfo changes with one track, blacklist playlist', function() {
1857 QUnit.equal(audioTracks.length, 1, 'still have one audio track'); 1866 QUnit.equal(audioTracks.length, 1, 'still have one audio track');
1858 QUnit.ok(oldMedia.excludeUntil > 0, 'blacklisted old playlist'); 1867 QUnit.ok(oldMedia.excludeUntil > 0, 'blacklisted old playlist');
1859 QUnit.equal(this.env.log.warn.calls, 2, 'firefox issue warning logged'); 1868 QUnit.equal(this.env.log.warn.calls, 2, 'firefox issue warning logged');
1869 videojs.Hls.supportsAudioInfoChange_ = origSupportsAudioInfoChange_;
1860 }); 1870 });
1861 1871
1862 QUnit.test('changing audioinfo for muxed audio blacklists the current playlist in Firefox', function() { 1872 QUnit.test('changing audioinfo for muxed audio blacklists the current playlist in Firefox', function() {
1863 let audioTracks = this.player.audioTracks(); 1873 let audioTracks = this.player.audioTracks();
1864 1874
1865 videojs.browser.IS_FIREFOX = true; 1875 videojs.browser.IS_FIREFOX = true;
1876 let origSupportsAudioInfoChange_ = videojs.Hls.supportsAudioInfoChange_;
1877
1878 videojs.Hls.supportsAudioInfoChange_ = () => false;
1879
1866 this.player.src({ 1880 this.player.src({
1867 src: 'manifest/multipleAudioGroupsCombinedMain.m3u8', 1881 src: 'manifest/multipleAudioGroupsCombinedMain.m3u8',
1868 type: 'application/vnd.apple.mpegurl' 1882 type: 'application/vnd.apple.mpegurl'
...@@ -1910,6 +1924,7 @@ QUnit.test('changing audioinfo for muxed audio blacklists the current playlist i ...@@ -1910,6 +1924,7 @@ QUnit.test('changing audioinfo for muxed audio blacklists the current playlist i
1910 QUnit.equal(defaultTrack.enabled, true, 'default audio still enabled'); 1924 QUnit.equal(defaultTrack.enabled, true, 'default audio still enabled');
1911 QUnit.ok(oldPlaylist.excludeUntil > 0, 'blacklisted the old playlist'); 1925 QUnit.ok(oldPlaylist.excludeUntil > 0, 'blacklisted the old playlist');
1912 QUnit.equal(this.env.log.warn.calls, 2, 'firefox issue warning logged'); 1926 QUnit.equal(this.env.log.warn.calls, 2, 'firefox issue warning logged');
1927 videojs.Hls.supportsAudioInfoChange_ = origSupportsAudioInfoChange_;
1913 }); 1928 });
1914 1929
1915 QUnit.test('cleans up the buffer when loading live segments', function() { 1930 QUnit.test('cleans up the buffer when loading live segments', function() {
......