I just started coding an application, my idea is to create something like StreamMyGame but for personal use, there is already a project called Single Player Game Transmiter that achieves some of this (http://sourceforge.net/projects/spgt/files/).
So far I'm not encoding nor streaming, I'm just capturing video and displaying it in my app window.
So how could I handle encoding/streaming? I was thinking an UDP stream of raw JPEGs would be the easiest path but I'm not sure.
Also how could I optimize what I have so far? It works fine for video playback but when capturing game windows it doesn't seem as snappy as the original video, I think it might be due to the fact that it's running in the background. That leads me to another question, how can I capture the Window with the specified title instead of the active Window?
https://github.com/fr500/desktop_streamer
EDIT:
Some tests with the current Capture Method:
Video Player Capture (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
Crysis 2 Capture (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
Saving image to BMP doesn't really add any overhead but saving as JPG does which gives me an idea of the overhead encoding to video could have. Still the biggest issue is getting the frames themselves it's too slow as it is now, it can't keep up and as a result some frames are missing. If frames could be captured at 60+ fps the encoding + streaming delay could be really manageable for single player games.
I will try a DX hook approach to get the frames.
Recently, I build a golang project called ScreenStreamer, is a tool to stream current active window (Linux's or Windows's) to other device, like phone or another PC, as MJPEG, it's very realtime(delay < 100ms)
the project link: https://github.com/fiefdx/ScreenStreamer
I'm not sure if performance/quality issues are effect of running in the background, however I'll try to answer your question.
Capturing window by its name
I suppose you can try to use
FindWindow
function instead ofGetForegroundWindow
that is used in the application. It allows you to get handle to a window by its title. In order to do this (in the desktop_streamer project you've posted a link to), go to theScreenCapture
class and:change
to
in
Capture
method change the lineto
I haven't tested this, so if you have any issues with running the code, let me know, so we can look for a solution.
For more information about
FindWindow
function, take a look here: http://www.pinvoke.net/default.aspx/user32.findwindow.Performance and images quality
When talking about performance, you may want to try measure network speed and latency in real time and then use those information to adjust images quality (compression level and resolution) appropriately. This can make the transmitted image pixelated from time to time, but should decrease effect of laggy gameplay.
You may also want to take a look at this page giving some performance comparison of two of the screen capturing methods: http://blog.bobcravens.com/2009/04/fastest-screen-capture-using-c-vista-vs-win7/. It may help you improve te performance of screen capturing process, but as you can see, frame rates achieved are still too low to provide high quality gaming experience.