Fix BehindLiveWindowException recovery on live HLS

The 'error is BehindLiveWindowException' check in onPlayerError was
always false (Kotlin compiler had been warning about it). The actual
exception is wrapped as the *cause* of an ExoPlaybackException, with
errorCode 1002 (ERROR_CODE_BEHIND_LIVE_WINDOW). This made the existing
recovery branch dead code, so when the live window slipped past the
player it would silently drop into STATE_IDLE and the user had to back
out of the video and reopen it.

Test the cause and the error code so the branch actually fires, and
snap to the live edge with seekToDefaultPosition() after both the
BehindLiveWindow and PlaylistStuckException reloads so the user lands
where the player would naturally play.
This commit is contained in:
Simon Gardling
2026-05-01 00:17:06 -04:00
parent 7a6b185e9d
commit 4bb09ec92e
@@ -1013,14 +1013,21 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
protected open fun onPlayerError(error: PlaybackException) {
Logger.i(TAG, "onPlayerError error=$error error.errorCode=${error.errorCode} connectivityLoss, cause=${error.cause}");
if(error is BehindLiveWindowException) {
// BehindLiveWindowException is wrapped as the *cause* of an ExoPlaybackException, so
// checking `error is BehindLiveWindowException` is always false (compiler warns). Use
// both the cause and the dedicated error code 1002 (ERROR_CODE_BEHIND_LIVE_WINDOW)
// so we recover whether the exception bubbled up wrapped or as an error code only.
if (error.cause is BehindLiveWindowException
|| error.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW) {
Logger.e(TAG, "BehindLiveWindowException, " + error.message);
reloadMediaSource(true, true);
exoPlayer?.player?.seekToDefaultPosition();
return;
}
if(error != null && error.cause is HlsPlaylistTracker.PlaylistStuckException) {
Logger.e(TAG, "PlaylistStuckException");
reloadMediaSource(true, true);
exoPlayer?.player?.seekToDefaultPosition();
UIDialogs.toast("Live playback error, reloading..");
return;
}