Skip to content

Commit

Permalink
revert: "revert: fix: use in-spec EME for versions of Safari which su…
Browse files Browse the repository at this point in the history
…pport it (#142) (#145)" (#146)

This reverts commit fdb57e3.
  • Loading branch information
gkatsev committed Oct 19, 2021
1 parent 51627ce commit c912bda
Show file tree
Hide file tree
Showing 7 changed files with 213 additions and 76 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,7 @@ player.src({
},
keySystems: {
'org.w3.clearkey': {
initDataTypes: ['cenc', 'webm'],
audioContentType: 'audio/webm; codecs="vorbis"',
videoContentType: 'video/webm; codecs="vp9"',
getCertificate: function(emeOptions, callback) {
Expand Down
140 changes: 97 additions & 43 deletions src/eme.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ import { requestPlayreadyLicense } from './playready';
import window from 'global/window';
import {mergeAndRemoveNull} from './utils';
import {httpResponseHandler} from './http-handler.js';
import {
defaultGetCertificate as defaultFairplayGetCertificate,
defaultGetLicense as defaultFairplayGetLicense,
defaultGetContentId as defaultFairplayGetContentId
} from './fairplay';

const isFairplayKeySystem = (str) => str.startsWith('com.apple.fps');

/**
* Returns an array of MediaKeySystemConfigurationObjects provided in the keySystem
Expand All @@ -15,16 +22,21 @@ import {httpResponseHandler} from './http-handler.js';
* @return {Object[]}
* Array of MediaKeySystemConfigurationObjects
*/
export const getSupportedConfigurations = (keySystemOptions) => {
export const getSupportedConfigurations = (keySystem, keySystemOptions) => {
if (keySystemOptions.supportedConfigurations) {
return keySystemOptions.supportedConfigurations;
}

// TODO use initDataTypes when appropriate
const isFairplay = isFairplayKeySystem(keySystem);
const supportedConfiguration = {};
const initDataTypes = keySystemOptions.initDataTypes ||
// fairplay requires an explicit initDataTypes
(isFairplay ? ['sinf'] : null);
const audioContentType = keySystemOptions.audioContentType;
const audioRobustness = keySystemOptions.audioRobustness;
const videoContentType = keySystemOptions.videoContentType;
const videoContentType = keySystemOptions.videoContentType ||
// fairplay requires an explicit videoCapabilities/videoContentType
(isFairplay ? 'video/mp4' : null);
const videoRobustness = keySystemOptions.videoRobustness;
const persistentState = keySystemOptions.persistentState;

Expand Down Expand Up @@ -52,6 +64,10 @@ export const getSupportedConfigurations = (keySystemOptions) => {
supportedConfiguration.persistentState = persistentState;
}

if (initDataTypes) {
supportedConfiguration.initDataTypes = initDataTypes;
}

return [supportedConfiguration];
};

Expand All @@ -62,7 +78,7 @@ export const getSupportedKeySystem = (keySystems) => {
let promise;

Object.keys(keySystems).forEach((keySystem) => {
const supportedConfigurations = getSupportedConfigurations(keySystems[keySystem]);
const supportedConfigurations = getSupportedConfigurations(keySystem, keySystems[keySystem]);

if (!promise) {
promise =
Expand All @@ -84,8 +100,10 @@ export const makeNewRequest = (requestOptions) => {
options,
getLicense,
removeSession,
eventBus
eventBus,
contentId
} = requestOptions;

const keySession = mediaKeys.createSession();

eventBus.trigger('keysessioncreated');
Expand All @@ -97,7 +115,8 @@ export const makeNewRequest = (requestOptions) => {
if (event.messageType !== 'license-request' && event.messageType !== 'license-renewal') {
return;
}
getLicense(options, event.message)

getLicense(options, event.message, contentId)
.then((license) => {
resolve(keySession.update(license));
})
Expand Down Expand Up @@ -192,29 +211,27 @@ export const addSession = ({
initData,
options,
getLicense,
contentId,
removeSession,
eventBus
}) => {
if (video.mediaKeysObject) {
return makeNewRequest({
mediaKeys: video.mediaKeysObject,
initDataType,
initData,
options,
getLicense,
removeSession,
eventBus
});
}

video.pendingSessionData.push({
const sessionData = {
initDataType,
initData,
options,
getLicense,
removeSession,
eventBus
});
eventBus,
contentId
};

if (video.mediaKeysObject) {
sessionData.mediaKeys = video.mediaKeysObject;
return makeNewRequest(sessionData);
}

video.pendingSessionData.push(sessionData);

return Promise.resolve();
};

Expand Down Expand Up @@ -261,7 +278,8 @@ export const addPendingSessions = ({
options: data.options,
getLicense: data.getLicense,
removeSession: data.removeSession,
eventBus: data.eventBus
eventBus: data.eventBus,
contentId: data.contentId
}));
}

Expand Down Expand Up @@ -292,10 +310,10 @@ export const defaultGetLicense = (keySystemOptions) => (emeOptions, keyMessage,
}, httpResponseHandler(callback, true));
};

const promisifyGetLicense = (getLicenseFn, eventBus) => {
return (emeOptions, keyMessage) => {
const promisifyGetLicense = (keySystem, getLicenseFn, eventBus) => {
return (emeOptions, keyMessage, contentId) => {
return new Promise((resolve, reject) => {
getLicenseFn(emeOptions, keyMessage, (err, license) => {
const callback = function(err, license) {
if (eventBus) {
eventBus.trigger('licenserequestattempted');
}
Expand All @@ -305,7 +323,13 @@ const promisifyGetLicense = (getLicenseFn, eventBus) => {
}

resolve(license);
});
};

if (isFairplayKeySystem(keySystem)) {
getLicenseFn(emeOptions, contentId, new Uint8Array(keyMessage), callback);
} else {
getLicenseFn(emeOptions, keyMessage, callback);
}
});
};
};
Expand All @@ -315,14 +339,36 @@ const standardizeKeySystemOptions = (keySystem, keySystemOptions) => {
keySystemOptions = { url: keySystemOptions };
}

if (!keySystemOptions.url && keySystemOptions.licenseUri) {
keySystemOptions.url = keySystemOptions.licenseUri;
}

if (!keySystemOptions.url && !keySystemOptions.getLicense) {
throw new Error('Neither URL nor getLicense function provided to get license');
throw new Error(`Missing url/licenseUri or getLicense in ${keySystem} keySystem configuration.`);
}

const isFairplay = isFairplayKeySystem(keySystem);

if (isFairplay && keySystemOptions.certificateUri && !keySystemOptions.getCertificate) {
keySystemOptions.getCertificate = defaultFairplayGetCertificate(keySystemOptions);
}

if (isFairplay && !keySystemOptions.getCertificate) {
throw new Error(`Missing getCertificate or certificateUri in ${keySystem} keySystem configuration.`);
}

if (isFairplay && !keySystemOptions.getContentId) {
keySystemOptions.getContentId = defaultFairplayGetContentId;
}

if (keySystemOptions.url && !keySystemOptions.getLicense) {
keySystemOptions.getLicense = keySystem === 'com.microsoft.playready' ?
defaultPlayreadyGetLicense(keySystemOptions) :
defaultGetLicense(keySystemOptions);
if (keySystem === 'com.microsoft.playready') {
keySystemOptions.getLicense = defaultPlayreadyGetLicense(keySystemOptions);
} else if (isFairplay) {
keySystemOptions.getLicense = defaultFairplayGetLicense(keySystemOptions);
} else {
keySystemOptions.getLicense = defaultGetLicense(keySystemOptions);
}
}

return keySystemOptions;
Expand All @@ -338,6 +384,21 @@ export const standard5July2016 = ({
eventBus
}) => {
let keySystemPromise = Promise.resolve();
const keySystem = keySystemAccess.keySystem;
let keySystemOptions;

// try catch so that we return a promise rejection
try {
keySystemOptions = standardizeKeySystemOptions(
keySystem,
options.keySystems[keySystem]
);
} catch (e) {
return Promise.reject(e);
}

const contentId = keySystemOptions.getContentId ?
keySystemOptions.getContentId(options, initData) : null;

if (typeof video.mediaKeysObject === 'undefined') {
// Prevent entering this path again.
Expand All @@ -347,16 +408,10 @@ export const standard5July2016 = ({
video.pendingSessionData = [];

let certificate;
let keySystemOptions;

keySystemPromise = new Promise((resolve, reject) => {
// save key system for adding sessions
video.keySystem = keySystemAccess.keySystem;

keySystemOptions = standardizeKeySystemOptions(
keySystemAccess.keySystem,
options.keySystems[keySystemAccess.keySystem]
);
video.keySystem = keySystem;

if (!keySystemOptions.getCertificate) {
resolve(keySystemAccess);
Expand Down Expand Up @@ -392,18 +447,17 @@ export const standard5July2016 = ({
}

return keySystemPromise.then(() => {
const {getLicense} = standardizeKeySystemOptions(
video.keySystem,
options.keySystems[video.keySystem]
);
// if key system has not been determined then addSession doesn't need getLicense
const getLicense = video.keySystem ?
promisifyGetLicense(keySystem, keySystemOptions.getLicense, eventBus) : null;

return addSession({
video,
initDataType,
initData,
options,
// if key system has not been determined then addSession doesn't need getLicense
getLicense: video.keySystem ? promisifyGetLicense(getLicense, eventBus) : null,
getLicense,
contentId,
removeSession,
eventBus
});
Expand Down
2 changes: 1 addition & 1 deletion src/fairplay.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ export const defaultGetCertificate = (fairplayOptions) => {
};
};

const defaultGetContentId = (emeOptions, initData) => {
export const defaultGetContentId = (emeOptions, initData) => {
return getHostnameFromUri(uint8ArrayToString(initData));
};

Expand Down
29 changes: 14 additions & 15 deletions src/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,18 @@ const onPlayerReady = (player, emeError) => {

setupSessions(player);

if (window.WebKitMediaKeys) {
if (window.MediaKeys) {
// Support EME 05 July 2016
// Chrome 42+, Firefox 47+, Edge, Safari 12.1+ on macOS 10.14+
player.tech_.el_.addEventListener('encrypted', (event) => {
// TODO convert to videojs.log.debug and add back in
// https://github.com/videojs/video.js/pull/4780
// videojs.log('eme', 'Received an \'encrypted\' event');
setupSessions(player);
handleEncryptedEvent(event, getOptions(player), player.eme.sessions, player.tech_)
.catch(emeError);
});
} else if (window.WebKitMediaKeys) {
const handleFn = (event) => {
// TODO convert to videojs.log.debug and add back in
// https://github.com/videojs/video.js/pull/4780
Expand Down Expand Up @@ -278,18 +289,6 @@ const onPlayerReady = (player, emeError) => {
}
});

} else if (window.MediaKeys) {
// Support EME 05 July 2016
// Chrome 42+, Firefox 47+, Edge, Safari 12.1+ on macOS 10.14+
player.tech_.el_.addEventListener('encrypted', (event) => {
// TODO convert to videojs.log.debug and add back in
// https://github.com/videojs/video.js/pull/4780
// videojs.log('eme', 'Received an \'encrypted\' event');
setupSessions(player);
handleEncryptedEvent(event, getOptions(player), player.eme.sessions, player.tech_)
.catch(emeError);
});

} else if (window.MSMediaKeys) {
// IE11 Windows 8.1+
// Since IE11 doesn't support promises, we have to use a combination of
Expand Down Expand Up @@ -364,7 +363,7 @@ const eme = function(options = {}) {

setupSessions(player);

if (player.tech_.el_.setMediaKeys) {
if (window.MediaKeys) {
handleEncryptedEvent(mockEncryptedEvent, mergedEmeOptions, player.eme.sessions, player.tech_)
.then(() => callback())
.catch((error) => {
Expand All @@ -373,7 +372,7 @@ const eme = function(options = {}) {
emeError(error);
}
});
} else if (player.tech_.el_.msSetMediaKeys) {
} else if (window.MSMediaKeys) {
const msKeyHandler = (event) => {
player.tech_.off('mskeyadded', msKeyHandler);
player.tech_.off('mskeyerror', msKeyHandler);
Expand Down
2 changes: 1 addition & 1 deletion src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const stringToUint16Array = (string) => {
};

export const uint8ArrayToString = (array) => {
return String.fromCharCode.apply(null, new Uint16Array(array.buffer));
return String.fromCharCode.apply(null, new Uint8Array(array.buffer || array));
};

export const getHostnameFromUri = (uri) => {
Expand Down
Loading

0 comments on commit c912bda

Please sign in to comment.