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

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

310 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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](https://github.com/FDH2/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 依赖
```toml
[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 原生投屏
- 音频支持
---
*三协议并行,不受系统权限限制,覆盖全部桌面端。*