Commit graph

14175 commits

Author SHA1 Message Date
Barnabás Pőcze
22ddb88072 spa: libcamera: source: process all requests in the ring buffer
It is possible that multiple requests complete before the data loop can run
`libcamera_on_fd_events()`. However, previously only the earliest item was
processed from the ring buffer, meaning that in those cases request processing
could be lagging request completion by multiple requests.

Fix that by getting the number of available requests and processing them all.
2025-08-13 10:23:28 +02:00
Barnabás Pőcze
c01a2977a5 spa: libcamera: source: reset ring buffer when stopping
Presently, the ring buffer of completed requests is only cleared
when the buffers are removed from the port. This is not entirely
correct since pause/start commands do not clear the buffers but
they stop the camera. As a consequence, it is possible that some
completed requests stay in the ring buffer, causing them to be
mistakenly processed when the camera is started next.

So reset the ring buffer after the camera is stopped, the same time
as the queue of free buffers is cleared.
2025-08-13 10:23:22 +02:00
Barnabás Pőcze
72fd462090 spa: libcamera: source: move request completion data to impl
A `libcamera::Request` is directly tied to the camera, not any ports ("streams")
of it. So move the request completion ring buffer into the `impl` struct.

This is a prerequisite for supporting multiple libcamera streams (~ exposing
multiple ports on the node) in the future.
2025-08-13 10:23:17 +02:00
Barnabás Pőcze
099292d63d spa: libcamera: source: store the request pointer in ring buffer
The request will be needed later, so store that directly in the
completion ring buffer for easy access.

This is fine even though `impl::requestComplete()` calls `Request::reuse()`
because only the request cookie is used in `libcamera_on_fd_events()` and
that remains constant during the lifetime of a request object.
2025-08-13 10:23:13 +02:00
Barnabás Pőcze
68627c5563 spa: libcamera: source: remove impl::pendingRequests
The handling of `impl::pendingRequests` is a bit problematic because,
for example, during startup, if `spa_libcamera_buffer_recycle()` observes
that `impl::active == false`, then it will try to append to `impl::pendingRequests`,
which is being iterated in the main thread in `spa_libcamera_stream_on()`.
That is not allowed on an `std::deque`.

So instead remove it altogether, and simply queue all requests when starting.
After `libcamera::Camera::stop()` returns, every request is guaranteed not
to be used by libcamera, and they can be freely reused, so this is safe to do.

This also removes the need for calling `spa_libcamera_buffer_recycle()` when
the buffers are set/unset on a port since that function no longer changes
anything apart from updating `buffer::flags` but `spa_libcamera_alloc_buffers()`
is modified appropriately to take care of that. And in the case of
`spa_libcamera_clear_buffers()` clearing the flag is not required because the
next `spa_libcamera_alloc_buffers()` call will reset reset the flags.
2025-08-13 10:23:09 +02:00
Barnabás Pőcze
475665d615 spa: libcamera: source: persistent requests <-> buffer association
Currently only a single stream is used. This makes it easy to associate
each request with the appropriate frame buffer when it is created. In
turn, this makes reusing requests a bit simpler and a bit more efficient.

So do that: add buffers to requests when they are allocated in `allocBuffers()`.
2025-08-13 10:23:05 +02:00
Barnabás Pőcze
29b0c87d71 spa: libcamera: source: allocBuffers(): more error checking
First, check if the request pool is empty, and signal an error if it
is not. Second, ensure that the number of allocated buffers matches.
2025-08-13 10:23:01 +02:00
Barnabás Pőcze
348e703be0 spa: libcamera: source: allocBuffers(): restore on failure
Undo the allocation and clear the requests if a failure is encountered
in order to leave things in a known state.
2025-08-13 10:22:57 +02:00
Barnabás Pőcze
b9b7c0ab05 spa: libcamera: source: freeBuffers(): call when format is unset
At the moment the libcamera buffer allocation is completely tied to format
negotiation. `freeBuffers()` undoes `allocBuffers()`. And `allocBuffers()`
is called as part of `spa_libcamera_set_format()`. Therefore `freeBuffers()`
should be called independent of the state of the buffers on any port.

Otherwise unsetting the format while there are no buffers on the port will
cause the libcamera requests and buffers not to be released correctly. Similarly,
removing the buffers from a port would clear the libcamera requests and buffers,
making the node unusable without setting a new format.
2025-08-13 10:22:53 +02:00
Barnabás Pőcze
89545946fd spa: libcamera: source: freeBuffers(): split pending request removal
`freeBuffers()` should undo exactly what `allocBuffers()` does. However,
it currently also clears `impl::pendingRequests`, but that is filled
by `spa_libcamera_buffer_recycle()` during `spa_libcamera_alloc_buffers()`.

So remove the clearing of `impl::pendingRequests` from `freeBuffers()` and
move it directly into `spa_libcamera_clear_buffers()`.
2025-08-13 10:22:50 +02:00
Barnabás Pőcze
14e0a8f66f spa: libcamera: source: propagate error when setting format
If `spa_libcamera_set_format()` fails, propagate its return value
as is without rewriting it to `EINVAL`.
2025-08-13 10:22:46 +02:00
Barnabás Pőcze
47ee86938b spa: libcamera: source: port_set_format(): remove goto
Remove the `done` label by moving things into the `format != nullptr` branch.
2025-08-13 10:22:41 +02:00
Barnabás Pőcze
860e455440 spa: libcamera: source: support libcamera::formats::R8
Map `libcamera::formats::R8` to `SPA_VIDEO_FORMAT_GRAY8`.
2025-08-13 09:46:56 +02:00
Sertonix
3914d0cab3 module-jack: fix name of LIBJACK_PATH environment variable
Fixes 0629647cb5 module-jack: load libjack.so.0 with dlopen
2025-08-13 07:15:16 +00:00
Barnabás Pőcze
0fcabdbd0c ci: cross compile on debian 13 to multiple architectures
Debian supports many architectures, and it is relatively easy to work
with multiarch packages, and finally `meson env2mfile` supports
generating cross files with the `--debarch` option.

Previously only native builds were done in the CI, so use debian to
build pipewire for multiple architectures.

Some packages are unfortunately not multiarch compatible, so a separate
container is built for every architecture.
2025-08-13 07:14:33 +00:00
Barnabás Pőcze
9438df8d30 Revert "ci: Add an x86 build"
This reverts commit 2042a0483b.
A new approach is added in subsequent commits based on debian
for more architectures.
2025-08-13 07:14:33 +00:00
Barnabás Pőcze
fcb318b9c5 pwtest: is_debugger_attached(): rework test
Check if the "TracerPid" field in `/proc/self/status` is non-zero. This does
not need libcap, and does not depend on capabilities, and it also works under
qemu user emulation.
2025-08-13 07:14:33 +00:00
Barnabás Pőcze
0d0108e954 test: spa-utils: utils_snprintf_abort_neg_size: remove valgrind check
Death tests are always skipped by the framework when running on valgrind,
so there is no need for the check.
2025-08-13 07:14:33 +00:00
Frédéric Danis
a50b66651e bluez5: backend-native: Add log for call state changes
This also to track each call state changes.
2025-08-12 18:22:40 +03:00
Frédéric Danis
1ad3fdff8a bluez5: backend-native: Free command list queue on RFComm free
When RFComm conection is closed or lost, the pending commands should
be freed, and if a DBus message is attached an error reply should be
sent.
2025-08-12 11:35:02 +02:00
Pauli Virtanen
618d60a1f2 alsa: show correct value in api.alsa.period-num 2025-08-09 12:53:41 +03:00
George Kiagiadakis
22e80e228c bluez5: backend-native: reset hfp_hf_in_progress state on error reply
If a AT+CHLD command fails, we may get stuck in the "in progress" state
forever unless we clear the state here.
2025-08-09 09:24:02 +00:00
Pauli Virtanen
a39462a6c0 bluez5: support 44.1kHz rate for BAP LC3
liblc3 doesn't support 44.1kHz directly, but its authors write one
should just use some nearby rate instead. Do just that.
2025-08-09 11:30:40 +03:00
Wim Taymans
206a30d100 examples: the example generates UMP 2025-08-08 15:10:56 +02:00
Barnabás Pőcze
9aeba05e47 spa: libcamera: source: rework control setting
Instead of applying each control separately, collect them into a
`libcamera::ControlList`, and try to apply them at the end.

