livesync: add support for variable framerate

A variable framerate is signaled by a framerate of 0/1 and the
max-framerate field. This may be the result of source that can produce
up to max-framerate frames, but may produce less. A live stream may
expect frames with the expected max-framerate and updated timestamps
even if the frame contents didn't change.

Support streams with variable framerate in livesync and send frames with
max-framerate to downstream.
This commit is contained in:
Michael Tretter 2024-01-24 15:22:00 +01:00
parent 97c0f68ca9
commit 06b97bcb3e
2 changed files with 32 additions and 1 deletions

View file

@ -39,7 +39,12 @@ fn audio_info_from_caps(
fn duration_from_caps(caps: &gst::CapsRef) -> Option<gst::ClockTime> {
caps.structure(0)
.filter(|s| s.name().starts_with("video/") || s.name().starts_with("image/"))
.and_then(|s| s.get::<gst::Fraction>("framerate").ok())
.and_then(|s| {
s.get::<gst::Fraction>("framerate")
.ok()
.filter(|f| f.denom() != 1 || f.numer() != 0)
.or_else(|| s.get::<gst::Fraction>("max-framerate").ok())
})
.filter(|framerate| framerate.denom() > 0 && framerate.numer() > 0)
.and_then(|framerate| {
gst::ClockTime::SECOND.mul_div_round(framerate.denom() as u64, framerate.numer() as u64)

View file

@ -120,6 +120,32 @@ fn test_video_negotiate_framerate_fixed() {
assert_eq!(current_caps, src_caps);
}
#[test]
fn test_video_negotiate_framerate_variable() {
init();
let mut h = gst_check::Harness::new("livesync");
let src_caps = gst::Caps::builder("video/x-raw")
.field("framerate", gst::Fraction::new(0, 1))
.field("max-framerate", gst::Fraction::new(30, 1))
.build();
h.set_src_caps(src_caps.clone());
h.play();
let buffer = gst::Buffer::new();
assert!(h.push_and_pull(buffer).is_ok());
let current_caps = h
.sinkpad()
.expect("harness has no sinkpad")
.current_caps()
.expect("current caps missing");
assert_eq!(current_caps, src_caps);
}
fn test_video(singlesegment: bool) {
init();