Commit graph

5232 commits

Author SHA1 Message Date
Wim Taymans
818ef4e138 spa: flags just have 1 value 2025-09-12 16:17:26 +02:00
Wim Taymans
2be4c2ba51 meta: add SPA_META_SYNC_TIMELINE_UNSCHEDULED_RELEASE
This flag is set by the producer and should be cleared by the consumer
when it promises to signal the release point.

When a consumer dequeues a buffer with the flag set, it should assume
the client is not going to signal the release point and so it should
reuse the buffer right away. This can only happen when the client
didn't dequeue the buffer at all (killed, timeout, error, ...) or when
it dequeued and queued the buffer without clearing the flag.

See #4885
2025-09-10 13:43:51 +02:00
Wim Taymans
1e5a938e43 adapter: disable rate_match for the video adapter
We don't actually implement this for the video adapter. We should
ideally check for the SPA_IO_RateMatch param to decide this..
2025-09-09 15:10:12 +02:00
Pauli Virtanen
589bc4b6f4 bluez5: iso-io: sync to ISO RX clock, align stream RX in group
Align RX of streams in same ISO group:

- Ensure all streams in ISO group have same target latency also for BAP
  Client

- Determine rate matching to ISO group clock from RX times of all
  streams in the group

- Based on this, compute nominal packet RX times, and feed them to
  decode-buffer instead of the real RX time. This is enough for
  sub-sample level sync.

- Customise buffer overrun handling for ISO so that it drops data to
  arrive exactly at the target, for faster convergence at RX start

The ISO clock matching is done based on kernel-provided packet RX times,
so it has unknown offset from the actual ISO clock, probably a few ms.

Current kernels (6.17) do not provide anything better to use for the
clock matching, and doing it properly appears to be controller
vendor-defined (if possible at all).
2025-09-07 18:26:03 +00:00
Pauli Virtanen
94c354c290 bluez5: decode-buffer: sub-sample accurate fill level tracking
Take resampler delay into account when computing the buffer fill level,
including the fractional part.

If decode-buffer is now fed nominal packet reference times in
write_packet(), it converges the total buffer + resampler latency to the
target at sub-sample accuracy.

This is needed for aligning RX of ISO streams in the same group, so that
e.g. stereo pair alignment is achieved even though the streams have
separate resamplers. Resampler phases get aligned via independent rate
matching.
2025-09-07 18:26:03 +00:00
Pauli Virtanen
e446e3aac5 bluez5: media-source: account for driver clock rate difference in rate match
The rate matching calculations are done in the system clock domain.  If
the driver ticks at a different rate, the correction factor needs to be
adjusted by the rate_diff.

setup_matching() also needs to be before spa_bt_decode_buffer_process():
as follower we should use rate matching value calculated on the
*previous* cycle, because this is what driver is doing when it adjusts
it tick rate.
2025-09-07 18:26:03 +00:00
Pauli Virtanen
f48a72a504 bluez5: smaller max latency for BAP client capture
4 packets should be enough jitter buffer. This matters only for BAP
client, server is controlled by presentation delay.
2025-09-07 18:26:03 +00:00
Pauli Virtanen
7e04f8fe44 bluez5: ensure capture target latency is uniform for an ISO group
All BAP client sources in the ISO group should use same target latency,
so that capture streams stay in sync.
2025-09-07 18:26:03 +00:00
Pauli Virtanen
396d37594c bluez5: media-source: drop all errqueue data when ignoring 2025-09-07 18:26:03 +00:00
Pauli Virtanen
28393cb896 audioconvert: add log topic for resampler 2025-09-07 18:26:03 +00:00
Pauli Virtanen
bf783ab08f alsa: report extra latency for FireWire drivers
Based on testing, ALSA FireWire drivers introduce additional latency
determined by the buffer size.

Report that latency.

Pass device.bus to the node, so it can recognize firewire.
2025-09-07 18:23:31 +00:00
Pauli Virtanen
916896c1cc alsa: force IRQ scheduling for firewire in pro-audio profile
FireWire ALSA driver latency is determined by the buffer size and not the
period. Timer-based scheduling is then not really useful on these devices as
the latency is fixed.

In pro-audio profile, enable IRQ scheduling unconditionally for these
devices, so that controlling the latency works properly.

See #4785
2025-09-07 18:23:31 +00:00
Pauli Virtanen
64aaf8a832 alsa: set minimum period count before automatic period size
Some devices (FireWire) fail to produce audio if period count is < 3,
and also have small buffer size. When quantum is too large, we might
then get too few periods and broken sound.

Set minimum for the period count in ALSA, to determine the maximum
period size we can use. If smaller than what we were going to use, round
down to power-of-2.

See #4785
2025-09-07 18:23:31 +00:00
Barnabás Pőcze
7a98bcf735 spa: libcamera: source: fix typo in log message
';' -> ':'
2025-09-07 18:21:53 +00:00
Barnabás Pőcze
756df7b6ae spa: libcamera: source: remove buffer::ptr
With the removal of `SPA_DATA_MemPtr` support, this member is no longer used.

Fixes: b948ffdb25 ("spa: libcamera: source: remove `SPA_DATA_MemPtr` support")
2025-09-07 18:21:53 +00:00
Barnabás Pőcze
93941e5207 spa: libcamera: source: query frame buffer planes just once 2025-09-07 18:21:53 +00:00
Pauli Virtanen
47780884e1 bluez5: media-source: pass through node.rate and node.latency
Allow user to specify custom values for node.rate and note.latency.

