diff options
author | Seungha Yang <seungha@centricular.com> | 2022-10-10 16:15:57 +0300 |
---|---|---|
committer | Seungha Yang <seungha@centricular.com> | 2022-10-10 16:16:15 +0300 |
commit | 3d317b976e661e89acd4a59f1b85bf55ebde217d (patch) | |
tree | 9019fe0f0023fd2c0cd0fc2245439368a36200e3 /video | |
parent | 6e7ebc30e06be73032151b8cc1c029ae750b81e3 (diff) |
jsontovtt: Add timeout property
As described in the spec D.4 Automatic Caption Blanking,
allows automatic clear if user specified timeout value
Diffstat (limited to 'video')
-rw-r--r-- | video/closedcaption/src/jsontovtt/imp.rs | 94 |
1 files changed, 89 insertions, 5 deletions
diff --git a/video/closedcaption/src/jsontovtt/imp.rs b/video/closedcaption/src/jsontovtt/imp.rs index abdbb865..dff254bf 100644 --- a/video/closedcaption/src/jsontovtt/imp.rs +++ b/video/closedcaption/src/jsontovtt/imp.rs @@ -24,6 +24,20 @@ struct TimestampedLines { lines: Lines, pts: gst::ClockTime, duration: gst::ClockTime, + line_running_time: Option<gst::ClockTime>, +} + +#[derive(Debug, Clone, Copy)] +struct Settings { + timeout: Option<gst::ClockTime>, +} + +impl Default for Settings { + fn default() -> Self { + Settings { + timeout: gst::ClockTime::NONE, + } + } } struct State { @@ -33,6 +47,7 @@ struct State { keyunit_requests: BinaryHeap<ForceKeyUnitRequest>, segment: gst::FormattedSegment<gst::ClockTime>, + settings: Settings, } impl Default for State { @@ -43,6 +58,7 @@ impl Default for State { last_pts: None, keyunit_requests: BinaryHeap::new(), segment: gst::FormattedSegment::new(), + settings: Settings::default(), } } } @@ -52,6 +68,7 @@ pub struct JsonToVtt { sinkpad: gst::Pad, state: Mutex<State>, + settings: Mutex<Settings>, } static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| { @@ -208,10 +225,25 @@ impl State { .unwrap_or_else(|| self.segment.stop().unwrap()) }; - if running_time.is_some() { - let mut cloned = drained_line.clone(); - cloned.pts = end_pts; - self.pending.push_front(cloned); + if let (Some(line_running_time), Some(running_time)) = + (drained_line.line_running_time, running_time) + { + if self + .settings + .timeout + .map_or(true, |timeout| running_time < line_running_time + timeout) + { + let mut cloned = drained_line.clone(); + cloned.pts = end_pts; + self.pending.push_front(cloned); + } else { + gst::debug!( + CAT, + "Reached timeout, clearing line running time {}, cur running time {}", + line_running_time, + running_time + ); + } } drained_line.duration = end_pts - drained_line.pts; } @@ -299,13 +331,16 @@ impl State { ret.push(buffer); } + let line_running_time = self.segment.to_running_time(pts); + self.pending.push_back(TimestampedLines { lines, pts, duration, + line_running_time, }); - self.drain(&mut ret, self.segment.to_running_time(pts)); + self.drain(&mut ret, line_running_time); self.last_pts = Some(pts + duration); @@ -528,11 +563,58 @@ impl ObjectSubclass for JsonToVtt { srcpad, sinkpad, state: Mutex::new(State::default()), + settings: Mutex::new(Settings::default()), } } } impl ObjectImpl for JsonToVtt { + fn properties() -> &'static [glib::ParamSpec] { + static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| { + vec![glib::ParamSpecUInt64::builder("timeout") + .nick("Timeout") + .blurb("Duration after which to erase text when no data has arrived") + .minimum(gst::ClockTime::from_seconds(16).nseconds()) + .default_value(u64::MAX) + .mutable_playing() + .build()] + }); + + PROPERTIES.as_ref() + } + + fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) { + match pspec.name() { + "timeout" => { + let mut settings = self.settings.lock().unwrap(); + let mut state = self.state.lock().unwrap(); + + let timeout = value.get().expect("type checked upstream"); + + settings.timeout = match timeout { + u64::MAX => gst::ClockTime::NONE, + _ => Some(gst::ClockTime::from_nseconds(timeout)), + }; + state.settings.timeout = settings.timeout; + } + _ => unimplemented!(), + } + } + + fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value { + match pspec.name() { + "timeout" => { + let settings = self.settings.lock().unwrap(); + if let Some(timeout) = settings.timeout { + timeout.nseconds().to_value() + } else { + u64::MAX.to_value() + } + } + _ => unimplemented!(), + } + } + fn constructed(&self) { self.parent_constructed(); @@ -597,8 +679,10 @@ impl ElementImpl for JsonToVtt { gst::trace!(CAT, imp: self, "Changing state {:?}", transition); if transition == gst::StateChange::ReadyToPaused { + let settings = self.settings.lock().unwrap(); let mut state = self.state.lock().unwrap(); *state = State::default(); + state.settings = *settings; } self.parent_change_state(transition) |