fix(tvos): make HDR toggle disable Dolby Vision

HDR-off now forces SDR display criteria for DV like it does for HDR10,
and the runtime toggle re-applies the criteria. Refs #1262 (part A).
This commit is contained in:
edde746
2026-06-06 14:17:52 +02:00
parent 1ef4032666
commit 8139fc2b17
2 changed files with 40 additions and 5 deletions
+14 -5
View File
@@ -268,10 +268,19 @@ class MpvPlayerCore: MpvPlayerCoreBase {
doviCompatibilityId: doviCompatibilityId doviCompatibilityId: doviCompatibilityId
) )
let sourceRange: DisplayDynamicRange = sourceHasDolbyVision ? .dolbyVision : sourceBaseRange let sourceRange: DisplayDynamicRange = sourceHasDolbyVision ? .dolbyVision : sourceBaseRange
var displayRange: DisplayDynamicRange = // The HDR toggle (`hdrEnabled`) is authoritative on tvOS: when it's off,
sourceHasDolbyVision // drive the HDMI link in SDR regardless of the source Dolby Vision
? .dolbyVision // included so turning HDR off actually leaves DV mode (issue #1262).
: Self.supportedDisplayDynamicRange(for: sourceBaseRange) // This is the only path that gates the HDMI mode on tvOS;
// target-colorspace-hint is inert in the avfoundation VO and EDR is iOS.
var displayRange: DisplayDynamicRange
if !hdrEnabled {
displayRange = .sdr
} else if sourceHasDolbyVision {
displayRange = .dolbyVision
} else {
displayRange = Self.supportedDisplayDynamicRange(for: sourceBaseRange)
}
guard displayManager.isDisplayCriteriaMatchingEnabled else { guard displayManager.isDisplayCriteriaMatchingEnabled else {
clearDisplayCriteria(displayManager, reason: "matching disabled") clearDisplayCriteria(displayManager, reason: "matching disabled")
return false return false
@@ -288,7 +297,7 @@ class MpvPlayerCore: MpvPlayerCoreBase {
doviProfile: doviProfile, doviProfile: doviProfile,
doviLevel: doviLevel, doviLevel: doviLevel,
doviCompatibilityId: doviCompatibilityId) doviCompatibilityId: doviCompatibilityId)
if formatDescription == nil, sourceHasDolbyVision { if formatDescription == nil, sourceHasDolbyVision, hdrEnabled {
displayRange = sourceBaseRange displayRange = sourceBaseRange
formatDescription = Self.makeDisplayFormatDescription( formatDescription = Self.makeDisplayFormatDescription(
dynamicRange: displayRange, dynamicRange: displayRange,
@@ -97,6 +97,7 @@ class MpvPlayerCoreBase: NSObject {
private var cachedVideoPrimaries: String? private var cachedVideoPrimaries: String?
private var cachedVideoColorMatrix: String? private var cachedVideoColorMatrix: String?
private var serverDisplayCriteriaActive = false private var serverDisplayCriteriaActive = false
private var lastServerCriteria: ServerDisplayCriteria?
private var cachedDvConversionMode = "auto" private var cachedDvConversionMode = "auto"
private var cachedDvConversionLogEnabled = false private var cachedDvConversionLogEnabled = false
var hdrEnabled: Bool { var hdrEnabled: Bool {
@@ -231,6 +232,7 @@ class MpvPlayerCoreBase: NSObject {
func setServerDisplayCriteria(_ criteria: ServerDisplayCriteria?) { func setServerDisplayCriteria(_ criteria: ServerDisplayCriteria?) {
cacheLock.lock() cacheLock.lock()
serverDisplayCriteriaActive = criteria != nil serverDisplayCriteriaActive = criteria != nil
lastServerCriteria = criteria
cacheLock.unlock() cacheLock.unlock()
let apply = { [weak self] in let apply = { [weak self] in
@@ -278,6 +280,21 @@ class MpvPlayerCoreBase: NSObject {
} }
} }
/// Re-evaluate the tvOS HDMI display mode using the most recent criteria.
/// On tvOS the HDR toggle only reaches the display through this path, so the
/// runtime toggle calls this to switch DV/HDR SDR without reloading.
func reapplyDisplayCriteria() {
cacheLock.lock()
let criteria = lastServerCriteria
cacheLock.unlock()
if let criteria {
setServerDisplayCriteria(criteria)
} else {
scheduleDisplayCriteriaUpdate()
}
}
func setupMpv() -> Bool { func setupMpv() -> Bool {
#if os(macOS) #if os(macOS)
guard let renderLayer = metalLayer else { return false } guard let renderLayer = metalLayer else { return false }
@@ -509,6 +526,15 @@ class MpvPlayerCoreBase: NSObject {
DispatchQueue.main.async { DispatchQueue.main.async {
self.updateEDRMode(sigPeak: sigPeak) self.updateEDRMode(sigPeak: sigPeak)
} }
// On tvOS the toggle only takes effect through the HDMI display-mode path
// (target-colorspace-hint is inert in the avfoundation VO and EDR is
// iOS-only), so re-evaluate the display criteria with the new flag.
#if os(tvOS)
DispatchQueue.main.async {
self.reapplyDisplayCriteria()
}
#endif
} }
/// PiP presents the AVSampleBufferDisplayLayer directly, so subtitles must /// PiP presents the AVSampleBufferDisplayLayer directly, so subtitles must