mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2024-09-27 14:30:27 +00:00
jsontovtt: Add timeout property
As described in the spec D.4 Automatic Caption Blanking, allows automatic clear if user specified timeout value
This commit is contained in:
parent
6e7ebc30e0
commit
3d317b976e
2 changed files with 105 additions and 5 deletions
|
@ -3645,6 +3645,22 @@
|
||||||
"presence": "always"
|
"presence": "always"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"properties": {
|
||||||
|
"timeout": {
|
||||||
|
"blurb": "Duration after which to erase text when no data has arrived",
|
||||||
|
"conditionally-available": false,
|
||||||
|
"construct": false,
|
||||||
|
"construct-only": false,
|
||||||
|
"controllable": false,
|
||||||
|
"default": "18446744073709551615",
|
||||||
|
"max": "18446744073709551615",
|
||||||
|
"min": "16000000000",
|
||||||
|
"mutable": "playing",
|
||||||
|
"readable": true,
|
||||||
|
"type": "guint64",
|
||||||
|
"writable": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"rank": "none"
|
"rank": "none"
|
||||||
},
|
},
|
||||||
"mccenc": {
|
"mccenc": {
|
||||||
|
|
|
@ -24,6 +24,20 @@ struct TimestampedLines {
|
||||||
lines: Lines,
|
lines: Lines,
|
||||||
pts: gst::ClockTime,
|
pts: gst::ClockTime,
|
||||||
duration: 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 {
|
struct State {
|
||||||
|
@ -33,6 +47,7 @@ struct State {
|
||||||
|
|
||||||
keyunit_requests: BinaryHeap<ForceKeyUnitRequest>,
|
keyunit_requests: BinaryHeap<ForceKeyUnitRequest>,
|
||||||
segment: gst::FormattedSegment<gst::ClockTime>,
|
segment: gst::FormattedSegment<gst::ClockTime>,
|
||||||
|
settings: Settings,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for State {
|
impl Default for State {
|
||||||
|
@ -43,6 +58,7 @@ impl Default for State {
|
||||||
last_pts: None,
|
last_pts: None,
|
||||||
keyunit_requests: BinaryHeap::new(),
|
keyunit_requests: BinaryHeap::new(),
|
||||||
segment: gst::FormattedSegment::new(),
|
segment: gst::FormattedSegment::new(),
|
||||||
|
settings: Settings::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,6 +68,7 @@ pub struct JsonToVtt {
|
||||||
sinkpad: gst::Pad,
|
sinkpad: gst::Pad,
|
||||||
|
|
||||||
state: Mutex<State>,
|
state: Mutex<State>,
|
||||||
|
settings: Mutex<Settings>,
|
||||||
}
|
}
|
||||||
|
|
||||||
static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
|
static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
|
||||||
|
@ -208,10 +225,25 @@ impl State {
|
||||||
.unwrap_or_else(|| self.segment.stop().unwrap())
|
.unwrap_or_else(|| self.segment.stop().unwrap())
|
||||||
};
|
};
|
||||||
|
|
||||||
if running_time.is_some() {
|
if let (Some(line_running_time), Some(running_time)) =
|
||||||
let mut cloned = drained_line.clone();
|
(drained_line.line_running_time, running_time)
|
||||||
cloned.pts = end_pts;
|
{
|
||||||
self.pending.push_front(cloned);
|
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;
|
drained_line.duration = end_pts - drained_line.pts;
|
||||||
}
|
}
|
||||||
|
@ -299,13 +331,16 @@ impl State {
|
||||||
ret.push(buffer);
|
ret.push(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let line_running_time = self.segment.to_running_time(pts);
|
||||||
|
|
||||||
self.pending.push_back(TimestampedLines {
|
self.pending.push_back(TimestampedLines {
|
||||||
lines,
|
lines,
|
||||||
pts,
|
pts,
|
||||||
duration,
|
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);
|
self.last_pts = Some(pts + duration);
|
||||||
|
|
||||||
|
@ -528,11 +563,58 @@ impl ObjectSubclass for JsonToVtt {
|
||||||
srcpad,
|
srcpad,
|
||||||
sinkpad,
|
sinkpad,
|
||||||
state: Mutex::new(State::default()),
|
state: Mutex::new(State::default()),
|
||||||
|
settings: Mutex::new(Settings::default()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ObjectImpl for JsonToVtt {
|
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) {
|
fn constructed(&self) {
|
||||||
self.parent_constructed();
|
self.parent_constructed();
|
||||||
|
|
||||||
|
@ -597,8 +679,10 @@ impl ElementImpl for JsonToVtt {
|
||||||
gst::trace!(CAT, imp: self, "Changing state {:?}", transition);
|
gst::trace!(CAT, imp: self, "Changing state {:?}", transition);
|
||||||
|
|
||||||
if transition == gst::StateChange::ReadyToPaused {
|
if transition == gst::StateChange::ReadyToPaused {
|
||||||
|
let settings = self.settings.lock().unwrap();
|
||||||
let mut state = self.state.lock().unwrap();
|
let mut state = self.state.lock().unwrap();
|
||||||
*state = State::default();
|
*state = State::default();
|
||||||
|
state.settings = *settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.parent_change_state(transition)
|
self.parent_change_state(transition)
|
||||||
|
|
Loading…
Reference in a new issue