Also restore the 512 default latency.
2025-09-07 18:04:28 +00:00
George Kiagiadakis
e9b78f1c31 bluez5: media-source: add option to control the target latency of the decode-buffer
On production systems, having a constant high latency is favored over
dynamically adjusting it in order to optimize for low latency,
because every time a dynamic adjustment happens, there's a glitch.

This adds an option to let the user specify the exact amount of latency
they want.
2025-09-07 18:04:28 +00:00
George Kiagiadakis
5af8340183 bluez5: media-source: don't set node.latency by default
The hardcoded latency of 512/<rate> is quite low on some ALSA devices.
Instead of forcing that latency onto the graph, just don't set it at all
unless it originates from the BAP presentation delay. That means that
the functionality remains the same for BAP but changes for A2DP to favor
the preferred quantum of the ALSA sink (or whatever is the driver).

Also, avoid setting an empty string ("") latency and rate in the cases
where it's not defined. This allows users to override those properties
through the wireplumber monitor rules if they need to.
2025-09-07 18:04:28 +00:00
Barnabás Pőcze
3b33f60d2f treewide: map SPA_PROP_exposure to V4L2_CID_EXPOSURE_ABSOLUTE
Currently the v4l2 and libcamera plugins map `SPA_PROP_exposure` in incompatible
ways. So change the v4l2 mapping to `V4L2_CID_EXPOSURE_ABSOLUTE` because at least
that is in units of time (a step closer to addressing #4697), and because that
is more relevant for UVC cameras.

Also change the pipewire-v4l2 translation layer.
2025-09-05 17:26:44 +02:00
Wim Taymans
f10dec9dae spa: fix typo in raw-types for LLFE
Spotted by Nikolai

Fixes #4881
2025-09-05 15:44:22 +02:00
Wim Taymans
9f88d6997f audiomixer: set change mask correctly 2025-09-03 10:01:38 +02:00
Wim Taymans
233b7f1d4a audiomixer: format is Id 2025-09-03 10:01:00 +02:00
Wim Taymans
0f6aae914f alsa: don't add MAX_LATENCY when using IRQ scheduling
The Max latency property only works for timer based scheduling so that
we don't select a quantum larger than we can handle in our buffer.

With IRQ based scheduling this does not make sense because we will
reconfigure the buffer completely when we change quantums and so the
currently selected buffer size does not limit the latency in any way.

Fixes #4877
2025-09-02 18:52:38 +02:00
Wim Taymans
9606b37776 alsa: use 3 periods in IRQ mode by default
3 seems to work better as a default for Firewire. It does not actually
add latency because we only keep 1 period filled with data at all times.
2025-09-02 17:29:26 +02:00
Wim Taymans
0095d79ef8 alsa: use 2 (or 3 for batch) periods in IRQ mode
Some drivers (Firewire) have a latency depending on the ALSA buffer size
instead of the period size.

In IRQ mode, we can safely use 2 (or 3 for batch devices) periods
because we always need to reconfigure the hardware when we want to
change the period and so we don't need to keep some headroom like we do
for timer based scheduling.

See #4785
2025-09-02 14:13:19 +02:00
Wim Taymans
0310bb5c5c audiommixer: only clear mix_ops when initialized
It's possible that the mix_ops was not initialized and then the free
pointer is NULL, so check this instead of segfaulting.
2025-09-01 12:39:08 +02:00
Wim Taymans
e2ac91b860 ump: make sure we set the group correctly 2025-08-29 16:59:38 +02:00
Martin Geier
c99311e822 filter-graph: clear external field in unsetup_graph
Without this change the playback with different number of channels
fails with `input port %s[%d]:%s already used as input %d, use mixer`
on the first port.

Signed-off-by: Martin Geier <martin.geier@streamunlimited.com>

Fixes #4866
2025-08-28 10:15:05 +02:00
Wim Taymans
2385aa18e1 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-08-27 17:56:14 +02:00
Pauli Virtanen
984c44b044 bluez5: fix BIS source presentation delay
The value comes from QoS preset, not configurable otherwise right now.

Patch from @michael-kong754
2025-08-27 15:55:50 +00:00
alexdlm
b0b6b1fcc5 Map Razer BlackShark v3 ACP 2025-08-27 15:55:02 +00:00
Wim Taymans
335d891ee9 spa: avoid warnings when compiling cpp
I don't think those qualifiers are needed when doing the atomic
operations.

../spa/include/spa/pod/body.h:250:9: note: in expansion of macro ‘SPA_POD_BODY_LOAD_FIELD_ONCE’
  250 |         SPA_POD_BODY_LOAD_FIELD_ONCE(&b, body, value);
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
../spa/include/spa/pod/body.h: In function ‘int spa_pod_body_get_rectangle(const spa_pod*, const void*, spa_rectangle*)’:
../spa/include/spa/pod/body.h:110:81: warning: type qualifiers ignored on cast result type [-Wignored-qualifiers]
  110 | #define SPA_POD_BODY_LOAD_FIELD_ONCE(a, b, field) ((a)->field = SPA_LOAD_ONCE(&((volatile __typeof__(a))(b))->field))
      |                                                                                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~
../spa/include/spa/utils/atomic.h:22:58: note: in definition of macro ‘SPA_LOAD_ONCE’
   22 | #define SPA_LOAD_ONCE(s)                __atomic_load_n((s), __ATOMIC_RELAXED)
      |                                                          ^
2025-08-26 14:54:23 +02:00
Wim Taymans
e3cc44966b filter-graph: pass void * to connect_port
This makes it a bit more generic and allows us to connect other things
that float arrays.

Add a SPA_FGA_PORT_SEQUENCE as a new port type. The data to connect to
this port is a Sequence type with the size field set to the max/size of
the data.
2025-08-26 13:19:01 +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
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
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
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