X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=tools%2Fgst-launch.c;h=a8ab1cdfa4b44dbd9ca7bcd92aac491faed483e0;hb=892d36211fac3a2c663d9a1198c8a75a2dc3645e;hp=2687dfd7fd94863d26adfd111c77b1d60f8c171e;hpb=2fe5b4cf91baa94c91b57914238f7e1773656c15;p=platform%2Fupstream%2Fgstreamer.git diff --git a/tools/gst-launch.c b/tools/gst-launch.c index 2687dfd..a8ab1cd 100644 --- a/tools/gst-launch.c +++ b/tools/gst-launch.c @@ -17,44 +17,33 @@ * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H # include "config.h" #endif -/* FIXME: hack alert */ -#ifdef HAVE_WIN32 -#define DISABLE_FAULT_HANDLER -#endif - +#include #include #include #include #ifdef HAVE_UNISTD_H #include #endif -#ifndef DISABLE_FAULT_HANDLER +#ifdef G_OS_UNIX +#include #include #endif #include /* for LC_ALL */ #include "tools.h" -/* FIXME: This is just a temporary hack. We should have a better - * check for siginfo handling. */ -#ifdef SA_SIGINFO -#define USE_SIGINFO -#endif - extern volatile gboolean glib_on_error_halt; -#ifndef DISABLE_FAULT_HANDLER +#ifdef G_OS_UNIX static void fault_restore (void); static void fault_spin (void); -static void sigint_restore (void); -static gboolean caught_intr = FALSE; #endif /* event_loop return codes */ @@ -69,6 +58,7 @@ static GstElement *pipeline; static EventLoopResult caught_error = ELR_NO_ERROR; static gboolean quiet = FALSE; static gboolean tags = FALSE; +static gboolean toc = FALSE; static gboolean messages = FALSE; static gboolean is_live = FALSE; static gboolean waiting_eos = FALSE; @@ -76,8 +66,7 @@ static gboolean waiting_eos = FALSE; /* convenience macro so we don't have to litter the code with if(!quiet) */ #define PRINT if(!quiet)g_print -#ifndef DISABLE_FAULT_HANDLER -#ifndef USE_SIGINFO +#ifdef G_OS_UNIX static void fault_handler_sighandler (int signum) { @@ -101,48 +90,21 @@ fault_handler_sighandler (int signum) fault_spin (); } -#else /* USE_SIGINFO */ - -static void -fault_handler_sigaction (int signum, siginfo_t * si, void *misc) -{ - fault_restore (); - - /* printf is used instead of g_print(), since it's less likely to - * deadlock */ - switch (si->si_signo) { - case SIGSEGV: - fprintf (stderr, "Caught SIGSEGV accessing address %p\n", si->si_addr); - break; - case SIGQUIT: - if (!quiet) - printf ("Caught SIGQUIT\n"); - break; - default: - fprintf (stderr, "signo: %d\n", si->si_signo); - fprintf (stderr, "errno: %d\n", si->si_errno); - fprintf (stderr, "code: %d\n", si->si_code); - break; - } - - fault_spin (); -} -#endif /* USE_SIGINFO */ - static void fault_spin (void) { int spinning = TRUE; glib_on_error_halt = FALSE; - g_on_error_stack_trace ("gst-launch"); + g_on_error_stack_trace ("gst-launch-" GST_API_VERSION); wait (NULL); /* FIXME how do we know if we were run by libtool? */ fprintf (stderr, - "Spinning. Please run 'gdb gst-launch %d' to continue debugging, " - "Ctrl-C to quit, or Ctrl-\\ to dump core.\n", (gint) getpid ()); + "Spinning. Please run 'gdb gst-launch-" GST_API_VERSION " %d' to " + "continue debugging, Ctrl-C to quit, or Ctrl-\\ to dump core.\n", + (gint) getpid ()); while (spinning) g_usleep (1000000); } @@ -165,18 +127,14 @@ fault_setup (void) struct sigaction action; memset (&action, 0, sizeof (action)); -#ifdef USE_SIGINFO - action.sa_sigaction = fault_handler_sigaction; - action.sa_flags = SA_SIGINFO; -#else action.sa_handler = fault_handler_sighandler; -#endif sigaction (SIGSEGV, &action, NULL); sigaction (SIGQUIT, &action, NULL); } -#endif /* DISABLE_FAULT_HANDLER */ +#endif /* G_OS_UNIX */ +#if 0 typedef struct _GstIndexStats { gint id; @@ -329,6 +287,7 @@ print_index_stats (GPtrArray * index_stats) } } } +#endif /* Kids, use the functions from libgstpbutils in gst-plugins-base in your * own code (we can't do that here because it would introduce a circular @@ -376,32 +335,45 @@ print_tag (const GstTagList * list, const gchar * tag, gpointer unused) count = gst_tag_list_get_tag_size (list, tag); for (i = 0; i < count; i++) { - gchar *str; + gchar *str = NULL; if (gst_tag_get_type (tag) == G_TYPE_STRING) { - if (!gst_tag_list_get_string_index (list, tag, i, &str)) + if (!gst_tag_list_get_string_index (list, tag, i, &str)) { + g_warning ("Couldn't fetch string for %s tag", tag); g_assert_not_reached (); - } else if (gst_tag_get_type (tag) == GST_TYPE_BUFFER) { - GstBuffer *img; + } + } else if (gst_tag_get_type (tag) == GST_TYPE_SAMPLE) { + GstSample *sample = NULL; + + if (gst_tag_list_get_sample_index (list, tag, i, &sample)) { + GstBuffer *img = gst_sample_get_buffer (sample); + GstCaps *caps = gst_sample_get_caps (sample); - img = gst_value_get_buffer (gst_tag_list_get_value_index (list, tag, i)); - if (img) { - gchar *caps_str; + if (img) { + if (caps) { + gchar *caps_str; - caps_str = g_strdup ("unknown"); - str = g_strdup_printf ("buffer of %" G_GSIZE_FORMAT " bytes, type: %s", - gst_buffer_get_size (img), caps_str); - g_free (caps_str); + caps_str = gst_caps_to_string (caps); + str = g_strdup_printf ("buffer of %" G_GSIZE_FORMAT " bytes, " + "type: %s", gst_buffer_get_size (img), caps_str); + g_free (caps_str); + } else { + str = g_strdup_printf ("buffer of %" G_GSIZE_FORMAT " bytes", + gst_buffer_get_size (img)); + } + } else { + str = g_strdup ("NULL buffer"); + } } else { - str = g_strdup ("NULL buffer"); + g_warning ("Couldn't fetch sample for %s tag", tag); + g_assert_not_reached (); } } else if (gst_tag_get_type (tag) == GST_TYPE_DATE_TIME) { GstDateTime *dt = NULL; gst_tag_list_get_date_time_index (list, tag, i, &dt); - if (gst_date_time_get_hour (dt) < 0) { - str = g_strdup_printf ("%02u-%02u-%04u", gst_date_time_get_day (dt), - gst_date_time_get_month (dt), gst_date_time_get_year (dt)); + if (!gst_date_time_has_time (dt)) { + str = gst_date_time_to_iso8601_string (dt); } else { gdouble tz_offset = gst_date_time_get_time_zone_offset (dt); gchar tz_str[32]; @@ -425,99 +397,115 @@ print_tag (const GstTagList * list, const gchar * tag, gpointer unused) g_strdup_value_contents (gst_tag_list_get_value_index (list, tag, i)); } - if (i == 0) { - PRINT ("%16s: %s\n", gst_tag_get_nick (tag), str); - } else { - PRINT ("%16s: %s\n", "", str); + if (str) { + PRINT ("%16s: %s\n", i == 0 ? gst_tag_get_nick (tag) : "", str); + g_free (str); } - - g_free (str); } } -#ifndef DISABLE_FAULT_HANDLER -/* we only use sighandler here because the registers are not important */ static void -sigint_handler_sighandler (int signum) +print_tag_foreach (const GstTagList * tags, const gchar * tag, + gpointer user_data) { - PRINT ("Caught interrupt -- "); - - /* If we were waiting for an EOS, we still want to catch - * the next signal to shutdown properly (and the following one - * will quit the program). */ - if (waiting_eos) { - waiting_eos = FALSE; - } else { - sigint_restore (); - } - /* we set a flag that is checked by the mainloop, we cannot do much in the - * interrupt handler (no mutex or other blocking stuff) */ - caught_intr = TRUE; -} + GValue val = { 0, }; + gchar *str; + gint depth = GPOINTER_TO_INT (user_data); -/* is called every 250 milliseconds (4 times a second), the interrupt handler - * will set a flag for us. We react to this by posting a message. */ -static gboolean -check_intr (GstElement * pipeline) -{ - if (!caught_intr) { - return TRUE; - } else { - caught_intr = FALSE; - PRINT ("handling interrupt.\n"); - - /* post an application specific message */ - gst_element_post_message (GST_ELEMENT (pipeline), - gst_message_new_application (GST_OBJECT (pipeline), - gst_structure_new ("GstLaunchInterrupt", - "message", G_TYPE_STRING, "Pipeline interrupted", NULL))); - - /* remove timeout handler */ - return FALSE; - } + if (!gst_tag_list_copy_value (&val, tags, tag)) + return; + + if (G_VALUE_HOLDS_STRING (&val)) + str = g_value_dup_string (&val); + else + str = gst_value_serialize (&val); + + g_print ("%*s%s: %s\n", 2 * depth, " ", gst_tag_get_nick (tag), str); + g_free (str); + + g_value_unset (&val); } +#define MAX_INDENT 40 + static void -sigint_setup (void) +print_toc_entry (gpointer data, gpointer user_data) { - struct sigaction action; + GstTocEntry *entry = (GstTocEntry *) data; + const gchar spc[MAX_INDENT + 1] = " "; + guint indent = MIN (GPOINTER_TO_UINT (user_data), MAX_INDENT); + const GstTagList *tags; + GList *subentries; + gint64 start, stop; + + gst_toc_entry_get_start_stop_times (entry, &start, &stop); + + PRINT ("%s%s:", &spc[MAX_INDENT - indent], + gst_toc_entry_type_get_nick (gst_toc_entry_get_entry_type (entry))); + if (GST_CLOCK_TIME_IS_VALID (start)) { + PRINT (" start: %" GST_TIME_FORMAT, GST_TIME_ARGS (start)); + } + if (GST_CLOCK_TIME_IS_VALID (stop)) { + PRINT (" stop: %" GST_TIME_FORMAT, GST_TIME_ARGS (stop)); + } + PRINT ("\n"); + indent += 2; - memset (&action, 0, sizeof (action)); - action.sa_handler = sigint_handler_sighandler; + /* print tags */ + tags = gst_toc_entry_get_tags (entry); + if (tags) + gst_tag_list_foreach (tags, print_tag_foreach, GUINT_TO_POINTER (indent)); - sigaction (SIGINT, &action, NULL); + /* loop over sub-toc entries */ + subentries = gst_toc_entry_get_sub_entries (entry); + g_list_foreach (subentries, print_toc_entry, GUINT_TO_POINTER (indent)); } -static void -sigint_restore (void) +#ifdef G_OS_UNIX +static guint signal_watch_id; +#endif + +#ifdef G_OS_UNIX +/* As the interrupt handler is dispatched from GMainContext as a GSourceFunc + * handler, we can react to this by posting a message. */ +static gboolean +intr_handler (gpointer user_data) { - struct sigaction action; + GstElement *pipeline = (GstElement *) user_data; - memset (&action, 0, sizeof (action)); - action.sa_handler = SIG_DFL; + PRINT ("handling interrupt.\n"); + + /* post an application specific message */ + gst_element_post_message (GST_ELEMENT (pipeline), + gst_message_new_application (GST_OBJECT (pipeline), + gst_structure_new ("GstLaunchInterrupt", + "message", G_TYPE_STRING, "Pipeline interrupted", NULL))); - sigaction (SIGINT, &action, NULL); + /* remove signal handler */ + signal_watch_id = 0; + return FALSE; } -#endif /* DISABLE_FAULT_HANDLER */ + +#endif /* G_OS_UNIX */ /* returns ELR_ERROR if there was an error * or ELR_INTERRUPT if we caught a keyboard interrupt * or ELR_NO_ERROR otherwise. */ static EventLoopResult -event_loop (GstElement * pipeline, gboolean blocking, GstState target_state) +event_loop (GstElement * pipeline, gboolean blocking, gboolean do_progress, + GstState target_state) { -#ifndef DISABLE_FAULT_HANDLER - gulong timeout_id; -#endif GstBus *bus; GstMessage *message = NULL; EventLoopResult res = ELR_NO_ERROR; - gboolean buffering = FALSE; + gboolean buffering = FALSE, in_progress = FALSE; + gboolean prerolled = target_state != GST_STATE_PAUSED; bus = gst_element_get_bus (GST_ELEMENT (pipeline)); -#ifndef DISABLE_FAULT_HANDLER - timeout_id = g_timeout_add (250, (GSourceFunc) check_intr, pipeline); +#ifdef G_OS_UNIX + signal_watch_id = + g_unix_signal_add (SIGINT, (GSourceFunc) intr_handler, pipeline); #endif while (TRUE) { @@ -590,7 +578,7 @@ event_loop (GstElement * pipeline, gboolean blocking, GstState target_state) } case GST_MESSAGE_TAG: if (tags) { - GstTagList *tags; + GstTagList *tag_list; if (GST_IS_ELEMENT (GST_MESSAGE_SRC (message))) { PRINT (_("FOUND TAG : found by element \"%s\".\n"), @@ -605,9 +593,32 @@ event_loop (GstElement * pipeline, gboolean blocking, GstState target_state) PRINT (_("FOUND TAG\n")); } - gst_message_parse_tag (message, &tags); - gst_tag_list_foreach (tags, print_tag, NULL); - gst_tag_list_free (tags); + gst_message_parse_tag (message, &tag_list); + gst_tag_list_foreach (tag_list, print_tag, NULL); + gst_tag_list_unref (tag_list); + } + break; + case GST_MESSAGE_TOC: + if (toc) { + GstToc *toc; + GList *entries; + gboolean updated; + + if (GST_IS_ELEMENT (GST_MESSAGE_SRC (message))) { + PRINT (_("FOUND TOC : found by element \"%s\".\n"), + GST_MESSAGE_SRC_NAME (message)); + } else if (GST_IS_OBJECT (GST_MESSAGE_SRC (message))) { + PRINT (_("FOUND TOC : found by object \"%s\".\n"), + GST_MESSAGE_SRC_NAME (message)); + } else { + PRINT (_("FOUND TOC\n")); + } + + gst_message_parse_toc (message, &toc, &updated); + /* recursively loop over toc entries */ + entries = gst_toc_get_entries (toc); + g_list_foreach (entries, print_toc_entry, GUINT_TO_POINTER (0)); + gst_toc_unref (toc); } break; case GST_MESSAGE_INFO:{ @@ -661,19 +672,23 @@ event_loop (GstElement * pipeline, gboolean blocking, GstState target_state) if (GST_MESSAGE_SRC (message) != GST_OBJECT_CAST (pipeline)) break; - /* ignore when we are buffering since then we mess with the states - * ourselves. */ - if (buffering) { - PRINT (_("Prerolled, waiting for buffering to finish...\n")); - break; - } - gst_message_parse_state_changed (message, &old, &new, &pending); /* if we reached the final target state, exit */ - if (target_state == GST_STATE_PAUSED && new == target_state) + if (target_state == GST_STATE_PAUSED && new == target_state) { + prerolled = TRUE; + /* ignore when we are buffering since then we mess with the states + * ourselves. */ + if (buffering) { + PRINT (_("Prerolled, waiting for buffering to finish...\n")); + break; + } + if (in_progress) { + PRINT (_("Prerolled, waiting for progress to finish...\n")); + break; + } goto exit; - + } /* else not an interesting message */ break; } @@ -694,7 +709,7 @@ event_loop (GstElement * pipeline, gboolean blocking, GstState target_state) if (target_state == GST_STATE_PLAYING) { PRINT (_("Done buffering, setting pipeline to PLAYING ...\n")); gst_element_set_state (pipeline, GST_STATE_PLAYING); - } else + } else if (prerolled && !in_progress) goto exit; } else { /* buffering busy */ @@ -742,6 +757,37 @@ event_loop (GstElement * pipeline, gboolean blocking, GstState target_state) } break; } + case GST_MESSAGE_PROGRESS: + { + GstProgressType type; + gchar *code, *text; + + gst_message_parse_progress (message, &type, &code, &text); + + switch (type) { + case GST_PROGRESS_TYPE_START: + case GST_PROGRESS_TYPE_CONTINUE: + if (do_progress) { + in_progress = TRUE; + blocking = TRUE; + } + break; + case GST_PROGRESS_TYPE_COMPLETE: + case GST_PROGRESS_TYPE_CANCELED: + case GST_PROGRESS_TYPE_ERROR: + in_progress = FALSE; + break; + default: + break; + } + PRINT (_("Progress: (%s) %s\n"), code, text); + g_free (code); + g_free (text); + + if (do_progress && !in_progress && !buffering && prerolled) + goto exit; + break; + } case GST_MESSAGE_ELEMENT:{ if (gst_is_missing_plugin_message (message)) { const gchar *desc; @@ -751,6 +797,23 @@ event_loop (GstElement * pipeline, gboolean blocking, GstState target_state) } break; } + case GST_MESSAGE_HAVE_CONTEXT:{ + GstContext *context; + const gchar *context_type; + gchar *context_str; + + gst_message_parse_have_context (message, &context); + + context_type = gst_context_get_context_type (context); + context_str = + gst_structure_to_string (gst_context_get_structure (context)); + PRINT (_("Got context from element '%s': %s=%s\n"), + GST_ELEMENT_NAME (GST_MESSAGE_SRC (message)), context_type, + context_str); + g_free (context_str); + gst_context_unref (context); + break; + } default: /* just be quiet by default */ break; @@ -765,8 +828,9 @@ exit: if (message) gst_message_unref (message); gst_object_unref (bus); -#ifndef DISABLE_FAULT_HANDLER - g_source_remove (timeout_id); +#ifdef G_OS_UNIX + if (signal_watch_id > 0) + g_source_remove (signal_watch_id); #endif return res; } @@ -808,6 +872,7 @@ bus_sync_handler (GstBus * bus, GstMessage * message, gpointer data) g_free (state_transition_name); } + break; default: break; } @@ -820,15 +885,18 @@ main (int argc, char *argv[]) /* options */ gboolean verbose = FALSE; gboolean no_fault = FALSE; - gboolean trace = FALSE; gboolean eos_on_shutdown = FALSE; +#if 0 gboolean check_index = FALSE; +#endif gchar *savefile = NULL; gchar *exclude_args = NULL; #ifndef GST_DISABLE_OPTION_PARSING GOptionEntry options[] = { {"tags", 't', 0, G_OPTION_ARG_NONE, &tags, N_("Output tags (also known as metadata)"), NULL}, + {"toc", 'c', 0, G_OPTION_ARG_NONE, &toc, + N_("Output TOC (chapters and editions)"), NULL}, {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, N_("Output status information and property notifications"), NULL}, {"quiet", 'q', 0, G_OPTION_ARG_NONE, &quiet, @@ -839,22 +907,25 @@ main (int argc, char *argv[]) N_("Do not output status information of TYPE"), N_("TYPE1,TYPE2,...")}, {"no-fault", 'f', 0, G_OPTION_ARG_NONE, &no_fault, N_("Do not install a fault handler"), NULL}, - {"trace", 'T', 0, G_OPTION_ARG_NONE, &trace, - N_("Print alloc trace (if enabled at compile time)"), NULL}, {"eos-on-shutdown", 'e', 0, G_OPTION_ARG_NONE, &eos_on_shutdown, N_("Force EOS on sources before shutting the pipeline down"), NULL}, +#if 0 {"index", 'i', 0, G_OPTION_ARG_NONE, &check_index, N_("Gather and print index statistics"), NULL}, +#endif GST_TOOLS_GOPTION_VERSION, {NULL} }; GOptionContext *ctx; GError *err = NULL; #endif +#if 0 GstIndex *index; GPtrArray *index_stats = NULL; +#endif gchar **argvn; GError *error = NULL; + gulong deep_notify_id = 0; gint res = 0; free (malloc (8)); /* -lefence */ @@ -865,9 +936,7 @@ main (int argc, char *argv[]) textdomain (GETTEXT_PACKAGE); #endif - g_thread_init (NULL); - - gst_tools_set_prgname ("gst-launch"); + g_set_prgname ("gst-launch-" GST_API_VERSION); #ifndef GST_DISABLE_OPTION_PARSING ctx = g_option_context_new ("PIPELINE-DESCRIPTION"); @@ -885,24 +954,13 @@ main (int argc, char *argv[]) gst_init (&argc, &argv); #endif - gst_tools_print_version ("gst-launch"); + gst_tools_print_version (); -#ifndef DISABLE_FAULT_HANDLER +#ifdef G_OS_UNIX if (!no_fault) fault_setup (); - - sigint_setup (); #endif - if (trace) { - if (!gst_alloc_trace_available ()) { - g_warning ("Trace not available (recompile with trace enabled)."); - } - gst_alloc_trace_set_flags_all (GST_ALLOC_TRACE_LIVE | - GST_ALLOC_TRACE_MEM_LIVE); - gst_alloc_trace_print_live (); - } - /* make a null-terminated version of argv */ argvn = g_new0 (char *, argc); memcpy (argvn, argv + 1, sizeof (char *) * (argc - 1)); @@ -931,7 +989,7 @@ main (int argc, char *argv[]) if (verbose) { gchar **exclude_list = exclude_args ? g_strsplit (exclude_args, ",", 0) : NULL; - g_signal_connect (pipeline, "deep-notify", + deep_notify_id = g_signal_connect (pipeline, "deep-notify", G_CALLBACK (gst_object_default_deep_notify), exclude_list); } @@ -951,7 +1009,7 @@ main (int argc, char *argv[]) gst_bin_add (GST_BIN (real_pipeline), pipeline); pipeline = real_pipeline; } - +#if 0 if (check_index) { /* gst_index_new() creates a null-index, it does not store anything, but * the entry-added signal works and this is what we use to build the @@ -966,9 +1024,10 @@ main (int argc, char *argv[]) gst_element_set_index (pipeline, index); } } +#endif bus = gst_element_get_bus (pipeline); - gst_bus_set_sync_handler (bus, bus_sync_handler, (gpointer) pipeline); + gst_bus_set_sync_handler (bus, bus_sync_handler, (gpointer) pipeline, NULL); gst_object_unref (bus); PRINT (_("Setting pipeline to PAUSED ...\n")); @@ -978,7 +1037,7 @@ main (int argc, char *argv[]) case GST_STATE_CHANGE_FAILURE: g_printerr (_("ERROR: Pipeline doesn't want to pause.\n")); res = -1; - event_loop (pipeline, FALSE, GST_STATE_VOID_PENDING); + event_loop (pipeline, FALSE, FALSE, GST_STATE_VOID_PENDING); goto end; case GST_STATE_CHANGE_NO_PREROLL: PRINT (_("Pipeline is live and does not need PREROLL ...\n")); @@ -986,9 +1045,10 @@ main (int argc, char *argv[]) break; case GST_STATE_CHANGE_ASYNC: PRINT (_("Pipeline is PREROLLING ...\n")); - caught_error = event_loop (pipeline, TRUE, GST_STATE_PAUSED); + caught_error = event_loop (pipeline, TRUE, TRUE, GST_STATE_PAUSED); if (caught_error) { g_printerr (_("ERROR: pipeline doesn't want to preroll.\n")); + res = caught_error; goto end; } state = GST_STATE_PAUSED; @@ -998,10 +1058,11 @@ main (int argc, char *argv[]) break; } - caught_error = event_loop (pipeline, FALSE, GST_STATE_PLAYING); + caught_error = event_loop (pipeline, FALSE, TRUE, GST_STATE_PLAYING); if (caught_error) { g_printerr (_("ERROR: pipeline doesn't want to preroll.\n")); + res = caught_error; } else { GstClockTime tfthen, tfnow; GstClockTimeDiff diff; @@ -1025,26 +1086,48 @@ main (int argc, char *argv[]) } tfthen = gst_util_get_timestamp (); - caught_error = event_loop (pipeline, TRUE, GST_STATE_PLAYING); - if (eos_on_shutdown && caught_error == ELR_INTERRUPT) { - PRINT (_("EOS on shutdown enabled -- Forcing EOS on the pipeline\n")); + caught_error = event_loop (pipeline, TRUE, FALSE, GST_STATE_PLAYING); + if (eos_on_shutdown && caught_error != ELR_NO_ERROR) { + gboolean ignore_errors; + waiting_eos = TRUE; - gst_element_send_event (pipeline, gst_event_new_eos ()); + if (caught_error == ELR_INTERRUPT) { + PRINT (_("EOS on shutdown enabled -- Forcing EOS on the pipeline\n")); + gst_element_send_event (pipeline, gst_event_new_eos ()); + ignore_errors = FALSE; + } else { + PRINT (_("EOS on shutdown enabled -- waiting for EOS after Error\n")); + ignore_errors = TRUE; + } PRINT (_("Waiting for EOS...\n")); - caught_error = event_loop (pipeline, TRUE, GST_STATE_PLAYING); - if (caught_error == ELR_NO_ERROR) { - /* we got EOS */ - PRINT (_("EOS received - stopping pipeline...\n")); - } else if (caught_error == ELR_ERROR) { - PRINT (_("An error happened while waiting for EOS\n")); + while (TRUE) { + caught_error = event_loop (pipeline, TRUE, FALSE, GST_STATE_PLAYING); + + if (caught_error == ELR_NO_ERROR) { + /* we got EOS */ + PRINT (_("EOS received - stopping pipeline...\n")); + break; + } else if (caught_error == ELR_INTERRUPT) { + PRINT (_ + ("Interrupt while waiting for EOS - stopping pipeline...\n")); + res = caught_error; + break; + } else if (caught_error == ELR_ERROR) { + if (!ignore_errors) { + PRINT (_("An error happened while waiting for EOS\n")); + res = caught_error; + break; + } + } } } tfnow = gst_util_get_timestamp (); diff = GST_CLOCK_DIFF (tfthen, tfnow); - PRINT (_("Execution ended after %" G_GUINT64_FORMAT " ns.\n"), diff); + PRINT (_("Execution ended after %" GST_TIME_FORMAT "\n"), + GST_TIME_ARGS (diff)); } PRINT (_("Setting pipeline to PAUSED ...\n")); @@ -1055,27 +1138,30 @@ main (int argc, char *argv[]) /* iterate mainloop to process pending stuff */ while (g_main_context_iteration (NULL, FALSE)); + /* No need to see all those pad caps going to NULL etc., it's just noise */ + if (deep_notify_id != 0) + g_signal_handler_disconnect (pipeline, deep_notify_id); + PRINT (_("Setting pipeline to READY ...\n")); gst_element_set_state (pipeline, GST_STATE_READY); gst_element_get_state (pipeline, &state, &pending, GST_CLOCK_TIME_NONE); +#if 0 if (check_index) { print_index_stats (index_stats); g_ptr_array_free (index_stats, TRUE); } +#endif end: PRINT (_("Setting pipeline to NULL ...\n")); gst_element_set_state (pipeline, GST_STATE_NULL); - gst_element_get_state (pipeline, &state, &pending, GST_CLOCK_TIME_NONE); } PRINT (_("Freeing pipeline ...\n")); gst_object_unref (pipeline); gst_deinit (); - if (trace) - gst_alloc_trace_print_live (); return res; }