@@ -215,7 +215,8 @@ private final class VsyncClock: @unchecked Sendable {
// / ~ 2 – 3 r e f r e s h e s o f q u e u e ( t h e m e a s u r e d 2 3 – 3 0 m s d i s p l a y s t a g e o n 1 2 0 H z P r o M o t i o n p a n e l s ) , a n d
// / t h e f u l l - q u e u e r e g i m e i s w h e r e h o s t ↔ p a n e l c l o c k d r i f t t u r n s i n t o p e r i o d i c r e p e a t s / d r o p s ( t h e
// / " f i x e d - i n t e r v a l " j i t t e r r e p o r t s ) .
// / - ` g l a s s ` ( s t a g e - 3 , t h e t v O S d e f a u l t ) : a t m o s t a s m a l l B O U N D E D n u m b e r o f p r e s e n t e d - b u t -
// / - ` g l a s s ` ( s t a g e - 3 ; t v O S ' s d e f a u l t u n t i l t h e 2 0 2 6 - 0 7 r e b u i l d m o v e d i t t o s t a g e - 4 , n o w a n
// / o n - d e v i c e A / B r u n g ) : a t m o s t a s m a l l B O U N D E D n u m b e r o f p r e s e n t e d - b u t -
// / u n d i s p l a y e d d r a w a b l e s i n f l i g h t ( ` P r e s e n t G a t e ` ; d e p t h 1 — s e e ` S e s s i o n P r e s e n t e r . g a t e D e p t h `
// / f o r w h y d e e p e r i s a r e g r e s s i o n ) . T h e r e n d e r t h r e a d p r e s e n t s o n l y w h i l e a g a t e s l o t i s f r e e
// / ( a d r a w a b l e ' s p r e s e n t e d h a n d l e r r e o p e n s i t s s l o t a n d r e - s i g n a l s ) ; f r a m e s d e c o d e d m e a n w h i l e
@@ -293,6 +294,108 @@ private final class FrameRateHint: @unchecked Sendable {
}
}
// / T h e c l i e n t h a l f o f p h a s e - l o c k e d c a p t u r e ( d e s i g n / p h a s e - l o c k e d - c a p t u r e . m d ) : t h e d e c o d e
// / c a l l b a c k d e p o s i t s p e r - A U a r r i v a l s t a m p s ( c l i e n t C L O C K _ R E A L T I M E — t h e c o r e ' s r e a s s e m b l y -
// / c o m p l e t i o n t i m e ) , t h e d e a d l i n e l i n k ' s t h r e a d d e p o s i t s t h e l a t c h g r i d , a n d ~ 1 H z t h a t s a m e
// / t h r e a d f l u s h e s t h e c i r c u l a r a r r i v a l - p h a s e s t a t i s t i c t o t h e h o s t . T h e s t a t i s t i c i s a
// / v e r b a t i m p o r t o f ` p u n k t f u n k _ c o r e : : p h a s e : : c i r c u l a r _ l a t c h ` — t h e h o s t ' s v 3 c o n t r o l l e r
// / ( g r i d - l o c k e d s u b m i t s , c o h e r e n c e - g a t e d e n g a g e ) w a s t u n e d a g a i n s t e x a c t l y i t , a n d a
// / p e r i o d - s m e a r e d W i - F i l i n k c o r r e c t l y r e a d s c o h e r e n c e ≈ 0 t h e r e , s o t h e c o n t r o l l e r n e v e r
// / e n g a g e s w h e r e a l i g n m e n t i s p h y s i c a l l y p o i n t l e s s . S h a r e d b o x ( n e v e r c a p t u r e s t h e p i p e l i n e ) ;
// / a s e s s i o n ' s c o n n e c t i o n b i n d s / u n b i n d s l i k e D e c o d e R e p o r t / K e y f r a m e R e c o v e r y .
final class PhaseReporter : @ unchecked Sendable {
private let lock = NSLock ( )
private var connection : PunktfunkConnection ?
// / A r r i v a l s t a m p s s i n c e t h e l a s t f l u s h , c l i e n t C L O C K _ R E A L T I M E . B o u n d e d : ~ 1 s a t 2 4 0 f p s .
private var arrivalsNs : [ Int64 ] = [ ]
// / S m a l l e s t u p d a t e - t o - u p d a t e s p a c i n g t h i s w i n d o w : s u c c e s s i v e ` n e x t L a t c h ` v a l u e s s i t o n e
// / p a n e l p e r i o d a p a r t e x c e p t a c r o s s s k i p p e d l i n k u p d a t e s ( 2 × , 3 × , … ) , s o t h e w i n d o w
// / m i n i m u m I S t h e p e r i o d . R e - l e a r n e d e v e r y f l u s h s o V R R / m o d e s w i t c h e s t r a c k b o t h w a y s .
private var periodNs : Int64 = 0
private var prevLatchRealNs : Int64 = 0
private var lastFlushRealNs : Int64 = 0
func bind ( _ c : PunktfunkConnection ? ) {
lock . lock ( )
connection = c
arrivalsNs . removeAll ( )
periodNs = 0
prevLatchRealNs = 0
lastFlushRealNs = 0
lock . unlock ( )
}
// / D e c o d e - c a l l b a c k s i d e : o n e A U ' s a r r i v a l ( r e a s s e m b l y - c o m p l e t i o n ) s t a m p .
func noteArrival ( receivedNs : Int64 ) {
lock . lock ( )
if connection != nil , arrivalsNs . count < 256 { arrivalsNs . append ( receivedNs ) }
lock . unlock ( )
}
// / L i n k - t h r e a d s i d e , o n c e p e r u p d a t e : w h e r e t h e N E X T l a t c h s i t s o n t h e c l i e n t ' s r e a l t i m e
// / c l o c k ( t h e a r r i v a l s t a m p s ' d o m a i n ) . L e a r n s t h e p e r i o d f r o m u p d a t e s p a c i n g a n d ~ 1 H z
// / c o n v e r t s t h e w i n d o w ' s a r r i v a l s i n t o l e a d s a g a i n s t t h i s g r i d , t h e n r e p o r t s — a
// / f i r e - a n d - f o r g e t d a t a g r a m p u s h o n t h e c o n t r o l p l a n e .
func noteGrid ( nextLatchRealNs : Int64 ) {
lock . lock ( )
if prevLatchRealNs > 0 {
let delta = nextLatchRealNs - prevLatchRealNs
// 2 – 1 0 0 m s a c c e p t s 1 0 – 5 0 0 H z p a n e l s , r e j e c t s w a k e u p h i c c u p s a n d c l o c k j u m p s .
if delta > 2_000_000 , delta < 100_000_000 , periodNs = = 0 || delta < periodNs {
periodNs = delta
}
}
prevLatchRealNs = nextLatchRealNs
guard let c = connection , periodNs > 0 , arrivalsNs . count >= 8 ,
nextLatchRealNs - lastFlushRealNs >= 1_000_000_000
else {
lock . unlock ( )
return
}
lastFlushRealNs = nextLatchRealNs
let period = periodNs
let leadsUs = arrivalsNs . map { a -> UInt64 in
let m = ( nextLatchRealNs - a ) % period
return UInt64 ( m < 0 ? m + period : m ) / 1000
}
arrivalsNs . removeAll ( keepingCapacity : true )
periodNs = 0
let offsetNs = c . clockOffsetNs
lock . unlock ( )
guard
let ( leadMeanNs , coherence ) = Self . circularLatch (
samplesUs : leadsUs , periodNs : period )
else { return }
c . reportPhase (
nextLatchHostNs : UInt64 ( max ( 0 , nextLatchRealNs + offsetNs ) ) ,
latchPeriodNs : UInt32 ( clamping : period ) ,
uncertaintyNs : 1_000_000 , // s k e w r e s i d u a l — s a m e c o n s e r v a t i v e 1 m s a s A n d r o i d
arrivalLeadNs : UInt32 ( clamping : leadMeanNs ) ,
coherenceMilli : coherence )
}
// / V e r b a t i m p o r t o f ` p u n k t f u n k _ c o r e : : p h a s e : : c i r c u l a r _ l a t c h ` ( µ s s a m p l e s a g a i n s t a n n s
// / p e r i o d ; n i l u n d e r 8 s a m p l e s ) . T h e M E A N i s w h a t a p h a s e c o n t r o l l e r c a n s t e e r u n d e r
// / j i t t e r — a p e r i o d - s p a n n i n g d i s t r i b u t i o n ' s m e d i a n i s i m m o v a b l e — a n d t h e c o h e r e n c e
// / ( r e s u l t a n t l e n g t h , ‰ ) s a y s w h e t h e r a n y p h a s e e x i s t s t o s t e e r a t a l l .
static func circularLatch ( samplesUs : [ UInt64 ] , periodNs : Int64 ) -> ( UInt64 , UInt16 ) ? {
guard samplesUs . count >= 8 , periodNs > 0 else { return nil }
let periodUs = Double ( periodNs ) / 1000.0
var x = 0.0
var y = 0.0
for s in samplesUs {
let theta = Double ( s ) . truncatingRemainder ( dividingBy : periodUs ) / periodUs * 2 * . pi
x += cos ( theta )
y += sin ( theta )
}
let n = Double ( samplesUs . count )
let r = ( x * x + y * y ) . squareRoot ( ) / n
var meanTheta = atan2 ( y , x )
if meanTheta < 0 { meanTheta += 2 * . pi }
return ( UInt64 ( meanTheta / ( 2 * . pi ) * Double ( periodNs ) ) , UInt16 ( r * 1000.0 ) )
}
}
// / T h e C A M e t a l D i s p l a y L i n k d e l e g a t e f o r d e a d l i n e p a c i n g : e a c h p e r - r e f r e s h u p d a t e s t a s h e s i t s
// / v e n d e d d r a w a b l e ( n e w e s t w i n s ) a n d n u d g e s t h e r e n d e r t h r e a d — w h i c h a l s o w a k e s o n d e c o d e r
// / a r r i v a l s , s o w h i c h e v e r h a l f c o m p l e t e s t h e ( f r a m e , d r a w a b l e ) p a i r t r i g g e r s t h e p r e s e n t . A l s o
@@ -304,6 +407,8 @@ private final class DeadlineLinkDelegate: NSObject, CAMetalDisplayLinkDelegate {
private let renderSignal : DispatchSemaphore
private let hint : FrameRateHint
private let stats : PresentDebugStats ?
// / P h a s e - l o c k e d c a p t u r e ' s g r i d f e e d — t h i s l i n k I S t h e l a t c h g r i d p r e s e n t s p a c e a g a i n s t .
private let phase : PhaseReporter ?
// / T h e O S - f l o o r s a m p l e r ( d e s i g n / a p p l e - p r e s e n t a t i o n - r e b u i l d . m d ) : e v e r y u p d a t e ' s v e n d → g l a s s
// / l e a d i s r e c o r d e d s o i t s p 5 0 b e c o m e s t h e " O S p r e s e n t f l o o r " t h e H U D s u b t r a c t s f r o m t h e
// / s h o w n d i s p l a y / e 2 e n u m b e r s . S e l f - a d a p t i n g — r e a d s ~ 2 r e f r e s h p e r i o d s c o m p o s i t e d t o d a y ,
@@ -316,13 +421,15 @@ private final class DeadlineLinkDelegate: NSObject, CAMetalDisplayLinkDelegate {
init (
stash : LatestBox < CAMetalDrawable > , renderSignal : DispatchSemaphore ,
hint : FrameRateHint , stats : PresentDebugStats ? , floorMeter : LatencyMeter ?
hint : FrameRateHint , stats : PresentDebugStats ? , floorMeter : LatencyMeter ? ,
phase : PhaseReporter ?
) {
self . stash = stash
self . renderSignal = renderSignal
self . hint = hint
self . stats = stats
self . floorMeter = floorMeter
self . phase = phase
}
func metalDisplayLink ( _ link : CAMetalDisplayLink , needsUpdate update : CAMetalDisplayLink . Update ) {
@@ -354,6 +461,15 @@ private final class DeadlineLinkDelegate: NSObject, CAMetalDisplayLinkDelegate {
floorMeter . record (
ptsNs : UInt64 ( nowNs - Int64 ( leadS * 1_000_000_000 ) ) , atNs : nowNs , offsetNs : 0 )
}
// P h a s e - l o c k e d c a p t u r e : t h i s u p d a t e ' s t a r g e t p r e s e n t , c o n v e r t e d i n t o t h e a r r i v a l
// s t a m p s ' C L O C K _ R E A L T I M E d o m a i n . P e r - u p d a t e c o s t i s o n e c l o c k r e a d ; t h e r e p o r t e r
// i t s e l f f l u s h e s ~ 1 H z .
if let phase {
var ts = timespec ( )
clock_gettime ( CLOCK_REALTIME , & ts )
let nowNs = Int64 ( ts . tv_sec ) * 1_000_000_000 + Int64 ( ts . tv_nsec )
phase . noteGrid ( nextLatchRealNs : nowNs + Int64 ( leadS * 1_000_000_000 ) )
}
stash . put ( update . drawable )
renderSignal . signal ( )
}
@@ -583,6 +699,7 @@ public final class Stage2Pipeline {
// / F e e d s t h e c o r e A u t o m a t i c - b i t r a t e c o n t r o l l e r ' s d e c o d e s i g n a l f r o m t h e d e c o d e c a l l b a c k ; ` s t a r t `
// / b i n d s t h e l i v e c o n n e c t i o n + a r m i n g f l a g ( s e e D e c o d e R e p o r t ) .
private let decodeReport = DecodeReport ( )
private let phaseReporter = PhaseReporter ( )
// / P o s t - l o s s f r e e z e - u n t i l - r e a n c h o r g a t e ( s h a r e d c o r e p o l i c y v i a t h e C A B I ) . C r e a t e d h e r e s e e d e d 0 ;
// / ` s t a r t ` r e s e e d s i t t o t h e l i v e c o n n e c t i o n ' s d r o p c o u n t . C a p t u r e d b y t h e d e c o d e r c a l l b a c k s
// / ( w h i c h w i t h h o l d c o n c e a l e d f r a m e s ) a n d d r i v e n b y t h e p u m p ( a r m o n a g a p , p o l l p e r i t e r a t i o n ) .
@@ -649,6 +766,7 @@ public final class Stage2Pipeline {
let renderSignal = renderSignal
let gate = gate
let decodeReport = decodeReport
let phaseReporter = phaseReporter
self . decoder = VideoDecoder (
onDecoded : { frame in
// D e c o d e s t a g e = r e c e i v e d → d e c o d e d , b o t h c l i e n t C L O C K _ R E A L T I M E ( o f f s e t 0 — n o
@@ -660,6 +778,9 @@ public final class Stage2Pipeline {
// d e v i c e ' s r e a l d e c o d e l i m i t i n s t e a d o f t h e n e t w o r k l i n k c e i l i n g . E v e r y d e c o d e d
// f r a m e ( n o t j u s t p r e s e n t e d o n e s ) , s o a n e w e s t - w i n s d r o p c a n ' t h i d e t h e b a c k l o g .
decodeReport . record ( receivedNs : frame . receivedNs , decodedNs : frame . decodedNs )
// P h a s e - l o c k e d c a p t u r e ' s a r r i v a l h a l f : t h e s t a m p V A L U E i s r e a s s e m b l y
// c o m p l e t i o n , s o r e c o r d i n g i t a t d e c o d e a d d s n o b i a s t o t h e 1 H z a g g r e g a t e .
phaseReporter . noteArrival ( receivedNs : frame . receivedNs )
// F r e e z e - u n t i l - r e a n c h o r : W I T H H O L D a d e c o d e r - c o n c e a l e d p o s t - l o s s f r a m e ( t h e g r a y /
// g a r b a g e V i d e o T o o l b o x r e t u r n s O k f o r a r e f e r e n c e - m i s s i n g d e l t a ) — d o n ' t s u b m i t i t ,
// s o t h e C A M e t a l L a y e r k e e p s i t s l a s t g o o d d r a w a b l e o n g l a s s . T h e g a t e l i f t s ( r e t u r n s
@@ -689,6 +810,7 @@ public final class Stage2Pipeline {
offsetNs = connection . clockOffsetNs
recovery . bind ( connection ) // a r m h o s t - k e y f r a m e r e c o v e r y f o r t h i s s e s s i o n
decodeReport . bind ( connection ) // a r m t h e A u t o m a t i c - b i t r a t e d e c o d e s i g n a l f o r t h i s s e s s i o n
phaseReporter . bind ( connection ) // a r m p h a s e r e p o r t s ( f l u s h e d o n l y b y t h e d e a d l i n e l i n k )
gate . reseed ( framesDropped : connection . framesDropped ( ) ) // b a s e l i n e t h e f r e e z e t o t h i s s e s s i o n
token = StopFlag ( ) // f r e s h t o k e n p e r s t a r t — a s t o p i s p e r m a n e n t ( l i k e S t r e a m P u m p )
@@ -975,6 +1097,7 @@ public final class Stage2Pipeline {
let stash = LatestBox < CAMetalDrawable > ( )
let floorMeter = presentFloorMeter
let phaseReporter = phaseReporter
// T h e l i n k s t a r t s L A Z I L Y — t h e r e n d e r t h r e a d t r i g g e r s t h i s a f t e r t h e F I R S T d e c o d e d
// f r a m e ' s r e c o n c i l e L a y e r . S t a r t e d e a g e r l y i t v e n d s i n t o t h e l a y e r ' s i n i t i a l 0 × 0
// d r a w a b l e S i z e f o r t h e w h o l e c o n n e c t w i n d o w : e v e r y v e n d f a i l s a l l o c a t i o n a n d t h e s y s t e m
@@ -985,7 +1108,7 @@ public final class Stage2Pipeline {
let linkThread = Thread {
let delegate = DeadlineLinkDelegate (
stash : stash , renderSignal : renderSignal , hint : hint , stats : debugStats ,
floorMeter : floorMeter )
floorMeter : floorMeter , phase : phaseReporter )
let link = CAMetalDisplayLink ( metalLayer : layer )
link . preferredFrameLatency = 1 // w a k e a s l a t e a s f i t s : l a t c h t h e N E X T r e f r e s h
if let range = hint . drain ( ) { link . preferredFrameRateRange = range }
@@ -1154,6 +1277,7 @@ public final class Stage2Pipeline {
}
decoder . reset ( )
recovery . bind ( nil ) // s t o p r e q u e s t i n g k e y f r a m e s o n c e t h e s e s s i o n i s t o r n d o w n
phaseReporter . bind ( nil ) // a n d s t o p p h a s e r e p o r t s t o w a r d t h e d e a d c o n n e c t i o n
}
deinit {