[gst-devel] Linking elements with dynamic pads.

Louis Bouchard lbouchard at sat.qc.ca
Tue Nov 15 09:16:01 CET 2005


Hi,

I am trying to set up a pipeline to capture video from a dv camera. 
The pipeline goes like this:

dv1394src -> ffdemux_dv -> ffdec_dvvideo - > fakesink

(the fakesink uses a handoff function to save the buffers)

My problem is with ffdemux_dv:  since it's got dynamic source pads, I
need to link it after the first pipeline iteration, which I do.  But
it seems that linking the video source of the demuxer to the sink of
the decoder breaks the whole pipeline.  But the tests I run tells me
everything is connected properly.

The flow of the program goes like this:

1 - connect dv1394src to the sink of ffdemux_dv w/ filtered caps -- works fine
2 - connect  ffdec_dvvideo's source to the sink of fakesink w/
filtered caps -- works fine
3 - start iterating -> ffdemux_dv calls it's callback function to
create the sources 'video_00' and 'audio_00'.
4 - in the callback function connects ffdemux_dv's video_00 pad to the
sink of ffdec_dvvideo -- works fine...
5 - the pipeline doesn't do anyting anymore and i don't know why.

I used a simple probe to see what was going on, what pads were working
or not..  If I  link the probe to dv1394src, the probe fires 3 times
after the first iteration but never after ffdemux_dv's new_pad
callback has been called.  I am at a loss.

my code is included below.  bear in mind that im just trying to make
the thing work before maknig my code beautiful.

thanks in advance,

Louis Bouchard



****************************************************
#include <gst/gst.h>
#include <sys/time.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
/*
 * Global objects are usually a bad thing. For the purpose of this
 * example, we will use them, however.
 */

GstElement *pipeline, *source, *demuxer, *parser, *decoder, *encoder,
*conv, *scale, *sink, *fakesink;

GstPad *imgPad;
GstBuffer *imgBuffer;

int imgNumber = 0;
int imgWidth = 0;
int imgHeight = 0;
int imgDepth = 0;

/************************************************************/

