[gst-devel] switch and seeking again
Thomas Comiotto
comiotto at rcfmedia.ch
Fri Jan 30 08:57:04 CET 2004
Hello,
I am still facing sort of strange difficulties getting things to work as
excpected with cvs-head and/or 7.3. My goal is still to create a simple
video-loop player, switching between several video sources, some of them
stored in files, others recieved as networked streams or from a v4l device. I
have some additional restrictions though: filesrc's should go into paused
state when switching to a different source, and continue playing at where
they were when re-activated (so I can't just load another file and play that,
I also can't feed a seek to 0 event into the pipe since then all involved
streams would seek to 0)
What I have managed to get in sort of a acceptable state is the following
setup:
videotestsrc ! switch
filesrc ! spider ! colorspace ! switch
switch ! videoscale ! ximagesink
I catch eos of the containing bin and send the srcpad of filesrc a seek to 0
event. Looping is ok although I get a
** (switcher:20597): CRITICAL **: file gstvideoscale.c: line 370
(gst_videoscale_chain): assertion `size == videoscale->from_buf_size' failed
(switcher:20597): GStreamer-CRITICAL **: file gstdata.c: line 236
(gst_data_unref): assertion `GST_DATA_REFCOUNT_VALUE (data) > 0' failed
error after/every time seeking is done.
Switching to filesrc is done without latency while switching back to
videotestsrc takes more and more time the longer the program runs - after
running it for a minute it takes about 5 seconds to switch back while
switching to the movie still happens immediately. Additionally, setting
filesrc to paused makes switch dropping some "not pulling from sink1" msgs
that of course make sense on one hand, on the other hand you probably want to
pause bins connected to unrouted channels and let them do nothing. I guess
currently a demuxer/decoder chain connected to an inactive sink pad of switch
will continue decoding and therefore use cpu resources for that?
Anyway, I wanted a different setup, so I added a second bin containing
filesrc2 ! spider2 ! colorspace2 and connected that so switch.
The result was a scheduler in error state. After commenting out the first
filesrc chain it worked just fine, playing the second filesrc without
complaining, so I come up with the following questions:
(1) how can I use multiple demuxer / decoder chains connected to switch,
possibly using spider.
(2) how can I let only a subset of elements seeking to somewhere? (purely
theoretical question at the moment because of (1))
Below my testing snippet.
Greetings,
Thomas
#include <gst/gst.h>
#include <gst/xoverlay/xoverlay.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include <unistd.h>
#include <stdlib.h>
#include "gstvideowidget.h"
GstElement *bin, *videobin, *videobin2;
GstElement *filesrc, *filesrc2, *v4lsrc;
GstElement *spider, *spider2, *colorspace, *colorspace2, *ffcolorspace,
*videotestsrc;
GstElement *switchbox;
GstElement *videoscale, *videosink;
GstCaps *scalecaps;
gint placement;
/* GTK Widgets */
GtkWidget *main_window;
GtkWidget *gstvideowidget;
void
eos (GstElement *element, gpointer data)
{
g_print ("have eos\n");
gst_element_set_state (bin, GST_STATE_PAUSED);
if (gst_pad_send_event (gst_element_get_pad (filesrc, "src"),
gst_event_new_seek (GST_SEEK_METHOD_SET | GST_FORMAT_BYTES, 0))) g_print
("gesendet");
gst_element_set_state (bin, GST_STATE_PLAYING);
}
static
gboolean key_press_event (GtkWidget *widget, GdkEventKey *event)
{
switch (event->keyval)
{
case GDK_Escape:
gtk_main_quit();
break;
case GDK_1:
{
g_object_set (G_OBJECT (switchbox), "active-source", 0, NULL);
break;
}
case GDK_2:
{
g_object_set (G_OBJECT (switchbox), "active-source", 1, NULL);
break;
}
case GDK_3:
{
g_object_set (G_OBJECT (switchbox), "active-source", 2, NULL);
break;
}
}
return TRUE;
}
void
init_all ()
{
scalecaps = gst_caps_new_simple ("video/x-raw-rgb",
"height", G_TYPE_INT, gdk_screen_height ()/2,
"width", G_TYPE_INT, gdk_screen_width ()/2,
NULL);
bin = gst_thread_new ("main bin");
switchbox = gst_element_factory_make ("switch", "switchbox");
videoscale = gst_element_factory_make ("videoscale", "videoscale");
videosink = gst_element_factory_make ("ximagesink", "videosink");
gst_element_link (switchbox, videoscale);
if (! gst_element_link_filtered (videoscale, videosink, scalecaps))
g_error ("Could not link filtered caps");
videotestsrc = gst_element_factory_make ("videotestsrc", "videotestsrc");
gst_pad_link (gst_element_get_pad (videotestsrc, "src"),
gst_element_get_request_pad (switchbox, "sink%d"));
videobin = gst_bin_new ("video bin");
g_signal_connect (G_OBJECT (videobin), "eos", G_CALLBACK (eos), NULL);
filesrc = gst_element_factory_make ("filesrc", "filesrc");
g_object_set (G_OBJECT (filesrc), "location", "/home/knoppix/videotestfiles/
test.mpg", NULL);
spider = gst_element_factory_make ("spider", "spider");
colorspace = gst_element_factory_make ("colorspace", "colorspace");
gst_element_add_ghost_pad (videobin, gst_element_get_pad (colorspace, "src"),
"src");
gst_element_link_many (filesrc, spider, colorspace, NULL);
gst_pad_link (gst_element_get_pad (videobin, "src"),
gst_element_get_request_pad (switchbox, "sink%d"));
gst_bin_add_many (GST_BIN (videobin), filesrc, spider, colorspace, NULL);
videobin2 = gst_bin_new ("video bin2");
g_signal_connect (G_OBJECT (videobin2), "eos", G_CALLBACK (eos), NULL);
filesrc2 = gst_element_factory_make ("filesrc", "filesrc2");
g_object_set (G_OBJECT (filesrc2), "location", "/home/knoppix/slsk-shared/
cash.mpg", NULL);
spider2 = gst_element_factory_make ("spider", "spider2");
colorspace2 = gst_element_factory_make ("colorspace", "colorspace2");
gst_element_add_ghost_pad (videobin2, gst_element_get_pad (colorspace2,
"src"), "src");
gst_element_link_many (filesrc2, spider2, colorspace2, NULL);
gst_pad_link (gst_element_get_pad (videobin2, "src"),
gst_element_get_request_pad (switchbox, "sink%d"));
gst_bin_add_many (GST_BIN (videobin2), filesrc2, spider2, colorspace2, NULL);
v4lsrc = gst_element_factory_make ("v4lsrc", "v4lsrc");
ffcolorspace = gst_element_factory_make ("ffcolorspace", "ffcolorspace");
gst_bin_add_many (GST_BIN (bin), videotestsrc, videobin, videobin2,
switchbox, videoscale, videosink, NULL);
/* GUI */
main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gstvideowidget = gst_video_widget_new ();
gtk_container_add (GTK_CONTAINER (main_window), gstvideowidget);
gtk_widget_show (gstvideowidget);
gtk_window_set_decorated(GTK_WINDOW(main_window), FALSE);
g_signal_connect (G_OBJECT (main_window), "key-press-event", G_CALLBACK
(key_press_event), NULL);
gtk_widget_show (main_window);
if (placement == 1) gtk_widget_set_uposition (main_window, 0, 0);
else if (placement == 2) gtk_widget_set_uposition (main_window,
gdk_screen_width ()/2, 0);
else if (placement == 3) gtk_widget_set_uposition (main_window, 0,
gdk_screen_height ()/2);
else if (placement == 4) gtk_widget_set_uposition (main_window,
gdk_screen_width ()/2, gdk_screen_height ()/2);
gtk_widget_set_usize (main_window, gdk_screen_width ()/2, gdk_screen_height
()/2);
gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (videosink),
GDK_WINDOW_XID(gstvideowidget->window));
}
gint
main (gint argc, char *argv[])
{
gtk_init (&argc, &argv);
gst_init (&argc, &argv);
placement = 1;
sscanf(argv[1], "%d", &placement);
init_all ();
gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING);
gtk_main ();
g_print("quitting\n");
gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
return 0;
}
More information about the gstreamer-devel
mailing list