feat(gst): enhance GStreamer integration with new modules and improved API
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:
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user