From a7c2da7ebb8d196d2e4d7ed23c707b416e3857e7 Mon Sep 17 00:00:00 2001 From: Luca Rosellini Date: Fri, 7 Aug 2026 09:24:45 +0200 Subject: [PATCH] fix: crash when opening a new video on media tunneling devices SurfaceHolderCallback handed the player a PlaceholderSurface of its own on surfaceDestroyed. MediaCodecVideoRenderer refuses to swap a surface onto a tunneled codec and releases it instead, so ours made the swap fail and the detach timed out. Pass null and let the renderer decide. --- .../org/schabi/newpipe/player/Player.java | 3 +-- .../playback/SurfaceHolderCallback.java | 21 +++---------------- 2 files changed, 4 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index e46818e41..58c75a4e3 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -5620,7 +5620,7 @@ private void setupVideoSurface() { cleanupVideoSurface(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // >=API23 - surfaceHolderCallback = new SurfaceHolderCallback(context, simpleExoPlayer); + surfaceHolderCallback = new SurfaceHolderCallback(simpleExoPlayer); binding.surfaceView.getHolder().addCallback(surfaceHolderCallback); final Surface surface = binding.surfaceView.getHolder().getSurface(); // ensure player is using an unreleased surface, which the surfaceView might not be @@ -5641,7 +5641,6 @@ private void cleanupVideoSurface() { if (binding != null) { binding.surfaceView.getHolder().removeCallback(surfaceHolderCallback); } - surfaceHolderCallback.release(); surfaceHolderCallback = null; } } diff --git a/app/src/main/java/org/schabi/newpipe/player/playback/SurfaceHolderCallback.java b/app/src/main/java/org/schabi/newpipe/player/playback/SurfaceHolderCallback.java index b02a9240d..bbc3a4636 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playback/SurfaceHolderCallback.java +++ b/app/src/main/java/org/schabi/newpipe/player/playback/SurfaceHolderCallback.java @@ -1,10 +1,8 @@ package org.schabi.newpipe.player.playback; -import android.content.Context; import android.view.SurfaceHolder; import androidx.media3.common.Player; -import androidx.media3.exoplayer.video.PlaceholderSurface; /** * Prevent error message: 'Unrecoverable player error occurred' @@ -12,7 +10,7 @@ * having a Callback that handles the lifecycle of the surface. *

* How?: In case we are no longer able to write to the surface eg. through rotation/putting in - * background we set set a DummySurface. Although it it works on API >= 23 only. + * background we clear the surface, and the player swaps in a placeholder one of its own. * Result: we get a little video interruption (audio is still fine) but we won't get the * 'Unrecoverable player error occurred' error message. *

@@ -24,12 +22,9 @@ */ public final class SurfaceHolderCallback implements SurfaceHolder.Callback { - private final Context context; private final Player player; - private PlaceholderSurface placeholderSurface; - public SurfaceHolderCallback(final Context context, final Player player) { - this.context = context; + public SurfaceHolderCallback(final Player player) { this.player = player; } @@ -47,16 +42,6 @@ public void surfaceChanged(final SurfaceHolder holder, @Override public void surfaceDestroyed(final SurfaceHolder holder) { - if (placeholderSurface == null) { - placeholderSurface = PlaceholderSurface.newInstanceV17(context, false); - } - player.setVideoSurface(placeholderSurface); - } - - public void release() { - if (placeholderSurface != null) { - placeholderSurface.release(); - placeholderSurface = null; - } + player.setVideoSurface(null); } }