Merge branch 'whip-sdp-munging' into 'main'

webrtc: whip_signaller: Add a mechanism for SDP munging

Closes #516

See merge request gstreamer/gst-plugins-rs!1525
This commit is contained in:
Arun Raghavan 2024-05-03 15:32:36 +00:00
commit 4b855770ac
3 changed files with 102 additions and 16 deletions

View file

@ -51,6 +51,19 @@ unsafe impl prelude::ObjectInterface for Signallable {
self.end_session = Signallable::end_session; self.end_session = Signallable::end_session;
} }
fn properties() -> &'static [glib::ParamSpec] {
static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| {
vec![glib::ParamSpecBoolean::builder("manual-sdp-munging")
.nick("Manual SDP munging")
.blurb("Whether the signaller manages SDP munging itself")
.default_value(false)
.read_only()
.build()]
});
PROPERTIES.as_ref()
}
fn signals() -> &'static [Signal] { fn signals() -> &'static [Signal] {
static SIGNALS: Lazy<Vec<Signal>> = Lazy::new(|| { static SIGNALS: Lazy<Vec<Signal>> = Lazy::new(|| {
vec![ vec![
@ -302,6 +315,46 @@ unsafe impl prelude::ObjectInterface for Signallable {
Signal::builder("consumer-removed") Signal::builder("consumer-removed")
.param_types([String::static_type(), gst::Element::static_type()]) .param_types([String::static_type(), gst::Element::static_type()])
.build(), .build(),
/**
* GstRSWebRTCSignallableIface::munge-session-description:
* @self: The object implementing #GstRSWebRTCSignallableIface
* @session_id: Id of the session being described
* @description: The WebRTC session description to modify
*
* For special-case handling, a callback can be registered to modify the session
* description before the signaller sends it to the peer.
*
* Return: A modified session description
*/
Signal::builder("munge-session-description")
.run_last()
.param_types([
str::static_type(),
gst_webrtc::WebRTCSessionDescription::static_type(),
])
.return_type::<gst_webrtc::WebRTCSessionDescription>()
.class_handler(|_tokens, args| {
let _ = args[0usize]
.get::<&super::Signallable>()
.unwrap_or_else(|e| {
panic!("Wrong type for argument {}: {:?}", 0usize, e)
});
let _ = args[1usize].get::<&str>().unwrap_or_else(|e| {
panic!("Wrong type for argument {}: {:?}", 1usize, e)
});
let desc = args[2usize]
.get::<&gst_webrtc::WebRTCSessionDescription>()
.unwrap_or_else(|e| {
panic!("Wrong type for argument {}: {:?}", 2usize, e)
});
Some(desc.clone().into())
})
.accumulator(move |_hint, output, input| {
*output = input.clone();
false
})
.build(),
/** /**
* GstRSWebRTCSignallableIface::send-session-description: * GstRSWebRTCSignallableIface::send-session-description:
* @self: The object implementing #GstRSWebRTCSignallableIface * @self: The object implementing #GstRSWebRTCSignallableIface
@ -435,18 +488,6 @@ where
} }
iface.stop = vstop_trampoline::<Obj>; iface.stop = vstop_trampoline::<Obj>;
fn send_sdp_trampoline<Obj: types::ObjectSubclass + SignallableImpl>(
this: &super::Signallable,
session_id: &str,
sdp: &gst_webrtc::WebRTCSessionDescription,
) {
let this = this
.dynamic_cast_ref::<<Obj as types::ObjectSubclass>::Type>()
.unwrap();
SignallableImpl::send_sdp(this.imp(), session_id, sdp)
}
iface.send_sdp = send_sdp_trampoline::<Obj>;
fn add_ice_trampoline<Obj: types::ObjectSubclass + SignallableImpl>( fn add_ice_trampoline<Obj: types::ObjectSubclass + SignallableImpl>(
this: &super::Signallable, this: &super::Signallable,
session_id: &str, session_id: &str,
@ -492,6 +533,11 @@ pub trait SignallableImpl: object::ObjectImpl + Send + Sync + 'static {
pub trait SignallableExt: 'static { pub trait SignallableExt: 'static {
fn start(&self); fn start(&self);
fn stop(&self); fn stop(&self);
fn munge_sdp(
&self,
session_id: &str,
sdp: &gst_webrtc::WebRTCSessionDescription,
) -> gst_webrtc::WebRTCSessionDescription;
fn send_sdp(&self, session_id: &str, sdp: &gst_webrtc::WebRTCSessionDescription); fn send_sdp(&self, session_id: &str, sdp: &gst_webrtc::WebRTCSessionDescription);
fn add_ice( fn add_ice(
&self, &self,
@ -512,6 +558,17 @@ impl<Obj: IsA<super::Signallable>> SignallableExt for Obj {
self.emit_by_name::<bool>("stop", &[]); self.emit_by_name::<bool>("stop", &[]);
} }
fn munge_sdp(
&self,
session_id: &str,
sdp: &gst_webrtc::WebRTCSessionDescription,
) -> gst_webrtc::WebRTCSessionDescription {
self.emit_by_name::<gst_webrtc::WebRTCSessionDescription>(
"munge-session-description",
&[&session_id, sdp],
)
}
fn send_sdp(&self, session_id: &str, sdp: &gst_webrtc::WebRTCSessionDescription) { fn send_sdp(&self, session_id: &str, sdp: &gst_webrtc::WebRTCSessionDescription) {
self.emit_by_name::<bool>("send-session-description", &[&session_id, sdp]); self.emit_by_name::<bool>("send-session-description", &[&session_id, sdp]);
} }

View file

@ -2130,7 +2130,17 @@ impl BaseWebRTCSink {
.emit_by_name::<()>("set-local-description", &[&offer, &None::<gst::Promise>]); .emit_by_name::<()>("set-local-description", &[&offer, &None::<gst::Promise>]);
drop(state); drop(state);
signaller.send_sdp(session_id, &offer); let maybe_munged_offer = if signaller
.has_property("manual-sdp-munging", Some(bool::static_type()))
&& signaller.property("manual-sdp-munging")
{
// Don't munge, signaller will manage this
offer
} else {
// Use the default munging mechanism (signal registered by user)
signaller.munge_sdp(session_id, &offer)
};
signaller.send_sdp(session_id, &maybe_munged_offer);
} }
} }
@ -2174,7 +2184,19 @@ impl BaseWebRTCSink {
} }
drop(state); drop(state);
signaller.send_sdp(&session_id, &answer);
let maybe_munged_answer = if signaller
.has_property("manual-sdp-munging", Some(bool::static_type()))
&& signaller.property("manual-sdp-munging")
{
// Don't munge, signaller will manage this
answer
} else {
// Use the default munging mechanism (signal registered by user)
signaller.munge_sdp(session_id.as_str(), &answer)
};
signaller.send_sdp(&session_id, &maybe_munged_answer);
self.on_remote_description_set(element, session_id) self.on_remote_description_set(element, session_id)
} }

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MPL-2.0 // SPDX-License-Identifier: MPL-2.0
use crate::signaller::{Signallable, SignallableImpl}; use crate::signaller::{Signallable, SignallableExt, SignallableImpl};
use crate::utils::{ use crate::utils::{
build_link_header, build_reqwest_client, parse_redirect_location, set_ice_servers, wait, build_link_header, build_reqwest_client, parse_redirect_location, set_ice_servers, wait,
wait_async, WaitError, wait_async, WaitError,
@ -120,7 +120,7 @@ impl WhipClient {
self.raise_error("Local description is not set".to_string()); self.raise_error("Local description is not set".to_string());
return; return;
} }
Some(offer) => offer, Some(offer) => self.obj().munge_sdp("unique", &offer),
}; };
gst::debug!( gst::debug!(
@ -562,6 +562,12 @@ impl ObjectImpl for WhipClient {
.maximum(3600) .maximum(3600)
.default_value(DEFAULT_TIMEOUT) .default_value(DEFAULT_TIMEOUT)
.build(), .build(),
glib::ParamSpecBoolean::builder("manual-sdp-munging")
.nick("Manual SDP munging")
.blurb("Whether the signaller manages SDP munging itself")
.default_value(false)
.read_only()
.build(),
] ]
}); });
@ -608,6 +614,7 @@ impl ObjectImpl for WhipClient {
let settings = self.settings.lock().unwrap(); let settings = self.settings.lock().unwrap();
settings.timeout.to_value() settings.timeout.to_value()
} }
"manual-sdp-munging" => true.to_value(),
_ => unimplemented!(), _ => unimplemented!(),
} }
} }