1 | /* GStreamer |
---|
2 | * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu> |
---|
3 | * 2000 Wim Taymans <wtay@chello.be> |
---|
4 | * 2004 Thomas Vander Stichele <thomas@apestaart.org> |
---|
5 | * |
---|
6 | * gst-launch.c: tool to launch GStreamer pipelines from the command line |
---|
7 | * |
---|
8 | * This library is free software; you can redistribute it and/or |
---|
9 | * modify it under the terms of the GNU Library General Public |
---|
10 | * License as published by the Free Software Foundation; either |
---|
11 | * version 2 of the License, or (at your option) any later version. |
---|
12 | * |
---|
13 | * This library is distributed in the hope that it will be useful, |
---|
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
16 | * Library General Public License for more details. |
---|
17 | * |
---|
18 | * You should have received a copy of the GNU Library General Public |
---|
19 | * License along with this library; if not, write to the |
---|
20 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
---|
21 | * Boston, MA 02111-1307, USA. |
---|
22 | */ |
---|
23 | |
---|
24 | #ifdef HAVE_CONFIG_H |
---|
25 | # include "config.h" |
---|
26 | #endif |
---|
27 | |
---|
28 | /* FIXME: hack alert */ |
---|
29 | #ifdef _MSC_VER |
---|
30 | #define DISABLE_FAULT_HANDLER |
---|
31 | #endif |
---|
32 | |
---|
33 | #include <string.h> |
---|
34 | #include <stdlib.h> |
---|
35 | #include <signal.h> |
---|
36 | #ifdef HAVE_UNISTD_H |
---|
37 | #include <unistd.h> |
---|
38 | #endif |
---|
39 | #ifndef DISABLE_FAULT_HANDLER |
---|
40 | #include <sys/wait.h> |
---|
41 | #endif |
---|
42 | #include <locale.h> /* for LC_ALL */ |
---|
43 | #include "gst/gst-i18n-app.h" |
---|
44 | |
---|
45 | #include <gst/gst.h> |
---|
46 | |
---|
47 | /* FIXME: This is just a temporary hack. We should have a better |
---|
48 | * check for siginfo handling. */ |
---|
49 | #ifdef SA_SIGINFO |
---|
50 | #define USE_SIGINFO |
---|
51 | #endif |
---|
52 | |
---|
53 | extern volatile gboolean glib_on_error_halt; |
---|
54 | |
---|
55 | #ifndef DISABLE_FAULT_HANDLER |
---|
56 | static void fault_restore (void); |
---|
57 | static void fault_spin (void); |
---|
58 | static void sigint_restore (void); |
---|
59 | #endif |
---|
60 | |
---|
61 | static gint max_iterations = 0; |
---|
62 | static guint64 iterations = 0; |
---|
63 | static guint64 sum = 0; |
---|
64 | static guint64 min = G_MAXINT64; |
---|
65 | static guint64 max = 0; |
---|
66 | static GstClock *s_clock; |
---|
67 | static GstElement *pipeline; |
---|
68 | static gboolean caught_intr = FALSE; |
---|
69 | static gboolean caught_error = FALSE; |
---|
70 | static gboolean need_new_state = FALSE; |
---|
71 | static GstElementState new_state; |
---|
72 | |
---|
73 | gboolean |
---|
74 | idle_func (gpointer data) |
---|
75 | { |
---|
76 | gboolean busy; |
---|
77 | GTimeVal tfthen, tfnow; |
---|
78 | GstClockTimeDiff diff; |
---|
79 | |
---|
80 | g_get_current_time (&tfthen); |
---|
81 | busy = gst_bin_iterate (GST_BIN (data)); |
---|
82 | iterations++; |
---|
83 | g_get_current_time (&tfnow); |
---|
84 | |
---|
85 | diff = GST_TIMEVAL_TO_TIME (tfnow) - GST_TIMEVAL_TO_TIME (tfthen); |
---|
86 | |
---|
87 | sum += diff; |
---|
88 | min = MIN (min, diff); |
---|
89 | max = MAX (max, diff); |
---|
90 | |
---|
91 | if (need_new_state) { |
---|
92 | gst_element_set_state (pipeline, new_state); |
---|
93 | need_new_state = FALSE; |
---|
94 | } |
---|
95 | |
---|
96 | if (!busy || caught_intr || caught_error || |
---|
97 | (max_iterations > 0 && iterations >= max_iterations)) { |
---|
98 | char *s_iterations; |
---|
99 | char *s_sum; |
---|
100 | char *s_ave; |
---|
101 | char *s_min; |
---|
102 | char *s_max; |
---|
103 | |
---|
104 | gst_main_quit (); |
---|
105 | |
---|
106 | /* We write these all to strings first because |
---|
107 | * G_GUINT64_FORMAT and gettext mix very poorly */ |
---|
108 | s_iterations = g_strdup_printf ("%" G_GUINT64_FORMAT, iterations); |
---|
109 | s_sum = g_strdup_printf ("%" G_GUINT64_FORMAT, sum); |
---|
110 | s_ave = g_strdup_printf ("%" G_GUINT64_FORMAT, sum / iterations); |
---|
111 | s_min = g_strdup_printf ("%" G_GUINT64_FORMAT, min); |
---|
112 | s_max = g_strdup_printf ("%" G_GUINT64_FORMAT, max); |
---|
113 | |
---|
114 | g_print (_("Execution ended after %s iterations (sum %s ns, " |
---|
115 | "average %s ns, min %s ns, max %s ns).\n"), |
---|
116 | s_iterations, s_sum, s_ave, s_min, s_max); |
---|
117 | g_free (s_iterations); |
---|
118 | g_free (s_sum); |
---|
119 | g_free (s_ave); |
---|
120 | g_free (s_min); |
---|
121 | g_free (s_max); |
---|
122 | } |
---|
123 | |
---|
124 | return busy; |
---|
125 | } |
---|
126 | |
---|
127 | #ifndef GST_DISABLE_LOADSAVE |
---|
128 | static GstElement * |
---|
129 | xmllaunch_parse_cmdline (const gchar ** argv) |
---|
130 | { |
---|
131 | GstElement *pipeline = NULL, *e; |
---|
132 | GstXML *xml; |
---|
133 | gboolean err; |
---|
134 | const gchar *arg; |
---|
135 | gchar *element, *property, *value; |
---|
136 | GList *l; |
---|
137 | gint i = 0; |
---|
138 | |
---|
139 | if (!(arg = argv[0])) { |
---|
140 | g_print (_ |
---|
141 | ("Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n")); |
---|
142 | exit (1); |
---|
143 | } |
---|
144 | |
---|
145 | xml = gst_xml_new (); |
---|
146 | err = gst_xml_parse_file (xml, arg, NULL); |
---|
147 | |
---|
148 | if (err != TRUE) { |
---|
149 | fprintf (stderr, _("ERROR: parse of xml file '%s' failed.\n"), arg); |
---|
150 | exit (1); |
---|
151 | } |
---|
152 | |
---|
153 | l = gst_xml_get_topelements (xml); |
---|
154 | if (!l) { |
---|
155 | fprintf (stderr, _("ERROR: no toplevel pipeline element in file '%s'.\n"), |
---|
156 | arg); |
---|
157 | exit (1); |
---|
158 | } |
---|
159 | |
---|
160 | if (l->next) |
---|
161 | fprintf (stderr, |
---|
162 | _("WARNING: only one toplevel element is supported at this time.")); |
---|
163 | |
---|
164 | pipeline = GST_ELEMENT (l->data); |
---|
165 | |
---|
166 | while ((arg = argv[++i])) { |
---|
167 | element = g_strdup (arg); |
---|
168 | property = strchr (element, '.'); |
---|
169 | value = strchr (element, '='); |
---|
170 | |
---|
171 | if (!(element < property && property < value)) { |
---|
172 | fprintf (stderr, |
---|
173 | _("ERROR: could not parse command line argument %d: %s.\n"), i, |
---|
174 | element); |
---|
175 | g_free (element); |
---|
176 | exit (1); |
---|
177 | } |
---|
178 | |
---|
179 | *property++ = '\0'; |
---|
180 | *value++ = '\0'; |
---|
181 | |
---|
182 | e = gst_bin_get_by_name (GST_BIN (pipeline), element); |
---|
183 | if (!e) { |
---|
184 | fprintf (stderr, _("WARNING: element named '%s' not found.\n"), element); |
---|
185 | } else { |
---|
186 | gst_util_set_object_arg (G_OBJECT (e), property, value); |
---|
187 | } |
---|
188 | g_free (element); |
---|
189 | } |
---|
190 | |
---|
191 | if (!l) |
---|
192 | return NULL; |
---|
193 | else |
---|
194 | return l->data; |
---|
195 | } |
---|
196 | #endif |
---|
197 | |
---|
198 | #ifndef DISABLE_FAULT_HANDLER |
---|
199 | #ifndef USE_SIGINFO |
---|
200 | static void |
---|
201 | fault_handler_sighandler (int signum) |
---|
202 | { |
---|
203 | fault_restore (); |
---|
204 | |
---|
205 | /* printf is used instead of g_print(), since it's less likely to |
---|
206 | * deadlock */ |
---|
207 | switch (signum) { |
---|
208 | case SIGSEGV: |
---|
209 | printf ("Caught SIGSEGV\n"); |
---|
210 | break; |
---|
211 | case SIGQUIT: |
---|
212 | printf ("Caught SIGQUIT\n"); |
---|
213 | break; |
---|
214 | default: |
---|
215 | printf ("signo: %d\n", signum); |
---|
216 | break; |
---|
217 | } |
---|
218 | |
---|
219 | fault_spin (); |
---|
220 | } |
---|
221 | |
---|
222 | #else |
---|
223 | |
---|
224 | static void |
---|
225 | fault_handler_sigaction (int signum, siginfo_t * si, void *misc) |
---|
226 | { |
---|
227 | fault_restore (); |
---|
228 | |
---|
229 | /* printf is used instead of g_print(), since it's less likely to |
---|
230 | * deadlock */ |
---|
231 | switch (si->si_signo) { |
---|
232 | case SIGSEGV: |
---|
233 | printf ("Caught SIGSEGV accessing address %p\n", si->si_addr); |
---|
234 | break; |
---|
235 | case SIGQUIT: |
---|
236 | printf ("Caught SIGQUIT\n"); |
---|
237 | break; |
---|
238 | default: |
---|
239 | printf ("signo: %d\n", si->si_signo); |
---|
240 | printf ("errno: %d\n", si->si_errno); |
---|
241 | printf ("code: %d\n", si->si_code); |
---|
242 | break; |
---|
243 | } |
---|
244 | |
---|
245 | fault_spin (); |
---|
246 | } |
---|
247 | #endif |
---|
248 | |
---|
249 | static void |
---|
250 | fault_spin (void) |
---|
251 | { |
---|
252 | int spinning = TRUE; |
---|
253 | |
---|
254 | glib_on_error_halt = FALSE; |
---|
255 | g_on_error_stack_trace ("gst-launch"); |
---|
256 | |
---|
257 | wait (NULL); |
---|
258 | |
---|
259 | /* FIXME how do we know if we were run by libtool? */ |
---|
260 | printf ("Spinning. Please run 'gdb gst-launch %d' to continue debugging, " |
---|
261 | "Ctrl-C to quit, or Ctrl-\\ to dump core.\n", (gint) getpid ()); |
---|
262 | while (spinning) |
---|
263 | g_usleep (1000000); |
---|
264 | } |
---|
265 | |
---|
266 | static void |
---|
267 | fault_restore (void) |
---|
268 | { |
---|
269 | struct sigaction action; |
---|
270 | |
---|
271 | memset (&action, 0, sizeof (action)); |
---|
272 | action.sa_handler = SIG_DFL; |
---|
273 | |
---|
274 | sigaction (SIGSEGV, &action, NULL); |
---|
275 | sigaction (SIGQUIT, &action, NULL); |
---|
276 | } |
---|
277 | |
---|
278 | static void |
---|
279 | fault_setup (void) |
---|
280 | { |
---|
281 | struct sigaction action; |
---|
282 | |
---|
283 | memset (&action, 0, sizeof (action)); |
---|
284 | #ifdef USE_SIGINFO |
---|
285 | action.sa_sigaction = fault_handler_sigaction; |
---|
286 | action.sa_flags = SA_SIGINFO; |
---|
287 | #else |
---|
288 | action.sa_handler = fault_handler_sighandler; |
---|
289 | #endif |
---|
290 | |
---|
291 | sigaction (SIGSEGV, &action, NULL); |
---|
292 | sigaction (SIGQUIT, &action, NULL); |
---|
293 | } |
---|
294 | #endif |
---|
295 | |
---|
296 | static void |
---|
297 | print_tag (const GstTagList * list, const gchar * tag, gpointer unused) |
---|
298 | { |
---|
299 | gint i, count; |
---|
300 | |
---|
301 | count = gst_tag_list_get_tag_size (list, tag); |
---|
302 | |
---|
303 | for (i = 0; i < count; i++) { |
---|
304 | gchar *str; |
---|
305 | |
---|
306 | if (gst_tag_get_type (tag) == G_TYPE_STRING) { |
---|
307 | if (!gst_tag_list_get_string_index (list, tag, i, &str)) |
---|
308 | g_assert_not_reached (); |
---|
309 | } else { |
---|
310 | str = |
---|
311 | g_strdup_value_contents (gst_tag_list_get_value_index (list, tag, i)); |
---|
312 | } |
---|
313 | |
---|
314 | if (i == 0) { |
---|
315 | g_print ("%15s: %s\n", gst_tag_get_nick (tag), str); |
---|
316 | } else { |
---|
317 | g_print (" : %s\n", str); |
---|
318 | } |
---|
319 | |
---|
320 | g_free (str); |
---|
321 | } |
---|
322 | } |
---|
323 | |
---|
324 | static void |
---|
325 | found_tag (GObject * pipeline, GstElement * source, GstTagList * tags) |
---|
326 | { |
---|
327 | g_print (_("FOUND TAG : found by element \"%s\".\n"), |
---|
328 | GST_STR_NULL (GST_ELEMENT_NAME (source))); |
---|
329 | gst_tag_list_foreach (tags, print_tag, NULL); |
---|
330 | } |
---|
331 | |
---|
332 | static void |
---|
333 | error_cb (GObject * object, GstObject * source, GError * error, gchar * debug) |
---|
334 | { |
---|
335 | gst_element_default_error (object, source, error, debug); |
---|
336 | caught_error = TRUE; |
---|
337 | } |
---|
338 | |
---|
339 | #ifndef DISABLE_FAULT_HANDLER |
---|
340 | /* we only use sighandler here because the registers are not important */ |
---|
341 | static void |
---|
342 | sigint_handler_sighandler (int signum) |
---|
343 | { |
---|
344 | sigint_restore (); |
---|
345 | |
---|
346 | caught_intr = TRUE; |
---|
347 | } |
---|
348 | |
---|
349 | static void |
---|
350 | sigint_setup (void) |
---|
351 | { |
---|
352 | struct sigaction action; |
---|
353 | |
---|
354 | memset (&action, 0, sizeof (action)); |
---|
355 | action.sa_handler = sigint_handler_sighandler; |
---|
356 | |
---|
357 | sigaction (SIGINT, &action, NULL); |
---|
358 | } |
---|
359 | |
---|
360 | static void |
---|
361 | sigint_restore (void) |
---|
362 | { |
---|
363 | struct sigaction action; |
---|
364 | |
---|
365 | memset (&action, 0, sizeof (action)); |
---|
366 | action.sa_handler = SIG_DFL; |
---|
367 | |
---|
368 | sigaction (SIGINT, &action, NULL); |
---|
369 | } |
---|
370 | |
---|
371 | static void |
---|
372 | play_handler (int signum) |
---|
373 | { |
---|
374 | switch (signum) { |
---|
375 | case SIGUSR1: |
---|
376 | new_state = GST_STATE_PLAYING; |
---|
377 | need_new_state = TRUE; |
---|
378 | break; |
---|
379 | case SIGUSR2: |
---|
380 | new_state = GST_STATE_NULL; |
---|
381 | need_new_state = TRUE; |
---|
382 | break; |
---|
383 | } |
---|
384 | } |
---|
385 | |
---|
386 | static void |
---|
387 | play_signal_setup (void) |
---|
388 | { |
---|
389 | struct sigaction action; |
---|
390 | |
---|
391 | memset (&action, 0, sizeof (action)); |
---|
392 | action.sa_handler = play_handler; |
---|
393 | sigaction (SIGUSR1, &action, NULL); |
---|
394 | sigaction (SIGUSR2, &action, NULL); |
---|
395 | } |
---|
396 | #endif |
---|
397 | |
---|
398 | int |
---|
399 | main (int argc, char *argv[]) |
---|
400 | { |
---|
401 | gint i, j; |
---|
402 | |
---|
403 | /* options */ |
---|
404 | gboolean verbose = FALSE; |
---|
405 | gboolean tags = FALSE; |
---|
406 | gboolean no_fault = FALSE; |
---|
407 | gboolean trace = FALSE; |
---|
408 | gchar *savefile = NULL; |
---|
409 | gchar *exclude_args = NULL; |
---|
410 | struct poptOption options[] = { |
---|
411 | {"tags", 't', POPT_ARG_NONE | POPT_ARGFLAG_STRIP, &tags, 0, |
---|
412 | N_("Output tags (also known as metadata)"), NULL}, |
---|
413 | {"verbose", 'v', POPT_ARG_NONE | POPT_ARGFLAG_STRIP, &verbose, 0, |
---|
414 | N_("Output status information and property notifications"), NULL}, |
---|
415 | {"exclude", 'X', POPT_ARG_STRING | POPT_ARGFLAG_STRIP, &exclude_args, 0, |
---|
416 | N_("Do not output status information of TYPE"), N_("TYPE1,TYPE2,...")}, |
---|
417 | #ifndef GST_DISABLE_LOADSAVE |
---|
418 | {"output", 'o', POPT_ARG_STRING | POPT_ARGFLAG_STRIP, &savefile, 0, |
---|
419 | N_("Save xml representation of pipeline to FILE and exit"), N_("FILE")}, |
---|
420 | #endif |
---|
421 | {"no-fault", 'f', POPT_ARG_NONE | POPT_ARGFLAG_STRIP, &no_fault, 0, |
---|
422 | N_("Do not install a fault handler"), NULL}, |
---|
423 | {"trace", 'T', POPT_ARG_NONE | POPT_ARGFLAG_STRIP, &trace, 0, |
---|
424 | N_("Print alloc trace (if enabled at compile time)"), NULL}, |
---|
425 | {"iterations", 'i', POPT_ARG_INT | POPT_ARGFLAG_STRIP, &max_iterations, 0, |
---|
426 | N_("Number of times to iterate pipeline"), NULL}, |
---|
427 | POPT_TABLEEND |
---|
428 | }; |
---|
429 | |
---|
430 | gchar **argvn; |
---|
431 | GError *error = NULL; |
---|
432 | gint res = 0; |
---|
433 | |
---|
434 | free (malloc (8)); /* -lefence */ |
---|
435 | |
---|
436 | #ifdef GETTEXT_PACKAGE |
---|
437 | bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); |
---|
438 | bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); |
---|
439 | textdomain (GETTEXT_PACKAGE); |
---|
440 | #endif |
---|
441 | |
---|
442 | gst_alloc_trace_set_flags_all (GST_ALLOC_TRACE_LIVE); |
---|
443 | |
---|
444 | gst_init_with_popt_table (&argc, &argv, options); |
---|
445 | |
---|
446 | /* FIXpopt: strip short args, too. We do it ourselves for now */ |
---|
447 | j = 1; |
---|
448 | for (i = 1; i < argc; i++) { |
---|
449 | if (*(argv[i]) == '-') { |
---|
450 | if (strlen (argv[i]) == 2) { |
---|
451 | gchar *c = argv[i]; |
---|
452 | |
---|
453 | c++; |
---|
454 | if (*c == 'X' || *c == 'o') { |
---|
455 | i++; |
---|
456 | } |
---|
457 | } |
---|
458 | } else { |
---|
459 | argv[j] = argv[i]; |
---|
460 | j++; |
---|
461 | } |
---|
462 | } |
---|
463 | argc = j; |
---|
464 | |
---|
465 | #ifndef DISABLE_FAULT_HANDLER |
---|
466 | if (!no_fault) |
---|
467 | fault_setup (); |
---|
468 | |
---|
469 | sigint_setup (); |
---|
470 | play_signal_setup (); |
---|
471 | #endif |
---|
472 | |
---|
473 | if (trace) { |
---|
474 | if (!gst_alloc_trace_available ()) { |
---|
475 | g_warning ("Trace not available (recompile with trace enabled)."); |
---|
476 | } |
---|
477 | gst_alloc_trace_print_all (); |
---|
478 | } |
---|
479 | |
---|
480 | /* make a null-terminated version of argv */ |
---|
481 | argvn = g_new0 (char *, argc); |
---|
482 | memcpy (argvn, argv + 1, sizeof (char *) * (argc - 1)); |
---|
483 | #ifndef GST_DISABLE_LOADSAVE |
---|
484 | if (strstr (argv[0], "gst-xmllaunch")) { |
---|
485 | pipeline = xmllaunch_parse_cmdline ((const gchar **) argvn); |
---|
486 | } else |
---|
487 | #endif |
---|
488 | { |
---|
489 | pipeline = |
---|
490 | (GstElement *) gst_parse_launchv ((const gchar **) argvn, &error); |
---|
491 | } |
---|
492 | g_free (argvn); |
---|
493 | |
---|
494 | if (!pipeline) { |
---|
495 | if (error) { |
---|
496 | fprintf (stderr, _("ERROR: pipeline could not be constructed: %s.\n"), |
---|
497 | error->message); |
---|
498 | g_error_free (error); |
---|
499 | } else { |
---|
500 | fprintf (stderr, _("ERROR: pipeline could not be constructed.\n")); |
---|
501 | } |
---|
502 | return 1; |
---|
503 | } else if (error) { |
---|
504 | fprintf (stderr, _("WARNING: erroneous pipeline: %s\n"), error->message); |
---|
505 | fprintf (stderr, _(" Trying to run anyway.\n")); |
---|
506 | g_error_free (error); |
---|
507 | } |
---|
508 | |
---|
509 | if (verbose) { |
---|
510 | gchar **exclude_list = |
---|
511 | exclude_args ? g_strsplit (exclude_args, ",", 0) : NULL; |
---|
512 | g_signal_connect (pipeline, "deep_notify", |
---|
513 | G_CALLBACK (gst_element_default_deep_notify), exclude_list); |
---|
514 | } |
---|
515 | if (tags) { |
---|
516 | g_signal_connect (pipeline, "found-tag", G_CALLBACK (found_tag), NULL); |
---|
517 | } |
---|
518 | g_signal_connect (pipeline, "error", G_CALLBACK (error_cb), NULL); |
---|
519 | |
---|
520 | #ifndef GST_DISABLE_LOADSAVE |
---|
521 | if (savefile) { |
---|
522 | gst_xml_write_file (GST_ELEMENT (pipeline), fopen (savefile, "w")); |
---|
523 | } |
---|
524 | #endif |
---|
525 | |
---|
526 | if (!savefile) { |
---|
527 | |
---|
528 | if (!GST_IS_BIN (pipeline)) { |
---|
529 | GstElement *real_pipeline = gst_element_factory_make ("pipeline", NULL); |
---|
530 | |
---|
531 | if (real_pipeline == NULL) { |
---|
532 | fprintf (stderr, _("ERROR: the 'pipeline' element wasn't found.\n")); |
---|
533 | return 1; |
---|
534 | } |
---|
535 | gst_bin_add (GST_BIN (real_pipeline), pipeline); |
---|
536 | pipeline = real_pipeline; |
---|
537 | } |
---|
538 | |
---|
539 | fprintf (stderr, _("RUNNING pipeline ...\n")); |
---|
540 | if (gst_element_set_state (pipeline, |
---|
541 | GST_STATE_PLAYING) == GST_STATE_FAILURE) { |
---|
542 | fprintf (stderr, _("ERROR: pipeline doesn't want to play.\n")); |
---|
543 | res = -1; |
---|
544 | goto end; |
---|
545 | } |
---|
546 | |
---|
547 | s_clock = gst_bin_get_clock (GST_BIN (pipeline)); |
---|
548 | |
---|
549 | if (!GST_FLAG_IS_SET (GST_OBJECT (pipeline), GST_BIN_SELF_SCHEDULABLE)) { |
---|
550 | g_idle_add (idle_func, pipeline); |
---|
551 | gst_main (); |
---|
552 | } else { |
---|
553 | g_print ("Waiting for the state change... "); |
---|
554 | gst_element_wait_state_change (pipeline); |
---|
555 | g_print ("got the state change.\n"); |
---|
556 | } |
---|
557 | if (caught_intr) { |
---|
558 | g_print ("Caught interrupt.\n"); |
---|
559 | res = 2; |
---|
560 | } |
---|
561 | if (caught_error) |
---|
562 | res = 3; |
---|
563 | |
---|
564 | gst_element_set_state (pipeline, GST_STATE_NULL); |
---|
565 | } |
---|
566 | |
---|
567 | end: |
---|
568 | |
---|
569 | gst_object_unref (GST_OBJECT (pipeline)); |
---|
570 | |
---|
571 | if (trace) |
---|
572 | gst_alloc_trace_print_all (); |
---|
573 | |
---|
574 | return res; |
---|
575 | } |
---|