Understanding Bins and Ghost_pads

Ian Davidson id012c3076 at blueyonder.co.uk
Tue Jan 1 09:56:01 PST 2013


On 17/12/2012 12:13, Tim-Philipp Müller wrote:
> On Sat, 2012-12-15 at 14:47 +0000, Ian Davidson wrote:
>
> Hi,
>
>> I have compiled the helloWorld example from the GStreamer
>> documentation and it worked.
> (Our Hello World should really just be a playbin example..)
>
>
I have modified my program and it gets a little further - but it still 
does not work. The program is based on the helloworld example, but I 
wanted to create two bins with the original pipeline split between the 
two bins - and then link the bins together. The program is below.  When 
I try to run it, I get a message "Error: Internal data stream error."

Question 1.
I can see the line(s) which outputs the message, but I don't know what 
generates the message.  I tried to use gst_message_src_name - but I did 
not get the usage right.  I thought it would give me a string, but 
evidently not.  I could not get it to compile.  How can I print the 
source of the message?  What line should I write?

Question 2
I add source and demuxer into bin1.  Then, later, I link source and 
demuxer.  I am assuming that source and demuxer can only be in one place 
- and that therefore, it is the only copies that are being linked.

Question 3
I suspect that I have not linked my Ghost Pads.  How/where should I do that?

Thanks
Ian


#include <gst/gst.h>

#include <glib.h>


static gboolean
bus_call (GstBus     *bus,
           GstMessage *msg,
           gpointer    data)
{
   GMainLoop *loop = (GMainLoop *) data;

   switch (GST_MESSAGE_TYPE (msg)) {

     case GST_MESSAGE_EOS:
       g_print ("End of stream\n");
       g_main_loop_quit (loop);
       break;

     case GST_MESSAGE_ERROR: {
       gchar  *debug;
       GError *error;

       gst_message_parse_error (msg, &error, &debug);
       g_free (debug);

       g_printerr ("Error: %s\n", error->message);
       g_error_free (error);

       g_main_loop_quit (loop);
       break;
     }
     default:
       break;
   }

   return TRUE;
}


static void
on_pad_added (GstElement *element,
               GstPad     *pad,
               gpointer    data)
{
   GstPad *sinkpad;
   GstElement *decoder = (GstElement *) data;

   /* We can now link this pad with the vorbis-decoder sink pad */
   g_print ("Dynamic pad created, linking demuxer/decoder\n");

   sinkpad = gst_element_get_static_pad (decoder, "sink");

   gst_pad_link (pad, sinkpad);

   gst_object_unref (sinkpad);
}



