On Sat, Jul 07, 2007 at 11:32:19AM +0200, David Härdeman wrote:
On Sat, Jul 07, 2007 at 01:48:22AM +0100, Bastien Nocera wrote:
On Sat, 2007-07-07 at 02:46 +0200, David Härdeman wrote:
<snip>
With this I get some visualizations when playing but it doesn't look right, the visualization is only shown at very brief intervals and then overwritten with the solid color of the stage again...I'm not sure what I'm doing wrong...

Totem uses GStreamer's playbin and visualisations. You might want to
take a quick looks at the GStreamer backend in totem/src/backend.

That is what I did when I wrote the sample...so either I messed up in copying the relevant parts from totem or the ClutterTexture messes things up...

I created a second version to test whether Clutter has something to do with the weird visualization.

When I create a separate video sink (an ximagesink) and plug that in as the video sink of the ClutterGstVideoTexture, everything works as expected.

#define NOCLUTTERTEXTURE 1 at the top of visual.c to try it.

When I use the default ClutterGstVideoSink as the video sink of the ClutterGstVideoTexture, I see the problems described above.

#define NOCLUTTERTEXTURE 0 at the top of visual.c to try it.

--
David Härdeman
#include <clutter-gst/clutter-gst.h>
#include <string.h>
#include <stdlib.h>

#define WIDTH 640
#define HEIGTH 480
#define SCALE 1
#define FPS 20
#define VISUALIZATION "goom"
#define NOCLUTTERTEXTURE 1

static void
die(char *msg)
{
	g_error(msg);
	exit(EXIT_FAILURE);
}

static gboolean
filter_features (GstPluginFeature * feature, gpointer data)
{
	GstElementFactory *f;

	if (!GST_IS_ELEMENT_FACTORY (feature))
		return FALSE;
	f = GST_ELEMENT_FACTORY (feature);
		if (!g_strrstr (gst_element_factory_get_klass (f), "Visualization"))
	return FALSE;

	return TRUE;
}

static void
add_visualization(ClutterGstVideoTexture *video_texture)
{
	GList *features;
	GList *feature;
	GstElementFactory *tmp;
	GstElementFactory *fac = NULL;
	GstElement *vis_bin;
	GstElement *vis_element;
	GstElement *vis_capsfilter;
	GstElement *playbin;
	GstPad *pad;
	GstCaps *caps;

	features = gst_registry_feature_filter(gst_registry_get_default(),
					       filter_features, FALSE, NULL);

	for (feature = features; feature; feature = feature->next) {
		tmp = GST_ELEMENT_FACTORY(feature->data);
		fprintf(stderr, "Found visualization: %s\n", GST_PLUGIN_FEATURE_NAME(tmp));
		if (!strcmp(GST_PLUGIN_FEATURE_NAME(tmp), VISUALIZATION))
			fac = tmp;
	}
	g_list_free(features);

	if (!fac)
		die("Failed to find visualization");
	else
		fprintf(stderr, "Using visualization " VISUALIZATION "\n");

	vis_element = gst_element_factory_create(fac, "vis_element");
	if (!GST_IS_ELEMENT(vis_element))
		die("Failed to create vis");

	vis_capsfilter = gst_element_factory_make("capsfilter", "vis_capsfilter");
	if (!GST_IS_ELEMENT(vis_capsfilter))
		die("Failed to create caps");

	vis_bin = gst_bin_new ("vis_bin");
	if (!GST_IS_ELEMENT (vis_bin))
		die("Failed to create bin");

	gst_bin_add_many(GST_BIN(vis_bin), vis_element, vis_capsfilter, NULL);

	/* Sink ghostpad */
	pad = gst_element_get_pad(vis_element, "sink");
	gst_element_add_pad(vis_bin, gst_ghost_pad_new("sink", pad));
	gst_object_unref(pad);

	/* Source ghostpad, link with vis_element */
	pad = gst_element_get_pad(vis_capsfilter, "src");
	gst_element_add_pad(vis_bin, gst_ghost_pad_new("src", pad));
	gst_element_link_pads(vis_element, "src", vis_capsfilter, "sink");
	gst_object_unref (pad);

	/* Get allowed output caps from visualisation element */
	pad = gst_element_get_pad(vis_element, "src");
	caps = gst_pad_get_allowed_caps(pad);
	gst_object_unref(pad);

	/* Can we fixate ? */
	if (caps && !gst_caps_is_fixed(caps)) {
		guint i;

		caps = gst_caps_make_writable(caps);

		/* Get visualization size */
		for (i = 0; i < gst_caps_get_size (caps); ++i) {
			GstStructure *s = gst_caps_get_structure (caps, i);

			/* Fixate */
			gst_structure_fixate_field_nearest_int(s, "width", WIDTH / SCALE);
			gst_structure_fixate_field_nearest_int(s, "height", HEIGTH / SCALE);
			gst_structure_fixate_field_nearest_fraction(s, "framerate", FPS, 1);
		}

		/* set this */
		g_object_set(vis_capsfilter, "caps", caps, NULL);
	}

	playbin = clutter_gst_video_texture_get_playbin(video_texture);

	if (NOCLUTTERTEXTURE) {
		GstElement *video = gst_element_factory_make("ximagesink", "video-sink");
		g_object_set (G_OBJECT(playbin), "vis-plugin", vis_bin, "video-sink", video, NULL);
	} else {
		g_object_set(playbin, "vis-plugin", vis_bin, NULL);
	}
}

int
main (int argc, char *argv[])
{
	ClutterActor *stage;
	ClutterActor *video;
	ClutterColor stage_color = { 0x00, 0x00, 0x00, 0xff };

	if (argc < 2)
		die("Missing argument");

	clutter_init(&argc, &argv);
	gst_init(&argc, &argv);
	stage = clutter_stage_get_default();
	clutter_stage_set_color(CLUTTER_STAGE(stage), &stage_color); 
	clutter_actor_set_size(stage, WIDTH, HEIGTH);

	video = g_object_new(CLUTTER_GST_TYPE_VIDEO_TEXTURE, "sync-size", FALSE, "tiled", FALSE, NULL);
	if (!video)
		die("Failed to create video texture");

	clutter_media_set_volume(CLUTTER_MEDIA(video), 1.0);
	clutter_media_set_filename(CLUTTER_MEDIA(video), argv[1]);
	clutter_group_add(CLUTTER_GROUP(stage), video);
	clutter_actor_set_size(video, WIDTH, HEIGTH);
	add_visualization(CLUTTER_GST_VIDEO_TEXTURE(video));

	clutter_media_set_playing(CLUTTER_MEDIA(video), TRUE);
	clutter_actor_show_all(stage);
	g_signal_connect(stage, "key-press-event", G_CALLBACK(clutter_main_quit), NULL);
	clutter_main();

	return EXIT_SUCCESS;
}

Reply via email to