diff options
author | Mathieu Duponchelle <mathieu@centricular.com> | 2021-06-04 02:29:09 +0300 |
---|---|---|
committer | GStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org> | 2021-06-30 03:46:46 +0300 |
commit | d38a84ab799117c3dae07e7451de32929b560af9 (patch) | |
tree | 6779b5912b81ea844c94f78fadf37805a56c8460 | |
parent | ef41adf776830eeb54ad21505fafb8ad7fc931e7 (diff) |
fallbacksrc: add support for still images as primary
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/515>
-rw-r--r-- | utils/fallbackswitch/src/fallbacksrc/imp.rs | 71 |
1 files changed, 69 insertions, 2 deletions
diff --git a/utils/fallbackswitch/src/fallbacksrc/imp.rs b/utils/fallbackswitch/src/fallbacksrc/imp.rs index a6e6a9b77..1f2b87f5a 100644 --- a/utils/fallbackswitch/src/fallbacksrc/imp.rs +++ b/utils/fallbackswitch/src/fallbacksrc/imp.rs @@ -179,6 +179,8 @@ struct State { // So that we don't schedule a restart when manually unblocking // and our source hasn't reached the required state schedule_restart_on_unblock: bool, + + is_image: bool, } #[derive(Default)] @@ -1089,6 +1091,7 @@ impl FallbackSrc { stats: Stats::default(), manually_blocked, schedule_restart_on_unblock: false, + is_image: false, }); drop(state_guard); @@ -1261,6 +1264,39 @@ impl FallbackSrc { Some(state) => state, }; + let mut is_image = false; + + if let Some(stream_event) = pad.sticky_event(gst::EventType::StreamStart, 0) { + let stream = match stream_event.view() { + gst::EventView::StreamStart(ref ev) => ev.stream(), + _ => unreachable!(), + }; + + if let Some(stream) = stream { + if let Some(caps) = stream.caps() { + if let Some(s) = caps.structure(0) { + is_image = s.name().starts_with("image/"); + } + } + } + } + + if is_image { + if let Some(timeout) = state.source_pending_restart_timeout.take() { + timeout.unschedule(); + } + + if let Some(timeout) = state.source_retry_timeout.take() { + timeout.unschedule(); + } + + if let Some(timeout) = state.source_restart_timeout.take() { + timeout.unschedule(); + } + } + + state.is_image |= is_image; + let (is_video, stream) = match pad.name() { x if x.starts_with("audio_") => (false, &mut state.audio_stream), x if x.starts_with("video_") => (true, &mut state.video_stream), @@ -1300,7 +1336,26 @@ impl FallbackSrc { Some(ref mut stream) => stream, }; - let sinkpad = stream.clocksync_queue.static_pad("sink").unwrap(); + let sinkpad = if is_image { + let imagefreeze = + gst::ElementFactory::make("imagefreeze", None).expect("no imagefreeze found"); + + gst_debug!(CAT, "image stream, inserting imagefreeze"); + element.add(&imagefreeze).unwrap(); + imagefreeze.set_property("is-live", &true).unwrap(); + if imagefreeze.sync_state_with_parent().is_err() { + gst_error!(CAT, obj: element, "imagefreeze failed to change state",); + return Err(gst::error_msg!( + gst::CoreError::StateChange, + ["Failed to change imagefreeze state"] + )); + } + imagefreeze.link(&stream.clocksync_queue).unwrap(); + imagefreeze.static_pad("sink").unwrap() + } else { + stream.clocksync_queue.static_pad("sink").unwrap() + }; + pad.link(&sinkpad).map_err(|err| { gst_error!( CAT, @@ -1339,7 +1394,10 @@ impl FallbackSrc { } Some(state) => state, }; - if state.settings.restart_on_eos { + + if is_image { + gst::PadProbeReturn::Ok + } else if state.settings.restart_on_eos { src.handle_source_error(&element, state, RetryReason::Eos); drop(state_guard); element.notify("statistics"); @@ -2226,6 +2284,15 @@ impl FallbackSrc { return; } + if state.is_image { + gst_debug!( + CAT, + obj: element, + "Not scheduling source restart timeout because we are playing back an image", + ); + return; + } + if state.manually_blocked { gst_debug!( CAT, |