mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-05 23:18:52 +00:00
bin: Only post EOS messages after reaching the PLAYING state
Fixes bug #647756.
This commit is contained in:
parent
c6e9ce64ae
commit
e22f5d8a68
1 changed files with 45 additions and 17 deletions
62
gst/gstbin.c
62
gst/gstbin.c
|
@ -202,6 +202,8 @@ struct _GstBinPrivate
|
||||||
GstIndex *index;
|
GstIndex *index;
|
||||||
/* forward messages from our children */
|
/* forward messages from our children */
|
||||||
gboolean message_forward;
|
gboolean message_forward;
|
||||||
|
|
||||||
|
gboolean posted_eos;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -226,6 +228,7 @@ static void bin_handle_async_done (GstBin * bin, GstStateChangeReturn ret,
|
||||||
gboolean flag_pending);
|
gboolean flag_pending);
|
||||||
static void bin_handle_async_start (GstBin * bin, gboolean new_base_time);
|
static void bin_handle_async_start (GstBin * bin, gboolean new_base_time);
|
||||||
static void bin_push_state_continue (BinContinueData * data);
|
static void bin_push_state_continue (BinContinueData * data);
|
||||||
|
static void bin_do_eos (GstBin * bin);
|
||||||
|
|
||||||
static gboolean gst_bin_add_func (GstBin * bin, GstElement * element);
|
static gboolean gst_bin_add_func (GstBin * bin, GstElement * element);
|
||||||
static gboolean gst_bin_remove_func (GstBin * bin, GstElement * element);
|
static gboolean gst_bin_remove_func (GstBin * bin, GstElement * element);
|
||||||
|
@ -950,10 +953,10 @@ bin_remove_messages (GstBin * bin, GstObject * src, GstMessageType types)
|
||||||
*
|
*
|
||||||
* call with bin LOCK */
|
* call with bin LOCK */
|
||||||
static gboolean
|
static gboolean
|
||||||
is_eos (GstBin * bin)
|
is_eos (GstBin * bin, guint32 * seqnum)
|
||||||
{
|
{
|
||||||
gboolean result;
|
gboolean result;
|
||||||
GList *walk;
|
GList *walk, *msgs;
|
||||||
|
|
||||||
result = TRUE;
|
result = TRUE;
|
||||||
for (walk = bin->children; walk; walk = g_list_next (walk)) {
|
for (walk = bin->children; walk; walk = g_list_next (walk)) {
|
||||||
|
@ -962,8 +965,10 @@ is_eos (GstBin * bin)
|
||||||
element = GST_ELEMENT_CAST (walk->data);
|
element = GST_ELEMENT_CAST (walk->data);
|
||||||
if (bin_element_is_sink (element, bin) == 0) {
|
if (bin_element_is_sink (element, bin) == 0) {
|
||||||
/* check if element posted EOS */
|
/* check if element posted EOS */
|
||||||
if (find_message (bin, GST_OBJECT_CAST (element), GST_MESSAGE_EOS)) {
|
if ((msgs =
|
||||||
|
find_message (bin, GST_OBJECT_CAST (element), GST_MESSAGE_EOS))) {
|
||||||
GST_DEBUG ("sink '%s' posted EOS", GST_ELEMENT_NAME (element));
|
GST_DEBUG ("sink '%s' posted EOS", GST_ELEMENT_NAME (element));
|
||||||
|
*seqnum = gst_message_get_seqnum (GST_MESSAGE_CAST (msgs->data));
|
||||||
} else {
|
} else {
|
||||||
GST_DEBUG ("sink '%s' did not post EOS yet",
|
GST_DEBUG ("sink '%s' did not post EOS yet",
|
||||||
GST_ELEMENT_NAME (element));
|
GST_ELEMENT_NAME (element));
|
||||||
|
@ -2392,6 +2397,7 @@ gst_bin_change_state_func (GstElement * element, GstStateChange transition)
|
||||||
GST_OBJECT_LOCK (bin);
|
GST_OBJECT_LOCK (bin);
|
||||||
GST_DEBUG_OBJECT (element, "clearing EOS elements");
|
GST_DEBUG_OBJECT (element, "clearing EOS elements");
|
||||||
bin_remove_messages (bin, NULL, GST_MESSAGE_EOS);
|
bin_remove_messages (bin, NULL, GST_MESSAGE_EOS);
|
||||||
|
bin->priv->posted_eos = FALSE;
|
||||||
GST_OBJECT_UNLOCK (bin);
|
GST_OBJECT_UNLOCK (bin);
|
||||||
if (current == GST_STATE_READY)
|
if (current == GST_STATE_READY)
|
||||||
if (!(gst_bin_src_pads_activate (bin, TRUE)))
|
if (!(gst_bin_src_pads_activate (bin, TRUE)))
|
||||||
|
@ -2586,6 +2592,8 @@ state_end:
|
||||||
gst_element_state_get_name (GST_STATE (element)),
|
gst_element_state_get_name (GST_STATE (element)),
|
||||||
gst_element_state_change_return_get_name (ret));
|
gst_element_state_change_return_get_name (ret));
|
||||||
|
|
||||||
|
bin_do_eos (bin);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
|
@ -2699,6 +2707,9 @@ gst_bin_continue_func (BinContinueData * data)
|
||||||
|
|
||||||
GST_STATE_UNLOCK (bin);
|
GST_STATE_UNLOCK (bin);
|
||||||
GST_DEBUG_OBJECT (bin, "state continue done");
|
GST_DEBUG_OBJECT (bin, "state continue done");
|
||||||
|
|
||||||
|
bin_do_eos (bin);
|
||||||
|
|
||||||
gst_object_unref (bin);
|
gst_object_unref (bin);
|
||||||
g_slice_free (BinContinueData, data);
|
g_slice_free (BinContinueData, data);
|
||||||
return;
|
return;
|
||||||
|
@ -2933,6 +2944,9 @@ bin_handle_async_done (GstBin * bin, GstStateChangeReturn ret,
|
||||||
gst_element_post_message (GST_ELEMENT_CAST (bin), amessage);
|
gst_element_post_message (GST_ELEMENT_CAST (bin), amessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!cont)
|
||||||
|
bin_do_eos (bin);
|
||||||
|
|
||||||
GST_OBJECT_LOCK (bin);
|
GST_OBJECT_LOCK (bin);
|
||||||
if (cont) {
|
if (cont) {
|
||||||
/* toplevel, start continue state */
|
/* toplevel, start continue state */
|
||||||
|
@ -2965,6 +2979,33 @@ nothing_pending:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bin_do_eos (GstBin * bin)
|
||||||
|
{
|
||||||
|
guint32 seqnum = 0;
|
||||||
|
gboolean eos;
|
||||||
|
|
||||||
|
GST_OBJECT_LOCK (bin);
|
||||||
|
/* If all sinks are EOS, we're in PLAYING and no state change is pending
|
||||||
|
* we forward the EOS message to the parent bin or application
|
||||||
|
*/
|
||||||
|
eos = GST_STATE (bin) == GST_STATE_PLAYING
|
||||||
|
&& GST_STATE_PENDING (bin) == GST_STATE_VOID_PENDING
|
||||||
|
&& is_eos (bin, &seqnum);
|
||||||
|
GST_OBJECT_UNLOCK (bin);
|
||||||
|
|
||||||
|
if (eos
|
||||||
|
&& g_atomic_int_compare_and_exchange (&bin->priv->posted_eos, FALSE,
|
||||||
|
TRUE)) {
|
||||||
|
GstMessage *tmessage;
|
||||||
|
tmessage = gst_message_new_eos (GST_OBJECT_CAST (bin));
|
||||||
|
gst_message_set_seqnum (tmessage, seqnum);
|
||||||
|
GST_DEBUG_OBJECT (bin,
|
||||||
|
"all sinks posted EOS, posting seqnum #%" G_GUINT32_FORMAT, seqnum);
|
||||||
|
gst_element_post_message (GST_ELEMENT_CAST (bin), tmessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* must be called with the object lock. This function releases the lock to post
|
/* must be called with the object lock. This function releases the lock to post
|
||||||
* the message. */
|
* the message. */
|
||||||
static void
|
static void
|
||||||
|
@ -3073,28 +3114,15 @@ gst_bin_handle_message_func (GstBin * bin, GstMessage * message)
|
||||||
}
|
}
|
||||||
case GST_MESSAGE_EOS:
|
case GST_MESSAGE_EOS:
|
||||||
{
|
{
|
||||||
gboolean eos;
|
|
||||||
|
|
||||||
/* collect all eos messages from the children */
|
/* collect all eos messages from the children */
|
||||||
GST_OBJECT_LOCK (bin);
|
GST_OBJECT_LOCK (bin);
|
||||||
bin_do_message_forward (bin, message);
|
bin_do_message_forward (bin, message);
|
||||||
/* ref message for future use */
|
/* ref message for future use */
|
||||||
gst_message_ref (message);
|
|
||||||
bin_replace_message (bin, message, GST_MESSAGE_EOS);
|
bin_replace_message (bin, message, GST_MESSAGE_EOS);
|
||||||
eos = is_eos (bin);
|
|
||||||
GST_OBJECT_UNLOCK (bin);
|
GST_OBJECT_UNLOCK (bin);
|
||||||
|
|
||||||
/* if we are completely EOS, we forward an EOS message */
|
bin_do_eos (bin);
|
||||||
if (eos) {
|
|
||||||
seqnum = gst_message_get_seqnum (message);
|
|
||||||
tmessage = gst_message_new_eos (GST_OBJECT_CAST (bin));
|
|
||||||
gst_message_set_seqnum (tmessage, seqnum);
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (bin,
|
|
||||||
"all sinks posted EOS, posting seqnum #%" G_GUINT32_FORMAT, seqnum);
|
|
||||||
gst_element_post_message (GST_ELEMENT_CAST (bin), tmessage);
|
|
||||||
}
|
|
||||||
gst_message_unref (message);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GST_MESSAGE_STATE_DIRTY:
|
case GST_MESSAGE_STATE_DIRTY:
|
||||||
|
|
Loading…
Reference in a new issue