Commit graph

309 commits

Author SHA1 Message Date
Wim Taymans
e86a68db3f gst: add a clock to gst pipewiresink 2024-03-12 17:36:50 +01:00
Wim Taymans
4437f6e000 gst: only remove port once
The port has node_data set/cleared when it is added/removed to/from
the node. Make sure we only remove the port once to avoid a valgrind
error.
2024-03-12 16:54:50 +01:00
Robert Mader
1a6bb994a5 gst: Fix sanitization of non-writable caps
`gst_caps_make_writable()` may create a copy which we have to keep
using afterwards. The return value was meant to be used for that,
but was promptly forgotten for the initial user.
Avoid such errors in the future by using an in-out parameter instead.

While on it, add a type check and remove a check for an impossible
condition.

Fixes: 8a271a87b ("gst: Sanitize caps before translating")
2024-03-07 17:16:18 +00:00
Antonio Larrosa
2df931483d Specify "Audio" in gstreamer sink/src metadata to fix autodetect
gst-play uses autoaudiosink by default when playing audio, which
iterates over all sinks sorting them by rank. By default,
pipewiresink sets the rank to 0, but it can be overridden
by setting the GST_PLUGIN_FEATURE_RANK env. var. like this:

`GST_PLUGIN_FEATURE_RANK=pipewiresink:268 gst-play-1.0  /usr/share/sounds/alsa/test.wav`

But that doesn't work either because the autoaudiosink plugin also
filters the available options, testing for "Sink" and "Audio" to
appear in the classification metadata

(in the strstr comparison in
https://gitlab.freedesktop.org/gstreamer/gstreamer/-/blob/main/subprojects/gst-plugins-good/gst/autodetect/gstautodetect.c?ref_type=heads#L220
klass is what's set by pipewire as classification,
self->type_klass is "Sink" and self->media_klass is "Audio")

Just adding the word Audio to the classification metadata fixes
this and allows pipewiresink to be selected by autoaudiosink.

I also set it in the source plugin since looking at the code,
autoaudiosrc works exactly the same.
2024-03-07 17:15:20 +00:00
Robert Mader
8a271a87b7 gst: Sanitize caps before translating
DMABuf caps without concrete formats and modifiers don't map well to the
Pipewire negotiation process.
Introduce a new gst_caps_sanitize() helper function, where such cases
can be handled.
2024-03-05 12:08:32 +01:00
Robert Mader
f1b75fc6f8 gst: Add support for DMA_DRM / explicit modifiers
Gstreamer 1.24 added and largely switched to a new, modifier aware
DMABuf API. Unfortunately that breaks the existing DMABuf support in the
PW Gst element.

Add support for the new API.
2024-03-05 12:08:32 +01:00
Wim Taymans
f4e391dd41 stream: add pw_stream_get_nsec() to get current time
Make a method to get the current time to compare agains the pw_time-now
field. This is currently CLOCK_MONOTONIC but make this into a method
so that we can more easily change it later.
2024-03-04 12:59:26 +01:00
Wim Taymans
0f14cc3b13 gst: remove timeouts when autoconnect=false
When we disable autoconnect, disable the timeouts as well. Otherwise the
user has to connect the stream within the 30 second timeout or get a
failure. With autoconnect we can reasonably assume there is a problem
when the stream is not connected after 30 seconds.

Fixes #3884
2024-03-01 10:29:18 +01:00
George Kiagiadakis
5a130ddd73 gstpipewiresrc: break out of wait_started() also on STATE_UNCONNECTED
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.
2023-12-26 16:01:44 +00:00
Michael Tretter
03173530da gst/pipewiresink: fix dts_offset
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.
2023-12-21 15:11:56 +01:00
Wim Taymans
ecf4b071e5 gst: keep track of node ports
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
2023-12-14 13:00:00 +01:00
Wim Taymans
5eb1f35997 gst: remove unused pending list 2023-12-14 12:59:04 +01:00
Michael Tretter
6a68c87b19 gst/pipewiresink: remove special case for size 0
There is no need for a special case with size 0. If size is 0, we can
also write the size instead of 0 to the buffer.
2023-12-05 14:44:56 +00:00
Michael Tretter
0bda84bca1 gst/pipewiresink: replace tabs with spaces
Tabs and spaces are mixed for indentation in the pipewiresink. Replace
all tabs with 8 spaces although indentation is 2 spaces, since that
looks like the intended indent.
2023-12-05 14:44:56 +00:00
Michael Tretter
49b971b5b1 gst/pipewirepool: change acquire/release to log messages
The messages are printed for every buffer. Therefore, they should be log
messages. Also add the bufferpool to the message to be able to identify
the bufferpool that handles the buffers.
2023-12-05 14:44:56 +00:00
Michael Tretter
5f916d8a2d gst/pipewirepool: print buffer type as debug message
The buffers are added to the pipewirepool during setup. Therefore, they
should be debug messages. As at it, use the debug helper to print the
string of the buffer type.
2023-12-05 14:44:56 +00:00
Wim Taymans
aef99f840f Revert "gstpipewiresrc: break out of wait_started() also on STATE_UNCONNECTED"
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.
2023-11-16 09:51:11 +01:00
George Kiagiadakis
7465175ad0 gstpipewiresrc: break out of wait_started() also on STATE_UNCONNECTED
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()
2023-11-09 20:59:40 +00:00
George Kiagiadakis
a852b979b6 gst: avoid reporting error twice
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.
2023-11-09 20:59:40 +00:00
Wim Taymans
bdb7f3adc8 gst: don't stop streaming when paused
We pause when we are unlinked, don't stop the streaming thread because
then we won't be able to resume when we are linked again.

