我在琢磨写一个 HyperV 串流传输的程序,应该采用什么方案呢?

150 天前
 shalingye
这个程序用于 HyperV ,将虚拟机画面通过 HVsocket 接口,也就是 vmbus ,将虚拟化画面实时传输到宿主机,从而显示和控制。目前已经在 ai 帮助下实现 HDC 的画面传输,但是采集效率很低,帧率只有 10-20 左右,使用 DirectX 等技术用于采集会如何呢?有了解的朋友吗?

vmbus 并不依赖网络,但在 winsock 上的实现似乎和 tcpip 有些类似。研究这个的目的是和虚拟显示适配器配合,超越现有的 HyperV Video 以及 RDP 的效果,是不是很酷😉
2156 次点击
所在节点    程序员
23 条回复
shalingye
148 天前
@kuanat #20 感谢您的回复,半虚拟化在 windows 叫做 gpupv ,直通在 windows 叫做 dda ,对于您提到的 framebuffer 来源非常复杂,可能是无显卡环境下来自于虚拟显示器+cpu ,也可能来自虚拟显示器+半虚拟化 gpu ,还可能是物理/虚拟显示器+直通 gpu ,情况比较多变,用显卡特定 api 似乎不太可行?
”就拿 kvm 常见的虚拟化方案来说,SPICE 是个网络协议,但与 qxl 搭配的时候,使用的是共享内存。“——这里我似有所悟,win 这边对应 spice 的是 winsock ,对应 qxl 的是 vmbus 。但想用于共享 framebuffer ,似乎没有案例。目前我卡在了 winsock 的 recv 速率过低,以及获取图像的 HDC 可能效率低下的问题上,还在想办法解决,因为我只是个小白
kuanat
148 天前
@shalingye #21

考虑先实现出来吧,就用系统的 api 这样可以覆盖所有情况,延迟和性能的问题先不去处理。

粗略估计 4k 120hz 10bit 无压缩每帧数据量在 30MB 左右,单帧时间 8.3ms ,单从数据量上来说,如果是通过某种网络协议传输是没有带宽压力的,主要困难是延迟,发送接收涉及编解码。obs 有个 ndi 实现(现在叫 DistroAV ),就是在一台设备上采集,然后通过网络将数据传输到另一台设备上进行编码,可以参考一下它去掉网络开销的延迟水平。



共享内存的路线,Linux 的实现方式大概是这样的:

1. Linux 宿主机内核驱动 virtio 实现了 IVSHMEM

2. Linux 虚拟机或者 windows 虚拟机也通过 virtio 的驱动模块启用 IVSHMEM

3. 虚拟机和宿主机通过指定相同的物理地址实现内存共享( IVSHMEM 本质是虚拟 PCI 设备)

4. 虚拟机内的特定应用(你要开发的)将 framebuffer 封装好后写入 IVSHMEM 的特定区域(手动管理)

5. (可选)宿主机应用通过 IVSHMEM 读取对应的 framebuffer 并做后续处理



这里可以看到 IVSHMEM 实际只是非常粗糙的共享内存机制,还需要在它的基础上实现用它完成 fb 数据交换。之前提到的 looking-glass 就是实现了一个叫 KVMFR 的模块,在 IVSHMEM 的基础上封装了一个用于 fb 数据交换的接口(硬件设备),同时实现了宿主与虚拟机之间的同步、锁,另外它用来做数据交换的格式是 dma-buf ,这样宿主机上的窗口合成器可以直接使用。之后,虚拟机的采集应用( obs/ffmpeg/系统采集)直接将数据写入 KVMFR 。

如果你要在 windows 实现类似的功能,需要把 vmbus 当作 IVSHMEM ,然后在上面实现一个 windows 版本的 KVMFR 。



估计这样表述应该就清楚了,由于我对 windows 不是特别了解,所以上面的方案不一定正确。
shalingye
147 天前
@kuanat #22 感谢大佬,我需要一点时间来慢慢理解,哈哈

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1123723

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX