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:
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user