Files
DisplayFlow/demo/README.md

213 lines
10 KiB
Markdown
Raw 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.
# 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]
```