From 197265e7f546633656e9cf76c4be27d9f81f9dfa Mon Sep 17 00:00:00 2001 From: Ludovico de Nittis Date: Mon, 12 Jan 2026 03:11:25 +0100 Subject: [PATCH] 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 dovi7 ### AI/LLM usage None Co-authored-by: Ray <154766448+damontecres@users.noreply.github.com> --- .../wholphin/preferences/AppPreference.kt | 12 ++++++++++++ .../wholphin/services/DeviceProfileService.kt | 3 +++ .../wholphin/util/profile/DeviceProfileUtils.kt | 9 ++++++--- app/src/main/proto/WholphinDataStore.proto | 1 + app/src/main/res/values/strings.xml | 2 ++ 5 files changed, 24 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/github/damontecres/wholphin/preferences/AppPreference.kt b/app/src/main/java/com/github/damontecres/wholphin/preferences/AppPreference.kt index 4b08b226..5ed8e6dc 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/preferences/AppPreference.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/preferences/AppPreference.kt @@ -414,6 +414,17 @@ sealed interface AppPreference { summaryOff = R.string.disabled, ) + val DirectPlayDoviProfile7 = + AppSwitchPreference( + 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( title = R.string.remember_selected_tab, @@ -984,6 +995,7 @@ val advancedPreferences = AppPreference.Ac3Supported, AppPreference.DirectPlayAss, AppPreference.DirectPlayPgs, + AppPreference.DirectPlayDoviProfile7, ), ), ConditionalPreferences( diff --git a/app/src/main/java/com/github/damontecres/wholphin/services/DeviceProfileService.kt b/app/src/main/java/com/github/damontecres/wholphin/services/DeviceProfileService.kt index 9ce70b21..95cebb3c 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/services/DeviceProfileService.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/services/DeviceProfileService.kt @@ -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, ) diff --git a/app/src/main/java/com/github/damontecres/wholphin/util/profile/DeviceProfileUtils.kt b/app/src/main/java/com/github/damontecres/wholphin/util/profile/DeviceProfileUtils.kt index 6203cc17..0f507fd3 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/util/profile/DeviceProfileUtils.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/util/profile/DeviceProfileUtils.kt @@ -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) { diff --git a/app/src/main/proto/WholphinDataStore.proto b/app/src/main/proto/WholphinDataStore.proto index e4cd52d7..f68ecae8 100644 --- a/app/src/main/proto/WholphinDataStore.proto +++ b/app/src/main/proto/WholphinDataStore.proto @@ -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 { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c9fc0ed5..90676968 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -410,6 +410,8 @@ DD DD+ DTS + Direct play Dolby Vision Profile 7 + Ignores device compatibility checks Disabled