mirror of
https://github.com/yattee/yattee.git
synced 2026-02-20 01:39:46 +00:00
Yattee v2 rewrite
This commit is contained in:
161
Yattee/Core/HardwareCapabilities.swift
Normal file
161
Yattee/Core/HardwareCapabilities.swift
Normal file
@@ -0,0 +1,161 @@
|
||||
//
|
||||
// HardwareCapabilities.swift
|
||||
// Yattee
|
||||
//
|
||||
// Detects hardware video decoding capabilities using VideoToolbox.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import VideoToolbox
|
||||
import CoreMedia
|
||||
|
||||
/// Detects and caches hardware video decoding capabilities for the current device.
|
||||
@MainActor
|
||||
final class HardwareCapabilities {
|
||||
static let shared = HardwareCapabilities()
|
||||
|
||||
// MARK: - Cached Results
|
||||
|
||||
private var _supportsH264Hardware: Bool?
|
||||
private var _supportsHEVCHardware: Bool?
|
||||
private var _supportsHEVCAlphaHardware: Bool?
|
||||
private var _supportsDolbyVisionHEVCHardware: Bool?
|
||||
private var _supportsVP9Hardware: Bool?
|
||||
private var _supportsAV1Hardware: Bool?
|
||||
private var _supportsProResHardware: Bool?
|
||||
|
||||
// MARK: - Hardware Support Properties
|
||||
|
||||
/// Whether the device supports H.264/AVC hardware decoding.
|
||||
var supportsH264Hardware: Bool {
|
||||
if let cached = _supportsH264Hardware { return cached }
|
||||
let supported = VTIsHardwareDecodeSupported(kCMVideoCodecType_H264)
|
||||
_supportsH264Hardware = supported
|
||||
return supported
|
||||
}
|
||||
|
||||
/// Whether the device supports HEVC/H.265 hardware decoding.
|
||||
var supportsHEVCHardware: Bool {
|
||||
if let cached = _supportsHEVCHardware { return cached }
|
||||
let supported = VTIsHardwareDecodeSupported(kCMVideoCodecType_HEVC)
|
||||
_supportsHEVCHardware = supported
|
||||
return supported
|
||||
}
|
||||
|
||||
/// Whether the device supports HEVC with Alpha hardware decoding.
|
||||
var supportsHEVCAlphaHardware: Bool {
|
||||
if let cached = _supportsHEVCAlphaHardware { return cached }
|
||||
let supported = VTIsHardwareDecodeSupported(kCMVideoCodecType_HEVCWithAlpha)
|
||||
_supportsHEVCAlphaHardware = supported
|
||||
return supported
|
||||
}
|
||||
|
||||
/// Whether the device supports Dolby Vision HEVC hardware decoding.
|
||||
var supportsDolbyVisionHEVCHardware: Bool {
|
||||
if let cached = _supportsDolbyVisionHEVCHardware { return cached }
|
||||
let supported = VTIsHardwareDecodeSupported(kCMVideoCodecType_DolbyVisionHEVC)
|
||||
_supportsDolbyVisionHEVCHardware = supported
|
||||
return supported
|
||||
}
|
||||
|
||||
/// Whether the device supports VP9 hardware decoding.
|
||||
var supportsVP9Hardware: Bool {
|
||||
if let cached = _supportsVP9Hardware { return cached }
|
||||
let supported = VTIsHardwareDecodeSupported(kCMVideoCodecType_VP9)
|
||||
_supportsVP9Hardware = supported
|
||||
return supported
|
||||
}
|
||||
|
||||
/// Whether the device supports AV1 hardware decoding.
|
||||
var supportsAV1Hardware: Bool {
|
||||
if let cached = _supportsAV1Hardware { return cached }
|
||||
let supported = VTIsHardwareDecodeSupported(kCMVideoCodecType_AV1)
|
||||
_supportsAV1Hardware = supported
|
||||
return supported
|
||||
}
|
||||
|
||||
/// Whether the device supports ProRes hardware decoding.
|
||||
var supportsProResHardware: Bool {
|
||||
if let cached = _supportsProResHardware { return cached }
|
||||
let supported = VTIsHardwareDecodeSupported(kCMVideoCodecType_AppleProRes422)
|
||||
_supportsProResHardware = supported
|
||||
return supported
|
||||
}
|
||||
|
||||
// MARK: - Codec Priority
|
||||
|
||||
/// Returns codec priority for stream selection (higher = better).
|
||||
///
|
||||
/// When hardware decode is available, the codec gets a higher priority
|
||||
/// to prefer battery-efficient playback. When not available, codecs that
|
||||
/// require software decode get priority 0 to prefer hardware-decodable
|
||||
/// alternatives at the same or similar resolution.
|
||||
///
|
||||
/// Priority levels:
|
||||
/// - 4: Best (AV1 with hardware)
|
||||
/// - 3: Great (VP9 with hardware, HEVC with hardware)
|
||||
/// - 2: Good (H.264 - always hardware supported)
|
||||
/// - 1: Acceptable (HEVC software - rare)
|
||||
/// - 0: Avoid (AV1/VP9 software - battery drain, potential performance issues)
|
||||
func codecPriority(for codec: String?) -> Int {
|
||||
guard let codec = codec?.lowercased() else { return 0 }
|
||||
|
||||
if codec.contains("av1") || codec.contains("av01") {
|
||||
// AV1: Best compression but avoid without hardware (heavy CPU usage)
|
||||
return supportsAV1Hardware ? 4 : 0
|
||||
} else if codec.contains("vp9") || codec.contains("vp09") {
|
||||
// VP9: Good compression but avoid without hardware (battery drain)
|
||||
return supportsVP9Hardware ? 3 : 0
|
||||
} else if codec.contains("avc") || codec.contains("h264") || codec.contains("h.264") {
|
||||
// H.264: Universal hardware support - reliable choice
|
||||
return 2
|
||||
} else if codec.contains("hevc") || codec.contains("hev") || codec.contains("h265") || codec.contains("h.265") {
|
||||
// HEVC: Good compression, most devices have hardware support
|
||||
return supportsHEVCHardware ? 3 : 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
/// Returns an ordered list of preferred codecs based on hardware support.
|
||||
var preferredCodecOrder: [String] {
|
||||
var codecs: [(String, Int)] = []
|
||||
|
||||
if supportsAV1Hardware {
|
||||
codecs.append(("AV1", 4))
|
||||
}
|
||||
if supportsVP9Hardware {
|
||||
codecs.append(("VP9", 3))
|
||||
}
|
||||
// H.264 is always hardware supported
|
||||
codecs.append(("H.264", 2))
|
||||
if supportsHEVCHardware {
|
||||
codecs.append(("HEVC", 2))
|
||||
}
|
||||
|
||||
return codecs.sorted { $0.1 > $1.1 }.map { $0.0 }
|
||||
}
|
||||
|
||||
// MARK: - All Capabilities
|
||||
|
||||
/// Returns all codec capabilities for display in Device Capabilities view.
|
||||
var allCapabilities: [(name: String, supported: Bool)] {
|
||||
[
|
||||
("H.264/AVC", supportsH264Hardware),
|
||||
("HEVC/H.265", supportsHEVCHardware),
|
||||
("HEVC with Alpha", supportsHEVCAlphaHardware),
|
||||
("Dolby Vision HEVC", supportsDolbyVisionHEVCHardware),
|
||||
("VP9", supportsVP9Hardware),
|
||||
("AV1", supportsAV1Hardware),
|
||||
("ProRes", supportsProResHardware)
|
||||
]
|
||||
}
|
||||
|
||||
// MARK: - Logging
|
||||
|
||||
/// Logs all hardware capabilities for debugging.
|
||||
func logCapabilities() {
|
||||
let capabilities = allCapabilities.map { "\($0.name): \($0.supported ? "Yes" : "No")" }.joined(separator: ", ")
|
||||
LoggingService.shared.info("Hardware decode capabilities: \(capabilities)", category: .general)
|
||||
LoggingService.shared.info("Preferred codec order: \(preferredCodecOrder.joined(separator: " > "))", category: .general)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user