mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-05-03 16:59:08 +00:00
test: libass overlay test
This commit is contained in:
parent
10b0f634f0
commit
88226ba127
3 changed files with 79 additions and 5 deletions
|
|
@ -45,6 +45,9 @@ import androidx.media3.ui.AspectRatioFrameLayout
|
||||||
import androidx.media3.ui.PlayerView
|
import androidx.media3.ui.PlayerView
|
||||||
import androidx.media3.ui.SubtitleView
|
import androidx.media3.ui.SubtitleView
|
||||||
import androidx.media3.ui.CaptionStyleCompat
|
import androidx.media3.ui.CaptionStyleCompat
|
||||||
|
import com.nuvio.app.R
|
||||||
|
import io.github.peerless2012.ass.media.kt.withAssSupport
|
||||||
|
import io.github.peerless2012.ass.media.widget.AssSubtitleView
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
|
|
@ -90,6 +93,10 @@ actual fun PlatformPlayerSurface(
|
||||||
val sanitizedSourceResponseHeaders = remember(sourceResponseHeaders) {
|
val sanitizedSourceResponseHeaders = remember(sourceResponseHeaders) {
|
||||||
sanitizePlaybackResponseHeaders(sourceResponseHeaders)
|
sanitizePlaybackResponseHeaders(sourceResponseHeaders)
|
||||||
}
|
}
|
||||||
|
val useLibass = playerSettings.useLibass
|
||||||
|
val libassRenderType = runCatching {
|
||||||
|
LibassRenderType.valueOf(playerSettings.libassRenderType)
|
||||||
|
}.getOrDefault(LibassRenderType.CUES)
|
||||||
|
|
||||||
val exoPlayer = remember(sourceUrl, sourceAudioUrl, sanitizedSourceHeaders, sanitizedSourceResponseHeaders) {
|
val exoPlayer = remember(sourceUrl, sourceAudioUrl, sanitizedSourceHeaders, sanitizedSourceResponseHeaders) {
|
||||||
val renderersFactory = DefaultRenderersFactory(context)
|
val renderersFactory = DefaultRenderersFactory(context)
|
||||||
|
|
@ -126,11 +133,6 @@ actual fun PlatformPlayerSurface(
|
||||||
useYoutubeChunkedPlayback = useYoutubeChunkedPlayback,
|
useYoutubeChunkedPlayback = useYoutubeChunkedPlayback,
|
||||||
)
|
)
|
||||||
|
|
||||||
val useLibass = playerSettings.useLibass
|
|
||||||
val libassRenderType = runCatching {
|
|
||||||
LibassRenderType.valueOf(playerSettings.libassRenderType)
|
|
||||||
}.getOrDefault(LibassRenderType.CUES)
|
|
||||||
|
|
||||||
val player = if (useLibass) {
|
val player = if (useLibass) {
|
||||||
ExoPlayer.Builder(context)
|
ExoPlayer.Builder(context)
|
||||||
.setTrackSelector(trackSelector)
|
.setTrackSelector(trackSelector)
|
||||||
|
|
@ -418,6 +420,11 @@ actual fun PlatformPlayerSurface(
|
||||||
this.resizeMode = resizeMode.toExoResizeMode()
|
this.resizeMode = resizeMode.toExoResizeMode()
|
||||||
setShutterBackgroundColor(android.graphics.Color.BLACK)
|
setShutterBackgroundColor(android.graphics.Color.BLACK)
|
||||||
playerViewRef = this
|
playerViewRef = this
|
||||||
|
syncLibassOverlay(
|
||||||
|
player = exoPlayer,
|
||||||
|
enabled = useLibass,
|
||||||
|
renderType = libassRenderType,
|
||||||
|
)
|
||||||
applySubtitleStyle(currentSubtitleStyle)
|
applySubtitleStyle(currentSubtitleStyle)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -426,6 +433,11 @@ actual fun PlatformPlayerSurface(
|
||||||
playerView.useController = useNativeController
|
playerView.useController = useNativeController
|
||||||
playerView.resizeMode = resizeMode.toExoResizeMode()
|
playerView.resizeMode = resizeMode.toExoResizeMode()
|
||||||
playerViewRef = playerView
|
playerViewRef = playerView
|
||||||
|
playerView.syncLibassOverlay(
|
||||||
|
player = exoPlayer,
|
||||||
|
enabled = useLibass,
|
||||||
|
renderType = libassRenderType,
|
||||||
|
)
|
||||||
playerView.applySubtitleStyle(currentSubtitleStyle)
|
playerView.applySubtitleStyle(currentSubtitleStyle)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
@ -456,6 +468,56 @@ private fun PlayerResizeMode.toExoResizeMode(): Int =
|
||||||
PlayerResizeMode.Zoom -> AspectRatioFrameLayout.RESIZE_MODE_ZOOM
|
PlayerResizeMode.Zoom -> AspectRatioFrameLayout.RESIZE_MODE_ZOOM
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun PlayerView.syncLibassOverlay(
|
||||||
|
player: ExoPlayer,
|
||||||
|
enabled: Boolean,
|
||||||
|
renderType: LibassRenderType,
|
||||||
|
) {
|
||||||
|
val subtitleView = subtitleView ?: return
|
||||||
|
val needsOverlay = enabled && renderType.usesOverlaySubtitleView()
|
||||||
|
val boundPlayer = getTag(R.id.libass_overlay_bound_player) as? ExoPlayer
|
||||||
|
val hasOverlayChild = subtitleView.hasAssOverlayChild()
|
||||||
|
|
||||||
|
if (!needsOverlay) {
|
||||||
|
if (hasOverlayChild) {
|
||||||
|
subtitleView.removeAssOverlayChildren()
|
||||||
|
}
|
||||||
|
if (boundPlayer != null) {
|
||||||
|
setTag(R.id.libass_overlay_bound_player, null)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val assHandler = player.getAssHandlerCompat() ?: return
|
||||||
|
if (boundPlayer === player && hasOverlayChild) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
subtitleView.removeAssOverlayChildren()
|
||||||
|
subtitleView.withAssSupport(assHandler)
|
||||||
|
setTag(R.id.libass_overlay_bound_player, player)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun LibassRenderType.usesOverlaySubtitleView(): Boolean =
|
||||||
|
this == LibassRenderType.OVERLAY_CANVAS || this == LibassRenderType.OVERLAY_OPEN_GL
|
||||||
|
|
||||||
|
private fun SubtitleView.hasAssOverlayChild(): Boolean {
|
||||||
|
for (index in 0 until childCount) {
|
||||||
|
if (getChildAt(index) is AssSubtitleView) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun SubtitleView.removeAssOverlayChildren() {
|
||||||
|
for (index in childCount - 1 downTo 0) {
|
||||||
|
if (getChildAt(index) is AssSubtitleView) {
|
||||||
|
removeViewAt(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun PlayerView.applySubtitleStyle(style: SubtitleStyleState) {
|
private fun PlayerView.applySubtitleStyle(style: SubtitleStyleState) {
|
||||||
subtitleView?.apply {
|
subtitleView?.apply {
|
||||||
val baseBottomPaddingFraction = SubtitleView.DEFAULT_BOTTOM_PADDING_FRACTION * 2f / 3f
|
val baseBottomPaddingFraction = SubtitleView.DEFAULT_BOTTOM_PADDING_FRACTION * 2f / 3f
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,10 @@ import io.github.peerless2012.ass.media.extractor.AssMatroskaExtractor
|
||||||
import io.github.peerless2012.ass.media.kt.withAssSupport
|
import io.github.peerless2012.ass.media.kt.withAssSupport
|
||||||
import io.github.peerless2012.ass.media.parser.AssSubtitleParserFactory
|
import io.github.peerless2012.ass.media.parser.AssSubtitleParserFactory
|
||||||
import io.github.peerless2012.ass.media.type.AssRenderType
|
import io.github.peerless2012.ass.media.type.AssRenderType
|
||||||
|
import java.util.Collections
|
||||||
|
import java.util.WeakHashMap
|
||||||
|
|
||||||
|
private val assHandlersByPlayer = Collections.synchronizedMap(WeakHashMap<ExoPlayer, AssHandler>())
|
||||||
|
|
||||||
@OptIn(UnstableApi::class)
|
@OptIn(UnstableApi::class)
|
||||||
internal fun ExoPlayer.Builder.buildWithAssSupportCompat(
|
internal fun ExoPlayer.Builder.buildWithAssSupportCompat(
|
||||||
|
|
@ -47,10 +51,14 @@ internal fun ExoPlayer.Builder.buildWithAssSupportCompat(
|
||||||
.setRenderersFactory(renderersFactory.withAssSupport(assHandler))
|
.setRenderersFactory(renderersFactory.withAssSupport(assHandler))
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
|
assHandlersByPlayer[player] = assHandler
|
||||||
|
|
||||||
assHandler.init(player)
|
assHandler.init(player)
|
||||||
return player
|
return player
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun ExoPlayer.getAssHandlerCompat(): AssHandler? = assHandlersByPlayer[this]
|
||||||
|
|
||||||
@OptIn(UnstableApi::class)
|
@OptIn(UnstableApi::class)
|
||||||
private class CompatAssSubtitleParserFactory(
|
private class CompatAssSubtitleParserFactory(
|
||||||
private val assHandler: AssHandler
|
private val assHandler: AssHandler
|
||||||
|
|
|
||||||
4
composeApp/src/androidMain/res/values/ids.xml
Normal file
4
composeApp/src/androidMain/res/values/ids.xml
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<item name="libass_overlay_bound_player" type="id" />
|
||||||
|
</resources>
|
||||||
Loading…
Reference in a new issue