* a toplevel bin */
#define BIN_IS_TOPLEVEL(bin) ((GST_OBJECT_PARENT (bin) == NULL) || bin->priv->asynchandling)
-#define GST_BIN_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BIN, GstBinPrivate))
-
struct _GstBinPrivate
{
gboolean asynchandling;
}
#define gst_bin_parent_class parent_class
-G_DEFINE_TYPE_WITH_CODE (GstBin, gst_bin, GST_TYPE_ELEMENT, _do_init);
+G_DEFINE_TYPE_WITH_CODE (GstBin, gst_bin, GST_TYPE_ELEMENT,
+ G_ADD_PRIVATE (GstBin)
+ _do_init);
static GObject *
gst_bin_child_proxy_get_child_by_index (GstChildProxy * child_proxy,
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
- g_type_class_add_private (klass, sizeof (GstBinPrivate));
-
gobject_class->set_property = gst_bin_set_property;
gobject_class->get_property = gst_bin_get_property;
/* Set up a bus for listening to child elements */
bus = g_object_new (GST_TYPE_BUS, "enable-async", FALSE, NULL);
+ gst_object_ref_sink (bus);
bin->child_bus = bus;
GST_DEBUG_OBJECT (bin, "using bus %" GST_PTR_FORMAT " to listen to children",
bus);
gst_bus_set_sync_handler (bus, (GstBusSyncHandler) bin_bus_handler, bin,
NULL);
- bin->priv = GST_BIN_GET_PRIVATE (bin);
+ bin->priv = gst_bin_get_instance_private (bin);
bin->priv->asynchandling = DEFAULT_ASYNC_HANDLING;
bin->priv->structure_cookie = 0;
bin->priv->message_forward = DEFAULT_MESSAGE_FORWARD;
s = (GstStructure *) gst_message_get_structure (msg);
gst_structure_get (s, "bin.old.context", GST_TYPE_CONTEXT, &context, NULL);
gst_structure_remove_field (s, "bin.old.context");
- gst_element_post_message (GST_ELEMENT_CAST (bin), msg);
+ /* Keep the msg around while we still need access to the context_type */
+ gst_element_post_message (GST_ELEMENT_CAST (bin), gst_message_ref (msg));
/* lock to avoid losing a potential write */
GST_OBJECT_LOCK (bin);
replacement =
gst_element_get_context_unlocked (GST_ELEMENT_CAST (bin), context_type);
+ gst_message_unref (msg);
if (replacement) {
/* we got the context set from GstElement::set_context */
GST_OBJECT_LOCK (bin);
g_warning ("Cannot add bin '%s' to itself", GST_ELEMENT_NAME (bin));
GST_OBJECT_UNLOCK (bin);
+ gst_object_ref_sink (element);
+ gst_object_unref (element);
return FALSE;
}
duplicate_name:
g_warning ("Element '%s' already has parent", elem_name);
GST_OBJECT_UNLOCK (bin);
g_free (elem_name);
- gst_object_ref_sink (element);
- gst_object_unref (element);
return FALSE;
}
}
GST_LOG_OBJECT (parent_bin, "emitting deep-element-added for element "
"%" GST_PTR_FORMAT " which has just been added to %" GST_PTR_FORMAT,
- sub_bin, child);
+ child, sub_bin);
g_signal_emit (parent_bin, gst_bin_signals[DEEP_ELEMENT_ADDED], 0, sub_bin,
child);
/**
* gst_bin_add:
* @bin: a #GstBin
- * @element: (transfer full): the #GstElement to add
+ * @element: (transfer floating): the #GstElement to add
*
* Adds the given element to the bin. Sets the element's parent, and thus
* takes ownership of the element. An element can only be added to one bin.
if (bit->best == NULL || bit->best_deg > degree) {
bit->best = element;
bit->best_deg = degree;
+ } else if (bit->best_deg == degree
+ && GST_OBJECT_FLAG_IS_SET (bit->best, GST_ELEMENT_FLAG_SOURCE)
+ && !GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_SOURCE)) {
+ /* If two elements have the same degree, we want to ensure we
+ * return non-source elements first. */
+ bit->best = element;
}
}
do_state:
GST_OBJECT_LOCK (bin);
/* the element was busy with an upwards async state change, we must wait for
- * an ASYNC_DONE message before we attemp to change the state. */
+ * an ASYNC_DONE message before we attempt to change the state. */
if ((found =
find_message (bin, GST_OBJECT_CAST (element),
GST_MESSAGE_ASYNC_START))) {
/* check if all elements managed to commit their state already */
if (!find_message (bin, NULL, GST_MESSAGE_ASYNC_START)) {
/* nothing found, remove all old ASYNC_DONE messages. This can happen when
- * all the elements commited their state while we were doing the state
+ * all the elements committed their state while we were doing the state
* change. We will still return ASYNC for consistency but we commit the
* state already so that a _get_state() will return immediately. */
bin_remove_messages (bin, NULL, GST_MESSAGE_ASYNC_DONE);
- GST_DEBUG_OBJECT (bin, "async elements commited");
+ GST_DEBUG_OBJECT (bin, "async elements committed");
bin_handle_async_done (bin, GST_STATE_CHANGE_SUCCESS, FALSE,
GST_CLOCK_TIME_NONE);
}
static void
bin_do_eos (GstBin * bin)
{
- guint32 seqnum = 0;
+ guint32 seqnum = GST_SEQNUM_INVALID;
gboolean eos;
GST_OBJECT_LOCK (bin);
/* If all sinks are EOS, we're in PLAYING and no state change is pending
- * (or we're doing playing to playing and noone else will trigger posting
+ * (or we're doing playing to playing and no one else will trigger posting
* EOS for us) we forward the EOS message to the parent bin or application
*/
eos = GST_STATE (bin) == GST_STATE_PLAYING
GST_OBJECT_UNLOCK (bin);
tmessage = gst_message_new_eos (GST_OBJECT_CAST (bin));
- gst_message_set_seqnum (tmessage, seqnum);
+ if (seqnum != GST_SEQNUM_INVALID)
+ 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);
static void
bin_do_stream_start (GstBin * bin)
{
- guint32 seqnum = 0;
+ guint32 seqnum = GST_SEQNUM_INVALID;
gboolean stream_start;
gboolean have_group_id = FALSE;
guint group_id = 0;
GST_OBJECT_UNLOCK (bin);
tmessage = gst_message_new_stream_start (GST_OBJECT_CAST (bin));
- gst_message_set_seqnum (tmessage, seqnum);
+ if (seqnum != GST_SEQNUM_INVALID)
+ gst_message_set_seqnum (tmessage, seqnum);
if (have_group_id)
gst_message_set_group_id (tmessage, group_id);
/* nothing found, remove all old ASYNC_DONE messages */
bin_remove_messages (bin, NULL, GST_MESSAGE_ASYNC_DONE);
- GST_DEBUG_OBJECT (bin, "async elements commited");
+ GST_DEBUG_OBJECT (bin, "async elements committed");
/* when we get an async done message when a state change was busy, we
* 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
*
* MT safe. Caller owns returned reference.
*
- * Returns: (transfer full): A #GstElement inside the bin implementing the interface
+ * Returns: (transfer full) (nullable): A #GstElement inside the bin
+ * implementing the interface
*/
GstElement *
gst_bin_get_by_interface (GstBin * bin, GType iface)