-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Prevent error msg: 'Unrecoverable player error occurred' while playin…
…g video during rotation (#6502) Playing a video in VideoDetailFragment and rotating the screen to landscape (back and forth more often) can trigger this error message. Especially if rotation for whatever reason takes long or playing a high resolution (1080p) video. The underlying logcat error messages: 05-12 16:38:38.251 24920 26037 E Surface : getSlotFromBufferLocked: unknown buffer: 0x923fc810 05-12 16:38:38.251 24920 26037 W ACodec : [OMX.qcom.video.decoder.avc] can not return buffer 35 to native window The problem is that that Exoplayer is trying to write to our -- during rotation -- no longer existant (VideoDetailFragment) SurfaceView. Solution: Implementing SurfaceHolder.Callback and using DummySurface we can now handle 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 can set a DummySurface. Although it only works on API >= 23. Result: we get a little video interruption (audio is still fine) but we won't get the 'Unrecoverable player error occurred' error message. This implementation is based on and more background information: 'ExoPlayer stuck in buffering after re-adding the surface view a few time 2703' -> exoplayer fix suggestion link google/ExoPlayer#2703 (comment)
- Loading branch information
1 parent
d6e0bd8
commit 2a68475
Showing
2 changed files
with
101 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
62 changes: 62 additions & 0 deletions
62
app/src/main/java/org/schabi/newpipe/player/playback/SurfaceHolderCallback.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package org.schabi.newpipe.player.playback; | ||
|
||
import android.content.Context; | ||
import android.view.SurfaceHolder; | ||
|
||
import com.google.android.exoplayer2.SimpleExoPlayer; | ||
import com.google.android.exoplayer2.video.DummySurface; | ||
|
||
/** | ||
* Prevent error message: 'Unrecoverable player error occurred' | ||
* In case of rotation some users see this kind of an error which is preventable | ||
* having a Callback that handles the lifecycle of the surface. | ||
* <p> | ||
* 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. | ||
* Result: we get a little video interruption (audio is still fine) but we won't get the | ||
* 'Unrecoverable player error occurred' error message. | ||
* <p> | ||
* This implementation is based on: | ||
* 'ExoPlayer stuck in buffering after re-adding the surface view a few time #2703' | ||
* <p> | ||
* -> exoplayer fix suggestion link | ||
* https://github.com/google/ExoPlayer/issues/2703#issuecomment-300599981 | ||
*/ | ||
public final class SurfaceHolderCallback implements SurfaceHolder.Callback { | ||
|
||
private final Context context; | ||
private final SimpleExoPlayer player; | ||
private DummySurface dummySurface; | ||
|
||
public SurfaceHolderCallback(final Context context, final SimpleExoPlayer player) { | ||
this.context = context; | ||
this.player = player; | ||
} | ||
|
||
@Override | ||
public void surfaceCreated(final SurfaceHolder holder) { | ||
player.setVideoSurface(holder.getSurface()); | ||
} | ||
|
||
@Override | ||
public void surfaceChanged(final SurfaceHolder holder, | ||
final int format, | ||
final int width, | ||
final int height) { | ||
} | ||
|
||
@Override | ||
public void surfaceDestroyed(final SurfaceHolder holder) { | ||
if (dummySurface == null) { | ||
dummySurface = DummySurface.newInstanceV17(context, false); | ||
} | ||
player.setVideoSurface(dummySurface); | ||
} | ||
|
||
public void release() { | ||
if (dummySurface != null) { | ||
dummySurface.release(); | ||
dummySurface = null; | ||
} | ||
} | ||
} |