我在琢磨写一个 HyperV 串流传输的程序,应该采用什么方案呢?
这个程序用于 HyperV ,将虚拟机画面通过 HVsocket 接口,也就是 vmbus ,将虚拟化画面实时传输到宿主机,从而显示和控制。目前已经在 ai 帮助下实现 HDC 的画面传输,但是采集效率很低,帧率只有 10-20 左右,使用 DirectX 等技术用于采集会如何呢?有了解的朋友吗?
vmbus 并不依赖网络,但在 winsock 上的实现似乎和 tcpip 有些类似。研究这个的目的是和虚拟显示适配器配合,超越现有的 HyperV Video 以及 RDP 的效果,是不是很酷😉
用 DXGI 采集画面会好一点。但其实还有个问题,画面数据量很大,虚拟机里还不能保证能用硬件加速视频编码……
HyperV Video 没用过,想要超过 RDP 的效果的话,Parsec 、Moonlight 这类串流软件已经能做到了。
酷当然是酷,但是我建议你直接找个成熟方案,把 vmbus 改上去就好了。。。可以直接改或者搞个 tcp 本机转发。远程控制说简单确实简单,但想做好麻烦的一比
好的,我研究下,硬件加速这块是有的,场景就是在分配了 gpu 分区的情况下,如果没有的话就降级到无硬件加速即可。
这类串流方案走的是网络方案,没有内核级别的 vmbus 通路好,连 gpupv 都用的是后者
是的是的,正在找了
#5
有点没懂,你这个东西不是为了远程操控吗?不需要网络怎么做的?
#7 vmbus 啊,很底层的技术,比网络好多了
有人做了,接管了 RDP ,再说了 RDP 协议的数据在 Windows 上自己抓取,可以 over 任何协议
是否有链接可以访问?这个和 RDP 本质不一样。我要做的是高性能的桌面,预期 4K144hz 这种,而 RDP 的”渲染适配器“是落后的,图形性能低下,各种图形 api 实现也很差。
# 8
我的意思是,如果不走网络,那你的 HOST 和 CLIENT 都在同一台机器上吗?如果都在同一台机器上,为什么还要串流?
#11 是的,宿主和虚拟机都在同一物理平台上,我没有表达清楚。因为目前普遍的本地虚拟机使用方式都是 Hyper-V Video 或者 RDP ,前者限制在了 1080p 和 62hz ,后者更是无法调整分辨率,且刷新率解锁也只有 60 ,但是如果走 vmbus 加上渲染适配器,是有希望达成 4K144hz 的。而目前普遍的串流方案是网络栈,延迟和码率都不令人满意,即使是局域网玩 fps 游戏,延迟也比较明显,我期待可以解决这个难题。
那是不是可以实现一台物理机(性能足够强)开网吧🐶
您好,如果对此感兴趣的话可以参见本人 Github 项目:
github.com/Justsenger/ExHyperV
其中的 DDA 功能模块,可以将一台物理机的显卡和键鼠分配给虚拟机独享使用,可能对你有所帮助。
目前正在解决的问题是 Gpupv 功能模块将视频信号高效引出虚拟机的方式。
Linux 这边 virtio 也有类似的需求和实现方案。
我个人的理解是:
- 如果虚拟机内部是虚拟的 gpu ,那么就可以直接共享内存,宿主机直接访问虚拟机内虚拟 gpu 的 framebuffer
- 如果虚拟机内部有直通的 gpu ,那就只能从 framebuffer 入手抓取视频源(比如 nvfbc ),然后再共享给宿主机
应该不存在比直接内存映射更高效的 IPC 方式了。
存在三种情况:直通的 GPU ,分区的 GPU ,无 GPU ,这样看来访问内存是不太现实的?
#16
如果我没理解错的话,你的需求是这样的:宿主机上运行的虚拟机,然后宿主机的某个客户端窗口,显示虚拟机的视频输出内容。
为了达到目标性能要求,一方面需要虚拟机本身能够实现高分辨率高刷新率,另一方面这个达标的显示输出能够在宿主机上正确还原,中间的通信延迟要足够低(输入设备还在宿主机上并没有直通到虚拟机)。
为了达到第一个要求,一般有两个方案:
- 使用半虚拟化驱动设备,比如 qxl ,virgl 还有一些都属于这种,在虚拟机里面使用虚拟的显卡设备,这个设备会将渲染指令传递给宿主机,通过宿主机执行后再将结果传回虚拟机
- 直通物理显卡或者利用 sriov 直通物理显卡虚拟出来的显卡
我对 windows 不熟悉,猜测 windows 的几个实现原理上应该都是上面两个思路。
不知道触发了什么关键词,我二分一下拆开回复。
#17
#16
我之前回复的是满足第二个要求的方法。先不考虑虚拟机里的视频信号从哪里来的,假设你已经获得了实时 framebuffer 流,可以走网络协议,同时由于宿主机和虚拟机在一起,也可以走共享内存。技术上说,所有走网络协议的方案因为存在编解码、封装,都不可能比直接内存共享延迟更低。就拿 kvm 常见的虚拟化方案来说,SPICE 是个网络协议,但与 qxl 搭配的时候,使用的是共享内存。
从原理上说,kvm 这边直接用 SPICE 就可以了。我搜了一下 vmbus 的文档,虽然提到了共享内存,但我感觉用它来共享 framebuffer 需要做的工作还很多。
#18
#16
最后再回到之前说的共享内存方案。实际上 framebuffer 的数据结构某种程度上说是硬件相关的。也就是说,即便在虚拟机和宿主机之间通过虚拟设备共享了内存,一方面要对接这个虚拟内存的读写接口,另一方面需要将 framebuffer 封装成一种统一的格式。这样在宿主机上,用于显示虚拟机内容的窗口可以直接将 framebuffer 提交给窗口管理器进行合成,即再次 DMA 到显卡。
如果我说得不是很清楚的话,可以参考 looking-glass.io/ 这个项目,它的核心实现是 KVMFR github.com/gnif/LookingGlass/blob/master/module/kvmfr.c 这个模块,基于 IVSHMEM 完成我之前说的流程。理论上 windows 上实现相同效果的原理是一样的。
#19
#16
中间发不出来的一段是关于如何获取 framebuffer 的。通过系统 api 会有二次复制的延迟,通过显卡特定 api 更合适。
#20 感谢您的回复,半虚拟化在 windows 叫做 gpupv ,直通在 windows 叫做 dda ,对于您提到的 framebuffer 来源非常复杂,可能是无显卡环境下来自于虚拟显示器+cpu ,也可能来自虚拟显示器+半虚拟化 gpu ,还可能是物理/虚拟显示器+直通 gpu ,情况比较多变,用显卡特定 api 似乎不太可行?
”就拿 kvm 常见的虚拟化方案来说,SPICE 是个网络协议,但与 qxl 搭配的时候,使用的是共享内存。“——这里我似有所悟,win 这边对应 spice 的是 winsock ,对应 qxl 的是 vmbus 。但想用于共享 framebuffer ,似乎没有案例。目前我卡在了 winsock 的 recv 速率过低,以及获取图像的 HDC 可能效率低下的问题上,还在想办法解决,因为我只是个小白
#21
考虑先实现出来吧,就用系统的 api 这样可以覆盖所有情况,延迟和性能的问题先不去处理。
粗略估计 4k 120hz 10bit 无压缩每帧数据量在 30MB 左右,单帧时间 8.3ms ,单从数据量上来说,如果是通过某种网络协议传输是没有带宽压力的,主要困难是延迟,发送接收涉及编解码。obs 有个 ndi 实现(现在叫 DistroAV ),就是在一台设备上采集,然后通过网络将数据传输到另一台设备上进行编码,可以参考一下它去掉网络开销的延迟水平。
共享内存的路线,Linux 的实现方式大概是这样的:
- Linux 宿主机内核驱动 virtio 实现了 IVSHMEM
- Linux 虚拟机或者 windows 虚拟机也通过 virtio 的驱动模块启用 IVSHMEM
- 虚拟机和宿主机通过指定相同的物理地址实现内存共享( IVSHMEM 本质是虚拟 PCI 设备)
- 虚拟机内的特定应用(你要开发的)将 framebuffer 封装好后写入 IVSHMEM 的特定区域(手动管理)
- (可选)宿主机应用通过 IVSHMEM 读取对应的 framebuffer 并做后续处理
这里可以看到 IVSHMEM 实际只是非常粗糙的共享内存机制,还需要在它的基础上实现用它完成 fb 数据交换。之前提到的 looking-glass 就是实现了一个叫 KVMFR 的模块,在 IVSHMEM 的基础上封装了一个用于 fb 数据交换的接口(硬件设备),同时实现了宿主与虚拟机之间的同步、锁,另外它用来做数据交换的格式是 dma-buf ,这样宿主机上的窗口合成器可以直接使用。之后,虚拟机的采集应用( obs/ffmpeg/系统采集)直接将数据写入 KVMFR 。
如果你要在 windows 实现类似的功能,需要把 vmbus 当作 IVSHMEM ,然后在上面实现一个 windows 版本的 KVMFR 。
估计这样表述应该就清楚了,由于我对 windows 不是特别了解,所以上面的方案不一定正确。
OS:Centos 网卡:有线网卡即可 CPU:x86 架构的,不用 arm GPU:用不到 预算:< 5000 内存:要求可以拓展到 64G 硬盘:要求可以拓展到 8T 希望…
我觉得它是,因为它确实可以将对象保存到数据库也可以从数据库里检索到对象,但隐约感觉哪里好像又有点不对劲。。它和 hibernate 以及 ebean 之流的框架到底谁是 ORM…
大家都说 Linux 的未来是 Windows ,或者是 macOS 。 大家都说 Linux 的桌面不堪用, 大家都说。。。 是的,大家也许都是对的,只是我想换主力机了。 从…