s/gst_element_install_std_props/gst_element_class_install_std_props/ -- it just makes...
[platform/upstream/gstreamer.git] / tools / gst-launch.c
1 #include <glib.h>
2 #include <gst/gst.h>
3 #include <gst/gstparse.h>
4 #include <string.h>
5 #include <stdlib.h>
6 #include <gst/gstpropsprivate.h>
7 #include <sys/time.h>
8
9 static int    launch_argc;
10 static char **launch_argv;
11
12 static guint64 iterations = 0;
13 static guint64 sum = 0;
14 static guint64 min = G_MAXINT;
15 static guint64 max = 0;
16
17 gboolean
18 idle_func (gpointer data)
19 {
20   gboolean busy;
21   struct timeval tfthen, tfnow;
22   guint64 diff;
23
24   gettimeofday (&tfthen, (struct timezone *)NULL);
25   busy = gst_bin_iterate (GST_BIN (data));
26   iterations++;
27   gettimeofday (&tfnow, (struct timezone *)NULL);
28
29   diff = ((guint64)tfnow.tv_sec*1000000LL+tfnow.tv_usec) - 
30          ((guint64)tfthen.tv_sec*1000000LL+tfthen.tv_usec); 
31
32   sum += diff; 
33   min = MIN (min, diff);
34   max = MAX (max, diff);
35
36   if (!busy) {
37     gst_main_quit ();
38     g_print ("execution ended after %llu iterations (sum %llu us, average %llu us, min %llu us, max %llu us)\n", 
39                     iterations, sum, sum/iterations, min, max);
40   }
41
42   return busy;
43 }
44
45 static void
46 property_change_callback (GObject *object, GstObject *orig, GParamSpec *pspec)
47 {
48   GValue value = { 0, }; /* the important thing is that value.type = 0 */
49   gchar *str = 0;
50   
51   if (pspec->flags & G_PARAM_READABLE) {
52     g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
53     g_object_get_property (G_OBJECT (orig), pspec->name, &value);
54     /* fix current bug with g_strdup_value_contents not working with gint64 */
55     if (G_IS_PARAM_SPEC_INT64 (pspec))
56       str = g_strdup_printf ("%lld", g_value_get_int64 (&value));
57     else
58       str = g_strdup_value_contents (&value);
59     g_print ("%s: %s = %s\n", GST_OBJECT_NAME (orig), pspec->name, str);
60     g_free (str);
61     g_value_unset(&value);
62   } else {
63     g_warning ("Parameter not readable. What's up with that?");
64   }
65 }
66
67 static void
68 error_callback (GObject *object, GstObject *orig, gchar *error)
69 {
70   g_print ("ERROR: %s: %s\n", GST_OBJECT_NAME (orig), error);
71 }
72
73 static GstElement*
74 xmllaunch_parse_cmdline (const gchar **argv) 
75 {
76   GstElement *pipeline = NULL, *e;
77   GstXML *xml;
78   gboolean err;
79   const gchar *arg;
80   gchar *element, *property, *value;
81   GList *l;
82   gint i = 0;
83   
84   if (!(arg = argv[0])) {
85     g_print ("usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n");
86     exit (1);
87   }
88   
89   xml = gst_xml_new ();
90   err = gst_xml_parse_file(xml, arg, NULL);
91   
92   if (err != TRUE) {
93     fprintf (stderr, "ERROR: parse of xml file '%s' failed\n", arg);
94     exit (1);
95   }
96   
97   l = gst_xml_get_topelements (xml);
98   if (!l) {
99     fprintf (stderr, "ERROR: no toplevel pipeline element in file '%s'\n", arg);
100     exit (1);
101   }
102     
103   if (l->next)
104     g_warning ("only one toplevel element is supported at this time");
105   
106   pipeline = GST_ELEMENT (l->data);
107   
108   while ((arg = argv[++i])) {
109     element = g_strdup (arg);
110     property = strchr (element, '.');
111     value = strchr (element, '=');
112     
113     if (!(element < property && property < value)) {
114       fprintf (stderr, "ERROR: could not parse command line argument %d: %s", i, element);
115       g_free (element);
116       exit (1);
117     }
118     
119     *property++ = '\0';
120     *value++ = '\0';
121     
122     e = gst_bin_get_by_name (GST_BIN (pipeline), element);
123     if (!e) {
124       g_warning ("element named '%s' not found", element);
125     } else {
126       gst_util_set_object_arg (G_OBJECT (e), property, value);
127     }
128     g_free (element);
129   }
130   
131   if (!l)
132     return NULL;
133   else
134     return l->data;
135 }
136
137 int
138 main(int argc, char *argv[])
139 {
140 /* options */
141   gboolean silent = FALSE;
142   struct poptOption options[] = {
143     {"silent",  's',  POPT_ARG_NONE|POPT_ARGFLAG_STRIP, &silent, 0, "do not output status information", NULL},
144     POPT_TABLEEND
145   };
146
147   GstElement *pipeline;
148   gchar **argvn;
149   gboolean save_pipeline = FALSE;
150   gboolean run_pipeline = TRUE;
151   gchar *savefile = "";
152
153   free (malloc (8)); /* -lefence */
154
155   gst_init_with_popt_table (&argc, &argv, options);
156   
157   if (argc >= 3 && !strcmp(argv[1], "-o")) {
158     save_pipeline = TRUE;
159     run_pipeline = FALSE;
160     savefile = argv[2];
161     argv[2] = argv[0];
162     argv+=2;
163     argc-=2;
164   }
165
166   launch_argc = argc;
167   launch_argv = argv;
168
169   /* make a null-terminated version of argv */
170   argvn = g_new0 (char *,argc);
171   memcpy (argvn, argv+1, sizeof (char*) * (argc-1));
172   if (strstr (argv[0], "gst-xmllaunch")) {
173     pipeline = xmllaunch_parse_cmdline (argvn);
174   } else {
175     pipeline = (GstElement*) gst_parse_launchv (argvn);
176   }
177
178   if (!pipeline) {
179     fprintf(stderr, "ERROR: pipeline could not be constructed\n");
180     exit(1);
181   }
182   
183   if (!silent)
184     g_signal_connect (pipeline, "deep_notify", G_CALLBACK (property_change_callback), NULL);
185   g_signal_connect (pipeline, "error", G_CALLBACK (error_callback), NULL);
186   
187 #ifndef GST_DISABLE_LOADSAVE
188   if (save_pipeline) {
189     gst_xml_write_file (GST_ELEMENT (pipeline), fopen (savefile, "w"));
190   }
191 #endif
192   
193   if (run_pipeline) {
194     gst_buffer_print_stats();
195     fprintf(stderr,"RUNNING pipeline\n");
196     if (gst_element_set_state (pipeline, GST_STATE_PLAYING) != GST_STATE_SUCCESS) {
197       fprintf(stderr,"pipeline doesn't want to play\n");
198       exit (-1);
199     }
200
201     if (!GST_FLAG_IS_SET (GST_OBJECT (pipeline), GST_BIN_SELF_ITERATING)) {
202         g_idle_add (idle_func, pipeline);
203         gst_main ();
204     } else {
205         g_print ("sleeping 100...\n");
206         sleep (100);
207     }
208
209     gst_element_set_state (pipeline, GST_STATE_NULL);
210     gst_buffer_print_stats();
211
212   }
213   gst_object_unref (GST_OBJECT (pipeline));
214
215   return 0;
216 }