Since we don't follow updates of the params on the mixer but only on the
port, we might get out of sync and fail to negotiate.
Going through the mixers for everything needs some more work.
Fixes#3971
When resample.disabled=true, which is now the default, Format has zero
rate, so latency buffers get zero size. The rate in this case is the
graph rate.
Fix by just using the delay in samples, as all streams must in any case
run at same rate for the combining to work.
Fixes: bff252ce60 ("combine-stream: actually make use of resample.disable")
Add config options to create and start multiple data loops, each with
their own priority and thread affinity if requested.
Make it possible to assign loop.classes to the data-loops. Use the
node.loop.class to find a data-loop for the node of the same class. Try
to evenly spread the nodes over the available matching loops.
With this, it is possible to separate the processing of the nodes
depending on the classes, like audio/video and improve concurency on
the server.
No attempt is done yet to move nodes between loops or to move
independent nodes to separate data loops.
Fixes#3969
We can remove most of the special async handling in adapter, filter and
stream because this is now handled in the core.
Add a node.data-loop property to assign the node to a named data-loop.
Assign the non-rt stream and filter to the main loop. This means that
the node fd will be added to the main-loop and will be woken up directly
without having to wake up the RT thread and invoke the process callback
in the main-loop first. Because non-RT implies async, we can do all of
this like we do our rt processing because the output will only be used
in the next cycle.
When node.async is set, make the node async.
Advertize SPA_IO_AsyncBuffers on mixer ports when supported. Set a new
port flag when AsyncBuffer is supported on the port.
When making a link and if one of the nodes is async and the linked ports
support AsyncBuffer, make the link async and set this as a property on
the link. For async nodes we will use SPA_IO_AsyncBuffers on the mixer
ports.
Nodes that are async will not increment the peer required counters. This
ensures that the peer can start immediately before the async node is
ready.
On an async link, writers will write to the (cycle+1 & 1) async buffers
entry and readers will read from (cycle & 1). This makes the readers read
from the previously filled area.
We need to have two very controlled areas with specific rules for who
reads and who writes where because the two nodes will run concurrently
and no special synchronization is possible otherwise.
These async nodes can be paused and blocked without blocking or xrunning
the rest of graph. If the node didn't produce anything when the next
cycle starts, the graph will run with silence.
See #3509
Go through the mixers of the port to get the params.
This makes it possible to let the mixer decide on formats, buffers and
io areas.
Currently, the format is the same on all mixer input and output ports
and the buffers are shared on the output port but the idea is to make it
possible to have different formats and buffers per link.
This is to iterate params that are common to all ports, such as
EnumFormat or the supported IO areas. Mostly interesting for mixer and
splitter nodes so that we don't have to create a new port just to query
things.
Make a new function to iterate the port params and update the flags etc.
Make sure we clear the cache first and reset the flags. This makes it
possible to call check_params later again.
PulseAudio's property list can store arbitrary data, but
pw_properties can only store null-terminated strings.
So for the time being, ignore those values that don't
have null-terminators or have zero bytes inside.
The length of the value for each value in a property list is serialized
twice. Both the reference implementation and pipewire-pulse send
the same length, so be stricter and only accept a property list
if both lengths are the same.
The eventfd is read/written from/to the data thread and the main thread
concurrently with the update_active() function.
Use an atomic compare and swap to make this update atomic and avoid an
inconsistency between the active boolean and the eventfd. This could
result in the eventfd being unsignaled while the active flag was true
and the application receiving a timeout and XRun in its poll loop.
Fixes#3711
resample.disable was made to default to true, but copying it to stream
properties was forgotten so it didn't have any effect. Make sure to copy
it.
This will also prevent different input/output streams from negotiating
to different rates, which would result to broken audio since we are just
passing sample data through.
spa_loop_invoke from data loop to main loop is not OK, as Wireplumber
currently runs its main loop with "pw_loop_enter(); pw_loop_iterate();
pw_loop_leave();" which causes the loop to be entered only when it is
processing an event.
In this case, part of the time the loop impl->thread==0, and calling
spa_loop_invoke() at such time causes the callback to be run from the
current thread, ie. in this case data loop which must not happen here.
Fix this by using eventfd instead, which is safe as the callback always
runs from the main loop.
Eventfd is also slightly more natural here, as multiple events will
group to the same mainloop cycle.
Use TX timestamps to get accurate reading of queue length and latency on
kernel + controller side.
This is new kernel BT feature, so requires kernel with the necessary
patches, available currently only in bluetooth-next/master branch.
Enabling Poll Errqueue kernel experimental Bluetooth feature is also
required for this.
Use the latency information to mitigate controller issues where ISO
streams are desynchronized due to tx problems or spontaneously when some
packets that should have been sent are left sitting in the queue, and
transmission is off by a multiple of the ISO interval. This state is
visible in the latency information, so if we see streams in a group have
persistently different latencies, drop packets to resynchronize them.
Also make corrections if the kernel/controller queues get too long, so
that we don't have too big latency there.
Since BlueZ watches the same socket for errors, and TX timestamps arrive
via the socket error queue, we need to set BT_POLL_ERRQUEUE in addition
to SO_TIMESTAMPING so that BlueZ doesn't think TX timestamps are errors.
Link: https://github.com/bluez/bluez/issues/515
Link: https://lore.kernel.org/linux-bluetooth/cover.1710440392.git.pav@iki.fi/
Link: https://lore.kernel.org/linux-bluetooth/f57e065bb571d633f811610d273711c7047af335.1712499936.git.pav@iki.fi/