gstreamer_core/gst/gstdebugutils.c
branchRCL_3
changeset 29 567bb019e3e3
parent 0 0e761a78d257
child 30 7e817e7e631c
equal deleted inserted replaced
6:9b2c3c7a1a9c 29:567bb019e3e3
    18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    19  * Boston, MA 02111-1307, USA.
    19  * Boston, MA 02111-1307, USA.
    20  */
    20  */
    21 /* TODO:
    21 /* TODO:
    22  * edge [ constraint=false ];
    22  * edge [ constraint=false ];
    23  * edge [ minlen=0 ];
    23  *   this creates strange graphs ("minlen=0" is better)
    24  *   does not create spacial dependency
    24  * try puting src/sink ghostpads for each bin into invisible clusters
    25  * node [ margin="0.02,0.01" ];
    25  *
    26  *   space surrounding the label
    26  * for more compact nodes, try
       
    27  * - changing node-shape from box into record
       
    28  * - use labels like : element [ label="{element | <src> src | <sink> sink}"]
       
    29  * - point to record-connectors : element1:src -> element2:sink
       
    30  * - we use head/tail labels for pad-caps right now
       
    31  *   - this does not work well, as dot seems to not llok at their sizen when
       
    32  *     doing the layout
       
    33  *   - we could add the caps to the pad itself, then we should use one line per
       
    34  *     caps (simple caps = one line)
    27  */
    35  */
    28 
    36 
    29 #include "gst_private.h"
    37 #include "gst_private.h"
    30 #include "gstdebugutils.h"
    38 #include "gstdebugutils.h"
    31 
    39 
    40 #include "gstbin.h"
    48 #include "gstbin.h"
    41 #include "gstobject.h"
    49 #include "gstobject.h"
    42 #include "gstghostpad.h"
    50 #include "gstghostpad.h"
    43 #include "gstpad.h"
    51 #include "gstpad.h"
    44 #include "gstutils.h"
    52 #include "gstutils.h"
       
    53 #include "gstvalue.h"
    45 
    54 
    46 /*** PIPELINE GRAPHS **********************************************************/
    55 /*** PIPELINE GRAPHS **********************************************************/
    47 
    56 
    48 const gchar *priv_gst_dump_dot_dir;     /* NULL *//* set from gst.c */
    57 const gchar *priv_gst_dump_dot_dir;     /* NULL *//* set from gst.c */
       
    58 
       
    59 const gchar spaces[] = {
       
    60   "                                "    /* 32 */
       
    61       "                                "        /* 64 */
       
    62       "                                "        /* 96 */
       
    63       "                                "        /* 128 */
       
    64 };
    49 
    65 
    50 extern GstClockTime _priv_gst_info_start_time;
    66 extern GstClockTime _priv_gst_info_start_time;
    51 
    67 
    52 static gchar *
    68 static gchar *
    53 debug_dump_make_object_name (GstObject * element)
    69 debug_dump_make_object_name (GstObject * element)
    65 
    81 
    66   gst_element_get_state (element, &state, &pending, 0);
    82   gst_element_get_state (element, &state, &pending, 0);
    67   if (pending == GST_STATE_VOID_PENDING) {
    83   if (pending == GST_STATE_VOID_PENDING) {
    68     state_name = g_strdup_printf ("\\n[%c]", state_icons[state]);
    84     state_name = g_strdup_printf ("\\n[%c]", state_icons[state]);
    69   } else {
    85   } else {
    70     state_name = g_strdup_printf ("\\n[%c]->[%c]", state_icons[state],
    86     state_name = g_strdup_printf ("\\n[%c] -> [%c]", state_icons[state],
    71         state_icons[pending]);
    87         state_icons[pending]);
    72   }
    88   }
    73   return state_name;
    89   return state_name;
    74 }
    90 }
    75 
    91 
   117     g_free (properties);
   133     g_free (properties);
   118   }
   134   }
   119   return param_name;
   135   return param_name;
   120 }
   136 }
   121 
   137 
       
   138 static void
       
   139 debug_dump_pad (GstPad * pad, gchar * color_name, gchar * element_name,
       
   140     FILE * out, const gint indent)
       
   141 {
       
   142   GstPadTemplate *pad_templ;
       
   143   GstPadPresence presence;
       
   144   gchar *pad_name, *style_name;
       
   145   gchar pad_flags[6];
       
   146   const gchar *activation_mode = "-><";
       
   147   const gchar *spc = &spaces[MAX (sizeof (spaces) - (1 + indent * 2), 0)];
       
   148 
       
   149   pad_name = debug_dump_make_object_name (GST_OBJECT (pad));
       
   150 
       
   151   /* pad availability */
       
   152   style_name = "filled,solid";
       
   153   if ((pad_templ = gst_pad_get_pad_template (pad))) {
       
   154     presence = GST_PAD_TEMPLATE_PRESENCE (pad_templ);
       
   155     if (presence == GST_PAD_SOMETIMES) {
       
   156       style_name = "filled,dotted";
       
   157     } else if (presence == GST_PAD_REQUEST) {
       
   158       style_name = "filled,dashed";
       
   159     }
       
   160   }
       
   161   /* check if pad flags */
       
   162   pad_flags[0] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_BLOCKED) ? 'B' : 'b';
       
   163   pad_flags[1] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLUSHING) ? 'F' : 'f';
       
   164   pad_flags[2] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_IN_GETCAPS) ? 'G' : 'g';
       
   165   pad_flags[3] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_IN_SETCAPS) ? 's' : 's';
       
   166   pad_flags[4] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_BLOCKING) ? 'B' : 'b';
       
   167   pad_flags[5] = '\0';
       
   168 
       
   169   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 */
       
   170       pad_flags, style_name);
       
   171 
       
   172   g_free (pad_name);
       
   173 }
       
   174 
       
   175 static void
       
   176 debug_dump_element_pad (GstPad * pad, GstElement * element,
       
   177     GstDebugGraphDetails details, FILE * out, const gint indent)
       
   178 {
       
   179   GstElement *target_element;
       
   180   GstPad *target_pad, *tmp_pad;
       
   181   GstPadDirection dir;
       
   182   gchar *pad_name, *element_name;
       
   183   gchar *target_element_name;
       
   184   gchar *color_name;
       
   185 
       
   186   dir = gst_pad_get_direction (pad);
       
   187   pad_name = debug_dump_make_object_name (GST_OBJECT (pad));
       
   188   element_name = debug_dump_make_object_name (GST_OBJECT (element));
       
   189   if (GST_IS_GHOST_PAD (pad)) {
       
   190     color_name =
       
   191         (dir == GST_PAD_SRC) ? "#ffdddd" : ((dir ==
       
   192             GST_PAD_SINK) ? "#ddddff" : "#ffffff");
       
   193     /* output target-pad so that it belongs to this element */
       
   194     if ((tmp_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (pad)))) {
       
   195       if ((target_pad = gst_pad_get_peer (tmp_pad))) {
       
   196         if ((target_element = gst_pad_get_parent_element (target_pad))) {
       
   197           target_element_name =
       
   198               debug_dump_make_object_name (GST_OBJECT (target_element));
       
   199         } else {
       
   200           target_element_name = "";
       
   201         }
       
   202         debug_dump_pad (target_pad, color_name, target_element_name, out,
       
   203             indent);
       
   204         if (target_element) {
       
   205           g_free (target_element_name);
       
   206           gst_object_unref (target_element);
       
   207         }
       
   208         gst_object_unref (target_pad);
       
   209       }
       
   210       gst_object_unref (tmp_pad);
       
   211     }
       
   212   } else {
       
   213     color_name =
       
   214         (dir == GST_PAD_SRC) ? "#ffaaaa" : ((dir ==
       
   215             GST_PAD_SINK) ? "#aaaaff" : "#cccccc");
       
   216   }
       
   217   /* pads */
       
   218   debug_dump_pad (pad, color_name, element_name, out, indent);
       
   219   g_free (element_name);
       
   220 }
       
   221 
       
   222 static gboolean
       
   223 string_append_field (GQuark field, const GValue * value, gpointer ptr)
       
   224 {
       
   225   GString *str = (GString *) ptr;
       
   226   gchar *value_str = gst_value_serialize (value);
       
   227 
       
   228   /* some enums can become really long */
       
   229   if (strlen (value_str) > 25) {
       
   230     gint pos = 24;
       
   231 
       
   232     /* truncate */
       
   233     value_str[25] = '\0';
       
   234 
       
   235     /* mirror any brackets */
       
   236     if (value_str[0] == '<')
       
   237       value_str[pos--] = '>';
       
   238     if (value_str[0] == '[')
       
   239       value_str[pos--] = ']';
       
   240     if (value_str[0] == '(')
       
   241       value_str[pos--] = ')';
       
   242     if (value_str[0] == '{')
       
   243       value_str[pos--] = '}';
       
   244     if (pos != 24)
       
   245       value_str[pos--] = ' ';
       
   246     /* elippsize */
       
   247     value_str[pos--] = '.';
       
   248     value_str[pos--] = '.';
       
   249     value_str[pos--] = '.';
       
   250   }
       
   251   g_string_append_printf (str, "  %18s: %s\\l", g_quark_to_string (field),
       
   252       value_str);
       
   253 
       
   254   g_free (value_str);
       
   255   return TRUE;
       
   256 }
       
   257 
       
   258 static gchar *
       
   259 debug_dump_describe_caps (GstCaps * caps, GstDebugGraphDetails details,
       
   260     gboolean * need_free)
       
   261 {
       
   262   gchar *media = NULL;
       
   263 
       
   264   if (details & GST_DEBUG_GRAPH_SHOW_CAPS_DETAILS) {
       
   265 
       
   266     if (gst_caps_is_any (caps) || gst_caps_is_empty (caps)) {
       
   267       media = gst_caps_to_string (caps);
       
   268       *need_free = TRUE;
       
   269 
       
   270     } else {
       
   271       GString *str = NULL;
       
   272       guint i;
       
   273       guint slen = 0;
       
   274 
       
   275       for (i = 0; i < gst_caps_get_size (caps); i++) {
       
   276         slen += 25 +
       
   277             STRUCTURE_ESTIMATED_STRING_LEN (gst_caps_get_structure (caps, i));
       
   278       }
       
   279 
       
   280       str = g_string_sized_new (slen);
       
   281       for (i = 0; i < gst_caps_get_size (caps); i++) {
       
   282         GstStructure *structure = gst_caps_get_structure (caps, i);
       
   283 
       
   284         g_string_append (str, gst_structure_get_name (structure));
       
   285         g_string_append (str, "\\l");
       
   286 
       
   287         gst_structure_foreach (structure, string_append_field, (gpointer) str);
       
   288       }
       
   289 
       
   290       media = g_string_free (str, FALSE);
       
   291       *need_free = TRUE;
       
   292     }
       
   293 
       
   294   } else {
       
   295     if (GST_CAPS_IS_SIMPLE (caps))
       
   296       media =
       
   297           (gchar *) gst_structure_get_name (gst_caps_get_structure (caps, 0));
       
   298     else
       
   299       media = "*";
       
   300     *need_free = FALSE;
       
   301   }
       
   302   return media;
       
   303 }
       
   304 
       
   305 static void
       
   306 debug_dump_element_pad_link (GstPad * pad, GstElement * element,
       
   307     GstDebugGraphDetails details, FILE * out, const gint indent)
       
   308 {
       
   309   GstElement *peer_element, *target_element;
       
   310   GstPad *peer_pad, *target_pad, *tmp_pad;
       
   311   GstCaps *caps, *peer_caps;
       
   312   gboolean free_caps, free_peer_caps;
       
   313   gboolean free_media, free_media_src, free_media_sink;
       
   314   gchar *media = NULL;
       
   315   gchar *media_src = NULL, *media_sink = NULL;
       
   316   gchar *pad_name, *element_name;
       
   317   gchar *peer_pad_name, *peer_element_name;
       
   318   gchar *target_pad_name, *target_element_name;
       
   319   const gchar *spc = &spaces[MAX (sizeof (spaces) - (1 + indent * 2), 0)];
       
   320 
       
   321   if ((peer_pad = gst_pad_get_peer (pad))) {
       
   322     free_media = free_media_src = free_media_sink = FALSE;
       
   323     if ((details & GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE) ||
       
   324         (details & GST_DEBUG_GRAPH_SHOW_CAPS_DETAILS)
       
   325         ) {
       
   326       if ((caps = gst_pad_get_negotiated_caps (pad))) {
       
   327         free_caps = TRUE;
       
   328       } else {
       
   329         free_caps = FALSE;
       
   330         if (!(caps = (GstCaps *)
       
   331                 gst_pad_get_pad_template_caps (pad))) {
       
   332           /* this should not happen */
       
   333           media = "?";
       
   334         }
       
   335       }
       
   336       if ((peer_caps = gst_pad_get_negotiated_caps (peer_pad))) {
       
   337         free_peer_caps = TRUE;
       
   338       } else {
       
   339         free_peer_caps = FALSE;
       
   340         peer_caps = (GstCaps *) gst_pad_get_pad_template_caps (peer_pad);
       
   341       }
       
   342       if (caps) {
       
   343         media = debug_dump_describe_caps (caps, details, &free_media);
       
   344         /* check if peer caps are different */
       
   345         if (peer_caps && !gst_caps_is_equal (caps, peer_caps)) {
       
   346           gchar *tmp;
       
   347           gboolean free_tmp;
       
   348 
       
   349           tmp = debug_dump_describe_caps (peer_caps, details, &free_tmp);
       
   350           if (gst_pad_get_direction (pad) == GST_PAD_SRC) {
       
   351             media_src = media;
       
   352             free_media_src = free_media;
       
   353             media_sink = tmp;
       
   354             free_media_sink = free_tmp;
       
   355           } else {
       
   356             media_src = tmp;
       
   357             free_media_src = free_tmp;
       
   358             media_sink = media;
       
   359             free_media_sink = free_media;
       
   360           }
       
   361           media = NULL;
       
   362           free_media = FALSE;
       
   363         }
       
   364         if (free_caps) {
       
   365           gst_caps_unref (caps);
       
   366         }
       
   367       }
       
   368       if (free_peer_caps && peer_caps) {
       
   369         gst_caps_unref (peer_caps);
       
   370       }
       
   371     }
       
   372 
       
   373     pad_name = debug_dump_make_object_name (GST_OBJECT (pad));
       
   374     if (element) {
       
   375       element_name = debug_dump_make_object_name (GST_OBJECT (element));
       
   376     } else {
       
   377       element_name = "";
       
   378     }
       
   379     peer_pad_name = debug_dump_make_object_name (GST_OBJECT (peer_pad));
       
   380     if ((peer_element = gst_pad_get_parent_element (peer_pad))) {
       
   381       peer_element_name =
       
   382           debug_dump_make_object_name (GST_OBJECT (peer_element));
       
   383     } else {
       
   384       peer_element_name = "";
       
   385     }
       
   386 
       
   387     if (GST_IS_GHOST_PAD (pad)) {
       
   388       if ((tmp_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (pad)))) {
       
   389         if ((target_pad = gst_pad_get_peer (tmp_pad))) {
       
   390           target_pad_name =
       
   391               debug_dump_make_object_name (GST_OBJECT (target_pad));
       
   392           if ((target_element = gst_pad_get_parent_element (target_pad))) {
       
   393             target_element_name =
       
   394                 debug_dump_make_object_name (GST_OBJECT (target_element));
       
   395           } else {
       
   396             target_element_name = "";
       
   397           }
       
   398           /* src ghostpad relationship */
       
   399           fprintf (out, "%s%s_%s -> %s_%s [style=dashed, minlen=0]\n", spc,
       
   400               target_element_name, target_pad_name, element_name, pad_name);
       
   401 
       
   402           g_free (target_pad_name);
       
   403           if (target_element) {
       
   404             g_free (target_element_name);
       
   405             gst_object_unref (target_element);
       
   406           }
       
   407           gst_object_unref (target_pad);
       
   408         }
       
   409         gst_object_unref (tmp_pad);
       
   410       }
       
   411     }
       
   412     if (GST_IS_GHOST_PAD (peer_pad)) {
       
   413       if ((tmp_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (peer_pad)))) {
       
   414         if ((target_pad = gst_pad_get_peer (tmp_pad))) {
       
   415           target_pad_name =
       
   416               debug_dump_make_object_name (GST_OBJECT (target_pad));
       
   417           if ((target_element = gst_pad_get_parent_element (target_pad))) {
       
   418             target_element_name =
       
   419                 debug_dump_make_object_name (GST_OBJECT (target_element));
       
   420           } else {
       
   421             target_element_name = "";
       
   422           }
       
   423           /* sink ghostpad relationship */
       
   424           fprintf (out, "%s%s_%s -> %s_%s [style=dashed, minlen=0]\n", spc,
       
   425               peer_element_name, peer_pad_name,
       
   426               target_element_name, target_pad_name);
       
   427           /* FIXME: we are missing links from the proxy pad
       
   428            * theoretically we need to:
       
   429            * pad=gst_object_ref(target_pad);
       
   430            * goto line 280: if ((peer_pad = gst_pad_get_peer (pad)))
       
   431            * as this would be ugly we need to refactor ...
       
   432            */
       
   433           debug_dump_element_pad_link (target_pad, target_element, details, out,
       
   434               indent);
       
   435           g_free (target_pad_name);
       
   436           if (target_element) {
       
   437             g_free (target_element_name);
       
   438             gst_object_unref (target_element);
       
   439           }
       
   440           gst_object_unref (target_pad);
       
   441         }
       
   442         gst_object_unref (tmp_pad);
       
   443       }
       
   444     }
       
   445 
       
   446     /* pad link */
       
   447     if (media) {
       
   448       fprintf (out, "%s%s_%s -> %s_%s [label=\"%s\"]\n", spc,
       
   449           element_name, pad_name, peer_element_name, peer_pad_name, media);
       
   450       if (free_media) {
       
   451         g_free (media);
       
   452       }
       
   453     } else if (media_src && media_sink) {
       
   454       /* dot has some issues with placement of head and taillabels,
       
   455        * we need an empty label to make space */
       
   456       fprintf (out, "%s%s_%s -> %s_%s [labeldistance=\"10\", labelangle=\"0\", "
       
   457           "label=\"                                                  \", "
       
   458           "headlabel=\"%s\", taillabel=\"%s\"]\n",
       
   459           spc, element_name, pad_name, peer_element_name, peer_pad_name,
       
   460           media_src, media_sink);
       
   461       if (free_media_src)
       
   462         g_free (media_src);
       
   463       if (free_media_sink)
       
   464         g_free (media_sink);
       
   465     } else {
       
   466       fprintf (out, "%s%s_%s -> %s_%s\n", spc,
       
   467           element_name, pad_name, peer_element_name, peer_pad_name);
       
   468     }
       
   469 
       
   470     g_free (pad_name);
       
   471     if (element) {
       
   472       g_free (element_name);
       
   473     }
       
   474     g_free (peer_pad_name);
       
   475     if (peer_element) {
       
   476       g_free (peer_element_name);
       
   477       gst_object_unref (peer_element);
       
   478     }
       
   479     gst_object_unref (peer_pad);
       
   480   }
       
   481 }
       
   482 
   122 /*
   483 /*
   123  * debug_dump_element:
   484  * debug_dump_element:
   124  * @bin: the bin that should be analyzed
   485  * @bin: the bin that should be analyzed
   125  * @out: file to write to
   486  * @out: file to write to
   126  * @indent: level of graph indentation
   487  * @indent: level of graph indentation
   131 debug_dump_element (GstBin * bin, GstDebugGraphDetails details, FILE * out,
   492 debug_dump_element (GstBin * bin, GstDebugGraphDetails details, FILE * out,
   132     const gint indent)
   493     const gint indent)
   133 {
   494 {
   134   GstIterator *element_iter, *pad_iter;
   495   GstIterator *element_iter, *pad_iter;
   135   gboolean elements_done, pads_done;
   496   gboolean elements_done, pads_done;
   136   GstElement *element, *peer_element, *target_element;
   497   GstElement *element;
   137   GstPad *pad, *peer_pad, *target_pad;
   498   GstPad *pad;
   138   GstPadDirection dir;
   499   GstPadDirection dir;
   139   GstCaps *caps;
       
   140   GstStructure *structure;
       
   141   gboolean free_caps, free_media;
       
   142   guint src_pads, sink_pads;
   500   guint src_pads, sink_pads;
   143   gchar *media = NULL;
   501   gchar *element_name;
   144   gchar *pad_name, *element_name;
       
   145   gchar *peer_pad_name, *peer_element_name;
       
   146   gchar *target_pad_name, *target_element_name;
       
   147   gchar *color_name;
       
   148   gchar *state_name = NULL;
   502   gchar *state_name = NULL;
   149   gchar *param_name = NULL;
   503   gchar *param_name = NULL;
   150   gchar *spc = NULL;
   504   const gchar *spc = &spaces[MAX (sizeof (spaces) - (1 + indent * 2), 0)];
   151 
       
   152   spc = g_malloc (1 + indent * 2);
       
   153   memset (spc, 32, indent * 2);
       
   154   spc[indent * 2] = '\0';
       
   155 
   505 
   156   element_iter = gst_bin_iterate_elements (bin);
   506   element_iter = gst_bin_iterate_elements (bin);
   157   elements_done = FALSE;
   507   elements_done = FALSE;
   158   while (!elements_done) {
   508   while (!elements_done) {
   159     switch (gst_iterator_next (element_iter, (gpointer) & element)) {
   509     switch (gst_iterator_next (element_iter, (gpointer) & element)) {
   170         fprintf (out, "%ssubgraph cluster_%s {\n", spc, element_name);
   520         fprintf (out, "%ssubgraph cluster_%s {\n", spc, element_name);
   171         fprintf (out, "%s  fontname=\"Bitstream Vera Sans\";\n", spc);
   521         fprintf (out, "%s  fontname=\"Bitstream Vera Sans\";\n", spc);
   172         fprintf (out, "%s  fontsize=\"8\";\n", spc);
   522         fprintf (out, "%s  fontsize=\"8\";\n", spc);
   173         fprintf (out, "%s  style=filled;\n", spc);
   523         fprintf (out, "%s  style=filled;\n", spc);
   174         fprintf (out, "%s  color=black;\n\n", spc);
   524         fprintf (out, "%s  color=black;\n\n", spc);
   175         fprintf (out, "%s  label=\"<%s>\\n%s%s%s\";\n", spc,
   525         fprintf (out, "%s  label=\"%s\\n%s%s%s\";\n", spc,
   176             G_OBJECT_TYPE_NAME (element), GST_OBJECT_NAME (element),
   526             G_OBJECT_TYPE_NAME (element), GST_OBJECT_NAME (element),
   177             (state_name ? state_name : ""), (param_name ? param_name : "")
   527             (state_name ? state_name : ""), (param_name ? param_name : "")
   178             );
   528             );
   179         if (state_name) {
   529         if (state_name) {
   180           g_free (state_name);
   530           g_free (state_name);
   190         if ((pad_iter = gst_element_iterate_pads (element))) {
   540         if ((pad_iter = gst_element_iterate_pads (element))) {
   191           pads_done = FALSE;
   541           pads_done = FALSE;
   192           while (!pads_done) {
   542           while (!pads_done) {
   193             switch (gst_iterator_next (pad_iter, (gpointer) & pad)) {
   543             switch (gst_iterator_next (pad_iter, (gpointer) & pad)) {
   194               case GST_ITERATOR_OK:
   544               case GST_ITERATOR_OK:
       
   545                 debug_dump_element_pad (pad, element, details, out, indent);
   195                 dir = gst_pad_get_direction (pad);
   546                 dir = gst_pad_get_direction (pad);
   196                 pad_name = debug_dump_make_object_name (GST_OBJECT (pad));
       
   197                 element_name =
       
   198                     debug_dump_make_object_name (GST_OBJECT (element));
       
   199                 if (GST_IS_GHOST_PAD (pad)) {
       
   200                   color_name =
       
   201                       (dir == GST_PAD_SRC) ? "#ffdddd" : ((dir ==
       
   202                           GST_PAD_SINK) ? "#ddddff" : "#ffffff");
       
   203                 } else {
       
   204                   color_name =
       
   205                       (dir == GST_PAD_SRC) ? "#ffaaaa" : ((dir ==
       
   206                           GST_PAD_SINK) ? "#aaaaff" : "#cccccc");
       
   207                 }
       
   208                 /* pads */
       
   209                 fprintf (out,
       
   210                     "%s  %s_%s [color=black, fillcolor=\"%s\", label=\"%s\"];\n",
       
   211                     spc, element_name, pad_name, color_name,
       
   212                     GST_OBJECT_NAME (pad));
       
   213 
       
   214                 if (dir == GST_PAD_SRC)
   547                 if (dir == GST_PAD_SRC)
   215                   src_pads++;
   548                   src_pads++;
   216                 else if (dir == GST_PAD_SINK)
   549                 else if (dir == GST_PAD_SINK)
   217                   sink_pads++;
   550                   sink_pads++;
   218                 g_free (pad_name);
       
   219                 g_free (element_name);
       
   220                 gst_object_unref (pad);
   551                 gst_object_unref (pad);
   221                 break;
   552                 break;
   222               case GST_ITERATOR_RESYNC:
   553               case GST_ITERATOR_RESYNC:
   223                 gst_iterator_resync (pad_iter);
   554                 gst_iterator_resync (pad_iter);
   224                 break;
   555                 break;
   250           while (!pads_done) {
   581           while (!pads_done) {
   251             switch (gst_iterator_next (pad_iter, (gpointer) & pad)) {
   582             switch (gst_iterator_next (pad_iter, (gpointer) & pad)) {
   252               case GST_ITERATOR_OK:
   583               case GST_ITERATOR_OK:
   253                 if (gst_pad_is_linked (pad)
   584                 if (gst_pad_is_linked (pad)
   254                     && gst_pad_get_direction (pad) == GST_PAD_SRC) {
   585                     && gst_pad_get_direction (pad) == GST_PAD_SRC) {
   255                   if ((peer_pad = gst_pad_get_peer (pad))) {
   586                   debug_dump_element_pad_link (pad, element, details, out,
   256                     free_media = FALSE;
   587                       indent);
   257                     if ((details & GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE) ||
       
   258                         (details & GST_DEBUG_GRAPH_SHOW_CAPS_DETAILS)
       
   259                         ) {
       
   260                       if ((caps = gst_pad_get_negotiated_caps (pad))) {
       
   261                         free_caps = TRUE;
       
   262                       } else {
       
   263                         free_caps = FALSE;
       
   264                         if (!(caps = (GstCaps *)
       
   265                                 gst_pad_get_pad_template_caps (pad))) {
       
   266                           /* this should not happen */
       
   267                           media = "?";
       
   268                         }
       
   269                       }
       
   270                       if (caps) {
       
   271                         if (details & GST_DEBUG_GRAPH_SHOW_CAPS_DETAILS) {
       
   272                           gchar *tmp =
       
   273                               g_strdelimit (gst_caps_to_string (caps), ",",
       
   274                               '\n');
       
   275 
       
   276                           media = g_strescape (tmp, NULL);
       
   277                           free_media = TRUE;
       
   278                           g_free (tmp);
       
   279                         } else {
       
   280                           if (GST_CAPS_IS_SIMPLE (caps)) {
       
   281                             structure = gst_caps_get_structure (caps, 0);
       
   282                             media =
       
   283                                 (gchar *) gst_structure_get_name (structure);
       
   284                           } else
       
   285                             media = "*";
       
   286                         }
       
   287                         if (free_caps) {
       
   288                           gst_caps_unref (caps);
       
   289                         }
       
   290                       }
       
   291                     }
       
   292 
       
   293                     pad_name = debug_dump_make_object_name (GST_OBJECT (pad));
       
   294                     element_name =
       
   295                         debug_dump_make_object_name (GST_OBJECT (element));
       
   296                     peer_pad_name =
       
   297                         debug_dump_make_object_name (GST_OBJECT (peer_pad));
       
   298                     if ((peer_element = gst_pad_get_parent_element (peer_pad))) {
       
   299                       peer_element_name =
       
   300                           debug_dump_make_object_name (GST_OBJECT
       
   301                           (peer_element));
       
   302                     } else {
       
   303                       peer_element_name = "";
       
   304                     }
       
   305                     /* pad link */
       
   306                     if (media) {
       
   307                       fprintf (out, "%s%s_%s -> %s_%s [label=\"%s\"]\n", spc,
       
   308                           element_name, pad_name, peer_element_name,
       
   309                           peer_pad_name, media);
       
   310                       if (free_media) {
       
   311                         g_free (media);
       
   312                       }
       
   313                     } else {
       
   314                       fprintf (out, "%s%s_%s -> %s_%s\n", spc,
       
   315                           element_name, pad_name, peer_element_name,
       
   316                           peer_pad_name);
       
   317                     }
       
   318 
       
   319                     if (GST_IS_GHOST_PAD (pad)) {
       
   320                       if ((target_pad =
       
   321                               gst_ghost_pad_get_target (GST_GHOST_PAD (pad)))) {
       
   322                         target_pad_name =
       
   323                             debug_dump_make_object_name (GST_OBJECT
       
   324                             (target_pad));
       
   325                         if ((target_element =
       
   326                                 gst_pad_get_parent_element (target_pad))) {
       
   327                           target_element_name =
       
   328                               debug_dump_make_object_name (GST_OBJECT
       
   329                               (target_element));
       
   330                         } else {
       
   331                           target_element_name = "";
       
   332                         }
       
   333                         /* src ghostpad relationship */
       
   334                         fprintf (out, "%s%s_%s -> %s_%s [style=dashed]\n", spc,
       
   335                             target_element_name, target_pad_name, element_name,
       
   336                             pad_name);
       
   337 
       
   338                         g_free (target_pad_name);
       
   339                         if (target_element) {
       
   340                           g_free (target_element_name);
       
   341                           gst_object_unref (target_element);
       
   342                         }
       
   343                         gst_object_unref (target_pad);
       
   344                       }
       
   345                     }
       
   346                     if (GST_IS_GHOST_PAD (peer_pad)) {
       
   347                       if ((target_pad =
       
   348                               gst_ghost_pad_get_target (GST_GHOST_PAD
       
   349                                   (peer_pad)))) {
       
   350                         target_pad_name =
       
   351                             debug_dump_make_object_name (GST_OBJECT
       
   352                             (target_pad));
       
   353                         if ((target_element =
       
   354                                 gst_pad_get_parent_element (target_pad))) {
       
   355                           target_element_name =
       
   356                               debug_dump_make_object_name (GST_OBJECT
       
   357                               (target_element));
       
   358                         } else {
       
   359                           target_element_name = "";
       
   360                         }
       
   361                         /* sink ghostpad relationship */
       
   362                         fprintf (out, "%s%s_%s -> %s_%s [style=dashed]\n", spc,
       
   363                             peer_element_name, peer_pad_name,
       
   364                             target_element_name, target_pad_name);
       
   365 
       
   366                         g_free (target_pad_name);
       
   367                         if (target_element) {
       
   368                           g_free (target_element_name);
       
   369                           gst_object_unref (target_element);
       
   370                         }
       
   371                         gst_object_unref (target_pad);
       
   372                       }
       
   373                     }
       
   374 
       
   375                     g_free (pad_name);
       
   376                     g_free (element_name);
       
   377                     g_free (peer_pad_name);
       
   378                     if (peer_element) {
       
   379                       g_free (peer_element_name);
       
   380                       gst_object_unref (peer_element);
       
   381                     }
       
   382                     gst_object_unref (peer_pad);
       
   383                   }
       
   384                 }
   588                 }
   385                 gst_object_unref (pad);
   589                 gst_object_unref (pad);
   386                 break;
   590                 break;
   387               case GST_ITERATOR_RESYNC:
   591               case GST_ITERATOR_RESYNC:
   388                 gst_iterator_resync (pad_iter);
   592                 gst_iterator_resync (pad_iter);
   405         elements_done = TRUE;
   609         elements_done = TRUE;
   406         break;
   610         break;
   407     }
   611     }
   408   }
   612   }
   409   gst_iterator_free (element_iter);
   613   gst_iterator_free (element_iter);
   410   g_free (spc);
       
   411 }
   614 }
   412 
   615 
   413 /*
   616 /*
   414  * _gst_debug_bin_to_dot_file:
   617  * _gst_debug_bin_to_dot_file:
   415  * @bin: the top-level pipeline that should be analyzed
   618  * @bin: the top-level pipeline that should be analyzed
   460 
   663 
   461     /* write header */
   664     /* write header */
   462     fprintf (out,
   665     fprintf (out,
   463         "digraph pipeline {\n"
   666         "digraph pipeline {\n"
   464         "  rankdir=LR;\n"
   667         "  rankdir=LR;\n"
   465         "  fontname=\"Bitstream Vera Sans\";\n"
   668         "  fontname=\"sans\";\n"
   466         "  fontsize=\"8\";\n"
   669         "  fontsize=\"10\";\n"
   467         "  labelloc=t;\n"
   670         "  labelloc=t;\n"
   468         "  nodesep=.1;\n"
   671         "  nodesep=.1;\n"
   469         "  ranksep=.2;\n"
   672         "  ranksep=.2;\n"
   470         "  label=\"<%s>\\n%s%s%s\";\n"
   673         "  label=\"<%s>\\n%s%s%s\";\n"
   471         "  node [style=filled, shape=box, fontsize=\"7\", fontname=\"Bitstream Vera Sans\"];\n"
   674         "  node [style=filled, shape=box, fontsize=\"9\", fontname=\"sans\", margin=\"0.0,0.0\"];\n"
   472         "  edge [labelfontsize=\"7\", fontsize=\"7\", labelfontname=\"Bitstream Vera Sans\", fontname=\"Bitstream Vera Sans\"];\n"
   675         "  edge [labelfontsize=\"6\", fontsize=\"9\", fontname=\"monospace\"];\n"
   473         "\n", G_OBJECT_TYPE_NAME (bin), GST_OBJECT_NAME (bin),
   676         "\n", G_OBJECT_TYPE_NAME (bin), GST_OBJECT_NAME (bin),
   474         (state_name ? state_name : ""), (param_name ? param_name : "")
   677         (state_name ? state_name : ""), (param_name ? param_name : "")
   475         );
   678         );
   476     if (state_name)
   679     if (state_name)
   477       g_free (state_name);
   680       g_free (state_name);
   519   }
   722   }
   520 
   723 
   521   /* add timestamp */
   724   /* add timestamp */
   522   elapsed = GST_CLOCK_DIFF (_priv_gst_info_start_time,
   725   elapsed = GST_CLOCK_DIFF (_priv_gst_info_start_time,
   523       gst_util_get_timestamp ());
   726       gst_util_get_timestamp ());
       
   727 
       
   728   /* we don't use GST_TIME_FORMAT as such filenames would fail on some
       
   729    * filesystems like fat */
   524   ts_file_name =
   730   ts_file_name =
   525       g_strdup_printf ("%" GST_TIME_FORMAT "-%s", GST_TIME_ARGS (elapsed),
   731       g_strdup_printf ("%u.%02u.%02u.%09u-%s", GST_TIME_ARGS (elapsed),
   526       file_name);
   732       file_name);
   527 
   733 
   528   _gst_debug_bin_to_dot_file (bin, details, ts_file_name);
   734   _gst_debug_bin_to_dot_file (bin, details, ts_file_name);
   529   g_free (ts_file_name);
   735   g_free (ts_file_name);
   530 }
   736 }
   531 
   737 #else /* !GST_DISABLE_GST_DEBUG */
       
   738 #ifndef GST_REMOVE_DISABLED
       
   739 void
       
   740 _gst_debug_bin_to_dot_file (GstBin * bin, GstDebugGraphDetails details,
       
   741     const gchar * file_name)
       
   742 {
       
   743 }
       
   744 #ifdef __SYMBIAN32__
       
   745 EXPORT_C
       
   746 #endif
       
   747 
       
   748 
       
   749 void
       
   750 _gst_debug_bin_to_dot_file_with_ts (GstBin * bin, GstDebugGraphDetails details,
       
   751     const gchar * file_name)
       
   752 {
       
   753 }
       
   754 #endif /* GST_REMOVE_DISABLED */
   532 #endif /* GST_DISABLE_GST_DEBUG */
   755 #endif /* GST_DISABLE_GST_DEBUG */