gst: gstpipewireclock: Return a valid clock before stream start

When a gstreamer pipeline transits to playing state, it sets the
base_time of all elements to the internal time of the current clock. At
that point, the pipewire stream has not yet started and the
gstpipewireclock returns last_time which is initialized to 0 in
gstpipewirestream. This leads to a incorrect base_time in the gstreamer
element and various synchronization issues.

The use-case for last_time is not really clear to me. My basic guesswork
is: If a stream is no longer streaming the internal clock should pause
at that time and return last_time.  So this patch keeps this behaviour
in place and only ensures that a valid time is returned when the stream
is not yet started and last_time was not purposely initialized with a
value != 0.

A gstreamer pipeline that can be used to replicate the issue is:
GST_DEBUG="pipeline:5,GST_CLOCK:6,pipewiresrc:6" gst-launch-1.0 \
pipewiresrc name=video target-object=<some video target> ! \
video/x-raw,format=UYVY !  fakesink \
pipewiresrc name=audio target-object=<some audio target> ! \
audio/x-raw ! f akesink 2>&1 | \
grep PTS

Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
This commit is contained in:
Stefan Klug 2026-04-22 13:08:08 +02:00
parent 4c421391d5
commit f5b21666bd

View file

@ -34,16 +34,17 @@ gst_pipewire_clock_get_internal_time (GstClock * clock)
GstClockTime result;
uint64_t now;
if (G_UNLIKELY (!s))
return pclock->last_time;
now = pw_stream_get_nsec(s->pwstream);
if (G_UNLIKELY (!s))
return pclock->last_time ? pclock->last_time : now;
#if 1
struct pw_time t;
if (s->pwstream == NULL ||
pw_stream_get_time_n (s->pwstream, &t, sizeof(t)) < 0 ||
t.rate.denom == 0)
return pclock->last_time;
return pclock->last_time ? pclock->last_time : now;
result = gst_util_uint64_scale (t.ticks, GST_SECOND * t.rate.num, t.rate.denom);
result += now - t.now;