Skip to content

[Bug] Fix decryption issue on legacy CDM (e.g. Tizen 3.0)#1656

Open
KunXi-Fox wants to merge 5 commits intocanalplus:devfrom
steve-taylor:feat/implement-force-reload-media-source
Open

[Bug] Fix decryption issue on legacy CDM (e.g. Tizen 3.0)#1656
KunXi-Fox wants to merge 5 commits intocanalplus:devfrom
steve-taylor:feat/implement-force-reload-media-source

Conversation

@KunXi-Fox
Copy link
Contributor

@KunXi-Fox KunXi-Fox commented Mar 17, 2025

This is a attempt fixes for issue: #1415

We observed a CDM issue on Tizen 3.0, the issue happens when playback starts from non-drm content and switch to drm protected content.

Turns out Tizen 3.0 CDM tries to decrypt the content by using the first init-segment appended to source buffer, if playback starts from non-drm segment, CDM will try to use the unencrypted init segment to decrypt the encrypted segment, which will eventually lead to a screen artifacts or blank screen.

re-create media source seems is the only way to fix this issue.

This PR is to introduce a new load video option reloadMediaSourceForFirstIncompatiblePeriodSwitch to make the user decide whether to enable the fixes. If so, rx-player will perform a reload media source action when:

  1. first period is non-drm protected
  2. first time period switch to drm-protected

@peaBerberian
Copy link
Collaborator

peaBerberian commented Mar 17, 2025

Hi @KunXi-Fox,

Thanks for the PR! It's always nice to see external contributions and the implementation makes sense :D

For the API, I'm wondering if we could perhaps be higher-level and provide an option like keySystems[].onEncryptionStatusChange: "reload".
This way the RxPlayer would be able to perform more optimizations. E.g. Period-preloading won't unnecessarily run if we know in advance that the next Period won't be playable without reloading.
Also, the application would not have there to handle the logic of what we call "reloading the MediaSource" which is a fairly low-level mechanism.

For the latter in worst scenarios, there is the reload API which also can reload the last content at the same position with the same options.

@KunXi-Fox
Copy link
Contributor Author

KunXi-Fox commented Mar 18, 2025

Hi @peaBerberian , Thanks for the feedback. I'm not very familiar with rx-player codebase, so my changes may not be proper one, that's why I put it as a draft and waiting for any feedback.

For more context, the issue only happens under this condition:

  1. Playback starts with non-drm protected period
  2. playback switch to drm protected period

keySystems[].onEncryptionStatusChange: "reload" Sounds good, the only concern is Tizen 3.0 issue not happens on every encryption change. keySystems[].onEncryptionStatusChange: "reload" could solve the issue, but it's not that "precision", , because:

  1. We only want to make a "reload" when ⬆️ condition matches
  2. Current "reload" method more like a destroy + re-open video, which takes more time, that's not what we want.

The perfect solution from my brain is:

  1. we have a flag let's call it enableLegacyDrmFix
  2. when the flag equals true, when playback starts from non-drm, we'll not pre-loading drm content (or loading and cache the buffer locally without append buffer)
  3. when first time switch to drm protected content, we perform a mediaSourceReload action and append drm protected buffer

Do you think it's a proper solution? If so, could you pls point me the right direction to implement it, I'm happy to make it happen. Thanks in advance!

@peaBerberian
Copy link
Collaborator

If we can pinpoint it to a specific device (Tizen 2017), we could even make it automatic and specific to this device without needing an option.

Generally the encryption status change at Period transitions - but it can also happen at track of even Representation transition technically, so there could be a lot of ways this could be implemented depending on if we want to handle all cases or only the most frequent ones.


To handle all possible cases: I guess we could create some logic somewhere in src/main_thread/init which catches information from the ContentDecryptor (the module handling DRM information) ) - and we'll also need to detect if playback already began without needing decryption (by listening to the playbackObserver and checking if any representation is encrypted?


To handle only at Period transitions: we'll have to update some code in the code handling Period transitions I guess, in: src/core/stream/orchestrator/stream_orchestrator.ts.
Though there are still many things to handle: detecting when it's the first transition clear->encrypted for example.


