pipeline: fix base_time selection when flush seeking live

When a live pipeline goes to PLAYING, its change_state method
is called twice for PAUSED_TO_PLAYING: the first time is
from GstElement, when NO_PREROLL is returned, the second
is from GstBin, after all async_done messages have been
collected.

base_time selection is done only the first time, through
comparisons with start_time.

On the other hand, when this live pipeline gets flush seeked,
even though start_time is reset by the sink upon reception
of flush_stop(reset_time=TRUE), PAUSED_TO_PLAYING only occurs
once, from GstBin, after all async_done messages have been
collected. This causes the base_time to be off by <latency>.

This commit addresses this by mimicing the behaviour of
GstElement on NO_PREROLL, and calling the change_state
method manually when the following conditions are met:

* The pipeline is live

* The target state is PLAYING
This commit is contained in:
Mathieu Duponchelle 2020-04-08 22:22:48 +02:00 committed by GStreamer Merge Bot
parent 4679c2ed6f
commit 0566b0528a

View File

@ -109,6 +109,7 @@ struct _GstPipelinePrivate
{
/* with LOCK */
gboolean auto_flush_bus;
gboolean is_live;
/* when we need to update stream_time or clock when going back to
* PLAYING*/
@ -228,6 +229,8 @@ gst_pipeline_init (GstPipeline * pipeline)
pipeline->delay = DEFAULT_DELAY;
pipeline->priv->latency = DEFAULT_LATENCY;
pipeline->priv->is_live = FALSE;
/* create and set a default bus */
bus = gst_bus_new ();
#if 0
@ -512,6 +515,7 @@ gst_pipeline_change_state (GstElement * element, GstStateChange transition)
break;
}
case GST_STATE_CHANGE_PAUSED_TO_READY:
pipeline->priv->is_live = FALSE;
reset_start_time (pipeline, 0);
break;
case GST_STATE_CHANGE_READY_TO_NULL:
@ -520,6 +524,12 @@ gst_pipeline_change_state (GstElement * element, GstStateChange transition)
result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
if (GST_STATE_TRANSITION_NEXT (transition) == GST_STATE_PAUSED) {
pipeline->priv->is_live = result == GST_STATE_CHANGE_NO_PREROLL;
GST_INFO_OBJECT (pipeline, "pipeline is%slive",
pipeline->priv->is_live ? " " : " not ");
}
switch (transition) {
case GST_STATE_CHANGE_NULL_TO_NULL:
break;
@ -613,6 +623,14 @@ gst_pipeline_handle_message (GstBin * bin, GstMessage * message)
/* reset our running time if we need to distribute a new base_time to the
* children. */
reset_start_time (pipeline, running_time);
/* If we are live, sample a new base_time immediately */
if (pipeline->priv->is_live
&& GST_STATE_TARGET (pipeline) == GST_STATE_PLAYING) {
gst_pipeline_change_state (GST_ELEMENT (pipeline),
GST_STATE_CHANGE_PAUSED_TO_PLAYING);
}
break;
}
case GST_MESSAGE_CLOCK_LOST: