void (*removed_decoded_pad) (GstElement * element, GstPad * pad);
/* signal fired when we found a pad that we cannot decode */
void (*unknown_type) (GstElement * element, GstPad * pad, GstCaps * caps);
+
/* signal fired to know if we continue trying to decode the given caps */
- gboolean (*autoplug_continue) (GstElement * element, GstCaps * caps);
- /* signal fired to reorder the proposed list of factories */
- gboolean (*autoplug_sort) (GstElement * element, GstCaps * caps,
- GList ** list);
+ gboolean (*autoplug_continue) (GstElement * element, GstPad * pad,
+ GstCaps * caps);
+ /* signal fired to get a list of factories to try to autoplug */
+ GValueArray *(*autoplug_factories) (GstElement * element, GstPad * pad,
+ GstCaps * caps);
+ /* signal fired to select from the proposed list of factories */
+ gint (*autoplug_select) (GstElement * element, GstPad * pad, GstCaps * caps,
+ GValueArray * factories);
};
/* signals */
SIGNAL_REMOVED_DECODED_PAD,
SIGNAL_UNKNOWN_TYPE,
SIGNAL_AUTOPLUG_CONTINUE,
- SIGNAL_AUTOPLUG_SORT,
+ SIGNAL_AUTOPLUG_FACTORIES,
+ SIGNAL_AUTOPLUG_SELECT,
LAST_SIGNAL
};
GstCaps * caps, GstDecodeBin * decode_bin);
static gboolean gst_decode_bin_autoplug_continue (GstElement * element,
- GstCaps * caps);
-static gboolean gst_decode_bin_autoplug_sort (GstElement * element,
- GstCaps * caps, GList ** list);
+ GstPad * pad, GstCaps * caps);
+static GValueArray *gst_decode_bin_autoplug_factories (GstElement *
+ element, GstPad * pad, GstCaps * caps);
+static gint gst_decode_bin_autoplug_select (GstElement * element,
+ GstPad * pad, GstCaps * caps, GValueArray * list);
+
static void gst_decode_bin_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_decode_bin_get_property (GObject * object, guint prop_id,
* This signal gets emitted as soon as a new pad of the same type as one of
* the valid 'raw' types is added.
*/
-
gst_decode_bin_signals[SIGNAL_NEW_DECODED_PAD] =
g_signal_new ("new-decoded-pad", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
*
* This signal is emitted when a 'final' caps pad has been removed.
*/
-
gst_decode_bin_signals[SIGNAL_REMOVED_DECODED_PAD] =
g_signal_new ("removed-decoded-pad", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
* This signal is emitted when a pad for which there is no further possible
* decoding is added to the decodebin.
*/
-
gst_decode_bin_signals[SIGNAL_UNKNOWN_TYPE] =
g_signal_new ("unknown-type", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, unknown_type),
/**
* GstDecodeBin2::autoplug-continue:
+ * @pad: The #GstPad.
* @caps: The #GstCaps found.
*
* This signal is emitted whenever decodebin2 finds a new stream. It is
* final and the pad will be exposed as such (see 'new-decoded-pad'
* signal).
*/
-
gst_decode_bin_signals[SIGNAL_AUTOPLUG_CONTINUE] =
g_signal_new ("autoplug-continue", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, autoplug_continue),
- _gst_boolean_accumulator, NULL, gst_play_marshal_BOOLEAN__OBJECT,
- G_TYPE_BOOLEAN, 1, GST_TYPE_CAPS);
+ _gst_boolean_accumulator, NULL, gst_play_marshal_BOOLEAN__OBJECT_OBJECT,
+ G_TYPE_BOOLEAN, 2, GST_TYPE_PAD, GST_TYPE_CAPS);
+
+ /**
+ * GstDecodeBin2::autoplug-factories:
+ * @pad: The #GstPad.
+ * @caps: The #GstCaps found.
+ *
+ * This function is emited when an array of possible factories for @caps on
+ * @pad is needed. Decodebin2 will by default return
+ *
+ * Returns: a #GValueArray* with a list of factories to try. The factories are
+ * by default tried in the returned order or based on the index returned by
+ * "autoplug-select".
+ */
+ gst_decode_bin_signals[SIGNAL_AUTOPLUG_FACTORIES] =
+ g_signal_new ("autoplug-factories", G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass,
+ autoplug_factories), NULL, NULL,
+ gst_play_marshal_BOXED__OBJECT_OBJECT, G_TYPE_VALUE_ARRAY, 2,
+ GST_TYPE_PAD, GST_TYPE_CAPS);
/**
- * GstDecodeBin2::autoplug-sort:
+ * GstDecodeBin2::autoplug-select:
+ * @pad: The #GstPad.
* @caps: The #GstCaps.
- * @factories: A #GList of possible #GstElementFactory to use.
+ * @factories: A #GValueArray of possible #GstElementFactory to use, sorted by
+ * rank (higher ranks come first).
*
* This signal is emitted once decodebin2 has found all the possible
* #GstElementFactory that can be used to handle the given @caps.
*
- * UNSTABLE API. Will change soon.
- *
- * Returns: #TRUE if you wish decodebin2 to start trying to decode
- * the given @caps with the list of factories. #FALSE if you do not want
- * these #GstCaps, if so the pad will be exposed as unknown (see
- * 'unknown-type' signal).
+ * Returns: A #gint indicating what factory index from the @factories array
+ * that you wish decodebin2 to use for trying to decode the given @caps.
+ * -1 to stop selection of a factory. The default handler always
+ * returns the first possible factory.
*/
-
- gst_decode_bin_signals[SIGNAL_AUTOPLUG_SORT] =
- g_signal_new ("autoplug-sort", G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, autoplug_sort),
- _gst_boolean_accumulator, NULL, gst_play_marshal_BOOLEAN__OBJECT_POINTER,
- G_TYPE_BOOLEAN, 2, GST_TYPE_CAPS, G_TYPE_POINTER);
+ gst_decode_bin_signals[SIGNAL_AUTOPLUG_SELECT] =
+ g_signal_new ("autoplug-select", G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, autoplug_select),
+ NULL, NULL, gst_play_marshal_INT__OBJECT_OBJECT_BOXED,
+ G_TYPE_INT, 3, GST_TYPE_PAD, GST_TYPE_CAPS, G_TYPE_VALUE_ARRAY);
g_object_class_install_property (gobject_klass, PROP_CAPS,
g_param_spec_boxed ("caps", "Caps", "The caps on which to stop decoding.",
klass->autoplug_continue =
GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_continue);
- klass->autoplug_sort = GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_sort);
+ klass->autoplug_factories =
+ GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_factories);
+ klass->autoplug_select = GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_select);
gst_element_class_add_pad_template (gstelement_klass,
gst_static_pad_template_get (&decoder_bin_sink_template));
return caps;
}
+static GValueArray *find_compatibles (GstDecodeBin * decode_bin,
+ GstPad * pad, const GstCaps * caps);
+
/*****
* Default autoplug signal handlers
*****/
-
static gboolean
-gst_decode_bin_autoplug_continue (GstElement * element, GstCaps * caps)
+gst_decode_bin_autoplug_continue (GstElement * element, GstPad * pad,
+ GstCaps * caps)
{
+ /* by default we always continue */
return TRUE;
}
-static gboolean
-gst_decode_bin_autoplug_sort (GstElement * element, GstCaps * caps,
- GList ** list)
+static GValueArray *
+gst_decode_bin_autoplug_factories (GstElement * element, GstPad * pad,
+ GstCaps * caps)
{
- return TRUE;
+ GValueArray *result;
+
+ /* return all compatible factories for caps */
+ result = find_compatibles (GST_DECODE_BIN (element), pad, caps);
+
+ return result;
}
+static gint
+gst_decode_bin_autoplug_select (GstElement * element, GstPad * pad,
+ GstCaps * caps, GValueArray * factories)
+{
+ g_return_val_if_fail (factories != NULL, -1);
+ g_return_val_if_fail (factories->n_values > 0, -1);
+ /* Return first factory. */
+ return 0;
+}
/********
* Discovery methods
static gboolean are_raw_caps (GstDecodeBin * dbin, GstCaps * caps);
static gboolean is_demuxer_element (GstElement * srcelement);
-static GList *find_compatibles (GstDecodeBin * decode_bin,
- const GstCaps * caps);
static gboolean connect_pad (GstDecodeBin * dbin, GstElement * src,
- GstPad * pad, GList * factories, GstDecodeGroup * group);
+ GstPad * pad, GstCaps * caps, GValueArray * factories,
+ GstDecodeGroup * group);
static gboolean connect_element (GstDecodeBin * dbin, GstElement * element,
GstDecodeGroup * group);
static void expose_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
GstCaps * caps, GstDecodeGroup * group)
{
gboolean apcontinue = TRUE;
- GList *factories = NULL;
- gboolean apsort = TRUE;
+ GValueArray *factories = NULL;
GST_DEBUG_OBJECT (dbin, "Pad %s:%s caps:%" GST_PTR_FORMAT,
GST_DEBUG_PAD_NAME (pad), caps);
if (gst_caps_is_any (caps))
goto any_caps;
- /* 1. Emit 'autoplug-continue' */
+ /* 1. Emit 'autoplug-continue' the result will tell us if this pads needs
+ * further autoplugging. */
g_signal_emit (G_OBJECT (dbin),
- gst_decode_bin_signals[SIGNAL_AUTOPLUG_CONTINUE], 0, caps, &apcontinue);
+ gst_decode_bin_signals[SIGNAL_AUTOPLUG_CONTINUE], 0, pad, caps,
+ &apcontinue);
/* 1.a if autoplug-continue is FALSE or caps is a raw format, goto pad_is_final */
if ((!apcontinue) || are_raw_caps (dbin, caps))
if (!gst_caps_is_fixed (caps))
goto non_fixed;
- /* 1.c else if there's no compatible factory or 'autoplug-sort' returned FALSE, goto pad_not_used */
- if ((factories = find_compatibles (dbin, caps))) {
- /* emit autoplug-sort */
- g_signal_emit (G_OBJECT (dbin),
- gst_decode_bin_signals[SIGNAL_AUTOPLUG_SORT],
- 0, caps, &factories, &apsort);
- if (!apsort) {
- g_list_free (factories);
- /* User doesn't want that pad */
- goto pad_not_wanted;
- }
- } else {
+ /* 1.c else if there's no compatible factory goto unknown_type */
+ g_signal_emit (G_OBJECT (dbin),
+ gst_decode_bin_signals[SIGNAL_AUTOPLUG_FACTORIES], 0, pad, caps,
+ &factories);
+ if (factories == NULL) {
/* no compatible factories */
goto unknown_type;
}
/* 1.d else goto pad_is_valid */
GST_LOG_OBJECT (pad, "Let's continue discovery on this pad");
- connect_pad (dbin, src, pad, factories, group);
- g_list_free (factories);
+ connect_pad (dbin, src, pad, caps, factories, group);
+ g_value_array_free (factories);
return;
return;
}
-pad_not_wanted:
- {
- GST_LOG_OBJECT (pad, "User doesn't want this pad, stopping discovery");
- return;
- }
-
unknown_type:
{
GST_LOG_OBJECT (pad, "Unknown type, firing signal");
static gboolean
connect_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
- GList * factories, GstDecodeGroup * group)
+ GstCaps * caps, GValueArray * factories, GstDecodeGroup * group)
{
gboolean res = FALSE;
- GList *tmp;
GstPad *mqpad = NULL;
g_return_val_if_fail (factories != NULL, FALSE);
+ g_return_val_if_fail (factories->n_values > 0, FALSE);
+
GST_DEBUG_OBJECT (dbin, "pad %s:%s , group:%p",
GST_DEBUG_PAD_NAME (pad), group);
}
/* 2. Try to create an element and link to it */
- for (tmp = factories; tmp; tmp = g_list_next (tmp)) {
- GstElementFactory *factory = (GstElementFactory *) tmp->data;
+ while (factories->n_values > 0) {
+ gint factidx;
+ GstElementFactory *factory;
GstElement *element;
GstPad *sinkpad;
+ /* emit autoplug-select */
+ g_signal_emit (G_OBJECT (dbin),
+ gst_decode_bin_signals[SIGNAL_AUTOPLUG_SELECT],
+ 0, pad, caps, factories, &factidx);
+
+ /* when the function returns -1, we leave the loop and stop */
+ if (factidx == -1) {
+ GST_DEBUG_OBJECT (dbin, "autoplug select returned -1");
+ break;
+ }
+
+ GST_DEBUG_OBJECT (dbin, "autoplug select returned %d", factidx);
+
+ factory = g_value_get_object (g_value_array_get_nth (factories, factidx));
+
+ /* factory is != NULL now since the default handler selects the first
+ * factory if all connected user handlers returned NULL. */
+
+ /* Remove selected factory from the list. */
+ g_value_array_remove (factories, factidx);
+
/* 2.1. Try to create an element */
if ((element = gst_element_factory_create (factory, NULL)) == NULL) {
GST_WARNING_OBJECT (dbin, "Could not create an element from %s",
gst_object_unref (element);
}
-/* this function runs through the element factories and returns a list
- * of all elements that are able to sink the given caps
+/* this function runs through the element factories and returns a value array of
+ * all elements that are able to sink the given caps
*/
-static GList *
-find_compatibles (GstDecodeBin * decode_bin, const GstCaps * caps)
+static GValueArray *
+find_compatibles (GstDecodeBin * decode_bin, GstPad * pad, const GstCaps * caps)
{
GList *factories;
- GList *to_try = NULL;
+ GValueArray *to_try = g_value_array_new (0);
/* loop over all the factories */
for (factories = decode_bin->factories; factories;
/* check if the intersection is empty */
if (!gst_caps_is_empty (intersect)) {
/* non empty intersection, we can use this element */
- to_try = g_list_prepend (to_try, factory);
+ GValue val = { 0, };
+ g_value_init (&val, G_TYPE_OBJECT);
+ g_value_set_object (&val, factory);
+ g_value_array_append (to_try, &val);
+ g_value_unset (&val);
gst_caps_unref (intersect);
break;
}
}
}
}
- to_try = g_list_reverse (to_try);
return to_try;
}