decodebin2: Post a element message on the bus with the stream topology

Fixes bug #598533.
This commit is contained in:
Sebastian Dröge 2009-10-15 13:13:43 +02:00
parent 50fdbcd9ea
commit efcca84bac

View file

@ -2447,6 +2447,128 @@ sort_end_pads (GstDecodePad * da, GstDecodePad * db)
return va - vb; return va - vb;
} }
static GstCaps *
_gst_element_get_linked_caps (GstElement * src, GstElement * sink)
{
GstIterator *it;
GstElement *parent;
GstPad *pad, *peer;
gboolean done = FALSE;
GstCaps *caps = NULL;
it = gst_element_iterate_src_pads (src);
while (!done) {
switch (gst_iterator_next (it, (gpointer) & pad)) {
case GST_ITERATOR_OK:
peer = gst_pad_get_peer (pad);
if (peer) {
parent = gst_pad_get_parent_element (peer);
if (parent == sink) {
caps = gst_pad_get_negotiated_caps (pad);
done = TRUE;
}
if (parent)
gst_object_unref (parent);
gst_object_unref (peer);
}
gst_object_unref (pad);
break;
case GST_ITERATOR_RESYNC:
gst_iterator_resync (it);
break;
case GST_ITERATOR_ERROR:
case GST_ITERATOR_DONE:
done = TRUE;
break;
}
}
gst_iterator_free (it);
return caps;
}
static GQuark topology_structure_name = 0;
static GQuark topology_caps = 0;
static GQuark topology_next = 0;
static GQuark topology_pad = 0;
/* FIXME: Invent gst_structure_take_structure() to prevent all the
* structure copying for nothing
*/
static GstStructure *
gst_decode_chain_get_topology (GstDecodeChain * chain)
{
GstStructure *s, *u;
GList *l;
GstCaps *caps;
u = gst_structure_id_empty_new (topology_structure_name);
/* Now at the last element */
if (chain->elements && (chain->endpad || chain->deadend)) {
s = gst_structure_id_empty_new (topology_structure_name);
gst_structure_id_set (u, topology_caps, GST_TYPE_CAPS, chain->endcaps,
NULL);
if (chain->endpad)
gst_structure_id_set (u, topology_pad, GST_TYPE_PAD, chain->endpad, NULL);
gst_structure_id_set (s, topology_next, GST_TYPE_STRUCTURE, u, NULL);
gst_structure_free (u);
u = s;
} else if (chain->active_group) {
GValue list = { 0, };
GValue item = { 0, };
g_value_init (&list, GST_TYPE_LIST);
g_value_init (&item, GST_TYPE_STRUCTURE);
for (l = chain->active_group->children; l; l = l->next) {
s = gst_decode_chain_get_topology (l->data);
gst_value_set_structure (&item, s);
gst_value_list_append_value (&list, &item);
g_value_reset (&item);
gst_structure_free (s);
}
gst_structure_id_set_value (u, topology_next, &list);
g_value_unset (&list);
g_value_unset (&item);
}
/* Get caps between all elements in this chain */
l = (chain->elements && chain->elements->next) ? chain->elements->next : NULL;
for (; l && l->next; l = l->next) {
GstCaps *caps = _gst_element_get_linked_caps (l->next->data, l->data);
s = gst_structure_id_empty_new (topology_structure_name);
gst_structure_id_set (u, topology_caps, GST_TYPE_CAPS, caps, NULL);
gst_caps_unref (caps);
gst_structure_id_set (s, topology_next, GST_TYPE_STRUCTURE, u, NULL);
gst_structure_free (u);
u = s;
}
/* Caps that resulted in this chain */
caps = gst_pad_get_negotiated_caps (chain->pad);
gst_structure_set (u, "caps", GST_TYPE_CAPS, caps, NULL);
gst_caps_unref (caps);
return u;
}
static void
gst_decode_bin_post_topology_message (GstDecodeBin * dbin)
{
GstStructure *s;
GstMessage *msg;
s = gst_decode_chain_get_topology (dbin->decode_chain);
msg = gst_message_new_element (GST_OBJECT (dbin), s);
gst_element_post_message (GST_ELEMENT (dbin), msg);
}
/* Must only be called if the toplevel chain is complete and blocked! */ /* Must only be called if the toplevel chain is complete and blocked! */
/* Not MT-safe, call with decodebin expose lock! */ /* Not MT-safe, call with decodebin expose lock! */
static gboolean static gboolean
@ -2528,12 +2650,15 @@ gst_decode_bin_expose (GstDecodeBin * dbin)
GST_DEBUG_OBJECT (dbin, "emitted new-decoded-pad"); GST_DEBUG_OBJECT (dbin, "emitted new-decoded-pad");
} }
/* signal no-more-pads. This allows the application to hook stuff to the /* 4. Signal no-more-pads. This allows the application to hook stuff to the
* exposed pads */ * exposed pads */
GST_LOG_OBJECT (dbin, "signalling no-more-pads"); GST_LOG_OBJECT (dbin, "signalling no-more-pads");
gst_element_no_more_pads (GST_ELEMENT (dbin)); gst_element_no_more_pads (GST_ELEMENT (dbin));
/* 4. Unblock internal pads. The application should have connected stuff now /* 5. Send a custom element message with the stream topology */
gst_decode_bin_post_topology_message (dbin);
/* 6. Unblock internal pads. The application should have connected stuff now
* so that streaming can continue. */ * so that streaming can continue. */
for (tmp = endpads; tmp; tmp = tmp->next) { for (tmp = endpads; tmp; tmp = tmp->next) {
GstDecodePad *dpad = (GstDecodePad *) tmp->data; GstDecodePad *dpad = (GstDecodePad *) tmp->data;
@ -2913,6 +3038,12 @@ gst_decode_bin_plugin_init (GstPlugin * plugin)
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
#endif /* ENABLE_NLS */ #endif /* ENABLE_NLS */
/* Register some quarks here for the stream topology message */
topology_structure_name = g_quark_from_static_string ("stream-topology");
topology_caps = g_quark_from_static_string ("caps");
topology_next = g_quark_from_static_string ("next");
topology_pad = g_quark_from_static_string ("pad");
return gst_element_register (plugin, "decodebin2", GST_RANK_NONE, return gst_element_register (plugin, "decodebin2", GST_RANK_NONE,
GST_TYPE_DECODE_BIN); GST_TYPE_DECODE_BIN);
} }