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

@@ -0,0 +1,125 @@
use crate::*;
pub struct Playbin3 {
inner: gstreamer::Element,
}
impl Drop for Playbin3 {
fn drop(&mut self) {
let _ = self
.inner
.set_state(gstreamer::State::Null)
.inspect_err(|e| {
tracing::error!("Failed to set playbin3 to Null state on drop: {:?}", e)
});
}
}
impl Playbin3 {
pub fn new(name: impl AsRef<str>) -> Result<Self> {
use gstreamer::prelude::*;
gstreamer::ElementFactory::make("playbin3")
.name(name.as_ref())
.build()
.map(|element| Playbin3 { inner: element })
.change_context(Error)
}
pub fn with_uri(self, uri: impl AsRef<str>) -> Self {
use gstreamer::prelude::*;
self.inner.set_property("uri", uri.as_ref());
self
}
pub fn with_video_sink(self, video_sink: &impl IsElement) -> Self {
use gstreamer::prelude::*;
self.inner
.set_property("video-sink", &video_sink.as_element().inner);
self
}
pub fn with_text_sink(self, text_sink: &impl IsElement) -> Self {
use gstreamer::prelude::*;
self.inner
.set_property("text-sink", &text_sink.as_element().inner);
self
}
pub fn with_audio_sink(self, audio_sink: &impl IsElement) -> Self {
use gstreamer::prelude::*;
self.inner
.set_property("audio-sink", &audio_sink.as_element().inner);
self
}
pub fn set_volume(&self, volume: f64) {
use gstreamer::prelude::*;
self.inner.set_property("volume", volume.clamp(1.0, 100.0))
}
pub fn get_volume(&self) -> f64 {
use gstreamer::prelude::*;
self.inner.property::<f64>("volume")
}
pub fn play(&self) -> Result<()> {
use gstreamer::prelude::*;
self.inner
.set_state(gstreamer::State::Playing)
.change_context(Error)
.attach("Failed to set playbin3 to Playing state")?;
Ok(())
}
pub fn bus(&self) -> Result<Bus> {
let bus = self
.inner
.bus()
.ok_or(Error)
.attach("Failed to get bus from playbin3")?;
Ok(Bus { bus })
}
}
#[test]
fn test_playbin3() {
use gstreamer::prelude::*;
use tracing_subscriber::prelude::*;
tracing_subscriber::registry()
.with(
tracing_subscriber::fmt::layer()
.with_thread_ids(true)
.with_file(true),
)
.init();
tracing::info!("Linking videoconvert to appsink");
gstreamer::init().unwrap();
let playbin3 = Playbin3::new("test_playbin3").unwrap().with_uri("https://jellyfin.tsuba.darksailor.dev/Items/6010382cf25273e624d305907010d773/Download?api_key=036c140222464878862231ef66a2bc9c");
// let mut video_sink = Bin::new("wgpu_video_sink");
//
// let video_convert = plugins::videoconvertscale::VideoConvert::new("wgpu_video_convert")
// .expect("Create videoconvert");
// let appsink = AppSink::new("test_appsink").expect("Create appsink");
let appsink = plugins::autodetect::AutoVideoSink::new("test_autodetect_video_sink")
.expect("Create autodetect video sink");
// video_convert
// .link(&appsink)
// .expect("Link videoconvert to appsink");
//
// let sink_pad = video_convert.sink_pad();
// let sink_pad = Pad::ghost(&sink_pad).expect("Create ghost pad from videoconvert src");
// video_sink
// .add(appsink)
// .expect("Add appsink to video sink")
// .add(video_convert)
// .expect("Add videoconvert to video sink")
// .add_pad(&sink_pad)
// .expect("Add ghost pad to video sink");
// sink_pad.activate(true).expect("Activate ghost pad");
let playbin3 = playbin3.with_video_sink(&appsink);
playbin3.play().unwrap();
let bus = playbin3.bus().unwrap();
for msg in bus.iter_timed(None) {
tracing::info!("{:#?}", &msg.view());
}
// std::thread::sleep(std::time::Duration::from_secs(5));
}