static void
cb_new_pad (GstElement *element,
	    GstPad     *pad,
	    gpointer    data)
{

  GstCaps* caps;
  int answer;
  g_print ("A new pad %s was created\n", gst_pad_get_name (pad));

  if ( strcmp(  gst_pad_get_name (pad), "video_00") != 0 ) {
    printf("new pad is not video, no linking done\n");
    return;
  }

  caps = gst_caps_new_simple ("video/x-dv",
                              "width", G_TYPE_INT, 720,
                              "height", G_TYPE_INT, 480,
                              "framerate", G_TYPE_DOUBLE, 29.970029970029969,
                              "systemstream", G_TYPE_BOOLEAN, FALSE,
                              NULL);

   answer = gst_pad_can_link_filtered ( pad,
                                       gst_element_get_pad( decoder, "sink" ),
                                       caps);

   printf( "can demuxer and decoder be linked with x-dv? ");
   if (answer) printf( "YES!\n" );
   else  printf( "NOOOOO!\n" );

   answer = gst_pad_link_filtered ( pad,
                                    gst_element_get_pad( decoder, "sink" ),
                                    caps);

   printf( "... are they ACTUALLY linked?? ");
   if (answer) printf( "YES!\n" );
   else  printf( "NOOOOO!\n" );

   /* big bunch of tests ... just to make sure im not missing
anything.. none of them come back negative anyways..  */

  gst_element_set_state (source, GST_STATE_READY);
  gst_element_set_state (decoder, GST_STATE_READY);
  gst_element_set_state (demuxer, GST_STATE_READY);
  gst_element_set_state (fakesink, GST_STATE_READY);

  if (gst_element_get_state (source) != GST_STATE_READY)
printf("source not ready\n");
  if (gst_element_get_state (decoder) != GST_STATE_READY)
printf("source not ready\n");
  if (gst_element_get_state (demuxer) != GST_STATE_READY)
printf("source not ready\n");
  if (gst_element_get_state (fakesink) != GST_STATE_READY)
printf("source not ready\n");

  gst_pad_set_active( gst_element_get_pad(source, "src"), TRUE ) ;
  gst_pad_set_active( gst_element_get_pad(demuxer, "sink"), TRUE ) ;
  gst_pad_set_active( gst_element_get_pad(demuxer, "video_00"), TRUE );
  gst_pad_set_active( gst_element_get_pad(decoder, "sink"), TRUE ) ;
  gst_pad_set_active( gst_element_get_pad(decoder, "src"), TRUE  );
  gst_pad_set_active( gst_element_get_pad(fakesink, "sink") , TRUE );


  if ( !GST_PAD_IS_LINKED( gst_element_get_pad(source, "src") ) )
printf( "source not linked\n");
  if ( !GST_PAD_IS_LINKED( gst_element_get_pad(demuxer, "sink") ) )
printf( "demux sink not linked\n");
  if ( !GST_PAD_IS_LINKED( gst_element_get_pad(demuxer, "video_00") )
) printf( "demux video_00 not linked\n");
  if ( !GST_PAD_IS_LINKED( gst_element_get_pad(decoder, "sink") ) )
printf( "decoder sink not linked\n");
  if ( !GST_PAD_IS_LINKED( gst_element_get_pad(decoder, "src") ) )
printf( "decoder src not linked\n");
  if ( !GST_PAD_IS_LINKED( gst_element_get_pad(fakesink, "sink") ) )
printf( "fakesink sink not linked\n");

  if ( !GST_PAD_IS_ACTIVE( gst_element_get_pad(source, "src") ) )
printf( "source not active\n");
  if ( !GST_PAD_IS_ACTIVE( gst_element_get_pad(demuxer, "sink") ) )
printf( "demux sink not active\n");
  if ( !GST_PAD_IS_ACTIVE( gst_element_get_pad(demuxer, "video_00") )
) printf( "demux video_00 not active\n");
  if ( !GST_PAD_IS_ACTIVE( gst_element_get_pad(decoder, "sink") ) )
printf( "decoder sink not active\n");
  if ( !GST_PAD_IS_ACTIVE( gst_element_get_pad(decoder, "src") ) )
printf( "decoder src not active\n");
  if ( !GST_PAD_IS_ACTIVE( gst_element_get_pad(fakesink, "sink") ) )
printf( "fakesink sink not active\n");

}

/************************************************************/

static void debug_probe    (GstProbe *probe,
                            GstData **data,
                            gpointer user_data)
{

  printf("PROBE!!!!!\n");

}

/************************************************************/