Alternatively, we could look at other solutions for this problem. E.g. I don't remember if pushing segments only once the license has been communicated fixes the issue? If it does, it may be much simpler to work-around by only pushing media segments once they are known to be decipherable (or clear) on that device.

This could be done in src/core/stream/representation/representation_stream.ts.

This has the advantage of still being able to pre-load Period and keep a smooth transition between them.


Though even in those, I'm unsure of what the extent of the issue is on Tizen. For example let's imagine that the audio is encrypted but not the video for a Period A, but the reverse once we transition to a Period B: Does the issue happen or are we good because we initialized the decryption logic?

@KunXi-Fox
Copy link
Contributor Author

Though even in those, I'm unsure of what the extent of the issue is on Tizen. For example let's imagine that the audio is encrypted but not the video for a Period A, but the reverse once we transition to a Period B: Does the issue happen or are we good because we initialized the decryption logic?

In our cases the audio + video was encrypted together, so ⬆️ scenario will not happens, so I can't tell, sorry for that.

@KunXi-Fox
Copy link
Contributor Author

Hi @peaBerberian baed on your suggestion, I revert the changes for expose reloadMediaSource API and add a config reloadMediaSourceForFirstIncompatiblePeriodSwitch and make the fixes determine the flag value inside the rx-player code base.

Could you please help review? Thanks.

@KunXi-Fox KunXi-Fox changed the title [Feat] Introduce reloadMediaSource method to allow user reload media source [Bug] Fix decryption issue on legacy CDM (e.g. Tizen 3.0) Mar 20, 2025
@KunXi-Fox KunXi-Fox force-pushed the feat/implement-force-reload-media-source branch from 7bce6e2 to b6a2e75 Compare March 26, 2025 07:15
@KunXi-Fox KunXi-Fox marked this pull request as ready for review March 26, 2025 07:17
@peaBerberian peaBerberian force-pushed the dev branch 2 times, most recently from 00fc806 to b7216b4 Compare April 15, 2025 18:14
@KunXi-Fox
Copy link
Contributor Author

Hi @peaBerberian , Could I please get this PR reviewed?

@peaBerberian
Copy link
Collaborator

The current implementation looks good and simple for the most usual case but I have some reservation before integrating it officially:

  1. In absolutes, encryption status change could even happen in-Period, such as a representation switch
  2. Technically, the first Period that is communicated to the StreamOrchestrator might not correspond to the first segments that are actually pushed or decoded in some rare conditions

Those are rarer cases, I think that inevitably people are going to encounter those and not understand why that option didn't work for their cases.

Though I get what it solves regarding mixed encryption on some devices and that's a real issue we see multiple applications have issue with.

Maybe I could see this being solved by giving the application the power to trigger that?
Letting the application do it seems less problematic to me because an application knows what kind of content it is going to encounter in a way we don't. But this may mean a more powerful API.


Current "reload" method more like a destroy + re-open video, which takes more time, that's not what we want.

I would think, without actually testing so I'm not 100% sure here, that the main difference in terms of timing between the reload API and what we here call "reloading the MediaSource" are:

  1. In "multithreading" mode, we reload the manifest in reload
  2. We may also be resetting some DRM stuff depending on the device and options (e.g. closeSessionsOnStop)

I don't know which step takes the main chunk of the time in your case (maybe it's both, maybe it's neither but some other thing), though both look solvable with some effort (we could save the last manifest worker-side, we could keep some option around to not reset DRM etc.)

@KunXi-Fox
Copy link
Contributor Author

Letting the application do it seems less problematic to me because an application knows what kind of content it is going to encounter in a way we don't. But this may mean a more powerful API.

Yeah, I agree with this. For this issue, I tried to solve it from application level via reload, but it's not perfect since:

  1. Currently I didn't found a proper event to detect period switching is happening, so the timing call reload is a little bit late, which means the user already saw the issue before we call reload.
  2. reload takes more time than we expected

So if we could expose the a event for period switching and an extra API for just reloading all segments, I think that's enough to solve this issue from application level.

@peaBerberian peaBerberian force-pushed the dev branch 8 times, most recently from 6d4fed2 to 9b856a5 Compare September 25, 2025 15:56
@peaBerberian peaBerberian force-pushed the dev branch 4 times, most recently from 6cfd206 to 1e55170 Compare October 13, 2025 20:54
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.

2 participants