Skip to content

Conversation

@peaBerberian
Copy link
Collaborator

@peaBerberian peaBerberian commented Mar 8, 2024

Issue

We noticed that the PlayStation 5 may have the HTMLMediaElement on which the content is played stop on a MEDIA_ERR_DECODE error if it encounters encrypted media data whose key is not usable due to policy restrictions (the most usual issue being non-respect of HDCP restrictions).

This is not an usual behavior, other platforms just do not attempt to decode the encrypted media data and stall the playback instead (which is a much preferable behavior for us as we have some advanced mechanism to restart playback when this happens).

To complexify even more, the RxPlayer learn of that error (through an "error" event) much later than after receiving the information that a key became undecipherable. The RxPlayer could thus already have performed several operations such as SourceBuffer.remove calls BEFORE it is aware that the media element is on error. Such operations will throw - at that time without any understood reason - which lead to a miscategorized fatal error by the RxPlayer.

Consequently, we have to specifically consider platforms with that fail-on-undecipherable-data issue, to perform a work-around in that case.

Work-around

The work-around found for now is to just directly cancel all streaming logic linked to a MediaSource as soon as the RxPlayer's ContentDecryptor (its module handling content decryption) signals about unusable keys, which should normally happen synchronously after the corresponding event is triggered by the browser.

To ensure this is done as soon as possible (because this is a race with the browser), this is performed in the ContentInitializer RxPlayer module, which is the module directly interfacing with the ContentDecryptor, with media element errors, and with the logic of creating MediaSource instances.
If we handled this in the StreamOrchestrator for example (which is better able to handle this scenario because it knows which segments have been buffered and are going to be buffered), we would have much more risk to "lose" the race with the browser here, as more RxPlayer modules will be involved as well as two threads and message-passing in a multithreaded scenario.

I'm not that satisfied with this solution though. Because a race is still going on between the browser and the RxPlayer, it may break in the future if we bring an asynchronicity (e.g. a round trip to the event loop) between the moment a decryption key becomes unusable and the moment we're reloading the MediaSource.

Perhaps a better solution would be to just let the corresponding MEDIA_ERR_DECODE happen, then determine heuristically if it had a good chance to happen due to the aforementioned decryption issue and reload in that case, but this is also difficult to implement.

@peaBerberian peaBerberian force-pushed the fix/reload-directly-on-undecipherable branch from e188aaf to 6d0f339 Compare March 8, 2024 11:13
Issue
-----

We noticed that the PlayStation 5 may have the HTMLMediaElement on which the
content is played stop on a `MEDIA_ERR_DECODE` error if it encounters
encrypted media data whose key is not usable due to policy restrictions (the
most usual issue being non-respect of HDCP restrictions).

This is not an usual behavior, other platforms just do not attempt to decode
the encrypted media data and stall the playback instead (which is a much
preferable behavior for us as we have some advanced mechanism to restart
playback when this happens).

Consequently, we have to specifically consider platforms with that
fail-on-undecipherable-data issue, to perform a work-around in that case.

Work-around
-----------

The work-around found for now is to just directly cancel all streaming
logic linked to a `MediaSource` as soon as the RxPlayer's
`ContentDecryptor` (its module handling content decryption) signals about
unusable keys, which should normally happen synchronously after the
corresponding event is triggered by the browser.

To ensure this is done as soon as possible (because this is a race with
the browser), this is performed in the `ContentInitializer` RxPlayer
module, which is the module directly interfacing with the
`ContentDecryptor`, with media element errors, and with the logic of
creating `MediaSource` instances.
If we handled this in the `StreamOrchestrator` for example (which is
better able to handle this scenario because it knows which segments have
been buffered and are going to be buffered), we would have much more risk
to "lose" the race with the browser here, as more RxPlayer modules will
be involved as well as two threads and message-passing in a multithreaded
scenario.

I'm not that satisfied with this solution though. Because a race is
still going on between the browser and the RxPlayer, it may break in the
future if we bring an asynchronicity (e.g. a round trip to the event
loop) between the moment a decryption key becomes unusable and the
moment we're reloading the `MediaSource`.

Perhaps a better solution would be to just let the corresponding
`MEDIA_ERR_DECODE` happen, then determine heuristically if it
had a good chance to happen due to the aforementioned decryption issue
and reload in that case, but this is also difficult to implement.
@peaBerberian peaBerberian force-pushed the fix/reload-directly-on-undecipherable branch from 6d0f339 to a95f738 Compare March 8, 2024 11:17
@peaBerberian peaBerberian added this to the 4.1.0 milestone Mar 11, 2024
@peaBerberian peaBerberian merged commit f02cc78 into dev Mar 11, 2024
@peaBerberian peaBerberian deleted the fix/reload-directly-on-undecipherable branch July 26, 2024 16:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants