summaryrefslogtreecommitdiff
path: root/gst/playback/gstfactorylists.c
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@gmail.com>2007-11-30 17:47:15 +0000
committerWim Taymans <wim.taymans@gmail.com>2007-11-30 17:47:15 +0000
commit11bf488b85877530ef34fb81ceeba877c11bac00 (patch)
treef09deac45e3da60dc764d399a0e86d8310298012 /gst/playback/gstfactorylists.c
parent06251604162c3a8573562e469e26008b15422a7e (diff)
gst/playback/: Refactor some common code to filter factories and check caps compat.
Original commit message from CVS: * gst/playback/Makefile.am: * gst/playback/gstfactorylists.c: (compare_ranks), (print_feature), (get_feature_array), (decoders_filter), (sinks_filter), (gst_factory_list_get_decoders), (gst_factory_list_get_sinks), (gst_factory_list_filter): * gst/playback/gstfactorylists.h: Refactor some common code to filter factories and check caps compat. * gst/playback/gstdecodebin.c: * gst/playback/gstdecodebin2.c: (gst_decode_bin_class_init), (gst_decode_bin_init), (gst_decode_bin_dispose), (gst_decode_bin_autoplug_continue), (gst_decode_bin_autoplug_factories), (gst_decode_bin_autoplug_select), (analyze_new_pad), (find_compatibles): * gst/playback/gstplaybin.c: * gst/playback/gstplaybin2.c: (gst_play_bin_class_init), (gst_play_bin_init), (gst_play_bin_finalize), (autoplug_factories_cb), (activate_group): * gst/playback/gstqueue2.c: * gst/playback/gsturidecodebin.c: (proxy_unknown_type_signal), (proxy_autoplug_continue_signal), (proxy_autoplug_factories_signal), (proxy_autoplug_select_signal), (proxy_drained_signal): Add some more debug info and use factor filtering code.
Diffstat (limited to 'gst/playback/gstfactorylists.c')
-rw-r--r--gst/playback/gstfactorylists.c254
1 files changed, 254 insertions, 0 deletions
diff --git a/gst/playback/gstfactorylists.c b/gst/playback/gstfactorylists.c
new file mode 100644
index 000000000..ca6166d83
--- /dev/null
+++ b/gst/playback/gstfactorylists.c
@@ -0,0 +1,254 @@
+/* GStreamer
+ * Copyright (C) <2007> Wim Taymans <wim.taymans@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include <string.h>
+
+#include "gstfactorylists.h"
+
+/* function used to sort element features. We first sort on the rank, then
+ * on the element name (to get a consistent, predictable list) */
+static gint
+compare_ranks (GValue * v1, GValue * v2)
+{
+ gint diff;
+ const gchar *rname1, *rname2;
+ GstPluginFeature *f1, *f2;
+
+ f1 = g_value_get_object (v1);
+ f2 = g_value_get_object (v2);
+
+ diff = gst_plugin_feature_get_rank (f2) - gst_plugin_feature_get_rank (f1);
+ if (diff != 0)
+ return diff;
+
+ rname1 = gst_plugin_feature_get_name (f1);
+ rname2 = gst_plugin_feature_get_name (f2);
+
+ diff = strcmp (rname2, rname1);
+
+ return diff;
+}
+
+#if 0
+static void
+print_feature (GstPluginFeature * feature)
+{
+ const gchar *rname;
+
+ rname = gst_plugin_feature_get_name (feature);
+
+ GST_DEBUG ("%s", rname);
+}
+#endif
+
+/* get a filtered feature list as a GValueArray */
+static GValueArray *
+get_feature_array (GstPluginFeatureFilter filter)
+{
+ GValueArray *result;
+ GList *walk, *list;
+
+ result = g_value_array_new (0);
+
+ /* get the feature list using the filter */
+ list = gst_default_registry_feature_filter (filter, FALSE, NULL);
+
+ /* convert to an array */
+ for (walk = list; walk; walk = g_list_next (walk)) {
+ GstElementFactory *factory = GST_ELEMENT_FACTORY (walk->data);
+ GValue val = { 0, };
+
+ g_value_init (&val, G_TYPE_OBJECT);
+ g_value_set_object (&val, factory);
+ g_value_array_append (result, &val);
+ g_value_unset (&val);
+ }
+ gst_plugin_feature_list_free (list);
+
+ /* sort on rank and name */
+ g_value_array_sort (result, (GCompareFunc) compare_ranks);
+
+ return result;
+}
+
+/* the filter function for selecting the elements we can use in
+ * autoplugging */
+static gboolean
+decoders_filter (GstPluginFeature * feature)
+{
+ guint rank;
+ const gchar *klass;
+
+ /* we only care about element factories */
+ if (!GST_IS_ELEMENT_FACTORY (feature))
+ return FALSE;
+
+ klass = gst_element_factory_get_klass (GST_ELEMENT_FACTORY (feature));
+ /* only demuxers, decoders, depayloaders and parsers can play */
+ if (strstr (klass, "Demux") == NULL &&
+ strstr (klass, "Decoder") == NULL &&
+ strstr (klass, "Depayloader") == NULL &&
+ strstr (klass, "Parse") == NULL) {
+ return FALSE;
+ }
+
+ /* only select elements with autoplugging rank */
+ rank = gst_plugin_feature_get_rank (feature);
+ if (rank < GST_RANK_MARGINAL)
+ return FALSE;
+
+ return TRUE;
+}
+
+/* the filter function for selecting the elements we can use in
+ * autoplugging */
+static gboolean
+sinks_filter (GstPluginFeature * feature)
+{
+ guint rank;
+ const gchar *klass;
+
+ /* we only care about element factories */
+ if (!GST_IS_ELEMENT_FACTORY (feature))
+ return FALSE;
+
+ klass = gst_element_factory_get_klass (GST_ELEMENT_FACTORY (feature));
+ /* only sinks can play */
+ if (strstr (klass, "Sink") == NULL) {
+ return FALSE;
+ }
+
+ /* must be audio or video sink */
+ if (strstr (klass, "Audio") == NULL && strstr (klass, "Video") == NULL) {
+ return FALSE;
+ }
+
+ /* only select elements with autoplugging rank */
+ rank = gst_plugin_feature_get_rank (feature);
+ if (rank < GST_RANK_MARGINAL)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+/**
+ * gst_factory_list_get_decoders:
+ *
+ * Get a sorted list of factories that can be used in decoding pipelines.
+ *
+ * Returns: a #GValueArray of #GstElementFactory elements. Use
+ * g_value_array_free() after usage.
+ */
+GValueArray *
+gst_factory_list_get_decoders (void)
+{
+ GValueArray *result;
+
+ /* first filter out the interesting element factories */
+ result = get_feature_array ((GstPluginFeatureFilter) decoders_filter);
+
+ return result;
+}
+
+/**
+ * gst_factory_list_get_sinks:
+ *
+ * Get a sorted list of factories that can be used as sinks in a decoding
+ * pipeline.
+ *
+ * Returns: a #GValueArray of #GstElementFactory elements. Use
+ * g_value_array_free() after usage.
+ */
+GValueArray *
+gst_factory_list_get_sinks (void)
+{
+ GValueArray *result;
+
+ /* first filter out the interesting element factories */
+ result = get_feature_array ((GstPluginFeatureFilter) sinks_filter);
+
+ return result;
+}
+
+/**
+ * gst_factory_list_filter:
+ * @array: a #GValueArray to filter
+ * @caps: a #GstCaps
+ *
+ * Filter out all the elementfactories in @array that can handle @caps as
+ * input.
+ *
+ * Returns: a #GValueArray of #GstElementFactory elements. Use
+ * g_value_array_free() after usage.
+ */
+GValueArray *
+gst_factory_list_filter (GValueArray * array, const GstCaps * caps)
+{
+ GValueArray *result;
+ gint i;
+
+ result = g_value_array_new (0);
+
+ GST_DEBUG ("finding factories");
+
+ /* loop over all the factories */
+ for (i = 0; i < array->n_values; i++) {
+ GValue *value;
+ GstElementFactory *factory;
+ const GList *templates;
+ GList *walk;
+
+ value = g_value_array_get_nth (array, i);
+ factory = g_value_get_object (value);
+
+ /* get the templates from the element factory */
+ templates = gst_element_factory_get_static_pad_templates (factory);
+ for (walk = (GList *) templates; walk; walk = g_list_next (walk)) {
+ GstStaticPadTemplate *templ = walk->data;
+
+ /* we only care about the sink templates */
+ if (templ->direction == GST_PAD_SINK) {
+ GstCaps *intersect;
+ GstCaps *tmpl_caps;
+
+ /* try to intersect the caps with the caps of the template */
+ tmpl_caps = gst_static_caps_get (&templ->static_caps);
+
+ /* FIXME, intersect is not the right method, we ideally want to check
+ * for a subset here */
+ intersect = gst_caps_intersect (caps, tmpl_caps);
+ gst_caps_unref (tmpl_caps);
+
+ /* check if the intersection is empty */
+ if (!gst_caps_is_empty (intersect)) {
+ /* non empty intersection, we can use this element */
+ GValue resval = { 0, };
+ g_value_init (&resval, G_TYPE_OBJECT);
+ g_value_set_object (&resval, factory);
+ g_value_array_append (result, &resval);
+ g_value_unset (&resval);
+ gst_caps_unref (intersect);
+ break;
+ }
+ gst_caps_unref (intersect);
+ }
+ }
+ }
+ return result;
+}