From a2491695b3234e5e96e20749d8e75a2385e3c75e Mon Sep 17 00:00:00 2001 From: uttarayan21 Date: Thu, 25 Dec 2025 06:28:52 +0530 Subject: [PATCH] fix(video): try to optimize memory leaks --- crates/iced-video/src/primitive.rs | 9 ++++--- crates/iced-video/src/source.rs | 35 ++++++++++++++-------------- flake.nix | 1 + gst/src/plugins/app/appsink.rs | 5 ++++ gst/src/plugins/playback/playbin3.rs | 18 ++++++++++++++ 5 files changed, 47 insertions(+), 21 deletions(-) diff --git a/crates/iced-video/src/primitive.rs b/crates/iced-video/src/primitive.rs index d57c2e8..bcf9e96 100644 --- a/crates/iced-video/src/primitive.rs +++ b/crates/iced-video/src/primitive.rs @@ -99,11 +99,14 @@ impl iced_wgpu::Primitive for VideoFrame { if video.ready.load(std::sync::atomic::Ordering::SeqCst) { let now = std::time::Instant::now(); let frame = self.frame.lock().expect("BUG: Mutex poisoned"); - let frame = frame + let buffer = frame .buffer() - .and_then(|b| b.map_readable().ok()) .expect("BUG: Failed to get frame data from gst::Sample"); - queue.write_buffer(&video.buffer, 0, &frame); + + let data = buffer + .map_readable() + .expect("BUG: Failed to map gst::Buffer readable"); + queue.write_buffer(&video.buffer, 0, &data); video .ready .store(false, std::sync::atomic::Ordering::SeqCst); diff --git a/crates/iced-video/src/source.rs b/crates/iced-video/src/source.rs index 437f8aa..f61381b 100644 --- a/crates/iced-video/src/source.rs +++ b/crates/iced-video/src/source.rs @@ -13,7 +13,7 @@ use std::sync::{Arc, Mutex, atomic::AtomicBool}; #[derive(Debug, Clone)] pub struct VideoSource { pub(crate) playbin: Playbin3, - pub(crate) videoconvert: VideoConvert, + // pub(crate) videoconvert: VideoConvert, pub(crate) appsink: AppSink, pub(crate) bus: Bus, pub(crate) ready: Arc, @@ -26,22 +26,25 @@ impl VideoSource { /// now. pub fn new(url: impl AsRef) -> Result { Gst::new(); - let videoconvert = VideoConvert::new("iced-video-convert") - // .change_context(Error)? - // .with_output_format(gst::plugins::videoconvertscale::VideoFormat::Rgba) - .change_context(Error)?; + // let videoconvert = VideoConvert::new("iced-video-convert") + // // .change_context(Error)? + // // .with_output_format(gst::plugins::videoconvertscale::VideoFormat::Rgba) + // .change_context(Error)?; let appsink = AppSink::new("iced-video-sink") .change_context(Error)? - .with_caps( - Caps::builder(CapsType::Video) - .field("format", "RGBA") - .build(), - ); - let video_sink = videoconvert.link(&appsink).change_context(Error)?; + .with_drop(true); + // .with_caps( + // Caps::builder(CapsType::Video) + // .field("format", "RGBA") + // .build(), + // ); + // let video_sink = videoconvert.link(&appsink).change_context(Error)?; let playbin = gst::plugins::playback::Playbin3::new("iced-video") .change_context(Error)? .with_uri(url.as_ref()) - .with_video_sink(&video_sink); + .with_buffer_duration(core::time::Duration::from_secs(2)) + .with_buffer_size(2000000) + .with_video_sink(&appsink); let bus = playbin.bus().change_context(Error)?; playbin.pause().change_context(Error)?; let ready = Arc::new(AtomicBool::new(false)); @@ -57,12 +60,8 @@ impl VideoSource { }; { let mut guard = frame.lock().expect("BUG: Mutex poisoned"); - let old_sample = core::mem::replace(&mut *guard, sample); - // dbg!(old_sample.caps()); - // dbg!(old_sample.inner.buffer_list()); - // drop(old_sample); + core::mem::replace(&mut *guard, sample); ready.store(true, std::sync::atomic::Ordering::Relaxed); - drop(guard); } Ok(()) @@ -71,7 +70,7 @@ impl VideoSource { Ok(Self { playbin, - videoconvert, + // videoconvert, appsink, bus, ready, diff --git a/flake.nix b/flake.nix index 30f50df..f05d81a 100644 --- a/flake.nix +++ b/flake.nix @@ -196,6 +196,7 @@ lld lldb cargo-audit + (crates.buildCrate "cargo-with" {doCheck = false;}) ] ++ (lib.optionals pkgs.stdenv.isDarwin [ apple-sdk_26 diff --git a/gst/src/plugins/app/appsink.rs b/gst/src/plugins/app/appsink.rs index f9427c5..d4a4dfc 100644 --- a/gst/src/plugins/app/appsink.rs +++ b/gst/src/plugins/app/appsink.rs @@ -40,6 +40,11 @@ impl AppSink { self } + pub fn with_drop(self, drop: bool) -> Self { + self.inner.set_property("drop", drop); + self + } + pub fn with_caps(self, caps: Caps) -> Self { self.inner.set_property("caps", caps.inner); self diff --git a/gst/src/plugins/playback/playbin3.rs b/gst/src/plugins/playback/playbin3.rs index 4da2f10..c0fd254 100644 --- a/gst/src/plugins/playback/playbin3.rs +++ b/gst/src/plugins/playback/playbin3.rs @@ -25,6 +25,24 @@ impl Playbin3 { self } + pub fn with_buffer_duration(self, duration: impl Into>) -> 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>) -> Self { + let size = match size.into() { + Some(size) => size as i32, + None => -1, + }; + self.inner.set_property("buffer-size", size); + self + } + pub fn with_video_sink(self, video_sink: &impl ChildOf) -> Self { self.inner .set_property("video-sink", &video_sink.upcast_ref().inner);