static void handoff(GstElement *element,
                    GstBuffer  *buffer,
                    GstPad     *pad,
                    gpointer    user_data)
{
  char filename[100];

  time_t tm;
  time(&tm);

  sprintf(filename, "img%05i.pgm", imgNumber++);
  printf( "saving file %s -- time: %s", filename, ctime(&tm) );

  /* save the buffer to a file */

}

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


  GstCaps* caps;
  GstProbe *probe;
  int answer;

  /* initialize GStreamer */
  gst_init (&argc, &argv);

  pipeline = gst_pipeline_new ("dv-grabber");
  source = gst_element_factory_make ("dv1394src", "source");
  demuxer = gst_element_factory_make( "ffdemux_dv", "demuxer" );
  decoder = gst_element_factory_make ("ffdec_dvvideo", "decoder");
  fakesink = gst_element_factory_make ("fakesink", "fakesink");


  /* listen for newly created pads */
  g_signal_connect (demuxer, "new-pad", G_CALLBACK (cb_new_pad), NULL);

  /* connect a handoff to the fakesink to save the incoming buffers */
  printf( "connecting the handoff function\n" );
  g_object_set (G_OBJECT (fakesink), "signal-handoffs", TRUE, NULL);
  g_signal_connect (fakesink, "handoff", G_CALLBACK (handoff), NULL);

  /* debug probe that just says 'PROBE!!!' */
  probe = gst_probe_new (FALSE, (GstProbeCallback) debug_probe, NULL);
  gst_pad_add_probe (gst_element_get_pad (source, "src"), probe);

  printf( "adding elements to the bin\n" );

  gst_bin_add_many( GST_BIN (pipeline), source, demuxer,
                    decoder, fakesink, NULL) ;



  printf( "linking elements\n" );

  caps = gst_caps_new_simple ("video/x-dv",
                              "format", G_TYPE_STRING, "NTSC",
                              "systemstream", G_TYPE_BOOLEAN, TRUE,
                              NULL);

  answer = gst_pad_can_link_filtered (gst_element_get_pad( source, "src" ),
                                      gst_element_get_pad( demuxer, "sink" ),
                                      caps);


  printf( "can source and demuxer be linked with x-dv? ");
  if (answer) printf( "YES!\n" );
  else  printf( "NOOOOO!\n" );

  answer = gst_pad_link_filtered (gst_element_get_pad( source, "src" ),
                                  gst_element_get_pad( demuxer, "sink" ),
                                  caps);


  printf( "... are they ACTUALLY linked?? ");
  if (answer) printf( "YES!\n" );
  else  printf( "NOOOOO!\n" );

  printf( "setting capabilities\n" );

  caps = gst_caps_new_simple ("video/x-raw-rgb",
                              "bpp", G_TYPE_INT, 24,
                              "depth", G_TYPE_INT, 24,
                              "endianness", G_TYPE_INT, 4321,
                              "red_mask", G_TYPE_INT, 16711680,
                              "green_mask", G_TYPE_INT, 65280,
                              "blue_mask", G_TYPE_INT, 255,
                              "width", G_TYPE_INT, 720,
                              "height", G_TYPE_INT, 480,
                              NULL);


   answer = gst_pad_can_link_filtered (gst_element_get_pad( decoder, "src" ),
                                       gst_element_get_pad( fakesink, "sink" ),
                                       caps);

   printf( "can decoder and fakesink be linked with x-raw-rgb? ");
   if (answer) printf( "YES!\n" );
   else  printf( "NOOOOO!\n" );

   answer = gst_pad_link_filtered (gst_element_get_pad( decoder, "src" ),
                                   gst_element_get_pad( fakesink, "sink" ),
                                   caps);
   printf( "... are they ACTUALLY linked?? ");
   if (answer) printf( "YES!\n" );
   else  printf( "NOOOOO!\n" );

  /* Now set to playing and iterate. We will set the decoder and
   * audio output to ready so they initialize their memory already.
   * This will decrease the amount of time spent on linking these
   * elements when the Ogg parser emits the new-pad signal. */

  printf( "setting ready state for elements\n" );

  gst_element_set_state (source, GST_STATE_READY);
  gst_element_set_state (decoder, GST_STATE_READY);
  gst_element_set_state (demuxer, GST_STATE_READY);
  gst_element_set_state (fakesink, GST_STATE_READY);

  if ( !source || !decoder || !demuxer || !fakesink )
    fprintf (stderr, "ERROR: one element not created.\n");

  if (gst_element_set_state (pipeline, GST_STATE_PLAYING) ==
GST_STATE_FAILURE) {
    fprintf (stderr, "ERROR: pipeline doesn't want to play.\n");
  }

  printf( "do it!\n" );

  /* and now iterate - the rest will be automatic from here on.
   * When the file is finished, gst_bin_iterate () will return
   * FALSE, thereby terminating this loop. */
  while (gst_bin_iterate (GST_BIN (pipeline))) ;

  /* clean up nicely */
  gst_element_set_state (pipeline, GST_STATE_NULL);
  gst_object_unref (GST_OBJECT (pipeline));

  printf("done... \n");

  return 0;
}

*************************************************************************




More information about the gstreamer-devel mailing list