Skip to content
This repository has been archived by the owner on Sep 16, 2023. It is now read-only.

Commit

Permalink
HDR: Use MPV instead of ffmpeg to detect primaries and trc
Browse files Browse the repository at this point in the history
Pros: Much easier to detect HDR content, including cases of swtiching video track, play list and network resources. The code can also be simplified.
Cons: Display-P3 will no longer be enabled because MPV doesn't honor mastering display metadata.

Fixes #6
  • Loading branch information
CarterLi committed Dec 11, 2021
1 parent 5599953 commit e5a4dae
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 100 deletions.
102 changes: 67 additions & 35 deletions iina/Base.lproj/InspectorWindowController.xib

Large diffs are not rendered by default.

22 changes: 11 additions & 11 deletions iina/InspectorWindowController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class InspectorWindowController: NSWindowController, NSTableViewDelegate, NSTabl
@IBOutlet weak var vformatField: NSTextField!
@IBOutlet weak var vcodecField: NSTextField!
@IBOutlet weak var vdecoderField: NSTextField!
@IBOutlet weak var vcolorspaceField: NSTextField!
@IBOutlet weak var vprimariesField: NSTextField!

@IBOutlet weak var voField: NSTextField!
Expand All @@ -44,7 +45,6 @@ class InspectorWindowController: NSWindowController, NSTableViewDelegate, NSTabl
@IBOutlet weak var abitrateField: NSTextField!
@IBOutlet weak var asamplerateField: NSTextField!

@IBOutlet weak var filePrimariesField: NSTextField!
@IBOutlet weak var trackIdField: NSTextField!
@IBOutlet weak var trackDefaultField: NSTextField!
@IBOutlet weak var trackForcedField: NSTextField!
Expand Down Expand Up @@ -143,12 +143,6 @@ class InspectorWindowController: NSWindowController, NSTableViewDelegate, NSTabl

let fileSize = controller.getInt(MPVProperty.fileSize)
self.fileSizeField.stringValue = "\(FloatingPointByteCountFormatter.string(fromByteCount: fileSize))B"

let sigPeak = controller.getDouble(MPVProperty.videoParamsSigPeak);
self.filePrimariesField.stringValue = sigPeak > 0
? "\(controller.getString(MPVProperty.videoParamsPrimaries) ?? "?") / \(controller.getString(MPVProperty.videoParamsGamma) ?? "?") (\(sigPeak > 1 ? "H" : "S")DR)"
: "N/A";
self.setLabelColor(self.filePrimariesField, by: sigPeak > 0)

// track list

Expand Down Expand Up @@ -199,14 +193,20 @@ class InspectorWindowController: NSWindowController, NSTableViewDelegate, NSTabl
v.stringValue = value ?? "N/A"
self.setLabelColor(v, by: value != nil)
}

let sigPeak = controller.getDouble(MPVProperty.videoParamsSigPeak);
self.vprimariesField.stringValue = sigPeak > 0
? "\(controller.getString(MPVProperty.videoParamsPrimaries) ?? "?") / \(controller.getString(MPVProperty.videoParamsGamma) ?? "?") (\(sigPeak > 1 ? "H" : "S")DR)"
: "N/A";
self.setLabelColor(self.vprimariesField, by: sigPeak > 0)

if controller.fileLoaded {
if PlayerCore.lastActive.mainWindow.loaded && controller.fileLoaded {
let colorspace = PlayerCore.lastActive.mainWindow.videoView.videoLayer.colorspace?.name;
self.vprimariesField.stringValue = colorspace == nil ? "Unspecified (SDR)" : String(colorspace!) + " (HDR)"
self.vcolorspaceField.stringValue = colorspace == nil ? "Unspecified (SDR)" : String(colorspace!) + " (HDR)"
} else {
self.vprimariesField.stringValue = "N/A"
self.vcolorspaceField.stringValue = "N/A"
}
self.setLabelColor(self.vprimariesField, by: controller.fileLoaded)
self.setLabelColor(self.vcolorspaceField, by: controller.fileLoaded)
}
}

Expand Down
4 changes: 4 additions & 0 deletions iina/MPVController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,10 @@ class MPVController: NSObject {
player.postNotification(.iinaVIDChanged)
player.sendOSD(.track(player.info.currentTrack(.video) ?? .noneVideoTrack))

if #available(macOS 10.15, *) {
player.refreshEdrMode()
}

case MPVOption.TrackSelection.aid:
player.info.aid = Int(getInt(MPVOption.TrackSelection.aid))
guard player.mainWindow.loaded else { break }
Expand Down
12 changes: 8 additions & 4 deletions iina/PlayerCore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1119,10 +1119,6 @@ class PlayerCore: NSObject {
NowPlayingInfoManager.updateInfo(withTitle: true)
}

if #available(macOS 10.15, *), !info.isNetworkResource {
mainWindow.videoView.requestHdrModeForFile(path)
}

// Auto load
backgroundQueueTicket += 1
let shouldAutoLoadFiles = info.shouldAutoLoadFiles
Expand Down Expand Up @@ -1245,6 +1241,14 @@ class PlayerCore: NSObject {
}
}

@available(macOS 10.15, *)
func refreshEdrMode() {
guard mainWindow.loaded else { return }
DispatchQueue.main.async {
self.mainWindow.videoView.refreshEdrMode()
}
}

