Skip to content

PlayerSurface (media3-ui-compose) can trigger IllegalArgumentException in MediaCodec.setOutputSurface #3011

@chosc0410

Description

@chosc0410

Version

Media3 1.9.0

More version details

Environment:

  • media3-ui-compose 1.9.0
  • Jetpack Compose
  • Surface type: SURFACE_TYPE_TEXTURE_VIEW
  • Device: low-end devices reproduce more frequently

Summary:
When using PlayerSurface with TextureView, we intermittently hit
ERROR_CODE_FAILED_RUNTIME_CHECK (1004) with IllegalArgumentException from
MediaCodec.setOutputSurface(). This seems to happen when the surface is
replaced/invalidated during rapid attach/detach.

Observed logs (verbatim):

2026-01-15 15:22:13.250 ... onPlayerErrorChanged: ERROR_CODE_FAILED_RUNTIME_CHECK, message: Unexpected runtime error
2026-01-15 15:22:13.250 ... onPlayerError: ERROR_CODE_FAILED_RUNTIME_CHECK
2026-01-15 15:22:13.250 ...   - errorCode: 1004
2026-01-15 15:22:13.250 ...   - message: Unexpected runtime error
2026-01-15 15:22:13.250 ...   - cause: java.lang.IllegalArgumentException

Stacktrace excerpt (verbatim):

java.lang.IllegalArgumentException
    at android.media.MediaCodec.native_setSurface(Native Method)
    at android.media.MediaCodec.setOutputSurface(MediaCodec.java:1954)
    at androidx.media3.exoplayer.mediacodec.SynchronousMediaCodecAdapter.setOutputSurface(SynchronousMediaCodecAdapter.java:193)
    at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.setOutputSurfaceV23(MediaCodecVideoRenderer.java:2405)
    at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.setOutputSurface(MediaCodecVideoRenderer.java:2393)
    at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.setOutput(MediaCodecVideoRenderer.java:1267)
    at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.handleMessage(MediaCodecVideoRenderer.java:1175)
    at androidx.media3.exoplayer.RendererHolder.setVideoOutput(RendererHolder.java:817)
    at androidx.media3.exoplayer.ExoPlayerImplInternal.setVideoOutputInternal(ExoPlayerImplInternal.java:1910)
    at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:739)

Repro steps:

  1. Use PlayerSurface in Compose with SURFACE_TYPE_TEXTURE_VIEW
  2. Show videos in a scrolling list (fast scroll triggers frequent attach/detach)
  3. Observe intermittent IllegalArgumentException in setOutputSurface

Code sample:

@Composable
fun VideoPlayerContent(...) {
    PlayerSurface(
        player = player,
        surfaceType = SURFACE_TYPE_TEXTURE_VIEW,
        modifier = Modifier.fillMaxSize()
    )
}

Analysis:
We inspected PlayerSurfaceKt.class (1.9.0) and found:

  • DisposableEffect onDispose only removes Player.Listener (no clearVideoSurface/stop)
  • AndroidView is used but there is no onRelease hook to clear player before view detaches
  • clearVideoView happens via LaunchedEffect (not ordered before view removal)

This can cause MediaCodec.setOutputSurface to receive an invalid or already-destroyed surface.

Expected:
PlayerSurface should guarantee that player is cleared/stopped before the underlying TextureView surface is replaced/detached, or provide a hook to enforce this order.

Potential fix ideas:

  • Provide onRelease/onDispose hook to clear surface before AndroidView detaches
  • Ensure clearVideoView is called synchronously before view removal
  • Allow custom SurfaceTextureListener or a “defer release” option for TextureView

Devices that reproduce the issue

Samsung Galaxy S8 running Android 9

Devices that do not reproduce the issue

Samsung Galaxy S24+ running Android 16

Reproducible in the demo app?

No

Reproduction steps

Repro steps:

  1. Use PlayerSurface in Compose with SURFACE_TYPE_TEXTURE_VIEW
  2. Show videos in a scrolling list (fast scroll triggers frequent attach/detach)
  3. Observe intermittent IllegalArgumentException in setOutputSurface

Expected result

Expected:
PlayerSurface should guarantee that player is cleared/stopped before the underlying TextureView surface is replaced/detached, or provide a hook to enforce this order.

Actual result

When using PlayerSurface with TextureView, we intermittently hit
ERROR_CODE_FAILED_RUNTIME_CHECK (1004) with IllegalArgumentException from
MediaCodec.setOutputSurface(). This seems to happen when the surface is
replaced/invalidated during rapid attach/detach.

And the video did not play.

Observed logs (verbatim):

2026-01-15 15:22:13.250 ... onPlayerErrorChanged: ERROR_CODE_FAILED_RUNTIME_CHECK, message: Unexpected runtime error
2026-01-15 15:22:13.250 ... onPlayerError: ERROR_CODE_FAILED_RUNTIME_CHECK
2026-01-15 15:22:13.250 ...   - errorCode: 1004
2026-01-15 15:22:13.250 ...   - message: Unexpected runtime error
2026-01-15 15:22:13.250 ...   - cause: java.lang.IllegalArgumentException

Stacktrace excerpt (verbatim):

java.lang.IllegalArgumentException
    at android.media.MediaCodec.native_setSurface(Native Method)
    at android.media.MediaCodec.setOutputSurface(MediaCodec.java:1954)
    at androidx.media3.exoplayer.mediacodec.SynchronousMediaCodecAdapter.setOutputSurface(SynchronousMediaCodecAdapter.java:193)
    at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.setOutputSurfaceV23(MediaCodecVideoRenderer.java:2405)
    at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.setOutputSurface(MediaCodecVideoRenderer.java:2393)
    at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.setOutput(MediaCodecVideoRenderer.java:1267)
    at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.handleMessage(MediaCodecVideoRenderer.java:1175)
    at androidx.media3.exoplayer.RendererHolder.setVideoOutput(RendererHolder.java:817)
    at androidx.media3.exoplayer.ExoPlayerImplInternal.setVideoOutputInternal(ExoPlayerImplInternal.java:1910)
    at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:739)

Media

Not applicable.

Repro by any video url

Bug Report

Metadata

Metadata

Assignees

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions