Crossfading-transition between more than 2 videos.

Rossana Guerra guerra.rossana at gmail.com
Mon Sep 26 13:18:59 PDT 2011


Hi Angel, thanks for your suggest, I did what you suggested but it didn't
work. It only play the 1st vido. So I put back the variables. In fact, I
want to have a play list, so I need to calculate the next start/duration
attribute (I need variables for that).
As I said if I test with 2 videos it works fine, the problems is when a 3rd
one comes to the scenario.

This is the situation. I want to play a playlist with crossfade between
videos. The crossfade time is fixed: 500ms.
The first video lasts 9000ms
The 2nd lasts 8000ms.
The 3rd lasts 9000ms.

2nd video, start duration: 9000 - 500 // video1 duration - crossfade
duration
3rd video start duration: 9000 + 8000 - 2*500  // video1 duration + video 2
duration - 2 * crossfade duration

According some test I did, it has to do with starting time of both,
operation and 3rd video.

Thanks and any suggestion is welcome.

Here's the problematic part (start and duration with fixed attributes,
didn't work)

void playSigVideo(gchar *argv[], GstElement *& video2, gint dur1, 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);

    // Playing 2nd video
    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 (op,"start", (dur1 + dur2 - 2*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);

   // Playin 3rd video, which is the first one played
    g_object_set (video2, "location", argv[1], NULL);
    g_object_set (video2,"uri",argv[1],NULL);
    g_object_set (video2, "start", (dur1 + dur2 - 2*dur_crossfade) *
GST_MSECOND, NULL);
    g_object_set (video2, "duration", dur1 * GST_MSECOND, NULL);
    g_object_set (video2, "media-start", 0 * GST_MSECOND, NULL);
    g_object_set (video2, "media-duration", dur1 * GST_MSECOND, NULL);
    g_object_set (video2, "priority", 3,NULL);

}



2011/9/26 Angel Martin <amartin at vicomtech.org>

> Hello,
>
> I suggest you to remove variable start and duration attributes and put
> fixed values instead in order to have a clear schedule of the different
> elements involved.
>
> Moreover, the priority of the operation should be always minor that the
> videos involved, I suggest you to put a 0 always in the transition operation
> priority.
>
> Best Regards,
>
> Angel
>
> 2011/9/25 Rossana Guerra <guerra.rossana at gmail.com>
>
>> Hello everyone, I am trying to do crossfade between 3 videos. It works
>> fine when I do the same with 2, but when I put the 3rd something happens and
>> the player displays only the first.
>> Actually I use 2 videos, and I did a playlist such video1 -> video2 ->
>> video2, where the 3rd time, I set the new starting time of the video2
>> object.
>>
>> video1 starts at 0, and its durations is dur1
>> I use an operator to handle the alpha channel, it starts at dur1 -
>> dur_crossfade
>> video2, starts at dur1 - dur_crossfade
>> And the starting time of video 2 the third time is dur1 + dur2 -
>> dur_crossfade.
>>
>> Maybe it's something wrong with the priority or start properties values, I
>> am very new with GStreamer, I could make several mistakes.
>>
>> Thanks and regards,
>>
>> Rossana
>>
>>
>> Here's the code:
>>
>>
>> const gint dur_crossfade = 500;
>>
>> // Error handler
>> static gboolean bus_call (GstBus *bus, GstMessage *msg, gpointer data)
>> {
>>
>>   :::::::::::::::::::::::::::::::::
>>     return TRUE;
>> }
>>
>> static void on_pad_added (GstElement *element, GstPad *pad, gpointer
>> data)
>> {
>>   GstPad *sinkpad = NULL;
>>   GstElement * queue = (GstElement *) data;
>>
>>   /* Ahora linkeo el pad de comp con sink pad */
>>   g_print ("Dynamic pad created, linking queue\n");
>>   sinkpad = gst_element_get_static_pad (queue, "sink");
>>
>>   gst_pad_link (pad, sinkpad);
>>
>>   gst_object_unref (sinkpad);
>>
>> }
>>
>> 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);
>>
>>   // Enlazamos elementos
>>   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;
>>    }
>>
>>   // Todo valor GValue debe inicializarse en 0
>>   GValue val_double = { 0, };
>>   g_value_init (&val_double, G_TYPE_DOUBLE);
>>
>>
>>   // Create de controller, source and set the interpolation mode
>>
>>   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);
>>
>>   // Set first value
>>   g_value_set_double(&val_double, 0.0);
>>   gst_interpolation_control_source_set(csource,(0 *
>> GST_MSECOND),&val_double);
>>
>>   // Ser 2nd value
>>   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 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)
>> {
>>
>>     GstElement *queue, *sink, *pipeline, *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
>>     queue = gst_element_factory_make("queue", "queue");
>>     sink  = gst_element_factory_make("autovideosink", "sink");
>>
>>     pipeline = gst_pipeline_new ("video-player");
>>
>>     /* Agrego elementos al pipeline */
>>
>>     gst_bin_add_many (GST_BIN (pipeline),comp, queue, sink, NULL);
>>
>>     g_signal_connect (comp, "pad-added", G_CALLBACK (on_pad_added),queue);
>>
>>     gst_element_link (queue, sink);
>>
>>     cout << "...PLAY" << endl;
>>
>>     gst_element_set_state (pipeline, GST_STATE_PLAYING);
>>
>>     return pipeline;
>> }
>>
>>
>> void playSigVideo(gchar *argv[], GstElement *& video2, gint dur1, 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);
>>
>>     gst_element_set_state (pip, GST_STATE_PLAYING);
>>
>>     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 (op,"start", ((dur2+dur1)- 2*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",3,NULL);
>>
>>     g_object_set (video2, "location", argv[1], NULL);
>>     g_object_set (video2,"uri",argv[1],NULL);
>>     g_object_set (video2, "start", ((dur2 + dur1) - 2*dur_crossfade) *
>> GST_MSECOND, NULL);
>>     g_object_set (video2, "duration", dur1 * GST_MSECOND, NULL);
>>     g_object_set (video2, "media-start", 0 * GST_MSECOND, NULL);
>>     g_object_set (video2, "media-duration", dur1 * GST_MSECOND, NULL);
>>     g_object_set (video2, "priority", 4,NULL);
>>
>> }
>>
>>
>> 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
>>     //gint dur_crossfade = 500; //number of milliseconds to crossfade for
>>     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;
>>     }
>>
>>     GstElement *comp = NULL;
>>     GstElement *op = NULL;
>>     GstElement *video1,*video2;
>>
>>     GstElement *play = getPipeline3(argv,video1, dur1,video2,comp, op);
>>
>>     playSigVideo(argv,video2, dur1, 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;
>>
>>
>>     /* 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;
>> }
>>
>>
>>
>>
>> _______________________________________________
>> gstreamer-devel mailing list
>> gstreamer-devel at lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
>>
>>
>
>
> _______________________________________________
> gstreamer-devel mailing list
> gstreamer-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/gstreamer-devel/attachments/20110926/42b54d34/attachment-0001.htm>


More information about the gstreamer-devel mailing list