gstreamer/subprojects/gst-docs/examples/tutorials/playback-tutorial-4.c

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

203 lines
5.5 KiB
C
Raw Normal View History

2012-06-18 10:19:06 +00:00
#include <gst/gst.h>
#include <string.h>
#ifdef __APPLE__
#include <TargetConditionals.h>
#endif
2013-10-31 09:13:31 +00:00
#define GRAPH_LENGTH 78
2013-10-31 09:13:31 +00:00
/* playbin flags */
2019-02-07 19:32:58 +00:00
typedef enum
{
GST_PLAY_FLAG_DOWNLOAD = (1 << 7) /* Enable progressive download (on selected formats) */
2012-06-18 10:19:06 +00:00
} GstPlayFlags;
2019-02-07 19:32:58 +00:00
typedef struct _CustomData
{
2012-06-18 10:19:06 +00:00
gboolean is_live;
GstElement *pipeline;
GMainLoop *loop;
gint buffering_level;
} CustomData;
2019-02-07 19:32:58 +00:00
static void
got_location (GstObject * gstobject, GstObject * prop_object, GParamSpec * prop,
gpointer data)
{
2012-06-19 10:31:06 +00:00
gchar *location;
g_object_get (G_OBJECT (prop_object), "temp-location", &location, NULL);
g_print ("Temporary file: %s\n", location);
2013-10-31 09:13:31 +00:00
g_free (location);
2012-06-19 10:31:06 +00:00
/* Uncomment this line to keep the temporary file after the program exits */
/* g_object_set (G_OBJECT (prop_object), "temp-remove", FALSE, NULL); */
}
2019-02-07 19:32:58 +00:00
static void
cb_message (GstBus * bus, GstMessage * msg, CustomData * data)
{
2012-06-18 10:19:06 +00:00
switch (GST_MESSAGE_TYPE (msg)) {
2019-02-07 19:32:58 +00:00
case GST_MESSAGE_ERROR:{
2012-06-18 10:19:06 +00:00
GError *err;
gchar *debug;
2012-06-18 10:19:06 +00:00
gst_message_parse_error (msg, &err, &debug);
g_print ("Error: %s\n", err->message);
g_error_free (err);
g_free (debug);
2012-06-18 10:19:06 +00:00
gst_element_set_state (data->pipeline, GST_STATE_READY);
g_main_loop_quit (data->loop);
break;
}
case GST_MESSAGE_EOS:
/* end-of-stream */
gst_element_set_state (data->pipeline, GST_STATE_READY);
g_main_loop_quit (data->loop);
break;
case GST_MESSAGE_BUFFERING:
/* If the stream is live, we do not care about buffering. */
2019-02-07 19:32:58 +00:00
if (data->is_live)
break;
2012-06-18 10:19:06 +00:00
gst_message_parse_buffering (msg, &data->buffering_level);
2012-06-18 10:19:06 +00:00
/* Wait until buffering is complete before start/resume playing */
if (data->buffering_level < 100)
gst_element_set_state (data->pipeline, GST_STATE_PAUSED);
else
gst_element_set_state (data->pipeline, GST_STATE_PLAYING);
break;
case GST_MESSAGE_CLOCK_LOST:
/* Get a new clock */
gst_element_set_state (data->pipeline, GST_STATE_PAUSED);
gst_element_set_state (data->pipeline, GST_STATE_PLAYING);
break;
default:
/* Unhandled message */
break;
2019-02-07 19:32:58 +00:00
}
2012-06-18 10:19:06 +00:00
}
2019-02-07 19:32:58 +00:00
static gboolean
refresh_ui (CustomData * data)
{
2012-06-18 10:19:06 +00:00
GstQuery *query;
gboolean result;
2012-06-18 10:19:06 +00:00
query = gst_query_new_buffering (GST_FORMAT_PERCENT);
result = gst_element_query (data->pipeline, query);
if (result) {
gint n_ranges, range, i;
gchar graph[GRAPH_LENGTH + 1];
gint64 position = 0, duration = 0;
2012-06-18 10:19:06 +00:00
memset (graph, ' ', GRAPH_LENGTH);
graph[GRAPH_LENGTH] = '\0';
2012-06-18 10:19:06 +00:00
n_ranges = gst_query_get_n_buffering_ranges (query);
for (range = 0; range < n_ranges; range++) {
gint64 start, stop;
gst_query_parse_nth_buffering_range (query, range, &start, &stop);
2013-10-31 09:13:31 +00:00
start = start * GRAPH_LENGTH / (stop - start);
stop = stop * GRAPH_LENGTH / (stop - start);
2019-02-07 19:32:58 +00:00
for (i = (gint) start; i < stop; i++)
graph[i] = '-';
2012-06-18 10:19:06 +00:00
}
2019-02-07 19:32:58 +00:00
if (gst_element_query_position (data->pipeline, GST_FORMAT_TIME, &position)
&& GST_CLOCK_TIME_IS_VALID (position)
&& gst_element_query_duration (data->pipeline, GST_FORMAT_TIME,
&duration) && GST_CLOCK_TIME_IS_VALID (duration)) {
i = (gint) (GRAPH_LENGTH * (double) position / (double) (duration + 1));
graph[i] = data->buffering_level < 100 ? 'X' : '>';
2012-06-18 10:19:06 +00:00
}
g_print ("[%s]", graph);
if (data->buffering_level < 100) {
g_print (" Buffering: %3d%%", data->buffering_level);
} else {
g_print (" ");
}
g_print ("\r");
}
2012-06-18 10:19:06 +00:00
return TRUE;
2012-06-18 10:19:06 +00:00
}
2019-02-07 19:32:58 +00:00
int
tutorial_main (int argc, char *argv[])
2019-02-07 19:32:58 +00:00
{
2012-06-18 10:19:06 +00:00
GstElement *pipeline;
GstBus *bus;
GstStateChangeReturn ret;
GMainLoop *main_loop;
CustomData data;
guint flags;
2012-06-18 10:19:06 +00:00
/* Initialize GStreamer */
gst_init (&argc, &argv);
2012-06-18 10:19:06 +00:00
/* Initialize our data structure */
memset (&data, 0, sizeof (data));
data.buffering_level = 100;
2012-06-18 10:19:06 +00:00
/* Build the pipeline */
2019-02-07 19:32:58 +00:00
pipeline =
gst_parse_launch
("playbin uri=https://gstreamer.freedesktop.org/data/media/sintel_trailer-480p.webm",
2019-02-07 19:32:58 +00:00
NULL);
2012-06-18 10:19:06 +00:00
bus = gst_element_get_bus (pipeline);
2012-06-18 10:19:06 +00:00
/* Set the download flag */
g_object_get (pipeline, "flags", &flags, NULL);
flags |= GST_PLAY_FLAG_DOWNLOAD;
g_object_set (pipeline, "flags", flags, NULL);
/* Uncomment this line to limit the amount of downloaded data */
/* g_object_set (pipeline, "ring-buffer-max-size", (guint64)4000000, NULL); */
2012-06-18 10:19:06 +00:00
/* Start playing */
ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
if (ret == GST_STATE_CHANGE_FAILURE) {
g_printerr ("Unable to set the pipeline to the playing state.\n");
gst_object_unref (pipeline);
return -1;
} else if (ret == GST_STATE_CHANGE_NO_PREROLL) {
data.is_live = TRUE;
}
2012-06-18 10:19:06 +00:00
main_loop = g_main_loop_new (NULL, FALSE);
data.loop = main_loop;
data.pipeline = pipeline;
2012-06-18 10:19:06 +00:00
gst_bus_add_signal_watch (bus);
2012-06-19 10:31:06 +00:00
g_signal_connect (bus, "message", G_CALLBACK (cb_message), &data);
2019-02-07 19:32:58 +00:00
g_signal_connect (pipeline, "deep-notify::temp-location",
G_CALLBACK (got_location), NULL);
2012-06-18 10:19:06 +00:00
/* Register a function that GLib will call every second */
2019-02-07 19:32:58 +00:00
g_timeout_add_seconds (1, (GSourceFunc) refresh_ui, &data);
2012-06-18 10:19:06 +00:00
g_main_loop_run (main_loop);
2012-06-18 10:19:06 +00:00
/* Free resources */
g_main_loop_unref (main_loop);
gst_object_unref (bus);
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (pipeline);
g_print ("\n");
return 0;
2013-10-31 09:13:31 +00:00
}
int
main (int argc, char *argv[])
{
#if defined(__APPLE__) && TARGET_OS_MAC && !TARGET_OS_IPHONE
return gst_macos_main (tutorial_main, argc, argv, NULL);
#else
return tutorial_main (argc, argv);
#endif
}