From eb534b4515ceac27fa5598f13cd5da9dff334c3a Mon Sep 17 00:00:00 2001 From: Sanchayan Maity Date: Wed, 19 Mar 2025 19:54:46 +0530 Subject: [PATCH] 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= ! 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. --- src/gst/gstpipewiresrc.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/gst/gstpipewiresrc.c b/src/gst/gstpipewiresrc.c index 5c77b76e2..1570c83e9 100644 --- a/src/gst/gstpipewiresrc.c +++ b/src/gst/gstpipewiresrc.c @@ -1099,14 +1099,34 @@ handle_format_change (GstPipeWireSrc *pwsrc, } pw_peer_caps = gst_caps_from_format (param); + if (pw_peer_caps && pwsrc->possible_caps) { + GST_DEBUG_OBJECT (pwsrc, "peer caps %" GST_PTR_FORMAT, pw_peer_caps); + GST_DEBUG_OBJECT (pwsrc, "possible caps %" GST_PTR_FORMAT, pwsrc->possible_caps); + pwsrc->caps = gst_caps_intersect_full (pw_peer_caps, pwsrc->possible_caps, GST_CAPS_INTERSECT_FIRST); + + /* + * We expect pw_peer_caps to be fixed caps as we receive that from + * PipeWire. See pw_context_find_format() and SPA_PARAM_Format. + * possible_caps can be non-fixated caps based on what is downstream + * in the pipeline. + * + * The intersection result above might give us non-fixated caps. A + * possible scenario for this is the below pipeline. + * pipewiresrc ! audioconvert ! audio/x-raw,rate=44100,channels=2 ! .. + * + * So we fixate the caps explicitly here. + */ + pwsrc->caps = gst_caps_fixate (pwsrc->caps); gst_caps_maybe_fixate_dma_format (pwsrc->caps); } - if (pwsrc->caps && gst_caps_is_fixed (pwsrc->caps)) { + if (pwsrc->caps) { + g_return_if_fail (gst_caps_is_fixed (pwsrc->caps)); + pwsrc->negotiated = TRUE; structure = gst_caps_get_structure (pwsrc->caps, 0);