Skip to content

Comments

feat: Implement subprocess streaming architecture for separated control/data planes#385

Draft
Copilot wants to merge 5 commits intomasterfrom
copilot/refactor-streaming-architecture
Draft

feat: Implement subprocess streaming architecture for separated control/data planes#385
Copilot wants to merge 5 commits intomasterfrom
copilot/refactor-streaming-architecture

Conversation

Copy link

Copilot AI commented Dec 22, 2025

Implements architecture separating control plane (main process/SYSTEM) from data plane (subprocess/User) to reduce latency by eliminating cross-process memory copies and enabling direct WGC/WASAPI access from user session.

IPC Infrastructure (src/subprocess/)

  • ipc_protocol.h: Binary message protocol with session init, socket handover (Windows WSADuplicateSocket), control commands (IDR/bitrate/ref-frame invalidation), status reporting, heartbeat
  • ipc_pipe.h/cpp: Cross-platform named pipes - Windows CreateNamedPipe with overlapped I/O, Linux FIFO in /tmp
  • subprocess_manager.h/cpp: Worker lifecycle, socket transfer, heartbeat monitoring, status callbacks
  • subprocess_logging.h: Compile-time switch between Boost.Log (main) and stderr (subprocess)

Subprocess Sender (src/sender/)

  • sender_main.cpp: Standalone executable - IPC connect, config receive, control message routing, Windows socket recreation from WSAPROTOCOL_INFO
  • Minimal dependencies (no Boost.Log linkage)

Build Integration

  • Sender target added for Windows/Linux in cmake/targets/
  • Subprocess sources added to main build in cmake/compile_definitions/common.cmake

Usage Pattern

// Main process
auto worker = subprocess_manager_t::instance().create_worker(session_id);
worker->start(config, status_callback);
worker->transfer_socket(SOCKET_VIDEO, socket_handle, remote_addr, AF_INET, port);
worker->request_idr_frame();
worker->change_bitrate(5000);

// Subprocess receives via IPC, handles capture→encode→send locally

Note: This PR establishes the framework. Actual capture/encode/send integration into the subprocess is a follow-up.

Original prompt

