gst/playback/gstdecodebin2.c: Remove fakesink hack, we can now implement this more elegantly.

Original commit message from CVS:
* gst/playback/gstdecodebin2.c: (gst_decode_bin_class_init),
(gst_decode_bin_init), (gst_decode_bin_dispose),
(gst_decode_bin_set_sink_caps), (gst_decode_bin_get_sink_caps),
(gst_decode_bin_set_property), (gst_decode_bin_get_property),
(analyze_new_pad), (connect_pad), (expose_pad),
(gst_decode_group_new), (gst_decode_group_control_demuxer_pad),
(gst_decode_group_expose), (gst_decode_group_free),
(do_async_start), (do_async_done), (gst_decode_bin_change_state):
Remove fakesink hack, we can now implement this more elegantly.
Added property to bypass typefinding.
Removed underrun callback and demuxer pad probe, we now use the srcpad
probe to expose groups.
API::sink-caps property
* gst/playback/gstplaybin2.c: (no_more_pads_cb):
Guard against multiple emissions of the no_more_pads signal, which
happens when we are dealing with chained oggs.
* gst/playback/gsturidecodebin.c: (remove_decoders),
(make_decoder), (type_found), (setup_streaming), (source_new_pad),
(setup_source):
For streams, use our own typefind element and plug our queue after it.
We will need this to determine the type of buffering to use for the
queue soon.
This commit is contained in:
Wim Taymans 2008-04-03 12:16:04 +00:00
parent ce67ac6373
commit c98a370f8c
4 changed files with 271 additions and 202 deletions

View file

@ -1,3 +1,30 @@
2008-04-03 Wim Taymans <wim.taymans@collabora.co.uk>
* gst/playback/gstdecodebin2.c: (gst_decode_bin_class_init),
(gst_decode_bin_init), (gst_decode_bin_dispose),
(gst_decode_bin_set_sink_caps), (gst_decode_bin_get_sink_caps),
(gst_decode_bin_set_property), (gst_decode_bin_get_property),
(analyze_new_pad), (connect_pad), (expose_pad),
(gst_decode_group_new), (gst_decode_group_control_demuxer_pad),
(gst_decode_group_expose), (gst_decode_group_free),
(do_async_start), (do_async_done), (gst_decode_bin_change_state):
Remove fakesink hack, we can now implement this more elegantly.
Added property to bypass typefinding.
Removed underrun callback and demuxer pad probe, we now use the srcpad
probe to expose groups.
API::sink-caps property
* gst/playback/gstplaybin2.c: (no_more_pads_cb):
Guard against multiple emissions of the no_more_pads signal, which
happens when we are dealing with chained oggs.
* gst/playback/gsturidecodebin.c: (remove_decoders),
(make_decoder), (type_found), (setup_streaming), (source_new_pad),
(setup_source):
For streams, use our own typefind element and plug our queue after it.
We will need this to determine the type of buffering to use for the
queue soon.
2008-04-03 Wim Taymans <wim.taymans@collabora.co.uk>
* gst-libs/gst/audio/gstbaseaudiosink.c:

View file

@ -89,7 +89,6 @@ struct _GstDecodeBin
gchar *encoding; /* encoding of subtitles */
GstElement *typefind; /* this holds the typefind object */
GstElement *fakesink;
GMutex *lock; /* Protects activegroup and groups */
GstDecodeGroup *activegroup; /* group currently active */
@ -104,6 +103,8 @@ struct _GstDecodeBin
gboolean have_type; /* if we received the have_type signal */
guint have_type_id; /* signal id for have-type from typefind */
gboolean async_pending; /* async-start has been emited */
};
struct _GstDecodeBinClass
@ -153,7 +154,9 @@ enum
{
PROP_0,
PROP_CAPS,
PROP_SUBTITLE_ENCODING
PROP_SUBTITLE_ENCODING,
PROP_SINK_CAPS,
PROP_LAST
};
static GstBinClass *parent_class;
@ -166,8 +169,8 @@ GST_ELEMENT_DETAILS ("Decoder Bin",
"Edward Hervey <edward@fluendo.com>");
static gboolean add_fakesink (GstDecodeBin * decode_bin);
static void remove_fakesink (GstDecodeBin * decode_bin);
static void do_async_start (GstDecodeBin * dbin);
static void do_async_done (GstDecodeBin * dbin);
static void type_found (GstElement * typefind, guint probability,
GstCaps * caps, GstDecodeBin * decode_bin);
@ -229,7 +232,6 @@ struct _GstDecodeGroup
gboolean complete; /* TRUE if we are not expecting anymore streams
* on this group */
gulong overrunsig;
gulong underrunsig;
guint nbdynamic; /* number of dynamic pads in the group. */
GList *endpads; /* List of GstDecodePad of source pads to be exposed */
@ -542,6 +544,11 @@ gst_decode_bin_class_init (GstDecodeBinClass * klass)
"ISO-8859-15 will be assumed.", NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_klass, PROP_SINK_CAPS,
g_param_spec_boxed ("sink-caps", "Sink Caps",
"The caps of the input data. (NULL = use typefind element)",
GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
klass->autoplug_continue =
GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_continue);
klass->autoplug_factories =
@ -606,10 +613,6 @@ gst_decode_bin_init (GstDecodeBin * decode_bin)
decode_bin->caps =
gst_caps_from_string ("video/x-raw-yuv;video/x-raw-rgb;video/x-raw-gray;"
"audio/x-raw-int;audio/x-raw-float;" "text/plain;text/x-pango-markup");
add_fakesink (decode_bin);
/* FILLME */
}
static void
@ -653,8 +656,6 @@ gst_decode_bin_dispose (GObject * object)
g_free (decode_bin->encoding);
decode_bin->encoding = NULL;
remove_fakesink (decode_bin);
g_list_free (decode_bin->subtitles);
decode_bin->subtitles = NULL;
@ -721,6 +722,26 @@ gst_decode_bin_get_caps (GstDecodeBin * dbin)
return caps;
}
static void
gst_decode_bin_set_sink_caps (GstDecodeBin * dbin, GstCaps * caps)
{
GST_DEBUG_OBJECT (dbin, "Setting new caps: %" GST_PTR_FORMAT, caps);
g_object_set (dbin->typefind, "force-caps", caps, NULL);
}
static GstCaps *
gst_decode_bin_get_sink_caps (GstDecodeBin * dbin)
{
GstCaps *caps;
GST_DEBUG_OBJECT (dbin, "Getting currently set caps");
g_object_get (dbin->typefind, "force-caps", &caps, NULL);
return caps;
}
static void
gst_decode_bin_set_subs_encoding (GstDecodeBin * dbin, const gchar * encoding)
{
@ -771,6 +792,9 @@ gst_decode_bin_set_property (GObject * object, guint prop_id,
case PROP_SUBTITLE_ENCODING:
gst_decode_bin_set_subs_encoding (dbin, g_value_get_string (value));
break;
case PROP_SINK_CAPS:
gst_decode_bin_set_sink_caps (dbin, g_value_get_boxed (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -791,6 +815,9 @@ gst_decode_bin_get_property (GObject * object, guint prop_id,
case PROP_SUBTITLE_ENCODING:
g_value_take_string (value, gst_decode_bin_get_subs_encoding (dbin));
break;
case PROP_SINK_CAPS:
g_value_take_boxed (value, gst_decode_bin_get_sink_caps (dbin));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -968,9 +995,10 @@ unknown_type:
g_signal_emit (G_OBJECT (dbin),
gst_decode_bin_signals[SIGNAL_UNKNOWN_TYPE], 0, pad, caps);
/* Check if there are no pending groups, if so, remove fakesink */
if (dbin->groups == NULL)
remove_fakesink (dbin);
/* Check if there are no pending groups, if so, commit our state */
if (dbin->groups == NULL) {
do_async_done (dbin);
}
if (src == dbin->typefind) {
gchar *desc;
@ -1045,6 +1073,7 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
if (!(group = get_current_group (dbin))) {
group = gst_decode_group_new (dbin, TRUE);
DECODE_BIN_LOCK (dbin);
GST_LOG_OBJECT (dbin, "added group %p", group);
dbin->groups = g_list_append (dbin->groups, group);
DECODE_BIN_UNLOCK (dbin);
}
@ -1316,6 +1345,7 @@ expose_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
if (!(group = get_current_group (dbin))) {
group = gst_decode_group_new (dbin, isdemux);
DECODE_BIN_LOCK (dbin);
GST_LOG_OBJECT (dbin, "added group %p", group);
dbin->groups = g_list_append (dbin->groups, group);
DECODE_BIN_UNLOCK (dbin);
newgroup = TRUE;
@ -1579,26 +1609,6 @@ multi_queue_overrun_cb (GstElement * queue, GstDecodeGroup * group)
DECODE_BIN_UNLOCK (group->dbin);
}
static void
multi_queue_underrun_cb (GstElement * queue, GstDecodeGroup * group)
{
GstDecodeBin *dbin = group->dbin;
GST_LOG_OBJECT (dbin, "multiqueue is empty for group %p", group);
/* Check if we need to activate another group */
DECODE_BIN_LOCK (dbin);
if ((group == dbin->activegroup) && dbin->groups) {
GST_DEBUG_OBJECT (dbin, "Switching to new group");
/* unexpose current active */
gst_decode_group_hide (group);
/* expose first group of groups */
gst_decode_group_expose ((GstDecodeGroup *) dbin->groups->data);
}
DECODE_BIN_UNLOCK (dbin);
}
/* gst_decode_group_new
*
* Creates a new GstDecodeGroup. It is up to the caller to add it to the list
@ -1643,10 +1653,6 @@ gst_decode_group_new (GstDecodeBin * dbin, gboolean use_queue)
/* will expose the group */
group->overrunsig = g_signal_connect (G_OBJECT (mq), "overrun",
G_CALLBACK (multi_queue_overrun_cb), group);
/* will hide the group again, this is usually called when the multiqueue is
* drained because of EOS. */
group->underrunsig = g_signal_connect (G_OBJECT (mq), "underrun",
G_CALLBACK (multi_queue_underrun_cb), group);
gst_bin_add (GST_BIN (dbin), mq);
gst_element_set_state (mq, GST_STATE_PAUSED);
@ -1687,20 +1693,6 @@ get_current_group (GstDecodeBin * dbin)
return group;
}
static gboolean
group_demuxer_event_probe (GstPad * pad, GstEvent * event,
GstDecodeGroup * group)
{
if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
GST_DEBUG_OBJECT (group->dbin,
"Got EOS on group input pads, exposing group if it wasn't before");
DECODE_BIN_LOCK (group->dbin);
gst_decode_group_expose (group);
DECODE_BIN_UNLOCK (group->dbin);
}
return TRUE;
}
/* gst_decode_group_control_demuxer_pad
*
* Adds a new demuxer srcpad to the given group.
@ -1742,9 +1734,6 @@ gst_decode_group_control_demuxer_pad (GstDecodeGroup * group, GstPad * pad)
goto chiringuito;
}
/* connect event handler on pad to intercept EOS events */
gst_pad_add_event_probe (pad, G_CALLBACK (group_demuxer_event_probe), group);
chiringuito:
g_free (srcname);
GROUP_MUTEX_UNLOCK (group);
@ -1939,22 +1928,11 @@ gst_decode_group_expose (GstDecodeGroup * group)
{
GList *tmp;
GList *next = NULL;
GstDecodeBin *dbin;
if (group->dbin->activegroup) {
GST_DEBUG_OBJECT (group->dbin, "A group is already active and exposed");
return TRUE;
}
dbin = group->dbin;
if (group->dbin->activegroup == group) {
GST_WARNING ("Group %p is already exposed", group);
return TRUE;
}
if (!group->dbin->groups
|| (group != (GstDecodeGroup *) group->dbin->groups->data)) {
GST_WARNING ("Group %p is not the first group to expose", group);
return FALSE;
}
GST_DEBUG_OBJECT (dbin, "going to expose group %p", group);
if (group->nbdynamic) {
GST_WARNING ("Group %p still has %d dynamic objects, not exposing yet",
@ -1962,7 +1940,10 @@ gst_decode_group_expose (GstDecodeGroup * group)
return FALSE;
}
GST_LOG ("Exposing group %p", group);
if (dbin->activegroup == group) {
GST_DEBUG_OBJECT (dbin, "Group %p is already exposed, all is fine", group);
return TRUE;
}
if (group->multiqueue) {
/* update runtime limits. At runtime, we try to keep the amount of buffers
@ -1979,6 +1960,21 @@ gst_decode_group_expose (GstDecodeGroup * group)
}
}
if (dbin->activegroup) {
GST_DEBUG_OBJECT (dbin,
"another group %p is already exposed, waiting for EOS",
dbin->activegroup);
return TRUE;
}
if (!dbin->groups || (group != (GstDecodeGroup *) dbin->groups->data)) {
GST_WARNING ("Group %p is not the first group to expose", group);
return FALSE;
}
GST_LOG ("Exposing group %p", group);
/* re-order pads : video, then audio, then others */
group->endpads = g_list_sort (group->endpads, (GCompareFunc) sort_end_pads);
@ -1992,31 +1988,31 @@ gst_decode_group_expose (GstDecodeGroup * group)
next = g_list_next (tmp);
/* 1. ghost pad */
padname = g_strdup_printf ("src%d", group->dbin->nbpads);
group->dbin->nbpads++;
padname = g_strdup_printf ("src%d", dbin->nbpads);
dbin->nbpads++;
GST_LOG_OBJECT (group->dbin, "About to expose pad %s:%s",
GST_LOG_OBJECT (dbin, "About to expose pad %s:%s",
GST_DEBUG_PAD_NAME (dpad->pad));
ghost = gst_ghost_pad_new (padname, dpad->pad);
gst_pad_set_active (ghost, TRUE);
gst_element_add_pad (GST_ELEMENT (group->dbin), ghost);
gst_element_add_pad (GST_ELEMENT (dbin), ghost);
group->ghosts = g_list_append (group->ghosts, ghost);
g_free (padname);
/* 2. emit signal */
GST_DEBUG_OBJECT (group->dbin, "emitting new-decoded-pad");
g_signal_emit (G_OBJECT (group->dbin),
GST_DEBUG_OBJECT (dbin, "emitting new-decoded-pad");
g_signal_emit (G_OBJECT (dbin),
gst_decode_bin_signals[SIGNAL_NEW_DECODED_PAD], 0, ghost,
(next == NULL));
GST_DEBUG_OBJECT (group->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
* exposed pads */
GST_LOG_OBJECT (group->dbin, "signalling no-more-pads");
gst_element_no_more_pads (GST_ELEMENT (group->dbin));
GST_LOG_OBJECT (dbin, "signalling no-more-pads");
gst_element_no_more_pads (GST_ELEMENT (dbin));
/* 3. Unblock internal pads. The application should have connected stuff now
* so that streaming can continue. */
@ -2031,17 +2027,21 @@ gst_decode_group_expose (GstDecodeGroup * group)
GST_DEBUG_OBJECT (dpad->pad, "unblocked");
}
group->dbin->activegroup = group;
dbin->activegroup = group;
/* pop off the first group */
group->dbin->groups =
g_list_delete_link (group->dbin->groups, group->dbin->groups);
if (dbin->groups && dbin->groups->data) {
GST_LOG_OBJECT (dbin, "removed group %p", dbin->groups->data);
dbin->groups = g_list_delete_link (dbin->groups, dbin->groups);
} else {
GST_LOG_OBJECT (dbin, "no more groups");
}
remove_fakesink (group->dbin);
do_async_done (dbin);
group->exposed = TRUE;
GST_LOG_OBJECT (group->dbin, "Group %p exposed", group);
GST_LOG_OBJECT (dbin, "Group %p exposed", group);
return TRUE;
}
@ -2178,8 +2178,6 @@ gst_decode_group_free (GstDecodeGroup * group)
/* disconnect signal handlers on multiqueue */
if (group->multiqueue) {
if (group->underrunsig)
g_signal_handler_disconnect (group->multiqueue, group->underrunsig);
if (group->overrunsig)
g_signal_handler_disconnect (group->multiqueue, group->overrunsig);
deactivate_free_recursive (group, group->multiqueue);
@ -2281,73 +2279,28 @@ gst_decode_pad_new (GstDecodeGroup * group, GstPad * pad, gboolean block)
* Element add/remove
*****/
/*
* add_fakesink / remove_fakesink
*
* We use a sink so that the parent ::change_state returns GST_STATE_CHANGE_ASYNC
* when that sink is present (since it's not connected to anything it will
* always return GST_STATE_CHANGE_ASYNC).
*
* But this is an ugly way of achieving this goal.
* Ideally, we shouldn't use a sink and just return GST_STATE_CHANGE_ASYNC in
* our ::change_state if we have not exposed the active group.
* We also need to override ::get_state to fake the asynchronous behaviour.
* Once the active group is exposed, we would then post a
* GST_MESSAGE_STATE_DIRTY and return GST_STATE_CHANGE_SUCCESS (which will call
* ::get_state .
*/
static gboolean
add_fakesink (GstDecodeBin * decode_bin)
static void
do_async_start (GstDecodeBin * dbin)
{
GST_DEBUG_OBJECT (decode_bin, "Adding the fakesink");
GstMessage *message;
if (decode_bin->fakesink)
return TRUE;
dbin->async_pending = TRUE;
decode_bin->fakesink =
gst_element_factory_make ("fakesink", "async-fakesink");
if (!decode_bin->fakesink)
goto no_fakesink;
/* enable sync so that we force ASYNC preroll */
g_object_set (G_OBJECT (decode_bin->fakesink), "sync", TRUE, NULL);
/* hacky, remove sink flag, we don't want our decodebin to become a sink
* just because we add a fakesink element to make us ASYNC */
GST_OBJECT_FLAG_UNSET (decode_bin->fakesink, GST_ELEMENT_IS_SINK);
if (!gst_bin_add (GST_BIN (decode_bin), decode_bin->fakesink))
goto could_not_add;
return TRUE;
/* ERRORS */
no_fakesink:
{
g_warning ("can't find fakesink element, decodebin will not work");
return FALSE;
}
could_not_add:
{
g_warning ("Could not add fakesink to decodebin, decodebin will not work");
gst_object_unref (decode_bin->fakesink);
decode_bin->fakesink = NULL;
return FALSE;
}
message = gst_message_new_async_start (GST_OBJECT_CAST (dbin), FALSE);
parent_class->handle_message (GST_BIN_CAST (dbin), message);
}
static void
remove_fakesink (GstDecodeBin * decode_bin)
do_async_done (GstDecodeBin * dbin)
{
if (decode_bin->fakesink == NULL)
return;
GstMessage *message;
GST_DEBUG_OBJECT (decode_bin, "Removing the fakesink");
if (dbin->async_pending) {
message = gst_message_new_async_done (GST_OBJECT_CAST (dbin));
parent_class->handle_message (GST_BIN_CAST (dbin), message);
gst_element_set_state (decode_bin->fakesink, GST_STATE_NULL);
gst_bin_remove (GST_BIN (decode_bin), decode_bin->fakesink);
decode_bin->fakesink = NULL;
dbin->async_pending = FALSE;
}
}
/*****
@ -2380,7 +2333,7 @@ find_sink_pad (GstElement * element)
static GstStateChangeReturn
gst_decode_bin_change_state (GstElement * element, GstStateChange transition)
{
GstStateChangeReturn ret;
GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
GstDecodeBin *dbin = GST_DECODE_BIN (element);
switch (transition) {
@ -2388,19 +2341,29 @@ gst_decode_bin_change_state (GstElement * element, GstStateChange transition)
if (dbin->typefind == NULL)
goto missing_typefind;
break;
case GST_STATE_CHANGE_READY_TO_PAUSED:{
case GST_STATE_CHANGE_READY_TO_PAUSED:
dbin->have_type = FALSE;
if (!add_fakesink (dbin))
goto missing_fakesink;
ret = GST_STATE_CHANGE_ASYNC;
do_async_start (dbin);
break;
}
default:
break;
}
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
{
GstStateChangeReturn bret;
/* FIXME : put some cleanup functions here.. if needed */
bret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
if (G_UNLIKELY (bret == GST_STATE_CHANGE_FAILURE))
goto activate_failed;
}
switch (transition) {
case GST_STATE_CHANGE_PAUSED_TO_READY:
do_async_done (dbin);
break;
default:
break;
}
return ret;
@ -2412,11 +2375,10 @@ missing_typefind:
GST_ELEMENT_ERROR (dbin, CORE, MISSING_PLUGIN, (NULL), ("no typefind!"));
return GST_STATE_CHANGE_FAILURE;
}
missing_fakesink:
activate_failed:
{
gst_element_post_message (element,
gst_missing_element_message_new (element, "fakesink"));
GST_ELEMENT_ERROR (dbin, CORE, MISSING_PLUGIN, (NULL), ("no fakesink!"));
GST_DEBUG_OBJECT (element,
"element failed to change states -- activation problem?");
return GST_STATE_CHANGE_FAILURE;
}
}

View file

@ -1610,7 +1610,12 @@ no_more_pads_cb (GstElement * decodebin, GstSourceGroup * group)
res);
}
}
group->pending--;
GST_DEBUG_OBJECT (playbin, "pending %d > %d", group->pending,
group->pending - 1);
if (group->pending > 0)
group->pending--;
if (group->pending == 0) {
/* we are the last group to complete, we will configure the output and then
* signal the other waiters. */

View file

@ -71,8 +71,8 @@ struct _GstURIDecodeBin
gboolean is_stream;
GstElement *source;
GstElement *queue;
GSList *decoders;
GstElement *typefind;
guint have_type_id; /* have-type signal id from typefind */
GSList *decodebins;
GSList *srcpads;
gint numpads;
@ -908,16 +908,14 @@ remove_decoders (GstURIDecodeBin * bin)
{
GSList *walk;
for (walk = bin->decoders; walk; walk = g_slist_next (walk)) {
for (walk = bin->decodebins; walk; walk = g_slist_next (walk)) {
GstElement *decoder = GST_ELEMENT_CAST (walk->data);
GST_DEBUG_OBJECT (bin, "removing old decoder element");
gst_element_set_state (decoder, GST_STATE_NULL);
gst_bin_remove (GST_BIN_CAST (bin), decoder);
}
g_slist_free (bin->decoders);
g_slist_free (bin->decodebins);
bin->decoders = NULL;
bin->decodebins = NULL;
}
@ -1001,10 +999,11 @@ proxy_drained_signal (GstElement * element, GstURIDecodeBin * dec)
gst_uri_decode_bin_signals[SIGNAL_DRAINED], 0, NULL);
}
/* make a decodebin and connect to all the signals */
static GstElement *
make_decoder (GstURIDecodeBin * decoder, gboolean use_queue)
make_decoder (GstURIDecodeBin * decoder)
{
GstElement *result, *decodebin;
GstElement *decodebin;
/* now create the decoder element */
decodebin = gst_element_factory_make ("decodebin2", NULL);
@ -1023,34 +1022,6 @@ make_decoder (GstURIDecodeBin * decoder, gboolean use_queue)
g_signal_connect (G_OBJECT (decodebin), "drained",
G_CALLBACK (proxy_drained_signal), decoder);
if (use_queue) {
GstElement *queue;
GstPad *gpad, *pad;
queue = gst_element_factory_make ("queue2", NULL);
if (!queue)
goto no_queue2;
/* configure the queue as a buffering element */
g_object_set (G_OBJECT (queue), "use-buffering", TRUE, NULL);
result = gst_bin_new ("source-bin");
gst_bin_add (GST_BIN_CAST (result), queue);
gst_bin_add (GST_BIN_CAST (result), decodebin);
gst_element_link (queue, decodebin);
pad = gst_element_get_pad (queue, "sink");
gpad = gst_ghost_pad_new (GST_PAD_NAME (pad), pad);
gst_object_unref (pad);
gst_pad_set_active (gpad, TRUE);
gst_element_add_pad (GST_ELEMENT_CAST (result), gpad);
} else {
result = decodebin;
}
/* set up callbacks to create the links between decoded data
* and video/audio/subtitle rendering/output. */
g_signal_connect (G_OBJECT (decodebin),
@ -1066,12 +1037,11 @@ make_decoder (GstURIDecodeBin * decoder, gboolean use_queue)
NULL);
decoder->pending++;
gst_bin_add (GST_BIN_CAST (decoder), result);
gst_bin_add (GST_BIN_CAST (decoder), decodebin);
decoder->decoders = g_slist_prepend (decoder->decoders, result);
decoder->decodebins = g_slist_prepend (decoder->decodebins, decodebin);
return result;
return decodebin;
/* ERRORS */
no_decodebin:
@ -1080,11 +1050,104 @@ no_decodebin:
(_("Could not create \"decodebin2\" element.")), (NULL));
return NULL;
}
}
static void
type_found (GstElement * typefind, guint probability,
GstCaps * caps, GstURIDecodeBin * decoder)
{
GstElement *dec_elem, *queue;
GST_DEBUG_OBJECT (decoder, "typefind found caps %" GST_PTR_FORMAT, caps);
dec_elem = g_object_get_data (G_OBJECT (typefind), "decodebin2");
if (!dec_elem)
goto no_decodebin;
queue = gst_element_factory_make ("queue2", NULL);
if (!queue)
goto no_queue2;
g_object_set (G_OBJECT (queue), "use-buffering", TRUE, NULL);
//g_object_set (G_OBJECT (queue), "temp-location", "temp", NULL);
gst_bin_add (GST_BIN_CAST (decoder), queue);
if (!gst_element_link (typefind, queue))
goto could_not_link;
g_object_set (G_OBJECT (dec_elem), "sink-caps", caps, NULL);
if (!gst_element_link (queue, dec_elem))
goto could_not_link;
gst_element_set_state (queue, GST_STATE_PLAYING);
gst_element_set_state (dec_elem, GST_STATE_PLAYING);
return;
/* ERRORS */
no_decodebin:
{
/* error was posted */
return;
}
could_not_link:
{
GST_ELEMENT_ERROR (decoder, CORE, NEGOTIATION,
(NULL), ("Can't link typefind to decodebin2 element"));
return;
}
no_queue2:
{
GST_ELEMENT_ERROR (decoder, CORE, MISSING_PLUGIN,
(_("Could not create \"queue2\" element.")), (NULL));
return NULL;
return;
}
}
/* setup a streaming source. This will first plug a typefind element to the
* source. After we find the type, we decide to plug a queue2 and continue to
* plug a decodebin2 starting from the found caps */
static gboolean
setup_streaming (GstURIDecodeBin * decoder, GstElement * dec_elem)
{
GstElement *typefind;
/* now create the decoder element */
typefind = gst_element_factory_make ("typefind", NULL);
if (!typefind)
goto no_typefind;
gst_bin_add (GST_BIN_CAST (decoder), typefind);
if (!gst_element_link (decoder->source, typefind))
goto could_not_link;
decoder->typefind = typefind;
/* connect a signal to find out when the typefind element found
* a type */
decoder->have_type_id =
g_signal_connect (G_OBJECT (decoder->typefind), "have-type",
G_CALLBACK (type_found), decoder);
g_object_set_data (G_OBJECT (typefind), "decodebin2", dec_elem);
return TRUE;
/* ERRORS */
no_typefind:
{
GST_ELEMENT_ERROR (decoder, CORE, MISSING_PLUGIN,
(_("Could not create \"typefind\" element.")), (NULL));
return FALSE;
}
could_not_link:
{
GST_ELEMENT_ERROR (decoder, CORE, NEGOTIATION,
(NULL), ("Can't link source to typefind element"));
return FALSE;
}
}
@ -1130,7 +1193,7 @@ source_new_pad (GstElement * element, GstPad * pad, GstURIDecodeBin * bin)
}
/* not raw, create decoder */
decoder = make_decoder (bin, FALSE);
decoder = make_decoder (bin);
if (!decoder)
goto no_decodebin;
@ -1223,15 +1286,22 @@ setup_source (GstURIDecodeBin * decoder)
} else {
GstElement *dec_elem;
GST_DEBUG_OBJECT (decoder, "Pluggin decodebin to source");
/* no dynamic source, we can link now */
dec_elem = make_decoder (decoder, decoder->is_stream);
dec_elem = make_decoder (decoder);
if (!dec_elem)
goto no_decoder;
if (!gst_element_link (decoder->source, dec_elem))
goto could_not_link;
if (decoder->is_stream) {
GST_DEBUG_OBJECT (decoder, "Setting up streaming");
/* do the stream things here */
if (!setup_streaming (decoder, dec_elem))
goto streaming_failed;
} else {
/* no streaming source, we can link now */
GST_DEBUG_OBJECT (decoder, "Plugging decodebin to source");
if (!gst_element_link (decoder->source, dec_elem))
goto could_not_link;
}
}
return TRUE;
@ -1252,6 +1322,11 @@ no_decoder:
/* message was posted */
return FALSE;
}
streaming_failed:
{
/* message was posted */
return FALSE;
}
could_not_link:
{
GST_ELEMENT_ERROR (decoder, CORE, NEGOTIATION,