Hi, I'm trying to do an audio crossfade, it plays the first audio file correctly, but when it should play the second one, these errors come:<br><br>mad gstmad.c:1489:gst_mad_chain: mad_header_decode had an error: lost synchronization<br>
0:00:11.054542971 5898 0x1757a60 WARN mad gstmad.c:1516:gst_mad_chain: mad_frame_decode had an error: reserved header layer v<br><br>I could did the video crossfade with a similar technique. I appreciate any tip on about what I am doing wrong.<br>
<br>Thanks and regards.<br><br>Rossana<br><br>Here's the core of the code:<br><br><br>static void on_pad_added (GstElement *element, GstPad *pad, gpointer data)<br>{<br> GstPad *sinkpad = NULL;<br> GstElement * queue = (GstElement *) data;<br>
<br> /* Ahora linkeo el pad de comp con sink pad */<br> g_print ("Dynamic pad created, linking queue\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><br>GstElement * getBin(const gchar * nomBin, GstElement * &v1, GstElement *&v2, GstElement * &mad1, GstElement * &mad2, GstElement * &mixer)<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> v1 = gst_element_factory_make ("volume","vol1");<br> v2 = gst_element_factory_make ("volume","vol2");<br>
mad1 = gst_element_factory_make ("mad","mad1");<br> mad2 = gst_element_factory_make ("mad","mad2");<br><br> mixer = gst_element_factory_make("adder", "mixer");<br>
<br><br> if ((!v1) || (!v2) || (!mad1) || (!mad2) || (!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),v1,v2,mad1,mad2,mixer, NULL);<br><br> gst_element_link (mad1,v1);<br> gst_element_link (mad2,v2);<br> g_print("enlazo los mad con los volumenes \n");<br><br><br> /* Now link volume outs to adder ins, on request */<br>
GstPad *pad = 0;<br><br> /* src #1 */<br> pad = gst_element_get_request_pad(mixer, "sink%d");<br> g_assert(pad != NULL);<br> gst_pad_link(gst_element_get_pad(v1, "src"), pad);<br> /* Same thing for #2 */<br>
pad = gst_element_get_request_pad (mixer, "sink%d");<br> g_assert(pad != NULL);<br> gst_pad_link(gst_element_get_pad(v2, "src"), pad);<br><br> g_print("hasta aqui ok!!! \n");<br> <br><br>
return bin;<br>}<br><br>void getAndSetController(GstElement * volumen2, gdouble duracion)<br>{<br> GstController * ctrl = NULL;<br> if (!(ctrl = gst_controller_new (G_OBJECT (volumen2), "volume",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> // Creo la fuente al controlador y la asocio al controlador<br> // Seteo modo de interpolacion<br><br> GstInterpolationControlSource * csource = gst_interpolation_control_source_new();<br> gst_controller_set_control_source (ctrl, "volume", GST_CONTROL_SOURCE (csource));<br>
<br> gst_interpolation_control_source_set_interpolation_mode(csource,GST_INTERPOLATE_LINEAR);<br><br> // Seteo primer valor<br> g_value_set_double(&val_double, 0.0);<br> gst_interpolation_control_source_set(csource,(0 * GST_MSECOND),&val_double);<br>
<br> // Seteo segundo valor<br> g_value_set_double (&val_double, 1.0);<br> gst_interpolation_control_source_set(csource,(duracion * GST_MSECOND),&val_double);<br><br><br> g_object_unref (csource);<br><br>}<br>
<br>void addGhostPadsToBin(GstElement *mad1, GstElement * mad2, GstElement * mixer, GstElement* bin)<br>{<br> /* add ghostpad */<br> GstPad * pad1 = gst_element_get_static_pad (mad1, "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 (mad2, "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 (mixer, "src");<br> gst_element_add_pad(bin, gst_ghost_pad_new("mixersrc", pad3));<br> gst_object_unref(GST_OBJECT(pad3));<br>}<br><br>void crossTransicion(gdouble duracion, GstElement * & bin,gint transicion = 1)<br>
{<br> // devuelve el bin<br> GstElement * volumen1, *volumen2, *mad1,*mad2,*mixer;<br> volumen1 = 0;<br> volumen2 = 0;<br> mad1 = 0;<br> mad2 = 0;<br> mixer = 0;<br><br> bin = getBin("bin",volumen1, volumen2,mad1,mad2,mixer); // Crea el bin y los elementos<br>
<br> getAndSetController(volumen2,duracion);<br><br> addGhostPadsToBin(mad1, mad2, mixer, bin);<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, *audio1, *audio2, *op, *bin, *queue, *sink;<br>
<br> // ejecuta 2 clips serialmente con un crosdfade entre ellos usando el elemento (GnlOlin) gnlcomposition<br> if ((comp = gst_element_factory_make("gnlcomposition", "micomposicion")) == NULL)<br>
{<br> printf ("\n Fallo al crear gnlcomposition \n");<br> return NULL;<br> }<br><br> GstCaps *caps = gst_caps_from_string("audio/x-raw-int;audio/x-raw-float");<br><br> // Create our composition<br>
g_object_set(G_OBJECT(comp), "caps", caps, NULL);<br><br> op = gst_element_factory_make("gnloperation", "op");<br><br> crossTransicion(dur_crossfade, bin,1);<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> // configura primer clip<br><br> if ((audio1 = gst_element_factory_make("gnlfilesource", "audio1")) == NULL)<br>
{<br> printf ("\n Falló la creacion del gnlfilesource \n");<br> return NULL;<br> }<br> if (gst_bin_add (GST_BIN (comp), audio1) == FALSE)<br> {<br> printf ("\n No pudo agregar audio1 a comp \n");<br>
return NULL;<br> }<br><br> g_object_set (audio1, "location", argv[1], NULL);<br> g_object_set(audio1, "uri", argv[1],NULL);<br> g_object_set (audio1, "start", 0 * GST_MSECOND, NULL);<br>
g_object_set (audio1, "duration", dur1 * GST_MSECOND, NULL);<br> g_object_set (audio1, "media-start", 0* GST_MSECOND, NULL);<br> g_object_set (audio1, "media-duration", dur1 * GST_MSECOND, NULL);<br>
g_object_set (audio1, "priority", 1,NULL);<br><br> // crea 2º clip<br> if ((audio2 = gst_element_factory_make("gnlfilesource", "audio2")) == NULL)<br> {<br> printf ("\n Falló la creacion del gnlfilesource \n");<br>
return NULL;<br> }<br><br> if (gst_bin_add (GST_BIN (comp), audio2) == FALSE)<br> {<br> printf ("\n No pudo agregar video2 a comp \n");<br> return NULL;<br> }<br><br> g_object_set (audio2, "location", argv[2], NULL);<br>
g_object_set (audio2,"uri",argv[2],NULL);<br> g_object_set (audio2, "start", (dur1-dur_crossfade) * GST_MSECOND, NULL);<br> g_object_set (audio2, "duration", dur2 * GST_MSECOND, NULL);<br>
g_object_set (audio2, "media-start", 0 * GST_MSECOND, NULL);<br> g_object_set (audio2, "media-duration", dur2 * GST_MSECOND, NULL);<br> g_object_set (audio2, "priority", 2,NULL);<br>
<br> // setup the backend viewer<br> queue = gst_element_factory_make("queue", "queue");<br> sink = gst_element_factory_make("autoaudiosink", "sink");<br><br> pipeline = gst_pipeline_new ("audio-player");<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> return pipeline;<br><br>}<br><br>void startPlay(GstElement * pip)<br>{<br> /* Set the pipeline to "playing" state*/<br> gst_element_set_state (pip, GST_STATE_PLAYING);<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> loop = g_main_loop_new (NULL, FALSE);<br><br> /* chequeamos sintaxis */<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><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 << "...PLAY" << endl;<br><br> startPlay(play);<br> GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(play), GST_DEBUG_GRAPH_SHOW_ALL,"audio2");<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>