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