ExoPlayer
ExoPlayer copied to clipboard
Getting ExoPlaybackException->IllegalArgumentException during setVideoSurface(null)
[REQUIRED] Issue description
Getting error while releasing surface:
main|E] EventLogger: playerFailed [4.80, 1.08, window=0, period=0]
com.google.android.exoplayer2.ExoPlaybackException: java.lang.IllegalArgumentException
at com.google.android.exoplayer2.t.handleMessage(ExoPlayerImplInternal.java:24)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:193)
at android.os.HandlerThread.run(HandlerThread.java:65)
Caused by: java.lang.IllegalArgumentException: null
at android.media.MediaCodec.native_setSurface(Native Method)
at android.media.MediaCodec.setOutputSurface(MediaCodec.java:1979)
at com.google.android.exoplayer2.video.MediaCodecVideoRenderer.a(MediaCodecVideoRenderer.java:176)
at com.google.android.exoplayer2.video.MediaCodecVideoRenderer.a(MediaCodecVideoRenderer.java:73)
at com.google.android.exoplayer2.video.MediaCodecVideoRenderer.a(MediaCodecVideoRenderer.java:57)
at com.google.android.exoplayer2.t.c(ExoPlayerImplInternal.java:9)
at com.google.android.exoplayer2.t.e(ExoPlayerImplInternal.java:4)
at com.google.android.exoplayer2.t.d(ExoPlayerImplInternal.java:50)
at com.google.android.exoplayer2.t.handleMessage(ExoPlayerImplInternal.java:4)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:193)
at android.os.HandlerThread.run(HandlerThread.java:65)
or
java.lang.IllegalStateException
at com.google.android.exoplayer2.t.handleMessage(ExoPlayerImplInternal.java:24)
at android.os.Handler.dispatchMessage(Handler.java:101)
at android.os.Looper.loop(Looper.java:164)
at android.os.HandlerThread.run(HandlerThread.java:65)
Caused by: java.lang.IllegalStateException: null
at android.media.MediaCodec.native_setSurface(Native Method)
at android.media.MediaCodec.setOutputSurface(MediaCodec.java:1954)
at com.google.android.exoplayer2.video.MediaCodecVideoRenderer.a(MediaCodecVideoRenderer.java:176)
at com.google.android.exoplayer2.video.MediaCodecVideoRenderer.a(MediaCodecVideoRenderer.java:73)
at com.google.android.exoplayer2.video.MediaCodecVideoRenderer.a(MediaCodecVideoRenderer.java:57)
at com.google.android.exoplayer2.t.c(ExoPlayerImplInternal.java:9)
at com.google.android.exoplayer2.t.e(ExoPlayerImplInternal.java:4)
at com.google.android.exoplayer2.t.d(ExoPlayerImplInternal.java:50)
at com.google.android.exoplayer2.t.handleMessage(ExoPlayerImplInternal.java:4)
at android.os.Handler.dispatchMessage(Handler.java:101)
at android.os.Looper.loop(Looper.java:164)
at android.os.HandlerThread.run(HandlerThread.java:65)
I'm not sure if it should be handled by the app, cause of integration specifics, or it can be workarounded with MediaCodeVideoRenderer.codecNeedsSetOutputSurfaceWorkaround
.
In other cases decoder errors are wrapped to MediaCodecVideoRenderer.VideoDecoderException
and it's easier to identify them and apply app-specific handling.
[REQUIRED] Reproduction steps
This is part of "tv input service" which adopts TIF on Android TV.
When TvInputService.Session.onSetSurface(null)
is called - this call routed to SimpleExoPlayer.setVideoSurface
.
Due TIF integration specifics - surface is owned by host app (Live TV/Live Channels) and "tv input service" does not own it's lifecycle.
[REQUIRED] Link to test content
non-applicable
[REQUIRED] A full bug report captured from the device
no full report, since issue is observed on user's devices through Crashlytics
[REQUIRED] Version of ExoPlayer being used
e267550d95a72ba7261eddad6dea8f8ce379e8e8
[REQUIRED] Device(s) and version(s) of Android being used
According to crashlytics devices distribution looks like: 56% Xiaomi 20% Droidlogic 8% Amlogic 4% fengmi 12% Other (12)
Some of them :
System: 4.9.113 (20190809)
Sdk: 28
Device: galilei
Product: galilei
Manufacturer: AZW Model: GTKing
Brand: Droidlogic
Model: X96Max_V311_P
Operating System Version: 9
Rooted: Yes
Brand: Droidlogic
Model: Tx5
Operating System Version: 9
Rooted: Yes
Brand: Amlogic
Model: TX5 Pro
Operating System Version: 8.1.0
Rooted: Yes
Brand: Xiaomi
Model: MiBox S
Operating System Version: 8.1.0
Rooted: No
Brand: Amlogic
Model: TX5 Pro
Operating System Version: 8.1.0
Rooted: Yes
Brand: NVIDIA
Model: SHIELD TV
Operating System Version: 9
Rooted: No
On first inspection, it appears this would be caused by MediaCodecVideoRenderer
calling setOutputSurface
with null. This appears to be impossible, however. There's only one call site and it's surround by a non-null check, here.
On closer inspection of android_media_MediaCodec_native_setSurface
in the Android platform, it looks like this would actually be caused by the following block:
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
return;
}
I'm not really sure how this happens though.
@andrewlewis - Any ideas? @stari4ek - Please can you deobfuscate the stack traces properly, so we can see the proper method names and line numbers? Please can you also give an indication of absolute crash numbers. It's impossible to gauge how to prioritize issues just from percentages adding up to 100.
Non-fatal Exception: java.lang.IllegalArgumentException
at android.media.MediaCodec.native_setSurface(MediaCodec.java)
at android.media.MediaCodec.setOutputSurface + 1979(MediaCodec.java:1979)
at com.google.android.exoplayer2.video.MediaCodecVideoRenderer.setOutputSurfaceV23 + 1158(MediaCodecVideoRenderer.java:1158)
at com.google.android.exoplayer2.video.MediaCodecVideoRenderer.setSurface + 563(MediaCodecVideoRenderer.java:563)
at com.google.android.exoplayer2.video.MediaCodecVideoRenderer.handleMessage + 529(MediaCodecVideoRenderer.java:529)
at com.google.android.exoplayer2.ExoPlayerImplInternal.deliverMessage + 976(ExoPlayerImplInternal.java:976)
at com.google.android.exoplayer2.ExoPlayerImplInternal.sendMessageToTarget + 947(ExoPlayerImplInternal.java:947)
at com.google.android.exoplayer2.ExoPlayerImplInternal.sendMessageInternal + 929(ExoPlayerImplInternal.java:929)
at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage + 363(ExoPlayerImplInternal.java:363)
at android.os.Handler.dispatchMessage + 102(Handler.java:102)
at android.os.Looper.loop + 193(Looper.java:193)
at android.os.HandlerThread.run + 65(HandlerThread.java:65)
Non-fatal Exception: java.lang.IllegalStateException
at android.media.MediaCodec.native_setSurface(MediaCodec.java)
at android.media.MediaCodec.setOutputSurface + 1954(MediaCodec.java:1954)
at com.google.android.exoplayer2.video.MediaCodecVideoRenderer.setOutputSurfaceV23 + 1158(MediaCodecVideoRenderer.java:1158)
at com.google.android.exoplayer2.video.MediaCodecVideoRenderer.setSurface + 563(MediaCodecVideoRenderer.java:563)
at com.google.android.exoplayer2.video.MediaCodecVideoRenderer.handleMessage + 529(MediaCodecVideoRenderer.java:529)
at com.google.android.exoplayer2.ExoPlayerImplInternal.deliverMessage + 976(ExoPlayerImplInternal.java:976)
at com.google.android.exoplayer2.ExoPlayerImplInternal.sendMessageToTarget + 947(ExoPlayerImplInternal.java:947)
at com.google.android.exoplayer2.ExoPlayerImplInternal.sendMessageInternal + 929(ExoPlayerImplInternal.java:929)
at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage + 363(ExoPlayerImplInternal.java:363)
at android.os.Handler.dispatchMessage + 101(Handler.java:101)
at android.os.Looper.loop + 164(Looper.java:164)
at android.os.HandlerThread.run + 65(HandlerThread.java:65)
One more a bit different, but with same steps. setSurface(null)
Non-fatal Exception: android.media.MediaCodec$CodecException: Error 0x80000000
at android.media.MediaCodec.native_setSurface(MediaCodec.java)
at android.media.MediaCodec.setOutputSurface + 1797(MediaCodec.java:1797)
at com.google.android.exoplayer2.video.MediaCodecVideoRenderer.setOutputSurfaceV23 + 1158(MediaCodecVideoRenderer.java:1158)
at com.google.android.exoplayer2.video.MediaCodecVideoRenderer.setSurface + 563(MediaCodecVideoRenderer.java:563)
at com.google.android.exoplayer2.video.MediaCodecVideoRenderer.handleMessage + 529(MediaCodecVideoRenderer.java:529)
at com.google.android.exoplayer2.ExoPlayerImplInternal.deliverMessage + 976(ExoPlayerImplInternal.java:976)
at com.google.android.exoplayer2.ExoPlayerImplInternal.sendMessageToTarget + 947(ExoPlayerImplInternal.java:947)
at com.google.android.exoplayer2.ExoPlayerImplInternal.sendMessageInternal + 929(ExoPlayerImplInternal.java:929)
at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage + 363(ExoPlayerImplInternal.java:363)
at android.os.Handler.dispatchMessage + 98(Handler.java:98)
at android.os.Looper.loop + 148(Looper.java:148)
at android.os.HandlerThread.run + 61(HandlerThread.java:61)
Brand: Skyworth
Model: Asia
Operating System Version: 6.0.1
Please can you also give an indication of absolute crash numbers. It's impossible to gauge how to prioritize issues just from percentages adding up to 100.
Stats for last month: "This issue has 1477 non-fatals affecting 675 users". (MAU is ~30k) It goes to playerFailed(), so no fatal crashes here.
It's hard to tell what exactly happens on device. Since it's TIF app, onSetSurface(null)
is called when user leaves "Live TV""Live Channels". Also there is a chance that device is going to sleep.
Timings:
01:19:53.384 PM main|D] Session: onSetSurface: [null]
01:19:53.416 PM main|D] EventLogger: surfaceSizeChanged [16.61, 20.84, window=0, period=0, 0, 0]
01:19:53.430 PM main|T] Session: onSetSurface: 51ms
01:19:53.443 PM main|E] EventLogger: playerFailed [16.63, 20.84, window=0, period=0]
com.google.android.exoplayer2.ExoPlaybackException: java.lang.IllegalArgumentException
at com.google.android.exoplayer2.t.handleMessage(ExoPlayerImplInternal.java:24)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:193)
at android.os.HandlerThread.run(HandlerThread.java:65)
Caused by: java.lang.IllegalArgumentException: null
at android.media.MediaCodec.native_setSurface(Native Method)
at android.media.MediaCodec.setOutputSurface(MediaCodec.java:1979)
Sorry for the delayed response. Do you know if there's any adverse effect on the user from what you're seeing here? Playback is failing with the error you've provided details about, but the user is exiting the playback anyway, so I wonder whether they'd even notice anything.
It's still not ideal, for example from a metrics perspective if these end up being logged as failed playbacks, but at this point I don't think we have a good theory as to what's happening here.
Yeah. This issue just needs special handling on the app's side to be sure that user experience does not degrade (do not show any UI notifications about an error).
The listed stack traces are very similar to the stack traces occurring during this issue: https://github.com/TeamNewPipe/NewPipe/issues/9023