Commit graph

14308 commits

Author SHA1 Message Date
Robert Mader
5f3ae4376e gst: pool: Keep dmabufs mapped
Downstream elements accessing dmabufs from the CPU currently need to map
and unmap buffers on every frame.
While the kernel's page cache avoids most overhead, this still requires a
round-trip through the kernel and possibly non-negligible work in
`dma_buf_mmap()`. Keeping the buffers mapped avoids that without causing
additional syncronization work, as the later should only happen when
`DMA_BUF_IOCTL_SYNC` is triggered in `gst_dmabuf_mem_map()`.

A common scenario where this matters is clients using cameras. The
downstream elements in question may not be aware of dmabufs - e.g.
`videoconvert` - or fail to import the dmabuf and fall back to import
from memory - e.g. `glupload`.

Notes:
 - GstShmAllocator implicitly does this already.
 - We could also do this in the MemFd case, however I'm less convinced
   about the trade-offs.
2025-08-24 13:54:32 +02:00
Robert Mader
95497f8777 gst: pool: Remove last g_slice remnants
It has long been deprecated and just makes the code harder to read.
2025-08-24 13:48:33 +02:00
Arun Raghavan
d991be6a26 doc: Fix Device::Info id field type in protocol documentation 2025-08-22 21:57:57 -04:00
Arun Raghavan
2958692eca doc: Fix some trailing whitespace in protocol.dox 2025-08-22 21:57:15 -04:00
Barnabás Pőcze
882737b077 pipewire: module-link-factory: cancel async work in link's destroy event
When a link enters the "ERROR" state, it is scheduled for destruction in
`module-link-factory.c:link_state_changed()`, which queues `destroy_link()`
to be executed on the context's work queue.

However, if the link is destroyed by means of `pw_impl_link_destroy()`
directly after that, then `link_destroy()` unregisters the associated
`pw_global`'s event hook, resulting in `global_destroy()` not being called
when `pw_impl_link_destroy()` proceeds to call `pw_global_destroy()` some
time later. This causes the scheduled async work to not be cancelled. When
it runs later, it will trigger a use-after-free since the `link_data` object
is directly tied to the `pw_impl_link` object.

For example, if the link is destroyed when the client disconnects:

==259313==ERROR: AddressSanitizer: heap-use-after-free on address 0x7ce753028af0 at pc 0x7f475354a565 bp 0x7ffd71501930 sp 0x7ffd71501920
READ of size 8 at 0x7ce753028af0 thread T0
    #0 0x7f475354a564 in destroy_link ../src/modules/module-link-factory.c:253
    #1 0x7f475575a234 in process_work_queue ../src/pipewire/work-queue.c:67
    #2 0x7b47504e7f24 in source_event_func ../spa/plugins/support/loop.c:1011
    [...]

0x7ce753028af0 is located 1136 bytes inside of 1208-byte region [0x7ce753028680,0x7ce753028b38)
freed by thread T0 here:
    #0 0x7f475631f79d in free /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_malloc_linux.cpp:51
    #1 0x7f4755594a44 in pw_impl_link_destroy ../src/pipewire/impl-link.c:1742
    #2 0x7f475569dc11 in do_destroy_link ../src/pipewire/impl-port.c:1386
    #3 0x7f47556a428b in pw_impl_port_for_each_link ../src/pipewire/impl-port.c:1673
    #4 0x7f475569dc3e in pw_impl_port_unlink ../src/pipewire/impl-port.c:1392
    #5 0x7f47556a02d8 in pw_impl_port_destroy ../src/pipewire/impl-port.c:1453
    #6 0x7f4755634f79 in pw_impl_node_destroy ../src/pipewire/impl-node.c:2447
    #7 0x7b474f722ba8 in client_node_resource_destroy ../src/modules/module-client-node/client-node.c:1253
    #8 0x7f47556d7c6c in pw_resource_destroy ../src/pipewire/resource.c:325
    #9 0x7f475545f07d in destroy_resource ../src/pipewire/impl-client.c:627
    #10 0x7f47554550cd in pw_map_for_each ../src/pipewire/map.h:222
    #11 0x7f4755460aa4 in pw_impl_client_destroy ../src/pipewire/impl-client.c:681
    #12 0x7b474fb0658b in handle_client_error ../src/modules/module-protocol-native.c:471
    [...]

