-
Pl
chevron_right
Michael Calabrese: Synchronizing Timeline Ticks with GES Framerates in Rust
news.movim.eu / PlanetGnome • 1 day ago • 1 minute
While working on my GSoC project (rewriting the Pitivi timeline in Rust), I ran into an issue getting precise UI ticks that map to the absolute nanosecond timestamps of the video frames. Initially I hardcoded NTSC fractional math (24000/1001) to calculate the boundaries of frames.
This led to issues with truncated timestamps, and had a glaring issue with other framerates (like 30fps). I needed a more robust solution that could handle any framerate and provide accurate tick positions.
I assumed that I could extract the framerate directly from
ges::Timeline
, however there is no direct getter in the Rust bindings. After some digging, I discovered that the framerate is actually stored in the
gst::Caps
of the timeline's video stream as a
gst::Fraction
.
My Approach
The steps I used:
-
Enumerate the timeline tracks (
timeline.tracks()) -
Filter for the video track (checking
ges::TrackType::VIDEO) -
Read the track's
restriction_caps -
Extract the
gst::Fraction
My helper
I wrote a helper function to extract the framerate from the timeline:
pub fn get_fps(&self, timeline: &ges::Timeline) -> Option<(i128, i128)> {
timeline
.tracks()
.into_iter()
.find(|track| track.track_type().contains(ges::TrackType::VIDEO))
.and_then(|track| {
let caps = track.restriction_caps().or_else(|| track.caps())?;
let structure = caps.structure(0)?;
let fps = structure.get::<gst::Fraction>("framerate").ok()?;
// Extract the safe numerator and denominator
Some((fps.numer() as i128, fps.denom() as i128))
})
}
// ... inside the timeline injection logic:
if let Some((fps_num, fps_denom)) = self.get_fps(timeline) {
self.fps_num.set(fps_num.max(1) as i32);
self.fps_denom.set(fps_denom.max(1) as i32);
} else {
// Default to 23.976 if we can't find a valid framerate caps
self.fps_num.set(24_000);
self.fps_denom.set(1_001);
}
I make some assumptions here, such as only one video track existing, and that the framerate is always present in the caps. This solution made the tick spacing and labels line up with the timeline’s actual frame boundaries at any framerate.