mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 23:51:21 +02:00
Fix MPV race condition causing no video output (#619)
## Description Fixes a race condition where `libmpv` is beginning playback before it has been attached to the output video surface. The solution is for the handler to re-enqueue commands if MPV is either not initialized or not attached yet. Once `libmpv` is ready, the commands will be processed. ### Related issues Should fix #576
This commit is contained in:
parent
0fe8e5d988
commit
4d9e3cb6de
1 changed files with 29 additions and 14 deletions
|
|
@ -109,6 +109,7 @@ class MpvPlayer(
|
||||||
Timber.v("config-dir=${context.filesDir.path}")
|
Timber.v("config-dir=${context.filesDir.path}")
|
||||||
MPVLib.addLogObserver(mpvLogger)
|
MPVLib.addLogObserver(mpvLogger)
|
||||||
|
|
||||||
|
Timber.v("Creating MPVLib")
|
||||||
MPVLib.create(context)
|
MPVLib.create(context)
|
||||||
MPVLib.setOptionString("config", "yes")
|
MPVLib.setOptionString("config", "yes")
|
||||||
MPVLib.setOptionString("config-dir", context.filesDir.path)
|
MPVLib.setOptionString("config-dir", context.filesDir.path)
|
||||||
|
|
@ -127,6 +128,7 @@ class MpvPlayer(
|
||||||
MPVLib.setOptionString("demuxer-max-bytes", "${cacheMegs * 1024 * 1024}")
|
MPVLib.setOptionString("demuxer-max-bytes", "${cacheMegs * 1024 * 1024}")
|
||||||
MPVLib.setOptionString("demuxer-max-back-bytes", "${cacheMegs * 1024 * 1024}")
|
MPVLib.setOptionString("demuxer-max-back-bytes", "${cacheMegs * 1024 * 1024}")
|
||||||
|
|
||||||
|
Timber.v("Initializing MPVLib")
|
||||||
MPVLib.initialize()
|
MPVLib.initialize()
|
||||||
|
|
||||||
MPVLib.setOptionString("force-window", "no")
|
MPVLib.setOptionString("force-window", "no")
|
||||||
|
|
@ -466,7 +468,6 @@ class MpvPlayer(
|
||||||
override fun clearVideoSurfaceHolder(surfaceHolder: SurfaceHolder?): Unit = throw UnsupportedOperationException()
|
override fun clearVideoSurfaceHolder(surfaceHolder: SurfaceHolder?): Unit = throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun setVideoSurfaceView(surfaceView: SurfaceView?) {
|
override fun setVideoSurfaceView(surfaceView: SurfaceView?) {
|
||||||
throwIfReleased()
|
|
||||||
if (DEBUG) Timber.v("setVideoSurfaceView")
|
if (DEBUG) Timber.v("setVideoSurfaceView")
|
||||||
val surface = surfaceView?.holder?.surface
|
val surface = surfaceView?.holder?.surface
|
||||||
if (surface != null && surface.isValid) {
|
if (surface != null && surface.isValid) {
|
||||||
|
|
@ -635,9 +636,9 @@ class MpvPlayer(
|
||||||
val title = it.label ?: "External Subtitles"
|
val title = it.label ?: "External Subtitles"
|
||||||
Timber.v("Adding external subtitle track '$title'")
|
Timber.v("Adding external subtitle track '$title'")
|
||||||
if (it.language.isNotNullOrBlank()) {
|
if (it.language.isNotNullOrBlank()) {
|
||||||
MPVLib.command(arrayOf("sub-add", url, "auto", title, it.language!!))
|
MPVLib.command(arrayOf("sub-add", url, "select", title, it.language!!))
|
||||||
} else {
|
} else {
|
||||||
MPVLib.command(arrayOf("sub-add", url, "auto", title))
|
MPVLib.command(arrayOf("sub-add", url, "select", title))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -837,7 +838,18 @@ class MpvPlayer(
|
||||||
|
|
||||||
override fun handleMessage(msg: Message): Boolean {
|
override fun handleMessage(msg: Message): Boolean {
|
||||||
val cmd = MpvCommand.entries[msg.what]
|
val cmd = MpvCommand.entries[msg.what]
|
||||||
Timber.v("handleMessage: cmd=$cmd")
|
Timber.d("handleMessage: cmd=$cmd")
|
||||||
|
if (isReleased && cmd != MpvCommand.DESTROY) {
|
||||||
|
Timber.w("Player is released, ignoring command %s", cmd)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (surface == null && !cmd.isLifecycle) {
|
||||||
|
// If libmpv isn't ready, re-enqueue the messages
|
||||||
|
// Note: this means nothing will play until it is attached to a surface,
|
||||||
|
// so MpvPlayer can't be used for background audio/music playback
|
||||||
|
Timber.v("MPV is not initialized/attached yet, requeue cmd %s", cmd)
|
||||||
|
internalHandler.sendMessageDelayed(Message.obtain(msg), 50)
|
||||||
|
}
|
||||||
when (cmd) {
|
when (cmd) {
|
||||||
MpvCommand.PLAY_PAUSE -> {
|
MpvCommand.PLAY_PAUSE -> {
|
||||||
val playWhenReady = msg.obj as Boolean
|
val playWhenReady = msg.obj as Boolean
|
||||||
|
|
@ -894,6 +906,7 @@ class MpvPlayer(
|
||||||
MPVLib.detachSurface()
|
MPVLib.detachSurface()
|
||||||
MPVLib.setPropertyString("vo", "null")
|
MPVLib.setPropertyString("vo", "null")
|
||||||
MPVLib.setPropertyString("force-window", "no")
|
MPVLib.setPropertyString("force-window", "no")
|
||||||
|
Timber.d("Detached surface")
|
||||||
}
|
}
|
||||||
if (surface != null) {
|
if (surface != null) {
|
||||||
MPVLib.attachSurface(surface)
|
MPVLib.attachSurface(surface)
|
||||||
|
|
@ -1035,14 +1048,16 @@ private data class MediaAndPosition(
|
||||||
val startPositionMs: Long,
|
val startPositionMs: Long,
|
||||||
)
|
)
|
||||||
|
|
||||||
enum class MpvCommand {
|
enum class MpvCommand(
|
||||||
PLAY_PAUSE,
|
val isLifecycle: Boolean,
|
||||||
SEEK,
|
) {
|
||||||
SET_TRACK_SELECTION,
|
PLAY_PAUSE(false),
|
||||||
SET_SPEED,
|
SEEK(false),
|
||||||
SET_SUBTITLE_DELAY,
|
SET_TRACK_SELECTION(false),
|
||||||
LOAD_FILE,
|
SET_SPEED(false),
|
||||||
ATTACH_SURFACE,
|
SET_SUBTITLE_DELAY(false),
|
||||||
INITIALIZE,
|
LOAD_FILE(false),
|
||||||
DESTROY,
|
ATTACH_SURFACE(true),
|
||||||
|
INITIALIZE(true),
|
||||||
|
DESTROY(true),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue