Split out documentation into subfolders.
[platform/upstream/gstreamer.git] / examples / tutorials / playback-tutorial-1.c
1 #include <stdio.h>
2 #include <gst/gst.h>
3
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 */
7
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 */
11
12   gint current_video;    /* Currently playing video stream */
13   gint current_audio;    /* Currently playing audio stream */
14   gint current_text;     /* Currently playing subtitle stream */
15
16   GMainLoop *main_loop;  /* GLib's Main Loop */
17 } CustomData;
18
19 /* playbin flags */
20 typedef enum {
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 */
24 } GstPlayFlags;
25
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);
29
30 int main(int argc, char *argv[]) {
31   CustomData data;
32   GstBus *bus;
33   GstStateChangeReturn ret;
34   gint flags;
35   GIOChannel *io_stdin;
36
37   /* Initialize GStreamer */
38   gst_init (&argc, &argv);
39
40   /* Create the elements */
41   data.playbin = gst_element_factory_make ("playbin", "playbin");
42
43   if (!data.playbin) {
44     g_printerr ("Not all elements could be created.\n");
45     return -1;
46   }
47
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);
50
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);
56
57   /* Set connection speed. This will affect some internal decisions of playbin */
58   g_object_set (data.playbin, "connection-speed", 56, NULL);
59
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);
63
64   /* Add a keyboard watch so we get notified of keystrokes */
65 #ifdef G_OS_WIN32
66   io_stdin = g_io_channel_win32_new_fd (fileno (stdin));
67 #else
68   io_stdin = g_io_channel_unix_new (fileno (stdin));
69 #endif
70   g_io_add_watch (io_stdin, G_IO_IN, (GIOFunc)handle_keyboard, &data);
71
72   /* Start playing */
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);
77     return -1;
78   }
79
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);
83
84   /* Free resources */
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);
90   return 0;
91 }
92
93 /* Extract some metadata from the streams and print it on the screen */
94 static void analyze_streams (CustomData *data) {
95   gint i;
96   GstTagList *tags;
97   gchar *str;
98   guint rate;
99
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);
104
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);
107
108   g_print ("\n");
109   for (i = 0; i < data->n_video; i++) {
110     tags = NULL;
111     /* Retrieve the stream's video tags */
112     g_signal_emit_by_name (data->playbin, "get-video-tags", i, &tags);
113     if (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");
117       g_free (str);
118       gst_tag_list_unref (tags);
119     }
120   }
121
122   g_print ("\n");
123   for (i = 0; i < data->n_audio; i++) {
124     tags = NULL;
125     /* Retrieve the stream's audio tags */
126     g_signal_emit_by_name (data->playbin, "get-audio-tags", i, &tags);
127     if (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);
131         g_free (str);
132       }
133       if (gst_tag_list_get_string (tags, GST_TAG_LANGUAGE_CODE, &str)) {
134         g_print ("  language: %s\n", str);
135         g_free (str);
136       }
137       if (gst_tag_list_get_uint (tags, GST_TAG_BITRATE, &rate)) {
138         g_print ("  bitrate: %d\n", rate);
139       }
140       gst_tag_list_unref (tags);
141     }
142   }
143
144   g_print ("\n");
145   for (i = 0; i < data->n_text; i++) {
146     tags = NULL;
147     /* Retrieve the stream's subtitle tags */
148     g_signal_emit_by_name (data->playbin, "get-text-tags", i, &tags);
149     if (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);
153         g_free (str);
154       }
155       gst_tag_list_unref (tags);
156     }
157   }
158
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);
162
163   g_print ("\n");
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");
167 }
168
169 /* Process messages from GStreamer */
170 static gboolean handle_message (GstBus *bus, GstMessage *msg, CustomData *data) {
171   GError *err;
172   gchar *debug_info;
173
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);
180       g_free (debug_info);
181       g_main_loop_quit (data->main_loop);
182       break;
183     case GST_MESSAGE_EOS:
184       g_print ("End-Of-Stream reached.\n");
185       g_main_loop_quit (data->main_loop);
186       break;
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);
194         }
195       }
196     } break;
197     default:
198       break;
199   }
200
201   /* We want to keep receiving messages */
202   return TRUE;
203 }
204
205 /* Process keyboard input */
206 static gboolean handle_keyboard (GIOChannel *source, GIOCondition cond, CustomData *data) {
207   gchar *str = NULL;
208
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");
213     } else {
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);
217     }
218   }
219   g_free (str);
220   return TRUE;
221 }