Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ms windows shadow server improvements #389

Open
totaam opened this issue Jul 18, 2013 · 24 comments
Open

ms windows shadow server improvements #389

totaam opened this issue Jul 18, 2013 · 24 comments
Labels
shadow win32 MS Windows OS
Milestone

Comments

@totaam
Copy link
Collaborator

totaam commented Jul 18, 2013

The current shadow server for win32 sort of works but we need to improve:

@totaam
Copy link
Collaborator Author

totaam commented Aug 18, 2013

Screenscraping may be the only feasible way to get 3D apps to work:
Since the hardware-accelerated 3D rendering commands typically bypass the GDI layer, most screen scrapers (WinVNC, LiveMeeting, GoToMeeting, etc.) cannot pick up the 3D rendering area of Windows applications, or they will not detect when the 3D area has been updated.

(from DRC @virtualgl-users)

@totaam
Copy link
Collaborator Author

totaam commented Sep 24, 2014

Some fixes:

@totaam
Copy link
Collaborator Author

totaam commented Jun 28, 2015

Generic Window API links:

Window Event Hooks:

  • Hooks: A global hook monitors messages for all threads in the same desktop as the calling thread. A thread-specific hook monitors messages for only an individual thread. A global hook procedure can be called in the context of any application in the same desktop as the calling thread, so the procedure must be in a separate DLL module.
  • RegisterShellHookWindow: This function is not intended for general use. It may be altered or unavailable in subsequent versions of Windows.
  • SetWindowsHookEx or SetWindowsHook: (needs the DLL to be injected? for all but mouse events)
  • with WH_SHELL (The function receives notifications of Shell events from the system.): ShellProc callback function, in particular:
    • HSHELL_REDRAW
    • maybe also: HSHELL_WINDOWACTIVATED, HSHELL_WINDOWCREATED, HSHELL_WINDOWDESTROYED and HSHELL_WINDOWREPLACED, which we could tie with the list of rectangles if we keep the hwnd at hand.
  • with WH_CBT (The system calls this function before activating, creating, destroying, minimizing, maximizing, moving, or sizing a window):

Example code:

@totaam
Copy link
Collaborator Author

totaam commented Jul 22, 2015

r10002 uses Pillow's ImageGrab module to capture the screen on win32, which is already much faster.

