MediaCodecRenderer crash on Pixel 2 when querying DRM keys
ExoPlayer Version
2.15.1
Devices that reproduce the issue
Pixel 2 on Android 11
Devices that do not reproduce the issue
all tested Huawei models all tested Samsung models Motorola Moto X Play Redmi Note 10 5G on Android 12 (it does on Android 11)
Reproducible in the demo app?
Not tested
Reproduction steps
The circumstances require additional player logic that parses usable DRM keys and therefore their associated tracks from a stream depending on license rules and device capabilities.
We have no reduced app with this logic that we could share with you, but hopefully the accompanying info and bugreport would be sufficient for an educated guess or answer as to what is going on.
Expected result
We are leveraging in our app MediaDrm.KeyStatus and onKeyStatusChange methods to filter out tracks from an adaptive stream that are unusable on given device, i.e. HD renditions with L1 restrictions on L3 devices.
In other words, if the device cannot play some tracks because their key status is anything but USABLE, the player should filter those out from the adaptive stream and keep and play only those where key status is USABLE.
The expected behavior is true on most tested devices and the implementation appears to work fine. However, we did run into an issue with Pixel 2 on Android 11, see below.
Actual result
ExoPlayer throws Failed to initialize decoder: OMX.qcom.video.decoder.avc.secure error during the initialization phase when DRM keys from the stream are being checked. The stream contains multiple DRM keys with different restrictions.
In logcat we are seeing a quick attempt to reconnect to surface and an interesting additional message E/SurfaceUtils: native window cannot handle protected buffers: the consumer should either be a hardware composer or support hardware protection so it likely has something to do with the problem.
It works fine if the stream has only one DRM key even on Pixel 2. Does each DRM key check allocate unique surface before actual playback?
Since we are still using ExoPlayer version 2.15.1, could this commit https://github.com/google/ExoPlayer/commit/07352a4585cd939805bc2dafe53166f02c7e9025 to version 2.17.0 fix our issue? We are asking beforehand as migrating to latest 2.18.1 would require a lot of work, se we would like to be sure by you hopefully confirming the theory.
FYI, we had similar issue also on Redmi Note 10 5G but upgrading to Android 12 fixed it, so it is definitely tied to specific models and their OS.
Media
Will be provided in the email.
Bug Report
- [X] You will email the zip file produced by
adb bugreportto [email protected] after filing this issue.
We have no reduced app with this logic that we could share with you, but hopefully the accompanying info and bugreport would be sufficient for an educated guess or answer as to what is going on.
I'm afraid it's not really possible for us to investigate without being able to reproduce the problem.
I understand the challenge, but you are not always able to replicate the same conditions being reported (issue on a specific device that you do not have in your labs, etc.] and that is why I believed you ask for adb bugreport to get a closer insight as to what happened. Didn't it prove useful in this case?
I can share via email with you apk of internal app we test new features with that can reproduce the problem on Pixel 2 but not sure how helpful it is going to be in your analysis. Please let me know if you want to give it a try.
If not, would you at least hazard a guess if https://github.com/google/ExoPlayer/commit/07352a4585cd939805bc2dafe53166f02c7e9025 might fix it?
It's very unlikely that linked commit is related to this issue. The symptoms of that problem are:
- It occurs when switching from encrypted content to encrypted or clear content.
- Whereas you report this problem occurs when startomg to play encrypted content from scratch.
- The logs contain a line like
E/SurfaceUtils: Failed to connect to surface 0x71e621ca70, err -22
Thank you for the feedback. Are the surface error messages somehow actionable from the app itself and do you think we can even affect the outcome from app layer? If it is a bug in the Pixel 2's platform, is there a workaround we can apply?
I did check already that it is not the L1 (HW_SECURE_ALL) license restriction itself for HD tracks as if I provide all video tracks encrypted in the stream with the same key associated with the L1 license and audio track with another key and its own L3 license rules, the device happily plays it. But once I add another group of video tracks with a different DRM key, the surface error is back.
In case you do not suggest anything more feasible, it seems to me that we will have to try to catch this specific error and filter the group of video tracks using one key out and retry with just the remaining video tracks encrypted with the second key. Since SD tracks with a L3 level license are safer to play, it would mean that users with such problematic devices (even though L1-capable) would never see HD quality. And I am sure that there will be more such devices, it was rather lucky that we managed to identify it already with a Pixel 2 device.
Just an update here, not sure what else has been fixed between ExoPlayer 2.15.1 and last versions if you think that https://github.com/google/ExoPlayer/commit/07352a4585cd939805bc2dafe53166f02c7e9025 does not have anything to do with it, but we have recently upgraded to 2.18.4 and the described issue in this ticket no longer occurs. Pixel 2 happily plays the content with 2.18.4 while the older version built with 2.15.1 still exhibits the problem.
We are glad even though we still have not actually managed to get to the bottom of the problem. Thank you.