Fixes #3620
2023-11-02 10:06:03 +01:00
Michael Tretter
e4def0ce18 pipewiresink: use maximum size of buffers to configure pool
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.
2023-10-27 18:01:37 +02:00
Michael Tretter
efa08e9892 gst: update buffer size only if format defines a size
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.
2023-10-27 18:01:37 +02:00
Michael Tretter
bd15e5275b pipewiresink: copy metadata into pipewirepool buffers
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.
2023-10-27 18:00:51 +02:00
Michael Tretter
9a72766ae8 pipewiresink: fix type of SPA_META
The SPA_PARAM_META_type must be configured as a SPA_POD_Id, not as
SPA_POD_Int. Otherwise, PipeWire won't allocate the metas.
2023-10-27 17:44:32 +02:00
Wim Taymans
3eed0fbe9b gst: mark streams async
From the process callback we signal a cond and don't dequeue/queue
a buffer directly.
2023-10-21 09:42:15 +02:00
Philippe Normand
140374d207 gst: Prevent a crash when stopping device provider
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.
2023-08-04 10:01:07 +01:00
Wim Taymans
b0a7e4a267 gst: lock/unlock around proxy destroy
See #3324
2023-07-04 12:04:29 +02:00
Wim Taymans
bb72e3bc00 gst: fill default stride in metadata
When there is no metadata on the buffer, use the default video stride
as the stride on the pipewire buffers instead of 0.

Fixes #3236
2023-05-23 09:00:30 +02:00
Robert Mader
004206db37 gst/pipewiresrc: Let GstBaseSrc handle pseudo-live calculations
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.
2023-04-19 19:22:24 +00:00
Wim Taymans
0962555291 gst: implement renegotiation
If the stream format changes, set the basesrc caps again before pushing
a new buffer.

See #3147
2023-04-14 10:42:01 +02:00
Robert Mader
5fc782b893 pipewireclock: Disable clock_reset() for now
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
2023-04-12 10:13:54 +00:00
Robert Mader
8fff69353b gst: deviceprodiver: Sort devices by session priority
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
2023-03-11 10:55:07 +01:00
Robert Mader
06bad5523d gstpipewiresrc: Set stream error on caps negotiation failure
In order to make `wait_started()` error out accordingly, which otherwise
blocks `change_state()` until the timeout is over.
2023-02-23 11:58:52 +00:00
Robert Mader
0b69f37a7c gstpipewiresrc: Do not alter meta plane count
Shared memory buffers may contain multiple planes.
Thus we need to keep the meta plane number as derived from the format.

Closes https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/3045
2023-02-21 08:17:26 +00:00
Mike Playle
23b86761a5 Add autoconnect parameter to pipewiresrc element 2023-02-21 08:16:44 +00:00
Barnabás Pőcze
934ab3036e treewide: use SPDX tags to specify copyright information
SPDX tags make the licensing information easy to understand and clear,
and they are machine parseable.

See https://spdx.dev for more information.
2023-02-16 10:54:48 +00:00
Robert Mader
353c1f709d gstpipewiresrc: make stream errors permanent
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.
2023-02-15 14:49:42 +01:00
Huang-Huang Bao
4b60569c4a gst: correct buffer & meta offset calculation
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
2023-02-06 06:34:14 +00:00
Huang-Huang Bao
023577e391 gst: add buffer video meta support
Fixes video buffer strides handling.
This enables passing of image datas with right line padding.
2023-02-03 07:23:35 +00:00
Georges Basile Stavracas Neto
0fd44bc9d0 pipewiresrc: Make it live by default
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.
2023-01-25 16:13:03 +00:00
Sanchayan Maity
92344bf8ac gst: Accept MP3 and FLAC for compressed sink 2023-01-24 08:44:14 +00:00
Robert Mader
6bf47e0bfa pipewiresrc: Always advertise support for DmaBuf
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
2023-01-12 11:27:27 +00:00
Robert Mader
17c53577e8 gst: Log buffer memory type
This is helpful when one wants to ensure the right memory type is used,
independently from the negotiated format.
2023-01-12 11:27:27 +00:00
Wim Taymans
cab3e3c1ce clarify deprecated use of NODE_TARGET 2023-01-10 17:21:02 +01:00
Wim Taymans
c3032c70b6 keys: move NODE_TARGET to deprecated properties
Add PW_ENABLE_DEPRECATED to some places where we can not yet
avoid removing support.
2023-01-10 17:17:34 +01:00
Wim Taymans
a7df07c449 gst: don't set the deprecated path anymore
Just use the target_object property instead which uses the object.serial
is is less prone to races when the object id is recycled.
2023-01-10 16:47:47 +01:00
Robert Mader
602aa7d541 pipewiresrc: Reenable DMABuf support
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.
2023-01-08 09:17:19 +00:00
Robert Mader
be2757c121 gstpipewireformat: Fully handle SPA_CHOICE_Step
The step value was not used.
2023-01-06 11:16:52 +00:00
Robert Mader
be99aa1eba gst: deviceprodiver: Add fd property / camera portal support
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.
2022-12-27 23:43:22 +01:00
Robert Mader
2bc3e0ca10 gst: deviceprodiver: Use GstPipeWireCore and some cleanups
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
2022-12-27 23:36:36 +01:00