Split out documentation into subfolders.
[platform/upstream/gstreamer.git] / examples / tutorials / basic-tutorial-4.c
1 #include <gst/gst.h>
2
3 /* Structure to contain all our information, so we can pass it around */
4 typedef struct _CustomData {
5   GstElement *playbin;  /* Our one and only element */
6   gboolean playing;      /* Are we in the PLAYING state? */
7   gboolean terminate;    /* Should we terminate execution? */
8   gboolean seek_enabled; /* Is seeking enabled for this media? */
9   gboolean seek_done;    /* Have we performed the seek already? */
10   gint64 duration;       /* How long does this media last, in nanoseconds */
11 } CustomData;
12
13 /* Forward definition of the message processing function */
14 static void handle_message (CustomData *data, GstMessage *msg);
15
16 int main(int argc, char *argv[]) {
17   CustomData data;
18   GstBus *bus;
19   GstMessage *msg;
20   GstStateChangeReturn ret;
21
22   data.playing = FALSE;
23   data.terminate = FALSE;
24   data.seek_enabled = FALSE;
25   data.seek_done = FALSE;
26   data.duration = GST_CLOCK_TIME_NONE;
27
28   /* Initialize GStreamer */
29   gst_init (&argc, &argv);
30
31   /* Create the elements */
32   data.playbin = gst_element_factory_make ("playbin", "playbin");
33
34   if (!data.playbin) {
35     g_printerr ("Not all elements could be created.\n");
36     return -1;
37   }
38
39   /* Set the URI to play */
40   g_object_set (data.playbin, "uri", "https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL);
41
42   /* Start playing */
43   ret = gst_element_set_state (data.playbin, GST_STATE_PLAYING);
44   if (ret == GST_STATE_CHANGE_FAILURE) {
45     g_printerr ("Unable to set the pipeline to the playing state.\n");
46     gst_object_unref (data.playbin);
47     return -1;
48   }
49
50   /* Listen to the bus */
51   bus = gst_element_get_bus (data.playbin);
52   do {
53     msg = gst_bus_timed_pop_filtered (bus, 100 * GST_MSECOND,
54         GST_MESSAGE_STATE_CHANGED | GST_MESSAGE_ERROR | GST_MESSAGE_EOS | GST_MESSAGE_DURATION);
55
56     /* Parse message */
57     if (msg != NULL) {
58       handle_message (&data, msg);
59     } else {
60       /* We got no message, this means the timeout expired */
61       if (data.playing) {
62         gint64 current = -1;
63
64         /* Query the current position of the stream */
65         if (!gst_element_query_position (data.playbin, GST_FORMAT_TIME, &current)) {
66           g_printerr ("Could not query current position.\n");
67         }
68
69         /* If we didn't know it yet, query the stream duration */
70         if (!GST_CLOCK_TIME_IS_VALID (data.duration)) {
71           if (!gst_element_query_duration (data.playbin, GST_FORMAT_TIME, &data.duration)) {
72             g_printerr ("Could not query current duration.\n");
73           }
74         }
75
76         /* Print current position and total duration */
77         g_print ("Position %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT "\r",
78             GST_TIME_ARGS (current), GST_TIME_ARGS (data.duration));
79
80         /* If seeking is enabled, we have not done it yet, and the time is right, seek */
81         if (data.seek_enabled && !data.seek_done && current > 10 * GST_SECOND) {
82           g_print ("\nReached 10s, performing seek...\n");
83           gst_element_seek_simple (data.playbin, GST_FORMAT_TIME,
84               GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT, 30 * GST_SECOND);
85           data.seek_done = TRUE;
86         }
87       }
88     }
89   } while (!data.terminate);
90
91   /* Free resources */
92   gst_object_unref (bus);
93   gst_element_set_state (data.playbin, GST_STATE_NULL);
94   gst_object_unref (data.playbin);
95   return 0;
96 }
97
98 static void handle_message (CustomData *data, GstMessage *msg) {
99   GError *err;
100   gchar *debug_info;
101
102   switch (GST_MESSAGE_TYPE (msg)) {
103     case GST_MESSAGE_ERROR:
104       gst_message_parse_error (msg, &err, &debug_info);
105       g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message);
106       g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none");
107       g_clear_error (&err);
108       g_free (debug_info);
109       data->terminate = TRUE;
110       break;
111     case GST_MESSAGE_EOS:
112       g_print ("End-Of-Stream reached.\n");
113       data->terminate = TRUE;
114       break;
115     case GST_MESSAGE_DURATION:
116       /* The duration has changed, mark the current one as invalid */
117       data->duration = GST_CLOCK_TIME_NONE;
118       break;
119     case GST_MESSAGE_STATE_CHANGED: {
120       GstState old_state, new_state, pending_state;
121       gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state);
122       if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data->playbin)) {
123         g_print ("Pipeline state changed from %s to %s:\n",
124             gst_element_state_get_name (old_state), gst_element_state_get_name (new_state));
125
126         /* Remember whether we are in the PLAYING state or not */
127         data->playing = (new_state == GST_STATE_PLAYING);
128
129         if (data->playing) {
130           /* We just moved to PLAYING. Check if seeking is possible */
131           GstQuery *query;
132           gint64 start, end;
133           query = gst_query_new_seeking (GST_FORMAT_TIME);
134           if (gst_element_query (data->playbin, query)) {
135             gst_query_parse_seeking (query, NULL, &data->seek_enabled, &start, &end);
136             if (data->seek_enabled) {
137               g_print ("Seeking is ENABLED from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT "\n",
138                   GST_TIME_ARGS (start), GST_TIME_ARGS (end));
139             } else {
140               g_print ("Seeking is DISABLED for this stream.\n");
141             }
142           }
143           else {
144             g_printerr ("Seeking query failed.");
145           }
146           gst_query_unref (query);
147         }
148       }
149     } break;
150     default:
151       /* We should not reach here */
152       g_printerr ("Unexpected message received.\n");
153       break;
154   }
155   gst_message_unref (msg);
156 }