Commit graph

383 commits

Author SHA1 Message Date
Arun Raghavan
cf5db17aa6 gst: sink: Only add VideoCrop meta for video 2025-04-03 06:15:11 -04:00
Wim Taymans
f0a432118a gst: require a buffer size of at least 1
Setting the default size to 0 and outside of the min/max range now means
that there is no suggestion for the size and it should use the
suggestion of the peer.
2025-04-03 06:14:26 -04:00
Sanchayan Maity
f571253ff3 gst: pipewiresrc: Fixate caps if intersect did not return fixated caps
We might end up in a situation where depending on the pipeline,
intersect might not give us fixated caps.

Possible example of such a pipeline can be below.

gst-launch-1.0 -e pipewiresrc target-object=<path> ! audioconvert !
audio/x-raw,format=S16LE,rate=48000,channels=2 ! lamemp3enc !
filesink location=test.mp3

This results in non-fixated caps like below when intersecting caps from
format param and possible_caps which depends on what we have downstream
in the pipeline.

audio/x-raw, layout=(string)interleaved, format=(string)S16LE, rate=(int)48000, channels=(int)2, channel-mask=(bitmask)0x0000000000000003;
audio/x-raw, layout=(string)interleaved, format=(string)S16LE, rate=(int)48000, channels=(int)2

To fix this, fixate the caps explicitly.
2025-04-03 06:14:02 -04:00
Philippe Normand
99b94015a7 gst: src: Fix buffer pool handling in case of caps renegotiation
In case negotiation is first attempted with unfixed caps, bufferpool support was
unconditionally disabled. Then at a second caps negotiation attempt it wasn't
restored according to the property value.
2025-04-03 06:13:24 -04:00
Sanchayan Maity
48a959bf2e gst: pipewireformat: Do not use RANGE if values are equal
This fixes assertion from the underlying gst_value_collect_int_range
when using gst_caps_set_simple with range types when the values are
equal.
2025-04-03 06:13:13 -04:00
Philippe Normand
81408597f4 gst: deviceprovider: Fix a leak and a heap-use-after-free
The device passed to gst_device_provider_device_add() is transfer:floating, so
we need increase its ref, otherwise the pointer we keep internally will be a
dangling ref.

Also gst_device_provider_device_remove() doesn't actually release the device, so
we have to do it ourselves.

Fixes #4616
2025-04-02 15:33:54 +02:00
Taruntej Kanakamalla
a4a9d3540d gst: sink: copy frames if video buffer from other pool
In case of the video, if the buffer to be rendered is from upstream and
not from the pipewirepool, map the memory into video frames and copy the
frames instead of doing a buffer copy.

Avoid splitting of buffers in the case of video, because that might break
the frame layout, especially planar formats, for the applications which
use pipewiresink as a camera source to capture video.
2025-03-04 22:54:47 +05:30
Philippe Normand
9296d1645f gst: deviceprovider: Notify default devices changes
This allows GStreamer apps using GstDeviceMonitor to be notified when the user
changes the default input/output devices.
2025-02-25 12:48:21 +00:00
Taruntej Kanakamalla
333b5aaa36 gst: don't use bufferpool for audio by default
Deprecate the `always-copy` property in pipewiresrc and use the new
property `use-bufferpool` in both pipewiresrc and pipewiresink to
specify whether to use the gstpipewirepool or not.

The gstpipewirepool is used for video by default unless `use-bufferpool`
is set to `false` and it is not used for audio by default unless
`use-bufferpool` is set to `true`
2025-02-03 17:22:34 +00:00
Olle Axelsson
1cc00923db gst: Ensure possible_caps exists before comparing caps
During negotiation, ensure that possible_caps exists before calling
gst_caps_intersect_full(). Sometimes possible_caps seem to be NULL which
cause the GST_IS_CAPS assert to fail.

The reason for the occasional NULL possible_caps during initial
negotiation is unknown, but this is also possible during renegotiation.
The handle_format_change() may be triggered before the next create(),
win which case we have not yet discovered in the streaming thread that
we are in the NOT_NEGOTIATED state. We should guard against this
possibility as well.
2025-01-30 13:38:55 -05:00
Taruntej Kanakamalla
180967bb64 gst: pipewirepool:fix lock evasion in release_buffer 2025-01-24 10:51:29 +00:00
Arun Raghavan
800cd53c56 gst: sink: Whitespace fixups 2025-01-23 10:17:19 -05:00
Arun Raghavan
9ece286c90 gst: Fix up some debug logs
Copy-pasto in the pause code, plus let's use GST_DEBUG_OBJECT() so
we can track which pool is affected.
2025-01-23 10:17:19 -05:00
Wim Taymans
d36a867788 gst: only return the custom flag when in _render()
Make a custom ACQUIRE flag and if it's set, return the custom error
when the pool is empty.
2025-01-17 17:08:07 +01:00
Wim Taymans
c7ccc5abca gst: handle blocking in the _render() function
When we do any other blocking in the render function, we should unblock
and call _wait_preroll() when we go to PAUSED.

We can have this situation when all the buffers are queued in the
pw_stream and we get a new _render() call. We can't get more buffers
from the pool and so we must block and wait.  When we go to PAUSED we
need to unlock and go to _wait_preroll(). Implement this by setting a
pool paused flag that is set when the sink goes to paused, we can then
return a special value that does the wait_preroll().

See !2248
2025-01-17 16:33:15 +01:00
Wim Taymans
c81910a51c gst: use gst_buffer_get_size() to get the buffer size
_get_sizes() contains the padding and we don't want to copy that.
2025-01-17 12:19:07 +01:00
Taruntej Kanakamalla
86e7429039 gst: pipewiresink: don't flush bufferpool in PLAYING_TO_PAUSED
Setting bufferpool to flushing state in PAUSED state is preventing the
buffer flow if there is a seek/flush event.
Instead, set the bufferpool to flushing during the `flush-start` event
and clear it during the `flush-stop`

Deactivate/activate the stream during flush event only if the sink is
in the PLAYING state. In the PAUSED or READY state, the stream would be
inactive and we do not want to alter that
2025-01-17 13:03:34 +05:30
Taruntej Kanakamalla
c0a6a7ea32 gst: handle flush event in pipewiresink
flush the pw buffers to the stream's queue during a FLUSH_START event
and return the unqueued pw buffers, if they are dropped/released without
being rendered, so they can be available to be dequeued for the subsequent
`acquire` calls
2025-01-15 17:03:21 +00:00
Philippe Normand
13c869801c gst: core: Fixup connection error handling
Commit b57b5703d6 made use of `spa_strerror()`
which is incorrect here because pw_connect sets `errno`, so we should use
`strerror()`.
2025-01-12 11:42:29 +00:00
Philippe Normand
b57b5703d6 gst: core: Properly report connection errors 2025-01-12 11:15:04 +00:00
Elliot Chen
419bc600a8 pipewiresink: split buffer and send them in turn if needed
For some streams, the buffer size is changed and may exceed
the acquired buffer size which is acquired from the pool of
pipewiresink. Need split buffer and send them in turn for
this case.
2025-01-03 15:58:37 +09:00
Elliot Chen
152a6683ef pipewiresink: active stream after finishing preoll when changing state from paused to playing 2024-12-30 11:48:34 +09:00
Barnabás Pőcze
b1443185ea gst: sink: remove unnecessary variable
`res` can be removed without changing the behaviour, so do that.
2024-12-14 23:27:45 +01:00
Arun Raghavan
85fa0aae40 gst: src: Set possible_caps before stream connect
The value is used when a the format changes in handle_format_change(),
and while it seems this was typically expected to happen async and thus
protected by the thread lock, there are cases (such as with
auto-port-config) where a param might be set within the
pw_stream_connect() call itself (in the case of auto-port-config, by the
impl_init() of the audioadapter).
2024-12-13 13:44:09 +00:00
Wim Taymans
0658ff93d8 gst: add slave-method property
Set the slave-method to none by default to disable the resampler.
2024-12-03 12:11:47 +01:00
Wim Taymans
9419a12e74 gst: add rate control to the sink
Track the elapsed time between buffers and try to keep the buffer fill
level constant by changing the rate of the stream.

See #4374
2024-12-03 12:11:47 +01:00
Taruntej Kanakamalla
922efaf6ed gst: drop empty buffers in pipewiresrc
In case the dequeued buffer is empty or of size 0, skip the buffer
so that the downstream elements do not report an error
2024-12-02 14:15:23 +05:30
Wim Taymans
89993a3cc6 gst: enable the pipewire ticks as a clock source
Use the pipewire ticks again as the clock source.

