dec05eba / gpu-screen-recorder-issues

GPU Screen Recorder issue tracker
15 stars 0 forks source link

[BUG] Display "screen" not found - Multi-GPU system #25

Closed DatCaptainHorse closed 3 months ago

DatCaptainHorse commented 3 months ago

Describe the bug gpu-screen-recorder is unable to capture screen when X11 is run on GPU another than /dev/dri/card0.

To Reproduce gpu-screen-recorder -w screen -c flv -f 60 -o /game/testout.flv Run within system with multiple GPU's (iGPU+dGPU for example), where the /dev/dri/card1 is used to run X11.

Screenshots If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

Additional context Output given by program:

Warning: opus audio codec is only supported by .mp4, .mkv and .webm files, falling back to aac instead
[h264_vaapi @ 0x5621bee0aa40] ignoring invalid SAR: 0/0
Info: using h264 encoder because a codec was not specified
Error: no available output found
gsr error: display "screen" not found, expected one of:
    "screen"

xrandr -q output:

Screen 0: minimum 320 x 200, current 1920 x 1080, maximum 16384 x 16384
DP-1 disconnected (normal left inverted right x axis y axis)
HDMI-1 disconnected primary 1920x1080+0+0 (normal left inverted right x axis y axis) 0mm x 0mm
   "1920x1080R"  59.93* 
DP-2 disconnected (normal left inverted right x axis y axis)
HDMI-2 disconnected (normal left inverted right x axis y axis)
DP-3 disconnected (normal left inverted right x axis y axis)
HDMI-3 disconnected (normal left inverted right x axis y axis)

trying to give X11 DISPLAY by -w ":0" doesn't work either:

gsr error: display ":0" not found, expected one of:
    "screen"

Only working method is to give -w a X11 window ID. But yeah that's not that seamless.

xwininfo -tree -root output, just in case that's useful:

xwininfo: Window id: 0x74a (the root window) (has no name)

  Root window id: 0x74a (the root window) (has no name)
  Parent window id: 0x0 (none)
     30 children:
     0x1400006 (has no name): ("steam_proton" "steam_proton")  1x1+0+0  +0+0
     0xa00008 (has no name): ("steam_proton" "steam_proton")  1x1+0+0  +0+0
     0x1400004 "Default IME": ("steam_proton" "steam_proton")  1x1+0+0  +0+0
     0xe00014 (has no name): ()  1x1+0+0  +0+0
     0xe0000e (has no name): ()  1x1+-1+-1  +-1+-1
     0x1200001 "Input": ("steam_proton" "steam_proton")  111x1+8+34  +8+34
     0x1200002 "Default IME": ("steam_proton" "steam_proton")  1x1+0+0  +0+0
     0x1000009 (has no name): ()  1x1+-1+-1  +-1+-1
     0xc00001 (has no name): ()  1x1+0+0  +0+0
     0xa00007 (has no name): ("steam_proton" "steam_proton")  1x1+0+0  +0+0
     0xa00006 (has no name): ("steam_proton" "steam_proton")  1x1+0+0  +0+0
     0xa00005 (has no name): ("steam_proton" "steam_proton")  1x1+0+0  +0+0
     0xa00004 (has no name): ("steam_proton" "steam_proton")  1x1+0+0  +0+0
     0xa00002 (has no name): ("steam_proton" "steam_proton")  160x20+3+29  +3+29
     0xa00003 "Default IME": ("steam_proton" "steam_proton")  1x1+0+0  +0+0
     0x800035 (has no name): ()  1x1+-1+-1  +-1+-1
     0xa00001 (has no name): ()  1x1+0+0  +0+0
     0x400001 (has no name): ()  10x10+-20+-20  +-20+-20
     0x20000e "Openbox": ("" (none))  1x1+-100+-100  +-100+-100
     0x200062 (has no name): ()  1x1+0+0  +0+0
        1 child:
        0x200063 (has no name): ()  1x1+0+0  +1+1
     0x200060 (has no name): ()  1x1+0+0  +0+0
        1 child:
        0x200061 (has no name): ()  1x1+0+0  +1+1
     0x20005d (has no name): ()  1x1+0+0  +0+0
        1 child:
        0x20005e (has no name): ()  1x1+0+0  +1+1
     0x200059 (has no name): ("OPENBOX_FOCUS_CYCLE_POPUP" "OPENBOX_FOCUS_CYCLE_POPUP")  1x1+0+0  +0+0
        3 children:
        0x20005c (has no name): ()  1x1+0+0  +1+1
        0x20005b (has no name): ()  1x1+0+0  +1+1
        0x20005a (has no name): ()  1x1+0+0  +1+1
     0x200056 (has no name): ()  1x1+0+0  +0+0
        2 children:
        0x200058 (has no name): ()  1x1+0+0  +1+1
        0x200057 (has no name): ()  1x1+0+0  +1+1
     0x200055 (has no name): ()  1x1+0+0  +0+0
     0x200054 (has no name): ()  1x1+0+0  +0+0
     0x200053 (has no name): ()  1x1+0+0  +0+0
     0x200052 (has no name): ()  1x1+0+0  +0+0
     0x20005f (has no name): ()  1x1+0+0  +0+0
     0x200064 (has no name): ()  1282x743+319+158  +319+158
        56 children:
        0x1400003 "Noita - Build Apr 30 2024 - 00:44:54": ("steam_proton" "steam_proton")  1280x720+1+22  +320+180
           1 child:
           0xe0002a (has no name): ()  1280x720+0+0  +320+180
        0x2000b0 (has no name): ()  1x1+0+0  +319+158
        0x2000af (has no name): ()  1x1+0+0  +319+158
        0x2000ae (has no name): ()  1x1+0+0  +319+158
        0x2000ad (has no name): ()  1x1+0+0  +319+158
        0x2000ac (has no name): ()  1x1+0+0  +319+158

