From 3cb8b33935f2f547996b375ffd6289eb7eff9a64 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Wed, 8 Jun 2011 13:40:32 +0200 Subject: [PATCH] message: move the new_base_time flag to async_done Move the flag to indicate that a new_base_time should be distributed to the pipeline, from the async_start to the async_done message. This would allow us to decide when to reset the pipeline time based on other reasons than the FLUSH_START event. The main goal eventually is to make the FLUSH events not reset time at all but reset the time based on the first buffer or segment that prerolls the pipeline again. --- gst/gstbin.c | 33 ++++++++++++++++----------------- gst/gstelement.c | 18 ++++++------------ gst/gstelement.h | 2 +- gst/gstmessage.c | 36 +++++++++++++++--------------------- gst/gstmessage.h | 6 +++--- gst/gstpipeline.c | 4 ++-- gst/gstquark.c | 2 +- gst/gstquark.h | 2 +- libs/gst/base/gstbasesink.c | 22 ++++++++++++++-------- 9 files changed, 59 insertions(+), 66 deletions(-) diff --git a/gst/gstbin.c b/gst/gstbin.c index 15714aa..3b553e3 100644 --- a/gst/gstbin.c +++ b/gst/gstbin.c @@ -227,8 +227,8 @@ static void gst_bin_state_changed (GstElement * element, GstState oldstate, static GstStateChangeReturn gst_bin_get_state_func (GstElement * element, GstState * state, GstState * pending, GstClockTime timeout); static void bin_handle_async_done (GstBin * bin, GstStateChangeReturn ret, - gboolean flag_pending); -static void bin_handle_async_start (GstBin * bin, gboolean new_base_time); + gboolean flag_pending, gboolean new_base_time); +static void bin_handle_async_start (GstBin * bin); static void bin_push_state_continue (BinContinueData * data); static void bin_do_eos (GstBin * bin); @@ -1125,13 +1125,12 @@ gst_bin_add_func (GstBin * bin, GstElement * element) { /* create message to track this aync element when it posts an async-done * message */ - async_message = - gst_message_new_async_start (GST_OBJECT_CAST (element), FALSE); + async_message = gst_message_new_async_start (GST_OBJECT_CAST (element)); break; } case GST_STATE_CHANGE_NO_PREROLL: /* ignore all async elements we might have and commit our state */ - bin_handle_async_done (bin, ret, FALSE); + bin_handle_async_done (bin, ret, FALSE, FALSE); break; case GST_STATE_CHANGE_FAILURE: break; @@ -1425,7 +1424,7 @@ gst_bin_remove_func (GstBin * bin, GstElement * element) else ret = GST_STATE_CHANGE_SUCCESS; - bin_handle_async_done (bin, ret, FALSE); + bin_handle_async_done (bin, ret, FALSE, FALSE); } else { GST_DEBUG_OBJECT (bin, "recalc state preroll: %d, other async: %d, this async %d", @@ -2628,7 +2627,7 @@ done: bin_remove_messages (bin, NULL, GST_MESSAGE_ASYNC_DONE); GST_DEBUG_OBJECT (bin, "async elements commited"); - bin_handle_async_done (bin, GST_STATE_CHANGE_SUCCESS, FALSE); + bin_handle_async_done (bin, GST_STATE_CHANGE_SUCCESS, FALSE, FALSE); } state_end: @@ -2803,7 +2802,7 @@ bin_push_state_continue (BinContinueData * data) * This function is called with the OBJECT lock. */ static void -bin_handle_async_start (GstBin * bin, gboolean new_base_time) +bin_handle_async_start (GstBin * bin) { GstState old_state, new_state; gboolean toplevel; @@ -2819,8 +2818,7 @@ bin_handle_async_start (GstBin * bin, gboolean new_base_time) * are busy with a state change or when we are NO_PREROLL. */ if (!toplevel) /* non toplevel bin, prepare async-start for the parent */ - amessage = - gst_message_new_async_start (GST_OBJECT_CAST (bin), new_base_time); + amessage = gst_message_new_async_start (GST_OBJECT_CAST (bin)); if (bin->polling || GST_STATE_PENDING (bin) != GST_STATE_VOID_PENDING) goto was_busy; @@ -2887,7 +2885,7 @@ was_no_preroll: */ static void bin_handle_async_done (GstBin * bin, GstStateChangeReturn ret, - gboolean flag_pending) + gboolean flag_pending, gboolean new_base_time) { GstState current, pending, target; GstStateChangeReturn old_ret; @@ -2915,7 +2913,7 @@ bin_handle_async_done (GstBin * bin, GstStateChangeReturn ret, target = GST_STATE_TARGET (bin); pending = GST_STATE_PENDING (bin) = target; - amessage = gst_message_new_async_done (GST_OBJECT_CAST (bin)); + amessage = gst_message_new_async_done (GST_OBJECT_CAST (bin), new_base_time); old_state = GST_STATE (bin); /* this is the state we should go to next */ @@ -3305,14 +3303,11 @@ gst_bin_handle_message_func (GstBin * bin, GstMessage * message) } case GST_MESSAGE_ASYNC_START: { - gboolean new_base_time; GstState target; GST_DEBUG_OBJECT (bin, "ASYNC_START message %p, %s", message, src ? GST_OBJECT_NAME (src) : "(NULL)"); - gst_message_parse_async_start (message, &new_base_time); - GST_OBJECT_LOCK (bin); bin_do_message_forward (bin, message); @@ -3323,7 +3318,7 @@ gst_bin_handle_message_func (GstBin * bin, GstMessage * message) /* takes ownership of the message */ bin_replace_message (bin, message, GST_MESSAGE_ASYNC_START); - bin_handle_async_start (bin, new_base_time); + bin_handle_async_start (bin); GST_OBJECT_UNLOCK (bin); break; @@ -3338,11 +3333,14 @@ gst_bin_handle_message_func (GstBin * bin, GstMessage * message) } case GST_MESSAGE_ASYNC_DONE: { + gboolean new_base_time; GstState target; GST_DEBUG_OBJECT (bin, "ASYNC_DONE message %p, %s", message, src ? GST_OBJECT_NAME (src) : "(NULL)"); + gst_message_parse_async_done (message, &new_base_time); + GST_OBJECT_LOCK (bin); bin_do_message_forward (bin, message); @@ -3363,7 +3361,8 @@ gst_bin_handle_message_func (GstBin * bin, GstMessage * message) * need to set the pending_done flag so that at the end of the state * change we can see if we need to verify pending async elements, hence * the TRUE argument here. */ - bin_handle_async_done (bin, GST_STATE_CHANGE_SUCCESS, TRUE); + bin_handle_async_done (bin, GST_STATE_CHANGE_SUCCESS, TRUE, + new_base_time); } else { GST_DEBUG_OBJECT (bin, "there are more async elements pending"); } diff --git a/gst/gstelement.c b/gst/gstelement.c index 4b2abfe..602601c 100644 --- a/gst/gstelement.c +++ b/gst/gstelement.c @@ -2335,17 +2335,14 @@ complete: /** * gst_element_lost_state: * @element: a #GstElement the state is lost of - * @new_base_time: if a new base time should be distributed * * Brings the element to the lost state. The current state of the * element is copied to the pending state so that any call to * gst_element_get_state() will return %GST_STATE_CHANGE_ASYNC. * - * An ASYNC_START message is posted with indication to distribute a new - * base_time to the element when @new_base_time is %TRUE. - * If the element was PLAYING, it will go to PAUSED. The element - * will be restored to its PLAYING state by the parent pipeline when it - * prerolls again. + * An ASYNC_START message is posted. If the element was PLAYING, it will + * go to PAUSED. The element will be restored to its PLAYING state by + * the parent pipeline when it prerolls again. * * This is mostly used for elements that lost their preroll buffer * in the %GST_STATE_PAUSED or %GST_STATE_PLAYING state after a flush, @@ -2357,7 +2354,7 @@ complete: * plugins or applications. */ void -gst_element_lost_state (GstElement * element, gboolean new_base_time) +gst_element_lost_state (GstElement * element) { GstState old_state, new_state; GstMessage *message; @@ -2389,14 +2386,11 @@ gst_element_lost_state (GstElement * element, gboolean new_base_time) GST_STATE_NEXT (element) = new_state; GST_STATE_PENDING (element) = new_state; GST_STATE_RETURN (element) = GST_STATE_CHANGE_ASYNC; - if (new_base_time) - GST_ELEMENT_START_TIME (element) = 0; GST_OBJECT_UNLOCK (element); _priv_gst_element_state_changed (element, new_state, new_state, new_state); - message = - gst_message_new_async_start (GST_OBJECT_CAST (element), new_base_time); + message = gst_message_new_async_start (GST_OBJECT_CAST (element)); gst_element_post_message (element, message); return; @@ -2410,7 +2404,7 @@ only_async_start: { GST_OBJECT_UNLOCK (element); - message = gst_message_new_async_start (GST_OBJECT_CAST (element), TRUE); + message = gst_message_new_async_start (GST_OBJECT_CAST (element)); gst_element_post_message (element, message); return; } diff --git a/gst/gstelement.h b/gst/gstelement.h index 8ffd6ed..33b36f1 100644 --- a/gst/gstelement.h +++ b/gst/gstelement.h @@ -802,7 +802,7 @@ GstStateChangeReturn gst_element_change_state (GstElement * element, GstStateChange transition); GstStateChangeReturn gst_element_continue_state (GstElement * element, GstStateChangeReturn ret); -void gst_element_lost_state (GstElement * element, gboolean new_base_time); +void gst_element_lost_state (GstElement * element); /* factory management */ GstElementFactory* gst_element_get_factory (GstElement *element); diff --git a/gst/gstmessage.c b/gst/gstmessage.c index 85fef49..2c81d89 100644 --- a/gst/gstmessage.c +++ b/gst/gstmessage.c @@ -870,27 +870,19 @@ gst_message_new_duration (GstObject * src, GstFormat format, gint64 duration) /** * gst_message_new_async_start: * @src: (transfer none): The object originating the message. - * @new_base_time: if a new base_time should be set on the element * - * This message is posted by elements when they start an ASYNC state change. - * @new_base_time is set to TRUE when the element lost its state when it was - * PLAYING. + * This message is posted by elements when they start an ASYNC state change. * * Returns: (transfer full): The new async_start message. * * MT safe. - * - * Since: 0.10.13 */ GstMessage * -gst_message_new_async_start (GstObject * src, gboolean new_base_time) +gst_message_new_async_start (GstObject * src) { GstMessage *message; - GstStructure *structure; - structure = gst_structure_id_new (GST_QUARK (MESSAGE_ASYNC_START), - GST_QUARK (NEW_BASE_TIME), G_TYPE_BOOLEAN, new_base_time, NULL); - message = gst_message_new_custom (GST_MESSAGE_ASYNC_START, src, structure); + message = gst_message_new_custom (GST_MESSAGE_ASYNC_START, src, NULL); return message; } @@ -898,21 +890,25 @@ gst_message_new_async_start (GstObject * src, gboolean new_base_time) /** * gst_message_new_async_done: * @src: (transfer none): The object originating the message. + * @new_base_time: if a new base_time should be set on the element * * The message is posted when elements completed an ASYNC state change. + * @new_base_time is set to TRUE when the element requests a new base_time + * before going to PLAYING. * * Returns: (transfer full): The new async_done message. * * MT safe. - * - * Since: 0.10.13 */ GstMessage * -gst_message_new_async_done (GstObject * src) +gst_message_new_async_done (GstObject * src, gboolean new_base_time) { GstMessage *message; + GstStructure *structure; - message = gst_message_new_custom (GST_MESSAGE_ASYNC_DONE, src, NULL); + structure = gst_structure_id_new (GST_QUARK (MESSAGE_ASYNC_DONE), + GST_QUARK (NEW_BASE_TIME), G_TYPE_BOOLEAN, new_base_time, NULL); + message = gst_message_new_custom (GST_MESSAGE_ASYNC_DONE, src, structure); return message; } @@ -1607,23 +1603,21 @@ gst_message_parse_duration (GstMessage * message, GstFormat * format, } /** - * gst_message_parse_async_start: + * gst_message_parse_async_done: * @message: A valid #GstMessage of type GST_MESSAGE_ASYNC_DONE. * @new_base_time: (out): Result location for the new_base_time or NULL * - * Extract the new_base_time from the async_start message. + * Extract the new_base_time from the async_done message. * * MT safe. - * - * Since: 0.10.13 */ void -gst_message_parse_async_start (GstMessage * message, gboolean * new_base_time) +gst_message_parse_async_done (GstMessage * message, gboolean * new_base_time) { GstStructure *structure; g_return_if_fail (GST_IS_MESSAGE (message)); - g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ASYNC_START); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ASYNC_DONE); structure = GST_MESSAGE_STRUCTURE (message); if (new_base_time) diff --git a/gst/gstmessage.h b/gst/gstmessage.h index c93e413..268b7a1 100644 --- a/gst/gstmessage.h +++ b/gst/gstmessage.h @@ -493,11 +493,11 @@ void gst_message_parse_duration (GstMessage *message, GstFormat GstMessage * gst_message_new_latency (GstObject * src); /* ASYNC_START */ -GstMessage * gst_message_new_async_start (GstObject * src, gboolean new_base_time); -void gst_message_parse_async_start (GstMessage *message, gboolean *new_base_time); +GstMessage * gst_message_new_async_start (GstObject * src); /* ASYNC_DONE */ -GstMessage * gst_message_new_async_done (GstObject * src); +GstMessage * gst_message_new_async_done (GstObject * src, gboolean new_base_time); +void gst_message_parse_async_done (GstMessage *message, gboolean *new_base_time); /* STRUCTURE CHANGE */ GstMessage * gst_message_new_structure_change (GstObject * src, GstStructureChangeType type, diff --git a/gst/gstpipeline.c b/gst/gstpipeline.c index 9a3b650..32cd111 100644 --- a/gst/gstpipeline.c +++ b/gst/gstpipeline.c @@ -548,11 +548,11 @@ gst_pipeline_handle_message (GstBin * bin, GstMessage * message) GstPipeline *pipeline = GST_PIPELINE_CAST (bin); switch (GST_MESSAGE_TYPE (message)) { - case GST_MESSAGE_ASYNC_START: + case GST_MESSAGE_ASYNC_DONE: { gboolean new_base_time; - gst_message_parse_async_start (message, &new_base_time); + gst_message_parse_async_done (message, &new_base_time); /* reset our running time if we need to distribute a new base_time to the * children. */ diff --git a/gst/gstquark.c b/gst/gstquark.c index 7254eb2..fe8f407 100644 --- a/gst/gstquark.c +++ b/gst/gstquark.c @@ -43,7 +43,7 @@ static const gchar *_quark_strings[] = { "GstMessageBuffering", "GstMessageState", "GstMessageClockProvide", "GstMessageClockLost", "GstMessageNewClock", "GstMessageStructureChange", "GstMessageSegmentStart", "GstMessageSegmentDone", "GstMessageDuration", - "GstMessageAsyncStart", "GstMessageRequestState", "GstMessageStreamStatus", + "GstMessageAsyncDone", "GstMessageRequestState", "GstMessageStreamStatus", "GstQueryPosition", "GstQueryDuration", "GstQueryLatency", "GstQueryConvert", "GstQuerySegment", "GstQuerySeeking", "GstQueryFormats", "GstQueryBuffering", "GstQueryURI", "GstEventStep", "GstMessageStepDone", "amount", "flush", diff --git a/gst/gstquark.h b/gst/gstquark.h index cb1f470..ee4c196 100644 --- a/gst/gstquark.h +++ b/gst/gstquark.h @@ -97,7 +97,7 @@ typedef enum _GstQuarkId GST_QUARK_MESSAGE_SEGMENT_START = 68, GST_QUARK_MESSAGE_SEGMENT_DONE = 69, GST_QUARK_MESSAGE_DURATION = 70, - GST_QUARK_MESSAGE_ASYNC_START = 71, + GST_QUARK_MESSAGE_ASYNC_DONE = 71, GST_QUARK_MESSAGE_REQUEST_STATE = 72, GST_QUARK_MESSAGE_STREAM_STATUS = 73, GST_QUARK_QUERY_POSITION = 74, diff --git a/libs/gst/base/gstbasesink.c b/libs/gst/base/gstbasesink.c index 7c3db5c..1413167 100644 --- a/libs/gst/base/gstbasesink.c +++ b/libs/gst/base/gstbasesink.c @@ -262,6 +262,8 @@ struct _GstBaseSinkPrivate /* for throttling and QoS */ GstClockTime earliest_in_time; GstClockTime throttle_time; + + gboolean reset_time; }; #define DO_RUNNING_AVG(avg,val,size) (((val) + ((size)-1) * (avg)) / (size)) @@ -1469,6 +1471,7 @@ gst_base_sink_commit_state (GstBaseSink * basesink) gboolean post_paused = FALSE; gboolean post_async_done = FALSE; gboolean post_playing = FALSE; + gboolean reset_time; /* we are certainly not playing async anymore now */ basesink->playing_async = FALSE; @@ -1478,6 +1481,8 @@ gst_base_sink_commit_state (GstBaseSink * basesink) next = GST_STATE_NEXT (basesink); pending = GST_STATE_PENDING (basesink); post_pending = pending; + reset_time = basesink->priv->reset_time; + basesink->priv->reset_time = FALSE; switch (pending) { case GST_STATE_PLAYING: @@ -1528,7 +1533,7 @@ gst_base_sink_commit_state (GstBaseSink * basesink) if (post_async_done) { GST_DEBUG_OBJECT (basesink, "posting async-done message"); gst_element_post_message (GST_ELEMENT_CAST (basesink), - gst_message_new_async_done (GST_OBJECT_CAST (basesink))); + gst_message_new_async_done (GST_OBJECT_CAST (basesink), reset_time)); } if (post_playing) { GST_DEBUG_OBJECT (basesink, "posting PLAYING state change message"); @@ -3257,7 +3262,8 @@ gst_base_sink_flush_start (GstBaseSink * basesink, GstPad * pad) * prerolled buffer */ basesink->playing_async = TRUE; if (basesink->priv->async_enabled) { - gst_element_lost_state (GST_ELEMENT_CAST (basesink), TRUE); + basesink->priv->reset_time = TRUE; + gst_element_lost_state (GST_ELEMENT_CAST (basesink)); } else { basesink->priv->have_latency = TRUE; } @@ -3928,7 +3934,7 @@ gst_base_sink_perform_step (GstBaseSink * sink, GstPad * pad, GstEvent * event) sink->playing_async = TRUE; priv->pending_step.need_preroll = TRUE; sink->need_preroll = FALSE; - gst_element_lost_state (GST_ELEMENT_CAST (sink), FALSE); + gst_element_lost_state (GST_ELEMENT_CAST (sink)); } else { sink->priv->have_latency = TRUE; sink->need_preroll = FALSE; @@ -4856,6 +4862,7 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition) priv->step_unlock = FALSE; basesink->need_preroll = TRUE; basesink->playing_async = TRUE; + basesink->priv->reset_time = FALSE; priv->current_sstart = GST_CLOCK_TIME_NONE; priv->current_sstop = GST_CLOCK_TIME_NONE; priv->eos_rtime = GST_CLOCK_TIME_NONE; @@ -4873,7 +4880,7 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition) * the state change function */ ret = GST_STATE_CHANGE_ASYNC; gst_element_post_message (GST_ELEMENT_CAST (basesink), - gst_message_new_async_start (GST_OBJECT_CAST (basesink), FALSE)); + gst_message_new_async_start (GST_OBJECT_CAST (basesink))); } else { priv->have_latency = TRUE; } @@ -4908,7 +4915,7 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition) GST_DEBUG_OBJECT (basesink, "doing async state change"); ret = GST_STATE_CHANGE_ASYNC; gst_element_post_message (GST_ELEMENT_CAST (basesink), - gst_message_new_async_start (GST_OBJECT_CAST (basesink), FALSE)); + gst_message_new_async_start (GST_OBJECT_CAST (basesink))); } } GST_BASE_SINK_PREROLL_UNLOCK (basesink); @@ -4970,8 +4977,7 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition) GST_DEBUG_OBJECT (basesink, "doing async state change"); ret = GST_STATE_CHANGE_ASYNC; gst_element_post_message (GST_ELEMENT_CAST (basesink), - gst_message_new_async_start (GST_OBJECT_CAST (basesink), - FALSE)); + gst_message_new_async_start (GST_OBJECT_CAST (basesink))); } } } @@ -5009,7 +5015,7 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition) GST_STATE_PLAYING, GST_STATE_PAUSED, GST_STATE_READY)); gst_element_post_message (GST_ELEMENT_CAST (basesink), - gst_message_new_async_done (GST_OBJECT_CAST (basesink))); + gst_message_new_async_done (GST_OBJECT_CAST (basesink), FALSE)); } priv->commited = TRUE; } else { -- 2.7.4