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.
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.
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>
Use target-object=<serial/name> instead of path=<id> for specifying
sink/src targets. Deprecate path= argument.
Change device provider to preferably expose serials instead of ids.
Make the alignment parameter optional when negotiating buffers.
Default to a 16 bytes alignment and adjust for the max cpu
alignment.
Remove the useless align buffer parameter in plugins, we always
set it to 16 anyway.
Gstreamer simply mmap()s the DMA buffers. This can be very very slow on
some hardware, so don't ask for it. For gstreamer to support DMA
buffers, it will need to support a proper way of transferring the
buffers from the GPU to the CPU, e.g. using EGL/OpenGL.
The current code has several issues if a pipewiresrc is stopped and deleted
while a buffer is still in use downstream.
- pw_stream_queue_buffer() is never called for the corresponding
pw_buffer. As a result, the busy counter is never decremented and
pw_stream_dequeue_buffer() of the corresponding pipewire output will
return NULL whenever it encounters this buffer.
- The pipewiresrc does not own the buffer reference unless the buffer is
queued in the source, so calling gst_buffer_unref() unconditionally
causes refcount issues for the buffer.
- buffer_recycle() can race with on_remove_buffer() and
gst_pipewire_src_close(). As a result, buffer_recycle() may access pwsrc
when it was already deleted.
The buffer has its own reference to the pool. So the pool object lock can
be used to ensure that the pwsrc, core and stream remain valid in.
buffer_recycle(). If the 'dispose' function pointer was already cleared,
then on_remove_buffer() has already finished, so abort early.
With the pool lock held, it is save to access the pipewire loop. Now the
loop lock can be used to synchronize with on_remove_buffer(). 'dispose'
must be checked again in case on_remove_buffer() was triggered by something
other than gst_pipewire_src_close().
In on_remove_buffer() unref the buffer if it is queued. Otherwise call
pw_stream_queue_buffer() to ensure that the busy counter is decremented
correctly.
PipeWire does not give DMABUF anymore to clients unless they
explicitly ask for it. This results in v4l2 sending an fd and
the mmapoffset + size fields in the buffer.
GStreamer does not handle the mmapoffset in the fd allocator and
thus runs into mmap problems when using the memory.
Enable DMABuf explicitly to work around the problem until
GStreamer is fixed.
Fixes#1115
Don't do any GStreamer data transport from the PipeWire callback
because it might block in preroll and block our communication with
PipeWire. Instead, take the caps and wake up the caller to continue
with negotiation.
Add a property to periodically send the last buffer to keep the
stream alive. Useful for sparse streams that need to keep the
encoder busy every once and a while.
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.
Fixes#241
Add an option to resend the last buffer on EOS with an updated
timestamp. This can be used to make sure encoders fill up the
gap between last buffer and EOS, like with sparse streams from
screen capture.
This makes sure we first nicely remove the stream from the server
and then close the socket.
If we don't do this, the disconnect might not have flushed out our
disconnect and the server is left with a non-responsive node,
especially if the disconnect on the core was done with a socket from
the portal that is still open.