# Rest cut off to keep length sane #

Note that ffmpeg kmsgrab does almost work, ffmpeg -hide_banner -v verbose -device /dev/dri/card1 -framerate 60 -f kmsgrab -i - -an -filter:v 'hwmap=derive_device=vaapi,scale_vaapi=format=nv12' -c:v h264_vaapi -b:v 4000k -maxrate 8000k /game/testffmpegout.mkv output:

[AVHWDeviceContext @ 0x56436e2b7580] Opened DRM device /dev/dri/card1: driver i915 version 1.6.0.
[kmsgrab @ 0x56436e2b7000] Using plane 31 to locate framebuffers.
[kmsgrab @ 0x56436e2b7000] Template framebuffer is 132: 1920x1080 format 34325258 modifier 100000000000001 flags 2.
[kmsgrab @ 0x56436e2b7000] Format is bgr0, from DRM format 34325258 modifier 100000000000001.
Input #0, kmsgrab, from 'fd:':
  Duration: N/A, start: 1718211470.200318, bitrate: N/A
  Stream #0:0: Video: wrapped_avframe, 1 reference frame, drm_prime, 1920x1080, 59.94 tbr, 1000k tbn
Stream mapping:
  Stream #0:0 -> #0:0 (wrapped_avframe (native) -> h264 (h264_vaapi))
[graph 0 input from stream 0:0 @ 0x56436e2c7780] w:1920 h:1080 pixfmt:drm_prime tb:1/1000000 fr:60000/1001 sar:0/1
[AVHWDeviceContext @ 0x56436e2c9580] Using render node /dev/dri/renderD129 in place of non-render DRM device.
[AVHWDeviceContext @ 0x56436e2c9580] libva: VA-API version 1.19.0
[AVHWDeviceContext @ 0x56436e2c9580] libva: Trying to open /usr/lib/x86_64-linux-gnu/dri/iHD_drv_video.so
[AVHWDeviceContext @ 0x56436e2c9580] libva: Found init function __vaDriverInit_1_18
[AVHWDeviceContext @ 0x56436e2c9580] libva: va_openDriver() returns 0
[AVHWDeviceContext @ 0x56436e2c9580] Initialised VAAPI connection: version 1.19
[AVHWDeviceContext @ 0x56436e2c9580] VAAPI driver: Intel iHD driver for Intel(R) Gen Graphics - 23.2.3 ().
[AVHWDeviceContext @ 0x56436e2c9580] Driver not found in known nonstandard list, using standard behaviour.
[h264_vaapi @ 0x56436e2bac00] Using input frames context (format vaapi) with h264_vaapi encoder.
[h264_vaapi @ 0x56436e2bac00] Input surface format is nv12.
[h264_vaapi @ 0x56436e2bac00] Using VAAPI profile VAProfileH264High (7).
[h264_vaapi @ 0x56436e2bac00] Using VAAPI entrypoint VAEntrypointEncSlice (6).
[h264_vaapi @ 0x56436e2bac00] Using VAAPI render target format YUV420 (0x1).
[h264_vaapi @ 0x56436e2bac00] RC mode: AVBR.
[h264_vaapi @ 0x56436e2bac00] RC target: 4000000 bps converging in 120 frames with 100% accuracy.
[h264_vaapi @ 0x56436e2bac00] RC framerate: 60000/1001 (59.94 fps).
[h264_vaapi @ 0x56436e2bac00] Driver does not report any additional prediction constraints.
[h264_vaapi @ 0x56436e2bac00] Using intra, P- and B-frames (supported references: 8 / 2).
[h264_vaapi @ 0x56436e2bac00] All wanted packed headers available (wanted 0xd, found 0x1f).
[h264_vaapi @ 0x56436e2bac00] Using level 4.2.
...

However the output is odd, it's as if it's doing 1 FPS (see attached video).

https://github.com/dec05eba/gpu-screen-recorder-issues/assets/14197772/c76c7f7f-b43a-4635-8c7e-4e2cd0f6140a

dec05eba commented 3 months ago

Include the sudo drm_info > log.txt output as mentioned in the report template..

dec05eba commented 3 months ago

Also, can you include the output of glxinfo and eglinfo?

