Update theme submodule
[platform/upstream/gstreamer.git] / examples / tutorials / basic-tutorial-9.c
1 #include <string.h>
2 #include <gst/gst.h>
3 #include <gst/pbutils/pbutils.h>
4
5 /* Structure to contain all our information, so we can pass it around */
6 typedef struct _CustomData {
7   GstDiscoverer *discoverer;
8   GMainLoop *loop;
9 } CustomData;
10
11 /* Print a tag in a human-readable format (name: value) */
12 static void print_tag_foreach (const GstTagList *tags, const gchar *tag, gpointer user_data) {
13   GValue val = { 0, };
14   gchar *str;
15   gint depth = GPOINTER_TO_INT (user_data);
16
17   gst_tag_list_copy_value (&val, tags, tag);
18
19   if (G_VALUE_HOLDS_STRING (&val))
20     str = g_value_dup_string (&val);
21   else
22     str = gst_value_serialize (&val);
23
24   g_print ("%*s%s: %s\n", 2 * depth, " ", gst_tag_get_nick (tag), str);
25   g_free (str);
26
27   g_value_unset (&val);
28 }
29
30 /* Print information regarding a stream */
31 static void print_stream_info (GstDiscovererStreamInfo *info, gint depth) {
32   gchar *desc = NULL;
33   GstCaps *caps;
34   const GstTagList *tags;
35
36   caps = gst_discoverer_stream_info_get_caps (info);
37
38   if (caps) {
39     if (gst_caps_is_fixed (caps))
40       desc = gst_pb_utils_get_codec_description (caps);
41     else
42       desc = gst_caps_to_string (caps);
43     gst_caps_unref (caps);
44   }
45
46   g_print ("%*s%s: %s\n", 2 * depth, " ", gst_discoverer_stream_info_get_stream_type_nick (info), (desc ? desc : ""));
47
48   if (desc) {
49     g_free (desc);
50     desc = NULL;
51   }
52
53   tags = gst_discoverer_stream_info_get_tags (info);
54   if (tags) {
55     g_print ("%*sTags:\n", 2 * (depth + 1), " ");
56     gst_tag_list_foreach (tags, print_tag_foreach, GINT_TO_POINTER (depth + 2));
57   }
58 }
59
60 /* Print information regarding a stream and its substreams, if any */
61 static void print_topology (GstDiscovererStreamInfo *info, gint depth) {
62   GstDiscovererStreamInfo *next;
63
64   if (!info)
65     return;
66
67   print_stream_info (info, depth);
68
69   next = gst_discoverer_stream_info_get_next (info);
70   if (next) {
71     print_topology (next, depth + 1);
72     gst_discoverer_stream_info_unref (next);
73   } else if (GST_IS_DISCOVERER_CONTAINER_INFO (info)) {
74     GList *tmp, *streams;
75
76     streams = gst_discoverer_container_info_get_streams (GST_DISCOVERER_CONTAINER_INFO (info));
77     for (tmp = streams; tmp; tmp = tmp->next) {
78       GstDiscovererStreamInfo *tmpinf = (GstDiscovererStreamInfo *) tmp->data;
79       print_topology (tmpinf, depth + 1);
80     }
81     gst_discoverer_stream_info_list_free (streams);
82   }
83 }
84
85 /* This function is called every time the discoverer has information regarding
86  * one of the URIs we provided.*/
87 static void on_discovered_cb (GstDiscoverer *discoverer, GstDiscovererInfo *info, GError *err, CustomData *data) {
88   GstDiscovererResult result;
89   const gchar *uri;
90   const GstTagList *tags;
91   GstDiscovererStreamInfo *sinfo;
92
93   uri = gst_discoverer_info_get_uri (info);
94   result = gst_discoverer_info_get_result (info);
95   switch (result) {
96     case GST_DISCOVERER_URI_INVALID:
97       g_print ("Invalid URI '%s'\n", uri);
98       break;
99     case GST_DISCOVERER_ERROR:
100       g_print ("Discoverer error: %s\n", err->message);
101       break;
102     case GST_DISCOVERER_TIMEOUT:
103       g_print ("Timeout\n");
104       break;
105     case GST_DISCOVERER_BUSY:
106       g_print ("Busy\n");
107       break;
108     case GST_DISCOVERER_MISSING_PLUGINS:{
109       const GstStructure *s;
110       gchar *str;
111
112       s = gst_discoverer_info_get_misc (info);
113       str = gst_structure_to_string (s);
114
115       g_print ("Missing plugins: %s\n", str);
116       g_free (str);
117       break;
118     }
119     case GST_DISCOVERER_OK:
120       g_print ("Discovered '%s'\n", uri);
121       break;
122   }
123
124   if (result != GST_DISCOVERER_OK) {
125     g_printerr ("This URI cannot be played\n");
126     return;
127   }
128
129   /* If we got no error, show the retrieved information */
130
131   g_print ("\nDuration: %" GST_TIME_FORMAT "\n", GST_TIME_ARGS (gst_discoverer_info_get_duration (info)));
132
133   tags = gst_discoverer_info_get_tags (info);
134   if (tags) {
135     g_print ("Tags:\n");
136     gst_tag_list_foreach (tags, print_tag_foreach, GINT_TO_POINTER (1));
137   }
138
139   g_print ("Seekable: %s\n", (gst_discoverer_info_get_seekable (info) ? "yes" : "no"));
140
141   g_print ("\n");
142
143   sinfo = gst_discoverer_info_get_stream_info (info);
144   if (!sinfo)
145     return;
146
147   g_print ("Stream information:\n");
148
149   print_topology (sinfo, 1);
150
151   gst_discoverer_stream_info_unref (sinfo);
152
153   g_print ("\n");
154 }
155
156 /* This function is called when the discoverer has finished examining
157  * all the URIs we provided.*/
158 static void on_finished_cb (GstDiscoverer *discoverer, CustomData *data) {
159   g_print ("Finished discovering\n");
160
161   g_main_loop_quit (data->loop);
162 }
163
164 int main (int argc, char **argv) {
165   CustomData data;
166   GError *err = NULL;
167   gchar *uri = "https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm";
168
169   /* if a URI was provided, use it instead of the default one */
170   if (argc > 1) {
171     uri = argv[1];
172   }
173
174   /* Initialize cumstom data structure */
175   memset (&data, 0, sizeof (data));
176
177   /* Initialize GStreamer */
178   gst_init (&argc, &argv);
179
180   g_print ("Discovering '%s'\n", uri);
181
182   /* Instantiate the Discoverer */
183   data.discoverer = gst_discoverer_new (5 * GST_SECOND, &err);
184   if (!data.discoverer) {
185     g_print ("Error creating discoverer instance: %s\n", err->message);
186     g_clear_error (&err);
187     return -1;
188   }
189
190   /* Connect to the interesting signals */
191   g_signal_connect (data.discoverer, "discovered", G_CALLBACK (on_discovered_cb), &data);
192   g_signal_connect (data.discoverer, "finished", G_CALLBACK (on_finished_cb), &data);
193
194   /* Start the discoverer process (nothing to do yet) */
195   gst_discoverer_start (data.discoverer);
196
197   /* Add a request to process asynchronously the URI passed through the command line */
198   if (!gst_discoverer_discover_uri_async (data.discoverer, uri)) {
199     g_print ("Failed to start discovering URI '%s'\n", uri);
200     g_object_unref (data.discoverer);
201     return -1;
202   }
203
204   /* Create a GLib Main Loop and set it to run, so we can wait for the signals */
205   data.loop = g_main_loop_new (NULL, FALSE);
206   g_main_loop_run (data.loop);
207
208   /* Stop the discoverer process */
209   gst_discoverer_stop (data.discoverer);
210
211   /* Free resources */
212   g_object_unref (data.discoverer);
213   g_main_loop_unref (data.loop);
214
215   return 0;
216 }