From 3c6d398598599a6dd67472f1cd9c48cf0c937b6c Mon Sep 17 00:00:00 2001 From: edde746 <86283021+edde746@users.noreply.github.com> Date: Wed, 26 Aug 2026 18:59:28 +0200 Subject: [PATCH] feat(player): default Android playback to the mpv backend With video on the MediaCodec plane, real bitstream passthrough, media3 demuxing, and the GL fallback ladder in place, mpv measures at parity or better than ExoPlayer on every device class tested (Tegra, Mali, Amlogic armv7, Adreno; API 28-36; phone, TV, and foldable), including the two historical Android mpv failure modes: low-end TV playback and Hi10P. Installs that never chose a backend move to mpv; a stored ExoPlayer choice is preserved, and the Player Backend toggle stays user-visible as the escape hatch. The automatic ExoPlayer-to-mpv runtime fallback is unchanged. --- lib/mpv/player/player.dart | 14 +++++++------- lib/services/settings_service.dart | 4 +++- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/mpv/player/player.dart b/lib/mpv/player/player.dart index e69a85cfd..38cf45436 100644 --- a/lib/mpv/player/player.dart +++ b/lib/mpv/player/player.dart @@ -379,13 +379,13 @@ abstract class Player { /// /// Returns a platform-specific implementation: /// - macOS/iOS: [PlayerNative] using MPVKit/libmpv with Metal rendering - /// - Android: [PlayerAndroid] using ExoPlayer (default) or [PlayerNative] using MPV (fallback) + /// - Android: [PlayerNative] using MPV (default) or [PlayerAndroid] using ExoPlayer (opt-in) /// - Windows: [PlayerWindows] using libmpv with native window embedding /// - Linux: [PlayerLinux] using libmpv on a native Wayland video plane /// /// On Android, pass [useExoPlayer] to override the default: - /// - true: Use ExoPlayer (default, better hardware support) - /// - false: Use MPV (more features, ASS subtitle rendering) + /// - false: Use MPV (default, more features, ASS subtitle rendering) + /// - true: Use ExoPlayer (the escape hatch for devices MPV mishandles) /// /// [hardwareDecoding] is the session's hardware-decoding setting. The /// Android mpv backend uses it to pick its initial video output — the fork's @@ -394,13 +394,13 @@ abstract class Player { /// MpvPlayerCore.initialVideoOutput; #2010). factory Player({bool? useExoPlayer, bool hardwareDecoding = true}) { if (Platform.isAndroid) { - // Default to ExoPlayer on Android, with MPV as fallback + // Default to MPV on Android, with ExoPlayer as the opt-in alternative. // The caller should pass useExoPlayer based on SettingsService.useExoPlayer. - final useExo = useExoPlayer ?? true; + final useExo = useExoPlayer ?? false; if (useExo) { - return PlayerAndroid(); // ExoPlayer (default) + return PlayerAndroid(); // ExoPlayer (opt-in) } - return PlayerNative(hardwareDecoding: hardwareDecoding); // MPV fallback + return PlayerNative(hardwareDecoding: hardwareDecoding); // MPV (default) } if (Platform.isMacOS || Platform.isIOS) { return PlayerNative(); diff --git a/lib/services/settings_service.dart b/lib/services/settings_service.dart index 0bd1d968a..c7c18747e 100644 --- a/lib/services/settings_service.dart +++ b/lib/services/settings_service.dart @@ -510,7 +510,9 @@ class SettingsService extends BaseSharedPreferencesService { defaultValue: SpecialsOrdering.respectServer, ); - static const useExoPlayer = BoolPref('use_exoplayer', defaultValue: true); + /// mpv is the default Android backend; ExoPlayer remains selectable as the + /// escape hatch while it still ships. + static const useExoPlayer = BoolPref('use_exoplayer'); static const startupSection = EnumPref( 'startup_section', values: NavigationTabId.values,