From 07272c33025ea5b670e3286e20f5c9f9f267c474 Mon Sep 17 00:00:00 2001 From: Gareth Sylvester-Bradley Date: Wed, 19 Aug 2026 17:51:36 +0100 Subject: [PATCH] gst-nmos-rs: enrich fake-chain caps via essence_caps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Run the caps property through essence_caps::caps_from so the dormant path gets the same optional fields as file-derived/SDP caps, and fake→real activation does not renegotiate solely on those defaults. Signed-off-by: Gareth Sylvester-Bradley --- rust/gst-nmos-rs/src/session/mod.rs | 58 ++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/rust/gst-nmos-rs/src/session/mod.rs b/rust/gst-nmos-rs/src/session/mod.rs index 1a59be9..dcd5244 100644 --- a/rust/gst-nmos-rs/src/session/mod.rs +++ b/rust/gst-nmos-rs/src/session/mod.rs @@ -442,7 +442,8 @@ impl Default for CommonSettings { /// Best-available caps for a fake inner chain (appsrc / capsfilter), /// resolved in priority order: -/// 1. `caps` property (user-supplied; authoritative). +/// 1. `caps` property (user-supplied fields win; absent optional +/// fields filled via [`crate::essence_caps::caps_from`]). /// 2. Caps derived from the literal `transport-file`. /// 3. Caps derived from the file at `transport-file-path`. pub(crate) fn fake_caps_from_settings( @@ -453,7 +454,7 @@ pub(crate) fn fake_caps_from_settings( transport_file_path: &str, ) -> Result, anyhow::Error> { if let Some(caps) = caps { - return Ok(Some(caps.clone())); + return Ok(Some(crate::essence_caps::caps_from(caps, None))); } if !transport_file.is_empty() { return caps_from_transport_file(element, transport, transport_file); @@ -1852,4 +1853,57 @@ mod tests { ); } } + + mod fake_caps { + use std::str::FromStr; + + use super::*; + + #[test] + fn caps_property_gets_essence_defaults_like_file_path() { + init_gst(); + let caps = gst::Caps::from_str( + "audio/x-raw,format=S24BE,rate=48000,channels=2,layout=interleaved", + ) + .expect("caps"); + let out = + super::fake_caps_from_settings("nmossrc", Transport::NvDsUdp, Some(&caps), "", "") + .expect("fake caps") + .expect("Some"); + let s = out.structure(0).expect("structure"); + assert_eq!( + s.get::<&str>("channel-order").unwrap(), + "SMPTE2110.(ST)", + "stereo default channel-order", + ); + assert_eq!( + s.get::("channel-mask").unwrap(), + gst::Bitmask::new(0x3), + "stereo default channel-mask", + ); + } + + #[test] + fn caps_property_preserves_explicit_channel_order() { + init_gst(); + // Parentheses in SMPTE2110.(…) need a quoted (string) value; + // bare `channel-order=SMPTE2110.(U02)` fails Caps::from_str. + let caps = gst::Caps::from_str( + "audio/x-raw,format=S24BE,rate=48000,channels=2,layout=interleaved,\ + channel-order=(string)\"SMPTE2110.(U02)\"", + ) + .expect("caps"); + let out = + super::fake_caps_from_settings("nmossrc", Transport::Udp, Some(&caps), "", "") + .expect("fake caps") + .expect("Some"); + assert_eq!( + out.structure(0) + .unwrap() + .get::<&str>("channel-order") + .unwrap(), + "SMPTE2110.(U02)", + ); + } + } }