Files
airdisplay/ARCHITECTURE.md
yuqianhe e302021958 fix: 三协议架构代码审查修复
- MiracastService.kt 初始化顺序修复(mediaRenderer 在 AirDisplayProtocol 之前)
- 补充误删的 protocolManager.setListener() 回调
- 所有 12 个 lateinit 变量使用前初始化验证

此提交对应全面代码审查发现的问题
2026-05-30 08:29:36 +00:00

13 KiB
Raw Blame History

AirDisplay 系统架构

概览

三协议并行架构,根据场景自动选择或用户手动指定:

┌─────────────────────────────────────────────────────────────┐
│                    Android 端 (AirDisplay)                   │
│                                                             │
│  ┌─────────────────────────────────────────────────────────┐│
│  │ 协议栈 & 自动选择                                        ││
│  │                                                         ││
│  │  ┌──────────────┐  ┌──────────────┐  ┌────────────────┐││
│  │  │  Miracast     │  │  ADP         │  │  AirPlay       │││
│  │  │  (保留)       │  │  (私有协议)   │  │  (Mac 原生)    │││
│  │  │               │  │              │  │                │││
│  │  │  WFD IE       │  │  mDNS 发现   │  │  UxPlay 移植   │││
│  │  │  RTSP→RTP→TS  │  │  TCP 帧协议  │  │  H.264+AAC     │││
│  │  │  Wi-Fi Direct │  │  P2P/LAN    │  │  FairPlay      │││
│  │  └──────┬───────┘  └──────┬───────┘  └───────┬────────┘││
│  │         └────────────────┼──────────────────┘          ││
│  │                          ▼                             ││
│  │             共用 MediaCodec 解码 + 渲染                 ││
│  │             UIBC 触摸回传 (已有)                        ││
│  │             DeviceName 配置 (已有)                      ││
│  └─────────────────────────────────────────────────────────┘│
│                                                             │
│  自动选择逻辑:                                              │
│    Wi-Fi Direct + WFD IE 可用 → Miracast                   │
│    Wi-Fi Direct + WFD IE 失败 → 降级 ADP (P2P)            │
│    同局域网                  → ADP (LAN)                   │
│    Mac 投屏请求              → AirPlay                      │
│    用户手动选择              → 指定协议                      │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│         Desktop Client (独立仓库 airdisplay-client)          │
│                                                             │
│  技术栈: Rust + Tauri v2                                    │
│  目标平台: Windows / macOS / Linux                          │
│                                                             │
│  ┌───────────┐  ┌────────────┐  ┌─────────────────────────┐ │
│  │ 屏幕采集    │→ │ 视频编码    │→ │ 网络层                  │ │
│  │           │  │            │  │                         │ │
│  │ Windows   │  │ NVENC      │  │ mDNS 发现 (mdns-sd)     │ │
│  │  DXGI     │  │ (NVIDIA)   │  │ ADP 协议 (自定义帧协议)   │ │
│  │ macOS     │  │ Video      │  │ TCP 可靠传输             │ │
│  │  CGDisplay│  │ Toolbox    │  │                         │ │
│  │ Linux     │  │ Intel QSV  │  │ QUIC 备选 (低延迟)      │ │
│  │  PipeWire │  │ x264 软编  │  │                         │ │
│  └───────────┘  └────────────┘  └─────────────────────────┘ │
│                                                             │
│  ┌─────────────────────────────────────────────────────────┐│
│  │ Tauri UI (React/TypeScript)                             ││
│  │  ├─ 自动发现设备列表 (mDNS)                              ││
│  │  ├─ 连接/断开控制                                        ││
│  │  ├─ 协议选择 (ADP 默认 / Miracast 备选)                  ││
│  │  ├─ 分辨率/帧率/延迟模式设置                              ││
│  │  └─ 连接状态 & 统计信息                                  ││
│  └─────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│                    Mac 端 (无额外客户端)                     │
│                                                             │
│  控制中心 → 屏幕镜像 → 选择 AirDisplay                       │
│  使用 Apple 内置 AirPlay 协议                               │
│  无需安装额外软件                                           │
│  备选:也可安装 airdisplay-client 走 ADP 协议                │
└─────────────────────────────────────────────────────────────┘

协议设计

1. Miracast (已实现,保留)

现有代码保持不变:

  • WiFiDirectManager.kt — P2P Group 创建 + WFD IE 反射 (失败不阻塞)
  • RtspServer.kt / RtspSession.kt — RTSP 握手
  • RtpReceiver.kt / TsDemuxer.kt — RTP/TS 媒体管道
  • 用于 Android TV / 系统签名设备 / WFD IE 兼容的环境

改动WFD IE 反射失败时不再终止流程,自动降级到 ADP。

2. AirDisplay Protocol (ADP) v1

自定义轻量屏幕投屏协议。设计目标:低延迟、简单可靠、跨平台。

发现阶段

场景 发现方式
WiFi Direct P2P P2P Group 创建后,在 192.168.49.1:7935 启动 TCP 监听
同局域网 mDNS 注册 _airdisplay._tcp 端口 7935

连接阶段 (TCP 7935)

[Client] ──TCP 连接──> [Server]

[Server] ADP/1.0 200 OK
         Capabilities: {
           "max_width": 1920,
           "max_height": 1080,
           "codecs": ["h264"],
           "features": ["uibc", "audio"]
         }

[Client] ADP/1.0 HANDSHAKE
         Settings: {
           "width": 1920,
           "height": 1080,
           "fps": 30,
           "codec": "h264",
           "bitrate": 20000000
         }

[Server] ADP/1.0 READY

数据阶段 (TCP 持久连接)

帧格式:

┌──────────────────────────────────────────────────────────┐
│ Type(1) │ Reserved(1) │ Length(2) │ Timestamp(4)         │
├──────────────────────────────────────────────────────────┤
│ Payload (变长)                                          │
└──────────────────────────────────────────────────────────┘

Type 定义:
  0x01 = Capability 协商 (JSON)
  0x02 = H.264 NAL 单元 (Annex B)
  0x03 = H.265 NAL 单元 (保留)
  0x04 = 音频帧 (AAC/Opus)
  0x05 = UIBC 事件 (触摸/鼠标/键盘)
  0x06 = Keepalive
  0x07 = 分辨率/参数变更

UIBC 格式

与现有 UibcServer.kt 兼容。

3. AirPlay

使用 UxPlay (MIT License) 移植到 Android NDK。

UxPlay 是一个开源的 AirPlay 接收端实现,支持:

  • AirPlay Mirroring (H.264 视频)
  • AirPlay Audio (ALAC/AAC)
  • FairPlay 解密 (需要系统证书)
  • macOS/iOS 屏幕镜像 & 扩展

移植策略

  1. airdisplay/native/uxplay/ — CMakeLists.txt + 源码
  2. JNI 桥接 — UxPlay 的 H.264 NAL 通过 JNI 传回 Android 层
  3. 共享 MediaRenderer.kt — 与 ADP/Miracast 共用 MediaCodec 解码

Android 端代码结构

app/src/main/java/com/qwenpaw/miracast/
├── AirDisplayService.kt        ← 前台服务 (改自 MiracastService)
├── protocol/
│   ├── ProtocolManager.kt      ← 协议选择逻辑 (新增)
│   ├── AirDisplayProtocol.kt   ← ADP 协议处理器 (新增)
│   ├── MdnsService.kt          ← mDNS 注册 (新增)
│   └── AirPlayBridge.kt        ← AirPlay JNI 桥接 (新增)
├── wifidirect/
│   └── WiFiDirectManager.kt    ← P2P 管理 (改造)
├── rtsp/                       ← 保留 (Miracast 用)
│   ├── RtspServer.kt
│   ├── RtspSession.kt
│   └── WfdParser.kt
├── media/
│   ├── RtpReceiver.kt
│   ├── TsDemuxer.kt
│   └── MediaRenderer.kt        ← 共享解码+渲染
├── uibc/
│   └── UibcServer.kt
├── DeviceNameManager.kt
├── ResolutionManager.kt
├── LatencyManager.kt
└── ui/
    ├── MainActivity.kt
    ├── SettingsActivity.kt
    └── ...

网络拓扑

P2P 模式:  手机(GO) ←── WiFi Direct ──→ PC
            IP: 192.168.49.1

LAN 模式:  手机 ──── WiFi Router ────→ PC
            ↑ mDNS              ↑ mDNS

Desktop Client 技术方案

技术栈

层面 方案 说明
语言 Rust 跨平台原生、零开销抽象、安全
桌面框架 Tauri v2 Rust 后端 + Web 前端,打包 < 10MB
异步运行时 tokio 全异步 I/O
前端框架 React + TypeScript 组件化 UI
构建工具 Vite HMR 快速开发

屏幕采集

平台 方案 Rust crate
Windows DXGI Desktop Duplication dxgi-rs / captrs
macOS CGDisplay Stream core-graphics (sys)
Linux (Wayland) PipeWire pipewire-rs
Linux (X11) X11 SHM GetImage x11 / scrap

视频编码

编码器 方式 适用平台
NVENC 硬件 Windows (NVIDIA)
VideoToolbox 硬件 macOS
Intel QSV 硬件 Windows/Linux (Intel)
x264 软件 全平台保底
VAAPI 硬件 Linux (AMD/Intel)

协议实现

  • adp-client crate — ADP 协议客户端库
    • TCP 连接管理 + 重连
    • 帧序列化 (Header + Payload)
    • Keepalive
    • UIBC 事件发送
  • mdns-resolver — mDNS 设备发现
    • 监听 _airdisplay._tcp 服务
    • 自动刷新设备列表

Tauri UI 功能

  • 发现页: 自动扫描局域网内 AirDisplay 设备
  • 连接页: 选中设备 → 连接 → 显示投屏状态
  • 设置页: 分辨率/帧率/延迟模式/协议选择
  • 状态栏: 连接状态、FPS、延迟、码率

Rust 依赖

[dependencies]
tauri = "2"
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
mdns-sd = "0.12"
tracing = "0.1"
anyhow = "1"

# 屏幕采集 (平台相关)
[target.'cfg(target_os = "windows")'.dependencies]
captrs = "0.3"

[target.'cfg(target_os = "macos")'.dependencies]
core-graphics = "0.24"

[target.'cfg(target_os = "linux")'.dependencies]
# PipeWire / x11

# 编码
ffmpeg-next = "7"

实现路线

Phase 1: ADP MVP (当前)

  1. Android: AirDisplayProtocol.kt — ADP 协议处理器
  2. Android: MdnsService.kt — mDNS 注册
  3. Android: 改造 WiFiDirectManager — WFD IE 失败不阻塞
  4. Android: ProtocolManager.kt — 协议选择
  5. Desktop: 创建 airdisplay-client 仓库 + Rust/Tauri 脚手架
  6. Desktop: ADP 协议客户端 + mDNS 发现
  7. Desktop: 屏幕采集 + x264 软编
  8. Desktop: Tauri UI
  9. 端到端第一次投屏

Phase 2: 优化

  • 硬件编码支持 (NVENC/VideoToolbox/QSV)
  • 延迟调优参数
  • UIBC 触摸回传
  • 分辨率/帧率自适应

Phase 3: AirPlay

  • UxPlay 移植到 Android NDK
  • Mac 原生投屏
  • 音频支持

三协议并行,不受系统权限限制,覆盖全部桌面端。