webrtcsrc: address non-compliant transceiver creation

Instead of adding transceivers explicitly then setting the remote
description, expecting the manually added transceivers to get picked
up, we pass a promise to set-remote-description-set, and set the
relevant properties on the automatically created transceivers at that
point.

We then call create-answer and proceed as before.

Fixes: https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/issues/596
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1829>
This commit is contained in:
Mathieu Duponchelle 2024-09-30 13:16:13 +02:00 committed by GStreamer Marge Bot
parent 027eead86d
commit 5e49f1d10e

View file

@ -767,15 +767,12 @@ impl Session {
ghostpad ghostpad
} }
fn handle_offer( fn remote_description_set(
&mut self, &mut self,
offer: &gst_webrtc::WebRTCSessionDescription,
element: &super::BaseWebRTCSrc, element: &super::BaseWebRTCSrc,
offer: &gst_webrtc::WebRTCSessionDescription,
) -> (gst::Promise, gst::Bin) { ) -> (gst::Promise, gst::Bin) {
gst::log!(CAT, obj = element, "Got offer {}", offer.sdp().to_string());
let sdp = offer.sdp(); let sdp = offer.sdp();
let direction = gst_webrtc::WebRTCRTPTransceiverDirection::Recvonly;
let webrtcbin = self.webrtcbin(); let webrtcbin = self.webrtcbin();
for (i, media) in sdp.medias().enumerate() { for (i, media) in sdp.medias().enumerate() {
let (codec_names, do_retransmission) = { let (codec_names, do_retransmission) = {
@ -845,15 +842,16 @@ impl Session {
gst::info!( gst::info!(
CAT, CAT,
obj = element, obj = element,
"Adding transceiver for {stream_id} with caps: {caps:#?}" "Getting transceiver for {stream_id} and index {i} with caps: {caps:#?}"
); );
let transceiver = webrtcbin.emit_by_name::<gst_webrtc::WebRTCRTPTransceiver>( let transceiver = webrtcbin.emit_by_name::<gst_webrtc::WebRTCRTPTransceiver>(
"add-transceiver", "get-transceiver",
&[&direction, &caps], &[&(i as i32)],
); );
transceiver.set_property("do_nack", do_retransmission); transceiver.set_property("do_nack", do_retransmission);
transceiver.set_property("fec-type", gst_webrtc::WebRTCFECType::UlpRed); transceiver.set_property("fec-type", gst_webrtc::WebRTCFECType::UlpRed);
transceiver.set_property("codec-preferences", caps);
} }
} else { } else {
gst::info!( gst::info!(
@ -864,10 +862,6 @@ impl Session {
} }
} }
webrtcbin.emit_by_name::<()>("set-remote-description", &[&offer, &None::<gst::Promise>]);
gst::info!(CAT, obj = element, "Set remote description");
let promise = gst::Promise::with_change_func(glib::clone!( let promise = gst::Promise::with_change_func(glib::clone!(
#[weak] #[weak]
element, element,
@ -884,14 +878,47 @@ impl Session {
} }
)); ));
// We cannot emit `create-answer` from here. The promise function
// of the answer needs the state lock which is held by the caller
// of `handle_offer`. So return the promise to the caller so that
// the it can drop the `state` and safely emit `create-answer`
(promise, webrtcbin.clone()) (promise, webrtcbin.clone())
} }
fn handle_offer(
&mut self,
offer: &gst_webrtc::WebRTCSessionDescription,
element: &super::BaseWebRTCSrc,
) -> (gst::Promise, gst::Bin) {
gst::log!(CAT, obj = element, "Got offer {}", offer.sdp().to_string());
let promise = gst::Promise::with_change_func(glib::clone!(
#[weak]
element,
#[strong]
offer,
#[strong(rename_to = session_id)]
self.id,
move |_| {
let mut state = element.imp().state.lock().unwrap();
gst::info!(CAT, obj = element, "got answer for session {session_id:?}");
let Some(session) = state.sessions.get_mut(&session_id) else {
gst::error!(CAT, obj = element, "no session {session_id:?}");
return;
};
let (promise, webrtcbin) = session.remote_description_set(&element, &offer);
drop(state);
webrtcbin.emit_by_name::<()>("create-answer", &[&None::<gst::Structure>, &promise]);
}
));
// We cannot emit `set-remote-description` from here. The promise
// function needs the state lock which is held by the caller
// of `handle_offer`. So return the promise to the caller so that
// the it can drop the `state` and safely emit `set-remote-description`
(promise, self.webrtcbin().clone())
}
fn on_answer_created( fn on_answer_created(
&self, &self,
reply: Result<Option<&gst::StructureRef>, gst::PromiseError>, reply: Result<Option<&gst::StructureRef>, gst::PromiseError>,
@ -1158,10 +1185,8 @@ impl BaseWebRTCSrc {
let (promise, webrtcbin) = session.handle_offer(desc, &this.obj()); let (promise, webrtcbin) = session.handle_offer(desc, &this.obj());
drop(state); drop(state);
webrtcbin.emit_by_name::<()>( webrtcbin
"create-answer", .emit_by_name::<()>("set-remote-description", &[&desc, &promise]);
&[&None::<gst::Structure>, &promise],
);
} }
), ),
), ),