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/1635>
This commit is contained in:
Sebastian Dröge 2024-06-26 10:06:14 +03:00 committed by GStreamer Marge Bot
parent 7caf6b2073
commit bbf131086a
2 changed files with 17 additions and 3 deletions

View file

@ -1053,7 +1053,16 @@ impl LiveSync {
None => None, None => None,
Some(Item::Buffer(buffer, timestamp, lateness)) => { 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 // Try this buffer again on the next iteration
state state
.queue .queue
@ -1261,8 +1270,11 @@ impl LiveSync {
return false; return false;
}; };
// When out_timestamp is set, we also have an out_buffer // When out_timestamp is set, we also have an out_buffer unless it is the first buffer
let slack = state.out_buffer.as_deref().unwrap().duration().unwrap(); let Some(ref out_buffer) = state.out_buffer else {
return false;
};
let slack = out_buffer.duration().unwrap();
if timestamp.start < out_timestamp.end + slack { if timestamp.start < out_timestamp.end + slack {
return false; 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();
h.push_from_src().unwrap(); h.push_from_src().unwrap();
assert_eq!(h.pull_event().unwrap().type_(), gst::EventType::StreamStart); 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::Caps);
assert_eq!(h.pull_event().unwrap().type_(), gst::EventType::Segment); assert_eq!(h.pull_event().unwrap().type_(), gst::EventType::Segment);
assert_crank_pull(h, o, 0, 0, gst::BufferFlags::DISCONT, singlesegment); assert_crank_pull(h, o, 0, 0, gst::BufferFlags::DISCONT, singlesegment);