Update theme submodule
[platform/upstream/gstreamer.git] / tutorials / playback-tutorial-2.c
1 #include <stdio.h>\r
2 #include <gst/gst.h>\r
3   \r
4 /* Structure to contain all our information, so we can pass it around */\r
5 typedef struct _CustomData {\r
6   GstElement *playbin;  /* Our one and only element */\r
7   \r
8   gint n_video;          /* Number of embedded video streams */\r
9   gint n_audio;          /* Number of embedded audio streams */\r
10   gint n_text;           /* Number of embedded subtitle streams */\r
11   \r
12   gint current_video;    /* Currently playing video stream */\r
13   gint current_audio;    /* Currently playing audio stream */\r
14   gint current_text;     /* Currently playing subtitle stream */\r
15   \r
16   GMainLoop *main_loop;  /* GLib's Main Loop */\r
17 } CustomData;\r
18   \r
19 /* playbin flags */\r
20 typedef enum {\r
21   GST_PLAY_FLAG_VIDEO         = (1 << 0), /* We want video output */\r
22   GST_PLAY_FLAG_AUDIO         = (1 << 1), /* We want audio output */\r
23   GST_PLAY_FLAG_TEXT          = (1 << 2)  /* We want subtitle output */\r
24 } GstPlayFlags;\r
25   \r
26 /* Forward definition for the message and keyboard processing functions */\r
27 static gboolean handle_message (GstBus *bus, GstMessage *msg, CustomData *data);\r
28 static gboolean handle_keyboard (GIOChannel *source, GIOCondition cond, CustomData *data);\r
29   \r
30 int main(int argc, char *argv[]) {\r
31   CustomData data;\r
32   GstBus *bus;\r
33   GstStateChangeReturn ret;\r
34   gint flags;\r
35   GIOChannel *io_stdin;\r
36   \r
37   /* Initialize GStreamer */\r
38   gst_init (&argc, &argv);\r
39    \r
40   /* Create the elements */\r
41   data.playbin = gst_element_factory_make ("playbin", "playbin");\r
42   \r
43   if (!data.playbin) {\r
44     g_printerr ("Not all elements could be created.\n");\r
45     return -1;\r
46   }\r
47   \r
48   /* Set the URI to play */\r
49   g_object_set (data.playbin, "uri", "https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.ogv", NULL);\r
50   \r
51   /* Set the subtitle URI to play and some font description */\r
52   g_object_set (data.playbin, "suburi", "https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer_gr.srt", NULL);\r
53   g_object_set (data.playbin, "subtitle-font-desc", "Sans, 18", NULL);\r
54   \r
55   /* Set flags to show Audio, Video and Subtitles */\r
56   g_object_get (data.playbin, "flags", &flags, NULL);\r
57   flags |= GST_PLAY_FLAG_VIDEO | GST_PLAY_FLAG_AUDIO | GST_PLAY_FLAG_TEXT;\r
58   g_object_set (data.playbin, "flags", flags, NULL);\r
59   \r
60   /* Add a bus watch, so we get notified when a message arrives */\r
61   bus = gst_element_get_bus (data.playbin);\r
62   gst_bus_add_watch (bus, (GstBusFunc)handle_message, &data);\r
63   \r
64   /* Add a keyboard watch so we get notified of keystrokes */\r
65 #ifdef G_OS_WIN32\r
66   io_stdin = g_io_channel_win32_new_fd (fileno (stdin));\r
67 #else\r
68   io_stdin = g_io_channel_unix_new (fileno (stdin));\r
69 #endif\r
70   g_io_add_watch (io_stdin, G_IO_IN, (GIOFunc)handle_keyboard, &data);\r
71   \r
72   /* Start playing */\r
73   ret = gst_element_set_state (data.playbin, GST_STATE_PLAYING);\r
74   if (ret == GST_STATE_CHANGE_FAILURE) {\r
75     g_printerr ("Unable to set the pipeline to the playing state.\n");\r
76     gst_object_unref (data.playbin);\r
77     return -1;\r
78   }\r
79   \r
80   /* Create a GLib Main Loop and set it to run */\r
81   data.main_loop = g_main_loop_new (NULL, FALSE);\r
82   g_main_loop_run (data.main_loop);\r
83   \r
84   /* Free resources */\r
85   g_main_loop_unref (data.main_loop);\r
86   g_io_channel_unref (io_stdin);\r
87   gst_object_unref (bus);\r
88   gst_element_set_state (data.playbin, GST_STATE_NULL);\r
89   gst_object_unref (data.playbin);\r
90   return 0;\r
91 }\r
92   \r
93 /* Extract some metadata from the streams and print it on the screen */\r
94 static void analyze_streams (CustomData *data) {\r
95   gint i;\r
96   GstTagList *tags;\r
97   gchar *str;\r
98   guint rate;\r
99   \r
100   /* Read some properties */\r
101   g_object_get (data->playbin, "n-video", &data->n_video, NULL);\r
102   g_object_get (data->playbin, "n-audio", &data->n_audio, NULL);\r
103   g_object_get (data->playbin, "n-text", &data->n_text, NULL);\r
104   \r
105   g_print ("%d video stream(s), %d audio stream(s), %d text stream(s)\n",\r
106     data->n_video, data->n_audio, data->n_text);\r
107   \r
108   g_print ("\n");\r
109   for (i = 0; i < data->n_video; i++) {\r
110     tags = NULL;\r
111     /* Retrieve the stream's video tags */\r
112     g_signal_emit_by_name (data->playbin, "get-video-tags", i, &tags);\r
113     if (tags) {\r
114       g_print ("video stream %d:\n", i);\r
115       gst_tag_list_get_string (tags, GST_TAG_VIDEO_CODEC, &str);\r
116       g_print ("  codec: %s\n", str ? str : "unknown");\r
117       g_free (str);\r
118       gst_tag_list_free (tags);\r
119     }\r
120   }\r
121   \r
122   g_print ("\n");\r
123   for (i = 0; i < data->n_audio; i++) {\r
124     tags = NULL;\r
125     /* Retrieve the stream's audio tags */\r
126     g_signal_emit_by_name (data->playbin, "get-audio-tags", i, &tags);\r
127     if (tags) {\r
128       g_print ("audio stream %d:\n", i);\r
129       if (gst_tag_list_get_string (tags, GST_TAG_AUDIO_CODEC, &str)) {\r
130         g_print ("  codec: %s\n", str);\r
131         g_free (str);\r
132       }\r
133       if (gst_tag_list_get_string (tags, GST_TAG_LANGUAGE_CODE, &str)) {\r
134         g_print ("  language: %s\n", str);\r
135         g_free (str);\r
136       }\r
137       if (gst_tag_list_get_uint (tags, GST_TAG_BITRATE, &rate)) {\r
138         g_print ("  bitrate: %d\n", rate);\r
139       }\r
140       gst_tag_list_free (tags);\r
141     }\r
142   }\r
143   \r
144   g_print ("\n");\r
145   for (i = 0; i < data->n_text; i++) {\r
146     tags = NULL;\r
147     /* Retrieve the stream's subtitle tags */\r
148     g_print ("subtitle stream %d:\n", i);\r
149     g_signal_emit_by_name (data->playbin, "get-text-tags", i, &tags);\r
150     if (tags) {\r
151       if (gst_tag_list_get_string (tags, GST_TAG_LANGUAGE_CODE, &str)) {\r
152         g_print ("  language: %s\n", str);\r
153         g_free (str);\r
154       }\r
155       gst_tag_list_free (tags);\r
156     } else {\r
157       g_print ("  no tags found\n");\r
158     }\r
159   }\r
160   \r
161   g_object_get (data->playbin, "current-video", &data->current_video, NULL);\r
162   g_object_get (data->playbin, "current-audio", &data->current_audio, NULL);\r
163   g_object_get (data->playbin, "current-text", &data->current_text, NULL);\r
164   \r
165   g_print ("\n");\r
166   g_print ("Currently playing video stream %d, audio stream %d and subtitle stream %d\n",\r
167       data->current_video, data->current_audio, data->current_text);\r
168   g_print ("Type any number and hit ENTER to select a different subtitle stream\n");\r
169 }\r
170   \r
171 /* Process messages from GStreamer */\r
172 static gboolean handle_message (GstBus *bus, GstMessage *msg, CustomData *data) {\r
173   GError *err;\r
174   gchar *debug_info;\r
175   \r
176   switch (GST_MESSAGE_TYPE (msg)) {\r
177     case GST_MESSAGE_ERROR:\r
178       gst_message_parse_error (msg, &err, &debug_info);\r
179       g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message);\r
180       g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none");\r
181       g_clear_error (&err);\r
182       g_free (debug_info);\r
183       g_main_loop_quit (data->main_loop);\r
184       break;\r
185     case GST_MESSAGE_EOS:\r
186       g_print ("End-Of-Stream reached.\n");\r
187       g_main_loop_quit (data->main_loop);\r
188       break;\r
189     case GST_MESSAGE_STATE_CHANGED: {\r
190       GstState old_state, new_state, pending_state;\r
191       gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state);\r
192       if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data->playbin)) {\r
193         if (new_state == GST_STATE_PLAYING) {\r
194           /* Once we are in the playing state, analyze the streams */\r
195           analyze_streams (data);\r
196         }\r
197       }\r
198     } break;\r
199     default:\r
200       break;\r
201   }\r
202   \r
203   /* We want to keep receiving messages */\r
204   return TRUE;\r
205 }\r
206   \r
207 /* Process keyboard input */\r
208 static gboolean handle_keyboard (GIOChannel *source, GIOCondition cond, CustomData *data) {\r
209   gchar *str = NULL;\r
210   \r
211   if (g_io_channel_read_line (source, &str, NULL, NULL, NULL) == G_IO_STATUS_NORMAL) {\r
212     int index = g_ascii_strtoull (str, NULL, 0);\r
213     if (index < 0 || index >= data->n_text) {\r
214       g_printerr ("Index out of bounds\n");\r
215     } else {\r
216       /* If the input was a valid subtitle stream index, set the current subtitle stream */\r
217       g_print ("Setting current subtitle stream to %d\n", index);\r
218       g_object_set (data->playbin, "current-text", index, NULL);\r
219     }\r
220   }\r
221   g_free (str);\r
222   return TRUE;\r
223 }\r