Files
DisplayFlow/demo

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.hWin10 1809+)。
    • 方案 B: 集成轻量级 C++ mDNS 库 (如 mdns.h)。
    • 功能: 扫描局域网,列出在线接收端供用户点击连接。

3.2 扩展屏投射 (Extended Display)

目标: 将 Windows 扩展屏(而非主屏)投射到 Android或将 Android 作为 Windows 的无线副屏。

场景 A: 投射物理扩展屏

  • 原理: 遍历 IDXGIAdapterIDXGIOutput
  • 实现: 修改 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:

[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]