3 #include <gst/pbutils/pbutils.h>
5 /* Structure to contain all our information, so we can pass it around */
6 typedef struct _CustomData {
7 GstDiscoverer *discoverer;
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) {
15 gint depth = GPOINTER_TO_INT (user_data);
17 gst_tag_list_copy_value (&val, tags, tag);
19 if (G_VALUE_HOLDS_STRING (&val))
20 str = g_value_dup_string (&val);
22 str = gst_value_serialize (&val);
24 g_print ("%*s%s: %s\n", 2 * depth, " ", gst_tag_get_nick (tag), str);
30 /* Print information regarding a stream */
31 static void print_stream_info (GstDiscovererStreamInfo *info, gint depth) {
34 const GstTagList *tags;
36 caps = gst_discoverer_stream_info_get_caps (info);
39 if (gst_caps_is_fixed (caps))
40 desc = gst_pb_utils_get_codec_description (caps);
42 desc = gst_caps_to_string (caps);
43 gst_caps_unref (caps);
46 g_print ("%*s%s: %s\n", 2 * depth, " ", gst_discoverer_stream_info_get_stream_type_nick (info), (desc ? desc : ""));
53 tags = gst_discoverer_stream_info_get_tags (info);
55 g_print ("%*sTags:\n", 2 * (depth + 1), " ");
56 gst_tag_list_foreach (tags, print_tag_foreach, GINT_TO_POINTER (depth + 2));
60 /* Print information regarding a stream and its substreams, if any */
61 static void print_topology (GstDiscovererStreamInfo *info, gint depth) {
62 GstDiscovererStreamInfo *next;
67 print_stream_info (info, depth);
69 next = gst_discoverer_stream_info_get_next (info);
71 print_topology (next, depth + 1);
72 gst_discoverer_stream_info_unref (next);
73 } else if (GST_IS_DISCOVERER_CONTAINER_INFO (info)) {
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);
81 gst_discoverer_stream_info_list_free (streams);
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;
90 const GstTagList *tags;
91 GstDiscovererStreamInfo *sinfo;
93 uri = gst_discoverer_info_get_uri (info);
94 result = gst_discoverer_info_get_result (info);
96 case GST_DISCOVERER_URI_INVALID:
97 g_print ("Invalid URI '%s'\n", uri);
99 case GST_DISCOVERER_ERROR:
100 g_print ("Discoverer error: %s\n", err->message);
102 case GST_DISCOVERER_TIMEOUT:
103 g_print ("Timeout\n");
105 case GST_DISCOVERER_BUSY:
108 case GST_DISCOVERER_MISSING_PLUGINS:{
109 const GstStructure *s;
112 s = gst_discoverer_info_get_misc (info);
113 str = gst_structure_to_string (s);
115 g_print ("Missing plugins: %s\n", str);
119 case GST_DISCOVERER_OK:
120 g_print ("Discovered '%s'\n", uri);
124 if (result != GST_DISCOVERER_OK) {
125 g_printerr ("This URI cannot be played\n");
129 /* If we got no error, show the retrieved information */
131 g_print ("\nDuration: %" GST_TIME_FORMAT "\n", GST_TIME_ARGS (gst_discoverer_info_get_duration (info)));
133 tags = gst_discoverer_info_get_tags (info);
136 gst_tag_list_foreach (tags, print_tag_foreach, GINT_TO_POINTER (1));
139 g_print ("Seekable: %s\n", (gst_discoverer_info_get_seekable (info) ? "yes" : "no"));
143 sinfo = gst_discoverer_info_get_stream_info (info);
147 g_print ("Stream information:\n");
149 print_topology (sinfo, 1);
151 gst_discoverer_stream_info_unref (sinfo);
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");
161 g_main_loop_quit (data->loop);
164 int main (int argc, char **argv) {
167 gchar *uri = "https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm";
169 /* if a URI was provided, use it instead of the default one */
174 /* Initialize cumstom data structure */
175 memset (&data, 0, sizeof (data));
177 /* Initialize GStreamer */
178 gst_init (&argc, &argv);
180 g_print ("Discovering '%s'\n", uri);
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);
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);
194 /* Start the discoverer process (nothing to do yet) */
195 gst_discoverer_start (data.discoverer);
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);
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);
208 /* Stop the discoverer process */
209 gst_discoverer_stop (data.discoverer);
212 g_object_unref (data.discoverer);
213 g_main_loop_unref (data.loop);