diff --git a/packaging/systemd/daedalus-v4l2.modules-load b/packaging/systemd/daedalus-v4l2.modules-load new file mode 100644 index 0000000..e7c22c2 --- /dev/null +++ b/packaging/systemd/daedalus-v4l2.modules-load @@ -0,0 +1,6 @@ +# /etc/modules-load.d/daedalus-v4l2.conf +# +# Load the daedalus_v4l2 kernel module at boot so /dev/daedalus-v4l2 +# + /dev/videoNN (V4L2 m2m decoder) + /dev/mediaNN (request API) +# come up before the daedalus-v4l2.service unit fires. +daedalus_v4l2 diff --git a/packaging/systemd/daedalus-v4l2.service b/packaging/systemd/daedalus-v4l2.service new file mode 100644 index 0000000..e9e75bb --- /dev/null +++ b/packaging/systemd/daedalus-v4l2.service @@ -0,0 +1,66 @@ +# SPDX-License-Identifier: BSD-2-Clause +# +# daedalus-v4l2 userspace decoder daemon. +# +# Pairs with the daedalus_v4l2 kernel module (DKMS-built into +# /lib/modules/.../updates/dkms/daedalus_v4l2.ko). When the +# module loads it creates /dev/daedalus-v4l2 (chardev bridge). +# This unit starts the userspace daemon that holds the chardev +# open and answers REQ_DECODE requests with FFmpeg-software +# decode + dmabuf-back. +# +# Without the daemon running, libva / V4L2 clients can S_FMT / +# REQBUFS / QBUF against /dev/videoNN but the decode never +# returns (device_run sends REQ_DECODE into the chardev and +# nothing answers). Always-on is the right disposition. + +[Unit] +Description=daedalus-v4l2 userspace decoder daemon +Documentation=https://git.reauktion.de/reauktion/daedalus-v4l2 + +# Wait until /dev/daedalus-v4l2 actually exists. systemd +# auto-derives the device unit name from the path. The kernel +# module is loaded via /etc/modules-load.d/daedalus-v4l2.conf +# (see daedalus-v4l2.modules-load) earlier in the boot sequence. +After=systemd-modules-load.service +Wants=systemd-modules-load.service +ConditionPathExists=/dev/daedalus-v4l2 + +[Service] +Type=simple +ExecStart=/usr/bin/daedalus_v4l2_daemon daemon + +# Daemon needs read+write on the chardev (created mode 0660 by +# the kernel module, owner root:video). Run as root for simplicity; +# can be relaxed to a daedalus system user with `video` supplementary +# group when we add the user. +User=root + +# Recover from crashes. RestartSec=2 picks a small but non-zero +# backoff so a tight crash-loop doesn't burn CPU. +Restart=on-failure +RestartSec=2 + +# Resource hygiene. Daemon's RSS settles around 25 MiB (per +# Phase 8.9 stress test); the cap is well above that to leave +# headroom for FFmpeg internal state on large frames. +MemoryHigh=128M +MemoryMax=256M + +# Hardening — keep what the daemon doesn't need locked down. +NoNewPrivileges=true +ProtectSystem=strict +ProtectHome=true +PrivateTmp=true +PrivateDevices=false # we need /dev/daedalus-v4l2 +ProtectKernelTunables=true +ProtectKernelModules=true +ProtectControlGroups=true +RestrictNamespaces=true +RestrictRealtime=true +LockPersonality=true +SystemCallFilter=@system-service +SystemCallErrorNumber=EPERM + +[Install] +WantedBy=multi-user.target