Crossfading-transition between more than 2 videos.
Rossana Guerra
guerra.rossana at gmail.com
Mon Sep 26 23:00:27 PDT 2011
Hi another thing I noticed is that it takes the last properties I set to
video2.
I meant, I execute video2 twice with differents properties, first for those
corresponding to argv[2], and the second to argv[1].
Whatever were the values at argv[2] it doesn't matter if argv[1] are the
correct ones.
I mean this:
video1
video2, argv[2] to play at x time
video2 argv[1] to play after video1
It skips argv[2], so it keeps with the las values set. So, how I do to play
a playlist with crossfade?.
I wish I were clear.
Thanks,
Ro
2011/9/26 Rossana Guerra <guerra.rossana at gmail.com>
> 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/20110927/1e5d7a1e/attachment.html>
More information about the gstreamer-devel
mailing list