Chore: log cleanups, and Vo settings enablement

Added the ability to swap VO options for android only between "GPU" and
"GPU-next"
Removed some console logs from previous debugging
Added the ability to see what VO is being used to render in the video
player

Signed-off-by: Lance Chant <13349722+lancechant@users.noreply.github.com>
This commit is contained in:
Lance Chant
2026-05-25 14:19:36 +02:00
parent 4253f0d5ab
commit 6b0f8b833f
12 changed files with 200 additions and 40 deletions

View File

@@ -105,7 +105,12 @@ class MPVLayerRenderer(private val context: Context) : MPVLib.EventObserver {
val duration: Double
get() = cachedDuration
fun start() {
/**
* The VO driver to use. Stored so attachSurface can re-enable the same driver.
*/
private var voDriver: String = "gpu-next"
fun start(voDriver: String = "gpu-next") {
if (isRunning) return
try {
@@ -159,7 +164,8 @@ class MPVLayerRenderer(private val context: Context) : MPVLib.EventObserver {
MPVLib.setOptionString("config-dir", mpvDir.path)
// Configure mpv options before initialization (based on Findroid)
MPVLib.setOptionString("vo", "gpu")
this.voDriver = voDriver
MPVLib.setOptionString("vo", voDriver)
MPVLib.setOptionString("gpu-context", "android")
MPVLib.setOptionString("opengl-es", "yes")
@@ -239,8 +245,8 @@ class MPVLayerRenderer(private val context: Context) : MPVLib.EventObserver {
MPVLib.attachSurface(surface)
// Re-enable video output after attaching surface (Findroid approach)
MPVLib.setOptionString("force-window", "yes")
MPVLib.setOptionString("vo", "gpu")
Log.i(TAG, "Surface attached, video output re-enabled")
MPVLib.setOptionString("vo", voDriver)
Log.i(TAG, "Surface attached, video output re-enabled (vo=$voDriver)")
}
}
@@ -573,6 +579,16 @@ class MPVLayerRenderer(private val context: Context) : MPVLib.EventObserver {
info["droppedFrames"] = it
}
// Active video output driver (read from MPV to confirm what's actually applied)
MPVLib.getPropertyString("vo")?.let {
info["voDriver"] = it
}
// Active hardware decoder
MPVLib.getPropertyString("hwdec-active")?.let {
info["hwdec"] = it
}
return info
}

View File

@@ -37,7 +37,8 @@ class MpvPlayerModule : Module() {
startPosition = (source["startPosition"] as? Number)?.toDouble(),
autoplay = (source["autoplay"] as? Boolean) ?: true,
initialSubtitleId = (source["initialSubtitleId"] as? Number)?.toInt(),
initialAudioId = (source["initialAudioId"] as? Number)?.toInt()
initialAudioId = (source["initialAudioId"] as? Number)?.toInt(),
voDriver = source["voDriver"] as? String
)
view.loadVideo(config)

View File

@@ -4,6 +4,7 @@ import android.content.Context
import android.graphics.Color
import android.os.Build
import android.util.Log
import android.view.Surface
import android.view.SurfaceHolder
import android.view.SurfaceView
import android.widget.FrameLayout
@@ -21,7 +22,8 @@ data class VideoLoadConfig(
val startPosition: Double? = null,
val autoplay: Boolean = true,
val initialSubtitleId: Int? = null,
val initialAudioId: Int? = null
val initialAudioId: Int? = null,
val voDriver: String? = null
)
/**
@@ -52,10 +54,12 @@ class MpvPlayerView(context: Context, appContext: AppContext) : ExpoView(context
private var intendedPlayState: Boolean = false
private var surfaceReady: Boolean = false
private var pendingConfig: VideoLoadConfig? = null
private var rendererStarted: Boolean = false
private var pendingSurface: Surface? = null
init {
setBackgroundColor(Color.BLACK)
// Create SurfaceView for video rendering
surfaceView = SurfaceView(context).apply {
layoutParams = FrameLayout.LayoutParams(
@@ -65,11 +69,7 @@ class MpvPlayerView(context: Context, appContext: AppContext) : ExpoView(context
holder.addCallback(this@MpvPlayerView)
}
addView(surfaceView)
// Initialize renderer
renderer = MPVLayerRenderer(context)
renderer?.delegate = this
// Initialize PiP controller with Expo's AppContext for proper activity access
pipController = PiPController(context, appContext)
pipController?.setPlayerView(surfaceView)
@@ -77,19 +77,39 @@ class MpvPlayerView(context: Context, appContext: AppContext) : ExpoView(context
override fun onPlay() {
play()
}
override fun onPause() {
pause()
}
override fun onSeekBy(seconds: Double) {
seekBy(seconds)
}
}
// Start the renderer
// Renderer is created lazily in loadVideo once we have the voDriver setting
renderer = MPVLayerRenderer(context)
renderer?.delegate = this
}
/**
* Start the renderer with the given VO driver.
* Called lazily on first loadVideo so the voDriver setting is available.
*/
private fun ensureRendererStarted(voDriver: String?) {
if (rendererStarted) return
try {
renderer?.start()
renderer?.start(voDriver ?: "gpu-next")
rendererStarted = true
Log.i(TAG, "Renderer started with vo=$voDriver")
// If surface was created before renderer started, attach it now
pendingSurface?.let { surface ->
renderer?.attachSurface(surface)
pendingSurface = null
Log.i(TAG, "Attached pending surface after renderer start")
}
} catch (e: Exception) {
Log.e(TAG, "Failed to start renderer: ${e.message}")
onError(mapOf("error" to "Failed to start renderer: ${e.message}"))
@@ -101,10 +121,18 @@ class MpvPlayerView(context: Context, appContext: AppContext) : ExpoView(context
override fun surfaceCreated(holder: SurfaceHolder) {
Log.i(TAG, "Surface created")
surfaceReady = true
renderer?.attachSurface(holder.surface)
if (rendererStarted) {
renderer?.attachSurface(holder.surface)
} else {
// Renderer not started yet - store surface to attach after start
pendingSurface = holder.surface
Log.i(TAG, "Surface created before renderer started, storing as pending")
}
// If we have a pending load, execute it now
pendingConfig?.let { config ->
ensureRendererStarted(config.voDriver)
loadVideoInternal(config)
pendingConfig = null
}
@@ -136,6 +164,9 @@ class MpvPlayerView(context: Context, appContext: AppContext) : ExpoView(context
return
}
// Ensure renderer is started with the configured VO driver
ensureRendererStarted(config.voDriver)
loadVideoInternal(config)
}

View File

@@ -54,6 +54,8 @@ export type VideoSource = {
/** Maximum backward cache size in MB (default: 50, range: 25-200) */
maxBackBytes?: number;
};
/** MPV video output driver (Android only) */
voDriver?: "gpu-next" | "gpu";
};
export type MpvPlayerViewProps = {
@@ -137,4 +139,8 @@ export type TechnicalInfo = {
audioBitrate?: number;
cacheSeconds?: number;
droppedFrames?: number;
/** Active video output driver (read from MPV at runtime) */
voDriver?: string;
/** Active hardware decoder (read from MPV at runtime) */
hwdec?: string;
};