Some V4L2 controls like focus, pan or tilt can be relative (change
the lens / angle relative to previous positions) these return EACCES
when calling VIDIOC_G_CTRL on them.
Fix the v4l2 SPA not working on cameras with relative controls,
such as e.g. the Logitech QuickCam Orbit MP.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
There is a race between logind applying ACLs to allow the active session
of a locally present user access to devices with a udev uaccess tag
(like /dev/video# nodes) getting applied vs wireplumber/pipewire starting.
Wireplumber/pipewire are part of the (user) default.target, which gets
started as soon as a user logs in and systemd --user is started for that
user, where as logind only starts applying the ACLs after the gnome-shell
associated logind session has been created.
This race may cause pipewire to not see v4l2 video sources at login,
this can be reproduced with these steps:
1. sudo setfacl --remove-all /dev/video*
2. systemctl --user restart pipewire
3. Now wp-ctl status will not show any video devices
(like if pipewire was started before the udev uaccess ACLs got applied)
4. Do a switch to another (test) user without logging out, e.g. in GNOME
go to the top right system menu press the power on/off icon and select
"Switch User..."
5. Switch back to your normal user. Run getfacl /dev/video0 this will show
your user has access now.
6. wp-ctl status should show the camera now, but it does not.
Fix pipewire not seeing v4l2 sources in this case by making v4l2-udev
monitor systemd-logind session changes and redoing the access() checks
on /dev/video# nodes when the session changes.
Closes: #3539Closes: #3960
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
The spa_loop_add_source() call for udev event monitoring which uses
impl_on_fd_events() is done from start_monitor() which also unconditionally
calls start_inotify().
Since start_monitor() already always calls start_inotify() there is no
scenario where start_inotify() has not been called yet when
impl_on_fd_events() gets called. So the start_inotify() call in
impl_on_fd_events() is redundant, remove it.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
When we drop the first buffer to avoid timestamp problems, queue it
again in the driver or else we will not be able to dequeue is again
later and we will be running with a buffer less.
Now that start_monitor() (which calls start_inotify()) is called before
enum_devices() it no longer is necessary to call start_watching_device()
for devices which have been enumerated before start_inotify() gets
called (since there will not be any such devices anymore).
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
This fixes 2 races wrt probing v4l2 devices:
1. Before this change there was a window where a new udev device can get
added between the udev_enumerate_scan_devices() call in enum_devices() and
the udev_monitor_enable_receiving(this->umonitor); call. If this window was
hit then enum_devices() would not see the device and no udev-event for it
would be received either causing the device to not be seen.
Enabling udev event monitoring before calling udev_enumerate_scan_devices()
fixes this. Note that the code is already prepared to deal with getting
multiple add/change events for the same udev device, so hitting the new
race window where PipeWire may receive both an add- or change-event and
also sees + probes the device from enum_devices() is not a problem.
2. Before this change devices added by enum_devices() would not have
inotify monitoring activated right away because notify.fd = -1 at this
time turning start_watching_device() into a no-op.
These devices without inotify monitoring would then have their access
checked by process_device() calling check_access().
Then after all devices have been enumerated start_monitor() would call
start_inotify() which calls start_watching_device() for all devices added
by enum_devices(). This leaves a window where the ACL can change without
there being an inotify watch for it.
Calling start_monitor() before enum_devices() puts start_inotify()
notify before enum_devices() so that the add_device() calls done
by enum_devices() will now successfully call start_watching_device()
closing this window.
PipeWire is somewhat likely to not notify ACL changes because of this
because PipeWire is part of the systemd user default.target, where as
logind only starts applying the ACLs after GNOME has created the seat
for the GNOME session. So on first login we have PipeWire starting
and logind applying the ACLs at the same time, which allows for the ACL
change to hit the small race window where PipeWire is not monitoring
for ACL changes. Fixing this second race should hopefully resolve
issue #3960.
Closes: #3960
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
The Pipewire libcamera spa plugin exposes multiple camera properties.
Unlike v4l2, libcamera usually exposes these as normalized floating
point values. But as the SPA_PROP types are based on v4l2, they are
currently set to integers.
This causes a problem when using pw-cli to change the properties,
as the spa_json_to_pod_part function casts the properties according
to their spa_type_info. Other software that doesn't depend on the
spa_type_info can correctly set the properties, as the values are
encoded in the spa_pod type and therefore also carry a type.
As the limited range from switching integers to floats is likely not a
problem, the affected spa properties were changed to the Float type.
This will cause pw-cli to also generate spa_pod values of type float
when setting v4l2 properties. Therefore the v4l2 spa plugin is also
adapted to allow floating point properties and cast these to integers.
Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
Use dynamic pod builder so that we can also build complex formats.
Make sure we zero the format before we parse it or else we end up with
potentially uninitialized values.
When ENUM_FRAMESIZES or VIDIOC_ENUM_FRAMEINTERVALS return EINVAL for the
first index, make a dummy result and continue with that. This will
trigger an intersect withe filter so that we end up with something valid
instead of nothing.
Handle 0 framerates without crashing.
See #4063
Can be used to group ports together. Mostly because they are all from
the same stream and split into multiple ports by audioconvert/adapter.
Also useful for the alsa sequence to group client ports together.
Also interesting when pw-filter would be able to handle streams in the
future to find out what ports belong to what streams.
Advertise support for the videotransform metadata.
Make a new meta.videotransform.transform property to configure the
desired video transformation in the metadata.
This makes it possible for a session manager or other rules to set
a custom transformation on the source.
See #4034
A quite big number of UVC cameras - due to firmware or kernel driver
issues - have bad timestamps of the first frame, confusing clients
like pipewiresrc.
Drop the first frame, as this seems to be the most reliable workaround
for the time being.
Closes https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/3910
Previously both `impl_on_notify_events()` and `process_{device,card}()`
called `check_access()`. Avoid that by merging `ACTION_ADD` and
`ACTION_DISABLE` into a single `ACTION_CHANGE` and let `process_{device,card}()`
call `check_access()` and decide what to do.
Split up `process_{device,card}()` to have a separate function that does
the lookup based on the udev device, and only use that when there is
no available reference to the actual device/card object.
Add a MAPPABLE data flag that hints that the fd in the data is mappable
with a simple mmap/munmap. Normally, DmaBuf is not mappable like that
unless explicitly indicated with this flag.
Set the MAPPABLE flag on the DmaBuf from v4l2 and libcamera fd.
When asked, mmap the buffer memory in all cases when the MAPPABLE
flag is set.
This solves the case where v4l2 has exported DmaBuf and is streaming to
node A and then node B links but doesn't get automatically mmaped
memory.
Fixes#3840
After we set the format, probe if we can do EXPBUF and enable/disable
the ALLOC_BUFFERS flag on the port.
This should gracefully handle the case where EXPBUF is not available.
Fixes#3821
When we try to alloc buffers but EXPBUF is not supported, make sure to
clear the alloc_buffers flag so that the caller can try again with
allocated buffers instead.
See #3821
When the filter has no format property, just enumerate all possible
framerates. Handle error case where the filter has the wrong type.
Makes gst-launch gstpipewiresrc ! video/x-raw ! fakesink work.
See #1793
Actually count the number of frame fractions we add. If we added 0, we
don't have any supported framerate that intersects with the filter and we
try the next frame size.
See #1793
Instead of watching /dev, use a separate watch for each device.
This is supposed to achieve the same result as the now reverted
88f0dbd6fc ("v4l2: don't set inotify on /dev"):
Doing inotify on /dev is not a good idea because we will be woken up by
a lot of unrelated events.
There is a report of a performance regression on some IO benchmark
because of lock contention within the fsnotify subsystem due to this.
Instead, just watch for attribute changes on the /dev/videoX files
directly. We are only interested in attribute changes, udev should
notify us when the file is added or removed.
Fixes#3439
Doing inotify on /dev is not a good idea because we will be woken up by
a lot of unrelated events.
There is a report of a performance regression on some IO benchmark
because of lock contention within the fsnotify subsystem due to this.
Instead, just watch for attribute changes on the /dev/videoX files
directly. We are only interested in attribute changes, udev should
notify us when the file is added or removed.
A driver node should use the target_duration and target_rate to adjust
the quantum and rate when the graph starts.
The camera nodes don't currently support any of this and simply enforce
a specific rate and duration for the graph clock. Mark this with a
FIXME. Otherwise, pipewire will complain that the node is ignoring the
configured graph rate.
We should really look at the graph target rate/quantum and only produce
a buffer when it is inside the current graph cycle. This would make it
possible to join audio and camera nodes and have them be in sync.