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.
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.
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.
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
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.
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`
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.
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
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
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
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.
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).
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.
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.
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")
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
`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)
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`.
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.
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.
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.
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
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.
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.
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
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.