gmbeard / shadow-cast

GPU accelerated screen and audio recording for Linux
GNU General Public License v2.0
38 stars 0 forks source link

Contract check failed #36

Closed SleepingPanda closed 3 months ago

SleepingPanda commented 3 months ago

Sorry to open so many issues in such a short space of time. I've tried executing shadow-cast but get this error:

$ shadow-cast Videos/Test.mkv
[hevc_nvenc @ 0x22c30280] ignoring invalid SAR: 0/0
capturing rate: 48000, channels: 2
Finalizing output. Please wait...
Contract check failed: pid_ == -1 - /home/SleepingPanda/shadow-cast/src/io/process.cpp:27
terminate called without an active exception
Aborted (core dumped)

As in the previous issue, I'm on Fedora 40 but also with the latest nvidia proprietary driver. Here's the output of nvidia-smi, uname -a and cat /etc/os-release:

+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 555.58.02              Driver Version: 555.58.02      CUDA Version: 12.5     |
|-----------------------------------------+------------------------+----------------------+
| GPU  Name                 Persistence-M | Bus-Id          Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |           Memory-Usage | GPU-Util  Compute M. |
|                                         |                        |               MIG M. |
|=========================================+========================+======================|
|   0  NVIDIA GeForce GTX 1080        Off |   00000000:01:00.0  On |                  N/A |
|  0%   56C    P8             12W /  240W |     790MiB /   8192MiB |      4%      Default |
|                                         |                        |                  N/A |
+-----------------------------------------+------------------------+----------------------+
$ uname -a
Linux VENUS 6.9.9-200.fc40.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Jul 11 19:29:01 UTC 2024 x86_64 GNU/Linux
$ cat /etc/os-release 
NAME="Fedora Linux"
VERSION="40 (KDE Plasma)"
ID=fedora
VERSION_ID=40
VERSION_CODENAME=""
PLATFORM_ID="platform:f40"
PRETTY_NAME="Fedora Linux 40 (KDE Plasma)"
ANSI_COLOR="0;38;2;60;110;180"
LOGO=fedora-logo-icon
CPE_NAME="cpe:/o:fedoraproject:fedora:40"
DEFAULT_HOSTNAME="fedora"
HOME_URL="https://fedoraproject.org/"
DOCUMENTATION_URL="https://docs.fedoraproject.org/en-US/fedora/f40/system-administrators-guide/"
SUPPORT_URL="https://ask.fedoraproject.org/"
BUG_REPORT_URL="https://bugzilla.redhat.com/"
REDHAT_BUGZILLA_PRODUCT="Fedora"
REDHAT_BUGZILLA_PRODUCT_VERSION=40
REDHAT_SUPPORT_PRODUCT="Fedora"
REDHAT_SUPPORT_PRODUCT_VERSION=40
SUPPORT_END=2025-05-13
VARIANT="KDE Plasma"
VARIANT_ID=kde
gmbeard commented 3 months ago

I'll have to try and reproduce this error myself. I've only tested the Wayland back-end with Gnome and Sway so far, and maybe this is a KDE specific issue.

If you're up to helping diagnose this, then applying the following patch may uncover some more detail about the error...

diff --git a/src/io/process.cpp b/src/io/process.cpp
index b42616c..bfceef7 100644
--- a/src/io/process.cpp
+++ b/src/io/process.cpp
@@ -24,7 +24,7 @@ Process::Process(Process&& other) noexcept
 {
 }

