We can only write from one thread to the ringbuffer so bypass the
ringbuffer when doing in-thread invoke. Only flush the current
items so that out-of-thread items don't get inserted.
Always append the item to the ringbuffer, even if we are invoking from
the thread itself. This ensure all items are always invoked in the
right order.
If we invoke from the thread, flush all items of the ringbuffer and
return.
Make sure to set the callback to NULL before invoking so that recursive
invoke doesn't call it again.
When while flushing the items we get a recursive invoke, detect this
with a counter and return immediately.
Mostly useful for when invoking from the thread itself so that the new
invoke item is executed before new items are added.
Imagine this case with module-loopback:
- data-loop goes into the capture process function
- mainloop invokes node remove of capture and waits
- data-loop invokes trigger -> node remove is first executed, mainloop
is woken up
- mainloop continues
- mainloop invokes remove of playback and waits
- data-loop continues flushing the ringbuffer -> playback remove is
executed, mainloop wakes up
- mainloop continues destroying items, frees playback
and capture streams
- data-loop finaly gets to flush the trigger and crashes because
streams are gone.
`Transform::Rot90` means the client should rotate 90 deg. clockwise,
which matches `SPA_META_TRANSFORMATION_90`, i.e. the buffer was
rotated 90 deg. anti-clockwise. The flipped cases should be correct
though.
Also add the source value to the debug print for easier future
debugging.
Fixes fa799aac86
First clear the started flag so that we ignore scheduling from the
follower. Then stop the follower and the converter.
This is the sequence we follow when deactivating a node, so do the
same here.
it is important that the node is not scheduled anymore when we clear
the format in suspend or else we might crash.
See #2877
And... we're back to 48Khz probing. Some devices fail to probe with
44.1KHz so when we need to choose between 2 bad things we choose to
do the right thing, which is probe in 48KHz.
Fixes#2857
Modules echo-cancel, filter-chain and loopback may print errors if no
applicable target nodes exist when they start up. For our products this
is not considered error/warning worthy, since the issue will resolve
itself once the target nodes exist.
We don't need to pass the client to the module create and load
functions, they can work without a client.
The only place the client is used is to access the properties to make a
new connection to pipewire. This is also however not a good idea, we
should simply use the defaults used by the context or else a client
could set strange properties like remote.name etc for these internal
connections.
Also removing the dependency of the client will make it possible to load
modules from the startup script or other modules later.
Many Gstreamer elements support transforming buffers via the
`image-orientation` tag. Use it to implement support for the new
VideoTransform meta.
In order for Gstreamer pipelines to enable support for these tags
usually the rotate method has to be set to `auto` or `automatic`,
e.g. `videoflip method=automatic`, `glimagesink rotate-method=automatic`
or `waylandsink rotate-method=auto`.
libcamera can detect camera transforms/rotation, e.g. from the device
tree, and makes that information usable for clients via
`CameraConfiguration::transform`.
Advertise this information via the VideoTransform meta so Pipewire
clients can adjust their output accordingly.
Rotated cameras are common in mobile devices such as the Pinephone Pro,
which was used to test this feature.
When in passthrough mode and there is no converter, simply return
our own PortConfig parameter with our direction and passthrough mode.
Otherwise, use the PortConfig from the converter but filter out only the
PortConfig that matches our direction.
This fixes enumeration of PortConfig on the adapter.
Also try to recycle a buffer if the current buffer_id is invalid.
Ignore -EPIPE from the sender, just ask for more data. -EPIPE is when
the sende runs out of buffers so in that case we need to recycle one
as well.
Fixes#2874
Wait for all pending Start commands from the followers to complete
before adding and starting the driver node.
This ensure that all links are set up and the nodes have received and
replied to the Start command and things can start without hickups.
Don't wait for the node to be added to the graph before we activate
the links to it.
We don't do the reverse for shutdown and the activation counters won't
actually be updated until the node is added.
Waiting can cause race conditions in some specific cases (see in
screen sharing unit test) because the driver node can start
pushing buffers before the link has sent the Buffer io area to the
ports.
With this fix, the receiver (input stream) will first trigger
the input link activation, then the Start command and then it will be
added to the graph.
This does not entirely fix the race conditions when starting. Ideally,
the driver node should wait until all pending Start commands of the
nodes in the graph have completed.
When we try to read one of the events and there was an error, don't
signal the callback. If the error is something else than EAGAIN log
a warning.
Especially for timerfd, EAGAIN can happen when the timer changed
while polling. This can happen when running the profiler because it
polls and updates the timer from different threads.
First we remove the node from the graph, then we disable all links
to it and then we Pause the node. It's possible that the node is still
scheduled while we remove the links. In this case we should not schedule
the node but resume the peer nodes. Also don't log a warning in this
case as it is expected.
Also don't log a warning when a node emits a ready event while it was
removed from the graph. This is also expected because we first remove
the node from the graph and then send the Pause/Suspend command to make
it stop emiting the ready events. Just ignore the event when this
happens.
See also !1449
Avoid scheduling non-active nodes by removing the eventfd source from
the data loop when the node is deactivated. Read any old value from the
eventfd when starting the node again in case it has been written to
while the source was removed from the loop.
The ready callback can still be called when the node isn't active since
it is not called via the eventfd.
The volume plugin was an experiment that's not really used anywhere
that we're aware of. As such it makes sense to switch the default to
disabled state and skip building something no one probably needs.
Signed-off-by: Niklāvs Koļesņikovs <89q1r14hd@relay.firefox.com>
This metadata can be used to signal that a buffer is transformed.
The values are intentionally choosen to coincide with
wl_output::transform from the wayland windowsystem.
First set some of the port flags and data, especially the owner_data
before calling pw_impl_port_set_mix(), which will use the owner_data
to send the mix_info.
See #2847