This was disabled because the v4l2 sources created bad ticks for the
graph. Now that this is improved we can enable the ticks again.

This has the advantage that simple audio playback does not drift
anymore. The only remaining problem would be timestamp drift or
discontinuities, which we don't handle here yet.
2024-11-26 17:23:00 +01:00
Wim Taymans
ef8d2ab125 gst: mark the pipewiresink as EARLY_PROCESS
We want to receive process callbacks as soon as a buffer is ready for
reuse because we dequeue it for use in our buffer pool.
2024-11-26 16:57:14 +01:00
Michael Olbrich
687075f2bd gst: handle interlace mode
If the peer announces an interlace mode then use it. Otherwise assume
that the video is not interlaced.

This also fixes a problem with caps negotiation:
If downstream reports caps with not fixated interlace mode, e.g.
"interlace-mode=(string){ progressive, interleaved, mixed }"
then without this, the caps handle_format_change() (in the pipewiresrc)
are not fixed and the source waits forever for the negotiation to
finish.
2024-11-14 17:18:28 +01:00
Wim Taymans
bebad7888f gst: take the thread lock before calling pw_stream functions 2024-11-08 12:22:35 +01:00
Ola Fornander
12c8cdf69b gst: deviceprovider: fix memory leak in do_add_nodes
Use `g_autoptr()` to free the new_devices GList that is allocated in
do_add_nodes.
2024-10-22 21:53:57 +00:00
Robert Mader
97719948a5 gst: Stop trying to use DMA_DRM with MOD_INVALID
GSTs DMA_DRM API does explicitely not support implicit modifiers and
trying to use it would result in assertions like
```
gst_video_dma_drm_fourcc_to_string: assertion 'modifier != DRM_FORMAT_MOD_INVALID' failed
```

Fixes: f1b75fc6f ("gst: Add support for DMA_DRM / explicit modifiers")
2024-09-16 15:44:21 +00:00
Wim Taymans
b5cccdb382 json: add and use spa_json_str_object_find()
Parse a string as a json object and copy the value with key as a string.
2024-09-16 13:12:05 +02:00
Philippe Normand
08057e0328 gst: deviceprovider: Signal default devices
By setting a "is-default" boolean property on the discovered GstDevice(s) the
application now gets a good hint of which device to select and use.

Fixes #4268
2024-09-11 13:14:26 +00:00
Robert Mader
586e116f3c gst: stream: Destroy stream before clearing variable
`pw_stream_destroy()` chains up to `on_remove_buffer()` in
GstPipeWireSrc which again needs the stream to still be around to call
`pw_stream_queue_buffer()` on it. By using `g_clear_pointer()` it will
already have been cleared, causing crashes.

Revert to the behavior from before the commit mentioned below and add a
comment in order to avoid regressing in a future cleanup.

Fixes: 0c40c0147 (gst: factor out the stream management and some common variables in a new class)
2024-07-02 20:36:57 +02:00
Robert Mader
226440382b gst: src: Reset transform on stream stop
When a stream is stopped, chances are high that downstream elements
change or get reset, i.e. don't remember a previously send rotation
event. Thus reset the transform value in order to ensure we create a new
one on the next stream start.

In order to not regress the case when downstream *does* remember the
orientation and the buffer orientation changes from e.g.
`TRANSFORMATION_90` to `TRANSFORMATION_None` between stream
stop and restart, initialize the remembered transform to an invalid
value and ensure we always send a rotation event, even for
`TRANSFORMATION_None`.
2024-07-02 15:15:05 +02:00
Michael Tretter
1b7cf61632 gst: pipewiresink: wait for activated buffer pool before updating buffers
PipeWire expects the SPA_TYPE_OBJECT_ParamBuffers to be valid after
setting SPA_PARAM_Format. The pipewiresink knows the final buffer size
only after the pipewirepool has been activated.

There is a race between PipeWire asking the pipewiresink for the buffers
and GStreamer activating the buffer pool. If GStreamer has not activated
the buffer pool before PipeWire asks for the Buffer params, PipeWire
won't allocate buffers with the correct type and size.