Fix this by cancelling the work queue item in `link_destroy()`, which should
always run, regardless of the ordering of events.

Fixes #4691
2025-08-20 23:21:26 +02:00
filmsi
07f36ab580 Updated Slovenian (sl.po) 2025-08-20 14:03:35 +00:00
Wim Taymans
b801527f88 jack: emit port_rename callbacks
When the port is renamed, we queue a PORT_RENAME callback with an arg1
as 1. Before emitting the event we check the registered state of the
port but we want to suppress the event if the port was *not* registered,
ie. when the registered state != 1 (arg1).
2025-08-20 11:39:30 +02:00
Dimitris Papaioannou
f60638a3aa spa: Make spa_pod_parser_pop return int again
This fixes an API break that couldn't let the Rust bindings build.

See e317edcfb9 (caedda3d4b09299412c1c1ea2f100ac54cfc7b6d_128_190)
2025-08-20 08:04:21 +00:00
Wim Taymans
b7412169f5 tools: Use the same -M option as pw-cat to force midi 2025-08-20 10:00:07 +02:00
Wim Taymans
00bb29de0f tools: add -M option to pw-cat and friends
It forces conversion to or from UMP. By default, the events will be
converted to UMP before injecting them into the graph.
2025-08-19 18:34:00 +02:00
Wim Taymans
e35a8554f8 control: improve UMP to Midi conversiom
Improve the spa_ump_to_midi function so that it can consume multiple UMP
messages and produce multiple midi messages.

Some UMP messages (like program changes) need to be translated into up
to 3 midi messages. Do this byt adding a state to the function and by
making it consume the input bytes, just like the spa_ump_from_midi
function.

Adapt code to this new world. This is a little API break..
2025-08-19 18:33:59 +02:00
Wim Taymans
bf10458604 tools: handle both Midi and UMP when recording
The midifile can handle both UMP and Midi formats when saving so allow
this here.
2025-08-19 18:33:59 +02:00
Wim Taymans
15f3b1f450 tools: add -m options to mididump
The -m option forces conversion to MIDI 1.0 and will then dump the midi
1 events.
2025-08-19 18:33:59 +02:00
Wim Taymans
c0a7c01a35 midifile: fix seeking in midifile
When we perform a seek, we need to update the current position in the
file as well or we calculate wrong offsets.
2025-08-19 18:33:58 +02:00
Wim Taymans
f562394596 alsa-seq: improve debug
Make it easier to change the event debug. Also add some more context
to the event debug.
2025-08-19 18:33:58 +02:00
Jordi Mas
0aff6e0ef0 Update Catalan translation 2025-08-18 11:58:40 +00:00
Wim Taymans
5153dc3362 stream: emit RUNNING state from Start
cd68819feb added code to follow the state
change of the node because at the time it the Start code was async and
it was better to complete it before emitting the state.

9b80855821 however made the Start command
sync again and so we can safely emit the running state in the Start.

The effect is that the Running state change is emitted first and then
the node eventfd is added to the data loop that can then call the process
callback. Having the process callback happen before the RUNNING state
change is unexpected and racy.
2025-08-18 13:40:01 +02:00
Wim Taymans
3643c468e4 impl-port: keep auto-generated port.alias in sync
When the port.alias was auto-generated from the port.name, make sure we
update it when the port.name changes.

See #4851
2025-08-18 11:28:15 +02:00
Wim Taymans
1d437dfb8e global: allow property updated for registered globals
The idea of fd2db174c1 was to allow for
property updates after the global was registered but this check was not
removed to actually make this happen.

Fixes #4851
2025-08-18 11:25:50 +02:00
Robert Mader
e8ae244b2b gst: src: Promote 'set format' log to info
Follow various other elements like glupload and gtk4paintablesink and
print the negotiated caps at a higher priority than debug. A small
quality of life improvement to facilitate debugging.
2025-08-13 22:41:38 +02:00
Barnabás Pőcze
b82160c2e7 spa: libcamera: source: remove stale data from buffers
When clearing the buffers, remove the stale pointers and file descriptors
as accidental reuse of those is problematic and potentially difficult to
diagnose. Do this for every data plane.

