[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