From fa006b9fc9f92cb88328315378630b3b1c706ec0 Mon Sep 17 00:00:00 2001 From: Jordan Yelloz Date: Tue, 13 Feb 2024 11:48:29 -0700 Subject: [PATCH] webrtcsrc: Added LiveKit source element Part-of: --- docs/plugins/gst_plugins_cache.json | 32 ++++++++++++++++ net/webrtc/src/webrtcsrc/imp.rs | 42 ++++++++++++++++++++ net/webrtc/src/webrtcsrc/mod.rs | 59 +++++++++++++++++++++++++++++ 3 files changed, 133 insertions(+) diff --git a/docs/plugins/gst_plugins_cache.json b/docs/plugins/gst_plugins_cache.json index f3837d0d..ef0f4a11 100644 --- a/docs/plugins/gst_plugins_cache.json +++ b/docs/plugins/gst_plugins_cache.json @@ -7319,6 +7319,38 @@ }, "rank": "none" }, + "livekitwebrtcsrc": { + "author": "Jordan Yelloz ", + "description": "WebRTC source with LiveKit signaller", + "hierarchy": [ + "GstLiveKitWebRTCSrc", + "GstBaseWebRTCSrc", + "GstBin", + "GstElement", + "GstObject", + "GInitiallyUnowned", + "GObject" + ], + "interfaces": [ + "GstChildProxy" + ], + "klass": "Source/Network/WebRTC", + "pad-templates": { + "audio_%%u": { + "caps": "audio/x-raw(ANY):\napplication/x-rtp:\naudio/x-opus:\n", + "direction": "src", + "presence": "sometimes", + "type": "GstWebRTCSrcPad" + }, + "video_%%u": { + "caps": "video/x-raw(ANY):\napplication/x-rtp:\nvideo/x-vp8:\nvideo/x-h264:\nvideo/x-vp9:\nvideo/x-h265:\n", + "direction": "src", + "presence": "sometimes", + "type": "GstWebRTCSrcPad" + } + }, + "rank": "none" + }, "webrtcsink": { "author": "Mathieu Duponchelle ", "description": "WebRTC sink with custom protocol signaller", diff --git a/net/webrtc/src/webrtcsrc/imp.rs b/net/webrtc/src/webrtcsrc/imp.rs index b978a0b4..8a152aa7 100644 --- a/net/webrtc/src/webrtcsrc/imp.rs +++ b/net/webrtc/src/webrtcsrc/imp.rs @@ -2,6 +2,7 @@ use gst::prelude::*; +use crate::livekit_signaller::LiveKitSignaller; use crate::signaller::{prelude::*, Signallable, Signaller}; use crate::utils::{Codec, Codecs, NavigationEvent, AUDIO_CAPS, RTP_CAPS, VIDEO_CAPS}; use crate::webrtcsrc::WebRTCSrcPad; @@ -1290,3 +1291,44 @@ impl ObjectSubclass for WhipServerSrc { type Type = super::WhipServerSrc; type ParentType = super::BaseWebRTCSrc; } + +#[derive(Default)] +pub struct LiveKitWebRTCSrc; + +impl ObjectImpl for LiveKitWebRTCSrc { + fn constructed(&self) { + self.parent_constructed(); + let element = self.obj(); + let ws = element.upcast_ref::().imp(); + + let _ = ws.set_signaller(LiveKitSignaller::new_consumer().upcast()); + } +} + +impl GstObjectImpl for LiveKitWebRTCSrc {} + +impl BinImpl for LiveKitWebRTCSrc {} + +impl ElementImpl for LiveKitWebRTCSrc { + fn metadata() -> Option<&'static gst::subclass::ElementMetadata> { + static ELEMENT_METADATA: Lazy = Lazy::new(|| { + gst::subclass::ElementMetadata::new( + "LiveKitWebRTCSrc", + "Source/Network/WebRTC", + "WebRTC source with LiveKit signaller", + "Jordan Yelloz ", + ) + }); + + Some(&*ELEMENT_METADATA) + } +} + +impl BaseWebRTCSrcImpl for LiveKitWebRTCSrc {} + +#[glib::object_subclass] +impl ObjectSubclass for LiveKitWebRTCSrc { + const NAME: &'static str = "GstLiveKitWebRTCSrc"; + type Type = super::LiveKitWebRTCSrc; + type ParentType = super::BaseWebRTCSrc; +} diff --git a/net/webrtc/src/webrtcsrc/mod.rs b/net/webrtc/src/webrtcsrc/mod.rs index 45bef4ba..6b57f607 100644 --- a/net/webrtc/src/webrtcsrc/mod.rs +++ b/net/webrtc/src/webrtcsrc/mod.rs @@ -53,6 +53,10 @@ glib::wrapper! { pub struct WhipServerSrc(ObjectSubclass) @extends BaseWebRTCSrc, gst::Bin, gst::Element, gst::Object, @implements gst::URIHandler, gst::ChildProxy; } +glib::wrapper! { + pub struct LiveKitWebRTCSrc(ObjectSubclass) @extends BaseWebRTCSrc, gst::Bin, gst::Element, gst::Object, @implements gst::URIHandler, gst::ChildProxy; +} + glib::wrapper! { pub struct WebRTCSrcPad(ObjectSubclass) @extends gst::GhostPad, gst::ProxyPad, gst::Pad, gst::Object; } @@ -76,5 +80,60 @@ pub fn register(plugin: Option<&gst::Plugin>) -> Result<(), glib::BoolError> { WhipServerSrc::static_type(), )?; + /** + * element-livekitwebrtcsrc: + * + * The `livekitwebrtcsrc` plays streams from a LiveKit room. + * + * The element can either subscribe to the streams published by a single + * peer in the room using the same `signaller::producer-peer-id` child + * property that other webrtcsrc elements use or auto-subscribe to all peers + * in a room by not specifying anything for that property. When in + * auto-subscribe mode, you can use + * `signaller::excluded-producer-peer-ids=` to ignore peers `a`, `b`, + * and `c` while subscribing to all other members of the room. + * + * ## Sample Pipeline + * + * First, start the livekit server with the `--dev` flag to enable the test credentials. + * + * Next, publish a stream: + * + * ```shell + * gst-launch-1.0 \ + * videotestsrc is-live=1 \ + * ! video/x-raw,width=640,height=360,framerate=15/1 \ + * ! timeoverlay ! videoconvert ! queue \ + * ! livekitwebrtcsink name=sink \ + * signaller::ws-url=ws://127.0.0.1:7880 \ + * signaller::api-key=devkey \ + * signaller::secret-key=secret \ + * signaller::room-name=testroom \ + * signaller::identity=gst-producer \ + * signaller::participant-name=gst-producer \ + * video-caps='video/x-vp8' + * ``` + * + * Finally, watch the stream: + * + * ```shell + * gst-launch-1.0 \ + * livekitwebrtcsrc \ + * signaller::ws-url=ws://127.0.0.1:7880 \ + * signaller::api-key=devkey \ + * signaller::secret-key=secret \ + * signaller::room-name=testroom \ + * signaller::identity=gst-consumer \ + * signaller::participant-name=gst-consumer \ + * ! queue ! videoconvert ! autovideosink + * ``` + */ + gst::Element::register( + plugin, + "livekitwebrtcsrc", + gst::Rank::NONE, + LiveKitWebRTCSrc::static_type(), + )?; + Ok(()) }