smasherprog / screen_capture_lite

cross platform screen/window capturing library
MIT License
638 stars 156 forks source link

Many blank windows #87

Closed JoeLudwig closed 4 years ago

JoeLudwig commented 4 years ago

This could be related to #72 but doesn't seem to have anything to do with DX12, so I doubt it.

image

This is every window that survives the filtering process described in #86. Some of them work fine, but most windows come out as all zeros (black and zero alpha.) In some cases (like the Steam client) some of content is captured, but most is not. One common thread seems to be that most of these windows (Hangouts, Chrome, a few windows from the Steam client) are all showing web content from Chromium.

The exception from that is the VR View window from SteamVR, which is a shared texture rendered by Qt.

Any idea what might be going on here? Can you repro the problem with the Steam client? It should be easy to get your hands on...

smasherprog commented 4 years ago

I have no idea whats going on here or exactly what you are trying to describe. Are you saying you are doing VR and trying to stream windows into the VR world?

JoeLudwig commented 4 years ago

The VR part is just how I'm displaying the textures. The textures I'm getting out of the library are all black with zero alpha.

JoeLudwig commented 4 years ago

Sorry the previous screenshot was unclear. Here's an image of the Steam client window as captured by the screen_capture_lite example. The only changes I made was to change the "cmake" filter string to "steam" and uncomment the lines that save a JPG on each capture.

2WINDIF_

For reference, here's what it should look like: image

JoeLudwig commented 4 years ago

Here's Chrome displaying this very bug: It seems like all content rendered by Chromium is broken.

5WINDIF_

JoeLudwig commented 4 years ago

I wonder if the missing content in these contexts is from owned windows. Chromium itself seems to explicitly walk them and copy them into the captured buffer when capturing desktop windows for RTC: https://chromium.googlesource.com/external/webrtc/+/refs/heads/lkgr/modules/desktop_capture/window_capturer_win.cc#422

That looks pretty likely from looking at Spy++: image

smasherprog commented 4 years ago

hmmmmm interesting.... it will take me some time to get around to this. if you wana take a stab at it. the code is pretty short https://github.com/smasherprog/screen_capture_lite/blob/964494851bcc6234d8c00fe40b52e608d41d8ce6/src/windows/GDIFrameProcessor.cpp#L85

but you could be right. The code needs to traverse the inner windows and copy the data. Shouldnt be too hard

JoeLudwig commented 4 years ago

Yeah I did some exploring in there and looked at the windows that aren't working in Spy++. It seems that in this case there aren't any popup windows, but there are layered windows and windows with the WS_EX_NOREDIRECTIONBITMAP style. I think those may need to be composited too. I don't know if I'll get another chance to look before the weekend, but we'll see how it goes.

JoeLudwig commented 4 years ago

In trying to fix this bug I encounted another source of black windows: Moving a window to a secondary monitor.

That may be #81. I have 150% scaling on my primary monitor. The code to select the monitor DC seems about right, so I don't think it's that. (Though if a window moves from one monitor to another does that mean the capture object needs to be destroyed and recreate? How does an app know to do that?)

smasherprog commented 4 years ago

u Working in a fork? If you have a partial fix for this, lets get it into master!

JoeLudwig commented 4 years ago

I don't have anything working yet. I just local changes that are broken in new and interesting ways. :)

smasherprog commented 4 years ago

if you want to work in a branch ill help out

JoeLudwig commented 4 years ago

I can't make a branch in your repo, but here's a fork with my not-yet-functional changes: https://github.com/JoeLudwig/screen_capture_lite/tree/joe_working_on_blank_windows

I don't know if I'm using bitblt wrong, if I'm picking the wrong window, or what. Still a black rect for any of this type of content.

JoeLudwig commented 4 years ago

I'm beginning to think that the problem is that GDI can't read windows that only contain D3D output. So even when using BitBlt on the child windows directly it still returns black pixels. The "popup windows" thing in Chromium is mostly about menus and dialogs, I think.

TrentWeiss commented 4 years ago

Perhaps it's worth looking into using the Windows GraphicsCapture API (the "modern" Windows way of doing this).

There is a (somewhat spaghetti-code) example here.