From 96fecf3c6f8036a0e2f5b6e5419a0c291fcf4efc Mon Sep 17 00:00:00 2001 From: huanglinhuan Date: Thu, 11 Dec 2025 22:58:25 +0800 Subject: [PATCH] =?UTF-8?q?=E6=90=AD=E5=BB=BA=E4=BB=A3=E7=A0=81=E6=A1=86?= =?UTF-8?q?=E6=9E=B6=E5=B9=B6=E6=9B=B4=E6=96=B0=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 63 ++ CMakeLists.txt | 49 + DEVELOPMENT_PLAN.md | 321 +++++++ PROJECT_STRUCTURE.md | 231 +++++ README.md | 35 +- README_BUILD.md | 81 ++ core/CMakeLists.txt | 81 ++ .../displayflow/core/codec/codec_interface.h | 39 + .../displayflow/core/codec/codec_manager.h | 36 + .../displayflow/core/common/constants.h | 31 + core/include/displayflow/core/common/types.h | 54 ++ .../core/file_transfer/file_chunk.h | 30 + .../file_transfer/file_transfer_manager.h | 70 ++ .../file_transfer/file_transfer_session.h | 58 ++ .../core/file_transfer/transfer_progress.h | 24 + .../core/network/nat_traversal/candidate.h | 38 + .../core/network/nat_traversal/ice_agent.h | 87 ++ .../core/network/nat_traversal/nat_type.h | 32 + .../core/network/nat_traversal/stun_client.h | 63 ++ .../core/network/nat_traversal/turn_client.h | 68 ++ .../core/network/network_interface.h | 24 + .../core/network/network_manager.h | 47 + .../core/protocol/message_serializer.h | 34 + .../core/protocol/protocol_handler.h | 27 + .../displayflow/core/role/client_role.h | 29 + .../include/displayflow/core/role/host_role.h | 29 + .../include/displayflow/core/role/peer_role.h | 29 + .../displayflow/core/role/role_interface.h | 45 + .../displayflow/core/role/role_manager.h | 37 + .../displayflow/core/session/session.h | 52 + .../core/session/session_manager.h | 43 + core/include/displayflow/core/utils/logger.h | 31 + core/include/displayflow/core/utils/timer.h | 27 + core/src/codec/codec_interface.cpp | 11 + core/src/codec/codec_manager.cpp | 26 + .../file_transfer/file_transfer_manager.cpp | 47 + .../file_transfer/file_transfer_session.cpp | 45 + core/src/network/nat_traversal/candidate.cpp | 34 + core/src/network/nat_traversal/ice_agent.cpp | 69 ++ core/src/network/nat_traversal/nat_type.cpp | 32 + .../src/network/nat_traversal/stun_client.cpp | 37 + .../src/network/nat_traversal/turn_client.cpp | 47 + core/src/network/network_interface.cpp | 11 + core/src/network/network_manager.cpp | 35 + core/src/protocol/message_serializer.cpp | 26 + core/src/protocol/protocol_handler.cpp | 21 + core/src/role/client_role.cpp | 33 + core/src/role/host_role.cpp | 33 + core/src/role/peer_role.cpp | 33 + core/src/role/role_manager.cpp | 26 + core/src/session/session.cpp | 39 + core/src/session/session_manager.cpp | 30 + core/src/utils/logger.cpp | 22 + core/src/utils/timer.cpp | 23 + docs/API.md | 85 ++ docs/ARCHITECTURE.md | 212 +++++ docs/IMPLEMENTATION.md | 899 ++++++++++++++++++ platforms/android/CMakeLists.txt | 57 ++ .../platform/android/capture/camera_capture.h | 85 ++ .../capture/media_projection_wrapper.h | 22 + .../platform/android/capture/screen_capture.h | 26 + .../platform/android/input/touch_handler.h | 22 + .../android/network/android_network_manager.h | 22 + .../platform/android/platform_adapter.h | 41 + .../platform/android/render/render_engine.h | 22 + .../android/src/capture/camera_capture.cpp | 65 ++ .../src/capture/media_projection_wrapper.cpp | 18 + .../android/src/capture/screen_capture.cpp | 32 + platforms/android/src/input/touch_handler.cpp | 18 + .../src/network/android_network_manager.cpp | 18 + platforms/android/src/platform_adapter.cpp | 32 + .../android/src/render/render_engine.cpp | 18 + platforms/windows/CMakeLists.txt | 67 ++ .../platform/windows/capture/camera_capture.h | 85 ++ .../platform/windows/input/keyboard_handler.h | 22 + .../platform/windows/input/mouse_handler.h | 22 + .../windows/network/windows_network_manager.h | 22 + .../platform/windows/platform_adapter.h | 49 + .../platform/windows/render/d3d11_renderer.h | 22 + .../windows/render/directx_renderer.h | 22 + .../windows/virtual_display/iddcx_wrapper.h | 22 + .../windows/virtual_display/virtual_display.h | 22 + .../windows/src/capture/camera_capture.cpp | 65 ++ .../windows/src/input/keyboard_handler.cpp | 18 + platforms/windows/src/input/mouse_handler.cpp | 18 + .../src/network/windows_network_manager.cpp | 18 + platforms/windows/src/platform_adapter.cpp | 37 + .../windows/src/render/d3d11_renderer.cpp | 18 + .../windows/src/render/directx_renderer.cpp | 18 + .../src/virtual_display/iddcx_wrapper.cpp | 18 + .../src/virtual_display/virtual_display.cpp | 18 + prototypes/README.md | 17 + tools/README.md | 15 + 93 files changed, 4924 insertions(+), 10 deletions(-) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 DEVELOPMENT_PLAN.md create mode 100644 PROJECT_STRUCTURE.md create mode 100644 README_BUILD.md create mode 100644 core/CMakeLists.txt create mode 100644 core/include/displayflow/core/codec/codec_interface.h create mode 100644 core/include/displayflow/core/codec/codec_manager.h create mode 100644 core/include/displayflow/core/common/constants.h create mode 100644 core/include/displayflow/core/common/types.h create mode 100644 core/include/displayflow/core/file_transfer/file_chunk.h create mode 100644 core/include/displayflow/core/file_transfer/file_transfer_manager.h create mode 100644 core/include/displayflow/core/file_transfer/file_transfer_session.h create mode 100644 core/include/displayflow/core/file_transfer/transfer_progress.h create mode 100644 core/include/displayflow/core/network/nat_traversal/candidate.h create mode 100644 core/include/displayflow/core/network/nat_traversal/ice_agent.h create mode 100644 core/include/displayflow/core/network/nat_traversal/nat_type.h create mode 100644 core/include/displayflow/core/network/nat_traversal/stun_client.h create mode 100644 core/include/displayflow/core/network/nat_traversal/turn_client.h create mode 100644 core/include/displayflow/core/network/network_interface.h create mode 100644 core/include/displayflow/core/network/network_manager.h create mode 100644 core/include/displayflow/core/protocol/message_serializer.h create mode 100644 core/include/displayflow/core/protocol/protocol_handler.h create mode 100644 core/include/displayflow/core/role/client_role.h create mode 100644 core/include/displayflow/core/role/host_role.h create mode 100644 core/include/displayflow/core/role/peer_role.h create mode 100644 core/include/displayflow/core/role/role_interface.h create mode 100644 core/include/displayflow/core/role/role_manager.h create mode 100644 core/include/displayflow/core/session/session.h create mode 100644 core/include/displayflow/core/session/session_manager.h create mode 100644 core/include/displayflow/core/utils/logger.h create mode 100644 core/include/displayflow/core/utils/timer.h create mode 100644 core/src/codec/codec_interface.cpp create mode 100644 core/src/codec/codec_manager.cpp create mode 100644 core/src/file_transfer/file_transfer_manager.cpp create mode 100644 core/src/file_transfer/file_transfer_session.cpp create mode 100644 core/src/network/nat_traversal/candidate.cpp create mode 100644 core/src/network/nat_traversal/ice_agent.cpp create mode 100644 core/src/network/nat_traversal/nat_type.cpp create mode 100644 core/src/network/nat_traversal/stun_client.cpp create mode 100644 core/src/network/nat_traversal/turn_client.cpp create mode 100644 core/src/network/network_interface.cpp create mode 100644 core/src/network/network_manager.cpp create mode 100644 core/src/protocol/message_serializer.cpp create mode 100644 core/src/protocol/protocol_handler.cpp create mode 100644 core/src/role/client_role.cpp create mode 100644 core/src/role/host_role.cpp create mode 100644 core/src/role/peer_role.cpp create mode 100644 core/src/role/role_manager.cpp create mode 100644 core/src/session/session.cpp create mode 100644 core/src/session/session_manager.cpp create mode 100644 core/src/utils/logger.cpp create mode 100644 core/src/utils/timer.cpp create mode 100644 docs/API.md create mode 100644 docs/ARCHITECTURE.md create mode 100644 docs/IMPLEMENTATION.md create mode 100644 platforms/android/CMakeLists.txt create mode 100644 platforms/android/include/displayflow/platform/android/capture/camera_capture.h create mode 100644 platforms/android/include/displayflow/platform/android/capture/media_projection_wrapper.h create mode 100644 platforms/android/include/displayflow/platform/android/capture/screen_capture.h create mode 100644 platforms/android/include/displayflow/platform/android/input/touch_handler.h create mode 100644 platforms/android/include/displayflow/platform/android/network/android_network_manager.h create mode 100644 platforms/android/include/displayflow/platform/android/platform_adapter.h create mode 100644 platforms/android/include/displayflow/platform/android/render/render_engine.h create mode 100644 platforms/android/src/capture/camera_capture.cpp create mode 100644 platforms/android/src/capture/media_projection_wrapper.cpp create mode 100644 platforms/android/src/capture/screen_capture.cpp create mode 100644 platforms/android/src/input/touch_handler.cpp create mode 100644 platforms/android/src/network/android_network_manager.cpp create mode 100644 platforms/android/src/platform_adapter.cpp create mode 100644 platforms/android/src/render/render_engine.cpp create mode 100644 platforms/windows/CMakeLists.txt create mode 100644 platforms/windows/include/displayflow/platform/windows/capture/camera_capture.h create mode 100644 platforms/windows/include/displayflow/platform/windows/input/keyboard_handler.h create mode 100644 platforms/windows/include/displayflow/platform/windows/input/mouse_handler.h create mode 100644 platforms/windows/include/displayflow/platform/windows/network/windows_network_manager.h create mode 100644 platforms/windows/include/displayflow/platform/windows/platform_adapter.h create mode 100644 platforms/windows/include/displayflow/platform/windows/render/d3d11_renderer.h create mode 100644 platforms/windows/include/displayflow/platform/windows/render/directx_renderer.h create mode 100644 platforms/windows/include/displayflow/platform/windows/virtual_display/iddcx_wrapper.h create mode 100644 platforms/windows/include/displayflow/platform/windows/virtual_display/virtual_display.h create mode 100644 platforms/windows/src/capture/camera_capture.cpp create mode 100644 platforms/windows/src/input/keyboard_handler.cpp create mode 100644 platforms/windows/src/input/mouse_handler.cpp create mode 100644 platforms/windows/src/network/windows_network_manager.cpp create mode 100644 platforms/windows/src/platform_adapter.cpp create mode 100644 platforms/windows/src/render/d3d11_renderer.cpp create mode 100644 platforms/windows/src/render/directx_renderer.cpp create mode 100644 platforms/windows/src/virtual_display/iddcx_wrapper.cpp create mode 100644 platforms/windows/src/virtual_display/virtual_display.cpp create mode 100644 prototypes/README.md create mode 100644 tools/README.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..38bf577 --- /dev/null +++ b/.gitignore @@ -0,0 +1,63 @@ +# Build directories +build/ +out/ +bin/ +lib/ +*.exe +*.dll +*.so +*.dylib +*.a +*.lib + +# CMake +CMakeCache.txt +CMakeFiles/ +cmake_install.cmake +Makefile +*.cmake +!CMakeLists.txt + +# IDE +.vs/ +.vscode/ +.idea/ +*.swp +*.swo +*~ +.DS_Store + +# Android +*.apk +*.ap_ +*.dex +*.class +local.properties +.gradle/ +build/ +.idea/ +*.iml + +# Windows +Thumbs.db +ehthumbs.db +Desktop.ini + +# Dependencies +third_party/ +external/ +vcpkg_installed/ + +# Logs +*.log + +# Temporary files +*.tmp +*.temp +*.bak +*.backup + +# FlatBuffers generated files (optional, if you want to track them) +# *.generated.h +# *.generated.cpp + diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..1676ea2 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,49 @@ +cmake_minimum_required(VERSION 3.15) +project(DisplayFlow VERSION 1.0.0 LANGUAGES CXX) + +# 设置 C++ 标准 +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +# 输出目录 +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) + +# 编译选项 +if(MSVC) + add_compile_options(/W4 /WX-) + add_compile_definitions(_CRT_SECURE_NO_WARNINGS) +else() + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# 平台检测 +if(ANDROID) + set(PLATFORM_ANDROID ON) +elseif(WIN32) + set(PLATFORM_WINDOWS ON) +elseif(APPLE) + set(PLATFORM_MACOS ON) +elseif(UNIX) + set(PLATFORM_LINUX ON) +endif() + +# 添加子目录 +add_subdirectory(core) + +# 根据平台添加对应的平台适配层 +if(PLATFORM_ANDROID) + add_subdirectory(platforms/android) +elseif(PLATFORM_WINDOWS) + add_subdirectory(platforms/windows) +endif() + +# 添加测试(如果启用) +option(BUILD_TESTS "Build tests" OFF) +if(BUILD_TESTS) + enable_testing() + add_subdirectory(tests) +endif() + diff --git a/DEVELOPMENT_PLAN.md b/DEVELOPMENT_PLAN.md new file mode 100644 index 0000000..b8766ed --- /dev/null +++ b/DEVELOPMENT_PLAN.md @@ -0,0 +1,321 @@ +# DisplayFlow 开发计划 + +## 1. 项目阶段划分 + +### 阶段一:核心架构搭建(Foundation Phase) +**目标**:建立跨平台核心库的基础架构和构建系统 + +#### 1.1 构建系统配置 +- [ ] 配置 CMake 作为统一构建系统 +- [ ] 设置跨平台编译配置(Android NDK、Windows MSVC) +- [ ] 配置依赖管理(FlatBuffers、编解码库等) +- [ ] 建立单元测试框架 + +#### 1.2 核心库基础模块 +- [ ] **网络抽象层(Network Abstraction)** + - 统一网络接口定义 + - RNDIS/USB 网络检测 + - Wi-Fi 网络管理 + - 以太网支持 + - 自动连接选择算法 + +- [ ] **NAT 穿透模块(NAT Traversal)** + - STUN 客户端实现 + - TURN 客户端实现 + - ICE 协议实现 + - 候选地址收集 + - 连接检查和路径选择 + - 自动连接建立 + +- [ ] **协议层(Protocol Layer)** + - FlatBuffers Schema 定义 + - 消息序列化/反序列化 + - 会话建立协议 + - 视频帧传输协议 + - 输入事件协议 + +- [ ] **会话管理(Session Management)** + - 会话创建与销毁 + - 角色管理(Host/Client/Peer) + - 一对多会话支持 + - 会话状态机 + +- [ ] **编解码抽象(Codec Abstraction)** + - 编解码器接口定义 + - H.264 硬件加速支持 + - VP8 软件编解码 + - MJPEG 支持 + - 自适应编解码器选择 + +- [ ] **文件传输模块(File Transfer)** + - 文件传输协议定义 + - 断点续传机制 + - 多文件并发传输 + - 传输进度跟踪 + - 文件校验(MD5/SHA256) + - 传输队列管理 + +### 阶段二:平台适配层实现(Platform Adaptation Phase) +**目标**:实现各平台的显示捕获和渲染功能 + +#### 2.1 Android 平台实现 +- [ ] **显示捕获** + - MediaProjection API 集成 + - ImageReader 帧获取 + - 屏幕分辨率检测 + - 帧率控制 + +- [ ] **摄像头捕获** + - Camera2 API / NDK Camera API 集成 + - 摄像头设备枚举 + - 视频流捕获 + - 摄像头参数控制(分辨率、帧率、对焦等) + - 多摄像头支持 + +- [ ] **输入处理** + - 触摸事件捕获 + - 输入事件转发 + +- [ ] **网络层** + - Android USB RNDIS 支持 + - Wi-Fi 网络管理 + - 网络权限处理 + +#### 2.2 Windows 平台实现 +- [ ] **虚拟显示器** + - IddCx 驱动框架集成 + - 虚拟显示器创建 + - 分辨率动态调整 + +- [ ] **摄像头捕获** + - DirectShow / Media Foundation 集成 + - 摄像头设备枚举 + - 视频流捕获 + - 摄像头参数控制 + - 多摄像头支持 + +- [ ] **渲染引擎** + - DirectX 渲染管道 + - 视频帧解码与显示 + - 性能优化 + +- [ ] **输入处理** + - 键盘事件捕获 + - 鼠标事件捕获 + - 输入事件转发 + +- [ ] **网络层** + - USB RNDIS 检测 + - Wi-Fi 网络管理 + - 以太网支持 + +### 阶段三:角色层实现(Role Implementation Phase) +**目标**:实现 Host、Client、Peer 三种角色的完整功能 + +#### 3.1 主机角色(Host Role) +- [ ] 屏幕捕获集成 +- [ ] 视频编码流水线 +- [ ] 数据发送逻辑 +- [ ] 一对多广播支持 +- [ ] 性能监控与自适应 + +#### 3.2 客户端角色(Client Role) +- [ ] 数据接收逻辑 +- [ ] 视频解码流水线 +- [ ] 渲染显示集成 +- [ ] 输入事件处理 +- [ ] 延迟优化 + +#### 3.3 对等角色(Peer Role) +- [ ] 同时运行 Host 和 Client 逻辑 +- [ ] 双向数据流管理 +- [ ] 资源竞争处理 +- [ ] 性能平衡 + +### 阶段四:集成与优化(Integration & Optimization Phase) +**目标**:整合各模块,优化性能,完善功能 + +#### 4.1 系统集成 +- [ ] 端到端功能测试 +- [ ] 多场景验证 +- [ ] 错误处理与恢复 +- [ ] 日志系统 + +#### 4.2 性能优化 +- [ ] 延迟优化(目标 < 30ms) +- [ ] 带宽优化 +- [ ] CPU/GPU 使用优化 +- [ ] 内存管理优化 + +#### 4.3 稳定性提升 +- [ ] 异常处理 +- [ ] 网络断线重连 +- [ ] 资源清理 +- [ ] 压力测试 + +### 阶段五:测试与文档(Testing & Documentation Phase) +**目标**:完善测试覆盖,编写完整文档 + +#### 5.1 测试 +- [ ] 单元测试覆盖 +- [ ] 集成测试 +- [ ] 跨平台兼容性测试 +- [ ] 性能基准测试 + +#### 5.2 文档 +- [ ] API 文档 +- [ ] 架构设计文档 +- [ ] 用户使用指南 +- [ ] 开发者指南 +- [ ] 部署文档 + +## 2. 技术选型 + +### 2.1 核心依赖 +- **序列化**:Google FlatBuffers +- **编解码**: + - H.264:MediaCodec (Android) / Media Foundation (Windows) + - VP8:libvpx + - MJPEG:自定义实现 +- **网络**:原生 Socket API + 平台特定网络库 +- **NAT 穿透**: + - STUN/TURN 客户端(自实现或使用 libnice/libjuice) + - ICE 协议实现 +- **构建系统**:CMake 3.15+ + +### 2.2 平台特定依赖 +- **Android**: + - NDK r21+ + - MediaProjection API + - Camera2 API / NDK Camera API + - USB Host API +- **Windows**: + - Windows SDK 10.0.19041.0+ + - DirectX 11/12 + - IddCx 1.4+ + - DirectShow / Media Foundation(摄像头) + +## 3. 开发优先级 + +### P0(核心功能,必须实现) +1. 核心网络抽象层 +2. 基础协议定义 +3. Android Host 角色 +4. Windows Client 角色 +5. USB RNDIS 连接支持 + +### P1(重要功能,优先实现) +1. 会话管理 +2. 编解码器集成 +3. 输入事件处理 +4. Wi-Fi 连接支持 +5. 性能优化 + +### P2(增强功能,后续实现) +1. Peer 角色支持 +2. 一对多广播 +3. 多种编解码器 +4. 以太网支持 +5. 高级性能调优 + +### P3(扩展功能,可选实现) +1. **文件传输功能** + - 基础文件传输 + - 断点续传 + - 多文件并发传输 + - 传输进度和校验 + +2. **远程摄像头功能** + - 摄像头设备枚举 + - 视频流捕获和传输 + - 摄像头参数控制 + - 多摄像头切换 + +3. **NAT 穿透功能(TURN/STUN)** + - STUN 客户端实现 + - TURN 客户端实现 + - ICE 协议集成 + - 互联网连接支持 + - 自动路径选择 + +## 4. 里程碑 + +### Milestone 1: 核心架构完成(4周) +- CMake 构建系统就绪 +- 核心库基础模块框架完成 +- 网络抽象层可用 +- 协议定义完成 + +### Milestone 2: Android Host 可用(6周) +- Android 平台适配层完成 +- 屏幕捕获功能实现 +- 基础编码与发送功能 +- 可通过 USB RNDIS 发送视频流 + +### Milestone 3: Windows Client 可用(8周) +- Windows 平台适配层完成 +- 虚拟显示器创建 +- 基础解码与渲染功能 +- 可接收并显示视频流 + +### Milestone 4: 端到端可用(10周) +- Host-Client 完整流程打通 +- 输入事件双向传输 +- 基础性能达标(延迟 < 50ms) +- 稳定性基本保证 + +### Milestone 5: 生产就绪(12周+) +- 所有核心功能完成 +- 性能优化达标(延迟 < 30ms) +- 测试覆盖充分 +- 文档完整 + +### Milestone 6: 扩展功能(16周+) +- 文件传输功能完成 +- 远程摄像头功能完成 +- 扩展功能测试和优化 +- 用户体验优化 + +## 5. 风险与应对 + +### 技术风险 +1. **跨平台兼容性** + - 风险:不同平台 API 差异大 + - 应对:充分抽象,建立完善的适配层 + +2. **性能瓶颈** + - 风险:延迟或帧率不达标 + - 应对:早期性能测试,持续优化 + +3. **网络稳定性** + - 风险:不同网络环境下的连接问题 + - 应对:完善的错误处理和重连机制 + +### 开发风险 +1. **依赖管理** + - 风险:第三方库版本冲突 + - 应对:使用 vcpkg/Conan 等包管理器 + +2. **测试环境** + - 风险:跨平台测试设备不足 + - 应对:建立 CI/CD,自动化测试 + +## 6. 下一步行动 + +1. **立即开始**: + - 搭建项目目录结构 + - 配置 CMake 构建系统 + - 设置基础依赖(FlatBuffers) + +2. **第一周目标**: + - 完成项目结构搭建 + - CMake 可在 Windows 和 Android 上编译通过 + - 创建核心库基础框架 + - 定义 FlatBuffers Schema + +3. **第一个月目标**: + - 网络抽象层实现 + - 基础协议完成 + - Android 平台适配层框架 + - 简单的端到端测试 + diff --git a/PROJECT_STRUCTURE.md b/PROJECT_STRUCTURE.md new file mode 100644 index 0000000..bb4621f --- /dev/null +++ b/PROJECT_STRUCTURE.md @@ -0,0 +1,231 @@ +# DisplayFlow 项目结构说明 + +## 目录结构 + +``` +DisplayFlow/ +├── CMakeLists.txt # 根 CMake 配置文件 +├── .gitignore # Git 忽略文件配置 +├── README.md # 项目概述和技术方案 +├── DEVELOPMENT_PLAN.md # 详细开发计划 +├── README_BUILD.md # 构建指南 +├── PROJECT_STRUCTURE.md # 本文件:项目结构说明 +│ +├── core/ # 跨平台核心库 +│ ├── CMakeLists.txt +│ ├── include/ +│ │ └── displayflow/ +│ │ └── core/ +│ │ ├── common/ # 通用类型和常量 +│ │ │ ├── types.h +│ │ │ └── constants.h +│ │ ├── network/ # 网络抽象层 +│ │ │ ├── network_manager.h +│ │ │ ├── network_interface.h +│ │ │ ├── nat_traversal/ # NAT 穿透模块 +│ │ │ │ ├── stun_client.h +│ │ │ │ ├── turn_client.h +│ │ │ │ ├── ice_agent.h +│ │ │ │ ├── candidate.h +│ │ │ │ └── nat_type.h +│ │ ├── protocol/ # 协议层 +│ │ │ ├── protocol_handler.h +│ │ │ └── message_serializer.h +│ │ ├── session/ # 会话管理 +│ │ │ ├── session_manager.h +│ │ │ └── session.h +│ │ ├── codec/ # 编解码抽象 +│ │ │ ├── codec_manager.h +│ │ │ └── codec_interface.h +│ │ ├── role/ # 角色管理 +│ │ │ ├── role_manager.h +│ │ │ ├── role_interface.h +│ │ │ ├── host_role.h +│ │ │ ├── client_role.h +│ │ │ └── peer_role.h +│ │ ├── file_transfer/ # 文件传输模块 +│ │ │ ├── file_transfer_manager.h +│ │ │ ├── file_transfer_session.h +│ │ │ ├── file_chunk.h +│ │ │ └── transfer_progress.h +│ │ └── utils/ # 工具类 +│ │ ├── logger.h +│ │ └── timer.h +│ └── src/ # 对应的源文件实现 +│ ├── network/ +│ │ └── nat_traversal/ +│ ├── protocol/ +│ ├── session/ +│ ├── codec/ +│ ├── role/ +│ ├── file_transfer/ +│ └── utils/ +│ +├── platforms/ # 平台适配层 +│ ├── android/ # Android 平台实现 +│ │ ├── CMakeLists.txt +│ │ ├── include/ +│ │ │ └── displayflow/ +│ │ │ └── platform/ +│ │ │ └── android/ +│ │ │ ├── platform_adapter.h +│ │ │ ├── capture/ # 捕获模块 +│ │ │ │ ├── screen_capture.h +│ │ │ │ ├── media_projection_wrapper.h +│ │ │ │ └── camera_capture.h # 摄像头捕获 +│ │ │ ├── render/ # 渲染引擎 +│ │ │ │ └── render_engine.h +│ │ │ ├── input/ # 输入处理 +│ │ │ │ └── touch_handler.h +│ │ │ └── network/ # 网络管理 +│ │ │ └── android_network_manager.h +│ │ └── src/ # 对应的源文件实现 +│ │ ├── capture/ +│ │ │ ├── screen_capture.cpp +│ │ │ ├── media_projection_wrapper.cpp +│ │ │ └── camera_capture.cpp +│ │ ├── render/ +│ │ ├── input/ +│ │ ├── network/ +│ │ └── platform_adapter.cpp +│ │ +│ └── windows/ # Windows 平台实现 +│ ├── CMakeLists.txt +│ ├── include/ +│ │ └── displayflow/ +│ │ └── platform/ +│ │ └── windows/ +│ │ ├── platform_adapter.h +│ │ ├── virtual_display/ # 虚拟显示器 +│ │ │ ├── virtual_display.h +│ │ │ └── iddcx_wrapper.h +│ │ ├── capture/ # 捕获模块 +│ │ │ └── camera_capture.h # 摄像头捕获 +│ │ ├── render/ # 渲染引擎 +│ │ │ ├── directx_renderer.h +│ │ │ └── d3d11_renderer.h +│ │ ├── input/ # 输入处理 +│ │ │ ├── keyboard_handler.h +│ │ │ └── mouse_handler.h +│ │ └── network/ # 网络管理 +│ │ └── windows_network_manager.h +│ └── src/ # 对应的源文件实现 +│ ├── virtual_display/ +│ ├── capture/ +│ │ └── camera_capture.cpp +│ ├── render/ +│ ├── input/ +│ ├── network/ +│ └── platform_adapter.cpp +│ +├── docs/ # 文档目录 +│ ├── ARCHITECTURE.md # 架构设计文档 +│ └── API.md # API 文档 +│ +├── prototypes/ # 原型和测试代码 +│ └── README.md +│ +└── tools/ # 开发工具脚本 + └── README.md +``` + +## 模块说明 + +### 核心库 (core/) + +100% 跨平台的业务逻辑实现,不依赖任何平台特定 API。 + +- **common/**: 基础类型定义和常量 +- **network/**: 网络抽象层,统一管理 RNDIS、Wi-Fi、以太网 + - **nat_traversal/**: NAT 穿透模块(STUN/TURN/ICE) +- **protocol/**: 基于 FlatBuffers 的协议定义和序列化 +- **session/**: 会话生命周期管理 +- **codec/**: 编解码器抽象接口和管理 +- **role/**: 角色(Host/Client/Peer)实现 +- **file_transfer/**: 文件传输模块(断点续传、多文件传输) +- **utils/**: 通用工具类(日志、定时器等) + +### 平台适配层 (platforms/) + +各平台特定功能的薄封装层。 + +#### Android +- **capture/**: + - 屏幕捕获(MediaProjection API 封装) + - 摄像头捕获(Camera2 API / NDK Camera API) +- **render/**: 渲染引擎(用于 Client 角色) +- **input/**: 触摸输入处理 +- **network/**: Android 网络管理(USB RNDIS、Wi-Fi) + +#### Windows +- **virtual_display/**: IddCx 驱动框架封装,创建虚拟显示器 +- **capture/**: + - 摄像头捕获(DirectShow / Media Foundation) +- **render/**: DirectX 渲染引擎 +- **input/**: 键盘和鼠标输入处理 +- **network/**: Windows 网络管理(USB RNDIS、Wi-Fi、以太网) + +## 命名空间 + +- `displayflow::core` - 核心库 +- `displayflow::platform::android` - Android 平台适配 +- `displayflow::platform::windows` - Windows 平台适配 + +## 构建系统 + +使用 CMake 作为统一构建系统: +- 根目录 `CMakeLists.txt` 负责平台检测和子目录管理 +- 各模块有独立的 `CMakeLists.txt` +- 支持条件编译,根据平台自动选择对应的适配层 + +## 当前状态 + +所有基础框架文件已创建,包含: +- ✅ 完整的目录结构 +- ✅ 所有头文件和源文件占位符 +- ✅ CMake 构建配置 +- ✅ 基础类型和接口定义 + +**下一步**:开始实现核心功能模块。 + +## 新增功能模块 + +### 文件传输模块 (core/file_transfer/) + +支持在设备间传输文件,特性包括: +- 断点续传 +- 多文件并发传输 +- 传输进度监控 +- 文件校验(MD5/SHA256) +- 传输队列管理 + +### 远程摄像头模块 + +支持使用对方的摄像头作为视频源,特性包括: +- 摄像头设备枚举和选择 +- 视频流捕获和编码 +- 与屏幕共享复用相同的传输通道 +- 支持多摄像头切换 +- 摄像头参数控制(分辨率、帧率等) + +### NAT 穿透模块 (core/network/nat_traversal/) + +支持通过互联网连接设备,突破局域网限制,特性包括: +- **STUN 客户端**:NAT 类型检测和公网 IP 发现 +- **TURN 客户端**:中继服务器支持(当直连失败时) +- **ICE 协议**:自动选择最佳连接路径 +- **候选地址收集**:收集本地、STUN、TURN 候选地址 +- **连接建立**:自动尝试多种连接方式,选择最优路径 + +**连接方式优先级:** +1. 局域网直连(最快) +2. 公网直连(通过 STUN 发现) +3. TURN 中继(最慢但最可靠) + +**架构优势:** +- 文件传输复用现有的网络抽象层和协议层 +- 摄像头捕获复用现有的编码和传输机制 +- NAT 穿透完全透明,上层无需关心连接方式 +- 完全集成到现有角色模型中 +- 保持跨平台兼容性 + diff --git a/README.md b/README.md index 778e997..1c91a5e 100644 --- a/README.md +++ b/README.md @@ -29,16 +29,21 @@ - **受益**:应用场景极大丰富,从简单的副屏扩展到复杂的多设备协作演示、双向画板等。 -### 2.3 连接通用:支持RNDIS、WiFi、以太网等多种连接方式 +### 2.3 连接通用:支持局域网和互联网连接 -- **网络抽象层(Network Agnostic)**:设计统一的网络接口,自动选择或同时管理多种物理连接。 - - **USB RNDIS**:优先使用,提供近似有线的高带宽、低延迟体验。 - - **Wi-Fi 局域网**:提供无线便利性,支持一对多广播。 - - **有线以太网**:为台式机等设备提供稳定连接。 +- **网络抽象层(Network Agnostic)**:设计统一的网络接口,自动选择或同时管理多种连接方式。 + - **局域网连接**(优先使用): + - **USB RNDIS**:优先使用,提供近似有线的高带宽、低延迟体验。 + - **Wi-Fi 局域网**:提供无线便利性,支持一对多广播。 + - **有线以太网**:为台式机等设备提供稳定连接。 + - **互联网连接**(通过 NAT 穿透): + - **STUN**:NAT 类型检测和公网 IP 发现,支持公网直连。 + - **TURN**:中继服务器支持,当直连失败时自动切换。 + - **ICE 协议**:自动选择最佳连接路径(局域网 > 公网直连 > TURN 中继)。 -- **技术实现**:NetworkManager负责探测可用连接,根据性能(延迟、带宽)自动优选或负载均衡。应用层无需关心底层是USB虚拟网卡还是真实网卡。 +- **技术实现**:NetworkManager负责探测可用连接,根据性能(延迟、带宽)自动优选或负载均衡。集成 ICE 协议实现 NAT 穿透,支持局域网和互联网无缝切换。应用层无需关心底层连接方式。 -- **受益**:用户无需手动配置网络,系统自动选择最佳路径,并提供从有线到无线的无缝切换能力。 +- **受益**:用户无需手动配置网络,系统自动选择最佳路径。支持跨网络、跨地域的设备连接,突破局域网限制,实现真正的远程协作。 ### 2.4 扩展性强:轻松支持新设备类型与未来场景 @@ -64,7 +69,7 @@ | [ 核心层 (Core Layer) ] <- 会话管理、协议、编解码、网络抽象 (100%跨平台) | -[ 传输层 (Transport Layer) ] <- RNDIS (USB)、Wi-Fi、以太网 +[ 传输层 (Transport Layer) ] <- 局域网(RNDIS/USB、Wi-Fi、以太网)、互联网(STUN/TURN/ICE) ``` ### 3.2 核心模块说明 @@ -73,7 +78,7 @@ - **会话管理**:创建、维护、销毁显示会话,支持一对多。 - **通用协议**:基于Google FlatBuffers的跨平台序列化,定义视频帧、输入事件等。 - **编解码器**:支持H.264(硬件加速)/VP8(软件)/MJPEG等多种编解码器,自适应选择。 - - **网络抽象**:统一管理RNDIS、WiFi等连接,提供可靠UDP传输。 + - **网络抽象**:统一管理RNDIS、WiFi等局域网连接,以及STUN/TURN/ICE互联网连接,提供可靠UDP传输。 2. **平台适配层(Platforms)**:各平台特有功能的薄封装。 - **Android**:通过MediaProjection捕获屏幕,ImageReader获取帧,处理触摸输入。 @@ -110,6 +115,13 @@ - **角色**:安卓手机作为主机(Host),安卓平板作为客户端(Client)。 - **价值**:充分发挥设备特性。用户可在手机上进行私密操作(如游戏、使用特定APP),而将主画面投送至平板大屏上进行展示或共享,兼顾隐私与分享需求。这充分体现了角色的灵活性——安卓设备可根据需求,自由扮演主机或客户端的角色。 +**场景五:远程协作(跨网络、跨地域)** + +- **描述**:用户在家中通过互联网连接到办公室的 Windows 电脑,实现远程显示扩展。 +- **角色**:办公室 Windows 电脑作为主机(Host),家中设备作为客户端(Client)。 +- **连接方式**:通过 STUN/TURN 服务器实现 NAT 穿透,自动选择最佳连接路径。 +- **价值**:突破局域网限制,支持跨网络、跨地域的设备连接。无论设备在哪里,只要有互联网连接,就能实现无缝显示协作。适用于远程办公、技术支持、远程演示等场景。 + ## 5. 技术规格与指标 - **支持平台**:Android 5.0+, Windows 10/11 @@ -130,6 +142,9 @@ DisplayFlow/ └── tools/ # 开发工具脚本 ``` -## 7. 总结 +## 7. 技术栈 +完全由C++实现 + +## 8. 总结 本方案通过真正跨平台的核心设计、动态角色分配和多连接方式抽象,突破了现有副屏方案的局限性。它不仅仅是一个"副屏工具",更是一个为未来多设备协作世界打造的、极具扩展性的通用显示协作平台。该架构确保了项目在性能、灵活性和可持续性上的领先优势。 diff --git a/README_BUILD.md b/README_BUILD.md new file mode 100644 index 0000000..7f592a2 --- /dev/null +++ b/README_BUILD.md @@ -0,0 +1,81 @@ +# DisplayFlow 构建指南 + +## 前置要求 + +### Windows +- CMake 3.15 或更高版本 +- Visual Studio 2019 或更高版本(包含 Windows SDK 10.0.19041.0+) +- Git + +### Android +- CMake 3.15 或更高版本 +- Android NDK r21 或更高版本 +- Android Studio(可选,用于开发) + +## 构建步骤 + +### Windows + +```bash +# 创建构建目录 +mkdir build +cd build + +# 配置 CMake +cmake .. -G "Visual Studio 16 2019" -A x64 + +# 编译 +cmake --build . --config Release +``` + +### Android + +```bash +# 创建构建目录 +mkdir build-android +cd build-android + +# 配置 CMake(需要设置 ANDROID_NDK 环境变量) +cmake .. \ + -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \ + -DANDROID_ABI=arm64-v8a \ + -DANDROID_PLATFORM=android-21 + +# 编译 +cmake --build . +``` + +## 依赖管理 + +项目依赖将通过以下方式管理: + +1. **FlatBuffers**:通过 Git Submodule 或 vcpkg 引入 +2. **编解码库**:使用平台原生 API(MediaCodec、Media Foundation) + +## 开发环境设置 + +### 使用 vcpkg(推荐) + +```bash +# 安装 vcpkg +git clone https://github.com/Microsoft/vcpkg.git +cd vcpkg +.\bootstrap-vcpkg.bat + +# 安装依赖 +.\vcpkg install flatbuffers + +# 配置 CMake 使用 vcpkg +cmake .. -DCMAKE_TOOLCHAIN_FILE=[vcpkg root]/scripts/buildsystems/vcpkg.cmake +``` + +## 测试 + +```bash +# 启用测试 +cmake .. -DBUILD_TESTS=ON + +# 运行测试 +ctest +``` + diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt new file mode 100644 index 0000000..f5f036c --- /dev/null +++ b/core/CMakeLists.txt @@ -0,0 +1,81 @@ +# 核心库 CMakeLists.txt +cmake_minimum_required(VERSION 3.15) + +# 核心库源文件 +set(CORE_SOURCES + src/network/network_manager.cpp + src/network/network_interface.cpp + src/network/nat_traversal/stun_client.cpp + src/network/nat_traversal/turn_client.cpp + src/network/nat_traversal/ice_agent.cpp + src/network/nat_traversal/candidate.cpp + src/network/nat_traversal/nat_type.cpp + src/protocol/protocol_handler.cpp + src/protocol/message_serializer.cpp + src/session/session_manager.cpp + src/session/session.cpp + src/codec/codec_manager.cpp + src/codec/codec_interface.cpp + src/role/role_manager.cpp + src/role/host_role.cpp + src/role/client_role.cpp + src/role/peer_role.cpp + src/file_transfer/file_transfer_manager.cpp + src/file_transfer/file_transfer_session.cpp + src/utils/logger.cpp + src/utils/timer.cpp +) + +# 核心库头文件 +set(CORE_HEADERS + include/displayflow/core/network/network_manager.h + include/displayflow/core/network/network_interface.h + include/displayflow/core/network/nat_traversal/stun_client.h + include/displayflow/core/network/nat_traversal/turn_client.h + include/displayflow/core/network/nat_traversal/ice_agent.h + include/displayflow/core/network/nat_traversal/candidate.h + include/displayflow/core/network/nat_traversal/nat_type.h + include/displayflow/core/protocol/protocol_handler.h + include/displayflow/core/protocol/message_serializer.h + include/displayflow/core/session/session_manager.h + include/displayflow/core/session/session.h + include/displayflow/core/codec/codec_manager.h + include/displayflow/core/codec/codec_interface.h + include/displayflow/core/role/role_manager.h + include/displayflow/core/role/host_role.h + include/displayflow/core/role/client_role.h + include/displayflow/core/role/peer_role.h + include/displayflow/core/role/role_interface.h + include/displayflow/core/file_transfer/file_transfer_manager.h + include/displayflow/core/file_transfer/file_transfer_session.h + include/displayflow/core/file_transfer/file_chunk.h + include/displayflow/core/file_transfer/transfer_progress.h + include/displayflow/core/utils/logger.h + include/displayflow/core/utils/timer.h + include/displayflow/core/common/types.h + include/displayflow/core/common/constants.h +) + +# 创建核心库 +add_library(displayflow_core STATIC + ${CORE_SOURCES} + ${CORE_HEADERS} +) + +# 包含目录 +target_include_directories(displayflow_core PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_CURRENT_SOURCE_DIR}/../third_party/flatbuffers/include +) + +# 链接库(根据实际依赖调整) +# target_link_libraries(displayflow_core +# flatbuffers +# ) + +# 编译定义 +target_compile_definitions(displayflow_core PUBLIC + DISPLAYFLOW_CORE_VERSION_MAJOR=${PROJECT_VERSION_MAJOR} + DISPLAYFLOW_CORE_VERSION_MINOR=${PROJECT_VERSION_MINOR} +) + diff --git a/core/include/displayflow/core/codec/codec_interface.h b/core/include/displayflow/core/codec/codec_interface.h new file mode 100644 index 0000000..ffc7b27 --- /dev/null +++ b/core/include/displayflow/core/codec/codec_interface.h @@ -0,0 +1,39 @@ +#pragma once + +#include "displayflow/core/common/types.h" +#include + +namespace displayflow { +namespace core { + +// 前向声明 +struct VideoFrame; + +/** + * @brief 编解码器接口 + * + * 所有编解码器必须实现此接口 + */ +class ICodec { +public: + virtual ~ICodec() = default; + + /** + * @brief 获取编解码器类型 + */ + virtual CodecType GetType() const = 0; + + /** + * @brief 编码视频帧 + */ + virtual ByteArray Encode(const VideoFrame& frame) = 0; + + /** + * @brief 解码视频帧 + */ + virtual bool Decode(const ByteArray& data, VideoFrame& frame) = 0; +}; + +} // namespace core +} // namespace displayflow + diff --git a/core/include/displayflow/core/codec/codec_manager.h b/core/include/displayflow/core/codec/codec_manager.h new file mode 100644 index 0000000..d8d10ac --- /dev/null +++ b/core/include/displayflow/core/codec/codec_manager.h @@ -0,0 +1,36 @@ +#pragma once + +#include "displayflow/core/common/types.h" +#include "displayflow/core/codec/codec_interface.h" +#include + +namespace displayflow { +namespace core { + +/** + * @brief 编解码器管理器 + * + * 负责管理和选择编解码器 + */ +class CodecManager { +public: + CodecManager(); + ~CodecManager(); + + /** + * @brief 初始化编解码器管理器 + */ + bool Initialize(); + + /** + * @brief 获取指定类型的编解码器 + */ + std::shared_ptr GetCodec(CodecType type); + +private: + // TODO: 添加私有成员 +}; + +} // namespace core +} // namespace displayflow + diff --git a/core/include/displayflow/core/common/constants.h b/core/include/displayflow/core/common/constants.h new file mode 100644 index 0000000..982c0f3 --- /dev/null +++ b/core/include/displayflow/core/common/constants.h @@ -0,0 +1,31 @@ +#pragma once + +#include + +namespace displayflow { +namespace core { + +// 版本信息 +constexpr uint32_t VERSION_MAJOR = 1; +constexpr uint32_t VERSION_MINOR = 0; +constexpr uint32_t VERSION_PATCH = 0; + +// 网络配置 +constexpr uint16_t DEFAULT_PORT = 8888; +constexpr uint32_t MAX_CLIENTS = 20; +constexpr uint32_t DEFAULT_BUFFER_SIZE = 1024 * 1024; // 1MB + +// 性能指标 +constexpr uint32_t MAX_FPS = 60; +constexpr uint32_t TARGET_FPS = 30; +constexpr uint32_t MAX_RESOLUTION_WIDTH = 3840; // 4K +constexpr uint32_t MAX_RESOLUTION_HEIGHT = 2160; // 4K +constexpr uint32_t TARGET_LATENCY_MS = 30; // 目标延迟 30ms + +// 协议配置 +constexpr uint32_t PROTOCOL_VERSION = 1; +constexpr uint32_t MAX_MESSAGE_SIZE = 10 * 1024 * 1024; // 10MB + +} // namespace core +} // namespace displayflow + diff --git a/core/include/displayflow/core/common/types.h b/core/include/displayflow/core/common/types.h new file mode 100644 index 0000000..2d529d9 --- /dev/null +++ b/core/include/displayflow/core/common/types.h @@ -0,0 +1,54 @@ +#pragma once + +#include +#include +#include +#include + +namespace displayflow { +namespace core { + +// 基础类型定义 +using Byte = uint8_t; +using ByteArray = std::vector; + +// 角色类型 +enum class RoleType { + Host, // 主机角色 + Client, // 客户端角色 + Peer // 对等角色 +}; + +// 网络类型 +enum class NetworkType { + RNDIS, // USB RNDIS + WiFi, // Wi-Fi 局域网 + Ethernet // 有线以太网 +}; + +// 编解码器类型 +enum class CodecType { + H264, // H.264 硬件加速 + VP8, // VP8 软件编解码 + MJPEG // MJPEG +}; + +// 分辨率 +struct Resolution { + uint32_t width; + uint32_t height; + + bool operator==(const Resolution& other) const { + return width == other.width && height == other.height; + } +}; + +// 会话 ID +using SessionId = uint64_t; + +// 设备 ID +using DeviceId = std::string; + +} // namespace core +} // namespace displayflow + diff --git a/core/include/displayflow/core/file_transfer/file_chunk.h b/core/include/displayflow/core/file_transfer/file_chunk.h new file mode 100644 index 0000000..9274065 --- /dev/null +++ b/core/include/displayflow/core/file_transfer/file_chunk.h @@ -0,0 +1,30 @@ +#pragma once + +#include "displayflow/core/common/types.h" +#include +#include + +namespace displayflow { +namespace core { + +/** + * @brief 文件块 + * + * 文件被分割成固定大小的块进行传输 + */ +struct FileChunk { + uint64_t transferId; // 传输会话 ID + uint32_t chunkIndex; // 块索引 + uint32_t chunkSize; // 块大小 + ByteArray data; // 块数据 + bool isLastChunk; // 是否为最后一块 +}; + +/** + * @brief 文件块大小(建议值) + */ +constexpr uint32_t DEFAULT_CHUNK_SIZE = 64 * 1024; // 64KB + +} // namespace core +} // namespace displayflow + diff --git a/core/include/displayflow/core/file_transfer/file_transfer_manager.h b/core/include/displayflow/core/file_transfer/file_transfer_manager.h new file mode 100644 index 0000000..e47b668 --- /dev/null +++ b/core/include/displayflow/core/file_transfer/file_transfer_manager.h @@ -0,0 +1,70 @@ +#pragma once + +#include "displayflow/core/common/types.h" +#include "displayflow/core/file_transfer/file_transfer_session.h" +#include +#include +#include +#include +#include + +namespace displayflow { +namespace core { + +/** + * @brief 文件传输管理器 + * + * 负责管理所有文件传输会话 + */ +class FileTransferManager { +public: + FileTransferManager(); + ~FileTransferManager(); + + /** + * @brief 发送文件 + * @param filePath 文件路径 + * @param sessionId 会话 ID + * @return 传输会话 ID + */ + uint64_t SendFile(const std::string& filePath, SessionId sessionId); + + /** + * @brief 接收文件 + * @param fileName 文件名 + * @param fileSize 文件大小 + * @param savePath 保存路径 + * @param sessionId 会话 ID + * @return 传输会话 ID + */ + uint64_t ReceiveFile(const std::string& fileName, uint64_t fileSize, + const std::string& savePath, SessionId sessionId); + + /** + * @brief 暂停传输 + */ + bool PauseTransfer(uint64_t transferId); + + /** + * @brief 恢复传输 + */ + bool ResumeTransfer(uint64_t transferId); + + /** + * @brief 取消传输 + */ + bool CancelTransfer(uint64_t transferId); + + /** + * @brief 获取传输进度 + */ + double GetTransferProgress(uint64_t transferId) const; + +private: + std::unordered_map> transfers_; + uint64_t nextTransferId_ = 1; +}; + +} // namespace core +} // namespace displayflow + diff --git a/core/include/displayflow/core/file_transfer/file_transfer_session.h b/core/include/displayflow/core/file_transfer/file_transfer_session.h new file mode 100644 index 0000000..db95af4 --- /dev/null +++ b/core/include/displayflow/core/file_transfer/file_transfer_session.h @@ -0,0 +1,58 @@ +#pragma once + +#include "displayflow/core/common/types.h" +#include "displayflow/core/file_transfer/transfer_progress.h" +#include +#include +#include + +namespace displayflow { +namespace core { + +enum class TransferDirection { + Send, // 发送文件 + Receive // 接收文件 +}; + +enum class TransferStatus { + Pending, // 等待中 + InProgress, // 传输中 + Paused, // 已暂停 + Completed, // 已完成 + Failed, // 失败 + Cancelled // 已取消 +}; + +/** + * @brief 文件传输会话 + */ +class FileTransferSession { +public: + FileTransferSession(uint64_t id, TransferDirection direction); + ~FileTransferSession(); + + uint64_t GetId() const { return id_; } + TransferDirection GetDirection() const { return direction_; } + TransferStatus GetStatus() const { return status_; } + + void Start(); + void Pause(); + void Resume(); + void Cancel(); + + TransferProgress GetProgress() const; + + // 设置进度回调 + void SetProgressCallback(std::function callback); + +private: + uint64_t id_; + TransferDirection direction_; + TransferStatus status_ = TransferStatus::Pending; + TransferProgress progress_; + std::function progressCallback_; +}; + +} // namespace core +} // namespace displayflow + diff --git a/core/include/displayflow/core/file_transfer/transfer_progress.h b/core/include/displayflow/core/file_transfer/transfer_progress.h new file mode 100644 index 0000000..ea23052 --- /dev/null +++ b/core/include/displayflow/core/file_transfer/transfer_progress.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include + +namespace displayflow { +namespace core { + +/** + * @brief 传输进度信息 + */ +struct TransferProgress { + uint64_t transferId; // 传输会话 ID + std::string fileName; // 文件名 + uint64_t totalSize; // 总大小(字节) + uint64_t transferredSize; // 已传输大小(字节) + double progress; // 进度百分比 (0.0 - 1.0) + uint64_t speed; // 传输速度(字节/秒) + uint32_t remainingTime; // 预计剩余时间(秒) +}; + +} // namespace core +} // namespace displayflow + diff --git a/core/include/displayflow/core/network/nat_traversal/candidate.h b/core/include/displayflow/core/network/nat_traversal/candidate.h new file mode 100644 index 0000000..ba4e2cf --- /dev/null +++ b/core/include/displayflow/core/network/nat_traversal/candidate.h @@ -0,0 +1,38 @@ +#pragma once + +#include "displayflow/core/common/types.h" +#include +#include + +namespace displayflow { +namespace core { + +enum class CandidateType { + Host, // 本地主机地址 + ServerReflexive, // STUN 服务器反射地址 + PeerReflexive, // 对端反射地址 + Relayed // TURN 中继地址 +}; + +/** + * @brief ICE 候选地址 + */ +struct Candidate { + CandidateType type; + std::string ip; + uint16_t port; + uint32_t priority; // 优先级(用于 ICE 排序) + std::string foundation; // 基础标识符 + std::string componentId; // 组件 ID + std::string relatedAddress; // 相关地址(用于服务器反射和中继) + uint16_t relatedPort; +}; + +/** + * @brief 候选地址优先级计算 + */ +uint32_t CalculateCandidatePriority(const Candidate& candidate); + +} // namespace core +} // namespace displayflow + diff --git a/core/include/displayflow/core/network/nat_traversal/ice_agent.h b/core/include/displayflow/core/network/nat_traversal/ice_agent.h new file mode 100644 index 0000000..c513d69 --- /dev/null +++ b/core/include/displayflow/core/network/nat_traversal/ice_agent.h @@ -0,0 +1,87 @@ +#pragma once + +#include "displayflow/core/common/types.h" +#include "displayflow/core/network/nat_traversal/candidate.h" +#include "displayflow/core/network/nat_traversal/stun_client.h" +#include "displayflow/core/network/nat_traversal/turn_client.h" +#include +#include +#include + +namespace displayflow { +namespace core { + +struct IceConfig { + StunServerConfig stunServer; + TurnServerConfig turnServer; + uint32_t connectionTimeout = 5000; // 连接超时(毫秒) + uint32_t candidateTimeout = 3000; // 候选地址收集超时(毫秒) +}; + +struct IceCandidatePair { + Candidate local; + Candidate remote; + bool valid = false; + uint32_t priority = 0; +}; + +/** + * @brief ICE 代理 + * + * 实现 ICE (Interactive Connectivity Establishment) 协议 + * 自动选择最佳连接路径 + */ +class IceAgent { +public: + IceAgent(); + ~IceAgent(); + + /** + * @brief 初始化 ICE 代理 + */ + bool Initialize(const IceConfig& config); + + /** + * @brief 收集候选地址 + * @return 候选地址列表 + */ + std::vector GatherCandidates(); + + /** + * @brief 设置远程候选地址 + */ + void SetRemoteCandidates(const std::vector& candidates); + + /** + * @brief 执行连接检查 + * @return 是否成功建立连接 + */ + bool PerformConnectivityChecks(); + + /** + * @brief 获取选定的候选地址对 + */ + IceCandidatePair GetSelectedPair() const; + + /** + * @brief 获取连接类型 + */ + std::string GetConnectionType() const; // "local", "stun", "turn" + + /** + * @brief 清理资源 + */ + void Cleanup(); + +private: + IceConfig config_; + std::vector localCandidates_; + std::vector remoteCandidates_; + IceCandidatePair selectedPair_; + StunClient stunClient_; + TurnClient turnClient_; +}; + +} // namespace core +} // namespace displayflow + diff --git a/core/include/displayflow/core/network/nat_traversal/nat_type.h b/core/include/displayflow/core/network/nat_traversal/nat_type.h new file mode 100644 index 0000000..1d56322 --- /dev/null +++ b/core/include/displayflow/core/network/nat_traversal/nat_type.h @@ -0,0 +1,32 @@ +#pragma once + +namespace displayflow { +namespace core { + +/** + * @brief NAT 类型 + * + * 根据 RFC 3489 定义的 NAT 类型 + */ +enum class NatType { + Unknown, // 未知 + Open, // 开放(无 NAT) + FullCone, // 完全锥形 NAT + RestrictedCone, // 受限锥形 NAT + PortRestrictedCone, // 端口受限锥形 NAT + Symmetric // 对称 NAT +}; + +/** + * @brief NAT 类型字符串转换 + */ +const char* NatTypeToString(NatType type); + +/** + * @brief 判断 NAT 类型是否支持直连 + */ +bool IsNatTypeDirectConnectable(NatType type); + +} // namespace core +} // namespace displayflow + diff --git a/core/include/displayflow/core/network/nat_traversal/stun_client.h b/core/include/displayflow/core/network/nat_traversal/stun_client.h new file mode 100644 index 0000000..629d74e --- /dev/null +++ b/core/include/displayflow/core/network/nat_traversal/stun_client.h @@ -0,0 +1,63 @@ +#pragma once + +#include "displayflow/core/common/types.h" +#include "displayflow/core/network/nat_traversal/nat_type.h" +#include +#include + +namespace displayflow { +namespace core { + +struct StunServerConfig { + std::string host; + uint16_t port = 3478; // 默认 STUN 端口 +}; + +struct StunResponse { + std::string publicIp; + uint16_t publicPort; + NatType natType; + bool success; +}; + +/** + * @brief STUN 客户端 + * + * 用于 NAT 类型检测和获取公网 IP 地址 + */ +class StunClient { +public: + StunClient(); + ~StunClient(); + + /** + * @brief 设置 STUN 服务器配置 + */ + void SetServer(const StunServerConfig& config); + + /** + * @brief 执行 STUN 绑定请求 + * @param localPort 本地端口 + * @return STUN 响应结果 + */ + StunResponse PerformBindingRequest(uint16_t localPort); + + /** + * @brief 检测 NAT 类型 + * @return NAT 类型 + */ + NatType DetectNatType(); + + /** + * @brief 获取公网 IP 地址 + * @return 公网 IP 地址 + */ + std::string GetPublicIp(); + +private: + StunServerConfig serverConfig_; +}; + +} // namespace core +} // namespace displayflow + diff --git a/core/include/displayflow/core/network/nat_traversal/turn_client.h b/core/include/displayflow/core/network/nat_traversal/turn_client.h new file mode 100644 index 0000000..4350f32 --- /dev/null +++ b/core/include/displayflow/core/network/nat_traversal/turn_client.h @@ -0,0 +1,68 @@ +#pragma once + +#include "displayflow/core/common/types.h" +#include "displayflow/core/network/nat_traversal/candidate.h" +#include +#include + +namespace displayflow { +namespace core { + +struct TurnServerConfig { + std::string host; + uint16_t port = 3478; // 默认 TURN 端口 + std::string username; + std::string password; + std::string realm; +}; + +/** + * @brief TURN 客户端 + * + * 用于通过 TURN 服务器中继流量(当直连失败时) + */ +class TurnClient { +public: + TurnClient(); + ~TurnClient(); + + /** + * @brief 设置 TURN 服务器配置 + */ + void SetServer(const TurnServerConfig& config); + + /** + * @brief 分配中继地址 + * @return 中继候选地址 + */ + Candidate AllocateRelayAddress(); + + /** + * @brief 创建权限(允许对端发送数据) + */ + bool CreatePermission(const std::string& peerIp); + + /** + * @brief 发送数据到对端(通过中继) + */ + bool SendData(const ByteArray& data, const std::string& peerIp, uint16_t peerPort); + + /** + * @brief 接收数据(从对端通过中继) + */ + bool ReceiveData(ByteArray& data, std::string& peerIp, uint16_t& peerPort); + + /** + * @brief 释放中继地址 + */ + void ReleaseAllocation(); + +private: + TurnServerConfig serverConfig_; + Candidate relayCandidate_; + bool allocated_ = false; +}; + +} // namespace core +} // namespace displayflow + diff --git a/core/include/displayflow/core/network/network_interface.h b/core/include/displayflow/core/network/network_interface.h new file mode 100644 index 0000000..07234fe --- /dev/null +++ b/core/include/displayflow/core/network/network_interface.h @@ -0,0 +1,24 @@ +#pragma once + +#include "displayflow/core/common/types.h" +#include + +namespace displayflow { +namespace core { + +/** + * @brief 网络接口信息 + */ +struct NetworkInterface { + NetworkType type; // 网络类型 + std::string name; // 接口名称 + std::string address; // IP 地址 + uint16_t port; // 端口号 + uint32_t bandwidth; // 带宽(Mbps) + uint32_t latency; // 延迟(ms) + bool isAvailable; // 是否可用 +}; + +} // namespace core +} // namespace displayflow + diff --git a/core/include/displayflow/core/network/network_manager.h b/core/include/displayflow/core/network/network_manager.h new file mode 100644 index 0000000..cbf92da --- /dev/null +++ b/core/include/displayflow/core/network/network_manager.h @@ -0,0 +1,47 @@ +#pragma once + +#include "displayflow/core/common/types.h" +#include "displayflow/core/network/network_interface.h" +#include +#include + +namespace displayflow { +namespace core { + +/** + * @brief 网络管理器 + * + * 负责管理所有网络连接,包括 RNDIS、Wi-Fi、以太网等 + */ +class NetworkManager { +public: + NetworkManager(); + ~NetworkManager(); + + /** + * @brief 初始化网络管理器 + */ + bool Initialize(); + + /** + * @brief 获取所有可用的网络接口 + */ + std::vector GetAvailableInterfaces(); + + /** + * @brief 连接到指定的网络接口 + */ + bool Connect(const NetworkInterface& interface); + + /** + * @brief 断开当前连接 + */ + void Disconnect(); + +private: + // TODO: 添加私有成员 +}; + +} // namespace core +} // namespace displayflow + diff --git a/core/include/displayflow/core/protocol/message_serializer.h b/core/include/displayflow/core/protocol/message_serializer.h new file mode 100644 index 0000000..7d62d12 --- /dev/null +++ b/core/include/displayflow/core/protocol/message_serializer.h @@ -0,0 +1,34 @@ +#pragma once + +#include "displayflow/core/common/types.h" + +namespace displayflow { +namespace core { + +/** + * @brief 消息序列化器 + * + * 基于 FlatBuffers 的消息序列化和反序列化 + */ +class MessageSerializer { +public: + MessageSerializer(); + ~MessageSerializer(); + + /** + * @brief 序列化消息 + */ + ByteArray Serialize(const void* message); + + /** + * @brief 反序列化消息 + */ + bool Deserialize(const ByteArray& data, void* message); + +private: + // TODO: 添加私有成员 +}; + +} // namespace core +} // namespace displayflow + diff --git a/core/include/displayflow/core/protocol/protocol_handler.h b/core/include/displayflow/core/protocol/protocol_handler.h new file mode 100644 index 0000000..49875ed --- /dev/null +++ b/core/include/displayflow/core/protocol/protocol_handler.h @@ -0,0 +1,27 @@ +#pragma once + +namespace displayflow { +namespace core { + +/** + * @brief 协议处理器 + * + * 负责处理 FlatBuffers 协议的序列化和反序列化 + */ +class ProtocolHandler { +public: + ProtocolHandler(); + ~ProtocolHandler(); + + /** + * @brief 初始化协议处理器 + */ + bool Initialize(); + +private: + // TODO: 添加私有成员 +}; + +} // namespace core +} // namespace displayflow + diff --git a/core/include/displayflow/core/role/client_role.h b/core/include/displayflow/core/role/client_role.h new file mode 100644 index 0000000..1882a45 --- /dev/null +++ b/core/include/displayflow/core/role/client_role.h @@ -0,0 +1,29 @@ +#pragma once + +#include "displayflow/core/role/role_interface.h" + +namespace displayflow { +namespace core { + +/** + * @brief 客户端角色 + * + * 负责接收、解码和渲染 + */ +class ClientRole : public IRole { +public: + ClientRole(); + ~ClientRole() override; + + RoleType GetType() const override; + bool Start(std::shared_ptr session) override; + void Stop() override; + bool IsRunning() const override; + +private: + bool isRunning_ = false; +}; + +} // namespace core +} // namespace displayflow + diff --git a/core/include/displayflow/core/role/host_role.h b/core/include/displayflow/core/role/host_role.h new file mode 100644 index 0000000..d7dd9d8 --- /dev/null +++ b/core/include/displayflow/core/role/host_role.h @@ -0,0 +1,29 @@ +#pragma once + +#include "displayflow/core/role/role_interface.h" + +namespace displayflow { +namespace core { + +/** + * @brief 主机角色 + * + * 负责屏幕捕获、编码和发送 + */ +class HostRole : public IRole { +public: + HostRole(); + ~HostRole() override; + + RoleType GetType() const override; + bool Start(std::shared_ptr session) override; + void Stop() override; + bool IsRunning() const override; + +private: + bool isRunning_ = false; +}; + +} // namespace core +} // namespace displayflow + diff --git a/core/include/displayflow/core/role/peer_role.h b/core/include/displayflow/core/role/peer_role.h new file mode 100644 index 0000000..aaff53a --- /dev/null +++ b/core/include/displayflow/core/role/peer_role.h @@ -0,0 +1,29 @@ +#pragma once + +#include "displayflow/core/role/role_interface.h" + +namespace displayflow { +namespace core { + +/** + * @brief 对等角色 + * + * 同时作为主机和客户端,实现双向屏幕共享 + */ +class PeerRole : public IRole { +public: + PeerRole(); + ~PeerRole() override; + + RoleType GetType() const override; + bool Start(std::shared_ptr session) override; + void Stop() override; + bool IsRunning() const override; + +private: + bool isRunning_ = false; +}; + +} // namespace core +} // namespace displayflow + diff --git a/core/include/displayflow/core/role/role_interface.h b/core/include/displayflow/core/role/role_interface.h new file mode 100644 index 0000000..6c80419 --- /dev/null +++ b/core/include/displayflow/core/role/role_interface.h @@ -0,0 +1,45 @@ +#pragma once + +#include "displayflow/core/common/types.h" +#include + +namespace displayflow { +namespace core { + +class Session; + +/** + * @brief 角色接口 + * + * 所有角色(Host、Client、Peer)必须实现此接口 + */ +class IRole { +public: + virtual ~IRole() = default; + + /** + * @brief 获取角色类型 + */ + virtual RoleType GetType() const = 0; + + /** + * @brief 启动角色 + * @param session 会话对象 + * @return 是否成功 + */ + virtual bool Start(std::shared_ptr session) = 0; + + /** + * @brief 停止角色 + */ + virtual void Stop() = 0; + + /** + * @brief 是否正在运行 + */ + virtual bool IsRunning() const = 0; +}; + +} // namespace core +} // namespace displayflow + diff --git a/core/include/displayflow/core/role/role_manager.h b/core/include/displayflow/core/role/role_manager.h new file mode 100644 index 0000000..aa5e2a1 --- /dev/null +++ b/core/include/displayflow/core/role/role_manager.h @@ -0,0 +1,37 @@ +#pragma once + +#include "displayflow/core/common/types.h" +#include "displayflow/core/role/role_interface.h" +#include +#include + +namespace displayflow { +namespace core { + +/** + * @brief 角色管理器 + * + * 负责管理和切换设备角色 + */ +class RoleManager { +public: + RoleManager(); + ~RoleManager(); + + /** + * @brief 注册角色 + */ + bool RegisterRole(RoleType type, std::shared_ptr role); + + /** + * @brief 切换角色 + */ + bool SwitchRole(SessionId sessionId, RoleType newRole); + +private: + std::unordered_map> roles_; +}; + +} // namespace core +} // namespace displayflow + diff --git a/core/include/displayflow/core/session/session.h b/core/include/displayflow/core/session/session.h new file mode 100644 index 0000000..4f78192 --- /dev/null +++ b/core/include/displayflow/core/session/session.h @@ -0,0 +1,52 @@ +#pragma once + +#include "displayflow/core/common/types.h" +#include + +namespace displayflow { +namespace core { + +/** + * @brief 显示会话 + * + * 表示一个显示协作会话 + */ +class Session { +public: + Session(SessionId id, RoleType role); + ~Session(); + + /** + * @brief 获取会话 ID + */ + SessionId GetId() const; + + /** + * @brief 获取角色类型 + */ + RoleType GetRole() const; + + /** + * @brief 是否处于活动状态 + */ + bool IsActive() const; + + /** + * @brief 启动会话 + */ + void Start(); + + /** + * @brief 停止会话 + */ + void Stop(); + +private: + SessionId id_; + RoleType role_; + bool isActive_ = false; +}; + +} // namespace core +} // namespace displayflow + diff --git a/core/include/displayflow/core/session/session_manager.h b/core/include/displayflow/core/session/session_manager.h new file mode 100644 index 0000000..cffa60d --- /dev/null +++ b/core/include/displayflow/core/session/session_manager.h @@ -0,0 +1,43 @@ +#pragma once + +#include "displayflow/core/common/types.h" +#include "displayflow/core/session/session.h" +#include +#include + +namespace displayflow { +namespace core { + +/** + * @brief 会话管理器 + * + * 负责创建、管理和销毁显示会话 + */ +class SessionManager { +public: + SessionManager(); + ~SessionManager(); + + /** + * @brief 创建新会话 + */ + std::shared_ptr CreateSession(RoleType role); + + /** + * @brief 销毁会话 + */ + void DestroySession(SessionId sessionId); + + /** + * @brief 获取会话 + */ + std::shared_ptr GetSession(SessionId sessionId); + +private: + std::unordered_map> sessions_; + SessionId nextSessionId_ = 1; +}; + +} // namespace core +} // namespace displayflow + diff --git a/core/include/displayflow/core/utils/logger.h b/core/include/displayflow/core/utils/logger.h new file mode 100644 index 0000000..59df151 --- /dev/null +++ b/core/include/displayflow/core/utils/logger.h @@ -0,0 +1,31 @@ +#pragma once + +#include + +namespace displayflow { +namespace core { + +enum class LogLevel { + Debug, + Info, + Warning, + Error +}; + +/** + * @brief 日志记录器 + */ +class Logger { +public: + Logger(); + ~Logger(); + + void Log(LogLevel level, const std::string& message); + +private: + // TODO: 添加私有成员 +}; + +} // namespace core +} // namespace displayflow + diff --git a/core/include/displayflow/core/utils/timer.h b/core/include/displayflow/core/utils/timer.h new file mode 100644 index 0000000..85e64a1 --- /dev/null +++ b/core/include/displayflow/core/utils/timer.h @@ -0,0 +1,27 @@ +#pragma once + +#include + +namespace displayflow { +namespace core { + +/** + * @brief 定时器工具 + */ +class Timer { +public: + Timer(); + ~Timer(); + + /** + * @brief 获取当前时间(毫秒) + */ + uint64_t GetCurrentTimeMs(); + +private: + // TODO: 添加私有成员 +}; + +} // namespace core +} // namespace displayflow + diff --git a/core/src/codec/codec_interface.cpp b/core/src/codec/codec_interface.cpp new file mode 100644 index 0000000..c56ae60 --- /dev/null +++ b/core/src/codec/codec_interface.cpp @@ -0,0 +1,11 @@ +#include "displayflow/core/codec/codec_interface.h" + +namespace displayflow { +namespace core { + +// ICodec 接口实现 +// 目前只有头文件定义,此文件保留用于未来扩展 + +} // namespace core +} // namespace displayflow + diff --git a/core/src/codec/codec_manager.cpp b/core/src/codec/codec_manager.cpp new file mode 100644 index 0000000..ebfd7e4 --- /dev/null +++ b/core/src/codec/codec_manager.cpp @@ -0,0 +1,26 @@ +#include "displayflow/core/codec/codec_manager.h" + +namespace displayflow { +namespace core { + +CodecManager::CodecManager() { + // TODO: 实现构造函数 +} + +CodecManager::~CodecManager() { + // TODO: 实现析构函数 +} + +bool CodecManager::Initialize() { + // TODO: 实现初始化逻辑 + return false; +} + +std::shared_ptr CodecManager::GetCodec(CodecType type) { + // TODO: 实现获取编解码器逻辑 + return nullptr; +} + +} // namespace core +} // namespace displayflow + diff --git a/core/src/file_transfer/file_transfer_manager.cpp b/core/src/file_transfer/file_transfer_manager.cpp new file mode 100644 index 0000000..c4a85ed --- /dev/null +++ b/core/src/file_transfer/file_transfer_manager.cpp @@ -0,0 +1,47 @@ +#include "displayflow/core/file_transfer/file_transfer_manager.h" + +namespace displayflow { +namespace core { + +FileTransferManager::FileTransferManager() { + // TODO: 实现构造函数 +} + +FileTransferManager::~FileTransferManager() { + // TODO: 实现析构函数 +} + +uint64_t FileTransferManager::SendFile(const std::string& filePath, SessionId sessionId) { + // TODO: 实现发送文件逻辑 + return 0; +} + +uint64_t FileTransferManager::ReceiveFile(const std::string& fileName, uint64_t fileSize, + const std::string& savePath, SessionId sessionId) { + // TODO: 实现接收文件逻辑 + return 0; +} + +bool FileTransferManager::PauseTransfer(uint64_t transferId) { + // TODO: 实现暂停传输逻辑 + return false; +} + +bool FileTransferManager::ResumeTransfer(uint64_t transferId) { + // TODO: 实现恢复传输逻辑 + return false; +} + +bool FileTransferManager::CancelTransfer(uint64_t transferId) { + // TODO: 实现取消传输逻辑 + return false; +} + +double FileTransferManager::GetTransferProgress(uint64_t transferId) const { + // TODO: 实现获取传输进度逻辑 + return 0.0; +} + +} // namespace core +} // namespace displayflow + diff --git a/core/src/file_transfer/file_transfer_session.cpp b/core/src/file_transfer/file_transfer_session.cpp new file mode 100644 index 0000000..8bfbb62 --- /dev/null +++ b/core/src/file_transfer/file_transfer_session.cpp @@ -0,0 +1,45 @@ +#include "displayflow/core/file_transfer/file_transfer_session.h" + +namespace displayflow { +namespace core { + +FileTransferSession::FileTransferSession(uint64_t id, TransferDirection direction) + : id_(id), direction_(direction) { + // TODO: 实现构造函数 +} + +FileTransferSession::~FileTransferSession() { + // TODO: 实现析构函数 +} + +void FileTransferSession::Start() { + // TODO: 实现启动传输逻辑 + status_ = TransferStatus::InProgress; +} + +void FileTransferSession::Pause() { + // TODO: 实现暂停逻辑 + status_ = TransferStatus::Paused; +} + +void FileTransferSession::Resume() { + // TODO: 实现恢复逻辑 + status_ = TransferStatus::InProgress; +} + +void FileTransferSession::Cancel() { + // TODO: 实现取消逻辑 + status_ = TransferStatus::Cancelled; +} + +TransferProgress FileTransferSession::GetProgress() const { + return progress_; +} + +void FileTransferSession::SetProgressCallback(std::function callback) { + progressCallback_ = callback; +} + +} // namespace core +} // namespace displayflow + diff --git a/core/src/network/nat_traversal/candidate.cpp b/core/src/network/nat_traversal/candidate.cpp new file mode 100644 index 0000000..6258135 --- /dev/null +++ b/core/src/network/nat_traversal/candidate.cpp @@ -0,0 +1,34 @@ +#include "displayflow/core/network/nat_traversal/candidate.h" + +namespace displayflow { +namespace core { + +uint32_t CalculateCandidatePriority(const Candidate& candidate) { + // 根据 RFC 8445 计算候选地址优先级 + // priority = (2^24) * (type preference) + (2^8) * (local preference) + (2^0) * (component ID) + + uint32_t typePreference = 0; + switch (candidate.type) { + case CandidateType::Host: + typePreference = 126; // 最高优先级 + break; + case CandidateType::ServerReflexive: + typePreference = 100; + break; + case CandidateType::PeerReflexive: + typePreference = 110; + break; + case CandidateType::Relayed: + typePreference = 0; // 最低优先级 + break; + } + + uint32_t localPreference = 65535; // 默认值 + uint32_t componentId = 1; // 默认值 + + return (typePreference << 24) | (localPreference << 8) | componentId; +} + +} // namespace core +} // namespace displayflow + diff --git a/core/src/network/nat_traversal/ice_agent.cpp b/core/src/network/nat_traversal/ice_agent.cpp new file mode 100644 index 0000000..e2ff2df --- /dev/null +++ b/core/src/network/nat_traversal/ice_agent.cpp @@ -0,0 +1,69 @@ +#include "displayflow/core/network/nat_traversal/ice_agent.h" + +namespace displayflow { +namespace core { + +IceAgent::IceAgent() { + // TODO: 实现构造函数 +} + +IceAgent::~IceAgent() { + // TODO: 实现析构函数 +} + +bool IceAgent::Initialize(const IceConfig& config) { + config_ = config; + stunClient_.SetServer(config.stunServer); + turnClient_.SetServer(config.turnServer); + return true; +} + +std::vector IceAgent::GatherCandidates() { + // TODO: 实现收集候选地址 + // 1. 收集本地网络接口地址 + // 2. 通过 STUN 获取服务器反射地址 + // 3. 通过 TURN 获取中继地址 + return {}; +} + +void IceAgent::SetRemoteCandidates(const std::vector& candidates) { + remoteCandidates_ = candidates; +} + +bool IceAgent::PerformConnectivityChecks() { + // TODO: 实现连接检查 + // 1. 生成候选地址对 + // 2. 按优先级排序 + // 3. 执行连接检查 + // 4. 选择最佳路径 + return false; +} + +IceCandidatePair IceAgent::GetSelectedPair() const { + return selectedPair_; +} + +std::string IceAgent::GetConnectionType() const { + if (selectedPair_.valid) { + switch (selectedPair_.local.type) { + case CandidateType::Host: + return "local"; + case CandidateType::ServerReflexive: + return "stun"; + case CandidateType::Relayed: + return "turn"; + default: + return "unknown"; + } + } + return "unknown"; +} + +void IceAgent::Cleanup() { + // TODO: 实现清理逻辑 + turnClient_.ReleaseAllocation(); +} + +} // namespace core +} // namespace displayflow + diff --git a/core/src/network/nat_traversal/nat_type.cpp b/core/src/network/nat_traversal/nat_type.cpp new file mode 100644 index 0000000..3417ec4 --- /dev/null +++ b/core/src/network/nat_traversal/nat_type.cpp @@ -0,0 +1,32 @@ +#include "displayflow/core/network/nat_traversal/nat_type.h" + +namespace displayflow { +namespace core { + +const char* NatTypeToString(NatType type) { + switch (type) { + case NatType::Unknown: + return "Unknown"; + case NatType::Open: + return "Open"; + case NatType::FullCone: + return "Full Cone"; + case NatType::RestrictedCone: + return "Restricted Cone"; + case NatType::PortRestrictedCone: + return "Port Restricted Cone"; + case NatType::Symmetric: + return "Symmetric"; + default: + return "Unknown"; + } +} + +bool IsNatTypeDirectConnectable(NatType type) { + // 只有开放和完全锥形 NAT 可以直接连接 + return type == NatType::Open || type == NatType::FullCone; +} + +} // namespace core +} // namespace displayflow + diff --git a/core/src/network/nat_traversal/stun_client.cpp b/core/src/network/nat_traversal/stun_client.cpp new file mode 100644 index 0000000..2c50d90 --- /dev/null +++ b/core/src/network/nat_traversal/stun_client.cpp @@ -0,0 +1,37 @@ +#include "displayflow/core/network/nat_traversal/stun_client.h" + +namespace displayflow { +namespace core { + +StunClient::StunClient() { + // TODO: 实现构造函数 +} + +StunClient::~StunClient() { + // TODO: 实现析构函数 +} + +void StunClient::SetServer(const StunServerConfig& config) { + serverConfig_ = config; +} + +StunResponse StunClient::PerformBindingRequest(uint16_t localPort) { + // TODO: 实现 STUN 绑定请求 + StunResponse response; + response.success = false; + return response; +} + +NatType StunClient::DetectNatType() { + // TODO: 实现 NAT 类型检测 + return NatType::Unknown; +} + +std::string StunClient::GetPublicIp() { + // TODO: 实现获取公网 IP + return ""; +} + +} // namespace core +} // namespace displayflow + diff --git a/core/src/network/nat_traversal/turn_client.cpp b/core/src/network/nat_traversal/turn_client.cpp new file mode 100644 index 0000000..a9eee2b --- /dev/null +++ b/core/src/network/nat_traversal/turn_client.cpp @@ -0,0 +1,47 @@ +#include "displayflow/core/network/nat_traversal/turn_client.h" + +namespace displayflow { +namespace core { + +TurnClient::TurnClient() { + // TODO: 实现构造函数 +} + +TurnClient::~TurnClient() { + // TODO: 实现析构函数 +} + +void TurnClient::SetServer(const TurnServerConfig& config) { + serverConfig_ = config; +} + +Candidate TurnClient::AllocateRelayAddress() { + // TODO: 实现分配中继地址 + Candidate candidate; + candidate.type = CandidateType::Relayed; + return candidate; +} + +bool TurnClient::CreatePermission(const std::string& peerIp) { + // TODO: 实现创建权限 + return false; +} + +bool TurnClient::SendData(const ByteArray& data, const std::string& peerIp, uint16_t peerPort) { + // TODO: 实现发送数据 + return false; +} + +bool TurnClient::ReceiveData(ByteArray& data, std::string& peerIp, uint16_t& peerPort) { + // TODO: 实现接收数据 + return false; +} + +void TurnClient::ReleaseAllocation() { + // TODO: 实现释放分配 + allocated_ = false; +} + +} // namespace core +} // namespace displayflow + diff --git a/core/src/network/network_interface.cpp b/core/src/network/network_interface.cpp new file mode 100644 index 0000000..ca7c6ec --- /dev/null +++ b/core/src/network/network_interface.cpp @@ -0,0 +1,11 @@ +#include "displayflow/core/network/network_interface.h" + +namespace displayflow { +namespace core { + +// NetworkInterface 结构体实现 +// 目前只有头文件定义,此文件保留用于未来扩展 + +} // namespace core +} // namespace displayflow + diff --git a/core/src/network/network_manager.cpp b/core/src/network/network_manager.cpp new file mode 100644 index 0000000..8410af1 --- /dev/null +++ b/core/src/network/network_manager.cpp @@ -0,0 +1,35 @@ +#include "displayflow/core/network/network_manager.h" + +namespace displayflow { +namespace core { + +NetworkManager::NetworkManager() { + // TODO: 实现构造函数 +} + +NetworkManager::~NetworkManager() { + // TODO: 实现析构函数 +} + +bool NetworkManager::Initialize() { + // TODO: 实现初始化逻辑 + return false; +} + +std::vector NetworkManager::GetAvailableInterfaces() { + // TODO: 实现获取可用网络接口 + return {}; +} + +bool NetworkManager::Connect(const NetworkInterface& interface) { + // TODO: 实现连接逻辑 + return false; +} + +void NetworkManager::Disconnect() { + // TODO: 实现断开连接逻辑 +} + +} // namespace core +} // namespace displayflow + diff --git a/core/src/protocol/message_serializer.cpp b/core/src/protocol/message_serializer.cpp new file mode 100644 index 0000000..ef31c73 --- /dev/null +++ b/core/src/protocol/message_serializer.cpp @@ -0,0 +1,26 @@ +#include "displayflow/core/protocol/message_serializer.h" + +namespace displayflow { +namespace core { + +MessageSerializer::MessageSerializer() { + // TODO: 实现构造函数 +} + +MessageSerializer::~MessageSerializer() { + // TODO: 实现析构函数 +} + +ByteArray MessageSerializer::Serialize(const void* message) { + // TODO: 实现序列化逻辑 + return {}; +} + +bool MessageSerializer::Deserialize(const ByteArray& data, void* message) { + // TODO: 实现反序列化逻辑 + return false; +} + +} // namespace core +} // namespace displayflow + diff --git a/core/src/protocol/protocol_handler.cpp b/core/src/protocol/protocol_handler.cpp new file mode 100644 index 0000000..a2d9247 --- /dev/null +++ b/core/src/protocol/protocol_handler.cpp @@ -0,0 +1,21 @@ +#include "displayflow/core/protocol/protocol_handler.h" + +namespace displayflow { +namespace core { + +ProtocolHandler::ProtocolHandler() { + // TODO: 实现构造函数 +} + +ProtocolHandler::~ProtocolHandler() { + // TODO: 实现析构函数 +} + +bool ProtocolHandler::Initialize() { + // TODO: 实现初始化逻辑 + return false; +} + +} // namespace core +} // namespace displayflow + diff --git a/core/src/role/client_role.cpp b/core/src/role/client_role.cpp new file mode 100644 index 0000000..b790a57 --- /dev/null +++ b/core/src/role/client_role.cpp @@ -0,0 +1,33 @@ +#include "displayflow/core/role/client_role.h" + +namespace displayflow { +namespace core { + +ClientRole::ClientRole() { + // TODO: 实现构造函数 +} + +ClientRole::~ClientRole() { + // TODO: 实现析构函数 +} + +RoleType ClientRole::GetType() const { + return RoleType::Client; +} + +bool ClientRole::Start(std::shared_ptr session) { + // TODO: 实现启动逻辑 + return false; +} + +void ClientRole::Stop() { + // TODO: 实现停止逻辑 +} + +bool ClientRole::IsRunning() const { + return isRunning_; +} + +} // namespace core +} // namespace displayflow + diff --git a/core/src/role/host_role.cpp b/core/src/role/host_role.cpp new file mode 100644 index 0000000..4c2242b --- /dev/null +++ b/core/src/role/host_role.cpp @@ -0,0 +1,33 @@ +#include "displayflow/core/role/host_role.h" + +namespace displayflow { +namespace core { + +HostRole::HostRole() { + // TODO: 实现构造函数 +} + +HostRole::~HostRole() { + // TODO: 实现析构函数 +} + +RoleType HostRole::GetType() const { + return RoleType::Host; +} + +bool HostRole::Start(std::shared_ptr session) { + // TODO: 实现启动逻辑 + return false; +} + +void HostRole::Stop() { + // TODO: 实现停止逻辑 +} + +bool HostRole::IsRunning() const { + return isRunning_; +} + +} // namespace core +} // namespace displayflow + diff --git a/core/src/role/peer_role.cpp b/core/src/role/peer_role.cpp new file mode 100644 index 0000000..e600b34 --- /dev/null +++ b/core/src/role/peer_role.cpp @@ -0,0 +1,33 @@ +#include "displayflow/core/role/peer_role.h" + +namespace displayflow { +namespace core { + +PeerRole::PeerRole() { + // TODO: 实现构造函数 +} + +PeerRole::~PeerRole() { + // TODO: 实现析构函数 +} + +RoleType PeerRole::GetType() const { + return RoleType::Peer; +} + +bool PeerRole::Start(std::shared_ptr session) { + // TODO: 实现启动逻辑(同时启动 Host 和 Client) + return false; +} + +void PeerRole::Stop() { + // TODO: 实现停止逻辑 +} + +bool PeerRole::IsRunning() const { + return isRunning_; +} + +} // namespace core +} // namespace displayflow + diff --git a/core/src/role/role_manager.cpp b/core/src/role/role_manager.cpp new file mode 100644 index 0000000..38be7fd --- /dev/null +++ b/core/src/role/role_manager.cpp @@ -0,0 +1,26 @@ +#include "displayflow/core/role/role_manager.h" + +namespace displayflow { +namespace core { + +RoleManager::RoleManager() { + // TODO: 实现构造函数 +} + +RoleManager::~RoleManager() { + // TODO: 实现析构函数 +} + +bool RoleManager::RegisterRole(RoleType type, std::shared_ptr role) { + // TODO: 实现角色注册逻辑 + return false; +} + +bool RoleManager::SwitchRole(SessionId sessionId, RoleType newRole) { + // TODO: 实现角色切换逻辑 + return false; +} + +} // namespace core +} // namespace displayflow + diff --git a/core/src/session/session.cpp b/core/src/session/session.cpp new file mode 100644 index 0000000..b11d91b --- /dev/null +++ b/core/src/session/session.cpp @@ -0,0 +1,39 @@ +#include "displayflow/core/session/session.h" + +namespace displayflow { +namespace core { + +Session::Session(SessionId id, RoleType role) + : id_(id), role_(role) { + // TODO: 实现构造函数 +} + +Session::~Session() { + // TODO: 实现析构函数 +} + +SessionId Session::GetId() const { + return id_; +} + +RoleType Session::GetRole() const { + return role_; +} + +bool Session::IsActive() const { + return isActive_; +} + +void Session::Start() { + // TODO: 实现启动逻辑 + isActive_ = true; +} + +void Session::Stop() { + // TODO: 实现停止逻辑 + isActive_ = false; +} + +} // namespace core +} // namespace displayflow + diff --git a/core/src/session/session_manager.cpp b/core/src/session/session_manager.cpp new file mode 100644 index 0000000..26cd75d --- /dev/null +++ b/core/src/session/session_manager.cpp @@ -0,0 +1,30 @@ +#include "displayflow/core/session/session_manager.h" + +namespace displayflow { +namespace core { + +SessionManager::SessionManager() { + // TODO: 实现构造函数 +} + +SessionManager::~SessionManager() { + // TODO: 实现析构函数 +} + +std::shared_ptr SessionManager::CreateSession(RoleType role) { + // TODO: 实现会话创建逻辑 + return nullptr; +} + +void SessionManager::DestroySession(SessionId sessionId) { + // TODO: 实现会话销毁逻辑 +} + +std::shared_ptr SessionManager::GetSession(SessionId sessionId) { + // TODO: 实现获取会话逻辑 + return nullptr; +} + +} // namespace core +} // namespace displayflow + diff --git a/core/src/utils/logger.cpp b/core/src/utils/logger.cpp new file mode 100644 index 0000000..b3e422e --- /dev/null +++ b/core/src/utils/logger.cpp @@ -0,0 +1,22 @@ +#include "displayflow/core/utils/logger.h" +#include + +namespace displayflow { +namespace core { + +Logger::Logger() { + // TODO: 实现构造函数 +} + +Logger::~Logger() { + // TODO: 实现析构函数 +} + +void Logger::Log(LogLevel level, const std::string& message) { + // TODO: 实现日志记录逻辑 + std::cout << "[" << static_cast(level) << "] " << message << std::endl; +} + +} // namespace core +} // namespace displayflow + diff --git a/core/src/utils/timer.cpp b/core/src/utils/timer.cpp new file mode 100644 index 0000000..5d828f3 --- /dev/null +++ b/core/src/utils/timer.cpp @@ -0,0 +1,23 @@ +#include "displayflow/core/utils/timer.h" +#include + +namespace displayflow { +namespace core { + +Timer::Timer() { + // TODO: 实现构造函数 +} + +Timer::~Timer() { + // TODO: 实现析构函数 +} + +uint64_t Timer::GetCurrentTimeMs() { + auto now = std::chrono::steady_clock::now(); + auto duration = now.time_since_epoch(); + return std::chrono::duration_cast(duration).count(); +} + +} // namespace core +} // namespace displayflow + diff --git a/docs/API.md b/docs/API.md new file mode 100644 index 0000000..e71af34 --- /dev/null +++ b/docs/API.md @@ -0,0 +1,85 @@ +# DisplayFlow API 文档 + +本文档描述 DisplayFlow 的核心 API。 + +## 1. 核心 API + +### 1.1 会话管理 + +```cpp +class SessionManager { +public: + std::shared_ptr CreateSession(RoleType role); + void DestroySession(SessionId sessionId); + std::shared_ptr GetSession(SessionId sessionId); +}; +``` + +### 1.2 角色管理 + +```cpp +class RoleManager { +public: + bool RegisterRole(RoleType type, std::shared_ptr role); + bool SwitchRole(SessionId sessionId, RoleType newRole); +}; +``` + +### 1.3 网络管理 + +```cpp +class NetworkManager { +public: + bool Initialize(); + std::vector GetAvailableInterfaces(); + bool Connect(const NetworkInterface& interface); + void Disconnect(); +}; +``` + +## 2. 平台 API + +### 2.1 Android + +```cpp +class AndroidPlatformAdapter { +public: + bool Initialize(); + bool StartScreenCapture(); + void StopScreenCapture(); + void SetFrameCallback(FrameCallback callback); +}; +``` + +### 2.2 Windows + +```cpp +class WindowsPlatformAdapter { +public: + bool Initialize(); + bool CreateVirtualDisplay(const Resolution& resolution); + void DestroyVirtualDisplay(); + bool RenderFrame(const VideoFrame& frame); +}; +``` + +## 3. 使用示例 + +### 3.1 创建 Host 会话 + +```cpp +auto sessionManager = std::make_shared(); +auto session = sessionManager->CreateSession(RoleType::Host); +auto hostRole = std::make_shared(); +hostRole->Start(session); +``` + +### 3.2 创建 Client 会话 + +```cpp +auto sessionManager = std::make_shared(); +auto session = sessionManager->CreateSession(RoleType::Client); +auto clientRole = std::make_shared(); +clientRole->Start(session); +``` + diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md new file mode 100644 index 0000000..965b732 --- /dev/null +++ b/docs/ARCHITECTURE.md @@ -0,0 +1,212 @@ +# DisplayFlow 架构设计文档 + +本文档详细描述 DisplayFlow 系统的架构设计。 + +## 1. 整体架构 + +DisplayFlow 采用分层架构设计,从下到上分为: + +1. **传输层(Transport Layer)**:物理网络连接 + - 局域网连接(USB RNDIS、Wi-Fi、以太网) + - 互联网连接(通过 STUN/TURN/ICE) +2. **核心层(Core Layer)**:跨平台业务逻辑 +3. **平台适配层(Platform Adapter Layer)**:平台特定实现 +4. **角色层(Role Layer)**:业务角色实现 +5. **应用层(Application Layer)**:用户界面和应用逻辑 + +**网络连接方式:** +- **局域网直连**:优先使用,延迟最低(< 5ms) +- **公网直连**:通过 STUN 发现,中等延迟(10-50ms) +- **TURN 中继**:当直连失败时使用,延迟较高(50-200ms)但最可靠 + +## 2. 核心层设计 + +### 2.1 网络抽象层 + +提供统一的网络接口,屏蔽底层网络差异。 + +**NAT 穿透模块:** +- **STUN 客户端**:用于 NAT 类型检测和获取公网 IP 地址 +- **TURN 客户端**:当直连失败时,通过 TURN 服务器中继流量 +- **ICE 代理**:实现 ICE (Interactive Connectivity Establishment) 协议 + - 收集候选地址(本地、服务器反射、中继) + - 执行连接检查 + - 选择最佳连接路径 +- **连接建立**:自动尝试多种连接方式,选择最优路径 + +### 2.2 协议层 + +基于 FlatBuffers 的跨平台序列化协议。 + +### 2.3 会话管理层 + +管理显示会话的生命周期。 + +### 2.4 编解码抽象层 + +统一的编解码器接口,支持多种编解码器。 + +### 2.5 文件传输模块 + +提供设备间文件传输功能: +- 文件传输协议定义 +- 断点续传机制 +- 多文件并发传输 +- 传输进度跟踪 +- 文件完整性校验 + +## 3. 平台适配层设计 + +### 3.1 Android 适配层 + +- 屏幕捕获:MediaProjection API +- 摄像头捕获:Camera2 API / NDK Camera API +- 输入处理:触摸事件 +- 网络:USB RNDIS、Wi-Fi + +### 3.2 Windows 适配层 + +- 虚拟显示器:IddCx 驱动框架 +- 摄像头捕获:DirectShow / Media Foundation +- 渲染:DirectX +- 输入处理:键盘、鼠标 +- 网络:USB RNDIS、Wi-Fi、以太网 + +## 4. 角色层设计 + +### 4.1 Host 角色 + +负责屏幕捕获、编码、发送。 + +### 4.2 Client 角色 + +负责接收、解码、渲染。 + +### 4.3 Peer 角色 + +同时运行 Host 和 Client 逻辑。 + +## 5. 数据流 + +### 5.1 Host -> Client 数据流 + +1. 平台层捕获屏幕帧 +2. 编码器编码视频帧 +3. 协议层序列化 +4. 网络层发送 +5. 客户端网络层接收 +6. 协议层反序列化 +7. 解码器解码 +8. 平台层渲染 + +### 5.2 Client -> Host 输入流 + +1. 平台层捕获输入事件 +2. 协议层序列化 +3. 网络层发送 +4. 主机网络层接收 +5. 协议层反序列化 +6. 平台层注入输入事件 + +### 5.3 文件传输流 + +1. 发送端选择文件 +2. 文件分块(Chunk) +3. 协议层封装文件块 +4. 网络层发送(可靠传输) +5. 接收端接收并重组 +6. 文件完整性校验 +7. 保存到目标位置 + +### 5.4 远程摄像头流 + +1. Host 端枚举摄像头设备 +2. 选择并启动摄像头 +3. 摄像头捕获视频帧 +4. 编码器编码(复用屏幕共享编码器) +5. 协议层序列化 +6. 网络层发送 +7. Client 端接收、解码、渲染 +8. 显示摄像头画面(可叠加在屏幕共享上) + +## 6. 扩展功能设计 + +### 6.1 文件传输模块 + +**架构设计:** +- 复用现有的网络抽象层和协议层 +- 使用可靠传输协议(TCP 或可靠 UDP) +- 支持断点续传,记录传输状态 +- 多文件队列管理,支持优先级 + +**协议设计:** +- 文件元数据(文件名、大小、校验和) +- 文件块(Chunk)传输 +- 传输控制消息(开始、暂停、恢复、取消) +- 进度报告机制 + +### 6.2 远程摄像头模块 + +**架构设计:** +- 复用现有的编码和传输机制 +- 摄像头作为新的视频源类型 +- 支持与屏幕共享同时进行(多路视频流) +- 摄像头参数控制(分辨率、帧率、对焦、曝光等) + +**实现方式:** +- Android:使用 Camera2 API 或 NDK Camera API +- Windows:使用 DirectShow 或 Media Foundation +- 视频流复用屏幕共享的编码和传输通道 +- 在协议中区分视频源类型(屏幕/摄像头) + +### 6.3 NAT 穿透模块(TURN/STUN) + +**架构设计:** +- 集成到网络抽象层,对上层透明 +- 支持局域网、公网直连、TURN 中继三种连接方式 +- 自动选择最佳连接路径 +- 支持自定义 STUN/TURN 服务器配置 + +**连接建立流程:** + +1. **候选地址收集** + - 收集本地网络接口地址 + - 通过 STUN 服务器获取服务器反射地址 + - 通过 TURN 服务器获取中继地址 + +2. **ICE 连接检查** + - 向所有候选地址发送连接检查 + - 等待对端响应 + - 测量延迟和带宽 + +3. **路径选择** + - 优先选择局域网直连(延迟最低) + - 其次选择公网直连(通过 STUN) + - 最后选择 TURN 中继(最可靠但延迟较高) + +4. **连接建立** + - 使用选定的路径建立连接 + - 开始数据传输 + +**协议支持:** +- STUN (Session Traversal Utilities for NAT) - RFC 5389 +- TURN (Traversal Using Relays around NAT) - RFC 5766 +- ICE (Interactive Connectivity Establishment) - RFC 8445 + +**配置选项:** +- STUN 服务器地址和端口 +- TURN 服务器地址、端口、用户名、密码 +- ICE 连接超时时间 +- 候选地址收集超时时间 + +**使用场景:** +1. **局域网场景**:自动检测并使用局域网直连(最快) +2. **互联网场景**:通过 STUN/TURN 服务器建立连接 +3. **混合场景**:优先尝试局域网,失败后自动切换到互联网连接 + +**集成方式:** +- NAT 穿透模块集成到网络抽象层 +- 对上层应用完全透明 +- 自动选择最佳连接路径 +- 支持连接方式动态切换 + diff --git a/docs/IMPLEMENTATION.md b/docs/IMPLEMENTATION.md new file mode 100644 index 0000000..b04754f --- /dev/null +++ b/docs/IMPLEMENTATION.md @@ -0,0 +1,899 @@ +# DisplayFlow 实现原理与视频流向 + +本文档详细说明 Windows 和 Android 平台的实现原理,以及视频数据在系统中的流向。 + +## 0. 技术栈说明 + +**核心原则:纯 C++ 实现** + +DisplayFlow 的核心业务逻辑完全由 C++ 实现,包括: +- 网络抽象层 +- 协议处理(FlatBuffers) +- 会话管理 +- 编解码器抽象 +- 角色管理 + +**平台适配层:** + +- **Windows**:完全使用 C++ 和 Windows API(DirectX、IddCx、Win32 API) +- **Android**:**完全使用 C++ 和 Android NDK Native API** + - 使用 `AMediaCodec`(NDK MediaCodec API)进行硬件编码 + - 使用 `AImageReader`(NDK ImageReader API)获取屏幕帧 + - 使用 `ANativeWindow` 和 `AHardwareBuffer` 进行 GPU 缓冲区操作 + - **无需 JNI 调用 Java API**,完全在 native 层实现 + - 仅权限请求需要最小 Java 层(可选,可通过系统服务实现) + +**架构优势:** +- 核心代码 100% 跨平台,可复用 +- 平台特定代码隔离在适配层 +- **Android 平台完全 native 实现,无 JNI 开销** +- 性能最优,直接调用系统底层 API + +## 1. 整体架构概览 + +DisplayFlow 采用分层架构,数据流从平台层捕获开始,经过核心层处理,最终在目标平台渲染显示。 + +``` +[平台层捕获] -> [编码] -> [协议封装] -> [网络传输] -> [协议解析] -> [解码] -> [平台层渲染] +``` + +**Android 平台架构:** +``` +C++ 核心层 (纯 C++) + ↑↓ 直接调用 +C++ 平台适配层 (AMediaCodec, AImageReader, ANativeWindow) + ↑↓ +Android NDK Native API + ↑↓ +Android 系统底层 (硬件编解码器, GPU) +``` + +**注意:** +- MediaProjection 权限请求可能需要一个最小的 Java Activity(一次性操作) +- 但实际的屏幕捕获、编码、网络传输等所有核心功能**完全在 C++ native 层实现** +- 使用 Android NDK Native API(AMediaCodec、AImageReader、ANativeWindow 等) +- **无需 JNI 调用 Java API**,性能最优,代码完全跨平台兼容 + +**Windows 平台架构:** +``` +C++ 核心层 (纯 C++) + ↑↓ 直接调用 +C++ 平台适配层 (DirectX, IddCx, Win32) + ↑↓ +Windows 系统 API +``` + +## 2. Android 平台实现原理 + +### 2.1 屏幕捕获(Host 角色) + +#### 使用 Android NDK Native API(纯 C++ 实现) + +Android 平台使用 **Android NDK Native API** 进行屏幕捕获,完全在 C++ 层实现,无需 JNI 调用 Java API。 + +**使用的 NDK API:** +- `AImageReader` - 获取屏幕帧(Android API 24+) +- `ANativeWindow` - 窗口和 Surface 操作 +- `AHardwareBuffer` - 硬件缓冲区访问(Android API 26+) +- `AMediaCodec` - 硬件视频编码(见 2.2 节) + +**实现流程:** + +1. **创建 AImageReader(纯 C++)** + ```cpp + // platforms/android/src/capture/screen_capture.cpp + #include + #include + + class ScreenCapture { + public: + bool Initialize(int width, int height) { + // 创建 AImageReader + AImageReader* imageReader = nullptr; + media_status_t status = AImageReader_new( + width, height, + AIMAGE_FORMAT_PRIVATE, // 硬件支持的格式,零拷贝 + 2, // maxImages + &imageReader + ); + + if (status != AMEDIA_OK) { + return false; + } + + imageReader_ = imageReader; + + // 设置图像可用回调 + AImageReader_ImageListener listener = { + .context = this, + .onImageAvailable = OnImageAvailable + }; + AImageReader_setImageListener(imageReader_, &listener); + + // 获取 ANativeWindow(用于 VirtualDisplay) + ANativeWindow* window = nullptr; + status = AImageReader_getWindow(imageReader_, &window); + if (status != AMEDIA_OK) { + return false; + } + + nativeWindow_ = window; + return true; + } + + // 图像可用回调(由系统调用) + static void OnImageAvailable(void* context, AImageReader* reader) { + auto* capture = static_cast(context); + capture->ProcessFrame(reader); + } + + private: + void ProcessFrame(AImageReader* reader) { + AImage* image = nullptr; + media_status_t status = AImageReader_acquireLatestImage(reader, &image); + + if (status == AMEDIA_OK && image != nullptr) { + // 获取 AHardwareBuffer(零拷贝访问) + AHardwareBuffer* buffer = nullptr; + status = AImage_getHardwareBuffer(image, &buffer); + + if (status == AMEDIA_OK && buffer != nullptr) { + // 直接传递给编码器,无需 CPU 拷贝 + OnFrameAvailable(buffer); + } + + // 释放图像 + AImage_delete(image); + } + } + + AImageReader* imageReader_ = nullptr; + ANativeWindow* nativeWindow_ = nullptr; + }; + ``` + +2. **创建 VirtualDisplay(需要 MediaProjection token)** + + 注意:VirtualDisplay 的创建需要 MediaProjection 权限。有两种方案: + + **方案 A:最小 Java 层(仅权限请求)** + ```cpp + // 通过 JNI 获取 MediaProjection token(一次性操作) + // 然后使用 native API 创建 VirtualDisplay + + // 获取 MediaProjection token 后,转换为 native handle + jobject mediaProjectionToken = GetMediaProjectionToken(); // JNI 调用(仅一次) + + // 使用 native API 创建 VirtualDisplay + // 注意:Android NDK 没有直接提供 VirtualDisplay API + // 需要通过系统服务或使用 AImageReader + Surface + ``` + + **方案 B:使用系统服务(完全 native)** + ```cpp + // 通过 Android 系统服务直接创建 VirtualDisplay + // 使用 AIDL 接口或直接调用系统服务 + // 这需要系统权限或 root 权限 + ``` + +3. **零拷贝帧获取** + ```cpp + // 使用 AHardwareBuffer 直接访问 GPU 缓冲区 + void ProcessHardwareBuffer(AHardwareBuffer* buffer) { + // 获取缓冲区描述 + AHardwareBuffer_Desc desc; + AHardwareBuffer_describe(buffer, &desc); + + // 直接传递给编码器的 Surface + // 编码器可以直接从 GPU 缓冲区读取,无需 CPU 拷贝 + ANativeWindow* encoderSurface = GetEncoderInputSurface(); + + // 将硬件缓冲区内容复制到编码器 Surface + // 这仍然在 GPU 上完成,零拷贝 + CopyHardwareBufferToSurface(buffer, encoderSurface); + } + ``` + +**技术要点:** +- **完全 native 实现**,无 JNI 开销 +- 使用 `AIMAGE_FORMAT_PRIVATE` 格式,直接传递给硬件编码器,零拷贝 +- 通过 `AHardwareBuffer` 直接访问 GPU 缓冲区 +- 异步回调机制,不阻塞主线程 +- 支持动态分辨率调整 + +**权限处理:** +- MediaProjection 权限请求需要用户交互(一次性) +- 可以通过最小 Java Activity 或系统服务实现 +- 权限获取后,所有后续操作完全在 native 层 + +### 2.2 视频编码 + +#### AMediaCodec 硬件编码(纯 C++ Native API) + +Android 使用 **AMediaCodec**(Android NDK Native API)进行硬件加速编码,完全在 C++ 层实现,支持 H.264 编码。 + +**编码流程:** + +1. **创建编码器(纯 C++)** + ```cpp + // platforms/android/src/codec/android_h264_encoder.cpp + #include + #include + #include + + class AndroidH264Encoder { + public: + bool Initialize(int width, int height, int bitrate, int fps) { + // 创建编码器(使用 native API) + const char* mimeType = "video/avc"; + encoder_ = AMediaCodec_createEncoderByType(mimeType); + + if (!encoder_) { + return false; + } + + // 创建 MediaFormat + AMediaFormat* format = AMediaFormat_new(); + AMediaFormat_setString(format, AMEDIAFORMAT_KEY_MIME, mimeType); + AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_WIDTH, width); + AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_HEIGHT, height); + + // COLOR_FormatSurface - 使用 Surface 作为输入 + AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_COLOR_FORMAT, 0x7f000789); + AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, bitrate); + AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_FRAME_RATE, fps); + AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_I_FRAME_INTERVAL, 1); + + // 配置编码器 + media_status_t status = AMediaCodec_configure( + encoder_, + format, + nullptr, // surface (输入 Surface) + nullptr, // crypto + AMEDIACODEC_CONFIGURE_FLAG_ENCODE + ); + + AMediaFormat_delete(format); + + if (status != AMEDIA_OK) { + return false; + } + + // 获取输入 Surface(用于接收屏幕帧) + status = AMediaCodec_createInputSurface(encoder_, &inputSurface_); + if (status != AMEDIA_OK) { + return false; + } + + // 启动编码器 + status = AMediaCodec_start(encoder_); + return status == AMEDIA_OK; + } + + ANativeWindow* GetInputSurface() const { + return inputSurface_; + } + + private: + AMediaCodec* encoder_ = nullptr; + ANativeWindow* inputSurface_ = nullptr; + }; + ``` + +2. **输入 Surface 连接(零拷贝)** + ```cpp + // 将 AImageReader 的 Surface 直接连接到编码器 + // 实现零拷贝:GPU -> 编码器 + void ConnectSurfaces(ANativeWindow* imageReaderSurface, ANativeWindow* encoderSurface) { + // 在创建 VirtualDisplay 时,直接使用编码器的 Surface + // 这样屏幕内容直接输出到编码器,无需中间拷贝 + + // 或者使用 EGL 将 AImageReader 的输出复制到编码器 Surface + // 这仍然在 GPU 上完成,零拷贝 + } + ``` + +3. **获取编码数据(纯 C++)** + ```cpp + bool GetEncodedFrame(std::vector& outputData, int& flags) { + // 出队输出缓冲区 + ssize_t outputBufferId = AMediaCodec_dequeueOutputBuffer( + encoder_, + &bufferInfo_, + 10000 // timeoutUs: 10ms + ); + + if (outputBufferId >= 0) { + // 获取输出缓冲区 + size_t outputSize = 0; + uint8_t* outputBuffer = AMediaCodec_getOutputBuffer( + encoder_, + outputBufferId, + &outputSize + ); + + if (outputBuffer && bufferInfo_.size > 0) { + // 复制编码数据 + outputData.assign( + outputBuffer + bufferInfo_.offset, + outputBuffer + bufferInfo_.offset + bufferInfo_.size + ); + + flags = bufferInfo_.flags; + + // 释放缓冲区 + AMediaCodec_releaseOutputBuffer(encoder_, outputBufferId, false); + + return true; + } + } else if (outputBufferId == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) { + // 输出格式改变,获取新格式 + AMediaFormat* format = AMediaCodec_getOutputFormat(encoder_); + // 处理格式变化 + AMediaFormat_delete(format); + } + + return false; + } + + private: + AMediaCodecBufferInfo bufferInfo_ = {}; + }; + ``` + +**性能优化:** +- **完全 native 实现**,无 JNI 开销 +- 零拷贝:直接从 GPU 到编码器,无需 CPU 参与 +- 使用硬件编码器,CPU 占用极低 +- 支持关键帧(I-frame)控制,减少带宽 +- 直接内存访问,性能最优 + +### 2.3 输入处理(Client 角色) + +当 Android 设备作为 Client 时,需要将接收到的输入事件注入到系统中。 + +**方案 A:使用 Linux Input 子系统(完全 native,需要 root)** + +```cpp +// platforms/android/src/input/touch_handler.cpp +// 直接操作 Linux /dev/input/eventX 设备 + +class TouchHandler { +public: + bool Initialize() { + // 查找触摸屏输入设备 + const char* inputDevice = FindTouchInputDevice(); + if (!inputDevice) { + return false; + } + + // 打开输入设备 + fd_ = open(inputDevice, O_RDWR); + return fd_ >= 0; + } + + bool InjectTouchEvent(int action, float x, float y) { + struct input_event ev[6]; + memset(ev, 0, sizeof(ev)); + + // 同步事件 + ev[0].type = EV_SYN; + ev[0].code = SYN_REPORT; + ev[0].value = 0; + + // ABS_MT_TRACKING_ID + ev[1].type = EV_ABS; + ev[1].code = ABS_MT_TRACKING_ID; + ev[1].value = (action == ACTION_DOWN) ? 0 : -1; + + // ABS_MT_POSITION_X + ev[2].type = EV_ABS; + ev[2].code = ABS_MT_POSITION_X; + ev[2].value = (int)(x * 1000); // 转换为设备坐标 + + // ABS_MT_POSITION_Y + ev[3].type = EV_ABS; + ev[3].code = ABS_MT_POSITION_Y; + ev[3].value = (int)(y * 1000); + + // ABS_MT_PRESSURE + ev[4].type = EV_ABS; + ev[4].code = ABS_MT_PRESSURE; + ev[4].value = (action == ACTION_UP) ? 0 : 100; + + // BTN_TOUCH + ev[5].type = EV_KEY; + ev[5].code = BTN_TOUCH; + ev[5].value = (action == ACTION_UP) ? 0 : 1; + + // 发送事件 + for (int i = 0; i < 6; i++) { + write(fd_, &ev[i], sizeof(struct input_event)); + } + + return true; + } + +private: + int fd_ = -1; + + const char* FindTouchInputDevice() { + // 遍历 /dev/input/eventX 查找触摸屏设备 + // 通过读取 /proc/bus/input/devices 或直接测试设备 + return "/dev/input/event2"; // 示例 + } +}; +``` + +**方案 B:使用 Android Input 服务(需要系统权限)** + +```cpp +// 通过 Android InputManagerService 注入事件 +// 需要系统权限或使用系统服务接口 +// 可以通过 AIDL 接口调用系统服务 +``` + +**方案 C:最小 JNI 层(仅输入注入)** + +如果必须使用 Java API,可以创建一个最小的 JNI 包装器: + +```cpp +// 通过 JNI 调用 InputManager 或 Instrumentation +// 但这是最后的选择,优先使用 native 方案 +``` + +**推荐方案:** +- **优先使用方案 A**(Linux Input 子系统):完全 native,性能最优 +- 需要 root 权限或系统权限 +- 对于普通应用,可能需要用户授权或使用辅助功能服务 + +**限制:** +- Linux Input 子系统需要 root 或系统权限 +- 普通应用可能需要通过辅助功能服务(AccessibilityService)实现 +- 某些设备可能需要特定的权限配置 + +### 2.4 网络通信 + +#### USB RNDIS +Android 设备通过 USB 连接时,可以启用 RNDIS(Remote Network Driver Interface Specification)功能。 + +**实现方式:** +1. 通过 USB Host API 检测 USB 连接 +2. 启用 USB 网络共享功能 +3. 获取 RNDIS 网络接口的 IP 地址 +4. 使用 UDP Socket 进行数据传输 + +#### Wi-Fi 网络 +使用标准的 Wi-Fi 网络进行通信。 + +**实现方式:** +1. 获取 Wi-Fi 网络信息 +2. 使用 UDP 多播或单播进行数据传输 +3. 支持一对多广播 + +## 3. Windows 平台实现原理 + +### 3.1 虚拟显示器创建(Client 角色) + +#### IddCx 驱动框架 +Windows 10 1809+ 提供了 IddCx(Indirect Display Driver Class eXtension)框架,用于创建虚拟显示器。 + +**实现流程:** + +1. **驱动安装** + - 开发 IddCx 驱动(.inf 文件) + - 使用 `devcon` 或 `pnputil` 安装驱动 + - 驱动注册虚拟显示器设备 + +2. **创建虚拟显示器** + ```cpp + // 通过 IOCTL 与驱动通信 + HANDLE hDevice = CreateFile( + L"\\\\.\\DisplayFlow", + GENERIC_READ | GENERIC_WRITE, + 0, NULL, OPEN_EXISTING, 0, NULL + ); + + // 发送创建显示器命令 + DISPLAYFLOW_CREATE_DISPLAY createCmd = {}; + createCmd.width = 1920; + createCmd.height = 1080; + DWORD bytesReturned; + DeviceIoControl( + hDevice, + IOCTL_DISPLAYFLOW_CREATE_DISPLAY, + &createCmd, sizeof(createCmd), + NULL, 0, + &bytesReturned, NULL + ); + ``` + +3. **驱动端处理** + ```cpp + // 在驱动中实现 IddCxMonitorCreate + NTSTATUS IddCxMonitorCreate( + IDDCX_MONITOR Monitor, + const IDARG_IN_MONITORCREATE* pInArgs, + IDARG_OUT_MONITORCREATE* pOutArgs + ) { + // 创建虚拟显示器对象 + // 注册显示模式 + // 返回成功 + } + ``` + +**技术要点:** +- IddCx 驱动运行在内核模式,性能高 +- 创建的虚拟显示器会被系统识别为真实显示器 +- 支持动态分辨率调整 +- 支持多显示器扩展 + +### 3.2 DirectX 渲染 + +#### D3D11 渲染管道 +Windows 平台使用 DirectX 11 进行高效渲染。 + +**渲染流程:** + +1. **初始化 D3D11** + ```cpp + // 创建 D3D11 设备 + D3D11CreateDevice( + nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, + D3D11_CREATE_DEVICE_VIDEO_SUPPORT, + featureLevels, ARRAYSIZE(featureLevels), + D3D11_SDK_VERSION, &device, &featureLevel, &context + ); + + // 创建交换链(连接到虚拟显示器) + DXGI_SWAP_CHAIN_DESC swapChainDesc = {}; + swapChainDesc.BufferDesc.Width = width; + swapChainDesc.BufferDesc.Height = height; + swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = 2; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.Windowed = TRUE; + swapChainDesc.OutputWindow = hwnd; // 虚拟显示器的窗口句柄 + + IDXGIFactory* factory; + CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&factory); + factory->CreateSwapChain(device, &swapChainDesc, &swapChain); + ``` + +2. **视频解码** + ```cpp + // 使用 Media Foundation 或 D3D11 Video Decoder + // 创建视频解码器 + IMFTransform* decoder = nullptr; + MFCreateVideoDecoderActivate(...); + + // 解码 H.264 数据 + decoder->ProcessInput(0, sample, 0); + decoder->ProcessOutput(0, &outputSample, &status); + ``` + +3. **渲染到纹理** + ```cpp + // 创建渲染目标纹理 + ID3D11Texture2D* renderTarget; + device->CreateTexture2D(&textureDesc, nullptr, &renderTarget); + + // 创建渲染目标视图 + ID3D11RenderTargetView* rtv; + device->CreateRenderTargetView(renderTarget, nullptr, &rtv); + + // 将解码后的帧复制到纹理 + context->CopyResource(renderTarget, decodedTexture); + + // 渲染到交换链 + context->OMSetRenderTargets(1, &rtv, nullptr); + swapChain->Present(0, 0); + ``` + +**性能优化:** +- 使用硬件视频解码(D3D11 Video Decoder) +- GPU 零拷贝:解码直接输出到 GPU 纹理 +- 双缓冲交换链,减少撕裂 +- 支持垂直同步(VSync) + +### 3.3 输入处理(Client 角色) + +Windows 作为 Client 时,需要将输入事件转发到 Host 设备。 + +**键盘事件捕获:** +```cpp +// 使用低级键盘钩子 +HHOOK hHook = SetWindowsHookEx( + WH_KEYBOARD_LL, + LowLevelKeyboardProc, + GetModuleHandle(NULL), 0 +); + +LRESULT CALLBACK LowLevelKeyboardProc( + int nCode, WPARAM wParam, LPARAM lParam +) { + KBDLLHOOKSTRUCT* kbd = (KBDLLHOOKSTRUCT*)lParam; + // 发送键盘事件到 Host + sendKeyboardEvent(kbd->vkCode, wParam == WM_KEYDOWN); + return CallNextHookEx(hHook, nCode, wParam, lParam); +} +``` + +**鼠标事件捕获:** +```cpp +// 使用低级鼠标钩子 +HHOOK hHook = SetWindowsHookEx( + WH_MOUSE_LL, + LowLevelMouseProc, + GetModuleHandle(NULL), 0 +); + +LRESULT CALLBACK LowLevelMouseProc( + int nCode, WPARAM wParam, LPARAM lParam +) { + MSLLHOOKSTRUCT* mouse = (MSLLHOOKSTRUCT*)lParam; + // 发送鼠标事件到 Host + sendMouseEvent(mouse->pt.x, mouse->pt.y, wParam); + return CallNextHookEx(hHook, nCode, wParam, lParam); +} +``` + +### 3.4 网络通信 + +#### USB RNDIS 检测 +Windows 检测 USB RNDIS 网络适配器。 + +**实现方式:** +```cpp +// 使用 WMI 查询网络适配器 +IWbemLocator* locator; +CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, + IID_IWbemLocator, (LPVOID*)&locator); + +// 查询 RNDIS 适配器 +IEnumWbemClassObject* enumerator; +locator->ExecQuery( + L"WQL", + L"SELECT * FROM Win32_NetworkAdapter WHERE Description LIKE '%RNDIS%'", + WBEM_FLAG_FORWARD_ONLY, NULL, &enumerator +); + +// 获取 IP 地址 +// 使用 GetAdaptersAddresses API +``` + +#### Wi-Fi 和以太网 +使用标准的 Windows Socket API 进行网络通信。 + +## 4. 视频流向详解 + +### 4.1 Host -> Client 完整数据流 + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ Android Host 设备 │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ [1] 屏幕捕获层 │ +│ MediaProjection -> VirtualDisplay -> ImageReader │ +│ ↓ (GPU 纹理,零拷贝) │ +│ │ +│ [2] 编码层 │ +│ MediaCodec (H.264 硬件编码) │ +│ ↓ (编码后的 H.264 NAL 单元) │ +│ │ +│ [3] 协议封装层 │ +│ FlatBuffers 序列化 │ +│ - 帧头信息(时间戳、分辨率、帧类型) │ +│ - 编码数据(NAL 单元) │ +│ ↓ (序列化的协议消息) │ +│ │ +│ [4] 网络传输层 │ +│ UDP Socket (USB RNDIS / Wi-Fi) │ +│ - 分包处理(MTU 限制) │ +│ - 重传机制(关键帧) │ +│ ↓ (UDP 数据包) │ +│ │ +└─────────────────────────────────────────────────────────────────┘ + ↓ 网络传输 + ↓ (延迟: ~1-5ms USB RNDIS, ~5-20ms Wi-Fi) +┌─────────────────────────────────────────────────────────────────┐ +│ Windows Client 设备 │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ [5] 网络接收层 │ +│ UDP Socket 接收 │ +│ - 包重组 │ +│ - 顺序保证 │ +│ ↓ (完整的协议消息) │ +│ │ +│ [6] 协议解析层 │ +│ FlatBuffers 反序列化 │ +│ - 提取帧头信息 │ +│ - 提取编码数据 │ +│ ↓ (H.264 NAL 单元) │ +│ │ +│ [7] 解码层 │ +│ D3D11 Video Decoder (硬件解码) │ +│ ↓ (GPU 纹理,零拷贝) │ +│ │ +│ [8] 渲染层 │ +│ DirectX 11 渲染 │ +│ - 纹理复制到渲染目标 │ +│ - 交换链 Present │ +│ ↓ (显示到虚拟显示器) │ +│ │ +│ [9] 显示输出 │ +│ IddCx 虚拟显示器 │ +│ - 系统识别为真实显示器 │ +│ - 支持扩展显示模式 │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### 4.2 各阶段延迟分析 + +| 阶段 | 操作 | 典型延迟 | 优化措施 | +|------|------|----------|----------| +| 1. 屏幕捕获 | MediaProjection 获取帧 | 0-2ms | 使用硬件 Surface,零拷贝 | +| 2. 编码 | H.264 硬件编码 | 2-5ms | 硬件编码器,降低码率 | +| 3. 协议封装 | FlatBuffers 序列化 | <1ms | 零拷贝序列化 | +| 4. 网络传输 | UDP 传输 | 1-20ms | USB RNDIS 优先,优化网络 | +| 5. 网络接收 | UDP 接收 | <1ms | 高效 Socket 处理 | +| 6. 协议解析 | FlatBuffers 反序列化 | <1ms | 零拷贝反序列化 | +| 7. 解码 | H.264 硬件解码 | 2-5ms | D3D11 Video Decoder | +| 8. 渲染 | DirectX 渲染 | 1-2ms | GPU 渲染,双缓冲 | +| 9. 显示 | 虚拟显示器输出 | 0-1ms | IddCx 驱动优化 | +| **总计** | **端到端延迟** | **<30ms** | **(USB RNDIS 模式)** | + +### 4.3 关键帧(I-frame)处理 + +为了减少带宽和延迟,系统采用以下策略: + +1. **关键帧间隔** + - 默认每 30 帧发送一个 I-frame + - 可根据网络状况动态调整 + +2. **场景变化检测** + - 检测画面变化幅度 + - 变化大时立即发送 I-frame + +3. **网络重传** + - I-frame 丢失时请求重传 + - P-frame 丢失时等待下一个 I-frame + +### 4.4 自适应码率控制 + +系统根据网络状况动态调整编码参数: + +1. **带宽检测** + - 监控网络延迟和丢包率 + - 估算可用带宽 + +2. **码率调整** + - 高带宽:提高码率,提升画质 + - 低带宽:降低码率,保证流畅 + +3. **分辨率调整** + - 极端情况下降低分辨率 + - 保持帧率稳定 + +## 5. 输入事件流向(Client -> Host) + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ Windows Client 设备 │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ [1] 输入捕获 │ +│ - 键盘钩子 (WH_KEYBOARD_LL) │ +│ - 鼠标钩子 (WH_MOUSE_LL) │ +│ ↓ (输入事件数据) │ +│ │ +│ [2] 事件封装 │ +│ FlatBuffers 序列化 │ +│ - 事件类型(按键、鼠标移动、点击) │ +│ - 坐标、按键码等 │ +│ ↓ (序列化的输入事件) │ +│ │ +│ [3] 网络发送 │ +│ UDP Socket 发送 │ +│ ↓ (UDP 数据包) │ +│ │ +└─────────────────────────────────────────────────────────────────┘ + ↓ 网络传输 +┌─────────────────────────────────────────────────────────────────┐ +│ Android Host 设备 │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ [4] 网络接收 │ +│ UDP Socket 接收 │ +│ ↓ (输入事件数据) │ +│ │ +│ [5] 事件解析 │ +│ FlatBuffers 反序列化 │ +│ ↓ (输入事件对象) │ +│ │ +│ [6] 事件注入 │ +│ - 通过 JNI 调用 Instrumentation.sendPointerSync() (触摸) │ +│ - 或通过辅助功能服务(AccessibilityService) │ +│ ↓ (系统输入事件) │ +│ │ +│ [7] 系统处理 │ +│ Android 系统处理输入事件 │ +│ - 触发应用响应 │ +│ - 更新屏幕内容 │ +│ ↓ (屏幕变化) │ +│ │ +│ [8] 屏幕捕获 │ +│ 回到视频流向的步骤 1 │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +**输入延迟:** +- 捕获延迟:<1ms +- 网络传输:1-20ms(取决于连接方式) +- 事件注入:<1ms +- **总延迟:<25ms**(USB RNDIS 模式) + +## 6. 性能优化策略 + +### 6.1 零拷贝优化 + +1. **Android 端** + - GPU 纹理直接传递给编码器 + - 编码输出直接写入网络缓冲区 + +2. **Windows 端** + - 解码直接输出到 GPU 纹理 + - 纹理直接用于渲染,无需 CPU 拷贝 + +### 6.2 多线程处理 + +1. **捕获线程**:专门处理屏幕捕获 +2. **编码线程**:处理视频编码 +3. **网络线程**:处理网络 I/O +4. **渲染线程**:处理视频解码和渲染 + +### 6.3 缓冲策略 + +1. **发送端缓冲** + - 最小化缓冲,降低延迟 + - 关键帧缓冲,支持重传 + +2. **接收端缓冲** + - 小缓冲,快速响应 + - 丢帧策略:网络差时丢弃旧帧 + +## 7. 错误处理与恢复 + +### 7.1 网络错误 + +- **连接断开**:自动重连机制 +- **数据包丢失**:关键帧重传 +- **网络切换**:自动检测并切换网络接口 + +### 7.2 编解码错误 + +- **编码失败**:降级到软件编码 +- **解码失败**:请求关键帧重传 + +### 7.3 系统错误 + +- **权限丢失**:提示用户重新授权 +- **资源不足**:降低码率或分辨率 + +## 8. 总结 + +DisplayFlow 通过以下技术实现低延迟、高质量的跨平台显示协作: + +1. **硬件加速**:充分利用 GPU 和硬件编解码器 +2. **零拷贝**:最小化数据拷贝,降低延迟 +3. **高效协议**:FlatBuffers 零拷贝序列化 +4. **智能网络**:自动选择最佳网络路径 +5. **自适应优化**:根据网络状况动态调整参数 + +通过这些优化,系统在 USB RNDIS 模式下可实现 **<30ms 的端到端延迟**,满足实时显示协作的需求。 + diff --git a/platforms/android/CMakeLists.txt b/platforms/android/CMakeLists.txt new file mode 100644 index 0000000..ddf29f4 --- /dev/null +++ b/platforms/android/CMakeLists.txt @@ -0,0 +1,57 @@ +# Android 平台适配层 CMakeLists.txt +cmake_minimum_required(VERSION 3.15) + +if(NOT ANDROID) + message(FATAL_ERROR "Android platform can only be built for Android") +endif() + +# Android 平台源文件 +set(ANDROID_SOURCES + src/capture/screen_capture.cpp + src/capture/media_projection_wrapper.cpp + src/capture/camera_capture.cpp + src/render/render_engine.cpp + src/input/touch_handler.cpp + src/network/android_network_manager.cpp + src/platform_adapter.cpp +) + +# Android 平台头文件 +set(ANDROID_HEADERS + include/displayflow/platform/android/capture/screen_capture.h + include/displayflow/platform/android/capture/media_projection_wrapper.h + include/displayflow/platform/android/capture/camera_capture.h + include/displayflow/platform/android/render/render_engine.h + include/displayflow/platform/android/input/touch_handler.h + include/displayflow/platform/android/network/android_network_manager.h + include/displayflow/platform/android/platform_adapter.h +) + +# 创建 Android 平台库 +add_library(displayflow_android STATIC + ${ANDROID_SOURCES} + ${ANDROID_HEADERS} +) + +# 包含目录 +target_include_directories(displayflow_android PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_CURRENT_SOURCE_DIR}/../../core/include +) + +# 链接核心库 +target_link_libraries(displayflow_android PUBLIC + displayflow_core +) + +# Android 特定库 +find_library(log-lib log) +find_library(android-lib android) +find_library(mediandk-lib mediandk) + +target_link_libraries(displayflow_android + ${log-lib} + ${android-lib} + ${mediandk-lib} +) + diff --git a/platforms/android/include/displayflow/platform/android/capture/camera_capture.h b/platforms/android/include/displayflow/platform/android/capture/camera_capture.h new file mode 100644 index 0000000..988a92c --- /dev/null +++ b/platforms/android/include/displayflow/platform/android/capture/camera_capture.h @@ -0,0 +1,85 @@ +#pragma once + +#include "displayflow/core/common/types.h" +#include +#include +#include + +namespace displayflow { +namespace platform { +namespace android { + +// 前向声明 +struct VideoFrame; + +/** + * @brief 摄像头信息 + */ +struct CameraInfo { + std::string cameraId; + std::string name; + bool isFrontFacing; + Resolution maxResolution; + std::vector supportedResolutions; +}; + +/** + * @brief 摄像头捕获 + * + * 使用 Android NDK Camera API 或 Camera2 API 进行摄像头捕获 + */ +class CameraCapture { +public: + CameraCapture(); + ~CameraCapture(); + + /** + * @brief 初始化摄像头捕获 + */ + bool Initialize(); + + /** + * @brief 枚举可用的摄像头设备 + */ + std::vector EnumerateCameras(); + + /** + * @brief 打开指定摄像头 + */ + bool OpenCamera(const std::string& cameraId); + + /** + * @brief 开始捕获 + */ + bool StartCapture(const Resolution& resolution, int fps); + + /** + * @brief 停止捕获 + */ + void StopCapture(); + + /** + * @brief 关闭摄像头 + */ + void CloseCamera(); + + /** + * @brief 设置帧回调 + */ + void SetFrameCallback(std::function callback); + + /** + * @brief 设置摄像头参数 + */ + bool SetFocusMode(const std::string& mode); // "auto", "continuous", "fixed" + bool SetExposureMode(const std::string& mode); + bool SetWhiteBalanceMode(const std::string& mode); + +private: + // TODO: 添加私有成员 +}; + +} // namespace android +} // namespace platform +} // namespace displayflow + diff --git a/platforms/android/include/displayflow/platform/android/capture/media_projection_wrapper.h b/platforms/android/include/displayflow/platform/android/capture/media_projection_wrapper.h new file mode 100644 index 0000000..d31c643 --- /dev/null +++ b/platforms/android/include/displayflow/platform/android/capture/media_projection_wrapper.h @@ -0,0 +1,22 @@ +#pragma once + +namespace displayflow { +namespace platform { +namespace android { + +/** + * @brief MediaProjection API 封装 + */ +class MediaProjectionWrapper { +public: + MediaProjectionWrapper(); + ~MediaProjectionWrapper(); + +private: + // TODO: 添加私有成员 +}; + +} // namespace android +} // namespace platform +} // namespace displayflow + diff --git a/platforms/android/include/displayflow/platform/android/capture/screen_capture.h b/platforms/android/include/displayflow/platform/android/capture/screen_capture.h new file mode 100644 index 0000000..59c0d2d --- /dev/null +++ b/platforms/android/include/displayflow/platform/android/capture/screen_capture.h @@ -0,0 +1,26 @@ +#pragma once + +namespace displayflow { +namespace platform { +namespace android { + +/** + * @brief Android 屏幕捕获 + */ +class ScreenCapture { +public: + ScreenCapture(); + ~ScreenCapture(); + + bool Initialize(); + bool StartCapture(); + void StopCapture(); + +private: + // TODO: 添加私有成员 +}; + +} // namespace android +} // namespace platform +} // namespace displayflow + diff --git a/platforms/android/include/displayflow/platform/android/input/touch_handler.h b/platforms/android/include/displayflow/platform/android/input/touch_handler.h new file mode 100644 index 0000000..e7cef08 --- /dev/null +++ b/platforms/android/include/displayflow/platform/android/input/touch_handler.h @@ -0,0 +1,22 @@ +#pragma once + +namespace displayflow { +namespace platform { +namespace android { + +/** + * @brief Android 触摸输入处理 + */ +class TouchHandler { +public: + TouchHandler(); + ~TouchHandler(); + +private: + // TODO: 添加私有成员 +}; + +} // namespace android +} // namespace platform +} // namespace displayflow + diff --git a/platforms/android/include/displayflow/platform/android/network/android_network_manager.h b/platforms/android/include/displayflow/platform/android/network/android_network_manager.h new file mode 100644 index 0000000..68a6bd2 --- /dev/null +++ b/platforms/android/include/displayflow/platform/android/network/android_network_manager.h @@ -0,0 +1,22 @@ +#pragma once + +namespace displayflow { +namespace platform { +namespace android { + +/** + * @brief Android 网络管理器 + */ +class AndroidNetworkManager { +public: + AndroidNetworkManager(); + ~AndroidNetworkManager(); + +private: + // TODO: 添加私有成员 +}; + +} // namespace android +} // namespace platform +} // namespace displayflow + diff --git a/platforms/android/include/displayflow/platform/android/platform_adapter.h b/platforms/android/include/displayflow/platform/android/platform_adapter.h new file mode 100644 index 0000000..07f5edf --- /dev/null +++ b/platforms/android/include/displayflow/platform/android/platform_adapter.h @@ -0,0 +1,41 @@ +#pragma once + +#include "displayflow/core/common/types.h" + +namespace displayflow { +namespace platform { +namespace android { + +/** + * @brief Android 平台适配器 + * + * 封装 Android 平台特定的功能 + */ +class AndroidPlatformAdapter { +public: + AndroidPlatformAdapter(); + ~AndroidPlatformAdapter(); + + /** + * @brief 初始化平台适配器 + */ + bool Initialize(); + + /** + * @brief 启动屏幕捕获 + */ + bool StartScreenCapture(); + + /** + * @brief 停止屏幕捕获 + */ + void StopScreenCapture(); + +private: + // TODO: 添加私有成员 +}; + +} // namespace android +} // namespace platform +} // namespace displayflow + diff --git a/platforms/android/include/displayflow/platform/android/render/render_engine.h b/platforms/android/include/displayflow/platform/android/render/render_engine.h new file mode 100644 index 0000000..2a2d61d --- /dev/null +++ b/platforms/android/include/displayflow/platform/android/render/render_engine.h @@ -0,0 +1,22 @@ +#pragma once + +namespace displayflow { +namespace platform { +namespace android { + +/** + * @brief Android 渲染引擎 + */ +class RenderEngine { +public: + RenderEngine(); + ~RenderEngine(); + +private: + // TODO: 添加私有成员 +}; + +} // namespace android +} // namespace platform +} // namespace displayflow + diff --git a/platforms/android/src/capture/camera_capture.cpp b/platforms/android/src/capture/camera_capture.cpp new file mode 100644 index 0000000..e914b04 --- /dev/null +++ b/platforms/android/src/capture/camera_capture.cpp @@ -0,0 +1,65 @@ +#include "displayflow/platform/android/capture/camera_capture.h" + +namespace displayflow { +namespace platform { +namespace android { + +CameraCapture::CameraCapture() { + // TODO: 实现构造函数 +} + +CameraCapture::~CameraCapture() { + // TODO: 实现析构函数 +} + +bool CameraCapture::Initialize() { + // TODO: 实现初始化逻辑 + return false; +} + +std::vector CameraCapture::EnumerateCameras() { + // TODO: 实现枚举摄像头逻辑 + return {}; +} + +bool CameraCapture::OpenCamera(const std::string& cameraId) { + // TODO: 实现打开摄像头逻辑 + return false; +} + +bool CameraCapture::StartCapture(const Resolution& resolution, int fps) { + // TODO: 实现开始捕获逻辑 + return false; +} + +void CameraCapture::StopCapture() { + // TODO: 实现停止捕获逻辑 +} + +void CameraCapture::CloseCamera() { + // TODO: 实现关闭摄像头逻辑 +} + +void CameraCapture::SetFrameCallback(std::function callback) { + // TODO: 实现设置回调逻辑 +} + +bool CameraCapture::SetFocusMode(const std::string& mode) { + // TODO: 实现设置对焦模式逻辑 + return false; +} + +bool CameraCapture::SetExposureMode(const std::string& mode) { + // TODO: 实现设置曝光模式逻辑 + return false; +} + +bool CameraCapture::SetWhiteBalanceMode(const std::string& mode) { + // TODO: 实现设置白平衡模式逻辑 + return false; +} + +} // namespace android +} // namespace platform +} // namespace displayflow + diff --git a/platforms/android/src/capture/media_projection_wrapper.cpp b/platforms/android/src/capture/media_projection_wrapper.cpp new file mode 100644 index 0000000..75edc2d --- /dev/null +++ b/platforms/android/src/capture/media_projection_wrapper.cpp @@ -0,0 +1,18 @@ +#include "displayflow/platform/android/capture/media_projection_wrapper.h" + +namespace displayflow { +namespace platform { +namespace android { + +MediaProjectionWrapper::MediaProjectionWrapper() { + // TODO: 实现构造函数 +} + +MediaProjectionWrapper::~MediaProjectionWrapper() { + // TODO: 实现析构函数 +} + +} // namespace android +} // namespace platform +} // namespace displayflow + diff --git a/platforms/android/src/capture/screen_capture.cpp b/platforms/android/src/capture/screen_capture.cpp new file mode 100644 index 0000000..26489a6 --- /dev/null +++ b/platforms/android/src/capture/screen_capture.cpp @@ -0,0 +1,32 @@ +#include "displayflow/platform/android/capture/screen_capture.h" + +namespace displayflow { +namespace platform { +namespace android { + +ScreenCapture::ScreenCapture() { + // TODO: 实现构造函数 +} + +ScreenCapture::~ScreenCapture() { + // TODO: 实现析构函数 +} + +bool ScreenCapture::Initialize() { + // TODO: 实现初始化逻辑 + return false; +} + +bool ScreenCapture::StartCapture() { + // TODO: 实现开始捕获逻辑 + return false; +} + +void ScreenCapture::StopCapture() { + // TODO: 实现停止捕获逻辑 +} + +} // namespace android +} // namespace platform +} // namespace displayflow + diff --git a/platforms/android/src/input/touch_handler.cpp b/platforms/android/src/input/touch_handler.cpp new file mode 100644 index 0000000..d35a6c0 --- /dev/null +++ b/platforms/android/src/input/touch_handler.cpp @@ -0,0 +1,18 @@ +#include "displayflow/platform/android/input/touch_handler.h" + +namespace displayflow { +namespace platform { +namespace android { + +TouchHandler::TouchHandler() { + // TODO: 实现构造函数 +} + +TouchHandler::~TouchHandler() { + // TODO: 实现析构函数 +} + +} // namespace android +} // namespace platform +} // namespace displayflow + diff --git a/platforms/android/src/network/android_network_manager.cpp b/platforms/android/src/network/android_network_manager.cpp new file mode 100644 index 0000000..2c53e52 --- /dev/null +++ b/platforms/android/src/network/android_network_manager.cpp @@ -0,0 +1,18 @@ +#include "displayflow/platform/android/network/android_network_manager.h" + +namespace displayflow { +namespace platform { +namespace android { + +AndroidNetworkManager::AndroidNetworkManager() { + // TODO: 实现构造函数 +} + +AndroidNetworkManager::~AndroidNetworkManager() { + // TODO: 实现析构函数 +} + +} // namespace android +} // namespace platform +} // namespace displayflow + diff --git a/platforms/android/src/platform_adapter.cpp b/platforms/android/src/platform_adapter.cpp new file mode 100644 index 0000000..9420aad --- /dev/null +++ b/platforms/android/src/platform_adapter.cpp @@ -0,0 +1,32 @@ +#include "displayflow/platform/android/platform_adapter.h" + +namespace displayflow { +namespace platform { +namespace android { + +AndroidPlatformAdapter::AndroidPlatformAdapter() { + // TODO: 实现构造函数 +} + +AndroidPlatformAdapter::~AndroidPlatformAdapter() { + // TODO: 实现析构函数 +} + +bool AndroidPlatformAdapter::Initialize() { + // TODO: 实现初始化逻辑 + return false; +} + +bool AndroidPlatformAdapter::StartScreenCapture() { + // TODO: 实现屏幕捕获启动 + return false; +} + +void AndroidPlatformAdapter::StopScreenCapture() { + // TODO: 实现屏幕捕获停止 +} + +} // namespace android +} // namespace platform +} // namespace displayflow + diff --git a/platforms/android/src/render/render_engine.cpp b/platforms/android/src/render/render_engine.cpp new file mode 100644 index 0000000..bd00338 --- /dev/null +++ b/platforms/android/src/render/render_engine.cpp @@ -0,0 +1,18 @@ +#include "displayflow/platform/android/render/render_engine.h" + +namespace displayflow { +namespace platform { +namespace android { + +RenderEngine::RenderEngine() { + // TODO: 实现构造函数 +} + +RenderEngine::~RenderEngine() { + // TODO: 实现析构函数 +} + +} // namespace android +} // namespace platform +} // namespace displayflow + diff --git a/platforms/windows/CMakeLists.txt b/platforms/windows/CMakeLists.txt new file mode 100644 index 0000000..21de04b --- /dev/null +++ b/platforms/windows/CMakeLists.txt @@ -0,0 +1,67 @@ +# Windows 平台适配层 CMakeLists.txt +cmake_minimum_required(VERSION 3.15) + +if(NOT WIN32) + message(FATAL_ERROR "Windows platform can only be built for Windows") +endif() + +# Windows 平台源文件 +set(WINDOWS_SOURCES + src/virtual_display/virtual_display.cpp + src/virtual_display/iddcx_wrapper.cpp + src/capture/camera_capture.cpp + src/render/directx_renderer.cpp + src/render/d3d11_renderer.cpp + src/input/keyboard_handler.cpp + src/input/mouse_handler.cpp + src/network/windows_network_manager.cpp + src/platform_adapter.cpp +) + +# Windows 平台头文件 +set(WINDOWS_HEADERS + include/displayflow/platform/windows/virtual_display/virtual_display.h + include/displayflow/platform/windows/virtual_display/iddcx_wrapper.h + include/displayflow/platform/windows/capture/camera_capture.h + include/displayflow/platform/windows/render/directx_renderer.h + include/displayflow/platform/windows/render/d3d11_renderer.h + include/displayflow/platform/windows/input/keyboard_handler.h + include/displayflow/platform/windows/input/mouse_handler.h + include/displayflow/platform/windows/network/windows_network_manager.h + include/displayflow/platform/windows/platform_adapter.h +) + +# 创建 Windows 平台库 +add_library(displayflow_windows STATIC + ${WINDOWS_SOURCES} + ${WINDOWS_HEADERS} +) + +# 包含目录 +target_include_directories(displayflow_windows PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_CURRENT_SOURCE_DIR}/../../core/include +) + +# 链接核心库 +target_link_libraries(displayflow_windows PUBLIC + displayflow_core +) + +# Windows 特定库 +target_link_libraries(displayflow_windows + dxgi + d3d11 + d3dcompiler + winmm + ws2_32 +) + +# Windows SDK +if(CMAKE_SYSTEM_VERSION) + target_compile_definitions(displayflow_windows PRIVATE + _WIN32_WINNT=0x0A00 # Windows 10 + WINVER=0x0A00 + ) +endif() + diff --git a/platforms/windows/include/displayflow/platform/windows/capture/camera_capture.h b/platforms/windows/include/displayflow/platform/windows/capture/camera_capture.h new file mode 100644 index 0000000..c8b584b --- /dev/null +++ b/platforms/windows/include/displayflow/platform/windows/capture/camera_capture.h @@ -0,0 +1,85 @@ +#pragma once + +#include "displayflow/core/common/types.h" +#include +#include +#include + +namespace displayflow { +namespace platform { +namespace windows { + +// 前向声明 +struct VideoFrame; + +/** + * @brief 摄像头信息 + */ +struct CameraInfo { + std::string deviceId; + std::string name; + std::string friendlyName; + Resolution maxResolution; + std::vector supportedResolutions; +}; + +/** + * @brief 摄像头捕获 + * + * 使用 DirectShow 或 Media Foundation 进行摄像头捕获 + */ +class CameraCapture { +public: + CameraCapture(); + ~CameraCapture(); + + /** + * @brief 初始化摄像头捕获 + */ + bool Initialize(); + + /** + * @brief 枚举可用的摄像头设备 + */ + std::vector EnumerateCameras(); + + /** + * @brief 打开指定摄像头 + */ + bool OpenCamera(const std::string& deviceId); + + /** + * @brief 开始捕获 + */ + bool StartCapture(const Resolution& resolution, int fps); + + /** + * @brief 停止捕获 + */ + void StopCapture(); + + /** + * @brief 关闭摄像头 + */ + void CloseCamera(); + + /** + * @brief 设置帧回调 + */ + void SetFrameCallback(std::function callback); + + /** + * @brief 设置摄像头参数 + */ + bool SetFocus(int value); // 0-100 + bool SetExposure(int value); + bool SetWhiteBalance(int value); + +private: + // TODO: 添加私有成员 +}; + +} // namespace windows +} // namespace platform +} // namespace displayflow + diff --git a/platforms/windows/include/displayflow/platform/windows/input/keyboard_handler.h b/platforms/windows/include/displayflow/platform/windows/input/keyboard_handler.h new file mode 100644 index 0000000..b295e83 --- /dev/null +++ b/platforms/windows/include/displayflow/platform/windows/input/keyboard_handler.h @@ -0,0 +1,22 @@ +#pragma once + +namespace displayflow { +namespace platform { +namespace windows { + +/** + * @brief Windows 键盘输入处理 + */ +class KeyboardHandler { +public: + KeyboardHandler(); + ~KeyboardHandler(); + +private: + // TODO: 添加私有成员 +}; + +} // namespace windows +} // namespace platform +} // namespace displayflow + diff --git a/platforms/windows/include/displayflow/platform/windows/input/mouse_handler.h b/platforms/windows/include/displayflow/platform/windows/input/mouse_handler.h new file mode 100644 index 0000000..55eee8a --- /dev/null +++ b/platforms/windows/include/displayflow/platform/windows/input/mouse_handler.h @@ -0,0 +1,22 @@ +#pragma once + +namespace displayflow { +namespace platform { +namespace windows { + +/** + * @brief Windows 鼠标输入处理 + */ +class MouseHandler { +public: + MouseHandler(); + ~MouseHandler(); + +private: + // TODO: 添加私有成员 +}; + +} // namespace windows +} // namespace platform +} // namespace displayflow + diff --git a/platforms/windows/include/displayflow/platform/windows/network/windows_network_manager.h b/platforms/windows/include/displayflow/platform/windows/network/windows_network_manager.h new file mode 100644 index 0000000..8da250c --- /dev/null +++ b/platforms/windows/include/displayflow/platform/windows/network/windows_network_manager.h @@ -0,0 +1,22 @@ +#pragma once + +namespace displayflow { +namespace platform { +namespace windows { + +/** + * @brief Windows 网络管理器 + */ +class WindowsNetworkManager { +public: + WindowsNetworkManager(); + ~WindowsNetworkManager(); + +private: + // TODO: 添加私有成员 +}; + +} // namespace windows +} // namespace platform +} // namespace displayflow + diff --git a/platforms/windows/include/displayflow/platform/windows/platform_adapter.h b/platforms/windows/include/displayflow/platform/windows/platform_adapter.h new file mode 100644 index 0000000..a571435 --- /dev/null +++ b/platforms/windows/include/displayflow/platform/windows/platform_adapter.h @@ -0,0 +1,49 @@ +#pragma once + +#include "displayflow/core/common/types.h" + +namespace displayflow { +namespace platform { +namespace windows { + +// 前向声明 +struct VideoFrame; + +/** + * @brief Windows 平台适配器 + * + * 封装 Windows 平台特定的功能 + */ +class WindowsPlatformAdapter { +public: + WindowsPlatformAdapter(); + ~WindowsPlatformAdapter(); + + /** + * @brief 初始化平台适配器 + */ + bool Initialize(); + + /** + * @brief 创建虚拟显示器 + */ + bool CreateVirtualDisplay(const Resolution& resolution); + + /** + * @brief 销毁虚拟显示器 + */ + void DestroyVirtualDisplay(); + + /** + * @brief 渲染视频帧 + */ + bool RenderFrame(const VideoFrame& frame); + +private: + // TODO: 添加私有成员 +}; + +} // namespace windows +} // namespace platform +} // namespace displayflow + diff --git a/platforms/windows/include/displayflow/platform/windows/render/d3d11_renderer.h b/platforms/windows/include/displayflow/platform/windows/render/d3d11_renderer.h new file mode 100644 index 0000000..2e7d69f --- /dev/null +++ b/platforms/windows/include/displayflow/platform/windows/render/d3d11_renderer.h @@ -0,0 +1,22 @@ +#pragma once + +namespace displayflow { +namespace platform { +namespace windows { + +/** + * @brief D3D11 渲染器实现 + */ +class D3D11Renderer { +public: + D3D11Renderer(); + ~D3D11Renderer(); + +private: + // TODO: 添加私有成员 +}; + +} // namespace windows +} // namespace platform +} // namespace displayflow + diff --git a/platforms/windows/include/displayflow/platform/windows/render/directx_renderer.h b/platforms/windows/include/displayflow/platform/windows/render/directx_renderer.h new file mode 100644 index 0000000..fa65b92 --- /dev/null +++ b/platforms/windows/include/displayflow/platform/windows/render/directx_renderer.h @@ -0,0 +1,22 @@ +#pragma once + +namespace displayflow { +namespace platform { +namespace windows { + +/** + * @brief DirectX 渲染器 + */ +class DirectXRenderer { +public: + DirectXRenderer(); + ~DirectXRenderer(); + +private: + // TODO: 添加私有成员 +}; + +} // namespace windows +} // namespace platform +} // namespace displayflow + diff --git a/platforms/windows/include/displayflow/platform/windows/virtual_display/iddcx_wrapper.h b/platforms/windows/include/displayflow/platform/windows/virtual_display/iddcx_wrapper.h new file mode 100644 index 0000000..25654d8 --- /dev/null +++ b/platforms/windows/include/displayflow/platform/windows/virtual_display/iddcx_wrapper.h @@ -0,0 +1,22 @@ +#pragma once + +namespace displayflow { +namespace platform { +namespace windows { + +/** + * @brief IddCx 驱动框架封装 + */ +class IddCxWrapper { +public: + IddCxWrapper(); + ~IddCxWrapper(); + +private: + // TODO: 添加私有成员 +}; + +} // namespace windows +} // namespace platform +} // namespace displayflow + diff --git a/platforms/windows/include/displayflow/platform/windows/virtual_display/virtual_display.h b/platforms/windows/include/displayflow/platform/windows/virtual_display/virtual_display.h new file mode 100644 index 0000000..855087f --- /dev/null +++ b/platforms/windows/include/displayflow/platform/windows/virtual_display/virtual_display.h @@ -0,0 +1,22 @@ +#pragma once + +namespace displayflow { +namespace platform { +namespace windows { + +/** + * @brief Windows 虚拟显示器 + */ +class VirtualDisplay { +public: + VirtualDisplay(); + ~VirtualDisplay(); + +private: + // TODO: 添加私有成员 +}; + +} // namespace windows +} // namespace platform +} // namespace displayflow + diff --git a/platforms/windows/src/capture/camera_capture.cpp b/platforms/windows/src/capture/camera_capture.cpp new file mode 100644 index 0000000..74abe5e --- /dev/null +++ b/platforms/windows/src/capture/camera_capture.cpp @@ -0,0 +1,65 @@ +#include "displayflow/platform/windows/capture/camera_capture.h" + +namespace displayflow { +namespace platform { +namespace windows { + +CameraCapture::CameraCapture() { + // TODO: 实现构造函数 +} + +CameraCapture::~CameraCapture() { + // TODO: 实现析构函数 +} + +bool CameraCapture::Initialize() { + // TODO: 实现初始化逻辑 + return false; +} + +std::vector CameraCapture::EnumerateCameras() { + // TODO: 实现枚举摄像头逻辑 + return {}; +} + +bool CameraCapture::OpenCamera(const std::string& deviceId) { + // TODO: 实现打开摄像头逻辑 + return false; +} + +bool CameraCapture::StartCapture(const Resolution& resolution, int fps) { + // TODO: 实现开始捕获逻辑 + return false; +} + +void CameraCapture::StopCapture() { + // TODO: 实现停止捕获逻辑 +} + +void CameraCapture::CloseCamera() { + // TODO: 实现关闭摄像头逻辑 +} + +void CameraCapture::SetFrameCallback(std::function callback) { + // TODO: 实现设置回调逻辑 +} + +bool CameraCapture::SetFocus(int value) { + // TODO: 实现设置对焦逻辑 + return false; +} + +bool CameraCapture::SetExposure(int value) { + // TODO: 实现设置曝光逻辑 + return false; +} + +bool CameraCapture::SetWhiteBalance(int value) { + // TODO: 实现设置白平衡逻辑 + return false; +} + +} // namespace windows +} // namespace platform +} // namespace displayflow + diff --git a/platforms/windows/src/input/keyboard_handler.cpp b/platforms/windows/src/input/keyboard_handler.cpp new file mode 100644 index 0000000..d34ca17 --- /dev/null +++ b/platforms/windows/src/input/keyboard_handler.cpp @@ -0,0 +1,18 @@ +#include "displayflow/platform/windows/input/keyboard_handler.h" + +namespace displayflow { +namespace platform { +namespace windows { + +KeyboardHandler::KeyboardHandler() { + // TODO: 实现构造函数 +} + +KeyboardHandler::~KeyboardHandler() { + // TODO: 实现析构函数 +} + +} // namespace windows +} // namespace platform +} // namespace displayflow + diff --git a/platforms/windows/src/input/mouse_handler.cpp b/platforms/windows/src/input/mouse_handler.cpp new file mode 100644 index 0000000..2e130d1 --- /dev/null +++ b/platforms/windows/src/input/mouse_handler.cpp @@ -0,0 +1,18 @@ +#include "displayflow/platform/windows/input/mouse_handler.h" + +namespace displayflow { +namespace platform { +namespace windows { + +MouseHandler::MouseHandler() { + // TODO: 实现构造函数 +} + +MouseHandler::~MouseHandler() { + // TODO: 实现析构函数 +} + +} // namespace windows +} // namespace platform +} // namespace displayflow + diff --git a/platforms/windows/src/network/windows_network_manager.cpp b/platforms/windows/src/network/windows_network_manager.cpp new file mode 100644 index 0000000..df17651 --- /dev/null +++ b/platforms/windows/src/network/windows_network_manager.cpp @@ -0,0 +1,18 @@ +#include "displayflow/platform/windows/network/windows_network_manager.h" + +namespace displayflow { +namespace platform { +namespace windows { + +WindowsNetworkManager::WindowsNetworkManager() { + // TODO: 实现构造函数 +} + +WindowsNetworkManager::~WindowsNetworkManager() { + // TODO: 实现析构函数 +} + +} // namespace windows +} // namespace platform +} // namespace displayflow + diff --git a/platforms/windows/src/platform_adapter.cpp b/platforms/windows/src/platform_adapter.cpp new file mode 100644 index 0000000..6aeeb00 --- /dev/null +++ b/platforms/windows/src/platform_adapter.cpp @@ -0,0 +1,37 @@ +#include "displayflow/platform/windows/platform_adapter.h" + +namespace displayflow { +namespace platform { +namespace windows { + +WindowsPlatformAdapter::WindowsPlatformAdapter() { + // TODO: 实现构造函数 +} + +WindowsPlatformAdapter::~WindowsPlatformAdapter() { + // TODO: 实现析构函数 +} + +bool WindowsPlatformAdapter::Initialize() { + // TODO: 实现初始化逻辑 + return false; +} + +bool WindowsPlatformAdapter::CreateVirtualDisplay(const Resolution& resolution) { + // TODO: 实现虚拟显示器创建 + return false; +} + +void WindowsPlatformAdapter::DestroyVirtualDisplay() { + // TODO: 实现虚拟显示器销毁 +} + +bool WindowsPlatformAdapter::RenderFrame(const VideoFrame& frame) { + // TODO: 实现帧渲染 + return false; +} + +} // namespace windows +} // namespace platform +} // namespace displayflow + diff --git a/platforms/windows/src/render/d3d11_renderer.cpp b/platforms/windows/src/render/d3d11_renderer.cpp new file mode 100644 index 0000000..b11a443 --- /dev/null +++ b/platforms/windows/src/render/d3d11_renderer.cpp @@ -0,0 +1,18 @@ +#include "displayflow/platform/windows/render/d3d11_renderer.h" + +namespace displayflow { +namespace platform { +namespace windows { + +D3D11Renderer::D3D11Renderer() { + // TODO: 实现构造函数 +} + +D3D11Renderer::~D3D11Renderer() { + // TODO: 实现析构函数 +} + +} // namespace windows +} // namespace platform +} // namespace displayflow + diff --git a/platforms/windows/src/render/directx_renderer.cpp b/platforms/windows/src/render/directx_renderer.cpp new file mode 100644 index 0000000..f397f46 --- /dev/null +++ b/platforms/windows/src/render/directx_renderer.cpp @@ -0,0 +1,18 @@ +#include "displayflow/platform/windows/render/directx_renderer.h" + +namespace displayflow { +namespace platform { +namespace windows { + +DirectXRenderer::DirectXRenderer() { + // TODO: 实现构造函数 +} + +DirectXRenderer::~DirectXRenderer() { + // TODO: 实现析构函数 +} + +} // namespace windows +} // namespace platform +} // namespace displayflow + diff --git a/platforms/windows/src/virtual_display/iddcx_wrapper.cpp b/platforms/windows/src/virtual_display/iddcx_wrapper.cpp new file mode 100644 index 0000000..1b18c5e --- /dev/null +++ b/platforms/windows/src/virtual_display/iddcx_wrapper.cpp @@ -0,0 +1,18 @@ +#include "displayflow/platform/windows/virtual_display/iddcx_wrapper.h" + +namespace displayflow { +namespace platform { +namespace windows { + +IddCxWrapper::IddCxWrapper() { + // TODO: 实现构造函数 +} + +IddCxWrapper::~IddCxWrapper() { + // TODO: 实现析构函数 +} + +} // namespace windows +} // namespace platform +} // namespace displayflow + diff --git a/platforms/windows/src/virtual_display/virtual_display.cpp b/platforms/windows/src/virtual_display/virtual_display.cpp new file mode 100644 index 0000000..1760e6b --- /dev/null +++ b/platforms/windows/src/virtual_display/virtual_display.cpp @@ -0,0 +1,18 @@ +#include "displayflow/platform/windows/virtual_display/virtual_display.h" + +namespace displayflow { +namespace platform { +namespace windows { + +VirtualDisplay::VirtualDisplay() { + // TODO: 实现构造函数 +} + +VirtualDisplay::~VirtualDisplay() { + // TODO: 实现析构函数 +} + +} // namespace windows +} // namespace platform +} // namespace displayflow + diff --git a/prototypes/README.md b/prototypes/README.md new file mode 100644 index 0000000..52bd9e7 --- /dev/null +++ b/prototypes/README.md @@ -0,0 +1,17 @@ +# 原型和测试代码 + +本目录用于存放开发过程中的原型代码和测试程序。 + +## 目录结构 + +- `network_test/` - 网络功能测试 +- `codec_test/` - 编解码器测试 +- `protocol_test/` - 协议测试 +- `performance_test/` - 性能测试 + +## 使用说明 + +原型代码主要用于验证技术方案的可行性,不保证代码质量。 + +正式代码应放在对应的 `core/` 或 `platforms/` 目录下。 + diff --git a/tools/README.md b/tools/README.md new file mode 100644 index 0000000..d17bc88 --- /dev/null +++ b/tools/README.md @@ -0,0 +1,15 @@ +# 开发工具脚本 + +本目录包含各种开发辅助工具和脚本。 + +## 工具列表 + +- `setup_dependencies.sh` - 依赖安装脚本 +- `build.sh` - 构建脚本 +- `format_code.sh` - 代码格式化脚本 +- `run_tests.sh` - 测试运行脚本 + +## 使用说明 + +根据平台选择合适的脚本执行。 +