DatCaptainHorse commented 3 months ago

Knew I had forgotten something :sweat_smile: - here you go! glxlog.txt egllog.txt drminfolog.txt

dec05eba commented 3 months ago

For some reason your driver is saying that the monitor is disconnected, so the error gpu screen recorder gives is correct that there are no available outputs. But it still says that the display is displaying something. I didn't even know that you could display something on a disconnected monitor. Is the monitor connected (and enabled) or not?

dec05eba commented 3 months ago

Thats for the first HDMI output, it says that its displaying graphics at 1080p but that its disconnected at the same time.

DatCaptainHorse commented 3 months ago

Yeah.. I found a very odd way to make that work using xrandr, here's the snippet of what's done to make that happen:

# Additional non-NVIDIA configuration required
if [[ ! "${selected_gpu,,}" =~ "nvidia" ]]; then
  modeline_xrandr="$(echo $MODELINE | sed 's/Modeline //')"
  modeline_mode="$(echo $modeline_xrandr | grep -o '"[^"]*"')"
  xrandr --newmode $(echo $modeline_xrandr)

  # We need to get a disconnected output for our shenanigans
  # priorize "HDMI-n" outputs as "DP-n" ones seem to have trouble with configuring output multiple times
  disconnected_output=$(xrandr --query | grep -Eo 'HDMI-[0-9]+ disconnected' | head -1 | awk '{print $1}')
  if [ -z "$disconnected_output" ]; then
    disconnected_output=$(xrandr --query | grep -Eo 'DP-[0-9]+ disconnected' | head -1 | awk '{print $1}')
  fi

  echo "Configuring output: '$disconnected_output' to use mode '$modeline_mode'"
  xrandr --addmode "$disconnected_output" $(echo $modeline_mode)
  xrandr --output "$disconnected_output" --primary --mode $(echo $modeline_mode)
fi

This somehow makes Xorg work with custom resolution under full GPU acceleration, without a connected display or dummy plug on non-NVIDIA GPU's.

dec05eba commented 3 months ago

I could technically make it work with disconnected output as well but im not sure if that is just a hack. There might be other applications or things that break as well if the output isn't connected. This setup doesn't happen on real systems.

DatCaptainHorse commented 3 months ago

Yeah that's valid reasoning, though now that this hack has been cooked and is on the open, I know bunch of projects that have wanted something like this for ages :sweat_smile: - In that case they can use x11grab or so thru ffmpeg I suppose? Since that worked in my testing without trouble (maybe latency?).

On real system config I'd still be nice to have some kind of way to let gpu-screen-recorder know which device to use primarily, but that's already on your TODO comments :+1:

Feel free to close if there's nothing else to it!

dec05eba commented 3 months ago

x11grab is bad for performance so its not a good solution, and especially as it blocks the entire X server when its grabbing frames so in some cases and especially at high resolutions it will cause a lot of mouse stutter in games even at high fps.

And I think I know why kmsgrab behaves like that.. if you do graphical things outside monitor areas it will limit fps to 1 to reduce power usage when things are not visible on the screen. So I guess even if i make gpu screen recorder work with that disconnected output it will likely have the same issue. Grabbing a single window is different since I think those become special windows that dont run at 1 fps. Something like that, dunno.

dec05eba commented 3 months ago

You can try it, go to src/utils.cc in gpu screen recorder and comment out lines 221-224 (where it checks for DRM_MODE_CONNECTED) and check if screen recording works without lag

dec05eba commented 3 months ago

oh and also on line 74, remove && out_info->connection == RR_Connected

DatCaptainHorse commented 3 months ago

:tada: Well that allows it to capture just like ffmpeg, but also at 1 FPS like ffmpeg :sweat_smile:

I wonder if there's any way to force the limiter off :thinking:

dec05eba commented 3 months ago

a hack would be to maybe have a compositor running, unless the compositor is optimized to not composite windows that are not visible on the screen :p. Or try more if you can get it to say that the monitor is connected so it appears as a regular working system.

dec05eba commented 3 months ago

I wonder if there's any way to force the limiter off 🤔

I think there is a driver option for this, but I cant see any right now. But getting the output to work correctly in docker would be better. Im sure there has to be a way to do it properly. The same thing will have to be done for amd as amd also behaves like that with 1 fps for window outside monitor (so it might be a mesa thing instead or even x11 modesetting driver thing, i forgot).

DatCaptainHorse commented 3 months ago

Option "AsyncFlipSecondaries" "yes" seems to have done it :laughing:

If you don't want to make those code changes into a flag like --allow-totally-broken-usecases, I'll just use a patch for it :+1:

https://github.com/dec05eba/gpu-screen-recorder-issues/assets/14197772/f24aa4a2-0bb0-472b-9912-e038ae347b8d

dec05eba commented 3 months ago

Yeah you will have to use a patch for it as im sure there is a way to do it properly. If it later turns out that there is no proper way to do it then I can add a flag to allow this use case.

DatCaptainHorse commented 3 months ago

Alright! Thanks for such quick responses and help! I'll finally let you rest :P