Also clear the node's `buffer` structures to remove any references to
the provided `spa_buffer` objects and related metadata.
2025-08-13 17:57:30 +02:00
Barnabás Pőcze
bf327d3dfb spa: libcamera: source: simplify spa_libcamera_clear_buffers()
Remove the unused `impl` parameter and the unnecessary early return.
2025-08-13 17:56:48 +02:00
Barnabás Pőcze
b948ffdb25 spa: libcamera: source: remove SPA_DATA_MemPtr support
The current handling of `SPA_DATA_MemPtr` is not entirely correct because
its handling of multi-planar buffers is not appropriate: it leaks memory
mappings because it overwrites `buffer::ptr` for each plane.

Since this data type should not really be in use in normal deployments,
let's remove it for now.
2025-08-13 17:56:44 +02:00
Barnabás Pőcze
3e28f3e859 spa: libcamera: source: rework startup sequence
After e0e8bf083 ("spa: libcamera: source: create eventfd before starting camera"),
things are still not entirely correct. This change ensures that if starting
the camera fails, then the runtime state, most importantly the ring buffer
of completed requests is restored to its initial state.

Furthermore, it is also ensured that `impl::active` can never be observed
by the data thread while it is being changed, which is achieved by setting
it before/after adding/removing the event source.
2025-08-13 10:24:24 +02:00
Barnabás Pőcze
507688e6c9 spa: libcamera: source: add eventfd to loop while locked
While concurrent `spa_loop_add_source()` invocations work with the current
main epoll-based implementation, this is not guaranteed, so lock the loop.
Similarly to how it is done elsewhere and for removal already.
2025-08-13 10:24:16 +02:00
Barnabás Pőcze
1f60cd291f spa: libcamera: source: keep libcamera::FrameBufferAllocator
Instantiate it once and keep it instead of always dynamically
allocating it when the camera is acquired.
2025-08-13 10:24:05 +02:00
Barnabás Pőcze
c517e712ed spa: libcamera: source: clear buffers when format is changed
pipewire assumes that the buffers are removed from a port when its format is
changed even without an explicit call to `port_use_buffer()`.

So if the format is not just tested, clear the buffers, as well as the libcamera
requests and buffers because they are also recreated when a new format is set.
This matches the behaviour of the v4l2 plugin. Furthermore, this change also
removes the call to `spa_libcamera_use_buffers()` because that function does
nothing. And finally this change necessitates that the current format is always
reset (when not testing), not just before reaching `spa_libcamera_set_format()`.
2025-08-13 10:24:01 +02:00
Barnabás Pőcze
31176120f5 spa: libcamera: source: handle try-only format unset
Do nothing if `format == nullptr` and `SPA_NODE_PARAM_FLAG_TEST_ONLY` is present.
2025-08-13 10:23:57 +02:00
Barnabás Pőcze
a8a60832cd spa: libcamera: source: do not emit param change if try-only
If `SPA_NODE_PARAM_FLAG_TEST_ONLY`, then the format does not change
on the node, it is only tested. So do not emit the param change events.
2025-08-13 10:23:52 +02:00
Barnabás Pőcze
dac9e40be6 spa: libcamera: source: extract presence of SPA_NODE_PARAM_FLAG_TEST_ONLY
Use a boolean named `try_only` instead of checking `flags` each time.
2025-08-13 10:23:46 +02:00
Barnabás Pőcze
05a9e52caf spa: libcamera: source: remove format config shortcut
Remove the code that is supposed to compare the current and the to-be-set
format for returning early if they match. This is removed:

  * v4l2 also does not have it either;
  * it needs more consideration (there are not properly handled fields);
  * it would make later changes somewhat more complicated.
2025-08-13 10:23:42 +02:00
Barnabás Pőcze
25075bb3d7 spa: libcamera: source: set chunk flags on error
Set `SPA_CHUNK_FLAG_CORRUPTED` if the frame buffer metadata
signals anything other than success.
2025-08-13 10:23:36 +02:00
Barnabás Pőcze
019a5c130f spa: libcamera: source: process requests on data loop
Since `impl::requestComplete()` runs in an internal libcamera thread, extra care
would need to be taken to validate all accesses to common data structures. For
example, the function might call `spa_libcamera_buffer_recycle()`, which accesses
`impl::ctrls`, which would be unsafe because it could read or modified at the same
time on the data thread. So move the processing of requests to the data loop.
2025-08-13 10:23:32 +02:00
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