manual: remove outdated autoplugging section
authorWim Taymans <wim.taymans@collabora.co.uk>
Tue, 9 Oct 2012 15:06:04 +0000 (17:06 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Tue, 9 Oct 2012 15:06:04 +0000 (17:06 +0200)
Remove autoplugging chapter and point to decodebin/playbin examples.

docs/manual/advanced-autoplugging.xml
tests/examples/manual/.gitignore
tests/examples/manual/Makefile.am

index 984617b..e2ccb4d 100644 (file)
@@ -234,390 +234,9 @@ main (gint   argc,
 
   <sect1 id="section-dynamic">
     <title>Dynamically autoplugging a pipeline</title>
-    <warning><para>
-      The code in this section is broken, outdated and overly complicated.
-      Also, you should use decodebin, playbin or uridecodebin to get
-      decoders plugged automatically.
-    </para></warning>
-    <para> 
-      In this chapter we will see how you can create a dynamic pipeline. A
-      dynamic pipeline is a pipeline that is updated or created while data
-     is flowing through it. We will create a partial pipeline first and add
-      more elements while the pipeline is playing. The basis of this player
-      will be the application that we wrote in the previous section (<xref
-      linkend="section-typefinding"/>) to identify unknown media streams.
-    </para>
-    <!-- example-begin dynamic.c a --><!--
-#include &lt;gst/gst.h&gt;
-
-GstElement *pipeline;
-    --><!-- example-end dynamic.c a -->
-    <para>
-      Once the type of the media has been found, we will find elements in
-      the registry that can decode this streamtype. For this, we will get
-      all element factories (which we've seen before in <xref
-      linkend="section-elements-create"/>) and find the ones with the
-      given media type and capabilities on their sinkpad. Note that we will
-      only use parsers, demuxers and decoders. We will not use factories for
-      any other element types, or we might get into a loop of encoders and
-      decoders. For this, we will want to build a list of <quote>allowed</quote>
-      factories right after initializing &GStreamer;.
-    </para>
-    <programlisting><!-- example-begin dynamic.c b -->
-static GList *factories;
-
-/*
- * This function is called by the registry loader. Its return value
- * (TRUE or FALSE) decides whether the given feature will be included
- * in the list that we're generating further down.
- */
-
-static gboolean
-cb_feature_filter (GstPluginFeature *feature,
-                  gpointer          data)
-{
-  const gchar *klass;
-  guint rank;
-
-  /* we only care about element factories */
-  if (!GST_IS_ELEMENT_FACTORY (feature))
-    return FALSE;
-
-  /* only parsers, demuxers and decoders */
-  klass = gst_element_factory_get_metadata (GST_ELEMENT_FACTORY (feature), GST_ELEMENT_METADATA_KLASS);
-  if (g_strrstr (klass, "Demux") == NULL &amp;&amp;
-      g_strrstr (klass, "Decoder") == NULL &amp;&amp;
-      g_strrstr (klass, "Parse") == NULL)
-    return FALSE;
-
-  /* only select elements with autoplugging rank */
-  rank = gst_plugin_feature_get_rank (feature);
-  if (rank &lt; GST_RANK_MARGINAL)
-    return FALSE;
-
-  return TRUE;
-}
-
-/*
- * This function is called to sort features by rank.
- */
-
-static gint
-cb_compare_ranks (GstPluginFeature *f1,
-                 GstPluginFeature *f2)
-{
-  return gst_plugin_feature_get_rank (f2) - gst_plugin_feature_get_rank (f1);
-}
-
-static void
-init_factories (void)
-{
-  /* first filter out the interesting element factories */
-  factories = gst_registry_feature_filter (
-      gst_registry_get (),
-      (GstPluginFeatureFilter) cb_feature_filter, FALSE, NULL);
-
-  /* sort them according to their ranks */
-  factories = g_list_sort (factories, (GCompareFunc) cb_compare_ranks);
-}
-    <!-- example-end dynamic.c b --></programlisting>
-    <para>
-      From this list of element factories, we will select the one that most
-      likely will help us decoding a media stream to a given output type.
-      For each newly created element, we will again try to autoplug new
-      elements to its source pad(s). Also, if the element has dynamic pads
-      (which we've seen before in <xref linkend="section-pads-dynamic"/>),
-      we will listen for newly created source pads and handle those, too.
-      The following code replaces the <function>cb_type_found</function>
-      from the previous section with a function to initiate autoplugging,
-      which will continue with the above approach.
-    </para>
-    <programlisting><!-- example-begin dynamic.c c -->
-static void try_to_plug (GstPad *pad, GstCaps *caps);
-
-static GstElement *audiosink;
-
-static void
-cb_newpad (GstElement *element,
-          GstPad     *pad,
-          gpointer    data)
-{
-  GstCaps *caps;
-
-  caps = gst_pad_query_caps (pad, NULL);
-  try_to_plug (pad, caps);
-  gst_caps_unref (caps);
-}
-
-static void
-close_link (GstPad      *srcpad,
-           GstElement  *sinkelement,
-           const gchar *padname,
-           const GList *templlist)
-{
-  GstPad *pad;
-  gboolean has_dynamic_pads = FALSE;
-
-  g_print ("Plugging pad %s:%s to newly created %s:%s\n",
-          gst_object_get_name (GST_OBJECT (gst_pad_get_parent (srcpad))),
-          gst_pad_get_name (srcpad),
-          gst_object_get_name (GST_OBJECT (sinkelement)), padname);
-
-  /* add the element to the pipeline and set correct state */
-  if (sinkelement != audiosink) {
-    gst_bin_add (GST_BIN (pipeline), sinkelement);
-    gst_element_set_state (sinkelement, GST_STATE_READY);
-  }
-  pad = gst_element_get_static_pad (sinkelement, padname);
-  gst_pad_link (srcpad, pad);
-  if (sinkelement != audiosink) {
-    gst_element_set_state (sinkelement, GST_STATE_PAUSED);
-  }
-  gst_object_unref (GST_OBJECT (pad));
-
-  /* if we have static source pads, link those. If we have dynamic
-   * source pads, listen for pad-added signals on the element */
-  for ( ; templlist != NULL; templlist = templlist->next) {
-    GstStaticPadTemplate *templ = templlist->data;
-
-    /* only sourcepads, no request pads */
-    if (templ->direction != GST_PAD_SRC ||
-        templ->presence == GST_PAD_REQUEST) {
-      continue;
-    }
-
-    switch (templ->presence) {
-      case GST_PAD_ALWAYS: {
-        GstPad *pad = gst_element_get_static_pad (sinkelement, templ->name_template);
-        GstCaps *caps = gst_pad_query_caps (pad, NULL);
-
-        /* link */
-        try_to_plug (pad, caps);
-        gst_object_unref (GST_OBJECT (pad));
-        gst_caps_unref (caps);
-        break;
-      }
-      case GST_PAD_SOMETIMES:
-        has_dynamic_pads = TRUE;
-        break;
-      default:
-        break;
-    }
-  }
-
-  /* listen for newly created pads if this element supports that */
-  if (has_dynamic_pads) {
-    g_signal_connect (sinkelement, "pad-added", G_CALLBACK (cb_newpad), NULL);
-  }
-}
-
-static void
-try_to_plug (GstPad        *pad,
-            GstCaps       *caps)
-{
-  GstObject *parent = GST_OBJECT (GST_OBJECT_PARENT (pad));
-  const gchar *media;
-  const GList *item;
-  GstCaps *res, *audiocaps;
-
-  /* don't plug if we're already plugged - FIXME: memleak for pad */
-  if (GST_PAD_IS_LINKED (gst_element_get_static_pad (audiosink, "sink"))) {
-    g_print ("Omitting link for pad %s:%s because we're already linked\n",
-            GST_OBJECT_NAME (parent), GST_OBJECT_NAME (pad));
-    return;
-  }
-
-  /* as said above, we only try to plug audio... Omit video */
-  media = gst_structure_get_name (gst_caps_get_structure (caps, 0));
-  if (g_strrstr (media, "video")) {
-    g_print ("Omitting link for pad %s:%s because media type %s is non-audio\n",
-            GST_OBJECT_NAME (parent), GST_OBJECT_NAME (pad), media);
-    return;
-  }
-
-  /* can it link to the audiopad? */
-  audiocaps = gst_pad_query_caps (gst_element_get_static_pad (audiosink, "sink"),
-  NULL);
-  res = gst_caps_intersect (caps, audiocaps);
-  if (res &amp;&amp; !gst_caps_is_empty (res)) {
-    g_print ("Found pad to link to audiosink - plugging is now done\n");
-    close_link (pad, audiosink, "sink", NULL);
-    gst_caps_unref (audiocaps);
-    gst_caps_unref (res);
-    return;
-  }
-  gst_caps_unref (audiocaps);
-  gst_caps_unref (res);
-
-  /* try to plug from our list */
-  for (item = factories; item != NULL; item = item->next) {
-    GstElementFactory *factory = GST_ELEMENT_FACTORY (item->data);
-    const GList *pads;
-
-    for (pads = gst_element_factory_get_static_pad_templates (factory);
-         pads != NULL; pads = pads->next) {
-      GstStaticPadTemplate *templ = pads->data;
-
-      /* find the sink template - need an always pad*/
-      if (templ->direction != GST_PAD_SINK ||
-          templ->presence != GST_PAD_ALWAYS) {
-        continue;
-      }
-
-      /* can it link? */
-      res = gst_caps_intersect (caps,
-          gst_static_caps_get (&amp;templ->static_caps));
-      if (res &amp;&amp; !gst_caps_is_empty (res)) {
-        GstElement *element;
-        gchar *name_template = g_strdup (templ->name_template);
-
-        /* close link and return */
-        gst_caps_unref (res);
-        element = gst_element_factory_create (factory, NULL);
-        close_link (pad, element, name_template,
-                   gst_element_factory_get_static_pad_templates (factory));
-        g_free (name_template);
-        return;
-      }
-      gst_caps_unref (res);
-
-      /* we only check one sink template per factory, so move on to the
-       * next factory now */
-      break;
-    }
-  }
-
-  /* if we get here, no item was found */
-  g_print ("No compatible pad found to decode %s on %s:%s\n",
-          media, GST_OBJECT_NAME (parent), GST_OBJECT_NAME (pad));
-}
-
-static void
-cb_typefound (GstElement *typefind,
-             guint       probability,
-             GstCaps    *caps,
-             gpointer    data)
-{
-  gchar *s;
-  GstPad *pad;
-
-  s = gst_caps_to_string (caps);
-  g_print ("Detected media type %s\n", s);
-  g_free (s);
-
-  /* actually plug now */
-  pad = gst_element_get_static_pad (typefind, "src");
-  try_to_plug (pad, caps);
-  gst_object_unref (GST_OBJECT (pad));
-}
-    <!-- example-end dynamic.c c --></programlisting>
-    <para>
-      By doing all this, we will be able to make a simple autoplugger that
-      can automatically setup a pipeline for any media type. In the example
-      above, we did this for audio only. However, we can also do this
-      for video to create a player that plays both audio and video.
-    </para>
-    <!-- example-begin dynamic.c d --><!--
-static gboolean
-my_bus_callback (GstBus     *bus,
-                 GstMessage *message,
-                 gpointer    data)
-{
-  GMainLoop *loop = data;
-
-  switch (GST_MESSAGE_TYPE (message)) {
-    case GST_MESSAGE_ERROR: {
-      GError *err;
-      gchar *debug;
-
-      gst_message_parse_error (message, &amp;err, &amp;debug);
-      g_print ("Error: %s\n", err-&gt;message);
-      g_error_free (err);
-      g_free (debug);
-
-      g_main_loop_quit (loop);
-      break;
-    }
-    case GST_MESSAGE_EOS:
-      /* end-of-stream */
-      g_main_loop_quit (loop);
-      break;
-    default:
-      break;
-  }
-
-  /* remove from queue */
-  return TRUE;
-}
-
-gint
-main (gint   argc,
-      gchar *argv[])
-{
-  GMainLoop *loop;
-  GstElement *typefind, *realsink;
-  GstBus *bus;
-  GError *err = NULL;
-  gchar *p;
-
-  /* init GStreamer and ourselves */
-  gst_init (&amp;argc, &amp;argv);
-  loop = g_main_loop_new (NULL, FALSE);
-  init_factories ();
-
-  /* args */
-  if (argc != 2) {
-    g_print ("Usage: %s &lt;filename&gt;\n", argv[0]);
-    return -1;
-  }
-
-  /* pipeline */
-  p = g_strdup_printf ("filesrc location=\"%s\" ! typefind name=tf", argv[1]);
-  pipeline = gst_parse_launch (p, &amp;err);
-  g_free (p);
-
-  if (err) {
-    g_error ("Could not construct pipeline: %s", err-&gt;message);
-    g_error_free (err);
-    return -1;
-  }
-
-  bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
-  gst_bus_add_watch (bus, my_bus_callback, NULL);
-  gst_object_unref (bus);
-
-  typefind = gst_bin_get_by_name (GST_BIN (pipeline), "tf");
-  g_signal_connect (typefind, "have-type", G_CALLBACK (cb_typefound), NULL);
-  gst_object_unref (GST_OBJECT (typefind));
-  audiosink = gst_element_factory_make ("audioconvert", "aconv");
-  realsink = gst_element_factory_make ("alsasink", "audiosink");
-  gst_bin_add_many (GST_BIN (pipeline), audiosink, realsink, NULL);
-  gst_element_link (audiosink, realsink);
-  gst_element_set_state (pipeline, GST_STATE_PLAYING);
-
-  /* run */
-  g_main_loop_run (loop);
-
-  /* exit */
-  gst_element_set_state (pipeline, GST_STATE_NULL);
-  gst_object_unref (GST_OBJECT (pipeline));
-
-  return 0;
-}
-    --><!-- example-end dynamic.c d -->
     <para>
-      The example above is a good first try for an autoplugger. Next steps
-      would be to listen for <quote>pad-removed</quote> signals, so we
-      can dynamically change the plugged pipeline if the stream changes
-      (this happens for DVB or Ogg radio). Also, you might want special-case
-      code for input with known content (such as a DVD or an audio-CD),
-      and much, much more. Moreover, you'll want many checks to prevent
-      infinite loops during autoplugging, maybe you'll want to implement
-      shortest-path-finding to make sure the most optimal pipeline is chosen,
-      and so on. Basically, the features that you implement in an autoplugger
-      depend on what you want to use it for. For full-blown implementations,
-      see the <quote>playbin</quote> and <quote>decodebin</quote> elements in
-      <xref linkend="chapter-components"/>.
+      See <xref linkend="chapter-components"/> for using the high level
+      object that you can use to dynamically construct pipelines.
     </para>
   </sect1>
 </chapter>
index 49574d9..4cf9593 100644 (file)
@@ -10,7 +10,6 @@ Makefile.in
 appsink
 appsrc
 blockprobe
-dynamic
 dynformat
 elementget
 elementmake
index dafec21..a632a3d 100644 (file)
@@ -21,7 +21,6 @@ TESTS_ENVIRONMENT = \
 EXTRA_DIST = extract.pl
 
 EXAMPLES = \
-       dynamic \
        $(GNOME) \
        elementcreate \
        elementmake \
@@ -53,7 +52,7 @@ BUILT_SOURCES = \
        helloworld.c \
        init.c \
        query.c \
-       typefind.c dynamic.c \
+       typefind.c \
        blockprobe.c \
        probe.c \
        appsrc.c \
@@ -90,7 +89,7 @@ init.c: $(top_srcdir)/docs/manual/basics-init.xml
 query.c: $(top_srcdir)/docs/manual/advanced-position.xml
        $(PERL_PATH) $(srcdir)/extract.pl $@ $<
 
-typefind.c dynamic.c: $(top_srcdir)/docs/manual/advanced-autoplugging.xml
+typefind.c: $(top_srcdir)/docs/manual/advanced-autoplugging.xml
        $(PERL_PATH) $(srcdir)/extract.pl $@ $<
 
 blockprobe.c: $(top_srcdir)/docs/manual/advanced-dataaccess.xml