213 lines
10 KiB
Markdown
213 lines
10 KiB
Markdown
|
|
# DisplayFlow Demo - 技术方案与规划
|
|||
|
|
|
|||
|
|
本文档记录了 DisplayFlow Demo 项目的当前架构、已实现功能以及未来高级功能的规划方案。
|
|||
|
|
|
|||
|
|
## 1. 项目概览
|
|||
|
|
|
|||
|
|
DisplayFlow 旨在实现高性能的 Windows 主机到 Android 客户端的低延迟桌面投屏。
|
|||
|
|
|
|||
|
|
- **Windows Sender**: 负责屏幕捕获、H.264 编码、UDP 网络传输。
|
|||
|
|
- **Android Receiver**: 负责 UDP 接收、分片重组、MediaCodec 硬解码渲染。
|
|||
|
|
|
|||
|
|
## 2. 当前架构 (Current Architecture)
|
|||
|
|
|
|||
|
|
### 2.1 Windows Sender (已实现)
|
|||
|
|
- **路径**: `demo/windows_sender`
|
|||
|
|
- **核心技术**:
|
|||
|
|
- **Capture**: Desktop Duplication API (DXGI) - 高性能、零拷贝捕获。
|
|||
|
|
- **Encoding**: FFmpeg (libx264) - 配置为 `ultrafast`, `zerolatency` 以实现极低延迟。
|
|||
|
|
- *Input*: BGRA (DXGI Surface) -> YUV420P (swscale) -> H.264.
|
|||
|
|
- **Network**: Winsock UDP - 自定义分片协议 (MTU ~1400 bytes)。
|
|||
|
|
|
|||
|
|
### 2.2 Android Receiver (开发中)
|
|||
|
|
- **路径**: `demo/android_receiver`
|
|||
|
|
- **核心技术**:
|
|||
|
|
- **Language**: C++ (NDK) 核心逻辑 + Kotlin UI 外壳。
|
|||
|
|
- **Network**: BSD Sockets (C++) - 独立线程接收与重组。
|
|||
|
|
- **Decoding**: AMediaCodec (NDK) - 直接渲染到 Surface (ANativeWindow)。
|
|||
|
|
- **Rendering**: SurfaceView - 保持屏幕常亮。
|
|||
|
|
|
|||
|
|
### 2.3 Windows UI (规划中)
|
|||
|
|
- **Framework**: **Qt 6 (C++)**。
|
|||
|
|
- **理由**:
|
|||
|
|
- **纯 C++ 技术栈**: 与底层核心逻辑无缝集成,无需跨语言调用。
|
|||
|
|
- **高性能渲染**: 支持将 D3D11 / OpenGL 上下文直接嵌入窗口,适合视频流显示。
|
|||
|
|
- **跨平台潜力**: 为未来移植 macOS/Linux 预留可能性。
|
|||
|
|
- **成熟稳定**: 工业级 UI 框架,开发效率高。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 3. 高级功能规划 (Future Plans)
|
|||
|
|
|
|||
|
|
以下功能为验证通过的技术方案,可根据需求排期实现。
|
|||
|
|
|
|||
|
|
### 3.1 设备发现 (mDNS/Bonjour)
|
|||
|
|
**目标**: 实现局域网内“零配置”连接,无需手动输入 IP。
|
|||
|
|
|
|||
|
|
* **协议**: mDNS (Multicast DNS) / DNS-SD。
|
|||
|
|
* **Service Type**: `_displayflow._udp`。
|
|||
|
|
* **Android 端 (广播者)**:
|
|||
|
|
* 使用 `android.net.nsd.NsdManager`。
|
|||
|
|
* 注册服务,广播设备名称、IP 和端口 (8888)。
|
|||
|
|
* **Windows 端 (发现者)**:
|
|||
|
|
* 方案 A: 使用 Windows Native DNS-SD API (`windns.h`,Win10 1809+)。
|
|||
|
|
* 方案 B: 集成轻量级 C++ mDNS 库 (如 `mdns.h`)。
|
|||
|
|
* 功能: 扫描局域网,列出在线接收端供用户点击连接。
|
|||
|
|
|
|||
|
|
### 3.2 扩展屏投射 (Extended Display)
|
|||
|
|
**目标**: 将 Windows 扩展屏(而非主屏)投射到 Android,或将 Android 作为 Windows 的无线副屏。
|
|||
|
|
|
|||
|
|
#### 场景 A: 投射物理扩展屏
|
|||
|
|
* **原理**: 遍历 `IDXGIAdapter` 和 `IDXGIOutput`。
|
|||
|
|
* **实现**: 修改 `ScreenCapture` 初始化逻辑,允许用户选择捕获哪个 `Monitor ID`。
|
|||
|
|
* **复杂度**: 低。仅需增加枚举和选择逻辑。
|
|||
|
|
|
|||
|
|
#### 场景 B: 虚拟无线副屏 (Virtual Display)
|
|||
|
|
* **目标**: Windows 未连接物理显示器时,创建一个虚拟屏幕投射给 Android。
|
|||
|
|
* **原理**: 开发 **Indirect Display Driver (IDD)**。
|
|||
|
|
* 驱动向系统注册一个虚拟显示器。
|
|||
|
|
* DWM 渲染桌面到该虚拟显示器的 SwapChain。
|
|||
|
|
* 驱动获取画面并传递给 Sender 应用。
|
|||
|
|
* **复杂度**: 高。涉及驱动开发 (UMDF)、驱动签名 (WHQL/EV证书) 和安装包制作。
|
|||
|
|
* **替代方案 (Demo阶段)**: 使用 HDMI 显卡诱骗器 (硬件) 模拟物理屏幕,配合场景 A 的软件逻辑。
|
|||
|
|
|
|||
|
|
### 3.3 双向文件传输 (File Transfer)
|
|||
|
|
**目标**: 实现 Windows 与 Android 之间的文件互传。
|
|||
|
|
|
|||
|
|
* **协议**: TCP (独立于视频流的 UDP 通道,例如端口 8889)。
|
|||
|
|
* **通道分离**:
|
|||
|
|
* **UDP (8888)**: 视频流 (追求低延迟,允许少量丢包)。
|
|||
|
|
* **TCP (8889)**: 信令控制 (鼠标/触摸事件) + 文件传输 (追求可靠性)。
|
|||
|
|
* **交互流程**:
|
|||
|
|
* **Windows -> Android**:
|
|||
|
|
* 支持文件拖拽 (Drag & Drop) 到投屏窗口。
|
|||
|
|
* 发送 `FILE_HEADER` (Name, Size, Hash) -> 接收端确认 -> 传输数据流。
|
|||
|
|
* **Android -> Windows**:
|
|||
|
|
* 通过 Android 系统“分享”菜单选择 DisplayFlow。
|
|||
|
|
* Windows 端自动接收并保存到指定文件夹(如桌面)。
|
|||
|
|
|
|||
|
|
### 3.4 摄像头投屏 (Android Camera to Windows)
|
|||
|
|
**目标**: 将 Android 手机作为 Windows 的无线高清摄像头 (类似于 DroidCam / Continuity Camera)。
|
|||
|
|
|
|||
|
|
* **反向流媒体**: 建立 `Android (Sender) -> Windows (Receiver)` 的反向通道。
|
|||
|
|
* **Android 端**:
|
|||
|
|
* 使用 `CameraX` / `Camera2 API` 采集视频。
|
|||
|
|
* 使用 `MediaCodec` 进行 H.264 硬编码。
|
|||
|
|
* 通过 UDP 推流到 Windows。
|
|||
|
|
* **Windows 端**:
|
|||
|
|
* **基础模式**: 在 DisplayFlow 窗口内显示摄像头画面 (画中画或独立窗口)。
|
|||
|
|
* **进阶模式 (虚拟摄像头)**: 开发 DirectShow Filter 或 Media Foundation Source 驱动,将接收到的视频流模拟为系统摄像头,供 Zoom、Teams、OBS 等软件直接调用。
|
|||
|
|
|
|||
|
|
### 3.5 安卓投屏与反向控制 (Android Mirroring & Control)
|
|||
|
|
**目标**: 将 Android 屏幕投射到 Windows,并允许使用 Windows 鼠标/键盘操作手机 (类似 Scrcpy / 多屏协同)。
|
|||
|
|
|
|||
|
|
* **屏幕镜像 (Mirroring)**:
|
|||
|
|
* 使用 Android `MediaProjection API` 录制屏幕。
|
|||
|
|
* 复用现有的 H.264 编码与 UDP 传输架构,流向反转为 `Android -> Windows`。
|
|||
|
|
* **反向控制 (Input Control)**:
|
|||
|
|
* **方案 A (无 Root/ADB)**: 使用 **AccessibilityService** (辅助功能)。Windows 发送鼠标坐标和点击事件,Android 端通过辅助服务执行 `dispatchGesture`。
|
|||
|
|
* **方案 B (高性能)**: 类似于 Scrcpy,通过 ADB 权限注入输入事件。
|
|||
|
|
* **方案 C (蓝牙 HID)**: Windows 模拟为蓝牙键盘/鼠标连接 Android,实现无延迟的硬件级控制。
|
|||
|
|
|
|||
|
|
### 3.6 安卓触控 Windows (Android Touch Control)
|
|||
|
|
**目标**: 允许用户在 Android 屏幕上通过触摸操作 Windows 桌面 (实现远程桌面控制)。
|
|||
|
|
|
|||
|
|
* **输入捕获 (Android)**:
|
|||
|
|
* 监听 `SurfaceView` 的触摸事件 (Touch Event)。
|
|||
|
|
* 支持多指手势映射:
|
|||
|
|
* 单指点击 -> 鼠标左键。
|
|||
|
|
* 双指点击 -> 鼠标右键。
|
|||
|
|
* 双指滑动 -> 鼠标滚轮。
|
|||
|
|
* 虚拟键盘输入 -> Windows 键盘事件。
|
|||
|
|
* **指令传输**: 通过 TCP 控制通道发送坐标和事件类型。
|
|||
|
|
* **输入模拟 (Windows)**:
|
|||
|
|
* 使用 Win32 `SendInput` API 注入鼠标和键盘事件。
|
|||
|
|
* 实现坐标自适应映射 (Android 屏幕坐标 -> Windows 桌面绝对坐标)。
|
|||
|
|
|
|||
|
|
### 3.7 安卓对安卓互联 (Android to Android)
|
|||
|
|
**目标**: 实现两台 Android 设备之间的屏幕共享与文件互传。
|
|||
|
|
|
|||
|
|
* **架构复用**:
|
|||
|
|
* App 同时集成 Sender (投屏) 和 Receiver (接收) 模块,用户可切换角色。
|
|||
|
|
* **屏幕投屏**:
|
|||
|
|
* Device A (Sender): 启动 `MediaProjection` 录屏 -> 编码 -> UDP 发送。
|
|||
|
|
* Device B (Receiver): 接收 UDP -> 解码 -> 显示。
|
|||
|
|
* **文件快传**:
|
|||
|
|
* 建立 TCP 直连通道。
|
|||
|
|
* 利用 Android `WiFi P2P` (WiFi Direct) 技术,实现无路由器的点对点高速传输。
|
|||
|
|
|
|||
|
|
### 3.8 剪贴板同步 (Universal Clipboard)
|
|||
|
|
**目标**: 实现跨设备的无缝复制粘贴(文本/图片)。
|
|||
|
|
|
|||
|
|
* **原理**: 监听系统剪贴板变化事件。
|
|||
|
|
* **实现**:
|
|||
|
|
* **Windows**: 使用 `AddClipboardFormatListener` 监控,通过 TCP 发送数据。
|
|||
|
|
* **Android**: 使用 `ClipboardManager.OnPrimaryClipChangedListener` 监控。
|
|||
|
|
* **策略**: 仅同步文本和轻量级图片;大文件建议走文件传输通道。
|
|||
|
|
|
|||
|
|
### 3.9 通知同步 (Notification Sync)
|
|||
|
|
**目标**: 在 Windows 电脑上实时查看并处理 Android 手机通知。
|
|||
|
|
|
|||
|
|
* **Android 端**: 使用 `NotificationListenerService` 获取通知内容(标题、正文、图标)。
|
|||
|
|
* **Windows 端**: 接收 TCP 消息,通过 Qt System Tray 或 Windows Toast API 弹出通知。
|
|||
|
|
* **交互**: 支持在电脑上点击“回复”或“消除”,同步操作回手机。
|
|||
|
|
|
|||
|
|
### 3.10 音频流转 (Audio Streaming)
|
|||
|
|
**目标**: 实现声画同步投屏,或单纯的跨设备音频播放。
|
|||
|
|
|
|||
|
|
* **场景**: 投屏看电影时,声音也从电脑音箱发出。
|
|||
|
|
* **技术**:
|
|||
|
|
* **捕获**: Windows WASAPI Loopback / Android AudioRecord (需系统权限或通过 MediaProjection)。
|
|||
|
|
* **编码**: Opus (低延迟、高音质) 或 AAC。
|
|||
|
|
* **传输**: 这里的延迟极其敏感,必须使用 UDP 通道,并配合时间戳进行音画同步 (AVSync)。
|
|||
|
|
|
|||
|
|
### 3.11 共享输入设备 (Shared Keyboard/Mouse)
|
|||
|
|
**目标**: 一套键鼠控制多台设备,鼠标跨屏即穿越 (类似 Logitech Flow)。
|
|||
|
|
|
|||
|
|
* **区别**: 不同于“投屏控制”,此模式下手机屏幕不投射到电脑,只是鼠标指针“飞”到了手机屏幕上。
|
|||
|
|
* **实现**:
|
|||
|
|
* Windows 监控鼠标位置,当到达边缘时,隐藏本地鼠标,通过 TCP 发送位移增量给 Android。
|
|||
|
|
* Android 端绘制一个虚拟鼠标指针(Overlay),并根据接收到的位移移动它,模拟点击事件。
|
|||
|
|
|
|||
|
|
### 3.12 远程协助 (Remote Assistance - Android to Android)
|
|||
|
|
**目标**: 实现一台 Android 设备远程控制另一台 Android 设备(如子女帮助父母操作手机)。
|
|||
|
|
|
|||
|
|
* **技术复用**:
|
|||
|
|
* 复用 **3.5 安卓投屏与反向控制** 的核心技术。
|
|||
|
|
* **被控端 (Parents)**: 开启 Screen Mirroring (Sender) + Accessibility Service (Input Receiver)。
|
|||
|
|
* **控制端 (Kids)**: 开启 Receiver 显示画面 + 捕获触摸事件发送控制指令。
|
|||
|
|
* **交互优化**: 支持语音通话(边操作边指导)。
|
|||
|
|
|
|||
|
|
### 3.13 局域网对讲机 (Walkie-Talkie)
|
|||
|
|
**目标**: 在局域网内的多台设备之间实现实时语音对讲。
|
|||
|
|
|
|||
|
|
* **场景**: 家庭/办公室内部快速沟通。
|
|||
|
|
* **技术**:
|
|||
|
|
* 按住说话 (Push-to-Talk)。
|
|||
|
|
* 音频采集 -> Opus 编码 -> UDP 组播/广播 -> 所有设备自动播放。
|
|||
|
|
* 无需互联网连接,纯局域网实现。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 4. 协议设计 (Protocol)
|
|||
|
|
|
|||
|
|
当前用于验证的自定义 UDP 协议:
|
|||
|
|
|
|||
|
|
**Packet Structure:**
|
|||
|
|
```text
|
|||
|
|
[Packet Header (8 bytes)]
|
|||
|
|
+-----------+-----------+-----------+
|
|||
|
|
| FrameID(4)| FragID(2) | Total(2) |
|
|||
|
|
+-----------+-----------+-----------+
|
|||
|
|
|
|
|||
|
|
v
|
|||
|
|
[Payload]
|
|||
|
|
|
|
|||
|
|
+-- (If FragID == 0) --> [Frame Header (24 bytes)] + [H.264 Data Chunk]
|
|||
|
|
| +-----------+-----------+-----------+-----------+-----------+
|
|||
|
|
| | Time(8) | W(4)| H(4)| Type(4) | Size(4) |
|
|||
|
|
| +-----------+-----------+-----------+-----------+-----------+
|
|||
|
|
|
|
|||
|
|
+-- (If FragID > 0) ---> [H.264 Data Chunk]
|
|||
|
|
```
|