From 742572d3cd7526f76616f15161408242b075d770 Mon Sep 17 00:00:00 2001 From: Garrett Singer Date: Thu, 18 Jun 2020 14:27:45 -0400 Subject: [PATCH] chore: simplify setupEmeOptions and add tests --- src/videojs-http-streaming.js | 54 ++++++---- test/videojs-http-streaming.test.js | 146 +++++++++++++++++++++++++++- 2 files changed, 179 insertions(+), 21 deletions(-) diff --git a/src/videojs-http-streaming.js b/src/videojs-http-streaming.js index 82cb19294..56017d1ac 100644 --- a/src/videojs-http-streaming.js +++ b/src/videojs-http-streaming.js @@ -171,27 +171,31 @@ const emeKeySystems = (keySystemOptions, videoPlaylist, audioPlaylist) => { return videojs.mergeOptions(keySystemOptions, keySystemContentTypes); }; -const setupEmeOptions = (vhsHandler) => { - const player = vhsHandler.player_; - - if (player.eme) { - const audioPlaylistLoader = vhsHandler.masterPlaylistController_.mediaTypes_.AUDIO.activePlaylistLoader; - const sourceOptions = emeKeySystems( - vhsHandler.source_.keySystems, - vhsHandler.playlists.media(), - audioPlaylistLoader && audioPlaylistLoader.media() - ); +const setupEmeOptions = ({ + player, + sourceKeySystems, + media, + audioMedia +}) => { + if (!player.eme) { + return; + } - if (sourceOptions) { - player.currentSource().keySystems = sourceOptions; + const sourceOptions = emeKeySystems(sourceKeySystems, media, audioMedia); - // works around https://bugs.chromium.org/p/chromium/issues/detail?id=895449 - // in non-IE11 browsers. In IE11 this is too early to initialize media keys - if (!(videojs.browser.IE_VERSION === 11) && player.eme.initializeMediaKeys) { - player.eme.initializeMediaKeys(); - } - } + if (!sourceOptions) { + return; } + + player.currentSource().keySystems = sourceOptions; + + // works around https://bugs.chromium.org/p/chromium/issues/detail?id=895449 + // in non-IE11 browsers. In IE11 this is too early to initialize media keys + if (videojs.browser.IE_VERSION === 11 || !player.eme.initializeMediaKeys) { + return; + } + + player.eme.initializeMediaKeys(); }; const getVhsLocalStorage = () => { @@ -723,7 +727,16 @@ class VhsHandler extends Component { this.masterPlaylistController_.on('selectedinitialmedia', () => { // Add the manual rendition mix-in to VhsHandler renditionSelectionMixin(this); - setupEmeOptions(this); + + const audioPlaylistLoader = + this.masterPlaylistController_.mediaTypes_.AUDIO.activePlaylistLoader; + + setupEmeOptions({ + player: this.player_, + sourceKeySystems: this.source_.keySystems, + media: this.playlists.media(), + audioMedia: audioPlaylistLoader && audioPlaylistLoader.media() + }); }); // the bandwidth of the primary segment loader is our best @@ -979,5 +992,6 @@ export { VhsSourceHandler, emeKeySystems, simpleTypeFromSourceType, - expandDataUri + expandDataUri, + setupEmeOptions }; diff --git a/test/videojs-http-streaming.test.js b/test/videojs-http-streaming.test.js index 4d57e2f0d..a2b549018 100644 --- a/test/videojs-http-streaming.test.js +++ b/test/videojs-http-streaming.test.js @@ -30,7 +30,8 @@ import { Vhs, emeKeySystems, LOCAL_STORAGE_KEY, - expandDataUri + expandDataUri, + setupEmeOptions } from '../src/videojs-http-streaming'; import window from 'global/window'; // we need this so the plugin registers itself @@ -5605,3 +5606,146 @@ QUnit.test('expandDataUri requires comma to parse', function(assert) { 'did not parse when no comma after data URI' ); }); + +QUnit.module('setupEmeOptions', { + beforeEach() { + this.origBrowser = videojs.browser; + // IE11 is a special case and should be tested separately + videojs.browser = videojs.mergeOptions(videojs.browser, { IE_VERSION: null }); + }, + afterEach() { + videojs.browser = this.origBrowser; + } +}); + +QUnit.test('no error if no eme', function(assert) { + const player = {}; + const sourceKeySystems = {}; + const media = {}; + const audioMedia = {}; + + setupEmeOptions({ player, sourceKeySystems, media, audioMedia }); + + assert.ok(true, 'no exception'); +}); + +QUnit.test('no initialize calls if no source key systems', function(assert) { + let numInitializeCalls = 0; + const player = { eme: { initializeMediaKeys: () => numInitializeCalls++ } }; + const sourceKeySystems = null; + const media = { + attributes: { CODECS: 'avc1.4d400d,mp4a.40.2' }, + contentProtection: { 'com.widevine.alpha': { pssh: new Uint8Array() } } + }; + const audioMedia = null; + + setupEmeOptions({ player, sourceKeySystems, media, audioMedia }); + + assert.equal(numInitializeCalls, 0, 'no initialize calls'); +}); + +QUnit.test('initializes for muxed playlist', function(assert) { + let numInitializeCalls = 0; + const player = { + eme: { initializeMediaKeys: () => numInitializeCalls++ }, + currentSource: () => { + return {}; + } + }; + const sourceKeySystems = { + 'com.widevine.alpha': { + url: 'license-url' + } + }; + const media = { + attributes: { CODECS: 'avc1.4d400d,mp4a.40.2' }, + contentProtection: { 'com.widevine.alpha': { pssh: new Uint8Array() } } + }; + const audioMedia = null; + + setupEmeOptions({ player, sourceKeySystems, media, audioMedia }); + + assert.equal(numInitializeCalls, 1, 'one initialize call'); +}); + +QUnit.test('initializes for demuxed playlist', function(assert) { + let numInitializeCalls = 0; + const player = { + eme: { initializeMediaKeys: () => numInitializeCalls++ }, + currentSource: () => { + return {}; + } + }; + const sourceKeySystems = { + 'com.widevine.alpha': { + url: 'license-url' + } + }; + const media = { + attributes: { CODECS: 'avc1.4d400d,mp4a.40.2' }, + contentProtection: { 'com.widevine.alpha': { pssh: new Uint8Array() } } + }; + const audioMedia = { + attributes: {}, + contentProtection: { 'com.widevine.alpha': { pssh: new Uint8Array() } } + }; + + setupEmeOptions({ player, sourceKeySystems, media, audioMedia }); + + assert.equal(numInitializeCalls, 1, 'one initialize call'); +}); + +QUnit.test('does not initialize if IE11', function(assert) { + videojs.browser.IE_VERSION = 11; + let numInitializeCalls = 0; + const player = { + eme: { initializeMediaKeys: () => numInitializeCalls++ }, + currentSource: () => { + return {}; + } + }; + const sourceKeySystems = { + 'com.widevine.alpha': { + url: 'license-url' + } + }; + const media = { + attributes: { CODECS: 'avc1.4d400d,mp4a.40.2' }, + contentProtection: { 'com.widevine.alpha': { pssh: new Uint8Array() } } + }; + const audioMedia = { + attributes: {}, + contentProtection: { 'com.widevine.alpha': { pssh: new Uint8Array() } } + }; + + setupEmeOptions({ player, sourceKeySystems, media, audioMedia }); + + assert.equal(numInitializeCalls, 0, 'no initialize calls'); +}); + +QUnit.test('only initializes once even for different pssh values', function(assert) { + let numInitializeCalls = 0; + const player = { + eme: { initializeMediaKeys: () => numInitializeCalls++ }, + currentSource: () => { + return {}; + } + }; + const sourceKeySystems = { + 'com.widevine.alpha': { + url: 'license-url' + } + }; + const media = { + attributes: { CODECS: 'avc1.4d400d,mp4a.40.2' }, + contentProtection: { 'com.widevine.alpha': { pssh: new Uint8Array([0]) } } + }; + const audioMedia = { + attributes: {}, + contentProtection: { 'com.widevine.alpha': { pssh: new Uint8Array([1]) } } + }; + + setupEmeOptions({ player, sourceKeySystems, media, audioMedia }); + + assert.equal(numInitializeCalls, 1, 'one initialize call'); +});