<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<div class="moz-text-html" lang="x-western">
<div style="color:#000; background-color:#fff; font-family:times
new roman, new york, times, serif;font-size:12pt">
<div>I have compiled the helloWorld example from the GStreamer
documentation and it worked.<br>
<br>
To attempt to understand Bins and Pipelines and so on a bit
better, I tried to split the helloworld into two parts. I
made two bins - but they would not link together. Then, I
re-read the documentation and realised that my bins needed
Ghost Pads so that they could talk to each other. However, I
have not got it right.<br>
<br>
The program fails after printing "Step 2a" because in
gst_ghost_pad_new, the assertion GST_IS_PAD failed. Clearly,
I don't know what I am doing. Help would be appreciated.<br>
<br>
<br>
#include <gst/gst.h><br>
#include <glib.h><br>
<br>
<br>
static gboolean<br>
bus_call (GstBus *bus,<br>
GstMessage *msg,<br>
gpointer data)<br>
{<br>
GMainLoop *loop = (GMainLoop *) data;<br>
<br>
switch (GST_MESSAGE_TYPE (msg)) {<br>
<br>
case GST_MESSAGE_EOS:<br>
g_print ("End of stream\n");<br>
g_main_loop_quit (loop);<br>
break;<br>
<br>
case GST_MESSAGE_ERROR: {<br>
gchar *debug;<br>
GError *error;<br>
<br>
gst_message_parse_error (msg, &error, &debug);<br>
g_free (debug);<br>
<br>
g_printerr ("Error: %s\n", error->message);<br>
g_error_free (error);<br>
<br>
g_main_loop_quit (loop);<br>
break;<br>
}<br>
default:<br>
break;<br>
}<br>
<br>
return TRUE;<br>
}<br>
<br>
<br>
static void<br>
on_pad_added (GstElement *element,<br>
GstPad *pad,<br>
gpointer data)<br>
{<br>
GstPad *sinkpad;<br>
GstElement *decoder = (GstElement *) data;<br>
<br>
/* We can now link this pad with the vorbis-decoder sink pad
*/<br>
g_print ("Dynamic pad created, linking demuxer/decoder\n");<br>
<br>
sinkpad = gst_element_get_static_pad (decoder, "sink");<br>
<br>
gst_pad_link (pad, sinkpad);<br>
<br>
gst_object_unref (sinkpad);<br>
}<br>
<br>
<br>
<br>
int<br>
main (int argc,<br>
char *argv[])<br>
{<br>
GMainLoop *loop;<br>
<br>
GstElement *bin1, *bin2, *pipeline, *pipeline1, *pipeline2,
*source, *demuxer, *decoder, *conv, *sink, *ghostsrc,
*ghostsink;<br>
GstBus *bus;<br>
GstPad *pad1, *pad2;<br>
guint bus_watch_id;<br>
<br>
/* Initialisation */<br>
gst_init (&argc, &argv);<br>
<br>
loop = g_main_loop_new (NULL, FALSE);<br>
<br>
<br>
/* Check input arguments */<br>
if (argc != 2) {<br>
g_printerr ("Usage: %s <Ogg/Vorbis filename>\n",
argv[0]);<br>
return -1;<br>
}<br>
<br>
<br>
/* Create gstreamer elements */<br>
pipeline = gst_pipeline_new ("audio-player");<br>
pipeline1 = gst_pipeline_new ("pipe1");<br>
pipeline2 = gst_pipeline_new ("pipe2");<br>
bin1 = gst_bin_new ("bin1");<br>
bin2 = gst_bin_new ("bin2");<br>
source = gst_element_factory_make ("filesrc",
"file-source");<br>
demuxer = gst_element_factory_make ("oggdemux",
"ogg-demuxer");<br>
decoder = gst_element_factory_make ("vorbisdec",
"vorbis-decoder");<br>
conv = gst_element_factory_make ("audioconvert",
"converter");<br>
sink = gst_element_factory_make ("autoaudiosink",
"audio-output");<br>
ghostsrc = gst_element_factory_make ("fakesrc",
"ghostsrc");<br>
ghostsink =gst_element_factory_make ("fakesink",
"ghostsink");<br>
<br>
if (!pipeline || !pipeline1 || !pipeline2 || !bin1 || !bin2
|| !source || !demuxer || !decoder || !conv || !sink) {<br>
g_printerr ("One element could not be created.
Exiting.\n");<br>
return -1;<br>
}<br>
<br>
/* Set up the pipeline */<br>
<br>
/* we set the input filename to the source element */<br>
g_object_set (G_OBJECT (source), "location", argv[1], NULL);<br>
<br>
/* we add a message handler */<br>
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));<br>
bus_watch_id = gst_bus_add_watch (bus, bus_call, loop);<br>
gst_object_unref (bus);<br>
<br>
/* we add all elements into the pipeline */<br>
/* file-source | ogg-demuxer | vorbis-decoder | converter |
alsa-output */<br>
g_print ("Step 1...\n");<br>
gst_bin_add_many (GST_BIN (bin1),<br>
source, demuxer, decoder, ghostsrc, NULL);<br>
g_print ("Step 2...\n"); <br>
pad1 = gst_element_get_static_pad (ghostsrc, "ghostsrc");<br>
g_print ("Step 2a...\n"); <br>
gst_element_add_pad (bin1, gst_ghost_pad_new ("ghostsrc",
pad1));<br>
g_print ("Step 2b...\n"); <br>
gst_object_unref (GST_OBJECT (pad1));<br>
g_print ("Step 3...\n");<br>
gst_bin_add_many (GST_BIN (bin2),<br>
ghostsink, conv, sink, NULL);<br>
g_print ("Step 4...\n"); <br>
pad2 = gst_element_get_static_pad (ghostsink, "ghostsink");<br>
g_print ("Step 4a...\n"); <br>
gst_element_add_pad (bin2, gst_ghost_pad_new ("ghostsink",
pad2));<br>
g_print ("Step 4b...\n"); <br>
gst_object_unref (GST_OBJECT (pad2)); <br>
g_print ("Step 5...\n");<br>
gst_bin_add_many (GST_BIN (pipeline), bin1, bin2, NULL);<br>
<br>
/* we link the elements together */<br>
/* file-source -> ogg-demuxer ~> vorbis-decoder ->
converter -> alsa-output */<br>
g_print ("Step 6...\n");<br>
gst_element_link (source, demuxer);<br>
g_print ("Step 7...\n");<br>
gst_element_link_many (conv, sink, NULL);<br>
g_print ("Step 8...\n");<br>
gst_element_link (bin1, bin2);<br>
g_print ("Step 9...\n");<br>
g_signal_connect (demuxer, "pad-added", G_CALLBACK
(on_pad_added), decoder);<br>
<br>
/* note that the demuxer will be linked to the decoder
dynamically.<br>
The reason is that Ogg may contain various streams (for
example<br>
audio and video). The source pad(s) will be created at
run time,<br>
by the demuxer when it detects the amount and nature of
streams.<br>
Therefore we connect a callback function which will be
executed<br>
when the "pad-added" is emitted.*/<br>
<br>
<br>
/* Set the pipeline to "playing" state*/<br>
g_print ("Now playing: %s\n", argv[1]);<br>
gst_element_set_state (pipeline, GST_STATE_PLAYING);<br>
<br>
<br>
/* Iterate */<br>
g_print ("Running...\n");<br>
g_main_loop_run (loop);<br>
<br>
<br>
/* Out of the main loop, clean up nicely */<br>
g_print ("Returned, stopping playback\n");<br>
gst_element_set_state (pipeline, GST_STATE_NULL);<br>
<br>
g_print ("Deleting pipeline\n");<br>
gst_object_unref (GST_OBJECT (pipeline));<br>
g_source_remove (bus_watch_id);<br>
g_main_loop_unref (loop);<br>
<br>
return 0;<br>
}<br>
</div>
</div>
</div>
<br>
<br>
<br>
<br>
<div class="moz-signature">-- <br>
--<br>
Ian Davidson<br>
--<br>
Facts used in this message may or may not reflect an underlying
objective reality. Facts are supplied for personal use only.<br>
Recipients quoting supplied information do so at their own risk.
Facts supplied may vary in whole or part from widely accepted
standards.<br>
While painstakingly researched, facts may or may not be indicative
of actually occurring events or natural phenomena.<br>
The author accepts no responsibility for personal loss or injury
resulting from memorisation and subsequent use.
</div>
</body>
</html>