From abf872130a4b50735423488b9ef7b5fd19975c8a Mon Sep 17 00:00:00 2001 From: Mathieu Duponchelle Date: Wed, 8 Jun 2022 21:48:18 +0200 Subject: [PATCH] fallbackswitch: fix gap processing regression This was broken by the rewrite, receiving gaps on the main pad should let the position progress, reset timeouts and keep the main pad active. This picks the simplest solution, transforming gap events into GAP buffers and letting them go through chain(), this achieves the desired effect. --- utils/fallbackswitch/Cargo.toml | 3 +- .../fallbackswitch/src/fallbackswitch/imp.rs | 58 ++++++++++++++++++- 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/utils/fallbackswitch/Cargo.toml b/utils/fallbackswitch/Cargo.toml index 8220fbad..18f70e15 100644 --- a/utils/fallbackswitch/Cargo.toml +++ b/utils/fallbackswitch/Cargo.toml @@ -37,9 +37,10 @@ required-features = ["gtk", "gio"] gst-plugin-version-helper = { path="../../version-helper" } [features] -default = ["libc"] +default = ["libc", "v1_20"] static = [] capi = [] +v1_20 = ["gst/v1_20"] [package.metadata.capi] min_version = "0.8.0" diff --git a/utils/fallbackswitch/src/fallbackswitch/imp.rs b/utils/fallbackswitch/src/fallbackswitch/imp.rs index 886aec3b..18ac958c 100644 --- a/utils/fallbackswitch/src/fallbackswitch/imp.rs +++ b/utils/fallbackswitch/src/fallbackswitch/imp.rs @@ -553,6 +553,16 @@ impl FallbackSwitch { pad: &super::FallbackSwitchSinkPad, element: &super::FallbackSwitch, buffer: gst::Buffer, + ) -> Result { + self.chain(pad, element, buffer, None) + } + + fn chain( + &self, + pad: &super::FallbackSwitchSinkPad, + element: &super::FallbackSwitch, + buffer: gst::Buffer, + from_gap: Option<&gst::event::Gap>, ) -> Result { let mut state = self.state.lock(); let settings = self.settings.lock().clone(); @@ -792,7 +802,30 @@ impl FallbackSwitch { /* TODO: Clip raw video and audio buffers to avoid going backward? */ log!(CAT, obj: pad, "Forwarding {:?}", buffer); - self.src_pad.push(buffer) + + if let Some(in_gap_event) = from_gap { + // Safe unwrap: the buffer was constructed from a gap event with + // a timestamp, and even if its timestamp was adjusted it should never + // be NONE by now + let pts = buffer.pts().unwrap(); + + let mut builder = gst::event::Gap::builder(pts) + .duration(buffer.duration()) + .seqnum(in_gap_event.seqnum()); + + #[cfg(feature = "v1_20")] + { + builder = builder.gap_flags(in_gap_event.gap_flags()); + } + + let out_gap_event = builder.build(); + + self.src_pad.push_event(out_gap_event); + + Ok(gst::FlowSuccess::Ok) + } else { + self.src_pad.push(buffer) + } } fn sink_chain_list( @@ -805,7 +838,7 @@ impl FallbackSwitch { // TODO: Keep the list intact and forward it in one go (or broken into several // pieces if needed) when outputting to the active pad for buffer in list.iter_owned() { - self.sink_chain(pad, element, buffer)?; + self.chain(pad, element, buffer, None)?; } Ok(gst::FlowSuccess::Ok) @@ -817,6 +850,27 @@ impl FallbackSwitch { element: &super::FallbackSwitch, event: gst::Event, ) -> bool { + if let gst::EventView::Gap(ev) = event.view() { + let mut buffer = gst::Buffer::new(); + + { + let buf_mut = buffer.get_mut().unwrap(); + buf_mut.set_flags(gst::BufferFlags::GAP); + let (pts, duration) = ev.get(); + buf_mut.set_pts(pts); + buf_mut.set_duration(duration); + } + + return match self.chain(pad, element, buffer, Some(ev)) { + Ok(_) => true, + Err(gst::FlowError::Flushing) | Err(gst::FlowError::Eos) => true, + Err(err) => { + gst::error!(CAT, obj: pad, "Error processing gap event: {}", err); + false + } + }; + } + let mut state = self.state.lock(); let forward = self.active_sinkpad.lock().as_ref() == Some(pad);