-
Notifications
You must be signed in to change notification settings - Fork 133
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Call generateRequest BEFORE pushing any segment with PlayReady
Another day, another PlayReady-specific issue :/ A partner signalled to us that they weren't able to play a mix of unencrypted and encrypted content on any PlayReady devices. After investigation, it seems that calling `generateRequest` for the first time after clear segments are already present on a MSE `SourceBuffer` associated to the MediaSource linked to the corresponding media element immediately triggered an HTML5 `MEDIA_ERR_DECODE` error. We tried A LOT of work-arounds: - patching clear segments with a `tenc` box with a `0x0` key id to incite the CDM to understand that encrypted contents may be pushed in the future - Rewriting the pssh sent through the EME `generateRequest` API so that it is barebone to limit weird PlayReady edge cases. - Replacing those stream clear segments' with those in our demo page, just to check that the clear segments were not at fault here - Waiting more time between the association of a MediaKeys to the media element and pushing the first segments. None of those actions had an effect. However, what had an effect, was to call the `generateRequest` API BEFORE buffering any segment yet AFTER attaching the MediaKeys (and perhaps MediaSource) to the media element. So this commit does just that, communicating dummy initialization data for a session that will be closed directly after. Note that we already do a fake `generateRequest` on Edge Chromium with Playready since #1434, yet this test was not sufficient, seemingly because it is performed BEFORE MediaKeys attachment. Note that this commit fixes the clear -> encrypted issues our partner were having, but we're unsure yet of if it fixes the encrypted -> clear issues (and I have good reasons to think it does not). So, uh, yeah, PlayReady seems to keep being hard-at-work giving us challenges and head-scratchers.
- Loading branch information
1 parent
74b603a
commit d5ba127
Showing
4 changed files
with
72 additions
and
7 deletions.
There are no files selected for viewing
19 changes: 19 additions & 0 deletions
19
src/compat/should_call_generate_request_before_buffering_media.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/** | ||
* (2024-07-23) We noticed issues with most devices relying on PlayReady when | ||
* playing some contents with mix encrypted and clear contents (not with | ||
* Canal+ own contents weirdly enough, yet with multiple other contents | ||
* encoded/packaged differently). | ||
* The issue fixed itself when we called the | ||
* `MediaKeySession.prototype.generateRequest` EME API **BEFORE** any segment | ||
* was buffered. | ||
* @param {string} keySystem - The key system in use. | ||
* @returns {boolean} | ||
*/ | ||
export default function shouldCallGenerateRequestBeforeBufferingMedia( | ||
keySystem: string, | ||
): boolean { | ||
if (keySystem.indexOf("playready") !== -1) { | ||
return true; | ||
} | ||
return false; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
33 changes: 33 additions & 0 deletions
33
src/main_thread/decrypt/utils/perform_fake_generate_request.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { closeSession } from "../../../compat/eme"; | ||
import type { ICustomMediaKeys } from "../../../compat/eme"; | ||
import { | ||
DUMMY_PLAY_READY_HEADER, | ||
generatePlayReadyInitData, | ||
} from "../../../compat/generate_init_data"; | ||
import log from "../../../log"; | ||
|
||
/** | ||
* The EME is badly implemented on many devices, leading us toward the need to | ||
* perform some heavy work-arounds. | ||
* | ||
* A frequent one is to call the `MediaKeySession.prototype.generateRequest` API | ||
* at some point for dummy data an see if it fails (or not, sometimes just | ||
* calling it is important). | ||
* | ||
* This method does just that, resolving the returned Promise if the | ||
* `generateRequest` call could be performed and succeeded or rejecting in other | ||
* cases. | ||
* @param {MediaKeys} mediaKeys | ||
* @returns {Promise} | ||
*/ | ||
export default async function performFakeGenerateRequest( | ||
mediaKeys: MediaKeys | ICustomMediaKeys, | ||
): Promise<void> { | ||
const session = mediaKeys.createSession(); | ||
const initData = generatePlayReadyInitData(DUMMY_PLAY_READY_HEADER); | ||
await session.generateRequest("cenc", initData); | ||
closeSession(session).catch((err) => { | ||
const error = err instanceof Error ? err : new Error("Unknown Error"); | ||
log.warn("DRM: unable to close fake MediaKeySession", error); | ||
}); | ||
} |