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