fix(android): derive the mpv fallback passthrough list from the audio route

Audio passthrough defaults on for Android TV, scoped to ExoPlayer because
mpv force-passes through every codec named in audio-spdif and has no
decode fallback. That scoping did not survive the ExoPlayer to mpv
handoff: PlayerAndroid queued the raw ac3,eac3,dts,dts-hd,truehd list as
a pending mpv property and prepareMpvFallback replayed it verbatim, so a
sink that bitstreams only Dolby formats was told to force TrueHD and
DTS-HD anyway. mpv selected spdif_truehd, the audio output never
initialised, and playback froze at its start position while still showing
a first frame — the stop timeline reported the position it opened with.

Treat passthrough as a request and resolve the codec list against the
route when mpv actually starts, so an HDMI or AVR change between
ExoPlayer startup and the handoff cannot replay codecs from the old sink.
Gate each codec on the exact advertised encoding rather than media3's
passthrough probe: that probe answers DTS-HD by downgrading to the DTS
core, and mpv reads "dts,dts-hd" as "dts-hd" alone, so accepting the
downgrade would name DTS-HD MA to a core-only receiver and lose DTS too.
This commit is contained in:
edde746
2026-07-28 19:44:16 +02:00
parent ae331b217c
commit a183c17c3b
6 changed files with 198 additions and 9 deletions
+5 -3
View File
@@ -20,8 +20,6 @@ class PlayerAndroid extends PlayerBase {
int _downmixCenterBoostDb = 0;
bool _downmixNormalize = true;
static const String _passthroughCodecs = 'ac3,eac3,dts,dts-hd,truehd';
/// The native plugin switched from ExoPlayer to its mpv fallback for this
/// session. Sticky for the instance lifetime, mirroring the native flag
/// (which resets only on initialize/dispose).
@@ -358,7 +356,11 @@ class PlayerAndroid extends PlayerBase {
() => invoke('setAudioPassthrough', {'enabled': enabled}),
() => _audioPassthroughEnabled == enabled,
);
await setProperty('audio-spdif', enabled ? _passthroughCodecs : '');
// Deliberately no 'audio-spdif' write: unlike normalization and downmix, the
// mpv value is not this list. mpv force-passthroughs every codec named there
// with no decode fallback, so the plugin derives it from the audio route when
// the fallback core starts. Queuing the raw list here would overwrite it and
// strand TrueHD/DTS-HD on sinks that cannot bitstream them (#1703).
}
@override