From b9ef6c3abbe15dc084ce327b9c21a519f059da0b Mon Sep 17 00:00:00 2001 From: mtkennerly Date: Sun, 1 Dec 2024 22:44:42 -0500 Subject: [PATCH] Stop pipeline on error --- src/video.rs | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/video.rs b/src/video.rs index 6f11fb9..f7a564a 100644 --- a/src/video.rs +++ b/src/video.rs @@ -240,24 +240,33 @@ impl Video { static NEXT_ID: AtomicU64 = AtomicU64::new(0); let id = NEXT_ID.fetch_add(1, Ordering::SeqCst); + // We need to ensure we stop the pipeline if we hit an error, + // or else there may be audio left playing in the background. + macro_rules! cleanup { + ($expr:expr) => { + $expr.map_err(|e| { + let _ = pipeline.set_state(gst::State::Null); + e + }) + }; + } + let pad = video_sink.pads().first().cloned().unwrap(); - pipeline.set_state(gst::State::Playing)?; + cleanup!(pipeline.set_state(gst::State::Playing))?; // wait for up to 5 seconds until the decoder gets the source capabilities - pipeline.state(gst::ClockTime::from_seconds(5)).0?; + cleanup!(pipeline.state(gst::ClockTime::from_seconds(5)).0)?; // extract resolution and framerate // TODO(jazzfool): maybe we want to extract some other information too? - let caps = pad.current_caps().ok_or(Error::Caps)?; - let s = caps.structure(0).ok_or(Error::Caps)?; - let width = s.get::("width").map_err(|_| Error::Caps)?; - let height = s.get::("height").map_err(|_| Error::Caps)?; + let caps = cleanup!(pad.current_caps().ok_or(Error::Caps))?; + let s = cleanup!(caps.structure(0).ok_or(Error::Caps))?; + let width = cleanup!(s.get::("width").map_err(|_| Error::Caps))?; + let height = cleanup!(s.get::("height").map_err(|_| Error::Caps))?; // resolution should be mod4 let width = ((width + 4 - 1) / 4) * 4; - let framerate = s - .get::("framerate") - .map_err(|_| Error::Caps)?; + let framerate = cleanup!(s.get::("framerate").map_err(|_| Error::Caps))?; let framerate = framerate.numer() as f64 / framerate.denom() as f64; if framerate.is_nan() @@ -265,6 +274,7 @@ impl Video { || framerate < 0.0 || framerate.abs() < f64::EPSILON { + let _ = pipeline.set_state(gst::State::Null); return Err(Error::Framerate(framerate)); }