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.
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.
Add a -P (--properties) option to create the context with custom
properties. This can be used to control the modules that are loaded, for
example when they have conditions.
Change the flag from MAPPABLE to UNMAPPABLE to ease compatibility.
Older servers with newer client will not set the flag and so memory is
mappable for the client.
Newer server will set the flag but the client will ignore it and act
like before.
gst_pad_get_current_caps may return NULL and passing that into
gst_caps_is_equal may result in fatal critical log due to the
"g_return_val_if_fail (GST_IS_CAPS (caps1)" check. Fix by checking for
NULL to avoid this.
The target.id might be needed to find existing targets.
Update the properties after setting the initial state for the node, it
is a driver for itself and the properties can make it a driving node
when the driver property is set.
There is no reason to use the fd to schedule process_node, we can call
it directly when we detect an underrun need to complete the cycle with
whatever data made it to the driver.
This avoids starting the graph while the process_node is running and
avoids some stuttering.
See #3937
Implement pw_impl_node_set_io() and do all the things that need to be
done in it, such as taking the clock.id, checking for driver etc.
We can then remove some code that tries to reimplement this, most
notably in the remote-node (where it was missing updates to the
target_rate and target_quantum and maybe related to #3845.
Only activate the nodes when it was not-triggered, do this check with an
atomic compare-and-swap so that we only activate a node once.
We might be able to use this later to make sure that we resume the
untriggered peer nodes when we remove a node from the graph.
The min should always be 1. We have other ways of bumping the number of
buffers to 2, like the ASYNC allocation flag which we can set if we are
also doing some async scheduling. We could make this an option later.
Otherwise, we would also allocate 2 buffers by default between the mixer
and the node, which is unnecessary.
Add link.min-buffers option to set the minimum amount of buffers to
create for links. Set this by default to 2 because we really need two
now in case the sink xruns and does async mixing.
Make this an option because in low-memory cases and when xruns are not
expected, we can set this to 1.
To check if the driver was not completed, check the pending state
instead of the status. This is more correct and we can do this a little
smarter by swapping the current state with 0 atomically.
When we detect a non-zero pending state, wake up the driver node.
Because we atomically swapped 0, we are the only ones doing this and it
will make the node process whatever was in the input ports instead of
underrunning.
Running 2 apps outputting to a sink and pausing one will still play the
output of the other one, this way.
See #3509Fixes#3937
Add a SPA_PARAM_BUFFERS_metaType in the Buffers object. This contains a
bitmask of the mandatory metadata items that should be included on a
buffer when using this Buffers param.
Make the buffer allocation logic skip over the Buffers params that
require unavailable metadata.
This can be used to, for example, enforce specific metadata to describe
extra buffer memory (such as the meaning of generic file descriptors).
One such use is the explicit sync, where an extra buffer data is needed
for the sync fd along with metadata that contains the sync_point.
Parse the metas right after we fixate the params and collec them in the
metas array. We don't have to loop twice and then we can simply pass the
prepared metas to alloc_buffers.
In case there are multiple Buffers params, take the first valid one and
ignore invalid ones.
This flags means that the fd can be mmaped without special handling. It
is the equivalent of the SPA_DATA_FLAG_MAPPABLE. Refuse to map memory
that is not mappable.
Make sure we make all allocated MemFd memory MAPPABLE by default. We can
then remove the stream and filter special handling for MemFd types and
just check the more generic MAPPABLE flag.
Make one exception when a client uploads MemFd buffer memory. We must
manually set the MAPPABLE flag for MemFd to make things backwards
compatible.
Some clients like many camera apps, including Cheese or Snapshot,
trigger a lot of unnessecary renegotiations. While arguably that should
be solved on a Gstreamer level, we can help out by checking if the
preferred new caps are the same that are already in use and skip the
renegotiation in this case.
This allows several apps to e.g. take pictures without a slow and heavy
stream restart.
clear_port() clears all struct mix and removes the port, and can occur
before port io is set to NULL. In this case the port memmaps are not
freed, and are leaked until client pool closes.
Fix by freeing the old io memmap when setting io to NULL, also when the
port was already cleared, so that the memmap lifecycle is the same as
that of the IO.
In order to follow the documentation more closely. Also restructure the
code a bit to make it easier to follow.
See also: e3227b2b5 (gst: simplify modifier extraction)
Fixes: f1b75fc6f (gst: Add support for DMA_DRM / explicit modifiers)
false by default, when true, no warning will be logged when the
context.modules in the config is empty. This can be useful when the
application wants to load all the modules itself.
We don't actually do anything when the name, factory or path is NULL so
don't count this as an action.
Commenting out these keys is a usual way for commenting out complete
sections.
spa_pod_get_values() handles both single values and Choice values and
turns the single value into a None choice.
Check that we have a None or Enum choice because we don't handle
anything else.
See !1952
A peer may announce support for a single modifier, in which case it may
not use a choice-pod. And while the documentation in `dma-buf.dox`
requires modifiers to always be announced as `SPA_CHOICE_Enum`, this has
been supported in the past - as well as matching Pipewire conventions.
Thus, in order to not break existing clients not crash, reintroduce
handling of modifiers as a single long.
Fixes: f1b75fc6f (gst: Add support for DMA_DRM / explicit modifiers)
Solution suggested by Barnabás Pőcze <pobrn@protonmail.com>
Handle allocation errors better, propagate the errors to the caller.
Avoid doing some useless work updating the dict, do this only after we
have done adding all the items when creating and copying.
Make update_string keep a temp array of updates and only apply the
updates when error checking was enabled and there was success. This
makes it possible to parse the JSON string only once.
Fix some of the lookup logic. We can just use spa_dict_lookup() and
spa_dict_lookup_item(), we don't need the index.
Add struct spa_error_location that holds information about some parsing
context such as the line and column number, error and line fragment
with the error.
Make spa_json_get_error() fill in the spa_error_location instead. Add
some error codes to the error state and use this to add a parsing reason
to the location.
Add a debug function to log the error location in a nice way. Also
add a FILE based debug context to log to any FILE.
Replace pw_properties_check_string() with
pw_properties_update_string_checked() and add
pw_properties_new_string_checked(). The check string behaviour can still
be done by setting props to NULL but the main purpose is to be able to
avoid parsing the json file twice in the future.
When using the old pw_properties_update_string(), log a warning to the
log when we fail to parse the complete string.
Use the new checked functions and the debug functions to report about
parsing errors in the tools and conf parsing.
This gives errors like:
```
> pw-loopback --playback-props '{ foo = [ f : g ] }'
error: syntax error in --playback-props: Invalid array separator
line: 1 | { foo = [ f : g ] }
col: 14 | ^
```
Check for JSON parse errors, and log error messages as appropriate.
It's mostly enough to do this where the input is parsed for the first
time, e.g. via pw_properties_new_string, as that already validates the
JSON syntax.
Call _activate() in the aec spa plugin before both capture and sink
streams are started and call _deactivate() after both capture and sink
streams are stopped, to make sure _run() is not called while the spa
plugin is inactive.
Make a new function to set the rtp stream in the error state.
When we fail to start the stream, set the error state. Otherwise (like
when we try to use an invalid interface name) the socket create will
fail but the stream will still try to send data to the invalid socket.