#include #ifdef __APPLE__ #include #endif /* Setup the video texture once its size is known */ void size_change (ClutterActor * texture, gint width, gint height, gpointer user_data) { ClutterActor *stage; gfloat new_x, new_y, new_width, new_height; gfloat stage_width, stage_height; ClutterAnimation *animation = NULL; stage = clutter_actor_get_stage (texture); if (stage == NULL) return; clutter_actor_get_size (stage, &stage_width, &stage_height); /* Center video on window and calculate new size preserving aspect ratio */ new_height = (height * stage_width) / width; if (new_height <= stage_height) { new_width = stage_width; new_x = 0; new_y = (stage_height - new_height) / 2; } else { new_width = (width * stage_height) / height; new_height = stage_height; new_x = (stage_width - new_width) / 2; new_y = 0; } clutter_actor_set_position (texture, new_x, new_y); clutter_actor_set_size (texture, new_width, new_height); clutter_actor_set_rotation (texture, CLUTTER_Y_AXIS, 0.0, stage_width / 2, 0, 0); /* Animate it */ animation = clutter_actor_animate (texture, CLUTTER_LINEAR, 10000, "rotation-angle-y", 360.0, NULL); clutter_animation_set_loop (animation, TRUE); } int tutorial_main (int argc, char *argv[]) { GstElement *pipeline, *sink; ClutterTimeline *timeline; ClutterActor *stage, *texture; /* clutter-gst takes care of initializing Clutter and GStreamer */ if (clutter_gst_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) { g_error ("Failed to initialize clutter\n"); return -1; } stage = clutter_stage_get_default (); /* Make a timeline */ timeline = clutter_timeline_new (1000); g_object_set (timeline, "loop", TRUE, NULL); /* Create new texture and disable slicing so the video is properly mapped onto it */ texture = CLUTTER_ACTOR (g_object_new (CLUTTER_TYPE_TEXTURE, "disable-slicing", TRUE, NULL)); g_signal_connect (texture, "size-change", G_CALLBACK (size_change), NULL); /* Build the GStreamer pipeline */ pipeline = gst_parse_launch ("playbin uri=https://gstreamer.freedesktop.org/data/media/sintel_trailer-480p.webm", NULL); /* Instantiate the Clutter sink */ sink = gst_element_factory_make ("autocluttersink", NULL); if (sink == NULL) { /* Revert to the older cluttersink, in case autocluttersink was not found */ sink = gst_element_factory_make ("cluttersink", NULL); } if (sink == NULL) { g_printerr ("Unable to find a Clutter sink.\n"); return -1; } /* Link GStreamer with Clutter by passing the Clutter texture to the Clutter sink */ g_object_set (sink, "texture", texture, NULL); /* Add the Clutter sink to the pipeline */ g_object_set (pipeline, "video-sink", sink, NULL); /* Start playing */ gst_element_set_state (pipeline, GST_STATE_PLAYING); /* start the timeline */ clutter_timeline_start (timeline); /* Add texture to the stage, and show it */ clutter_group_add (CLUTTER_GROUP (stage), texture); clutter_actor_show_all (stage); clutter_main (); /* Free resources */ gst_element_set_state (pipeline, GST_STATE_NULL); gst_object_unref (pipeline); return 0; } int main (int argc, char *argv[]) { #if defined(__APPLE__) && TARGET_OS_MAC && !TARGET_OS_IPHONE return gst_macos_main ((GstMainFunc) tutorial_main, argc, argv, NULL); #else return tutorial_main (argc, argv); #endif }