Cannot initialize d3d11screencapturesrc in a Windows service

Pipeline with d3d11screencapturesrc started from Windows service doesn’t work
Instead of actually working, it errors out:

Error: Failed to prepare capture object with given configuration, monitor-index: -1, monitor-handle: 0000000000000000, window-handle: 0000000000000000

Setup:

  • Operating System: Windows 11 23H2
  • GStreamer Version: main (a4c976dd20a9634028b8e68747b16c6ae630db6d)

Reproducing:

  1. Create service with nssm (something like gst-launch-1.0.exe d3d11screencapturesrc ! videoconvert ! x264enc ! h264parse ! mp4mux ! filesink location=test.mp4, set GST_DEBUG=5 and stdout to some file
  2. Start it

Logs: gdrive

Is this expected? If so, how can I record screen from service?

I have not tried the use case but in general service process has limited privileges and it’s isolated. Could you try spawning capture process as an user via CreateProcessAsUser() in your service process?

Thanks for this suggestion. We ended up using startup folder as it was easier and haven’t required developing a custom Windows service.

BTW, is there a way to make d3d11screencapturesrc record all the displays at once (that is, put them side by side in the resulting video stream)? This is what ximagesrc does by default, for example.

DXGI desktop duplication session can capture only single desktop, unlike x11.

So capturing multiple desktops in a single {d3d11,d3d12}screencapturesrc is not supported. You will need to configure multiple source elements and mix streams by using {d3d11,d3d12}compositor or so.

What will be the minimal pipeline for doing this?

This is an example.

gst-launch-1.0.exe d3d12compositor name=c sink_0::xpos=0 sink_1::xpos=640 \
d3d12screencapturesrc monitor-handle={YOUR-HMONITOR-HANDLE} ! queue ! d3d12convert ! "video/x-raw(memory:D3D12Memory),format=BGRA,width=640,height=480,pixel-aspect-ratio=1/1" ! c.sink_0 \
d3d12screencapturesrc monitor-handle={ANOTHER-HMONITOR-HANDLE} ! queue ! d3d12convert ! "video/x-raw(memory:D3D12Memory),format=BGRA,width=640,height=480,pixel-aspect-ratio=1/1" ! c.sink_1 \
c. ! "video/x-raw(memory:D3D12Memory),format=BGRA,width=1280,height=480" ! queue ! d3d12videosink 

Note that you can query monitor resolution, desktop coordinates, etc by using GstDeviceProvider, and gst-device-monitor-1.0.exe "Source/Monitor" will print the information as well.

Then you might want to organize composition layout as you wanted depending on resolution/position of monitors, instead of hardcoding values like the above example pipeline.

1 Like

We’ve tried to start the capture process using runas or by directly modifying the user in the service manager. Nothing changed, same error is still shown.

Interestingly, using task scheduler to run the program didn’t help either. If the task is launched after the login manually (more specifically, by having the batch script in the startup folder), capture works. But automatically launching via triggers leads to the same behavior.

Is there anything else we can try?

Is it even possible to capture login screen via GStreamer in Windows?

BTW, is it possible to enable wgc capture API if GStreamer is cross-compiled with MinGW? It doesn’t seem to be enabled by default for some reason and the capture-api option is rejected in runtime.