From de5baa7620b2250c869843ed410486b1693699b8 Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Wed, 28 Jul 2021 10:55:28 -0400 Subject: [PATCH] fix: exclude playlists on DRM key status of output-restricted (#1171) --- scripts/sources.json | 44 +++++++++++++ src/videojs-http-streaming.js | 10 +++ test/videojs-http-streaming.test.js | 96 +++++++++++++++++++++++++++++ 3 files changed, 150 insertions(+) diff --git a/scripts/sources.json b/scripts/sources.json index 364382b89..c9f78e37c 100644 --- a/scripts/sources.json +++ b/scripts/sources.json @@ -393,5 +393,49 @@ "uri": "https://d2zihajmogu5jn.cloudfront.net/first-pmt-only/index.m3u8", "mimetype": "application/x-mpegurl", "features": [] + }, + { + "name": "HDCP v1.0 DRM dash", + "uri": "https://storage.googleapis.com/wvmedia/cenc/h264/tears/tears.mpd#1", + "mimetype": "application/dash+xml", + "features": [], + "keySystems": { + "com.widevine.alpha": { + "url": "https://proxy.uat.widevine.com/proxy?video_id=GTS_SW_SECURE_CRYPTO_HDCP_V1&provider=widevine_test" + } + } + }, + { + "name": "HDCP v2.0 DRM dash", + "uri": "https://storage.googleapis.com/wvmedia/cenc/h264/tears/tears.mpd#2", + "mimetype": "application/dash+xml", + "features": [], + "keySystems": { + "com.widevine.alpha": { + "url": "https://proxy.uat.widevine.com/proxy?video_id=GTS_SW_SECURE_CRYPTO_HDCP_V2&provider=widevine_test" + } + } + }, + { + "name": "HDCP v2.1 DRM dash", + "uri": "https://storage.googleapis.com/wvmedia/cenc/h264/tears/tears.mpd@21", + "mimetype": "application/dash+xml", + "features": [], + "keySystems": { + "com.widevine.alpha": { + "url": "https://proxy.uat.widevine.com/proxy?video_id=GTS_SW_SECURE_CRYPTO_HDCP_V2_1&provider=widevine_test" + } + } + }, + { + "name": "HDCP v2.2 DRM dash", + "uri": "https://storage.googleapis.com/wvmedia/cenc/h264/tears/tears.mpd#22", + "mimetype": "application/dash+xml", + "features": [], + "keySystems": { + "com.widevine.alpha": { + "url": "https://proxy.uat.widevine.com/proxy?video_id=GTS_SW_SECURE_CRYPTO_HDCP_V2_2&provider=widevine_test" + } + } } ] diff --git a/src/videojs-http-streaming.js b/src/videojs-http-streaming.js index 179999816..15d1eb42b 100644 --- a/src/videojs-http-streaming.js +++ b/src/videojs-http-streaming.js @@ -1001,6 +1001,16 @@ class VhsHandler extends Component { audioMedia: audioPlaylistLoader && audioPlaylistLoader.media() }); + this.player_.tech_.on('keystatuschange', (e) => { + if (e.status === 'output-restricted') { + this.masterPlaylistController_.blacklistCurrentPlaylist({ + playlist: this.masterPlaylistController_.media(), + message: `DRM keystatus changed to ${e.status}. Playlist will fail to play. Check for HDCP content.`, + blacklistDuration: Infinity + }); + } + }); + // In IE11 this is too early to initialize media keys, and IE11 does not support // promises. if (videojs.browser.IE_VERSION === 11 || !didSetupEmeOptions) { diff --git a/test/videojs-http-streaming.test.js b/test/videojs-http-streaming.test.js index a3990c2aa..dd552cd90 100644 --- a/test/videojs-http-streaming.test.js +++ b/test/videojs-http-streaming.test.js @@ -4503,6 +4503,102 @@ QUnit.test('configures eme for HLS on source buffer creation', function(assert) }, 'set source eme options'); }); +QUnit.test('eme handles keystatuschange where status is output-restricted', function(assert) { + this.player.eme = { + options: { + previousSetting: 1 + } + }; + this.player.src({ + src: 'manifest/master.m3u8', + type: 'application/x-mpegURL', + keySystems: { + keySystem1: { + url: 'url1' + } + } + }); + + this.clock.tick(1); + + const media = { + attributes: { + CODECS: 'avc1.420015, mp4a.40.2c' + }, + contentProtection: { + keySystem1: { + pssh: 'test' + } + } + }; + + this.player.tech_.vhs.playlists = { + master: { playlists: [media] }, + media: () => media + }; + + const excludes = []; + + this.player.tech_.vhs.masterPlaylistController_.blacklistCurrentPlaylist = (exclude) => { + excludes.push(exclude); + }; + + this.player.tech_.vhs.masterPlaylistController_.sourceUpdater_.trigger('createdsourcebuffers'); + this.player.tech_.trigger({type: 'keystatuschange', status: 'output-restricted'}); + + assert.deepEqual(excludes, [{ + blacklistDuration: Infinity, + message: 'DRM keystatus changed to output-restricted. Playlist will fail to play. Check for HDCP content.', + playlist: undefined + }], 'excluded playlist'); +}); + +QUnit.test('eme handles keystatuschange where status is usable', function(assert) { + this.player.eme = { + options: { + previousSetting: 1 + } + }; + this.player.src({ + src: 'manifest/master.m3u8', + type: 'application/x-mpegURL', + keySystems: { + keySystem1: { + url: 'url1' + } + } + }); + + this.clock.tick(1); + + const media = { + attributes: { + CODECS: 'avc1.420015, mp4a.40.2c' + }, + contentProtection: { + keySystem1: { + pssh: 'test' + } + } + }; + + this.player.tech_.vhs.playlists = { + master: { playlists: [media] }, + media: () => media + }; + + const excludes = []; + + this.player.tech_.vhs.masterPlaylistController_.blacklistCurrentPlaylist = (exclude) => { + excludes.push(exclude); + }; + + this.player.tech_.vhs.masterPlaylistController_.sourceUpdater_.trigger('createdsourcebuffers'); + this.player.tech_.trigger({type: 'keystatuschange', status: 'usable'}); + + assert.deepEqual(excludes, [], 'did not exclude anything'); +}); + QUnit.test('integration: configures eme for DASH on source buffer creation', function(assert) { assert.timeout(3000); const done = assert.async();