fix(iced-video): Fix the very high ram usage
feat(playback): add GstPlayFlags for playbin and playbin3
This commit is contained in:
@@ -10,11 +10,14 @@ error-stack = "0.6"
|
||||
futures = "0.3.31"
|
||||
futures-lite = "2.6.1"
|
||||
glib = "0.21.5"
|
||||
glib-sys = "0.21.5"
|
||||
gstreamer = { version = "0.24.4", features = ["v1_26"] }
|
||||
gstreamer-app = { version = "0.24.4", features = ["v1_26"] }
|
||||
gstreamer-video = { version = "0.24.4", features = ["v1_26"] }
|
||||
gstreamer-base = { version = "0.24.4", features = ["v1_26"] }
|
||||
thiserror = "2.0"
|
||||
tracing = { version = "0.1", features = ["log"] }
|
||||
bitflags = "2.10.0"
|
||||
|
||||
[dev-dependencies]
|
||||
smol = "2.0.2"
|
||||
|
||||
@@ -23,7 +23,6 @@ impl Pipeline {
|
||||
}
|
||||
|
||||
/// Get the state
|
||||
#[track_caller]
|
||||
pub fn state(
|
||||
&self,
|
||||
timeout: impl Into<Option<core::time::Duration>>,
|
||||
@@ -33,7 +32,6 @@ impl Pipeline {
|
||||
Ok(current)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn play(&self) -> Result<()> {
|
||||
self.inner
|
||||
.set_state(gstreamer::State::Playing)
|
||||
@@ -42,7 +40,6 @@ impl Pipeline {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn pause(&self) -> Result<()> {
|
||||
self.inner
|
||||
.set_state(gstreamer::State::Paused)
|
||||
@@ -51,7 +48,6 @@ impl Pipeline {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn ready(&self) -> Result<()> {
|
||||
self.inner
|
||||
.set_state(gstreamer::State::Ready)
|
||||
@@ -60,7 +56,6 @@ impl Pipeline {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn stop(&self) -> Result<()> {
|
||||
self.inner
|
||||
.set_state(gstreamer::State::Null)
|
||||
@@ -69,7 +64,6 @@ impl Pipeline {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn set_state(&self, state: gstreamer::State) -> Result<gstreamer::StateChangeSuccess> {
|
||||
let result = self
|
||||
.inner
|
||||
|
||||
@@ -2,3 +2,83 @@ pub mod playbin3;
|
||||
pub use playbin3::*;
|
||||
pub mod playbin;
|
||||
pub use playbin::*;
|
||||
|
||||
bitflags::bitflags! {
|
||||
/// Extra flags to configure the behaviour of the sinks.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct PlayFlags: u32 {
|
||||
/// Render the video stream
|
||||
const VIDEO = (1 << 0);
|
||||
/// Render the audio stream
|
||||
const AUDIO = (1 << 1);
|
||||
/// Render subtitles
|
||||
const TEXT = (1 << 2);
|
||||
/// Render visualisation when no video is present
|
||||
const VIS = (1 << 3);
|
||||
/// Use software volume
|
||||
const SOFT_VOLUME = (1 << 4);
|
||||
/// Only use native audio formats
|
||||
const NATIVE_AUDIO = (1 << 5);
|
||||
/// Only use native video formats
|
||||
const NATIVE_VIDEO = (1 << 6);
|
||||
/// Attempt progressive download buffering
|
||||
const DOWNLOAD = (1 << 7);
|
||||
/// Buffer demuxed/parsed data
|
||||
const BUFFERING = (1 << 8);
|
||||
/// Deinterlace video if necessary
|
||||
const DEINTERLACE = (1 << 9);
|
||||
/// Use software color balance
|
||||
const SOFT_COLORBALANCE = (1 << 10);
|
||||
/// Force audio/video filter(s) to be applied
|
||||
const FORCE_FILTERS = (1 << 11);
|
||||
/// Force only software-based decoders (no effect for playbin3)
|
||||
const FORCE_SW_DECODERS = (1 << 12);
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for PlayFlags {
|
||||
/// Flags "GstPlayFlags" Default: 0x00000717, "soft-colorbalance+deinterlace+buffering+soft-volume+text+audio+video"
|
||||
fn default() -> Self {
|
||||
Self::SOFT_COLORBALANCE
|
||||
| Self::DEINTERLACE
|
||||
| Self::BUFFERING
|
||||
| Self::SOFT_VOLUME
|
||||
| Self::TEXT
|
||||
| Self::AUDIO
|
||||
| Self::VIDEO
|
||||
}
|
||||
}
|
||||
|
||||
const _: () = {
|
||||
use glib::types::StaticType;
|
||||
impl glib::types::StaticType for PlayFlags {
|
||||
#[inline]
|
||||
#[doc(alias = "gst_play_flags_get_type")]
|
||||
fn static_type() -> glib::Type {
|
||||
glib::Type::from_name("GstPlayFlags").expect("GstPlayFlags type not found")
|
||||
}
|
||||
}
|
||||
|
||||
impl glib::value::ToValue for PlayFlags {
|
||||
#[inline]
|
||||
fn to_value(&self) -> glib::Value {
|
||||
let value = self.bits().to_value();
|
||||
value
|
||||
.transform_with_type(Self::static_type())
|
||||
.expect("Failed to transform PlayFlags(u32) to GstPlayFlags")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn value_type(&self) -> glib::Type {
|
||||
Self::static_type()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PlayFlags> for glib::Value {
|
||||
#[inline]
|
||||
fn from(v: PlayFlags) -> Self {
|
||||
// skip_assert_initialized!();
|
||||
glib::value::ToValue::to_value(&v)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
82
gst/src/plugins/playback/playbin.rs
Normal file
82
gst/src/plugins/playback/playbin.rs
Normal file
@@ -0,0 +1,82 @@
|
||||
use crate::priv_prelude::*;
|
||||
|
||||
wrap_gst!(Playbin, gstreamer::Element);
|
||||
parent_child!(Element, Playbin);
|
||||
parent_child!(Pipeline, Playbin, downcast);
|
||||
parent_child!(Bin, Playbin, downcast);
|
||||
|
||||
impl Drop for Playbin {
|
||||
fn drop(&mut self) {
|
||||
self.set_state(gstreamer::State::Null).ok();
|
||||
}
|
||||
}
|
||||
|
||||
impl Playbin {
|
||||
pub fn new(name: impl AsRef<str>) -> Result<Self> {
|
||||
gstreamer::ElementFactory::make("playbin3")
|
||||
.name(name.as_ref())
|
||||
.build()
|
||||
.map(|element| Playbin { inner: element })
|
||||
.change_context(Error)
|
||||
}
|
||||
|
||||
pub fn with_uri(self, uri: impl AsRef<str>) -> Self {
|
||||
self.inner.set_property("uri", uri.as_ref());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_buffer_duration(self, duration: impl Into<Option<core::time::Duration>>) -> Self {
|
||||
let duration = match duration.into() {
|
||||
Some(dur) => dur.as_secs() as i64,
|
||||
None => -1,
|
||||
};
|
||||
self.inner.set_property("buffer-duration", duration);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_buffer_size(self, size: impl Into<Option<u32>>) -> Self {
|
||||
let size = match size.into() {
|
||||
Some(size) => size as i32,
|
||||
None => -1,
|
||||
};
|
||||
self.inner.set_property("buffer-size", size);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the maximum size of the ring buffer in bytes.
|
||||
pub fn with_ring_buffer_max_size(self, size: u64) -> Self {
|
||||
self.inner.set_property("ring-buffer-max-size", size);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_video_sink(self, video_sink: &impl ChildOf<Element>) -> Self {
|
||||
self.inner
|
||||
.set_property("video-sink", &video_sink.upcast_ref().inner);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_text_sink(self, text_sink: &impl ChildOf<Element>) -> Self {
|
||||
self.inner
|
||||
.set_property("text-sink", &text_sink.upcast_ref().inner);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_audio_sink(self, audio_sink: &impl ChildOf<Element>) -> Self {
|
||||
self.inner
|
||||
.set_property("audio-sink", &audio_sink.upcast_ref().inner);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_volume(&self, volume: f64) {
|
||||
self.inner.set_property("volume", volume.clamp(1.0, 100.0))
|
||||
}
|
||||
|
||||
pub fn get_volume(&self) -> f64 {
|
||||
self.inner.property::<f64>("volume")
|
||||
}
|
||||
|
||||
pub fn with_flags(self, flags: playback::PlayFlags) -> Self {
|
||||
self.inner.set_property("flags", flags);
|
||||
self
|
||||
}
|
||||
}
|
||||
@@ -74,4 +74,9 @@ impl Playbin3 {
|
||||
pub fn get_volume(&self) -> f64 {
|
||||
self.inner.property::<f64>("volume")
|
||||
}
|
||||
|
||||
pub fn with_flags(self, flags: playback::PlayFlags) -> Self {
|
||||
self.inner.set_property("flags", flags);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
37
gst/src/sample.rs
Normal file
37
gst/src/sample.rs
Normal file
@@ -0,0 +1,37 @@
|
||||
impl From<gstreamer::Sample> for Sample {
|
||||
fn from(inner: gstreamer::Sample) -> Self {
|
||||
Sample { inner }
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Sample {
|
||||
pub inner: gstreamer::Sample,
|
||||
}
|
||||
|
||||
use gstreamer::BufferRef;
|
||||
impl Sample {
|
||||
#[doc(alias = "empty")]
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
inner: gstreamer::Sample::builder().build(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn buffer(&self) -> Option<&BufferRef> {
|
||||
self.inner.buffer()
|
||||
}
|
||||
|
||||
pub fn caps(&self) -> Option<&gstreamer::CapsRef> {
|
||||
self.inner.caps()
|
||||
}
|
||||
|
||||
pub fn info(&self) -> Option<&gstreamer::StructureRef> {
|
||||
self.inner.info()
|
||||
}
|
||||
|
||||
// pub fn set_buffer(&mut self) {
|
||||
// self.inner.set_buffer(None);
|
||||
// }
|
||||
}
|
||||
Reference in New Issue
Block a user