mirror of
https://github.com/FluxaMedia/fluxa.git
synced 2026-08-18 13:05:56 +00:00
Fix libass relay renderer never activating for HTTP streams
Pre-extraction is skipped for non-local streams so embeddedNativeAssTracks is always empty, which meant embeddedSubtitle was always null, which meant the relay renderer was never assigned as the active renderer. Relay renderer should win whenever there is no external subtitle selected.
This commit is contained in:
parent
5254b5152f
commit
c58d1cb0d7
1 changed files with 41 additions and 4 deletions
|
|
@ -4,6 +4,7 @@ import android.content.Context
|
|||
import android.graphics.Bitmap
|
||||
import android.graphics.Canvas
|
||||
import android.net.Uri
|
||||
import android.os.SystemClock
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import androidx.compose.runtime.Composable
|
||||
|
|
@ -19,6 +20,7 @@ import androidx.media3.common.Player
|
|||
import androidx.media3.exoplayer.ExoPlayer
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.fluxa.app.player.ExternalSubtitleTrack
|
||||
import com.fluxa.app.player.LibassDebugLog
|
||||
import com.fluxa.app.player.MediaPlayerController
|
||||
import com.fluxa.app.player.MediaTrack
|
||||
import com.fluxa.app.player.MkvNativeAssExtractor
|
||||
|
|
@ -72,6 +74,10 @@ internal fun NativeLibassSubtitleOverlay(
|
|||
var localRenderer by remember { mutableStateOf<NativeLibassRenderer?>(null) }
|
||||
|
||||
LaunchedEffect(externalSubtitle?.url, embeddedSubtitle?.id) {
|
||||
LibassDebugLog.d(
|
||||
"overlay selection external=${externalSubtitle?.let { "${LibassDebugLog.urlSummary(it.url)} label=${it.label} lang=${it.language}" } ?: "<none>"} " +
|
||||
"embedded=${embeddedSubtitle?.let { "id=${it.id} label=${it.label} lang=${it.language} bytes=${it.assData.size} fonts=${it.fonts.size}" } ?: "<none>"}"
|
||||
)
|
||||
val previous = localRenderer
|
||||
localRenderer = null
|
||||
previous?.close()
|
||||
|
|
@ -83,19 +89,29 @@ internal fun NativeLibassSubtitleOverlay(
|
|||
fonts = embedded.fonts,
|
||||
fontsDir = context.filesDir.resolve("fonts").absolutePath
|
||||
)
|
||||
}.onFailure { e -> Log.w("NativeLibassOverlay", "Embedded renderer failed", e) }.getOrNull()
|
||||
}.onFailure { e ->
|
||||
Log.w("NativeLibassOverlay", "Embedded renderer failed", e)
|
||||
LibassDebugLog.w("overlay embedded renderer failed id=${embedded.id}", e)
|
||||
}.getOrNull()
|
||||
LibassDebugLog.d("overlay embedded renderer ${if (localRenderer != null) "ready" else "not ready"} id=${embedded.id}")
|
||||
return@LaunchedEffect
|
||||
}
|
||||
val url = externalSubtitle?.url ?: return@LaunchedEffect
|
||||
localRenderer = runCatching {
|
||||
val data = fetchSubtitleBytes(context, url)
|
||||
LibassDebugLog.d("overlay fetched external ASS bytes=${data.size} url=${LibassDebugLog.urlSummary(url)}")
|
||||
val fonts = MkvNativeAssExtractor.extractExternalFontHints(url)
|
||||
LibassDebugLog.d("overlay external font hints fonts=${fonts.size} url=${LibassDebugLog.urlSummary(url)}")
|
||||
NativeLibassRenderer.create(
|
||||
assData = data,
|
||||
fonts = fonts,
|
||||
fontsDir = context.filesDir.resolve("fonts").absolutePath
|
||||
)
|
||||
}.onFailure { e -> Log.w("NativeLibassOverlay", "External renderer failed", e) }.getOrNull()
|
||||
}.onFailure { e ->
|
||||
Log.w("NativeLibassOverlay", "External renderer failed", e)
|
||||
LibassDebugLog.w("overlay external renderer failed url=${LibassDebugLog.urlSummary(url)}", e)
|
||||
}.getOrNull()
|
||||
LibassDebugLog.d("overlay external renderer ${if (localRenderer != null) "ready" else "not ready"} url=${LibassDebugLog.urlSummary(url)}")
|
||||
}
|
||||
|
||||
DisposableEffect(Unit) {
|
||||
|
|
@ -106,9 +122,14 @@ internal fun NativeLibassSubtitleOverlay(
|
|||
}
|
||||
|
||||
val activeRenderer = when {
|
||||
embeddedSubtitle != null -> relayRenderer ?: localRenderer
|
||||
externalSubtitle != null -> localRenderer
|
||||
else -> null
|
||||
else -> relayRenderer ?: localRenderer
|
||||
}
|
||||
LaunchedEffect(activeRenderer, relayRenderer, localRenderer, externalSubtitle?.url, embeddedSubtitle?.id) {
|
||||
LibassDebugLog.d(
|
||||
"overlay activeRenderer=${activeRenderer != null} relayRenderer=${relayRenderer != null} localRenderer=${localRenderer != null} " +
|
||||
"external=${externalSubtitle != null} embedded=${embeddedSubtitle != null}"
|
||||
)
|
||||
}
|
||||
|
||||
AndroidView(
|
||||
|
|
@ -133,6 +154,9 @@ private class NativeLibassSubtitleView(context: Context) : View(context) {
|
|||
|
||||
var renderer: NativeLibassRenderer? = null
|
||||
set(value) {
|
||||
if (field !== value) {
|
||||
LibassDebugLog.d("overlay view renderer changed active=${value != null} view=${width}x$height attached=$isAttachedToWindow")
|
||||
}
|
||||
field = value
|
||||
if (isAttachedToWindow) postInvalidateOnAnimation()
|
||||
}
|
||||
|
|
@ -144,6 +168,8 @@ private class NativeLibassSubtitleView(context: Context) : View(context) {
|
|||
}
|
||||
|
||||
private var bitmap: Bitmap? = null
|
||||
private var lastDrawLogMs = 0L
|
||||
private var lastDrawHadPixels: Boolean? = null
|
||||
|
||||
private val playerListener = object : Player.Listener {
|
||||
override fun onIsPlayingChanged(isPlaying: Boolean) {
|
||||
|
|
@ -161,12 +187,14 @@ private class NativeLibassSubtitleView(context: Context) : View(context) {
|
|||
|
||||
override fun onAttachedToWindow() {
|
||||
super.onAttachedToWindow()
|
||||
LibassDebugLog.d("overlay view attached size=${width}x$height")
|
||||
player?.addListener(playerListener)
|
||||
postInvalidateOnAnimation()
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow()
|
||||
LibassDebugLog.d("overlay view detached")
|
||||
player?.removeListener(playerListener)
|
||||
bitmap?.recycle()
|
||||
bitmap = null
|
||||
|
|
@ -186,6 +214,15 @@ private class NativeLibassSubtitleView(context: Context) : View(context) {
|
|||
|
||||
val result = activeRenderer.render(activePlayer.currentPosition + subtitleDelayMs, targetBitmap)
|
||||
if (result > 0) canvas.drawBitmap(targetBitmap, 0f, 0f, null)
|
||||
val hasPixels = result > 0
|
||||
val now = SystemClock.elapsedRealtime()
|
||||
if (lastDrawHadPixels != hasPixels || now - lastDrawLogMs > 1_500L) {
|
||||
LibassDebugLog.d(
|
||||
"overlay draw positionMs=${activePlayer.currentPosition} delayMs=$subtitleDelayMs size=${width}x$height result=$result hasPixels=$hasPixels playing=${activePlayer.isPlaying} playWhenReady=${activePlayer.playWhenReady}"
|
||||
)
|
||||
lastDrawHadPixels = hasPixels
|
||||
lastDrawLogMs = now
|
||||
}
|
||||
|
||||
if (activePlayer.isPlaying || activePlayer.playWhenReady) {
|
||||
if (result == 0) postInvalidateDelayed(100) else postInvalidateOnAnimation()
|
||||
|
|
|
|||
Loading…
Reference in a new issue