GStreamer uses a time stamp for the decoding time, but PipeWire uses an
offset to the presentation time. Thus, the pipewiresink must not use the
DTS as dts_offset, but has to calculate the offset.
If the buffer's DTS is invalid, assume that dts is pts.
When the session manager sends an error to the client, it typically
also destroys the node after the error, which causes the stream to go
to STATE_UNCONNECTED via proxy_removed(). In that case, make sure
we exit the loop early, otherwise it will take 30 seconds to unblock
gst_element_set_state()
This is a revised version of the fix that was commited via !1763
and then reverted, as it was problematic. Now the code ensures
that it breaks out only if the state was previously CONNECTING
or higher.
Keep a list of ports for the node. When the node goes away, clear the
port links to the node. Handle the case where the port no longer has a
node.
This avoids a crash when, for example, the node permission is removed
and the port points to the now freed node_data.
Fixes#3708
This reverts commit 7465175ad0.
wait_started() is called before the stream is connecting and so
exits with an error immediately, which then makes the stream start
too early and block.
When the session manager sends an error to the client, it typically
also destroys the node after the error, which causes the stream to go
to STATE_UNCONNECTED via proxy_removed(). In that case, make sure
we exit the loop early, otherwise it will take 30 seconds to unblock
gst_element_set_state()
First, make the error permanent by calling pw_stream_set_error()
and when this emits an error state again, report that to GStreamer.
Do the same in pipewiresink, which didn't even have the
pw_stream_set_error() call before, so the stream wasn't really going
into an error state at all.
For encoded formats, buffer size is the size of the actual data in the
buffer and may change for each frame depending on the content. Thus,
configuring the buffer pool of the pipewiresrc with the size of the
first buffer may be insufficient for later buffers.
Configure the buffer pool to the maximum size of the first upstream
buffer and assume that the following buffers will be allocated with the
same size as the first buffer.
For encoded formats, p->video_info.size will be 0. If the pipewiresrc
handles an encoded format, the bufferpool will be configured to allocate
buffers of size 0. This will cause errors later when trying to copy the
frames into the pipewire buffers.
Update the bufferpool size only if video_info defines an actual buffer
size.
If the pipewiresink needs to copy the GStreamer buffers to the PipeWire
buffers, because the upstream element didn't use the pipewirepool, the
metadata must be copied, too. Otherwise the pipewire datas will be
filled with the metadata from the buffer during the initialization and
not the currently used buffer.
For example, without copying the metadata the buffer timestamp will be
missing on the pipewire buffers.
The provider might fail to connect to the PipeWire core when starting up, so
when stopping we need to check the core is valid before attempting to acquire a
mutex on its loop.
Let's avoid doing timestamp math as much as possible and let `GstBaseSrc`
do it for us instead.
This bring the source more in line with others in Gstreamer and
may help to avoid bugs and share concepts or code.
This was introduced in 4faa28fd96 in order to correctly map the time
from the stream. From d52df30c88 on, however, the clock switched to
monotonic time, which does not need the extra-offset.
Disable `clock_reset()` for now but leave it in place so we can easily
reenable it once we use the stream time again.
This fixes video recording in Cheese and similar apps.
Closes https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/3149
Applications using the device provider typically list devices in the
order they were added. In order to ensure that apps pick nodes like cameras
with the highest priority by default, sort devices accordingly.
This unfortunately does not not have an effect on nodes added later,
e.g. on hotplug.
Closes https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/3072
When pw_stream receives a proxy error it does not set its state to an
error state on its own, commenting:
```
we just emit the state change here to inform the application.
If this is supposed to be a permanent error, the app should
do a pw_stream_set_error()
```
Until now this was not done in the pipewiresrc, resulting in the
negotiation loop to not bail out after an error as a successive
`pw_stream_get_state()` did not return an error state.
Make the error permanent so negotiation errors make us take the
appropriate error paths.
The offset in GstVideoMeta point to location of merge-mapped buffer memories (see "gst_buffer_find_memory()") instead of raw memory location for each plane, make adjustment to comply this rule.
Also some cleanups.
Fixes 023577e391
In theory, the pipewiresrc element is a live element by default.
However, that is not reflected in code, as the element never sets
that flag unless explicltly requested through stream properties.
Make it live by default, but still respect if consumers of the
element mark it as not live.
Quoting https://docs.pipewire.org/page_dma_buf.html section "v4l2":
```
It's the the responsibility of the producer while the add_buffer event
to choose DMA-BUF as the used buffer type even though no modifier is
present, if it can guarantee, that the used buffer is mmapable.
```
As Gstreamer internally can mmap dmabufs just fine, support this case.
This enables dmabuf support with V4L2 and libcamera.
This was also tested against Gnome-Shell, which correctly handles this
case and only chooses DmaBuf if the negotiated format has a modifier,
i.e. if the Gstreamer peer supports the format with
`GST_CAPS_FEATURE_MEMORY_DMABUF`.
Fixes 602aa7d541
This was disabled in 15b4c58e as under various circumstances Gstreamer
pipelines would mmap the DMABufs, which can be very slow in various cases.
One typical example of that is screen casting using a dedicated graphics card.
Thus we only want to use DMABufs if the peer element advertises support for
`GST_CAPS_FEATURE_MEMORY_DMABUF`, ensuring no mapping will happen if we
set the format accordingly.
This allows pipewiresrc to be used with DMABufs for fully accelerated
pipelines or in combination with a download element such as `gldownload`[1]
without regressing the commit above. The `gldownload` approach mirrors
what webrtc (Chromium/Firefox) does, but without duplicating the
functionality into pipewiresrc.
While on it, also implement dmabuf negotiation according to
https://docs.pipewire.org/page_dma_buf.html with the modifiers
`DRM_FORMAT_MOD_INVALID` and `DRM_FORMAT_MOD_LINEAR` in order to allow
dmabuf negotiation with more modern clients, including Gnome-Shell.
1: for now use something like `glupload ! glcolorconvert ! gldownload` -
`gldownload` does not support importing DMABufs yet but `glupload` does.
Add a `fd` property to `GstPipeWireDeviceProvider` so it can be used
with fds obtained from e.g. the camera xdg-desktop-portal.
This is needed so apps like Cheese or Camera can easily implement the
camera portal.
Quoting the commit introducing `GstPipeWireCore`:
```
Make all sources in the same process with the same fd share the
connection to the server. This makes it possible to set the same
fd on multiple sources/sinks and have them all use the same
connection, like when capturing multiple monitors from screencast
with the portal.
```
Do the same for `GstPipeWireDeviceProvider`, so it can share a
connection with device sinks as well. This will be needed for fd based
connections introduced in the next commit.
Further more it allows some cleanups.
1: 70652d1a37
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`.
When always-copy is enabled we should copy buffer memory instead of
sharing buffer memory and using gst_buffer_copy_deep.
This should ensure we recycle the parent buffer as soon as the memory
is copied.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Since gst_fd_allocator_alloc lazy mmap's the buffer to the assigned
file descriptor we can get downstream mmap failures if the pipewire
src(such as the v4l2 spa plugin) closes the file descriptor before
it gets mmap'd. To prevent the closed original file descriptor from
causing a mmap failure dup the file descriptor so that the original
being closed doesn't invalidate the descriptor passed to
gst_fd_allocator_alloc.
Add some more validation to dequeue_buffer as well.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
When in driver mode (mode=provide), the process() function is never
called. It needs to be triggered manually every now and then.
This fixes starting a mode=provide sink, but it doesn't fix re-starting
it... if the client disconnects while streaming, all buffers are getting
filled up and the pool blocks in aqcuiring one more; when the client
connects again, even if we signal the cond to unblock the pool, it still
can't acquire any more buffers and deadlocks.
Relates to: #1980