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