1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22 #ifdef HAVE_UNISTD_H
23 #include <unistd.h>
24 #endif
25 #ifdef HAVE_STDLIB_H
26 #include <stdlib.h>             /* exit */
27 #endif
28 #include <gst/gst.h>
29 
30 static void
pad_added_cb(GstElement * decodebin,GstPad * new_pad,GstElement * pipeline)31 pad_added_cb (GstElement * decodebin, GstPad * new_pad, GstElement * pipeline)
32 {
33   GstElement *fakesink;
34   GstPad *sinkpad;
35 
36   fakesink = gst_element_factory_make ("fakesink", NULL);
37   gst_bin_add (GST_BIN (pipeline), fakesink);
38 
39   sinkpad = gst_element_get_static_pad (fakesink, "sink");
40   if (GST_PAD_LINK_FAILED (gst_pad_link (new_pad, sinkpad))) {
41     g_warning ("Failed to link %s:%s to %s:%s", GST_DEBUG_PAD_NAME (new_pad),
42         GST_DEBUG_PAD_NAME (sinkpad));
43     gst_bin_remove (GST_BIN (pipeline), fakesink);
44   } else {
45     gst_element_set_state (fakesink, GST_STATE_PAUSED);
46   }
47 }
48 
49 static void
show_error(const gchar * errmsg,GstBus * bus)50 show_error (const gchar * errmsg, GstBus * bus)
51 {
52   GstMessage *msg;
53   GError *err = NULL;
54   gchar *dbg = NULL;
55 
56   msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, 0);
57   if (msg) {
58     g_assert (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR);
59 
60     gst_message_parse_error (msg, &err, &dbg);
61   }
62 
63   g_print ("ERROR: %s\n", errmsg);
64   g_print ("       %s\n", (err) ? err->message : "");
65   if (dbg) {
66     g_print ("\ndebug: %s\n\n", dbg);
67     g_free (dbg);
68   }
69 
70   if (err)
71     g_error_free (err);
72 }
73 
74 gint
main(gint argc,gchar * argv[])75 main (gint argc, gchar * argv[])
76 {
77   GstElement *pipeline, *filesrc, *decodebin;
78   GstStateChangeReturn res;
79   GstIterator *it;
80   GstBus *bus;
81   GValue data = { 0, };
82 
83   gst_init (&argc, &argv);
84 
85   pipeline = gst_pipeline_new ("pipeline");
86 
87   filesrc = gst_element_factory_make ("filesrc", "filesrc");
88   g_assert (filesrc);
89 
90   decodebin = gst_element_factory_make ("decodebin", "decodebin");
91   g_assert (decodebin);
92 
93   gst_bin_add_many (GST_BIN (pipeline), filesrc, decodebin, NULL);
94   gst_element_link (filesrc, decodebin);
95 
96   if (argc < 2) {
97     g_print ("usage: %s <filenames>\n", argv[0]);
98     exit (-1);
99   }
100 
101   if (!g_str_has_prefix (argv[1], "file://")) {
102     g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
103   } else {
104     g_object_set (G_OBJECT (filesrc), "location", argv[1] + 7, NULL);
105   }
106 
107   /* we've got to connect fakesinks to newly decoded pads to make sure
108    * buffers have actually been flowing over those pads and caps have
109    * been set on them. decodebin might insert internal queues and
110    * without fakesinks it's pot-luck what caps we get from the pad, because
111    * it depends on whether the queues have started pushing buffers yet or not.
112    * With fakesinks we make sure that the pipeline doesn't go to PAUSED state
113    * before each fakesink has a buffer queued. */
114   g_signal_connect (decodebin, "pad-added",
115       G_CALLBACK (pad_added_cb), pipeline);
116 
117   bus = gst_element_get_bus (pipeline);
118 
119   g_print ("pause..\n");
120   res = gst_element_set_state (pipeline, GST_STATE_PAUSED);
121   if (res == GST_STATE_CHANGE_FAILURE) {
122     show_error ("Could not go to PAUSED state", bus);
123     exit (-1);
124   }
125   g_print ("waiting..\n");
126   res = gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
127   if (res != GST_STATE_CHANGE_SUCCESS) {
128     show_error ("Failed to complete state change to PAUSED", bus);
129     exit (-1);
130   }
131   g_print ("stats..\n");
132 
133   it = gst_element_iterate_src_pads (decodebin);
134   while (gst_iterator_next (it, &data) == GST_ITERATOR_OK) {
135     GstPad *pad = g_value_get_object (&data);
136     GstCaps *caps;
137     gchar *str;
138     GstQuery *query;
139 
140     g_print ("stream %s:\n", GST_OBJECT_NAME (pad));
141 
142     caps = gst_pad_query_caps (pad, NULL);
143     str = gst_caps_to_string (caps);
144     g_print (" caps: %s\n", str);
145     g_free (str);
146     gst_caps_unref (caps);
147 
148     query = gst_query_new_duration (GST_FORMAT_TIME);
149     if (gst_pad_query (pad, query)) {
150       gint64 duration;
151 
152       gst_query_parse_duration (query, NULL, &duration);
153 
154       g_print (" duration: %" GST_TIME_FORMAT "\n", GST_TIME_ARGS (duration));
155     }
156     gst_query_unref (query);
157 
158     g_value_reset (&data);
159   }
160   g_value_unset (&data);
161   gst_iterator_free (it);
162 
163   return 0;
164 }
165