The chance of hitting this window increases, if the upstream GStreamer
element doesn't use the buffer pool. In this case the buffer pool is
activated by the first buffer that arrives at the pipewiresink, which
may take some time.

Instead of not updating the Buffer params when the buffer pool is not
active, wait for the buffer pool to become active.
2024-06-20 21:05:45 +00:00
Michael Tretter
21358526d5 gst: pipewiresink: extract gst_pipewire_sink_update_params
Add a helper function for updating the params instead of handling it in
the pool_activated callback. This allows to explicitly set the params
from the element.
2024-06-20 21:05:45 +00:00
Michael Tretter
6468e5338f gst: pipewirepool: print buffer type with numeric value
If the buffer type is invalid, the short_name will be (null). Printing
the numeric value helps the reader to understand the (null) type.
2024-06-20 21:05:45 +00:00
Michael Tretter
7b8b6d92d9 gst: pipewiresink: decrease log level of on_process to LOG
on_process is called whenever a buffer may be queued. This happens for
every buffer. The correct log level is LOG.
2024-06-19 15:43:06 +00:00
Michael Tretter
3b581b2417 gst: pipewiresink: print stream state as string
Print the state of the stream not only as the numeric value, but also
print the name of the state to help the reader.

While at it, add the sink element to the log output to be able to
identify the sink that received the state change.
2024-06-19 15:43:06 +00:00
Robert Rosengren
3cbda26f07 gst: src: disable active state when only going to PAUSED
The pipewiresrc starts the stream in active state but should be inactive
if only going to PAUSED state. This patch sets the stream to inactive
when wait_started has returned in the GStreamer state tranistions.

Also resets internal started state when going PAUSED -> READY.

Fixes #4049
2024-06-17 15:11:48 +02:00
Arun Raghavan
9da01413a1 gst: sink: Disable active state setting when going to PAUSED
On first start, the stream is set to be active when connected. However,
when the element is going to PAUSED and not subsequently to PLAYING,
this is incorrect behaviour.

Fixes: https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/4049
2024-06-12 06:58:44 +00:00
Michael Tretter
a9bf5fa24a gst: fix JPEG format
Since commit f400ff2050 ("gst: Check for video/ caps before parsing
for info") JPEG support in the GStreamer elements is broken as JPEG is
not recognized as a video format anymore.

gst_video_info_from_caps is able to handle "video/" and "image/"
formats. Therefore, the check needs to allow "image/" too.

While at it, cleanup the formatting to make the check more readable.
2024-06-12 06:56:03 +00:00
Michael Tretter
3b68b5088b gst: pipewiresrc: move correct brace under HAVE_GSTREAMER_DMA_DRM
The HAVE_GSTREAMER_DMA_DRM belongs to the inner brace, not the outer
brace, since the inner if statement is under HAVE_GSTREAMER_DMA_DRM.

While doesn't make a difference to the compiler, but confuses a reader.

Put the other brace under the HAVE_GSTREAMER_DMA_DRM.
2024-06-12 06:56:03 +00:00
George Kiagiadakis
8da35df0bf gst: use G_DECLARE_FINAL_TYPE for all classes 2024-06-11 12:51:51 +00:00
George Kiagiadakis
0bde0ebad8 gst: reference the GstPipeWireStream from the pool & the clock 2024-06-11 12:51:51 +00:00
George Kiagiadakis
0c40c01477 gst: factor out the stream management and some common variables in a new class
Construct this new class from both the src and sink to be able to share code

Consolidate the previous mess of open/close/start/stop into a single pair
of open/close functions in the new stream class
2024-06-11 12:51:51 +00:00
Robert Mader
e6f2aa6ce0 gst: src: Improve DMA_DRM caps selection
The translation between Pipewire parameters and Gstreamer caps is,
for compatibility reasons, ambiguous. Formats with linear modifier
are translated both in the legacy way as `format`, as well as
`drm-format`.

When finishing negotiation and setting caps, ensure that we:
1. set caps that the peer actually supports in order to prevent
   negotiation errors.
2. fixate caps to DMA_DRM if both options are supported, using the newly
   introduced helper, in order to prevent hangs.

While on it, add some small clean-ups that hopefully make the code
easier to follow, notably that `pwsrc->caps` and `pwsrc->possible_caps`
are only used during negotiation.
2024-05-29 19:29:02 +02:00