Furthermore, instead of doing a blocking loop invoke, use `spa_loop_locked()`
as it is sufficient to update `impl::ctrls`.

After this change control setting works in a more "atomic" way since every
control is parsed and checked before actually reaching the camera. It is
also detected if the given control is not supported by the camera.
2025-08-07 07:59:54 +00:00
Niklas Carlsson
30ba62e47c filter-graph: set NULL data support in LV2
In LV2, a port supports NULL data if the connectionOptional
property is set.
2025-08-06 12:09:13 +02:00
Niklas Carlsson
2ac708d916 filter-graph: add NULL data support per port
It would be good to define NULL support per port in e.g. LV2
plugins where sidechains are usually defined optional.
2025-08-06 12:08:23 +02:00
Carlos Rafael Giani
97a1609b29 module-rtp: Reset ring buffer contents when stream starts 2025-08-05 17:54:56 +00:00
Carlos Rafael Giani
c9a8b8629f module-rtp: Limit actual max buffer size to an integer multiple of stride
Opus and MIDI code get TODOs added, since it is currently unclear how to
implement that fix for them.
2025-08-05 17:54:56 +00:00
Carlos Rafael Giani
e5be9cce4f module-rtp: Reorder sync checks and resynchronization code
This fixes the case when synchronization is established but actually not
valid anymore. In such a case, the code would _first_ write to the ring
buffer (at the wrong position due to the invalid sync), and _then_ detect
the bogus synchronization. Reorder the code blocks to _first_ check the
current sync, then resynchronize if neeeded (or perform initial sync if
no sync is established yet), and _then_ write to the ring buffer.
2025-08-05 17:54:56 +00:00
Carlos Rafael Giani
b8d98d03fe module-rtp: Fix timestamp check and add discontinuity check
Until now, the timestamp check was comparing the timestamp delta against
the value of the "quantum" variable. However, the timestamps use clock
samples as units, while the "quantum" variable uses nanoseconds. The
outcome is that this check virtually never returned true. Use the
spa_io_clock duration instead of that quantum nanosecond duration to make
the check actually work.

Also, do not just rely on vast timestamp deltas to detect discontinuities;
instead, check first for the presence of the SPA_IO_CLOCK_FLAG_DISCONT
flag to detect said discontinuities.
2025-08-05 17:54:56 +00:00
Carlos Rafael Giani
2a460e18e3 module-rtp: Rename timestamp to actual_timestamp for clarity 2025-08-05 17:54:56 +00:00
Carlos Rafael Giani
6c4cd0f1b2 doc: spa: Fix offset in driver documentation 2025-08-05 17:54:56 +00:00
Barnabás Pőcze
e6f767d41d spa: libcamera: source: use dynamic builder for controls
Use a dynamic spa pod builder when enumerating controls since previous
changes can report more information from any given control. Also increase
the stack buffer size to 4096 bytes.
2025-08-05 17:51:53 +00:00
Barnabás Pőcze
8673f17c0a spa: libcamera: source: provide value labels if available
For enumerated controls of type `libcamera::ControlTypeInteger32`, libcamera
provides the names of the enumerators, so add them to `SPA_PROP_INFO_labels`.
2025-08-05 17:51:53 +00:00
Barnabás Pőcze
e379267274 spa: libcamera: source: handle enum controls better
If the `libcamera::ControlInfo` object explicitly lists the values of a
control, then use those values when adding `SPA_PROP_INFO_type` to
construct an enumerated choice object.
2025-08-05 17:51:53 +00:00
Barnabás Pőcze
8d9e469e09 spa: libcamera: source: unify control range logic
If libcamera does not provide a default value, then the average of the
minimum and maximum values is taken. The same logic is duplicated for
`float` and `int32_t`, so move it into a function template.
2025-08-05 17:51:53 +00:00
Barnabás Pőcze
e9367443ac spa: libcamera: source: ignore array controls
Properly ignore array controls because they are not supported for now.
2025-08-05 17:51:53 +00:00
Barnabás Pőcze
66cc01ee2d spa: libcamera: source: rework bool control type info
`SPA_POD_CHOICE_Bool()` assumes that both true and false are available,
which may not be the case for libcamera controls, so manualy construct
the enumerated choice object and only add the actually available options.
2025-08-05 17:51:53 +00:00
Barnabás Pőcze
44c05cfa7b spa: libcamera: source: move control enumeration to loop
Remove the `goto`s and instead move everything into a loop.
2025-08-05 17:51:53 +00:00
Barnabás Pőcze
cc187b035b spa: libcamera: source: separate type info generation
Add a new function `control_details_to_pod()` that builds a
`SPA_TYPE_OBJECT_PropInfo` object describing a libcamera control.
2025-08-05 17:51:53 +00:00
Jan Grulich
3c759ae293 Add IWYU annotations
This allows to use clang-include-cleaner tool without <pipewire/foo.h>
headers being automatically added when <pipewire/pipewire.h> is included
instead.

