question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Failure on some Android 11 devices when switching from secure decoder to a different decoder

See original GitHub issue

Reproduction Steps

Set SimpleExoPlayer to play a MediaItem configured to play using Widevine, with M3U8 mimetype. Email coming with replacements for <snip> values.

Exoplayer version: 2.13.2 Android Version: 11

Devices

  • Samsung S20 FE 5G (Qualcomm and Exynos chipsets both repro)
  • Samsung Notes - (tablet)
  • Samsung Galaxy Note - (phone)
  • Samsung Galaxy Note Ultra OS

Basic Reproduction Case:

val player = SimpleExoPlayer.Builder(applicationContext).build()
val mediaItem = MediaItem.Builder()
            .setUri(<snip>)
            .setMimeType(MimeTypes.APPLICATION_M3U8)
            .setDrmUuid(C.WIDEVINE_UUID)
            .setDrmLicenseUri(<snip>)
            .setDrmLicenseRequestHeaders(mutableMapOf(
                <snip>
            ))
            .build()

player.addMediaItem(mediaItem)
player.prepare()
player.play()

The content piece is a 45-second snippet of a live playlist setup as VOD. It is 30 seconds of the content which is Widevine CTR encrypted content with a 15-second ad. On the switch to the ad, there is a discontinuity and switch to unencrypted content.

On the failure case:

I/ACodec: [OMX.Exynos.avc.dec] Now Loaded
D/SurfaceUtils: connecting to surface 0x71e621ca70, reason connectToSurface
E/SurfaceUtils: Failed to connect to surface 0x71e621ca70, err -22
E/MediaCodec: nativeWindowConnect returned an error: Invalid argument (-22)

When it does not fail, there is no failure to connect the surface with the code -22.

This does not occur on all Android 11 devices. And even on the Samsung devices we have seen it occur on, not all of them have a 100% reproduction rate. On a device with a high reproduction rate, we’ve also discovered that setting a logging breakpoint in SynchronousMediaCodecAdapter on the codec.configure line eliminates the issue.

Additionally, calling setDrmSessionForClearPeriods(true) on the MediaItem does resolve the error. But raises the question of what other issues this will potentially cause.

Content to follow in email, along with complete Logcat output from both successful and failure cases.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:1
  • Comments:14 (10 by maintainers)

github_iconTop GitHub Comments

2reactions
icbakercommented, Dec 8, 2021

The commit above works around this issue by retrying a failed decoder creation after a short delay.

2reactions
icbakercommented, Aug 9, 2021

Adding some more info from some brief investigations, and responding to @cdongieux’s request for additional workaround suggestions in https://github.com/google/ExoPlayer/issues/9250#issuecomment-892462112:

I experimented with a couple of hacks in MediaCodecVideoRenderer and found they both resolve this issue. We’d like to understand exactly what’s going wrong inside the framework before submitting any workaround like this to the library, but you’re free to make the changes to a local copy of the library (or subclass MediaCodecVideoRenderer). In both cases I overrode MediaCodecRenderer#releaseCodec in MediaCodecVideoRenderer:

  1. Based on @itsjamie’s observations above that it’s a timing issue I tried just adding naive Thread.sleep() calls after MediaCodec#release() and before we try and set the surface onto the new codec. In my overriding implementation of MediaCodecVideoRenderer#releaseCodec() I called super.releaseCodec() and then Thread.sleep(60). For the content I was using I found that 60ms was long enough, but 45ms wasn’t. Obviously this is really hacky, and hard-coding sleep times like this isn’t really a reliable or production-ready approach. I include it here mainly for completeness.
  2. Instead of sleeping after the release, I tried setting a dummy surface before the release. MediaCodecVideoRenderer already has a dummySurface field we can use (it might be null and need initializing). Calling getCodec().setOutputSurface(dummySurface) before super.releaseCodec() resolved the issue for me.
Read more comments on GitHub >

github_iconTop Results From Across the Web

MediaCodec - Android Developers
MediaCodec class can be used to access low-level media codecs, i.e. encoder/decoder components. It is part of the Android low-level multimedia support ...
Read more >
Barcode Input - Zebra Technologies TechDocs
This permits the Bluetooth scanner to scan data into the Android device inserted in ... However, to configure decoders, reader parameters and other...
Read more >
Use your phone's built-in security key - Google Support
Make sure Bluetooth is turned on for both devices. · Sign in on the new device: · Check your Android phone for a...
Read more >
Requirements for Multimedia Apps (Fire TV)
For Fire TV applications to interact harmoniously with other ... Requirement 5.1: Limitations on Secure Decoders; Requirement 5.2: Release ...
Read more >
FFmpeg
Converting video and audio has never been so easy. ... Some of the highlights: ... CrystalHD decoder moved to new decode API; configure...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found