mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-10 17:35:59 +00:00
docs/manual/: Try to get autoplugging working, fix type detection. Fix text in hello-world image.
Original commit message from CVS: * docs/manual/advanced-autoplugging.xml: * docs/manual/mime-world.fig: Try to get autoplugging working, fix type detection. Fix text in hello-world image.
This commit is contained in:
parent
06ab4b7831
commit
92865101cc
3 changed files with 145 additions and 72 deletions
|
@ -1,3 +1,10 @@
|
|||
2005-06-29 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
|
||||
|
||||
* docs/manual/advanced-autoplugging.xml:
|
||||
* docs/manual/mime-world.fig:
|
||||
Try to get autoplugging working, fix type detection. Fix text
|
||||
in hello-world image.
|
||||
|
||||
2005-06-29 Wim Taymans <wim@fluendo.com>
|
||||
|
||||
* gst/base/gstbasesink.c: (gst_base_sink_handle_object),
|
||||
|
|
|
@ -114,8 +114,51 @@
|
|||
was not found. The next section will introduce more useful behaviours,
|
||||
such as plugging together a decoding pipeline.
|
||||
</para>
|
||||
<programlisting><!-- example-begin typefind.c -->
|
||||
<programlisting><!-- example-begin typefind.c a -->
|
||||
#include <gst/gst.h>
|
||||
<!-- example-end typefind.c a -->
|
||||
<!-- example-begin typefind.c b --><!--
|
||||
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, &err, &debug);
|
||||
g_print ("Error: %s\n", err->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;
|
||||
}
|
||||
--><!-- example-end typefind.c b -->
|
||||
<!-- example-begin typefind.c c -->
|
||||
static gboolean
|
||||
idle_exit_loop (gpointer data)
|
||||
{
|
||||
g_main_loop_quit ((GMainLoop *) data);
|
||||
|
||||
/* once */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
cb_typefound (GstElement *typefind,
|
||||
|
@ -123,38 +166,29 @@ cb_typefound (GstElement *typefind,
|
|||
GstCaps *caps,
|
||||
gpointer data)
|
||||
{
|
||||
GMainLoop *loop = data;
|
||||
gchar *type;
|
||||
|
||||
type = gst_caps_to_string (caps);
|
||||
g_print ("Media type %s found, probability %d%%\n", type, probability);
|
||||
g_free (type);
|
||||
|
||||
/* done */
|
||||
(* (gboolean *) data) = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
cb_error (GstElement *pipeline,
|
||||
GstElement *source,
|
||||
GError *error,
|
||||
gchar *debug,
|
||||
gpointer data)
|
||||
{
|
||||
g_print ("Error: %s\n", error->message);
|
||||
|
||||
/* done */
|
||||
(* (gboolean *) data) = TRUE;
|
||||
/* since we connect to a signal in the pipeline thread context, we need
|
||||
* to set an idle handler to exit the main loop in the mainloop context.
|
||||
* Normally, your app should not need to worry about such things. */
|
||||
g_idle_add (idle_exit_loop, loop);
|
||||
}
|
||||
|
||||
gint
|
||||
main (gint argc,
|
||||
gchar *argv[])
|
||||
{
|
||||
GMainLoop *loop;
|
||||
GstElement *pipeline, *filesrc, *typefind;
|
||||
gboolean done = FALSE;
|
||||
|
||||
/* init GStreamer */
|
||||
gst_init (&argc, &argv);
|
||||
loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
/* check args */
|
||||
if (argc != 2) {
|
||||
|
@ -164,24 +198,20 @@ main (gint argc,
|
|||
|
||||
/* create a new pipeline to hold the elements */
|
||||
pipeline = gst_pipeline_new ("pipe");
|
||||
g_signal_connect (pipeline, "error", G_CALLBACK (cb_error), &done);
|
||||
gst_bus_add_watch (gst_pipeline_get_bus (GST_PIPELINE (pipeline)),
|
||||
my_bus_callback, NULL);
|
||||
|
||||
/* create file source and typefind element */
|
||||
filesrc = gst_element_factory_make ("filesrc", "source");
|
||||
g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
|
||||
typefind = gst_element_factory_make ("typefind", "typefinder");
|
||||
g_signal_connect (typefind, "have-type", G_CALLBACK (cb_typefound), &done);
|
||||
g_signal_connect (typefind, "have-type", G_CALLBACK (cb_typefound), loop);
|
||||
|
||||
/* setup */
|
||||
gst_bin_add_many (GST_BIN (pipeline), filesrc, typefind, NULL);
|
||||
gst_element_link (filesrc, typefind);
|
||||
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
|
||||
|
||||
/* now iterate until the type is found */
|
||||
do {
|
||||
if (!gst_bin_iterate (GST_BIN (pipeline)))
|
||||
break;
|
||||
} while (!done);
|
||||
g_main_loop_run (loop);
|
||||
|
||||
/* unset */
|
||||
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
|
||||
|
@ -189,7 +219,7 @@ main (gint argc,
|
|||
|
||||
return 0;
|
||||
}
|
||||
<!-- example-end typefind.c --></programlisting>
|
||||
<!-- example-end typefind.c c --></programlisting>
|
||||
<para>
|
||||
Once a media type has been detected, you can plug an element (e.g. a
|
||||
demuxer or decoder) to the source pad of the typefind element, and
|
||||
|
@ -305,7 +335,7 @@ cb_newpad (GstElement *element,
|
|||
|
||||
caps = gst_pad_get_caps (pad);
|
||||
try_to_plug (pad, caps);
|
||||
gst_caps_free (caps);
|
||||
gst_caps_unref (caps);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -314,6 +344,7 @@ close_link (GstPad *srcpad,
|
|||
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",
|
||||
|
@ -322,15 +353,18 @@ close_link (GstPad *srcpad,
|
|||
gst_object_get_name (GST_OBJECT (sinkelement)), padname);
|
||||
|
||||
/* add the element to the pipeline and set correct state */
|
||||
gst_element_set_state (sinkelement, GST_STATE_PAUSED);
|
||||
gst_bin_add (GST_BIN (pipeline), sinkelement);
|
||||
gst_pad_link (srcpad, gst_element_get_pad (sinkelement, padname));
|
||||
gst_bin_sync_children_state (GST_BIN (pipeline));
|
||||
if (sinkelement != audiosink) {
|
||||
gst_element_set_state (sinkelement, GST_STATE_PAUSED);
|
||||
gst_bin_add (GST_BIN (pipeline), sinkelement);
|
||||
}
|
||||
pad = gst_element_get_pad (sinkelement, padname);
|
||||
gst_pad_link (srcpad, pad);
|
||||
gst_object_unref (GST_OBJECT (pad));
|
||||
|
||||
/* if we have static source pads, link those. If we have dynamic
|
||||
* source pads, listen for new-pad signals on the element */
|
||||
for ( ; templlist != NULL; templlist = templlist->next) {
|
||||
GstPadTemplate *templ = GST_PAD_TEMPLATE (templlist->data);
|
||||
GstStaticPadTemplate *templ = templlist->data;
|
||||
|
||||
/* only sourcepads, no request pads */
|
||||
if (templ->direction != GST_PAD_SRC ||
|
||||
|
@ -345,7 +379,8 @@ close_link (GstPad *srcpad,
|
|||
|
||||
/* link */
|
||||
try_to_plug (pad, caps);
|
||||
gst_caps_free (caps);
|
||||
gst_object_unref (GST_OBJECT (pad));
|
||||
gst_caps_unref (caps);
|
||||
break;
|
||||
}
|
||||
case GST_PAD_SOMETIMES:
|
||||
|
@ -366,15 +401,15 @@ static void
|
|||
try_to_plug (GstPad *pad,
|
||||
const GstCaps *caps)
|
||||
{
|
||||
GstObject *parent = GST_OBJECT (gst_pad_get_parent (pad));
|
||||
GstObject *parent = GST_OBJECT (GST_OBJECT_PARENT (pad));
|
||||
const gchar *mime;
|
||||
const GList *item;
|
||||
GstCaps *res, *audiocaps;
|
||||
|
||||
/* don't plug if we're already plugged */
|
||||
/* don't plug if we're already plugged - FIXME: memleak for pad */
|
||||
if (GST_PAD_IS_LINKED (gst_element_get_pad (audiosink, "sink"))) {
|
||||
g_print ("Omitting link for pad %s:%s because we're already linked\n",
|
||||
gst_object_get_name (parent), gst_pad_get_name (pad));
|
||||
GST_OBJECT_NAME (parent), GST_OBJECT_NAME (pad));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -382,7 +417,7 @@ try_to_plug (GstPad *pad,
|
|||
mime = gst_structure_get_name (gst_caps_get_structure (caps, 0));
|
||||
if (g_strrstr (mime, "video")) {
|
||||
g_print ("Omitting link for pad %s:%s because mimetype %s is non-audio\n",
|
||||
gst_object_get_name (parent), gst_pad_get_name (pad), mime);
|
||||
GST_OBJECT_NAME (parent), GST_OBJECT_NAME (pad), mime);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -392,21 +427,21 @@ try_to_plug (GstPad *pad,
|
|||
if (res && !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_free (audiocaps);
|
||||
gst_caps_free (res);
|
||||
gst_caps_unref (audiocaps);
|
||||
gst_caps_unref (res);
|
||||
return;
|
||||
}
|
||||
gst_caps_free (audiocaps);
|
||||
gst_caps_free (res);
|
||||
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_pad_templates (factory);
|
||||
for (pads = gst_element_factory_get_static_pad_templates (factory);
|
||||
pads != NULL; pads = pads->next) {
|
||||
GstPadTemplate *templ = GST_PAD_TEMPLATE (pads->data);
|
||||
GstStaticPadTemplate *templ = pads->data;
|
||||
|
||||
/* find the sink template - need an always pad*/
|
||||
if (templ->direction != GST_PAD_SINK ||
|
||||
|
@ -415,18 +450,21 @@ try_to_plug (GstPad *pad,
|
|||
}
|
||||
|
||||
/* can it link? */
|
||||
res = gst_caps_intersect (caps, templ->caps);
|
||||
res = gst_caps_intersect (caps,
|
||||
gst_static_caps_get (&templ->static_caps));
|
||||
if (res && !gst_caps_is_empty (res)) {
|
||||
GstElement *element;
|
||||
gchar *name_template = g_strdup (templ->name_template);
|
||||
|
||||
/* close link and return */
|
||||
gst_caps_free (res);
|
||||
gst_caps_unref (res);
|
||||
element = gst_element_factory_create (factory, NULL);
|
||||
close_link (pad, element, templ->name_template,
|
||||
gst_element_factory_get_pad_templates (factory));
|
||||
close_link (pad, element, name_template,
|
||||
gst_element_factory_get_static_pad_templates (factory));
|
||||
g_free (name_template);
|
||||
return;
|
||||
}
|
||||
gst_caps_free (res);
|
||||
gst_caps_unref (res);
|
||||
|
||||
/* we only check one sink template per factory, so move on to the
|
||||
* next factory now */
|
||||
|
@ -436,7 +474,7 @@ try_to_plug (GstPad *pad,
|
|||
|
||||
/* if we get here, no item was found */
|
||||
g_print ("No compatible pad found to decode %s on %s:%s\n",
|
||||
mime, gst_object_get_name (parent), gst_pad_get_name (pad));
|
||||
mime, GST_OBJECT_NAME (parent), GST_OBJECT_NAME (pad));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -446,13 +484,16 @@ cb_typefound (GstElement *typefind,
|
|||
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 */
|
||||
try_to_plug (gst_element_get_pad (typefind, "src"), caps);
|
||||
pad = gst_element_get_pad (typefind, "src");
|
||||
try_to_plug (pad, caps);
|
||||
gst_object_unref (GST_OBJECT (pad));
|
||||
}
|
||||
<!-- example-end dynamic.c c --></programlisting>
|
||||
<para>
|
||||
|
@ -462,25 +503,49 @@ cb_typefound (GstElement *typefind,
|
|||
for video to create a player that plays both audio and video.
|
||||
</para>
|
||||
<!-- example-begin dynamic.c d --><!--
|
||||
static void
|
||||
cb_error (GstElement *pipeline,
|
||||
GstElement *source,
|
||||
GError *error,
|
||||
gchar *debug,
|
||||
gpointer data)
|
||||
static gboolean
|
||||
my_bus_callback (GstBus *bus,
|
||||
GstMessage *message,
|
||||
gpointer data)
|
||||
{
|
||||
g_print ("Error: %s\n", error->message);
|
||||
GMainLoop *loop = data;
|
||||
|
||||
switch (GST_MESSAGE_TYPE (message)) {
|
||||
case GST_MESSAGE_ERROR: {
|
||||
GError *err;
|
||||
gchar *debug;
|
||||
|
||||
gst_message_parse_error (message, &err, &debug);
|
||||
g_print ("Error: %s\n", err->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;
|
||||
gchar *p;
|
||||
|
||||
/* init GStreamer and ourselves */
|
||||
gst_init (&argc, &argv);
|
||||
loop = g_main_loop_new (NULL, FALSE);
|
||||
init_factories ();
|
||||
|
||||
/* args */
|
||||
|
@ -492,16 +557,18 @@ main (gint argc,
|
|||
/* pipeline */
|
||||
p = g_strdup_printf ("filesrc location=\"%s\" ! typefind name=tf", argv[1]);
|
||||
pipeline = gst_parse_launch (p, NULL);
|
||||
gst_bus_add_watch (gst_pipeline_get_bus (GST_PIPELINE (pipeline)),
|
||||
my_bus_callback, NULL);
|
||||
g_free (p);
|
||||
typefind = gst_bin_get_by_name (GST_BIN (pipeline), "tf");
|
||||
g_signal_connect (pipeline, "error", G_CALLBACK (cb_error), NULL);
|
||||
g_signal_connect (typefind, "have-type", G_CALLBACK (cb_typefound), NULL);
|
||||
gst_object_unref (GST_OBJECT (typefind));
|
||||
audiosink = gst_element_factory_make ("alsasink", "audiosink");
|
||||
gst_element_set_state (audiosink, GST_STATE_PAUSED);
|
||||
gst_bin_add (GST_BIN (pipeline), audiosink);
|
||||
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
|
||||
/* run */
|
||||
while (gst_bin_iterate (GST_BIN (pipeline))) ;
|
||||
g_main_loop_run (loop);
|
||||
|
||||
/* exit */
|
||||
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||
|
@ -521,8 +588,7 @@ main (gint argc,
|
|||
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>, <quote>decodebin</quote> and
|
||||
<quote>spider</quote> elements.
|
||||
see the <quote>playbin</quote> and <quote>decodebin</quote> elements.
|
||||
</para>
|
||||
</sect1>
|
||||
</chapter>
|
||||
|
|
|
@ -143,20 +143,20 @@ Single
|
|||
8775 4050 8775 5475
|
||||
2 1 1 1 0 7 50 0 -1 5.000 0 0 -1 0 0 2
|
||||
9975 4050 9975 5250
|
||||
4 0 0 50 0 16 12 0.0000 4 135 255 2175 2250 bin\001
|
||||
4 0 0 50 0 16 12 0.0000 4 135 255 2175 2250 pipeline\001
|
||||
4 0 0 50 0 16 12 0.0000 4 105 255 3525 3975 src\001
|
||||
4 0 0 50 0 16 12 0.0000 4 135 330 4725 3975 sink\001
|
||||
4 0 0 50 0 16 12 0.0000 4 105 255 6075 3975 src\001
|
||||
4 0 0 50 0 16 12 0.0000 4 135 330 7350 3975 sink\001
|
||||
4 0 0 50 0 16 12 0.0000 4 105 255 8625 3975 src\001
|
||||
4 0 0 50 0 16 12 0.0000 4 135 330 9750 3975 sink\001
|
||||
4 0 0 50 0 16 12 0.0000 4 165 1005 2250 3075 disk_source\001
|
||||
4 0 0 50 0 16 12 0.0000 4 150 465 4725 3075 parse\001
|
||||
4 0 0 50 0 16 12 0.0000 4 135 690 7275 3075 decoder\001
|
||||
4 0 0 50 0 16 12 0.0000 4 180 930 9750 3075 play_audio\001
|
||||
4 0 0 50 0 16 12 0.0000 4 165 1005 2250 3075 file source\001
|
||||
4 0 0 50 0 16 12 0.0000 4 150 465 4725 3075 ogg demuxer\001
|
||||
4 0 0 50 0 16 12 0.0000 4 135 690 7275 3075 vorbis decoder\001
|
||||
4 0 0 50 0 16 12 0.0000 4 180 930 9750 3075 audio output\001
|
||||
4 0 0 50 0 0 12 0.0000 4 135 75 3675 5475 ?\001
|
||||
4 0 0 50 0 0 12 0.0000 4 135 735 9825 5475 audio/raw\001
|
||||
4 0 0 50 0 0 12 0.0000 4 180 855 4350 5325 audio/mpeg\001
|
||||
4 0 0 50 0 0 12 0.0000 4 135 735 8700 5625 audio/raw\001
|
||||
4 0 0 50 0 0 12 0.0000 4 180 855 5775 5625 audio/mpeg\001
|
||||
4 0 0 50 0 0 12 0.0000 4 180 855 7125 5325 audio/mpeg\001
|
||||
4 0 0 50 0 0 12 0.0000 4 135 735 9825 5475 audio/x-raw-int\001
|
||||
4 0 0 50 0 0 12 0.0000 4 180 855 4350 5325 application/ogg\001
|
||||
4 0 0 50 0 0 12 0.0000 4 135 735 8700 5625 audio/x-raw-int\001
|
||||
4 0 0 50 0 0 12 0.0000 4 180 855 5775 5625 audio/x-vorbis\001
|
||||
4 0 0 50 0 0 12 0.0000 4 180 855 7125 5325 audio/x-vorbis\001
|
||||
|
|
Loading…
Reference in a new issue