搭建代码框架并更新文档
This commit is contained in:
63
.gitignore
vendored
Normal file
63
.gitignore
vendored
Normal file
@@ -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
|
||||||
|
|
||||||
49
CMakeLists.txt
Normal file
49
CMakeLists.txt
Normal file
@@ -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()
|
||||||
|
|
||||||
321
DEVELOPMENT_PLAN.md
Normal file
321
DEVELOPMENT_PLAN.md
Normal file
@@ -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 平台适配层框架
|
||||||
|
- 简单的端到端测试
|
||||||
|
|
||||||
231
PROJECT_STRUCTURE.md
Normal file
231
PROJECT_STRUCTURE.md
Normal file
@@ -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 穿透完全透明,上层无需关心连接方式
|
||||||
|
- 完全集成到现有角色模型中
|
||||||
|
- 保持跨平台兼容性
|
||||||
|
|
||||||
35
README.md
35
README.md
@@ -29,16 +29,21 @@
|
|||||||
|
|
||||||
- **受益**:应用场景极大丰富,从简单的副屏扩展到复杂的多设备协作演示、双向画板等。
|
- **受益**:应用场景极大丰富,从简单的副屏扩展到复杂的多设备协作演示、双向画板等。
|
||||||
|
|
||||||
### 2.3 连接通用:支持RNDIS、WiFi、以太网等多种连接方式
|
### 2.3 连接通用:支持局域网和互联网连接
|
||||||
|
|
||||||
- **网络抽象层(Network Agnostic)**:设计统一的网络接口,自动选择或同时管理多种物理连接。
|
- **网络抽象层(Network Agnostic)**:设计统一的网络接口,自动选择或同时管理多种连接方式。
|
||||||
- **USB RNDIS**:优先使用,提供近似有线的高带宽、低延迟体验。
|
- **局域网连接**(优先使用):
|
||||||
- **Wi-Fi 局域网**:提供无线便利性,支持一对多广播。
|
- **USB RNDIS**:优先使用,提供近似有线的高带宽、低延迟体验。
|
||||||
- **有线以太网**:为台式机等设备提供稳定连接。
|
- **Wi-Fi 局域网**:提供无线便利性,支持一对多广播。
|
||||||
|
- **有线以太网**:为台式机等设备提供稳定连接。
|
||||||
|
- **互联网连接**(通过 NAT 穿透):
|
||||||
|
- **STUN**:NAT 类型检测和公网 IP 发现,支持公网直连。
|
||||||
|
- **TURN**:中继服务器支持,当直连失败时自动切换。
|
||||||
|
- **ICE 协议**:自动选择最佳连接路径(局域网 > 公网直连 > TURN 中继)。
|
||||||
|
|
||||||
- **技术实现**:NetworkManager负责探测可用连接,根据性能(延迟、带宽)自动优选或负载均衡。应用层无需关心底层是USB虚拟网卡还是真实网卡。
|
- **技术实现**:NetworkManager负责探测可用连接,根据性能(延迟、带宽)自动优选或负载均衡。集成 ICE 协议实现 NAT 穿透,支持局域网和互联网无缝切换。应用层无需关心底层连接方式。
|
||||||
|
|
||||||
- **受益**:用户无需手动配置网络,系统自动选择最佳路径,并提供从有线到无线的无缝切换能力。
|
- **受益**:用户无需手动配置网络,系统自动选择最佳路径。支持跨网络、跨地域的设备连接,突破局域网限制,实现真正的远程协作。
|
||||||
|
|
||||||
### 2.4 扩展性强:轻松支持新设备类型与未来场景
|
### 2.4 扩展性强:轻松支持新设备类型与未来场景
|
||||||
|
|
||||||
@@ -64,7 +69,7 @@
|
|||||||
|
|
|
|
||||||
[ 核心层 (Core Layer) ] <- 会话管理、协议、编解码、网络抽象 (100%跨平台)
|
[ 核心层 (Core Layer) ] <- 会话管理、协议、编解码、网络抽象 (100%跨平台)
|
||||||
|
|
|
|
||||||
[ 传输层 (Transport Layer) ] <- RNDIS (USB)、Wi-Fi、以太网
|
[ 传输层 (Transport Layer) ] <- 局域网(RNDIS/USB、Wi-Fi、以太网)、互联网(STUN/TURN/ICE)
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3.2 核心模块说明
|
### 3.2 核心模块说明
|
||||||
@@ -73,7 +78,7 @@
|
|||||||
- **会话管理**:创建、维护、销毁显示会话,支持一对多。
|
- **会话管理**:创建、维护、销毁显示会话,支持一对多。
|
||||||
- **通用协议**:基于Google FlatBuffers的跨平台序列化,定义视频帧、输入事件等。
|
- **通用协议**:基于Google FlatBuffers的跨平台序列化,定义视频帧、输入事件等。
|
||||||
- **编解码器**:支持H.264(硬件加速)/VP8(软件)/MJPEG等多种编解码器,自适应选择。
|
- **编解码器**:支持H.264(硬件加速)/VP8(软件)/MJPEG等多种编解码器,自适应选择。
|
||||||
- **网络抽象**:统一管理RNDIS、WiFi等连接,提供可靠UDP传输。
|
- **网络抽象**:统一管理RNDIS、WiFi等局域网连接,以及STUN/TURN/ICE互联网连接,提供可靠UDP传输。
|
||||||
|
|
||||||
2. **平台适配层(Platforms)**:各平台特有功能的薄封装。
|
2. **平台适配层(Platforms)**:各平台特有功能的薄封装。
|
||||||
- **Android**:通过MediaProjection捕获屏幕,ImageReader获取帧,处理触摸输入。
|
- **Android**:通过MediaProjection捕获屏幕,ImageReader获取帧,处理触摸输入。
|
||||||
@@ -110,6 +115,13 @@
|
|||||||
- **角色**:安卓手机作为主机(Host),安卓平板作为客户端(Client)。
|
- **角色**:安卓手机作为主机(Host),安卓平板作为客户端(Client)。
|
||||||
- **价值**:充分发挥设备特性。用户可在手机上进行私密操作(如游戏、使用特定APP),而将主画面投送至平板大屏上进行展示或共享,兼顾隐私与分享需求。这充分体现了角色的灵活性——安卓设备可根据需求,自由扮演主机或客户端的角色。
|
- **价值**:充分发挥设备特性。用户可在手机上进行私密操作(如游戏、使用特定APP),而将主画面投送至平板大屏上进行展示或共享,兼顾隐私与分享需求。这充分体现了角色的灵活性——安卓设备可根据需求,自由扮演主机或客户端的角色。
|
||||||
|
|
||||||
|
**场景五:远程协作(跨网络、跨地域)**
|
||||||
|
|
||||||
|
- **描述**:用户在家中通过互联网连接到办公室的 Windows 电脑,实现远程显示扩展。
|
||||||
|
- **角色**:办公室 Windows 电脑作为主机(Host),家中设备作为客户端(Client)。
|
||||||
|
- **连接方式**:通过 STUN/TURN 服务器实现 NAT 穿透,自动选择最佳连接路径。
|
||||||
|
- **价值**:突破局域网限制,支持跨网络、跨地域的设备连接。无论设备在哪里,只要有互联网连接,就能实现无缝显示协作。适用于远程办公、技术支持、远程演示等场景。
|
||||||
|
|
||||||
## 5. 技术规格与指标
|
## 5. 技术规格与指标
|
||||||
|
|
||||||
- **支持平台**:Android 5.0+, Windows 10/11
|
- **支持平台**:Android 5.0+, Windows 10/11
|
||||||
@@ -130,6 +142,9 @@ DisplayFlow/
|
|||||||
└── tools/ # 开发工具脚本
|
└── tools/ # 开发工具脚本
|
||||||
```
|
```
|
||||||
|
|
||||||
## 7. 总结
|
## 7. 技术栈
|
||||||
|
完全由C++实现
|
||||||
|
|
||||||
|
## 8. 总结
|
||||||
|
|
||||||
本方案通过真正跨平台的核心设计、动态角色分配和多连接方式抽象,突破了现有副屏方案的局限性。它不仅仅是一个"副屏工具",更是一个为未来多设备协作世界打造的、极具扩展性的通用显示协作平台。该架构确保了项目在性能、灵活性和可持续性上的领先优势。
|
本方案通过真正跨平台的核心设计、动态角色分配和多连接方式抽象,突破了现有副屏方案的局限性。它不仅仅是一个"副屏工具",更是一个为未来多设备协作世界打造的、极具扩展性的通用显示协作平台。该架构确保了项目在性能、灵活性和可持续性上的领先优势。
|
||||||
|
|||||||
81
README_BUILD.md
Normal file
81
README_BUILD.md
Normal file
@@ -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
|
||||||
|
```
|
||||||
|
|
||||||
81
core/CMakeLists.txt
Normal file
81
core/CMakeLists.txt
Normal file
@@ -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}
|
||||||
|
)
|
||||||
|
|
||||||
39
core/include/displayflow/core/codec/codec_interface.h
Normal file
39
core/include/displayflow/core/codec/codec_interface.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "displayflow/core/common/types.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
36
core/include/displayflow/core/codec/codec_manager.h
Normal file
36
core/include/displayflow/core/codec/codec_manager.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "displayflow/core/common/types.h"
|
||||||
|
#include "displayflow/core/codec/codec_interface.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace displayflow {
|
||||||
|
namespace core {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 编解码器管理器
|
||||||
|
*
|
||||||
|
* 负责管理和选择编解码器
|
||||||
|
*/
|
||||||
|
class CodecManager {
|
||||||
|
public:
|
||||||
|
CodecManager();
|
||||||
|
~CodecManager();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 初始化编解码器管理器
|
||||||
|
*/
|
||||||
|
bool Initialize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取指定类型的编解码器
|
||||||
|
*/
|
||||||
|
std::shared_ptr<ICodec> GetCodec(CodecType type);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// TODO: 添加私有成员
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace core
|
||||||
|
} // namespace displayflow
|
||||||
|
|
||||||
31
core/include/displayflow/core/common/constants.h
Normal file
31
core/include/displayflow/core/common/constants.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
54
core/include/displayflow/core/common/types.h
Normal file
54
core/include/displayflow/core/common/types.h
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace displayflow {
|
||||||
|
namespace core {
|
||||||
|
|
||||||
|
// 基础类型定义
|
||||||
|
using Byte = uint8_t;
|
||||||
|
using ByteArray = std::vector<Byte>;
|
||||||
|
|
||||||
|
// 角色类型
|
||||||
|
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
|
||||||
|
|
||||||
30
core/include/displayflow/core/file_transfer/file_chunk.h
Normal file
30
core/include/displayflow/core/file_transfer/file_chunk.h
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "displayflow/core/common/types.h"
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "displayflow/core/common/types.h"
|
||||||
|
#include "displayflow/core/file_transfer/file_transfer_session.h"
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
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<uint64_t, std::shared_ptr<FileTransferSession>> transfers_;
|
||||||
|
uint64_t nextTransferId_ = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace core
|
||||||
|
} // namespace displayflow
|
||||||
|
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "displayflow/core/common/types.h"
|
||||||
|
#include "displayflow/core/file_transfer/transfer_progress.h"
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
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<void(const TransferProgress&)> callback);
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint64_t id_;
|
||||||
|
TransferDirection direction_;
|
||||||
|
TransferStatus status_ = TransferStatus::Pending;
|
||||||
|
TransferProgress progress_;
|
||||||
|
std::function<void(const TransferProgress&)> progressCallback_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace core
|
||||||
|
} // namespace displayflow
|
||||||
|
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "displayflow/core/common/types.h"
|
||||||
|
#include <string>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
@@ -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 <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
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<Candidate> GatherCandidates();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置远程候选地址
|
||||||
|
*/
|
||||||
|
void SetRemoteCandidates(const std::vector<Candidate>& 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<Candidate> localCandidates_;
|
||||||
|
std::vector<Candidate> remoteCandidates_;
|
||||||
|
IceCandidatePair selectedPair_;
|
||||||
|
StunClient stunClient_;
|
||||||
|
TurnClient turnClient_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace core
|
||||||
|
} // namespace displayflow
|
||||||
|
|
||||||
@@ -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
|
||||||
|
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "displayflow/core/common/types.h"
|
||||||
|
#include "displayflow/core/network/nat_traversal/nat_type.h"
|
||||||
|
#include <string>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "displayflow/core/common/types.h"
|
||||||
|
#include "displayflow/core/network/nat_traversal/candidate.h"
|
||||||
|
#include <string>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
24
core/include/displayflow/core/network/network_interface.h
Normal file
24
core/include/displayflow/core/network/network_interface.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "displayflow/core/common/types.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
47
core/include/displayflow/core/network/network_manager.h
Normal file
47
core/include/displayflow/core/network/network_manager.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "displayflow/core/common/types.h"
|
||||||
|
#include "displayflow/core/network/network_interface.h"
|
||||||
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace displayflow {
|
||||||
|
namespace core {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 网络管理器
|
||||||
|
*
|
||||||
|
* 负责管理所有网络连接,包括 RNDIS、Wi-Fi、以太网等
|
||||||
|
*/
|
||||||
|
class NetworkManager {
|
||||||
|
public:
|
||||||
|
NetworkManager();
|
||||||
|
~NetworkManager();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 初始化网络管理器
|
||||||
|
*/
|
||||||
|
bool Initialize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取所有可用的网络接口
|
||||||
|
*/
|
||||||
|
std::vector<NetworkInterface> GetAvailableInterfaces();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 连接到指定的网络接口
|
||||||
|
*/
|
||||||
|
bool Connect(const NetworkInterface& interface);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 断开当前连接
|
||||||
|
*/
|
||||||
|
void Disconnect();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// TODO: 添加私有成员
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace core
|
||||||
|
} // namespace displayflow
|
||||||
|
|
||||||
34
core/include/displayflow/core/protocol/message_serializer.h
Normal file
34
core/include/displayflow/core/protocol/message_serializer.h
Normal file
@@ -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
|
||||||
|
|
||||||
27
core/include/displayflow/core/protocol/protocol_handler.h
Normal file
27
core/include/displayflow/core/protocol/protocol_handler.h
Normal file
@@ -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
|
||||||
|
|
||||||
29
core/include/displayflow/core/role/client_role.h
Normal file
29
core/include/displayflow/core/role/client_role.h
Normal file
@@ -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> session) override;
|
||||||
|
void Stop() override;
|
||||||
|
bool IsRunning() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool isRunning_ = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace core
|
||||||
|
} // namespace displayflow
|
||||||
|
|
||||||
29
core/include/displayflow/core/role/host_role.h
Normal file
29
core/include/displayflow/core/role/host_role.h
Normal file
@@ -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> session) override;
|
||||||
|
void Stop() override;
|
||||||
|
bool IsRunning() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool isRunning_ = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace core
|
||||||
|
} // namespace displayflow
|
||||||
|
|
||||||
29
core/include/displayflow/core/role/peer_role.h
Normal file
29
core/include/displayflow/core/role/peer_role.h
Normal file
@@ -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> session) override;
|
||||||
|
void Stop() override;
|
||||||
|
bool IsRunning() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool isRunning_ = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace core
|
||||||
|
} // namespace displayflow
|
||||||
|
|
||||||
45
core/include/displayflow/core/role/role_interface.h
Normal file
45
core/include/displayflow/core/role/role_interface.h
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "displayflow/core/common/types.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
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> session) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 停止角色
|
||||||
|
*/
|
||||||
|
virtual void Stop() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 是否正在运行
|
||||||
|
*/
|
||||||
|
virtual bool IsRunning() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace core
|
||||||
|
} // namespace displayflow
|
||||||
|
|
||||||
37
core/include/displayflow/core/role/role_manager.h
Normal file
37
core/include/displayflow/core/role/role_manager.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "displayflow/core/common/types.h"
|
||||||
|
#include "displayflow/core/role/role_interface.h"
|
||||||
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace displayflow {
|
||||||
|
namespace core {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 角色管理器
|
||||||
|
*
|
||||||
|
* 负责管理和切换设备角色
|
||||||
|
*/
|
||||||
|
class RoleManager {
|
||||||
|
public:
|
||||||
|
RoleManager();
|
||||||
|
~RoleManager();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 注册角色
|
||||||
|
*/
|
||||||
|
bool RegisterRole(RoleType type, std::shared_ptr<IRole> role);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 切换角色
|
||||||
|
*/
|
||||||
|
bool SwitchRole(SessionId sessionId, RoleType newRole);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<RoleType, std::shared_ptr<IRole>> roles_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace core
|
||||||
|
} // namespace displayflow
|
||||||
|
|
||||||
52
core/include/displayflow/core/session/session.h
Normal file
52
core/include/displayflow/core/session/session.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "displayflow/core/common/types.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
43
core/include/displayflow/core/session/session_manager.h
Normal file
43
core/include/displayflow/core/session/session_manager.h
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "displayflow/core/common/types.h"
|
||||||
|
#include "displayflow/core/session/session.h"
|
||||||
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace displayflow {
|
||||||
|
namespace core {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 会话管理器
|
||||||
|
*
|
||||||
|
* 负责创建、管理和销毁显示会话
|
||||||
|
*/
|
||||||
|
class SessionManager {
|
||||||
|
public:
|
||||||
|
SessionManager();
|
||||||
|
~SessionManager();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 创建新会话
|
||||||
|
*/
|
||||||
|
std::shared_ptr<Session> CreateSession(RoleType role);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 销毁会话
|
||||||
|
*/
|
||||||
|
void DestroySession(SessionId sessionId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取会话
|
||||||
|
*/
|
||||||
|
std::shared_ptr<Session> GetSession(SessionId sessionId);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<SessionId, std::shared_ptr<Session>> sessions_;
|
||||||
|
SessionId nextSessionId_ = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace core
|
||||||
|
} // namespace displayflow
|
||||||
|
|
||||||
31
core/include/displayflow/core/utils/logger.h
Normal file
31
core/include/displayflow/core/utils/logger.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
27
core/include/displayflow/core/utils/timer.h
Normal file
27
core/include/displayflow/core/utils/timer.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace displayflow {
|
||||||
|
namespace core {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 定时器工具
|
||||||
|
*/
|
||||||
|
class Timer {
|
||||||
|
public:
|
||||||
|
Timer();
|
||||||
|
~Timer();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取当前时间(毫秒)
|
||||||
|
*/
|
||||||
|
uint64_t GetCurrentTimeMs();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// TODO: 添加私有成员
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace core
|
||||||
|
} // namespace displayflow
|
||||||
|
|
||||||
11
core/src/codec/codec_interface.cpp
Normal file
11
core/src/codec/codec_interface.cpp
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#include "displayflow/core/codec/codec_interface.h"
|
||||||
|
|
||||||
|
namespace displayflow {
|
||||||
|
namespace core {
|
||||||
|
|
||||||
|
// ICodec 接口实现
|
||||||
|
// 目前只有头文件定义,此文件保留用于未来扩展
|
||||||
|
|
||||||
|
} // namespace core
|
||||||
|
} // namespace displayflow
|
||||||
|
|
||||||
26
core/src/codec/codec_manager.cpp
Normal file
26
core/src/codec/codec_manager.cpp
Normal file
@@ -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<ICodec> CodecManager::GetCodec(CodecType type) {
|
||||||
|
// TODO: 实现获取编解码器逻辑
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace core
|
||||||
|
} // namespace displayflow
|
||||||
|
|
||||||
47
core/src/file_transfer/file_transfer_manager.cpp
Normal file
47
core/src/file_transfer/file_transfer_manager.cpp
Normal file
@@ -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
|
||||||
|
|
||||||
45
core/src/file_transfer/file_transfer_session.cpp
Normal file
45
core/src/file_transfer/file_transfer_session.cpp
Normal file
@@ -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<void(const TransferProgress&)> callback) {
|
||||||
|
progressCallback_ = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace core
|
||||||
|
} // namespace displayflow
|
||||||
|
|
||||||
34
core/src/network/nat_traversal/candidate.cpp
Normal file
34
core/src/network/nat_traversal/candidate.cpp
Normal file
@@ -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
|
||||||
|
|
||||||
69
core/src/network/nat_traversal/ice_agent.cpp
Normal file
69
core/src/network/nat_traversal/ice_agent.cpp
Normal file
@@ -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<Candidate> IceAgent::GatherCandidates() {
|
||||||
|
// TODO: 实现收集候选地址
|
||||||
|
// 1. 收集本地网络接口地址
|
||||||
|
// 2. 通过 STUN 获取服务器反射地址
|
||||||
|
// 3. 通过 TURN 获取中继地址
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void IceAgent::SetRemoteCandidates(const std::vector<Candidate>& 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
|
||||||
|
|
||||||
32
core/src/network/nat_traversal/nat_type.cpp
Normal file
32
core/src/network/nat_traversal/nat_type.cpp
Normal file
@@ -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
|
||||||
|
|
||||||
37
core/src/network/nat_traversal/stun_client.cpp
Normal file
37
core/src/network/nat_traversal/stun_client.cpp
Normal file
@@ -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
|
||||||
|
|
||||||
47
core/src/network/nat_traversal/turn_client.cpp
Normal file
47
core/src/network/nat_traversal/turn_client.cpp
Normal file
@@ -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
|
||||||
|
|
||||||
11
core/src/network/network_interface.cpp
Normal file
11
core/src/network/network_interface.cpp
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#include "displayflow/core/network/network_interface.h"
|
||||||
|
|
||||||
|
namespace displayflow {
|
||||||
|
namespace core {
|
||||||
|
|
||||||
|
// NetworkInterface 结构体实现
|
||||||
|
// 目前只有头文件定义,此文件保留用于未来扩展
|
||||||
|
|
||||||
|
} // namespace core
|
||||||
|
} // namespace displayflow
|
||||||
|
|
||||||
35
core/src/network/network_manager.cpp
Normal file
35
core/src/network/network_manager.cpp
Normal file
@@ -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<NetworkInterface> NetworkManager::GetAvailableInterfaces() {
|
||||||
|
// TODO: 实现获取可用网络接口
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NetworkManager::Connect(const NetworkInterface& interface) {
|
||||||
|
// TODO: 实现连接逻辑
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkManager::Disconnect() {
|
||||||
|
// TODO: 实现断开连接逻辑
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace core
|
||||||
|
} // namespace displayflow
|
||||||
|
|
||||||
26
core/src/protocol/message_serializer.cpp
Normal file
26
core/src/protocol/message_serializer.cpp
Normal file
@@ -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
|
||||||
|
|
||||||
21
core/src/protocol/protocol_handler.cpp
Normal file
21
core/src/protocol/protocol_handler.cpp
Normal file
@@ -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
|
||||||
|
|
||||||
33
core/src/role/client_role.cpp
Normal file
33
core/src/role/client_role.cpp
Normal file
@@ -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> session) {
|
||||||
|
// TODO: 实现启动逻辑
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientRole::Stop() {
|
||||||
|
// TODO: 实现停止逻辑
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClientRole::IsRunning() const {
|
||||||
|
return isRunning_;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace core
|
||||||
|
} // namespace displayflow
|
||||||
|
|
||||||
33
core/src/role/host_role.cpp
Normal file
33
core/src/role/host_role.cpp
Normal file
@@ -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> session) {
|
||||||
|
// TODO: 实现启动逻辑
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HostRole::Stop() {
|
||||||
|
// TODO: 实现停止逻辑
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HostRole::IsRunning() const {
|
||||||
|
return isRunning_;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace core
|
||||||
|
} // namespace displayflow
|
||||||
|
|
||||||
33
core/src/role/peer_role.cpp
Normal file
33
core/src/role/peer_role.cpp
Normal file
@@ -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> session) {
|
||||||
|
// TODO: 实现启动逻辑(同时启动 Host 和 Client)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PeerRole::Stop() {
|
||||||
|
// TODO: 实现停止逻辑
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PeerRole::IsRunning() const {
|
||||||
|
return isRunning_;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace core
|
||||||
|
} // namespace displayflow
|
||||||
|
|
||||||
26
core/src/role/role_manager.cpp
Normal file
26
core/src/role/role_manager.cpp
Normal file
@@ -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<IRole> role) {
|
||||||
|
// TODO: 实现角色注册逻辑
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RoleManager::SwitchRole(SessionId sessionId, RoleType newRole) {
|
||||||
|
// TODO: 实现角色切换逻辑
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace core
|
||||||
|
} // namespace displayflow
|
||||||
|
|
||||||
39
core/src/session/session.cpp
Normal file
39
core/src/session/session.cpp
Normal file
@@ -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
|
||||||
|
|
||||||
30
core/src/session/session_manager.cpp
Normal file
30
core/src/session/session_manager.cpp
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#include "displayflow/core/session/session_manager.h"
|
||||||
|
|
||||||
|
namespace displayflow {
|
||||||
|
namespace core {
|
||||||
|
|
||||||
|
SessionManager::SessionManager() {
|
||||||
|
// TODO: 实现构造函数
|
||||||
|
}
|
||||||
|
|
||||||
|
SessionManager::~SessionManager() {
|
||||||
|
// TODO: 实现析构函数
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Session> SessionManager::CreateSession(RoleType role) {
|
||||||
|
// TODO: 实现会话创建逻辑
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionManager::DestroySession(SessionId sessionId) {
|
||||||
|
// TODO: 实现会话销毁逻辑
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Session> SessionManager::GetSession(SessionId sessionId) {
|
||||||
|
// TODO: 实现获取会话逻辑
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace core
|
||||||
|
} // namespace displayflow
|
||||||
|
|
||||||
22
core/src/utils/logger.cpp
Normal file
22
core/src/utils/logger.cpp
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#include "displayflow/core/utils/logger.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace displayflow {
|
||||||
|
namespace core {
|
||||||
|
|
||||||
|
Logger::Logger() {
|
||||||
|
// TODO: 实现构造函数
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger::~Logger() {
|
||||||
|
// TODO: 实现析构函数
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::Log(LogLevel level, const std::string& message) {
|
||||||
|
// TODO: 实现日志记录逻辑
|
||||||
|
std::cout << "[" << static_cast<int>(level) << "] " << message << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace core
|
||||||
|
} // namespace displayflow
|
||||||
|
|
||||||
23
core/src/utils/timer.cpp
Normal file
23
core/src/utils/timer.cpp
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#include "displayflow/core/utils/timer.h"
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
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<std::chrono::milliseconds>(duration).count();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace core
|
||||||
|
} // namespace displayflow
|
||||||
|
|
||||||
85
docs/API.md
Normal file
85
docs/API.md
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
# DisplayFlow API 文档
|
||||||
|
|
||||||
|
本文档描述 DisplayFlow 的核心 API。
|
||||||
|
|
||||||
|
## 1. 核心 API
|
||||||
|
|
||||||
|
### 1.1 会话管理
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class SessionManager {
|
||||||
|
public:
|
||||||
|
std::shared_ptr<Session> CreateSession(RoleType role);
|
||||||
|
void DestroySession(SessionId sessionId);
|
||||||
|
std::shared_ptr<Session> GetSession(SessionId sessionId);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.2 角色管理
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class RoleManager {
|
||||||
|
public:
|
||||||
|
bool RegisterRole(RoleType type, std::shared_ptr<IRole> role);
|
||||||
|
bool SwitchRole(SessionId sessionId, RoleType newRole);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.3 网络管理
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class NetworkManager {
|
||||||
|
public:
|
||||||
|
bool Initialize();
|
||||||
|
std::vector<NetworkInterface> 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<SessionManager>();
|
||||||
|
auto session = sessionManager->CreateSession(RoleType::Host);
|
||||||
|
auto hostRole = std::make_shared<HostRole>();
|
||||||
|
hostRole->Start(session);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 创建 Client 会话
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto sessionManager = std::make_shared<SessionManager>();
|
||||||
|
auto session = sessionManager->CreateSession(RoleType::Client);
|
||||||
|
auto clientRole = std::make_shared<ClientRole>();
|
||||||
|
clientRole->Start(session);
|
||||||
|
```
|
||||||
|
|
||||||
212
docs/ARCHITECTURE.md
Normal file
212
docs/ARCHITECTURE.md
Normal file
@@ -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 穿透模块集成到网络抽象层
|
||||||
|
- 对上层应用完全透明
|
||||||
|
- 自动选择最佳连接路径
|
||||||
|
- 支持连接方式动态切换
|
||||||
|
|
||||||
899
docs/IMPLEMENTATION.md
Normal file
899
docs/IMPLEMENTATION.md
Normal file
@@ -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 <media/NdkImageReader.h>
|
||||||
|
#include <android/native_window.h>
|
||||||
|
|
||||||
|
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<ScreenCapture*>(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 <media/NdkMediaCodec.h>
|
||||||
|
#include <media/NdkMediaFormat.h>
|
||||||
|
#include <android/native_window.h>
|
||||||
|
|
||||||
|
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<uint8_t>& 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 的端到端延迟**,满足实时显示协作的需求。
|
||||||
|
|
||||||
57
platforms/android/CMakeLists.txt
Normal file
57
platforms/android/CMakeLists.txt
Normal file
@@ -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}
|
||||||
|
)
|
||||||
|
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "displayflow/core/common/types.h"
|
||||||
|
#include <functional>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace displayflow {
|
||||||
|
namespace platform {
|
||||||
|
namespace android {
|
||||||
|
|
||||||
|
// 前向声明
|
||||||
|
struct VideoFrame;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 摄像头信息
|
||||||
|
*/
|
||||||
|
struct CameraInfo {
|
||||||
|
std::string cameraId;
|
||||||
|
std::string name;
|
||||||
|
bool isFrontFacing;
|
||||||
|
Resolution maxResolution;
|
||||||
|
std::vector<Resolution> supportedResolutions;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 摄像头捕获
|
||||||
|
*
|
||||||
|
* 使用 Android NDK Camera API 或 Camera2 API 进行摄像头捕获
|
||||||
|
*/
|
||||||
|
class CameraCapture {
|
||||||
|
public:
|
||||||
|
CameraCapture();
|
||||||
|
~CameraCapture();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 初始化摄像头捕获
|
||||||
|
*/
|
||||||
|
bool Initialize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 枚举可用的摄像头设备
|
||||||
|
*/
|
||||||
|
std::vector<CameraInfo> 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<void(const VideoFrame&)> 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
|
||||||
|
|
||||||
@@ -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
|
||||||
|
|
||||||
@@ -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
|
||||||
|
|
||||||
@@ -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
|
||||||
|
|
||||||
@@ -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
|
||||||
|
|
||||||
@@ -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
|
||||||
|
|
||||||
@@ -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
|
||||||
|
|
||||||
65
platforms/android/src/capture/camera_capture.cpp
Normal file
65
platforms/android/src/capture/camera_capture.cpp
Normal file
@@ -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<CameraInfo> 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<void(const VideoFrame&)> 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
|
||||||
|
|
||||||
18
platforms/android/src/capture/media_projection_wrapper.cpp
Normal file
18
platforms/android/src/capture/media_projection_wrapper.cpp
Normal file
@@ -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
|
||||||
|
|
||||||
32
platforms/android/src/capture/screen_capture.cpp
Normal file
32
platforms/android/src/capture/screen_capture.cpp
Normal file
@@ -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
|
||||||
|
|
||||||
18
platforms/android/src/input/touch_handler.cpp
Normal file
18
platforms/android/src/input/touch_handler.cpp
Normal file
@@ -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
|
||||||
|
|
||||||
18
platforms/android/src/network/android_network_manager.cpp
Normal file
18
platforms/android/src/network/android_network_manager.cpp
Normal file
@@ -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
|
||||||
|
|
||||||
32
platforms/android/src/platform_adapter.cpp
Normal file
32
platforms/android/src/platform_adapter.cpp
Normal file
@@ -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
|
||||||
|
|
||||||
18
platforms/android/src/render/render_engine.cpp
Normal file
18
platforms/android/src/render/render_engine.cpp
Normal file
@@ -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
|
||||||
|
|
||||||
67
platforms/windows/CMakeLists.txt
Normal file
67
platforms/windows/CMakeLists.txt
Normal file
@@ -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()
|
||||||
|
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "displayflow/core/common/types.h"
|
||||||
|
#include <functional>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace displayflow {
|
||||||
|
namespace platform {
|
||||||
|
namespace windows {
|
||||||
|
|
||||||
|
// 前向声明
|
||||||
|
struct VideoFrame;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 摄像头信息
|
||||||
|
*/
|
||||||
|
struct CameraInfo {
|
||||||
|
std::string deviceId;
|
||||||
|
std::string name;
|
||||||
|
std::string friendlyName;
|
||||||
|
Resolution maxResolution;
|
||||||
|
std::vector<Resolution> supportedResolutions;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 摄像头捕获
|
||||||
|
*
|
||||||
|
* 使用 DirectShow 或 Media Foundation 进行摄像头捕获
|
||||||
|
*/
|
||||||
|
class CameraCapture {
|
||||||
|
public:
|
||||||
|
CameraCapture();
|
||||||
|
~CameraCapture();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 初始化摄像头捕获
|
||||||
|
*/
|
||||||
|
bool Initialize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 枚举可用的摄像头设备
|
||||||
|
*/
|
||||||
|
std::vector<CameraInfo> 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<void(const VideoFrame&)> callback);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置摄像头参数
|
||||||
|
*/
|
||||||
|
bool SetFocus(int value); // 0-100
|
||||||
|
bool SetExposure(int value);
|
||||||
|
bool SetWhiteBalance(int value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// TODO: 添加私有成员
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace windows
|
||||||
|
} // namespace platform
|
||||||
|
} // namespace displayflow
|
||||||
|
|
||||||
@@ -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
|
||||||
|
|
||||||
@@ -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
|
||||||
|
|
||||||
@@ -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
|
||||||
|
|
||||||
@@ -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
|
||||||
|
|
||||||
@@ -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
|
||||||
|
|
||||||
@@ -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
|
||||||
|
|
||||||
@@ -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
|
||||||
|
|
||||||
@@ -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
|
||||||
|
|
||||||
65
platforms/windows/src/capture/camera_capture.cpp
Normal file
65
platforms/windows/src/capture/camera_capture.cpp
Normal file
@@ -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<CameraInfo> 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<void(const VideoFrame&)> 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
|
||||||
|
|
||||||
18
platforms/windows/src/input/keyboard_handler.cpp
Normal file
18
platforms/windows/src/input/keyboard_handler.cpp
Normal file
@@ -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
|
||||||
|
|
||||||
18
platforms/windows/src/input/mouse_handler.cpp
Normal file
18
platforms/windows/src/input/mouse_handler.cpp
Normal file
@@ -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
|
||||||
|
|
||||||
18
platforms/windows/src/network/windows_network_manager.cpp
Normal file
18
platforms/windows/src/network/windows_network_manager.cpp
Normal file
@@ -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
|
||||||
|
|
||||||
37
platforms/windows/src/platform_adapter.cpp
Normal file
37
platforms/windows/src/platform_adapter.cpp
Normal file
@@ -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
|
||||||
|
|
||||||
18
platforms/windows/src/render/d3d11_renderer.cpp
Normal file
18
platforms/windows/src/render/d3d11_renderer.cpp
Normal file
@@ -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
|
||||||
|
|
||||||
18
platforms/windows/src/render/directx_renderer.cpp
Normal file
18
platforms/windows/src/render/directx_renderer.cpp
Normal file
@@ -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
|
||||||
|
|
||||||
18
platforms/windows/src/virtual_display/iddcx_wrapper.cpp
Normal file
18
platforms/windows/src/virtual_display/iddcx_wrapper.cpp
Normal file
@@ -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
|
||||||
|
|
||||||
18
platforms/windows/src/virtual_display/virtual_display.cpp
Normal file
18
platforms/windows/src/virtual_display/virtual_display.cpp
Normal file
@@ -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
|
||||||
|
|
||||||
17
prototypes/README.md
Normal file
17
prototypes/README.md
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# 原型和测试代码
|
||||||
|
|
||||||
|
本目录用于存放开发过程中的原型代码和测试程序。
|
||||||
|
|
||||||
|
## 目录结构
|
||||||
|
|
||||||
|
- `network_test/` - 网络功能测试
|
||||||
|
- `codec_test/` - 编解码器测试
|
||||||
|
- `protocol_test/` - 协议测试
|
||||||
|
- `performance_test/` - 性能测试
|
||||||
|
|
||||||
|
## 使用说明
|
||||||
|
|
||||||
|
原型代码主要用于验证技术方案的可行性,不保证代码质量。
|
||||||
|
|
||||||
|
正式代码应放在对应的 `core/` 或 `platforms/` 目录下。
|
||||||
|
|
||||||
15
tools/README.md
Normal file
15
tools/README.md
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# 开发工具脚本
|
||||||
|
|
||||||
|
本目录包含各种开发辅助工具和脚本。
|
||||||
|
|
||||||
|
## 工具列表
|
||||||
|
|
||||||
|
- `setup_dependencies.sh` - 依赖安装脚本
|
||||||
|
- `build.sh` - 构建脚本
|
||||||
|
- `format_code.sh` - 代码格式化脚本
|
||||||
|
- `run_tests.sh` - 测试运行脚本
|
||||||
|
|
||||||
|
## 使用说明
|
||||||
|
|
||||||
|
根据平台选择合适的脚本执行。
|
||||||
|
|
||||||
Reference in New Issue
Block a user