diff options
author | Taruntej Kanakamalla <taruntej@asymptotic.io> | 2023-07-28 16:09:38 +0300 |
---|---|---|
committer | GStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org> | 2023-11-17 21:08:44 +0300 |
commit | a0638ec983a8e8126f39a7e77856d3994555363f (patch) | |
tree | 007f986e70873170bdd10b09ba80ffdf0c1fdeff | |
parent | 3fcab675703f9d1bbb6f13c6dd5c8d256940ceb5 (diff) |
net/webrtc: Extract BaseWebRTCSrc
Define a Base for all the webrtcsrc type elements
so they can all be derived from it. Similar to base
element defined for webrtcsink type elements
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1284>
-rw-r--r-- | docs/plugins/gst_plugins_cache.json | 219 | ||||
-rw-r--r-- | net/webrtc/src/webrtcsrc/imp.rs | 157 | ||||
-rw-r--r-- | net/webrtc/src/webrtcsrc/mod.rs | 7 |
3 files changed, 221 insertions, 162 deletions
diff --git a/docs/plugins/gst_plugins_cache.json b/docs/plugins/gst_plugins_cache.json index 6cdfe0b27..bec111845 100644 --- a/docs/plugins/gst_plugins_cache.json +++ b/docs/plugins/gst_plugins_cache.json @@ -6440,6 +6440,7 @@ "description": "WebRTC src", "hierarchy": [ "GstWebRTCSrc", + "GstBaseWebRTCSrc", "GstBin", "GstElement", "GstObject", @@ -6466,108 +6467,7 @@ "type": "GstWebRTCSrcPad" } }, - "properties": { - "audio-codecs": { - "blurb": "Names of audio codecs to be be used during the SDP negotiation. Valid values: [OPUS]", - "conditionally-available": false, - "construct": false, - "construct-only": false, - "controllable": false, - "mutable": "ready", - "readable": true, - "type": "GstValueArray", - "writable": true - }, - "enable-data-channel-navigation": { - "blurb": "Enable navigation events through a dedicated WebRTCDataChannel", - "conditionally-available": false, - "construct": false, - "construct-only": false, - "controllable": false, - "default": "false", - "mutable": "ready", - "readable": true, - "type": "gboolean", - "writable": true - }, - "meta": { - "blurb": "Free form metadata about the consumer", - "conditionally-available": false, - "construct": false, - "construct-only": false, - "controllable": false, - "mutable": "ready", - "readable": true, - "type": "GstStructure", - "writable": true - }, - "signaller": { - "blurb": "The Signallable object to use to handle WebRTC Signalling", - "conditionally-available": false, - "construct": false, - "construct-only": true, - "controllable": false, - "mutable": "null", - "readable": true, - "type": "GstRSWebRTCSignallableIface", - "writable": true - }, - "stun-server": { - "blurb": "The STUN server of the form stun://host:port", - "conditionally-available": false, - "construct": false, - "construct-only": false, - "controllable": false, - "default": "stun://stun.l.google.com:19302", - "mutable": "ready", - "readable": true, - "type": "gchararray", - "writable": true - }, - "turn-servers": { - "blurb": "The TURN servers of the form <\"turn(s)://username:password@host:port\", \"turn(s)://username1:password1@host1:port1\">", - "conditionally-available": false, - "construct": false, - "construct-only": false, - "controllable": false, - "mutable": "ready", - "readable": true, - "type": "GstValueArray", - "writable": true - }, - "video-codecs": { - "blurb": "Names of video codecs to be be used during the SDP negotiation. Valid values: [VP8, H264, VP9, H265]", - "conditionally-available": false, - "construct": false, - "construct-only": false, - "controllable": false, - "mutable": "ready", - "readable": true, - "type": "GstValueArray", - "writable": true - } - }, - "rank": "primary", - "signals": { - "request-encoded-filter": { - "args": [ - { - "name": "arg0", - "type": "gchararray" - }, - { - "name": "arg1", - "type": "gchararray" - }, - { - "name": "arg2", - "type": "GstCaps" - } - ], - "return-type": "GstElement", - "when": "last" - } - } + "rank": "primary" }, "whipclientsink": { "author": "Taruntej Kanakamalla <taruntej@asymptotic.io>", @@ -6890,6 +6790,121 @@ } } }, + "GstBaseWebRTCSrc": { + "hierarchy": [ + "GstBaseWebRTCSrc", + "GstBin", + "GstElement", + "GstObject", + "GInitiallyUnowned", + "GObject" + ], + "interfaces": [ + "GstChildProxy" + ], + "kind": "object", + "properties": { + "audio-codecs": { + "blurb": "Names of audio codecs to be be used during the SDP negotiation. Valid values: [OPUS]", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "mutable": "ready", + "readable": true, + "type": "GstValueArray", + "writable": true + }, + "enable-data-channel-navigation": { + "blurb": "Enable navigation events through a dedicated WebRTCDataChannel", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "false", + "mutable": "ready", + "readable": true, + "type": "gboolean", + "writable": true + }, + "meta": { + "blurb": "Free form metadata about the consumer", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "mutable": "ready", + "readable": true, + "type": "GstStructure", + "writable": true + }, + "signaller": { + "blurb": "The Signallable object to use to handle WebRTC Signalling", + "conditionally-available": false, + "construct": false, + "construct-only": true, + "controllable": false, + "mutable": "null", + "readable": true, + "type": "GstRSWebRTCSignallableIface", + "writable": true + }, + "stun-server": { + "blurb": "The STUN server of the form stun://host:port", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "stun://stun.l.google.com:19302", + "mutable": "ready", + "readable": true, + "type": "gchararray", + "writable": true + }, + "turn-servers": { + "blurb": "The TURN servers of the form <\"turn(s)://username:password@host:port\", \"turn(s)://username1:password1@host1:port1\">", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "mutable": "ready", + "readable": true, + "type": "GstValueArray", + "writable": true + }, + "video-codecs": { + "blurb": "Names of video codecs to be be used during the SDP negotiation. Valid values: [VP8, H264, VP9, H265]", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "mutable": "ready", + "readable": true, + "type": "GstValueArray", + "writable": true + } + }, + "signals": { + "request-encoded-filter": { + "args": [ + { + "name": "arg0", + "type": "gchararray" + }, + { + "name": "arg1", + "type": "gchararray" + }, + { + "name": "arg2", + "type": "GstCaps" + } + ], + "return-type": "GstElement", + "when": "last" + } + } + }, "GstRSWebRTCSignallableIface": { "hierarchy": [ "GstRSWebRTCSignallableIface", diff --git a/net/webrtc/src/webrtcsrc/imp.rs b/net/webrtc/src/webrtcsrc/imp.rs index 8b27cecf6..42a05108c 100644 --- a/net/webrtc/src/webrtcsrc/imp.rs +++ b/net/webrtc/src/webrtcsrc/imp.rs @@ -43,7 +43,7 @@ struct Settings { } #[derive(Default)] -pub struct WebRTCSrc { +pub struct BaseWebRTCSrc { settings: Mutex<Settings>, n_video_pads: AtomicU16, n_audio_pads: AtomicU16, @@ -51,14 +51,21 @@ pub struct WebRTCSrc { } #[glib::object_subclass] -impl ObjectSubclass for WebRTCSrc { - const NAME: &'static str = "GstWebRTCSrc"; - type Type = super::WebRTCSrc; +impl ObjectSubclass for BaseWebRTCSrc { + const NAME: &'static str = "GstBaseWebRTCSrc"; + type Type = super::BaseWebRTCSrc; type ParentType = gst::Bin; - type Interfaces = (gst::URIHandler, gst::ChildProxy); + type Interfaces = (gst::ChildProxy,); } -impl ObjectImpl for WebRTCSrc { +unsafe impl<T: BaseWebRTCSrcImpl> IsSubclassable<T> for super::BaseWebRTCSrc { + fn class_init(class: &mut glib::Class<Self>) { + Self::parent_class_init::<T>(class); + } +} +pub(crate) trait BaseWebRTCSrcImpl: BinImpl {} + +impl ObjectImpl for BaseWebRTCSrc { fn properties() -> &'static [glib::ParamSpec] { static PROPS: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| { vec![ @@ -205,7 +212,7 @@ impl ObjectImpl for WebRTCSrc { static SIGNALS: Lazy<Vec<glib::subclass::Signal>> = Lazy::new(|| { vec![ /** - * WebRTCSrc::request-encoded-filter: + * BaseWebRTCSrc::request-encoded-filter: * @producer_id: Identifier of the producer * @pad_name: The name of the output pad * @allowed_caps: the allowed caps for the output pad @@ -278,7 +285,7 @@ struct SignallerSignals { handle_ice: glib::SignalHandlerId, } -impl WebRTCSrc { +impl BaseWebRTCSrc { fn webrtcbin(&self) -> gst::Bin { let state = self.state.lock().unwrap(); let webrtcbin = state @@ -562,15 +569,22 @@ impl WebRTCSrc { let mline = transceiver.map_or(mline, |t| Some(t.mlineindex())); // Same logic as gst_pad_create_stream_id and friends, making a hash of - // the URI and adding `:<some-id>`, here the ID is the mline of the + // the URI (session id, if URI doesn't exist) and adding `:<some-id>`, here the ID is the mline of the // stream in the SDP. mline.map(|mline| { let mut cs = glib::Checksum::new(glib::ChecksumType::Sha256).unwrap(); - cs.update( - self.uri() - .expect("get_stream_id should never be called if no URI has been set") - .as_bytes(), - ); + + let data: String = if self + .signaller() + .has_property("uri", Some(String::static_type())) + { + self.signaller().property::<Option<String>>("uri").unwrap() + } else { + // use the session id + self.state.lock().unwrap().session_id.clone().unwrap() + }; + + cs.update(data.as_bytes()); format!("{}:{mline}", cs.string().unwrap()) }) @@ -983,20 +997,7 @@ impl WebRTCSrc { } } -impl ElementImpl for WebRTCSrc { - fn metadata() -> Option<&'static gst::subclass::ElementMetadata> { - static ELEMENT_METADATA: Lazy<gst::subclass::ElementMetadata> = Lazy::new(|| { - gst::subclass::ElementMetadata::new( - "WebRTCSrc", - "Source/Network/WebRTC", - "WebRTC src", - "Thibault Saunier <tsaunier@igalia.com>", - ) - }); - - Some(&*ELEMENT_METADATA) - } - +impl ElementImpl for BaseWebRTCSrc { fn pad_templates() -> &'static [gst::PadTemplate] { static PAD_TEMPLATES: Lazy<Vec<gst::PadTemplate>> = Lazy::new(|| { let mut video_caps_builder = gst::Caps::builder_full() @@ -1095,11 +1096,11 @@ impl ElementImpl for WebRTCSrc { } } -impl GstObjectImpl for WebRTCSrc {} +impl GstObjectImpl for BaseWebRTCSrc {} -impl BinImpl for WebRTCSrc {} +impl BinImpl for BaseWebRTCSrc {} -impl ChildProxyImpl for WebRTCSrc { +impl ChildProxyImpl for BaseWebRTCSrc { fn child_by_index(&self, index: u32) -> Option<glib::Object> { if index == 0 { Some(self.signaller().upcast()) @@ -1123,6 +1124,60 @@ impl ChildProxyImpl for WebRTCSrc { } } +#[derive(PartialEq)] +enum SignallerState { + Started, + Stopped, +} + +struct State { + session_id: Option<String>, + signaller_state: SignallerState, + webrtcbin: Option<gst::Element>, + flow_combiner: gst_base::UniqueFlowCombiner, + signaller_signals: Option<SignallerSignals>, + data_channel: Option<WebRTCDataChannel>, +} + +impl Default for State { + fn default() -> Self { + Self { + signaller_state: SignallerState::Stopped, + session_id: None, + webrtcbin: None, + flow_combiner: Default::default(), + signaller_signals: Default::default(), + data_channel: None, + } + } +} + +#[derive(Default)] +pub struct WebRTCSrc {} + +impl ObjectImpl for WebRTCSrc {} + +impl GstObjectImpl for WebRTCSrc {} + +impl BinImpl for WebRTCSrc {} + +impl ElementImpl for WebRTCSrc { + fn metadata() -> Option<&'static gst::subclass::ElementMetadata> { + static ELEMENT_METADATA: Lazy<gst::subclass::ElementMetadata> = Lazy::new(|| { + gst::subclass::ElementMetadata::new( + "WebRTCSrc", + "Source/Network/WebRTC", + "WebRTC src", + "Thibault Saunier <tsaunier@igalia.com>", + ) + }); + + Some(&*ELEMENT_METADATA) + } +} + +impl BaseWebRTCSrcImpl for WebRTCSrc {} + impl URIHandlerImpl for WebRTCSrc { const URI_TYPE: gst::URIType = gst::URIType::Src; @@ -1131,7 +1186,9 @@ impl URIHandlerImpl for WebRTCSrc { } fn uri(&self) -> Option<String> { - self.signaller().property::<Option<String>>("uri") + let obj = self.obj(); + let base = obj.upcast_ref::<super::BaseWebRTCSrc>().imp(); + base.signaller().property::<Option<String>>("uri") } fn set_uri(&self, uri: &str) -> Result<(), glib::Error> { @@ -1153,36 +1210,18 @@ impl URIHandlerImpl for WebRTCSrc { // See https://github.com/servo/rust-url/pull/768 for a PR implementing that url_str.replace_range(0..uri.scheme().len(), socket_scheme); - self.signaller().set_property("uri", &url_str); + let obj = self.obj(); + let base = obj.upcast_ref::<super::BaseWebRTCSrc>().imp(); + base.signaller().set_property("uri", &url_str); Ok(()) } } -#[derive(PartialEq)] -enum SignallerState { - Started, - Stopped, -} - -struct State { - session_id: Option<String>, - signaller_state: SignallerState, - webrtcbin: Option<gst::Element>, - flow_combiner: gst_base::UniqueFlowCombiner, - signaller_signals: Option<SignallerSignals>, - data_channel: Option<WebRTCDataChannel>, -} - -impl Default for State { - fn default() -> Self { - Self { - signaller_state: SignallerState::Stopped, - session_id: None, - webrtcbin: None, - flow_combiner: Default::default(), - signaller_signals: Default::default(), - data_channel: None, - } - } +#[glib::object_subclass] +impl ObjectSubclass for WebRTCSrc { + const NAME: &'static str = "GstWebRTCSrc"; + type Type = super::WebRTCSrc; + type ParentType = super::BaseWebRTCSrc; + type Interfaces = (gst::URIHandler,); } diff --git a/net/webrtc/src/webrtcsrc/mod.rs b/net/webrtc/src/webrtcsrc/mod.rs index 72167d5d1..b85612bcc 100644 --- a/net/webrtc/src/webrtcsrc/mod.rs +++ b/net/webrtc/src/webrtcsrc/mod.rs @@ -42,7 +42,11 @@ use gst::prelude::*; use gst::{glib, prelude::StaticType}; glib::wrapper! { - pub struct WebRTCSrc(ObjectSubclass<imp::WebRTCSrc>) @extends gst::Bin, gst::Element, gst::Object, @implements gst::URIHandler, gst::ChildProxy; + pub struct BaseWebRTCSrc(ObjectSubclass<imp::BaseWebRTCSrc>) @extends gst::Bin, gst::Element, gst::Object, @implements gst::ChildProxy; +} + +glib::wrapper! { + pub struct WebRTCSrc(ObjectSubclass<imp::WebRTCSrc>) @extends BaseWebRTCSrc, gst::Bin, gst::Element, gst::Object, @implements gst::URIHandler, gst::ChildProxy; } glib::wrapper! { @@ -50,6 +54,7 @@ glib::wrapper! { } pub fn register(plugin: Option<&gst::Plugin>) -> Result<(), glib::BoolError> { + BaseWebRTCSrc::static_type().mark_as_plugin_api(gst::PluginAPIFlags::empty()); WebRTCSignallerRole::static_type().mark_as_plugin_api(gst::PluginAPIFlags::empty()); WebRTCSrcPad::static_type().mark_as_plugin_api(gst::PluginAPIFlags::empty()); Signallable::static_type().mark_as_plugin_api(gst::PluginAPIFlags::empty()); |