-Process::~Process() { SC_EXPECT(pid_ == -1); }
+Process::~Process() {}

 auto Process::operator=(Process&& other) noexcept -> Process&
 {

No worries if not, though. You've been patient enough :smile:

SleepingPanda commented 3 months ago

I'm fine with testing. I've got the time and patience. Here's what occurs after making that change and rebuilding:

$ shadow-cast ~/Videos/Test.mp4
[hevc_nvenc @ 0x2ee45240] ignoring invalid SAR: 0/0
capturing rate: 48000, channels: 2
Finalizing output. Please wait...
ERROR: Connection timed out
gmbeard commented 3 months ago

Could you paste the output of the following commands...

$ command -v shadow-cast-kms
$ which shadow-cast-kms
SleepingPanda commented 3 months ago
$ command -v shadow-cast-kms 
/usr/local/bin/shadow-cast-kms
$ which shadow-cast-kms
/usr/local/bin/shadow-cast-kms
gmbeard commented 3 months ago

Could you also provide the output of...

$ getcap /usr/local/bin/shadow-cast-kms
SleepingPanda commented 3 months ago
$ getcap /usr/local/bin/shadow-cast-kms
/usr/local/bin/shadow-cast-kms cap_sys_admin=ep
gmbeard commented 3 months ago

Thank you. Everything looks to be installed correctly, so there must be a bug in the Wayland frame capture.

This patch will enable some extra logging to STDERR. It may give some indication where the failure is...

diff --git a/src/kms.cpp b/src/kms.cpp
index bc20e24..ff09a7b 100644
--- a/src/kms.cpp
+++ b/src/kms.cpp
@@ -24,7 +24,7 @@
 using IncomingMessage = sc::DRMRequest;
 using OutgoingMessage = sc::DRMResponse;

-auto constexpr kEnableLogging = false;
+auto constexpr kEnableLogging = true;

 struct NullLogger
 {

(The logging can be quite extensive with this enabled, hence why it's normally disabled)

SleepingPanda commented 3 months ago

It's not excessive unless I'm doing something wrong:

$ shadow-cast ~/Videos/Test.mp4
[hevc_nvenc @ 0x2bb3d140] ignoring invalid SAR: 0/0
capturing rate: 48000, channels: 2
ERROR: DRM not available
Finalizing output. Please wait...
ERROR: Connection timed out

I'm just supposed to change that line, rebuild, reinstall and run shadow-cast like above, right?

gmbeard commented 3 months ago

No, that's fine. It's showing exactly where the problem lies - it's claiming that there isn't a DRM kernel driver loaded.

That's seems odd as it was my understanding that a DRM driver is a prerequisite for running Wayland!

Do you know if you're booting your kernel with the following setting - nvidia_drm.modeset=1

SleepingPanda commented 3 months ago

It seems to be missing from cmdline

$ cat /proc/cmdline 
BOOT_IMAGE=(hd0,gpt2)/vmlinuz-6.9.9-200.fc40.x86_64 root=UUID=496ab329-409d-4028-b148-f4bd7d5e851b ro rd.driver.blacklist=nouveau modprobe.blacklist=nouveau rhgb quiet rd.driver.blacklist=nouveau modprobe.blacklist=nouveau

I'll try adding it manually like explained here and reboot.

SleepingPanda commented 3 months ago

Nothing changed. I can confirm it's enabled by following this guide:

$ sudo cat /sys/module/nvidia_drm/parameters/modeset
Y

and

$ cat /proc/cmdline 
BOOT_IMAGE=(hd0,gpt2)/vmlinuz-6.9.9-200.fc40.x86_64 root=UUID=496ab329-409d-4028-b148-f4bd7d5e851b ro rd.driver.blacklist=nouveau modprobe.blacklist=nouveau rhgb quiet rd.driver.blacklist=nouveau modprobe.blacklist=nouveau nvidia-drm.modeset=1
$ shadow-cast ~/Videos/Test.mp4
[hevc_nvenc @ 0x9a5f000] ignoring invalid SAR: 0/0
capturing rate: 48000, channels: 2
ERROR: DRM not available
Finalizing output. Please wait...
ERROR: Connection timed out
gmbeard commented 3 months ago

I shall have to do some further digging. It may be that a later nvidia driver has changed this behaviour. Appreciate the help with debugging :+1:

SleepingPanda commented 3 months ago

No problem. Let me know if you need any testing done. I'll give any help I can in that regard. This is a great project and any chance to contribute to it (even a little) feels gratifying.

gmbeard commented 3 months ago

@SleepingPanda I'm still struggling to reproduce the ERROR: DRM not available issue. Is there any chance you may be able to try this patch at some point?

diff --git a/src/kms.cpp b/src/kms.cpp
index bc20e24..58c8e1e 100644
--- a/src/kms.cpp
+++ b/src/kms.cpp
@@ -52,7 +52,7 @@ decltype(auto) log()
     }
 }

-[[nodiscard]] auto is_drm_available() -> bool { return drmAvailable() == 1; }
+[[nodiscard]] auto is_drm_available() -> bool { return true; }

 [[nodiscard]] auto get_drm_device_path() -> std::string
 {

I'm wondering if the DRM driver check is reporting a false negative, so this patch will force the DRM check to pass

SleepingPanda commented 3 months ago

I had to stop the output manually because it would get cut off by my terminal's limit:

$ shadow-cast ~/Videos/Test.mp4
[hevc_nvenc @ 0x3866d200] ignoring invalid SAR: 0/0
capturing rate: 48000, channels: 2
[DRM] Checking DRM path: /dev/dri/card0
[DRM] Checking DRM path: /dev/dri/card1
[DRM] Found: nvidia-drm, NVIDIA DRM driver
[DRM] count_fbs: 0
[DRM] Checking plane:
  plane_id: 35
  count_formats: 11
  fb_id: 99
  crtc_id: 41
  crtc_x: 0, crtc_y: 0
  x: 0, y: 0
[DRM] Found FB
[DRM] Connecting to: /tmp/shadow-cast.sock
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
^C[DRM] Stopping
[DRM] Closing DRM FD...
Finalizing output. Please wait...
gmbeard commented 3 months ago

Aha, that looks promising. Does your output file have content?

SleepingPanda commented 3 months ago

It sort of does. It seems corrupted somehow. The colors are strange but I can make out shapes and words.

https://github.com/user-attachments/assets/06874c81-820d-4187-ba0c-2ea6072de10a

gmbeard commented 3 months ago

Thanks for providing that example.

This looks like a pixel format issue. Apologies to keep asking, but would you be able to apply this patch and paste some of the log output? you shouldn't have to run the capture for more than a couple of seconds.

diff --git a/src/kms.cpp b/src/kms.cpp
index bc20e24..d3d9084 100644
--- a/src/kms.cpp
+++ b/src/kms.cpp
@@ -289,6 +289,10 @@ auto get_fb(int drm_fd) -> OutgoingMessage
         msg.descriptors[descriptor_index].modifier = fb->modifier;

         log() << "[DRM] Got FB FD: " << fb_fd << '\n';
+        log() << "[DRM] Pixel format: " << static_cast<char>(fb->pixel_format)
+              << static_cast<char>(fb->pixel_format >> 8)
+              << static_cast<char>(fb->pixel_format >> 16)
+              << static_cast<char>(fb->pixel_format >> 24) << '\n';
         log() << "[DRM] FB: " << fb->handles[0] << ' ' << fb->handles[1] << ' '
               << fb->handles[2] << ' ' << fb->handles[3] << '\n';
SleepingPanda commented 3 months ago
$ shadow-cast ~/Videos/Test.mp4 
[hevc_nvenc @ 0xf0492c0] ignoring invalid SAR: 0/0
capturing rate: 48000, channels: 2
[DRM] Checking DRM path: /dev/dri/card0
[DRM] Checking DRM path: /dev/dri/card1
[DRM] Found: nvidia-drm, NVIDIA DRM driver
[DRM] count_fbs: 0
[DRM] Checking plane:
  plane_id: 35
  count_formats: 11
  fb_id: 100
  crtc_id: 41
  crtc_x: 0, crtc_y: 0
  x: 0, y: 0
[DRM] Found FB
[DRM] Connecting to: /tmp/shadow-cast.sock
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] Pixel format: AB30
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] Pixel format: AB30
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] Pixel format: AB30
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] Pixel format: AB30
[DRM] FB: 1 0 0 0

