Problem with AVI files, there's no sound
Rossana Guerra
guerra.rossana at gmail.com
Sun Oct 9 22:18:06 PDT 2011
Hi I a beginner with GStreamer, I am clueless about of the behavior and role
of some GStreamer elements.
I am trying to do a player with a transition-crossfade effect, it works for
avi files, but without sound. My piplene was compound by the composition,
queue and videosink elements.
I was said I need to add an avidemuxer and I did, but doesn't work anymore.
I use this example as a base
http://lists.freedesktop.org/archives/gstreamer-devel/2008-October/019240.html,
but any adaptation didn't work for me.
This is the runtime error I got:
"GStreamer-CRITICAL **: gst_pad_link_full: assertion `GST_IS_PAD (sinkpad)'
failed"
it seems it couldn't get the pad between the composition and the avidemuxer,
I have been working around with decoders, but there are pad linking errors
as well.
Thanks for any suggestion, regards
Rossana
This is the code and the pipeline is below it.
const gint dur_crossfade = 500;
static GstElement *play = NULL;
static GstElement *comp = NULL;
static GstElement *op = NULL;
static GstElement *video1,*video2;
// error handler
static gboolean bus_call (GstBus *bus, GstMessage *msg, gpointer data)
{
// code for hadling errors
return TRUE;
}
static void on_pad_added (GstElement *element, GstPad *pad, gpointer data)
{
GstPad *sinkpad = NULL;
GstElement * queue = (GstElement *) data;
g_print ("Dynamic pad created, linking queue\n");
sinkpad = gst_element_get_compatible_pad(queue,pad
,gst_pad_get_caps(pad));
gst_pad_link (pad, sinkpad);
gst_object_unref (sinkpad);
}
void on_pad_added2 (GstElement *element, GstPad *pad,GstElement *dec )
{
g_debug ("Signal: pad-added");
GstCaps *caps;
GstStructure *str;
caps = gst_pad_get_caps (pad);
g_assert (caps != NULL);
str = gst_caps_get_structure (caps, 0);
g_assert (str != NULL);
if (g_strrstr (gst_structure_get_name (str), "video")) {
g_debug ("Linking video pad to dec_vd");
// Link it actually
GstPad *targetsink = gst_element_get_pad (dec, "sink");
g_assert (targetsink != NULL);
gst_pad_link (pad, targetsink);
gst_object_unref (targetsink);
}
if (g_strrstr (gst_structure_get_name (str), "audio")) {
g_debug ("Linking audio pad to dec_ad");
// Link it actually
GstPad *targetsink = gst_element_get_pad (dec, "sink");
g_assert (targetsink != NULL);
gst_pad_link (pad, targetsink);
gst_object_unref (targetsink);
}
gst_caps_unref (caps);
}
GstElement * getBin(const gchar * nomBin, GstElement * &alfa1, GstElement
*&smpte, GstElement * &color, gint transicion = 1)
{
GstElement * bin = gst_bin_new(nomBin);
if (!bin)
{
g_printerr ("No se pudo crear el bin. Saliendo\n");
return NULL;
}
alfa1 = gst_element_factory_make ("alpha","alfa1");
smpte = gst_element_factory_make ("smptealpha","smpte");
color = gst_element_factory_make ("ffmpegcolorspace", "color");
GstElement * mixer = gst_element_factory_make("videomixer", "mixer");
if ((!alfa1) || (!smpte) || (!color) || (!mixer))
{
g_printerr ("Alguno de los elementos del Bin no pudo ser creado.
Saliendo\n");
return NULL;
}
// Anexamos al bin
gst_bin_add_many(GST_BIN (bin),alfa1,smpte,mixer,color,NULL);
gst_element_link (alfa1, mixer);
gst_element_link (smpte, mixer);
gst_element_link (mixer,color);
g_object_set(smpte,"type", transicion, NULL);
return bin;
}
void getAndSetController(GstElement * smpte, gdouble duracion)
{
GstController * ctrl = NULL;
if (!(ctrl = gst_controller_new (G_OBJECT (smpte), "alpha",NULL))) {
GST_WARNING ("No puede controlar el elemento fuente\n");
return;
}
GValue val_double = { 0, };
g_value_init (&val_double, G_TYPE_DOUBLE);
GstInterpolationControlSource * csource =
gst_interpolation_control_source_new();
gst_controller_set_control_source (ctrl, "alpha", GST_CONTROL_SOURCE
(csource));
gst_interpolation_control_source_set_interpolation_mode(csource,GST_INTERPOLATE_LINEAR);
// Seteo primer valor
g_value_set_double(&val_double, 0.0);
gst_interpolation_control_source_set(csource,(0 *
GST_MSECOND),&val_double);
// Seteo segundo valor
g_value_set_double (&val_double, duracion);
gst_interpolation_control_source_set(csource,(1 *
GST_MSECOND),&val_double);
g_object_unref (csource);
}
void addGhostPadsToBin(GstElement *alfa1, GstElement * smpte, GstElement *
color, GstElement* bin)
{
/* add ghostpad */
GstPad * pad1 = gst_element_get_static_pad (alfa1, "sink");
gst_element_add_pad(bin, gst_ghost_pad_new("alfasink1", pad1));
gst_object_unref (GST_OBJECT (pad1));
GstPad * pad2 = gst_element_get_static_pad (smpte, "sink");
gst_element_add_pad(bin, gst_ghost_pad_new("alfasink2", pad2));
gst_object_unref(GST_OBJECT(pad2));
GstPad * pad3 = gst_element_get_static_pad (color, "src");
gst_element_add_pad(bin, gst_ghost_pad_new("colorsrc", pad3));
gst_object_unref(GST_OBJECT(pad3));
}
void crossTransicion(gdouble duracion, GstElement * & bin,gint transicion =
1)
{
// devuelve el bin
GstElement * alfa1, *smpte, *color;
alfa1 = 0;
smpte = 0;
color = 0;
bin = getBin("bin",alfa1, smpte,color,transicion); // Crea el bin y los
elementos
getAndSetController(smpte,duracion);
addGhostPadsToBin(alfa1, smpte, color, bin);
}
GstElement * crearVideo(const gchar *nomVideo, GstElement *&comp)
{
GstElement* video = NULL;
if ((video = gst_element_factory_make("gnlfilesource", nomVideo)) == NULL)
{
printf ("\n Falló la creacion del gnlfilesource \n");
return NULL;
}
if (gst_bin_add (GST_BIN (comp), video) == FALSE)
{
printf ("\n No pudo agregar video %s a comp \n", nomVideo);
return NULL;
}
return video;
}
void crearBinyCrossfade(GstElement *&op, GstElement *&bin2)
{
crossTransicion(dur_crossfade, bin2,1);
op = gst_element_factory_make("gnloperation", "op");
if (gst_bin_add (GST_BIN (op), bin2) == FALSE)
{
printf ("\n No pudo agregar el bin a la gnloperacion op \n");
return;
}
// comp es Global
if (gst_bin_add (GST_BIN (comp), op) == FALSE)
{
printf ("\n No pudo agregar la gnloperacion a la gnlcomposition \n");
return;
}
}
void crearCompYoper(GstElement*& compo, GstElement *&op, GstElement*& bin2)
{
if ((compo = gst_element_factory_make("gnlcomposition",
"micomposicion")) == NULL)
{
printf ("\n Fallo al crear gnlcomposition \n");
return;
}
//Aqui se crea el bin
crossTransicion(dur_crossfade, bin2,1);
op = gst_element_factory_make("gnloperation", "op");
if (gst_bin_add (GST_BIN (op), bin2) == FALSE)
{
printf ("\n No pudo agregar el bin a la gnloperacion op \n");
return;
}
if (gst_bin_add (GST_BIN (compo), op) == FALSE)
{
printf ("\n No pudo agregar la gnloperacion a la gnlcomposition \n");
return;
}
}
/// Aqui pipeline3
GstElement * getPipeline3(gchar *argv[],GstElement *&video1, gint dur1,
GstElement *& video2,GstElement *& comp, GstElement *&op)
{
queueA, *sinkV,*sinkA, *decA, *decV, *demux, *pipeline, *aconvert,*bin;
crearCompYoper(comp, op,bin);
video1 = crearVideo("video1",comp);
video2 = crearVideo("video2",comp);
g_object_set (video1, "location", argv[1], NULL);
g_object_set(video1, "uri", argv[1],NULL);
g_object_set (video1, "start", 0 * GST_MSECOND, NULL);
g_object_set (video1, "duration", dur1 * GST_MSECOND, NULL);
g_object_set (video1, "media-start", 0* GST_MSECOND, NULL);
g_object_set (video1, "media-duration", dur1 * GST_MSECOND, NULL);
g_object_set (video1, "priority", 1,NULL);
// setup the backend viewer
queueA = gst_element_factory_make("queue", "queueA");
queueV = gst_element_factory_make("queue", "queueV");
sinkV = gst_element_factory_make("autovideosink", "sink1");
sinkA = gst_element_factory_make("alsasink", "sink2");
demux = gst_element_factory_make("avidemux", "demux");
pipeline = gst_pipeline_new ("video-player");
/* Agrego elementos al pipeline */
gst_bin_add_many (GST_BIN (pipeline),comp, demux, queueV, sinkV, queueA,
sinkA, decA, NULL);
g_signal_connect (comp, "pad-added", G_CALLBACK (on_pad_added),demux);
g_signal_connect (demux, "pad-added", G_CALLBACK
(on_pad_added2),queueA);
g_signal_connect (demux, "pad-added", G_CALLBACK
(on_pad_added2),queueV);
gst_element_link (comp, demux);
gst_element_link (queueV, sinkV);
gst_element_link (queueA, sinkA);
return pipeline;
}
void playSigVideo(gchar *argv[], GstElement *& video1, gint dur1,GstElement
*& video2, gint dur2,GstElement *&op, GstElement *pip)
{
g_object_set (op,"start", (dur1 - dur_crossfade) * GST_MSECOND,NULL);
g_object_set (op,"duration", dur_crossfade * GST_MSECOND,NULL);
g_object_set (op,"media-start", 0 * GST_MSECOND,NULL);
g_object_set(op,"media-duration", dur_crossfade * GST_MSECOND,NULL);
g_object_set(op,"priority",0,NULL);
g_object_set (video2, "location", argv[2], NULL);
g_object_set (video2,"uri",argv[2],NULL);
g_object_set (video2, "start", (dur1 - dur_crossfade) * GST_MSECOND,
NULL);
g_object_set (video2, "duration", dur2 * GST_MSECOND, NULL);
g_object_set (video2, "media-start", 0 * GST_MSECOND, NULL);
g_object_set (video2, "media-duration", dur2 * GST_MSECOND, NULL);
g_object_set (video2, "priority", 2,NULL);
//g_object_set(video2,"caps",gst_caps_from_string("video/x-raw-yuv;video/x-raw-rgb"),NULL);
//g_object_set(video2,"caps",gst_caps_from_string("audio/x-dv"),NULL);
}
void startPlay(GstElement * pip)
{
/* Set the pipeline to "playing" state*/
gst_element_set_state (pip, GST_STATE_PLAYING);
}
int main(gint argc, gchar *argv[])
{
gint dur1 = 9000; // d uration (in ms) to play of first clip
gint dur2 = 8000; // duration (in ms) to play of second clip
GMainLoop *loop = NULL;
/* init GStreamer */
gst_init (&argc, &argv);
gst_controller_init (&argc, &argv);
loop = g_main_loop_new (NULL, FALSE);
/* chequeamos sintaxis */
if (argc != 3)
{
g_print ("Uso: %s <URI1> <URI2>\n", argv[0]);
return -1;
}
play = getPipeline3(argv,video1, dur1,video2,comp, op);
playSigVideo(argv,video1,dur1,video2,dur2,op,play);
GstBus *bus2 = gst_pipeline_get_bus (GST_PIPELINE (play));
gst_bus_add_watch (bus2, bus_call, loop);
gst_object_unref (bus2);
cout << "...PLAY" << endl;
startPlay(play);
/* now run */
g_main_loop_run (loop);
/* also clean up */
gst_element_set_state (play, GST_STATE_NULL);
gst_object_unref (GST_OBJECT (play));
return 0;
}
bin
-----------------------------------------------------------------------------------------------
alpha --------------------
|----------videomixer ------------fmpegcolorspace
smptealpha ----------
^
|
-----------------------------------------------------------------------------------------------
|
Controller // it controls the start-duration property of smptealpha
composition
--------------------------------------------------------------------------------------------------------
gnlfilesource
| gnloperation // contains the *bin*
described above
|
gnlfilesource
--------------------------------------------------------------------------------------------------------
gnlfilesource is for each video
pipeline
____________________
|
|
composition operation |___________ avidemux ____________ queueV
___________ sinkV
___________________ |
____________ queueA
___________ sinkA
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/gstreamer-devel/attachments/20111010/3ee8680f/attachment-0001.html>
More information about the gstreamer-devel
mailing list