Add option to always direct play Dolby Vision Profile 7 (#670)

## Description
A few devices, like the Nvidia Shield Pro 2019, are able to correctly
handle Dolby Vision Profile 7. However, when a Full Enhancement Layer
(FEL) is present, these devices effectively ignore the enhancement layer
and only apply the RPU metadata.

Due to this behavior, device capabilities are reported as not supporting
`DOVIWithEL`, which causes the Jellyfin server to strip the DV layer
entirely with a remux.

This commit adds an option to force direct play of Dolby Vision Profile
7 content, preventing the server from stripping the Dolby Vision layer
and allowing compatible devices to handle playback as intended.

### Related issues
Fixes https://github.com/damontecres/Wholphin/issues/449

### Screenshots
<img width="1280" height="720" alt="dovi7"
src="https://github.com/user-attachments/assets/849e9897-93b6-419f-a1fb-7f361f9c88dd"
/>

### AI/LLM usage
None

Co-authored-by: Ray <154766448+damontecres@users.noreply.github.com>
This commit is contained in:
Ludovico de Nittis 2026-01-12 03:11:25 +01:00 committed by GitHub
parent b78f5fcc77
commit 197265e7f5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 24 additions and 3 deletions

View file

@ -414,6 +414,17 @@ sealed interface AppPreference<Pref, T> {
summaryOff = R.string.disabled,
)
val DirectPlayDoviProfile7 =
AppSwitchPreference<AppPreferences>(
title = R.string.force_dovi_profile_7,
defaultValue = false,
getter = { it.playbackPreferences.overrides.directPlayDolbyVisionEL },
setter = { prefs, value ->
prefs.updatePlaybackOverrides { directPlayDolbyVisionEL = value }
},
summary = R.string.force_dovi_profile_7_summary,
)
val RememberSelectedTab =
AppSwitchPreference<AppPreferences>(
title = R.string.remember_selected_tab,
@ -984,6 +995,7 @@ val advancedPreferences =
AppPreference.Ac3Supported,
AppPreference.DirectPlayAss,
AppPreference.DirectPlayPgs,
AppPreference.DirectPlayDoviProfile7,
),
),
ConditionalPreferences(

View file

@ -42,6 +42,7 @@ class DeviceProfileService
downMixAudio = prefs.overrides.downmixStereo,
assDirectPlay = prefs.overrides.directPlayAss,
pgsDirectPlay = prefs.overrides.directPlayPgs,
dolbyVisionELDirectPlay = prefs.overrides.directPlayDolbyVisionEL,
jellyfinTenEleven =
serverVersion != null && serverVersion >= ServerVersion(10, 11, 0),
)
@ -55,6 +56,7 @@ class DeviceProfileService
downMixAudio = newConfig.downMixAudio,
assDirectPlay = newConfig.assDirectPlay,
pgsDirectPlay = newConfig.pgsDirectPlay,
dolbyVisionELDirectPlay = newConfig.dolbyVisionELDirectPlay,
jellyfinTenEleven = newConfig.jellyfinTenEleven,
)
}
@ -72,5 +74,6 @@ data class DeviceProfileConfiguration(
val downMixAudio: Boolean,
val assDirectPlay: Boolean,
val pgsDirectPlay: Boolean,
val dolbyVisionELDirectPlay: Boolean,
val jellyfinTenEleven: Boolean,
)

View file

@ -66,6 +66,7 @@ fun createDeviceProfile(
downMixAudio: Boolean,
assDirectPlay: Boolean,
pgsDirectPlay: Boolean,
dolbyVisionELDirectPlay: Boolean,
jellyfinTenEleven: Boolean,
) = buildDeviceProfile {
val allowedAudioCodecs =
@ -428,9 +429,11 @@ fun createDeviceProfile(
if (jellyfinTenEleven) add("DOVIInvalid")
if (!supportsHevcDolbyVisionEL) {
if (jellyfinTenEleven) {
add("DOVIWithEL")
if (!supportsHevcHDR10Plus && !KnownDefects.hevcDoviHdr10PlusBug) add("DOVIWithELHDR10Plus")
if (!dolbyVisionELDirectPlay) {
if (jellyfinTenEleven) {
add("DOVIWithEL")
if (!supportsHevcHDR10Plus && !KnownDefects.hevcDoviHdr10PlusBug) add("DOVIWithELHDR10Plus")
}
}
if (!supportsHevcDolbyVision) {

View file

@ -45,6 +45,7 @@ message PlaybackOverrides{
bool direct_play_ass = 3;
bool direct_play_pgs = 4;
MediaExtensionStatus media_extensions_enabled = 5;
bool direct_play_dolby_vision_e_l = 6;
}
message PlaybackPreferences {

View file

@ -410,6 +410,8 @@
<string name="dolby_digital">DD</string>
<string name="dolby_digital_plus">DD+</string>
<string name="dts">DTS</string>
<string name="force_dovi_profile_7">Direct play Dolby Vision Profile 7</string>
<string name="force_dovi_profile_7_summary">Ignores device compatibility checks</string>
<string-array name="theme_song_volume">
<item>Disabled</item>