Still looks corrupted

https://github.com/user-attachments/assets/15cc58a4-38c9-4943-b968-2a585e75eb88

gmbeard commented 3 months ago

Thanks. Ok, that looks like a "10bit" pixel format. Do you have HDR enabled by any chance. If so, are you able to switch to non HDR temporarily to see if that has any effect?

SleepingPanda commented 3 months ago

Nope I'm not using HDR, but I am using my display's ICC profile. Would that have something to do with it? Edit: Just tested without it and it still looks the same.

gmbeard commented 3 months ago

Potentially, yeah. Shadow Cast naively only supports 8bit per pixel formats on Wayland, currently. The colorspace / color conversion needs a bit of TLC

SleepingPanda commented 3 months ago

Disabling the color profile didn't change anything though. What else can I do?

gmbeard commented 3 months ago

I found this post about KDE's default color depth - https://discuss.kde.org/t/kde-wayland-view-set-color-bit-depth/2019/2

It suggests that KDE defaults to 10 bit-per-pixel color if it's supported (which is what appears to be happening in our case), and you can change it by adding this to /etc/environment (would require a reboot)

KWIN_DRM_PREFER_COLOR_DEPTH=24

I can't vouch for this, though, so it's up to you if you're comfortable trying it or not. Idealy, I need to fix this in Shadow Cast itself

SleepingPanda commented 3 months ago

I'm sorry to always bring you bad news, but no, it didn't work.

$ shadow-cast ~/Videos/Test.mp4
[hevc_nvenc @ 0x3cf08840] ignoring invalid SAR: 0/0
capturing rate: 48000, channels: 2
[DRM] Checking DRM path: /dev/dri/card0
[DRM] Checking DRM path: /dev/dri/card1
[DRM] Found: nvidia-drm, NVIDIA DRM driver
[DRM] count_fbs: 0
[DRM] Checking plane:
  plane_id: 35
  count_formats: 11
  fb_id: 100
  crtc_id: 41
  crtc_x: 0, crtc_y: 0
  x: 0, y: 0
[DRM] Found FB
[DRM] Connecting to: /tmp/shadow-cast.sock
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] Pixel format: AB30
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] Pixel format: AB30
[DRM] FB: 1 0 0 0
[DRM] Closing 1 fds
[DRM] Got Plane
[DRM] Got FB FD: 5
[DRM] Pixel format: AB30

https://github.com/user-attachments/assets/3daa5acf-90be-46cb-976d-e4dd45fcb205

gmbeard commented 3 months ago

Ah, looks like that env var had no effect. Worth a try!

No problem. I'm going to spend some time implementing proper color conversion for Wayland - I've been putting it off long enough at this point, really!

Really appreciate your help with debugging these issues. You've been more than helpful. Nice work :smile:

I'll probably open some new GitHub issues to track some of the problems we've faced here - They can be useful for posterity if others have similar issues

gmbeard commented 3 months ago

Hi @SleepingPanda,

I've done a first pass of the color conversion. I' haven't yet managed to get KDE plasma running to test it myself, but feel free to try it yourself if you wish - it's on the fix/drm-color-conversion branch.

SleepingPanda commented 3 months ago

Hey @gmbeard,

I'll give it a try later today and reply back with results. Thanks for putting in the work to get this working!

gmbeard commented 3 months ago

No problem. Thank you.

BTW, I'm now tracking this issue here: https://github.com/gmbeard/shadow-cast/issues/39, so I will close this one