mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-28 12:41:05 +00:00
Merge branch 'master' into 0.11
Conflicts: gst/playback/gstsubtitleoverlay.c tests/check/elements/decodebin2.c
This commit is contained in:
commit
8ee3da5bba
3 changed files with 252 additions and 17 deletions
|
@ -1,6 +1,8 @@
|
||||||
/* GStreamer
|
/* GStreamer
|
||||||
* Copyright (C) <2006> Edward Hervey <edward@fluendo.com>
|
* Copyright (C) <2006> Edward Hervey <edward@fluendo.com>
|
||||||
* Copyright (C) <2009> Sebastian Dröge <sebastian.droege@collabora.co.uk>
|
* Copyright (C) <2009> Sebastian Dröge <sebastian.droege@collabora.co.uk>
|
||||||
|
* Copyright (C) <2011> Hewlett-Packard Development Company, L.P.
|
||||||
|
* Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Library General Public
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
@ -111,6 +113,7 @@ GST_DEBUG_CATEGORY_STATIC (gst_decode_bin_debug);
|
||||||
#define GST_CAT_DEFAULT gst_decode_bin_debug
|
#define GST_CAT_DEFAULT gst_decode_bin_debug
|
||||||
|
|
||||||
typedef struct _GstPendingPad GstPendingPad;
|
typedef struct _GstPendingPad GstPendingPad;
|
||||||
|
typedef struct _GstDecodeElement GstDecodeElement;
|
||||||
typedef struct _GstDecodeChain GstDecodeChain;
|
typedef struct _GstDecodeChain GstDecodeChain;
|
||||||
typedef struct _GstDecodeGroup GstDecodeGroup;
|
typedef struct _GstDecodeGroup GstDecodeGroup;
|
||||||
typedef struct _GstDecodePad GstDecodePad;
|
typedef struct _GstDecodePad GstDecodePad;
|
||||||
|
@ -345,6 +348,12 @@ struct _GstPendingPad
|
||||||
gulong event_probe_id;
|
gulong event_probe_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct _GstDecodeElement
|
||||||
|
{
|
||||||
|
GstElement *element;
|
||||||
|
GstElement *capsfilter; /* Optional capsfilter for Parser/Convert */
|
||||||
|
};
|
||||||
|
|
||||||
/* GstDecodeGroup
|
/* GstDecodeGroup
|
||||||
*
|
*
|
||||||
* Streams belonging to the same group/chain of a media file
|
* Streams belonging to the same group/chain of a media file
|
||||||
|
@ -1328,11 +1337,15 @@ analyze_new_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
|
||||||
gboolean apcontinue = TRUE;
|
gboolean apcontinue = TRUE;
|
||||||
GValueArray *factories = NULL, *result = NULL;
|
GValueArray *factories = NULL, *result = NULL;
|
||||||
GstDecodePad *dpad;
|
GstDecodePad *dpad;
|
||||||
|
GstElementFactory *factory;
|
||||||
|
const gchar *classification;
|
||||||
|
gboolean is_parser_converter;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (dbin, "Pad %s:%s caps:%" GST_PTR_FORMAT,
|
GST_DEBUG_OBJECT (dbin, "Pad %s:%s caps:%" GST_PTR_FORMAT,
|
||||||
GST_DEBUG_PAD_NAME (pad), caps);
|
GST_DEBUG_PAD_NAME (pad), caps);
|
||||||
|
|
||||||
if (chain->elements && src != chain->elements->data) {
|
if (chain->elements
|
||||||
|
&& src != ((GstDecodeElement *) chain->elements->data)->element) {
|
||||||
GST_ERROR_OBJECT (dbin, "New pad from not the last element in this chain");
|
GST_ERROR_OBJECT (dbin, "New pad from not the last element in this chain");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1379,12 +1392,20 @@ analyze_new_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
|
||||||
if ((!apcontinue) || are_final_caps (dbin, caps))
|
if ((!apcontinue) || are_final_caps (dbin, caps))
|
||||||
goto expose_pad;
|
goto expose_pad;
|
||||||
|
|
||||||
/* 1.b when the caps are not fixed yet, we can't be sure what element to
|
/* 1.b For Parser/Converter that can output different stream formats
|
||||||
|
* we insert a capsfilter with the sorted caps of all possible next
|
||||||
|
* elements and continue with the capsfilter srcpad */
|
||||||
|
factory = gst_element_get_factory (src);
|
||||||
|
classification = gst_element_factory_get_klass (factory);
|
||||||
|
is_parser_converter = (strstr (classification, "Parser")
|
||||||
|
&& strstr (classification, "Converter"));
|
||||||
|
|
||||||
|
/* 1.c when the caps are not fixed yet, we can't be sure what element to
|
||||||
* connect. We delay autoplugging until the caps are fixed */
|
* connect. We delay autoplugging until the caps are fixed */
|
||||||
if (!gst_caps_is_fixed (caps))
|
if (!is_parser_converter && !gst_caps_is_fixed (caps))
|
||||||
goto non_fixed;
|
goto non_fixed;
|
||||||
|
|
||||||
/* 1.c else get the factories and if there's no compatible factory goto
|
/* 1.d else get the factories and if there's no compatible factory goto
|
||||||
* unknown_type */
|
* unknown_type */
|
||||||
g_signal_emit (G_OBJECT (dbin),
|
g_signal_emit (G_OBJECT (dbin),
|
||||||
gst_decode_bin_signals[SIGNAL_AUTOPLUG_FACTORIES], 0, dpad, caps,
|
gst_decode_bin_signals[SIGNAL_AUTOPLUG_FACTORIES], 0, dpad, caps,
|
||||||
|
@ -1401,6 +1422,7 @@ analyze_new_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
|
||||||
|
|
||||||
/* If the caps are raw, this just means we don't want to expose them */
|
/* If the caps are raw, this just means we don't want to expose them */
|
||||||
if (gst_caps_can_intersect (raw, caps)) {
|
if (gst_caps_can_intersect (raw, caps)) {
|
||||||
|
g_value_array_free (factories);
|
||||||
gst_caps_unref (raw);
|
gst_caps_unref (raw);
|
||||||
gst_object_unref (dpad);
|
gst_object_unref (dpad);
|
||||||
goto discarded_type;
|
goto discarded_type;
|
||||||
|
@ -1414,7 +1436,7 @@ analyze_new_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
|
||||||
goto unknown_type;
|
goto unknown_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 1.d sort some more. */
|
/* 1.e sort some more. */
|
||||||
g_signal_emit (G_OBJECT (dbin),
|
g_signal_emit (G_OBJECT (dbin),
|
||||||
gst_decode_bin_signals[SIGNAL_AUTOPLUG_SORT], 0, dpad, caps, factories,
|
gst_decode_bin_signals[SIGNAL_AUTOPLUG_SORT], 0, dpad, caps, factories,
|
||||||
&result);
|
&result);
|
||||||
|
@ -1432,7 +1454,7 @@ analyze_new_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
|
||||||
|
|
||||||
GST_DEBUG ("Checking if we can abort early");
|
GST_DEBUG ("Checking if we can abort early");
|
||||||
|
|
||||||
/* 1.e Do an early check to see if the candidates are potential decoders, but
|
/* 1.f Do an early check to see if the candidates are potential decoders, but
|
||||||
* due to the fact that they decode to a mediatype that is not final we don't
|
* due to the fact that they decode to a mediatype that is not final we don't
|
||||||
* need them */
|
* need them */
|
||||||
|
|
||||||
|
@ -1473,14 +1495,76 @@ analyze_new_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
|
||||||
|
|
||||||
if (dontuse) {
|
if (dontuse) {
|
||||||
gst_object_unref (dpad);
|
gst_object_unref (dpad);
|
||||||
|
g_value_array_free (factories);
|
||||||
goto discarded_type;
|
goto discarded_type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 1.f else continue autoplugging something from the list. */
|
/* 1.g now get the factory template caps and insert the capsfilter if this
|
||||||
|
* is a parser/converter
|
||||||
|
*/
|
||||||
|
if (is_parser_converter) {
|
||||||
|
GstCaps *filter_caps;
|
||||||
|
gint i;
|
||||||
|
GstPad *p;
|
||||||
|
GstDecodeElement *delem;
|
||||||
|
|
||||||
|
g_assert (chain->elements != NULL);
|
||||||
|
delem = (GstDecodeElement *) chain->elements->data;
|
||||||
|
|
||||||
|
filter_caps = gst_caps_new_empty ();
|
||||||
|
for (i = 0; i < factories->n_values; i++) {
|
||||||
|
GstElementFactory *factory =
|
||||||
|
g_value_get_object (g_value_array_get_nth (factories, i));
|
||||||
|
GstCaps *tcaps;
|
||||||
|
const GList *tmps;
|
||||||
|
|
||||||
|
GST_DEBUG ("Trying factory %s",
|
||||||
|
gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
|
||||||
|
|
||||||
|
if (gst_element_get_factory (src) == factory) {
|
||||||
|
GST_DEBUG ("Skipping factory");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (tmps = gst_element_factory_get_static_pad_templates (factory); tmps;
|
||||||
|
tmps = tmps->next) {
|
||||||
|
GstStaticPadTemplate *st = (GstStaticPadTemplate *) tmps->data;
|
||||||
|
if (st->direction != GST_PAD_SINK || st->presence != GST_PAD_ALWAYS)
|
||||||
|
continue;
|
||||||
|
tcaps = gst_static_pad_template_get_caps (st);
|
||||||
|
gst_caps_merge (filter_caps, gst_caps_copy (tcaps));
|
||||||
|
gst_caps_unref (tcaps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Append the parser caps to prevent any not-negotiated errors */
|
||||||
|
gst_caps_merge (filter_caps, gst_caps_copy (caps));
|
||||||
|
|
||||||
|
delem->capsfilter = gst_element_factory_make ("capsfilter", NULL);
|
||||||
|
g_object_set (G_OBJECT (delem->capsfilter), "caps", filter_caps, NULL);
|
||||||
|
gst_caps_unref (filter_caps);
|
||||||
|
gst_element_set_state (delem->capsfilter, GST_STATE_PAUSED);
|
||||||
|
gst_bin_add (GST_BIN_CAST (dbin), gst_object_ref (delem->capsfilter));
|
||||||
|
|
||||||
|
gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (dpad), NULL);
|
||||||
|
p = gst_element_get_static_pad (delem->capsfilter, "sink");
|
||||||
|
gst_pad_link_full (pad, p, GST_PAD_LINK_CHECK_NOTHING);
|
||||||
|
gst_object_unref (p);
|
||||||
|
p = gst_element_get_static_pad (delem->capsfilter, "src");
|
||||||
|
gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (dpad), p);
|
||||||
|
pad = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 1.h else continue autoplugging something from the list. */
|
||||||
GST_LOG_OBJECT (pad, "Let's continue discovery on this pad");
|
GST_LOG_OBJECT (pad, "Let's continue discovery on this pad");
|
||||||
connect_pad (dbin, src, dpad, pad, caps, factories, chain);
|
connect_pad (dbin, src, dpad, pad, caps, factories, chain);
|
||||||
|
|
||||||
|
/* Need to unref the capsfilter srcpad here if
|
||||||
|
* we inserted a capsfilter */
|
||||||
|
if (is_parser_converter)
|
||||||
|
gst_object_unref (pad);
|
||||||
|
|
||||||
gst_object_unref (dpad);
|
gst_object_unref (dpad);
|
||||||
g_value_array_free (factories);
|
g_value_array_free (factories);
|
||||||
|
|
||||||
|
@ -1628,6 +1712,7 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad,
|
||||||
while (factories->n_values > 0) {
|
while (factories->n_values > 0) {
|
||||||
GstAutoplugSelectResult ret;
|
GstAutoplugSelectResult ret;
|
||||||
GstElementFactory *factory;
|
GstElementFactory *factory;
|
||||||
|
GstDecodeElement *delem;
|
||||||
GstElement *element;
|
GstElement *element;
|
||||||
GstPad *sinkpad;
|
GstPad *sinkpad;
|
||||||
gboolean subtitle;
|
gboolean subtitle;
|
||||||
|
@ -1642,6 +1727,48 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad,
|
||||||
/* Remove selected factory from the list. */
|
/* Remove selected factory from the list. */
|
||||||
g_value_array_remove (factories, 0);
|
g_value_array_remove (factories, 0);
|
||||||
|
|
||||||
|
/* Check if the caps are really supported by the factory. The
|
||||||
|
* factory list is non-empty-subset filtered while caps
|
||||||
|
* are only accepted by a pad if they are a subset of the
|
||||||
|
* pad caps.
|
||||||
|
*
|
||||||
|
* FIXME: Only do this for fixed caps here. Non-fixed caps
|
||||||
|
* can happen if a Parser/Converter was autoplugged before
|
||||||
|
* this. We then assume that it will be able to convert to
|
||||||
|
* everything that the decoder would want.
|
||||||
|
*
|
||||||
|
* A subset check will fail here because the parser caps
|
||||||
|
* will be generic and while the decoder will only
|
||||||
|
* support a subset of the parser caps.
|
||||||
|
*/
|
||||||
|
if (gst_caps_is_fixed (caps)) {
|
||||||
|
const GList *templs;
|
||||||
|
gboolean skip = FALSE;
|
||||||
|
|
||||||
|
templs = gst_element_factory_get_static_pad_templates (factory);
|
||||||
|
|
||||||
|
while (templs) {
|
||||||
|
GstStaticPadTemplate *templ = (GstStaticPadTemplate *) templs->data;
|
||||||
|
|
||||||
|
if (templ->direction == GST_PAD_SINK) {
|
||||||
|
GstCaps *templcaps = gst_static_caps_get (&templ->static_caps);
|
||||||
|
|
||||||
|
if (!gst_caps_is_subset (caps, templcaps)) {
|
||||||
|
gst_caps_unref (templcaps);
|
||||||
|
skip = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_caps_unref (templcaps);
|
||||||
|
}
|
||||||
|
templs = g_list_next (templs);
|
||||||
|
}
|
||||||
|
if (skip) {
|
||||||
|
gst_object_unref (factory);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* If the factory is for a parser we first check if the factory
|
/* If the factory is for a parser we first check if the factory
|
||||||
* was already used for the current chain. If it was used already
|
* was already used for the current chain. If it was used already
|
||||||
* we would otherwise create an infinite loop here because the
|
* we would otherwise create an infinite loop here because the
|
||||||
|
@ -1657,7 +1784,8 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad,
|
||||||
|
|
||||||
CHAIN_MUTEX_LOCK (chain);
|
CHAIN_MUTEX_LOCK (chain);
|
||||||
for (l = chain->elements; l; l = l->next) {
|
for (l = chain->elements; l; l = l->next) {
|
||||||
GstElement *otherelement = GST_ELEMENT_CAST (l->data);
|
GstDecodeElement *delem = (GstDecodeElement *) l->data;
|
||||||
|
GstElement *otherelement = delem->element;
|
||||||
|
|
||||||
if (gst_element_get_factory (otherelement) == factory) {
|
if (gst_element_get_factory (otherelement) == factory) {
|
||||||
skip = TRUE;
|
skip = TRUE;
|
||||||
|
@ -1749,8 +1877,10 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad,
|
||||||
GST_LOG_OBJECT (dbin, "linked on pad %s:%s", GST_DEBUG_PAD_NAME (pad));
|
GST_LOG_OBJECT (dbin, "linked on pad %s:%s", GST_DEBUG_PAD_NAME (pad));
|
||||||
|
|
||||||
CHAIN_MUTEX_LOCK (chain);
|
CHAIN_MUTEX_LOCK (chain);
|
||||||
chain->elements =
|
delem = g_slice_new (GstDecodeElement);
|
||||||
g_list_prepend (chain->elements, gst_object_ref (element));
|
delem->element = gst_object_ref (element);
|
||||||
|
delem->capsfilter = NULL;
|
||||||
|
chain->elements = g_list_prepend (chain->elements, delem);
|
||||||
chain->demuxer = is_demuxer_element (element);
|
chain->demuxer = is_demuxer_element (element);
|
||||||
CHAIN_MUTEX_UNLOCK (chain);
|
CHAIN_MUTEX_UNLOCK (chain);
|
||||||
|
|
||||||
|
@ -1773,6 +1903,7 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad,
|
||||||
/* Bring the element to the state of the parent */
|
/* Bring the element to the state of the parent */
|
||||||
if ((gst_element_set_state (element,
|
if ((gst_element_set_state (element,
|
||||||
GST_STATE_PAUSED)) == GST_STATE_CHANGE_FAILURE) {
|
GST_STATE_PAUSED)) == GST_STATE_CHANGE_FAILURE) {
|
||||||
|
GstDecodeElement *dtmp = NULL;
|
||||||
GstElement *tmp = NULL;
|
GstElement *tmp = NULL;
|
||||||
|
|
||||||
GST_WARNING_OBJECT (dbin, "Couldn't set %s to PAUSED",
|
GST_WARNING_OBJECT (dbin, "Couldn't set %s to PAUSED",
|
||||||
|
@ -1784,7 +1915,8 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad,
|
||||||
do {
|
do {
|
||||||
GList *l;
|
GList *l;
|
||||||
|
|
||||||
tmp = chain->elements->data;
|
dtmp = chain->elements->data;
|
||||||
|
tmp = dtmp->element;
|
||||||
|
|
||||||
/* Disconnect any signal handlers that might be connected
|
/* Disconnect any signal handlers that might be connected
|
||||||
* in connect_element() or analyze_pad() */
|
* in connect_element() or analyze_pad() */
|
||||||
|
@ -1813,10 +1945,18 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad,
|
||||||
l = n;
|
l = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dtmp->capsfilter) {
|
||||||
|
gst_bin_remove (GST_BIN (dbin), dtmp->capsfilter);
|
||||||
|
gst_element_set_state (dtmp->capsfilter, GST_STATE_NULL);
|
||||||
|
gst_object_unref (dtmp->capsfilter);
|
||||||
|
}
|
||||||
|
|
||||||
gst_bin_remove (GST_BIN (dbin), tmp);
|
gst_bin_remove (GST_BIN (dbin), tmp);
|
||||||
gst_element_set_state (tmp, GST_STATE_NULL);
|
gst_element_set_state (tmp, GST_STATE_NULL);
|
||||||
|
|
||||||
gst_object_unref (tmp);
|
gst_object_unref (tmp);
|
||||||
|
g_slice_free (GstDecodeElement, dtmp);
|
||||||
|
|
||||||
chain->elements = g_list_delete_link (chain->elements, chain->elements);
|
chain->elements = g_list_delete_link (chain->elements, chain->elements);
|
||||||
} while (tmp != element);
|
} while (tmp != element);
|
||||||
CHAIN_MUTEX_UNLOCK (chain);
|
CHAIN_MUTEX_UNLOCK (chain);
|
||||||
|
@ -2180,7 +2320,8 @@ no_more_pads_cb (GstElement * element, GstDecodeChain * chain)
|
||||||
GST_LOG_OBJECT (element, "got no more pads");
|
GST_LOG_OBJECT (element, "got no more pads");
|
||||||
|
|
||||||
CHAIN_MUTEX_LOCK (chain);
|
CHAIN_MUTEX_LOCK (chain);
|
||||||
if (!chain->elements || (GstElement *) chain->elements->data != element) {
|
if (!chain->elements
|
||||||
|
|| ((GstDecodeElement *) chain->elements->data)->element != element) {
|
||||||
GST_LOG_OBJECT (chain->dbin, "no-more-pads from old chain element '%s'",
|
GST_LOG_OBJECT (chain->dbin, "no-more-pads from old chain element '%s'",
|
||||||
GST_OBJECT_NAME (element));
|
GST_OBJECT_NAME (element));
|
||||||
CHAIN_MUTEX_UNLOCK (chain);
|
CHAIN_MUTEX_UNLOCK (chain);
|
||||||
|
@ -2425,12 +2566,22 @@ gst_decode_chain_free_internal (GstDecodeChain * chain, gboolean hide)
|
||||||
chain->pending_pads = NULL;
|
chain->pending_pads = NULL;
|
||||||
|
|
||||||
for (l = chain->elements; l; l = l->next) {
|
for (l = chain->elements; l; l = l->next) {
|
||||||
GstElement *element = GST_ELEMENT (l->data);
|
GstDecodeElement *delem = l->data;
|
||||||
|
GstElement *element = delem->element;
|
||||||
|
|
||||||
g_signal_handlers_disconnect_by_func (element, pad_added_cb, chain);
|
g_signal_handlers_disconnect_by_func (element, pad_added_cb, chain);
|
||||||
g_signal_handlers_disconnect_by_func (element, pad_removed_cb, chain);
|
g_signal_handlers_disconnect_by_func (element, pad_removed_cb, chain);
|
||||||
g_signal_handlers_disconnect_by_func (element, no_more_pads_cb, chain);
|
g_signal_handlers_disconnect_by_func (element, no_more_pads_cb, chain);
|
||||||
|
|
||||||
|
if (delem->capsfilter) {
|
||||||
|
if (GST_OBJECT_PARENT (delem->capsfilter) ==
|
||||||
|
GST_OBJECT_CAST (chain->dbin))
|
||||||
|
gst_bin_remove (GST_BIN_CAST (chain->dbin), delem->capsfilter);
|
||||||
|
if (!hide) {
|
||||||
|
gst_element_set_state (delem->capsfilter, GST_STATE_NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (GST_OBJECT_PARENT (element) == GST_OBJECT_CAST (chain->dbin))
|
if (GST_OBJECT_PARENT (element) == GST_OBJECT_CAST (chain->dbin))
|
||||||
gst_bin_remove (GST_BIN_CAST (chain->dbin), element);
|
gst_bin_remove (GST_BIN_CAST (chain->dbin), element);
|
||||||
if (!hide) {
|
if (!hide) {
|
||||||
|
@ -2443,8 +2594,15 @@ gst_decode_chain_free_internal (GstDecodeChain * chain, gboolean hide)
|
||||||
SUBTITLE_UNLOCK (chain->dbin);
|
SUBTITLE_UNLOCK (chain->dbin);
|
||||||
|
|
||||||
if (!hide) {
|
if (!hide) {
|
||||||
|
if (delem->capsfilter) {
|
||||||
|
gst_object_unref (delem->capsfilter);
|
||||||
|
delem->capsfilter = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
gst_object_unref (element);
|
gst_object_unref (element);
|
||||||
l->data = NULL;
|
l->data = NULL;
|
||||||
|
|
||||||
|
g_slice_free (GstDecodeElement, delem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!hide) {
|
if (!hide) {
|
||||||
|
@ -3179,7 +3337,16 @@ gst_decode_chain_get_topology (GstDecodeChain * chain)
|
||||||
/* Get caps between all elements in this chain */
|
/* Get caps between all elements in this chain */
|
||||||
l = (chain->elements && chain->elements->next) ? chain->elements : NULL;
|
l = (chain->elements && chain->elements->next) ? chain->elements : NULL;
|
||||||
for (; l && l->next; l = l->next) {
|
for (; l && l->next; l = l->next) {
|
||||||
GstCaps *caps = _gst_element_get_linked_caps (l->next->data, l->data);
|
GstDecodeElement *delem, *delem_next;
|
||||||
|
GstElement *elem, *elem_next;
|
||||||
|
GstCaps *caps;
|
||||||
|
|
||||||
|
delem = l->data;
|
||||||
|
elem = delem->element;
|
||||||
|
delem_next = l->next->data;
|
||||||
|
elem_next = delem_next->element;
|
||||||
|
|
||||||
|
caps = _gst_element_get_linked_caps (elem_next, elem);
|
||||||
|
|
||||||
if (caps) {
|
if (caps) {
|
||||||
s = gst_structure_id_empty_new (topology_structure_name);
|
s = gst_structure_id_empty_new (topology_structure_name);
|
||||||
|
|
|
@ -2929,6 +2929,34 @@ drained_cb (GstElement * decodebin, GstSourceGroup * group)
|
||||||
setup_next_source (playbin, GST_STATE_PAUSED);
|
setup_next_source (playbin, GST_STATE_PAUSED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Like gst_element_factory_can_sink_any_caps() but doesn't
|
||||||
|
* allow ANY caps on the sinkpad template */
|
||||||
|
static gboolean
|
||||||
|
_factory_can_sink_caps (GstElementFactory * factory, GstCaps * caps)
|
||||||
|
{
|
||||||
|
const GList *templs;
|
||||||
|
|
||||||
|
templs = gst_element_factory_get_static_pad_templates (factory);
|
||||||
|
|
||||||
|
while (templs) {
|
||||||
|
GstStaticPadTemplate *templ = (GstStaticPadTemplate *) templs->data;
|
||||||
|
|
||||||
|
if (templ->direction == GST_PAD_SINK) {
|
||||||
|
GstCaps *templcaps = gst_static_caps_get (&templ->static_caps);
|
||||||
|
|
||||||
|
if (!gst_caps_is_any (templcaps)
|
||||||
|
&& gst_caps_can_intersect (templcaps, caps)) {
|
||||||
|
gst_caps_unref (templcaps);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
gst_caps_unref (templcaps);
|
||||||
|
}
|
||||||
|
templs = g_list_next (templs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Called when we must provide a list of factories to plug to @pad with @caps.
|
/* Called when we must provide a list of factories to plug to @pad with @caps.
|
||||||
* We first check if we have a sink that can handle the format and if we do, we
|
* We first check if we have a sink that can handle the format and if we do, we
|
||||||
* return NULL, to expose the pad. If we have no sink (or the sink does not
|
* return NULL, to expose the pad. If we have no sink (or the sink does not
|
||||||
|
@ -2957,12 +2985,52 @@ autoplug_factories_cb (GstElement * decodebin, GstPad * pad,
|
||||||
GST_DEBUG_OBJECT (playbin, "found factories %p", mylist);
|
GST_DEBUG_OBJECT (playbin, "found factories %p", mylist);
|
||||||
GST_PLUGIN_FEATURE_LIST_DEBUG (mylist);
|
GST_PLUGIN_FEATURE_LIST_DEBUG (mylist);
|
||||||
|
|
||||||
result = g_value_array_new (g_list_length (mylist));
|
/* 2 additional elements for the already set audio/video sinks */
|
||||||
|
result = g_value_array_new (g_list_length (mylist) + 2);
|
||||||
|
|
||||||
|
/* Check if we already have an audio/video sink and if this is the case
|
||||||
|
* put it as the first element of the array */
|
||||||
|
if (group->audio_sink) {
|
||||||
|
GstElementFactory *factory = gst_element_get_factory (group->audio_sink);
|
||||||
|
|
||||||
|
if (factory && _factory_can_sink_caps (factory, caps)) {
|
||||||
|
GValue val = { 0, };
|
||||||
|
|
||||||
|
g_value_init (&val, G_TYPE_OBJECT);
|
||||||
|
g_value_set_object (&val, factory);
|
||||||
|
result = g_value_array_append (result, &val);
|
||||||
|
g_value_unset (&val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (group->video_sink) {
|
||||||
|
GstElementFactory *factory = gst_element_get_factory (group->video_sink);
|
||||||
|
|
||||||
|
if (factory && _factory_can_sink_caps (factory, caps)) {
|
||||||
|
GValue val = { 0, };
|
||||||
|
|
||||||
|
g_value_init (&val, G_TYPE_OBJECT);
|
||||||
|
g_value_set_object (&val, factory);
|
||||||
|
result = g_value_array_append (result, &val);
|
||||||
|
g_value_unset (&val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (tmp = mylist; tmp; tmp = tmp->next) {
|
for (tmp = mylist; tmp; tmp = tmp->next) {
|
||||||
GstElementFactory *factory = GST_ELEMENT_FACTORY_CAST (tmp->data);
|
GstElementFactory *factory = GST_ELEMENT_FACTORY_CAST (tmp->data);
|
||||||
GValue val = { 0, };
|
GValue val = { 0, };
|
||||||
|
|
||||||
|
if (group->audio_sink && gst_element_factory_list_is_type (factory,
|
||||||
|
GST_ELEMENT_FACTORY_TYPE_SINK |
|
||||||
|
GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (group->video_sink && gst_element_factory_list_is_type (factory,
|
||||||
|
GST_ELEMENT_FACTORY_TYPE_SINK | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO
|
||||||
|
| GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
g_value_init (&val, G_TYPE_OBJECT);
|
g_value_init (&val, G_TYPE_OBJECT);
|
||||||
g_value_set_object (&val, factory);
|
g_value_set_object (&val, factory);
|
||||||
g_value_array_append (result, &val);
|
g_value_array_append (result, &val);
|
||||||
|
@ -3009,7 +3077,7 @@ autoplug_continue_cb (GstElement * element, GstPad * pad, GstCaps * caps,
|
||||||
gst_object_unref (sinkpad);
|
gst_object_unref (sinkpad);
|
||||||
} else {
|
} else {
|
||||||
GstCaps *subcaps = gst_subtitle_overlay_create_factory_caps ();
|
GstCaps *subcaps = gst_subtitle_overlay_create_factory_caps ();
|
||||||
ret = !gst_caps_can_intersect (caps, subcaps);
|
ret = !gst_caps_is_subset (caps, subcaps);
|
||||||
gst_caps_unref (subcaps);
|
gst_caps_unref (subcaps);
|
||||||
}
|
}
|
||||||
/* If autoplugging can stop don't do additional checks */
|
/* If autoplugging can stop don't do additional checks */
|
||||||
|
|
|
@ -1763,7 +1763,7 @@ static gboolean
|
||||||
gst_subtitle_overlay_subtitle_sink_acceptcaps (GstPad * pad, GstCaps * caps)
|
gst_subtitle_overlay_subtitle_sink_acceptcaps (GstPad * pad, GstCaps * caps)
|
||||||
{
|
{
|
||||||
GstCaps *othercaps = gst_subtitle_overlay_subtitle_sink_getcaps (pad, NULL);
|
GstCaps *othercaps = gst_subtitle_overlay_subtitle_sink_getcaps (pad, NULL);
|
||||||
gboolean ret = gst_caps_can_intersect (caps, othercaps);
|
gboolean ret = gst_caps_is_subset (caps, othercaps);
|
||||||
|
|
||||||
gst_caps_unref (othercaps);
|
gst_caps_unref (othercaps);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue