livesync: Synchronize on the first buffer too

Previously the first buffer would be output immediately and
synchronization would only happen from the second buffer onwards.
This would mean that the first buffer would potentially be output too
early.

Instead, if there is no known output timestamp yet but a buffer with a
timestamp, first of all take its start as the initial output timestamp
and synchronize on that buffer.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1643>
This commit is contained in:
Sebastian Dröge 2024-06-26 10:06:14 +03:00 committed by Backport Bot
parent 6d177f5d3c
commit 000e9c92d2
2 changed files with 17 additions and 3 deletions

View file

@ -1053,7 +1053,16 @@ impl LiveSync {
None => None,
Some(Item::Buffer(buffer, timestamp, lateness)) => {
if self.buffer_is_early(&state, timestamp) {
// Synchronize on the first buffer with timestamps to not output it too early
if let Some(Timestamps { start, .. }) =
state.out_timestamp.is_none().then_some(timestamp).flatten()
{
state.out_timestamp = Some(Timestamps { start, end: start });
state
.queue
.push_front(Item::Buffer(buffer, timestamp, lateness));
return Ok(gst::FlowSuccess::Ok);
} else if self.buffer_is_early(&state, timestamp) {
// Try this buffer again on the next iteration
state
.queue
@ -1261,8 +1270,11 @@ impl LiveSync {
return false;
};
// When out_timestamp is set, we also have an out_buffer
let slack = state.out_buffer.as_deref().unwrap().duration().unwrap();
// When out_timestamp is set, we also have an out_buffer unless it is the first buffer
let Some(ref out_buffer) = state.out_buffer else {
return false;
};
let slack = out_buffer.duration().unwrap();
if timestamp.start < out_timestamp.end + slack {
return false;

View file

@ -138,6 +138,8 @@ fn test_livesync(h: &mut gst_check::Harness, o: u64, singlesegment: bool) {
h.push_from_src().unwrap();
h.push_from_src().unwrap();
assert_eq!(h.pull_event().unwrap().type_(), gst::EventType::StreamStart);
// Caps are only output once waiting for the first buffer has finished
h.crank_single_clock_wait().unwrap();
assert_eq!(h.pull_event().unwrap().type_(), gst::EventType::Caps);
assert_eq!(h.pull_event().unwrap().type_(), gst::EventType::Segment);
assert_crank_pull(h, o, 0, 0, gst::BufferFlags::DISCONT, singlesegment);