See https://issues.webrtc.org/issues/422940461
2025-08-05 17:51:13 +00:00
Demi Marie Obenour
bac3d31283 pod: fix some data races in body code
The body code didn't use atomic loads, so it had undefined behavior if
the body was concurrently modified.  Use atomic loads to fix this.
Since the memory order is __ATOMIC_RELAXED this has no runtime overhead.
Also add barriers around a strncpy call and cast to volatile before
checking for a NUL terminator, though NUL-terminated strings in shared
memory are unuseable.  There are some places where bytewise atomic
memcpy(), which doesn't currently exist, is needed.  Instead, try to
fake it by using two barriers around memcpy().
2025-08-05 10:49:33 -04:00
Wim Taymans
c9c7552fed alsa: clear port before adding to free list
If we clear the port after adding, we will destroy the links into the
list and cause crashes later.
2025-08-04 11:02:02 +02:00
Pauli Virtanen
02aee17cc3 test: fix test library path and fix test-functional with ASAN
Set LD_LIBRARY_PATH to have processes spawned by test load the right
library.

Mark openal-info test skipped if ASAN is enabled. The problem is that
openal-info would need LD_PRELOAD to work properly then. Just disable
the test then.
2025-08-04 08:34:02 +00:00
Barnabás Pőcze
58d86cfb5f pw-cli: print pw_core errors
At the moment errors are printed using `pw_log_error()`, however, that does
not display them by default because `client.conf` sets `log.level=0`.

Use `fprintf()` and always print the errors.
2025-08-04 08:28:10 +00:00
Barnabás Pőcze
5ecf27681e pipewire: module-rt: acquire_rt(): return error if thread not found
Instead of implicitly acting on the current thread if the provided thread
handle is unknown, return an error. This behaviour is not depended on inside
pipewire, and if needed, special casing e.g. `thread == NULL` could be added,
but any random `thread` value shouldn't affect the current thread.
2025-08-01 21:42:32 +02:00
Pauli Virtanen
a346a7d42e doc: document more properties
Also add examples for customizing properties.
2025-08-01 16:20:27 +00:00
Wim Taymans
35b3c8c279 vban: truncate sess.name when too large 2025-08-01 18:17:21 +02:00
Barnabás Pőcze
8614fc45f8 spa: libcamera: manager: keep libcamera::CameraManager
At the moment, the camera manager shared pointer is released when the last
listener is removed, and recreated when the first listener is added. This
is the same behaviour that the alsa and v4l2 monitors implement with their
respective udev, inotify monitors.

However, for `libcamera::CameraManager`, this is likely not the best way
for multiple reasons:

  (a) it is a complex object with significant construction and starting cost,
      which includes starting threads and usually loading shared libraries;
  (b) usually one listener is added right after creating, and it is removed
      right before destruction, in which there are real no advantages;
  (c) the camera manager, being a shared resource, might very well be kept
      alive by some other component, in which case there is again not much
      real benefit.

So simplify the code by getting a camera manager reference at the beginning
and keeping it until the libcamera monitor is destroyed.

This also fixes a race condition where a hot-plugged camera might not have
been detected if the libcamera event was emitted between these two:

  collect_existing_devices(impl);
  start_monitor(impl);
2025-08-01 15:54:10 +00:00