跳到主要内容
版本:4.2

DmtpPixStream像素流传输

定义

命名空间:
TouchSocketPro.Dmtp.PixStream
安装:
dotnet add package TouchSocketPro.Dmtp.PixStream

一、说明

DmtpPixStream 是基于 DMTP 协议的像素流图像传输扩展,适用于需要将画面(摄像头、屏幕截图、工业相机帧等)从一个终端实时传输到另一个终端的场景。

三种典型拓扑:

拓扑说明
服务器采集 → 客户端显示服务器持有 Provider,客户端直连并拉取帧
客户端采集 → 服务器显示客户端持有 Provider,服务器主动向该客户端发起会话并拉取帧
客户端采集 → 客户端显示(路由)服务器作为纯路由节点,采集端与接收端均为 TcpDmtpClient,接收端通过采集端 ID 路由寻址
提示

第三种路由拓扑与 DmtpRpc 路由调用完全一致。前两种是直连模式,无需路由配置。

核心传输机制:

  • 首次请求:采集端返回完整帧(Full Frame),包含全部像素数据。
  • 后续请求:若启用差分传输,采集端仅返回相对上一帧发生变化的像素块(Delta Frame),接收端将变化块叠加到本地缓存画面,大幅降低网络带宽消耗。

二、功能特性

特性说明
完整帧传输首次请求或关闭差分传输时,一次传输完整画面
增量差分传输仅传输变化像素块,带宽利用率高
JPEG 压缩可配置 JPEG 质量,进一步减少传输数据量
多会话隔离每个接收端会话独立维护差分帧状态
三种拓扑直连(服务器采集)、直连(客户端采集)、路由(客户端间转发)均支持
会话审批可通过插件拦截并审批会话创建请求

三、场景一:服务器采集,客户端直连显示

这是最简单的直连场景:服务器持有 IPixStreamProvider客户端直接连接后调用 CreatePixStreamSessionAsync(request) 拉取帧,无需 targetId

3.1 服务器配置

服务器注册 UseDmtpPixStream 并设置 Provider

🔄 正在加载代码...

3.2 推送帧数据

服务器采集到新帧后调用 UpdateFrame 推入缓冲区:

🔄 正在加载代码...
说明

UpdateFrame 接受 Image<Bgr24> 类型(来自 ImageSharp)。示例使用随机测试帧,实际项目中替换为相机 SDK 回调、屏幕截图等任意来源即可。

3.3 客户端直连配置与创建会话

客户端注册 UseDmtpPixStream(不设 Provider)后,直接调用无 targetId 的重载创建会话:

🔄 正在加载代码...
🔄 正在加载代码...

四、场景二:客户端采集,服务器主动拉取

此场景中客户端持有 IPixStreamProvider服务器在客户端连接后,通过 TcpDmtpSessionClient.GetDmtpPixStreamActor() 主动向该客户端发起会话来拉取画面。

4.1 服务器配置(接收端)

服务器不设 Provider,在 IDmtpConnectedPlugin 生命周期事件中主动向刚连接的客户端发起会话:

🔄 正在加载代码...
🔄 正在加载代码...

4.2 客户端配置(采集端)

客户端注册 UseDmtpPixStream 并设置 Provider,连接服务器即可等待服务器主动拉取:

🔄 正在加载代码...

五、场景三:两个客户端间路由传输

此场景下路由服务器作为纯中间节点,采集端接收端 都是普通的 TcpDmtpClient,接收端通过采集端的 DMTP ID 路由寻址。拓扑与 DmtpRpc 路由完全一致。

5.1 路由服务器配置

服务器注册 UseDmtpPixStream(不设 Provider)、启用 AddDmtpRouteService 并允许转发:

🔄 正在加载代码...
说明

服务器 UseDmtpPixStream() 不设 Provider,仅用于识别和转发像素流协议报文,不参与任何帧数据的生产。

5.2 采集端(TcpDmtpClient)配置

采集端是普通客户端,连接路由服务器后设置 Provider 并持续推送帧。其 DMTP ID 即为接收端路由寻址的目标:

🔄 正在加载代码...
🔄 正在加载代码...

5.3 接收端(TcpDmtpClient)配置与路由会话

接收端也是普通客户端,连接路由服务器后使用 targetId 的重载 创建会话:

🔄 正在加载代码...
🔄 正在加载代码...

六、接收和处理帧数据

无论哪种拓扑,接收到的 PixFrame 结构相同:

属性类型说明
FrameTypePixFrameTypeFull(完整帧)或 Delta(增量帧)
Width / Heightint图像尺寸(像素)
BlocksIReadOnlyList<PixBlock>本次传输的像素块集合
TransferredByteslong本次实际传输的字节数

每个 PixBlock 表示图像中的一个矩形区域:

属性类型说明
X / Yint块左上角坐标
Width / Heightint块尺寸
PixelFormatPixelFormat编码格式:Bgr24Jpeg
RawDataReadOnlyMemory<byte>原始像素数据
Bgr24DataReadOnlyMemory<byte>解码后的 BGR24 数据(JPEG 时惰性解码)

以下示例展示如何在 WPF 中将帧块写入 WriteableBitmap 渲染:

🔄 正在加载代码...
注意

PixFrame 实现了 IDisposable,内部像素块使用内存池分配。框架在 OnReceived 回调返回后自动释放;若需异步持有,应在回调内将所需数据解码拷贝后再返回。

七、差分传输

差分传输(Delta Transfer)是 DmtpPixStream 的核心优化机制。启用后,采集端对相邻两帧进行逐块比较(按 BlockSize 分块,默认 64 像素),仅将发生变化的块打包传输。

  • 对于静态画面,增量帧可能只包含少量块,带宽消耗极低。
  • 对于高动态场景,增量帧大小可能接近完整帧,差分传输优势减弱。

可通过 IPixStreamSession.EnableDeltaTransfer 在运行时动态切换。DmtpPixStreamOption.BlockSize 可调整块大小,块越小差异检测越精细,但计算开销越大,默认 64 像素在大多数场景下均有良好表现。

八、会话审批

任意场景下,采集端所在节点(服务器或客户端)均可实现 IDmtpPixStreamCreatingPlugin 插件来审批或拒绝会话创建请求。事件参数 DmtpPixStreamCreatingEventArgs 提供了源端 ID、目标端 ID、会话 ID 及请求参数。

🔄 正在加载代码...

e.IsPermitOperation 设为 false(默认值)即可拒绝,并可通过 e.Message 设置拒绝原因。