4 /* Structure to contain all our information, so we can pass it around */
5 typedef struct _CustomData {
6 GstElement *playbin; /* Our one and only element */
8 gint n_video; /* Number of embedded video streams */
9 gint n_audio; /* Number of embedded audio streams */
10 gint n_text; /* Number of embedded subtitle streams */
12 gint current_video; /* Currently playing video stream */
13 gint current_audio; /* Currently playing audio stream */
14 gint current_text; /* Currently playing subtitle stream */
16 GMainLoop *main_loop; /* GLib's Main Loop */
21 GST_PLAY_FLAG_VIDEO = (1 << 0), /* We want video output */
22 GST_PLAY_FLAG_AUDIO = (1 << 1), /* We want audio output */
23 GST_PLAY_FLAG_TEXT = (1 << 2) /* We want subtitle output */
26 /* Forward definition for the message and keyboard processing functions */
27 static gboolean handle_message (GstBus *bus, GstMessage *msg, CustomData *data);
28 static gboolean handle_keyboard (GIOChannel *source, GIOCondition cond, CustomData *data);
30 int main(int argc, char *argv[]) {
33 GstStateChangeReturn ret;
37 /* Initialize GStreamer */
38 gst_init (&argc, &argv);
40 /* Create the elements */
41 data.playbin = gst_element_factory_make ("playbin", "playbin");
44 g_printerr ("Not all elements could be created.\n");
48 /* Set the URI to play */
49 g_object_set (data.playbin, "uri", "https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_cropped_multilingual.webm", NULL);
51 /* Set flags to show Audio and Video but ignore Subtitles */
52 g_object_get (data.playbin, "flags", &flags, NULL);
53 flags |= GST_PLAY_FLAG_VIDEO | GST_PLAY_FLAG_AUDIO;
54 flags &= ~GST_PLAY_FLAG_TEXT;
55 g_object_set (data.playbin, "flags", flags, NULL);
57 /* Set connection speed. This will affect some internal decisions of playbin */
58 g_object_set (data.playbin, "connection-speed", 56, NULL);
60 /* Add a bus watch, so we get notified when a message arrives */
61 bus = gst_element_get_bus (data.playbin);
62 gst_bus_add_watch (bus, (GstBusFunc)handle_message, &data);
64 /* Add a keyboard watch so we get notified of keystrokes */
66 io_stdin = g_io_channel_win32_new_fd (fileno (stdin));
68 io_stdin = g_io_channel_unix_new (fileno (stdin));
70 g_io_add_watch (io_stdin, G_IO_IN, (GIOFunc)handle_keyboard, &data);
73 ret = gst_element_set_state (data.playbin, GST_STATE_PLAYING);
74 if (ret == GST_STATE_CHANGE_FAILURE) {
75 g_printerr ("Unable to set the pipeline to the playing state.\n");
76 gst_object_unref (data.playbin);
80 /* Create a GLib Main Loop and set it to run */
81 data.main_loop = g_main_loop_new (NULL, FALSE);
82 g_main_loop_run (data.main_loop);
85 g_main_loop_unref (data.main_loop);
86 g_io_channel_unref (io_stdin);
87 gst_object_unref (bus);
88 gst_element_set_state (data.playbin, GST_STATE_NULL);
89 gst_object_unref (data.playbin);
93 /* Extract some metadata from the streams and print it on the screen */
94 static void analyze_streams (CustomData *data) {
100 /* Read some properties */
101 g_object_get (data->playbin, "n-video", &data->n_video, NULL);
102 g_object_get (data->playbin, "n-audio", &data->n_audio, NULL);
103 g_object_get (data->playbin, "n-text", &data->n_text, NULL);
105 g_print ("%d video stream(s), %d audio stream(s), %d text stream(s)\n",
106 data->n_video, data->n_audio, data->n_text);
109 for (i = 0; i < data->n_video; i++) {
111 /* Retrieve the stream's video tags */
112 g_signal_emit_by_name (data->playbin, "get-video-tags", i, &tags);
114 g_print ("video stream %d:\n", i);
115 gst_tag_list_get_string (tags, GST_TAG_VIDEO_CODEC, &str);
116 g_print (" codec: %s\n", str ? str : "unknown");
118 gst_tag_list_unref (tags);
123 for (i = 0; i < data->n_audio; i++) {
125 /* Retrieve the stream's audio tags */
126 g_signal_emit_by_name (data->playbin, "get-audio-tags", i, &tags);
128 g_print ("audio stream %d:\n", i);
129 if (gst_tag_list_get_string (tags, GST_TAG_AUDIO_CODEC, &str)) {
130 g_print (" codec: %s\n", str);
133 if (gst_tag_list_get_string (tags, GST_TAG_LANGUAGE_CODE, &str)) {
134 g_print (" language: %s\n", str);
137 if (gst_tag_list_get_uint (tags, GST_TAG_BITRATE, &rate)) {
138 g_print (" bitrate: %d\n", rate);
140 gst_tag_list_unref (tags);
145 for (i = 0; i < data->n_text; i++) {
147 /* Retrieve the stream's subtitle tags */
148 g_signal_emit_by_name (data->playbin, "get-text-tags", i, &tags);
150 g_print ("subtitle stream %d:\n", i);
151 if (gst_tag_list_get_string (tags, GST_TAG_LANGUAGE_CODE, &str)) {
152 g_print (" language: %s\n", str);
155 gst_tag_list_unref (tags);
159 g_object_get (data->playbin, "current-video", &data->current_video, NULL);
160 g_object_get (data->playbin, "current-audio", &data->current_audio, NULL);
161 g_object_get (data->playbin, "current-text", &data->current_text, NULL);
164 g_print ("Currently playing video stream %d, audio stream %d and text stream %d\n",
165 data->current_video, data->current_audio, data->current_text);
166 g_print ("Type any number and hit ENTER to select a different audio stream\n");
169 /* Process messages from GStreamer */
170 static gboolean handle_message (GstBus *bus, GstMessage *msg, CustomData *data) {
174 switch (GST_MESSAGE_TYPE (msg)) {
175 case GST_MESSAGE_ERROR:
176 gst_message_parse_error (msg, &err, &debug_info);
177 g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message);
178 g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none");
179 g_clear_error (&err);
181 g_main_loop_quit (data->main_loop);
183 case GST_MESSAGE_EOS:
184 g_print ("End-Of-Stream reached.\n");
185 g_main_loop_quit (data->main_loop);
187 case GST_MESSAGE_STATE_CHANGED: {
188 GstState old_state, new_state, pending_state;
189 gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state);
190 if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data->playbin)) {
191 if (new_state == GST_STATE_PLAYING) {
192 /* Once we are in the playing state, analyze the streams */
193 analyze_streams (data);
201 /* We want to keep receiving messages */
205 /* Process keyboard input */
206 static gboolean handle_keyboard (GIOChannel *source, GIOCondition cond, CustomData *data) {
209 if (g_io_channel_read_line (source, &str, NULL, NULL, NULL) == G_IO_STATUS_NORMAL) {
210 int index = g_ascii_strtoull (str, NULL, 0);
211 if (index < 0 || index >= data->n_audio) {
212 g_printerr ("Index out of bounds\n");
214 /* If the input was a valid audio stream index, set the current audio stream */
215 g_print ("Setting current audio stream to %d\n", index);
216 g_object_set (data->playbin, "current-audio", index, NULL);