mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-24 02:31:03 +00:00
gst/playback/gstdecodebin.c: Implement support for dynamic pad changing. We listen to "live" pad removals (i.e. while...
Original commit message from CVS: * gst/playback/gstdecodebin.c: (gst_decode_bin_class_init), (get_unconnected_element), (remove_starting_from), (pad_removed), (close_link): Implement support for dynamic pad changing. We listen to "live" pad removals (i.e. while playing) and re-setup autoplugging after that. Playbasebin/playbin need some more work for this to finally work, but decodebin supports (and replugs) chained ogg now.
This commit is contained in:
parent
4cf67a0834
commit
abd34577da
2 changed files with 127 additions and 0 deletions
11
ChangeLog
11
ChangeLog
|
@ -1,3 +1,14 @@
|
||||||
|
2004-11-01 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
|
||||||
|
|
||||||
|
* gst/playback/gstdecodebin.c: (gst_decode_bin_class_init),
|
||||||
|
(get_unconnected_element), (remove_starting_from), (pad_removed),
|
||||||
|
(close_link):
|
||||||
|
Implement support for dynamic pad changing. We listen to "live"
|
||||||
|
pad removals (i.e. while playing) and re-setup autoplugging
|
||||||
|
after that. Playbasebin/playbin need some more work for this
|
||||||
|
to finally work, but decodebin supports (and replugs) chained
|
||||||
|
ogg now.
|
||||||
|
|
||||||
2004-11-02 Jan Schmidt <thaytan@mad.scientist.com>
|
2004-11-02 Jan Schmidt <thaytan@mad.scientist.com>
|
||||||
* ext/alsa/gstalsa.c: (gst_alsa_class_init), (gst_alsa_dispose),
|
* ext/alsa/gstalsa.c: (gst_alsa_class_init), (gst_alsa_dispose),
|
||||||
(gst_alsa_finalize):
|
(gst_alsa_finalize):
|
||||||
|
|
|
@ -76,6 +76,8 @@ struct _GstDecodeBinClass
|
||||||
void (*new_decoded_pad) (GstElement * element, GstPad * pad, gboolean last);
|
void (*new_decoded_pad) (GstElement * element, GstPad * pad, gboolean last);
|
||||||
/* signal fired when we found a pad that we cannot decode */
|
/* signal fired when we found a pad that we cannot decode */
|
||||||
void (*unknown_type) (GstElement * element, GstPad * pad, GstCaps * caps);
|
void (*unknown_type) (GstElement * element, GstPad * pad, GstCaps * caps);
|
||||||
|
/* called on dynamic pad removal */
|
||||||
|
void (*removed_decoded_pad) (GstElement * element, GstPad * pad);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* props */
|
/* props */
|
||||||
|
@ -90,6 +92,7 @@ enum
|
||||||
{
|
{
|
||||||
SIGNAL_NEW_DECODED_PAD,
|
SIGNAL_NEW_DECODED_PAD,
|
||||||
SIGNAL_UNKNOWN_TYPE,
|
SIGNAL_UNKNOWN_TYPE,
|
||||||
|
SIGNAL_REMOVED_DECODED_PAD,
|
||||||
LAST_SIGNAL
|
LAST_SIGNAL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -191,6 +194,11 @@ gst_decode_bin_class_init (GstDecodeBinClass * klass)
|
||||||
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, unknown_type),
|
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, unknown_type),
|
||||||
NULL, NULL, gst_marshal_VOID__OBJECT_BOXED, G_TYPE_NONE, 2,
|
NULL, NULL, gst_marshal_VOID__OBJECT_BOXED, G_TYPE_NONE, 2,
|
||||||
GST_TYPE_PAD, GST_TYPE_CAPS);
|
GST_TYPE_PAD, GST_TYPE_CAPS);
|
||||||
|
gst_decode_bin_signals[SIGNAL_REMOVED_DECODED_PAD] =
|
||||||
|
g_signal_new ("removed-decoded-pad", G_TYPE_FROM_CLASS (klass),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (GstDecodeBinClass, removed_decoded_pad), NULL, NULL,
|
||||||
|
g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_PAD);
|
||||||
|
|
||||||
gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_decode_bin_dispose);
|
gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_decode_bin_dispose);
|
||||||
|
|
||||||
|
@ -550,6 +558,110 @@ no_more_pads (GstElement * element, GstDynamic * dynamic)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* get unconnected element (after unlink/pad-remove). */
|
||||||
|
static GstElement *
|
||||||
|
get_unconnected_element (GstDecodeBin * decode_bin)
|
||||||
|
{
|
||||||
|
const GList *walk;
|
||||||
|
|
||||||
|
for (walk = gst_bin_get_list (GST_BIN (decode_bin));
|
||||||
|
walk != NULL; walk = walk->next) {
|
||||||
|
GstElement *element = walk->data;
|
||||||
|
const GList *pwalk;
|
||||||
|
|
||||||
|
for (pwalk = gst_element_get_pad_list (GST_ELEMENT (element));
|
||||||
|
pwalk != NULL; pwalk = pwalk->next) {
|
||||||
|
GstPad *pad = pwalk->data;
|
||||||
|
|
||||||
|
if (GST_PAD_IS_SINK (pad) && GST_PAD_PEER (pad) == NULL)
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove all elements linked forward from this element on from the bin */
|
||||||
|
static void
|
||||||
|
remove_starting_from (GstDecodeBin * decode_bin, GstElement * start)
|
||||||
|
{
|
||||||
|
const GList *pwalk;
|
||||||
|
|
||||||
|
for (pwalk = gst_element_get_pad_list (start);
|
||||||
|
pwalk != NULL; pwalk = pwalk->next) {
|
||||||
|
GstPad *pad = pwalk->data;
|
||||||
|
|
||||||
|
if (GST_PAD_IS_SRC (pad)) {
|
||||||
|
GstPad *peer = GST_PAD_PEER (pad);
|
||||||
|
GstElement *peer_parent = NULL;
|
||||||
|
|
||||||
|
if (peer)
|
||||||
|
peer_parent = gst_pad_get_parent (peer);
|
||||||
|
|
||||||
|
/* be recursive */
|
||||||
|
if (peer_parent != NULL) {
|
||||||
|
if (gst_object_get_parent (GST_OBJECT (peer_parent))
|
||||||
|
== GST_OBJECT (decode_bin)) {
|
||||||
|
remove_starting_from (decode_bin, peer_parent);
|
||||||
|
} else {
|
||||||
|
/* linked outside us - signal pad removal */
|
||||||
|
g_signal_emit (decode_bin,
|
||||||
|
gst_decode_bin_signals[SIGNAL_REMOVED_DECODED_PAD], 0, pad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now remove ourselves */
|
||||||
|
gst_bin_remove (GST_BIN (decode_bin), start);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This function will be called for elements with dynamic elements when
|
||||||
|
* they remove pads. This might just be because they're disposed, in
|
||||||
|
* which case we don't care. It might also be because they're changing
|
||||||
|
* chain, in which case we want to re-plug afterwards. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
pad_removed (GstElement * element, GstPad * pad, GstDecodeBin * decode_bin)
|
||||||
|
{
|
||||||
|
GList *walk;
|
||||||
|
GstElement *peer;
|
||||||
|
GstDynamic *dyn;
|
||||||
|
|
||||||
|
/* don't care about disposal - it's really only for replugging.
|
||||||
|
* We only need to check for pending is ready because if pending
|
||||||
|
* is NULL, then state is READY. */
|
||||||
|
if (GST_STATE (element) <= GST_STATE_READY ||
|
||||||
|
GST_STATE_PENDING (element) == GST_STATE_READY)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* clean up. FIXME: getting peer of removed pad is dirty. */
|
||||||
|
peer = get_unconnected_element (decode_bin);
|
||||||
|
g_assert (peer);
|
||||||
|
remove_starting_from (decode_bin, peer);
|
||||||
|
|
||||||
|
/* if an element removes two pads, then we don't want this twice */
|
||||||
|
for (walk = decode_bin->dynamics; walk != NULL; walk = walk->next) {
|
||||||
|
dyn = walk->data;
|
||||||
|
if (dyn->element == element)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (decode_bin, "pad removal while alive - chained?");
|
||||||
|
|
||||||
|
/* re-setup dynamic plugging */
|
||||||
|
dyn = g_new0 (GstDynamic, 1);
|
||||||
|
dyn->np_sig_id = g_signal_connect (G_OBJECT (element), "new-pad",
|
||||||
|
G_CALLBACK (new_pad), dyn);
|
||||||
|
dyn->nmp_sig_id = g_signal_connect (G_OBJECT (element), "no-more-pads",
|
||||||
|
G_CALLBACK (no_more_pads), dyn);
|
||||||
|
dyn->element = element;
|
||||||
|
dyn->decode_bin = decode_bin;
|
||||||
|
|
||||||
|
/* and add this element to the dynamic elements */
|
||||||
|
decode_bin->dynamics = g_list_prepend (decode_bin->dynamics, dyn);
|
||||||
|
}
|
||||||
|
|
||||||
/* this function inspects the given element and tries to connect something
|
/* this function inspects the given element and tries to connect something
|
||||||
* on the srcpads. If there are dynamic pads, it sets up a signal handler to
|
* on the srcpads. If there are dynamic pads, it sets up a signal handler to
|
||||||
* continue autoplugging when they become available */
|
* continue autoplugging when they become available */
|
||||||
|
@ -639,6 +751,10 @@ close_link (GstElement * element, GstDecodeBin * decode_bin)
|
||||||
|
|
||||||
/* and add this element to the dynamic elements */
|
/* and add this element to the dynamic elements */
|
||||||
decode_bin->dynamics = g_list_prepend (decode_bin->dynamics, dyn);
|
decode_bin->dynamics = g_list_prepend (decode_bin->dynamics, dyn);
|
||||||
|
|
||||||
|
/* let's keep this one around longer than the lifetime of dynamicity */
|
||||||
|
g_signal_connect (G_OBJECT (element), "pad-removed",
|
||||||
|
G_CALLBACK (pad_removed), decode_bin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if this is an element with more than 1 pad. If this element
|
/* Check if this is an element with more than 1 pad. If this element
|
||||||
|
|
Loading…
Reference in a new issue