Commit eb3571a
committed
fix(macos): recover capture after the display sleeps
Capture waited on the session semaphore with DISPATCH_TIME_FOREVER, but that
semaphore is only signalled when the frame callback returns false — that is,
when capture is deliberately stopped. A sleeping display stops
AVCaptureSession delivering sample buffers and the session does not resume
when the display wakes, so the capture thread parked for the lifetime of the
process. Since capture() could also only ever return capture_e::ok, and
video.cpp rebuilds the display only on capture_e::reinit, nothing could bring
the stream back and the user had to restart Sunshine.
Poll the semaphore instead and watch the display while waiting. A display
that slept and then woke returns capture_e::reinit so the caller rebuilds it.
Waiting for the wake transition rather than for a frame-arrival timeout keeps
a static screen from being mistaken for a stalled one.
Abandoning a capture needs the same teardown the frame callback performs when
it returns false, so AVVideo grows a stopCapture: for it. Merely stopping the
session leaves the output in the capture session and in the map tables, and
-[AVVideo dealloc] releases those map tables before it stops the session, so
the output is released while the session still holds it and the process dies
in objc_msgSend during the next reinitialization.
dummy_img() had the same unbounded wait, where the semaphore genuinely does
mean "one frame arrived". Encoder probing hung there indefinitely when the
display was asleep, so bound it and report failure instead.
Tested on macOS 26.6.1 (Apple M1 Max): with a stream running, a hot corner set
to Put Display to Sleep, and the display then woken, capture is rebuilt in
under 100 ms and a fresh IDR frame follows within 300 ms. Two sleep/wake
cycles in a row were survived by a single uninterrupted client session.1 parent cf52f4b commit eb3571a
3 files changed
Lines changed: 91 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
88 | 88 | | |
89 | 89 | | |
90 | 90 | | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
91 | 102 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
93 | 93 | | |
94 | 94 | | |
95 | 95 | | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
96 | 122 | | |
97 | 123 | | |
98 | 124 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
52 | 52 | | |
53 | 53 | | |
54 | 54 | | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
55 | 80 | | |
56 | 81 | | |
57 | 82 | | |
| |||
105 | 130 | | |
106 | 131 | | |
107 | 132 | | |
108 | | - | |
109 | | - | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
110 | 152 | | |
111 | 153 | | |
112 | 154 | | |
| |||
184 | 226 | | |
185 | 227 | | |
186 | 228 | | |
187 | | - | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
188 | 239 | | |
189 | 240 | | |
190 | 241 | | |
| |||
0 commit comments