Peering은 Mac 화면을 iPhone으로 어떻게 스트리밍할까
원격 데스크톱은 요구 사항이 하나 특이한 영상 스트림입니다. 보는 사람이 곧 조작하는 사람이라는 점입니다. 아래의 모든 설계 선택은 이 순환을 짧게 유지하는 데서 나옵니다.
캡처: 시스템에 화면을 요청합니다
Mac 앱은 Apple의 ScreenCaptureKit으로 프레임을 얻습니다. 소스는 디스플레이 전체, 한 앱의 모든 창, 또는 창 하나이며, 연결을 끊지 않고 서로 전환할 수 있습니다. macOS가 처음에 화면 기록 권한을 요청하는 이유도 여기에 있습니다. 권한이 없으면 Mac은 검은 화면밖에 넘길 수 없습니다.
인코딩: 낮은 지연, 순서 바꿈 없음
프레임은 Mac의 Apple VideoToolbox 인코더로 들어가 H.264 또는 HEVC가 되며, iPhone이 디코딩할 수 있다고 알린 쪽을 씁니다. 설정은 스트리밍 서비스가 쓰는 것과 정반대입니다.
- B 프레임 없음. B 프레임은 미래의 프레임이 필요하므로, 쓰면 화면을 붙잡아 두게 됩니다. 없으면 디코딩 순서가 곧 표시 순서이고 기다리는 것이 없습니다.
- 저지연 레이트 컨트롤. 인코더는 미리 내다보지 않고 진행하면서 비트를 씁니다.
- 최소 2초마다 키프레임, 그리고 새 시청자가 들어오거나 재개하거나 소스를 바꿀 때는 즉시 보냅니다. 그래서 잃어버린 화면이 빠르게 복구됩니다.
- 화면에 따라 달라지는 비트레이트. 기본값은 픽셀 수에 프레임 레이트를 곱하고 0.12를 곱한 값이며, 4에서 30Mbps 사이로 유지하고, 기본 프레임 레이트는 초당 60입니다.
디코더의 설정 정보(파라미터 세트)는 프레임마다 반복하지 않고, 별도의 메시지로 한 번만 보냅니다. 스트림 중간에 들어온 iPhone은 이 메시지를 받은 뒤 키프레임을 받습니다.
전송: 버려도 되는 프레임, 보호되는 키프레임
각 프레임에는 25바이트의 작은 헤더가 붙습니다. 키프레임인지 여부, 픽셀 크기, 표시 시각이 들어 있습니다. 릴레이 연결이나 직접 연결에서는 약 1,080바이트의 데이터그램으로 잘라 보내며, 각 데이터그램은 두 기기만 아는 키로 ChaCha20-Poly1305로 봉인됩니다. 모든 데이터그램의 카운터는 64개 항목의 리플레이 윈도에 들어가므로, 가로챈 패킷을 나중에 다시 재생할 수 없습니다.
혼잡 시의 규칙은 단순합니다. 영상은 버려도 되고 키프레임은 아닙니다. 오래된 프레임이 아직 나가기를 기다리는 중에 새 프레임이 준비되면 오래된 것을 교체하되, 전달되지 않은 키프레임은 일반 프레임으로 교체하지 않습니다. 존재했던 모든 프레임을 보여 주는 것보다 지금의 화면을 보여 주는 것이 더 중요합니다.
집 네트워크에서는 화면이 별도의 TCP 연결로 전달됩니다. 네트워크가 충분히 안정적이어서 같은 규칙이 발동할 일이 거의 없습니다.
모든 소켓은 TCP_NODELAY를 설정합니다.
작은 쓰기를 모아 보내는 기본 동작은 홉마다 수십 밀리초를 더하는데, 다운로드에서는 눈에 띄지 않지만
커서를 움직일 때는 아주 잘 느껴집니다.
복구: 손실은 지연이 아니라 화면으로 치릅니다
UDP는 재전송하지 않으므로, 데이터그램이 손실되면 프레임이 손상됩니다. iPhone은 그것을 기다리지 않습니다. 계속 디코딩하며, 손상은 최대 2초 뒤에 오는 다음 키프레임에서 사라집니다. 불안정한 Wi-Fi를 지난 뒤 화면이 번져 보인다면 바로 이것을 보고 있는 것입니다. 화면을 일시정지했다가 재개하면 즉시 키프레임이 강제됩니다.
빠른 경로가 아예 전달을 멈추면, 연결에 대한 글에서 설명한 대로 스트림은 더 낮은 비트레이트로 제어 연결로 되돌아가고, 빠른 경로가 회복되면 다시 돌아옵니다.
표시: Mac이 아니라 iPhone에 맞춥니다
iPhone은 품질 단계를 고르고 초당 프레임 수를 줄여 달라고 요청할 수 있으며, Mac은 이를 적절한 범위로 제한합니다. 앱은 데스크톱 전체를 화면에 맞추거나 화면을 채울 수 있고, iPhone 모양의 가상 디스플레이를 Mac에 요청할 수도 있어서 가로로 긴 모니터를 세로 화면에 욱여넣지 않습니다. 화면을 탭하는 입력은 반대 방향으로 이동하며, 이는 탭이 클릭이 되는 과정에서 다룹니다.
자주 묻는 질문
Peering은 어떤 비디오 코덱을 쓰나요?
Mac에서 VideoToolbox로 인코딩하는 H.264 또는 HEVC이며, B 프레임 없이 저지연 설정을 씁니다. 어느 쪽을 디코딩할 수 있는지는 iPhone이 Mac에 알려 줍니다.
화면이 가끔 잠깐 번지는 이유는 무엇인가요?
네트워크 패킷이 손실되면 프레임이 손상되고, 화면은 최소 2초마다 오는 다음 키프레임에서 복구됩니다. Peering은 재전송을 기다리는 것보다 잠깐 번지는 쪽을 택합니다.