When renegotiating stream parameters (e.g. size), the buffers
are cleared should no longer be queued back. Add a flag to detect this,
while logging a warning and erroring out when the user tries to queue
such a buffer.
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
Initialization of PipeWire could happen too early and deadlock in some
cases. Instead, initialize pipewire right before we're going to actually
use it for the first time.
Fixes#4859
This is required in order to allow plugins to use GL as mincore
is used in Mesas `_eglPointerIsDereferenceable()`.
One example for a client wanting to do so is the in-development
libcamera GPUISP, see https://patchwork.libcamera.org/cover/24183/
When a link enters the "ERROR" state, it is scheduled for destruction in
`module-link-factory.c:link_state_changed()`, which queues `destroy_link()`
to be executed on the context's work queue.
However, if the link is destroyed by means of `pw_impl_link_destroy()`
directly after that, then `link_destroy()` unregisters the associated
`pw_global`'s event hook, resulting in `global_destroy()` not being called
when `pw_impl_link_destroy()` proceeds to call `pw_global_destroy()` some
time later. This causes the scheduled async work to not be cancelled. When
it runs later, it will trigger a use-after-free since the `link_data` object
is directly tied to the `pw_impl_link` object.
For example, if the link is destroyed when the client disconnects:
==259313==ERROR: AddressSanitizer: heap-use-after-free on address 0x7ce753028af0 at pc 0x7f475354a565 bp 0x7ffd71501930 sp 0x7ffd71501920
READ of size 8 at 0x7ce753028af0 thread T0
#0 0x7f475354a564 in destroy_link ../src/modules/module-link-factory.c:253
#1 0x7f475575a234 in process_work_queue ../src/pipewire/work-queue.c:67
#2 0x7b47504e7f24 in source_event_func ../spa/plugins/support/loop.c:1011
[...]
0x7ce753028af0 is located 1136 bytes inside of 1208-byte region [0x7ce753028680,0x7ce753028b38)
freed by thread T0 here:
#0 0x7f475631f79d in free /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_malloc_linux.cpp:51
#1 0x7f4755594a44 in pw_impl_link_destroy ../src/pipewire/impl-link.c:1742
#2 0x7f475569dc11 in do_destroy_link ../src/pipewire/impl-port.c:1386
#3 0x7f47556a428b in pw_impl_port_for_each_link ../src/pipewire/impl-port.c:1673
#4 0x7f475569dc3e in pw_impl_port_unlink ../src/pipewire/impl-port.c:1392
#5 0x7f47556a02d8 in pw_impl_port_destroy ../src/pipewire/impl-port.c:1453
#6 0x7f4755634f79 in pw_impl_node_destroy ../src/pipewire/impl-node.c:2447
#7 0x7b474f722ba8 in client_node_resource_destroy ../src/modules/module-client-node/client-node.c:1253
#8 0x7f47556d7c6c in pw_resource_destroy ../src/pipewire/resource.c:325
#9 0x7f475545f07d in destroy_resource ../src/pipewire/impl-client.c:627
#10 0x7f47554550cd in pw_map_for_each ../src/pipewire/map.h:222
#11 0x7f4755460aa4 in pw_impl_client_destroy ../src/pipewire/impl-client.c:681
#12 0x7b474fb0658b in handle_client_error ../src/modules/module-protocol-native.c:471
[...]
Fix this by cancelling the work queue item in `link_destroy()`, which should
always run, regardless of the ordering of events.
Fixes#4691
When the port is renamed, we queue a PORT_RENAME callback with an arg1
as 1. Before emitting the event we check the registered state of the
port but we want to suppress the event if the port was *not* registered,
ie. when the registered state != 1 (arg1).
Add support for FairPlay SAP v2.5 (encryption type 5) type devices such as Apple Home Pod Minis.
Apparently only these devices require the `POST /feedback` heartbeat, so fix that.
Get the clock pointer using the io_changed stream event.
and update the clock before triggering the process
The clock needs to be updated in the data loop thread
and before triggering the process so move the calls to
`pw_stream_trigger_process` from gstreamer thread context
into the data loop thread context by invoking a callback
and update the clock inside the data loop callback
before the trigger
In case of encoded video we get n_planes as 0 from the video info so
passing that as n_datas is failing during the buffer negotiation. Make
sure to use an appropriate value based on whether we have raw video or
not.
Co-authored-by: Taruntej Kanakamalla <taruntej@asymptotic.io>
When PW source is used with something like Camera and the camera is
disconnected, all buffers are removed and stream will be paused.
When using PW sink with source, the sink side pipeline can go to EOS.
This again results in all the buffers being removed and stream being
paused on the source side. PW source side pipeline can also crash if
the sink was in the middle of frame copying a buffer to render which
got removed.
Handle this scenario by sending a flush-start event at the start of
buffer removal and flush-stop at the end followed by an end of stream
or pipeline error depending on user selection.
For a pipeline like below, we might want to dynamically switch the audio
source.
gst-launch-1.0 -e pipewiresrc autoconnect=false ! queue ! audioconvert ! autoaudiosink
On switching to a different audio source, any one of driver, quantum
or clock rate might change which changes the return `result` value of
gst_pipewire_clock_get_internal_time.
This can result in the basesrc create function incorrectly waiting in
gst_clock_id_wait. We post clock lost message to fix this. In the case
of gst-launch, it will set the pipeline to PAUSED and then PLAYING to
to force a new clock and a new base_time distribution.
Without the clock lost message, the following can be seen
before re-linking to a different source
0:00:30.887602864 79499 0x7fffe8000d40 DEBUG GST_CLOCK gstsystemclock.c:1158:gst_system_clock_id_wait_jitter_unlocked:<pipewireclock0> entry 0x7fffd803fad0 time 0:00:17.024565416 now 0:00:17.024109144 diff (time-now) 456272
after re-linking to a different source
0:00:45.790843245 79499 0x7fffe8000d40 DEBUG GST_CLOCK gstsystemclock.c:1158:gst_system_clock_id_wait_jitter_unlocked:<pipewireclock0> entry 0x7fffd803fad0 time 0:00:31.927694059 now 0:00:17.066883864 diff (time-now) 14860810195
With the clock lost message, the following can be seen
before re-linking to a different source
0:01:09.336533552 89461 0x7fffe8000d40 DEBUG GST_CLOCK gstsystemclock.c:1158:gst_system_clock_id_wait_jitter_unlocked:<pipewireclock0> entry 0x7fffd803fad0 time 0:00:58.198536772 now 0:00:58.197444926 diff (time-now) 1091846
after re-linking to a different source
0:01:21.659827958 89461 0x7fffe8000d40 DEBUG GST_CLOCK gstsystemclock.c:1158:gst_system_clock_id_wait_jitter_unlocked:<pipewireclock0> entry 0x7fffd803fad0 time 0:28:24.853517646 now 0:28:24.853527204 diff (time-now) -9558
Note the difference in `time` and `now` fields of the above log message.
This is easy to reproduce by using a pipewiresink as the audio source
with a pipeline like below, as one of the sources during switching.
gst-launch-1.0 -e audiotestsrc wave=ticks ! audioconvert ! audio/x-raw,format=F32LE,rate=48000,channels=1 !
pipewiresink stream-properties="props,media.class=Audio/Source,node.description=pwsink" client-name=pwsink
Applications need to handle the GST_MESSAGE_CLOCK_LOST message in their
bus handlers.
Let's make sure we own the memory in buffers, so that we can be
resilient to the PW link going away. This currently maintains the status
quo of copying data into the pipewirepool for sending to the remote end,
but moves the allocation of buffers so that ownership is maintained by
the sink in all cases.
There are some tricky corners, especially with bufferpool vs. buffers
param negotiation -- bufferpool parameters can be negotiated in
GStreamer before the link even comes up, so we try to adapt the buffers
param to use the negotiated value. For now, that is more brittle than
tying those two aspects together. We can revisit this if we can find a
way to tie pipeline state and link state more closely.
Co-authored-by: Arun Raghavan <arun@asymptotic.io>
A number of changes for correctness.
1) We expose the actualy min and max values we support in the
allocation query.
2) We don't support max_buffers as 0, as unlimited buffers is not an
option
3) In ParamBuffers, we request the max_buffers from bufferpool config,
as we cannot dynamically allocate buffers
We need to make sure the memory sizes are correctly initialised so the
meta makes sense, and we don't copy the meta from the input buffer as
that doesn't make sense given we have our own meta already.
Counter-intuitive as it seems, when we are driving the clock, we can't
also provide a clock from PipeWire to the pipeline -- we need the
pipeline to drive the graph.
So we make the mode control whether we provide a clock or not.
When using PW source, one might want to dynamically link PW source to
a different source. Setting possible_caps to NULL prevents the caps
intersect from returning a successful result on format change. Do not
set possible_caps to NULL as we get that from peer caps which should
stay the same ideally for the duration of pipeline run. That allows
re-linking PW source any number of times with a pipeline like below.
gst-launch-1.0 pipewiresrc autoconnect=false ! queue ! video/x-raw,format=YUY2 ! videoconvert ! xvimagesink
The above pipeline can be made to switch between a camera source and a
screen capture source like wf-recorder.
Note that this fix only improves the status quo and won't work if the
peer caps change due to a re-negotiation.
We don't actually need to calculate the GCD for each resampler rate
update. The GCD is only used to scale the in/out rates when using the
full resampler and this we can cache and reuse when we did the setup.
The interpolating resampler can work perfectly fine with a GCD of 1 and
so we can just assume that.
spa_alsa_read is called from the source process function when we are a
follower and no buffer is ready yet.
Part of the rate correction was performed by the ALSA driver when it
woke up but now, the resampler has updated the requested size and we
need to requery it before we can start reading samples.
Otherwise, we end up with requested samples from before the rate update
and we might not give enough samples to the resampler. In that case, the
adapter will call us again and we will again try to produce a buffer
worth of the requested samples, which will xrun.
We also need to close the SynObj fd we got, just like we close any
DmaBuf or MemFd.
Make sure we get a compiler error when we add more items to the
data type enumeration later.
Fixes#4807