[v2] gstreamer: Honor downstream format preferences in caps negotiation
diff mbox series

Message ID 20260722034011.1016641-1-elliot.chen@oss.nxp.com
State New
Headers show
Series
  • [v2] gstreamer: Honor downstream format preferences in caps negotiation
Related show

Commit Message

elliot.chen@oss.nxp.com July 22, 2026, 3:40 a.m. UTC
From: Elliot Chen <elliot.chen@nxp.com>

When using libcamerasrc as a camera source in camerabin with a
video-source-filter that specifies a particular output format,
the negotiated format was not respecting the downstream preference.
This occurred because gst_pad_peer_query_caps() was called with the
libcamera stream format filter directly as its filter argument, which
caused the returned caps to be ordered by the libcamera source format
list rather than by the downstream element's preference.

Fix this by splitting the caps query into two steps: first query the
full set of caps supported by the downstream peer without any filter,
then intersect with the libcamera stream formats using
GST_CAPS_INTERSECT_FIRST. This intersection mode preserves the order
of the first operand (the downstream peer caps), so when the caps are
subsequently fixated, the format preferred by the downstream element
(e.g. the video-source-filter in camerabin) is selected.

Signed-off-by: Elliot Chen <elliot.chen@nxp.com>
---
 src/gstreamer/gstlibcamerasrc.cpp | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

Patch
diff mbox series

diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp
index 9061f9163..579bd466d 100644
--- a/src/gstreamer/gstlibcamerasrc.cpp
+++ b/src/gstreamer/gstlibcamerasrc.cpp
@@ -598,8 +598,13 @@  gst_libcamera_src_negotiate(GstLibcameraSrc *self)
 		StreamConfiguration &stream_cfg = state->config_->at(i);
 
 		/* Retrieve the supported caps. */
+		g_autoptr(GstCaps) peer_caps = gst_pad_peer_query_caps(srcpad, NULL);
+		if (!peer_caps || gst_caps_is_empty(peer_caps))
+			return false;
+
 		g_autoptr(GstCaps) filter = gst_libcamera_stream_formats_to_caps(stream_cfg.formats());
-		g_autoptr(GstCaps) caps = gst_pad_peer_query_caps(srcpad, filter);
+		/* Intersect with downstream's preferred format order first. */
+		g_autoptr(GstCaps) caps = gst_caps_intersect_full(peer_caps, filter, GST_CAPS_INTERSECT_FIRST);
 		if (gst_caps_is_empty(caps))
 			return false;