feat(gst): enhance GStreamer integration with new modules and improved API
Some checks failed
build / checks-matrix (push) Has been cancelled
build / codecov (push) Has been cancelled
docs / docs (push) Has been cancelled
build / checks-build (push) Has been cancelled

This commit introduces significant enhancements to the GStreamer integration by:
- Adding new modules for bins, caps, elements, pads, and plugins
- Implementing a more ergonomic API with helper methods like play(), pause(), ready()
- Adding support for various GStreamer plugins including app, autodetect, playback, and videoconvertscale
- Improving error handling with better context attachment
- Updating dependencies to latest versions including gstreamer-video 0.24.4
- Refactoring existing code to use modern Rust patterns and features
This commit is contained in:
uttarayan21
2025-12-17 23:35:05 +05:30
parent 21cbaff610
commit d42ef3b550
19 changed files with 619 additions and 117 deletions

View File

@@ -1,5 +1,20 @@
pub mod bin;
pub mod caps;
pub mod element;
pub mod errors;
pub mod playbin3;
pub mod pad;
pub mod plugins;
// pub mod playbin3;
// pub mod videoconvert;
pub use bin::*;
pub use caps::*;
pub use element::*;
pub use pad::*;
pub use plugins::*;
// pub use playbin3::*;
// pub use videoconvert::*;
use errors::*;
use gstreamer::prelude::*;
use std::sync::Arc;
@@ -28,25 +43,18 @@ impl Gst {
Err(_e) => return Err(Error).attach("Failed to downcast to Pipeline"),
Ok(p) => p,
};
Ok(Pipeline { pipeline })
Ok(Pipeline { inner: pipeline })
}
}
pub struct Bin {
bin: gstreamer::Bin,
}
pub struct Sample {
sample: gstreamer::Sample,
}
pub struct Pipeline {
pipeline: gstreamer::Pipeline,
inner: gstreamer::Pipeline,
}
impl core::fmt::Debug for Pipeline {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Pipeline")
.field("pipeline", &self.pipeline)
.field("pipeline", &self.inner)
// .field("state", &self.pipeline.state(gstreamer::ClockTime::NONE))
.finish()
}
@@ -54,23 +62,50 @@ impl core::fmt::Debug for Pipeline {
impl Drop for Pipeline {
fn drop(&mut self) {
let _ = self.pipeline.set_state(gstreamer::State::Null);
let _ = self.inner.set_state(gstreamer::State::Null);
}
}
impl Pipeline {
pub fn bus(&self) -> Result<Bus> {
let bus = self
.pipeline
.inner
.bus()
.ok_or(Error)
.attach("Failed to get bus from pipeline")?;
Ok(Bus { bus })
}
pub fn set_state(&self, state: gstreamer::State) -> Result<gstreamer::StateChangeSuccess> {
pub fn play(&self) -> Result<()> {
self.inner
.set_state(gstreamer::State::Playing)
.change_context(Error)
.attach("Failed to set pipeline to Playing state")?;
Ok(())
}
pub fn pause(&self) -> Result<()> {
self.inner
.set_state(gstreamer::State::Paused)
.change_context(Error)
.attach("Failed to set pipeline to Paused state")?;
Ok(())
}
pub fn ready(&self) -> Result<()> {
self.inner
.set_state(gstreamer::State::Ready)
.change_context(Error)
.attach("Failed to set pipeline to Paused state")?;
Ok(())
}
pub unsafe fn set_state(
&self,
state: gstreamer::State,
) -> Result<gstreamer::StateChangeSuccess> {
let result = self
.pipeline
.inner
.set_state(state)
.change_context(Error)
.attach("Failed to set pipeline state")?;
@@ -93,19 +128,10 @@ impl Bus {
};
self.bus.iter_timed(clocktime)
}
}
/// Pads are link points between elements
pub struct Pad {
pad: gstreamer::Pad,
}
pub struct Element {
element: gstreamer::Element,
}
pub struct AppSink {
appsink: gstreamer_app::AppSink,
pub fn stream(&self) -> gstreamer::bus::BusStream {
self.bus.stream()
}
}
pub struct Playbin3Builder {
@@ -140,7 +166,7 @@ fn gst_play_pipeline() {
let bus = pipeline.bus().expect("Failed to get bus from pipeline");
pipeline
.set_state(gstreamer::State::Playing)
.play()
.expect("Unable to set the pipeline to the `Playing` state");
for msg in bus.iter_timed(None) {
@@ -160,10 +186,6 @@ fn gst_play_pipeline() {
_ => (),
}
}
pipeline
.set_state(gstreamer::State::Null)
.expect("Unable to set the pipeline to the `Null` state");
}
#[test]
@@ -212,13 +234,13 @@ fn test_appsink() {
let bus = pipeline.bus().expect("Failed to get bus from pipeline");
let sink = pipeline
.pipeline
.inner
.by_name("video-sink")
.expect("Sink not found")
.downcast::<gstreamer_app::AppSink>()
.expect("Failed to downcast to AppSink");
let capsfilter = pipeline
.pipeline
.inner
.by_name("video-filter")
.expect("Capsfilter not found");
@@ -236,12 +258,8 @@ fn test_appsink() {
.build(),
);
// let appsink = sink
// .dynamic_cast::<gstreamer_app::AppSink>()
// .expect("Failed to cast to AppSink");
pipeline
.set_state(gstreamer::State::Playing)
.play()
.expect("Unable to set the pipeline to the `Playing` state");
for msg in bus.iter_timed(None) {