如何实时将视频从视频游戏流式传输到另一台计算机?

时间:2012-07-14 05:50:04

标签: c# encoding streaming capture

我刚开始编写应用程序代码,我的想法是创建类似StreamMyGame的东西但是供个人使用,已经有一个名为Single Player Game Transmiter的项目实现了一些(http://sourceforge.net/projects/spgt /文件/).

到目前为止,我不是编码也不是流媒体,我只是捕捉视频并在我的应用窗口中显示它。

那我怎么能处理编码/流媒体?我认为原始JPEG的UDP流将是最简单的路径,但我不确定。

我怎么能优化到目前为止我所拥有的?它适用于视频播放,但在捕捉游戏窗口时,它看起来并不像原始视频那样活泼,我想这可能是因为它在后台运行。这引出了另一个问题,我如何使用指定的标题而不是活动的窗口捕获窗口?

https://github.com/fr500/desktop_streamer

修改

使用当前捕获方法的一些测试:

视频播放器捕获(960x720p)

starting benchmark
================================================
looking for window: test.mp4
looking for window: test.mp4
looking for window: test.mp4
looking for window: test.mp4
looking for window: test.mp4
================================================
starting single thread capture only test

Time Elapsed: 19480 milliseconds
Frame Time: 32 milliseconds
Rough FPS: 30
Sleeping 2 seconds

starting single thread capture and save as bmp test

Time Elapsed: 19768 milliseconds
Frame Time: 32 milliseconds
Rough FPS: 30
Sleeping 2 seconds

starting single thread capture and save as jpg test

Time Elapsed: 28593 milliseconds
Frame Time: 47 milliseconds
Rough FPS: 20
Sleeping 2 seconds

starting dual thread capture only test

Time Elapsed: 19515 milliseconds
Frame Time: 32 milliseconds
Rough FPS: 30
Sleeping 2 seconds

starting quad thread capture only test

Time Elapsed: 19481 milliseconds
Frame Time: 32 milliseconds
Rough FPS: 30
Sleeping 2 seconds

孤岛危机2捕获(1024x768p)

starting benchmark
================================================
looking for window: Crysis 2 (TM)
looking for window: Crysis 2 (TM)
looking for window: Crysis 2 (TM)
looking for window: Crysis 2 (TM)
looking for window: Crysis 2 (TM)
looking for window: Crysis 2 (TM)
looking for window: Crysis 2 (TM)
================================================
starting single thread capture only test

Time Elapsed: 20003 milliseconds
Frame Time: 33 milliseconds
Rough FPS: 29
Sleeping 2 seconds

starting single thread capture and save as bmp test

Time Elapsed: 20105 milliseconds
Frame Time: 33 milliseconds
Rough FPS: 29
Sleeping 2 seconds

starting single thread capture and save as jpg test

Time Elapsed: 17353 milliseconds
Frame Time: 28 milliseconds
Rough FPS: 34
Sleeping 2 seconds

starting dual thread capture only test

Time Elapsed: 19991 milliseconds
Frame Time: 33 milliseconds
Rough FPS: 30
Sleeping 2 seconds

starting quad thread capture only test

Time Elapsed: 19983 milliseconds
Frame Time: 33 milliseconds
Rough FPS: 30
Sleeping 2 seconds

将图像保存到BMP并没有真正增加任何开销,但保存为JPG会让我了解视频可能具有的开销编码。仍然最大的问题是让帧本身变得太慢,因为它现在太快了,它无法跟上,因此一些帧丢失。如果可以以60 + fps捕获帧,则编码+流延迟对于单人游戏来说实际上是可管理的。

我将尝试DX钩子方法来获取帧。

2 个答案:

答案 0 :(得分:1)

我不确定性能/质量问题是否会在后台运行,但我会尝试回答您的问题。

按名称捕获窗口

我想您可以尝试使用FindWindow函数而不是应用程序中使用的GetForegroundWindow。它允许您通过标题来处理窗口。为了做到这一点(在desktop_streamer项目中你发布了一个链接),转到ScreenCapture类并:

  • 变化

    [DllImport("user32.dll")]
    private static extern IntPtr GetForegroundWindow();
    

    [DllImport("user32.dll", SetLastError = true)]
    private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
    
  • Capture方法中更改行

    var foregroundWindowsHandle = GetForegroundWindow();
    

    var foregroundWindowsHandle = FindWindow(null, "mywindowName");
    

我没有对此进行测试,因此如果您在运行代码时遇到任何问题,请告诉我们,以便我们寻找解决方案。

有关FindWindow功能的详细信息,请查看此处:http://www.pinvoke.net/default.aspx/user32.findwindow

性能和图像质量

在谈论性能时,您可能希望尝试实时测量网络速度和延迟,然后使用这些信息来适当调整图像质量(压缩级别和分辨率)。这可以使传输的图像不时地像素化,但应该减少滞后游戏的效果。

您可能还想查看此页面,对两种屏幕捕获方法进行性能比较:http://blog.bobcravens.com/2009/04/fastest-screen-capture-using-c-vista-vs-win7/。它可以帮助您提高屏幕捕获过程的性能,但正如您所看到的,实现的帧速率仍然太低,无法提供高质量的游戏体验。

答案 1 :(得分:0)

最近,我构建了一个名为ScreenStreamer的golang项目,是一个将当前活动窗口(Linux或Windows)流式传输到其他设备(如手机或其他PC)的工具,如MJPEG,它非常实时(延迟<100ms)

项目链接:https://github.com/fiefdx/ScreenStreamer