Commit graph

13626 commits

Author SHA1 Message Date
Wim Taymans
8c9c378e9f audioconvert: handle filter-graph setup better
Force filter graph reconfiguration in setup_convert.

When adding/removing filter-graphs, only perform setup when we were
already setup, otherwise we will do this in setup_convert later.

Don't do channelmix_init when we were not setup.

Deactivate the filter-graphs when we suspend.

Fixes #4866
2025-12-16 20:36:05 -08:00
Wim Taymans
cb6e61af49 audioconvert: do params after init of the node
First do the essential properties to set up the node, then set up the
node and then parse the params. The params might do some setup that
relies on a completely configured node, such as emit events.
2025-12-16 20:36:05 -08:00
Wim Taymans
3d4bef6e31 filter-graph: remove a memcpy and some cleanups
We don't need to memcpy if we swap between 2 buffers for overlap.

Remove a duplicate variable.
2025-12-16 20:36:05 -08:00
Wim Taymans
84659234bf filter-graph: remove port check
Remove the port number check, we never call this with an invalid port
number and the check was wrong for the sofa_plugin.

Fixes #4700
2025-12-16 20:36:05 -08:00
Wim Taymans
b308c2a914 filter-graph: fix port find logic
We need both ports to be NULL (failed to find the ports as audio ports)
when we try to link control/notify ports.
2025-12-16 20:36:05 -08:00
Wim Taymans
5f07d7a2a6 filter-graph: ensure we can call setup_graph multiple times
We need to reset the fields used for sorting so that we can run the
setup_graph code multiple times.
2025-12-16 20:36:05 -08:00
Wim Taymans
b90dd20dc5 audioconvert: improve tmp buffer allocation
Use per port allocated memory so that we can easily increase the size
and add more buffers. This is necessary when we add filter-graphs that
require more ports.
2025-12-16 20:36:05 -08:00
Wim Taymans
5af9020ff3 filter-graph: clean control_port array on unload
Because we created it when we loaded the graph.
2025-12-16 20:36:05 -08:00
Wim Taymans
39e0ca2f46 filter-graph: process controls after loading the graph
Do some of the counting of the nodes and controls when we add a node
to make things easier later.

Do the setup of the graph controls after loading the graph because we
know exactly how many controls we will have.

Fixes controls being unavailable until the filter-graph is activated.
2025-12-16 20:36:05 -08:00
Janne Grunau
be1677f569 stream: Fix pw_time.delay calculation for rate.num > 1
Pipewire uses a rate of 256/7680 with the integrated camera of Apple
silicon Macbooks. To calculate pw_time.delay correctly in this case it
has to be divided by time->rate.num. Without this division the delay
contribution of the `((latency->min_ns + latency->max_ns) / 2)` term
ends up as 255 which are 8.5 seconds.
pipewiresrc reports the delay as latency in the gstreamer pipeline which
results in rendering a frame every 8.5 seconds.
I suspect the non-normalized rate of 256/7680 is another bug in
pipewire. The rate for an UVC webcam is reported as 1/30. Both
Video4Linux2 devices report a discrete frame interval of 0.033s (30fps).

Fixes #4957

(cherry picked from commit f03021edd1)
2025-12-15 09:54:16 +01:00
Wim Taymans
43b6a83518 audioconvert: rework the filter-graphs a little
Use a simple free/active linked list for the filter-graphs and insert
the new filters in the right position in the list. Then simply copy the
list to an array for the processing thread.

when reconfiguring, set up all the filters again because the number of
channels might have changed.
2025-12-13 01:25:03 +00:00
Wim Taymans
ce3ff1b54a filter-graph: add support for channel positions
Make it possible to define a channel position in filter-graph.
Use the channel positions to perform the final channelmix.
2025-12-13 01:25:03 +00:00
Wim Taymans
666f6d7d31 filter-graph: make the filter-graph ports dynamic
When parsing the graph, parse the input and output port names into
a separate string array. This was we can keep them around when
setting up the graph.

Instead of setting up the graph right after loading it, do the graph
setup when we activate the graph. This makes it possible to pass the
input channels to the filter-graph and let it create the right amount of
plugins and ouput channels.

When setting up the graphs in the audioconverter, pass the current
number of channels as the input to the graph and keep track of the
channels that each filter produces.

This way we can also load a custom upmix or downmix graph, for example.
2025-12-13 01:25:03 +00:00
Wim Taymans
b46a2b3d95 audioconvert: emit Props changed in all cases
When we apply_props and they changed, mark the Props change event so
that it gets emitted later.

Fixes #4610
2025-11-21 13:23:34 +01:00
Wim Taymans
31d7a88f41 spa: add check for AUX channels 2025-11-21 13:06:09 +01:00
Robert Mader
68a57c58bf gst: Use gst_util_uint64_scale instead of scale_int
GST_SECOND * t.rate.num can turn into a negative gint, resulting in
assertions like:
_gst_util_uint64_scale_int: assertion 'num >= 0' failed

Just use the 64bit version instead.

(cherry picked from commit 77a5100280)
2025-10-30 18:05:48 +01:00
Pauli Virtanen
8c5dd0c9f7 doc: update doxygen-awesome.css
Update doxygen-awesome.css to v2.4.1 (1f3620084ff7573) from upstream.

Link: https://github.com/jothepro/doxygen-awesome-css/
2025-10-16 00:17:26 +03:00
Wim Taymans
2799350a59 modules: use timer-queue in avahi-poll
Pass the pw_context to get to the shared queue and loop.
Patch up the users of avahi-poll.

Fixes #4913
2025-10-13 11:27:56 -07:00
Wim Taymans
181269cafc timer-queue: delete next timer event when it got fired
When we fire the timer event, mark the next timeout as NULL because
nothing else is going to timeout anymore until we rearm the timer.

This has the effect that if we cancel and add the same timer from the
callback that we will reprogram the timer with the new timeout instead
of thinking the item as already programmed.
2025-10-13 11:26:43 -07:00
Wim Taymans
cf0de8f86d timer: fix compilation on arm 2025-10-13 11:26:12 -07:00
Wim Taymans
3fb9524cf1 pulse-server: clear timer when stream is created
Make a function when the stream is created so that we can clear the
create_tag and the timer.
2025-10-13 11:25:47 -07:00
Wim Taymans
5ff1cb5545 pulse-server: use the new timer-queue for timeouts
Use the timer queue for scheduling stream and object data timeouts.

This avoids allocating timerfds for these timeouts and the timer queue
can handle many timeouts more efficiently.
2025-10-13 11:25:41 -07:00
Wim Taymans
f2a11fadf4 timer-queue: add a new timer queue helper
This allows you to schedule timeouts. It keeps a sorted list of
timeouts and uses just 1 timerfd to schedule the head of the timeout
list.
2025-10-13 11:25:37 -07:00
Wim Taymans
ca51f72900 pulse-server: make timer function static and fix formatting 2025-10-13 11:25:32 -07:00
Arun Raghavan
db69a93b82 pulse: Handle timed out streams
If we don't get a link on a stream, we might never send a create stream
reply. The client handles this fine by timing out after 30s and dropping
the stream, but the server holds on to the pw_stream forever (or until
the client quits).

Let's add a timer to clean up such streams on the server.

Fixes: https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/4901
2025-10-13 11:25:25 -07:00
Wim Taymans
fd60e04525 1.4.9 2025-10-09 11:14:51 +02:00
Barnabás Pőcze
3bdc84aadb spa: libcamera: device: adapt to libcamera change
The interface of string typed controls has recently been changed in
libcamera[0], which affects `properties::Model`, so adapt to that change
in such a way that is compatible with both the new and old versions.

[0]: f84522d7cd
2025-10-08 17:55:14 +02:00
Wim Taymans
96b4fdec0a profiler: avoid null dereference
Avoid shadowing some variables from the parent block.

The node of a target can be NULL when the target is running in another
instance. We already do some checks for this but make sure we never
deref the NULL pointer.

Fixes #4922
2025-10-08 17:54:21 +02:00
Wim Taymans
b000859938 module-rtp: fix initial session id and hash
Add a flag to make_sdp to note if this should be a new SDP or a temp
SDP to compare to the existing one.

Move the update of session_id and hash to when we make a new SDP. This
way we also update session_id and hash when we make the first SDP.

This fixes the initial undefined SDP session id and hash.

Fixes #4852
2025-10-06 19:45:01 +02:00
Wim Taymans
636cbae9b6 avahi: handle fd allocation errors
When we fail to allocate an io source or a timerfd, return NULL instead
of crashing later on.

See #4913
2025-09-29 17:33:18 +02:00
Peter Ujfalusi
ba7790123c alsa: Use the minimum period size as headroom for SOF cards
Configure the headroom to be equal of the minimum allowed period size for
the configuration.

This is desirable when the ALSA driver's hw_ptr is 'jumpy' due to
underplaying hardware architecture, like SOF.
In case of SOF the DSP firmware will burst read at stream start to fill
it's host facing buffer and later settles to a constant pace. The minimal
period size is constrained by the driver to cover the initial burst and
settling time of the hw_ptr.

Guard this mode of working with a new boolean flag, which is only enabled
for SOF cards, kept it disabled for other cards to avoid any unforeseen
side effects.

