From 0566b0528a5228804fa3e71aa5dca4fbd620de1e Mon Sep 17 00:00:00 2001 From: Mathieu Duponchelle Date: Wed, 8 Apr 2020 22:22:48 +0200 Subject: [PATCH] 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 . 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 --- gst/gstpipeline.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/gst/gstpipeline.c b/gst/gstpipeline.c index f967d8e..032fe69 100644 --- a/gst/gstpipeline.c +++ b/gst/gstpipeline.c @@ -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: -- 2.7.4