# screencast iOS receiver A native iOS receiver app (Swift) so an iPhone can act as a second receiver. It speaks the **existing signaling + RTP protocol unchanged** — no C++ changes — mirroring the Android receiver (Phase 8) source-to-source. - **Min iOS:** 17 (validated on iPhone 16 / iOS 26.6.1) - **No third-party dependencies** — only Apple system frameworks (SwiftUI, AVFoundation, VideoToolbox, CoreMedia, BSD sockets). ## Pipeline ``` Bonjour advertise (_screencast._tcp) + TCP signaling server (offer → answer) UDP RTP → jitter buffer (16 pkt / 60 ms) → depacketize (single-NAL + FU-A) → VideoToolbox H.264 (in-band SPS/PPS) → AVSampleBufferDisplayLayer (letterbox) ``` Recovery matches the C++ receiver: a damaged frame is dropped and a PLI (rate-limited to one per 500 ms) asks the sender for a keyframe. ## Layout ``` Receiver/ App/ SwiftUI app, video surface (AVSampleBufferDisplayLayer), controller Rtp/ RtpHeader, RtpPacket, JitterBuffer, H264Depacketizer, Avcc, NAL extraction Signaling/ SignalingMessage (JSON), LineAssembler, SignalingServer (BSD sockets) Decode/ RenderSink, H.264 format description, VideoToolbox decoder Support/ UdpTransport (poll-based), LocalAddress Pipeline/ ReceiverPipeline (coordinates everything) ReceiverTests/ XCTest port of the Android JVM tests + added coverage (signaling, line framing, AVCC, NAL extraction) ``` ## Build and test (on a Mac with Xcode 26) ```sh ./bootstrap.sh # installs XcodeGen, generates the project, builds for device ./bootstrap.sh test # runs the unit tests on the simulator ``` `bootstrap.sh` downloads XcodeGen from the GitHub release into `tools/` (no Homebrew). Override the simulator with `IOS_DEST="platform=iOS Simulator,name=…"`. ## Install on a device Free provisioning (or your team) is set in Xcode — this can't be scripted: 1. Open `Receiver.xcodeproj`. 2. Select the **Receiver** target → *Signing & Capabilities* → set your Apple ID (a 7-day development certificate is fine for sideloading). 3. Run to the iPhone (USB, trust the computer). The first run prompts for **Local Network** access — allow it, or the sender will never discover the phone (silent failure, like the Android `PROTOCOL_DNS_SD` bug). ## Stream to the phone On the sender (Linux desktop): ```sh screencast --send --peer :5005 # target the phone directly screencast --discover # or list receivers; the phone shows up ``` Expected: the phone shows the captured desktop, letterboxed to its screen, with PLI recovery on Wi-Fi loss. ## Testing notes The pure protocol core (RTP, jitter, depacketizer, signaling JSON, line framing, AVCC, NAL extraction) is unit-tested in the simulator. The VideoToolbox decode path and the local-network/Bonjour flow are on-device validation items — the highest-risk parts to verify on the borrowed Mac + iPhone.