diff -r 567bb019e3e3 -r 7e817e7e631c gstreamer_core/gst/gstdebugutils.c --- a/gstreamer_core/gst/gstdebugutils.c Tue Aug 31 15:30:33 2010 +0300 +++ b/gstreamer_core/gst/gstdebugutils.c Wed Sep 01 12:16:41 2010 +0100 @@ -20,18 +20,10 @@ */ /* TODO: * edge [ constraint=false ]; - * this creates strange graphs ("minlen=0" is better) - * try puting src/sink ghostpads for each bin into invisible clusters - * - * for more compact nodes, try - * - changing node-shape from box into record - * - use labels like : element [ label="{element | src | sink}"] - * - point to record-connectors : element1:src -> element2:sink - * - we use head/tail labels for pad-caps right now - * - this does not work well, as dot seems to not llok at their sizen when - * doing the layout - * - we could add the caps to the pad itself, then we should use one line per - * caps (simple caps = one line) + * edge [ minlen=0 ]; + * does not create spacial dependency + * node [ margin="0.02,0.01" ]; + * space surrounding the label */ #include "gst_private.h" @@ -50,19 +42,11 @@ #include "gstghostpad.h" #include "gstpad.h" #include "gstutils.h" -#include "gstvalue.h" /*** PIPELINE GRAPHS **********************************************************/ const gchar *priv_gst_dump_dot_dir; /* NULL *//* set from gst.c */ -const gchar spaces[] = { - " " /* 32 */ - " " /* 64 */ - " " /* 96 */ - " " /* 128 */ -}; - extern GstClockTime _priv_gst_info_start_time; static gchar * @@ -83,7 +67,7 @@ if (pending == GST_STATE_VOID_PENDING) { state_name = g_strdup_printf ("\\n[%c]", state_icons[state]); } else { - state_name = g_strdup_printf ("\\n[%c] -> [%c]", state_icons[state], + state_name = g_strdup_printf ("\\n[%c]->[%c]", state_icons[state], state_icons[pending]); } return state_name; @@ -135,351 +119,6 @@ return param_name; } -static void -debug_dump_pad (GstPad * pad, gchar * color_name, gchar * element_name, - FILE * out, const gint indent) -{ - GstPadTemplate *pad_templ; - GstPadPresence presence; - gchar *pad_name, *style_name; - gchar pad_flags[6]; - const gchar *activation_mode = "-><"; - const gchar *spc = &spaces[MAX (sizeof (spaces) - (1 + indent * 2), 0)]; - - pad_name = debug_dump_make_object_name (GST_OBJECT (pad)); - - /* pad availability */ - style_name = "filled,solid"; - if ((pad_templ = gst_pad_get_pad_template (pad))) { - presence = GST_PAD_TEMPLATE_PRESENCE (pad_templ); - if (presence == GST_PAD_SOMETIMES) { - style_name = "filled,dotted"; - } else if (presence == GST_PAD_REQUEST) { - style_name = "filled,dashed"; - } - } - /* check if pad flags */ - pad_flags[0] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_BLOCKED) ? 'B' : 'b'; - pad_flags[1] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLUSHING) ? 'F' : 'f'; - pad_flags[2] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_IN_GETCAPS) ? 'G' : 'g'; - pad_flags[3] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_IN_SETCAPS) ? 's' : 's'; - pad_flags[4] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_BLOCKING) ? 'B' : 'b'; - pad_flags[5] = '\0'; - - fprintf (out, "%s %s_%s [color=black, fillcolor=\"%s\", label=\"%s\\n[%c][%s]\", height=\"0.2\", style=\"%s\"];\n", spc, element_name, pad_name, color_name, GST_OBJECT_NAME (pad), activation_mode[pad->mode], /* NONE/PUSH/PULL */ - pad_flags, style_name); - - g_free (pad_name); -} - -static void -debug_dump_element_pad (GstPad * pad, GstElement * element, - GstDebugGraphDetails details, FILE * out, const gint indent) -{ - GstElement *target_element; - GstPad *target_pad, *tmp_pad; - GstPadDirection dir; - gchar *pad_name, *element_name; - gchar *target_element_name; - gchar *color_name; - - dir = gst_pad_get_direction (pad); - pad_name = debug_dump_make_object_name (GST_OBJECT (pad)); - element_name = debug_dump_make_object_name (GST_OBJECT (element)); - if (GST_IS_GHOST_PAD (pad)) { - color_name = - (dir == GST_PAD_SRC) ? "#ffdddd" : ((dir == - GST_PAD_SINK) ? "#ddddff" : "#ffffff"); - /* output target-pad so that it belongs to this element */ - if ((tmp_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (pad)))) { - if ((target_pad = gst_pad_get_peer (tmp_pad))) { - if ((target_element = gst_pad_get_parent_element (target_pad))) { - target_element_name = - debug_dump_make_object_name (GST_OBJECT (target_element)); - } else { - target_element_name = ""; - } - debug_dump_pad (target_pad, color_name, target_element_name, out, - indent); - if (target_element) { - g_free (target_element_name); - gst_object_unref (target_element); - } - gst_object_unref (target_pad); - } - gst_object_unref (tmp_pad); - } - } else { - color_name = - (dir == GST_PAD_SRC) ? "#ffaaaa" : ((dir == - GST_PAD_SINK) ? "#aaaaff" : "#cccccc"); - } - /* pads */ - debug_dump_pad (pad, color_name, element_name, out, indent); - g_free (element_name); -} - -static gboolean -string_append_field (GQuark field, const GValue * value, gpointer ptr) -{ - GString *str = (GString *) ptr; - gchar *value_str = gst_value_serialize (value); - - /* some enums can become really long */ - if (strlen (value_str) > 25) { - gint pos = 24; - - /* truncate */ - value_str[25] = '\0'; - - /* mirror any brackets */ - if (value_str[0] == '<') - value_str[pos--] = '>'; - if (value_str[0] == '[') - value_str[pos--] = ']'; - if (value_str[0] == '(') - value_str[pos--] = ')'; - if (value_str[0] == '{') - value_str[pos--] = '}'; - if (pos != 24) - value_str[pos--] = ' '; - /* elippsize */ - value_str[pos--] = '.'; - value_str[pos--] = '.'; - value_str[pos--] = '.'; - } - g_string_append_printf (str, " %18s: %s\\l", g_quark_to_string (field), - value_str); - - g_free (value_str); - return TRUE; -} - -static gchar * -debug_dump_describe_caps (GstCaps * caps, GstDebugGraphDetails details, - gboolean * need_free) -{ - gchar *media = NULL; - - if (details & GST_DEBUG_GRAPH_SHOW_CAPS_DETAILS) { - - if (gst_caps_is_any (caps) || gst_caps_is_empty (caps)) { - media = gst_caps_to_string (caps); - *need_free = TRUE; - - } else { - GString *str = NULL; - guint i; - guint slen = 0; - - for (i = 0; i < gst_caps_get_size (caps); i++) { - slen += 25 + - STRUCTURE_ESTIMATED_STRING_LEN (gst_caps_get_structure (caps, i)); - } - - str = g_string_sized_new (slen); - for (i = 0; i < gst_caps_get_size (caps); i++) { - GstStructure *structure = gst_caps_get_structure (caps, i); - - g_string_append (str, gst_structure_get_name (structure)); - g_string_append (str, "\\l"); - - gst_structure_foreach (structure, string_append_field, (gpointer) str); - } - - media = g_string_free (str, FALSE); - *need_free = TRUE; - } - - } else { - if (GST_CAPS_IS_SIMPLE (caps)) - media = - (gchar *) gst_structure_get_name (gst_caps_get_structure (caps, 0)); - else - media = "*"; - *need_free = FALSE; - } - return media; -} - -static void -debug_dump_element_pad_link (GstPad * pad, GstElement * element, - GstDebugGraphDetails details, FILE * out, const gint indent) -{ - GstElement *peer_element, *target_element; - GstPad *peer_pad, *target_pad, *tmp_pad; - GstCaps *caps, *peer_caps; - gboolean free_caps, free_peer_caps; - gboolean free_media, free_media_src, free_media_sink; - gchar *media = NULL; - gchar *media_src = NULL, *media_sink = NULL; - gchar *pad_name, *element_name; - gchar *peer_pad_name, *peer_element_name; - gchar *target_pad_name, *target_element_name; - const gchar *spc = &spaces[MAX (sizeof (spaces) - (1 + indent * 2), 0)]; - - if ((peer_pad = gst_pad_get_peer (pad))) { - free_media = free_media_src = free_media_sink = FALSE; - if ((details & GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE) || - (details & GST_DEBUG_GRAPH_SHOW_CAPS_DETAILS) - ) { - if ((caps = gst_pad_get_negotiated_caps (pad))) { - free_caps = TRUE; - } else { - free_caps = FALSE; - if (!(caps = (GstCaps *) - gst_pad_get_pad_template_caps (pad))) { - /* this should not happen */ - media = "?"; - } - } - if ((peer_caps = gst_pad_get_negotiated_caps (peer_pad))) { - free_peer_caps = TRUE; - } else { - free_peer_caps = FALSE; - peer_caps = (GstCaps *) gst_pad_get_pad_template_caps (peer_pad); - } - if (caps) { - media = debug_dump_describe_caps (caps, details, &free_media); - /* check if peer caps are different */ - if (peer_caps && !gst_caps_is_equal (caps, peer_caps)) { - gchar *tmp; - gboolean free_tmp; - - tmp = debug_dump_describe_caps (peer_caps, details, &free_tmp); - if (gst_pad_get_direction (pad) == GST_PAD_SRC) { - media_src = media; - free_media_src = free_media; - media_sink = tmp; - free_media_sink = free_tmp; - } else { - media_src = tmp; - free_media_src = free_tmp; - media_sink = media; - free_media_sink = free_media; - } - media = NULL; - free_media = FALSE; - } - if (free_caps) { - gst_caps_unref (caps); - } - } - if (free_peer_caps && peer_caps) { - gst_caps_unref (peer_caps); - } - } - - pad_name = debug_dump_make_object_name (GST_OBJECT (pad)); - if (element) { - element_name = debug_dump_make_object_name (GST_OBJECT (element)); - } else { - element_name = ""; - } - peer_pad_name = debug_dump_make_object_name (GST_OBJECT (peer_pad)); - if ((peer_element = gst_pad_get_parent_element (peer_pad))) { - peer_element_name = - debug_dump_make_object_name (GST_OBJECT (peer_element)); - } else { - peer_element_name = ""; - } - - if (GST_IS_GHOST_PAD (pad)) { - if ((tmp_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (pad)))) { - if ((target_pad = gst_pad_get_peer (tmp_pad))) { - target_pad_name = - debug_dump_make_object_name (GST_OBJECT (target_pad)); - if ((target_element = gst_pad_get_parent_element (target_pad))) { - target_element_name = - debug_dump_make_object_name (GST_OBJECT (target_element)); - } else { - target_element_name = ""; - } - /* src ghostpad relationship */ - fprintf (out, "%s%s_%s -> %s_%s [style=dashed, minlen=0]\n", spc, - target_element_name, target_pad_name, element_name, pad_name); - - g_free (target_pad_name); - if (target_element) { - g_free (target_element_name); - gst_object_unref (target_element); - } - gst_object_unref (target_pad); - } - gst_object_unref (tmp_pad); - } - } - if (GST_IS_GHOST_PAD (peer_pad)) { - if ((tmp_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (peer_pad)))) { - if ((target_pad = gst_pad_get_peer (tmp_pad))) { - target_pad_name = - debug_dump_make_object_name (GST_OBJECT (target_pad)); - if ((target_element = gst_pad_get_parent_element (target_pad))) { - target_element_name = - debug_dump_make_object_name (GST_OBJECT (target_element)); - } else { - target_element_name = ""; - } - /* sink ghostpad relationship */ - fprintf (out, "%s%s_%s -> %s_%s [style=dashed, minlen=0]\n", spc, - peer_element_name, peer_pad_name, - target_element_name, target_pad_name); - /* FIXME: we are missing links from the proxy pad - * theoretically we need to: - * pad=gst_object_ref(target_pad); - * goto line 280: if ((peer_pad = gst_pad_get_peer (pad))) - * as this would be ugly we need to refactor ... - */ - debug_dump_element_pad_link (target_pad, target_element, details, out, - indent); - g_free (target_pad_name); - if (target_element) { - g_free (target_element_name); - gst_object_unref (target_element); - } - gst_object_unref (target_pad); - } - gst_object_unref (tmp_pad); - } - } - - /* pad link */ - if (media) { - fprintf (out, "%s%s_%s -> %s_%s [label=\"%s\"]\n", spc, - element_name, pad_name, peer_element_name, peer_pad_name, media); - if (free_media) { - g_free (media); - } - } else if (media_src && media_sink) { - /* dot has some issues with placement of head and taillabels, - * we need an empty label to make space */ - fprintf (out, "%s%s_%s -> %s_%s [labeldistance=\"10\", labelangle=\"0\", " - "label=\" \", " - "headlabel=\"%s\", taillabel=\"%s\"]\n", - spc, element_name, pad_name, peer_element_name, peer_pad_name, - media_src, media_sink); - if (free_media_src) - g_free (media_src); - if (free_media_sink) - g_free (media_sink); - } else { - fprintf (out, "%s%s_%s -> %s_%s\n", spc, - element_name, pad_name, peer_element_name, peer_pad_name); - } - - g_free (pad_name); - if (element) { - g_free (element_name); - } - g_free (peer_pad_name); - if (peer_element) { - g_free (peer_element_name); - gst_object_unref (peer_element); - } - gst_object_unref (peer_pad); - } -} - /* * debug_dump_element: * @bin: the bin that should be analyzed @@ -494,14 +133,25 @@ { GstIterator *element_iter, *pad_iter; gboolean elements_done, pads_done; - GstElement *element; - GstPad *pad; + GstElement *element, *peer_element, *target_element; + GstPad *pad, *peer_pad, *target_pad; GstPadDirection dir; + GstCaps *caps; + GstStructure *structure; + gboolean free_caps, free_media; guint src_pads, sink_pads; - gchar *element_name; + gchar *media = NULL; + gchar *pad_name, *element_name; + gchar *peer_pad_name, *peer_element_name; + gchar *target_pad_name, *target_element_name; + gchar *color_name; gchar *state_name = NULL; gchar *param_name = NULL; - const gchar *spc = &spaces[MAX (sizeof (spaces) - (1 + indent * 2), 0)]; + gchar *spc = NULL; + + spc = g_malloc (1 + indent * 2); + memset (spc, 32, indent * 2); + spc[indent * 2] = '\0'; element_iter = gst_bin_iterate_elements (bin); elements_done = FALSE; @@ -522,7 +172,7 @@ fprintf (out, "%s fontsize=\"8\";\n", spc); fprintf (out, "%s style=filled;\n", spc); fprintf (out, "%s color=black;\n\n", spc); - fprintf (out, "%s label=\"%s\\n%s%s%s\";\n", spc, + fprintf (out, "%s label=\"<%s>\\n%s%s%s\";\n", spc, G_OBJECT_TYPE_NAME (element), GST_OBJECT_NAME (element), (state_name ? state_name : ""), (param_name ? param_name : "") ); @@ -542,12 +192,31 @@ while (!pads_done) { switch (gst_iterator_next (pad_iter, (gpointer) & pad)) { case GST_ITERATOR_OK: - debug_dump_element_pad (pad, element, details, out, indent); dir = gst_pad_get_direction (pad); + pad_name = debug_dump_make_object_name (GST_OBJECT (pad)); + element_name = + debug_dump_make_object_name (GST_OBJECT (element)); + if (GST_IS_GHOST_PAD (pad)) { + color_name = + (dir == GST_PAD_SRC) ? "#ffdddd" : ((dir == + GST_PAD_SINK) ? "#ddddff" : "#ffffff"); + } else { + color_name = + (dir == GST_PAD_SRC) ? "#ffaaaa" : ((dir == + GST_PAD_SINK) ? "#aaaaff" : "#cccccc"); + } + /* pads */ + fprintf (out, + "%s %s_%s [color=black, fillcolor=\"%s\", label=\"%s\"];\n", + spc, element_name, pad_name, color_name, + GST_OBJECT_NAME (pad)); + if (dir == GST_PAD_SRC) src_pads++; else if (dir == GST_PAD_SINK) sink_pads++; + g_free (pad_name); + g_free (element_name); gst_object_unref (pad); break; case GST_ITERATOR_RESYNC: @@ -583,8 +252,135 @@ case GST_ITERATOR_OK: if (gst_pad_is_linked (pad) && gst_pad_get_direction (pad) == GST_PAD_SRC) { - debug_dump_element_pad_link (pad, element, details, out, - indent); + if ((peer_pad = gst_pad_get_peer (pad))) { + free_media = FALSE; + if ((details & GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE) || + (details & GST_DEBUG_GRAPH_SHOW_CAPS_DETAILS) + ) { + if ((caps = gst_pad_get_negotiated_caps (pad))) { + free_caps = TRUE; + } else { + free_caps = FALSE; + if (!(caps = (GstCaps *) + gst_pad_get_pad_template_caps (pad))) { + /* this should not happen */ + media = "?"; + } + } + if (caps) { + if (details & GST_DEBUG_GRAPH_SHOW_CAPS_DETAILS) { + gchar *tmp = + g_strdelimit (gst_caps_to_string (caps), ",", + '\n'); + + media = g_strescape (tmp, NULL); + free_media = TRUE; + g_free (tmp); + } else { + if (GST_CAPS_IS_SIMPLE (caps)) { + structure = gst_caps_get_structure (caps, 0); + media = + (gchar *) gst_structure_get_name (structure); + } else + media = "*"; + } + if (free_caps) { + gst_caps_unref (caps); + } + } + } + + pad_name = debug_dump_make_object_name (GST_OBJECT (pad)); + element_name = + debug_dump_make_object_name (GST_OBJECT (element)); + peer_pad_name = + debug_dump_make_object_name (GST_OBJECT (peer_pad)); + if ((peer_element = gst_pad_get_parent_element (peer_pad))) { + peer_element_name = + debug_dump_make_object_name (GST_OBJECT + (peer_element)); + } else { + peer_element_name = ""; + } + /* pad link */ + if (media) { + fprintf (out, "%s%s_%s -> %s_%s [label=\"%s\"]\n", spc, + element_name, pad_name, peer_element_name, + peer_pad_name, media); + if (free_media) { + g_free (media); + } + } else { + fprintf (out, "%s%s_%s -> %s_%s\n", spc, + element_name, pad_name, peer_element_name, + peer_pad_name); + } + + if (GST_IS_GHOST_PAD (pad)) { + if ((target_pad = + gst_ghost_pad_get_target (GST_GHOST_PAD (pad)))) { + target_pad_name = + debug_dump_make_object_name (GST_OBJECT + (target_pad)); + if ((target_element = + gst_pad_get_parent_element (target_pad))) { + target_element_name = + debug_dump_make_object_name (GST_OBJECT + (target_element)); + } else { + target_element_name = ""; + } + /* src ghostpad relationship */ + fprintf (out, "%s%s_%s -> %s_%s [style=dashed]\n", spc, + target_element_name, target_pad_name, element_name, + pad_name); + + g_free (target_pad_name); + if (target_element) { + g_free (target_element_name); + gst_object_unref (target_element); + } + gst_object_unref (target_pad); + } + } + if (GST_IS_GHOST_PAD (peer_pad)) { + if ((target_pad = + gst_ghost_pad_get_target (GST_GHOST_PAD + (peer_pad)))) { + target_pad_name = + debug_dump_make_object_name (GST_OBJECT + (target_pad)); + if ((target_element = + gst_pad_get_parent_element (target_pad))) { + target_element_name = + debug_dump_make_object_name (GST_OBJECT + (target_element)); + } else { + target_element_name = ""; + } + /* sink ghostpad relationship */ + fprintf (out, "%s%s_%s -> %s_%s [style=dashed]\n", spc, + peer_element_name, peer_pad_name, + target_element_name, target_pad_name); + + g_free (target_pad_name); + if (target_element) { + g_free (target_element_name); + gst_object_unref (target_element); + } + gst_object_unref (target_pad); + } + } + + g_free (pad_name); + g_free (element_name); + g_free (peer_pad_name); + if (peer_element) { + g_free (peer_element_name); + gst_object_unref (peer_element); + } + gst_object_unref (peer_pad); + } } gst_object_unref (pad); break; @@ -611,6 +407,7 @@ } } gst_iterator_free (element_iter); + g_free (spc); } /* @@ -665,14 +462,14 @@ fprintf (out, "digraph pipeline {\n" " rankdir=LR;\n" - " fontname=\"sans\";\n" - " fontsize=\"10\";\n" + " fontname=\"Bitstream Vera Sans\";\n" + " fontsize=\"8\";\n" " labelloc=t;\n" " nodesep=.1;\n" " ranksep=.2;\n" " label=\"<%s>\\n%s%s%s\";\n" - " node [style=filled, shape=box, fontsize=\"9\", fontname=\"sans\", margin=\"0.0,0.0\"];\n" - " edge [labelfontsize=\"6\", fontsize=\"9\", fontname=\"monospace\"];\n" + " node [style=filled, shape=box, fontsize=\"7\", fontname=\"Bitstream Vera Sans\"];\n" + " edge [labelfontsize=\"7\", fontsize=\"7\", labelfontname=\"Bitstream Vera Sans\", fontname=\"Bitstream Vera Sans\"];\n" "\n", G_OBJECT_TYPE_NAME (bin), GST_OBJECT_NAME (bin), (state_name ? state_name : ""), (param_name ? param_name : "") ); @@ -724,32 +521,12 @@ /* add timestamp */ elapsed = GST_CLOCK_DIFF (_priv_gst_info_start_time, gst_util_get_timestamp ()); - - /* we don't use GST_TIME_FORMAT as such filenames would fail on some - * filesystems like fat */ ts_file_name = - g_strdup_printf ("%u.%02u.%02u.%09u-%s", GST_TIME_ARGS (elapsed), + g_strdup_printf ("%" GST_TIME_FORMAT "-%s", GST_TIME_ARGS (elapsed), file_name); _gst_debug_bin_to_dot_file (bin, details, ts_file_name); g_free (ts_file_name); } -#else /* !GST_DISABLE_GST_DEBUG */ -#ifndef GST_REMOVE_DISABLED -void -_gst_debug_bin_to_dot_file (GstBin * bin, GstDebugGraphDetails details, - const gchar * file_name) -{ -} -#ifdef __SYMBIAN32__ -EXPORT_C -#endif - -void -_gst_debug_bin_to_dot_file_with_ts (GstBin * bin, GstDebugGraphDetails details, - const gchar * file_name) -{ -} -#endif /* GST_REMOVE_DISABLED */ #endif /* GST_DISABLE_GST_DEBUG */