mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2024-11-26 05:21:00 +00:00
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:
parent
027eead86d
commit
5e49f1d10e
1 changed files with 46 additions and 21 deletions
|
@ -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],
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
Loading…
Reference in a new issue