Merge pull request #67 from TsaiGaggery/fix-camera-v4l2-relayd-v2
intel-ipu7-camera: v4l2-relayd with OBS and Zoom fixes
This commit is contained in:
1 parent
b19cf292e8
commit
e3ed6931a0
11 files changed
+92
-237
No files matched your search
@@ -0,0 +1,8 @@
|
|||||||
|
# Hide raw IPU7 ISYS capture devices from ALL applications.
|
||||||
|
# These are internal ISP nodes that output raw 12-bit Bayer data and cannot produce usable frames.
|
||||||
|
# Camera is provided via v4l2loopback (/dev/video50) through v4l2-relayd instead.
|
||||||
|
#
|
||||||
|
# This rule MUST run after 70-uaccess.rules (which adds TAG="uaccess" to video4linux)
|
||||||
|
# but BEFORE 73-seat-late.rules (which applies per-user ACLs based on that tag).
|
||||||
|
# MODE=0600 + GROUP=root blocks even users in the 'video' group.
|
||||||
|
SUBSYSTEM=="video4linux", ATTR{name}=="Intel IPU7 ISYS Capture *", TAG-="uaccess", TAG-="seat", MODE="0600", GROUP="root"
|
||||||
@@ -1,6 +1 @@
|
|||||||
KERNEL=="ipu7-psys0", MODE="0666", SYMLINK+="ipu-psys0"
|
KERNEL=="ipu7-psys0", MODE="0666", SYMLINK+="ipu-psys0"
|
||||||
|
|
||||||
# Hide raw IPU7 ISYS capture devices from applications.
|
|
||||||
# These are internal ISP nodes that cannot produce frames directly.
|
|
||||||
# Camera is provided via v4l2loopback (/dev/video50) instead.
|
|
||||||
SUBSYSTEM=="video4linux", ATTR{name}=="Intel IPU7 ISYS Capture *", TAG-="uaccess"
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
# Maintainer: Omarchy <packages@omarchy.org>
|
# Maintainer: Omarchy <packages@omarchy.org>
|
||||||
|
|
||||||
pkgname=intel-ipu7-camera
|
pkgname=intel-ipu7-camera
|
||||||
pkgver=1.0.2
|
pkgver=1.0.3
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
pkgdesc="Intel IPU7 MIPI camera stack for Hurrican/Performance (OV08X40 + hardware ISP)"
|
pkgdesc="Intel IPU7 MIPI camera stack for Hurrican/Performance (OV08X40 + hardware ISP)"
|
||||||
arch=('x86_64')
|
arch=('x86_64')
|
||||||
@@ -11,13 +11,13 @@ depends=(
|
|||||||
'dkms'
|
'dkms'
|
||||||
'linux-headers'
|
'linux-headers'
|
||||||
'v4l2loopback-dkms'
|
'v4l2loopback-dkms'
|
||||||
|
'v4l2-relayd'
|
||||||
'gstreamer'
|
'gstreamer'
|
||||||
'gst-plugins-base'
|
'gst-plugins-base'
|
||||||
'gst-plugins-good'
|
'gst-plugins-good'
|
||||||
'gst-plugins-bad'
|
'gst-plugins-bad'
|
||||||
'jsoncpp'
|
'jsoncpp'
|
||||||
'libdrm'
|
'libdrm'
|
||||||
'python'
|
|
||||||
)
|
)
|
||||||
makedepends=(
|
makedepends=(
|
||||||
'git'
|
'git'
|
||||||
@@ -48,16 +48,16 @@ source=(
|
|||||||
"dkms-vision-drivers.conf"
|
"dkms-vision-drivers.conf"
|
||||||
"camera-deps.conf"
|
"camera-deps.conf"
|
||||||
"v4l2loopback-modprobe.conf"
|
"v4l2loopback-modprobe.conf"
|
||||||
"v4l2loopback-modules-load.conf"
|
|
||||||
"camera-init.service"
|
"camera-init.service"
|
||||||
"camera-feed-watch"
|
|
||||||
"camera-feed-watch.service"
|
|
||||||
"hide-ipu7-v4l2.conf"
|
"hide-ipu7-v4l2.conf"
|
||||||
"disable-libcamera.conf"
|
"disable-libcamera.conf"
|
||||||
|
"71-ipu7-hide-isys.rules"
|
||||||
"90-ipu7-psys.rules"
|
"90-ipu7-psys.rules"
|
||||||
"camera-tmpfiles.conf"
|
"camera-tmpfiles.conf"
|
||||||
"ov08x40.yaml"
|
"ov08x40.yaml"
|
||||||
"camera-sleep-hook"
|
"camera-sleep-hook"
|
||||||
|
"v4l2-relayd-ipu7.conf"
|
||||||
|
"v4l2-relayd-ipu7-override.conf"
|
||||||
)
|
)
|
||||||
sha256sums=(
|
sha256sums=(
|
||||||
'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP'
|
'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP'
|
||||||
@@ -194,16 +194,10 @@ package() {
|
|||||||
"${pkgdir}/usr/lib/modprobe.d/camera-deps.conf"
|
"${pkgdir}/usr/lib/modprobe.d/camera-deps.conf"
|
||||||
install -Dm644 "${srcdir}/v4l2loopback-modprobe.conf" \
|
install -Dm644 "${srcdir}/v4l2loopback-modprobe.conf" \
|
||||||
"${pkgdir}/usr/lib/modprobe.d/v4l2loopback-camera.conf"
|
"${pkgdir}/usr/lib/modprobe.d/v4l2loopback-camera.conf"
|
||||||
install -Dm644 "${srcdir}/v4l2loopback-modules-load.conf" \
|
|
||||||
"${pkgdir}/usr/lib/modules-load.d/v4l2loopback.conf"
|
|
||||||
|
|
||||||
# systemd
|
# systemd
|
||||||
install -Dm644 "${srcdir}/camera-init.service" \
|
install -Dm644 "${srcdir}/camera-init.service" \
|
||||||
"${pkgdir}/usr/lib/systemd/system/camera-init.service"
|
"${pkgdir}/usr/lib/systemd/system/camera-init.service"
|
||||||
install -Dm644 "${srcdir}/camera-feed-watch.service" \
|
|
||||||
"${pkgdir}/usr/lib/systemd/user/camera-feed-watch.service"
|
|
||||||
install -Dm755 "${srcdir}/camera-feed-watch" \
|
|
||||||
"${pkgdir}/usr/bin/camera-feed-watch"
|
|
||||||
|
|
||||||
# WirePlumber
|
# WirePlumber
|
||||||
install -Dm644 "${srcdir}/hide-ipu7-v4l2.conf" \
|
install -Dm644 "${srcdir}/hide-ipu7-v4l2.conf" \
|
||||||
@@ -211,9 +205,17 @@ package() {
|
|||||||
install -Dm644 "${srcdir}/disable-libcamera.conf" \
|
install -Dm644 "${srcdir}/disable-libcamera.conf" \
|
||||||
"${pkgdir}/usr/share/wireplumber/wireplumber.conf.d/disable-libcamera.conf"
|
"${pkgdir}/usr/share/wireplumber/wireplumber.conf.d/disable-libcamera.conf"
|
||||||
|
|
||||||
# udev / tmpfiles / libcamera tuning
|
# udev rules
|
||||||
|
install -Dm644 "${srcdir}/71-ipu7-hide-isys.rules" \
|
||||||
|
"${pkgdir}/usr/lib/udev/rules.d/71-ipu7-hide-isys.rules"
|
||||||
install -Dm644 "${srcdir}/90-ipu7-psys.rules" \
|
install -Dm644 "${srcdir}/90-ipu7-psys.rules" \
|
||||||
"${pkgdir}/usr/lib/udev/rules.d/90-ipu7-psys.rules"
|
"${pkgdir}/usr/lib/udev/rules.d/90-ipu7-psys.rules"
|
||||||
|
|
||||||
|
# v4l2-relayd config for IPU7 camera
|
||||||
|
install -Dm644 "${srcdir}/v4l2-relayd-ipu7.conf" \
|
||||||
|
"${pkgdir}/etc/v4l2-relayd.d/ipu7.conf"
|
||||||
|
install -Dm644 "${srcdir}/v4l2-relayd-ipu7-override.conf" \
|
||||||
|
"${pkgdir}/etc/systemd/system/v4l2-relayd@ipu7.service.d/override.conf"
|
||||||
install -Dm644 "${srcdir}/camera-tmpfiles.conf" \
|
install -Dm644 "${srcdir}/camera-tmpfiles.conf" \
|
||||||
"${pkgdir}/usr/lib/tmpfiles.d/camera.conf"
|
"${pkgdir}/usr/lib/tmpfiles.d/camera.conf"
|
||||||
install -Dm644 "${srcdir}/ov08x40.yaml" \
|
install -Dm644 "${srcdir}/ov08x40.yaml" \
|
||||||
|
|||||||
@@ -1,144 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
"""On-demand camera feed for v4l2loopback.
|
|
||||||
|
|
||||||
Holds /dev/video50 open permanently so v4l2loopback stays in capture mode.
|
|
||||||
Writes black frames when idle (0% CPU, LED off). Starts the real camera
|
|
||||||
pipeline when an app opens the device, relaying frames through the same fd.
|
|
||||||
Stops the camera when all readers close. No fd gap = no stream interruption.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import fcntl, os, signal, struct, subprocess, sys, threading, time
|
|
||||||
|
|
||||||
DEVICE = "/dev/video50"
|
|
||||||
W, H = 1920, 1080
|
|
||||||
FSIZE = W * H * 3 // 2
|
|
||||||
POLL = 2
|
|
||||||
STOP_DELAY = 6
|
|
||||||
|
|
||||||
BLACK = bytes(W * H) + bytes([128] * (W * H // 2))
|
|
||||||
|
|
||||||
dev = os.open(DEVICE, os.O_WRONLY)
|
|
||||||
pixfmt = struct.pack("II4sIIII4x188x", W, H, b"NV12", 1, W, FSIZE, 0)
|
|
||||||
fmt = struct.pack("I4x", 2) + pixfmt
|
|
||||||
fcntl.ioctl(dev, 0xC0D05605, fmt)
|
|
||||||
os.write(dev, BLACK)
|
|
||||||
|
|
||||||
# Restart WirePlumber so it sees the capture device
|
|
||||||
time.sleep(1)
|
|
||||||
subprocess.run(["systemctl", "--user", "restart", "wireplumber.service"],
|
|
||||||
capture_output=True, timeout=10)
|
|
||||||
|
|
||||||
cam_proc = None
|
|
||||||
cam_lock = threading.Lock()
|
|
||||||
stop_idle = threading.Event()
|
|
||||||
|
|
||||||
|
|
||||||
def write_idle():
|
|
||||||
while not stop_idle.is_set():
|
|
||||||
try:
|
|
||||||
os.write(dev, BLACK)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
stop_idle.wait(2)
|
|
||||||
|
|
||||||
|
|
||||||
def relay_camera():
|
|
||||||
global cam_proc
|
|
||||||
env = os.environ.copy()
|
|
||||||
env["GST_PLUGIN_PATH"] = "/usr/lib/gstreamer-1.0"
|
|
||||||
cam_proc = subprocess.Popen(
|
|
||||||
["gst-launch-1.0", "-q",
|
|
||||||
"icamerasrc", "device-name=ov08x40-uf",
|
|
||||||
"sharpness=80", "ev=-1", "saturation=10",
|
|
||||||
"!", "video/x-raw,format=NV12,width=1920,height=1080",
|
|
||||||
"!", "videoflip", "method=rotate-180",
|
|
||||||
"!", "fdsink", "fd=1"],
|
|
||||||
stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, env=env,
|
|
||||||
)
|
|
||||||
buf = b""
|
|
||||||
while cam_proc.poll() is None:
|
|
||||||
data = cam_proc.stdout.read(65536)
|
|
||||||
if not data:
|
|
||||||
break
|
|
||||||
buf += data
|
|
||||||
while len(buf) >= FSIZE:
|
|
||||||
try:
|
|
||||||
os.write(dev, buf[:FSIZE])
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
buf = buf[FSIZE:]
|
|
||||||
cam_proc = None
|
|
||||||
|
|
||||||
|
|
||||||
def has_readers():
|
|
||||||
try:
|
|
||||||
r = subprocess.run(["fuser", DEVICE], capture_output=True, text=True, timeout=5)
|
|
||||||
for pid in r.stdout.strip().split():
|
|
||||||
pid = pid.strip()
|
|
||||||
if not pid:
|
|
||||||
continue
|
|
||||||
if int(pid) == os.getpid():
|
|
||||||
continue
|
|
||||||
with cam_lock:
|
|
||||||
if cam_proc and int(pid) == cam_proc.pid:
|
|
||||||
continue
|
|
||||||
return True
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def start_camera():
|
|
||||||
stop_idle.set()
|
|
||||||
t = threading.Thread(target=relay_camera, daemon=True)
|
|
||||||
t.start()
|
|
||||||
return t
|
|
||||||
|
|
||||||
|
|
||||||
def stop_camera():
|
|
||||||
with cam_lock:
|
|
||||||
if cam_proc:
|
|
||||||
cam_proc.terminate()
|
|
||||||
try:
|
|
||||||
cam_proc.wait(timeout=5)
|
|
||||||
except subprocess.TimeoutExpired:
|
|
||||||
cam_proc.kill()
|
|
||||||
stop_idle.clear()
|
|
||||||
t = threading.Thread(target=write_idle, daemon=True)
|
|
||||||
t.start()
|
|
||||||
return t
|
|
||||||
|
|
||||||
|
|
||||||
def shutdown(sig, frame):
|
|
||||||
stop_idle.set()
|
|
||||||
with cam_lock:
|
|
||||||
if cam_proc:
|
|
||||||
cam_proc.terminate()
|
|
||||||
os.close(dev)
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
|
|
||||||
signal.signal(signal.SIGTERM, shutdown)
|
|
||||||
signal.signal(signal.SIGINT, shutdown)
|
|
||||||
|
|
||||||
# Start idle
|
|
||||||
idle_thread = threading.Thread(target=write_idle, daemon=True)
|
|
||||||
idle_thread.start()
|
|
||||||
|
|
||||||
active = False
|
|
||||||
idle_count = 0
|
|
||||||
|
|
||||||
while True:
|
|
||||||
if has_readers():
|
|
||||||
idle_count = 0
|
|
||||||
if not active:
|
|
||||||
start_camera()
|
|
||||||
active = True
|
|
||||||
else:
|
|
||||||
if active:
|
|
||||||
idle_count += 1
|
|
||||||
if idle_count >= STOP_DELAY // POLL:
|
|
||||||
stop_camera()
|
|
||||||
active = False
|
|
||||||
idle_count = 0
|
|
||||||
time.sleep(POLL)
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
[Unit]
|
|
||||||
Description=Camera feed for v4l2loopback (on-demand, LED off when idle)
|
|
||||||
After=pipewire.service camera-init.service
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
ExecStart=/usr/bin/camera-feed-watch
|
|
||||||
Restart=on-failure
|
|
||||||
RestartSec=5
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=default.target
|
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=Initialize camera (CVS ownership then sensor driver)
|
Description=Initialize camera (CVS ownership, sensor driver, v4l2loopback)
|
||||||
After=systemd-modules-load.service
|
After=systemd-modules-load.service
|
||||||
|
Before=graphical.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=oneshot
|
Type=oneshot
|
||||||
RemainAfterExit=yes
|
RemainAfterExit=yes
|
||||||
ExecStart=/bin/bash -c "modprobe intel_cvs && sleep 2 && modprobe ov08x40"
|
ExecStart=/bin/bash -c "modprobe intel_cvs && sleep 2 && modprobe ov08x40 && modprobe v4l2loopback"
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
@@ -1,52 +1,23 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Re-probe the IPU7 camera sensor after suspend/hibernate resume.
|
# Handle camera service around suspend/resume.
|
||||||
#
|
#
|
||||||
# The OV08X40 sensor connects through a USB-to-I2C bridge (usbio-bridge).
|
# v4l2-relayd must be stopped before suspend to avoid GStreamer crashes,
|
||||||
# After resume the ipu_bridge software fwnode graph is gone, leaving the
|
# then restarted after resume once the camera hardware is ready.
|
||||||
# sensor driver unable to bind. Removing and rescanning the IPU PCI device
|
#
|
||||||
# triggers a fresh probe that recreates the fwnode graph.
|
# The post-resume restart uses systemd-run to avoid blocking the
|
||||||
|
# password prompt while waiting for the camera to initialize.
|
||||||
IPU_PCI="0000:00:05.0"
|
|
||||||
|
|
||||||
case "$1" in
|
case "$1" in
|
||||||
|
pre)
|
||||||
|
systemctl stop v4l2-relayd@ipu7.service 2>/dev/null || true
|
||||||
|
;;
|
||||||
post)
|
post)
|
||||||
(
|
systemd-run --no-block --unit=camera-resume bash -c '
|
||||||
# Wait for the USB-I2C bridge to re-enumerate
|
systemctl restart camera-init.service 2>/dev/null
|
||||||
for i in $(seq 1 15); do
|
systemctl reset-failed v4l2-relayd@ipu7.service 2>/dev/null || true
|
||||||
if grep -q "OVTI08F4" /sys/bus/i2c/devices/*/name 2>/dev/null; then
|
systemctl start v4l2-relayd@ipu7.service 2>/dev/null || true
|
||||||
break
|
'
|
||||||
fi
|
|
||||||
sleep 1
|
|
||||||
done
|
|
||||||
sleep 1
|
|
||||||
|
|
||||||
# Unload sensor so the IPU device can be cleanly removed
|
|
||||||
modprobe -r ov08x40 2>/dev/null || true
|
|
||||||
|
|
||||||
# Remove and rescan the IPU PCI device to trigger fresh ipu_bridge_init
|
|
||||||
echo 1 > "/sys/bus/pci/devices/$IPU_PCI/remove" 2>/dev/null || true
|
|
||||||
sleep 1
|
|
||||||
echo 1 > /sys/bus/pci/rescan 2>/dev/null || true
|
|
||||||
sleep 3
|
|
||||||
|
|
||||||
# Reload sensor driver
|
|
||||||
modprobe intel_cvs 2>/dev/null || true
|
|
||||||
sleep 2
|
|
||||||
modprobe ov08x40 2>/dev/null || true
|
|
||||||
|
|
||||||
# Restart the camera feed service
|
|
||||||
for uid_dir in /run/user/*; do
|
|
||||||
uid=$(basename "$uid_dir")
|
|
||||||
if [[ -S $uid_dir/bus ]]; then
|
|
||||||
sudo -u "#$uid" env \
|
|
||||||
XDG_RUNTIME_DIR="$uid_dir" \
|
|
||||||
DBUS_SESSION_BUS_ADDRESS="unix:path=$uid_dir/bus" \
|
|
||||||
systemctl --user restart camera-feed-watch.service 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
) &
|
|
||||||
disown
|
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
exit 0
|
exit 0
|
||||||
@@ -1,3 +1,19 @@
|
|||||||
|
_add_pipewire_camera() {
|
||||||
|
local conf="$1"
|
||||||
|
if [ -f "$conf" ] && ! grep -q 'PipeWireCamera' "$conf"; then
|
||||||
|
if grep -q 'enable-features=' "$conf"; then
|
||||||
|
sed -i 's/--enable-features=\([^ ]*\)/--enable-features=\1,PipeWireCamera/' "$conf"
|
||||||
|
else
|
||||||
|
echo '--enable-features=PipeWireCamera' >> "$conf"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_remove_pipewire_camera() {
|
||||||
|
local conf="$1"
|
||||||
|
[ -f "$conf" ] && sed -i 's/,PipeWireCamera//g' "$conf"
|
||||||
|
}
|
||||||
|
|
||||||
_install_sleep_hook() {
|
_install_sleep_hook() {
|
||||||
cp /usr/share/intel-ipu7-camera/camera-sleep-hook /usr/lib/systemd/system-sleep/camera-sleep-hook
|
cp /usr/share/intel-ipu7-camera/camera-sleep-hook /usr/lib/systemd/system-sleep/camera-sleep-hook
|
||||||
chmod 755 /usr/lib/systemd/system-sleep/camera-sleep-hook
|
chmod 755 /usr/lib/systemd/system-sleep/camera-sleep-hook
|
||||||
@@ -7,44 +23,44 @@ post_install() {
|
|||||||
_install_sleep_hook
|
_install_sleep_hook
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
systemctl enable camera-init.service
|
systemctl enable camera-init.service
|
||||||
systemctl --global enable camera-feed-watch.service
|
systemctl enable v4l2-relayd@ipu7.service
|
||||||
udevadm control --reload-rules 2>/dev/null || true
|
udevadm control --reload-rules 2>/dev/null || true
|
||||||
|
|
||||||
if [ -n "$SUDO_USER" ]; then
|
if [ -n "$SUDO_USER" ]; then
|
||||||
usermod -aG video "$SUDO_USER" 2>/dev/null || true
|
usermod -aG video "$SUDO_USER" 2>/dev/null || true
|
||||||
|
|
||||||
# Start the service in the current user session if one is active
|
_add_pipewire_camera "/home/$SUDO_USER/.config/chromium-flags.conf"
|
||||||
local uid
|
_add_pipewire_camera "/home/$SUDO_USER/.config/brave-flags.conf"
|
||||||
uid=$(id -u "$SUDO_USER" 2>/dev/null)
|
_add_pipewire_camera "/home/$SUDO_USER/.config/chrome-flags.conf"
|
||||||
if [ -n "$uid" ] && [ -d "/run/user/$uid" ]; then
|
|
||||||
XDG_RUNTIME_DIR="/run/user/$uid" \
|
|
||||||
DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$uid/bus" \
|
|
||||||
runuser -u "$SUDO_USER" -- \
|
|
||||||
systemctl --user start camera-feed-watch.service 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
post_upgrade() {
|
post_upgrade() {
|
||||||
_install_sleep_hook
|
_install_sleep_hook
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
|
systemctl enable v4l2-relayd@ipu7.service
|
||||||
|
# Disable old camera-feed-watch (replaced by v4l2-relayd)
|
||||||
|
systemctl --global disable camera-feed-watch.service 2>/dev/null || true
|
||||||
udevadm control --reload-rules 2>/dev/null || true
|
udevadm control --reload-rules 2>/dev/null || true
|
||||||
|
|
||||||
|
if [ -n "$SUDO_USER" ]; then
|
||||||
|
_add_pipewire_camera "/home/$SUDO_USER/.config/chromium-flags.conf"
|
||||||
|
_add_pipewire_camera "/home/$SUDO_USER/.config/brave-flags.conf"
|
||||||
|
_add_pipewire_camera "/home/$SUDO_USER/.config/chrome-flags.conf"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
pre_remove() {
|
pre_remove() {
|
||||||
|
systemctl disable v4l2-relayd@ipu7.service 2>/dev/null || true
|
||||||
|
systemctl stop v4l2-relayd@ipu7.service 2>/dev/null || true
|
||||||
systemctl --global disable camera-feed-watch.service 2>/dev/null || true
|
systemctl --global disable camera-feed-watch.service 2>/dev/null || true
|
||||||
systemctl disable camera-init.service 2>/dev/null || true
|
systemctl disable camera-init.service 2>/dev/null || true
|
||||||
systemctl stop camera-init.service 2>/dev/null || true
|
systemctl stop camera-init.service 2>/dev/null || true
|
||||||
|
|
||||||
if [ -n "$SUDO_USER" ]; then
|
if [ -n "$SUDO_USER" ]; then
|
||||||
local uid
|
_remove_pipewire_camera "/home/$SUDO_USER/.config/chromium-flags.conf"
|
||||||
uid=$(id -u "$SUDO_USER" 2>/dev/null)
|
_remove_pipewire_camera "/home/$SUDO_USER/.config/brave-flags.conf"
|
||||||
if [ -n "$uid" ] && [ -d "/run/user/$uid" ]; then
|
_remove_pipewire_camera "/home/$SUDO_USER/.config/chrome-flags.conf"
|
||||||
XDG_RUNTIME_DIR="/run/user/$uid" \
|
|
||||||
DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$uid/bus" \
|
|
||||||
runuser -u "$SUDO_USER" -- \
|
|
||||||
systemctl --user stop camera-feed-watch.service 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
[Unit]
|
||||||
|
After=camera-init.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Environment=GST_PLUGIN_PATH=/usr/lib/gstreamer-1.0
|
||||||
|
# Relax sandboxing for icamerasrc hardware access
|
||||||
|
PrivateNetwork=no
|
||||||
|
InaccessibleDirectories=
|
||||||
|
ReadOnlyDirectories=
|
||||||
|
DevicePolicy=auto
|
||||||
|
# Give v4l2-relayd time to initialize, then restart WirePlumber
|
||||||
|
# so PipeWire re-probes the device with the correct format
|
||||||
|
ExecStartPost=/bin/bash -c 'sleep 2 && systemctl --user -M 1000@ restart wireplumber.service 2>/dev/null || true'
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
VIDEOSRC="icamerasrc device-name=ov08x40-uf sharpness=80 ev=-1 saturation=10 ! videoflip method=rotate-180"
|
||||||
|
FORMAT=NV12
|
||||||
|
WIDTH=1920
|
||||||
|
HEIGHT=1080
|
||||||
|
FRAMERATE=30/1
|
||||||
|
CARD_LABEL="Hardware ISP Camera"
|
||||||
@@ -1 +0,0 @@
|
|||||||
v4l2loopback
|
|
||||||
Reference in new issue
Block a user