@objc
private func reEnableOSDAfterFileLoading() {
info.disableOSDForFileLoading = false
Expand Down
62 changes: 14 additions & 48 deletions iina/VideoView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,6 @@ class VideoView: NSView {

var pendingRedrawAfterEnteringPIP = false;

// HDR
var hdrMetadata: (primaries: String?, transfer: String?, max_luminance: Float?, min_luminance: Float?)?;

// MARK: - Attributes

override var mouseDownCanMoveWindow: Bool {
Expand Down Expand Up @@ -265,35 +262,33 @@ class VideoView: NSView {

@available(macOS 10.15, *)
extension VideoView {
func requestHdrModeForFile(_ path: String) {
hdrMetadata = importFileColorSpace(path)
refreshEdrMode()
}

func refreshEdrMode() {
guard let displayId = currentDisplay, let meta = hdrMetadata else { return };
let edrEnabled = requestEdrMode(meta.primaries, meta.transfer, meta.max_luminance, meta.min_luminance)
guard player.mainWindow.loaded else { return }
guard let displayId = currentDisplay else { return };
let edrEnabled = requestEdrMode()
let edrAvailable = edrEnabled != false
if player.info.hdrAvailable != edrAvailable {
player.mainWindow.quickSettingView.pleaseChangeHdrAvailable(available: edrAvailable)
}
if edrEnabled != true { setICCProfile(displayId) }
}

func requestEdrMode(_ primaries: String?, _ transfer: String?, _ max_luminance: Float?, _ min_luminance: Float?) -> Bool? {
guard let transfer = transfer, let primaries = primaries else {
// SDR content
return false;
}
func requestEdrMode() -> Bool? {
guard let mpv = player.mpv else { return false }

guard mpv.getDouble(MPVProperty.videoParamsSigPeak) > 1.0 else { return false } // SDR content

guard (window?.screen?.maximumPotentialExtendedDynamicRangeColorComponentValue ?? 1.0) > 1.0 else {
Logger.log("HDR: HDR video was found but the display does not support EDR mode");
return false;
}

guard let primaries = mpv.getString(MPVProperty.videoParamsPrimaries), let gamma = mpv.getString(MPVProperty.videoParamsGamma) else { return false }

var name: CFString? = nil;
switch primaries {
case "display-p3":
switch transfer {
switch gamma {
case "pq":
if #available(macOS 10.15.4, *) {
name = CGColorSpace.displayP3_PQ
Expand All @@ -307,7 +302,7 @@ extension VideoView {
}

case "bt.2020": // deprecated
switch transfer {
switch gamma {
case "pq":
if #available(macOS 11.0, *) {
name = CGColorSpace.itur_2020_PQ
Expand All @@ -324,11 +319,8 @@ extension VideoView {
name = CGColorSpace.itur_2020
}

case "dci-p3":
name = CGColorSpace.dcip3

default:
Logger.log("HDR: Unknown HDR color space information transfer=\(transfer) primaries=\(primaries)");
Logger.log("HDR: Unknown HDR color space information gamma=\(gamma) primaries=\(primaries)");
return false;
}

Expand All @@ -338,36 +330,10 @@ extension VideoView {

videoLayer.colorspace = CGColorSpace(name: name!)
player.mpv.setString(MPVOption.GPURendererOptions.iccProfile, "")
player.mpv.setString(MPVOption.GPURendererOptions.targetTrc, transfer)
player.mpv.setString(MPVOption.GPURendererOptions.targetTrc, gamma)
player.mpv.setString(MPVOption.GPURendererOptions.targetPrim, primaries)
// videoLayer.edrMetadata = CAEDRMetadata.hdr10(minLuminance: min_luminance, maxLuminance: max_luminance, opticalOutputScale: 100); // OpenGL layer doesn't support edrMetadata
return true;
}

private func importFileColorSpace(_ path: String) -> (primaries: String?, transfer: String?, max_luminance: Float?, min_luminance: Float?)
{
var result: (primaries: String?, transfer: String?, max_luminance: Float?, min_luminance: Float?)
guard let colorspaceData = FFmpegController.getColorSpaceMetadata(forFile: path) else { return result }

colorspaceData.forEach { (k, v) in
switch k as? String {
case "primaries":
result.primaries = v as? String
case "color-trc":
result.transfer = v as? String
case "max_luminance":
result.max_luminance = (v as? NSNumber)?.floatValue
case "min_luminance":
result.min_luminance = (v as? NSNumber)?.floatValue
default:
break
}
}

Logger.log("HDR: Received color space metadata for HDR activation: \(result)")

return result;
}
}

fileprivate func displayLinkCallback(
Expand Down
4 changes: 2 additions & 2 deletions iina/zh-Hans.lproj/InspectorWindowController.strings
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@
/* Class = "NSTextFieldCell"; title = "Editions:"; ObjectID = "POj-mQ-zP9"; */
"POj-mQ-zP9.title" = "集数:";

/* Class = "NSTextFieldCell"; title = "Primaries:"; ObjectID = "tpN-Ov-ew9"; */
"tpN-Ov-ew9.title" = "色域:";
/* Class = "NSTextFieldCell"; title = "Primaries:"; ObjectID = "1kw-LO-KmJ"; */
"1kw-LO-KmJ.title" = "色域:";

/* Class = "NSTextFieldCell"; title = "Format:"; ObjectID = "PQD-yB-mm6"; */
"PQD-yB-mm6.title" = "格式:";
Expand Down

0 comments on commit e5a4dae

Please sign in to comment.