Even if the use-period-size-min-as-headroom is set to true, the manual
headroom configuration will take precedence to allow experimentation.

Link: https://github.com/thesofproject/linux/issues/5284
Link: https://github.com/thesofproject/sof/issues/9695#issuecomment-2569033847
Link: https://github.com/thesofproject/sof/issues/10172
Link: https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/4489
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
2025-09-29 17:32:33 +02:00
Wim Taymans
78937ee0ec adapter: fix Start of adapter
Commit cbbf37c3b8 changed the logic of the
Start command. Before this commit, when there was no converter, the
follower would always get the Start command. After the commit, the
follower would only get Start when previously Paused.

This however breaks when we set a format or buffers on the follower
without a converter because those actions might change the state of the
follower to Paused implicitly.

We should simply remove the started check here and always call Start on
the converter and follower, the implementations themselves will keep track
if anything needs to be done.

Fixes #4911
2025-09-29 17:26:20 +02:00
Pauli Virtanen
dd3798487c alsa: don't fail if 3 periods_min fails
Some drivers (emu10k1) appear to not necessarily support more than 2
periods.

Don't fail start if snd_pcm_hw_params_set_periods_min() fails, then we
just set nearest possible periods and buffer sizes.
2025-09-29 17:25:41 +02:00
Barnabás Pőcze
989b2150dc spa: libcamera: source: fix typo in log message
';' -> ':'

(cherry picked from commit 7a98bcf735)
2025-09-27 13:22:59 +02:00
Barnabás Pőcze
b6c0f26fd1 spa: libcamera: source: query frame buffer planes just once
(cherry picked from commit 93941e5207)
2025-09-27 13:22:59 +02:00
Barnabás Pőcze
88aa30f0d2 spa: libcamera: source: simplify spa_libcamera_clear_buffers()
Remove the unused `impl` parameter and the unnecessary early return.

(cherry picked from commit bf327d3dfb)
2025-09-27 13:22:59 +02:00
Barnabás Pőcze
9be2e3d7e9 spa: libcamera: source: keep libcamera::FrameBufferAllocator
Instantiate it once and keep it instead of always dynamically
allocating it when the camera is acquired.

(cherry picked from commit 1f60cd291f)
2025-09-27 13:22:59 +02:00
Barnabás Pőcze
657e55a65b 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()`.

(cherry picked from commit c517e712ed)
2025-09-27 13:22:59 +02:00
Barnabás Pőcze
a6ec4521f7 spa: libcamera: source: handle try-only format unset
Do nothing if `format == nullptr` and `SPA_NODE_PARAM_FLAG_TEST_ONLY` is present.

(cherry picked from commit 31176120f5)
2025-09-27 13:22:59 +02:00
Barnabás Pőcze
e7eef5f7ec 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.

(cherry picked from commit a8a60832cd)
2025-09-27 13:22:59 +02:00
Barnabás Pőcze
0c418d05c3 spa: libcamera: source: extract presence of SPA_NODE_PARAM_FLAG_TEST_ONLY
Use a boolean named `try_only` instead of checking `flags` each time.

(cherry picked from commit dac9e40be6)
2025-09-27 13:22:59 +02:00
Barnabás Pőcze
3b5a2c06f3 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.

(cherry picked from commit 05a9e52caf)
2025-09-27 13:22:59 +02:00
Barnabás Pőcze
11d224befa spa: libcamera: source: set chunk flags on error
Set `SPA_CHUNK_FLAG_CORRUPTED` if the frame buffer metadata
signals anything other than success.

(cherry picked from commit 25075bb3d7)
2025-09-27 13:22:59 +02:00
Barnabás Pőcze
8ed8f21100 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.

(cherry picked from commit 019a5c130f)
2025-09-27 13:22:59 +02:00
Barnabás Pőcze
3ca1e20b3d 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.

(cherry picked from commit 22ddb88072)
2025-09-27 13:22:59 +02:00
Barnabás Pőcze
746805d30b 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.

(cherry picked from commit c01a2977a5)
2025-09-27 13:22:59 +02:00
Barnabás Pőcze
1d0a1cbf12 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.

(cherry picked from commit 72fd462090)
2025-09-27 13:22:59 +02:00
Barnabás Pőcze
ad1dbf1541 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.

(cherry picked from commit 099292d63d)
2025-09-27 13:22:59 +02:00
Barnabás Pőcze
c80af0c2c0 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.

(cherry picked from commit 68627c5563)
2025-09-27 13:22:59 +02:00
Barnabás Pőcze
ceb10964d3 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()`.

(cherry picked from commit 475665d615)
2025-09-27 13:22:59 +02:00