It is still quite slow: timeit clocks it at about 100ms for 1080p on a mid-range system, which is a lot better than GTK, but has room for improvement:

  • we call tobytes - which makes a copy, we could avoid this by going pure native via pywin32 and managing the target buffer's lifetime ourselves (and ideally, straight into nvenc's input buffer - tall order!)
  • we use the BGRX format so that we can use nvenc... (we could use whatever RGB format is native to win32 and just add the necessary kernel to nvenc instead, see nvenc support for shadowing on win32 #558)

Some links:

@totaam
Copy link
Collaborator Author

totaam commented Jul 24, 2015

The code in r10002 only captured one screen, this is fixed in r10026, see #637#comment:11 for details. Will backport.

r10028 should help speed things up a bit by re-using the same bitmap and context objects until the display settings change.
But this is still not good enough: it takes about 100ms for copying 4 megapixels (2 x 1080p screens).
About 65% of this time is spent in BitBlt, and the rest is in GetBitmapBits.
The BitBlt performance with Aero enabled is just poor. Disabling aero is a temporary workaround.

We want to stay on the GPU if we can (#365), especially if we're going to use the GPU for encoding (ie: nvenc) - the difference is in the order of a factor 100!

More info:

This will have to do for now. (nvenc needs fixing first anyway... see #389)

@totaam
Copy link
Collaborator Author

totaam commented Dec 26, 2015

r11482 added a basic systray for the shadow server which only shows: "about", "exit" and "close menu".

@totaam
Copy link
Collaborator Author

totaam commented Dec 27, 2015

2015-12-27 08:11:04: antoine uploaded file namedpipes.patch (12.7 KiB)

work in progress named pipes support

@totaam
Copy link
Collaborator Author

totaam commented Mar 25, 2016

Moving the named pipes to #1150.

@totaam
Copy link
Collaborator Author

totaam commented Mar 26, 2016

Keyboard issues in #1099.

Stumbled upon this info python-win32: Global Window Messages: What you probably want is a WH_CBT hook so that you can catch WM_ACTIVATE and WM_DEACTIVATE.
There is some code that does something similar in pyAA apparently.

@totaam
Copy link
Collaborator Author

totaam commented Mar 29, 2016

See my original question to python-win32 mailing list: https://mail.python.org/pipermail/python-win32/2009-September/009584.html
And Win32 WH_CBT Hook - close window before it is created, WH_CBT hook, using SetWindowsHookEx to monitor windows events, KeyboardHookProc in DLL doesn't do anything when called from python

This is going to take some effort and will require Windows 8 or later and probably building things with MSVC 2013 (not the "free" express version..) for the newer API: IDXGIOutputDuplication: The IDXGIOutputDuplication interface accesses and manipulates the duplicated desktop image.

Printing may be possible using redmon: The RedMon port monitor redirects a special printer port to a program

@totaam
Copy link
Collaborator Author

totaam commented Apr 7, 2016

For sound see: wasapisink

r12394 will use directsoundsrc by default for win32 shadow servers

@totaam
Copy link
Collaborator Author

totaam commented May 22, 2016

2016-05-22 12:20:35: antoine commented


  • r12647 should fix sound shadowing on win32 (untested - virtualbox is having a fit)
  • r12707 (skip warnings)

@totaam
Copy link
Collaborator Author

totaam commented Jun 17, 2016

2016-06-17 10:16:22: antoine commented


@totaam
Copy link
Collaborator Author

totaam commented Jun 17, 2016

2016-06-17 14:28:41: antoine commented


r12850 disables composition on vista and later, r12852 + r12853 + r12854 improve error handling - which fires a lot more with vista onwards when the UAC prompt shows up.

@totaam
Copy link
Collaborator Author

totaam commented Sep 20, 2016

A good solution for solving shadow performance issues is #1317 (requires an nvidia card...)

@totaam
Copy link
Collaborator Author

totaam commented Feb 9, 2017

If we go down the directx route, with mingw #678 these may be helpful / needed:

So, by injecting the DLL into every process, we could get individual windows as surfaces.

If we are willing to require windows 8 or later, the solution is likely to be the Desktop Duplication API:

Some links on the logon stuff, which we need for running as a service:

For audio:

@totaam
Copy link
Collaborator Author

totaam commented Apr 20, 2017

Added basic NVIDIA Capture SDK support using basic "copy to system memory" API.
Screen capturing + downloading to system RAM at 4K takes less than 30ms, so we should be able to do 30fps at 4K (given enough bandwidth / fast encoder).

Much more can be done with this API:

  • TODO: error recovery, re-instantiate context on recoverable failures, bubble up if unrecoverable
  • download to RGB since we don't use the alpha channel (will save memory bandwidth and CPU time)
  • integrate with NVENC - via CUDA?
  • port to Linux - the examples refuse to run on Fedora 26 (could be glvnd related?)
  • meh: support 32-bit mode?
  • ARGB10 10-bit colour modes
  • download as YUV420 when quality is set lower? (NVENC is probably better in all cases)

@totaam
Copy link
Collaborator Author

totaam commented Apr 27, 2017

Minor updates in r15727 + r15730. Helped uncover a core imagewrapper bug: r15728.

The NVFBC progress should now be tracked here: #1317.

@totaam
Copy link
Collaborator Author

totaam commented May 23, 2017

Some scripts that could be useful - and not just for shadow servers:

from comtypes.client import CreateObject
o=CreateObject('WbemScripting.SWbemLocator')
s=o.ConnectServer('.', 'root\\cimv2')
res=s.ExecQuery('SELECT * FROM Win32_DisplayConfiguration')
print([int(x.Properties_['BitsPerPel'].Value) for x in res])

Could also be useful for detecting virtualbox:

print([(x.Properties_['DeviceName'].Value) for x in res])
[u'VirtualBox Graphics Adapter']

Now for making a service:

@totaam
Copy link
Collaborator Author

totaam commented Sep 20, 2017

Moving the system service to #1527.

Python3 #1568 is making progress, this may help.

@totaam
Copy link
Collaborator Author

totaam commented Feb 3, 2018

For capturing the screen with directx, a good example is found in the gstreamer source: winscreencap.

See also multi-monitor handling as windows: #1805

@totaam
Copy link
Collaborator Author

totaam commented Jun 25, 2019

NVFBC is now deprecated on windows-10: #1317#comment:11.

DDA example: nvEncDXGIOutputDuplicationSample

@totaam
Copy link
Collaborator Author

totaam commented Dec 2, 2019

@totaam
Copy link
Collaborator Author

totaam commented Oct 1, 2022

Windows 10 Screen capture example code looks simple enough.
Using Windows.Graphics.Capture from a Cython C / C++ context will be harder.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
shadow win32 MS Windows OS
Projects
None yet
Development

No branches or pull requests

1 participant