mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-25 19:21:06 +00:00
examples: webrtc: sendrecv: rust: Use the correct payload types if the remote is the offerer
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3758>
This commit is contained in:
parent
8eeaeab6af
commit
083b9f2a6e
1 changed files with 87 additions and 20 deletions
|
@ -115,8 +115,8 @@ impl App {
|
|||
> {
|
||||
// Create the GStreamer pipeline
|
||||
let pipeline = gst::parse_launch(
|
||||
"videotestsrc pattern=ball is-live=true ! vp8enc deadline=1 ! rtpvp8pay pt=96 ! webrtcbin. \
|
||||
audiotestsrc is-live=true ! opusenc ! rtpopuspay pt=97 ! application/x-rtp,encoding-name=OPUS ! webrtcbin. \
|
||||
"videotestsrc pattern=ball is-live=true ! vp8enc deadline=1 ! rtpvp8pay name=vpay pt=96 ! webrtcbin. \
|
||||
audiotestsrc is-live=true ! opusenc perfect-timestamp=true ! rtpopuspay name=apay pt=97 ! application/x-rtp,encoding-name=OPUS ! webrtcbin. \
|
||||
webrtcbin name=webrtcbin"
|
||||
)?;
|
||||
|
||||
|
@ -200,24 +200,20 @@ impl App {
|
|||
}
|
||||
});
|
||||
|
||||
// Asynchronously set the pipeline to Playing
|
||||
app.pipeline.call_async(|pipeline| {
|
||||
// If this fails, post an error on the bus so we exit
|
||||
if pipeline.set_state(gst::State::Playing).is_err() {
|
||||
gst::element_error!(
|
||||
pipeline,
|
||||
gst::LibraryError::Failed,
|
||||
("Failed to set pipeline to Playing")
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Asynchronously set the pipeline to Playing
|
||||
app.pipeline.call_async(|pipeline| {
|
||||
pipeline
|
||||
.set_state(gst::State::Playing)
|
||||
.expect("Couldn't set pipeline to Playing");
|
||||
});
|
||||
// Asynchronously set the pipeline to Playing if we're creating the offer,
|
||||
// otherwise do that after the offer was received.
|
||||
if app.args.peer_id.is_some() {
|
||||
app.pipeline.call_async(|pipeline| {
|
||||
// If this fails, post an error on the bus so we exit
|
||||
if pipeline.set_state(gst::State::Playing).is_err() {
|
||||
gst::element_error!(
|
||||
pipeline,
|
||||
gst::LibraryError::Failed,
|
||||
("Failed to set pipeline to Playing")
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Ok((app, send_gst_msg_rx, send_ws_msg_rx))
|
||||
}
|
||||
|
@ -377,6 +373,63 @@ impl App {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn configure_pipeline_on_offer(
|
||||
&self,
|
||||
offer: &gst_sdp::SDPMessage,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
// Extract audio/video payload types from the SDP and configure accordingly on the
|
||||
// pipeline as these have to match with the offer
|
||||
let mut opus_id = None;
|
||||
let mut vp8_id = None;
|
||||
for media in offer.medias() {
|
||||
for fmt in media.formats() {
|
||||
if fmt == "webrtc-datachannel" {
|
||||
continue;
|
||||
}
|
||||
|
||||
let pt = match fmt.parse::<u8>() {
|
||||
Ok(pt) => pt,
|
||||
Err(_) => continue,
|
||||
};
|
||||
|
||||
let caps = match media.caps_from_media(pt as i32) {
|
||||
Some(caps) if caps.size() > 0 => caps,
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
let s = caps.structure(0).unwrap();
|
||||
let encoding_name = match s.get::<&str>("encoding-name") {
|
||||
Ok(encoding_name) => encoding_name,
|
||||
Err(_) => continue,
|
||||
};
|
||||
|
||||
if encoding_name == "VP8" && vp8_id.is_none() {
|
||||
vp8_id = Some(pt);
|
||||
} else if encoding_name == "OPUS" && opus_id.is_none() {
|
||||
opus_id = Some(pt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let (Some(opus_id), Some(vp8_id)) = (opus_id, vp8_id) {
|
||||
let apay = self.pipeline.by_name("apay").unwrap();
|
||||
let vpay = self.pipeline.by_name("vpay").unwrap();
|
||||
|
||||
for (pay, pt) in [(apay, opus_id), (vpay, vp8_id)] {
|
||||
pay.set_property("pt", pt as u32);
|
||||
}
|
||||
} else {
|
||||
gst::element_error!(
|
||||
self.pipeline,
|
||||
gst::LibraryError::Failed,
|
||||
("Not all streams found in the offer")
|
||||
);
|
||||
bail!("Not all streams found in the offer");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Handle incoming SDP answers from the peer
|
||||
fn handle_sdp(&self, type_: &str, sdp: &str) -> Result<(), anyhow::Error> {
|
||||
if type_ == "answer" {
|
||||
|
@ -403,6 +456,20 @@ impl App {
|
|||
self.pipeline.call_async(move |_pipeline| {
|
||||
let app = upgrade_weak!(app_clone);
|
||||
|
||||
if app.configure_pipeline_on_offer(&ret).is_err() {
|
||||
return;
|
||||
}
|
||||
|
||||
// If this fails, post an error on the bus so we exit
|
||||
if app.pipeline.set_state(gst::State::Playing).is_err() {
|
||||
gst::element_error!(
|
||||
app.pipeline,
|
||||
gst::LibraryError::Failed,
|
||||
("Failed to set pipeline to Playing")
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let offer = gst_webrtc::WebRTCSessionDescription::new(
|
||||
gst_webrtc::WebRTCSDPType::Offer,
|
||||
ret,
|
||||
|
|
Loading…
Reference in a new issue