Hi all, I am totally new with GSteamer, so sorry for the lots of mistakes I have. I am trying to do the example of this link in C/C++ <a href="http://notes.brooks.nu/gstreamer-video-crossfade-example/">http://notes.brooks.nu/gstreamer-video-crossfade-example/</a><br>
It's about crossfade. I doing it with .AVI files.<br><br>At runtime I got the Resource not found error. Another examples, like a playbin, work properly with .AVI's, so I don't think is a codec issue.<br>The video files are passing as arguments (uri format).<br>
<br>Thanks in advance.<br><br>/////////////////////////<br>Heres the code<br><br><br>#include <gst.h><br>#include <controller/gstcontroller.h><br><br>#include <iostream><br><br>using namespace std;<br><br>
// Error handler<br>static gboolean bus_call (GstBus *bus, GstMessage *msg, gpointer data)<br>{<br> GMainLoop *loop = (GMainLoop *) data;<br><br> switch (GST_MESSAGE_TYPE (msg))<br> {<br> case GST_MESSAGE_EOS:<br>
g_print ("Final de stream\n");<br> g_main_loop_quit (loop);<br> break;<br> case GST_MESSAGE_ERROR:<br> {<br> gchar *debug;<br> GError *error;<br> gst_message_parse_error (msg, &error, &debug);<br>
g_free (debug);<br> g_printerr ("Error: %s\n", error->message);<br> g_error_free (error);<br> g_main_loop_quit (loop);<br> break;<br> }<br> default:<br> break;<br>
}<br> return TRUE;<br>}<br><br>static void on_pad_added (GstElement *element, GstPad *pad, gpointer data)<br>{<br> GstPad *sinkpad;<br> GstElement * queue = (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> sinkpad = gst_element_get_static_pad (queue, "sink");<br><br> gst_pad_link (pad, sinkpad);<br><br> gst_object_unref (sinkpad);<br>}<br>
<br>GstElement * getBin(const gchar * nomBin, GstElement * &alfa1, GstElement *&alfa2, GstElement * &color)<br>{<br><br> GstElement * bin = gst_bin_new(nomBin);<br><br> if (!bin)<br> {<br> g_printerr ("No se pudo crear el bin. Saliendo\n");<br>
return NULL;<br> }<br><br> alfa1 = gst_element_factory_make ("alpha","alfa1");<br> alfa2 = gst_element_factory_make ("alpha","alfa2");<br> color = gst_element_factory_make ("ffmpegcolorspace", "color");<br>
GstElement * mixer = gst_element_factory_make("videomixer", "mixer");<br><br> if ((!alfa1) || (!alfa2) || (!color) || (!mixer))<br> {<br> g_printerr ("Alguno de los elementos del Bin no pudo ser creado. Saliendo\n");<br>
return NULL;<br> }<br><br> // Anexamos al bin<br> gst_bin_add_many(GST_BIN (bin),alfa1,alfa2,mixer,color,NULL);<br><br> // Enlazamos elementos<br> gst_element_link (alfa1, mixer);<br> gst_element_link (alfa2, mixer);<br>
gst_element_link (mixer,color);<br><br> return bin;<br>}<br><br>void getAndSetController(GstElement * alfa2, gdouble duracion)<br>{<br> GstController * ctrl = NULL;<br> if (!(ctrl = gst_controller_new (G_OBJECT (alfa2), "alpha",NULL))) {<br>
GST_WARNING ("No puede controlar el elemento fuente\n");<br> return;<br> }<br><br> // Todo valor GValue debe inicializarse en 0<br> GValue val_double = { 0, };<br> g_value_init (&val_double, G_TYPE_DOUBLE);<br>
<br><br> // Seteo los valores de control del alfa2<br><br> GstInterpolationControlSource * csource = gst_interpolation_control_source_new();<br><br> gst_controller_set_control_source (ctrl, "alpha", GST_CONTROL_SOURCE (csource));<br>
<br> gst_interpolation_control_source_set_interpolation_mode(csource,GST_INTERPOLATE_LINEAR);<br><br><br> g_value_set_double(&val_double, 0.0);<br> gst_interpolation_control_source_set(csource,(0* GST_MSECOND),&val_double); <br>
<br> g_value_set_double (&val_double, duracion);<br> gst_interpolation_control_source_set(csource,(1 * GST_MSECOND),&val_double);<br><br><br> g_object_unref (csource);<br><br>}<br><br>void addGhostPadsToBin(GstElement *alfa1, GstElement * alfa2, GstElement * color, GstElement* bin)<br>
{<br> /* add ghostpad */<br> GstPad * pad1 = gst_element_get_static_pad (alfa1, "sink");<br> gst_element_add_pad(bin, gst_ghost_pad_new("alfasink1", pad1));<br> gst_object_unref (GST_OBJECT (pad1));<br>
<br> GstPad * pad2 = gst_element_get_static_pad (alfa2, "sink");<br> gst_element_add_pad(bin, gst_ghost_pad_new("alfasink2", pad2));<br> gst_object_unref(GST_OBJECT(pad2));<br><br> GstPad * pad3 = gst_element_get_static_pad (color, "src");<br>
gst_element_add_pad(bin, gst_ghost_pad_new("colorsrc", pad3));<br> gst_object_unref(GST_OBJECT(pad3));<br> <br><br>}<br><br>void crossFade(gdouble duracion, GstElement * & bin)<br>{<br> // devuelve el bin<br>
GstElement * alfa1, *alfa2, *color;<br> alfa1 = 0;<br> alfa2 = 0;<br> color = 0;<br><br> bin = getBin("bin",alfa1, alfa2,color); // Crea el bin y los elementos<br><br> getAndSetController(alfa2,duracion);<br>
<br> addGhostPadsToBin(alfa1, alfa2, color, bin);<br> <br><br>}<br><br>GstElement * getSetPipeline(gchar *argv[])<br>{<br> gint dur1 = 9000; // duration (in ms) to play of first clip<br> gint dur2 = 8000; // duration (in ms) to play of second clip<br>
gint dur_crossfade = 500; //number of milliseconds to crossfade for<br> GstElement *comp = 0;<br> GstElement *pipeline, *video1, *video2, *op, *bin, *queue, *sink;<br><br> //we play two clips serially with a crossfade between them<br>
// using the gnonlin gnlcomposition element.<br> if ((comp = gst_element_factory_make("gnlcomposition", "mycomposition")) == NULL)<br> {<br> printf ("\n Fallo al crear gnlcomposition \n");<br>
return NULL;<br> }<br><br> // setup first clip<br><br> if ((video1 = gst_element_factory_make("gnlfilesource", "video1")) == NULL)<br> {<br> printf ("\n Falló la creacion del gnlfilesource \n");<br>
return NULL;<br> }<br> if (gst_bin_add (GST_BIN (comp), video1) == FALSE)<br> {<br> printf ("\n No pudo agregar video1 a comp \n");<br> return NULL;<br> }<br><br> g_object_set (video1, "location", argv[1], NULL);<br>
g_object_set (video1, "start", 0 * GST_MSECOND, NULL);<br> g_object_set (video1, "duration", dur1 * GST_MSECOND, NULL);<br> g_object_set (video1, "media-start", 0* GST_MSECOND, NULL);<br>
g_object_set (video1, "media-duration", dur1 * GST_MSECOND, NULL);<br> g_object_set (video1, "priority", 1,NULL);<br><br> if ((video2 = gst_element_factory_make("gnlfilesource", "video2")) == NULL)<br>
{<br> printf ("\n Falló la creacion del gnlfilesource \n");<br> return NULL;<br> }<br> if (gst_bin_add (GST_BIN (comp), video2) == FALSE)<br> {<br> printf ("\n No pudo agregar video2 a comp \n");<br>
return NULL;<br> }<br><br> // setup second clip<br> g_object_set (video2, "location", argv[2], NULL);<br> g_object_set (video2, "start", (dur1-dur_crossfade) * GST_MSECOND, NULL);<br>
g_object_set (video2, "duration", dur2 * GST_MSECOND, NULL);<br> g_object_set (video2, "media-start", 0 * GST_MSECOND, NULL);<br> g_object_set (video2, "media-duration", dur2 * GST_MSECOND, NULL);<br>
g_object_set (video2, "priority", 2,NULL);<br><br> // setup the crossfade<br> op = gst_element_factory_make("gnloperation", "op");<br><br> crossFade(dur_crossfade, bin);<br><br> if (gst_bin_add (GST_BIN (op), bin) == FALSE)<br>
{<br> printf ("\n No pudo agregar el bin a la gnloperacion op \n");<br> return NULL;<br> }<br><br> g_object_set (op,"start", (dur1-dur_crossfade) * GST_MSECOND,NULL);<br> g_object_set (op,"duration", dur_crossfade * GST_MSECOND,NULL);<br>
g_object_set (op,"media-start", 0 * GST_MSECOND,NULL);<br> g_object_set(op,"media-duration", dur_crossfade * GST_MSECOND,NULL);<br> g_object_set(op,"priority",0,NULL);<br><br> if (gst_bin_add (GST_BIN (comp), op) == FALSE)<br>
{<br> printf ("\n No pudo agregar la gnloperacion a la gnlcomposition \n");<br> return NULL;<br> }<br><br> // setup the backend viewer<br> queue = gst_element_factory_make("queue", "queue");<br>
sink = gst_element_factory_make("autovideosink", "sink");<br><br> pipeline = gst_pipeline_new ("video-player");<br><br><br> /* Agrego elementos al pipeline */<br><br> gst_bin_add_many (GST_BIN (pipeline),comp, queue, sink, NULL);<br>
<br> g_signal_connect (comp, "pad-added", G_CALLBACK (on_pad_added), queue);<br><br> gst_element_link (queue, sink);<br><br> cout << "creó pipeline!!!" << endl;<br><br> return pipeline;<br>
<br>}<br><br>void startPlay(GstElement * pip)<br>{<br> /* Set the pipeline to "playing" state*/<br> cout << "antes del PLAY" << endl;<br> gst_element_set_state (pip, GST_STATE_PLAYING);<br>
cout << "dp del PLAY" << endl;<br><br>}<br><br><br>int main(gint argc, gchar *argv[])<br>{<br> GMainLoop *loop = NULL;<br><br> /* init GStreamer */<br> gst_init (&argc, &argv);<br>
gst_controller_init (&argc, &argv);<br><br><br> loop = g_main_loop_new (NULL, FALSE);<br><br> /* make sure we have a URI */<br> if (argc != 3)<br> {<br> g_print ("Uso: %s <URI1> <URI2>\n", argv[0]);<br>
return -1;<br> }<br><br> GstElement * play = getSetPipeline(argv);<br><br> cout << "creo pipeline" << endl;<br><br> GstBus *bus2 = gst_pipeline_get_bus (GST_PIPELINE (play));<br> gst_bus_add_watch (bus2, bus_call, loop);<br>
gst_object_unref (bus2);<br><br> cout << "start play" << endl;<br><br> startPlay(play);<br><br> /* now run */<br> g_main_loop_run (loop);<br><br> /* also clean up */<br> gst_element_set_state (play, GST_STATE_NULL);<br>
gst_object_unref (GST_OBJECT (play));<br> return 0;<br>}<br><br><br><br>