shaka-player
shaka-player copied to clipboard
Auto-selection of hardware vs software DRM
Have you read the FAQ and checked for duplicate open issues? Yes
Is your feature request related to a problem? Please describe. No
Describe the solution you'd like Support hardware secure CDM playback in Chrome for Windows with documentation.
Describe alternatives you've considered Whether Chrome can support PlayReady like Edge with "hardware secure CDM".
Additional context In Chrome 99, enabling "Hardware Secure Decryption" in chrome://flags will show "Google Widevine Windows CDM" in chrome://components. Does shaka player support this CDM?
👋 There are no reasons Shaka shouldn't support L1 implementation of Widevine (already does on Android w/ Chrome)
I believe that once enabled, L1 support on Windows is triggered in software by setting robustness to HW_SECURE_ALL
. @xhwang-chromium, can you confirm? To trigger the L1 implementation where possible, should this be set for both audio and video, or just video?
We recommend to set video to be HW_SECURE_ALL
and audio to be HW_SECURE_CRYPTO
. But the L1 path will be selected when either is set.
Is there an api in shaka player to detect whether the CDM supports HW or SW? Or can shaka try HW first and fallback to SW? Thanks.
You could use this to detect what is the maximum level that is supported.
async function getWidevineRobustness () {
const robustnessLevels = [
'SW_SECURE_CRYPTO', // Widevine L3
'SW_SECURE_DECODE', // Widevine L3
'HW_SECURE_CRYPTO', // Widevine L2
'HW_SECURE_DECODE', // Widevine L1
'HW_SECURE_ALL', // Widevine L1
];
const videoTestConfig = [
{
videoCapabilities: [
{
contentType: 'video/mp4; codecs="avc1.42E01E"',
robustness: 'SW_SECURE_DECODE',
},
],
},
];
const audioTestConfig = [
{
audioCapabilities: [
{
contentType: 'audio/mp4;codecs="mp4a.40.2"',
robustness: 'SW_SECURE_DECODE',
},
],
},
];
let videoRobustness;
let audioRobustness;
for (let i = 0; i < robustnessLevels.length; i++) {
const level = robustnessLevels[i];
videoTestConfig[0].videoCapabilities[0].robustness = level;
try {
// eslint-disable-next-line no-await-in-loop
await navigator.requestMediaKeySystemAccess('com.widevine.alpha', videoTestConfig);
videoRobustness = level;
} catch (err) {}
}
for (let j = 0; j < robustnessLevels.length; j++) {
const level = robustnessLevels[j];
audioTestConfig[0].audioCapabilities[0].robustness = level;
try {
// eslint-disable-next-line no-await-in-loop
await navigator.requestMediaKeySystemAccess('com.widevine.alpha', audioTestConfig);
audioRobustness = level;
} catch (err) {}
}
return {
videoRobustness: videoRobustness,
audioRobustness: audioRobustness,
}
}
@xhwang-chromium or if anybody else knows, can you please comment on what are the system requirements for Widevine to leverage L1 on Windows?
I assume some form of Trusted Execution Environment is required, so only selected processors are suitable. Can you confirm?
Does operating system version itself play a role in this? Is presence of Trusted Platform Module (TPM) required as well?
As mentioned above Shaka supports hardware DRM, just through DRM configuration. There is no automatic selection of hardware vs software CDM, though. If not specified by the app, the default is up to the browser/platform.
Shaka could offer something in the future where we will automatically try HW first, then fall back to SW. I'll rename the issue to reflect this.
But before doing any work on this, we would need @xhwang-chromium to confirm is this is even necessary. If no robustness is specified, will Chrome choose the L1 CDM by default if available, and L3 otherwise? Or would L3 always be used by default?
Re https://github.com/shaka-project/shaka-player/issues/4013#issuecomment-1110579710. For Chrome browser we only support 'SW_SECURE_CRYPTO' (on Android), 'SW_SECURE_DECODE' and 'HW_SECURE_ALL'
. So querying for the following would be sufficient. Also, if L1 is preferred, it should be queried first, e.g.
const robustnessLevels = [
'HW_SECURE_ALL', // Widevine L1
'SW_SECURE_DECODE', // Widevine L3
'SW_SECURE_CRYPTO', // Widevine L3
]
Re https://github.com/shaka-project/shaka-player/issues/4013#issuecomment-1118998669. In short, for Widevine in Chrome, if no robustness is specified, we'll default to the lowest robustness, e.g. Widevine L3. This behavior is subject to change at any time so don't rely on it.
Here's our general recommendation on this topic:
Avoid Empty Robustness
What does the spec say?
http://w3c.github.io/encrypted-media/#idl-def-mediakeysystemmediacapability, emphasis added
Implementations MUST configure the CDM to support at least the robustness levels specified in the configuration of the MediaKeySystemAccess object used to create the MediaKeys object. Exact configuration of the CDM is implementation-specific, and implementations MAY configure the CDM to use the highest robustness level in the configuration even if a higher robustness level is available. If only the empty string is specified, implementations MAY be configured to use the lowest robustness level the implementation supports.
Applications SHOULD specify the robustness level(s) they require to avoid unexpected client incompatibilities.
What does Chrome do for empty robustness?
Chrome’s behavior is platform-dependent and is subject to change in the future. You may end up with the lowest level even though higher levels are available.
When an empty robustness is used, Chrome will show a warning message in the dev console.
It is recommended that a robustness level be specified. Not specifying the robustness level could result in unexpected behavior, potentially including failure to play.
What should applications do?
Always specify the robustness level(s) required (by the license server) and/or that would affect the streams selected. The application could specify multiple MediaKeySystemMediaCapability values with different robustness levels and make decisions based on which one is supported.
I enabled "Google Widevine Windows CDM" in Chrome Beta 102. When video robustness is SW_SECURE_DECODE and audio robustness is SW_SECURE_CRYPTO, it seems like this L1 CDM is still selected, instead of the L3 "Widevine Content Decryption Module". Widevine proxy generates EXTERNAL_LICENSE_ERROR with message "Missing ContentId within Pssh data for ExternalLicenseRequest". When the L1 CDM is disabled, the L3 CDM can play the content. The test content uses custom encryption keys and the keys are sent to the widevine proxy. However, test content with contend id in pssh and widevine keys (https://storage.googleapis.com/shaka-demo-assets/sintel-widevine/dash.mpd) can play when L1 CDM is enabled.
Do you have a repro page I can look at? Thanks!
Also, which codec did you query for?
Please try this repro:
https://shaka-player-demo.appspot.com/demo/#audiolang=en-US;textlang=en-US;uilang=en-US;panel=CUSTOM%20CONTENT;build=compiled
Manifest url: https://personal-data-2018.s3.amazonaws.com/bbb/b5.mpd
DRM custom license server url: https://widevine-proxy.appspot.com/proxy
Shaka reports error code 6007 when L1 CDM (Hardware Secure Decryption flag) is enabled. Widevine proxy error message is EXTERNAL_LICENSE_ERROR "Challenge type cannot be Unknown"
Codec: avc1.640029,mp4a.40.2
It's querying for HEVC w empty robustness (which will be defaulted to SW_* levels).
I think I know how this happened. I'll file a Chromium bug and fix it.
Again, it's always recommended not to have any empty robustness when querying Widevine capabilities.
@xhwang-chromium can you paste the link to the Chromium bug? Thanks!
Fix is here. The CL description has all the info. https://chromium-review.googlesource.com/c/chromium/src/+/3654750
Closing due to inactivity. If this is still an issue for you or if you have further questions, the OP can ask shaka-bot to reopen it by including @shaka-bot reopen
in a comment.