mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-04-01 06:31:53 +01:00
refactor(tv): unify subtitle track selector and search into tabbed sheet
This commit is contained in:
@@ -4,12 +4,21 @@ import CoreMedia
|
||||
import CoreVideo
|
||||
import AVFoundation
|
||||
|
||||
/// HDR mode detected from video properties
|
||||
enum HDRMode {
|
||||
case sdr
|
||||
case hdr10
|
||||
case dolbyVision
|
||||
case hlg
|
||||
}
|
||||
|
||||
protocol MPVLayerRendererDelegate: AnyObject {
|
||||
func renderer(_ renderer: MPVLayerRenderer, didUpdatePosition position: Double, duration: Double)
|
||||
func renderer(_ renderer: MPVLayerRenderer, didChangePause isPaused: Bool)
|
||||
func renderer(_ renderer: MPVLayerRenderer, didChangeLoading isLoading: Bool)
|
||||
func renderer(_ renderer: MPVLayerRenderer, didBecomeReadyToSeek: Bool)
|
||||
func renderer(_ renderer: MPVLayerRenderer, didBecomeTracksReady: Bool)
|
||||
func renderer(_ renderer: MPVLayerRenderer, didDetectHDRMode mode: HDRMode, fps: Double)
|
||||
}
|
||||
|
||||
/// MPV player using vo_avfoundation for video output.
|
||||
@@ -427,7 +436,10 @@ final class MPVLayerRenderer {
|
||||
self.delegate?.renderer(self, didChangeLoading: false)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Detect HDR mode for tvOS display switching
|
||||
detectHDRMode()
|
||||
|
||||
case MPV_EVENT_SEEK:
|
||||
// Seek started - show loading indicator and enable immediate progress updates
|
||||
isSeeking = true
|
||||
@@ -793,6 +805,53 @@ final class MPVLayerRenderer {
|
||||
return Int(aid)
|
||||
}
|
||||
|
||||
// MARK: - HDR Detection
|
||||
|
||||
/// Detects the HDR mode of the currently playing video by reading mpv properties
|
||||
private func detectHDRMode() {
|
||||
guard let handle = mpv else { return }
|
||||
|
||||
// Get video color properties
|
||||
let primaries = getStringProperty(handle: handle, name: "video-params/primaries")
|
||||
let gamma = getStringProperty(handle: handle, name: "video-params/gamma")
|
||||
|
||||
// Get FPS for display criteria
|
||||
var fps: Double = 24.0
|
||||
getProperty(handle: handle, name: "container-fps", format: MPV_FORMAT_DOUBLE, value: &fps)
|
||||
if fps <= 0 { fps = 24.0 }
|
||||
|
||||
Logger.shared.log("HDR Detection - primaries: \(primaries ?? "nil"), gamma: \(gamma ?? "nil"), fps: \(fps)", type: "Info")
|
||||
|
||||
// Determine HDR mode based on color properties
|
||||
// bt.2020 primaries with PQ gamma = HDR10 or Dolby Vision
|
||||
// bt.2020 primaries with HLG gamma = HLG
|
||||
// Otherwise SDR
|
||||
let hdrMode: HDRMode
|
||||
|
||||
if primaries == "bt.2020" || primaries == "bt.2020-ncl" {
|
||||
if gamma == "pq" {
|
||||
// PQ gamma indicates HDR10 or Dolby Vision
|
||||
// We'll use hdr10 as the base, Dolby Vision detection would need codec inspection
|
||||
// For DV Profile 8.1, HDR10 fallback should work
|
||||
hdrMode = .hdr10
|
||||
} else if gamma == "hlg" {
|
||||
hdrMode = .hlg
|
||||
} else {
|
||||
// bt.2020 without HDR gamma - still request HDR mode for wide color
|
||||
hdrMode = .hdr10
|
||||
}
|
||||
} else {
|
||||
hdrMode = .sdr
|
||||
}
|
||||
|
||||
Logger.shared.log("HDR Detection - detected mode: \(hdrMode)", type: "Info")
|
||||
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
guard let self else { return }
|
||||
self.delegate?.renderer(self, didDetectHDRMode: hdrMode, fps: fps)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Technical Info
|
||||
|
||||
func getTechnicalInfo() -> [String: Any] {
|
||||
|
||||
@@ -308,6 +308,9 @@ class MpvPlayerView: ExpoView {
|
||||
}
|
||||
|
||||
deinit {
|
||||
#if os(tvOS)
|
||||
resetDisplayCriteria()
|
||||
#endif
|
||||
pipController?.stopPictureInPicture()
|
||||
renderer?.stop()
|
||||
displayLayer.removeFromSuperlayer()
|
||||
@@ -376,8 +379,63 @@ extension MpvPlayerView: MPVLayerRendererDelegate {
|
||||
self.onTracksReady([:])
|
||||
}
|
||||
}
|
||||
|
||||
func renderer(_: MPVLayerRenderer, didDetectHDRMode mode: HDRMode, fps: Double) {
|
||||
#if os(tvOS)
|
||||
setDisplayCriteria(for: mode, fps: Float(fps))
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - tvOS HDR Display Criteria
|
||||
|
||||
#if os(tvOS)
|
||||
import AVKit
|
||||
|
||||
extension MpvPlayerView {
|
||||
/// Sets the preferred display criteria for HDR content on tvOS
|
||||
func setDisplayCriteria(for hdrMode: HDRMode, fps: Float) {
|
||||
guard let window = self.window else {
|
||||
print("🎬 HDR: No window available for display criteria")
|
||||
return
|
||||
}
|
||||
|
||||
let manager = window.avDisplayManager
|
||||
|
||||
switch hdrMode {
|
||||
case .sdr:
|
||||
print("🎬 HDR: Setting display criteria to SDR (nil)")
|
||||
manager.preferredDisplayCriteria = nil
|
||||
case .hdr10:
|
||||
print("🎬 HDR: Setting display criteria to HDR10, fps: \(fps)")
|
||||
manager.preferredDisplayCriteria = AVDisplayCriteria(
|
||||
refreshRate: fps,
|
||||
videoDynamicRange: "hdr10"
|
||||
)
|
||||
case .dolbyVision:
|
||||
print("🎬 HDR: Setting display criteria to Dolby Vision, fps: \(fps)")
|
||||
manager.preferredDisplayCriteria = AVDisplayCriteria(
|
||||
refreshRate: fps,
|
||||
videoDynamicRange: "dolbyVision"
|
||||
)
|
||||
case .hlg:
|
||||
print("🎬 HDR: Setting display criteria to HLG, fps: \(fps)")
|
||||
manager.preferredDisplayCriteria = AVDisplayCriteria(
|
||||
refreshRate: fps,
|
||||
videoDynamicRange: "hlg"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Resets display criteria when playback ends
|
||||
func resetDisplayCriteria() {
|
||||
guard let window = self.window else { return }
|
||||
print("🎬 HDR: Resetting display criteria")
|
||||
window.avDisplayManager.preferredDisplayCriteria = nil
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// MARK: - PiPControllerDelegate
|
||||
|
||||
extension MpvPlayerView: PiPControllerDelegate {
|
||||
|
||||
Reference in New Issue
Block a user