[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