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);
{
/* 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;
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",
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:
* 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;
* 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;
*/
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;
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 */
}
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);
/* 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;
}
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);
* 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");
}
/**
* 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,
* 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;
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;
{
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;
}
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);
/**
* 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;
}
/**
* 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;
}
}
/**
- * 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)
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,
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. */
"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",
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,
/* 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))
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;
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:
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");
* 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;
}
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;
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;
* 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;
}
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);
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_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 {