import Foundation // The caller supplies monotonic seconds, keeping the policy independent of timers and extraction. struct AutomaticQuality { struct Sample { var enabled = true var network = true var playing = true var opening = false var seeking = false var live = false var buffering = false var position: Double var duration: Double var ahead: Double? var height: Int? var heights: [Int] } private var lowSince: Double? private var healthySince: Double? private var stallSince: Double? private var lastPosition: Double? private var lastProgress: Double? private var notBefore = -Double.infinity mutating func resetHealth() { lowSince = nil healthySince = nil stallSince = nil lastPosition = nil lastProgress = nil } mutating func extractionFailed(at now: Double) { resetHealth() notBefore = max(notBefore, now + 120) } mutating func choose(_ sample: Sample, at now: Double) -> Int? { guard sample.enabled, sample.network, sample.playing, !sample.opening, !sample.seeking, sample.position.isFinite, let height = sample.height, height > 0 else { resetHealth() return nil } guard !sample.heights.isEmpty, sample.live || !sample.duration.isFinite || sample.duration <= 0 || sample.duration - sample.position > 15 else { resetHealth() return nil } if let lastPosition, sample.position < lastPosition - 0.1 { resetHealth() } if lastPosition == nil || sample.position > lastPosition! + 0.01 { lastPosition = sample.position lastProgress = now } let stalled = sample.buffering || now - (lastProgress ?? now) >= 3 let ahead = sample.ahead.flatMap { $0.isFinite && $0 >= 0 ? $0 : nil } // Live packet timestamps are not a reliable reserve estimate. let knownReserve = !sample.live && ahead != nil if stalled { stallSince = stallSince ?? now } else { stallSince = nil } if knownReserve && ahead! < 4 { lowSince = lowSince ?? now } else { lowSince = nil } if !stalled && (!knownReserve || ahead! >= 20) { healthySince = healthySince ?? now } else { healthySince = nil } guard now >= notBefore else { return nil } let downshift = stallSince.map({ now - $0 >= 3 }) == true || lowSince.map({ now - $0 >= 6 }) == true let upshift = healthySince.map({ now - $0 >= (knownReserve ? 60 : 120) }) == true guard height > 1080 || downshift || upshift else { return nil } var target: Int? for available in sample.heights where available > 0 && available <= 1080 { if height > 1080 || downshift { if available < height && available > (target ?? 0) { target = available } } else if available > height && available < (target ?? Int.max) { target = available } } guard let target else { return nil } notBefore = now + 30 resetHealth() return target } }