4 #define GRAPH_LENGTH 78
8 GST_PLAY_FLAG_DOWNLOAD = (1 << 7) /* Enable progressive download (on selected formats) */
11 typedef struct _CustomData {
18 static void got_location (GstObject *gstobject, GstObject *prop_object, GParamSpec *prop, gpointer data) {
20 g_object_get (G_OBJECT (prop_object), "temp-location", &location, NULL);
21 g_print ("Temporary file: %s\n", location);
23 /* Uncomment this line to keep the temporary file after the program exits */
24 /* g_object_set (G_OBJECT (prop_object), "temp-remove", FALSE, NULL); */
27 static void cb_message (GstBus *bus, GstMessage *msg, CustomData *data) {
29 switch (GST_MESSAGE_TYPE (msg)) {
30 case GST_MESSAGE_ERROR: {
34 gst_message_parse_error (msg, &err, &debug);
35 g_print ("Error: %s\n", err->message);
39 gst_element_set_state (data->pipeline, GST_STATE_READY);
40 g_main_loop_quit (data->loop);
45 gst_element_set_state (data->pipeline, GST_STATE_READY);
46 g_main_loop_quit (data->loop);
48 case GST_MESSAGE_BUFFERING:
49 /* If the stream is live, we do not care about buffering. */
50 if (data->is_live) break;
52 gst_message_parse_buffering (msg, &data->buffering_level);
54 /* Wait until buffering is complete before start/resume playing */
55 if (data->buffering_level < 100)
56 gst_element_set_state (data->pipeline, GST_STATE_PAUSED);
58 gst_element_set_state (data->pipeline, GST_STATE_PLAYING);
60 case GST_MESSAGE_CLOCK_LOST:
62 gst_element_set_state (data->pipeline, GST_STATE_PAUSED);
63 gst_element_set_state (data->pipeline, GST_STATE_PLAYING);
66 /* Unhandled message */
71 static gboolean refresh_ui (CustomData *data) {
75 query = gst_query_new_buffering (GST_FORMAT_PERCENT);
76 result = gst_element_query (data->pipeline, query);
78 gint n_ranges, range, i;
79 gchar graph[GRAPH_LENGTH + 1];
80 gint64 position = 0, duration = 0;
82 memset (graph, ' ', GRAPH_LENGTH);
83 graph[GRAPH_LENGTH] = '\0';
85 n_ranges = gst_query_get_n_buffering_ranges (query);
86 for (range = 0; range < n_ranges; range++) {
88 gst_query_parse_nth_buffering_range (query, range, &start, &stop);
89 start = start * GRAPH_LENGTH / (stop - start);
90 stop = stop * GRAPH_LENGTH / (stop - start);
91 for (i = (gint)start; i < stop; i++)
94 if (gst_element_query_position (data->pipeline, GST_FORMAT_TIME, &position) &&
95 GST_CLOCK_TIME_IS_VALID (position) &&
96 gst_element_query_duration (data->pipeline, GST_FORMAT_TIME, &duration) &&
97 GST_CLOCK_TIME_IS_VALID (duration)) {
98 i = (gint)(GRAPH_LENGTH * (double)position / (double)(duration + 1));
99 graph [i] = data->buffering_level < 100 ? 'X' : '>';
101 g_print ("[%s]", graph);
102 if (data->buffering_level < 100) {
103 g_print (" Buffering: %3d%%", data->buffering_level);
114 int main(int argc, char *argv[]) {
115 GstElement *pipeline;
117 GstStateChangeReturn ret;
118 GMainLoop *main_loop;
122 /* Initialize GStreamer */
123 gst_init (&argc, &argv);
125 /* Initialize our data structure */
126 memset (&data, 0, sizeof (data));
127 data.buffering_level = 100;
129 /* Build the pipeline */
130 pipeline = gst_parse_launch ("playbin uri=https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL);
131 bus = gst_element_get_bus (pipeline);
133 /* Set the download flag */
134 g_object_get (pipeline, "flags", &flags, NULL);
135 flags |= GST_PLAY_FLAG_DOWNLOAD;
136 g_object_set (pipeline, "flags", flags, NULL);
138 /* Uncomment this line to limit the amount of downloaded data */
139 /* g_object_set (pipeline, "ring-buffer-max-size", (guint64)4000000, NULL); */
142 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
143 if (ret == GST_STATE_CHANGE_FAILURE) {
144 g_printerr ("Unable to set the pipeline to the playing state.\n");
145 gst_object_unref (pipeline);
147 } else if (ret == GST_STATE_CHANGE_NO_PREROLL) {
151 main_loop = g_main_loop_new (NULL, FALSE);
152 data.loop = main_loop;
153 data.pipeline = pipeline;
155 gst_bus_add_signal_watch (bus);
156 g_signal_connect (bus, "message", G_CALLBACK (cb_message), &data);
157 g_signal_connect (pipeline, "deep-notify::temp-location", G_CALLBACK (got_location), NULL);
159 /* Register a function that GLib will call every second */
160 g_timeout_add_seconds (1, (GSourceFunc)refresh_ui, &data);
162 g_main_loop_run (main_loop);
165 g_main_loop_unref (main_loop);
166 gst_object_unref (bus);
167 gst_element_set_state (pipeline, GST_STATE_NULL);
168 gst_object_unref (pipeline);