aggregator: Don't produce buffers when live but not in PLAYING yet

Especially in force-live=true mode it was possible to produce buffers before the
element was set to PLAYING as long as a clock was available already.

This could easily lead to outputting buffers too early, and e.g. before the
correct base time is set and available.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8897>
This commit is contained in:
Sebastian Dröge 2025-04-25 12:18:19 +03:00
parent b05a498187
commit df46cfcb28

View File

@ -367,6 +367,8 @@ struct _GstAggregatorPrivate
/* Our state is >= PAUSED */
gboolean running; /* protected by src_lock */
/* Our state is >= PAUSED but < PLAYING */
gboolean blocked; /* protected by src_lock */
/* seqnum from last seek or common seqnum to flush start events received
* on all pads, for flushing without a seek */
@ -912,7 +914,8 @@ gst_aggregator_wait_and_check (GstAggregator * self, gboolean * timeout)
* that pad.
*/
GST_OBJECT_LOCK (self);
if (!GST_CLOCK_TIME_IS_VALID (latency) ||
if (!GST_CLOCK_TIME_IS_VALID (latency) || /* not live */
self->priv->blocked || /* live but not PLAYING yet */
!GST_IS_CLOCK (GST_ELEMENT_CLOCK (self)) ||
!GST_CLOCK_TIME_IS_VALID (start) ||
(self->priv->first_buffer
@ -973,7 +976,7 @@ gst_aggregator_wait_and_check (GstAggregator * self, gboolean * timeout)
status, GST_STIME_ARGS (jitter));
/* After waiting, check if we're actually still running */
if (!self->priv->running || !self->priv->send_eos) {
if (!self->priv->running || !self->priv->send_eos || self->priv->blocked) {
SRC_UNLOCK (self);
return FALSE;
@ -1628,6 +1631,8 @@ gst_aggregator_start (GstAggregator * self)
self->priv->peer_latency_live = FALSE;
self->priv->peer_latency_min = self->priv->peer_latency_max = 0;
self->priv->blocked = TRUE;
gst_aggregator_set_allocation (self, NULL, NULL, NULL, NULL);
klass = GST_AGGREGATOR_GET_CLASS (self);
@ -2084,6 +2089,7 @@ gst_aggregator_stop (GstAggregator * agg)
agg->priv->peer_latency_live = FALSE;
agg->priv->peer_latency_min = agg->priv->peer_latency_max = 0;
agg->priv->posted_latency_msg = FALSE;
agg->priv->blocked = FALSE;
gst_aggregator_set_allocation (agg, NULL, NULL, NULL, NULL);
@ -2114,6 +2120,7 @@ gst_aggregator_change_state (GstElement * element, GstStateChange transition)
/* Wake up any waiting as now we have a clock and can do
* proper waiting on the clock if necessary */
SRC_LOCK (self);
self->priv->blocked = FALSE;
SRC_BROADCAST (self);
SRC_UNLOCK (self);
break;
@ -2138,6 +2145,7 @@ gst_aggregator_change_state (GstElement * element, GstStateChange transition)
/* Wake up any waiting as now clock might be gone and we might
* need to wait on the condition variable again */
SRC_LOCK (self);
self->priv->blocked = TRUE;
SRC_BROADCAST (self);
SRC_UNLOCK (self);
if (self->priv->force_live) {