12 /* FIXME: This is just a temporary hack. We should have a better
13 * check for siginfo handling. */
18 extern volatile gboolean glib_on_error_halt;
19 static void fault_restore (void);
20 static void fault_spin (void);
21 static void sigint_restore (void);
23 static gint max_iterations = 0;
24 static guint64 iterations = 0;
25 static guint64 sum = 0;
26 static guint64 min = G_MAXINT64;
27 static guint64 max = 0;
28 static GstClock *s_clock;
29 static GstElement *pipeline;
30 gboolean caught_intr = FALSE;
33 idle_func (gpointer data)
36 GTimeVal tfthen, tfnow;
37 GstClockTimeDiff diff;
40 //g_print ("%" G_GINT64_FORMAT "\n", gst_clock_get_time (s_clock));
43 g_get_current_time (&tfthen);
44 busy = gst_bin_iterate (GST_BIN (data));
46 g_get_current_time (&tfnow);
48 diff = GST_TIMEVAL_TO_TIME (tfnow) -
49 GST_TIMEVAL_TO_TIME (tfthen);
52 min = MIN (min, diff);
53 max = MAX (max, diff);
55 if (!busy || caught_intr || (max_iterations>0 && iterations>=max_iterations)) {
57 g_print ("execution ended after %" G_GUINT64_FORMAT " iterations (sum %" G_GUINT64_FORMAT " ns, average %" G_GUINT64_FORMAT " ns, min %" G_GUINT64_FORMAT " ns, max %" G_GUINT64_FORMAT " ns)\n",
58 iterations, sum, sum/iterations, min, max);
64 #ifndef GST_DISABLE_LOADSAVE
66 xmllaunch_parse_cmdline (const gchar **argv)
68 GstElement *pipeline = NULL, *e;
72 gchar *element, *property, *value;
76 if (!(arg = argv[0])) {
77 g_print ("usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n");
82 err = gst_xml_parse_file(xml, arg, NULL);
85 fprintf (stderr, "ERROR: parse of xml file '%s' failed\n", arg);
89 l = gst_xml_get_topelements (xml);
91 fprintf (stderr, "ERROR: no toplevel pipeline element in file '%s'\n", arg);
96 g_warning ("only one toplevel element is supported at this time");
98 pipeline = GST_ELEMENT (l->data);
100 while ((arg = argv[++i])) {
101 element = g_strdup (arg);
102 property = strchr (element, '.');
103 value = strchr (element, '=');
105 if (!(element < property && property < value)) {
106 fprintf (stderr, "ERROR: could not parse command line argument %d: %s", i, element);
114 e = gst_bin_get_by_name (GST_BIN (pipeline), element);
116 g_warning ("element named '%s' not found", element);
118 gst_util_set_object_arg (G_OBJECT (e), property, value);
132 fault_handler_sighandler (int signum)
136 if (signum == SIGSEGV) {
137 g_print ("Caught SIGSEGV\n");
139 else if (signum == SIGQUIT){
140 g_print ("Caught SIGQUIT\n");
143 g_print ("signo: %d\n", signum);
152 fault_handler_sigaction (int signum, siginfo_t *si, void *misc)
156 if (si->si_signo == SIGSEGV) {
157 g_print ("Caught SIGSEGV accessing address %p\n", si->si_addr);
159 else if (si->si_signo == SIGQUIT){
160 g_print ("Caught SIGQUIT\n");
163 g_print ("signo: %d\n", si->si_signo);
164 g_print ("errno: %d\n", si->si_errno);
165 g_print ("code: %d\n", si->si_code);
177 glib_on_error_halt = FALSE;
178 g_on_error_stack_trace ("gst-launch");
182 /* FIXME how do we know if we were run by libtool? */
183 g_print ("Spinning. Please run 'gdb gst-launch %d' to continue debugging, "
184 "Ctrl-C to quit, or Ctrl-\\ to dump core.\n",
186 while (spinning) g_usleep (1000000);
192 struct sigaction action;
194 memset (&action, 0, sizeof (action));
195 action.sa_handler = SIG_DFL;
197 sigaction(SIGSEGV, &action, NULL);
198 sigaction(SIGQUIT, &action, NULL);
204 struct sigaction action;
206 memset (&action, 0, sizeof (action));
208 action.sa_sigaction = fault_handler_sigaction;
209 action.sa_flags = SA_SIGINFO;
211 action.sa_handler = fault_handler_sighandler;
214 sigaction (SIGSEGV, &action, NULL);
215 sigaction (SIGQUIT, &action, NULL);
218 /* we only use sighandler here because the registers are not important */
220 sigint_handler_sighandler (int signum)
222 g_print ("Caught interrupt\n");
232 struct sigaction action;
234 memset (&action, 0, sizeof (action));
235 action.sa_handler = sigint_handler_sighandler;
237 sigaction (SIGINT, &action, NULL);
241 sigint_restore (void)
243 struct sigaction action;
245 memset (&action, 0, sizeof (action));
246 action.sa_handler = SIG_DFL;
248 sigaction(SIGINT, &action, NULL);
252 main(int argc, char *argv[])
256 gboolean verbose = FALSE;
257 gboolean no_fault = FALSE;
258 gboolean trace = FALSE;
259 gchar *savefile = NULL;
260 gchar *exclude_args = NULL;
261 struct poptOption options[] = {
262 {"verbose", 'v', POPT_ARG_NONE|POPT_ARGFLAG_STRIP, &verbose, 0,
263 "output status information and property notifications", NULL},
264 {"exclude", 'X', POPT_ARG_STRING|POPT_ARGFLAG_STRIP, &exclude_args, 0,
265 "do not output status information of TYPE", "TYPE1,TYPE2,..."},
266 #ifndef GST_DISABLE_LOADSAVE
267 {"output", 'o', POPT_ARG_STRING|POPT_ARGFLAG_STRIP, &savefile, 0,
268 "save xml representation of pipeline to FILE and exit", "FILE"},
270 {"no-fault", 'f', POPT_ARG_NONE|POPT_ARGFLAG_STRIP, &no_fault, 0,
271 "Do not install a fault handler", NULL},
272 {"trace", 't', POPT_ARG_NONE|POPT_ARGFLAG_STRIP, &trace, 0,
273 "print alloc trace if enabled at compile time", NULL},
274 {"iterations",'i',POPT_ARG_INT|POPT_ARGFLAG_STRIP, &max_iterations, 0,
275 "number of times to iterate pipeline", NULL},
280 GError *error = NULL;
283 free (malloc (8)); /* -lefence */
285 gst_alloc_trace_set_flags_all (GST_ALLOC_TRACE_LIVE);
287 gst_init_with_popt_table (&argc, &argv, options);
289 /* FIXpopt: strip short args, too. We do it ourselves for now */
291 for (i = 1; i < argc; i++) {
292 if (*(argv[i]) == '-') {
293 if (strlen (argv[i]) == 2) {
296 if (*c == 'X' || *c == 'o') {
313 if (!gst_alloc_trace_available()) {
314 g_warning ("trace not available (recompile with trace enabled)");
316 gst_alloc_trace_print_all ();
319 /* make a null-terminated version of argv */
320 argvn = g_new0 (char*, argc);
321 memcpy (argvn, argv+1, sizeof (char*) * (argc-1));
322 #ifndef GST_DISABLE_LOADSAVE
323 if (strstr (argv[0], "gst-xmllaunch")) {
324 pipeline = xmllaunch_parse_cmdline ((const gchar**)argvn);
329 pipeline = (GstElement*) gst_parse_launchv ((const gchar**)argvn, &error);
335 fprintf(stderr, "ERROR: pipeline could not be constructed: %s\n", error->message);
336 g_error_free (error);
338 fprintf(stderr, "ERROR: pipeline could not be constructed\n");
342 fprintf(stderr, "WARNING: erroneous pipeline: %s\n Trying to run anyway\n", error->message);
343 g_error_free (error);
347 gchar **exclude_list = exclude_args ? g_strsplit (exclude_args, ",", 0) : NULL;
348 g_signal_connect (pipeline, "deep_notify", G_CALLBACK (gst_element_default_deep_notify), exclude_list);
350 g_signal_connect (pipeline, "error", G_CALLBACK (gst_element_default_error), NULL);
352 #ifndef GST_DISABLE_LOADSAVE
354 gst_xml_write_file (GST_ELEMENT (pipeline), fopen (savefile, "w"));
360 if (!GST_IS_BIN (pipeline)) {
361 GstElement *real_pipeline = gst_element_factory_make ("pipeline", NULL);
362 if (real_pipeline == NULL) {
363 fprintf(stderr, "ERROR: The pipeline element wasn't found.\n");
366 gst_bin_add (GST_BIN (real_pipeline), pipeline);
367 pipeline = real_pipeline;
370 fprintf(stderr,"RUNNING pipeline\n");
371 if (gst_element_set_state (pipeline, GST_STATE_PLAYING) == GST_STATE_FAILURE) {
372 fprintf(stderr,"pipeline doesn't want to play\n");
377 s_clock = gst_bin_get_clock (GST_BIN (pipeline));
379 if (!GST_FLAG_IS_SET (GST_OBJECT (pipeline), GST_BIN_SELF_SCHEDULABLE)) {
380 g_idle_add (idle_func, pipeline);
383 g_print ("waiting for the state change...\n");
384 gst_element_wait_state_change (pipeline);
385 g_print ("got the state change...\n");
388 gst_element_set_state (pipeline, GST_STATE_NULL);
393 gst_object_unref (GST_OBJECT (pipeline));
396 gst_alloc_trace_print_all ();