mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2025-01-22 08:58:15 +00:00
webrtcsink: Added sinkpad with "msid" property
This forwards to the webrtcbin sinkpad's msid when specified. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1460>
This commit is contained in:
parent
aa2d056ea1
commit
606352d7cf
4 changed files with 129 additions and 17 deletions
|
@ -6704,12 +6704,14 @@
|
||||||
"audio_%%u": {
|
"audio_%%u": {
|
||||||
"caps": "audio/x-raw:\naudio/x-opus:\n",
|
"caps": "audio/x-raw:\naudio/x-opus:\n",
|
||||||
"direction": "sink",
|
"direction": "sink",
|
||||||
"presence": "request"
|
"presence": "request",
|
||||||
|
"type": "GstWebRTCSinkPad"
|
||||||
},
|
},
|
||||||
"video_%%u": {
|
"video_%%u": {
|
||||||
"caps": "video/x-raw:\n\nvideo/x-raw(memory:CUDAMemory):\n\nvideo/x-raw(memory:GLMemory):\n\nvideo/x-raw(memory:NVMM):\n\nvideo/x-raw(memory:D3D11Memory):\nvideo/x-vp8:\nvideo/x-h264:\nvideo/x-vp9:\nvideo/x-h265:\n",
|
"caps": "video/x-raw:\n\nvideo/x-raw(memory:CUDAMemory):\n\nvideo/x-raw(memory:GLMemory):\n\nvideo/x-raw(memory:NVMM):\n\nvideo/x-raw(memory:D3D11Memory):\nvideo/x-vp8:\nvideo/x-h264:\nvideo/x-vp9:\nvideo/x-h265:\n",
|
||||||
"direction": "sink",
|
"direction": "sink",
|
||||||
"presence": "request"
|
"presence": "request",
|
||||||
|
"type": "GstWebRTCSinkPad"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rank": "none"
|
"rank": "none"
|
||||||
|
@ -6735,12 +6737,14 @@
|
||||||
"audio_%%u": {
|
"audio_%%u": {
|
||||||
"caps": "audio/x-raw:\naudio/x-opus:\n",
|
"caps": "audio/x-raw:\naudio/x-opus:\n",
|
||||||
"direction": "sink",
|
"direction": "sink",
|
||||||
"presence": "request"
|
"presence": "request",
|
||||||
|
"type": "GstWebRTCSinkPad"
|
||||||
},
|
},
|
||||||
"video_%%u": {
|
"video_%%u": {
|
||||||
"caps": "video/x-raw:\n\nvideo/x-raw(memory:CUDAMemory):\n\nvideo/x-raw(memory:GLMemory):\n\nvideo/x-raw(memory:NVMM):\n\nvideo/x-raw(memory:D3D11Memory):\nvideo/x-vp8:\nvideo/x-h264:\nvideo/x-vp9:\nvideo/x-h265:\n",
|
"caps": "video/x-raw:\n\nvideo/x-raw(memory:CUDAMemory):\n\nvideo/x-raw(memory:GLMemory):\n\nvideo/x-raw(memory:NVMM):\n\nvideo/x-raw(memory:D3D11Memory):\nvideo/x-vp8:\nvideo/x-h264:\nvideo/x-vp9:\nvideo/x-h265:\n",
|
||||||
"direction": "sink",
|
"direction": "sink",
|
||||||
"presence": "request"
|
"presence": "request",
|
||||||
|
"type": "GstWebRTCSinkPad"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rank": "none"
|
"rank": "none"
|
||||||
|
@ -6766,12 +6770,14 @@
|
||||||
"audio_%%u": {
|
"audio_%%u": {
|
||||||
"caps": "audio/x-raw:\naudio/x-opus:\n",
|
"caps": "audio/x-raw:\naudio/x-opus:\n",
|
||||||
"direction": "sink",
|
"direction": "sink",
|
||||||
"presence": "request"
|
"presence": "request",
|
||||||
|
"type": "GstWebRTCSinkPad"
|
||||||
},
|
},
|
||||||
"video_%%u": {
|
"video_%%u": {
|
||||||
"caps": "video/x-raw:\n\nvideo/x-raw(memory:CUDAMemory):\n\nvideo/x-raw(memory:GLMemory):\n\nvideo/x-raw(memory:NVMM):\n\nvideo/x-raw(memory:D3D11Memory):\nvideo/x-vp8:\nvideo/x-h264:\nvideo/x-vp9:\nvideo/x-h265:\n",
|
"caps": "video/x-raw:\n\nvideo/x-raw(memory:CUDAMemory):\n\nvideo/x-raw(memory:GLMemory):\n\nvideo/x-raw(memory:NVMM):\n\nvideo/x-raw(memory:D3D11Memory):\nvideo/x-vp8:\nvideo/x-h264:\nvideo/x-vp9:\nvideo/x-h265:\n",
|
||||||
"direction": "sink",
|
"direction": "sink",
|
||||||
"presence": "request"
|
"presence": "request",
|
||||||
|
"type": "GstWebRTCSinkPad"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rank": "none"
|
"rank": "none"
|
||||||
|
@ -6797,12 +6803,14 @@
|
||||||
"audio_%%u": {
|
"audio_%%u": {
|
||||||
"caps": "audio/x-raw:\naudio/x-opus:\n",
|
"caps": "audio/x-raw:\naudio/x-opus:\n",
|
||||||
"direction": "sink",
|
"direction": "sink",
|
||||||
"presence": "request"
|
"presence": "request",
|
||||||
|
"type": "GstWebRTCSinkPad"
|
||||||
},
|
},
|
||||||
"video_%%u": {
|
"video_%%u": {
|
||||||
"caps": "video/x-raw:\n\nvideo/x-raw(memory:CUDAMemory):\n\nvideo/x-raw(memory:GLMemory):\n\nvideo/x-raw(memory:NVMM):\n\nvideo/x-raw(memory:D3D11Memory):\nvideo/x-vp8:\nvideo/x-h264:\nvideo/x-vp9:\nvideo/x-h265:\n",
|
"caps": "video/x-raw:\n\nvideo/x-raw(memory:CUDAMemory):\n\nvideo/x-raw(memory:GLMemory):\n\nvideo/x-raw(memory:NVMM):\n\nvideo/x-raw(memory:D3D11Memory):\nvideo/x-vp8:\nvideo/x-h264:\nvideo/x-vp9:\nvideo/x-h265:\n",
|
||||||
"direction": "sink",
|
"direction": "sink",
|
||||||
"presence": "request"
|
"presence": "request",
|
||||||
|
"type": "GstWebRTCSinkPad"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rank": "none"
|
"rank": "none"
|
||||||
|
@ -6862,12 +6870,14 @@
|
||||||
"audio_%%u": {
|
"audio_%%u": {
|
||||||
"caps": "audio/x-raw:\naudio/x-opus:\n",
|
"caps": "audio/x-raw:\naudio/x-opus:\n",
|
||||||
"direction": "sink",
|
"direction": "sink",
|
||||||
"presence": "request"
|
"presence": "request",
|
||||||
|
"type": "GstWebRTCSinkPad"
|
||||||
},
|
},
|
||||||
"video_%%u": {
|
"video_%%u": {
|
||||||
"caps": "video/x-raw:\n\nvideo/x-raw(memory:CUDAMemory):\n\nvideo/x-raw(memory:GLMemory):\n\nvideo/x-raw(memory:NVMM):\n\nvideo/x-raw(memory:D3D11Memory):\nvideo/x-vp8:\nvideo/x-h264:\nvideo/x-vp9:\nvideo/x-h265:\n",
|
"caps": "video/x-raw:\n\nvideo/x-raw(memory:CUDAMemory):\n\nvideo/x-raw(memory:GLMemory):\n\nvideo/x-raw(memory:NVMM):\n\nvideo/x-raw(memory:D3D11Memory):\nvideo/x-vp8:\nvideo/x-h264:\nvideo/x-vp9:\nvideo/x-h265:\n",
|
||||||
"direction": "sink",
|
"direction": "sink",
|
||||||
"presence": "request"
|
"presence": "request",
|
||||||
|
"type": "GstWebRTCSinkPad"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rank": "none"
|
"rank": "none"
|
||||||
|
@ -7590,6 +7600,32 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"GstWebRTCSinkPad": {
|
||||||
|
"hierarchy": [
|
||||||
|
"GstWebRTCSinkPad",
|
||||||
|
"GstGhostPad",
|
||||||
|
"GstProxyPad",
|
||||||
|
"GstPad",
|
||||||
|
"GstObject",
|
||||||
|
"GInitiallyUnowned",
|
||||||
|
"GObject"
|
||||||
|
],
|
||||||
|
"kind": "object",
|
||||||
|
"properties": {
|
||||||
|
"msid": {
|
||||||
|
"blurb": "Remote MediaStream ID in use for this pad",
|
||||||
|
"conditionally-available": false,
|
||||||
|
"construct": false,
|
||||||
|
"construct-only": false,
|
||||||
|
"controllable": false,
|
||||||
|
"default": "NULL",
|
||||||
|
"mutable": "ready",
|
||||||
|
"readable": true,
|
||||||
|
"type": "gchararray",
|
||||||
|
"writable": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"GstWebRTCSrcPad": {
|
"GstWebRTCSrcPad": {
|
||||||
"hierarchy": [
|
"hierarchy": [
|
||||||
"GstWebRTCSrcPad",
|
"GstWebRTCSrcPad",
|
||||||
|
|
|
@ -20,7 +20,9 @@ use std::ops::Mul;
|
||||||
use std::sync::{mpsc, Arc, Condvar, Mutex};
|
use std::sync::{mpsc, Arc, Condvar, Mutex};
|
||||||
|
|
||||||
use super::homegrown_cc::CongestionController;
|
use super::homegrown_cc::CongestionController;
|
||||||
use super::{WebRTCSinkCongestionControl, WebRTCSinkError, WebRTCSinkMitigationMode};
|
use super::{
|
||||||
|
WebRTCSinkCongestionControl, WebRTCSinkError, WebRTCSinkMitigationMode, WebRTCSinkPad,
|
||||||
|
};
|
||||||
use crate::aws_kvs_signaller::AwsKvsSignaller;
|
use crate::aws_kvs_signaller::AwsKvsSignaller;
|
||||||
use crate::janusvr_signaller::JanusVRSignaller;
|
use crate::janusvr_signaller::JanusVRSignaller;
|
||||||
use crate::livekit_signaller::LiveKitSignaller;
|
use crate::livekit_signaller::LiveKitSignaller;
|
||||||
|
@ -186,7 +188,7 @@ impl futures::stream::FusedStream for CustomBusStream {
|
||||||
/// Wrapper around our sink pads
|
/// Wrapper around our sink pads
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct InputStream {
|
struct InputStream {
|
||||||
sink_pad: gst::GhostPad,
|
sink_pad: WebRTCSinkPad,
|
||||||
producer: Option<StreamProducer>,
|
producer: Option<StreamProducer>,
|
||||||
/// The (fixed) caps coming in
|
/// The (fixed) caps coming in
|
||||||
in_caps: Option<gst::Caps>,
|
in_caps: Option<gst::Caps>,
|
||||||
|
@ -1434,6 +1436,10 @@ impl InputStream {
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn msid(&self) -> Option<String> {
|
||||||
|
self.sink_pad.property("msid")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NavigationEventHandler {
|
impl NavigationEventHandler {
|
||||||
|
@ -1738,6 +1744,11 @@ impl BaseWebRTCSink {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if let Some(msid) = stream.msid() {
|
||||||
|
gst::trace!(CAT, obj: element, "forwarding msid={msid:?} to webrtcbin sinkpad");
|
||||||
|
pad.set_property("msid", &msid);
|
||||||
|
}
|
||||||
|
|
||||||
let transceiver = pad.property::<gst_webrtc::WebRTCRTPTransceiver>("transceiver");
|
let transceiver = pad.property::<gst_webrtc::WebRTCRTPTransceiver>("transceiver");
|
||||||
|
|
||||||
transceiver.set_property(
|
transceiver.set_property(
|
||||||
|
@ -4071,11 +4082,12 @@ impl ElementImpl for BaseWebRTCSink {
|
||||||
caps_builder = caps_builder.structure(codec.caps.structure(0).unwrap().to_owned());
|
caps_builder = caps_builder.structure(codec.caps.structure(0).unwrap().to_owned());
|
||||||
}
|
}
|
||||||
|
|
||||||
let video_pad_template = gst::PadTemplate::new(
|
let video_pad_template = gst::PadTemplate::with_gtype(
|
||||||
"video_%u",
|
"video_%u",
|
||||||
gst::PadDirection::Sink,
|
gst::PadDirection::Sink,
|
||||||
gst::PadPresence::Request,
|
gst::PadPresence::Request,
|
||||||
&caps_builder.build(),
|
&caps_builder.build(),
|
||||||
|
WebRTCSinkPad::static_type(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -4084,11 +4096,12 @@ impl ElementImpl for BaseWebRTCSink {
|
||||||
for codec in Codecs::audio_codecs() {
|
for codec in Codecs::audio_codecs() {
|
||||||
caps_builder = caps_builder.structure(codec.caps.structure(0).unwrap().to_owned());
|
caps_builder = caps_builder.structure(codec.caps.structure(0).unwrap().to_owned());
|
||||||
}
|
}
|
||||||
let audio_pad_template = gst::PadTemplate::new(
|
let audio_pad_template = gst::PadTemplate::with_gtype(
|
||||||
"audio_%u",
|
"audio_%u",
|
||||||
gst::PadDirection::Sink,
|
gst::PadDirection::Sink,
|
||||||
gst::PadPresence::Request,
|
gst::PadPresence::Request,
|
||||||
&caps_builder.build(),
|
&caps_builder.build(),
|
||||||
|
WebRTCSinkPad::static_type(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -4127,13 +4140,13 @@ impl ElementImpl for BaseWebRTCSink {
|
||||||
(name, false)
|
(name, false)
|
||||||
};
|
};
|
||||||
|
|
||||||
let sink_pad = gst::GhostPad::builder_from_template(templ)
|
let sink_pad = gst::PadBuilder::<WebRTCSinkPad>::from_template(templ)
|
||||||
.name(name.as_str())
|
.name(name.as_str())
|
||||||
.chain_function(|pad, parent, buffer| {
|
.chain_function(|pad, parent, buffer| {
|
||||||
BaseWebRTCSink::catch_panic_pad_function(
|
BaseWebRTCSink::catch_panic_pad_function(
|
||||||
parent,
|
parent,
|
||||||
|| Err(gst::FlowError::Error),
|
|| Err(gst::FlowError::Error),
|
||||||
|this| this.chain(pad, buffer),
|
|this| this.chain(pad.upcast_ref(), buffer),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.event_function(|pad, parent, event| {
|
.event_function(|pad, parent, event| {
|
||||||
|
@ -4250,7 +4263,7 @@ impl ChildProxyImpl for BaseWebRTCSink {
|
||||||
fn child_by_name(&self, name: &str) -> Option<glib::Object> {
|
fn child_by_name(&self, name: &str) -> Option<glib::Object> {
|
||||||
match name {
|
match name {
|
||||||
"signaller" => Some(self.settings.lock().unwrap().signaller.clone().upcast()),
|
"signaller" => Some(self.settings.lock().unwrap().signaller.clone().upcast()),
|
||||||
_ => None,
|
_ => self.obj().static_pad(name).map(|pad| pad.upcast()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,11 +39,16 @@ use gst::subclass::prelude::*;
|
||||||
mod homegrown_cc;
|
mod homegrown_cc;
|
||||||
|
|
||||||
mod imp;
|
mod imp;
|
||||||
|
mod pad;
|
||||||
|
|
||||||
glib::wrapper! {
|
glib::wrapper! {
|
||||||
pub struct BaseWebRTCSink(ObjectSubclass<imp::BaseWebRTCSink>) @extends gst::Bin, gst::Element, gst::Object, @implements gst::ChildProxy, gst_video::Navigation;
|
pub struct BaseWebRTCSink(ObjectSubclass<imp::BaseWebRTCSink>) @extends gst::Bin, gst::Element, gst::Object, @implements gst::ChildProxy, gst_video::Navigation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glib::wrapper! {
|
||||||
|
pub struct WebRTCSinkPad(ObjectSubclass<pad::WebRTCSinkPad>) @extends gst::GhostPad, gst::ProxyPad, gst::Pad, gst::Object;
|
||||||
|
}
|
||||||
|
|
||||||
glib::wrapper! {
|
glib::wrapper! {
|
||||||
pub struct WebRTCSink(ObjectSubclass<imp::WebRTCSink>) @extends BaseWebRTCSink, gst::Bin, gst::Element, gst::Object, @implements gst::ChildProxy, gst_video::Navigation;
|
pub struct WebRTCSink(ObjectSubclass<imp::WebRTCSink>) @extends BaseWebRTCSink, gst::Bin, gst::Element, gst::Object, @implements gst::ChildProxy, gst_video::Navigation;
|
||||||
}
|
}
|
||||||
|
@ -124,6 +129,7 @@ enum WebRTCSinkMitigationMode {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
|
pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
|
||||||
|
WebRTCSinkPad::static_type().mark_as_plugin_api(gst::PluginAPIFlags::empty());
|
||||||
BaseWebRTCSink::static_type().mark_as_plugin_api(gst::PluginAPIFlags::empty());
|
BaseWebRTCSink::static_type().mark_as_plugin_api(gst::PluginAPIFlags::empty());
|
||||||
WebRTCSinkCongestionControl::static_type().mark_as_plugin_api(gst::PluginAPIFlags::empty());
|
WebRTCSinkCongestionControl::static_type().mark_as_plugin_api(gst::PluginAPIFlags::empty());
|
||||||
gst::Element::register(
|
gst::Element::register(
|
||||||
|
|
57
net/webrtc/src/webrtcsink/pad.rs
Normal file
57
net/webrtc/src/webrtcsink/pad.rs
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
use gst::{glib, prelude::*, subclass::prelude::*};
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct WebRTCSinkPad {
|
||||||
|
settings: Mutex<Settings>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
struct Settings {
|
||||||
|
msid: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[glib::object_subclass]
|
||||||
|
impl ObjectSubclass for WebRTCSinkPad {
|
||||||
|
const NAME: &'static str = "GstWebRTCSinkPad";
|
||||||
|
type Type = super::WebRTCSinkPad;
|
||||||
|
type ParentType = gst::GhostPad;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ObjectImpl for WebRTCSinkPad {
|
||||||
|
fn properties() -> &'static [glib::ParamSpec] {
|
||||||
|
static PROPS: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| {
|
||||||
|
vec![glib::ParamSpecString::builder("msid")
|
||||||
|
.flags(glib::ParamFlags::READWRITE | gst::PARAM_FLAG_MUTABLE_READY)
|
||||||
|
.blurb("Remote MediaStream ID in use for this pad")
|
||||||
|
.build()]
|
||||||
|
});
|
||||||
|
PROPS.as_ref()
|
||||||
|
}
|
||||||
|
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
|
||||||
|
let mut settings = self.settings.lock().unwrap();
|
||||||
|
match pspec.name() {
|
||||||
|
"msid" => {
|
||||||
|
settings.msid = value
|
||||||
|
.get::<Option<String>>()
|
||||||
|
.expect("type checked upstream")
|
||||||
|
}
|
||||||
|
name => panic!("no writable property {name:?}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
|
||||||
|
let settings = self.settings.lock().unwrap();
|
||||||
|
match pspec.name() {
|
||||||
|
"msid" => settings.msid.to_value(),
|
||||||
|
name => panic!("no readable property {name:?}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GstObjectImpl for WebRTCSinkPad {}
|
||||||
|
impl PadImpl for WebRTCSinkPad {}
|
||||||
|
impl ProxyPadImpl for WebRTCSinkPad {}
|
||||||
|
impl GhostPadImpl for WebRTCSinkPad {}
|
Loading…
Reference in a new issue