diff --git a/gst/gstbin.c b/gst/gstbin.c index 15714aa47c..3b553e31c2 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 4b2abfecdf..602601c832 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 8ffd6edecb..33b36f1e99 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 85fef49490..2c81d8907f 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 c93e4131cc..268b7a1485 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 9a3b650cb3..32cd11162d 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 7254eb2528..fe8f407efe 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 cb1f470170..ee4c19648a 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 7c3db5cceb..14131671c5 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 {