int
main (int   argc,
       char *argv[])
{
   GMainLoop *loop;

   GstElement *bin1, *bin2, *pipeline, *pipeline1, *pipeline2, *source, 
*demuxer, *decoder, *conv, *sink, *ghostsrc, *ghostsink;
   GstBus *bus;
   GstPad *pad1, *pad2;
   guint bus_watch_id;

   /* Initialisation */
   gst_init (&argc, &argv);

   loop = g_main_loop_new (NULL, FALSE);


   /* Check input arguments */
   if (argc != 2) {
     g_printerr ("Usage: %s <Ogg/Vorbis filename>\n", argv[0]);
     return -1;
   }


   /* Create gstreamer elements */
   pipeline = gst_pipeline_new ("audio-player");
   pipeline1 = gst_pipeline_new ("pipe1");
   pipeline2 = gst_pipeline_new ("pipe2");
   bin1 = gst_bin_new ("bin1");
   bin2 = gst_bin_new ("bin2");
   source   = gst_element_factory_make ("filesrc", "file-source");
   demuxer  = gst_element_factory_make ("oggdemux", "ogg-demuxer");
   decoder  = gst_element_factory_make ("vorbisdec", "vorbis-decoder");
   conv     = gst_element_factory_make ("audioconvert", "converter");
   sink     = gst_element_factory_make ("autoaudiosink", "audio-output");
   ghostsrc = gst_element_factory_make ("fakesrc", "ghostsrc");
   ghostsink =gst_element_factory_make ("fakesink", "ghostsink");

   if (!pipeline || !pipeline1 || !pipeline2 || !bin1 ||  !bin2 || 
!source || !demuxer || !decoder || !conv || !sink) {
     g_printerr ("One element could not be created. Exiting.\n");
     return -1;
   }

   /* Set up the pipeline */

   /* we set the input filename to the source element */
   g_object_set (G_OBJECT (source), "location", argv[1], NULL);

   /* we add a message handler */
   bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
   bus_watch_id = gst_bus_add_watch (bus, bus_call, loop);
   gst_object_unref (bus);

   /* we add all elements into the pipeline */
   /* file-source | ogg-demuxer | vorbis-decoder | converter | 
alsa-output */
   g_print ("Step 1...\n");
   gst_bin_add_many (GST_BIN (bin1),
                     source, demuxer, decoder, ghostsrc, NULL);
   g_print ("Step 2...\n");
   pad1 = gst_element_get_static_pad (ghostsrc, "src");
   g_print ("Step 2a...\n");
   gst_element_add_pad (bin1, gst_ghost_pad_new ("ghostsrc", pad1));
   g_print ("Step 2b...\n");
   gst_object_unref (GST_OBJECT (pad1));
   g_print ("Step 3...\n");
   gst_bin_add_many (GST_BIN (bin2),
                     ghostsink, conv, sink, NULL);
   g_print ("Step 4...\n");
   pad2 = gst_element_get_static_pad (ghostsink, "sink");
   g_print ("Step 4a...\n");
   gst_element_add_pad (bin2, gst_ghost_pad_new ("ghostsink", pad2));
   g_print ("Step 4b...\n");
   gst_object_unref (GST_OBJECT (pad2));
   g_print ("Step 5...\n");
   gst_bin_add_many (GST_BIN (pipeline), bin1, bin2, NULL);

   /* we link the elements together */
   /* file-source -> ogg-demuxer ~> vorbis-decoder -> converter -> 
alsa-output */
   g_print ("Step 6...\n");
   gst_element_link (source, demuxer);
   g_print ("Step 7...\n");
   gst_element_link_many (conv, sink, NULL);
   g_print ("Step 8...\n");
   gst_element_link (bin1, bin2);
   g_print ("Step 9...\n");
   g_signal_connect (demuxer, "pad-added", G_CALLBACK (on_pad_added), 
decoder);

   /* note that the demuxer will be linked to the decoder dynamically.
      The reason is that Ogg may contain various streams (for example
      audio and video). The source pad(s) will be created at run time,
      by the demuxer when it detects the amount and nature of streams.
      Therefore we connect a callback function which will be executed
      when the "pad-added" is emitted.*/


   /* Set the pipeline to "playing" state*/
   g_print ("Now playing: %s\n", argv[1]);
   gst_element_set_state (pipeline, GST_STATE_PLAYING);


   /* Iterate */
   g_print ("Running...\n");
   g_main_loop_run (loop);


   /* Out of the main loop, clean up nicely */
   g_print ("Returned, stopping playback\n");
   gst_element_set_state (pipeline, GST_STATE_NULL);

   g_print ("Deleting pipeline\n");
   gst_object_unref (GST_OBJECT (pipeline));
   g_source_remove (bus_watch_id);
   g_main_loop_unref (loop);

   return 0;
}


-- 
--
Ian Davidson
--
Facts used in this message may or may not reflect an underlying 
objective reality. Facts are supplied for personal use only.
Recipients quoting supplied information do so at their own risk. Facts 
supplied may vary in whole or part from widely accepted standards.
While painstakingly researched, facts may or may not be indicative of 
actually occurring events or natural phenomena.
The author accepts no responsibility for personal loss or injury 
resulting from memorisation and subsequent use.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/gstreamer-devel/attachments/20130101/4ae570f5/attachment.html>


More information about the gstreamer-devel mailing list