gstzenoh/
lib.rs

1//! # gst-plugin-zenoh
2//!
3//! A high-performance GStreamer plugin for distributed media streaming using Zenoh.
4//!
5//! This plugin provides seamless integration between GStreamer multimedia pipelines
6//! and Zenoh networks, enabling distributed applications, edge computing scenarios,
7//! robotics systems, and IoT data streaming.
8//!
9//! ## Elements
10//!
11//! - [`zenohsink`]: Publishes GStreamer buffers to Zenoh networks
12//! - [`zenohsrc`]: Subscribes to Zenoh data and delivers it to GStreamer pipelines
13//! - [`zenohdemux`]: Demultiplexes Zenoh streams by key expression, creating dynamic pads
14//!
15//! ## Features
16//!
17//! - **Advanced QoS Control**: Configurable reliability, congestion control, and priority
18//! - **Express Mode**: Ultra-low latency streaming with queue bypass
19//! - **Session Sharing**: Efficient resource management across multiple elements
20//! - **Thread Safety**: Safe concurrent access to all components
21//! - **Error Recovery**: Comprehensive error handling and network resilience
22//! - **Optional Compression**: zstd, lz4, and gzip support via feature flags
23//!
24//! ## Quick Start (gst-launch)
25//!
26//! ```bash
27//! # Set plugin path
28//! export GST_PLUGIN_PATH=/path/to/target/release
29//!
30//! # Sender
31//! gst-launch-1.0 videotestsrc ! zenohsink key-expr=demo/video
32//!
33//! # Receiver
34//! gst-launch-1.0 zenohsrc key-expr=demo/video ! videoconvert ! autovideosink
35//! ```
36//!
37//! ## Rust API
38//!
39//! ### Strongly-Typed API (Recommended)
40//!
41//! Use the builder pattern for type-safe element creation.
42//! Main types are re-exported at the crate root for convenience:
43//!
44//! ```no_run
45//! use gst::prelude::*;
46//! use gstzenoh::{ZenohSink, ZenohSrc};
47//!
48//! fn main() -> Result<(), Box<dyn std::error::Error>> {
49//!     gst::init()?;
50//!     gstzenoh::plugin_register_static()?;
51//!
52//!     // Create ZenohSink with the builder pattern
53//!     let sink = ZenohSink::builder("demo/video")
54//!         .reliability("reliable")
55//!         .priority(2)  // InteractiveHigh
56//!         .express(true)
57//!         .send_caps(true)
58//!         .build();
59//!
60//!     // Or use new() and setters
61//!     let src = ZenohSrc::new("demo/video");
62//!     src.set_receive_timeout_ms(500);
63//!     src.set_apply_buffer_meta(true);
64//!
65//!     // Access statistics with typed getters
66//!     println!("Bytes sent: {}", sink.bytes_sent());
67//!     println!("Messages received: {}", src.messages_received());
68//!
69//!     Ok(())
70//! }
71//! ```
72//!
73//! ### Building Pipelines with Strongly-Typed Elements
74//!
75//! ```no_run
76//! use gst::prelude::*;
77//! use gstzenoh::ZenohSink;
78//!
79//! fn main() -> Result<(), Box<dyn std::error::Error>> {
80//!     gst::init()?;
81//!     gstzenoh::plugin_register_static()?;
82//!
83//!     let pipeline = gst::Pipeline::new();
84//!     let src = gst::ElementFactory::make("videotestsrc").build()?;
85//!
86//!     // Create sink with strongly-typed API
87//!     let sink = ZenohSink::builder("demo/video")
88//!         .reliability("reliable")
89//!         .priority(2)
90//!         .express(true)
91//!         .build();
92//!
93//!     // Add to pipeline (upcast to Element)
94//!     pipeline.add_many([&src, sink.upcast_ref()])?;
95//!     src.link(&sink)?;
96//!
97//!     pipeline.set_state(gst::State::Playing)?;
98//!     // ... run pipeline ...
99//!     pipeline.set_state(gst::State::Null)?;
100//!     Ok(())
101//! }
102//! ```
103//!
104//! ### Converting from Generic Elements
105//!
106//! ```no_run
107//! use gst::prelude::*;
108//! use gstzenoh::ZenohSink;
109//!
110//! fn main() -> Result<(), Box<dyn std::error::Error>> {
111//!     gst::init()?;
112//!     gstzenoh::plugin_register_static()?;
113//!
114//!     // Create via ElementFactory
115//!     let element = gst::ElementFactory::make("zenohsink")
116//!         .property("key-expr", "demo/video")
117//!         .build()?;
118//!
119//!     // Convert to strongly-typed wrapper
120//!     let sink = ZenohSink::try_from(element).expect("Should be a ZenohSink");
121//!
122//!     // Now use typed API
123//!     sink.set_reliability("reliable");
124//!     println!("Key expression: {}", sink.key_expr());
125//!
126//!     Ok(())
127//! }
128//! ```
129//!
130//! ### Using the Generic Property API
131//!
132//! For compatibility or dynamic configuration:
133//!
134//! ```no_run
135//! use gst::prelude::*;
136//!
137//! fn main() -> Result<(), Box<dyn std::error::Error>> {
138//!     gst::init()?;
139//!     gstzenoh::plugin_register_static()?;
140//!
141//!     let sink = gst::ElementFactory::make("zenohsink")
142//!         .property("key-expr", "demo/video")
143//!         .property("reliability", "reliable")
144//!         .property("priority", 2u32)
145//!         .property("express", true)
146//!         .build()?;
147//!
148//!     Ok(())
149//! }
150//! ```
151//!
152//! ### Using parse_launch for Quick Prototyping
153//!
154//! ```no_run
155//! use gst::prelude::*;
156//!
157//! fn main() -> Result<(), Box<dyn std::error::Error>> {
158//!     gst::init()?;
159//!     gstzenoh::plugin_register_static()?;
160//!
161//!     let pipeline = gst::parse::launch(
162//!         "videotestsrc ! zenohsink key-expr=demo/video"
163//!     )?;
164//!
165//!     pipeline.set_state(gst::State::Playing)?;
166//!     // ... run pipeline ...
167//!     pipeline.set_state(gst::State::Null)?;
168//!     Ok(())
169//! }
170//! ```
171//!
172//! ## Examples
173//!
174//! See the `examples/` directory for comprehensive usage demonstrations:
175//! - `basic.rs`: Simple video streaming setup
176//! - `configuration.rs`: Advanced QoS configuration showcase
177//! - `video_stream.rs`: Full video streaming pipeline
178//!
179//! [`zenohsink`]: zenohsink
180//! [`zenohsrc`]: zenohsrc
181//! [`zenohdemux`]: zenohdemux
182
183use gst::glib;
184
185mod error;
186pub mod metadata;
187pub(crate) mod session;
188pub mod utils;
189pub mod zenohdemux;
190pub mod zenohsink;
191pub mod zenohsrc;
192
193// Re-export main types at crate root for convenience
194pub use zenohdemux::{PadNaming, ZenohDemux, ZenohDemuxBuilder};
195pub use zenohsink::{ZenohSink, ZenohSinkBuilder};
196pub use zenohsrc::{ZenohSrc, ZenohSrcBuilder};
197
198#[cfg(any(
199    feature = "compression-zstd",
200    feature = "compression-lz4",
201    feature = "compression-gzip"
202))]
203pub mod compression;
204
205fn plugin_init(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
206    zenohsink::register(plugin)?;
207    zenohsrc::register(plugin)?;
208    zenohdemux::register(plugin)?;
209    Ok(())
210}
211
212gst::plugin_define!(
213    zenoh,
214    env!("CARGO_PKG_DESCRIPTION"),
215    plugin_init,
216    concat!(env!("CARGO_PKG_VERSION"), "-", env!("COMMIT_ID")),
217    "MPL-2.0",
218    env!("CARGO_PKG_NAME"),
219    "gst-plugin-zenoh",
220    env!("CARGO_PKG_REPOSITORY"),
221    env!("BUILD_REL_DATE")
222);