oficina / meet Public

Clone
git clone https://amadan.net/oficina/meet

Plain git — no account needed to clone.

Download

Download this file

1import LiveKitWebRTC
2import XCTest
3
4@testable import CallsKit
5
6/// The screen's sending half: what each "Optimise for" mode asks of the
7/// sender, the camera capped beside a share and given back after it, and
8/// the statistics line that says how the screen is actually leaving.
9/// room-share.test.mjs holds the browser's sharePlan and cameraCap to the
10/// same numbers; a change here belongs there too.
11final class ScreenSendTests: XCTestCase {
12 // MARK: - Policy
13
14 func testDetailKeepsResolutionAtTheHighestCeiling() {
15 let plan = ScreenSendPolicy.screen(.detail, width: 1920, height: 1080)
16 XCTAssertEqual(plan.degradation, .maintainResolution)
17 XCTAssertEqual(plan.maxBitrate, 3_500_000)
18 XCTAssertEqual(plan.maxFramerate, 30)
19 XCTAssertNil(plan.scaleResolutionDownBy, "a 1080p screen is sent whole")
20 XCTAssertTrue(plan.highPriority)
21 XCTAssertEqual(plan.bitratePriority, 4)
22 }
23
24 func testMotionKeepsTheFrameRateAt1280() {
25 let plan = ScreenSendPolicy.screen(.motion, width: 1920, height: 1080)
26 XCTAssertEqual(plan.degradation, .maintainFramerate)
27 XCTAssertEqual(plan.maxFramerate, 30)
28 XCTAssertEqual(plan.scaleResolutionDownBy ?? 0, 1.5, accuracy: 0.0001, "1920 down to 1280")
29 XCTAssertTrue(plan.highPriority)
30 // A portrait window is scaled by its long side, too — and then a
31 // little further, to H.264 level 3.1's 3,600 blocks (see
32 // realtimeMacroblocks): 800×1280 would be 4,000.
33 let portrait = ScreenSendPolicy.screen(.motion, width: 1000, height: 1600).scaleResolutionDownBy ?? 0
34 XCTAssertGreaterThan(portrait, 1.25)
35 XCTAssertLessThanOrEqual(blocks(1000, 1600, portrait), 3600)
36 // Something already small enough is left alone.
37 XCTAssertNil(ScreenSendPolicy.screen(.motion, width: 1280, height: 720).scaleResolutionDownBy)
38 }
39
40 /// Paul's freeze of 2026-09-28: a 16:10 MacBook display in motion mode
41 /// was 1280×830 at its cap, over level 3.1's 3,600 blocks, and the Mac's
42 /// encoder refused every frame at that size. Motion now fits the level;
43 /// a screencast source (every other mode) is not held to it.
44 func testMotionFitsH264Level31() {
45 for (w, h) in [(3024, 1964), (1920, 1246), (2560, 1600), (1920, 1200), (1470, 956), (1920, 1080)] {
46 let scale = ScreenSendPolicy.screen(.motion, width: w, height: h).scaleResolutionDownBy ?? 1
47 XCTAssertLessThanOrEqual(blocks(w, h, scale), 3600, "\(w)×\(h) at 1/\(scale)")
48 XCTAssertGreaterThan(blocks(w, h, scale), 3200, "\(w)×\(h) is not shrunk further than it has to be")
49 }
50 // 1080p at 1280×720 is exactly the level, and unchanged.
51 XCTAssertEqual(ScreenSendPolicy.screen(.motion, width: 1920, height: 1080).scaleResolutionDownBy ?? 0, 1.5, accuracy: 0.0001)
52 // Balanced and detail are screencasts and keep their full size.
53 XCTAssertNil(ScreenSendPolicy.screen(.balanced, width: 1920, height: 1246).scaleResolutionDownBy)
54 XCTAssertNil(ScreenSendPolicy.screen(.detail, width: 1920, height: 1200).scaleResolutionDownBy)
55 // A share that started in motion keeps a camera-like source whatever
56 // the mode becomes, and stays within the level.
57 let switched = ScreenSendPolicy.screen(.detail, width: 1920, height: 1246, screencast: false)
58 XCTAssertLessThanOrEqual(blocks(1920, 1246, switched.scaleResolutionDownBy ?? 1), 3600)
59 }
60
61 private func blocks(_ w: Int, _ h: Int, _ scale: Double) -> Int {
62 ((Int(Double(w) / scale) + 15) / 16) * ((Int(Double(h) / scale) + 15) / 16)
63 }
64
65 func testBalancedIsTheDefaultAndKeepsTheFrameRateAtFullSize() {
66 XCTAssertEqual(ScreenShareMode.allCases.first, .balanced)
67 let plan = ScreenSendPolicy.screen(.balanced, width: 1920, height: 1080)
68 // Frames are held; resolution gives way only when it must, from full
69 // size rather than motion's 1280.
70 XCTAssertEqual(plan.degradation, .maintainFramerate)
71 XCTAssertNil(plan.scaleResolutionDownBy)
72 XCTAssertEqual(plan.maxBitrate, 3_000_000)
73 XCTAssertEqual(plan.maxFramerate, 30)
74 XCTAssertTrue(plan.highPriority)
75 XCTAssertTrue(ScreenSendPolicy.screencast(.balanced))
76 XCTAssertTrue(ScreenSendPolicy.screencast(.detail))
77 XCTAssertFalse(ScreenSendPolicy.screencast(.motion))
78 }
79
80 func testH264IsPreferredAndNothingIsDropped() {
81 let factory = RTCPeerConnectionFactory(
82 encoderFactory: RTCDefaultVideoEncoderFactory(), decoderFactory: RTCDefaultVideoDecoderFactory())
83 let codecs = factory.rtpSenderCapabilities(forKind: "video").codecs
84 let preferred = ScreenSendPolicy.preferringH264(codecs)
85 XCTAssertEqual(preferred.count, codecs.count, "every codec stays on offer")
86 XCTAssertEqual(preferred.first?.name, "H264")
87 XCTAssertTrue(preferred.contains { $0.name == "VP8" }, "a browser without H.264 still has VP8")
88 }
89
90 func testAScreenLargerThan1920IsNeverSentLarger() {
91 for mode in ScreenShareMode.allCases {
92 let plan = ScreenSendPolicy.screen(mode, width: 3840, height: 2160)
93 XCTAssertGreaterThanOrEqual(plan.scaleResolutionDownBy ?? 1, 2, "\(mode)")
94 }
95 }
96
97 func testAnUnknownSizeLeavesTheScaleAlone() {
98 for mode in ScreenShareMode.allCases {
99 XCTAssertNil(ScreenSendPolicy.screen(mode).scaleResolutionDownBy, "\(mode)")
100 }
101 }
102
103 func testTheCameraIsCappedWhileSharingAndGivenBackAfter() {
104 let capped = ScreenSendPolicy.camera(sharing: true, height: 480)
105 XCTAssertEqual(capped.maxBitrate, 500_000)
106 XCTAssertEqual(capped.scaleResolutionDownBy ?? 0, 480.0 / 360.0, accuracy: 0.0001)
107 XCTAssertFalse(capped.highPriority)
108 XCTAssertNil(ScreenSendPolicy.camera(sharing: true, height: 360).scaleResolutionDownBy)
109 XCTAssertEqual(ScreenSendPolicy.camera(sharing: false), EncodingPlan(), "the encoder's own defaults")
110 }
111
112 func testTheModeIsRemembered() {
113 let defaults = UserDefaults.standard
114 let saved = defaults.object(forKey: ScreenShareMode.key)
115 defer { defaults.set(saved, forKey: ScreenShareMode.key) }
116 defaults.removeObject(forKey: ScreenShareMode.key)
117 XCTAssertEqual(ScreenShareMode.remembered, .balanced)
118 ScreenShareMode.remembered = .motion
119 XCTAssertEqual(ScreenShareMode.remembered, .motion)
120 defaults.set("nonsense", forKey: ScreenShareMode.key)
121 XCTAssertEqual(ScreenShareMode.remembered, .balanced)
122 }
123
124 // MARK: - Applying it to a real sender
125
126 /// The plan reaches a real WebRTC sender, and the camera's defaults
127 /// really come back: set, read back, restored. No call is placed.
128 func testAPlanIsAppliedToASenderAndRestored() throws {
129 let factory = RTCPeerConnectionFactory()
130 let configuration = RTCConfiguration()
131 configuration.sdpSemantics = .unifiedPlan
132 let pc = try XCTUnwrap(
133 factory.peerConnection(
134 with: configuration,
135 constraints: RTCMediaConstraints(mandatoryConstraints: nil, optionalConstraints: nil),
136 delegate: nil))
137 defer { pc.close() }
138 let track = factory.videoTrack(with: factory.videoSource(), trackId: "camera")
139 let sender = try XCTUnwrap(pc.add(track, streamIds: ["calls"]))
140
141 XCTAssertTrue(sender.apply(ScreenSendPolicy.camera(sharing: true, height: 480)))
142 var encoding = try XCTUnwrap(sender.parameters.encodings.first)
143 XCTAssertEqual(encoding.maxBitrateBps?.intValue, 500_000)
144 XCTAssertEqual(encoding.scaleResolutionDownBy?.doubleValue ?? 0, 480.0 / 360.0, accuracy: 0.001)
145 XCTAssertFalse(
146 sender.apply(ScreenSendPolicy.camera(sharing: true, height: 480)), "the same plan twice is a no-op")
147
148 XCTAssertTrue(sender.apply(ScreenSendPolicy.camera(sharing: false)))
149 encoding = try XCTUnwrap(sender.parameters.encodings.first)
150 XCTAssertNil(encoding.maxBitrateBps)
151 XCTAssertEqual(encoding.scaleResolutionDownBy?.doubleValue ?? 1, 1, accuracy: 0.001)
152
153 XCTAssertTrue(sender.apply(ScreenSendPolicy.screen(.motion, width: 1920, height: 1080)))
154 let parameters = sender.parameters
155 encoding = try XCTUnwrap(parameters.encodings.first)
156 XCTAssertEqual(encoding.maxBitrateBps?.intValue, 2_500_000)
157 XCTAssertEqual(encoding.maxFramerate?.intValue, 30)
158 XCTAssertEqual(encoding.networkPriority, .high)
159 XCTAssertEqual(encoding.bitratePriority, 4)
160 XCTAssertEqual(
161 parameters.degradationPreference?.intValue, RTCDegradationPreference.maintainFramerate.rawValue)
162 }
163
164 // MARK: - The readout
165
166 private typealias Stats = [String: (type: String, values: [String: Any])]
167
168 private func stats(mid: String = "2", local: String = "host", remote: String = "host") -> Stats {
169 [
170 "OT1": (
171 "outbound-rtp",
172 [
173 "mid": mid, "frameWidth": 1920, "frameHeight": 1080, "framesPerSecond": 8.0,
174 "framesSent": 400, "framesEncoded": 400, "qualityLimitationReason": "bandwidth",
175 "qualityLimitationDurations": ["none": 2.0, "bandwidth": 30.0, "cpu": 0.0, "other": 0.0],
176 "targetBitrate": 1_200_000, "bytesSent": 5_000_000,
177 "encoderImplementation": "VideoToolbox", "totalEncodeTime": 8.0,
178 "mediaSourceId": "SV1", "codecId": "C1",
179 ]
180 ),
181 "OT0": ("outbound-rtp", ["mid": "1", "frameWidth": 640, "framesPerSecond": 30.0]),
182 "SV1": ("media-source", ["frames": 900, "framesPerSecond": 30.0, "width": 1920, "height": 1080]),
183 "C1": ("codec", ["mimeType": "video/H264"]),
184 "RI1": ("remote-inbound-rtp", ["localId": "OT1", "packetsLost": 12, "roundTripTime": 0.085]),
185 "T1": ("transport", ["selectedCandidatePairId": "P1"]),
186 "P1": ("candidate-pair", ["localCandidateId": "L1", "remoteCandidateId": "R1"]),
187 "L1": ("local-candidate", ["candidateType": local]),
188 "R1": ("remote-candidate", ["candidateType": remote]),
189 ]
190 }
191
192 func testTheScreensOwnStreamIsReadByMid() throws {
193 let r = try XCTUnwrap(ScreenSendReport.read(stats(), mid: "2"))
194 XCTAssertEqual(r.width, 1920)
195 XCTAssertEqual(r.height, 1080)
196 XCTAssertEqual(r.framesPerSecond, 8)
197 XCTAssertEqual(r.capturedPerSecond, 30, "the capture is fine; the sender is not keeping up")
198 XCTAssertEqual(r.framesCaptured, 900)
199 XCTAssertEqual(r.sourceWidth, 1920)
200 XCTAssertEqual(r.limitation, "bandwidth")
201 XCTAssertEqual(r.limitationSeconds["bandwidth"], 30)
202 XCTAssertEqual(r.targetBitrate, 1_200_000)
203 XCTAssertEqual(r.codec, "video/H264")
204 XCTAssertTrue(r.hardwareEncoder)
205 XCTAssertEqual(r.encodeMsPerFrame, 20, accuracy: 0.001)
206 XCTAssertEqual(r.packetsLost, 12)
207 XCTAssertEqual(r.roundTripTime, 0.085)
208 XCTAssertEqual(r.path, "host")
209 XCTAssertNil(ScreenSendReport.read(stats(), mid: "9"), "a stream not negotiated yet")
210 XCTAssertNil(ScreenSendReport.read(stats(), mid: ""))
211 }
212
213 func testARelayAtEitherEndIsTheRelay() {
214 XCTAssertEqual(ScreenSendReport.path(stats(local: "relay")), "relay")
215 XCTAssertEqual(ScreenSendReport.path(stats(remote: "relay")), "relay")
216 XCTAssertEqual(ScreenSendReport.path(stats(local: "srflx", remote: "host")), "srflx")
217 }
218
219 func testTheSummaryIsOneLine() throws {
220 var r = try XCTUnwrap(ScreenSendReport.read(stats(local: "relay"), mid: "2"))
221 XCTAssertEqual(
222 r.summary, "Screen: 1920×1080 at 8 fps, limited by bandwidth, 1.2 Mbit/s, relay (H264 hardware)")
223 var previous = r
224 previous.bytesSent = 4_900_000
225 previous.timestamp = 9
226 r.timestamp = 10
227 r = r.measured(since: previous)
228 XCTAssertEqual(r.sentBitrate, 800_000, "the rate actually sent wins over the target")
229 XCTAssertTrue(r.summary.contains("800 kbit/s"))
230 XCTAssertEqual(ScreenSendReport().summary, "Screen: starting…")
231 }
232
233 func testTheSlowestConnectionIsTheOneShown() {
234 var fast = ScreenSendReport()
235 fast.framesPerSecond = 29
236 var slow = ScreenSendReport()
237 slow.framesPerSecond = 4
238 XCTAssertEqual(ScreenSendReport.worst([fast, slow])?.framesPerSecond, 4)
239 XCTAssertNil(ScreenSendReport.worst([]))
240 }
241}
242