fix(vlc): prevent crashes with pip & cast

This commit is contained in:
2026-07-30 13:44:27 +02:00
parent cebe97f168
commit 77a8b2337d
3 changed files with 26 additions and 5 deletions
@@ -279,7 +279,7 @@ class OmniPlayer(
override var playbackRate by mainThreadProperty(
get = { player.playbackParameters.speed.toDouble() },
set = { value -> player.setPlaybackSpeed(value.toFloat().coerceAtLeast(0f)) }
set = { value -> player.setPlaybackSpeed(value.toFloat().coerceAtLeast(0.01f)) }
)
override var muted by mainThreadProperty(
@@ -219,6 +219,11 @@ class OmniView(val context: ThemedReactContext) :
return
}
if (boundPlayer?.isCasting == true) {
clearPictureInPictureParams()
return
}
val autoEnterEnabled =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.S &&
autoPip == true &&
@@ -242,9 +247,18 @@ class OmniView(val context: ThemedReactContext) :
)
}
private fun clampedAspectRatio(width: Int, height: Int): Rational {
val minRatio = 0.42
val maxRatio = 2.38
val ratio = width.toDouble() / height.toDouble()
if (ratio in minRatio..maxRatio) return Rational(width, height)
val clamped = ratio.coerceIn(minRatio, maxRatio)
return Rational((clamped * 1000).toInt(), 1000)
}
private fun buildPipParams(autoEnterEnabled: Boolean): PictureInPictureParams {
val aspectRatio = if (surfaceView.width > 0 && surfaceView.height > 0) {
Rational(surfaceView.width, surfaceView.height)
clampedAspectRatio(surfaceView.width, surfaceView.height)
} else {
Rational(16, 9)
}
@@ -97,9 +97,11 @@ class VlcPlayer(ctx: Context) :
private var mediaItems: List<MediaItem> = emptyList()
private var currentMediaItemIndex: Int = INDEX_UNSET
private var currentTrackSelectionParameters = TrackSelectionParameters.Builder().build()
@Volatile
private var playerError: PlaybackException? = null
private var playlistMetadata: MediaMetadata = MediaMetadata.EMPTY
private var userInitiatedTransition: Boolean = false
@Volatile
private var cachedBufferedPosition: Long = 0L
private var boundSurfaceView: SurfaceView? = null
@@ -467,7 +469,11 @@ class VlcPlayer(ctx: Context) :
override fun getShuffleModeEnabled(): Boolean = false
override fun isLoading() = player.playerState == IMedia.State.Opening
override fun isLoading(): Boolean {
val state = playbackState
if (state == STATE_IDLE || state == STATE_ENDED) return false
return player.playerState == IMedia.State.Opening
}
override fun seekTo(
mediaItemIndex: Int,
@@ -493,11 +499,11 @@ class VlcPlayer(ctx: Context) :
override fun getSeekForwardIncrement(): Long = 15_000L
override fun setPlaybackParameters(playbackParameters: PlaybackParameters) {
player.rate = playbackParameters.speed.coerceAtLeast(0f)
player.rate = playbackParameters.speed.coerceAtLeast(0.01f)
}
override fun getPlaybackParameters(): PlaybackParameters =
PlaybackParameters(player.rate.coerceAtLeast(0f))
PlaybackParameters(player.rate.takeIf { it > 0f } ?: 1f)
override fun stop() {
player.stop()
@@ -505,6 +511,7 @@ class VlcPlayer(ctx: Context) :
override fun release() {
player.setEventListener(null)
listeners.release()
abandonAudioFocus()
player.stop()
clearVideoSurface()