直接由子进程负责“采集 -> 编码 -> 发送”的全流程,确实可以显著降低延迟并减少架构复杂度。
在高性能流媒体(如 Sunshine/Moonlight)中,频繁的跨进程大内存拷贝(哪怕是共享内存)都会带来不可忽视的 CPU/GPU 调度开销。让子进程成为一个**独立的“流媒体引擎”**是完全可行的。

  1. 架构逻辑:控制流与数据流分离
    在这种设计下,Sunshine 的主进程和子进程的角色将发生转变:
  • 主进程 (SYSTEM - 控制平面):
    • 维持网络监听(RTSP 握手、身份验证)。
    • 接收控制指令(如:开始流览、停止、更改比特率)。
    • 任务: 启动子进程,并将必要的网络 Socket 或授权信息传递给它。
  • 子进程 (User - 数据平面):
    • 捕获: 使用 WGC 采集桌面。
    • 编码: 调用 NVENC/AMF/QSV 进行硬件编码。
    • 发送: 直接通过 UDP (RTP) 将编码后的包发送给客户端。
  1. 技术关键点:如何绕过数据传递?
    A. Socket 句柄继承 (Socket Handover)
    主进程在处理完 RTSP 握手后,可以将已经建立的 Socket 句柄“交给”子进程。
  • 在 Windows 中,你可以使用 WSADuplicateSocket API 将一个进程中的 Socket 复制到另一个进程中。
  • 这样,子进程拿到 Socket 后,可以直接进行 sendto 或 send 操作,数据包直接从子进程的内存发出,不经过主进程。
    B. 音频捕获的天然优势
    在 Windows 中,Loopback 音频捕获(WASAPI)也是 Session 相关的。如果主进程是 SYSTEM,它很难捕获到当前用户的声音。让子进程(User 权限)负责发送视频流的同时,顺便把音频也采集并发送了,逻辑上更统一。
    C. 指令反馈环 (Back-channel)
    虽然视频流出去了,但客户端可能会反馈“丢包了,请重发 IDR 帧”或“网络波动,请降低比特率”。
  • 主进程收到这些网络反馈后,通过一个轻量级 IPC(如命名管道或消息队列)下发给子进程。
  • 由于这类指令数据量极小(几个字节),不会产生性能瓶颈。
  1. 实现细节与挑战
    3.1 修改 foundation-sunshine 的发送逻辑
    你需要在源码中找到负责网络发送的部分(通常是 rtp.cpp 或相关的 streaming 类):
  • 解耦编码器: 确保编码器初始化不依赖于主进程的全局单例。
  • 独立打包: 子进程需要集成 RTP 打包逻辑(把 H.264/H.265 NALUs 切片封装进 UDP 包)。
    3.2 权限与网络隔离
  • 防火墙: 确保子进程(即使是随机命名的临时进程)有权限访问网络。通常建议给子进程一个固定的名称,并预先在防火墙中加白。
  • 用户 Token: 使用 CreateProcessAsUser 启动时,确保其环境块(Environment Block)正确,否则编码器(驱动层调用)可能会因为找不到显卡驱动环境而初始化失败。
  1. 优缺点对比
    | 特性 | 方案一:跨进程传递数据 (IPC) | 方案二:子进程直接发送 (分离) |
    |---|---|---|
    | 延迟 | 较高 (存在跨进程拷贝与上下文切换) | 极低 (原生速度) |
    | 内存占用 | 较高 (两份缓存) | 低 |
    | 开发难度 | 中等 | 较高 (需重构发送模块) |
    | 安全性 | 较好 (网络权限集中在 SYSTEM) | 一般 (子进程需网络访问权限) |
    | WGC/音频兼容性 | 差 (需处理 Session 隔离) | 完美 |
  2. 建议尝试路径
  • 第一步: 在 foundation-sunshine 中实现一个简易的“外部发送模式”开关。
  • 第二步: 编写一个最小化的 sender.exe,它不具备捕获功能,只负责接收主进程通过命名管道传来的 NALU 数据并发送(验证 Socket 传递和 RTP 打包)。
  • 第三步: 将 WGC 捕获和硬件编码搬迁到 sender.exe 中,实现最终的“子程序全承包”。
    实现这个架构

💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 4 commits December 22, 2025 04:10
- Add IPC protocol definitions (ipc_protocol.h)
- Implement cross-platform named pipe IPC (ipc_pipe.h/cpp)
- Add subprocess configuration (subprocess_config.h/cpp)
- Implement subprocess lifecycle management (subprocess_manager.h/cpp)
- Add subprocess module initialization (subprocess.h/cpp)
- Update CMake to include subprocess module files

Co-authored-by: ShadowLemoon <119576779+ShadowLemoon@users.noreply.github.com>
- Create sender_main.cpp with IPC message handling
- Add CMakeLists.txt for building sunshine-sender
- Create logging wrapper for subprocess module compatibility
- Integrate sender build into Windows and Linux targets
- Implement basic message routing for control commands

Co-authored-by: ShadowLemoon <119576779+ShadowLemoon@users.noreply.github.com>
- Add missing <unordered_map> include to subprocess_manager.h
- Use raw string literal for Windows pipe name
- Fix Unix pipe path to use /tmp directory
- Change 'using namespace std::literals' to 'using namespace std::chrono_literals'

Co-authored-by: ShadowLemoon <119576779+ShadowLemoon@users.noreply.github.com>
Co-authored-by: ShadowLemoon <119576779+ShadowLemoon@users.noreply.github.com>
Copilot AI changed the title [WIP] Refactor streaming architecture for reduced latency feat: Implement subprocess streaming architecture for separated control/data planes Dec 22, 2025
Copilot AI requested a review from ShadowLemoon December 22, 2025 04:18
@qiin2333 qiin2333 force-pushed the master branch 2 times, most recently from 728df07 to 33745c6 Compare January 13, 2026 08:19
@qiin2333 qiin2333 force-pushed the master branch 2 times, most recently from 029ba99 to eba4145 Compare February 14, 2026 06:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants