GstElementFactory: Add listing features
authorEdward Hervey <edward.hervey@collabora.co.uk>
Mon, 16 Aug 2010 17:01:15 +0000 (19:01 +0200)
committerEdward Hervey <bilboed@bilboed.com>
Fri, 3 Sep 2010 17:31:12 +0000 (19:31 +0200)
https://bugzilla.gnome.org/show_bug.cgi?id=626181

docs/gst/gstreamer-sections.txt
gst/gstelementfactory.c
gst/gstelementfactory.h
gst/gstpluginfeature.c
gst/gstpluginfeature.h

index 361ed23..fd81982 100644 (file)
@@ -648,6 +648,32 @@ gst_element_factory_make
 gst_element_factory_can_sink_caps
 gst_element_factory_can_src_caps
 gst_element_factory_get_static_pad_templates
+GstElementFactoryListType
+GST_ELEMENT_FACTORY_TYPE_ANY
+GST_ELEMENT_FACTORY_TYPE_AUDIOVIDEO_SINKS
+GST_ELEMENT_FACTORY_TYPE_AUDIO_ENCODER
+GST_ELEMENT_FACTORY_TYPE_DECODABLE
+GST_ELEMENT_FACTORY_TYPE_DECODER
+GST_ELEMENT_FACTORY_TYPE_DEMUXER
+GST_ELEMENT_FACTORY_TYPE_DEPAYLOADER
+GST_ELEMENT_FACTORY_TYPE_ENCODER
+GST_ELEMENT_FACTORY_TYPE_FORMATTER
+GST_ELEMENT_FACTORY_TYPE_MAX_ELEMENTS
+GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO
+GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE
+GST_ELEMENT_FACTORY_TYPE_MEDIA_METADATA
+GST_ELEMENT_FACTORY_TYPE_MEDIA_SUBTITLE
+GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO
+GST_ELEMENT_FACTORY_TYPE_MEDIA_ANY
+GST_ELEMENT_FACTORY_TYPE_MUXER
+GST_ELEMENT_FACTORY_TYPE_PARSER
+GST_ELEMENT_FACTORY_TYPE_PAYLOADER
+GST_ELEMENT_FACTORY_TYPE_SINK
+GST_ELEMENT_FACTORY_TYPE_SRC
+GST_ELEMENT_FACTORY_TYPE_VIDEO_ENCODER
+gst_element_factory_list_filter
+gst_element_factory_list_get_elements
+gst_element_factory_list_is_type
 <SUBSECTION Standard>
 GstElementFactoryClass
 GST_ELEMENT_FACTORY
@@ -1814,7 +1840,9 @@ gst_plugin_feature_get_name
 gst_plugin_feature_load
 gst_plugin_feature_list_copy
 gst_plugin_feature_list_free
+gst_plugin_feature_list_debug
 gst_plugin_feature_check_version
+gst_plugin_feature_rank_compare_func
 <SUBSECTION Standard>
 GstPluginFeatureClass
 GST_PLUGIN_FEATURE
index 713c42b..d19d584 100644 (file)
@@ -669,3 +669,199 @@ gst_element_factory_has_interface (GstElementFactory * factory,
   }
   return FALSE;
 }
+
+
+typedef struct
+{
+  GstElementFactoryListType type;
+  GstRank minrank;
+} FilterData;
+
+
+/**
+ * gst_element_factory_list_is_type:
+ * @factory: a #GstElementFactory
+ * @type: a #GstElementFactoryListType
+ *
+ * Check if @factory if of the given types.
+ *
+ * Returns: %TRUE if @factory is of @type.
+ *
+ * Since: 0.10.31
+ */
+gboolean
+gst_element_factory_list_is_type (GstElementFactory * factory,
+    GstElementFactoryListType type)
+{
+  gboolean res = FALSE;
+  const gchar *klass;
+
+  klass = gst_element_factory_get_klass (factory);
+
+  /* Filter by element type first, as soon as it matches
+   * one type, we skip all other tests */
+  if (!res && (type & GST_ELEMENT_FACTORY_TYPE_SINK))
+    res = (strstr (klass, "Sink") != NULL);
+
+  if (!res && (type & GST_ELEMENT_FACTORY_TYPE_SRC))
+    res = (strstr (klass, "Source") != NULL);
+
+  if (!res && (type & GST_ELEMENT_FACTORY_TYPE_DECODER))
+    res = (strstr (klass, "Decoder") != NULL);
+
+  if (!res && (type & GST_ELEMENT_FACTORY_TYPE_ENCODER))
+    res = (strstr (klass, "Encoder") != NULL);
+
+  if (!res && (type & GST_ELEMENT_FACTORY_TYPE_MUXER))
+    res = (strstr (klass, "Muxer") != NULL);
+
+  if (!res && (type & GST_ELEMENT_FACTORY_TYPE_DEMUXER))
+    res = (strstr (klass, "Demux") != NULL);
+
+  /* FIXME : We're actually parsing two Classes here... */
+  if (!res && (type & GST_ELEMENT_FACTORY_TYPE_PARSER))
+    res = ((strstr (klass, "Parser") != NULL)
+        && (strstr (klass, "Codec") != NULL));
+
+  if (!res && (type & GST_ELEMENT_FACTORY_TYPE_DEPAYLOADER))
+    res = (strstr (klass, "Depayloader") != NULL);
+
+  if (!res && (type & GST_ELEMENT_FACTORY_TYPE_PAYLOADER))
+    res = (strstr (klass, "Payloader") != NULL);
+
+  if (!res && (type & GST_ELEMENT_FACTORY_TYPE_FORMATTER))
+    res = (strstr (klass, "Formatter") != NULL);
+
+  /* Filter by media type now, we only test if it
+   * matched any of the types above. */
+  if (res
+      && (type & (GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO |
+              GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO |
+              GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE)))
+    res = ((type & GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO)
+        && (strstr (klass, "Audio") != NULL))
+        || ((type & GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO)
+        && (strstr (klass, "Video") != NULL))
+        || ((type & GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE)
+        && (strstr (klass, "Image") != NULL));
+
+  return res;
+}
+
+static gboolean
+element_filter (GstPluginFeature * feature, FilterData * data)
+{
+  gboolean res;
+
+  /* we only care about element factories */
+  if (G_UNLIKELY (!GST_IS_ELEMENT_FACTORY (feature)))
+    return FALSE;
+
+  res = (gst_plugin_feature_get_rank (feature) >= data->minrank) &&
+      gst_element_factory_list_is_type (GST_ELEMENT_FACTORY_CAST (feature),
+      data->type);
+
+  return res;
+}
+
+/**
+ * gst_element_factory_list_get_elements:
+ * @type: a #GstElementFactoryListType
+ * @minrank: Minimum rank
+ *
+ * Get a list of factories that match the given @type. Only elements
+ * with a rank greater or equal to @minrank will be returned.
+ * The list of factories is returned by decreasing rank.
+ *
+ * Returns: a #GList of #GstElementFactory elements. Use
+ * gst_plugin_feature_list_free() after usage.
+ *
+ * Since: 0.10.31
+ */
+GList *
+gst_element_factory_list_get_elements (GstElementFactoryListType type,
+    GstRank minrank)
+{
+  GList *result;
+  FilterData data;
+
+  /* prepare type */
+  data.type = type;
+  data.minrank = minrank;
+
+  /* get the feature list using the filter */
+  result = gst_default_registry_feature_filter ((GstPluginFeatureFilter)
+      element_filter, FALSE, &data);
+
+  /* sort on rank and name */
+  result = g_list_sort (result, gst_plugin_feature_rank_compare_func);
+
+  return result;
+}
+
+/**
+ * gst_element_factory_list_filter:
+ * @list: a #GList of #GstElementFactory to filter
+ * @caps: a #GstCaps
+ * @direction: a #GstPadDirection to filter on
+ * @subsetonly: whether to filter on caps subsets or not.
+ *
+ * Filter out all the elementfactories in @list that can handle @caps in
+ * the given direction.
+ *
+ * If @subsetonly is %TRUE, then only the elements whose pads templates
+ * are a complete superset of @caps will be returned. Else any element
+ * whose pad templates caps can intersect with @caps will be returned.
+ *
+ * Returns: a #GList of #GstElementFactory elements that match the
+ * given requisits. Use #gst_plugin_feature_list_free after usage.
+ *
+ * Since: 0.10.31
+ */
+GList *
+gst_element_factory_list_filter (GList * list,
+    const GstCaps * caps, GstPadDirection direction, gboolean subsetonly)
+{
+  GList *result = NULL;
+
+  GST_DEBUG ("finding factories");
+
+  /* loop over all the factories */
+  for (; list; list = list->next) {
+    GstElementFactory *factory;
+    const GList *templates;
+    GList *walk;
+
+    factory = (GstElementFactory *) list->data;
+
+    GST_DEBUG ("Trying %s",
+        gst_plugin_feature_get_name ((GstPluginFeature *) factory));
+
+    /* 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 == direction) {
+        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 */
+
+        /* check if the intersection is empty */
+        if ((subsetonly && gst_caps_is_subset (caps, tmpl_caps)) ||
+            (!subsetonly && gst_caps_can_intersect (caps, tmpl_caps))) {
+          /* non empty intersection, we can use this element */
+          result = g_list_prepend (result, gst_object_ref (factory));
+          break;
+        }
+        gst_caps_unref (tmpl_caps);
+      }
+    }
+  }
+  return g_list_reverse (result);
+}
index 39772b0..1a71d73 100644 (file)
@@ -165,8 +165,140 @@ void                    __gst_element_factory_add_interface     (GstElementFacto
 gboolean                gst_element_register                    (GstPlugin *plugin, const gchar *name,
                                                                  guint rank, GType type);
 
+/* Factory list functions */
+
+/**
+ * GstFactoryListType:
+ * @GST_ELEMENT_FACTORY_TYPE_DECODER: Decoder elements
+ * @GST_ELEMENT_FACTORY_TYPE_ENCODER: Encoder elements
+ * @GST_ELEMENT_FACTORY_TYPE_SINK: Sink elements
+ * @GST_ELEMENT_FACTORY_TYPE_SRC: Source elements
+ * @GST_ELEMENT_FACTORY_TYPE_MUXER: Muxer elements
+ * @GST_ELEMENT_FACTORY_TYPE_DEMUXER: Demuxer elements
+ * @GST_ELEMENT_FACTORY_TYPE_PARSER: Parser elements
+ * @GST_ELEMENT_FACTORY_TYPE_PAYLOADER: Payloader elements
+ * @GST_ELEMENT_FACTORY_TYPE_DEPAYLOADER: Depayloader elements
+ * @GST_ELEMENT_FACTORY_TYPE_MAX_ELEMENTS: Private, do not use
+ * @GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO: Elements handling video media types
+ * @GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO: Elements handling audio media types
+ * @GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE: Elements handling image media types
+ * @GST_ELEMENT_FACTORY_TYPE_MEDIA_SUBTITLE: Elements handling subtitle media types
+ * @GST_ELEMENT_FACTORY_TYPE_MEDIA_METADATA: Elements handling metadata media types
+ *
+ * The type of #GstElementFactory to filter.
+ *
+ * All @GstFactoryListType up to @GST_ELEMENT_FACTORY_TYPE_MAX_ELEMENTS are exclusive.
+ *
+ * If one or more of the MEDIA types are specified, then only elements
+ * matching the specified media types will be selected.
+ *
+ * Since: 0.10.31
+ */
+
+typedef guint64 GstElementFactoryListType;
+
+#define  GST_ELEMENT_FACTORY_TYPE_DECODER        (G_GUINT64_CONSTANT (1) << 0)
+#define  GST_ELEMENT_FACTORY_TYPE_ENCODER        (G_GUINT64_CONSTANT (1) << 1)
+#define  GST_ELEMENT_FACTORY_TYPE_SINK           (G_GUINT64_CONSTANT (1) << 2)
+#define  GST_ELEMENT_FACTORY_TYPE_SRC            (G_GUINT64_CONSTANT (1) << 3)
+#define  GST_ELEMENT_FACTORY_TYPE_MUXER          (G_GUINT64_CONSTANT (1) << 4)
+#define  GST_ELEMENT_FACTORY_TYPE_DEMUXER        (G_GUINT64_CONSTANT (1) << 5)
+#define  GST_ELEMENT_FACTORY_TYPE_PARSER         (G_GUINT64_CONSTANT (1) << 6)
+#define  GST_ELEMENT_FACTORY_TYPE_PAYLOADER      (G_GUINT64_CONSTANT (1) << 7)
+#define  GST_ELEMENT_FACTORY_TYPE_DEPAYLOADER    (G_GUINT64_CONSTANT (1) << 8)
+#define  GST_ELEMENT_FACTORY_TYPE_FORMATTER      (G_GUINT64_CONSTANT (1) << 9)
+
+#define  GST_ELEMENT_FACTORY_TYPE_MAX_ELEMENTS   (G_GUINT64_CONSTANT (1) << 48)
+
+#define  GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO    (G_GUINT64_CONSTANT (1) << 49)
+#define  GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO    (G_GUINT64_CONSTANT (1) << 50)
+#define  GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE    (G_GUINT64_CONSTANT (1) << 51)
+#define  GST_ELEMENT_FACTORY_TYPE_MEDIA_SUBTITLE (G_GUINT64_CONSTANT (1) << 52)
+#define  GST_ELEMENT_FACTORY_TYPE_MEDIA_METADATA (G_GUINT64_CONSTANT (1) << 53)
+
+/**
+ * GST_ELEMENT_FACTORY_TYPE_ANY:
+ * Elements of any of the defined GST_ELEMENT_FACTORY_LIST types
+ *
+ * Since: 0.10.31
+ */
+#define  GST_ELEMENT_FACTORY_TYPE_ANY G_GUINT64_CONSTANT ((1 << 49) - 1)
+
+/**
+ * GST_ELEMENT_FACTORY_TYPE_MEDIA_ANY:
+ * Elements matching any of the defined GST_ELEMENT_FACTORY_TYPE_MEDIA types
+ *
+ * Note: Do not use this if you wish to not filter against any of the defined
+ * media types. If you wish to do this, simply don't specify any 
+ * GST_ELEMENT_FACTORY_TYPE_MEDIA flag.
+ *
+ * Since: 0.10.31
+ */
+#define GST_ELEMENT_FACTORY_TYPE_MEDIA_ANY (~G_GUINT64_CONSTANT (0) << 48)
+
+/**
+ * GST_ELEMENT_FACTORY_TYPE_VIDEO_ENCODER:
+ * All encoders handling video or image media types
+ *
+ * Since: 0.10.31
+ */
+#define GST_ELEMENT_FACTORY_TYPE_VIDEO_ENCODER (GST_ELEMENT_FACTORY_TYPE_ENCODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO | GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE)
+
+/**
+ * GST_ELEMENT_FACTORY_TYPE_AUDIO_ENCODER:
+ * All encoders handling audio media types
+ *
+ * Since: 0.10.31
+ */
+#define GST_ELEMENT_FACTORY_TYPE_AUDIO_ENCODER (GST_ELEMENT_FACTORY_TYPE_ENCODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO)
+
+/**
+ * GST_ELEMENT_FACTORY_TYPE_AUDIOVIDEO_SINKS:
+ *
+ * All sinks handling audio, video or image media types
+ *
+ * Since: 0.10.31
+ */
+#define GST_ELEMENT_FACTORY_TYPE_AUDIOVIDEO_SINKS (GST_ELEMENT_FACTORY_TYPE_SINK | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO | GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE)
+
+/**
+ * GST_ELEMENT_FACTORY_TYPE_DECODABLE:
+ *
+ * All elements used to 'decode' streams (decoders, demuxers, parsers, depayloaders)
+ *
+ * Since: 0.10.31
+ */
+#define GST_ELEMENT_FACTORY_TYPE_DECODABLE \
+  (GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_DEMUXER | GST_ELEMENT_FACTORY_TYPE_DEPAYLOADER | GST_ELEMENT_FACTORY_TYPE_PARSER)
+
+/* Element klass defines */
+#define GST_ELEMENT_FACTORY_KLASS_DECODER              "Decoder"
+#define GST_ELEMENT_FACTORY_KLASS_ENCODER              "Encoder"
+#define GST_ELEMENT_FACTORY_KLASS_SINK                 "Sink"
+#define GST_ELEMENT_FACTORY_KLASS_SRC                  "Source"
+#define GST_ELEMENT_FACTORY_KLASS_MUXER                        "Muxer"
+#define GST_ELEMENT_FACTORY_KLASS_DEMUXER              "Demuxer"
+#define GST_ELEMENT_FACTORY_KLASS_PARSER               "Parser"
+#define GST_ELEMENT_FACTORY_KLASS_PAYLOADER            "Payloader"
+#define GST_ELEMENT_FACTORY_KLASS_DEPAYLOADER          "Depayloader"
+#define GST_ELEMENT_FACTORY_KLASS_FORMATTER            "Formatter"
+
+#define GST_ELEMENT_FACTORY_KLASS_MEDIA_VIDEO          "Video"
+#define GST_ELEMENT_FACTORY_KLASS_MEDIA_AUDIO          "Audio"
+#define GST_ELEMENT_FACTORY_KLASS_MEDIA_IMAGE          "Image"
+#define GST_ELEMENT_FACTORY_KLASS_MEDIA_SUBTITLE       "Subtitle"
+#define GST_ELEMENT_FACTORY_KLASS_MEDIA_METADATA       "Metadata"
+
+gboolean      gst_element_factory_list_is_type      (GstElementFactory *factory,
+                                                    GstElementFactoryListType type);
+
+GList *       gst_element_factory_list_get_elements (GstElementFactoryListType type,
+                                                    GstRank minrank);
 
 
+GList *       gst_element_factory_list_filter       (GList *list, const GstCaps *caps,
+                                                    GstPadDirection direction,
+                                                    gboolean subsetonly);
 G_END_DECLS
 
 #endif /* __GST_ELEMENT_FACTORY_H__ */
index 0ca7ab5..51961e5 100644 (file)
@@ -296,6 +296,26 @@ gst_plugin_feature_list_copy (GList * list)
 }
 
 /**
+ * gst_plugin_feature_list_debug:
+ * @list: a #GList of plugin features
+ *
+ * Debug the plugin feature names in @list.
+ *
+ * Since: 0.10.31
+ */
+void
+gst_plugin_feature_list_debug (GList * list)
+{
+#ifndef GST_DISABLE_GST_DEBUG
+  while (list) {
+    GST_DEBUG ("%s",
+        gst_plugin_feature_get_name ((GstPluginFeature *) list->data));
+    list = list->next;
+  }
+#endif
+}
+
+/**
  * gst_plugin_feature_check_version:
  * @feature: a feature
  * @min_major: minimum required major version
@@ -368,3 +388,36 @@ gst_plugin_feature_check_version (GstPluginFeature * feature,
 
   return ret;
 }
+
+/**
+ * gst_plugin_feature_rank_compare_func:
+ * @p1: a #GstPluginFeature
+ * @p2: a #GstPluginFeature
+ *
+ * Compares the two given #GstPluginFeature instances. This function can be
+ * used as a #GCompareFunc when sorting by rank and then by name.
+ *
+ * Returns: negative value if the rank of p1 > the rank of p2 or the ranks are
+ * equal but the name of p1 comes before the name of p2; zero if the rank
+ * and names are equal; positive value if the rank of p1 < the rank of p2 or the
+ * ranks are equal but the name of p2 comes after the name of p1
+ *
+ * Since: 0.10.31
+ */
+gint
+gst_plugin_feature_rank_compare_func (gconstpointer p1, gconstpointer p2)
+{
+  GstPluginFeature *f1, *f2;
+  gint diff;
+
+  f1 = (GstPluginFeature *) p1;
+  f2 = (GstPluginFeature *) p2;
+
+  diff = f2->rank - f1->rank;
+  if (diff != 0)
+    return diff;
+
+  diff = strcmp (f2->name, f1->name);
+
+  return diff;
+}
index ee1a6ce..ee615d9 100644 (file)
@@ -138,11 +138,20 @@ G_CONST_RETURN gchar *gst_plugin_feature_get_name       (GstPluginFeature *featu
 
 void            gst_plugin_feature_list_free            (GList *list);
 GList          *gst_plugin_feature_list_copy            (GList *list);
+void            gst_plugin_feature_list_debug           (GList *list);
+
+#ifndef GST_DISABLE_GST_DEBUG
+#define GST_PLUGIN_FEATURE_LIST_DEBUG(list) gst_plugin_feature_list_debug(list)
+#else
+#define GST_PLUGIN_FEATURE_LIST_DEBUG(list)
+#endif
 
 gboolean        gst_plugin_feature_check_version        (GstPluginFeature *feature,
                                                          guint             min_major,
                                                          guint             min_minor,
                                                          guint             min_micro);
+gint            gst_plugin_feature_rank_compare_func    (gconstpointer p1,
+                                                        gconstpointer p2);
 
 G_END_DECLS